Files
workspace/code/fms-workflow-refactor-backup-20260923/workflow/index.vue
T
2026-09-23 16:54:54 +08:00

251 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
/**
* 系统管理 —— 流程管理:流程定义列表(《FMS审批流程交互重构设计》§4.1)。
*
* 数据源 v_wf_definition(wf_definition 带出已发布版本、版本数、绑定模块数等派生列)。
* 模块的 b_save_table 为空:列表不进入可编辑模式——流程的写入必须走流程服务
* (发布校验、版本快照、发布后不可改、幂等,见《FMS工作流与审批设计》§6.2 / §12),
* 通用保存接口不参与。
*
* 操作分工:需要草稿的操作(保存 / 校验 / 模拟 / 发布)都在编辑页的工具栏,
* 因为草稿只在那里存在;列表这边提供进入编辑、查看版本记录、停用已发布版本。
* 「批量删除」仍是占位 —— 删除定义同样要流程服务,接口未接入时只提示不假装成功。
*/
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { History, Plus, Trash2 } from '@lucide/vue'
import { Button, Message, Modal, Tag } from '@/components/ui'
import { FmsModuleListPage } from '@/components/fms-module-list'
import { VERSION_STATUS } from './designer/constants'
import {
WORKFLOW_SERVICE_MISSING_MESSAGE,
isWorkflowServiceMissing,
loadVersionList,
retireVersionApi,
} from './designer/api'
const MODULE_CODE = 'v_wf_definition'
const router = useRouter()
const selectedRowKeys = ref([])
const historyOpen = ref(false)
const historyLoading = ref(false)
const historyDefinition = ref(null)
const historyVersions = ref([])
const retiringId = ref('')
const rowSelection = computed(() => ({
selectedRowKeys: selectedRowKeys.value,
onChange: (keys) => {
selectedRowKeys.value = keys
},
}))
/* ================= 新增 / 设计 ================= */
/** 新增:不带参数进设计页,由新建向导收集流程元数据(§4.2) */
function onCreate() {
router.push({ name: 'system-workflow-design' })
}
/** 行操作:进设计页编辑这条流程 */
const rowActions = [
{
key: 'design',
label: '设计',
onClick: (row) => router.push({ name: 'system-workflow-design', query: { id: row.b_id } }),
},
{
key: 'versions',
label: '版本记录',
onClick: (row) => openHistory(row),
},
]
/* ================= 版本记录 ================= */
async function openHistory(row) {
historyDefinition.value = row
historyVersions.value = []
historyOpen.value = true
historyLoading.value = true
try {
historyVersions.value = await loadVersionList(row.b_id)
} catch {
historyVersions.value = []
} finally {
historyLoading.value = false
}
}
function statusMeta(status) {
return VERSION_STATUS.find((item) => item.value === status) || { label: status, tag: 'default' }
}
/** 停用:不再接受新实例,运行中的实例继续走完(§4.2) */
async function onRetire(row) {
retiringId.value = row.b_id
try {
await retireVersionApi(row.b_id)
Message.success(`v${row.b_version_no} 已停用`)
if (historyDefinition.value) openHistory(historyDefinition.value)
} catch (error) {
if (isWorkflowServiceMissing(error)) Message.warning(WORKFLOW_SERVICE_MISSING_MESSAGE)
else Message.error(error?.message || '停用失败')
} finally {
retiringId.value = ''
}
}
/* ================= 批量删除 ================= */
/** 批量删除:占位,未落库;删除定义要走流程服务,不能借通用保存接口删 */
function confirmBatchDelete() {
const keys = [...selectedRowKeys.value]
if (!keys.length) return
Modal.confirm({
title: `删除 ${keys.length} 条流程定义?`,
content: `${WORKFLOW_SERVICE_MISSING_MESSAGE}。删除前还要确认没有运行中的实例引用这些流程。`,
okText: '知道了',
onOk: () => {
Message.info('流程定义的删除需要工作流服务接口,当前未接入')
},
})
}
</script>
<template>
<div class="fms-page">
<FmsModuleListPage :data-code="MODULE_CODE" :row-selection="rowSelection" :row-actions="rowActions">
<template #actions="{ loading }">
<Button type="primary" :disabled="loading" @click="onCreate">
<Plus :size="14" />
新增
</Button>
<Button
type="danger-outline"
:disabled="loading || !selectedRowKeys.length"
@click="confirmBatchDelete"
>
<Trash2 :size="14" />
批量删除{{ selectedRowKeys.length ? `(${selectedRowKeys.length})` : '' }}
</Button>
</template>
</FmsModuleListPage>
<Modal v-model:open="historyOpen" title="版本记录" :width="640" :footer="false">
<div class="version-history">
<p class="version-history__subject">
{{ historyDefinition?.b_name }}({{ historyDefinition?.b_id }})
</p>
<p v-if="historyLoading" class="version-history__hint">读取中…</p>
<p v-else-if="!historyVersions.length" class="version-history__hint">
没有读到版本记录。流程服务未接入时,版本由后端创建,这里只会是空的。
</p>
<ul v-else class="version-history__list">
<li v-for="row in historyVersions" :key="row.b_id" class="version-history__item">
<span class="version-history__no">v{{ row.b_version_no }}</span>
<Tag :variant="statusMeta(row.b_status).tag">{{ statusMeta(row.b_status).label }}</Tag>
<span class="version-history__meta">
{{ row.b_published_by || '—' }} · {{ row.b_published_at || row.b_updated_at || '—' }}
</span>
<span class="version-history__nodes">{{ row.v_node_count ?? '—' }} 个节点</span>
<Button
v-if="row.b_status === 'published'"
type="outline"
:loading="retiringId === row.b_id"
@click="onRetire(row)"
>
停用
</Button>
</li>
</ul>
<p class="version-history__hint">
已发布版本不可原地编辑:改流程时复制为新版本,重新校验并发布;运行中的实例继续绑定原版本。
版本记录只读,b_canvas_json 不进视图。
</p>
<div class="version-history__footer">
<Button
type="primary"
@click="router.push({ name: 'system-workflow-design', query: { id: historyDefinition?.b_id } })"
>
<History :size="14" />
去编辑
</Button>
</div>
</div>
</Modal>
</div>
</template>
<style scoped>
.version-history {
display: flex;
flex-direction: column;
gap: 10px;
}
.version-history__subject {
margin: 0;
font-size: 13px;
color: var(--fms-text);
}
.version-history__list {
display: flex;
flex-direction: column;
gap: 6px;
padding: 0;
margin: 0;
max-height: 50vh;
overflow: auto;
list-style: none;
}
.version-history__item {
display: flex;
gap: 10px;
align-items: center;
padding: 8px 10px;
background: var(--fms-background);
border: 1px solid var(--fms-border);
border-radius: var(--fms-control-radius);
}
.version-history__no {
flex: none;
font-size: 13px;
color: var(--fms-text);
}
.version-history__meta {
flex: 1;
min-width: 0;
font-size: 12px;
color: var(--fms-text-secondary);
}
.version-history__nodes {
flex: none;
font-size: 12px;
color: var(--fms-text-secondary);
}
.version-history__hint {
margin: 0;
font-size: 12px;
line-height: 1.5;
color: var(--fms-text-secondary);
}
.version-history__footer {
display: flex;
justify-content: flex-end;
}
</style>