liding
5 天以前 ace1b66fe094e791216f6c46f4bd628e1c23b2dd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<template>
  <el-dialog v-model="visible" title="预设审批流程" width="820px">
    <div class="toolbar"><el-button type="primary" @click="editFlow()">新增流程</el-button></div>
    <el-table :data="flowList" border>
      <el-table-column prop="flowName" label="流程名称" />
      <el-table-column label="默认流程" width="100"><template #default="{ row }">{{ row.isDefault === 1 ? '是' : '否' }}</template></el-table-column>
      <el-table-column label="状态" width="90"><template #default="{ row }"><el-tag :type="row.enabled === 1 ? 'success' : 'info'">{{ row.enabled === 1 ? '启用' : '停用' }}</el-tag></template></el-table-column>
      <el-table-column label="操作" width="250">
        <template #default="{ row }">
          <el-button link type="primary" @click="editFlow(row)">编辑</el-button>
          <el-button link type="primary" @click="toggleEnabled(row)">{{ row.enabled === 1 ? '停用' : '启用' }}</el-button>
          <el-button link type="danger" @click="removeFlow(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
 
    <el-dialog v-model="editorVisible" :title="editor.definition.id ? '编辑流程' : '新增流程'" width="720px" append-to-body>
      <el-form label-width="100px">
        <el-form-item label="流程名称"><el-input v-model="editor.definition.flowName" /></el-form-item>
        <el-form-item label="设为默认"><el-switch v-model="editor.definition.isDefault" :active-value="1" :inactive-value="0" /></el-form-item>
        <el-form-item label="启用"><el-switch v-model="editor.definition.enabled" :active-value="1" :inactive-value="0" /></el-form-item>
      </el-form>
      <el-divider content-position="left">审批节点</el-divider>
      <div v-for="(node, index) in editor.nodes" :key="node.key" class="node-row">
        <span>{{ index + 1 }}</span>
        <el-input v-model="node.nodeName" placeholder="节点名称" style="width: 150px" />
        <el-select v-model="node.approverValue" filterable placeholder="审批人" style="width: 150px">
          <el-option v-for="user in users" :key="user.userId" :label="user.nickName" :value="String(user.userId)" />
        </el-select>
        <el-select v-model="node.conditionOperator" style="width: 130px">
          <el-option label="始终执行" value="ALWAYS" /><el-option label="金额大于" value="GT" /><el-option label="金额大于等于" value="GTE" />
        </el-select>
        <el-input-number v-if="node.conditionOperator !== 'ALWAYS'" v-model="node.conditionValue" :min="0" :precision="2" style="width: 120px" />
        <el-button link type="danger" :disabled="editor.nodes.length === 1" @click="editor.nodes.splice(index, 1)">删除</el-button>
      </div>
      <el-button type="primary" plain @click="editor.nodes.push(createNode())">新增节点</el-button>
      <template #footer><el-button @click="editorVisible = false">取消</el-button><el-button type="primary" :loading="saving" @click="saveFlow">保存</el-button></template>
    </el-dialog>
  </el-dialog>
</template>
 
<script setup>
import { getCurrentInstance, reactive, ref } from 'vue'
import { approveFlowDefinitionAdd, approveFlowDefinitionDelete, approveFlowDefinitionEnabled, approveFlowDefinitionGet, approveFlowDefinitionList, approveFlowDefinitionUpdate } from '@/api/collaborativeApproval/approvalProcess'
import { userListNoPageByTenantId } from '@/api/system/user'
 
const { proxy } = getCurrentInstance()
const visible = ref(false)
const editorVisible = ref(false)
const saving = ref(false)
const approveType = ref(3)
const flowList = ref([])
const users = ref([])
let key = 1
const createNode = (data = {}) => ({ key: key++, nodeName: data.nodeName || '', approverType: 'USER', approverValue: data.approverValue ? String(data.approverValue) : '', conditionField: data.conditionField || null, conditionOperator: data.conditionOperator || 'ALWAYS', conditionValue: data.conditionValue == null ? null : Number(data.conditionValue) })
const editor = reactive({ definition: {}, nodes: [] })
 
const load = async () => {
  const [flows, userRes] = await Promise.all([approveFlowDefinitionList({ approveType: approveType.value }), userListNoPageByTenantId()])
  flowList.value = flows.data || []
  users.value = userRes.data || []
}
const open = async type => { approveType.value = Number(type); visible.value = true; await load() }
const editFlow = async row => {
  if (row?.id) {
    const res = await approveFlowDefinitionGet(row.id)
    editor.definition = { ...res.data.definition }
    editor.nodes = (res.data.nodes || []).map(createNode)
  } else {
    editor.definition = { id: null, flowName: '', approveType: approveType.value, enabled: 1, isDefault: 0 }
    editor.nodes = [createNode()]
  }
  editorVisible.value = true
}
const saveFlow = async () => {
  if (!editor.definition.flowName?.trim()) return proxy.$modal.msgError('请输入流程名称')
  if (editor.nodes.some(node => !node.nodeName?.trim() || !node.approverValue)) return proxy.$modal.msgError('请完整填写审批节点')
  const payload = { definition: { ...editor.definition, approveType: approveType.value }, nodes: editor.nodes.map((node, index) => ({ ...node, id: null, nodeOrder: index + 1, conditionField: node.conditionOperator === 'ALWAYS' ? null : 'amount', conditionValue: node.conditionValue == null ? null : String(node.conditionValue) })) }
  saving.value = true
  try {
    if (editor.definition.id) await approveFlowDefinitionUpdate(editor.definition.id, payload)
    else await approveFlowDefinitionAdd(payload)
    proxy.$modal.msgSuccess('保存成功')
    editorVisible.value = false
    await load()
  } finally { saving.value = false }
}
const toggleEnabled = async row => { await approveFlowDefinitionEnabled(row.id, row.enabled === 1 ? 0 : 1); await load() }
const removeFlow = async row => {
  await proxy.$modal.confirm(`确认删除流程“${row.flowName}”吗?`)
  await approveFlowDefinitionDelete(row.id)
  await load()
}
defineExpose({ open })
</script>
 
<style scoped>
.toolbar { margin-bottom: 12px; text-align: right; }
.node-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
</style>