<template>
  <div class="approval-button-item reject-button">
    <el-button
      type="danger"
      :disabled="disabled"
      :size="btnSize"
      @click="handleReject"
    >
      {{ name }}
    </el-button>
    <el-drawer
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      :before-close="handleClose"
      :close-on-click-modal="false"
      :size="380"
      :modal="false"
      :wrapper-closable="false"
      class="right-drawer-wrap"
      :class="{
        'dialog-model-drawer': isDialog && !isFromTaskManager,
        'horizontal-layout-drawer': layout === 'horizontal',
        'flow-module-drawer': isFromApplicationModule,
      }"
      append-to-body
    >
      <div class="dialog__content">
        <el-form
          v-form="{ inputsDisplay: 'block' }"
          :model="formData"
          label-width="120px"
          data-vv-scope="rejectForm"
        >
          <ht-form-item :label="$t('task.RejectRecallMode')">
            <ht-radio
              v-model="rejectRecallMode"
              :options="rejectRecallModeOptions"
              validate="required"
              @change="changeRejectRecallMode"
            ></ht-radio>
          </ht-form-item>
          <ht-form-item
            :label="$t('task.RejectMethod')"
            class="reject-method-item"
          >
            <ht-radio
              v-model="rejectMethod"
              validate="required"
              :options="rejectMethodOptions"
            ></ht-radio>
            <ht-select
              v-if="isShowSelect"
              v-model="nodeId"
              style="width: 200px"
              validate="required"
              :options="canRejectNode"
              :props="{ key: 'nodeId', value: 'name' }"
            ></ht-select>
          </ht-form-item>

          <ht-form-item
            v-if="
              rejectInfo.signTaskHisAssignMap &&
              rejectInfo.signTaskHisAssignMap[destinationNodeId]
            "
            label="选择处理人"
          >
            <ht-select
              v-model="rejectUserIds"
              validate="required"
              multiple
              :options="rejectInfo.signTaskHisAssignMap[destinationNodeId]"
              :props="{ key: 'id', value: 'name' }"
            ></ht-select>
          </ht-form-item>

          <ht-form-item
            :label="$t('task.RejectOpinion')"
            class="opinion-label"
            label-width="80px"
          >
            <approval-comments
              :approval-opinion="approvalOpinion"
              @get-opinion="getOpinion"
            ></approval-comments>
          </ht-form-item>
          <ht-form-item :label="$t('task.RejectAttachmentUpload')">
            <ht-file
              v-model="fileList"
              :uploading.sync="fileUploading"
              type="list"
              :downloadable="false"
            />
          </ht-form-item>
        </el-form>
      </div>
      <div class="dialog-footer__btns">
        <el-button
          type="primary"
          :loading="loading || fileUploading"
          @click="confirm"
        >
          {{ $t('Common.Confirm') }}
        </el-button>
        <el-button :disabled="loading || fileUploading" @click="handleClose">
          {{ $t('Common.Cancel') }}
        </el-button>
      </div>
    </el-drawer>
    <!-- 选择领导代审批弹窗 -->
    <leader-dialog ref="leaderDialog"></leader-dialog>
  </div>
</template>

<script>
  import { getRejectTaskParams } from '@/api/process'
  import approvalButton from '@/mixins/approvalButton'
  import { mapState } from 'vuex'
  import { resultJudge } from '@/utils/event.js'
  const OPTIONS = [
    { key: 'normal', value: '重新审批' },
    { key: 'direct', value: '回到本节点' },
  ]
  const REJECT_METHOD_OPIONS = [
    { key: 'backToStart', value: '驳回发起人' },
    { key: 'rejectPre', value: '驳回上一步' },
    { key: 'reject', value: '驳回指定节点' },
  ]
  const REJECT_TYPE_MAP = {
    backToStart: 'isShowRejectSponsor',
    rejectPre: 'isShowRejectPreStep',
    reject: 'isShowRejectNode',
  }
  export default {
    name: 'RejectButton',
    mixins: [approvalButton],
    props: {
      action: {
        type: String,
        default: '',
      },
      beforeClick: {
        type: Function,
        default: null,
      },
    },
    data() {
      return {
        fileList: '',
        formData: {},
        loading: false,
        actionUrl: '',
        dialogTitle: '驳回',
        rejectRecallMode: 'normal',
        rejectMethod: '',
        nodeId: '', //驳回节点
        options: OPTIONS,
        rejectMethodOptions: REJECT_METHOD_OPIONS,
        selectOptions: [],
        rejectInfo: {},
        isSameNode: true,
        canRejectNode: [],
        parentTaskId: '', //用户加签后的父任务id
        fileUploading: false,
        rejectUserIds: null,
      }
    },
    computed: {
      ...mapState('process', ['curNodeDef']),
      isShowSelect() {
        return (
          this.rejectInfo.canRejectToAnyNode && this.rejectMethod === 'reject'
        )
      },
      isShowRejectSponsor() {
        const { canRejectToStart } = this.rejectInfo
        return canRejectToStart
      },
      isShowRejectPreStep() {
        const { afterGateway, inGateway, canRejectPreAct } = this.rejectInfo
        return canRejectPreAct && !afterGateway && !inGateway
      },
      isShowRejectNode() {
        const { canRejectToAnyNode } = this.rejectInfo
        return canRejectToAnyNode
      },
      backNode() {
        const { nodeProperties } = this.curNodeDef
        return nodeProperties.length > 0 ? nodeProperties[0].backNode : ''
      },
      // 允许的驳回重提模式
      permitRejectRecallMode() {
        return this.rejectInfo.rejectRecallMode?.split(',') || []
      },
      // 驳回重提模式选项
      rejectRecallModeOptions() {
        return this.options.filter(
          (m) => this.permitRejectRecallMode.indexOf(m.key) > -1
        )
      },
      rejectPreName() {
        if (
          this.rejectRecallMode == 'normal' &&
          this.rejectInfo.allowNormalNode.length > 0
        ) {
          return this.rejectInfo.allowNormalNode[0].name
        }
        if (
          this.rejectRecallMode == 'direct' &&
          this.rejectInfo.allowDirectNode.length > 0
        ) {
          return this.rejectInfo.allowDirectNode[0].name
        }
        return '不支持'
      },
      destinationNodeId() {
        //根据用户所选的驳回策略，计算目标节点id。从而判断目标节点是不是会签，需不需要显示选择驳回会签处理人的下拉
        let nodeId = ''
        // 驳回发起人时的节点id, 取可驳回节点的最后一个
        if (
          this.rejectMethod == 'backToStart' &&
          this.canRejectNode.length > 0
        ) {
          nodeId = this.canRejectNode[this.canRejectNode.length - 1].nodeId
          // 驳回上一步的节点id, 取可驳回节点的第一个
        } else if (
          this.rejectMethod == 'rejectPre' &&
          this.canRejectNode.length > 0
        ) {
          nodeId = this.canRejectNode[0].nodeId
          // 驳回指定节点的驳回节点id，就是用户所选的
        } else if (this.rejectMethod == 'reject') {
          nodeId = this.nodeId
        }
        return nodeId
      },
    },
    watch: {
      // 监听驳回的节点id变化。发生变化时从会签历史用户的map中取出历史审批人，选中
      destinationNodeId: function (nval, oval) {
        if (this.rejectInfo.signTaskHisAssignMap[nval]) {
          let ids = []
          this.rejectInfo.signTaskHisAssignMap[nval].forEach((i) => {
            ids.push(i.id)
          })
          this.$set(this, 'rejectUserIds', ids.join(','))
        }
      },
    },
    methods: {
      //驳回重提模式值改变
      changeRejectRecallMode(val) {
        console.log(val)
        const { allowNormalNode, allowDirectNode } = this.rejectInfo

        if (!this.isSameNode) {
          this.canRejectNode =
            val === 'normal' ? allowNormalNode : allowDirectNode
          this.canRejectNode.map((item) => {
            if (item.nodeId !== this.nodeId) {
              this.nodeId = ''
            }
          })
          this.filterRejectNode()
        }
        this.filterRejectMethod()
      },
      //过滤指定驳回节点
      filterRejectNode() {
        if (this.backNode && this.canRejectNode?.length > 0) {
          this.canRejectNode = this.canRejectNode.filter((item) =>
            this.backNode.includes(item.nodeId)
          )
        }
      },
      async handleReject() {
        //表单校验
        let res = true
        if (this.beforeClick) {
          res = await resultJudge(this.beforeClick(this.alias))
        }
        if (!res) return
        this.$emit('update:disabled', true)
        //判断是否用户任务加签
        if (
          this.curNodeDef?.type === 'USERTASK' &&
          this.bpmTask?.parentId != '0'
        ) {
          this.parentTaskId = this.bpmTask.parentId
        }
        this.getRejectTaskParamsByTaskId()
      },
      //打开弹窗时获取驳回页面参数
      getRejectTaskParamsByTaskId() {
        const query = {
          taskId: this.taskId,
          backModel: 'reject',
        }
        getRejectTaskParams(query, (res) => {
          this.rejectInfo = res
          const {
            allowNormalNode,
            allowDirectNode,
            inGateway,
            defaultRejectRecallMode,
          } = res
          const nodeIds = allowNormalNode?.map((item) => item.nodeId)
          this.rejectRecallMode =
            defaultRejectRecallMode || this.permitRejectRecallMode[0]
          allowDirectNode?.map((it) => {
            if (!nodeIds.includes(it.nodeId)) {
              this.isSameNode = false
            }
            this.canRejectNode =
              this.rejectRecallMode === 'normal'
                ? allowNormalNode
                : allowDirectNode
            this.filterRejectNode()
            //只有驳回发起人的情况
            this.rejectSponsor()
            this.rejectPreStep()
            this.rejectSpecifiedNode()
            this.setRejectMethod()
          })
          this.dialogTitle = '驳回设置'
          this.dialogVisible = true
          this.filterRejectMethod()
        })
      },
      filterRejectMethod() {
        this.rejectMethodOptions = REJECT_METHOD_OPIONS.map((item) => {
          if (item.key == 'rejectPre') {
            item.value = '驳回上一步(' + this.rejectPreName + ')'
          }
          return {
            ...item,
            isShow: this[REJECT_TYPE_MAP[item.key]],
          }
        }).filter((it) => it.isShow)
      },
      //驳回发起人情况
      rejectSponsor() {
        const { canRejectToStart, canRejectPreAct, canRejectToAnyNode } =
          this.rejectInfo
        if (canRejectToStart && !canRejectPreAct && !canRejectToAnyNode) {
          this.rejectMethod = 'backToStart'
          this.dialogVisible = true
          return
        }
      },
      //只有驳回上一步的情况
      rejectPreStep() {
        const { canRejectToStart, canRejectPreAct, canRejectToAnyNode } =
          this.rejectInfo
        if (!canRejectToStart && canRejectPreAct && !canRejectToAnyNode) {
          this.rejectMethod = 'rejectPre'
          this.dialogVisible = true
          return
        }
      },
      // 只有驳回指定节点的情况并且指定节点只有一个
      rejectSpecifiedNode() {
        const { canRejectToStart, canRejectPreAct, canRejectToAnyNode } =
          this.rejectInfo
        if (
          !canRejectToStart &&
          !canRejectPreAct &&
          canRejectToAnyNode &&
          this.canRejectNode.length === 1
        ) {
          this.nodeId = this.canRejectNode?.[0]?.nodeId
          this.rejectMethod = 'reject'
          this.dialogVisible = true
          return
        }
      },
      setRejectMethod() {
        if (this.isShowRejectSponsor) {
          this.rejectMethod = 'backToStart'
        } else if (this.isShowRejectPreStep) {
          this.rejectMethod = 'rejectPre'
        } else if (this.isShowRejectNode) {
          this.rejectMethod = 'reject'
        }
      },
      confirm() {
        this.$root.$validator.validateAll('rejectForm').then((result) => {
          if (!result) {
            this.loading = false
            return this.$message.error('有必填的内容未填写。')
          }

          if (this.dialogBeforeClick) {
            resultJudge(this.dialogBeforeClick(this.alias)).then((result) => {
              if (result) {
                this.doSubmit()
              } else {
                this.loading = false
              }
            })
          } else {
            this.doSubmit()
          }
          this.submitAfter('reject')
        })
      },
      doSubmit() {
        let params = {
          actionName:
            this.rejectMethod == 'backToStart' ? 'backToStart' : 'reject',
          backHandMode: this.rejectRecallMode,
          destination: this.nodeId,
          files: this.fileList && JSON.stringify(this.fileList),
          rejectTaskId: this.parentTaskId,
        }
        if (
          this.rejectUserIds &&
          this.rejectInfo.signTaskHisAssignMap[this.destinationNodeId]
        ) {
          let nodeUser = { nodeId: this.destinationNodeId, executors: [] }
          this.rejectUserIds.split(',').forEach((n) => {
            nodeUser.executors.push({
              id: n,
              name: this.rejectInfo.signTaskHisAssignMap[
                this.destinationNodeId
              ].filter((a) => a.id == n)[0].name,
            })
          })
          params.assignSignUser = true
          params.nodeUsers = JSON.stringify([nodeUser])
        }
        this.$emit('update:params', params)
        this.submitBefore('reject', 'rejectForm')
      },
    },
  }
</script>

<style lang="scss" scoped>
  .reject-dailog__content {
    .reject-method-item {
      ::v-deep {
        .el-form-item__content {
          display: flex;
          .inputs.ht-form-inputs__block {
            width: unset;
          }
        }
      }
    }
  }
</style>
