<template>
  <div>
    <sd-data-table
      v-if="category.id"
      :key="category.id"
      ref="dataTable"
      data-url="api/framework/v1/process-prop/process-list"
      :columns="_columns"
      :actions="_actions"
      :process-req="processReq"
      :search-fields="['name']"
      :show-selection="editable"
      @rowClick="editFlow"
    >
      <template slot="type" slot-scope="text">
        {{ text === 'MAIN' ? '主流程' : text === 'SUB' ? '子流程' : '部件流程' }}
      </template>
      <div slot="action" slot-scope="text, record" :class="$style.action">
        <a-button type="link" size="small" @click="flowDesign(record)">流程设计</a-button>
        <a-button type="link" size="small" @click="copyFlow(record)">复制</a-button>
        <a-button type="link" size="small" @click="saveAsTemplate(record)">存为模板</a-button>
      </div>
    </sd-data-table>
    <a-modal
      v-model="flowVisible"
      :title="flowModalTitle"
      destroy-on-close
      :width="600"
      :mask-closable="false"
      :confirm-loading="confirmLoadingFlow"
      :footer="editable ? undefined : null"
      @ok="saveFlow"
      @cancel="() => (flowVisible = false)"
    >
      <sd-form ref="flowForm" :init-values="flowValues" :read-only="!editable">
        <template v-slot="{ model }">
          <sd-form-item v-if="flowAction === 'save2Template'" name="id" />
          <sd-form-item v-else name="id" :input-props="{ addonBefore: idPrefix }" />
          <sd-form-item name="name" />
          <a-form-model-item
            v-if="editable"
            label="上级分类"
            :rules="[
              {
                required: true,
                message: '不能为空',
                trigger: ['change', 'blur'],
              },
            ]"
            prop="categoryId"
          >
            <sd-tree-picker
              v-model="parentFlowSel"
              single
              :load-tree-data="loadTreePickerData"
              @change="flowParentChange"
            />
          </a-form-model-item>
          <sd-form-item v-else name="categoryId">
            <template v-slot:read-and-edit>
              {{ parentFlowSel[0]?.name }}
            </template>
          </sd-form-item>
          <!-- 从模板创建流程 显示 -->
          <a-form-model-item
            v-if="flowAction === 'template2flow'"
            label="流程模板"
            :rules="[
              {
                required: true,
                message: '不能为空',
                trigger: ['change', 'blur'],
              },
            ]"
            prop="templateId"
          >
            <sd-tree-picker
              v-model="templateSel"
              single
              :read-only="!editable"
              :load-tree-data="loadTreeListPickerDataTemplate"
              @change="templateChange"
            />
          </a-form-model-item>
          <sd-form-item v-if="flowAction === 'template2flow'" name="templateId" hidden />
          <!-- 存为模板 显示 -->
          <sd-form-item
            v-if="flowAction === 'save2Template'"
            name="description"
            :input-props="{ type: 'textarea' }"
          />
          <!-- 新建流程、编辑流程 显示 -->
          <sd-form-item v-if="['create', 'edit'].includes(flowAction)" name="orderNum" />
          <sd-form-item v-if="['create', 'edit'].includes(flowAction)" name="type" />
          <!-- 新建流程 显示 -->
          <sd-form-item v-if="['create'].includes(flowAction)" name="appModuleId">
            <a-select v-model="model.appModuleId" :options="formOptions" allow-clear />
          </sd-form-item>
          <sd-form-item
            name="categoryId"
            hidden
            :input-props="{ defaultValue: parentFlow && parentFlow.id }"
          />
        </template>
      </sd-form>
    </a-modal>
  </div>
</template>

<script>
import cloneDeep from 'lodash.clonedeep'
import { message } from 'ant-design-vue'
import PageService from '@/common/services/page-service'
import { sdLocalStorage } from '@/common/services/storage-service'
import TableActionTypes from '@/common/services/table-action-types'
import loginService from '@/login/login-service'
import flowService from './flow-service'
import SdFlowDesignMixin from './sd-flow-design-mixin.vue'
import components from './_import-components/sd-flow-design-list-import'

export default {
  name: 'SdFlowDesignList',
  components,
  mixins: [SdFlowDesignMixin],
  props: {
    category: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      columns: [
        {
          dataIndex: 'name',
          title: '流程名称',
          sdClickable: true,
        },
        {
          dataIndex: 'type',
          title: '流程类型',
          scopedSlots: { customRender: 'type' },
        },
        {
          title: '操作',
          dataIndex: 'action',
          scopedSlots: { customRender: 'action' },
          width: '250px',
        },
      ],
      actions: [
        {
          label: '新建',
          id: 'new',
          type: TableActionTypes.primary,
          permission: null,
          callback: this.createFlow,
          children: [
            {
              label: '从模板创建',
              id: 'templatetoflow',
              permission: null,
              callback: this.createFlowFormTemplate,
            },
          ],
        },
        {
          label: '删除',
          id: 'delete',
          type: TableActionTypes.batch,
          permission: null,
          callback: this.deleteFlow,
        },
      ],
      flowVisible: false,
      flowModalTitle: '',
      confirmLoadingFlow: false,
      flowAction: '',
      flowData: [
        {
          name: 'id',
          caption: '流程ID',
          dataType: 'string',
          required: true,
          attr: {
            regex: '^[A-Za-z]\\w*$',
            regexMessage: '以字母开头，输入字母、数字或下划线！',
            maxLength: 20,
          },
        },
        {
          name: 'name',
          caption: '流程名称',
          dataType: 'string',
          required: true,
          attr: {},
        },
        {
          name: 'categoryId',
          caption: '上级分类',
          dataType: 'string',
          required: true,
        },
        {
          name: 'orderNum',
          caption: '排序号',
          dataType: 'number',
          required: false,
        },
        {
          name: 'templateId',
          caption: '流程模板',
          dataType: 'string',
          required: false,
        },
        {
          name: 'type',
          caption: '流程类型',
          dataType: 'selectlist',
          attr: {
            defaultValue: 'MAIN',
            selectListItem: [
              { label: '主流程', value: 'MAIN' },
              { label: '子流程', value: 'SUB' },
              { label: '部件流程', value: 'TEMPLATE' },
            ],
          },
        },
        {
          name: 'appModuleId',
          caption: '关联表单',
          dataType: 'string',
          required: true,
        },
      ],
      flowTemplateData: [
        {
          name: 'id',
          caption: '模板ID',
          dataType: 'string',
          required: true,
          attr: {},
        },
        {
          name: 'name',
          caption: '模板名称',
          dataType: 'string',
          required: true,
          attr: {},
        },
        {
          name: 'categoryId',
          caption: '上级分类',
          dataType: 'string',
          required: true,
        },
        {
          name: 'description',
          caption: '描述',
          dataType: 'string',
          required: false,
        },
      ],
      currentFlow: null,
      formOptions: [],
      parentFlow: null,
      parentFlowSel: [],
      templateRoot: { id: 'X', name: '模板管理' },
      templateSel: [],
    }
  },
  computed: {
    _columns() {
      if (!this.editable) {
        return this.columns.filter((col) => col.dataIndex !== 'action')
      }
      return this.columns
    },
    _actions() {
      return this.editable ? this.actions : []
    },
    flowValues() {
      if (this.flowAction) {
        const initValues =
          this.flowAction === 'save2Template'
            ? cloneDeep(this.flowTemplateData)
            : cloneDeep(this.flowData)
        if (['create', 'template2flow'].includes(this.flowAction)) {
          initValues.map((item) => {
            if (item.name === 'id') {
              // id中必须包含字母和数字
              item.attr.defaultValue = 'F' + this.times
            }
            if (item.name === 'name') {
              item.attr.defaultValue = `flow${this.times}`
            }
            return item
          })
        } else {
          initValues.map((item) => {
            // 编辑
            if (this.flowAction === 'edit') {
              item.value = this.currentFlow[item.name]
              // id不可修改
              if (item.name === 'id') {
                item.readonly = true
                // 不可修改时无需校验，置为{}后无校验属性
                item.attr = {}
              }
            }
            // 复制
            if (this.flowAction === 'copy') {
              item.value = this.currentFlow[item.name]
              if (item.name === 'id') {
                item.value = null
                item.attr.defaultValue = this.currentFlow[item.name].slice(this.idPrefix.length)
              }
              if (item.name === 'name') {
                item.value = null
                item.attr.defaultValue = this.currentFlow[item.name]
              }
            }
            // 存为模板
            if (this.flowAction === 'save2Template') {
              if (item.name === 'id') {
                item.attr.defaultValue = this.times
              }
              if (item.name === 'name') {
                item.attr.defaultValue = `template${this.times}`
              }
            }
            return item
          })
        }
        return initValues
      }
      return []
    },
    isShareAppCus() {
      return this.editable && !!this.appNodeId
    },
    formatAppId() {
      return this.isShareAppCus ? 'N' + this.appNodeId : this.appId
    },
  },
  methods: {
    processReq(req) {
      if (req.data) {
        req.data.orderBy = 'orderNum asc, name asc'
        req.data.categoryId = this.category.id.slice(1)
        // 非个性化时传appNodeId
        if (!this.isShareAppCus) {
          req.data.appNodeId = this.appNodeId
        }
      }
      return req
    },
    initFlowFormOptions() {
      const params = {
        startPosition: 0,
        maxResults: -1,
        expressions: [
          {
            dataType: 'str',
            name: 'appId',
            op: 'eq',
            stringValue: this.appId,
          },
          {
            dataType: 'str',
            name: 'isFlow',
            op: 'eq',
            stringValue: '1',
          },
        ],
        formId: 'weAppModule',
        columns: 'id,name',
      }
      if (this.appNodeId) {
        params.expressions.push({
          dataType: 'str',
          name: 'appNodeId',
          op: 'eq',
          stringValue: this.appNodeId,
        })
      }
      return PageService.getList(params).then((res) => {
        this.formOptions = res.data.data.map((val) => {
          return {
            value: val.id,
            label: val.name,
          }
        })
      })
    },
    createFlow() {
      this.parentFlow = { id: this.category.id.slice(1), name: this.category.text }
      this.parentFlowSel = [{ ...this.parentFlow }]
      this.flowModalTitle = '新建流程'
      this.flowAction = 'create'
      this.currentFlow = null
      this.updateTimes()
      this.initFlowFormOptions()
      this.flowVisible = true
    },
    createFlowFormTemplate() {
      this.parentFlow = { id: this.category.id.slice(1), name: this.category.text }
      this.parentFlowSel = [{ ...this.parentFlow }]
      this.templateSel = []
      this.flowModalTitle = '从模板创建流程'
      this.flowAction = 'template2flow'
      this.currentFlow = null
      this.updateTimes()
      this.flowVisible = true
    },
    editFlow(record) {
      return flowService.getFlowCateInfo({ categoryId: record.categoryId }).then((res) => {
        this.parentFlow = { id: record.categoryId, name: res.data.name }
        this.parentFlowSel = [{ ...this.parentFlow }]
        return flowService.getFlowInfo({ flowId: record.id }).then((res) => {
          this.flowModalTitle = '修改流程'
          this.flowAction = 'edit'
          this.currentFlow = res.data
          this.flowVisible = true
        })
      })
    },
    saveFlow() {
      this.$refs.flowForm.validateFields().then((flag) => {
        if (flag) {
          let p
          const formData = {}
          this.$refs.flowForm.getBackendValues().forEach((item) => {
            formData[item.name] = item.value
          })
          switch (this.flowAction) {
            case 'create':
              // 新建流程：id添加前缀
              formData.id = this.idPrefix + formData.id
              p = flowService.createFlow(formData)
              break
            case 'template2flow':
              // 从模板创建
              formData.id = this.idPrefix + formData.id
              p = flowService.createFlowFormTemplate({
                templateId: formData.templateId,
                categoryId: formData.categoryId,
                flowId: formData.id,
                flowName: formData.name,
              })
              break
            case 'edit':
              // 编辑流程
              p = flowService.editFlow(formData)
              break
            case 'copy':
              // 复制流程
              p = flowService.copyFlow({
                categoryId: formData.categoryId,
                flowId: this.currentFlow.id,
                newId: this.idPrefix + formData.id,
                newName: formData.name,
              })
              break
            case 'save2Template':
              // 存为模板
              p = flowService.save2template({
                flowId: this.currentFlow.id,
                id: formData.id,
                name: formData.name,
                description: formData.description || '',
                parentId: formData.categoryId,
              })
              break
            default:
              break
          }
          this.confirmLoadingFlow = true
          p?.then((res) => {
            if (res.status === 200) {
              this.flowVisible = false
              // 存为模板时，不需要刷新列表
              if (this.flowAction !== 'save2Template') {
                this.$refs.dataTable.refresh()
              }
              // 新建流程时，默认打开流程设计
              if (this.flowAction === 'create') {
                this.flowDesign({ id: res.data.id })
              }
            } else {
              message.error(res.data?.errors || '保存失败')
            }
          }).finally(() => {
            this.confirmLoadingFlow = false
          })
        }
      })
    },
    // 复制流程
    copyFlow(record) {
      return flowService.getFlowCateInfo({ categoryId: record.categoryId }).then((res) => {
        this.flowAction = 'copy'
        this.currentFlow = record
        this.flowModalTitle = `复制流程：${record.name}`
        this.parentFlow = { id: record.categoryId, name: res.data.name }
        this.parentFlowSel = [{ ...this.parentFlow }]
        this.flowVisible = true
      })
    },
    saveAsTemplate(record) {
      this.flowAction = 'save2Template'
      this.currentFlow = record
      this.flowModalTitle = '存为模板'
      this.parentFlow = { ...this.templateRoot }
      this.parentFlowSel = [{ ...this.parentFlow }]
      this.updateTimes()
      this.flowVisible = true
    },
    deleteFlow(keys) {
      return this.deleteRows(() => flowService.deleteFlow({ ids: keys.toString() })).then(
        (flag) => {
          if (flag) {
            this.$refs.dataTable.clearSelection()
            this.$refs.dataTable.refresh()
          }
        }
      )
    },
    loadTreePickerData(parentCatId) {
      // 存为模板：选择模板分类树
      if (this.flowAction === 'save2Template') {
        return this.loadTreePickerDataTemplate(parentCatId)
      } else {
        // 选择流程分类
        const pId = parentCatId ? 'C' + parentCatId : ''
        return this.loadTreeData(pId).then((treeData) =>
          treeData.map((d) => ({
            id: d.id.slice(1), // 分类选择时，id去掉前缀'C'
            name: d.text,
            checkable: true,
            isLeaf: d.leaf,
          }))
        )
      }
    },
    loadTreePickerDataTemplate(parentCatId) {
      let p
      if (parentCatId) {
        p = flowService.getFlowTemplateCate({ catId: parentCatId }).then((res) => res.data)
      } else {
        p = Promise.resolve([{ ...this.templateRoot, leaf: false }])
      }
      return p.then((data) =>
        data.map((d) => ({
          id: d.id,
          name: d.name,
          checkable: true,
          isLeaf: false,
        }))
      )
    },
    loadTreeListPickerDataTemplate(parentCatId) {
      let p
      if (parentCatId) {
        const params = { catId: parentCatId }
        p = Promise.all([
          flowService.getFlowTemplateCate(params).then((res) => res.data),
          flowService.getFlowTemlplateList(params).then((res) => res.data),
        ])
      } else {
        p = Promise.all([
          Promise.resolve([{ ...this.templateRoot, leaf: false }]),
          Promise.resolve([]),
        ])
      }
      return p.then((items) => {
        return items[0]
          .map((item) => ({
            id: item.id,
            name: item.name,
            checkable: false,
            isLeaf: false,
          }))
          .concat(
            items[1].map((item) => ({
              id: item.id,
              name: item.name,
              checkable: true,
              isLeaf: true,
            }))
          )
      })
    },
    flowParentChange(data) {
      this.$refs.flowForm.setFieldValue('categoryId', data[0]?.id || '')
    },
    templateChange(data) {
      this.$refs.flowForm.setFieldValue('templateId', data[0]?.id || '')
    },
    // 流程设计
    flowDesign(record) {
      loginService.updateAccessToken().then((accessToken) => {
        const sysManageUrl = JSON.parse(sdLocalStorage.getItem('commonConfig') || '{}').weSysManage
          ?.sysManageUrl
        const url = `api/ssologin?destUrl=${sysManageUrl}/user/flowNew/userDesigner.jsp%3FdirectModifyFlowId=${
          record.id
        }%26appId=${this.formatAppId}&token=${accessToken.replace('Bearer ', '')}`
        const newWindow = window.open(url, '_blank')
        newWindow.opener = null
      })
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.action {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  :global(.ant-btn-sm) {
    padding: 0 3px;
  }
}
</style>
