|
|
@@ -1973,21 +1973,31 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
console.log('当前 workflowWorkNodeDOList:', workflowWorkNodeDOList);
|
|
|
|
|
|
if (nodeDO) {
|
|
|
- // 如果找到节点数据,解析data字段并回显
|
|
|
+ const isReleaseIsolation = nodeDO.type === 'releaseIsolation' || nodeDO.type === '解除隔离';
|
|
|
+ const isolationNodeUuid = nodeDO.isolationNodeUuid || '';
|
|
|
+ // 解除隔离节点:从对应的隔离/方案节点抓取表单信息填充,保证两节点内容一致
|
|
|
+ const isolationNodeDO = isReleaseIsolation && isolationNodeUuid
|
|
|
+ ? workflowWorkNodeDOList.find(
|
|
|
+ (item: WorkflowWorkNodeDO) =>
|
|
|
+ item.uuid === isolationNodeUuid &&
|
|
|
+ (item.type === 'isolation' || item.type === '隔离' || item.type === '隔离/方案')
|
|
|
+ )
|
|
|
+ : null;
|
|
|
+ const dataSource = isolationNodeDO ?? nodeDO;
|
|
|
let nodeData: any = {};
|
|
|
- if (nodeDO.data) {
|
|
|
+ if (dataSource.data) {
|
|
|
try {
|
|
|
- nodeData = typeof nodeDO.data === 'string' ? JSON.parse(nodeDO.data) : nodeDO.data;
|
|
|
+ nodeData = typeof dataSource.data === 'string' ? JSON.parse(dataSource.data) : dataSource.data;
|
|
|
} catch (e) {
|
|
|
console.error('解析节点data失败:', e);
|
|
|
}
|
|
|
}
|
|
|
+ const source = nodeData || node.data || {};
|
|
|
|
|
|
- // 从 nodeUserList 中提取上锁人和共锁人
|
|
|
let lockPersonId: string | number = '';
|
|
|
const coLockPersonIds: (string | number)[] = [];
|
|
|
- if (nodeDO.nodeUserList && Array.isArray(nodeDO.nodeUserList)) {
|
|
|
- nodeDO.nodeUserList.forEach((user: any) => {
|
|
|
+ if (dataSource.nodeUserList && Array.isArray(dataSource.nodeUserList)) {
|
|
|
+ dataSource.nodeUserList.forEach((user: any) => {
|
|
|
if (user.type === 'jtlocker' && user.userId) {
|
|
|
lockPersonId = typeof user.userId === 'number' ? user.userId : Number(user.userId);
|
|
|
} else if (user.type === 'jtcolocker' && user.userId) {
|
|
|
@@ -1996,76 +2006,57 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- // 优先使用 nodeDO 中的数据(编辑时从后端获取的真实数据)
|
|
|
- // 如果 nodeDO 存在且有 id,说明是已保存的节点,优先使用 nodeDO 的数据
|
|
|
- const source = nodeData || node.data || {};
|
|
|
const config = nodeConfigs.find(c => c.type === (nodeDO.type || source.type));
|
|
|
|
|
|
- // 解析隔离点
|
|
|
let isolationPoints: string[] = [];
|
|
|
- if (nodeDO.isolationPoints) {
|
|
|
+ if (dataSource.isolationPoints) {
|
|
|
try {
|
|
|
- isolationPoints = typeof nodeDO.isolationPoints === 'string'
|
|
|
- ? JSON.parse(nodeDO.isolationPoints)
|
|
|
- : (Array.isArray(nodeDO.isolationPoints) ? nodeDO.isolationPoints : []);
|
|
|
+ isolationPoints = typeof dataSource.isolationPoints === 'string'
|
|
|
+ ? JSON.parse(dataSource.isolationPoints)
|
|
|
+ : (Array.isArray(dataSource.isolationPoints) ? dataSource.isolationPoints : []);
|
|
|
} catch (e) {
|
|
|
- console.error('解析隔离点失败:', e);
|
|
|
isolationPoints = source.isolationPoints || [];
|
|
|
}
|
|
|
} else {
|
|
|
isolationPoints = source.isolationPoints || [];
|
|
|
}
|
|
|
|
|
|
- // 构建节点配置,优先使用 nodeDO 中的数据
|
|
|
- console.log('构建节点配置 - nodeDO.workerUserId:', nodeDO.workerUserId, 'source.workerUserId:', source.workerUserId);
|
|
|
const nodeConfig = {
|
|
|
- nodeName: nodeDO.nodeName || source.label || config?.label || '',
|
|
|
- nodeIcon: nodeDO.nodeIcon || source.icon || '',
|
|
|
- responsible: (nodeDO.workerUserId !== null && nodeDO.workerUserId !== undefined && nodeDO.workerUserId !== 0)
|
|
|
- ? (typeof nodeDO.workerUserId === 'number' ? nodeDO.workerUserId : Number(nodeDO.workerUserId))
|
|
|
- : (source.workerUserId && source.workerUserId !== '' && source.workerUserId !== '0')
|
|
|
- ? (typeof source.workerUserId === 'number' ? source.workerUserId : Number(source.workerUserId))
|
|
|
+ nodeName: dataSource.nodeName || source.label || config?.label || '',
|
|
|
+ nodeIcon: (isolationNodeDO ? nodeDO.nodeIcon : dataSource.nodeIcon) || source.icon || '',
|
|
|
+ responsible: (dataSource.workerUserId !== null && dataSource.workerUserId !== undefined && dataSource.workerUserId !== 0)
|
|
|
+ ? (typeof dataSource.workerUserId === 'number' ? dataSource.workerUserId : Number(dataSource.workerUserId))
|
|
|
+ : (source.workerUserId && source.workerUserId !== '' && source.workerUserId !== '0')
|
|
|
+ ? (typeof source.workerUserId === 'number' ? source.workerUserId : Number(source.workerUserId))
|
|
|
: undefined,
|
|
|
remark: source.remark || '',
|
|
|
- submitForm: nodeDO.formId ? (typeof nodeDO.formId === 'number' ? nodeDO.formId : Number(nodeDO.formId)) : (source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined),
|
|
|
- isolationType: (nodeDO.isolationType !== null && nodeDO.isolationType !== undefined) ? String(nodeDO.isolationType) : (source.isolationType || ''),
|
|
|
- isolationPoints: isolationPoints,
|
|
|
+ submitForm: dataSource.formId ? (typeof dataSource.formId === 'number' ? dataSource.formId : Number(dataSource.formId)) : (source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined),
|
|
|
+ isolationType: (dataSource.isolationType !== null && dataSource.isolationType !== undefined) ? String(dataSource.isolationType) : (source.isolationType || ''),
|
|
|
+ isolationPoints,
|
|
|
isolationNode: source.isolationNode || [],
|
|
|
isolationNodeUuid: nodeDO.isolationNodeUuid || source.isolationNodeUuid || '',
|
|
|
lockPerson: lockPersonId || (source.lockPerson ? (typeof source.lockPerson === 'number' ? source.lockPerson : Number(source.lockPerson)) : undefined),
|
|
|
coLockPersons: coLockPersonIds.length > 0 ? coLockPersonIds : (source.coLockPersons && Array.isArray(source.coLockPersons) ? source.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : []),
|
|
|
- notificationMethods: source.notificationMethods || {
|
|
|
- sms: false,
|
|
|
- message: false,
|
|
|
- email: false,
|
|
|
- app: false,
|
|
|
- },
|
|
|
+ notificationMethods: source.notificationMethods || { sms: false, message: false, email: false, app: false },
|
|
|
notificationPerson: source.notificationPerson || '',
|
|
|
- notificationTime: nodeDO.notifyTime || source.notificationTime || '',
|
|
|
+ notificationTime: dataSource.notifyTime || source.notificationTime || '',
|
|
|
smsTemplateCode: source.smsTemplateCode || 'false',
|
|
|
messageTemplateCode: source.messageTemplateCode || 'false',
|
|
|
emailTemplateCode: source.emailTemplateCode || 'false',
|
|
|
appTemplateCode: source.appTemplateCode || 'false',
|
|
|
};
|
|
|
|
|
|
- // 优先使用缓存中的配置(如果有),这样可以保持用户未保存的修改
|
|
|
- // 如果缓存中没有,再使用 nodeDO 的数据
|
|
|
- console.log('设置节点配置 - nodeConfig.responsible:', nodeConfig.responsible, 'node.id:', node.id);
|
|
|
- const cachedConfig = workflowNodeConfigCache.get(node.id);
|
|
|
- console.log('缓存中的配置:', cachedConfig);
|
|
|
- if (cachedConfig) {
|
|
|
- // 如果缓存中有配置,使用缓存(可能包含用户未保存的修改)
|
|
|
- console.log('使用缓存配置');
|
|
|
- // 使用函数式更新确保状态正确更新
|
|
|
- setWorkflowNodeConfig(() => ({ ...cachedConfig }));
|
|
|
- } else if (nodeDO.id) {
|
|
|
- // 如果缓存中没有,但节点已保存,使用 nodeDO 的数据
|
|
|
- console.log('使用 nodeDO 配置');
|
|
|
+ if (isReleaseIsolation && isolationNodeDO) {
|
|
|
setWorkflowNodeConfig(() => ({ ...nodeConfig }));
|
|
|
} else {
|
|
|
- // 如果既没有缓存也没有保存,使用节点数据
|
|
|
- console.log('使用节点数据配置');
|
|
|
- setWorkflowNodeConfig(() => ({ ...nodeConfig }));
|
|
|
+ const cachedConfig = workflowNodeConfigCache.get(node.id);
|
|
|
+ if (cachedConfig) {
|
|
|
+ setWorkflowNodeConfig(() => ({ ...cachedConfig }));
|
|
|
+ } else if (nodeDO.id) {
|
|
|
+ setWorkflowNodeConfig(() => ({ ...nodeConfig }));
|
|
|
+ } else {
|
|
|
+ setWorkflowNodeConfig(() => ({ ...nodeConfig }));
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
// 如果没有找到节点数据,使用原有逻辑
|
|
|
@@ -4637,7 +4628,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
placeholder="请选择提交表单"
|
|
|
className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
|
|
|
allowClear
|
|
|
- disabled={isViewMode}
|
|
|
+ disabled={isViewMode || selectedWorkflowNode.data?.type === 'releaseIsolation'}
|
|
|
>
|
|
|
{workflowFormList.map(form => (
|
|
|
<Select.Option key={form.id} value={form.id}>{form.name}</Select.Option>
|
|
|
@@ -4954,7 +4945,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
smsTemplateCode: e.target.checked ? 'true' : 'false',
|
|
|
})
|
|
|
}
|
|
|
- disabled={isViewMode}
|
|
|
+ disabled={isViewMode || selectedWorkflowNode.data?.type === 'releaseIsolation'}
|
|
|
>
|
|
|
短信
|
|
|
</Checkbox>
|
|
|
@@ -4972,7 +4963,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
messageTemplateCode: e.target.checked ? 'true' : 'false',
|
|
|
})
|
|
|
}
|
|
|
- disabled={isViewMode}
|
|
|
+ disabled={isViewMode || selectedWorkflowNode.data?.type === 'releaseIsolation'}
|
|
|
>
|
|
|
站内信
|
|
|
</Checkbox>
|
|
|
@@ -4990,7 +4981,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
emailTemplateCode: e.target.checked ? 'true' : 'false',
|
|
|
})
|
|
|
}
|
|
|
- disabled={isViewMode}
|
|
|
+ disabled={isViewMode || selectedWorkflowNode.data?.type === 'releaseIsolation'}
|
|
|
>
|
|
|
邮件
|
|
|
</Checkbox>
|
|
|
@@ -5008,7 +4999,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
appTemplateCode: e.target.checked ? 'true' : 'false',
|
|
|
})
|
|
|
}
|
|
|
- disabled={isViewMode}
|
|
|
+ disabled={isViewMode || selectedWorkflowNode.data?.type === 'releaseIsolation'}
|
|
|
>
|
|
|
APP通知
|
|
|
</Checkbox>
|
|
|
@@ -5093,6 +5084,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
|
|
|
// 在外部作用域定义,确保在自动切换节点时可以使用
|
|
|
let mergedWorkflowWorkNodeDOList: WorkflowWorkNodeDO[] = [];
|
|
|
+ let didRefreshFlowNodes = false; // 是否已用合并列表刷新过画布所有节点
|
|
|
|
|
|
if (nodeDO && nodeDO.id && workflowWorkId) {
|
|
|
// 构建节点用户信息列表
|
|
|
@@ -5164,6 +5156,14 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 从 nodeUserDOList 派生 lockPerson(jtlocker 的 userId 字符串)、colockPersons(jtcolocker 的 userId 字符串,如 "[181,182]")
|
|
|
+ const lockPersonEntry = nodeUserDOList.find((u: any) => u.type === 'jtlocker');
|
|
|
+ const lockPerson = lockPersonEntry?.userId != null ? String(lockPersonEntry.userId) : undefined;
|
|
|
+ const colockPersonIds = nodeUserDOList
|
|
|
+ .filter((u: any) => u.type === 'jtcolocker' && u.userId != null)
|
|
|
+ .map((u: any) => Number(u.userId));
|
|
|
+ const colockPersons = colockPersonIds.length > 0 ? JSON.stringify(colockPersonIds) : undefined;
|
|
|
+
|
|
|
const updateParam: UpdateWorkflowWorkNodeParam = {
|
|
|
nodeId: nodeDO.id,
|
|
|
nodeName: workflowNodeConfig.nodeName,
|
|
|
@@ -5178,6 +5178,8 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
? workflowNodeConfig.isolationNodeUuid
|
|
|
: undefined,
|
|
|
nodeUserDOList: nodeUserDOList.length > 0 ? nodeUserDOList : undefined,
|
|
|
+ lockPerson,
|
|
|
+ colockPersons: colockPersons.length > 0 ? colockPersons : undefined,
|
|
|
// 如果获取到了表单数据,将整个对象内容转换成字符串传递给 formData 字段
|
|
|
formData: formData,
|
|
|
// 根据选中值传递模板代码参数(字符串类型的 'true' 或 'false')
|
|
|
@@ -5189,19 +5191,99 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
|
|
|
await workJobApi.updateWorkflowWorkNode(updateParam);
|
|
|
|
|
|
- // 更新成功后,立即调用详情接口获取最新数据
|
|
|
- let mergedWorkflowWorkNodeDOList: WorkflowWorkNodeDO[] = [];
|
|
|
+ // 若是隔离/方案节点且含上锁人/共锁人:先本地复刻到对应解除隔离节点并刷新画布,保证切换节点时立即看到一致数据(不依赖详情接口)
|
|
|
+ const isIsolationWithLock = (selectedWorkflowNode.data?.type === 'isolation' || selectedWorkflowNode.data?.type === '隔离' || selectedWorkflowNode.data?.type === '隔离/方案') &&
|
|
|
+ workflowNodeConfig.isolationType === '1' && nodeUserDOList.length > 0;
|
|
|
+ if (isIsolationWithLock) {
|
|
|
+ const listForSync = workflowWorkNodeDOList.map((item: WorkflowWorkNodeDO) => {
|
|
|
+ if ((item.type === 'releaseIsolation' || item.type === '解除隔离') && item.isolationNodeUuid === selectedWorkflowNode.id) {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ nodeUserList: nodeUserDOList.map((u: any) => ({ userId: u.userId, type: u.type, ...(u.userName != null && { userName: u.userName }) })),
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+ setWorkflowWorkNodeDOList(listForSync);
|
|
|
+ const releaseUuids = listForSync
|
|
|
+ .filter((n: WorkflowWorkNodeDO) => (n.type === 'releaseIsolation' || n.type === '解除隔离') && n.isolationNodeUuid === selectedWorkflowNode.id)
|
|
|
+ .map((n: WorkflowWorkNodeDO) => n.uuid).filter((id: any) => id != null && id !== '');
|
|
|
+ if (releaseUuids.length > 0) {
|
|
|
+ setWorkflowNodeConfigCache(prev => {
|
|
|
+ const next = new Map(prev);
|
|
|
+ releaseUuids.forEach((uuid: any) => next.delete(uuid));
|
|
|
+ return next;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ setWorkflowNodes((nds) =>
|
|
|
+ nds.map((node) => {
|
|
|
+ const nodeDO = listForSync.find((item: WorkflowWorkNodeDO) => item.uuid === node.id);
|
|
|
+ if (!nodeDO) return node.id === selectedWorkflowNode.id ? { ...node, data: { ...node.data, completed: true }, selected: false } : node;
|
|
|
+ let nodeData: any = {};
|
|
|
+ if (nodeDO.data) {
|
|
|
+ try {
|
|
|
+ nodeData = typeof nodeDO.data === 'string' ? JSON.parse(nodeDO.data) : nodeDO.data;
|
|
|
+ } catch (e) {}
|
|
|
+ }
|
|
|
+ const source = nodeData || node.data || {};
|
|
|
+ let lockPersonVal: string | number | undefined = undefined;
|
|
|
+ const coLockPersonIds: (string | number)[] = [];
|
|
|
+ if (nodeDO.nodeUserList && Array.isArray(nodeDO.nodeUserList)) {
|
|
|
+ nodeDO.nodeUserList.forEach((user: any) => {
|
|
|
+ if (user.type === 'jtlocker' && user.userId != null) {
|
|
|
+ lockPersonVal = typeof user.userId === 'number' ? user.userId : Number(user.userId);
|
|
|
+ } else if (user.type === 'jtcolocker' && user.userId != null) {
|
|
|
+ coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ let isolationPoints: string[] = [];
|
|
|
+ if (nodeDO.isolationPoints) {
|
|
|
+ try {
|
|
|
+ isolationPoints = typeof nodeDO.isolationPoints === 'string' ? JSON.parse(nodeDO.isolationPoints) : (Array.isArray(nodeDO.isolationPoints) ? nodeDO.isolationPoints : []);
|
|
|
+ } catch (e) {}
|
|
|
+ } else {
|
|
|
+ isolationPoints = source.isolationPoints || [];
|
|
|
+ }
|
|
|
+ const config = nodeConfigs.find((c: any) => c.type === (nodeDO.type || source.type));
|
|
|
+ const isCurrent = node.id === selectedWorkflowNode.id;
|
|
|
+ const updatedData = {
|
|
|
+ ...source,
|
|
|
+ label: nodeDO.nodeName || source.label || config?.label || '',
|
|
|
+ icon: nodeDO.nodeIcon || source.icon || '',
|
|
|
+ responsible: (nodeDO.workerUserId !== null && nodeDO.workerUserId !== undefined && nodeDO.workerUserId !== 0) ? nodeDO.workerUserId : source.responsible,
|
|
|
+ remark: source.remark ?? '',
|
|
|
+ submitForm: nodeDO.formId ?? source.submitForm,
|
|
|
+ isolationType: (nodeDO.isolationType != null && nodeDO.isolationType !== '') ? String(nodeDO.isolationType) : (source.isolationType ?? ''),
|
|
|
+ isolationPoints,
|
|
|
+ isolationNode: source.isolationNode || [],
|
|
|
+ isolationNodeUuid: nodeDO.isolationNodeUuid ?? source.isolationNodeUuid ?? '',
|
|
|
+ lockPerson: lockPersonVal !== undefined ? lockPersonVal : source.lockPerson,
|
|
|
+ coLockPersons: coLockPersonIds.length > 0 ? coLockPersonIds : (source.coLockPersons || []),
|
|
|
+ notificationMethods: source.notificationMethods || { sms: false, message: false, email: false, app: false },
|
|
|
+ notificationPerson: source.notificationPerson ?? '',
|
|
|
+ notificationTime: nodeDO.notifyTime ?? source.notificationTime ?? '',
|
|
|
+ completed: isCurrent ? true : (node.data?.completed ?? false),
|
|
|
+ };
|
|
|
+ return { ...node, data: updatedData, selected: isCurrent ? false : node.selected };
|
|
|
+ })
|
|
|
+ );
|
|
|
+ didRefreshFlowNodes = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新成功后,再调作业详情接口获取最新数据并合并(可选,用于其他字段与后端一致)
|
|
|
if (workflowWorkId) {
|
|
|
try {
|
|
|
const detailResponse = await workJobApi.selectWorkflowWorkById(workflowWorkId);
|
|
|
- const detail = detailResponse as any;
|
|
|
- if (detail.workflowWorkNodeDOList && Array.isArray(detail.workflowWorkNodeDOList)) {
|
|
|
+ const detailRaw = detailResponse as any;
|
|
|
+ const detail = detailRaw?.data != null ? detailRaw.data : detailRaw;
|
|
|
+ const nodeListFromApi = detail?.workflowWorkNodeDOList;
|
|
|
+ if (nodeListFromApi && Array.isArray(nodeListFromApi)) {
|
|
|
// 使用接口返回的最新数据更新 workflowWorkNodeDOList
|
|
|
// 合并更新:保留现有数据,只更新接口返回的数据
|
|
|
- // 先计算合并后的数据,然后再更新状态
|
|
|
const prev = workflowWorkNodeDOList;
|
|
|
console.log('合并更新前的 workflowWorkNodeDOList:', prev);
|
|
|
- console.log('接口返回的 workflowWorkNodeDOList:', detail.workflowWorkNodeDOList);
|
|
|
+ console.log('接口返回的 workflowWorkNodeDOList:', nodeListFromApi);
|
|
|
|
|
|
// 创建一个映射,方便查找
|
|
|
const prevMap = new Map<string | number, WorkflowWorkNodeDO>();
|
|
|
@@ -5210,7 +5292,21 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
if (item.uuid) prevMap.set(item.uuid, item);
|
|
|
});
|
|
|
|
|
|
- const updatedList = detail.workflowWorkNodeDOList.map((newItem: WorkflowWorkNodeDO) => {
|
|
|
+ const updatedList = nodeListFromApi.map((newItem: WorkflowWorkNodeDO) => {
|
|
|
+ // 解除隔离节点且对应本次保存的隔离/方案节点:用本次保存的隔离方案数据复刻到解除隔离节点(上锁人/共锁人),保证与隔离方案一致
|
|
|
+ const isReleaseForCurrentIsolation =
|
|
|
+ (newItem.type === 'releaseIsolation' || newItem.type === '解除隔离') &&
|
|
|
+ newItem.isolationNodeUuid === selectedWorkflowNode.id;
|
|
|
+ if (isReleaseForCurrentIsolation) {
|
|
|
+ const copiedNodeUserList = nodeUserDOList.length > 0
|
|
|
+ ? nodeUserDOList.map((u: any) => ({ userId: u.userId, type: u.type, ...(u.userName != null && { userName: u.userName }) }))
|
|
|
+ : [];
|
|
|
+ return {
|
|
|
+ ...newItem,
|
|
|
+ nodeUserList: copiedNodeUserList,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
// 查找现有列表中对应的节点(通过 id 或 uuid 匹配)
|
|
|
const existingItem = (newItem.id && prevMap.get(newItem.id)) ||
|
|
|
(newItem.uuid && prevMap.get(newItem.uuid)) ||
|
|
|
@@ -5218,43 +5314,28 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
|
|
|
// 如果找到现有节点,合并数据(优先使用接口返回的数据,但保留现有数据中接口没有返回的字段)
|
|
|
if (existingItem) {
|
|
|
- // 合并数据,确保关键字段不被覆盖为空
|
|
|
- // 只有当接口返回的值是有效的(不是 null、undefined、0 或空字符串)时,才使用接口的值
|
|
|
const merged: WorkflowWorkNodeDO = {
|
|
|
...existingItem,
|
|
|
...newItem,
|
|
|
- // 如果接口返回的 workerUserId 是 null、undefined 或 0,保留现有的值
|
|
|
workerUserId: (newItem.workerUserId !== null && newItem.workerUserId !== undefined && newItem.workerUserId !== 0)
|
|
|
? newItem.workerUserId
|
|
|
: existingItem.workerUserId,
|
|
|
- // 如果接口返回的 formId 是 null、undefined 或 0,保留现有的值
|
|
|
formId: (newItem.formId !== null && newItem.formId !== undefined && newItem.formId !== 0)
|
|
|
? newItem.formId
|
|
|
: existingItem.formId,
|
|
|
- // 如果接口返回的 isolationType 是 null 或 undefined,保留现有的值
|
|
|
isolationType: (newItem.isolationType !== null && newItem.isolationType !== undefined && newItem.isolationType !== '')
|
|
|
? newItem.isolationType
|
|
|
: existingItem.isolationType,
|
|
|
- // 如果接口返回的 isolationPoints 是 null 或 undefined,保留现有的值
|
|
|
isolationPoints: (newItem.isolationPoints !== null && newItem.isolationPoints !== undefined && newItem.isolationPoints !== '')
|
|
|
? newItem.isolationPoints
|
|
|
: existingItem.isolationPoints,
|
|
|
- // 如果接口返回的 nodeUserList 是空数组或不存在,保留现有的值
|
|
|
nodeUserList: (newItem.nodeUserList && Array.isArray(newItem.nodeUserList) && newItem.nodeUserList.length > 0)
|
|
|
? newItem.nodeUserList
|
|
|
: (existingItem.nodeUserList || []),
|
|
|
};
|
|
|
-
|
|
|
- console.log(`合并节点 ${newItem.uuid || newItem.id}:`, {
|
|
|
- existing: { workerUserId: existingItem.workerUserId, formId: existingItem.formId },
|
|
|
- new: { workerUserId: newItem.workerUserId, formId: newItem.formId },
|
|
|
- merged: { workerUserId: merged.workerUserId, formId: merged.formId }
|
|
|
- });
|
|
|
-
|
|
|
return merged;
|
|
|
}
|
|
|
|
|
|
- // 如果没找到,直接使用接口返回的数据
|
|
|
return newItem;
|
|
|
});
|
|
|
|
|
|
@@ -5265,7 +5346,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
if (item.uuid) existingUuids.add(item.uuid);
|
|
|
});
|
|
|
|
|
|
- const newItems = detail.workflowWorkNodeDOList.filter((item: WorkflowWorkNodeDO) => {
|
|
|
+ const newItems = nodeListFromApi.filter((item: WorkflowWorkNodeDO) => {
|
|
|
const itemKey = item.id || item.uuid;
|
|
|
return itemKey && !existingUuids.has(itemKey);
|
|
|
});
|
|
|
@@ -5275,6 +5356,75 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
|
|
|
// 更新状态
|
|
|
setWorkflowWorkNodeDOList(mergedWorkflowWorkNodeDOList);
|
|
|
+
|
|
|
+ // 清除与该隔离节点对应的解除隔离节点的配置缓存,切换节点时从最新 workflowWorkNodeDOList 拉取(显示后端已同步的上锁人/共锁人)
|
|
|
+ const releaseIsolationUuids = mergedWorkflowWorkNodeDOList
|
|
|
+ .filter((n: WorkflowWorkNodeDO) => (n.type === 'releaseIsolation' || n.type === '解除隔离') && n.isolationNodeUuid === selectedWorkflowNode.id)
|
|
|
+ .map((n: WorkflowWorkNodeDO) => n.uuid)
|
|
|
+ .filter((id: any): id is string => id != null && id !== '');
|
|
|
+ if (releaseIsolationUuids.length > 0) {
|
|
|
+ setWorkflowNodeConfigCache(prev => {
|
|
|
+ const next = new Map(prev);
|
|
|
+ releaseIsolationUuids.forEach(uuid => next.delete(uuid));
|
|
|
+ return next;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 用最新列表刷新流程画布上所有节点的 data,保证画布与数据一致、解除隔离与隔离方案一致
|
|
|
+ setWorkflowNodes((nds) =>
|
|
|
+ nds.map((node) => {
|
|
|
+ const nodeDO = mergedWorkflowWorkNodeDOList.find((item: WorkflowWorkNodeDO) => item.uuid === node.id);
|
|
|
+ if (!nodeDO) return node.id === selectedWorkflowNode.id ? { ...node, data: { ...node.data, completed: true }, selected: false } : node;
|
|
|
+ let nodeData: any = {};
|
|
|
+ if (nodeDO.data) {
|
|
|
+ try {
|
|
|
+ nodeData = typeof nodeDO.data === 'string' ? JSON.parse(nodeDO.data) : nodeDO.data;
|
|
|
+ } catch (e) {}
|
|
|
+ }
|
|
|
+ const source = nodeData || node.data || {};
|
|
|
+ let lockPersonVal: string | number | undefined = undefined;
|
|
|
+ const coLockPersonIds: (string | number)[] = [];
|
|
|
+ if (nodeDO.nodeUserList && Array.isArray(nodeDO.nodeUserList)) {
|
|
|
+ nodeDO.nodeUserList.forEach((user: any) => {
|
|
|
+ if (user.type === 'jtlocker' && user.userId != null) {
|
|
|
+ lockPersonVal = typeof user.userId === 'number' ? user.userId : Number(user.userId);
|
|
|
+ } else if (user.type === 'jtcolocker' && user.userId != null) {
|
|
|
+ coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ let isolationPoints: string[] = [];
|
|
|
+ if (nodeDO.isolationPoints) {
|
|
|
+ try {
|
|
|
+ isolationPoints = typeof nodeDO.isolationPoints === 'string' ? JSON.parse(nodeDO.isolationPoints) : (Array.isArray(nodeDO.isolationPoints) ? nodeDO.isolationPoints : []);
|
|
|
+ } catch (e) {}
|
|
|
+ } else {
|
|
|
+ isolationPoints = source.isolationPoints || [];
|
|
|
+ }
|
|
|
+ const config = nodeConfigs.find((c: any) => c.type === (nodeDO.type || source.type));
|
|
|
+ const isCurrent = node.id === selectedWorkflowNode.id;
|
|
|
+ const updatedData = {
|
|
|
+ ...source,
|
|
|
+ label: nodeDO.nodeName || source.label || config?.label || '',
|
|
|
+ icon: nodeDO.nodeIcon || source.icon || '',
|
|
|
+ responsible: (nodeDO.workerUserId !== null && nodeDO.workerUserId !== undefined && nodeDO.workerUserId !== 0) ? nodeDO.workerUserId : source.responsible,
|
|
|
+ remark: source.remark ?? '',
|
|
|
+ submitForm: nodeDO.formId ?? source.submitForm,
|
|
|
+ isolationType: (nodeDO.isolationType != null && nodeDO.isolationType !== '') ? String(nodeDO.isolationType) : (source.isolationType ?? ''),
|
|
|
+ isolationPoints,
|
|
|
+ isolationNode: source.isolationNode || [],
|
|
|
+ isolationNodeUuid: nodeDO.isolationNodeUuid ?? source.isolationNodeUuid ?? '',
|
|
|
+ lockPerson: lockPersonVal !== undefined ? lockPersonVal : source.lockPerson,
|
|
|
+ coLockPersons: coLockPersonIds.length > 0 ? coLockPersonIds : (source.coLockPersons || []),
|
|
|
+ notificationMethods: source.notificationMethods || { sms: false, message: false, email: false, app: false },
|
|
|
+ notificationPerson: source.notificationPerson ?? '',
|
|
|
+ notificationTime: nodeDO.notifyTime ?? source.notificationTime ?? '',
|
|
|
+ completed: isCurrent ? true : (node.data?.completed ?? false),
|
|
|
+ };
|
|
|
+ return { ...node, data: updatedData, selected: isCurrent ? false : node.selected };
|
|
|
+ })
|
|
|
+ );
|
|
|
+ didRefreshFlowNodes = true;
|
|
|
}
|
|
|
} catch (error: any) {
|
|
|
console.error('获取最新节点数据失败:', error);
|
|
|
@@ -5336,33 +5486,35 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
newSavedStatusCache.set(selectedWorkflowNode.id, true);
|
|
|
setNodeSavedStatusCache(newSavedStatusCache);
|
|
|
|
|
|
- // 更新节点显示
|
|
|
- const { isolationMethod, ...restData } = selectedWorkflowNode.data || {};
|
|
|
- const updatedData = {
|
|
|
- ...restData,
|
|
|
- label: workflowNodeConfig.nodeName,
|
|
|
- icon: workflowNodeConfig.nodeIcon,
|
|
|
- responsible: workflowNodeConfig.responsible,
|
|
|
- remark: workflowNodeConfig.remark,
|
|
|
- submitForm: workflowNodeConfig.submitForm,
|
|
|
- isolationType: workflowNodeConfig.isolationType,
|
|
|
- isolationPoints: workflowNodeConfig.isolationPoints,
|
|
|
- isolationNode: workflowNodeConfig.isolationNode,
|
|
|
- isolationNodeUuid: workflowNodeConfig.isolationNodeUuid,
|
|
|
- lockPerson: workflowNodeConfig.lockPerson,
|
|
|
- coLockPersons: workflowNodeConfig.coLockPersons,
|
|
|
- notificationMethods: workflowNodeConfig.notificationMethods,
|
|
|
- notificationPerson: workflowNodeConfig.notificationPerson,
|
|
|
- notificationTime: workflowNodeConfig.notificationTime,
|
|
|
- completed: true, // 标记为已完成
|
|
|
- };
|
|
|
- setWorkflowNodes((nds) =>
|
|
|
- nds.map((node) =>
|
|
|
- node.id === selectedWorkflowNode.id
|
|
|
- ? { ...node, data: updatedData, selected: false }
|
|
|
- : node
|
|
|
- )
|
|
|
- );
|
|
|
+ // 更新节点显示(若已用详情合并列表刷新过画布则不再覆盖,避免解除隔离等节点被旧数据覆盖)
|
|
|
+ if (!didRefreshFlowNodes) {
|
|
|
+ const { isolationMethod, ...restData } = selectedWorkflowNode.data || {};
|
|
|
+ const updatedData = {
|
|
|
+ ...restData,
|
|
|
+ label: workflowNodeConfig.nodeName,
|
|
|
+ icon: workflowNodeConfig.nodeIcon,
|
|
|
+ responsible: workflowNodeConfig.responsible,
|
|
|
+ remark: workflowNodeConfig.remark,
|
|
|
+ submitForm: workflowNodeConfig.submitForm,
|
|
|
+ isolationType: workflowNodeConfig.isolationType,
|
|
|
+ isolationPoints: workflowNodeConfig.isolationPoints,
|
|
|
+ isolationNode: workflowNodeConfig.isolationNode,
|
|
|
+ isolationNodeUuid: workflowNodeConfig.isolationNodeUuid,
|
|
|
+ lockPerson: workflowNodeConfig.lockPerson,
|
|
|
+ coLockPersons: workflowNodeConfig.coLockPersons,
|
|
|
+ notificationMethods: workflowNodeConfig.notificationMethods,
|
|
|
+ notificationPerson: workflowNodeConfig.notificationPerson,
|
|
|
+ notificationTime: workflowNodeConfig.notificationTime,
|
|
|
+ completed: true,
|
|
|
+ };
|
|
|
+ setWorkflowNodes((nds) =>
|
|
|
+ nds.map((node) =>
|
|
|
+ node.id === selectedWorkflowNode.id
|
|
|
+ ? { ...node, data: updatedData, selected: false }
|
|
|
+ : node
|
|
|
+ )
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
// 查找下一个未完成的节点(使用新的completedSet,而不是状态中的)
|
|
|
// 优先查找当前节点的子节点
|