钉钉回调事件处理
This commit is contained in:
@@ -2,13 +2,6 @@ import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
|
||||
const STAGE_DICT = 'mes_xsl_approval_stage';
|
||||
|
||||
function hasStage(values: Recordable, stage: string) {
|
||||
const raw = values?.enabledStages;
|
||||
if (!raw) return false;
|
||||
if (Array.isArray(raw)) return raw.includes(stage);
|
||||
return String(raw).split(',').includes(stage);
|
||||
}
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{ title: '业务编码', dataIndex: 'docCode', width: 140, align: 'left' },
|
||||
{ title: '物理表名', dataIndex: 'tableName', width: 200, align: 'left' },
|
||||
@@ -84,46 +77,11 @@ export const formSchema: FormSchema[] = [
|
||||
componentProps: { placeholder: '默认 status' },
|
||||
},
|
||||
{
|
||||
label: '校对人字段',
|
||||
field: 'proofreadByField',
|
||||
label: '列表接口路径',
|
||||
field: 'listApiPath',
|
||||
component: 'Input',
|
||||
defaultValue: 'proofread_by',
|
||||
ifShow: ({ values }) => hasStage(values, 'proofread'),
|
||||
},
|
||||
{
|
||||
label: '校对时间字段',
|
||||
field: 'proofreadTimeField',
|
||||
component: 'Input',
|
||||
defaultValue: 'proofread_time',
|
||||
ifShow: ({ values }) => hasStage(values, 'proofread'),
|
||||
},
|
||||
{
|
||||
label: '审核人字段',
|
||||
field: 'auditByField',
|
||||
component: 'Input',
|
||||
defaultValue: 'audit_by',
|
||||
ifShow: ({ values }) => hasStage(values, 'audit'),
|
||||
},
|
||||
{
|
||||
label: '审核时间字段',
|
||||
field: 'auditTimeField',
|
||||
component: 'Input',
|
||||
defaultValue: 'audit_time',
|
||||
ifShow: ({ values }) => hasStage(values, 'audit'),
|
||||
},
|
||||
{
|
||||
label: '批准人字段',
|
||||
field: 'approveByField',
|
||||
component: 'Input',
|
||||
defaultValue: 'approve_by',
|
||||
ifShow: ({ values }) => hasStage(values, 'approve'),
|
||||
},
|
||||
{
|
||||
label: '批准时间字段',
|
||||
field: 'approveTimeField',
|
||||
component: 'Input',
|
||||
defaultValue: 'approve_time',
|
||||
ifShow: ({ values }) => hasStage(values, 'approve'),
|
||||
slot: 'listApiPath',
|
||||
helpMessage: '从二级菜单选取后自动填入路径;配置后列表响应自动追加 traceProofreadBy / traceAuditBy / traceApproveBy 等6个字段',
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
{ title: '流程节点', dataIndex: 'nodeName', width: 200 },
|
||||
{ title: '识别环节', dataIndex: 'stage', width: 130 },
|
||||
{ title: '前置状态', dataIndex: 'expectedFromLabel', width: 90 },
|
||||
{ title: '通过后状态', dataIndex: 'statusAfterLabel', width: 100 },
|
||||
{ title: '生成方案', dataIndex: 'willGenerate', width: 88 },
|
||||
{ title: '未配置原因', dataIndex: 'unconfiguredReason', ellipsis: true },
|
||||
];
|
||||
@@ -182,6 +183,12 @@
|
||||
return '环节未完整配置';
|
||||
}
|
||||
|
||||
function resolveStatusAfter(stage?: string, statusChain?: any[]) {
|
||||
if (!stage) return null;
|
||||
const hit = (statusChain || []).find((item) => item.value === stage);
|
||||
return hit ? stage : null;
|
||||
}
|
||||
|
||||
function resolveExpectedFrom(bindings: any[], index: number, statusChain: any[], initialStatus: string) {
|
||||
const current = bindings[index];
|
||||
if (!current?.stage) {
|
||||
@@ -226,6 +233,8 @@
|
||||
record.triggerPhase = null;
|
||||
record.expectedFrom = null;
|
||||
record.expectedFromLabel = '-';
|
||||
record.statusAfter = null;
|
||||
record.statusAfterLabel = '-';
|
||||
return;
|
||||
}
|
||||
const cfgIdx = configuredBindings.indexOf(record);
|
||||
@@ -234,6 +243,9 @@
|
||||
const expectedFrom = resolveExpectedFrom(bindings, bindings.indexOf(record), statusChain, initialStatus);
|
||||
record.expectedFrom = expectedFrom;
|
||||
record.expectedFromLabel = labelOfStatusChain(statusChain, expectedFrom);
|
||||
const statusAfter = resolveStatusAfter(record.stage, statusChain);
|
||||
record.statusAfter = statusAfter;
|
||||
record.statusAfterLabel = statusAfter ? labelOfStatusChain(statusChain, statusAfter) : '需手配';
|
||||
});
|
||||
|
||||
preview.value.configuredNodeCount = configuredBindings.length;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="640" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm" />
|
||||
<BasicForm @register="registerForm">
|
||||
<template #listApiPath="{ model, field }">
|
||||
<RegistryMenuSelect :value="model[field]" @change="(val) => (model[field] = val)" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
@@ -10,6 +14,7 @@
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { formSchema } from '../MesXslBizDocRegistry.data';
|
||||
import { saveOrUpdate } from '../MesXslBizDocRegistry.api';
|
||||
import RegistryMenuSelect from './RegistryMenuSelect.vue';
|
||||
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const isUpdate = ref(false);
|
||||
|
||||
@@ -96,10 +96,11 @@
|
||||
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 after = cfg.registryStage?.statusAfter || cfg.statusAfter || stage;
|
||||
return `环节→${STAGE_LABELS[stage] || stage || '?'}${from ? `,前置=${from}` : ''},通过后=${after}`;
|
||||
}
|
||||
const target = cfg.registryStage?.targetStage || cfg.targetStage || 'compile';
|
||||
return `回退→${target}`;
|
||||
const target = cfg.registryStage?.targetStage ?? cfg.targetStage;
|
||||
return target !== undefined && target !== null && target !== '' ? `回退→${target}` : '回退→未配置';
|
||||
} catch {
|
||||
return record.actionConfig || '-';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-select
|
||||
:value="selectedPaths"
|
||||
mode="multiple"
|
||||
allow-clear
|
||||
show-search
|
||||
placeholder="从二级菜单选取,自动填入列表接口路径;也可在下方直接编辑"
|
||||
:filter-option="filterOption"
|
||||
style="width: 100%"
|
||||
@change="handleSelectChange"
|
||||
>
|
||||
<a-select-opt-group v-for="group in menuGroups" :key="group.path" :label="group.title">
|
||||
<a-select-option
|
||||
v-for="item in group.children"
|
||||
:key="item.apiPath"
|
||||
:value="item.apiPath"
|
||||
:title="item.apiPath"
|
||||
>
|
||||
<span>{{ item.title }}</span>
|
||||
<span style="margin-left: 8px; color: #8c8c8c; font-size: 11px">{{ item.apiPath }}</span>
|
||||
</a-select-option>
|
||||
</a-select-opt-group>
|
||||
</a-select>
|
||||
|
||||
<a-input
|
||||
:value="inputVal"
|
||||
style="margin-top: 6px"
|
||||
placeholder="列表接口路径(多个逗号分隔,可手动编辑)"
|
||||
@change="handleInputChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { usePermissionStoreWithOut } from '/@/store/modules/permission';
|
||||
import type { Menu } from '/@/router/types';
|
||||
|
||||
interface MenuGroup {
|
||||
path: string;
|
||||
title: string;
|
||||
children: { apiPath: string; title: string; path: string }[];
|
||||
}
|
||||
|
||||
const props = defineProps<{ value?: string }>();
|
||||
const emit = defineEmits(['change', 'update:value']);
|
||||
|
||||
const permStore = usePermissionStoreWithOut();
|
||||
|
||||
const menuGroups = computed<MenuGroup[]>(() => {
|
||||
const list = permStore.getBackMenuList as Menu[];
|
||||
if (!list || list.length === 0) return [];
|
||||
const groups: MenuGroup[] = [];
|
||||
for (const parent of list) {
|
||||
if (!parent.children || parent.children.length === 0) continue;
|
||||
const leafChildren = parent.children.filter((c) => !c.hideMenu);
|
||||
if (leafChildren.length === 0) continue;
|
||||
groups.push({
|
||||
path: parent.path,
|
||||
title: (parent.meta?.title as string) || parent.name,
|
||||
children: leafChildren.map((c) => ({
|
||||
path: c.path,
|
||||
apiPath: c.path + '/list',
|
||||
title: (c.meta?.title as string) || c.name,
|
||||
})),
|
||||
});
|
||||
}
|
||||
return groups;
|
||||
});
|
||||
|
||||
const allApiPaths = computed<string[]>(() =>
|
||||
menuGroups.value.flatMap((g) => g.children.map((c) => c.apiPath)),
|
||||
);
|
||||
|
||||
// 当前文本框的值(原始逗号分隔串)
|
||||
const inputVal = ref(props.value || '');
|
||||
|
||||
// 从文本框值解析出在 menuGroups 里的路径(用于 Select 的高亮选中)
|
||||
const selectedPaths = computed<string[]>(() => {
|
||||
if (!inputVal.value) return [];
|
||||
return inputVal.value
|
||||
.split(',')
|
||||
.map((p) => p.trim())
|
||||
.filter((p) => allApiPaths.value.includes(p));
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(val) => {
|
||||
inputVal.value = val || '';
|
||||
},
|
||||
);
|
||||
|
||||
function handleSelectChange(vals: string[]) {
|
||||
// 将已有的手动路径(不在菜单里的)保留,把菜单选取结果合并进去
|
||||
const manualPaths = inputVal.value
|
||||
.split(',')
|
||||
.map((p) => p.trim())
|
||||
.filter((p) => p && !allApiPaths.value.includes(p));
|
||||
const merged = [...manualPaths, ...vals].filter(Boolean).join(',');
|
||||
inputVal.value = merged;
|
||||
emit('change', merged);
|
||||
emit('update:value', merged);
|
||||
}
|
||||
|
||||
function handleInputChange(e: Event) {
|
||||
const val = (e.target as HTMLInputElement).value;
|
||||
inputVal.value = val;
|
||||
emit('change', val);
|
||||
emit('update:value', val);
|
||||
}
|
||||
|
||||
function filterOption(input: string, option: any) {
|
||||
const title = option?.children?.[0]?.children || '';
|
||||
const path = option.value || '';
|
||||
const lc = input.toLowerCase();
|
||||
return String(title).toLowerCase().includes(lc) || String(path).toLowerCase().includes(lc);
|
||||
}
|
||||
</script>
|
||||
@@ -58,7 +58,7 @@
|
||||
type="info"
|
||||
show-icon
|
||||
style="margin-bottom: 14px"
|
||||
message="按审批注册中心配置自动更新源单状态、操作人/时间,并双写审批痕迹明细,无需绑定 Java 校对/审核/批准接口。"
|
||||
message="审批环节仅用于匹配审批流与写入痕迹;业务表 status 由「通过后状态」控制。操作人/时间写入痕迹表,无需绑定 Java 接口。"
|
||||
/>
|
||||
<template v-if="vc.registryStage">
|
||||
<a-form-item v-if="vc.visualType === 'REGISTRY_STAGE_SYNC'" label="审批环节" required>
|
||||
@@ -73,6 +73,9 @@
|
||||
<div v-if="!registryStageOptions.length" style="font-size: 12px; color: #faad14; margin-top: 4px">
|
||||
未配置启用环节,请先在审批注册中心配置 enabled_stages
|
||||
</div>
|
||||
<div v-else style="font-size: 12px; color: #888; margin-top: 4px">
|
||||
仅参与审批流匹配与痕迹同步(proofread/audit/approve),不会直接写入业务表 status。
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="vc.visualType === 'REGISTRY_STAGE_SYNC'" label="前置状态">
|
||||
<a-select
|
||||
@@ -88,24 +91,45 @@
|
||||
<a-input
|
||||
v-else
|
||||
v-model:value="vc.registryStage.expectedFrom"
|
||||
placeholder="未解析到状态字典,可手填 compile / proofread / audit"
|
||||
placeholder="未解析到状态字典,可手填状态字典值"
|
||||
/>
|
||||
<div style="font-size: 12px; color: #888; margin-top: 4px">
|
||||
取自触发表「{{ sourceStatusFieldName }}」字段字典{{ sourceStatusDictCode ? `(${sourceStatusDictCode})` : '' }};留空则自动推断。仅当前状态等于此前置值时才执行。
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="vc.visualType === 'REGISTRY_STAGE_REVERT'" label="回退目标">
|
||||
<a-form-item v-if="vc.visualType === 'REGISTRY_STAGE_SYNC'" label="通过后状态" required>
|
||||
<a-select
|
||||
v-if="sourceStatusDictItems.length"
|
||||
v-model:value="vc.registryStage.targetStage"
|
||||
v-model:value="vc.registryStage.statusAfter"
|
||||
:options="sourceStatusDictItems"
|
||||
placeholder="默认 compile(编制态)"
|
||||
allow-clear
|
||||
placeholder="请选择本环节通过后业务表应变为的状态"
|
||||
show-search
|
||||
option-filter-prop="label"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<a-input v-else v-model:value="vc.registryStage.targetStage" placeholder="默认 compile(编制态)" />
|
||||
<a-input
|
||||
v-else
|
||||
v-model:value="vc.registryStage.statusAfter"
|
||||
placeholder="未解析到状态字典,可手填业务状态值"
|
||||
/>
|
||||
<div style="font-size: 12px; color: #888; margin-top: 4px">
|
||||
本环节审批通过后,将触发表「{{ sourceStatusFieldName }}」更新为此值(与审批环节码无关,按各单据自己的状态字典配置)。
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="vc.visualType === 'REGISTRY_STAGE_REVERT'" label="回退目标" required>
|
||||
<a-select
|
||||
v-if="sourceStatusDictItems.length"
|
||||
v-model:value="vc.registryStage.targetStage"
|
||||
:options="sourceStatusDictItems"
|
||||
placeholder="请选择驳回后回退到的业务状态"
|
||||
show-search
|
||||
option-filter-prop="label"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<a-input v-else v-model:value="vc.registryStage.targetStage" placeholder="未解析到状态字典,可手填字典键值(item_value)" />
|
||||
<div style="font-size: 12px; color: #888; margin-top: 4px">
|
||||
保存为字典键值(item_value),执行时原样写入触发表「{{ sourceStatusFieldName }}」,与界面显示文字无关。
|
||||
</div>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</template>
|
||||
@@ -305,6 +329,7 @@
|
||||
interface RegistryStageConfig {
|
||||
stage?: string;
|
||||
expectedFrom?: string;
|
||||
statusAfter?: string;
|
||||
targetStage?: string;
|
||||
}
|
||||
|
||||
@@ -321,10 +346,18 @@
|
||||
const emit = defineEmits<{ success: [action: any] }>();
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
/** 审批环节码固定中文名(与业务 status 字典无关) */
|
||||
const APPROVAL_STAGE_LABELS: Record<string, string> = {
|
||||
proofread: '校对',
|
||||
audit: '审核',
|
||||
approve: '批准',
|
||||
};
|
||||
|
||||
/** 触发表 status 字段未带字典注释时的兜底映射 */
|
||||
const SOURCE_TABLE_STATUS_DICT: Record<string, string> = {
|
||||
mes_xsl_mixer_ps_compile: 'xslmes_mixer_ps_status',
|
||||
mes_xsl_formula_spec: 'xslmes_formula_spec_status',
|
||||
mes_xsl_raw_material_entry: 'xslmes_entry_status',
|
||||
};
|
||||
|
||||
/** 目标表 status 字段未带字典注释时的兜底映射 */
|
||||
@@ -362,7 +395,7 @@
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
.map((v) => ({ value: v, label: dictLabelMap[v] || v }));
|
||||
.map((v) => ({ value: v, label: APPROVAL_STAGE_LABELS[v] || dictLabelMap[v] || v }));
|
||||
});
|
||||
const targetColumns = ref<ColMeta[]>([]);
|
||||
|
||||
@@ -387,6 +420,7 @@
|
||||
const defaultRegistryStage = (): RegistryStageConfig => ({
|
||||
stage: '',
|
||||
expectedFrom: '',
|
||||
statusAfter: '',
|
||||
targetStage: '',
|
||||
});
|
||||
|
||||
@@ -428,7 +462,12 @@
|
||||
if (parsed.expectedFrom !== undefined && parsed.expectedFrom !== null) {
|
||||
merged.registryStage!.expectedFrom = parsed.expectedFrom;
|
||||
}
|
||||
if (parsed.targetStage) merged.registryStage!.targetStage = parsed.targetStage;
|
||||
if (parsed.statusAfter !== undefined && parsed.statusAfter !== null) {
|
||||
merged.registryStage!.statusAfter = parsed.statusAfter;
|
||||
}
|
||||
if (parsed.targetStage !== undefined && parsed.targetStage !== null) {
|
||||
merged.registryStage!.targetStage = parsed.targetStage;
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
@@ -461,7 +500,7 @@
|
||||
},
|
||||
);
|
||||
|
||||
// 审批环节变化时,前置状态留空则填入默认推断值
|
||||
// 审批环节变化时,前置/通过后状态留空则填入默认推断值
|
||||
watch(
|
||||
() => vc.value.registryStage?.stage,
|
||||
(stage) => {
|
||||
@@ -469,6 +508,9 @@
|
||||
if (!vc.value.registryStage.expectedFrom) {
|
||||
vc.value.registryStage.expectedFrom = defaultExpectedFromForStage(stage);
|
||||
}
|
||||
if (!vc.value.registryStage.statusAfter) {
|
||||
vc.value.registryStage.statusAfter = defaultStatusAfterForStage(stage);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -548,6 +590,16 @@
|
||||
return items.length ? items[0].value : '';
|
||||
}
|
||||
|
||||
/** 推断通过后业务状态:字典含环节码时用环节码,否则不自动填充(需用户手选) */
|
||||
function defaultStatusAfterForStage(stage?: string): string {
|
||||
if (!stage) return '';
|
||||
const items = sourceStatusDictItems.value;
|
||||
if (items.some((i) => i.value === stage)) {
|
||||
return stage;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function defaultRevertTargetStage(): string {
|
||||
const items = sourceStatusDictItems.value;
|
||||
if (!items.length) return 'compile';
|
||||
@@ -565,7 +617,12 @@
|
||||
if (config.registryStage?.expectedFrom !== undefined && config.registryStage?.expectedFrom !== null) {
|
||||
payload.expectedFrom = config.registryStage.expectedFrom;
|
||||
}
|
||||
if (config.registryStage?.targetStage) payload.targetStage = config.registryStage.targetStage;
|
||||
if (config.registryStage?.statusAfter !== undefined && config.registryStage?.statusAfter !== null) {
|
||||
payload.statusAfter = config.registryStage.statusAfter;
|
||||
}
|
||||
if (config.registryStage?.targetStage !== undefined && config.registryStage?.targetStage !== null) {
|
||||
payload.targetStage = config.registryStage.targetStage;
|
||||
}
|
||||
return JSON.stringify(payload);
|
||||
}
|
||||
|
||||
@@ -607,6 +664,7 @@
|
||||
if (type === 'REGISTRY_STAGE_SYNC' && registryStageOptions.value.length && !vc.value.registryStage?.stage) {
|
||||
vc.value.registryStage!.stage = registryStageOptions.value[0].value;
|
||||
vc.value.registryStage!.expectedFrom = defaultExpectedFromForStage(vc.value.registryStage!.stage);
|
||||
vc.value.registryStage!.statusAfter = defaultStatusAfterForStage(vc.value.registryStage!.stage);
|
||||
}
|
||||
if (type === 'REGISTRY_STAGE_REVERT' && !vc.value.registryStage?.targetStage) {
|
||||
vc.value.registryStage!.targetStage = defaultRevertTargetStage();
|
||||
@@ -687,6 +745,7 @@
|
||||
if (registryStageOptions.value.length) {
|
||||
vc.value.registryStage!.stage = registryStageOptions.value[0].value;
|
||||
vc.value.registryStage!.expectedFrom = defaultExpectedFromForStage(vc.value.registryStage!.stage);
|
||||
vc.value.registryStage!.statusAfter = defaultStatusAfterForStage(vc.value.registryStage!.stage);
|
||||
}
|
||||
vc.value.registryStage!.targetStage = defaultRevertTargetStage();
|
||||
formRef.value?.clearValidate?.();
|
||||
@@ -702,6 +761,10 @@
|
||||
createMessage.warning('请选择审批环节');
|
||||
return;
|
||||
}
|
||||
if (!vc.value.registryStage?.statusAfter) {
|
||||
createMessage.warning('请选择通过后状态');
|
||||
return;
|
||||
}
|
||||
emit('success', {
|
||||
...form.value,
|
||||
actionType: 'REGISTRY_STAGE_SYNC',
|
||||
@@ -712,6 +775,10 @@
|
||||
return;
|
||||
}
|
||||
if (vc.value.visualType === 'REGISTRY_STAGE_REVERT') {
|
||||
if (vc.value.registryStage?.targetStage === undefined || vc.value.registryStage?.targetStage === null || vc.value.registryStage?.targetStage === '') {
|
||||
createMessage.warning('请选择回退目标(业务状态字典项)');
|
||||
return;
|
||||
}
|
||||
emit('success', {
|
||||
...form.value,
|
||||
actionType: 'REGISTRY_STAGE_REVERT',
|
||||
@@ -777,10 +844,19 @@
|
||||
}
|
||||
|
||||
await loadSourceStatusDict();
|
||||
// 旧数据兼容:未配置 statusAfter 时,若字典含环节码则回填,否则保持空由用户手选
|
||||
if (isUpdate.value && vc.value.registryStage?.stage && !vc.value.registryStage?.statusAfter) {
|
||||
const legacy = defaultStatusAfterForStage(vc.value.registryStage.stage);
|
||||
if (legacy) {
|
||||
vc.value.registryStage.statusAfter = legacy;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isUpdate.value) {
|
||||
if (registryStageOptions.value.length && !vc.value.registryStage?.stage) {
|
||||
vc.value.registryStage!.stage = registryStageOptions.value[0].value;
|
||||
vc.value.registryStage!.expectedFrom = defaultExpectedFromForStage(vc.value.registryStage!.stage);
|
||||
vc.value.registryStage!.statusAfter = defaultStatusAfterForStage(vc.value.registryStage!.stage);
|
||||
}
|
||||
if (!vc.value.registryStage?.targetStage) {
|
||||
vc.value.registryStage!.targetStage = defaultRevertTargetStage();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
|
||||
/**
|
||||
* 按 sentinel key 分组的审批痕迹列。
|
||||
* key = 后端注入的字段名(traceProofreadBy / traceAuditBy / traceApproveBy)
|
||||
* 只要响应里出现该 key,就注入对应两列。
|
||||
*/
|
||||
export const traceColumnsByStage: Record<string, BasicColumn[]> = {
|
||||
traceProofreadBy: [
|
||||
{ title: '校对人', dataIndex: 'traceProofreadBy', width: 100, align: 'center', defaultHidden: true },
|
||||
{ title: '校对时间', dataIndex: 'traceProofreadTime', width: 165, align: 'center', defaultHidden: true },
|
||||
],
|
||||
traceAuditBy: [
|
||||
{ title: '审核人', dataIndex: 'traceAuditBy', width: 100, align: 'center', defaultHidden: true },
|
||||
{ title: '审核时间', dataIndex: 'traceAuditTime', width: 165, align: 'center', defaultHidden: true },
|
||||
],
|
||||
traceApproveBy: [
|
||||
{ title: '批准人', dataIndex: 'traceApproveBy', width: 100, align: 'center', defaultHidden: true },
|
||||
{ title: '批准时间', dataIndex: 'traceApproveTime', width: 165, align: 'center', defaultHidden: true },
|
||||
],
|
||||
};
|
||||
|
||||
/** 全量痕迹列(密炼PS等已知需要全部的场景直接引用) */
|
||||
export const traceColumns: BasicColumn[] = Object.values(traceColumnsByStage).flat();
|
||||
@@ -0,0 +1,16 @@
|
||||
import { useTable } from '/@/components/Table';
|
||||
import type { BasicTableProps } from '/@/components/Table';
|
||||
import { traceColumns } from './traceColumns';
|
||||
|
||||
/**
|
||||
* 替换 useTable(不经过 useListPage 的特殊场景):自动追加审批痕迹列(默认隐藏)。
|
||||
* 普通列表页已由 useListPage 统一注入,无需使用本函数。
|
||||
*/
|
||||
export function useTraceTable(tableProps: BasicTableProps) {
|
||||
const columns = tableProps.columns as any[] | undefined;
|
||||
const alreadyHasTrace = columns?.some((c) => c.dataIndex === 'traceProofreadBy');
|
||||
return useTable({
|
||||
...tableProps,
|
||||
columns: alreadyHasTrace ? columns : [...(columns ?? []), ...traceColumns],
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user