浏览代码

隔离类型默认设置为1

wyn 1 周之前
父节点
当前提交
a697eafea2
共有 4 个文件被更改,包括 147 次插入43 次删除
  1. 74 29
      src/components/IsolationWork.tsx
  2. 30 10
      src/components/ProcessDesigner.tsx
  3. 9 4
      src/components/WorkJobDetail.tsx
  4. 34 0
      src/utils/workflowNodeTypes.ts

+ 74 - 29
src/components/IsolationWork.tsx

@@ -51,14 +51,17 @@ import { getFormPage, getForm, FormVO } from '../api/bpm/form';
 import { setConfAndFields2, FormCreateData } from '../utils/formCreate';
 import { generateIconPaths, getIconPathByFileName, getWorkflowNodeDescription } from '../utils/workflowNodePanelUi';
 import {
+  isWorkflowCoLockFamilySubmitFormOptional,
   isWorkflowCoLockType,
   isWorkflowIsolationSchemePanelType,
+  isWorkflowJobFlowResponsibleRequired,
   isWorkflowLockLikeValidationType,
   isWorkflowLockSchemeType,
   isWorkflowUnlockCoLockType,
   isWorkflowUnlockLikeValidationType,
   isWorkflowUnlockParentMatch,
   isWorkflowUnlockSchemeType,
+  normalizeIsolationTypeForCoLockFamily,
   resolveWorkflowPaletteType,
 } from '../utils/workflowNodeTypes';
 import './IsolationWorkListTable.css';
@@ -288,14 +291,8 @@ function validateWorkflowJobNodeConfig(config: any, nodeType: string): boolean {
   if (formRequiredNodeTypes.includes(nodeType) && !config.submitForm) {
     return false;
   }
-  if (
-    nodeType !== 'createJob' &&
-    !isWorkflowLockLikeValidationType(nodeType) &&
-    !isWorkflowUnlockLikeValidationType(nodeType)
-  ) {
-    if (!config.responsible) {
-      return false;
-    }
+  if (isWorkflowJobFlowResponsibleRequired(nodeType) && !config.responsible) {
+    return false;
   }
   if (isWorkflowCoLockType(nodeType)) {
     if (!config.isolationNodeUuid || config.isolationNodeUuid === '') {
@@ -1751,7 +1748,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                     : undefined,
                 remark: nodeData.remark || '',
                 submitForm: nodeDO.formId ? (typeof nodeDO.formId === 'number' ? nodeDO.formId : Number(nodeDO.formId)) : (nodeData.submitForm ? (typeof nodeData.submitForm === 'number' ? nodeData.submitForm : Number(nodeData.submitForm)) : undefined),
-                isolationType: (nodeDO.isolationType !== null && nodeDO.isolationType !== undefined) ? String(nodeDO.isolationType) : (nodeData.isolationType || ''),
+                isolationType: normalizeIsolationTypeForCoLockFamily(
+                  nodeDO.type || nodeData.type,
+                  (nodeDO.isolationType !== null && nodeDO.isolationType !== undefined) ? String(nodeDO.isolationType) : (nodeData.isolationType || '')
+                ),
                 isolationPoints: nodeDO.isolationPoints ? (typeof nodeDO.isolationPoints === 'string' ? JSON.parse(nodeDO.isolationPoints) : nodeDO.isolationPoints) : (nodeData.isolationPoints || []),
                 isolationNode: nodeData.isolationNode || [],
                 isolationNodeUuid: nodeDO.isolationNodeUuid || nodeData.isolationNodeUuid || '',
@@ -1969,7 +1969,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                           : undefined,
                       remark: nodeData.remark || '',
                       submitForm: nodeDO.formId ? (typeof nodeDO.formId === 'number' ? nodeDO.formId : Number(nodeDO.formId)) : (nodeData.submitForm ? (typeof nodeData.submitForm === 'number' ? nodeData.submitForm : Number(nodeData.submitForm)) : undefined),
-                      isolationType: (nodeDO.isolationType !== null && nodeDO.isolationType !== undefined) ? String(nodeDO.isolationType) : (nodeData.isolationType || ''),
+                      isolationType: normalizeIsolationTypeForCoLockFamily(
+                        nodeDO.type || nodeData.type,
+                        (nodeDO.isolationType !== null && nodeDO.isolationType !== undefined) ? String(nodeDO.isolationType) : (nodeData.isolationType || '')
+                      ),
                       isolationPoints: nodeDO.isolationPoints ? (typeof nodeDO.isolationPoints === 'string' ? JSON.parse(nodeDO.isolationPoints) : nodeDO.isolationPoints) : (nodeData.isolationPoints || []),
                       isolationNode: nodeData.isolationNode || [],
                       isolationNodeUuid: nodeDO.isolationNodeUuid || nodeData.isolationNodeUuid || '',
@@ -2014,7 +2017,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                       responsible: source.workerUserId ? (typeof source.workerUserId === 'number' ? source.workerUserId : Number(source.workerUserId)) : undefined,
                       remark: source.remark || '',
                       submitForm: source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined,
-                      isolationType: source.isolationType || '',
+                      isolationType: normalizeIsolationTypeForCoLockFamily(source.type, source.isolationType || ''),
                       isolationPoints: source.isolationPoints || [],
                       isolationNode: source.isolationNode || [],
                       isolationNodeUuid: source.isolationNodeUuid || '',
@@ -2347,11 +2350,14 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
         submitForm: fromIsolationOnly
           ? (nodeDO.formId != null && nodeDO.formId !== '' ? (typeof nodeDO.formId === 'number' ? nodeDO.formId : Number(nodeDO.formId)) : (releaseNodeData.submitForm != null ? (typeof releaseNodeData.submitForm === 'number' ? releaseNodeData.submitForm : Number(releaseNodeData.submitForm)) : undefined))
           : (dataSource.formId ? (typeof dataSource.formId === 'number' ? dataSource.formId : Number(dataSource.formId)) : (source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined)),
-        isolationType: fromIsolationOnly
-          ? isolationTypeFromOwn || isolationTypeFromParent
-          : dataSource.isolationType !== null && dataSource.isolationType !== undefined
-            ? String(dataSource.isolationType)
-            : source.isolationType || '',
+        isolationType: normalizeIsolationTypeForCoLockFamily(
+          node.data?.type || nodeDO?.type,
+          fromIsolationOnly
+            ? isolationTypeFromOwn || isolationTypeFromParent
+            : dataSource.isolationType !== null && dataSource.isolationType !== undefined
+              ? String(dataSource.isolationType)
+              : source.isolationType || ''
+        ),
         isolationPoints: fromIsolationOnly ? isolationOnlyIsolationPoints : isolationPoints,
         isolationNode: source.isolationNode || [],
         isolationNodeUuid: nodeDO.isolationNodeUuid || source.isolationNodeUuid || '',
@@ -2414,7 +2420,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
           responsible: source.workerUserId ? (typeof source.workerUserId === 'number' ? source.workerUserId : Number(source.workerUserId)) : undefined,
           remark: source.remark || '',
           submitForm: source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined,
-          isolationType: source.isolationType || '',
+          isolationType: normalizeIsolationTypeForCoLockFamily(source.type, source.isolationType || ''),
           isolationPoints: source.isolationPoints || [],
           isolationNode: source.isolationNode || [],
           isolationNodeUuid: source.isolationNodeUuid || '',
@@ -2462,7 +2468,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
         responsible: workflowNodeConfig.responsible,
         remark: workflowNodeConfig.remark,
         submitForm: workflowNodeConfig.submitForm,
-        isolationType: workflowNodeConfig.isolationType,
+        isolationType: normalizeIsolationTypeForCoLockFamily(
+          selectedWorkflowNode.data?.type,
+          workflowNodeConfig.isolationType || ''
+        ),
         isolationPoints: workflowNodeConfig.isolationPoints,
         isolationNode: workflowNodeConfig.isolationNode,
         isolationNodeUuid: workflowNodeConfig.isolationNodeUuid,
@@ -5106,7 +5115,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                       </div>
                                       {selectedWorkflowNode.data?.type === 'confirm' && (
                                         <div>
-                                          <label className="block text-sm font-medium text-gray-700 mb-2">{t('isolationWork.responsible')}</label>
+                                          <label className="block text-sm font-medium text-gray-700 mb-2">
+                                            {t('isolationWork.responsible')}{' '}
+                                            <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
+                                          </label>
                                           <Select
                                             value={
                                               workflowNodeConfig.responsible !== undefined && workflowNodeConfig.responsible !== null && workflowNodeConfig.responsible !== ''
@@ -5135,7 +5147,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                       )}
                                       {selectedWorkflowNode.data?.type === 'review' && (
                                         <div>
-                                          <label className="block text-sm font-medium text-gray-700 mb-2">{t('isolationWork.responsible')}</label>
+                                          <label className="block text-sm font-medium text-gray-700 mb-2">
+                                            {t('isolationWork.responsible')}{' '}
+                                            <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
+                                          </label>
                                           <Select
                                             value={
                                               workflowNodeConfig.responsible !== undefined && workflowNodeConfig.responsible !== null && workflowNodeConfig.responsible !== ''
@@ -5167,7 +5182,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                         selectedWorkflowNode.data?.type !== 'review' &&
                                         !workflowSchemePanelOpen && (
                                           <div>
-                                            <label className="block text-sm font-medium text-gray-700 mb-2">{t('isolationWork.responsible')}</label>
+                                            <label className="block text-sm font-medium text-gray-700 mb-2">
+                                              {t('isolationWork.responsible')}{' '}
+                                              <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
+                                            </label>
                                             <Select
                                               value={
                                                 workflowNodeConfig.responsible !== undefined && workflowNodeConfig.responsible !== null && workflowNodeConfig.responsible !== ''
@@ -5228,9 +5246,12 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                 <div>
                                   <label className="block text-sm font-medium text-gray-700 mb-2">
                                     {t('isolationWork.businessForm')}
-                                    {['confirm', 'review', 'inputInfo'].includes(selectedWorkflowNode.data?.type || '') && (
-                                      <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
-                                    )}
+                                    {!isWorkflowCoLockFamilySubmitFormOptional(selectedWorkflowNode.data?.type || '') &&
+                                      ['confirm', 'review', 'inputInfo'].includes(
+                                        resolveWorkflowPaletteType(selectedWorkflowNode.data?.type || '')
+                                      ) && (
+                                        <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
+                                      )}
                                   </label>
                                   <div className="flex gap-2">
                                     <Select
@@ -6165,7 +6186,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                         nodeName: workflowNodeConfig.nodeName,
                                         formId: formId,
                                         workerUserId: workflowNodeConfig.responsible ? Number(workflowNodeConfig.responsible) : undefined,
-                                        isolationType: workflowNodeConfig.isolationType || undefined,
+                                        isolationType: (() => {
+                                          const v = normalizeIsolationTypeForCoLockFamily(
+                                            selectedWorkflowNode.data?.type,
+                                            workflowNodeConfig.isolationType || ''
+                                          );
+                                          return v !== '' ? v : undefined;
+                                        })(),
                                         isolationPoints: workflowNodeConfig.isolationPoints && Array.isArray(workflowNodeConfig.isolationPoints) && workflowNodeConfig.isolationPoints.length > 0 
                                           ? JSON.stringify(workflowNodeConfig.isolationPoints) 
                                           : undefined,
@@ -6499,7 +6526,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                                 nodeName: workflowNodeConfig.nodeName,
                                                 formId: workflowNodeConfig.submitForm ? Number(workflowNodeConfig.submitForm) : undefined,
                                                 workerUserId: workflowNodeConfig.responsible ? Number(workflowNodeConfig.responsible) : undefined,
-                                                isolationType: workflowNodeConfig.isolationType || undefined,
+                                                isolationType: (() => {
+                                                  const v = normalizeIsolationTypeForCoLockFamily(
+                                                    selectedWorkflowNode.data?.type,
+                                                    workflowNodeConfig.isolationType || ''
+                                                  );
+                                                  return v !== '' ? v : undefined;
+                                                })(),
                                                 isolationPoints: workflowNodeConfig.isolationPoints && workflowNodeConfig.isolationPoints.length > 0 
                                                   ? JSON.stringify(workflowNodeConfig.isolationPoints) 
                                                   : undefined,
@@ -6515,7 +6548,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                                     responsible: workflowNodeConfig.responsible ? String(workflowNodeConfig.responsible) : '',
                                                     remark: workflowNodeConfig.remark,
                                                     submitForm: workflowNodeConfig.submitForm ? String(workflowNodeConfig.submitForm) : '',
-                                                    isolationType: workflowNodeConfig.isolationType,
+                                                    isolationType: normalizeIsolationTypeForCoLockFamily(
+                                                      selectedWorkflowNode.data?.type,
+                                                      workflowNodeConfig.isolationType || ''
+                                                    ),
                                                     isolationPoints: workflowNodeConfig.isolationPoints,
                                                     isolationNode: workflowNodeConfig.isolationNode,
                                                     isolationNodeUuid: workflowNodeConfig.isolationNodeUuid,
@@ -6542,7 +6578,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                     
                                     // 缓存当前节点配置
                                     const newCache = new Map(workflowNodeConfigCache);
-                                    newCache.set(selectedWorkflowNode.id, { ...workflowNodeConfig });
+                                    newCache.set(selectedWorkflowNode.id, {
+                                      ...workflowNodeConfig,
+                                      isolationType: normalizeIsolationTypeForCoLockFamily(
+                                        selectedWorkflowNode.data?.type,
+                                        workflowNodeConfig.isolationType || ''
+                                      ),
+                                    });
                                     setWorkflowNodeConfigCache(newCache);
                                     
                                     // 标记当前节点为已完成
@@ -6565,7 +6607,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
                                         responsible: workflowNodeConfig.responsible,
                                         remark: workflowNodeConfig.remark,
                                         submitForm: workflowNodeConfig.submitForm,
-                                        isolationType: workflowNodeConfig.isolationType,
+                                        isolationType: normalizeIsolationTypeForCoLockFamily(
+                                          selectedWorkflowNode.data?.type,
+                                          workflowNodeConfig.isolationType || ''
+                                        ),
                                         isolationPoints: workflowNodeConfig.isolationPoints,
                                         isolationNode: workflowNodeConfig.isolationNode,
                                         isolationNodeUuid: workflowNodeConfig.isolationNodeUuid,

+ 30 - 10
src/components/ProcessDesigner.tsx

@@ -150,13 +150,16 @@ import { setConfAndFields2, FormCreateData } from '../utils/formCreate';
 import { dictDataApi, DictDataVO } from '../api/DictData';
 import FormUploadField from './FormUploadField';
 import {
+  isWorkflowCoLockFamilySubmitFormOptional,
   isWorkflowCoLockType,
   isWorkflowIsolationSchemePanelType,
   isWorkflowLockSchemeType,
   isWorkflowUnlockCoLockType,
   isWorkflowUnlockParentMatch,
   isWorkflowUnlockSchemeType,
+  normalizeIsolationTypeForCoLockFamily,
   resolveWorkflowPaletteType,
+  WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE,
 } from '../utils/workflowNodeTypes';
 import { generateIconPaths, getIconPathByFileName, getWorkflowNodeDescription } from '../utils/workflowNodePanelUi';
 
@@ -207,6 +210,7 @@ function toWorkflowCopyIdsCommaString(value: unknown): string {
 /**
  * 共锁 / 解除共锁:设计器提交表单不维护隔离方式、隔离点、上锁人等(由关联任务在运行时解析)。
  * 保存/导出流程 JSON 时清空同步进 data 的上述字段,避免与表单语义不一致。
+ * - coLock / unlockCoLock:isolationType 固定为「1」(上锁挂牌);其余隔离字段清空,由关联上锁任务解析。
  * - coLock:保留 formId、isolationNodeUuid(上锁任务)、coLockPersons
  * - unlockCoLock:保留 formId、isolationNodeUuid(共锁任务)、coLockPersons(与所选共锁任务同步,供下游使用)
  */
@@ -224,7 +228,7 @@ function sanitizeCoLockFamilyNodeDataForExport(
   }
   return {
     ...processedData,
-    isolationType: '',
+    isolationType: WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE,
     isolationPoints: [],
     isolationNode: [],
     lockPerson: '',
@@ -1440,7 +1444,7 @@ export default function ProcessDesigner() {
         workerUserId: responsibleValue, // 同时保存 workerUserId 字段
         remark: nodeConfig.remark,
         formId: nodeConfig.formId,
-        isolationType: nodeConfig.isolationType,
+        isolationType: normalizeIsolationTypeForCoLockFamily(selectedNode.data?.type, nodeConfig.isolationType),
         isolationPoints: nodeConfig.isolationPoints,
         isolationNode: nodeConfig.isolationNode,
         isolationNodeUuid: nodeConfig.isolationNodeUuid,
@@ -1465,7 +1469,9 @@ export default function ProcessDesigner() {
       const isolationSyncPayload =
         isLockSchemeSource || isCoLockSchemeSource
         ? {
-            isolationType: nodeConfig.isolationType,
+            isolationType: isCoLockSchemeSource
+              ? WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE
+              : nodeConfig.isolationType,
             isolationPoints: nodeConfig.isolationPoints,
             lockPerson: nodeConfig.lockPerson,
             coLockPersons: nodeConfig.coLockPersons,
@@ -1476,7 +1482,7 @@ export default function ProcessDesigner() {
       /** 上锁节点变更时同步到「共锁」节点:不覆盖共锁节点自身的共锁人 */
       const lockSchemeToCoLockPayload = isLockSchemeSource
         ? {
-            isolationType: nodeConfig.isolationType,
+            isolationType: WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE,
             isolationPoints: nodeConfig.isolationPoints,
             lockPerson: nodeConfig.lockPerson,
             responsible: responsibleValue,
@@ -1621,7 +1627,11 @@ export default function ProcessDesigner() {
           copyUserIds: parseWorkflowCopyIds(nodeData.copyUserIds, nodeData.ccUserId),
           ...nodeData, // 保留其他可能的字段
         };
-        
+        const coLockFamilyT = completeData.type || node.type;
+        if (isWorkflowCoLockType(coLockFamilyT) || isWorkflowUnlockCoLockType(coLockFamilyT)) {
+          completeData.isolationType = WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE;
+        }
+
         return {
           id: nodeId, // 使用uuid或id作为id
           type: node.type,
@@ -2041,7 +2051,7 @@ export default function ProcessDesigner() {
       responsible: responsible,
       remark: source.remark || '',
       formId: source.formId || source.submitForm ? String(source.formId || source.submitForm) : '', // 兼容旧的 submitForm 字段,确保是字符串类型
-      isolationType: isolationType,
+      isolationType: normalizeIsolationTypeForCoLockFamily(source.type, isolationType),
       isolationPoints: isolationPointsData,
       isolationNode: Array.isArray(source.isolationNode) ? source.isolationNode : (source.isolationNode ? [source.isolationNode] : []),
       isolationNodeUuid: source.isolationNodeUuid || '',
@@ -2338,6 +2348,9 @@ export default function ProcessDesigner() {
             messageTemplateCode: 'false',
             emailTemplateCode: 'false',
             appTemplateCode: 'false',
+            ...(type === 'coLock' || type === 'unlockCoLock'
+              ? { isolationType: WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE }
+              : {}),
           },
         };
 
@@ -2424,7 +2437,7 @@ export default function ProcessDesigner() {
               responsible: nodeConfig.responsible,
               remark: nodeConfig.remark,
               formId: nodeConfig.formId ? String(nodeConfig.formId) : '',
-              isolationType: nodeConfig.isolationType,
+              isolationType: normalizeIsolationTypeForCoLockFamily(node.data?.type, nodeConfig.isolationType),
               isolationPoints: nodeConfig.isolationPoints,
               isolationNode: nodeConfig.isolationNode,
               isolationNodeUuid: nodeConfig.isolationNodeUuid,
@@ -3087,7 +3100,11 @@ export default function ProcessDesigner() {
           appTemplateCode: topLevelAppTemplateCode !== undefined ? topLevelAppTemplateCode : (nodeData.appTemplateCode || 'false'),
           ...nodeData, // 保留其他可能的字段
         };
-        
+        const coLockFamilyT2 = completeData.type || node.type;
+        if (isWorkflowCoLockType(coLockFamilyT2) || isWorkflowUnlockCoLockType(coLockFamilyT2)) {
+          completeData.isolationType = WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE;
+        }
+
         return {
           id: nodeId, // 使用uuid或id作为id
           type: node.type,
@@ -3145,7 +3162,7 @@ export default function ProcessDesigner() {
             responsible: source.responsible || '',
             remark: source.remark || '',
             formId: source.formId || source.submitForm ? String(source.formId || source.submitForm) : '', // 兼容旧的 submitForm 字段,确保是字符串类型
-            isolationType: source.isolationType || '',
+            isolationType: normalizeIsolationTypeForCoLockFamily(source.type, source.isolationType || ''),
             isolationPoints: source.isolationPoints || [],
             isolationNode: Array.isArray(source.isolationNode) ? source.isolationNode : (source.isolationNode ? [source.isolationNode] : []),
             isolationNodeUuid: source.isolationNodeUuid || '',
@@ -3721,7 +3738,10 @@ export default function ProcessDesigner() {
                         <div className="space-y-5">
                           <div>
                             <label className="block text-sm font-medium text-gray-700 mb-2">
-                              提交表单 <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
+                              提交表单{' '}
+                              {!isWorkflowCoLockFamilySubmitFormOptional(selectedDataType) && (
+                                <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
+                              )}
                             </label>
                             <div className="flex gap-2">
                             <Select

+ 9 - 4
src/components/WorkJobDetail.tsx

@@ -45,12 +45,14 @@ import { segregationPointApi } from '../api/spm';
 import { Select, Input, Checkbox, Tabs, Tooltip } from 'antd';
 import { useTranslation } from 'react-i18next';
 import {
+  isWorkflowCoLockFamilySubmitFormOptional,
   isWorkflowCoLockType,
   isWorkflowIsolationSchemePanelType,
   isWorkflowLockSchemeType,
   isWorkflowUnlockCoLockType,
   isWorkflowUnlockParentMatch,
   isWorkflowUnlockSchemeType,
+  resolveWorkflowPaletteType,
 } from '../utils/workflowNodeTypes';
 
 interface WorkflowStep {
@@ -1551,10 +1553,13 @@ const NodeInfoPanel: React.FC<NodeInfoPanelProps> = ({
             <div>
               <label className="block text-sm font-medium text-gray-700 mb-2">
                 {t('workJobDetail.businessForm')}
-                {/* 只有确认节点、审核节点、录入信息节点显示必填标记 */}
-                {['confirm', 'review', 'inputInfo'].includes(nodeData.type || '') && (
-                  <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
-                )}
+                {/* 确认/审核/录入为必填;共锁、解除共锁不标必填(与流程设计器一致) */}
+                {!isWorkflowCoLockFamilySubmitFormOptional(nodeData.type || '') &&
+                  ['confirm', 'review', 'inputInfo'].includes(
+                    resolveWorkflowPaletteType(nodeData.type || '')
+                  ) && (
+                    <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
+                  )}
               </label>
               <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                 {getFormName()}

+ 34 - 0
src/utils/workflowNodeTypes.ts

@@ -28,6 +28,40 @@ export function isWorkflowUnlockLikeValidationType(t: string | undefined | null)
   return isWorkflowUnlockSchemeType(t) || isWorkflowUnlockCoLockType(t);
 }
 
+/** 共锁、解除共锁:业务提交表单不强制(右侧面板不标必填,与作业流程校验一致) */
+export function isWorkflowCoLockFamilySubmitFormOptional(t: string | undefined | null): boolean {
+  return isWorkflowCoLockType(t) || isWorkflowUnlockCoLockType(t);
+}
+
+/** 共锁/解除共锁仅随「上锁挂牌」存在,流程 JSON 与接口 isolationType 固定为字典值 1(字符串) */
+export const WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE = '1';
+
+/** 共锁族节点落库/导出时的 isolationType,其余类型保持 current */
+export function normalizeIsolationTypeForCoLockFamily(
+  nodeType: string | undefined | null,
+  current: string | undefined | null
+): string {
+  if (isWorkflowCoLockType(nodeType) || isWorkflowUnlockCoLockType(nodeType)) {
+    return WORKFLOW_CO_LOCK_FAMILY_ISOLATION_TYPE;
+  }
+  return current != null && String(current) !== '' ? String(current) : '';
+}
+
+/**
+ * 作业流程管理(IsolationWork)右侧面板:节点信息里出现「负责人」选择框时是否必填(与 UI 红星一致)。
+ * 含:确认、审核、录入、还锁、完成;上锁方案里盲板/拆除的负责人仍由 lock 分支按 isolationType 单独校验。
+ */
+export function isWorkflowJobFlowResponsibleRequired(paletteType: string | undefined | null): boolean {
+  if (!paletteType) return false;
+  return (
+    paletteType === 'confirm' ||
+    paletteType === 'review' ||
+    paletteType === 'inputInfo' ||
+    paletteType === 'returnLock' ||
+    paletteType === 'complete'
+  );
+}
+
 /** 右侧配置:隔离方式、隔离点、关联方案节点等整块 UI */
 export function isWorkflowIsolationSchemePanelType(t: string | undefined | null): boolean {
   return (