20260928220222

This commit is contained in:
oneao committed 2026-09-28 22:02:22 +08:00
1 parent cbd49ded6f
commit ebeeca45b6
3 files changed
+127 -32

No files matched your search

@@ -1,18 +1,35 @@
<script setup>
/**
* 系统管理 —— 流程管理:流程定义 / 流程版本 / 流程绑定 / 运行监控 四个页签。
* 系统管理 —— 流程管理:流程定义 / 流程绑定 / 运行监控 三个页签。
*
* 读取全部走通用模块接口(列表视图 v_wf_*,四张视图都已注册且只读),
* 读取全部走通用模块接口(列表视图 v_wf_*,都已注册且只读),
* 写入走流程服务:发布、停用、复制版本、绑定、删除都要经过服务端的发布校验与版本约束
* (设计 §6.2 / §11 / §12)——流程定义不在列表里直接编辑,b_save_table 为空,通用保存接口不参与。
*
* 页签切换用 v-show 而不是 v-if:四个列表各自保留滚动位置、查询条件与分页,
* 流程版本不单独占页签:版本是某个定义的从属数据,在流程定义行上点「版本」开抽屉查看,
* 抽屉内仍是同一份只读视图 v_wf_version + 发布 / 停用 / 复制动作。
*
* 运行监控是「先找单、再看流程」:列表只回答有哪些实例,行上「查看」进审批详情抽屉
* (复用审批中心的 ApprovalDetailDrawer,只读:实例摘要 + 运行态流程图 + 节点办理明细)。
*
* 页签切换用 v-show 而不是 v-if:各列表各自保留滚动位置、查询条件与分页,
* 切回来不会重新加载。
*/
import { computed, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { Ban, Copy, Plus, Send, SquarePen, Trash2 } from '@lucide/vue'
import { Button, Checkbox, Form, FormItem, Input, Message, Modal, Select, Tabs } from '@/components/ui'
import { Ban, Copy, Eye, Layers, Plus, Send, SquarePen, Trash2 } from '@lucide/vue'
import {
Button,
Checkbox,
Drawer,
Form,
FormItem,
Input,
Message,
Modal,
Select,
Tabs,
} from '@/components/ui'
import { FmsModuleListPage } from '@/components/fms-module-list'
import { loadDataApi } from '@/services/api'
import { escapeSqlText } from '@/components/fms-module-common/queryUtils'
@@ -24,18 +41,18 @@ import {
retireWorkflowVersionApi,
saveWorkflowBindingApi,
} from '@/services/workflow'
import ApprovalDetailDrawer from '@/views/approval/components/ApprovalDetailDrawer.vue'
const router = useRouter()
const TAB_ITEMS = [
{ key: 'definition', label: '流程定义' },
{ key: 'version', label: '流程版本' },
{ key: 'binding', label: '流程绑定' },
{ key: 'instance', label: '运行监控' },
]
const activeTab = ref('definition')
/** 各列表的刷新入口(FmsModuleListPage 暴露 reload) */
/** 列表刷新入口(FmsModuleListPage 暴露 reload);版本列表在抽屉里,见下方「流程版本」 */
const definitionListRef = ref(null)
const versionListRef = ref(null)
const bindingListRef = ref(null)
@@ -78,21 +95,9 @@ function openDesign(definitionId) {
router.push({ name: 'system-workflow-design', query: { id: definitionId } })
}
/** 复制版本:已发布版本只读,改流程先复制出新草稿(§4.2) */
async function handleCopyVersion(row) {
try {
const version = await loadLatestVersion(row.b_id)
await copyWorkflowVersionApi(version.b_id)
Message.success('已复制为新草稿')
versionListRef.value?.reload()
} catch (error) {
notifyError('复制版本失败:', error)
}
}
const definitionRowActions = computed(() => [
{ key: 'design', label: '设计', icon: SquarePen, onClick: (row) => openDesign(row.b_id) },
{ key: 'copy', label: '复制版本', icon: Copy, onClick: (row) => handleCopyVersion(row) },
{ key: 'versions', label: '版本', icon: Layers, onClick: (row) => openVersionDrawer(row) },
{ key: 'delete', label: '删除', icon: Trash2, danger: true, onClick: (row) => handleDeleteDefinition(row) },
])
@@ -110,6 +115,7 @@ function handleDeleteDefinition(row) {
throw error // 保持确认框打开,便于重试
}
Message.success('删除成功')
closeVersionDrawerIfDeleted([row.b_id])
definitionListRef.value?.reload()
versionListRef.value?.reload()
bindingListRef.value?.reload()
@@ -141,6 +147,7 @@ function handleBatchDeleteDefinitions() {
Message.success(`已删除 ${keys.length} 个流程`)
selectedDefinitionKeys.value = []
}
closeVersionDrawerIfDeleted(keys)
definitionListRef.value?.reload()
versionListRef.value?.reload()
bindingListRef.value?.reload()
@@ -149,9 +156,50 @@ function handleBatchDeleteDefinitions() {
}
/* ============================================================================
流程版本
流程版本(流程定义行上的「版本」抽屉)
============================================================================ */
const versionDrawer = reactive({ open: false, definitionId: '', definitionName: '' })
const versionDrawerTitle = computed(() =>
versionDrawer.definitionName ? `流程「${versionDrawer.definitionName}」版本` : '流程版本',
)
/** 抽屉只显示当前定义的版本:固定条件拼进列表查询,抽屉里的查询/分页都基于它 */
const versionCondition = computed(() =>
versionDrawer.definitionId
? `b_definition_id = N'${escapeSqlText(versionDrawer.definitionId)}'`
: '',
)
function openVersionDrawer(row) {
versionDrawer.definitionId = row.b_id
versionDrawer.definitionName = row.b_name || row.b_id
versionDrawer.open = true
}
/** 流程被删掉后抽屉里的数据已失效,及时关掉避免停在空列表上 */
function closeVersionDrawerIfDeleted(definitionIds) {
if (versionDrawer.open && definitionIds.includes(versionDrawer.definitionId)) {
versionDrawer.open = false
}
}
/** 复制版本:已发布版本只读,改流程先复制出新草稿(§4.2);以该流程最新版本为模板 */
async function handleCopyVersion() {
const definitionId = versionDrawer.definitionId
if (!definitionId) return
try {
const version = await loadLatestVersion(definitionId)
await copyWorkflowVersionApi(version.b_id)
Message.success('已复制为新草稿')
versionListRef.value?.reload()
definitionListRef.value?.reload()
} catch (error) {
notifyError('复制版本失败:', error)
}
}
/** 发布:服务端校验零 error 才发布,不通过时把第一条错误顶出来 */
async function handlePublishVersion(row) {
try {
@@ -369,6 +417,23 @@ const bindingRowActions = computed(() => [
{ key: 'edit', label: '编辑', icon: SquarePen, onClick: (row) => openBindingEdit(row) },
{ key: 'delete', label: '删除', icon: Trash2, danger: true, onClick: (row) => handleDeleteBinding(row) },
])
/* ============================================================================
运行监控
============================================================================ */
const instanceDetailOpen = ref(false)
const instanceDetailId = ref('')
/** 查看这张单的流程:复用审批中心的详情抽屉,只传实例、不开审批动作,是纯查看 */
function openInstanceDetail(row) {
instanceDetailId.value = row.b_id
instanceDetailOpen.value = true
}
const instanceRowActions = computed(() => [
{ key: 'view', label: '查看', icon: Eye, onClick: (row) => openInstanceDetail(row) },
])
</script>
<template>
@@ -406,14 +471,6 @@ const bindingRowActions = computed(() => [
</template>
</FmsModuleListPage>
<FmsModuleListPage
v-show="activeTab === 'version'"
ref="versionListRef"
data-code="v_wf_version"
:row-actions="versionRowActions"
:inline-action-limit="3"
/>
<FmsModuleListPage
v-show="activeTab === 'binding'"
ref="bindingListRef"
@@ -437,7 +494,11 @@ const bindingRowActions = computed(() => [
</template>
</FmsModuleListPage>
<FmsModuleListPage v-show="activeTab === 'instance'" data-code="v_wf_instance" />
<FmsModuleListPage
v-show="activeTab === 'instance'"
data-code="v_wf_instance"
:row-actions="instanceRowActions"
/>
</div>
<Modal
@@ -467,6 +528,34 @@ const bindingRowActions = computed(() => [
</FormItem>
</Form>
</Modal>
<!-- 流程版本:内容是同一份只读视图列表,固定条件锁定到当前定义 -->
<Drawer
v-model:open="versionDrawer.open"
:title="versionDrawerTitle"
placement="right"
width="min(1000px, 96%)"
>
<div class="wf-version-drawer">
<FmsModuleListPage
ref="versionListRef"
data-code="v_wf_version"
:fixed-search-condition="versionCondition"
:row-actions="versionRowActions"
:inline-action-limit="3"
>
<template #actions="{ loading }">
<Button type="primary" :disabled="loading" @click="handleCopyVersion">
<Copy :size="14" />
复制版本
</Button>
</template>
</FmsModuleListPage>
</div>
</Drawer>
<!-- 运行监控 → 查看:复用审批中心的只读详情抽屉(实例摘要 + 运行态流程图 + 节点办理明细) -->
<ApprovalDetailDrawer v-model:open="instanceDetailOpen" :instance-id="instanceDetailId" />
</div>
</template>
@@ -493,4 +582,10 @@ const bindingRowActions = computed(() => [
flex: 1;
min-height: 0;
}
/* 抽屉里的版本列表:铺满抽屉内容区,滚动交给列表内部(外层 body 不再出现滚动条) */
.wf-version-drawer {
height: 100%;
min-height: 0;
}
</style>