增强审批流管理能力,新增审批环节的 stageKey 区分关键环节与过路审批节点,完善钉钉回调日志记录,停用部分 HTTP 回调接口,改由集成方案驱动审批流,优化审批注册中心的查询逻辑。
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<a-drawer v-model:open="visible" :title="`动作管理 — ${planName}`" width="900" destroy-on-close @close="visible = false">
|
||||
<div style="margin-bottom: 12px">
|
||||
<a-button type="primary" size="small" @click="handleAddAction">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
添加动作
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<a-table :dataSource="actions" :columns="tableColumns" :loading="loading" :pagination="false" row-key="id" size="small" bordered>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'enabled'">
|
||||
<a-tag :color="record.enabled ? 'green' : 'default'">{{ record.enabled ? '启用' : '停用' }}</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'actionType'">
|
||||
<a-tag color="blue">{{ actionTypeLabel(record.actionType) }}</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'onFail'">
|
||||
<a-tag :color="record.onFail === 'stop' ? 'orange' : 'default'">{{ record.onFail === 'stop' ? '终止' : '继续' }}</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'summary'">
|
||||
<span style="font-size: 12px; color: #666">{{ formatActionSummary(record) }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'operation'">
|
||||
<a-space>
|
||||
<a-button size="small" @click="handleEditAction(record)">编辑</a-button>
|
||||
<a-popconfirm title="确认删除该动作?" @confirm="handleDeleteAction(record)">
|
||||
<a-button size="small" danger>删除</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
<!-- update-begin---author:GHT ---date:2026-06-05 for:【XSLMES-20260605-K8R2】动作管理复用可视化编辑器,与向导添加动作一致 -->
|
||||
<VisualActionEditor ref="visualEditorRef" @success="handleActionSaved" />
|
||||
<!-- update-end---author:GHT ---date:2026-06-05 for:【XSLMES-20260605-K8R2】动作管理复用可视化编辑器 -->
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import {
|
||||
listActions,
|
||||
saveAction,
|
||||
editAction,
|
||||
deleteAction,
|
||||
getTableColumns,
|
||||
listBizDocRegistry,
|
||||
getRegistryByTable,
|
||||
} from '../MesXslIntegrationPlan.api';
|
||||
import VisualActionEditor from './VisualActionEditor.vue';
|
||||
|
||||
const STAGE_LABELS: Record<string, string> = { proofread: '校对', audit: '审核', approve: '批准' };
|
||||
|
||||
const ACTION_TYPE_LABELS: Record<string, string> = {
|
||||
REGISTRY_STAGE_SYNC: '审批环节同步',
|
||||
REGISTRY_STAGE_REVERT: '审批环节回退',
|
||||
SQL_UPDATE: 'SQL更新',
|
||||
};
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
const planId = ref('');
|
||||
const planName = ref('');
|
||||
const planRecord = ref<Recordable>({});
|
||||
const actions = ref<any[]>([]);
|
||||
|
||||
const visualEditorRef = ref();
|
||||
const bizDocList = ref<any[]>([]);
|
||||
const sourceColumns = ref<any[]>([]);
|
||||
const sourceRegistry = ref<any>(null);
|
||||
|
||||
const tableColumns = [
|
||||
{ title: '顺序', dataIndex: 'execOrder', width: 60, align: 'center' },
|
||||
{ title: '动作名称', dataIndex: 'actionName', width: 140 },
|
||||
{ title: '类型', dataIndex: 'actionType', width: 120 },
|
||||
{ title: '配置摘要', dataIndex: 'summary', ellipsis: true },
|
||||
{ title: '失败策略', dataIndex: 'onFail', width: 90 },
|
||||
{ title: '启用', dataIndex: 'enabled', width: 70 },
|
||||
{ title: '操作', key: 'operation', width: 130, align: 'center' },
|
||||
];
|
||||
|
||||
function actionTypeLabel(type: string) {
|
||||
return ACTION_TYPE_LABELS[type] || type || '-';
|
||||
}
|
||||
|
||||
function formatActionSummary(record: Recordable) {
|
||||
if (record.actionType === 'REGISTRY_STAGE_SYNC' || record.actionType === 'REGISTRY_STAGE_REVERT') {
|
||||
try {
|
||||
const cfg = JSON.parse(record.actionConfig || '{}');
|
||||
if (record.actionType === 'REGISTRY_STAGE_SYNC') {
|
||||
const stage = cfg.registryStage?.stage || cfg.stage;
|
||||
const from = cfg.registryStage?.expectedFrom || cfg.expectedFrom;
|
||||
return `环节→${STAGE_LABELS[stage] || stage || '?'}${from ? `,前置=${from}` : ''}`;
|
||||
}
|
||||
const target = cfg.registryStage?.targetStage || cfg.targetStage || 'compile';
|
||||
return `回退→${target}`;
|
||||
} catch {
|
||||
return record.actionConfig || '-';
|
||||
}
|
||||
}
|
||||
return record.sqlTemplate || '-';
|
||||
}
|
||||
|
||||
async function loadEditorContext() {
|
||||
const sourceTable = planRecord.value.sourceTable;
|
||||
if (!sourceTable) return;
|
||||
try {
|
||||
const [cols, registryRes, docsRes] = await Promise.all([
|
||||
getTableColumns(sourceTable),
|
||||
getRegistryByTable(sourceTable),
|
||||
listBizDocRegistry(),
|
||||
]);
|
||||
sourceColumns.value = (cols as any) || [];
|
||||
sourceRegistry.value = registryRes || null;
|
||||
bizDocList.value = (docsRes as any)?.records || (Array.isArray(docsRes) ? docsRes : []);
|
||||
} catch {
|
||||
sourceColumns.value = [];
|
||||
sourceRegistry.value = null;
|
||||
bizDocList.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
async function open(plan: Recordable) {
|
||||
planId.value = plan.id;
|
||||
planName.value = plan.planName;
|
||||
planRecord.value = plan;
|
||||
visible.value = true;
|
||||
await Promise.all([loadActions(), loadEditorContext()]);
|
||||
}
|
||||
|
||||
async function loadActions() {
|
||||
loading.value = true;
|
||||
try {
|
||||
actions.value = (await listActions(planId.value)) || [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function openVisualEditor(action?: Recordable) {
|
||||
if (!planRecord.value.sourceTable) {
|
||||
createMessage.warning('方案未配置触发业务表');
|
||||
return;
|
||||
}
|
||||
visualEditorRef.value?.open({
|
||||
sourceTable: planRecord.value.sourceTable,
|
||||
sourceColumns: sourceColumns.value,
|
||||
bizDocList: bizDocList.value,
|
||||
sourceRegistry: sourceRegistry.value,
|
||||
action: action
|
||||
? { ...action, planId: planId.value }
|
||||
: { planId: planId.value, execOrder: actions.value.length + 1 },
|
||||
execOrder: action?.execOrder ?? actions.value.length + 1,
|
||||
});
|
||||
}
|
||||
|
||||
function handleAddAction() {
|
||||
openVisualEditor();
|
||||
}
|
||||
|
||||
function handleEditAction(record: Recordable) {
|
||||
openVisualEditor(record);
|
||||
}
|
||||
|
||||
async function handleDeleteAction(record: Recordable) {
|
||||
await deleteAction({ id: record.id }, loadActions);
|
||||
}
|
||||
|
||||
async function handleActionSaved(actionData: Recordable) {
|
||||
const payload = {
|
||||
...actionData,
|
||||
planId: planId.value,
|
||||
enabled: actionData.enabled !== false && actionData.enabled !== 0 ? 1 : 0,
|
||||
};
|
||||
try {
|
||||
if (actionData.id) {
|
||||
await editAction(payload);
|
||||
} else {
|
||||
await saveAction(payload);
|
||||
}
|
||||
createMessage.success('保存成功');
|
||||
await loadActions();
|
||||
} catch (e: any) {
|
||||
createMessage.error(e?.message || '保存失败');
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ open });
|
||||
</script>
|
||||
Reference in New Issue
Block a user