|
|
@@ -0,0 +1,592 @@
|
|
|
+<!-- 工作流配置(ETC/加油充值) -->
|
|
|
+<!-- eslint-disable vue/no-v-model-argument -->
|
|
|
+<template>
|
|
|
+ <div class="page-container">
|
|
|
+ <section class="panel">
|
|
|
+ <div class="wf-info-bar">
|
|
|
+ <span><b>流程名称:</b>{{ wfDef.wfName || '-' }}</span>
|
|
|
+ <span>
|
|
|
+ <b>状态:</b>
|
|
|
+ <el-tag :type="statusTagType(wfDef.status)" size="small">
|
|
|
+ {{ statusLabel(wfDef.status) }}
|
|
|
+ </el-tag>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="list-toolbar">
|
|
|
+ <div class="list-toolbar-row">
|
|
|
+ <ListQuickSearchInput
|
|
|
+ v-model="quickSearchKeyword"
|
|
|
+ placeholder="节点名称/审批人"
|
|
|
+ @search="handleQuickSearch"
|
|
|
+ @clear="handleQuickSearchClear"
|
|
|
+ />
|
|
|
+ <el-button class="btn-main" type="primary" @click="openAddDialog">
|
|
|
+ <el-icon><Plus /></el-icon>新增节点
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ class="btn-ghost"
|
|
|
+ :disabled="selectedRows.length !== 1"
|
|
|
+ @click="handleToolbarEdit"
|
|
|
+ >
|
|
|
+ <el-icon><EditPen /></el-icon>编辑
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ class="btn-ghost"
|
|
|
+ type="danger"
|
|
|
+ :disabled="selectedRows.length !== 1 || !canDeleteByCreator(selectedRows[0])"
|
|
|
+ :title="selectedRows.length === 1 && !canDeleteByCreator(selectedRows[0]) ? CREATOR_DELETE_TIP : ''"
|
|
|
+ :loading="loadingMap.rowDelete"
|
|
|
+ @click="handleToolbarDelete"
|
|
|
+ >
|
|
|
+ <el-icon><Delete /></el-icon>删除
|
|
|
+ </el-button>
|
|
|
+ <el-button class="btn-ghost" :disabled="selectedRows.length !== 1" @click="handleToolbarMoveUp">
|
|
|
+ <el-icon><ArrowUp /></el-icon>上移
|
|
|
+ </el-button>
|
|
|
+ <el-button class="btn-ghost" :disabled="selectedRows.length !== 1" @click="handleToolbarMoveDown">
|
|
|
+ <el-icon><ArrowDown /></el-icon>下移
|
|
|
+ </el-button>
|
|
|
+ <el-button class="btn-ghost" :loading="loadingMap.save" @click="saveNodes">
|
|
|
+ <el-icon><Upload /></el-icon>保存配置
|
|
|
+ </el-button>
|
|
|
+
|
|
|
+ <ListToolbarEndActions
|
|
|
+ :loading="loading"
|
|
|
+ :column-defs="listColumnDefs"
|
|
|
+ v-model:visible-columns="visibleColumns"
|
|
|
+ v-model:check-all="checkAll"
|
|
|
+ :is-indeterminate="isIndeterminate"
|
|
|
+ @refresh="loadWfDef"
|
|
|
+ @reset-columns="resetToDefault"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="list-body list-wrap">
|
|
|
+ <div ref="wfReimburseTableWrapRef" class="list-table-viewport-anchor">
|
|
|
+ <ListTable
|
|
|
+ ref="wfReimburseTableRef"
|
|
|
+ table-key="pl-vehicle-recharge-workflow"
|
|
|
+ class="list-table"
|
|
|
+ :height="tableHeight"
|
|
|
+ :data="filteredNodes"
|
|
|
+ v-loading="loading"
|
|
|
+ stripe
|
|
|
+ @selection-change="onSelectionChange"
|
|
|
+ @row-dblclick="openEditDialog"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="48" align="center" header-align="center" />
|
|
|
+ <el-table-column type="index" label="序号" width="68" align="center" header-align="center" />
|
|
|
+ <el-table-column
|
|
|
+ prop="nodeName"
|
|
|
+ label="节点名称"
|
|
|
+ min-width="180"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ show-overflow-tooltip
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ prop="actionType"
|
|
|
+ label="节点动作"
|
|
|
+ min-width="120"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag
|
|
|
+ :type="(row.actionType || row.action_type || 'approve') === 'disburse' ? 'success' : 'primary'"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ {{ (row.actionType || row.action_type || 'approve') === 'disburse' ? '发放登记' : '审批' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ v-if="isColumnVisible('nodeOrder')"
|
|
|
+ prop="nodeOrder"
|
|
|
+ label="节点顺序"
|
|
|
+ min-width="100"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ v-if="isColumnVisible('approverName')"
|
|
|
+ prop="approverName"
|
|
|
+ label="审批人"
|
|
|
+ min-width="120"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ show-overflow-tooltip
|
|
|
+ />
|
|
|
+ <el-table-column
|
|
|
+ v-if="isColumnVisible('configStatus')"
|
|
|
+ label="配置状态"
|
|
|
+ min-width="110"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag :type="(row.approverId ?? row.approver_id) ? 'success' : 'warning'" size="small">
|
|
|
+ {{ (row.approverId ?? row.approver_id) ? '已配置' : '未配置' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </ListTable>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div ref="wfReimbursePagerRef" class="pagination list-pager-bar">
|
|
|
+ <div class="list-pager-selected">
|
|
|
+ 已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialogs.addNode"
|
|
|
+ title="新增节点"
|
|
|
+ width="560px"
|
|
|
+ class="dialog-form-layout"
|
|
|
+ align-center
|
|
|
+ destroy-on-close
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <el-form
|
|
|
+ ref="addFormRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="formRules"
|
|
|
+ label-position="top"
|
|
|
+ class="bx-dialog-form"
|
|
|
+ scroll-to-error
|
|
|
+ :scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
|
|
|
+ >
|
|
|
+ <div class="form-grid-2">
|
|
|
+ <el-form-item label="节点名称" prop="nodeName">
|
|
|
+ <el-input v-model="formData.nodeName" placeholder="请输入节点名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="节点顺序">
|
|
|
+ <el-input-number v-model="formData.nodeOrder" controls-position="right" :min="1" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="节点动作" prop="actionType">
|
|
|
+ <el-select v-model="formData.actionType" placeholder="请选择" style="width: 100%">
|
|
|
+ <el-option label="审批" value="approve" />
|
|
|
+ <el-option label="发放登记" value="disburse" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="审批人" style="grid-column: 1 / -1">
|
|
|
+ <el-select
|
|
|
+ v-model="formData.approverId"
|
|
|
+ placeholder="请选择审批人"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ style="width: 100%"
|
|
|
+ @change="handleApproverChange"
|
|
|
+ >
|
|
|
+ <el-option v-for="u in userOptions" :key="u.id" :label="u.displayName" :value="u.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button class="btn-ghost" @click="dialogs.addNode = false">
|
|
|
+ <el-icon><Close /></el-icon>取消
|
|
|
+ </el-button>
|
|
|
+ <el-button class="btn-main" type="primary" :loading="loadingMap.addNodeSubmit" @click="submitAddNode">
|
|
|
+ <el-icon><Check /></el-icon>确定
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialogs.editNode"
|
|
|
+ title="编辑节点"
|
|
|
+ width="560px"
|
|
|
+ class="dialog-form-layout"
|
|
|
+ align-center
|
|
|
+ destroy-on-close
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <el-form
|
|
|
+ ref="editFormRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="formRules"
|
|
|
+ label-position="top"
|
|
|
+ class="bx-dialog-form"
|
|
|
+ scroll-to-error
|
|
|
+ :scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
|
|
|
+ >
|
|
|
+ <div class="form-grid-2">
|
|
|
+ <el-form-item label="节点名称" prop="nodeName">
|
|
|
+ <el-input v-model="formData.nodeName" placeholder="请输入节点名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="节点顺序">
|
|
|
+ <el-input-number v-model="formData.nodeOrder" controls-position="right" :min="1" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="节点动作" prop="actionType">
|
|
|
+ <el-select v-model="formData.actionType" placeholder="请选择" style="width: 100%">
|
|
|
+ <el-option label="审批" value="approve" />
|
|
|
+ <el-option label="发放登记" value="disburse" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="审批人" style="grid-column: 1 / -1">
|
|
|
+ <el-select
|
|
|
+ v-model="formData.approverId"
|
|
|
+ placeholder="请选择审批人"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ style="width: 100%"
|
|
|
+ @change="handleApproverChange"
|
|
|
+ >
|
|
|
+ <el-option v-for="u in userOptions" :key="u.id" :label="u.displayName" :value="u.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button class="btn-ghost" @click="dialogs.editNode = false">
|
|
|
+ <el-icon><Close /></el-icon>取消
|
|
|
+ </el-button>
|
|
|
+ <el-button class="btn-main" type="primary" :loading="loadingMap.editNodeSubmit" @click="submitEditNode">
|
|
|
+ <el-icon><Check /></el-icon>确定
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { reactive, ref, computed, onMounted, nextTick } from 'vue'
|
|
|
+import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
|
|
+import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
|
|
+import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
|
|
+import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
|
|
|
+import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
+import type { FormInstance } from 'element-plus'
|
|
|
+import {
|
|
|
+ Plus,
|
|
|
+ EditPen,
|
|
|
+ Delete,
|
|
|
+ Close,
|
|
|
+ Check,
|
|
|
+ Upload,
|
|
|
+ ArrowUp,
|
|
|
+ ArrowDown
|
|
|
+} from '@element-plus/icons-vue'
|
|
|
+import { workflowApi } from '@/api/bx'
|
|
|
+import { fetchUserOptions } from '@/api/admin'
|
|
|
+import { statusLabel, statusTagType } from '@/utils/bx/format'
|
|
|
+
|
|
|
+type DialogKey = 'addNode' | 'editNode'
|
|
|
+
|
|
|
+const loadingMap = reactive<Record<string, boolean>>({})
|
|
|
+const dialogs = reactive<Record<DialogKey, boolean>>({
|
|
|
+ addNode: false,
|
|
|
+ editNode: false
|
|
|
+})
|
|
|
+
|
|
|
+const quickSearchKeyword = ref('')
|
|
|
+const appliedQuickSearch = ref('')
|
|
|
+
|
|
|
+const listColumnDefs = [
|
|
|
+ { prop: 'nodeOrder', label: '节点顺序' },
|
|
|
+ { prop: 'approverName', label: '审批人' },
|
|
|
+ { prop: 'configStatus', label: '配置状态' }
|
|
|
+]
|
|
|
+
|
|
|
+const {
|
|
|
+ visibleColumns,
|
|
|
+ checkAll,
|
|
|
+ isIndeterminate,
|
|
|
+ isColumnVisible,
|
|
|
+ resetToDefault
|
|
|
+} = usePersistedListColumns('pl-vehicle-recharge-workflow-list-columns', listColumnDefs)
|
|
|
+
|
|
|
+const wfReimburseTableWrapRef = ref<HTMLElement | null>(null)
|
|
|
+const wfReimbursePagerRef = ref<HTMLElement | null>(null)
|
|
|
+const wfReimburseTableRef = ref<any>(null)
|
|
|
+const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
|
|
|
+ tableEl: wfReimburseTableWrapRef,
|
|
|
+ pagerEl: wfReimbursePagerRef,
|
|
|
+ tableRef: wfReimburseTableRef
|
|
|
+})
|
|
|
+const loading = ref(false)
|
|
|
+const selectedRows = ref<Record<string, any>[]>([])
|
|
|
+const wfDef = ref<Record<string, any>>({})
|
|
|
+const allNodes = computed(() => wfDef.value.nodes || [])
|
|
|
+const filteredNodes = computed(() => {
|
|
|
+ const kw = appliedQuickSearch.value.trim().toLowerCase()
|
|
|
+ if (!kw) return allNodes.value
|
|
|
+ return allNodes.value.filter(
|
|
|
+ (n: any) =>
|
|
|
+ String(n.nodeName || '')
|
|
|
+ .toLowerCase()
|
|
|
+ .includes(kw) ||
|
|
|
+ String(n.approverName || '')
|
|
|
+ .toLowerCase()
|
|
|
+ .includes(kw)
|
|
|
+ )
|
|
|
+})
|
|
|
+const nodes = allNodes
|
|
|
+const userOptions = ref<
|
|
|
+ { id: string; realName: string; username: string; roles: string; displayName: string }[]
|
|
|
+>([])
|
|
|
+
|
|
|
+const formData = reactive({
|
|
|
+ nodeName: '',
|
|
|
+ nodeOrder: 1,
|
|
|
+ actionType: 'approve' as 'approve' | 'disburse',
|
|
|
+ approverId: null as string | null,
|
|
|
+ approverName: ''
|
|
|
+})
|
|
|
+
|
|
|
+const formRules = {
|
|
|
+ nodeName: [{ required: true, message: '节点名称不能为空', trigger: 'blur' }],
|
|
|
+ actionType: [{ required: true, message: '请选择节点动作', trigger: 'change' }]
|
|
|
+}
|
|
|
+
|
|
|
+const addFormRef = ref<FormInstance>()
|
|
|
+const editFormRef = ref<FormInstance>()
|
|
|
+
|
|
|
+async function loadUsers() {
|
|
|
+ try {
|
|
|
+ const res = await fetchUserOptions()
|
|
|
+ const data: any = (res as any)?.data ?? res ?? []
|
|
|
+ userOptions.value = (Array.isArray(data) ? data : []).map((u: any) => {
|
|
|
+ const name = u.label || u.nickName || ''
|
|
|
+ const account = u.userNo || ''
|
|
|
+ return {
|
|
|
+ id: String(u.value ?? u.id ?? ''),
|
|
|
+ realName: name,
|
|
|
+ username: account,
|
|
|
+ roles: '',
|
|
|
+ displayName: account ? `${name}(${account})` : name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch {
|
|
|
+ userOptions.value = []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function loadWfDef() {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const res = await workflowApi.getByBizType('vehicle_recharge')
|
|
|
+ wfDef.value = res.data ?? {}
|
|
|
+ } catch {
|
|
|
+ wfDef.value = {}
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ loadWfDef()
|
|
|
+ loadUsers()
|
|
|
+ nextTick(() => recalcTableHeight())
|
|
|
+})
|
|
|
+
|
|
|
+function onSelectionChange(rows: Record<string, any>[]) {
|
|
|
+ selectedRows.value = rows
|
|
|
+}
|
|
|
+
|
|
|
+function handleQuickSearch() {
|
|
|
+ appliedQuickSearch.value = quickSearchKeyword.value.trim()
|
|
|
+}
|
|
|
+
|
|
|
+function handleQuickSearchClear() {
|
|
|
+ quickSearchKeyword.value = ''
|
|
|
+ appliedQuickSearch.value = ''
|
|
|
+}
|
|
|
+
|
|
|
+function handleToolbarEdit() {
|
|
|
+ if (selectedRows.value.length !== 1) {
|
|
|
+ ElMessage.warning('请先勾选一条节点')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ openEditDialog(selectedRows.value[0])
|
|
|
+}
|
|
|
+
|
|
|
+function handleToolbarDelete() {
|
|
|
+ if (selectedRows.value.length !== 1) {
|
|
|
+ ElMessage.warning('请先勾选一条节点')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ deleteNode(selectedRows.value[0])
|
|
|
+}
|
|
|
+
|
|
|
+function handleToolbarMoveUp() {
|
|
|
+ if (selectedRows.value.length !== 1) return
|
|
|
+ moveUp(selectedRows.value[0])
|
|
|
+}
|
|
|
+
|
|
|
+function handleToolbarMoveDown() {
|
|
|
+ if (selectedRows.value.length !== 1) return
|
|
|
+ moveDown(selectedRows.value[0])
|
|
|
+}
|
|
|
+
|
|
|
+function buildNodePayload(list: Record<string, any>[]) {
|
|
|
+ return list.map((n, i) => ({
|
|
|
+ nodeName: n.nodeName,
|
|
|
+ nodeOrder: i + 1,
|
|
|
+ actionType: n.actionType ?? n.action_type ?? 'approve',
|
|
|
+ approverId: n.approverId ?? n.approver_id ?? null,
|
|
|
+ approverName: n.approverName ?? n.approver_name ?? ''
|
|
|
+ }))
|
|
|
+}
|
|
|
+
|
|
|
+async function saveNodes() {
|
|
|
+ loadingMap.save = true
|
|
|
+ try {
|
|
|
+ await workflowApi.saveNodes(wfDef.value.id, buildNodePayload(nodes.value))
|
|
|
+ ElMessage.success('保存成功')
|
|
|
+ await loadWfDef()
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e.message || '保存失败')
|
|
|
+ } finally {
|
|
|
+ loadingMap.save = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function openAddDialog() {
|
|
|
+ Object.assign(formData, {
|
|
|
+ nodeName: '',
|
|
|
+ nodeOrder: nodes.value.length + 1,
|
|
|
+ actionType: 'approve',
|
|
|
+ approverId: null,
|
|
|
+ approverName: ''
|
|
|
+ })
|
|
|
+ dialogs.addNode = true
|
|
|
+}
|
|
|
+
|
|
|
+function openEditDialog(node: Record<string, any>) {
|
|
|
+ Object.assign(formData, {
|
|
|
+ nodeName: node.nodeName,
|
|
|
+ nodeOrder: node.nodeOrder,
|
|
|
+ actionType: (node.actionType ?? node.action_type ?? 'approve') as 'approve' | 'disburse',
|
|
|
+ approverId: node.approverId ?? node.approver_id ?? null,
|
|
|
+ approverName: node.approverName ?? node.approver_name ?? ''
|
|
|
+ })
|
|
|
+ dialogs.editNode = true
|
|
|
+}
|
|
|
+
|
|
|
+function handleApproverChange(userId: string | null) {
|
|
|
+ if (userId == null) {
|
|
|
+ formData.approverName = ''
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const found = userOptions.value.find((u) => u.id === userId)
|
|
|
+ formData.approverName = found ? found.realName : ''
|
|
|
+}
|
|
|
+
|
|
|
+async function submitAddNode() {
|
|
|
+ const valid = await addFormRef.value?.validate().catch(() => false)
|
|
|
+ if (!valid) return
|
|
|
+ loadingMap.addNodeSubmit = true
|
|
|
+ try {
|
|
|
+ const newNodes = [
|
|
|
+ ...nodes.value,
|
|
|
+ {
|
|
|
+ nodeName: formData.nodeName,
|
|
|
+ nodeOrder: formData.nodeOrder,
|
|
|
+ actionType: formData.actionType,
|
|
|
+ approverId: formData.approverId,
|
|
|
+ approverName: formData.approverName
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ await workflowApi.saveNodes(wfDef.value.id, buildNodePayload(newNodes))
|
|
|
+ ElMessage.success('新增成功')
|
|
|
+ dialogs.addNode = false
|
|
|
+ await loadWfDef()
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e.message || '新增失败')
|
|
|
+ } finally {
|
|
|
+ loadingMap.addNodeSubmit = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function submitEditNode() {
|
|
|
+ const valid = await editFormRef.value?.validate().catch(() => false)
|
|
|
+ if (!valid) return
|
|
|
+ loadingMap.editNodeSubmit = true
|
|
|
+ try {
|
|
|
+ const newNodes = nodes.value.map((n: Record<string, any>) =>
|
|
|
+ n.nodeOrder === formData.nodeOrder
|
|
|
+ ? {
|
|
|
+ ...n,
|
|
|
+ nodeName: formData.nodeName,
|
|
|
+ actionType: formData.actionType,
|
|
|
+ approverId: formData.approverId,
|
|
|
+ approverName: formData.approverName
|
|
|
+ }
|
|
|
+ : n
|
|
|
+ )
|
|
|
+ await workflowApi.saveNodes(wfDef.value.id, buildNodePayload(newNodes))
|
|
|
+ ElMessage.success('编辑成功')
|
|
|
+ dialogs.editNode = false
|
|
|
+ await loadWfDef()
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e.message || '编辑失败')
|
|
|
+ } finally {
|
|
|
+ loadingMap.editNodeSubmit = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function deleteNode(node: Record<string, any>) {
|
|
|
+ if (!canDeleteByCreator(node)) {
|
|
|
+ ElMessage.warning(CREATOR_DELETE_TIP)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ await ElMessageBox.confirm(`确定要删除节点「${node.nodeName}」吗?`, '删除确认', {
|
|
|
+ confirmButtonText: '确定删除',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ loadingMap.rowDelete = true
|
|
|
+ try {
|
|
|
+ const newNodes = nodes.value.filter((n: Record<string, any>) => n.id !== node.id)
|
|
|
+ await workflowApi.saveNodes(wfDef.value.id, buildNodePayload(newNodes))
|
|
|
+ ElMessage.success('删除成功')
|
|
|
+ await loadWfDef()
|
|
|
+ } catch (e: any) {
|
|
|
+ if (e !== 'cancel') ElMessage.error(e.message || '删除失败')
|
|
|
+ } finally {
|
|
|
+ loadingMap.rowDelete = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function moveUp(node: Record<string, any>) {
|
|
|
+ const idx = nodes.value.findIndex((n: Record<string, any>) => n.id === node.id)
|
|
|
+ if (idx <= 0) return
|
|
|
+ const arr = [...nodes.value]
|
|
|
+ const temp = arr[idx]
|
|
|
+ arr[idx] = arr[idx - 1]
|
|
|
+ arr[idx - 1] = temp
|
|
|
+ arr.forEach((n: Record<string, any>, i: number) => (n.nodeOrder = i + 1))
|
|
|
+ try {
|
|
|
+ await workflowApi.saveNodes(wfDef.value.id, buildNodePayload(arr))
|
|
|
+ ElMessage.success('上移成功')
|
|
|
+ await loadWfDef()
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e.message || '上移失败')
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function moveDown(node: Record<string, any>) {
|
|
|
+ const arr = [...nodes.value]
|
|
|
+ const idx = arr.findIndex((n: Record<string, any>) => n.id === node.id)
|
|
|
+ if (idx < 0 || idx >= arr.length - 1) return
|
|
|
+ const temp = arr[idx]
|
|
|
+ arr[idx] = arr[idx + 1]
|
|
|
+ arr[idx + 1] = temp
|
|
|
+ arr.forEach((n: Record<string, any>, i: number) => (n.nodeOrder = i + 1))
|
|
|
+ try {
|
|
|
+ await workflowApi.saveNodes(wfDef.value.id, buildNodePayload(arr))
|
|
|
+ ElMessage.success('下移成功')
|
|
|
+ await loadWfDef()
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e.message || '下移失败')
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|