<template>
  <!-- 我的待办 -->
  <div class="todo">
    <ht-table
      v-if="tableHeaderConfig"
      ref="htTable"
      :data="getCurrentTableData"
      :page-result="pageResult"
      :selectable="false"
      :quick-search-props="quickSearchProps"
      :quick-search-width="300"
      :show-export="false"
      pagination-justify="end"
      multi-view-switch
      :page-sizes="pageSizes"
      :card-item-mode="false"
      :nopagination="isShowPagination"
      :header-cell-class-name="headerCellClassName"
      :row-class-name="rowClassName"
      :default-sorter="defaultSorter"
      :auto-fix="true"
      @load="loadData"
      @view-change="handleViewChange"
      @selection-change="handleSelectionChange"
    >
      <template #toolbar>
        <el-button
          size="small"
          :disabled="isDisabled"
          type="primary"
          icon="icon-my-todo-circulate"
          @click="handleCirculate"
        >
          {{ $t('myTask.Circulate') }}
        </el-button>
        <el-button
          size="small"
          :disabled="isDisabled"
          icon="icon-my-todo-mul-deal"
          @click="handleBatchProcessing"
        >
          {{ $t('todo.BatchProcessing') }}
        </el-button>
        <todo-setting />
      </template>
      <template #search>
        <ht-table-search-panel
          v-model="baseSearchQuery"
          :divide="3"
          :label-width="110"
          display-style="block"
        >
          <ht-table-search-field
            :label="$t('myTask.flowCode')"
            prop="bt.proc_inst_id_"
            operation="LIKE"
          />
          <ht-table-search-field
            :label="$t('myTask.flowSubject')"
            prop="bt.subject_"
            operation="LIKE"
          />
          <ht-table-search-field
            :label="$t('myTask.flowProcDefName')"
            prop="bt.proc_def_name_"
            operation="LIKE"
          />
          <ht-table-search-field
            :label="$t('myTask.flowTaskName')"
            prop="bt.name_"
            operation="LIKE"
          />
          <ht-table-search-field
            :label="$t('myTask.flowCreator')"
            prop="inst.creator_"
            operation="LIKE"
          />
          <ht-table-search-field
            v-model="baseSearchQuery.orgId"
            :label="$t('myTask.flowCreatorOrganization')"
            prop="inst.CREATE_ORG_ID_"
            operation="IN"
          >
            <ht-org-selector-input
              v-model="baseSearchQuery.orgName"
              display-style="block"
              :config="{ id: 'data.baseSearchQuery.orgId' }"
            />
          </ht-table-search-field>
          <ht-table-search-field
            :label="$t('myTask.flowCreateTime')"
            prop="inst.create_time_"
            type="datetimerange"
            operation="BETWEEN"
          />
          <ht-table-search-field
            :label="$t('myTask.flowDeadline')"
            prop="bt.create_time_"
            type="datetimerange"
            operation="BETWEEN"
          />
        </ht-table-search-panel>
      </template>
      <template #default>
        <ht-table-column
          type="selection"
          width="50"
          align="center"
          fixed="left"
        />
        <ht-table-column
          :label="$t('myTask.flowIndex')"
          type="index"
          width="50"
          align="center"
          fixed="left"
        />
        <ht-table-column
          v-if="tableHeaderConfig.procInstId.frontShow"
          align="left"
          prop="procInstId"
          width="210"
          :required="true"
          :label="tableHeaderConfig.procInstId.desc"
          show-overflow-tooltip
          fixed="left"
        >
          <template #default="{ row }">
            <div class="instance-id_wrap">
              <i
                class="icon-follow special-focus-icon"
                :class="{ 'has-special-focus': row.isFocus }"
                @click.stop="handleSpecialFocus(row)"
              ></i>
              {{ row.procInstId }}
              <span
                class="copy-icon"
                @click="(event) => clipboard(row.procInstId, event)"
              >
                <i class="icon-copy"></i>
              </span>
            </div>
          </template>
        </ht-table-column>
        <ht-table-column
          v-if="tableHeaderConfig.status.frontShow"
          align="left"
          width="120"
          prop="bt.status_"
          :label="tableHeaderConfig.status.desc"
          :render-header="renderHeaderMethod"
          :filters="statusArr"
          fixed="left"
        >
          <template #default="{ row }">
            <span>
              <ht-icon
                name="dot"
                :class="statusDotClassName[row.status]"
              ></ht-icon>
              {{ status[row.status] }}
            </span>
          </template>
        </ht-table-column>
        <ht-table-column
          :label="$t('myTask.flowChart')"
          width="70"
          align="center"
          fixed="left"
          :required="true"
        >
          <template #default="{ row }">
            <div class="process-box">
              <ht-icon
                name="process"
                class="process-icon"
                @click="handleShowFlowChart(row)"
              ></ht-icon>
            </div>
          </template>
        </ht-table-column>
        <ht-table-column
          v-if="tableHeaderConfig.subject.frontShow"
          :label="tableHeaderConfig.subject.desc"
          min-width="300"
          show-overflow-tooltip
          align="left"
          fixed="left"
          :required="true"
        >
          <template #default="{ row }">
            <span
              class="subject"
              @click.stop="
                handleClick(row, tableData.length === 1 ? 'onlyOneTask' : '')
              "
            >
              {{ row.subject }}
            </span>
          </template>
        </ht-table-column>
        <ht-table-column
          v-if="tableHeaderConfig.procDefName.frontShow"
          :label="tableHeaderConfig.procDefName.desc"
          align="left"
          prop="procDefName"
          class-name="cell-def-name-wrap"
          width="160"
          show-overflow-tooltip
        />
        <ht-table-column
          v-if="tableHeaderConfig.name.frontShow"
          :label="tableHeaderConfig.name.desc"
          align="left"
          prop="name"
          width="120"
          class-name="cell-name-wrap"
          show-overflow-tooltip
        ></ht-table-column>
        <ht-table-column
          :label="$t('myTask.flowDeadline')"
          width="160"
          align="left"
          show-overflow-tooltip
        >
          <template #default="{ row }">
            <span
              v-if="row.instIsForbidden !== '1'"
              :class="currentDateClassName(row.deadline)"
            >
              {{ calcExpireTime(row.deadline) }}
            </span>
          </template>
        </ht-table-column>
        <ht-table-column
          v-if="tableHeaderConfig.createTime.frontShow"
          :label="tableHeaderConfig.createTime.desc"
          align="left"
          prop="createDate"
          width="160"
          show-overflow-tooltip
          sortable
        >
          <template slot-scope="{ row }">
            <span>{{ row.createDate }}</span>
          </template>
        </ht-table-column>
        <ht-table-column
          :label="$t('myTask.flowTaskDeadline')"
          align="left"
          prop="bt.create_time_"
          width="160"
          show-overflow-tooltip
          sortable
        >
          <template slot-scope="{ row }">
            <span>{{ row.createTime }}</span>
          </template>
        </ht-table-column>
        <ht-table-column
          :label="$t('myTask.flowNodeApprover')"
          align="left"
          width="140"
          show-overflow-tooltip
        >
          <template #default="{ row }">
            <div
              v-if="
                extraField[row.procInstId] &&
                extraField[row.procInstId].nodeApprover
              "
              class="flowlist-node-approver"
            >
              <template
                v-for="(candidate, index) in extraField[row.procInstId]
                  .nodeApprover"
              >
                <span
                  v-if="
                    candidate &&
                    candidate.name &&
                    candidate.type === 'user' &&
                    candidate.taskId === row.id
                  "
                  :key="`node-approver_${row.procInstId}_${index}`"
                  class="showOverTooltip"
                >
                  <el-tooltip
                    v-if="candidate.type === 'group'"
                    :content="candidate.userNames"
                    placement="top"
                    effect="light"
                  >
                    <el-tag plain type="info">
                      {{ candidate.name }}
                    </el-tag>
                  </el-tooltip>
                  {{
                    candidate.type === 'user' && candidate.taskId === row.id
                      ? candidate.name
                      : ''
                  }}
                </span>
              </template>
            </div>
          </template>
        </ht-table-column>
        <ht-table-column
          v-if="tableHeaderConfig.creator.frontShow"
          :label="tableHeaderConfig.creator.desc"
          align="left"
          prop="creator"
          width="100"
          show-overflow-tooltip
        ></ht-table-column>
        <ht-table-column
          v-if="tableHeaderConfig.assigneeName.frontShow"
          :label="tableHeaderConfig.assigneeName.desc"
          prop="assigneeName"
          width="100"
          class-name="assignee-name"
          show-overflow-tooltip
        ></ht-table-column>
        <ht-table-column
          v-if="tableHeaderConfig.ownerName.frontShow"
          :label="tableHeaderConfig.ownerName.desc"
          prop="ownerName"
          show-overflow-tooltip
          width="100"
        />
        <ht-table-column
          v-if="tableHeaderConfig.urgentStateValue.frontShow"
          :label="tableHeaderConfig.urgentStateValue.desc"
          prop="urgentStateValue"
          show-overflow-tooltip
          width="80"
        >
          <template slot-scope="scope">
            <template
              v-if="
                scope.row.urgentStateValue &&
                urgentStateMap[scope.row.procDefId] &&
                urgentStateMap[scope.row.procDefId].length
              "
            >
              <span
                v-for="urgent in urgentStateMap[scope.row.procDefId]"
                :key="scope.row.procDefId + '_' + urgent.state"
              >
                <span
                  v-if="urgent.state == scope.row.urgentStateValue"
                  :style="{ color: urgent.color }"
                >
                  {{ urgent.name }}
                </span>
              </span>
            </template>
            <template v-else>{{ scope.row.urgentStateValue }}</template>
          </template>
        </ht-table-column>
        <template v-for="item in tableExtendFieldList">
          <ht-table-column
            v-if="item.frontShow"
            :key="item.prop"
            :label="item.desc"
            :prop="item.name"
            width="80"
          />
        </template>
      </template>
      <template #card="{ data }">
        <card-todo
          :card-data="data"
          :card-loading="cardLoading"
          @card-click="(item) => handleCardClick(item, '')"
          @checkbox-change="handleCheckboxChange"
          @click-more="(item) => handleClickMore(item, 'todo')"
          @card-back="handleCardBack"
        ></card-todo>
      </template>
    </ht-table>

    <leader-dialog ref="leaderDialog" />
    <ht-flow-chart
      ref="flowChart"
      :inst-id="instanceId"
      :bpmn-inst-id="bpmnInstId"
    />
    <processForecast
      ref="processForecast"
      :inst-id="instanceId"
      :def-id="defId"
      :node-id="nodeId"
      :bpmn-inst-id="bpmnInstId"
    ></processForecast>
    <!-- 传阅 -->
    <circulate ref="circulate" :task-id="selectedIds" />
    <!-- 批量处理弹窗 -->
    <batch-processing-dialog
      ref="batchProcessingDialog"
      :selected-ids="selectedIds"
      @complete="handleComplete"
      @jump-approval-form="handleJumps"
    />
    <approval-dialog
      ref="approvalDialogForm"
      :current-task-id="currentTaskId"
      :current-inst-id="currentInstId"
      @close-approval-dialog="handleComplete"
    />
  </div>
</template>

<script>
  import BatchProcessingDialog from './BatchProcessingDialog'
  import TodoSetting from '@/views/matter/components/TodoSetting.vue'

  import todoCommon from '@/mixins/todoCommon'
  import tableHeaderFilter from '@/mixins/tableHeaderFilter'
  import nodeAndApprover from '@/mixins/nodeAndApprover'
  import fromModule from '@/mixins/fromModule'
  import processForecast from '@/views/matter/processForecast/processForecast.vue'
  import {
    filterUnBatchTask,
    getTodoExtendField,
    getUrgentStateConf,
  } from '@/api/process'

  import { TODO_QUICK_SEARCH_PROPS } from './const'

  export default {
    name: 'Todo',
    components: {
      BatchProcessingDialog,
      TodoSetting,
      processForecast,
    },
    mixins: [todoCommon, tableHeaderFilter, nodeAndApprover, fromModule],
    data() {
      return {
        defaultSorter: [{ property: 'bt.create_time_', direction: 'DESC' }],
        quickSearchProps: TODO_QUICK_SEARCH_PROPS,
        tableExtendFieldList: [],
        tableHeaderConfig: null,
        urgentStateMap: {},
      }
    },
    computed: {
      statusArr() {
        return Object.keys(this.status).map((item) => {
          return {
            text: this.status[item],
            value: item,
          }
        })
      },
    },
    watch: {
      tableData(rows) {
        if (!rows.length) {
          return
        }
        this.handleUrStateConf(rows)
        rows?.length > 0 && this.loadTaskInfo(rows, 'procInstId')
      },
    },
    created() {
      this.getTodoExtendFieldByAlias()
    },
    activated() {
      this.$nextTick(() => {
        if (this.tableHeaderConfig) {
          this.$refs.htTable.calcTableHeight()
        }
      })
      this.handleComplete(true)
      if (localStorage.getItem(this.account)) {
        this.specialFocusTaskList =
          JSON.parse(localStorage.getItem(this.account)) || []
      }
    },
    methods: {
      //如果带有紧急状态值，需要获取该定义的流程紧急状态信息和配置
      handleUrStateConf(rows) {
        let handleMap = {}
        const this_ = this
        let handler = function (row, future) {
          future.then((confAndRight) => {
            if (confAndRight && confAndRight.right === 'w') {
              this_.$set(
                this_.urgentStateMap,
                row.procDefId,
                eval(confAndRight.conf)
              )
            }
          })
        }
        rows
          .filter((item) => item['urgentStateValue'])
          .forEach((row) => {
            const defId = row.procDefId
            if (handleMap.hasOwnProperty(defId)) {
              handler(row, handleMap[defId])
            } else {
              const data = { defId }
              handleMap[defId] = new Promise((resolve, reject) => {
                getUrgentStateConf(data).then((resp) => {
                  resolve(resp)
                })
              })
              handler(row, handleMap[defId])
            }
          })
      },
      getTodoExtendFieldByAlias() {
        getTodoExtendField().then((res) => {
          if (res?.value) {
            const currentTableHeadaer = JSON.parse(res.value)
            this.tableExtendFieldList = currentTableHeadaer.filter((item) =>
              item.name.match('prop')
            )
            this.handleArrayToObject(currentTableHeadaer)
          }
        })
      },
      handleArrayToObject(data) {
        this.tableHeaderConfig = data?.reduce?.((pre, cur) => {
          return { ...pre, [cur.name]: cur }
        }, {})
      },
      loadData(param, cb) {
        if (!param) {
          param = {}
        }
        let isBack = param?.isBack
        delete param.isBack
        const isGetCardList = (this.isCardView && !this.isShowMore) || isBack
        param.sorter = param.sorter || []
        param.querys = param.querys || []
        if (this.isFromApplicationModule && this.$route.query.flowKey) {
          param.querys = param.querys || []
          param.querys.push({
            property: 'inst.proc_def_key_',
            value: this.$route.query.flowKey,
            operation: 'EQUAL',
            relation: 'AND',
          })
          isBack = false
        }
        const oldSorter = isBack ? [] : param.sorter
        const data = {
          ...param,
          querys: this.getCurrentQuery(param, 'bt.type_id_'),
          sorter: [
            { direction: 'ASC', property: 'PRIORITY_' },
            ...oldSorter,
            { direction: 'DESC', property: 'inst.create_time_' },
          ],
        }
        isGetCardList
          ? this.getTodoCardList(isBack ? {} : data, 'todo', cb)
          : this.getTodoList(data, 'todo', cb)
      },
      handleJumps(row, key) {
        this.jumpApproval(row, key)
      },
      handleBatchProcessing() {
        const tableSelection =
          !this.isCardView && this.$refs.htTable.$refs.htTable.selection
        let selection = this.isCardView ? this.selectedList : tableSelection
        let selectedIds = []
        let skipMsg = []
        for (let i = selection.length - 1; i >= 0; i--) {
          if (selection[i].status == 'NORMAL') {
            selectedIds.push(selection[i].id)
          } else {
            skipMsg.push(selection[i].subject)
            selection.splice(i, 1)
          }
        }
        if (selection?.length > 0) {
          this.handleNotConfiguredBatchProcessing(
            selection,
            selectedIds,
            skipMsg
          )
        }
      },
      handleComplete(doNotResetPage) {
        if (this.tableHeaderConfig) {
          this.$nextTick(() => {
            this.$refs.htTable.load(doNotResetPage)
          })
        }
        this.isDisabled = true
      },
      handleNotConfiguredBatchProcessing(selection, ids, skipMsg) {
        filterUnBatchTask(ids, (res) => {
          let message = ''
          if (res.state && res.value?.length > 0) {
            ids = res.value
            let unBatchTaskSubject = []
            for (let i = selection.length - 1; i >= 0; i--) {
              if (!res.value.includes(selection[i].id)) {
                this.$set(selection[i], 'checked', false)
                unBatchTaskSubject.push(selection[i].subject)
                selection.splice(i, 1)
              }
            }
            message = `以下任务未配置批量处理:<br/>${unBatchTaskSubject?.join(
              '</br>'
            )}`
            if (unBatchTaskSubject.length > 0 && ids.length > 0) {
              this.$confirm(
                `${message}</br><div style="text-align:right;color:#1890ff">是否继续?</div>`,
                '提示',
                {
                  confirmButtonText: '确定',
                  cancelButtonText: '取消',
                  dangerouslyUseHTMLString: true,
                  type: 'warning',
                }
              )
                .then(() => {
                  if (ids?.length > 0) {
                    this.selectedIds = ids?.join(',')
                    this.$refs.batchProcessingDialog.openBatchProcessingDialog()
                  }
                })
                .catch(() => {})
            } else if (ids.length > 0) {
              this.selectedIds = ids?.join(',')
              this.$refs.batchProcessingDialog.openBatchProcessingDialog()
            }
          } else if (res.state && res.value?.length === 0) {
            const skipTip = `以下任务不是待办任务，不支持批量处理:</br>${skipMsg?.join(
              '</br>'
            )}`
            const selectSubjects = selection.map((item) => item.subject)
            message = `以下任务未配置批量处理:<br/>${selectSubjects?.join(
              '</br>'
            )} ${skipMsg.length > 0 ? '</br>' + skipTip : ''}`
            return this.showTipMessage(message)
          }
        })
      },
      showTipMessage(message) {
        this.$message({
          dangerouslyUseHTMLString: true,
          message,
          type: 'warning',
        })
      },
    },
  }
</script>

<style lang="scss" scoped>
  $base-border-color: #e5e5e6;
  $base-gray-icon-color: #dedede;
  ::v-deep .el-select__tags {
    max-height: 56px;
    overflow: auto;
    .el-tag {
      margin-left: 6px;
    }
  }
  .todo {
    height: 100%;
    ::v-deep {
      .ht-card .ht-card__container {
        .el-card__body {
          padding: 12px 10px 14px 10px;
        }
      }
      .pagination-panel {
        padding: 24px 0 0 0;
      }
      .assignee-name {
        .cell {
          width: 100px;
        }
      }
      .cell-name-wrap {
        .cell {
          width: 120px;
        }
      }
      .cell-def-name-wrap {
        .cell {
          width: 160px;
        }
      }
    }
    .open-model {
      font-size: 14px;
    }
    .open-next-type {
      display: inline-block;
      height: 28px;
      line-height: 28px;
      margin-left: 10px;
      font-size: 14px;
      font-weight: 400;
      padding: 0 10px;
      border-radius: $base-radius;
      color: $base-color-second-color;
      border: 1px solid $base-border-color;
      ::v-deep {
        .el-switch__core {
          width: 34px !important;
          height: 18px;
          &::after {
            width: 15px;
            height: 15px;
            top: 0;
          }
        }
      }
    }
    .subject,
    .process-icon {
      cursor: pointer;
      color: var(--themeColor);
    }
    .card-item__wrap {
      display: flex;
      width: 250px;
      .items {
        list-style: none;
        padding-left: 8px;
        .item {
          color: $base-color-second-color;
          font-size: $base-font-size-small;
          padding-left: 1px;
          &:last-child {
            padding-left: 2px;
          }
        }
        .card-item-title {
          margin: 0;
          width: calc(100% - 30px);
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
          font-weight: bold;
          color: $base-menu-color;
          font-size: $base-font-size-default;
        }
        .item-padding {
          padding: 10px 0;
        }
      }
    }
  }
  ::v-deep .el-table--scrollable-x .el-table__body-wrapper {
    overflow-x: auto;
    z-index: 0;
  }
  ::v-deep .el-table__body-wrapper {
    height: 100%;
  }
  .showOverTooltip {
    width: 120px;
    display: inline-block;
    text-overflow: ellipsis;
    overflow: hidden;
    /*这里是3行*/
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
  }
  .flowlist-node-approver {
    display: flex;
    justify-content: center;
  }
</style>
