import axios from '@/common/services/axios-instance'
import asyncComponent from '@/common/services/async-component'
import { getUserInfo } from '@/common/store-mixin'
import { router } from '@/common/router-ready'
import { sdLocalStorage } from '@/common/services/storage-service'
import crossWindowWatcher from '@/common/services/cross-window-watcher'
import qs from 'qs'
const flowFormMap = {}
const props = { source: 'WE.OFFICE' }
function caller() {
  return {
    userName: getUserInfo().name,
    userAccount: getUserInfo().account,
  }
}

const flowFormByDesigner = asyncComponent(
  // 设计器画的form
  () =>
    import(
      /* webpackChunkName: "src-form-designer-flow-form" */ '@/form-designer/sd-flow-form-by-designer.vue'
    )
)
class FlowService {
  getRootNode() {
    return Promise.resolve([{ id: 'G-1', text: '组织机构' }])
  }

  getNodeInfo(FormData, nodeData, inputs, actionType) {
    const { instId, activeStepId, processId: flowId, flowFormModelRelationId } = FormData // activeStepId为0时说明是起草的,processId即为flowId
    const actionId = nodeData.buttonId || nodeData.actionId //
    let url
    // 主协办的加签
    if (actionType === 'addOperator') {
      url = `api/framework/v1/task-process/task/add-operator-candidate-infos`
    } else {
      url = `api/framework/v1/process-drive/task-${
        activeStepId ? '' : 'start-instance-'
      }candidate-infos`
    }
    return axios
      .post(
        url,
        {
          instId,
          activeStepId,
          actionId,
          flowId,
          inputs,
          flowFormModelRelationId,
          props: { custom: FormData.customProps },
        },
        {
          // 起草时参数需要actionID，flowId,非起草时需要 instid activeStepId actionId
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  getActionInfo(FormData, nodeData, inputs) {
    const { instId, activeStepId, processId: flowId, flowFormModelRelationId } = FormData // activeStepId为0时说明是起草的,processId即为flowId
    const actionId = nodeData.buttonId || nodeData.actionId //
    return axios
      .post(`api/framework/v1/group-manager/action/hierarchical`, {
        instId,
        activeStepId,
        actionId,
        flowId,
        inputs,
        flowFormModelRelationId,
      })
      .then(function(res) {
        return res.data
      })
  }

  getTaskCandidateRoots(FormData, nodeData, inputs) {
    const { instId, processId: flowId, flowFormModelRelationId } = FormData
    const actionId = nodeData.actionId
    return axios
      .post(
        `api/framework/v1/process-drive/task-${
          FormData.activeStepId ? '' : 'start-instance-'
        }candidate-roots`,
        {
          instId,
          actionId,
          flowId,
          inputs,
          flowFormModelRelationId,
          props: { custom: FormData.customProps, ...nodeData.props },
        },
        {
          // 起草时参数必要actionID，flowId,非起草时必要 instid actionId
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then(function(res) {
        res.data.forEach((item) => {
          item.key = item.code
          item.slots = { icon: item.type === 'User' ? 'U' : 'G' }
          item.isLeaf = item.type === 'User' || item.attrs.expandable === 'false'
          item.title = item.name
          item.checkable = item.attrs?.['propagate_group_can_checke'] !== 'false'
        })
        return res.data
      })
  }

  childNodes(node, operator, flowinfo, actionId, type) {
    // 提交，参数依赖表单,node是当前节点，operator是根节点,type取人员或部门，不传取所有
    const { activeStepId, inputs, instId, processId: flowId, flowFormModelRelationId } = flowinfo
    let url = ''
    if (!actionId) {
      // 加签减签没有actionId
      url = 'api/framework/v1/task-process/task/add-operator-candidates'
    } else {
      url = `api/framework/v1/process-drive/task${activeStepId ? '' : '-start-instance'}-candidates`
    }
    return axios
      .post(
        url, // 返回值包含部门和人员的，
        { operator, node, actionId, activeStepId, inputs, instId, flowId, flowFormModelRelationId }
      )
      .then(function(res) {
        const data = res.data
        function flatten(data) {
          data = data.filter((item) => {
            if (type === 'Group' && item.type === 'User') {
              // 如果指定的是机构，返回的是人员就过滤掉
              return false
            }
            return true
          })
          data.forEach((item) => {
            item.key = item.code
            item.slots = { icon: item.type === 'User' ? 'U' : 'G' }
            item.isLeaf = item.type === 'User' || item.attrs.expandable === 'false'
            item.title = item.name
            item.checkable = item.attrs?.['propagate_group_can_checke'] !== 'false'
            item.rootkey = operator.rootkey // 保留祖宗的key
            if (item.children) {
              item.children = flatten(item.children)
            }
          })
          return data
        }
        return flatten(data)
      })
  }

  searchCandidates(searchVal, flowinfo, actionId, operator) {
    const { activeStepId, inputs, instId, processId: flowId, flowFormModelRelationId } = flowinfo
    const url = `api/framework/v1/process-drive/task${
      activeStepId ? '' : '-start'
    }-search-candidates`
    return axios
      .post(
        url, // 返回值包含部门和人员的，
        {
          actionId,
          activeStepId,
          inputs,
          instId,
          flowId,
          maxResults: 99,
          startPosition: 0,
          searchVal,
          operator,
          flowFormModelRelationId,
          expressions: [
            {
              expressionsValue: [
                {
                  name: 'name',
                  op: 'like',
                  stringValue: `%${searchVal}%`,
                  dataType: 'str',
                },
                {
                  name: 'code',
                  op: 'like',
                  stringValue: `%${searchVal}%`,
                  dataType: 'str',
                },
                {
                  name: 'pinyin',
                  op: 'like',
                  stringValue: `%${searchVal}%`,
                  dataType: 'str',
                },
              ],
              op: 'or',
              dataType: 'exps',
            },
          ],
        },
        {
          // flowId非起草是用到
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then(function(res) {
        const data = res.data?.datas || []
        data.forEach((item) => {
          item.key = item.code
          item.slots = { icon: item.type === 'User' ? 'U' : 'G' }
          item.isLeaf = true
          item.title = item.name
        })
        return data
      })
  }

  dispatch(FlowData, taskCandidateInfos, buttonId, notify) {
    props.custom = FlowData.customProps
    var {
      instId,
      activeStepId,
      lockId = 0,
      processId: flowId,
      inputs,
      timer,
      flowFormModelRelationId,
      auditElement,
    } = FlowData
    var formId = FlowData.processFormData.formId
    var flowCallbackBeanName = 'subflowDataBinderCallback'
    var actionId = buttonId
    var participantInfos = []
    taskCandidateInfos.forEach(function(taskinfo) {
      // 选中了的，不是自由选择的，只有一个目标环节的
      if (
        taskinfo.props.actionProps?.freeSplitAction !== 'true' ||
        taskinfo.checked ||
        taskCandidateInfos.length === 1
      ) {
        participantInfos.push({
          strategy: taskinfo.strategy,
          destStepId: taskinfo.destStepId,
          participants: taskinfo.targetNodes || undefined,
        })
      }
    })
    if (
      participantInfos.length &&
      participantInfos?.[0]?.destStepId === participantInfos?.[1]?.destStepId
    ) {
      // 主协办的时候目标id都一样，需要合并成一个
      let participants = []
      participantInfos.forEach((item) => {
        participants = participants.concat(item.participants || [])
      })
      participantInfos = [
        {
          destStepId: participantInfos[0].destStepId,
          participants,
        },
      ]
    }
    return axios
      .post(
        `api/framework/v1/process-drive/${
          FlowData.activeStepId ? 'task/dispatch' : 'process-instance/start_dispatch'
        }`, // 起草提交和普通提交接口不同
        {
          instId,
          activeStepId,
          actionId,
          participantInfos,
          lockId,
          inputs,
          flowId,
          flowCallbackBeanName,
          formId,
          props: { ...props, sendNotify: notify?.toString() },
          timer,
          flowFormModelRelationId,
          auditElement,
        }, // 起草需要flowid
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then(function(res) {
        // 提交后清除本地锁信息
        // imLocalStorage.removeItem(`imLock${instId}`)
        return res.data
      })
  }

  getData(data) {
    const { type, mode, id } = data
    // @ts-ignore
    const query = router.history?.pending?.query || router.currentRoute.query
    if (query.flowId || query.businessTypeId) {
      let extParams = query.extParams || '{}'
      // @ts-ignore
      extParams = JSON.parse(extParams)
      let tempField = query.tempField
      // @ts-ignore
      tempField = JSON.parse(tempField || '{}')
      extParams = Object.assign(extParams, tempField)
      const params = []
      // @ts-ignore
      for (const key in extParams) {
        params.push({
          name: key,
          value: extParams[key],
        })
      }
      if (query.businessTypeId) {
        return axios
          .post(`api/framework/v1/task-form-process/start-process-pages`, {
            extParams: params,
            businessTypeId: query.businessTypeId,
          })
          .then((res) => res.data)
      }
      return axios
        .post(`api/framework/v1/task-form-process/start-process-pages`, {
          extParams: params,
          processUrl: `bpm/create.htm?flowId=${query.flowId}`,
        })
        .then((res) => res.data)
    }
    let p
    if (mode === 'inform' || mode === 'informleader') {
      p = axios.post(`api/framework/v1/task-form-process/${type}${mode ? '/' + mode : ''}`, {
        id,
        props,
      })
    } else {
      p = axios({
        url: `api/framework/v1/task-form-process/${type}${mode ? '/' + mode : ''}/${id}${
          qs.stringify(query) ? '?' + qs.stringify(query) : ''
        }`,
      })
    }
    return p.then((res) => res.data)
  }

  inform(FlowData, informUsers, opinions, feedbackOpinionRequired, isFollowFeedback, notify) {
    var { instId, activeStepId, lockId = 0, inputs } = FlowData
    var formId = FlowData.processFormData.formId
    return axios
      .post(
        'api/framework/v1/extra-task-process/inform',
        {
          instId,
          activeStepId,
          lockId,
          formId,
          informUsers,
          inputs,
          opinions,
          feedbackOpinionRequired,
          isFollowFeedback,
          props: { sendNotify: notify?.toString() },
        },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 获取知会人员
  senderinform(FlowData, userInfo) {
    var { instId } = FlowData
    var expressions = [
      {
        dataType: 'int',
        name: 'isRead',
        op: 'eq',
        intValue: 0,
      },
      {
        dataType: 'int',
        name: 'sendType',
        op: 'eq',
        intValue: 1,
      },
      {
        dataType: 'str',
        name: 'instId',
        op: 'eq',
        stringValue: instId,
      },
    ]
    var maxResults = -1
    var orderBy = 'instId DESC'
    var startPosition = 0
    var url = 'api/framework/v1/user-tasks/sender-inform'
    return axios
      .post(
        url,
        { expressions, maxResults, orderBy, startPosition },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 回复知会
  feedbackToRead(FlowData, informId, opinions) {
    var { instId, activeStepId, lockId = 0, inputs } = FlowData
    var formId = FlowData.processFormData.formId
    var url = 'api/framework/v1/extra-task-process/inform/reply'
    return axios
      .post(
        url,
        { instId, activeStepId, formId, lockId, inputs, informId, opinions },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 撤销知会
  retractInform(FlowData, users) {
    var { instId, activeStepId } = FlowData
    var { formId } = FlowData.processFormData
    var stepN
    if (FlowData.attrs && FlowData.attrs.stepN) {
      stepN = FlowData.attrs.stepN
    } else {
      stepN = -1 // 处理bug646，平台反馈写死-1
    }
    var informId = users.map((item) => item.id).toString()
    var url = 'api/framework/v1/extra-task-process/inform/cancel'
    return axios.post(
      url,
      { instId, activeStepId, formId, stepN, informId, props },
      {
        headers: {
          'Content-Type': 'application/json',
        },
      }
    )
  }

  // 转换时间
  timestampToTime(timestamp) {
    var date = new Date(timestamp) // 时间戳为10位需*1000，时间戳为13位的话不需乘1000
    var Y = date.getFullYear()
    var M = date.getMonth()
    var D = date.getDate()
    var h = '23'
    var m = '59'
    var s = '59'
    return new Date(Number(Y), Number(M), Number(D), Number(h), Number(m), Number(s))
  }

  // 保存
  save(FormData, inputs, actionId) {
    var { instId, activeStepId, lockId = 0, processId: flowId, flowFormModelRelationId } = FormData
    var formId = FormData.processFormData.formId
    var flowCallbackBeanName = 'subflowDataBinderCallback'
    actionId = actionId || FormData.saveButtons[0].buttonId // 为了兼容之前的
    return axios
      .post(
        actionId === 'workflow$adminFormSave'
          ? 'api/framework/v1/process-manager/process-instance/admin-save'
          : `api/framework/v1/process-drive/process-instance/${
              FormData.activeStepId ? 'save' : 'start'
            }`, // 起草保存和普通保存接口不同
        {
          instId,
          activeStepId,
          actionId,
          lockId,
          inputs,
          formId,
          flowCallbackBeanName,
          flowId,
          props,
          flowFormModelRelationId,
        }, // 起草需要flowid
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then(function(res) {
        // 清除本地锁信息
        // imLocalStorage.removeItem(`imLock${instId}`)
        return res.data
      })
  }

  // 驳回
  reject(FlowData, nodeData, rollbackType, notify) {
    props.custom = FlowData.customProps
    var { instId, activeStepId, inputs, lockId } = FlowData
    var formId = FlowData.processFormData.formId
    var histroyStepId = nodeData.historyStepId
    var rollbackToUser = nodeData.users
    var deliveryToThisStep = !!(rollbackType === 'workflow$return_interfere')
    return axios
      .post(
        `api/framework/v1/process-drive/task/reject`,
        {
          instId,
          activeStepId,
          formId,
          histroyStepId,
          rollbackToUser,
          inputs,
          deliveryToThisStep,
          props: { ...props, sendNotify: notify?.toString() },
          lockId,
        },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  // 关注\取消关注 add by yaopeng 2020-5-20
  attention(instId, title, type, srcTrustId) {
    var url = ''
    if (type === 'retract') {
      url = 'api/framework/v1/extra-task-process/attention/retract'
    } else {
      url = 'api/framework/v1/extra-task-process/attention'
    }
    let headers
    if (srcTrustId) {
      headers = {
        'X-RUN-AS': srcTrustId,
      }
    }
    return axios
      .post(
        url,
        {
          instId,
          title,
        },
        {
          headers,
        }
      )
      .then((_) => _.data)
  }

  // 发起沟通
  goutongstart(FlowData, communicateUsers, inputs) {
    var { activeStepId, instId, lockId = 0 } = FlowData
    var { formId } = FlowData.processFormData
    var url = 'api/framework/v1/extra-task-process/communicate'
    return axios
      .post(
        url,
        { activeStepId, instId, lockId, formId, communicateUsers, inputs },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 获取沟通人员
  senderCommunication(FlowData, userInfo) {
    var { instId, activeStepId } = FlowData
    var { formId, beanId } = FlowData.processFormData
    var account = userInfo.account
    var parentId = FlowData.attrs.commId
    var url = 'api/framework/v1/user-tasks/sender-communication'
    return axios
      .post(
        url,
        { instId, activeStepId, formId, account, parentId, beanId },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 撤销沟通
  retractCommunicate(FlowData, users) {
    var { instId, activeStepId } = FlowData
    var { formId } = FlowData.processFormData
    var stepN = FlowData.attrs.stepN
    var commId = users.map((item) => item.id).toString()
    var url = 'api/framework/v1/extra-task-process/communicate/retract'
    return axios
      .post(
        url,
        { instId, activeStepId, formId, stepN, commId },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 沟通反馈
  feedbackComm(FlowData, inputs) {
    var { instId, activeStepId, lockId = 0 } = FlowData
    var { formId } = FlowData.processFormData
    var commId = FlowData.attrs.commId
    var url = 'api/framework/v1/extra-task-process/communicate/reply'
    return axios
      .post(
        url,
        { instId, activeStepId, formId, lockId, inputs, commId },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 转办
  transfer(FlowData, informUsers, inputs, notify) {
    props.custom = FlowData.customProps
    var { instId, activeStepId, lockId = 0 } = FlowData
    var formId = FlowData.processFormData.formId
    var url = 'api/framework/v1/task-process/transfer'
    var targetUsers = informUsers
    return axios
      .post(
        url,
        {
          instId,
          activeStepId,
          formId,
          lockId,
          targetUsers,
          inputs,
          props: { ...props, sendNotify: notify?.toString() },
        },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 撤回--撤回流程实例
  encancel(FlowData, props) {
    var { instId, formId = FlowData.processFormData.formId } = FlowData
    var url = 'api/framework/v1/process-drive/task/retractBackId'
    return axios
      .post(
        url,
        { instId, formId, props },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 撤回转办--撤回已转办给指定人员的任务
  transferRetract(FlowData, userInfo, inputs) {
    var { instId, activeStepId, lockId = 0 } = FlowData
    var formId = FlowData.processFormData.formId
    var caller = { userAccount: userInfo.account, userName: userInfo.name }
    var url = 'api/framework/v1/task-process/transfer/retractBackId'
    return axios
      .post(
        url,
        { instId, activeStepId, formId, lockId, inputs, caller },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 作废
  workflowCancel(params) {
    var url = 'api/framework/v1/flow-manage/flow/suspend'
    return axios
      .post(url, params, {
        headers: {
          'Content-Type': 'application/json',
        },
      })
      .then((_) => _.data)
  }

  // 恢复
  workflowResume(FlowData) {
    var { instId } = FlowData
    var flowCallbackBeanName = 'subflowDataBinderCallback'
    var url = 'api/framework/v1/flow-manage/flow/resume'

    return axios
      .post(
        url,
        { processInstanceIds: instId, flowCallbackBeanName },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 获取流程流转记录列表
  getHistorySteps(instId) {
    return axios({
      url: `api/framework/v1/process-tracing/history-steps/${instId}`,
    })
  }

  // 获取流程实例当前活动环节记录信息列表
  getCurrentSteps(instId) {
    return axios({
      url: `api/framework/v1/process-tracing/current-steps/${instId}`,
    })
  }

  // 获取流程实例当前活动环节记录信息列表
  getCurrentStepsInfo(instId) {
    return axios({
      url: `api/framework/v1/process-tracing/current-steps-info/${instId}`,
    })
  }

  addFlowForm(pageId, component) {
    flowFormMap[pageId] = component
  }

  getWebForm(FlowData) {
    if (!flowFormMap[FlowData.processFormData.pageId]) {
      // 设计器画的form
      if (FlowData.processFormData.attrFD) {
        return flowFormByDesigner
      }
      flowFormMap[FlowData.processFormData.pageId] = asyncComponent(
        // 默认form
        () =>
          import(
            /* webpackChunkName: "src-webflow-common-form" */ '@/webflow/sd-common-subform.vue'
          )
      )
    }
    return flowFormMap[FlowData.processFormData.pageId]
  }

  // 流程树
  getFlowsList(params) {
    return axios({
      url: `api/framework/v1/flow-manage/flows/list`,
      method: 'get',
      params,
    })
  }

  // 流程表单拷贝新建
  copyFlowForm(FlowData) {
    const advancedFields = []
    const attFields = []
    FlowData.processFormData.processFormPropertyValues.forEach(function(item) {
      if (item.dataType === 'selectperson') {
        advancedFields.push(item.name)
      } else if (item.dataType === 'attachment') {
        attFields.push(item.name)
      }
    })
    const inputs = [
      {
        name: 'flowId',
        value: FlowData.processId,
      },
      {
        name: 'formId',
        value: FlowData.processFormData.formId,
      },
      {
        name: 'beanId',
        value: FlowData.processFormData.beanId,
      },
      {
        name: 'advancedFields',
        value: advancedFields.join(','),
      },
      {
        name: 'attFields',
        value: attFields.join(','),
      },
      {
        name: 'pageId',
        value: FlowData.processFormData.pageId,
      },
    ]
    return axios
      .post(
        'api/framework/v1/copy-manager/new-process-form',
        { inputs },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 获取催办人员
  getReminderUsers(FlowData) {
    var { instId } = FlowData
    return axios
      .get('api/framework/v1/extra-task-process/getReminderUser', {
        params: {
          instId: instId,
        },
      })
      .then((res) => {
        return res.data
      })
  }

  // 催办
  reminder(FlowData, inputs, content, users, notify) {
    var { instId } = FlowData
    var formId = FlowData.processFormData.formId
    var url = 'api/framework/v1/extra-task-process/reminider'
    return axios
      .post(
        url,
        { instId, formId, inputs, content, users, props: { sendNotify: notify?.toString() } },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((res) => {
        return res.data
      })
  }

  // 原来是获取加签候选人根节点，现在除了根节点还有props
  getAddOperatorCandicateRoots(FlowData, inputs, nodeData) {
    const { instId } = FlowData
    const data = { instId, inputs }
    if (nodeData) {
      data.actionId = nodeData.actionId
      data.props = { ...nodeData.props }
    }
    return axios
      .post('api/framework/v1/task-process/task/add-operator-candidate-roots', data)
      .then(function(res) {
        res.data.candidates.forEach((item) => {
          item.key = item.code
          item.slots = { icon: item.type === 'User' ? 'U' : 'G' }
          item.isLeaf = item.type === 'User' || item.attrs?.expandable === 'false'
          item.title = item.name
          item.checkable = item.attrs?.['propagate_group_can_checke'] !== 'false'
        })
        return res.data
      })
  }

  addOperator(FlowData, operators) {
    const { instId } = FlowData
    const formId = FlowData.processFormData.formId
    return axios
      .post(
        'api/framework/v1/task-process/task/add-operator',
        { instId, formId, caller: caller(), operators },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  addSubOperator(FormData, operators) {
    var { instId } = FormData
    var formId = FormData.processFormData.formId
    var flowCallbackBeanName = 'subflowDataBinderCallback'
    return axios
      .post(
        'api/framework/v1/task-process/sub-task/add-operator',
        { instId, formId, flowCallbackBeanName, caller: caller(), operators },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  hasOperator(FlowData, action) {
    let task = 'task/operatorsByAddOperator'
    if (action === 'workflow$addSubFlowOperator') {
      task = 'sub-task/operators'
    }
    var { instId } = FlowData
    return axios.get(`api/framework/v1/task-process/${task}/${instId}`).then(function(res) {
      return res.data
    })
  }

  operators(FlowData, action) {
    let task = 'task'
    if (action === 'workflow$removeSubFlowOperator') {
      task = 'sub-task'
    }
    var { instId } = FlowData
    return axios
      .get(`api/framework/v1/task-process/${task}/operators/${instId}`)
      .then(function(res) {
        return res.data
      })
  }

  canRemoveListOperators(FlowData, operators) {
    const { instId } = FlowData
    const formId = FlowData.processFormData.formId
    operators = operators.map((operator) => {
      const { code, name, type, attr = {} } = operator
      return {
        operator: { code, name, type, attr },
        subflowInstId: operator.subFlowInstance,
      }
    })
    return axios
      .post(
        `api/framework/v1/task-process/can-remove-list-operators`,
        { instId, operators, caller: caller(), formId },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  actions(FlowData) {
    const { instId, activeStepId } = FlowData
    return axios
      .post(
        `api/framework/v1/process-drive/actions`,
        { instId, activeStepId, caller: caller(), noWait: true },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  subRemoveOperator(FlowData, operators, inputs) {
    props.custom = FlowData.customProps
    var { instId } = FlowData
    var formId = FlowData.processFormData.formId
    operators = operators.map((operator) => {
      const { code, name, type, attrs = {} } = operator
      return {
        operator: { code, name, type, attrs },
        subflowInstId: operator.subFlowInstance,
      }
    })
    return axios
      .post(
        `api/framework/v1/task-process/sub-task/remove-operator`,
        { instId, operators, caller: caller(), formId, props, inputs },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  toaction(FlowData, taskCandidateInfos, actionId) {
    props.custom = FlowData.customProps
    props.jumpActionName = ''
    var { instId, activeStepId, inputs } = FlowData
    var operators = []
    taskCandidateInfos.forEach(function(taskinfo) {
      if (!taskinfo.autoSubmit) {
        operators = taskinfo.targetNodes
      }
    })
    return axios
      .post(
        `api/framework/v1/process-manager/intervene/to-action`,
        {
          instId,
          activeStepId,
          actionId,
          operators,
          props,
          thirdBeanIdProperty: 'id',
          thirdBeanIdType: 'long',
          thirdBeanTitleProperty: 'title',
          flowCallbackBeanName: 'subflowDataBinderCallback',
          thirdBean: {
            id: FlowData.processFormData.beanId,
            title: FlowData.processFormData.processFormPropertyValues.find(
              (item) => item.dataType === 'title'
            ).value,
            businessTypeName: FlowData.processFormData.processFormPropertyValues.find(
              (item) => item.name === 'businessTypeName'
            ).value,
            businessTypeId: FlowData.processFormData.processFormPropertyValues.find(
              (item) => item.name === 'businessTypeId'
            ).value,
          },
          inputs,
        },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  removeOperator(FlowData, operators, inputs) {
    props.custom = FlowData.customProps
    var { instId } = FlowData
    var stepOperators = operators.map((operator) => {
      const { stepOperatorId, code, name, type, attr = {} } = operator
      return { stepOperatorId, operators: [{ code, name, type, attr }] }
    })
    return axios
      .post(
        `api/framework/v1/task-process/task/remove-operators`,
        { instId, stepOperators, props, inputs },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  // 流程实例-返回可干预至环节列表
  getInterveneSteps(FlowData) {
    const { instId } = FlowData
    return axios
      .post(`api/framework/v1/process-manager/intervene/steps/${instId}`)
      .then(function(res) {
        return res.data
      })
  }

  // 特送接口-返回可干预的环节列表
  deliverySteps(FlowData, params = {}) {
    const { instId } = FlowData
    return axios
      .post(`api/framework/v1/flow-manage/intervene/steps/${instId}`, params)
      .then(function(res) {
        return res.data
      })
  }

  // 流程实例-干预到指定的流转环节
  getInterveneTostep(FlowData, operators, thirdBean) {
    props.custom = FlowData.customProps
    const { instId, activeStepId, stepId } = FlowData
    return axios
      .post(
        `api/framework/v1/process-manager/intervene/to-step`,
        {
          activeStepId,
          instId,
          operators,
          stepId,
          caller: caller(),
          props,
          thirdBean,
          flowCallbackBeanName: 'subflowDataBinderCallback',
        },
        {
          headers: { 'Content-Type': 'application/json' },
        }
      )
      .then(function(res) {
        return res.data
      })
  }

  getLock(instId, update = false) {
    // 不管过没过期有锁就拿当前的锁
    var lock = sdLocalStorage.getItem(`Lock${instId}`)
    let lockId
    if (lock) {
      lockId = JSON.parse(lock).sessionId
    }
    if (!update && lockId) {
      return Promise.resolve(lockId)
    } else {
      var nowtamp = new Date().getTime()
      return axios
        .post('api/framework/v1/process-drive/process-instance/lock-refresh', { instId, lockId })
        .then(
          (res) => {
            res.data.localExpire = nowtamp + (res.data.expire - res.data.lastActive)
            sdLocalStorage.setItem(`Lock${instId}`, JSON.stringify(res.data)) // 更新锁
            return res.data.sessionId
          },
          (res) => {
            return false
          }
        )
    }
  }

  unLock(instId) {
    var lock = sdLocalStorage.getItem(`Lock${instId}`)
    if (lock?.startsWith('{') && instId) {
      return axios
        .post('api/framework/v1/process-drive/process-instance/unlock', {
          instId,
          lockId: JSON.parse(lock).sessionId,
        })
        .finally(function() {
          sdLocalStorage.removeItem(`Lock${instId}`)
        })
    }
    return Promise.resolve()
  }

  unLockWhenBrowerClose(instId) {
    var lock = sdLocalStorage.getItem(`Lock${instId}`)
    if (lock?.startsWith('{') && instId) {
      const blob = new Blob(
        [
          JSON.stringify({
            instId,
            lockId: JSON.parse(lock).sessionId,
          }),
        ],
        {
          type: 'application/json',
        }
      )
      const url = 'api/framework/v1/process-drive/process-instance/unlock'
      if (navigator.sendBeacon) {
        navigator.sendBeacon(url, blob)
      } else {
        const httpRequest = new XMLHttpRequest()
        httpRequest.open('POST', url, false)
        httpRequest.setRequestHeader('Content-Type', 'application/json')
        httpRequest.send(blob)
      }
      sdLocalStorage.removeItem(`Lock${instId}`)
    }
  }

  startProcess(
    flowId,
    extParams = {},
    { srcTrustId = null, newWindow = true, tempField = {} } = {}
  ) {
    const url = router.resolve({
      path: '/sd-create-webflow',
      query: {
        flowId,
        extParams: JSON.stringify(extParams),
        tempField: JSON.stringify(tempField),
      },
    }).route.fullPath
    if (!newWindow) {
      router.push(url)
    } else {
      return crossWindowWatcher.waitForChanged(url, srcTrustId)
    }
  }

  startProcessByBusinessTypeId(
    businessTypeId,
    extParams = {},
    { srcTrustId = null, newWindow = true, tempField = {} } = {}
  ) {
    const url = router.resolve({
      path: '/sd-create-webflow',
      query: {
        businessTypeId,
        extParams: JSON.stringify(extParams),
        tempField: JSON.stringify(tempField),
      },
    }).route.fullPath
    if (!newWindow) {
      router.push(url)
    } else {
      return crossWindowWatcher.waitForChanged(url, srcTrustId)
    }
  }

  // 收藏按钮
  saveFavorities(params) {
    return axios({
      url: 'api/framework/v1/page/handleData',
      method: 'post',
      data: params,
    })
  }

  // 取消收藏按钮
  cancelFavorities(params) {
    return axios({
      url: `api/framework/v1/oabookmarkcontent/cancelCollection?formId=${params.formId}&beanType=${params.beanType}`,
      method: 'get',
    })
  }

  isStart(flowdata) {
    return flowdata.attrs?.stepN === 0
  }

  // 回复流程
  resumeFlowById(params) {
    return axios({
      url: 'api/framework/v1/process-manager/process-instance/resume',
      method: 'post',
      data: params,
    }).then((res) => {
      return res.data
    })
  }

  // 终止流程
  terminateFlowById(params) {
    return axios({
      url: 'api/framework/v1/process-manager/process-instance/terminate',
      method: 'post',
      data: params,
    })
  }

  // 暂停流程
  suspendFlowById(params) {
    return axios({
      url: 'api/framework/v1/process-manager/process-instance/suspend',
      method: 'post',
      data: params,
    }).then((res) => {
      return res.data
    })
  }

  // 干预到指定流转环节
  toSteps(params) {
    return axios({
      url: `api/framework/v1/flow-manage/intervene/to-step`,
      method: 'post',
      data: params,
    }).then((res) => {
      return res.data
    })
  }

  // 干预到指定流转操作
  interToActions(params) {
    return axios({
      url: `api/framework/v1/process-manager/intervene/to-action`,
      method: 'post',
      data: params,
    })
  }

  // 删除流程
  removeFlowById(params) {
    return axios({
      url: 'api/framework/v1/process-manager/process-instance/remove',
      method: 'post',
      data: params,
    }).then((res) => {
      return res.data
    })
  }

  // 流程处理意见
  optionList(params) {
    return axios({
      url: `api/framework/v1/flows/opinion-list`,
      method: 'get',
      params,
    }).then((res) => {
      return res.data
    })
  }

  // 修改流程意见
  updateOptions(params) {
    return axios({
      url: `api/framework/v1/flows/update-opinion`,
      method: 'post',
      data: params,
    }).then((res) => {
      return res.data
    })
  }

  // 各类流转记录
  getLog(FlowData, type, config) {
    if (type === 'operation') {
      return axios({
        url: `api/framework/v1/operation-log/log-list/${FlowData.processFormData.beanId}`,
        data: {
          expressions: [],
          startPosition: 0,
          maxResults: -1,
          orderBy: 'createdTime desc',
          formId: FlowData.processFormData.formId,
        },
        method: 'post',
      }).then((res) => res?.data?.data)
    }
    return axios
      .get(`api/framework/v1/task-form-process/inst-logs-${type}/${FlowData.instId}`, config)
      .then((res) => res.data)
  }

  // 获取便签列表
  getNoteList(formId, bId, nId) {
    return axios({
      url: `api/framework/v1/note-info/note-list?formId=${formId}&businessDataId=${bId}&nextActiveStepid=${nId}`,
      method: 'get',
    }).then((res) => {
      return res.data
    })
  }

  // 保存便签
  saveNote(params) {
    return axios({
      url: `api/framework/v1/page/handleData`,
      method: 'post',
      data: params,
    }).then((res) => {
      return res
    })
  }

  getAttOpinion(params) {
    return axios({
      url:
        `api/framework/v1/flows/opinion/` + params.opinionId + '?opinionType=' + params.opinionType,
      method: 'get',
    }).then((res) => {
      return res
    })
  }

  // 删除一条会签意见
  delAttOpinion(opinionId, opinionType) {
    return axios({
      url: `api/framework/v1/process-tracing/delete-opinion/${opinionId}/${opinionType}`,
      method: 'get',
    }).then((res) => {
      return res.data
    })
  }

  subTaskReturn(FlowData) {
    const {
      processFormData: { formId },
      inputs,
      attrs: { parentFlowInstanceId: parentInstId },
      instId: subflowInstId,
    } = FlowData
    return axios.post(`api/framework/v1/task-process/sub-task/return`, {
      parentInstId,
      subflowOperator: {
        operator: {
          code: caller().userAccount,
          name: caller().userName,
          type: 'User',
          attr: {},
        },
        subflowInstId,
      },
      formId,
      inputs,
      props,
    })
  }

  //  获取 groupId
  getGroupCode() {
    return axios({
      url: 'api/framework/v1/attachment-extend/attachments-create-group-code',
      method: 'get',
    })
  }

  // 指定人员发起沟通
  startCommunicate(FlowData, communicateUsers, opinions) {
    var { activeStepId, instId, lockId = 0, inputs } = FlowData
    var { formId } = FlowData.processFormData
    var url = 'api/flow-mobile/v1/communicatecontroller/communicate'
    return axios
      .post(
        url,
        {
          activeStepId,
          instId,
          lockId,
          formId,
          communicateUsers,
          opinions,
          commId: FlowData.attrs.commId || -1, // 第一次沟通写死为 -1
          beanIdProperty: 'id',
          beanIdType: 'long',
          beanTitleProperty: 'title',
          bean: {
            id: FlowData.processFormData.beanId,
            title: FlowData.processFormData.processFormPropertyValues.find(
              (item) => item.dataType === 'title'
            ).value,
          },
          inputs,
        },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 沟通反馈
  connectReply(FlowData, opinions) {
    var { activeStepId, instId, lockId = 0, inputs } = FlowData
    var { formId } = FlowData.processFormData
    var url = 'api/flow-mobile/v1/communicatecontroller/communicate/reply'
    return axios
      .post(
        url,
        {
          activeStepId,
          instId,
          lockId,
          formId,
          opinions,
          commId: FlowData.attrs.commId,
          beanIdProperty: 'id',
          beanIdType: 'long',
          beanTitleProperty: 'title',
          bean: {
            id: FlowData.processFormData.beanId,
            title: FlowData.processFormData.processFormPropertyValues.find(
              (item) => item.dataType === 'title'
            ).value,
          },
          inputs,
        },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 获取终止沟通实例树
  getConnectTree(instId, stepSN, status) {
    const params = {
      instId,
      stepSN,
      status,
    }
    return axios({
      url: `api/flow-mobile/v1/communicatecontroller/communicate/findcancleusers`,
      method: 'post',
      params,
    }).then((res) => {
      return res
    })
  }

  // 获取沟通数据
  getConnectData(instId) {
    return axios({
      url: `api/flow-mobile/v1/communicatecontroller/communicate/gettrees/?instId=${instId}`,
      method: 'post',
    }).then((res) => {
      return res
    })
  }

  // 终止沟通
  cancelFeed(FlowData, users) {
    var { activeStepId, instId, lockId = 0, inputs } = FlowData
    var { formId } = FlowData.processFormData
    var url = 'api/flow-mobile/v1/communicatecontroller/communicate/retract'
    const getSelectId = (usersArr) => {
      let selectedId = []
      usersArr.forEach((item) => {
        selectedId.push(item.id)
        if (item.childrens.length > 0) {
          selectedId = selectedId.concat(getSelectId(item.childrens))
        }
      })
      return selectedId
    }
    return axios
      .post(
        url,
        {
          activeStepId,
          instId,
          lockId,
          formId,
          commId: getSelectId(users).toString(),
          beanIdProperty: 'id',
          beanIdType: 'long',
          beanTitleProperty: 'title',
          bean: {
            id: FlowData.processFormData.beanId,
            title: FlowData.processFormData.processFormPropertyValues.find(
              (item) => item.dataType === 'title'
            ).value,
          },
          inputs,
        },
        {
          headers: {
            'Content-Type': 'application/json',
          },
        }
      )
      .then((_) => _.data)
  }

  // 获取流程实例
  getProcessInstance(instId) {
    return axios
      .get(`api/framework/v1/process-instance-query/process-instances/${instId}`)
      .then((res) => {
        return res.data
      })
  }

  // 获取子流程最顶层流程的信息
  getRootFlowInstanceId(instId) {
    const _this = this
    let rootParentInfo = {}
    const getFlowInstanceId = function(resolve, reject, instId) {
      _this.getProcessInstance(instId).then((res) => {
        const parentFlowInstanceId = res.parentInfo?.flowInstanceId
        rootParentInfo = res
        if (parentFlowInstanceId) {
          getFlowInstanceId(resolve, reject, parentFlowInstanceId)
        } else {
          resolve(rootParentInfo)
        }
      })
    }
    return new Promise((resolve, reject) => {
      getFlowInstanceId(resolve, reject, instId)
    })
  }

  // 获取顶层主流程的各类流转记录
  getRootLog(rootParentInfo, FlowData, type) {
    if (type === 'operation') {
      return axios({
        url: `api/framework/v1/operation-log/log-list/${FlowData.processFormData.beanId}`,
        data: {
          expressions: [],
          startPosition: 0,
          maxResults: -1,
          orderBy: 'createdTime desc',
          formId: FlowData.processFormData.formId,
        },
        method: 'post',
      }).then((res) => res?.data?.data)
    }
    return axios
      .get(
        `api/framework/v1/task-form-process/inst-logs-${type}/${rootParentInfo.id}?subInstIdStr=${FlowData.instId}`
      )
      .then((res) => {
        return res.data
      })
  }

  // 获取流水号列表
  getLsh(data) {
    return axios({
      url: 'api/framework/v1/autonumber-manager/current-autonumber',
      method: 'post',
      data,
    }).then((res) => {
      return res
    })
  }

  // 获取漏号、预留号
  getReservednumber(data) {
    return axios({
      url: 'api/framework/v1/autonumber-manager/reserved-autonumbers',
      method: 'post',
      data,
    }).then((res) => {
      return res
    })
  }

  // 获取跳号
  getSkipnumber(data) {
    return axios({
      url: 'api/framework/v1/autonumber-manager/skip-autonumbers',
      method: 'post',
      data,
    }).then((res) => {
      return res
    })
  }

  // 校验手动输入编号的格式是否正确
  checkNumberStyle(data) {
    return axios({
      url: 'api/framework/v1/autonumber-record-manager/check-serial-value',
      method: 'post',
      data,
    }).then((res) => {
      return res
    })
  }

  // 查找流程树
  searchFlowTree(params) {
    return axios.post('api/framework/v1/flow-manage/flows/list-search-box', params)
  }
}

export default new FlowService()
