import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { flushSync } from 'react-dom';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Plus, Search, Edit2, Trash2, MoreVertical, FileText, Eye, Play, CheckCircle, RefreshCw, Workflow, Hand } from 'lucide-react';
import { Button, Input, Space, Select, TreeSelect, Table as AntdTable, message, Modal, Form, Row, Col, Tabs, Radio, DatePicker, Checkbox, Tooltip, Switch as AntdSwitch } from 'antd';
import { Button as UIButton } from './ui/button';
import type { ColumnsType } from 'antd/es/table';
import { workflowDesignApi, WorkflowDesignVO } from '../api/WorkflowDesign';
import { workJobApi, WorkJobVO, WorkflowWorkNodeDO, UpdateWorkflowWorkNodeParam, WorkflowWorkNodeUserDO, UpdateStartWorkParam } from '../api/WorkJob';
import { dictDataApi, DictDataVO } from '../api/DictData';
import ReactFlow, {
  Node,
  Edge,
  useNodesState,
  useEdgesState,
  Controls,
  Background,
  NodeTypes,
  BackgroundVariant,
  Handle,
  Position,
  ConnectionMode,
} from 'reactflow';
import { sharedFlowEdgeTypes } from './FlowEdge';
import { getLayoutedNodes, shouldApplyLayout } from '../utils/flowLayout';
import 'reactflow/dist/style.css';
import {
  ToolOutlined,
  CheckCircleOutlined,
  FileTextOutlined,
  EditOutlined,
  UnlockOutlined,
  LockOutlined,
  TeamOutlined,
  KeyOutlined,
  CheckSquareOutlined,
  CloseOutlined,
  DeleteOutlined,
  ExclamationCircleOutlined,
  ClockCircleOutlined,
  FireOutlined,
  WarningOutlined,
} from '@ant-design/icons';
import { userApi, UserVO } from '../api/user';
import { deptApi, type DeptVO } from '../api/dept';
import { segregationPointApi, SegregationPointVO } from '../api/spm';
import { getFormPage, getForm, FormVO } from '../api/bpm/form';
import {
  isWorkflowCoLockType,
  isWorkflowIsolationSchemePanelType,
  isWorkflowLockLikeValidationType,
  isWorkflowLockSchemeType,
  isWorkflowUnlockCoLockType,
  isWorkflowUnlockLikeValidationType,
  isWorkflowUnlockParentMatch,
  isWorkflowUnlockSchemeType,
  resolveWorkflowPaletteType,
} from '../utils/workflowNodeTypes';
import './IsolationWorkListTable.css';
import urgecy1Icon from '../assets/urgecy1.png';
import urgecy2Icon from '../assets/urgecy2.png';
import urgecy3Icon from '../assets/urgecy3.png';

interface TableRow {
  id: number;
  [key: string]: any;
}

interface IsolationWorkProps {
  subMenu: string;
}

/** 抄送部门/人员 ID：支持数组、逗号分隔字符串、JSON 数组字符串，兼容旧 cc* 单选 */
function parseWorkflowCopyIds(multi: unknown, legacySingle: unknown): string[] {
  const pushValid = (out: string[], x: unknown) => {
    if (x !== undefined && x !== null && x !== '') out.push(String(x));
  };
  if (Array.isArray(multi)) {
    const out: string[] = [];
    multi.forEach((x) => pushValid(out, x));
    return out;
  }
  if (typeof multi === 'string' && multi.trim()) {
    try {
      const parsed = JSON.parse(multi);
      if (Array.isArray(parsed)) return parseWorkflowCopyIds(parsed, undefined);
      if (parsed !== null && parsed !== undefined && parsed !== '') {
        return [String(parsed)];
      }
    } catch {
      /* 非 JSON：逗号分隔 ID，如 "380,381" */
      return multi
        .split(',')
        .map((s) => s.trim())
        .filter((s) => s !== '');
    }
  }
  if (legacySingle !== undefined && legacySingle !== null && legacySingle !== '') {
    return [String(legacySingle)];
  }
  return [];
}

function workflowCopyDeptIds(nodeData: any, nodeDO?: any): string[] {
  return parseWorkflowCopyIds(
    nodeData?.copyDeptIds ?? nodeDO?.copyDeptIds,
    nodeData?.ccDeptId ?? nodeDO?.ccDeptId
  );
}

function workflowCopyUserIds(nodeData: any, nodeDO?: any): string[] {
  return parseWorkflowCopyIds(
    nodeData?.copyUserIds ?? nodeDO?.copyUserIds,
    nodeData?.ccUserId ?? nodeDO?.ccUserId
  );
}

/** 更新作业节点接口要求 copyDeptIds/copyUserIds 为逗号分隔字符串，不能为 JSON 数组 */
function workflowCopyIdsToApiCommaString(ids: readonly (string | number)[]): string {
  return ids
    .map((id) => String(id).trim())
    .filter((s) => s !== '')
    .join(',');
}

// 节点配置（从ProcessDesigner复制）
const nodeConfigs = [
  {
    type: 'createJob',
    label: '创建作业',
    icon: ToolOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-blue-600',
    iconColorCustom: '#165dff',
    borderColor: 'border-blue-100',
  },
  {
    type: 'confirm',
    label: '确认',
    icon: CheckCircleOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-green-600',
    iconColorCustom: '#36d399',
    borderColor: 'border-green-100',
  },
  {
    type: 'review',
    label: '审核',
    icon: FileTextOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-orange-600',
    iconColorCustom: '#fb923c',
    borderColor: 'border-orange-100',
  },
  {
    type: 'inputInfo',
    label: '录入信息',
    icon: EditOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-purple-600',
    iconColorCustom: '#9665ff',
    borderColor: 'border-purple-100',
  },
  {
    type: 'lock',
    label: '上锁',
    icon: LockOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-red-600',
    iconColorCustom: '#f87272',
    borderColor: 'border-red-100',
  },
  {
    type: 'unlock',
    label: '解锁',
    icon: UnlockOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-yellow-600',
    iconColorCustom: '#38bdf8',
    borderColor: 'border-yellow-100',
  },
  {
    type: 'coLock',
    label: '共锁',
    icon: TeamOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-red-600',
    iconColorCustom: '#f87272',
    borderColor: 'border-red-100',
  },
  {
    type: 'unlockCoLock',
    label: '解除共锁',
    icon: KeyOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-yellow-600',
    iconColorCustom: '#38bdf8',
    borderColor: 'border-yellow-100',
  },
  {
    type: 'returnLock',
    label: '还锁',
    icon: LockOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-indigo-600',
    iconColorCustom: '#6b7280',
    borderColor: 'border-indigo-100',
  },
  {
    type: 'complete',
    label: '完成/结束',
    icon: CheckSquareOutlined,
    bgColor: 'bg-white',
    bgColorCustom: '#ffffff',
    iconColor: 'text-gray-600',
    iconColorCustom: '#10b981',
    borderColor: 'border-gray-100',
  },
];

// 使用 import.meta.glob 动态导入所有图标（用于节点显示）
const iconModulesForNode = import.meta.glob('../assets/节点图标/**/*.png', { eager: true, as: 'url' });

// 根据文件名获取图标路径（用于节点显示）
const getIconPathByFileName = (fileName: string | undefined): string | null => {
  if (!fileName) return null;
  
  // 如果已经是完整路径，尝试提取文件名
  let actualFileName = fileName;
  if (fileName.includes('/') || fileName.includes('\\')) {
    // 从路径中提取文件名
    const pathParts = fileName.replace(/\\/g, '/').split('/');
    actualFileName = pathParts[pathParts.length - 1];
  }
  
  // 从文件名中提取数字和分类
  const match = actualFileName.match(/^(\d+)\.png$/);
  if (!match) return null;
  
  const iconNumber = parseInt(match[1], 10);
  
  // 根据数字范围判断分类
  let category = '';
  if (iconNumber >= 1000 && iconNumber <= 1011) category = '审核';
  else if (iconNumber >= 2000 && iconNumber <= 2016) category = '开始';
  else if (iconNumber >= 3000 && iconNumber <= 3028) category = '录入';
  else if (iconNumber >= 4000 && iconNumber <= 4024) category = '确认';
  else if (iconNumber >= 5000 && iconNumber <= 5018) category = '结束';
  else if (iconNumber >= 6000 && iconNumber <= 6027) category = '能量隔离';
  else if (iconNumber >= 7000 && iconNumber <= 7021) category = '解除隔离';
  
  if (!category) return null;
  
  // 查找对应的路径
  const allKeys = Object.keys(iconModulesForNode);
  const matchingKey = allKeys.find(k => {
    const normalizedKey = k.replace(/\\/g, '/').toLowerCase();
    return normalizedKey.includes(category.toLowerCase()) && normalizedKey.endsWith(actualFileName.toLowerCase());
  });
  
  if (matchingKey) {
    return iconModulesForNode[matchingKey] as string;
  }
  
  return null;
};

// 自定义节点组件
function CustomNode({ data, selected, id, nodeSavedStatusCache }: any) {
  const paletteType = resolveWorkflowPaletteType(data.type);
  const config = nodeConfigs.find(c => c.type === paletteType);
  const Icon = config?.icon || FileTextOutlined;
  const nodeId = data.nodeId || (id ? String(parseInt(id.split('-').pop() || '0') % 1000).padStart(3, '0') : '001');
  // 优先使用缓存中的保存状态，如果没有则使用 data.completed
  const isSaved = nodeSavedStatusCache ? (nodeSavedStatusCache.get(id) || false) : (data.completed || false);
  const isCompleted = data.completed || false;
  
  // 检查是否是图片文件名（如 "1000.png"）
  let iconImagePath: string | null = null;
  // 支持多种格式：纯文件名（如 "1000.png"）或完整路径
  if (data.icon) {
    // 如果是纯文件名格式
    if (/^\d+\.png$/.test(data.icon)) {
      iconImagePath = getIconPathByFileName(data.icon);
    } 
    // 如果已经是完整路径（兼容旧数据）
    else if (data.icon.includes('/') || data.icon.includes('\\')) {
      // 尝试从路径中提取文件名
      const pathParts = data.icon.replace(/\\/g, '/').split('/');
      const fileName = pathParts[pathParts.length - 1];
      if (/^\d+\.png$/.test(fileName)) {
        iconImagePath = getIconPathByFileName(fileName);
      }
    }
  }
  
  // 确定边框颜色和粗细：选中 > 已完成 > 默认
  // 选中：蓝色边框，加粗
  // 未选中但已完成：绿色边框，加粗
  // 未选中且未完成：灰色边框，加粗
  let borderClass = 'border-gray-400';
  let borderStyle: React.CSSProperties = { borderWidth: '3px' };
  let shadowStyle = {};
  
  if (selected) {
    // 选中的节点：蓝色边框，加粗
    borderClass = 'border-blue-500 shadow-md ring-2 ring-blue-300';
    borderStyle = { borderWidth: '4px' };
    shadowStyle = { boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.1)' };
  } else if (isSaved) {
    // 未选中但已保存的节点：绿色边框，加粗
    borderClass = 'border-green-500';
    borderStyle = { borderWidth: '3px' };
    shadowStyle = { boxShadow: '0 0 0 1px rgba(34, 197, 94, 0.1)' };
  } else {
    // 未选中且未保存的节点：灰色边框，加粗
    borderClass = 'border-gray-400';
    borderStyle = { borderWidth: '3px' };
    shadowStyle = {};
  }
  
  return (
    <div
      className={`relative px-4 py-4 rounded-lg shadow-sm w-[180px] h-auto min-h-[140px] bg-white ${borderClass} transition-all`}
      style={{ ...borderStyle, ...shadowStyle }}
    >
        <Handle
          id="top-source"
          type="source"
          position={Position.Top}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ top: -6, left: '50%', transform: 'translateX(-50%)' }}
          isConnectable={true}
        />
        <Handle
          id="top-target"
          type="target"
          position={Position.Top}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ top: -6, left: '50%', transform: 'translateX(-50%)' }}
          isConnectable={true}
        />
        <Handle
          id="bottom-source"
          type="source"
          position={Position.Bottom}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ bottom: -6, left: '50%', transform: 'translateX(-50%)' }}
          isConnectable={true}
        />
        <Handle
          id="bottom-target"
          type="target"
          position={Position.Bottom}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ bottom: -6, left: '50%', transform: 'translateX(-50%)' }}
          isConnectable={true}
        />
        <Handle
          id="left-source"
          type="source"
          position={Position.Left}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ left: -6, top: '50%', transform: 'translateY(-50%)' }}
          isConnectable={true}
        />
        <Handle
          id="left-target"
          type="target"
          position={Position.Left}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ left: -6, top: '50%', transform: 'translateY(-50%)' }}
          isConnectable={true}
        />
        <Handle
          id="right-source"
          type="source"
          position={Position.Right}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ right: -6, top: '50%', transform: 'translateY(-50%)' }}
          isConnectable={true}
        />
        <Handle
          id="right-target"
          type="target"
          position={Position.Right}
          className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
          style={{ right: -6, top: '50%', transform: 'translateY(-50%)' }}
          isConnectable={true}
        />
        
        <div className="flex flex-col items-center justify-between gap-3 h-full">
        <div className={`${config?.bgColor || 'bg-gray-50'} ${config?.borderColor || 'border-gray-100'} border p-3 rounded-xl shadow-sm flex items-center justify-center flex-shrink-0 relative`} style={{ borderRadius: '12px' }}>
          {iconImagePath ? (
            <img 
              src={iconImagePath} 
              alt={data.icon || '节点图标'}
              className="w-6 h-6 object-contain"
              onError={(e) => {
                // 如果图片加载失败，回退到默认图标
                console.error('节点图标加载失败:', iconImagePath);
                (e.target as HTMLImageElement).style.display = 'none';
              }}
            />
          ) : (
            <Icon 
              className={`${config?.iconColor || 'text-gray-600'} text-2xl`} 
              style={{ color: config?.iconColorCustom || undefined }}
            />
          )}
        </div>
        <div className="font-semibold text-sm text-gray-900 leading-tight text-center break-words w-full flex-1 flex items-center justify-center px-1">
          {data.label || config?.label}
        </div>
        <div className="text-xs text-gray-500 text-center flex-shrink-0">
          ID: {nodeId}
        </div>
        {/* 保存状态显示 */}
        <div className="flex items-center justify-center mt-2 mb-0 flex-shrink-0">
          {isSaved ? (
            <div className="flex items-center gap-1.5 text-green-600">
              <CheckCircleOutlined style={{ fontSize: '20px', color: '#22c55e' }} />
              <span className="text-xs font-medium">已配置</span>
            </div>
          ) : (
            <div className="flex items-center gap-1.5 text-gray-400">
              <ClockCircleOutlined style={{ fontSize: '18px' }} />
              <span className="text-xs">未配置</span>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// 节点类型映射（将在组件内部重新定义以访问状态）

export default function IsolationWork({ subMenu }: IsolationWorkProps) {
  const { t, i18n } = useTranslation();
  const navigate = useNavigate();
  const [searchTerm, setSearchTerm] = useState('');
  const [showAddModal, setShowAddModal] = useState(false);
  const [editingItem, setEditingItem] = useState<TableRow | null>(null);
  const [form] = Form.useForm();
  
  // 发起作业多步骤表单状态
  const [workJobStep, setWorkJobStep] = useState(0); // 0: 基本信息, 1: 流程管理, 2: 发布作业
  const [workJobBasicForm] = Form.useForm(); // 基本信息表单
  const [workJobPublishForm] = Form.useForm(); // 发布作业表单
  const [workflowJson, setWorkflowJson] = useState<any>(null); // 流程设计JSON
  const [workflowWorkId, setWorkflowWorkId] = useState<number | null>(null); // 作业票ID（新增后返回）
  const [workflowWorkNodeDOList, setWorkflowWorkNodeDOList] = useState<WorkflowWorkNodeDO[]>([]); // 作业节点数据列表
  const [originalBasicFormData, setOriginalBasicFormData] = useState<any>(null); // 编辑时的原始表单数据（用于判断是否有修改）
  
  // 查看详情弹框状态（只读模式）
  const [showViewModal, setShowViewModal] = useState(false);
  const [viewWorkJobStep, setViewWorkJobStep] = useState(0); // 0: 基本信息, 1: 流程管理, 2: 发布作业
  const [viewWorkJobBasicForm] = Form.useForm(); // 查看模式基本信息表单
  const [viewWorkJobPublishForm] = Form.useForm(); // 查看模式发布作业表单
  const [viewWorkflowJson, setViewWorkflowJson] = useState<any>(null); // 查看模式流程设计JSON
  const [viewWorkDetailData, setViewWorkDetailData] = useState<any>(null); // 查看模式详情数据
  const [isViewMode, setIsViewMode] = useState(false); // 是否为查看模式（只读）
  
  // ReactFlow相关状态（用于流程管理tab）
  const [workflowNodes, setWorkflowNodes, onWorkflowNodesChange] = useNodesState([]);
  const [workflowEdges, setWorkflowEdges, onWorkflowEdgesChange] = useEdgesState([]);
  const [selectedWorkflowNode, setSelectedWorkflowNode] = useState<Node | null>(null);
  const [workflowActiveTabKey, setWorkflowActiveTabKey] = useState<string>('info');
  const workflowReactFlowWrapper = useRef<HTMLDivElement>(null);
  const [workflowReactFlowInstance, setWorkflowReactFlowInstance] = useState<any>(null);
  /** 当前 workflowNodeConfig 对应的节点 id，用于切换节点时避免把上一节点的 config 应用到画布 */
  const workflowNodeConfigForIdRef = useRef<string | null>(null);
  
  // 节点配置状态
  const [workflowNodeConfig, setWorkflowNodeConfig] = useState({
    nodeName: '',
    nodeIcon: '',
    responsible: undefined as number | string | undefined,
    remark: '',
    submitForm: undefined as number | string | undefined,
    isolationType: '',
    isolationPoints: [] as string[],
    isolationNode: [] as string[],
    isolationNodeUuid: '',
    lockPerson: undefined as number | string | undefined,
    coLockPersons: [] as (number | string)[],
    notificationMethods: {
      sms: false,
      message: false,
      email: false,
      app: false,
    },
    notificationPerson: '',
    notificationTime: '',
    smsTemplateCode: 'false',
    messageTemplateCode: 'false',
    emailTemplateCode: 'false',
    appTemplateCode: 'false',
    copyDeptIds: [] as string[],
    copyUserIds: [] as string[],
  });
  
  // 节点配置缓存（Map<nodeId, config>）
  const [workflowNodeConfigCache, setWorkflowNodeConfigCache] = useState<Map<string, any>>(new Map());
  
  // 已完成的节点ID集合
  const [completedNodeIds, setCompletedNodeIds] = useState<Set<string>>(new Set());
  
  // 节点保存状态缓存（Map<nodeId, boolean>）- 用于记录当前作业中哪些节点已保存
  const [nodeSavedStatusCache, setNodeSavedStatusCache] = useState<Map<string, boolean>>(new Map());
  
  // 计算是否有未保存的节点（用于控制流程管理tab的下一步按钮）
  const hasUnsavedNodes = useMemo(() => {
    if (workflowNodes.length === 0) {
      return false; // 如果没有节点，认为没有未保存的节点
    }
    // 检查所有节点是否都已保存
    return workflowNodes.some(node => {
      const isSaved = nodeSavedStatusCache.get(node.id) || false;
      return !isSaved;
    });
  }, [workflowNodes, nodeSavedStatusCache]);

  const workflowSelectedType = selectedWorkflowNode?.data?.type || '';
  const workflowUnlockSideReadonly = useMemo(
    () =>
      isWorkflowUnlockSchemeType(workflowSelectedType) ||
      isWorkflowUnlockCoLockType(workflowSelectedType),
    [workflowSelectedType]
  );
  const workflowSchemePanelOpen = useMemo(
    () => isWorkflowIsolationSchemePanelType(workflowSelectedType),
    [workflowSelectedType]
  );
  
  // 节点类型映射（使用 useMemo 避免每次渲染都创建新对象）
  const nodeTypes: NodeTypes = useMemo(() => ({
    createJob: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    confirm: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    review: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    inputInfo: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    lock: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    isolation: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    unlock: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    releaseIsolation: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    coLock: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    unlockCoLock: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    returnLock: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
    complete: (props: any) => <CustomNode {...props} nodeSavedStatusCache={nodeSavedStatusCache} />,
  }), [nodeSavedStatusCache]);
  
  // 角色用户列表和表单列表
  const [workflowDrawerUsers, setWorkflowDrawerUsers] = useState<UserVO[]>([]);
  const [workflowLockerUsers, setWorkflowLockerUsers] = useState<UserVO[]>([]);
  const [workflowColockerUsers, setWorkflowColockerUsers] = useState<UserVO[]>([]);
  const [workflowCcDeptList, setWorkflowCcDeptList] = useState<DeptVO[]>([]);
  const [workflowCcUserList, setWorkflowCcUserList] = useState<UserVO[]>([]);
  const workflowCcDeptTreeData = useMemo(() => {
    const nodeMap = new Map<string, any>();
    const roots: any[] = [];
    workflowCcDeptList.forEach((dept) => {
      const id = String(dept.id);
      nodeMap.set(id, {
        key: `dept-${id}`,
        value: id,
        title: dept.name,
        children: [] as any[],
      });
    });
    workflowCcDeptList.forEach((dept) => {
      const id = String(dept.id);
      const parentId = String(dept.parentId ?? '');
      const node = nodeMap.get(id);
      const parent = nodeMap.get(parentId);
      if (parent && parentId !== id) {
        parent.children.push(node);
      } else {
        roots.push(node);
      }
    });
    return roots;
  }, [workflowCcDeptList]);
  const workflowCcUserTreeData = useMemo(() => {
    const buildDeptNode = (node: any): any => ({
      key: node.key,
      value: node.value,
      title: node.title,
      selectable: false,
      children: (node.children || []).map((c: any) => buildDeptNode(c)),
    });
    const roots = workflowCcDeptTreeData.map((n: any) => buildDeptNode(n));
    const deptNodeMap = new Map<string, any>();
    const walk = (nodes: any[]) => {
      nodes.forEach((n) => {
        deptNodeMap.set(String(n.value), n);
        if (Array.isArray(n.children) && n.children.length > 0) walk(n.children);
      });
    };
    walk(roots);
    const unknownDeptNode = {
      key: 'workflow-dept-unknown',
      value: 'unknown',
      title: '未分配部门',
      selectable: false,
      children: [] as any[],
    };
    workflowCcUserList.forEach((user) => {
      const userNode = {
        key: `workflow-user-${user.id}`,
        value: String(user.id),
        title: user.nickname || user.username,
        isLeaf: true,
      };
      const deptKey = user.deptId !== undefined && user.deptId !== null ? String(user.deptId) : '';
      const deptNode = deptNodeMap.get(deptKey);
      if (deptNode) {
        deptNode.children = [...(deptNode.children || []), userNode];
      } else {
        unknownDeptNode.children.push(userNode);
      }
    });
    if (unknownDeptNode.children.length > 0) {
      roots.push(unknownDeptNode);
    }
    return roots;
  }, [workflowCcDeptTreeData, workflowCcUserList]);
  const [workflowIsolationPoints, setWorkflowIsolationPoints] = useState<SegregationPointVO[]>([]);
  const [workflowFormList, setWorkflowFormList] = useState<FormVO[]>([]);

  const isTemplateEnabled = useCallback((value: any): boolean => {
    return value === true || value === 'true' || value === 1 || value === '1';
  }, []);

  const resolveNotificationMethods = useCallback((source: any, fallback?: any) => {
    const methods = source?.notificationMethods || {};
    const smsCode = source?.smsTemplateCode ?? fallback?.smsTemplateCode;
    const messageCode = source?.messageTemplateCode ?? fallback?.messageTemplateCode;
    const emailCode = source?.emailTemplateCode ?? fallback?.emailTemplateCode;
    const appCode = source?.appTemplateCode ?? fallback?.appTemplateCode;
    return {
      sms: (methods.sms === true || methods.sms === 'true') || isTemplateEnabled(smsCode),
      message: (methods.message === true || methods.message === 'true') || isTemplateEnabled(messageCode),
      email: (methods.email === true || methods.email === 'true') || isTemplateEnabled(emailCode),
      app: (methods.app === true || methods.app === 'true') || isTemplateEnabled(appCode),
    };
  }, [isTemplateEnabled]);
  
  // 流程设计列表数据（用于流程设计页面）
  const [processDesignList, setProcessDesignList] = useState<WorkflowDesignVO[]>([]);
  const [processDesignTotal, setProcessDesignTotal] = useState(0);
  const [processDesignLoading, setProcessDesignLoading] = useState(false);
  const [processDesignStatusUpdating, setProcessDesignStatusUpdating] = useState<Record<number, boolean>>({});
  
  // 作业分类字典数据
  const [workTypeDictList, setWorkTypeDictList] = useState<DictDataVO[]>([]);
  
  // 紧急程度字典数据
  const [urgencyLevelDictList, setUrgencyLevelDictList] = useState<DictDataVO[]>([]);
  
  // 隔离方式字典数据
  const [isolationTypeDictList, setIsolationTypeDictList] = useState<DictDataVO[]>([]);
  const [jobStatusDictList, setJobStatusDictList] = useState<DictDataVO[]>([]);
  
  // 流程设计列表数据（用于流程模板下拉框）
  const [workflowTemplateList, setWorkflowTemplateList] = useState<WorkflowDesignVO[]>([]);

  // iPad(iOS Safari) 触摸场景：点击页面空白处不会触发 Select blur，导致下拉不收起
  const workflowTemplateSelectWrapRef = useRef<HTMLDivElement | null>(null);
  const jobCategorySelectWrapRef = useRef<HTMLDivElement | null>(null);
  const workflowTemplateSelectRef = useRef<any>(null);
  const jobCategorySelectRef = useRef<any>(null);
  const [workflowTemplateDropdownVisible, setWorkflowTemplateDropdownVisible] = useState(false);
  const [jobCategoryDropdownVisible, setJobCategoryDropdownVisible] = useState(false);

  useEffect(() => {
    if (!workflowTemplateDropdownVisible && !jobCategoryDropdownVisible) return;

    const closeIfPointerOutside = (evt: Event) => {
      const target = (evt.target as HTMLElement | null);
      if (!target) return;

      const inWrap =
        (workflowTemplateSelectWrapRef.current && workflowTemplateSelectWrapRef.current.contains(target)) ||
        (jobCategorySelectWrapRef.current && jobCategorySelectWrapRef.current.contains(target));
      const inDropdown = !!target.closest?.('.ant-select-dropdown');

      if (!inWrap && !inDropdown) {
        setWorkflowTemplateDropdownVisible(false);
        setJobCategoryDropdownVisible(false);
      }
    };

    document.addEventListener('touchstart', closeIfPointerOutside, { passive: true });
    document.addEventListener('mousedown', closeIfPointerOutside);
    return () => {
      document.removeEventListener('touchstart', closeIfPointerOutside as any);
      document.removeEventListener('mousedown', closeIfPointerOutside as any);
    };
  }, [workflowTemplateDropdownVisible, jobCategoryDropdownVisible]);

  // 作业管理列表数据
  const [workJobList, setWorkJobList] = useState<WorkJobVO[]>([]);
  const [workJobTotal, setWorkJobTotal] = useState(0);
  const [workJobLoading, setWorkJobLoading] = useState(false);

  // 流程模板数据
  const templateData: TableRow[] = [
    { 
      id: 1, 
      code: 'TPL-001', 
      name: '高压设备隔离流程', 
      type: '标准流程',
      category: '高压作业',
      steps: 8,
      approvalLevel: '二级审批',
      creator: '张三',
      createTime: '2024-01-10',
      status: '启用',
      useCount: 45,
      remark: '适用于10kV及以上高压设备'
    },
    { 
      id: 2, 
      code: 'TPL-002', 
      name: '低压配电柜隔离流程', 
      type: '标准流程',
      category: '低压作业',
      steps: 6,
      approvalLevel: '一级审批',
      creator: '李四',
      createTime: '2024-01-15',
      status: '启用',
      useCount: 128,
      remark: '适用于380V配电柜'
    },
    { 
      id: 3, 
      code: 'TPL-003', 
      name: '紧急抢修隔离流程', 
      type: '应急流程',
      category: '应急处理',
      steps: 5,
      approvalLevel: '特殊审批',
      creator: '王五',
      createTime: '2024-02-01',
      status: '启用',
      useCount: 12,
      remark: '用于紧急故障抢修'
    },
    { 
      id: 4, 
      code: 'TPL-004', 
      name: '定期维护隔离流程', 
      type: '标准流程',
      category: '定期维护',
      steps: 7,
      approvalLevel: '一级审批',
      creator: '张三',
      createTime: '2024-02-10',
      status: '启用',
      useCount: 67,
      remark: '用于定期维护保养'
    },
  ];

  // SOP管理数据
  const sopData: TableRow[] = [
    { 
      id: 1, 
      code: 'SOP-001', 
      name: '高压开关操作规程', 
      version: 'V2.1',
      category: '操作规程',
      department: '技术部',
      effectiveDate: '2024-01-01',
      reviewDate: '2025-01-01',
      status: '有效',
      reviewer: '李四',
      lastUpdate: '2024-12-01',
      attachments: 2,
      remark: '包含视频培训资料'
    },
    { 
      id: 2, 
      code: 'SOP-002', 
      name: '配电柜断电操作规程', 
      version: 'V1.5',
      category: '操作规程',
      department: '运维部',
      effectiveDate: '2024-02-01',
      reviewDate: '2025-02-01',
      status: '有效',
      reviewer: '张三',
      lastUpdate: '2024-11-15',
      attachments: 1,
      remark: ''
    },
    { 
      id: 3, 
      code: 'SOP-003', 
      name: '接地线安装规程', 
      version: 'V3.0',
      category: '安全规程',
      department: '安全部',
      effectiveDate: '2024-01-15',
      reviewDate: '2025-01-15',
      status: '有效',
      reviewer: '王五',
      lastUpdate: '2024-12-03',
      attachments: 3,
      remark: '新增便携式接地线章节'
    },
    { 
      id: 4, 
      code: 'SOP-004', 
      name: '验电作业规程', 
      version: 'V2.0',
      category: '安全规程',
      department: '安全部',
      effectiveDate: '2024-03-01',
      reviewDate: '2025-03-01',
      status: '待审核',
      reviewer: '赵六',
      lastUpdate: '2024-11-30',
      attachments: 1,
      remark: '待技术部审核'
    },
  ];

  // 表单管理数据
  const formManagementData: TableRow[] = [
    { 
      id: 1, 
      name: '高压作业申请表', 
      creator: '张三',
      createTime: '2024-01-10 14:30',
      version: 'V1.0',
      status: '启用',
      description: '用于高压设备作业申请的表单',
      useCount: 45
    },
    { 
      id: 2, 
      name: '低压作业申请表', 
      creator: '李四',
      createTime: '2024-01-15 09:20',
      version: 'V1.2',
      status: '启用',
      description: '用于低压设备作业申请的表单',
      useCount: 128
    },
    { 
      id: 3, 
      name: '紧急抢修申请表', 
      creator: '王五',
      createTime: '2024-02-01 16:45',
      version: 'V2.0',
      status: '启用',
      description: '用于紧急故障抢修申请的表单',
      useCount: 12
    },
    { 
      id: 4, 
      name: '定期维护申请表', 
      creator: '张三',
      createTime: '2024-02-10 11:15',
      version: 'V1.5',
      status: '停用',
      description: '用于定期维护申请的表单',
      useCount: 67
    },
  ];

  // 表单管理搜索参数
  const [formManagementQuery, setFormManagementQuery] = useState({
    name: '',
    status: undefined as string | undefined,
  });
  const [formManagementPagination, setFormManagementPagination] = useState({
    pageNo: 1,
    pageSize: 10,
  });

  // 流程设计数据
  const processDesignData: TableRow[] = [
    { 
      id: 1, 
      name: '高压设备隔离流程设计', 
      designer: '张三',
      designTime: '2024-01-10 14:30',
      nodeCount: 8,
      description: '适用于10kV及以上高压设备的隔离作业流程',
      status: '启用'
    },
    { 
      id: 2, 
      name: '低压配电柜隔离流程设计', 
      designer: '李四',
      designTime: '2024-01-15 09:20',
      nodeCount: 6,
      description: '适用于380V配电柜的隔离作业流程',
      status: '启用'
    },
    { 
      id: 3, 
      name: '紧急抢修隔离流程设计', 
      designer: '王五',
      designTime: '2024-02-01 16:45',
      nodeCount: 5,
      description: '用于紧急故障抢修的快速隔离流程',
      status: '启用'
    },
    { 
      id: 4, 
      name: '定期维护隔离流程设计', 
      designer: '张三',
      designTime: '2024-02-10 11:15',
      nodeCount: 7,
      description: '用于定期维护保养的隔离流程',
      status: '停用'
    },
  ];

  // 流程设计搜索参数
  const [processDesignQuery, setProcessDesignQuery] = useState({
    name: '',
  });
  const [processDesignPagination, setProcessDesignPagination] = useState({
    pageNo: 1,
    pageSize: 10,
  });

  // 作业管理搜索参数
  // 从 sessionStorage 读取初始 status
  const getInitialWorkStatus = () => {
    const status = sessionStorage.getItem('workManagementStatus');
    return status || undefined;
  };

  const [workJobQuery, setWorkJobQuery] = useState({
    name: '',
    status: getInitialWorkStatus() as string | undefined,
  });
  const [workJobPagination, setWorkJobPagination] = useState({
    pageNo: 1,
    pageSize: 10,
  });

  // 作业管理数据（旧数据，保留用于兼容）
  const workData: TableRow[] = [
    { 
      id: 1, 
      code: 'WORK-2025-001', 
      name: '1号变压器定期检修', 
      type: '定期维护',
      template: '定期维护隔离流程',
      location: 'B区地下室变压器房',
      equipment: '变压器柜A',
      applicant: '李四',
      department: '技术部',
      planStartTime: '2025-12-10 08:00',
      planEndTime: '2025-12-10 18:00',
      status: '待审批',
      approver: '王五',
      priority: '普通',
      remark: '年度例行检修'
    },
    { 
      id: 2, 
      code: 'WORK-2025-002', 
      name: '2号配电柜故障抢修', 
      type: '应急处理',
      template: '紧急抢修隔离流程',
      location: 'A区2层配电室',
      equipment: '2号配电柜',
      applicant: '张三',
      department: '运维部',
      planStartTime: '2025-12-04 14:00',
      planEndTime: '2025-12-04 18:00',
      status: '进行中',
      approver: '李四',
      priority: '紧急',
      remark: '断路器跳闸需紧急处理'
    },
    { 
      id: 3, 
      code: 'WORK-2025-003', 
      name: 'A区照明回路维护', 
      type: '定期维护',
      template: '低压配电柜隔离流程',
      location: 'A区1层配电室',
      equipment: '1号配电柜',
      applicant: '王五',
      department: '运维部',
      planStartTime: '2025-12-05 09:00',
      planEndTime: '2025-12-05 12:00',
      status: '已完成',
      approver: '张三',
      priority: '普通',
      remark: ''
    },
    { 
      id: 4, 
      code: 'WORK-2025-004', 
      name: 'C区空调系统检查', 
      type: '定期维护',
      template: '低压配电柜隔离流程',
      location: 'C区3层控制室',
      equipment: '控制柜C1',
      applicant: '赵六',
      department: '运维部',
      planStartTime: '2025-12-06 08:00',
      planEndTime: '2025-12-06 11:00',
      status: '已完成',
      approver: '张三',
      priority: '普通',
      remark: '冬季例行检查'
    },
    { 
      id: 5, 
      code: 'WORK-2025-005', 
      name: '高压开关柜年检', 
      type: '定期维护',
      template: '高压设备隔离流程',
      location: 'B区地下室变压器房',
      equipment: '变压器柜A',
      applicant: '李四',
      department: '技术部',
      planStartTime: '2025-12-15 08:00',
      planEndTime: '2025-12-15 17:00',
      status: '待审批',
      approver: '王五',
      priority: '重要',
      remark: '需第三方检测机构配合'
    },
  ];

  // 表单管理搜索处理
  const handleFormManagementQuery = () => {
    // 这里可以添加搜索逻辑
    console.log('搜索表单管理:', formManagementQuery);
  };

  const resetFormManagementQuery = () => {
    setFormManagementQuery({
      name: '',
      status: undefined,
    });
  };

  // 获取流程设计列表
  const getProcessDesignList = async () => {
    setProcessDesignLoading(true);
    try {
      const response = await workflowDesignApi.getWorkflowDesignPage({
        pageNo: processDesignPagination.pageNo,
        pageSize: processDesignPagination.pageSize,
        name: processDesignQuery.name || undefined,
      });
      setProcessDesignList(response.list || []);
      setProcessDesignTotal(response.total || 0);
    } catch (error: any) {
      console.error('获取流程设计列表失败:', error);
      message.error(error?.message || '获取流程设计列表失败');
    } finally {
      setProcessDesignLoading(false);
    }
  };
  
  // 获取流程设计列表（用于流程模板下拉框，获取全部数据）
  const getWorkflowTemplateList = async () => {
    try {
      const response = await workflowDesignApi.getWorkflowDesignPage({
        pageNo: 1,
        pageSize: -1,
        status: 1, // 只获取启用状态（status=1）的流程模板
      });
      setWorkflowTemplateList(response.list || []);
    } catch (error: any) {
      console.error('获取流程模板列表失败:', error);
      setWorkflowTemplateList([]);
    }
  };

  // 处理流程设计状态切换
  const handleProcessDesignStatusChanged = async (record: WorkflowDesignVO, newStatus: number) => {
    if (!record.id) {
      message.error('流程设计ID不存在');
      return;
    }

    // 设置该记录为更新中状态
    setProcessDesignStatusUpdating(prev => ({ ...prev, [record.id!]: true }));

    try {
      await workflowDesignApi.updateWorkflowDesignStatus({
        id: record.id,
        status: newStatus,
      });
      
      // 更新本地列表中的状态
      setProcessDesignList(prev => 
        prev.map(item => 
          item.id === record.id ? { ...item, status: newStatus } : item
        )
      );
      
      message.success(newStatus === 1 ? '已启用' : '已禁用');
    } catch (error: any) {
      console.error('更新流程设计状态失败:', error);
      message.error(error?.message || '更新状态失败');
    } finally {
      // 清除更新中状态
      setProcessDesignStatusUpdating(prev => {
        const newState = { ...prev };
        delete newState[record.id!];
        return newState;
      });
    }
  };
  
  // 获取作业分类字典数据
  const getWorkTypeDictList = async () => {
    try {
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'work_type',
      });
      console.log('作业分类字典API响应:', response);
      const data = (response as any)?.data || response;
      console.log('作业分类字典解析后的data:', data);
      const list = data?.list || [];
      console.log('作业分类字典数据list:', list);
      setWorkTypeDictList(list);
    } catch (error: any) {
      console.error('获取作业分类字典失败:', error);
      console.error('错误详情:', error?.response?.data || error);
      setWorkTypeDictList([]);
    }
  };
  
  // 获取紧急程度字典数据
  const getUrgencyLevelDictList = async () => {
    try {
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'urgency_level',
      });
      console.log('紧急程度字典API响应:', response);
      const data = (response as any)?.data || response;
      console.log('紧急程度字典解析后的data:', data);
      const list = data?.list || [];
      console.log('紧急程度字典数据list:', list);
      console.log('紧急程度字典数据list长度:', list.length);
      setUrgencyLevelDictList(list);
      // 如果有数据且表单还没有设置值，设置默认值为第一项
      if (list.length > 0 && !workJobBasicForm.getFieldValue('urgency')) {
        workJobBasicForm.setFieldsValue({ urgency: list[0].value });
      }
    } catch (error: any) {
      console.error('获取紧急程度字典失败:', error);
      console.error('错误详情:', error?.response?.data || error);
      setUrgencyLevelDictList([]);
    }
  };
  
  // 获取隔离方式字典数据
  const getIsolationMethodDictList = async () => {
    try {
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'isolation_method',
      });
      const data = (response as any)?.data || response;
      const list = data?.list || [];
      setIsolationTypeDictList(list);
    } catch (error: any) {
      console.error('获取隔离方式字典失败:', error);
      setIsolationTypeDictList([]);
    }
  };

  // 获取作业状态字典数据
  const getJobStatusDictList = async () => {
    try {
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'job_status',
      });
      const data = (response as any)?.data || response;
      const list = data?.list || [];
      setJobStatusDictList(list);
    } catch (error: any) {
      console.error('获取作业状态字典失败:', error);
      setJobStatusDictList([]);
    }
  };

  // 流程设计搜索处理
  const handleProcessDesignQuery = () => {
    setProcessDesignPagination({ ...processDesignPagination, pageNo: 1 });
  };

  const resetProcessDesignQuery = () => {
    setProcessDesignQuery({
      name: '',
    });
    setProcessDesignPagination({ pageNo: 1, pageSize: 10 });
    // 立即调用接口刷新数据
    getProcessDesignList();
  };

  // 监听菜单切换，重置状态并加载数据
  useEffect(() => {
    // 当切换菜单时，重置相关状态并加载数据
    if (subMenu === '流程设计') {
      // 重置分页到第一页
      setProcessDesignPagination({ pageNo: 1, pageSize: 10 });
      // 重置查询条件
      setProcessDesignQuery({ name: '' });
      // 加载数据
      getProcessDesignList();
    } else if (subMenu === '作业管理') {
      // 重置分页到第一页
      setWorkJobPagination({ pageNo: 1, pageSize: 10 });
      // 检查是否有从 sessionStorage 传入的 status
      const statusFromStorage = sessionStorage.getItem('workManagementStatus');
      // 重置查询条件（如果有 status 则保留，否则清空）
      setWorkJobQuery({ name: '', status: statusFromStorage || undefined });
      // 如果读取了 status，清除 sessionStorage
      if (statusFromStorage) {
        sessionStorage.removeItem('workManagementStatus');
      }
      // 加载数据
      getWorkJobList();
      // 加载作业分类字典数据
      getWorkTypeDictList();
      // 加载紧急程度字典数据
      getUrgencyLevelDictList();
      // 加载作业状态字典数据
      getJobStatusDictList();
      // 加载隔离方式字典数据
      getIsolationMethodDictList();
      // 加载流程设计列表（用于流程模板下拉框）
      getWorkflowTemplateList();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [subMenu]);

  // 流程设计页面加载时获取列表
  useEffect(() => {
    if (subMenu === '流程设计') {
      getProcessDesignList();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [processDesignPagination.pageNo, processDesignPagination.pageSize, processDesignQuery.name]);

  // 获取作业管理列表
  const getWorkJobList = async () => {
    setWorkJobLoading(true);
    try {
      const response = await workJobApi.getWorkflowWorkPage({
        pageNo: workJobPagination.pageNo,
        pageSize: workJobPagination.pageSize,
        name: workJobQuery.name || undefined,
        status: workJobQuery.status || undefined,
      });
      setWorkJobList(response.list || []);
      setWorkJobTotal(response.total || 0);
    } catch (error: any) {
      console.error('获取作业列表失败:', error);
      message.error(error?.message || '获取作业列表失败');
      setWorkJobList([]);
      setWorkJobTotal(0);
    } finally {
      setWorkJobLoading(false);
    }
  };

  // 作业管理搜索处理
  const handleWorkJobQuery = () => {
    setWorkJobPagination({ ...workJobPagination, pageNo: 1 });
  };

  const resetWorkJobQuery = () => {
    setWorkJobQuery({
      name: '',
      status: undefined,
    });
    setWorkJobPagination({ pageNo: 1, pageSize: 10 });
  };

  // 组件挂载时从 sessionStorage 读取 status
  useEffect(() => {
    const status = sessionStorage.getItem('workManagementStatus');
    if (status) {
      console.log('从 sessionStorage 读取到 workManagementStatus:', status);
      setWorkJobQuery(prev => ({
        ...prev,
        status: status,
      }));
      // 读取后清除 sessionStorage，避免下次进入时自动应用
      sessionStorage.removeItem('workManagementStatus');
    }
  }, []);

  // 作业管理页面加载时获取列表
  useEffect(() => {
    if (subMenu === '作业管理') {
      getWorkJobList();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [workJobPagination.pageNo, workJobPagination.pageSize, workJobQuery.name, workJobQuery.status]);

  // 加载流程设计JSON并渲染到ReactFlow
  const loadWorkflowJson = async (workflowId: number) => {
    try {
      const response = await workflowDesignApi.selectWorkflowDesignById(workflowId);
      console.log('流程设计详情API响应:', response);
      
      // axios拦截器可能已经处理了数据格式，直接使用response
      const workflow = response;
      console.log('流程设计数据:', workflow);
      // console.log('content字段:', workflow.content);
      
      // 流程设计数据在 content 字段中（JSON字符串）
      let jsonData: any = null;
      // 检查 content 是否为 null 或空字符串
      const hasContent = workflow.content && workflow.content !== null && workflow.content !== '';
      
      if (hasContent) {
        try {
          jsonData = typeof workflow.content === 'string' 
            ? JSON.parse(workflow.content) 
            : workflow.content;
          console.log('解析后的JSON数据:', jsonData);
          setWorkflowJson(jsonData);
        } catch (parseError) {
          console.error('解析JSON失败:', parseError);
          console.error('原始content:', workflow.content);
          message.error('流程设计JSON格式错误');
          // 解析失败时清空流程
          setWorkflowJson(null);
          setWorkflowNodes([]);
          setWorkflowEdges([]);
          setWorkflowNodeConfigCache(new Map());
          setCompletedNodeIds(new Set());
          setNodeSavedStatusCache(new Map());
          setSelectedWorkflowNode(null);
          return;
        }
      } else {
        // content 为 null 或空时，清空流程，不使用备用数据
        console.warn('流程设计content为空或null，清空流程');
        setWorkflowJson(null);
        setWorkflowNodes([]);
        setWorkflowEdges([]);
        setWorkflowNodeConfigCache(new Map());
        setCompletedNodeIds(new Set());
        setNodeSavedStatusCache(new Map());
        setSelectedWorkflowNode(null);
        return;
      }
      
      // 解析并渲染到ReactFlow
      if (jsonData && jsonData.nodes && Array.isArray(jsonData.nodes) && jsonData.edges && Array.isArray(jsonData.edges)) {
        console.log('开始渲染节点和连线，节点数量:', jsonData.nodes.length, '连线数量:', jsonData.edges.length);
        
        // 创建节点映射，方便后续查找已保存的节点
        const nodeDOMap = new Map<string, WorkflowWorkNodeDO>();
        workflowWorkNodeDOList.forEach((nodeDO: WorkflowWorkNodeDO) => {
          if (nodeDO.uuid) {
            nodeDOMap.set(nodeDO.uuid, nodeDO);
          }
        });
        
        const importedNodes: Node[] = jsonData.nodes.map((node: any) => {
          const nodeData = node.data || {};
          const nodeId = node.id || node.uuid;
          const nodeDO = nodeDOMap.get(nodeId);
          
          // 获取图标：优先使用 nodeIcon（顶层），其次使用 data.icon
          const iconValue = node.nodeIcon || nodeData.icon || '';
          
          return {
            id: nodeId,
            type: node.type || 'createJob',
            position: node.position || { x: 0, y: 0 },
            data: (() => {
              const { isolationMethod, ...restNodeData } = nodeData || {};
              return {
                ...restNodeData,
                label: nodeData.label || node.label || node.nodeName || nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(node.type || nodeData.type)))?.label || '节点',
                type: node.type || nodeData.type || 'createJob',
                icon: iconValue, // 确保icon字段被正确传递
                // 标记节点是否已完成配置（如果 nodeDO 存在且有 id，说明已经保存过）
                completed: !!nodeDO?.id,
              };
            })(),
          };
        });
        
        const importedEdges: Edge[] = jsonData.edges.map((edge: any) => {
          // 处理sourceHandle和targetHandle
          // 如果JSON中有指定handle，使用指定的；否则根据连接方向推断
          let sourceHandle = edge.sourceHandle;
          let targetHandle = edge.targetHandle;
          
          // 如果没有指定handle，尝试从edge的id或其他字段推断
          // 例如：edge id可能是 "edge-confirm-xxx-right-source-createJob-xxx-left-target-xxx"
          if (!sourceHandle && edge.id) {
            const sourceMatch = edge.id.match(/right-source|left-source|top-source|bottom-source/);
            if (sourceMatch) {
              sourceHandle = sourceMatch[0].replace('-source', '');
            } else {
              // 默认使用右侧连接点
              sourceHandle = 'right-source';
            }
          } else if (!sourceHandle) {
            // 默认使用右侧连接点
            sourceHandle = 'right-source';
          }
          
          if (!targetHandle && edge.id) {
            const targetMatch = edge.id.match(/right-target|left-target|top-target|bottom-target/);
            if (targetMatch) {
              targetHandle = targetMatch[0].replace('-target', '');
            } else {
              // 默认使用左侧连接点
              targetHandle = 'left-target';
            }
          } else if (!targetHandle) {
            // 默认使用左侧连接点
            targetHandle = 'left-target';
          }
          
          return {
            id: edge.id || `${edge.source}-${edge.target}`,
            source: edge.source,
            target: edge.target,
            sourceHandle: sourceHandle,
            targetHandle: targetHandle,
            type: edge.type || 'straight',
            data: {
              fixedLength: edge.data?.fixedLength ?? 150,
              edgeType: edge.type || 'straight',
            },
            style: { strokeWidth: 2, stroke: '#000000' },
            markerStart: {
              type: 'arrowclosed',
              color: '#000000',
            },
          };
        });
        
        console.log('导入的节点:', importedNodes);
        console.log('导入的连线:', importedEdges);
        
        const finalNodes = shouldApplyLayout(importedNodes, importedEdges)
          ? getLayoutedNodes(importedNodes, importedEdges)
          : importedNodes;
        setWorkflowNodes(finalNodes);
        setWorkflowEdges(importedEdges);
        
        // 清空之前的缓存和完成状态
        setWorkflowNodeConfigCache(new Map());
        setCompletedNodeIds(new Set());
        // 清除节点保存状态缓存
        setNodeSavedStatusCache(new Map());
        
        // 自动选中第一个节点
        if (finalNodes.length > 0) {
          const firstNode = finalNodes[0];
          setTimeout(() => {
            setSelectedWorkflowNode(firstNode);
            const source = firstNode.data || {};
            const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(source.type)));
            setWorkflowNodeConfig({
              nodeName: source.label || config?.label || '',
              nodeIcon: source.icon || '',
              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 || '',
              isolationPoints: source.isolationPoints || [],
              isolationNode: source.isolationNode || [],
              isolationNodeUuid: source.isolationNodeUuid || '',
              lockPerson: source.lockPerson ? (typeof source.lockPerson === 'number' ? source.lockPerson : Number(source.lockPerson)) : undefined,
              coLockPersons: source.coLockPersons && Array.isArray(source.coLockPersons) ? source.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : [],
              notificationMethods: resolveNotificationMethods(source),
              notificationPerson: source.notificationPerson || '',
              notificationTime: source.notificationTime || '',
              smsTemplateCode: source.smsTemplateCode || 'false',
              messageTemplateCode: source.messageTemplateCode || 'false',
              emailTemplateCode: source.emailTemplateCode || 'false',
              appTemplateCode: source.appTemplateCode || 'false',
              copyDeptIds: workflowCopyDeptIds(source),
              copyUserIds: workflowCopyUserIds(source),
            });
            // 高亮第一个节点
            setWorkflowNodes((nds) =>
              nds.map((node) =>
                node.id === firstNode.id
                  ? { ...node, selected: true }
                  : { ...node, selected: false }
              )
            );
          }, 200);
        }
      } else {
        console.error('JSON数据格式错误，缺少nodes或edges:', jsonData);
        message.error('流程设计数据格式错误：缺少节点或连线数据');
      }
    } catch (error: any) {
      console.error('加载流程设计失败:', error);
      console.error('错误详情:', error?.response?.data || error);
      message.error('加载流程设计失败: ' + (error?.message || '未知错误'));
      
      // 使用备用JSON
      const fallbackJson = {
        nodes: [
          { id: '1', type: 'createJob', label: '提交/开始', position: { x: 100, y: 100 } },
          { id: '2', type: 'review', label: '审核/确认', position: { x: 300, y: 100 } },
          { id: '3', type: 'inputInfo', label: '录入/表单', position: { x: 500, y: 100 } },
          { id: '4', type: 'lock', label: '上锁', position: { x: 700, y: 100 } },
          { id: '5', type: 'unlock', label: '解锁', position: { x: 700, y: 300 } },
          { id: '6', type: 'complete', label: '完成/结束', position: { x: 900, y: 300 } },
        ],
        edges: [
          { id: 'e1-2', source: '1', target: '2' },
          { id: 'e2-3', source: '2', target: '3' },
          { id: 'e3-4', source: '3', target: '4' },
          { id: 'e4-5', source: '4', target: '5' },
          { id: 'e5-6', source: '5', target: '6' },
          { id: 'e2-5', source: '2', target: '5' },
        ],
      };
      setWorkflowJson(fallbackJson);
      
      const importedNodes: Node[] = fallbackJson.nodes.map((node: any) => ({
        id: node.id,
        type: node.type,
        position: node.position,
        data: {
          label: node.label,
          type: node.type,
          icon: node.icon || node.nodeIcon || '', // 确保icon字段被传递
        },
      }));
      
      const importedEdges: Edge[] = fallbackJson.edges.map((edge: any) => ({
        id: edge.id,
        source: edge.source,
        target: edge.target,
        type: edge.type || 'straight',
        data: {
          fixedLength: edge.data?.fixedLength ?? 150,
          edgeType: edge.type || 'straight',
        },
        style: { strokeWidth: 2, stroke: '#000000' },
        markerStart: {
          type: 'arrowclosed',
          color: '#000000',
        },
      }));
      
      const finalNodes = shouldApplyLayout(importedNodes, importedEdges)
        ? getLayoutedNodes(importedNodes, importedEdges)
        : importedNodes;
      setWorkflowNodes(finalNodes);
      setWorkflowEdges(importedEdges);
    }
  };
  
  // 加载角色用户列表和表单列表（用于节点配置）
  useEffect(() => {
    if (workJobStep === 1) {
      const loadRoleUsers = async () => {
        try {
          const [drawerRes, lockerRes, colockerRes] = await Promise.all([
            userApi.getRoleUser('jtdrawer'),
            userApi.getRoleUser('jtlocker'),
            userApi.getRoleUser('jtcolocker'),
          ]);
          setWorkflowDrawerUsers(drawerRes || []);
          setWorkflowLockerUsers(lockerRes || []);
          setWorkflowColockerUsers(colockerRes || []);
        } catch (error) {
          console.error('加载角色用户失败:', error);
        }
      };
      
      const loadIsolationPoints = async () => {
        try {
          const res = await segregationPointApi.getIsIsolationPointPage({ pageNo: 1, pageSize: -1 });
          setWorkflowIsolationPoints(res.list || []);
        } catch (error) {
          console.error('加载隔离点列表失败:', error);
        }
      };
      
      const loadFormList = async () => {
        try {
          // 只获取开启状态（status=0）的表单
          const res = await getFormPage({ pageNo: 1, pageSize: -1, status: 0 });
          setWorkflowFormList(res.list || []);
        } catch (error) {
          console.error('加载表单列表失败:', error);
        }
      };

      const loadCcOptions = async () => {
        try {
          const [depts, users] = await Promise.all([
            deptApi.getSimpleDeptList(),
            userApi.getSimpleUserList(),
          ]);
          setWorkflowCcDeptList(depts || []);
          setWorkflowCcUserList(users || []);
        } catch (error) {
          console.error('加载抄送下拉数据失败:', error);
        }
      };
      
      // 初始化节点状态：调用 checkWorkById 和 selectWorkflowWorkById 接口
      const initializeNodeStates = async () => {
        if (!workflowWorkId) {
          console.warn('workflowWorkId 不存在，无法初始化节点状态');
          return;
        }
        
        try {
          // 1. 调用 checkWorkById 获取未保存的节点列表
          const checkResponse = await workJobApi.checkWorkById(workflowWorkId);
          const checkData = (checkResponse as any)?.data || checkResponse;
          const unsavedNodeMessages = Array.isArray(checkData) ? checkData : (checkData ? [checkData] : []);
          
          // 2. 调用 selectWorkflowWorkById 获取所有节点数据
          const detailResponse = await workJobApi.selectWorkflowWorkById(workflowWorkId);
          const detail = detailResponse as any;
          
          if (detail.workflowWorkNodeDOList && Array.isArray(detail.workflowWorkNodeDOList)) {
            // 更新 workflowWorkNodeDOList
            setWorkflowWorkNodeDOList(detail.workflowWorkNodeDOList);
            
            // 3. 根据接口数据初始化缓存和节点状态
            // 创建新的缓存和状态，不使用旧的（因为我们要用接口数据覆盖）
            const newCache = new Map<string, any>();
            const newCompleted = new Set<string>();
            const newSavedStatusCache = new Map<string, boolean>();
            
            // 遍历所有节点，初始化缓存
            detail.workflowWorkNodeDOList.forEach((nodeDO: WorkflowWorkNodeDO) => {
              if (!nodeDO.uuid) return;
              
              // 解析节点数据
              let nodeData: any = {};
              if (nodeDO.data) {
                try {
                  nodeData = typeof nodeDO.data === 'string' ? JSON.parse(nodeDO.data) : nodeDO.data;
                } catch (e) {
                  console.error('解析节点data失败:', e);
                }
              }
              
              // 构建节点配置
              const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(nodeDO.type || nodeData.type)));
              const nodeConfig = {
                nodeName: nodeDO.nodeName || nodeData.label || config?.label || '',
                nodeIcon: nodeDO.nodeIcon || nodeData.icon || '',
                responsible: (nodeDO.workerUserId !== null && nodeDO.workerUserId !== undefined && nodeDO.workerUserId !== 0) 
                  ? (typeof nodeDO.workerUserId === 'number' ? nodeDO.workerUserId : Number(nodeDO.workerUserId)) 
                  : (nodeData.workerUserId && nodeData.workerUserId !== '' && nodeData.workerUserId !== '0') 
                    ? (typeof nodeData.workerUserId === 'number' ? nodeData.workerUserId : Number(nodeData.workerUserId)) 
                    : 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 || ''),
                isolationPoints: nodeDO.isolationPoints ? (typeof nodeDO.isolationPoints === 'string' ? JSON.parse(nodeDO.isolationPoints) : nodeDO.isolationPoints) : (nodeData.isolationPoints || []),
                isolationNode: nodeData.isolationNode || [],
                isolationNodeUuid: nodeDO.isolationNodeUuid || nodeData.isolationNodeUuid || '',
                lockPerson: (() => {
                  // 优先从 nodeUserList 中提取
                  let lockPersonId: number | undefined = undefined;
                  if (nodeDO.nodeUserList && Array.isArray(nodeDO.nodeUserList)) {
                    const lockerUser = nodeDO.nodeUserList.find((user: any) => user.type === 'jtlocker');
                    if (lockerUser?.userId) {
                      lockPersonId = typeof lockerUser.userId === 'number' ? lockerUser.userId : Number(lockerUser.userId);
                    }
                  }
                  return lockPersonId || (nodeData.lockPerson ? (typeof nodeData.lockPerson === 'number' ? nodeData.lockPerson : Number(nodeData.lockPerson)) : undefined);
                })(),
                coLockPersons: (() => {
                  // 优先从 nodeUserList 中提取
                  const coLockPersonIds: number[] = [];
                  if (nodeDO.nodeUserList && Array.isArray(nodeDO.nodeUserList)) {
                    nodeDO.nodeUserList.forEach((user: any) => {
                      if (user.type === 'jtcolocker' && user.userId) {
                        coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
                      }
                    });
                  }
                  return coLockPersonIds.length > 0 ? coLockPersonIds : (nodeData.coLockPersons && Array.isArray(nodeData.coLockPersons) ? nodeData.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : []);
                })(),
                notificationMethods: resolveNotificationMethods(nodeData, nodeDO),
                notificationPerson: nodeData.notificationPerson || '',
                notificationTime: nodeDO.notifyTime || nodeData.notificationTime || '',
                smsTemplateCode: nodeData.smsTemplateCode || (nodeData.notificationMethods?.sms ? 'true' : 'false'),
                messageTemplateCode: nodeData.messageTemplateCode || (nodeData.notificationMethods?.message ? 'true' : 'false'),
                emailTemplateCode: nodeData.emailTemplateCode || (nodeData.notificationMethods?.email ? 'true' : 'false'),
                appTemplateCode: nodeData.appTemplateCode || (nodeData.notificationMethods?.app ? 'true' : 'false'),
                copyDeptIds: workflowCopyDeptIds(nodeData, nodeDO),
                copyUserIds: workflowCopyUserIds(nodeData, nodeDO),
              };
              
              // 将节点配置存入缓存
              newCache.set(nodeDO.uuid, nodeConfig);
              
              // 检查节点是否已保存（如果不在未保存列表中，说明已保存）
              // 通过检查未保存消息中是否包含该节点的信息来判断
              const isNodeUnsaved = unsavedNodeMessages.some((msg: string) => {
                // 如果消息中包含节点名称或UUID，说明该节点未保存
                return msg.includes(nodeDO.nodeName || '') || msg.includes(nodeDO.uuid || '');
              });
              
              if (!isNodeUnsaved) {
                // 节点已保存，标记为已完成
                newCompleted.add(nodeDO.uuid);
                newSavedStatusCache.set(nodeDO.uuid, true);
              } else {
                // 节点未保存
                newSavedStatusCache.set(nodeDO.uuid, false);
              }
            });
            
            // 更新缓存和状态
            setWorkflowNodeConfigCache(newCache);
            setCompletedNodeIds(newCompleted);
            setNodeSavedStatusCache(newSavedStatusCache);
            
            console.log('节点状态初始化完成:', {
              totalNodes: detail.workflowWorkNodeDOList.length,
              completedNodes: newCompleted.size,
              unsavedNodes: unsavedNodeMessages.length,
            });
            
            // 找到第一个未保存的节点并自动选中（按照流程顺序）
            // 等待 workflowNodes 渲染完成后再选中
            // 使用 setState 的回调形式确保获取最新的 workflowNodes
            setTimeout(() => {
              setWorkflowNodes((currentNodes) => {
                // 使用 getNextIncompleteNode 的逻辑，但基于 nodeSavedStatusCache 来判断
                // 找到第一个未保存的节点（按照流程顺序）
                let firstUnsavedNode: Node | null = null;
                
                if (workflowJson && workflowJson.adjacency && currentNodes.length > 0) {
                  const adjacency = workflowJson.adjacency;
                  const nodeMap = new Map<string, Node>();
                  
                  // 初始化节点映射
                  currentNodes.forEach(node => {
                    nodeMap.set(node.id, node);
                  });
                  
                  // 辅助函数：检查节点的所有父节点是否都已保存
                  const areAllParentsSaved = (nodeId: string): boolean => {
                    const nodeInfo = adjacency[nodeId];
                    if (!nodeInfo || !nodeInfo.parentUuid || nodeInfo.parentUuid.length === 0) {
                      return true; // 没有父节点，可以执行
                    }
                    return nodeInfo.parentUuid.every((parentId: string) => {
                      const isParentSaved = newSavedStatusCache.get(parentId);
                      return isParentSaved === true; // 父节点已保存
                    });
                  };
                  
                  // 辅助函数：获取节点的第一个未保存的子节点
                  const getFirstUnsavedChild = (nodeId: string): string | null => {
                    const nodeInfo = adjacency[nodeId];
                    if (!nodeInfo || !nodeInfo.childrenUuid || nodeInfo.childrenUuid.length === 0) {
                      return null; // 没有子节点
                    }
                    
                    // 按顺序查找第一个未保存的子节点
                    for (const childId of nodeInfo.childrenUuid) {
                      const isChildSaved = newSavedStatusCache.get(childId);
                      if (isChildSaved === false && areAllParentsSaved(childId)) {
                        return childId;
                      }
                    }
                    
                    return null;
                  };
                  
                  // BFS遍历查找第一个未保存的节点
                  const queue: string[] = [];
                  const visited = new Set<string>();
                  
                  // 找到所有开始节点（parentUuid 为空的节点）
                  for (const nodeId in adjacency) {
                    const nodeInfo = adjacency[nodeId];
                    if (!nodeInfo.parentUuid || nodeInfo.parentUuid.length === 0) {
                      const isSaved = newSavedStatusCache.get(nodeId);
                      if (isSaved === false) {
                        // 如果开始节点未保存，直接返回
                        firstUnsavedNode = nodeMap.get(nodeId) || null;
                        if (firstUnsavedNode) {
                          break;
                        }
                      } else {
                        // 如果开始节点已保存，将其子节点加入队列
                        if (nodeInfo.childrenUuid && nodeInfo.childrenUuid.length > 0) {
                          nodeInfo.childrenUuid.forEach((childId: string) => {
                            if (!visited.has(childId)) {
                              queue.push(childId);
                              visited.add(childId);
                            }
                          });
                        }
                      }
                    }
                  }
                  
                  // 如果开始节点都已保存，BFS遍历查找下一个未保存的节点
                  if (!firstUnsavedNode) {
                    while (queue.length > 0) {
                      const currentNodeId = queue.shift()!;
                      
                      const isSaved = newSavedStatusCache.get(currentNodeId);
                      if (isSaved === false && areAllParentsSaved(currentNodeId)) {
                        firstUnsavedNode = nodeMap.get(currentNodeId) || null;
                        if (firstUnsavedNode) {
                          break;
                        }
                      }
                      
                      // 如果当前节点已保存，将其子节点加入队列
                      const nodeInfo = adjacency[currentNodeId];
                      if (nodeInfo && nodeInfo.childrenUuid && nodeInfo.childrenUuid.length > 0) {
                        nodeInfo.childrenUuid.forEach((childId: string) => {
                          if (!visited.has(childId)) {
                            queue.push(childId);
                            visited.add(childId);
                          }
                        });
                      }
                    }
                  }
                } else {
                  // 如果没有 adjacency 信息，回退到简单查找
                  firstUnsavedNode = currentNodes.find(node => {
                    const isSaved = newSavedStatusCache.get(node.id);
                    return isSaved === false; // 明确为 false 表示未保存
                  }) || null;
                }
                
                if (!firstUnsavedNode) {
                  console.log('没有找到未保存的节点，所有节点都已保存');
                  return currentNodes;
                }
                
                // 选中第一个未保存的节点
                setSelectedWorkflowNode(firstUnsavedNode);
                
                // 从缓存中获取节点配置
                const cachedConfig = newCache.get(firstUnsavedNode.id);
                if (cachedConfig) {
                  setWorkflowNodeConfig(cachedConfig);
                } else {
                  // 如果缓存中没有，从 nodeDO 中获取
                  const nodeDO = detail.workflowWorkNodeDOList.find(item => item.uuid === firstUnsavedNode.id);
                  if (nodeDO) {
                    let nodeData: any = {};
                    if (nodeDO.data) {
                      try {
                        nodeData = typeof nodeDO.data === 'string' ? JSON.parse(nodeDO.data) : nodeDO.data;
                      } catch (e) {
                        console.error('解析节点data失败:', e);
                      }
                    }
                    const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(nodeDO.type || nodeData.type)));
                    setWorkflowNodeConfig({
                      nodeName: nodeDO.nodeName || nodeData.label || config?.label || '',
                      nodeIcon: nodeDO.nodeIcon || nodeData.icon || '',
                      responsible: (nodeDO.workerUserId !== null && nodeDO.workerUserId !== undefined && nodeDO.workerUserId !== 0) 
                        ? (typeof nodeDO.workerUserId === 'number' ? nodeDO.workerUserId : Number(nodeDO.workerUserId)) 
                        : (nodeData.workerUserId && nodeData.workerUserId !== '' && nodeData.workerUserId !== '0') 
                          ? (typeof nodeData.workerUserId === 'number' ? nodeData.workerUserId : Number(nodeData.workerUserId)) 
                          : 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 || ''),
                      isolationPoints: nodeDO.isolationPoints ? (typeof nodeDO.isolationPoints === 'string' ? JSON.parse(nodeDO.isolationPoints) : nodeDO.isolationPoints) : (nodeData.isolationPoints || []),
                      isolationNode: nodeData.isolationNode || [],
                      isolationNodeUuid: nodeDO.isolationNodeUuid || nodeData.isolationNodeUuid || '',
                      lockPerson: (() => {
                        let lockPersonId: number | undefined = undefined;
                        if (nodeDO.nodeUserList && Array.isArray(nodeDO.nodeUserList)) {
                          const lockerUser = nodeDO.nodeUserList.find((user: any) => user.type === 'jtlocker');
                          if (lockerUser?.userId) {
                            lockPersonId = typeof lockerUser.userId === 'number' ? lockerUser.userId : Number(lockerUser.userId);
                          }
                        }
                        return lockPersonId || (nodeData.lockPerson ? (typeof nodeData.lockPerson === 'number' ? nodeData.lockPerson : Number(nodeData.lockPerson)) : undefined);
                      })(),
                      coLockPersons: (() => {
                        const coLockPersonIds: number[] = [];
                        if (nodeDO.nodeUserList && Array.isArray(nodeDO.nodeUserList)) {
                          nodeDO.nodeUserList.forEach((user: any) => {
                            if (user.type === 'jtcolocker' && user.userId) {
                              coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
                            }
                          });
                        }
                        return coLockPersonIds.length > 0 ? coLockPersonIds : (nodeData.coLockPersons && Array.isArray(nodeData.coLockPersons) ? nodeData.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : []);
                      })(),
                      notificationMethods: resolveNotificationMethods(nodeData, nodeDO),
                      notificationPerson: nodeData.notificationPerson || '',
                      notificationTime: nodeDO.notifyTime || nodeData.notificationTime || '',
                      smsTemplateCode: nodeData.smsTemplateCode || (nodeData.notificationMethods?.sms ? 'true' : 'false'),
                      messageTemplateCode: nodeData.messageTemplateCode || (nodeData.notificationMethods?.message ? 'true' : 'false'),
                      emailTemplateCode: nodeData.emailTemplateCode || (nodeData.notificationMethods?.email ? 'true' : 'false'),
                      appTemplateCode: nodeData.appTemplateCode || (nodeData.notificationMethods?.app ? 'true' : 'false'),
                      copyDeptIds: workflowCopyDeptIds(nodeData, nodeDO),
                      copyUserIds: workflowCopyUserIds(nodeData, nodeDO),
                    });
                  } else {
                    // 如果既没有缓存也没有 nodeDO，使用节点原始数据
                    const source = firstUnsavedNode.data || {};
                    const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(source.type)));
                    setWorkflowNodeConfig({
                      nodeName: source.label || config?.label || '',
                      nodeIcon: source.icon || '',
                      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 || '',
                      isolationPoints: source.isolationPoints || [],
                      isolationNode: source.isolationNode || [],
                      isolationNodeUuid: source.isolationNodeUuid || '',
                      lockPerson: source.lockPerson ? (typeof source.lockPerson === 'number' ? source.lockPerson : Number(source.lockPerson)) : undefined,
                      coLockPersons: source.coLockPersons && Array.isArray(source.coLockPersons) ? source.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : [],
                      notificationMethods: resolveNotificationMethods(source),
                      notificationPerson: source.notificationPerson || '',
                      notificationTime: source.notificationTime || '',
                      smsTemplateCode: source.smsTemplateCode || 'false',
                      messageTemplateCode: source.messageTemplateCode || 'false',
                      emailTemplateCode: source.emailTemplateCode || 'false',
                      appTemplateCode: source.appTemplateCode || 'false',
                      copyDeptIds: workflowCopyDeptIds(source),
                      copyUserIds: workflowCopyUserIds(source),
                    });
                  }
                }
                
                console.log('自动选中第一个未保存的节点:', firstUnsavedNode.id);
                
                // 高亮选中的节点
                return currentNodes.map((node) =>
                  node.id === firstUnsavedNode.id
                    ? { ...node, selected: true }
                    : { ...node, selected: false }
                );
              });
            }, 300); // 延迟300ms，确保 workflowNodes 已经渲染完成
          }
        } catch (error: any) {
          console.error('初始化节点状态失败:', error);
          message.error('加载节点状态失败: ' + (error?.message || '未知错误'));
        }
      };
      
      loadRoleUsers();
      loadIsolationPoints();
      loadFormList();
      loadCcOptions();
      initializeNodeStates();
    }
  }, [workJobStep, workflowWorkId]);
  
  // 验证节点配置是否完整
  const validateNodeConfig = useCallback((config: any, nodeType: string): boolean => {
    // 节点名称必填
    if (!config.nodeName || config.nodeName.trim() === '') {
      return false;
    }
    
    // 业务表单必填（只有确认节点、审核节点、录入信息节点需要必填）
    const formRequiredNodeTypes = ['confirm', 'review', 'inputInfo'];
    if (formRequiredNodeTypes.includes(nodeType) && !config.submitForm) {
      return false;
    }
    
    // 负责人必填（创建作业、上锁/解锁/共锁类方案节点除外）；方案节点负责人在隔离方式规则中校验
    if (
      nodeType !== 'createJob' &&
      !isWorkflowLockLikeValidationType(nodeType) &&
      !isWorkflowUnlockLikeValidationType(nodeType)
    ) {
      if (!config.responsible) {
        return false;
      }
    }
    
    // 共锁节点：仅校验关联的上锁任务（隔离方式等随上锁任务同步）
    if (isWorkflowCoLockType(nodeType)) {
      if (!config.isolationNodeUuid || config.isolationNodeUuid === '') {
        return false;
      }
      return true;
    }

    // 上锁节点特殊验证（不含共锁节点）
    if (isWorkflowLockSchemeType(nodeType)) {
      if (!config.isolationType || config.isolationType === '') {
        return false;
      }
      if (!config.isolationPoints || !Array.isArray(config.isolationPoints) || config.isolationPoints.length === 0) {
        return false;
      }
      // 字典值：0=盲板，1=上锁挂牌，2=拆除
      if (config.isolationType === '0' || config.isolationType === '2') {
        if (!config.responsible) {
          return false;
        }
      }
      if (config.isolationType === '1') {
        if (!config.lockPerson) {
          return false;
        }
      }
    }
    
    // 解锁/解除共锁节点特殊验证
    if (isWorkflowUnlockLikeValidationType(nodeType)) {
      if (!config.isolationNodeUuid || config.isolationNodeUuid === '') {
        return false;
      }
    }
    
    return true;
  }, []);
  
  // 获取下一个未完成的节点（基于 workflowJson 中的 adjacency 信息）
  // 规则：
  // 1. 从开始节点（parentUuid 为空的节点）开始
  // 2. 按照 adjacency 中的 childrenUuid 顺序执行
  // 3. 如果有多个子节点，按顺序一个一个执行
  // 4. 所有子节点完成后，再找下一个节点
  const getNextIncompleteNode = useCallback((completedSet?: Set<string>, currentNodeId?: string): Node | null => {
    const completed = completedSet || completedNodeIds;
    
    // 如果所有节点都已完成，返回null
    if (completed.size === workflowNodes.length) {
      return null;
    }
    
    // 从 workflowJson 中获取 adjacency 信息
    if (!workflowJson || !workflowJson.adjacency) {
      // 如果没有 adjacency 信息，回退到使用边的逻辑
      console.warn('workflowJson 中没有 adjacency 信息，使用边的逻辑');
      return null;
    }
    
    const adjacency = workflowJson.adjacency;
    const nodeMap = new Map<string, Node>(); // 节点ID -> 节点对象
    
    // 初始化节点映射
    workflowNodes.forEach(node => {
      nodeMap.set(node.id, node);
    });
    
    // 辅助函数：检查节点的所有父节点是否都已完成
    const areAllParentsCompleted = (nodeId: string): boolean => {
      const nodeInfo = adjacency[nodeId];
      if (!nodeInfo || !nodeInfo.parentUuid || nodeInfo.parentUuid.length === 0) {
        return true; // 没有父节点，可以执行
      }
      return nodeInfo.parentUuid.every((parentId: string) => completed.has(parentId));
    };
    
    // 辅助函数：获取节点的第一个未完成的子节点
    const getFirstIncompleteChild = (nodeId: string): string | null => {
      const nodeInfo = adjacency[nodeId];
      if (!nodeInfo || !nodeInfo.childrenUuid || nodeInfo.childrenUuid.length === 0) {
        return null; // 没有子节点
      }
      
      // 按顺序查找第一个未完成的子节点
      for (const childId of nodeInfo.childrenUuid) {
        if (!completed.has(childId) && areAllParentsCompleted(childId)) {
          return childId;
        }
      }
      
      return null;
    };
    
    // 如果提供了当前节点ID，优先查找当前节点的下一个子节点
    if (currentNodeId && adjacency[currentNodeId]) {
      const nextChildId = getFirstIncompleteChild(currentNodeId);
      if (nextChildId) {
        const nextNode = nodeMap.get(nextChildId);
        if (nextNode) {
          return nextNode;
        }
      }
    }
    
    // 如果没有当前节点或当前节点的子节点都已完成，使用BFS查找下一个可执行的节点
    const queue: string[] = [];
    const visited = new Set<string>();
    
    // 找到所有开始节点（parentUuid 为空的节点）
    for (const nodeId in adjacency) {
      const nodeInfo = adjacency[nodeId];
      if (!nodeInfo.parentUuid || nodeInfo.parentUuid.length === 0) {
        if (!completed.has(nodeId)) {
          // 如果开始节点未完成，直接返回
          const node = nodeMap.get(nodeId);
          if (node) {
            return node;
          }
        } else {
          // 如果开始节点已完成，将其子节点加入队列
          if (nodeInfo.childrenUuid && nodeInfo.childrenUuid.length > 0) {
            nodeInfo.childrenUuid.forEach((childId: string) => {
              if (!visited.has(childId)) {
                queue.push(childId);
                visited.add(childId);
              }
            });
          }
        }
      }
    }
    
    // BFS遍历查找下一个可执行的未完成节点
    while (queue.length > 0) {
      const currentNodeId = queue.shift()!;
      
      // 如果当前节点未完成，检查是否可执行（所有父节点都已完成）
      if (!completed.has(currentNodeId) && areAllParentsCompleted(currentNodeId)) {
        const node = nodeMap.get(currentNodeId);
        if (node) {
          return node;
        }
      }
      
      // 如果当前节点已完成，将其子节点加入队列（按顺序）
      if (completed.has(currentNodeId)) {
        const nodeInfo = adjacency[currentNodeId];
        if (nodeInfo && nodeInfo.childrenUuid && nodeInfo.childrenUuid.length > 0) {
          nodeInfo.childrenUuid.forEach((childId: string) => {
            if (!visited.has(childId)) {
              queue.push(childId);
              visited.add(childId);
            }
          });
        }
      }
    }
    
    return null;
  }, [workflowNodes, workflowEdges, completedNodeIds, workflowJson]);
  
  // 节点点击事件
  const onWorkflowNodeClick = useCallback((event: React.MouseEvent, node: Node) => {
    console.log('点击节点:', node.id);
    workflowNodeConfigForIdRef.current = node.id;
    
    // 更新节点选中状态
    setWorkflowNodes((nds) =>
      nds.map((n) =>
        n.id === node.id
          ? { ...n, selected: true }
          : { ...n, selected: false }
      )
    );
    
    // 先计算并设置右侧面板的 config，再设置选中的节点，避免切换时出现「选中已变但面板仍显示上一节点」的中间状态
    const nodeDO = workflowWorkNodeDOList.find(item => item.uuid === node.id);
    
    console.log('点击节点:', node.id, '找到的 nodeDO:', nodeDO);
    console.log('当前 workflowWorkNodeDOList:', workflowWorkNodeDOList);
    
    if (nodeDO) {
      const isUnlockBranch =
        isWorkflowUnlockSchemeType(nodeDO.type) || isWorkflowUnlockCoLockType(nodeDO.type);
      const isolationNodeUuid = nodeDO.isolationNodeUuid || '';
      // 解锁/解除共锁：从关联的上锁或共锁节点抓取表单信息填充，保证两节点内容一致
      const isolationNodeDO =
        isUnlockBranch && isolationNodeUuid
          ? workflowWorkNodeDOList.find(
              (item: WorkflowWorkNodeDO) =>
                item.uuid === isolationNodeUuid &&
                isWorkflowUnlockParentMatch(nodeDO.type, item.type)
            )
          : null;
      // 解除类节点：仅从关联方案源携带「隔离方式」及以下数据；节点名称、业务表单保持本节点自身不变
      const dataSource = isolationNodeDO ?? nodeDO;
      let nodeData: any = {};
      if (dataSource.data) {
        try {
          nodeData = typeof dataSource.data === 'string' ? JSON.parse(dataSource.data) : dataSource.data;
        } catch (e) {
          console.error('解析节点data失败:', e);
        }
      }
      const source = nodeData || node.data || {};
      // 解除类节点自身的 data（仅用于 nodeName、submitForm 保持本节点）
      let releaseNodeData: any = {};
      if (isUnlockBranch && isolationNodeDO && nodeDO.data) {
        try {
          releaseNodeData = typeof nodeDO.data === 'string' ? JSON.parse(nodeDO.data) : nodeDO.data;
        } catch (_) {}
      }
      
      let lockPersonId: string | number = '';
      const coLockPersonIds: (string | number)[] = [];
      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) {
            coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
          }
        });
      }
      
      const config = nodeConfigs.find((c) =>
        c.type === resolveWorkflowPaletteType(String(nodeDO.type || source.type))
      );
      
      let isolationPoints: string[] = [];
      if (dataSource.isolationPoints) {
        try {
          isolationPoints = typeof dataSource.isolationPoints === 'string'
            ? JSON.parse(dataSource.isolationPoints)
            : (Array.isArray(dataSource.isolationPoints) ? dataSource.isolationPoints : []);
        } catch (e) {
          isolationPoints = source.isolationPoints || [];
        }
      } else {
        isolationPoints = source.isolationPoints || [];
      }
      
      const fromIsolationOnly = isUnlockBranch && isolationNodeDO;
      // 解除类节点且有关联方案源时：表单项仅从方案源(dataSource)取数，不兜底 source/node.data
      const isolationOnlyIsolationPoints = fromIsolationOnly && dataSource.isolationPoints
        ? (() => {
            try {
              return typeof dataSource.isolationPoints === 'string'
                ? JSON.parse(dataSource.isolationPoints)
                : (Array.isArray(dataSource.isolationPoints) ? dataSource.isolationPoints : []);
            } catch (_) { return []; }
          })()
        : (fromIsolationOnly ? [] : isolationPoints);
      const nodeConfig = {
        nodeName: fromIsolationOnly
          ? (nodeDO.nodeName || releaseNodeData.label || node.data?.label || config?.label || '')
          : (dataSource.nodeName || source.label || config?.label || ''),
        nodeIcon: (isolationNodeDO ? nodeDO.nodeIcon : dataSource.nodeIcon) || source.icon || '',
        responsible: fromIsolationOnly
          ? (dataSource.workerUserId !== null && dataSource.workerUserId !== undefined && dataSource.workerUserId !== 0 ? (typeof dataSource.workerUserId === 'number' ? dataSource.workerUserId : Number(dataSource.workerUserId)) : undefined)
          : (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: 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 ? (dataSource.isolationType != null && dataSource.isolationType !== undefined ? String(dataSource.isolationType) : '') : (dataSource.isolationType !== null && dataSource.isolationType !== undefined ? String(dataSource.isolationType) : (source.isolationType || '')),
        isolationPoints: fromIsolationOnly ? isolationOnlyIsolationPoints : isolationPoints,
        isolationNode: source.isolationNode || [],
        isolationNodeUuid: nodeDO.isolationNodeUuid || source.isolationNodeUuid || '',
        lockPerson: fromIsolationOnly ? (lockPersonId || undefined) : (lockPersonId || (source.lockPerson ? (typeof source.lockPerson === 'number' ? source.lockPerson : Number(source.lockPerson)) : undefined)),
        coLockPersons: fromIsolationOnly ? coLockPersonIds : (coLockPersonIds.length > 0 ? coLockPersonIds : (source.coLockPersons && Array.isArray(source.coLockPersons) ? source.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : [])),
        notificationMethods: resolveNotificationMethods(source, dataSource),
        notificationPerson: source.notificationPerson || '',
        notificationTime: fromIsolationOnly ? (dataSource.notifyTime ?? '') : (dataSource.notifyTime || source.notificationTime || ''),
        smsTemplateCode: source.smsTemplateCode || 'false',
        messageTemplateCode: source.messageTemplateCode || 'false',
        emailTemplateCode: source.emailTemplateCode || 'false',
        appTemplateCode: source.appTemplateCode || 'false',
        copyDeptIds: workflowCopyDeptIds(source, nodeDO),
        copyUserIds: workflowCopyUserIds(source, nodeDO),
      };
      
      if (isUnlockBranch && isolationNodeDO) {
        setWorkflowNodeConfig(() => ({ ...nodeConfig }));
      } else {
        const cachedConfig = workflowNodeConfigCache.get(node.id);
        if (cachedConfig) {
          setWorkflowNodeConfig(() => ({ ...cachedConfig }));
        } else if (nodeDO.id) {
          setWorkflowNodeConfig(() => ({ ...nodeConfig }));
        } else {
          setWorkflowNodeConfig(() => ({ ...nodeConfig }));
        }
      }
    } else {
      // 如果没有找到节点数据，使用原有逻辑
      console.log('没有找到 nodeDO，使用节点数据');
      const cachedConfig = workflowNodeConfigCache.get(node.id);
      if (cachedConfig) {
        console.log('使用缓存配置（无 nodeDO）');
        setWorkflowNodeConfig(() => cachedConfig);
      } else {
        console.log('使用节点原始数据');
        const source = node.data || {};
        const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(source.type)));
        setWorkflowNodeConfig({
          nodeName: source.label || config?.label || '',
          nodeIcon: source.icon || '',
          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 || '',
          isolationPoints: source.isolationPoints || [],
          isolationNode: source.isolationNode || [],
          isolationNodeUuid: source.isolationNodeUuid || '',
          lockPerson: source.lockPerson ? (typeof source.lockPerson === 'number' ? source.lockPerson : Number(source.lockPerson)) : undefined,
          coLockPersons: source.coLockPersons && Array.isArray(source.coLockPersons) ? source.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : [],
          notificationMethods: resolveNotificationMethods(source),
          notificationPerson: source.notificationPerson || '',
          notificationTime: source.notificationTime || '',
          smsTemplateCode: source.smsTemplateCode || 'false',
          messageTemplateCode: source.messageTemplateCode || 'false',
          emailTemplateCode: source.emailTemplateCode || 'false',
          appTemplateCode: source.appTemplateCode || 'false',
          copyDeptIds: workflowCopyDeptIds(source),
          copyUserIds: workflowCopyUserIds(source),
        });
      }
    }
    // 使用 flushSync 立即提交选中节点，确保右侧面板在本轮事件中完成切换，避免「有时切换未生效」
    flushSync(() => {
      setSelectedWorkflowNode(node);
    });
    setWorkflowActiveTabKey('info');
  }, [workflowNodeConfigCache, workflowWorkNodeDOList, nodeConfigs]);
  
  // 画布点击事件（取消选择）
  const onWorkflowPaneClick = useCallback(() => {
    setSelectedWorkflowNode(null);
  }, []);
  
  // 实时更新节点显示（仅当当前 config 属于当前选中节点时才写回画布，避免切换节点时把上一节点的 config 误写到新节点）
  useEffect(() => {
    if (!selectedWorkflowNode || selectedWorkflowNode.id !== workflowNodeConfigForIdRef.current) return;
    if (workflowNodeConfig.nodeName) {
      const { isolationMethod, ...restData } = selectedWorkflowNode.data || {};
      // 从缓存中读取 completed 状态，保持保存状态不变
      const isSaved = nodeSavedStatusCache.get(selectedWorkflowNode.id) || false;
      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,
        smsTemplateCode: workflowNodeConfig.smsTemplateCode,
        messageTemplateCode: workflowNodeConfig.messageTemplateCode,
        emailTemplateCode: workflowNodeConfig.emailTemplateCode,
        appTemplateCode: workflowNodeConfig.appTemplateCode,
        copyDeptIds: workflowNodeConfig.copyDeptIds,
        copyUserIds: workflowNodeConfig.copyUserIds,
        // 保持 completed 状态从缓存中读取，不覆盖
        completed: isSaved,
      };
      setWorkflowNodes((nds) =>
        nds.map((node) =>
          node.id === selectedWorkflowNode.id
            ? { ...node, data: updatedData }
            : node
        )
      );
    }
  }, [workflowNodeConfig, selectedWorkflowNode?.id, setWorkflowNodes, nodeSavedStatusCache]);

  // 作业管理删除处理
  const handleWorkJobDelete = async (id: number) => {
    Modal.confirm({
      title: t('common.confirmDeleteWork'),
      content: t('common.confirmDeleteWorkText'),
      okText: t('common.confirmDeleteWorkButton'),
      okType: 'danger',
      cancelText: t('common.cancel'),
      onOk: async () => {
        try {
          await workJobApi.deleteWorkflowWorkList([id]);
          message.success(t('common.deleteWorkSuccess'));
          // 删除成功后刷新列表
          if (workJobList.length === 1 && workJobPagination.pageNo > 1) {
            setWorkJobPagination({ ...workJobPagination, pageNo: workJobPagination.pageNo - 1 });
          } else {
            await getWorkJobList();
          }
        } catch (error: any) {
          console.error('删除失败:', error);
          message.error(error?.message || t('common.deleteWorkFailed'));
        }
      },
    });
  };

  // 作业管理编辑处理
  const handleWorkJobEdit = async (item: WorkJobVO, viewMode: boolean = false) => {
    // 如果明确指定了 viewMode，设置查看模式
    if (viewMode) {
      setIsViewMode(true);
    } else {
      // 否则，如果是直接调用（不是通过 handleWorkJobView），确保是编辑模式
      setIsViewMode(false);
    }
    try {
      // 调用详情接口获取完整数据
      const response = await workJobApi.selectWorkflowWorkById(item.id!);
      // axios拦截器可能已经处理了数据格式，直接使用response
      const detail = response as any;
      
      // 设置作业ID，这样点击"下一步"时会调用更新接口
      setWorkflowWorkId(detail.id);
      
      // 重置表单和步骤
      setWorkJobStep(0);
      workJobBasicForm.resetFields();
      workJobPublishForm.resetFields();
      
      // 加载字典数据和流程模板列表
      await Promise.all([
        getWorkTypeDictList(),
        getUrgencyLevelDictList(),
        getIsolationMethodDictList(),
        getWorkflowTemplateList(),
      ]);
      
      // 回显基本信息表单数据
      const formData = {
        workflowTemplate: detail.designId || undefined,
        jobCategory: detail.type || undefined,
        jobName: detail.name || '',
        jobContent: detail.description || '',
        urgency: detail.urgencyLevel || undefined,
      };
      workJobBasicForm.setFieldsValue(formData);
      
      // 保存原始表单数据（用于判断是否有修改）
      setOriginalBasicFormData(formData);
      
      // 保存 workflowWorkNodeDOList
      if (detail.workflowWorkNodeDOList && Array.isArray(detail.workflowWorkNodeDOList)) {
        setWorkflowWorkNodeDOList(detail.workflowWorkNodeDOList);
      } else {
        setWorkflowWorkNodeDOList([]);
      }
      
      // 如果有流程设计内容，加载流程设计JSON
      // 优先使用 designContent（如果存在），否则使用 designId 调用接口
      // 但如果 designContent 和 workflowWorkNodeDOList 都为 null，应该清空流程
      const hasDesignContent = detail.designContent && detail.designContent !== null;
      const hasWorkflowNodes = detail.workflowWorkNodeDOList && Array.isArray(detail.workflowWorkNodeDOList) && detail.workflowWorkNodeDOList.length > 0;
      
      if (hasDesignContent) {
        try {
          // 如果详情中直接包含流程设计内容，直接解析并设置
          const jsonData = typeof detail.designContent === 'string' 
            ? JSON.parse(detail.designContent) 
            : detail.designContent;
          setWorkflowJson(jsonData);
          
          // 调用 loadWorkflowJson 的逻辑来渲染节点和连线
          // 这里直接使用已有的 loadWorkflowJson 函数，但需要先设置 workflowJson
          // 然后手动触发渲染逻辑
          if (jsonData && jsonData.nodes && Array.isArray(jsonData.nodes) && jsonData.edges && Array.isArray(jsonData.edges)) {
            // 使用 loadWorkflowJson 中的渲染逻辑
            // 先创建节点映射，方便后续查找
            const nodeDOMap = new Map<string, WorkflowWorkNodeDO>();
            detail.workflowWorkNodeDOList?.forEach((nodeDO: WorkflowWorkNodeDO) => {
              if (nodeDO.uuid) {
                nodeDOMap.set(nodeDO.uuid, nodeDO);
              }
            });
            
            const importedNodes: Node[] = jsonData.nodes.map((node: any) => {
              const nodeData = node.data || {};
              const nodeId = node.id || node.uuid;
              const nodeDO = nodeDOMap.get(nodeId);
              
              // 优先使用 nodeDO 中的 position，否则使用 JSON 中的 position
              let nodePosition = { x: 0, y: 0 };
              if (nodeDO?.position) {
                try {
                  nodePosition = typeof nodeDO.position === 'string' ? JSON.parse(nodeDO.position) : nodeDO.position;
                } catch (e) {
                  console.error('解析节点position失败:', e);
                  nodePosition = node.position || { x: 0, y: 0 };
                }
              } else {
                nodePosition = node.position || { x: 0, y: 0 };
              }
              
              // 如果 nodeDO 中有 data，优先使用 nodeDO 中的数据
              let finalNodeData = nodeData;
              if (nodeDO?.data) {
                try {
                  const nodeDOData = typeof nodeDO.data === 'string' ? JSON.parse(nodeDO.data) : nodeDO.data;
                  finalNodeData = { ...nodeData, ...nodeDOData };
                } catch (e) {
                  console.error('解析节点data失败:', e);
                }
              }
              
              return {
                id: nodeId,
                type: node.type || nodeDO?.type || 'createJob',
                position: nodePosition,
                data: (() => {
                  const { isolationMethod, ...restFinalNodeData } = finalNodeData || {};
                  return {
                    ...restFinalNodeData,
                    label: nodeDO?.nodeName || finalNodeData.label || node.label || nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(node.type || finalNodeData.type)))?.label || '节点',
                    type: node.type || nodeDO?.type || finalNodeData.type || 'createJob',
                    // 标记节点是否已完成配置（如果 nodeDO 存在且有 id，说明已经保存过）
                    completed: !!nodeDO?.id,
                  };
                })(),
              };
            });
            
            const importedEdges: Edge[] = jsonData.edges.map((edge: any) => {
              let sourceHandle = edge.sourceHandle;
              let targetHandle = edge.targetHandle;
              
              if (!sourceHandle && edge.id) {
                const sourceMatch = edge.id.match(/right-source|left-source|top-source|bottom-source/);
                if (sourceMatch) {
                  sourceHandle = sourceMatch[0].replace('-source', '');
                } else {
                  sourceHandle = 'right-source';
                }
              } else if (!sourceHandle) {
                sourceHandle = 'right-source';
              }
              
              if (!targetHandle && edge.id) {
                const targetMatch = edge.id.match(/right-target|left-target|top-target|bottom-target/);
                if (targetMatch) {
                  targetHandle = targetMatch[0].replace('-target', '');
                } else {
                  targetHandle = 'left-target';
                }
              } else if (!targetHandle) {
                targetHandle = 'left-target';
              }
              
              return {
                id: edge.id || `${edge.source}-${edge.target}`,
                source: edge.source,
                target: edge.target,
                sourceHandle: sourceHandle,
                targetHandle: targetHandle,
                type: edge.type || 'straight',
                data: {
                  fixedLength: edge.data?.fixedLength ?? 150,
                  edgeType: edge.type || 'straight',
                },
                style: { strokeWidth: 2, stroke: '#000000' },
                markerStart: {
                  type: 'arrowclosed',
                  color: '#000000',
                },
              };
            });
            
            const finalNodes = shouldApplyLayout(importedNodes, importedEdges)
              ? getLayoutedNodes(importedNodes, importedEdges)
              : importedNodes;
            setWorkflowNodes(finalNodes);
            setWorkflowEdges(importedEdges);
            
            // 清空之前的缓存和完成状态
            setWorkflowNodeConfigCache(new Map());
            setCompletedNodeIds(new Set());
            // 清除节点保存状态缓存
            setNodeSavedStatusCache(new Map());
            
            // 自动选中第一个节点
            if (finalNodes.length > 0) {
              setTimeout(() => {
                const firstNode = finalNodes[0];
                setSelectedWorkflowNode(firstNode);
                
                // 查找对应的 nodeDO
                const firstNodeDO = nodeDOMap.get(firstNode.id);
                
                if (firstNodeDO) {
                  // 如果找到 nodeDO，从 nodeDO 中读取数据
                  let nodeData: any = {};
                  if (firstNodeDO.data) {
                    try {
                      nodeData = typeof firstNodeDO.data === 'string' ? JSON.parse(firstNodeDO.data) : firstNodeDO.data;
                    } catch (e) {
                      console.error('解析节点data失败:', e);
                    }
                  }
                  
                  // 从 nodeUserList 中提取上锁人和共锁人
                  let lockPersonId: string | number = '';
                  const coLockPersonIds: (string | number)[] = [];
                  if (firstNodeDO.nodeUserList && Array.isArray(firstNodeDO.nodeUserList)) {
                    firstNodeDO.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) {
                        coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
                      }
                    });
                  }
                  
                  const source = nodeData || firstNode.data || {};
                  const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(firstNodeDO.type || source.type)));
                  
                  // 解析隔离点
                  let isolationPoints: string[] = [];
                  if (firstNodeDO.isolationPoints) {
                    try {
                      isolationPoints = typeof firstNodeDO.isolationPoints === 'string' 
                        ? JSON.parse(firstNodeDO.isolationPoints) 
                        : (Array.isArray(firstNodeDO.isolationPoints) ? firstNodeDO.isolationPoints : []);
                    } catch (e) {
                      console.error('解析隔离点失败:', e);
                      isolationPoints = source.isolationPoints || [];
                    }
                  } else {
                    isolationPoints = source.isolationPoints || [];
                  }
                  
                  setWorkflowNodeConfig({
                    nodeName: firstNodeDO.nodeName || source.label || config?.label || '',
                    nodeIcon: firstNodeDO.nodeIcon || source.icon || '',
                    responsible: firstNodeDO.workerUserId ? (typeof firstNodeDO.workerUserId === 'number' ? firstNodeDO.workerUserId : Number(firstNodeDO.workerUserId)) : (source.workerUserId ? (typeof source.workerUserId === 'number' ? source.workerUserId : Number(source.workerUserId)) : undefined),
                    remark: source.remark || '',
                    submitForm: firstNodeDO.formId ? (typeof firstNodeDO.formId === 'number' ? firstNodeDO.formId : Number(firstNodeDO.formId)) : (source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined),
                    isolationType: (firstNodeDO.isolationType !== null && firstNodeDO.isolationType !== undefined) ? String(firstNodeDO.isolationType) : (source.isolationType || ''),
                    isolationPoints: isolationPoints,
                    isolationNode: source.isolationNode || [],
                    isolationNodeUuid: firstNodeDO.isolationNodeUuid || source.isolationNodeUuid || '',
                    lockPerson: lockPersonId || source.lockPerson || '',
                    coLockPersons: coLockPersonIds.length > 0 ? coLockPersonIds : (source.coLockPersons || []),
                    notificationMethods: resolveNotificationMethods(source, firstNodeDO),
                    notificationPerson: source.notificationPerson || '',
                    notificationTime: firstNodeDO.notifyTime || source.notificationTime || '',
                    smsTemplateCode: source.smsTemplateCode || (source.notificationMethods?.sms ? 'true' : 'false'),
                    messageTemplateCode: source.messageTemplateCode || (source.notificationMethods?.message ? 'true' : 'false'),
                    emailTemplateCode: source.emailTemplateCode || (source.notificationMethods?.email ? 'true' : 'false'),
                    appTemplateCode: source.appTemplateCode || (source.notificationMethods?.app ? 'true' : 'false'),
                    copyDeptIds: workflowCopyDeptIds(source, firstNodeDO),
                    copyUserIds: workflowCopyUserIds(source, firstNodeDO),
                  });
                } else {
                  // 如果没有找到 nodeDO，使用原有逻辑
                  const source = firstNode.data || {};
                  const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(source.type)));
                  setWorkflowNodeConfig({
                    nodeName: source.label || config?.label || '',
                    nodeIcon: source.icon || '',
                    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 || '',
                    isolationPoints: source.isolationPoints || [],
                    isolationNode: source.isolationNode || [],
                    isolationNodeUuid: source.isolationNodeUuid || '',
                    lockPerson: source.lockPerson || '',
                    coLockPersons: source.coLockPersons || [],
                    notificationMethods: resolveNotificationMethods(source),
                    notificationPerson: source.notificationPerson || '',
                    notificationTime: source.notificationTime || '',
                    smsTemplateCode: source.smsTemplateCode || 'false',
                    messageTemplateCode: source.messageTemplateCode || 'false',
                    emailTemplateCode: source.emailTemplateCode || 'false',
                    appTemplateCode: source.appTemplateCode || 'false',
                    copyDeptIds: workflowCopyDeptIds(source),
                    copyUserIds: workflowCopyUserIds(source),
                  });
                }
                
                setWorkflowNodes(prev => prev.map(n => ({
                  ...n,
                  selected: n.id === firstNode.id,
                })));
              }, 100);
            }
          }
        } catch (error: any) {
          console.error('解析流程设计内容失败:', error);
          // 如果解析失败，清空流程
          setWorkflowJson(null);
          setWorkflowNodes([]);
          setWorkflowEdges([]);
          setWorkflowNodeConfigCache(new Map());
          setCompletedNodeIds(new Set());
          setNodeSavedStatusCache(new Map());
        }
      } else if (!hasDesignContent && !hasWorkflowNodes) {
        // 如果 designContent 和 workflowWorkNodeDOList 都为 null，清空流程
        console.log('designContent 和 workflowWorkNodeDOList 都为 null，清空流程');
        setWorkflowJson(null);
        setWorkflowNodes([]);
        setWorkflowEdges([]);
        setWorkflowNodeConfigCache(new Map());
        setCompletedNodeIds(new Set());
        setNodeSavedStatusCache(new Map());
        setSelectedWorkflowNode(null);
      } else if (detail.designId && hasWorkflowNodes) {
        // 只有在有 workflowWorkNodeDOList 数据时，才尝试通过 designId 加载模板
        // 这样可以避免在编辑时，即使没有流程数据也加载模板
        try {
          await loadWorkflowJson(detail.designId);
        } catch (error: any) {
          console.error('加载流程设计失败:', error);
          // 加载失败时也清空流程
          setWorkflowJson(null);
          setWorkflowNodes([]);
          setWorkflowEdges([]);
          setWorkflowNodeConfigCache(new Map());
          setCompletedNodeIds(new Set());
          setNodeSavedStatusCache(new Map());
        }
      }
      
      // 打开多步骤弹框
    setShowAddModal(true);
      setEditingItem(null); // 确保不是编辑模式（使用新增的多步骤弹框）
    } catch (error: any) {
      console.error('获取作业详情失败:', error);
      message.error(error?.message || '获取作业详情失败');
    }
  };

  // 作业管理查看处理（跳转到作业详情页面）
  const handleWorkJobView = (item: WorkJobVO) => {
    // 跳转到作业详情页面
    const workId = item.id;
    if (workId) {
      navigate(`/work-job/detail?id=${workId}`);
    } else {
      message.warning(t('common.workIdNotExistsForView'));
    }
  };
  
  // 为查看模式加载流程设计JSON
  const loadWorkflowJsonForView = async (workflowId: number) => {
    try {
      const response = await workflowDesignApi.selectWorkflowDesignById(workflowId);
      const workflow = response as any;
      // 检查 content 是否为 null 或空字符串
      const hasContent = workflow.content && workflow.content !== null && workflow.content !== '';
      
      if (hasContent) {
        try {
          const jsonData = typeof workflow.content === 'string' 
            ? JSON.parse(workflow.content) 
            : workflow.content;
          setViewWorkflowJson(jsonData);
        } catch (parseError) {
          console.error('解析流程设计JSON失败:', parseError);
          // 解析失败时清空
          setViewWorkflowJson(null);
        }
      } else {
        // content 为 null 或空时，清空流程
        console.warn('流程设计content为空或null，清空查看模式的流程');
        setViewWorkflowJson(null);
      }
    } catch (error: any) {
      console.error('加载流程设计失败:', error);
      // 加载失败时也清空
      setViewWorkflowJson(null);
    }
  };

  // 根据当前子菜单获取数据和列配置
  const getTableConfig = () => {
    if (subMenu === '表单管理') {
      // 表单管理使用单独的过滤逻辑
      let filtered = formManagementData;
      if (formManagementQuery.name) {
        filtered = filtered.filter(item => 
          item.name.toLowerCase().includes(formManagementQuery.name.toLowerCase())
        );
      }
      if (formManagementQuery.status) {
        filtered = filtered.filter(item => item.status === formManagementQuery.status);
      }
      return {
        data: filtered,
        columns: [
          { key: 'name', label: t('table.formName'), width: '20%' },
          { key: 'status', label: t('table.status'), width: '10%' },
          { key: 'description', label: t('table.remark'), width: '25%' },
          { key: 'createTime', label: t('table.createTime'), width: '15%' },
        ],
      };
    } else if (subMenu === '流程设计') {
      // 流程设计使用单独的过滤逻辑
      let filtered = processDesignData;
      if (processDesignQuery.name) {
        filtered = filtered.filter(item => 
          item.name.toLowerCase().includes(processDesignQuery.name.toLowerCase())
        );
      }
      return {
        data: filtered,
        columns: [
          { key: 'name', label: t('table.name') || '名称', width: '20%' },
          { key: 'designer', label: t('table.designer'), width: '10%' },
          { key: 'designTime', label: t('table.designTime'), width: '15%' },
          { key: 'nodeCount', label: t('table.nodeCount'), width: '10%' },
          { key: 'description', label: t('table.description'), width: '25%' },
          { key: 'status', label: t('table.status'), width: '10%' },
        ],
      };
    } else if (subMenu === '流程模板') {
      return {
        data: templateData,
        columns: [
          { key: 'code', label: t('table.templateCode'), width: '10%' },
          { key: 'name', label: t('table.templateName'), width: '15%' },
          { key: 'type', label: t('table.templateType'), width: '10%' },
          { key: 'category', label: t('table.templateCategory'), width: '10%' },
          { key: 'steps', label: t('table.stepCount'), width: '8%' },
          { key: 'approvalLevel', label: t('table.approvalLevel'), width: '10%' },
          { key: 'creator', label: t('table.creator'), width: '8%' },
          { key: 'status', label: t('table.status'), width: '8%' },
          { key: 'useCount', label: t('table.useCount'), width: '9%' },
          { key: 'createTime', label: t('table.createTime'), width: '12%' },
        ],
      };
    } else if (subMenu === 'SOP管理') {
      return {
        data: sopData,
        columns: [
          { key: 'code', label: 'SOP编号', width: '10%' },
          { key: 'name', label: 'SOP名称', width: '15%' },
          { key: 'version', label: '版本', width: '8%' },
          { key: 'category', label: '分类', width: '10%' },
          { key: 'department', label: '所属部门', width: '10%' },
          { key: 'effectiveDate', label: '生效日期', width: '10%' },
          { key: 'reviewDate', label: '复审日期', width: '10%' },
          { key: 'status', label: '状态', width: '8%' },
          { key: 'reviewer', label: '审核人', width: '8%' },
          { key: 'attachments', label: '附件数', width: '8%' },
        ],
      };
    } else if (subMenu === '作业管理') {
      // 作业管理使用API数据，不需要在这里返回
      return {
        data: [],
        columns: [],
      };
    }
    return { data: [], columns: [] };
  };

  const { data, columns } = getTableConfig();

  // 过滤数据（表单管理和流程设计除外，因为它们有自己的搜索逻辑）
  const filteredData = (subMenu === '表单管理' || subMenu === '流程设计')
    ? data 
    : data.filter((item) =>
        Object.values(item).some((value) =>
          String(value).toLowerCase().includes(searchTerm.toLowerCase())
        )
      );

  const handleDelete = async (id: number) => {
    const isProcessTemplate = subMenu === '流程模板';
    Modal.confirm({
      title: t('common.confirmDelete'),
      content: isProcessTemplate ? t('common.deleteProcessTemplate') : `${t('common.confirmDeleteText')} ${t('isolationWork.processDesign')}？${t('common.confirmDeleteWarning')}`,
      okText: t('common.confirmDeleteButton'),
      okType: 'danger',
      cancelText: t('common.cancel'),
      onOk: async () => {
        try {
          await workflowDesignApi.deleteWorkflowDesignList([id]);
          message.success(t('common.deleteSuccess'));
          // 删除成功后刷新列表
          // 如果当前页只有一条数据且不是第一页，删除后跳转到上一页
          if (processDesignList.length === 1 && processDesignPagination.pageNo > 1) {
            setProcessDesignPagination({ ...processDesignPagination, pageNo: processDesignPagination.pageNo - 1 });
          } else {
            // 否则直接刷新当前页数据
            await getProcessDesignList();
          }
        } catch (error: any) {
          console.error('删除失败:', error);
          message.error(error?.message || t('common.deleteFailed'));
        }
      },
    });
  };

  const handleEdit = (item: TableRow | WorkflowDesignVO) => {
    setEditingItem(item as TableRow);
    // 设置表单初始值
    form.setFieldsValue({
      name: item.name || '',
      description: item.description || '',
    });
    setShowAddModal(true);
  };

  const handleDesign = (item: TableRow | WorkflowDesignVO) => {
    console.log('设计流程:', item);
    // 跳转到流程设计页面，传递流程ID
    if (item.id) {
      // 记录来源菜单：用于从流程设计器返回时恢复菜单到「隔离作业 > 流程模板」
      sessionStorage.setItem(
        'processDesignerSource',
        JSON.stringify({ menu: 'isolationWork', subMenu: 'processTemplate' })
      );
      navigate(`/process-designer?id=${item.id}`);
    }
  };

  // 获取表单字段
  const getFormFields = () => {
    if (subMenu === '流程模板') {
      return (
        <div className="grid grid-cols-2 gap-4">
          <div>
            <label className="block text-sm text-gray-700 mb-2">{t('common.templateCode')} *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder={t('common.templateCodePlaceholder')}
              defaultValue={editingItem?.code || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">{t('form.templateName')} *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder={t('form.templateNamePlaceholder')}
              defaultValue={editingItem?.name || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">{t('common.processType')} *</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">{t('common.processTypePlaceholder')}</option>
              <option value="标准流程">{t('common.standardProcess')}</option>
              <option value="应急流程">{t('common.emergencyProcess')}</option>
              <option value="临时流程">{t('common.temporaryProcess')}</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">{t('common.workCategory')} *</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">{t('common.workCategoryPlaceholder')}</option>
              <option value="高压作业">{t('common.highVoltageWork')}</option>
              <option value="低压作业">{t('common.lowVoltageWork')}</option>
              <option value="应急处理">{t('common.emergencyHandling')}</option>
              <option value="定期维护">{t('common.regularMaintenance')}</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">{t('common.approvalLevel')} *</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">{t('common.approvalLevelPlaceholder')}</option>
              <option value="一级审批">{t('common.firstLevelApproval')}</option>
              <option value="二级审批">{t('common.secondLevelApproval')}</option>
              <option value="特殊审批">{t('common.specialApproval')}</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">{t('common.stepCount')}</label>
            <input
              type="number"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder={t('common.stepCountPlaceholder')}
              defaultValue={editingItem?.steps || ''}
            />
          </div>
          <div className="col-span-2">
            <label className="block text-sm text-gray-700 mb-2">{t('common.remark')}</label>
            <textarea
              rows={3}
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm resize-none"
              placeholder={t('common.remarkPlaceholder')}
              defaultValue={editingItem?.remark || ''}
            ></textarea>
          </div>
        </div>
      );
    } else if (subMenu === 'SOP管理') {
      return (
        <div className="grid grid-cols-2 gap-4">
          <div>
            <label className="block text-sm text-gray-700 mb-2">SOP编号 *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="请输入SOP编号"
              defaultValue={editingItem?.code || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">SOP名称 *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="请输入SOP名称"
              defaultValue={editingItem?.name || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">版本号 *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="如：V1.0"
              defaultValue={editingItem?.version || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">分类 *</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">请选择</option>
              <option value="操作规程">操作规程</option>
              <option value="安全规程">安全规程</option>
              <option value="管理规程">管理规程</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">所属部门 *</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">请选择</option>
              <option value="技术部">技术部</option>
              <option value="运维部">运维部</option>
              <option value="安全部">安全部</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">审核人</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="请输入审核人"
              defaultValue={editingItem?.reviewer || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">生效日期</label>
            <input
              type="date"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              defaultValue={editingItem?.effectiveDate || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">复审日期</label>
            <input
              type="date"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              defaultValue={editingItem?.reviewDate || ''}
            />
          </div>
          <div className="col-span-2">
            <label className="block text-sm text-gray-700 mb-2">备注</label>
            <textarea
              rows={3}
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm resize-none"
              placeholder="请输入备注"
              defaultValue={editingItem?.remark || ''}
            ></textarea>
          </div>
        </div>
      );
    } else if (subMenu === '作业管理') {
      return (
        <div className="grid grid-cols-2 gap-4">
          <div>
            <label className="block text-sm text-gray-700 mb-2">作业编号 *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="系统自动生成"
              defaultValue={editingItem?.code || ''}
              disabled
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">作业名称 *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="请输入作业名称"
              defaultValue={editingItem?.name || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">作业类型 *</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">请选择</option>
              <option value="定期维护">定期维护</option>
              <option value="应急处理">应急处理</option>
              <option value="故障检修">故障检修</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">流程模板 *</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">请选择</option>
              <option value="高压设备隔离流程">高压设备隔离流程</option>
              <option value="低压配电柜隔离流程">低压配电柜隔离流程</option>
              <option value="紧急抢修隔离流程">紧急抢修隔离流程</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">作业位置 *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="请输入作业位置"
              defaultValue={editingItem?.location || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">设备名称 *</label>
            <input
              type="text"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              placeholder="请输入设备名称"
              defaultValue={editingItem?.equipment || ''}
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">计划开始时间 *</label>
            <input
              type="datetime-local"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">计划结束时间 *</label>
            <input
              type="datetime-local"
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
            />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">优先级</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="普通">普通</option>
              <option value="重要">重要</option>
              <option value="紧急">紧急</option>
            </select>
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-2">审批人</label>
            <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
              <option value="">请选择</option>
              <option value="张三">张三</option>
              <option value="李四">李四</option>
              <option value="王五">王五</option>
            </select>
          </div>
          <div className="col-span-2">
            <label className="block text-sm text-gray-700 mb-2">作业说明</label>
            <textarea
              rows={3}
              className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm resize-none"
              placeholder="请输入作业说明"
              defaultValue={editingItem?.remark || ''}
            ></textarea>
          </div>
        </div>
      );
    }
    return null;
  };

  // 表单管理表格列配置
  const formManagementColumns: ColumnsType<TableRow> = useMemo(() => [
    {
      title: t('table.formId'),
      width: '5%',
      render: (_: any, __: TableRow, index: number) => index + 1,
    },
    {
      title: t('table.formName'),
      dataIndex: 'name',
      width: '20%',
    },
    {
      title: t('table.status'),
      dataIndex: 'status',
      width: '10%',
      render: (status: string) => (
        <span
          className={`inline-flex px-3 py-1 rounded-lg text-xs ${
            status === '启用' || status === t('common.enabled')
              ? 'bg-green-100 text-green-700'
              : 'bg-gray-100 text-gray-700'
          }`}
        >
          {status === '启用' ? t('common.enabled') : status === '停用' ? t('common.disabled') : status}
        </span>
      ),
    },
    {
      title: t('table.remark'),
      dataIndex: 'description',
      width: '25%',
      ellipsis: true,
    },
    {
      title: t('table.createTime'),
      dataIndex: 'createTime',
      width: '15%',
    },
    {
      title: t('table.operation'),
      width: '15%',
      align: 'center',
      fixed: 'right',
      render: (_: any, record: TableRow) => (
        <div className="flex items-center justify-center gap-2">
          <UIButton
            variant="ghost"
            size="sm"
            onClick={() => handleEdit(record)}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-1">{t('common.edit')}</span>
          </UIButton>
          <UIButton
            variant="ghost"
            size="sm"
            onClick={() => handleDelete(record.id)}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-1">{t('common.delete')}</span>
          </UIButton>
        </div>
      ),
    },
  ], [t, i18n.language]);

  // 流程设计表格列配置
  const processDesignColumns: ColumnsType<WorkflowDesignVO> = useMemo(() => [
    {
      title: t('table.processDesignId'),
      width: '5%',
      align: 'center',
      render: (_: any, __: WorkflowDesignVO, index: number) => 
        (processDesignPagination.pageNo - 1) * processDesignPagination.pageSize + index + 1,
    },
    {
      title: t('table.name') || '名称',
      dataIndex: 'name',
      width: '15%',
      align: 'center',
    },
    {
      title: t('table.nodeCount'),
      dataIndex: 'nodeCount',
      width: '10%',
      align: 'center',
      render: (count: number) => count ?? 0,
    },
    {
      title: t('table.status'),
      dataIndex: 'status',
      width: '10%',
      align: 'center',
      render: (status: number, record: WorkflowDesignVO) => {
        const isChecked = status === 1;
        const isUpdating = processDesignStatusUpdating[record.id!] || false;
        return (
          <div className="flex items-center justify-center">
            <AntdSwitch
              checked={isChecked}
              onChange={(checked) => {
                if (!isUpdating) {
                  const newStatus = checked ? 1 : 0;
                  handleProcessDesignStatusChanged(record, newStatus);
                }
              }}
              disabled={isUpdating}
              loading={isUpdating}
              style={{
                ...(isChecked ? { 
                  backgroundColor: '#52c41a',
                } : {})
              }}
              className={isChecked ? 'ant-switch-checked-green' : ''}
            />
          </div>
        );
      },
    },
    {
      title: t('table.createTime'),
      dataIndex: 'createTime',
      width: '15%',
      align: 'center',
      render: (time: string | Date | number) => {
        if (!time) return '-';
        let date: Date;
        if (typeof time === 'number') {
          date = new Date(time);
        } else if (typeof time === 'string') {
          date = new Date(time);
        } else {
          date = time;
        }
        return date.toLocaleString(i18n.language === 'en' ? 'en-US' : 'zh-CN', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
          second: '2-digit',
        });
      },
    },
    {
      title: t('table.updateTime'),
      dataIndex: 'updateTime',
      width: '15%',
      align: 'center',
      render: (time: string | Date | number) => {
        if (!time) return '-';
        let date: Date;
        if (typeof time === 'number') {
          date = new Date(time);
        } else if (typeof time === 'string') {
          date = new Date(time);
        } else {
          date = time;
        }
        return date.toLocaleString(i18n.language === 'en' ? 'en-US' : 'zh-CN', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
          second: '2-digit',
        });
      },
    },
    {
      title: t('table.description'),
      dataIndex: 'description',
      width: '18%',
      align: 'center',
      render: (desc: string) => {
        const text = desc || '-';
        const maxLength = 20;
        const shouldTruncate = text.length > maxLength;
        const displayText = shouldTruncate ? text.slice(0, maxLength) + '...' : text;
        
        return (
          <Tooltip placement="topLeft" title={text}>
            <span>{displayText}</span>
          </Tooltip>
        );
      },
    },
    {
      title: t('table.operation'),
      width: '20%',
      align: 'center',
      fixed: 'right',
      render: (_: any, record: WorkflowDesignVO) => (
        <div className="flex items-center justify-center gap-2">
          <UIButton
            variant="ghost"
            size="sm"
            onClick={() => handleDesign(record as any)}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Workflow className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-0.5">{t('common.design')}</span>
          </UIButton>
          <UIButton
            variant="ghost"
            size="sm"
            onClick={() => handleEdit(record as any)}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-0.5">{t('common.edit')}</span>
          </UIButton>
          <UIButton
            variant="ghost"
            size="sm"
            onClick={() => handleDelete(record.id!)}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-0.5">{t('common.delete')}</span>
          </UIButton>
        </div>
      ),
    },
  ], [t, i18n.language, processDesignPagination]);

  // 获取作业状态样式
  const getWorkJobStatusStyle = (status: string | number | undefined): React.CSSProperties => {
    if (!status) {
      return {
        backgroundColor: '#e5e5e5',
        color: '#333333',
      };
    }
    
    // 从字典中查找状态文本
    const statusItem = jobStatusDictList.find(item => String(item.value) === String(status));
    const statusText = statusItem ? (statusItem.label || '') : String(status || '');
    const statusTextLower = statusText.toLowerCase();
    
    // 根据状态文本判断颜色
    // 待执行、待发布：灰色 #e5e5e5
    if (statusTextLower.includes('待执行') || statusTextLower.includes('待发布') || 
        statusTextLower.includes('pending') || statusTextLower.includes('unreleased')) {
      return {
        backgroundColor: '#e5e5e5',
        color: '#333333',
      };
    }
    // 进行中：蓝色 #1677ff
    if (statusTextLower.includes('进行中') || statusTextLower.includes('执行中') || 
        statusTextLower.includes('running') || statusTextLower.includes('in_progress')) {
      return {
        backgroundColor: '#1677ff',
        color: '#ffffff',
      };
    }
    // 已完成：绿色 #0acb57
    if (statusTextLower.includes('已完成') || statusTextLower.includes('执行完成') || 
        statusTextLower.includes('completed') || statusTextLower.includes('完成')) {
      return {
        backgroundColor: '#0acb57',
        color: '#ffffff',
      };
    }
    
    // 如果没有匹配到，默认灰色
    return {
      backgroundColor: '#e5e5e5',
      color: '#333333',
    };
  };

  // 获取紧急程度图标和样式（根据字典 value 判断：0=一般，1=紧急，2=非常紧急）
  const getUrgencyLevelIconAndStyle = (urgencyValue: string | number | undefined): { icon: React.ReactNode; style: React.CSSProperties } => {
    if (urgencyValue === null || urgencyValue === undefined || urgencyValue === '') {
      return {
        icon: null,
        style: {
          backgroundColor: '#e5e5e5',
          color: '#333333',
        },
      };
    }
    
    const value = Number(urgencyValue);
    
    // 0 = 一般：使用 urgecy1.png 图标 + 黑色文字
    if (value === 0) {
      return {
        icon: (
          <img 
            src={urgecy1Icon} 
            alt="一般" 
            className="w-5 h-5 flex-shrink-0 mr-1.5"
            style={{ objectFit: 'contain' }}
          />
        ),
        style: {
          backgroundColor: 'transparent',
          color: '#000000',
        },
      };
    }
    
    // 1 = 紧急：使用 urgecy2.png 图标 + 橙色加粗文字
    if (value === 1) {
      return {
        icon: (
          <img 
            src={urgecy2Icon} 
            alt="紧急" 
            className="w-5 h-5 flex-shrink-0 mr-1.5"
            style={{ objectFit: 'contain' }}
          />
        ),
        style: {
          backgroundColor: 'transparent',
          color: '#fa8c16',
          fontWeight: 'bold',
        },
      };
    }
    
    // 2 = 非常紧急：使用 urgecy3.png 图标 + 红色加粗文字
    if (value === 2) {
      return {
        icon: (
          <img 
            src={urgecy3Icon} 
            alt="非常紧急" 
            className="w-5 h-5 flex-shrink-0 mr-1.5"
            style={{ objectFit: 'contain' }}
          />
        ),
        style: {
          backgroundColor: 'transparent',
          color: '#ff4d4f',
          fontWeight: 'bold',
        },
      };
    }
    
    // 如果没有匹配到，默认灰色
    return {
      icon: null,
      style: {
        backgroundColor: '#e5e5e5',
        color: '#333333',
      },
    };
  };

  // 获取紧急程度样式（保留用于向后兼容）
  const getUrgencyLevelStyle = (urgencyValue: string | number | undefined): React.CSSProperties => {
    return getUrgencyLevelIconAndStyle(urgencyValue).style;
  };

  // 作业管理表格列配置
  const workJobColumns: ColumnsType<WorkJobVO> = useMemo(() => [
    {
      title: t('table.workOrderNo'),
      dataIndex: 'orderNo',
      width: '9%',
      align: 'center',
      render: (orderNo: string, record: WorkJobVO) => orderNo || record.code || '-',
    },
    {
      title: t('table.workName'),
      dataIndex: 'name',
      width: '18%',
      align: 'center',
      render: (name: string, record: WorkJobVO) => {
        if (!name || name === '-') return <span>{name || '-'}</span>;
        return (
          <div className="flex items-center justify-center">
            <span
              className="text-blue-600 cursor-pointer hover:text-blue-800 hover:underline"
              onClick={(e) => {
                e.stopPropagation();
                handleWorkJobView(record);
              }}
            >
              {name}
            </span>
          </div>
        );
      },
    },
    {
      title: t('table.workStatus'),
      dataIndex: 'status',
      width: '9%',
      align: 'center',
      render: (status: string | number) => {
        const statusItem = jobStatusDictList.find(item => String(item.value) === String(status));
        const statusText = statusItem ? (statusItem.label || '') : String(status || '-');
        return (
          <div className="flex items-center justify-center">
            <span 
              className="inline-flex px-3 py-1 rounded-lg text-xs"
              style={getWorkJobStatusStyle(status)}
            >
              {statusText}
            </span>
          </div>
        );
      },
    },
    {
      title: t('table.currentTask'),
      dataIndex: 'currentNodeName',
      width: '10%',
      align: 'center',
      render: (currentNodeName: string, record: WorkJobVO) => {
        const text = currentNodeName || record.currentNode || '-';
        if (!text || text === '-') return text;
        return (
          <Tooltip title={text}>
            <span className="inline-block max-w-[140px] truncate align-middle">
              {text}
            </span>
          </Tooltip>
        );
      },
    },
    {
      title: t('table.workContent'),
      dataIndex: 'description',
      width: '15%',
      align: 'center',
      render: (description: string, record: WorkJobVO) => {
        const content = description || record.content || '-';
        if (content === '-') return content;
        
        const maxLength = 20;
        const shouldTruncate = content.length > maxLength;
        const displayText = shouldTruncate ? content.slice(0, maxLength) + '...' : content;
        
        return (
          <Tooltip placement="topLeft" title={content}>
            <span>{displayText}</span>
          </Tooltip>
        );
      },
    },
    {
      title: t('table.initiator'),
      dataIndex: 'initiatorName',
      width: '8%',
      align: 'center',
      render: (initiatorName: string, record: WorkJobVO) => initiatorName || record.initiator || '-',
    },
    {
      title: t('table.initiationTime'),
      dataIndex: 'initiationTime',
      width: '13%',
      align: 'center',
      render: (time: string | Date | number, record: WorkJobVO) => {
        const actualTime = time || record.initiateTime;
        if (!actualTime) return '-';
        let date: Date;
        if (typeof actualTime === 'number') {
          date = new Date(actualTime);
        } else if (typeof actualTime === 'string') {
          date = new Date(actualTime);
        } else {
          date = actualTime;
        }
        return date.toLocaleString(i18n.language === 'en' ? 'en-US' : 'zh-CN', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
          second: '2-digit',
        });
      },
    },
    {
      title: t('table.urgencyLevel'),
      dataIndex: 'urgencyLevel',
      
       width: '9%',    
      align: 'center',
      render: (urgencyLevel: string | number | undefined, record: WorkJobVO) => {
        const urgencyValue = urgencyLevel || record.urgency || record.urgencyLevel;
        const urgencyItem = urgencyLevelDictList.find(item => String(item.value) === String(urgencyValue));
        const urgencyText = urgencyItem ? (urgencyItem.label || '') : (urgencyValue ? String(urgencyValue) : '-');
        
        if (!urgencyValue || urgencyValue === null || urgencyValue === undefined || urgencyValue === '') {
          return <div className="flex items-center justify-center"><span>-</span></div>;
        }
        
        const { icon, style } = getUrgencyLevelIconAndStyle(urgencyValue);
        
        return (
          <div className="flex items-center justify-center">
            <span 
              className="inline-flex items-center justify-center gap-1.5"
            >
              {icon}
              <span style={style}>{urgencyText}</span>
            </span>
          </div>
        );
      },
    },
    {
      title: t('table.operation'),
      width: '20%',
      align: 'center',
      fixed: 'right',
      render: (_: any, record: WorkJobVO) => {
        // 只有未发布状态(unreleased)才能编辑
        const canEdit = String(record.status).toLowerCase() === 'unreleased';
        
        return (
        <div className="flex items-center justify-center gap-2">
          <UIButton
            variant="ghost"
            size="sm"
            onClick={(e) => {
              e.stopPropagation();
              e.preventDefault();
              handleWorkJobView(record);
            }}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Eye className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-0.5">{t('table.view')}</span>
          </UIButton>
            {canEdit ? (
          <UIButton
            variant="ghost"
            size="sm"
            onClick={() => handleWorkJobEdit(record)}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Edit2 className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-0.5">{t('common.edit')}</span>
          </UIButton>
            ) : (
              <UIButton
                variant="ghost"
                size="sm"
                disabled
                className="h-8 px-2 opacity-50 cursor-not-allowed"
                title={t('common.editDisabled') || '只有未发布状态才能编辑'}
              >
                <Edit2 className="w-4 h-4" />
                <span className="ml-0.5">{t('common.edit')}</span>
              </UIButton>
            )}
          <UIButton
            variant="ghost"
            size="sm"
            onClick={() => handleWorkJobDelete(record.id!)}
            className="h-8 px-2 transition-colors hover:underline"
            style={{ color: '#000000' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.color = '#1677ff';
              e.currentTarget.style.textDecoration = 'underline';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.color = '#000000';
              e.currentTarget.style.textDecoration = 'none';
              e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
            }}
          >
            <Trash2 className="w-4 h-4" style={{ color: '#000000' }} />
            <span className="ml-0.5">{t('common.delete')}</span>
          </UIButton>
        </div>
        );
      },
    },
  ], [t, i18n.language, jobStatusDictList, urgencyLevelDictList]);

  // 如果是表单管理页面，使用特殊的布局
  if (subMenu === '表单管理') {
    // 计算分页数据
    const formManagementTotal = filteredData.length;
    const formManagementStartIndex = (formManagementPagination.pageNo - 1) * formManagementPagination.pageSize;
    const formManagementEndIndex = formManagementStartIndex + formManagementPagination.pageSize;
    const formManagementPageData = filteredData.slice(formManagementStartIndex, formManagementEndIndex);
    const formManagementTotalPages = Math.ceil(formManagementTotal / formManagementPagination.pageSize) || 1;

    return (
      <div className="space-y-6">
        {/* 搜索栏和表格容器 */}
        <div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm overflow-hidden">
          {/* 搜索栏 */}
          <div className="p-4 lg:p-5 border-b border-gray-200/50">
            <div className="flex items-center justify-between gap-3 lg:gap-4 flex-wrap min-w-0">
              {/* 搜索条件 + 搜索、重置：按原宽度 200px，不超出，可缩小 */}
              <div className="flex items-center gap-2 lg:gap-3 flex-wrap min-w-0">
                <div className="flex items-center gap-2 lg:gap-3 w-[200px] min-w-[100px] flex-shrink">
                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap flex-shrink-0">{t('form.formName')}：</label>
                  <Input
                    value={formManagementQuery.name}
                    onChange={(e) => setFormManagementQuery({ ...formManagementQuery, name: e.target.value })}
                    onPressEnter={handleFormManagementQuery}
                    placeholder={t('form.formNamePlaceholder')}
                    className="min-w-0 w-full"
                    allowClear
                  />
                </div>
                <div className="flex items-center gap-2 lg:gap-3 w-[200px] min-w-[100px] flex-shrink">
                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap flex-shrink-0">{t('form.status')}：</label>
                  <Select
                    value={formManagementQuery.status}
                    onChange={(value) => setFormManagementQuery({ ...formManagementQuery, status: value })}
                    placeholder={t('form.statusPlaceholder') || t('common.pleaseSelect')}
                    className="min-w-0 w-full"
                    allowClear
                  >
                    <Select.Option value="启用">{t('common.enabled')}</Select.Option>
                    <Select.Option value="停用">{t('common.disabled')}</Select.Option>
                  </Select>
                </div>
                <Space className="flex-shrink-0">
                  <Button
                    type="primary"
                    icon={<Search className="w-4 h-4" />}
                    onClick={handleFormManagementQuery}
                  >
                    {t('common.search')}
                  </Button>
                  <Button
                    icon={<RefreshCw className="w-4 h-4" />}
                    onClick={() => {
                      resetFormManagementQuery();
                      setFormManagementPagination({ pageNo: 1, pageSize: 10 });
                    }}
                  >
                    {t('common.reset')}
                  </Button>
                </Space>
              </div>
              {/* 新增等按钮留在最右侧 */}
              <Space className="flex-shrink-0">
                <Button
                  type="primary"
                  icon={<Plus className="w-4 h-4" />}
                  onClick={() => {
                    setEditingItem(null);
                    setShowAddModal(true);
                  }}
                >
                  {t('form.addForm')}
                </Button>
              </Space>
            </div>
          </div>

          {/* 表格容器 */}
          <div className="isolation-work-list-table overflow-hidden min-w-0">
            <AntdTable
              columns={formManagementColumns}
              dataSource={formManagementPageData}
              rowKey="id"
              pagination={false}
              scroll={{ x: 'max-content' }}
              rowClassName={(_, index) =>
                index !== undefined && index % 2 === 1 ? 'isolation-work-list-row-alt' : ''
              }
            />
          </div>
        </div>

        {/* 分页 */}
        {formManagementTotal > 0 && (
          <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
            <div className="flex items-center justify-between">
              <div className="text-sm text-gray-600">
                {t('common.total')} <span className="text-blue-600 font-medium">{formManagementTotal}</span> {t('common.records')}
              </div>
              <div className="flex gap-2">
                <Button
                  onClick={() => setFormManagementPagination({ ...formManagementPagination, pageNo: formManagementPagination.pageNo - 1 })}
                  disabled={formManagementPagination.pageNo <= 1}
                >
                  {t('common.prevPage')}
                </Button>
                <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                  {formManagementPagination.pageNo} / {formManagementTotalPages}
                </span>
                <Button
                  onClick={() => setFormManagementPagination({ ...formManagementPagination, pageNo: formManagementPagination.pageNo + 1 })}
                  disabled={formManagementPagination.pageNo >= formManagementTotalPages}
                >
                  {t('common.nextPage')}
                </Button>
              </div>
            </div>
          </div>
        )}

        {/* 新增/编辑弹窗 */}
        {showAddModal && (
          <div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 animate-in fade-in duration-200">
            <div className="bg-white rounded-2xl shadow-2xl w-full max-w-3xl mx-4 max-h-[90vh] overflow-y-auto animate-in zoom-in duration-200">
              <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between sticky top-0 bg-white z-10">
                <h3 className="text-lg text-gray-900">
                  {editingItem ? t('common.editFormManagement') : t('common.addFormManagement')}
                </h3>
                <button
                  onClick={() => setShowAddModal(false)}
                  className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
                >
                  <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                  </svg>
                </button>
              </div>
              <div className="px-6 py-6">
                <div className="grid grid-cols-2 gap-4">
                  <div>
                    <label className="block text-sm text-gray-700 mb-2">名称 *</label>
                    <input
                      type="text"
                      className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
                      placeholder="请输入名称"
                      defaultValue={editingItem?.name || ''}
                    />
                  </div>
                  <div>
                    <label className="block text-sm text-gray-700 mb-2">创建人 *</label>
                    <input
                      type="text"
                      className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
                      placeholder="请输入创建人"
                      defaultValue={editingItem?.creator || ''}
                    />
                  </div>
                  <div>
                    <label className="block text-sm text-gray-700 mb-2">版本</label>
                    <input
                      type="text"
                      className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
                      placeholder="如：V1.0"
                      defaultValue={editingItem?.version || ''}
                    />
                  </div>
                  <div>
                    <label className="block text-sm text-gray-700 mb-2">状态 *</label>
                    <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
                      <option value="">请选择</option>
                      <option value="启用">启用</option>
                      <option value="停用">停用</option>
                    </select>
                  </div>
                  <div className="col-span-2">
                    <label className="block text-sm text-gray-700 mb-2">{t('common.description')}</label>
                    <textarea
                      rows={3}
                      className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm resize-none"
                      placeholder={t('common.descriptionPlaceholder')}
                      defaultValue={editingItem?.description || ''}
                    ></textarea>
                  </div>
                </div>
              </div>
              <div className="px-6 py-4 bg-gray-50/50 border-t border-gray-200 flex justify-end gap-3 rounded-b-2xl">
                <button
                  onClick={() => setShowAddModal(false)}
                  className="px-5 py-2.5 text-sm text-gray-600 bg-white border border-gray-200 rounded-xl hover:bg-gray-50 transition-colors"
                >
                  取消
                </button>
                <button
                  onClick={() => {
                    console.log('保存:', editingItem);
                    setShowAddModal(false);
                  }}
                  className="px-5 py-2.5 text-sm text-white bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl hover:shadow-lg hover:shadow-blue-400/40 transition-all"
                >
                  {editingItem ? '保存修改' : '确定'}
                </button>
              </div>
            </div>
          </div>
        )}
      </div>
    );
  }

  // 如果是流程设计页面，使用特殊的布局
  if (subMenu === '流程设计') {
    // 使用接口返回的数据
    const processDesignPageData = processDesignList;
    const processDesignTotalPages = Math.ceil(processDesignTotal / processDesignPagination.pageSize) || 1;

    return (
      <div className="space-y-6">
        {/* 搜索栏和表格容器 */}
        <div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm overflow-hidden">
          {/* 搜索栏 */}
          <div className="p-4 lg:p-5 border-b border-gray-200/50">
            <div className="flex items-center justify-between gap-3 lg:gap-4 flex-wrap min-w-0">
              {/* 搜索条件 + 搜索、重置：按原宽度 200px，不超出，可缩小 */}
              <div className="flex items-center gap-2 lg:gap-3 flex-wrap min-w-0">
                <div className="flex items-center gap-2 lg:gap-3 w-[200px] min-w-[100px] flex-shrink">
                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap flex-shrink-0">{t('form.processDesignName')}：</label>
                  <Input
                    value={processDesignQuery.name}
                    onChange={(e) => setProcessDesignQuery({ ...processDesignQuery, name: e.target.value })}
                    onPressEnter={handleProcessDesignQuery}
                    placeholder={t('form.processDesignNamePlaceholder')}
                    className="min-w-0 w-full"
                    allowClear
                  />
                </div>
                <Space className="flex-shrink-0">
                  <Button
                    type="primary"
                    icon={<Search className="w-4 h-4" />}
                    onClick={handleProcessDesignQuery}
                  >
                    {t('common.search')}
                  </Button>
                  <Button
                    icon={<RefreshCw className="w-4 h-4" />}
                    onClick={() => {
                      resetProcessDesignQuery();
                    }}
                  >
                    {t('common.reset')}
                  </Button>
                </Space>
              </div>
              {/* 新增等按钮留在最右侧 */}
              <Space className="flex-shrink-0">
                <Button
                  type="primary"
                  icon={<Plus className="w-4 h-4" />}
                  onClick={() => {
                    setEditingItem(null);
                    form.resetFields();
                    setShowAddModal(true);
                  }}
                >
                  {t('form.addProcess')}
                </Button>
              </Space>
            </div>
          </div>

          {/* 表格容器 */}
          <div className="isolation-work-list-table overflow-hidden min-w-0">
            <AntdTable
              columns={processDesignColumns}
              dataSource={processDesignPageData}
              rowKey="id"
              pagination={false}
              scroll={{ x: 'max-content' }}
              loading={processDesignLoading}
              rowClassName={(_, index) =>
                index !== undefined && index % 2 === 1 ? 'isolation-work-list-row-alt' : ''
              }
            />
          </div>
        </div>

        {/* 分页 */}
        {processDesignTotal > 0 && (
          <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
            <div className="flex items-center justify-between">
              <div className="text-sm text-gray-600">
                {t('common.total')} <span className="text-blue-600 font-medium">{processDesignTotal}</span> {t('common.records')}
              </div>
              <div className="flex gap-2">
                <Button
                  onClick={() => {
                    setProcessDesignPagination({ ...processDesignPagination, pageNo: processDesignPagination.pageNo - 1 });
                  }}
                  disabled={processDesignPagination.pageNo <= 1}
                >
                  {t('common.prevPage')}
                </Button>
                <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                  {processDesignPagination.pageNo} / {processDesignTotalPages}
                </span>
                <Button
                  onClick={() => {
                    setProcessDesignPagination({ ...processDesignPagination, pageNo: processDesignPagination.pageNo + 1 });
                  }}
                  disabled={processDesignPagination.pageNo >= processDesignTotalPages}
                >
                  {t('common.nextPage')}
                </Button>
              </div>
            </div>
          </div>
        )}

        {/* 新增/编辑弹窗 */}
        {subMenu === '流程设计' ? (
          <Modal
            title={editingItem ? t('common.editProcessDesign') : t('common.addProcessDesign')}
            open={showAddModal}
            onCancel={() => {
              setShowAddModal(false);
              setEditingItem(null);
              form.resetFields();
            }}
            onOk={async () => {
              try {
                const values = await form.validateFields();
                if (editingItem) {
                  // 编辑模式：调用更新接口，只更新name和description，content不变
                  await workflowDesignApi.updateWorkflowDesign({
                    id: editingItem.id!,
                    name: values.name,
                    description: values.description || '',
                  });
                  message.success(t('common.updateProcessSuccess'));
                  setShowAddModal(false);
                  setEditingItem(null);
                  form.resetFields();
                  getProcessDesignList();
                } else {
                  // 新建模式：调用新建接口
                  const result = await workflowDesignApi.insertWorkflowDesign({
                    name: values.name,
                    description: values.description || '',
                  });
                  
                  // API返回的是流程ID（数字），不是对象
                  const workflowId = typeof result === 'number' ? result : result?.id;
                  
                  // 关闭新建弹窗
                  setShowAddModal(false);
                  setEditingItem(null);
                  form.resetFields();
                  getProcessDesignList();
                  
                  // 显示确认框
                  if (workflowId) {
                    Modal.confirm({
                      title: t('common.processDesignComplete'),
                      okText: t('common.designNow'),
                      cancelText: t('common.later'),
                      onOk: () => {
                        // 直接跳转到流程设计页面，与设计按钮逻辑一致
                        navigate(`/process-designer?id=${workflowId}`);
                      },
                    });
                  } else {
                    // 如果没有ID，直接显示成功消息
                    message.success(t('common.addProcessSuccess'));
                  }
                }
              } catch (error: any) {
                if (error.errorFields) {
                  // 表单验证错误
                  return;
                }
                console.error(editingItem ? '更新流程失败:' : '新建流程失败:', error);
                message.error(error?.message || (editingItem ? t('common.updateProcessFailed') : t('common.addProcessFailed')));
              }
            }}
            okText={t('common.confirm')}
            cancelText={t('common.cancel')}
            width={700}
            destroyOnClose
          >
            <Form
              form={form}
              labelCol={{ span: 5 }}
              wrapperCol={{ span: 19 }}
              key={editingItem?.id || 'new'} // 使用key确保编辑时重新初始化表单
            >
              <Form.Item
                label={t('common.processName')}
                name="name"
                rules={[{ required: true, message: t('common.processNameRequired') }]}
              >
                <Input placeholder={t('common.processNamePlaceholder')} />
              </Form.Item>
              <Form.Item
                label={t('common.description')}
                name="description"
                style={{ marginBottom: '24px' }}
              >
                <Input.TextArea rows={7} placeholder={t('common.descriptionPlaceholder')} />
              </Form.Item>
            </Form>
          </Modal>
        ) : showAddModal && (
          <div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 animate-in fade-in duration-200">
            <div className="bg-white rounded-2xl shadow-2xl w-full max-w-3xl mx-4 max-h-[90vh] overflow-y-auto animate-in zoom-in duration-200">
              <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between sticky top-0 bg-white z-10">
                <h3 className="text-lg text-gray-900">
                  {editingItem ? t('common.editProcessDesign') : t('common.addProcessDesign')}
                </h3>
                <button
                  onClick={() => setShowAddModal(false)}
                  className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
                >
                  <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                  </svg>
                </button>
              </div>
              <div className="px-6 py-6">
                {(
                  // 其他菜单的表单保持原样
                  <div className="grid grid-cols-2 gap-4">
                    <div>
                      <label className="block text-sm text-gray-700 mb-2">名称 *</label>
                      <input
                        type="text"
                        className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
                        placeholder="请输入名称"
                        defaultValue={editingItem?.name || ''}
                      />
                    </div>
                    <div>
                      <label className="block text-sm text-gray-700 mb-2">设计人 *</label>
                      <input
                        type="text"
                        className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
                        placeholder="请输入设计人"
                        defaultValue={editingItem?.designer || ''}
                      />
                    </div>
                    <div>
                      <label className="block text-sm text-gray-700 mb-2">任务数量</label>
                      <input
                        type="number"
                        className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
                        placeholder="请输入任务数量"
                        defaultValue={editingItem?.nodeCount || ''}
                      />
                    </div>
                    <div>
                      <label className="block text-sm text-gray-700 mb-2">状态 *</label>
                      <select className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm">
                        <option value="">请选择</option>
                        <option value="启用">启用</option>
                        <option value="停用">停用</option>
                      </select>
                    </div>
                    <div className="col-span-2">
                      <label className="block text-sm text-gray-700 mb-2">{t('common.description')}</label>
                      <textarea
                        rows={3}
                        className="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm resize-none"
                        placeholder={t('common.descriptionPlaceholder')}
                        defaultValue={editingItem?.description || ''}
                      ></textarea>
                    </div>
                  </div>
                )}
              </div>
              <div className="px-6 py-4 bg-gray-50/50 border-t border-gray-200 flex justify-end gap-3 rounded-b-2xl">
                <button
                  onClick={() => setShowAddModal(false)}
                  className="px-5 py-2.5 text-sm text-gray-600 bg-white border border-gray-200 rounded-xl hover:bg-gray-50 transition-colors"
                >
                  取消
                </button>
                <button
                  onClick={() => {
                    // 其他菜单的保存逻辑
                    console.log('保存:', editingItem);
                    setShowAddModal(false);
                  }}
                  className="px-5 py-2.5 text-sm text-white bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl hover:shadow-lg hover:shadow-blue-400/40 transition-all"
                >
                  {editingItem ? '保存修改' : '确定'}
                </button>
              </div>
            </div>
          </div>
        )}
      </div>
    );
  }

  // 如果是作业管理页面，使用特殊的布局
  if (subMenu === '作业管理') {
    const workJobPageData = workJobList;

    return (
      <div className="space-y-6">
        {/* 搜索栏和表格容器 */}
        <div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm overflow-hidden">
          {/* 搜索栏 */}
          <div className="p-4 lg:p-5 border-b border-gray-200/50">
            <div className="flex flex-wrap items-center justify-between gap-3 lg:gap-4">
              {/* 搜索条件 + 搜索、重置：按原宽度 200px，不超出，可缩小 */}
              <div className="flex flex-wrap items-center gap-2 lg:gap-3 min-w-0">
                <div className="flex items-center gap-2 lg:gap-3 w-[200px] min-w-[100px] flex-shrink">
                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap flex-shrink-0">{t('form.workName')}：</label>
                  <Input
                    value={workJobQuery.name}
                    onChange={(e) => setWorkJobQuery({ ...workJobQuery, name: e.target.value })}
                    onPressEnter={handleWorkJobQuery}
                    placeholder={t('form.workNamePlaceholder')}
                    allowClear
                    className="min-w-0 w-full"
                  />
                </div>
                <div className="flex items-center gap-2 lg:gap-3 w-[200px] min-w-[100px] flex-shrink">
                  <label className="text-sm font-medium text-gray-700 whitespace-nowrap flex-shrink-0">{t('form.workStatus')}：</label>
                  <Select
                    value={workJobQuery.status ?? undefined}
                    onChange={(value) => setWorkJobQuery({ ...workJobQuery, status: value || undefined })}
                    placeholder={t('form.workStatusPlaceholder')}
                    allowClear
                    className="min-w-0 w-full"
                  >
                    {jobStatusDictList.map(item => (
                      <Select.Option key={item.value} value={item.value}>
                        {item.label}
                      </Select.Option>
                    ))}
                  </Select>
                </div>
                <Space className="flex-shrink-0">
                  <Button
                    type="primary"
                    icon={<Search className="w-4 h-4" />}
                    onClick={handleWorkJobQuery}
                  >
                    {t('common.search')}
                  </Button>
                  <Button
                    icon={<RefreshCw className="w-4 h-4" />}
                    onClick={() => {
                      resetWorkJobQuery();
                      getWorkJobList();
                    }}
                  >
                    {t('common.reset')}
                  </Button>
                </Space>
              </div>
              {/* 新增/发起作业等按钮留在最右侧 */}
              <Space className="flex-shrink-0">
                <Button
                  type="primary"
                  icon={<Plus className="w-4 h-4" />}
                  onClick={() => {
                    setEditingItem(null);
                    setShowAddModal(true);
                    setOriginalBasicFormData(null); // 清空原始表单数据（新增模式）
                    getWorkTypeDictList();
                    getUrgencyLevelDictList();
                    getIsolationMethodDictList();
                    getWorkflowTemplateList();
                  }}
                >
                  {t('form.initiateWork')}
                </Button>
              </Space>
            </div>
          </div>

          {/* 表格容器 */}
          <div className="isolation-work-list-table overflow-hidden min-w-0">
            <AntdTable
              columns={workJobColumns}
              dataSource={workJobPageData}
              rowKey="id"
              pagination={false}
              scroll={{ x: 'max-content' }}
              loading={workJobLoading}
              rowClassName={(_, index) =>
                index !== undefined && index % 2 === 1 ? 'isolation-work-list-row-alt' : ''
              }
            />
          </div>
        </div>

        {/* 分页 */}
        {workJobTotal > 0 && (
          <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
            <div className="flex items-center justify-between">
              <div className="text-sm text-gray-600">
                {t('common.total')} <span className="text-blue-600 font-medium">{workJobTotal}</span> {t('common.records')}
              </div>
              <div className="flex gap-2">
                <Button
                  onClick={() => setWorkJobPagination({ ...workJobPagination, pageNo: workJobPagination.pageNo - 1 })}
                  disabled={workJobPagination.pageNo <= 1}
                >
                  {t('common.prevPage')}
                </Button>
                <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                  {workJobPagination.pageNo} / {Math.ceil(workJobTotal / workJobPagination.pageSize) || 1}
                </span>
                <Button
                  onClick={() => setWorkJobPagination({ ...workJobPagination, pageNo: workJobPagination.pageNo + 1 })}
                  disabled={workJobPagination.pageNo >= Math.ceil(workJobTotal / workJobPagination.pageSize)}
                >
                  {t('common.nextPage')}
                </Button>
              </div>
            </div>
          </div>
        )}

        {/* 发起作业多步骤弹窗（新增和编辑共用） */}
        {subMenu === '作业管理' && showAddModal && !editingItem ? (
          <Modal
            title={null}
            open={showAddModal}
            onCancel={() => {
              setShowAddModal(false);
              setWorkJobStep(0);
              workJobBasicForm.resetFields();
              workJobPublishForm.resetFields();
              setWorkflowJson(null);
              setWorkflowWorkId(null); // 清空作业ID
              setIsViewMode(false); // 重置查看模式
              // 清空流程管理相关状态
              setWorkflowNodes([]);
              setWorkflowEdges([]);
              setSelectedWorkflowNode(null);
              setWorkflowNodeConfigCache(new Map());
              setCompletedNodeIds(new Set());
              setNodeSavedStatusCache(new Map());
              setWorkflowWorkNodeDOList([]); // 清空节点数据列表
              setOriginalBasicFormData(null); // 清空原始表单数据
              // 关闭弹框时刷新列表
              getWorkJobList();
            }}
            footer={null}
            width={1400}
            destroyOnClose
            styles={{
              body: { padding: 0 }
            }}
          >
            <div className="flex flex-col h-[80vh]">
              {/* Tab导航 */}
              <div className="px-6 py-4 bg-white">
                <Tabs
                  activeKey={String(workJobStep)}
                  onChange={(key) => {
                    // 查看模式下可以自由切换tab
                    if (isViewMode) {
                      setWorkJobStep(Number(key));
                      return;
                    }
                    // 只有第一个tab完成才能进入第二个tab
                    if (key === '1' && workJobStep === 0) {
                      workJobBasicForm.validateFields().then(() => {
                        setWorkJobStep(1);
                      }).catch(() => {
                        message.warning(t('common.pleaseCompleteBasicInfo'));
                      });
                    } else if (key === '2' && workJobStep < 2) {
                      // 只有第二个tab完成才能进入第三个tab
                      if (workflowJson) {
                        setWorkJobStep(2);
                      } else {
                        message.warning(t('common.pleaseCompleteWorkflowManagement'));
                      }
                    } else {
                      setWorkJobStep(Number(key));
                    }
                  }}
                  items={[
                    {
                      key: '0',
                      label: (
                        <span className="flex items-center gap-2">
                          <FileText className="w-4 h-4" />
                          {t('common.basicInfo')}
                        </span>
                      ),
                    },
                    {
                      key: '1',
                      label: (
                        <span className="flex items-center gap-2">
                          <Workflow className="w-4 h-4" />
                          {t('common.workflowManagement')}
                        </span>
                      ),
                      disabled: isViewMode ? false : workJobStep < 1,
                    },
                    {
                      key: '2',
                      label: (
                        <span className="flex items-center gap-2">
                          <Play className="w-4 h-4" />
                          {t('common.publishWork')}
                        </span>
                      ),
                      disabled: isViewMode ? false : workJobStep < 2,
                    },
                  ]}
                />
              </div>

              {/* Tab内容 */}
              <div className="flex-1 overflow-y-auto px-6 py-4 bg-white">
                {workJobStep === 0 && (
                  <div className="flex justify-center">
                    <Form
                      form={workJobBasicForm}
                      layout="vertical"
                      className="max-w-2xl w-full"
                    >
                    <Form.Item
                      label={t('common.workflowTemplate')}
                      required
                      extra={t('common.workflowTemplateHelp')}
                    >
                      <div ref={workflowTemplateSelectWrapRef}>
                        <Form.Item
                          name="workflowTemplate"
                          noStyle
                          rules={[{ required: true, message: t('common.workflowTemplateRequired') }]}
                        >
                          <Select
                            ref={workflowTemplateSelectRef}
                            placeholder={t('common.workflowTemplatePlaceholder')}
                            allowClear
                            showSearch
                            disabled={isViewMode}
                            open={workflowTemplateDropdownVisible}
                            onDropdownVisibleChange={setWorkflowTemplateDropdownVisible}
                            onClear={() => {
                              setWorkflowTemplateDropdownVisible(false);
                            }}
                            filterOption={(input, option) =>
                              (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
                            }
                            options={workflowTemplateList
                              .filter(item => item.status === 1) // 只显示启用的
                              .map(item => ({
                                label: item.name,
                                value: item.id,
                              }))}
                            onSelect={() => {
                              setWorkflowTemplateDropdownVisible(false);
                            }}
                            onChange={(value) => {
                              setWorkflowTemplateDropdownVisible(false);
                              if (value) {
                                // 加载流程设计JSON
                                loadWorkflowJson(value);
                                // 自动填充作业名称为流程模板名称
                                const selectedTemplate = workflowTemplateList.find(item => item.id === value);
                                if (selectedTemplate?.name) {
                                  workJobBasicForm.setFieldsValue({ jobName: selectedTemplate.name });
                                }
                              } else {
                                setWorkflowJson(null);
                                // 清空作业名称
                                workJobBasicForm.setFieldsValue({ jobName: '' });
                              }
                            }}
                          />
                        </Form.Item>
                      </div>
                    </Form.Item>

                    <Form.Item
                      label={t('common.jobCategory')}
                      required
                    >
                      <div ref={jobCategorySelectWrapRef}>
                        <Form.Item
                          name="jobCategory"
                          noStyle
                          rules={[{ required: true, message: t('common.jobCategoryRequired') }]}
                        >
                          <Select
                            ref={jobCategorySelectRef}
                            placeholder={t('common.jobCategoryPlaceholder')}
                            allowClear
                            disabled={isViewMode}
                            open={jobCategoryDropdownVisible}
                            onDropdownVisibleChange={setJobCategoryDropdownVisible}
                            onSelect={() => {
                              setJobCategoryDropdownVisible(false);
                            }}
                            onClear={() => {
                              setJobCategoryDropdownVisible(false);
                            }}
                            onChange={() => {
                              // 保险：某些端 onSelect 不触发时，onChange 兜底收起
                              setJobCategoryDropdownVisible(false);
                            }}
                          >
                            {workTypeDictList.map((item) => (
                              <Select.Option key={item.id} value={item.value}>
                                {item.label}
                              </Select.Option>
                            ))}
                          </Select>
                        </Form.Item>
                      </div>
                    </Form.Item>

                    <Form.Item
                      label={t('common.workName')}
                      name="jobName"
                      required
                      rules={[{ required: true, message: t('common.workNameRequired') }]}
                    >
                      <Input placeholder={t('common.workNamePlaceholder')} disabled={isViewMode} readOnly={isViewMode} />
                    </Form.Item>

                    <Form.Item
                      label={t('common.workContent')}
                      name="jobContent"
                      required
                      rules={[{ required: true, message: t('common.workContentPlaceholder') }]}
                    >
                      <Input.TextArea 
                        rows={4} 
                        placeholder={t('common.workContentPlaceholder')}
                        showCount
                        maxLength={500}
                        disabled={isViewMode}
                        readOnly={isViewMode}
                      />
                    </Form.Item>

                    <Form.Item
                      label={t('common.urgencyLevel')}
                      name="urgency"
                    >
                      <Radio.Group disabled={isViewMode}>
                        {urgencyLevelDictList.length > 0 ? (
                          urgencyLevelDictList.map((item) => (
                            <Radio key={item.id} value={item.value}>
                              {item.label}
                            </Radio>
                          ))
                        ) : (
                          <span className="text-gray-400 text-sm">{t('common.loading')}</span>
                        )}
                      </Radio.Group>
                    </Form.Item>
                  </Form>
                  </div>
                )}

                {workJobStep === 1 && (
                  <div className="flex gap-4" style={{ height: 'calc(80vh - 250px)' }}>
                      {/* 左侧：流程设计渲染区域（面积大一些），带点状网状背景 */}
                      <div
                        className="flex-1 border border-gray-200 rounded-lg overflow-hidden"
                        style={{
                          minWidth: 0,
                          backgroundColor: '#f8fafc',
                          backgroundImage: 'radial-gradient(circle at center, #cbd5e1 1.2px, transparent 1.2px)',
                          backgroundSize: '14px 14px',
                        }}
                      >
                      {workflowNodes.length > 0 ? (
                        <div className="h-full" ref={workflowReactFlowWrapper}>
                          <style>{`
                            .react-flow__arrowhead {
                              fill: #000000 !important;
                            }
                            .react-flow__edge-path {
                              stroke: #000000 !important;
                            }
                            .react-flow__edge marker path {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            .react-flow__edge path {
                              stroke: #000000 !important;
                            }
                            svg marker path {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            svg marker polygon {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            .react-flow__edge .react-flow__edge-path {
                              stroke: #000000 !important;
                            }
                            .react-flow__edge svg path {
                              stroke: #000000 !important;
                            }
                            .react-flow__edge svg marker polygon {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            .react-flow__edge svg marker path {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            .react-flow__edge svg marker {
                              fill: #000000 !important;
                            }
                            svg defs marker path {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            svg defs marker polygon {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            .react-flow__edge svg defs marker path {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                            .react-flow__edge svg defs marker polygon {
                              fill: #000000 !important;
                              stroke: #000000 !important;
                            }
                          `}</style>
                          <ReactFlow
                            nodes={workflowNodes}
                            edges={workflowEdges}
                            onNodesChange={isViewMode ? undefined : onWorkflowNodesChange}
                            onEdgesChange={isViewMode ? undefined : onWorkflowEdgesChange}
                            onNodeClick={isViewMode ? undefined : onWorkflowNodeClick}
                            onPaneClick={isViewMode ? undefined : onWorkflowPaneClick}
                            nodesDraggable={!isViewMode}
                            nodesConnectable={!isViewMode}
                            elementsSelectable={!isViewMode}
                            nodeTypes={nodeTypes}
                            edgeTypes={sharedFlowEdgeTypes}
                            fitView
                            onInit={(instance) => {
                              setWorkflowReactFlowInstance(instance);
                              // 初始化后自动适应视图
                              setTimeout(() => {
                                instance.fitView({ padding: 0.2 });
                              }, 100);
                            }}
                            connectionMode={ConnectionMode.Loose}
                            snapToGrid={true}
                            snapGrid={[16, 16]}
                            connectionRadius={40}
                            defaultEdgeOptions={{
                              style: { strokeWidth: 2, stroke: '#000000' },
                              type: 'straight',
                              markerStart: {
                                type: 'arrowclosed',
                                color: '#000000',
                              },
                            }}
                            edgesUpdatable={!isViewMode}
                          >
                            <Controls className="!bg-white !border !border-gray-200 !rounded-lg !shadow-md" />
                            <Background variant={BackgroundVariant.Dots} gap={12} size={1.5} color="#cbd5e1" />
                          </ReactFlow>
                        </div>
                      ) : (
                        <div className="flex items-center justify-center h-full text-gray-400">
                          {workflowJson ? '正在加载流程设计...' : '请先在基本信息中选择流程模板'}
                        </div>
                      )}
                    </div>

                    {/* 右侧：配置面板；key 随选中节点变化以强制重挂载，避免切换节点后面板内容未刷新 */}
                    <div className="w-80 border border-gray-200 rounded-lg bg-white overflow-y-auto flex-shrink-0">
                      {selectedWorkflowNode ? (
                        <div key={selectedWorkflowNode.id} className="h-full flex flex-col">
                          {/* 头部 */}
                          <div className="px-4 py-2.5 bg-white border-b border-gray-200 flex items-center justify-between sticky top-0 z-10 shadow-sm">
                            <h3 className="text-sm font-medium text-gray-900">
                              {t('isolationWork.nodeSettingsTitle', {
                                nodeName: workflowNodeConfig.nodeName || selectedWorkflowNode.data?.label || t('isolationWork.nodeDefaultName'),
                              })}
                            </h3>
                            <button
                              onClick={() => setSelectedWorkflowNode(null)}
                              className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
                              disabled={isViewMode}
                            >
                              <CloseOutlined className="text-gray-500" />
                            </button>
                          </div>

                          {/* 内容 */}
                          <div className="flex-1 p-4 overflow-y-auto space-y-6">
                            {/* 节点信息 */}
                            <div>
                              <h4 className="flex items-center gap-3 text-base font-semibold text-gray-900 mb-4">
                                <span className="w-1 h-5 bg-blue-500 rounded-full flex-shrink-0" style={{ minWidth: '4px', minHeight: '20px' }}></span>
                                {t('isolationWork.nodeInfo')}
                              </h4>
                              <div className="space-y-5">
                                {/* 节点名称 */}
                                <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-2">
                                    {t('isolationWork.nodeName')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                                  </label>
                                  <Input
                                    value={workflowNodeConfig.nodeName || ''}
                                    onChange={(e) =>
                                      setWorkflowNodeConfig({ ...workflowNodeConfig, nodeName: e.target.value })
                                    }
                                    placeholder={t('isolationWork.nodeNamePlaceholder')}
                                    className="rounded-lg border-gray-200"
                                    disabled={isViewMode}
                                  />
                                </div>

                                {/* 负责人 */}
                                {selectedWorkflowNode.data?.type !== 'createJob' && !workflowSchemePanelOpen && (
                                  <div>
                                    <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}
                                      onChange={(value) =>
                                        setWorkflowNodeConfig({ ...workflowNodeConfig, responsible: value || undefined })
                                      }
                                      placeholder={t('isolationWork.responsiblePlaceholder')}
                                      className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                      allowClear
                                      disabled={isViewMode}
                                    >
                                      {workflowDrawerUsers.map(user => (
                                        <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                      ))}
                                    </Select>
                                    <p className="text-xs text-gray-500 mt-1.5 leading-relaxed">
                                      {t('isolationWork.responsibleHelp')}
                                    </p>
                                  </div>
                                )}

                                {/* 备注 */}
                                {selectedWorkflowNode.data?.type !== 'createJob' && selectedWorkflowNode.data?.type !== 'confirm' && selectedWorkflowNode.data?.type !== 'review' && selectedWorkflowNode.data?.type !== 'inputInfo' && !workflowSchemePanelOpen && selectedWorkflowNode.data?.type !== 'returnLock' && selectedWorkflowNode.data?.type !== 'complete' && (
                                  <div>
                                    <label className="block text-sm font-medium text-gray-700 mb-2">
                                      备注
                                    </label>
                                    <Input.TextArea
                                      value={workflowNodeConfig.remark || ''}
                                      onChange={(e) =>
                                        setWorkflowNodeConfig({ ...workflowNodeConfig, remark: e.target.value })
                                      }
                                      placeholder="请输入备注"
                                      rows={3}
                                      className="rounded-lg border-gray-200"
                                      disabled={isViewMode}
                                    />
                                  </div>
                                )}
                              </div>
                            </div>

                            {/* 提交表单 - 创建作业节点不显示 */}
                            {selectedWorkflowNode.data?.type !== 'createJob' && (
                            <div>
                              <h4 className="flex items-center gap-3 text-base font-semibold text-gray-900 mb-4">
                                <span className="w-1 h-5 bg-blue-500 rounded-full flex-shrink-0" style={{ minWidth: '4px', minHeight: '20px' }}></span>
                                {t('isolationWork.submitFormSection')}
                              </h4>
                              <div className="space-y-5">
                                <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>
                                    )}
                                  </label>
                                  <Select
                                    value={workflowNodeConfig.submitForm || undefined}
                                    onChange={(value) =>
                                      setWorkflowNodeConfig({ ...workflowNodeConfig, submitForm: value || undefined })
                                    }
                                    placeholder={t('isolationWork.businessFormPlaceholder')}
                                    className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                    allowClear
                                    disabled={isViewMode || workflowUnlockSideReadonly}
                                  >
                                    {workflowFormList.map(form => (
                                      <Select.Option key={form.id} value={form.id}>{form.name}</Select.Option>
                                    ))}
                                  </Select>
                                </div>

                                {/* 上锁/解锁/共锁/解除共锁 节点特有的字段 */}
                                {workflowSchemePanelOpen && (
                                  <>
                                    {/* 解锁/解除共锁：选择关联的上锁或共锁节点 */}
                                    {workflowUnlockSideReadonly && (
                                      <div>
                                        <label className="block text-sm font-medium text-gray-700 mb-2">
                                          {isWorkflowUnlockCoLockType(selectedWorkflowNode.data?.type || '')
                                            ? '选择共锁任务'
                                            : '选择上锁任务'}{' '}
                                          <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                                        </label>
                                        <Select
                                          value={workflowNodeConfig.isolationNodeUuid || undefined}
                                          disabled={isViewMode}
                                          onChange={(value) => {
                                            setWorkflowNodeConfig((prev) => {
                                              if (!value) {
                                                return { ...prev, isolationNodeUuid: '' };
                                              }
                                              
                                              // 从 workflowWorkNodeDOList 中查找对应的隔离节点数据
                                              const isolationNodeDO = workflowWorkNodeDOList.find(
                                                (item) =>
                                                  item.uuid === value &&
                                                  isWorkflowUnlockParentMatch(
                                                    selectedWorkflowNode.data?.type,
                                                    item.type
                                                  )
                                              );
                                              
                                              if (isolationNodeDO) {
                                                // 解析隔离节点的 data 字段
                                                let isolationNodeData: any = {};
                                                if (isolationNodeDO.data) {
                                                  try {
                                                    isolationNodeData = typeof isolationNodeDO.data === 'string' 
                                                      ? JSON.parse(isolationNodeDO.data) 
                                                      : isolationNodeDO.data;
                                                  } catch (e) {
                                                    console.error('解析隔离节点data失败:', e);
                                                  }
                                                }
                                                
                                                // 解析隔离点
                                                let isolationPoints: string[] = [];
                                                if (isolationNodeDO.isolationPoints) {
                                                  try {
                                                    isolationPoints = typeof isolationNodeDO.isolationPoints === 'string' 
                                                      ? JSON.parse(isolationNodeDO.isolationPoints) 
                                                      : (Array.isArray(isolationNodeDO.isolationPoints) ? isolationNodeDO.isolationPoints : []);
                                                  } catch (e) {
                                                    console.error('解析隔离点失败:', e);
                                                    isolationPoints = isolationNodeData.isolationPoints || [];
                                                  }
                                                } else {
                                                  isolationPoints = isolationNodeData.isolationPoints || [];
                                                }
                                                
                                                // 从 nodeUserList 中提取上锁人和共锁人
                                                let lockPersonId: number | undefined = undefined;
                                                const coLockPersonIds: (number | string)[] = [];
                                                if (isolationNodeDO.nodeUserList && Array.isArray(isolationNodeDO.nodeUserList)) {
                                                  isolationNodeDO.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) {
                                                      coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
                                                    }
                                                  });
                                                }
                                                
                                                // 复制隔离节点的所有数据到解除隔离节点
                                                return {
                                                  ...prev,
                                                  isolationNodeUuid: value || '',
                                                  // 复制隔离方式
                                                  isolationType: (isolationNodeDO.isolationType !== null && isolationNodeDO.isolationType !== undefined) 
                                                    ? String(isolationNodeDO.isolationType) 
                                                    : (isolationNodeData.isolationType || ''),
                                                  // 复制隔离点
                                                  isolationPoints: isolationPoints,
                                                  // 复制负责人（如果隔离方式是盲板或拆除）
                                                  responsible: isolationNodeDO.workerUserId 
                                                    ? (typeof isolationNodeDO.workerUserId === 'number' ? isolationNodeDO.workerUserId : Number(isolationNodeDO.workerUserId)) 
                                                    : (isolationNodeData.workerUserId ? (typeof isolationNodeData.workerUserId === 'number' ? isolationNodeData.workerUserId : Number(isolationNodeData.workerUserId)) : undefined),
                                                  // 复制上锁人
                                                  lockPerson: lockPersonId || (isolationNodeData.lockPerson ? (typeof isolationNodeData.lockPerson === 'number' ? isolationNodeData.lockPerson : Number(isolationNodeData.lockPerson)) : undefined),
                                                  // 复制共锁人
                                                  coLockPersons: coLockPersonIds.length > 0 
                                                    ? coLockPersonIds 
                                                    : (isolationNodeData.coLockPersons && Array.isArray(isolationNodeData.coLockPersons) 
                                                      ? isolationNodeData.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) 
                                                      : []),
                                                };
                                              }
                                              
                                              // 如果没找到 nodeDO，尝试从 workflowNodes 中获取
                                              const target = workflowNodes.find(
                                                (n) =>
                                                  n.id === value &&
                                                  isWorkflowUnlockParentMatch(
                                                    selectedWorkflowNode.data?.type,
                                                    n.data?.type
                                                  )
                                              );
                                              if (target) {
                                                const source = target.data || {};
                                                return {
                                                  ...prev,
                                                  isolationNodeUuid: value || '',
                                                  isolationType: source.isolationType || '',
                                                  isolationPoints: source.isolationPoints || [],
                                                  isolationNode: Array.isArray(source.isolationNode)
                                                    ? source.isolationNode
                                                    : (source.isolationNode ? [source.isolationNode] : []),
                                                  responsible: source.workerUserId ? (typeof source.workerUserId === 'number' ? source.workerUserId : Number(source.workerUserId)) : undefined,
                                                  lockPerson: source.lockPerson ? (typeof source.lockPerson === 'number' ? source.lockPerson : Number(source.lockPerson)) : undefined,
                                                  coLockPersons: source.coLockPersons && Array.isArray(source.coLockPersons) 
                                                    ? source.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) 
                                                    : [],
                                                };
                                              }
                                              
                                              return { ...prev, isolationNodeUuid: value || '' };
                                            });
                                          }}
                                          placeholder={
                                            isWorkflowUnlockCoLockType(selectedWorkflowNode.data?.type || '')
                                              ? '请选择共锁任务'
                                              : '请选择上锁任务'
                                          }
                                          className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                          allowClear
                                        >
                                          {(() => {
                                            const wantCoLockParent = isWorkflowUnlockCoLockType(
                                              selectedWorkflowNode.data?.type || ''
                                            );
                                            const currentNodeId = selectedWorkflowNode?.id;

                                            const incomingEdges = workflowEdges.filter(
                                              (edge) => String(edge.target) === String(currentNodeId)
                                            );

                                            const outgoingEdges = workflowEdges.filter(
                                              (edge) => String(edge.source) === String(currentNodeId)
                                            );

                                            const connectedSchemeNodeIds = new Set<string>();
                                            incomingEdges.forEach((edge) => {
                                              connectedSchemeNodeIds.add(String(edge.source));
                                            });
                                            outgoingEdges.forEach((edge) => {
                                              connectedSchemeNodeIds.add(String(edge.target));
                                            });

                                            const schemeNodes = workflowNodes.filter((n) =>
                                              wantCoLockParent
                                                ? isWorkflowCoLockType(n.data?.type)
                                                : isWorkflowLockSchemeType(n.data?.type)
                                            );

                                            let nodesToShow =
                                              connectedSchemeNodeIds.size > 0
                                                ? schemeNodes.filter((n) =>
                                                    connectedSchemeNodeIds.has(String(n.id))
                                                  )
                                                : schemeNodes;

                                            const selectedId = workflowNodeConfig.isolationNodeUuid;
                                            if (
                                              selectedId &&
                                              !nodesToShow.some((n) => String(n.id) === String(selectedId))
                                            ) {
                                              const selectedNode = schemeNodes.find(
                                                (n) => String(n.id) === String(selectedId)
                                              );
                                              if (selectedNode) {
                                                nodesToShow = [selectedNode, ...nodesToShow];
                                              }
                                            }

                                            const defaultLabel = wantCoLockParent
                                              ? nodeConfigs.find((c) => c.type === 'coLock')?.label || '共锁'
                                              : nodeConfigs.find((c) => c.type === 'lock')?.label || '上锁';

                                            return nodesToShow.map((node) => {
                                              const nodeDO = workflowWorkNodeDOList.find(
                                                (item) =>
                                                  item.uuid === node.id &&
                                                  (wantCoLockParent
                                                    ? isWorkflowCoLockType(item.type)
                                                    : isWorkflowLockSchemeType(item.type))
                                              );
                                              const displayName =
                                                nodeDO?.nodeName || node.data?.label || defaultLabel;
                                              
                                              return (
                                                <Select.Option key={node.id} value={node.id}>
                                                  {displayName}
                                                </Select.Option>
                                              );
                                            });
                                          })()}
                                        </Select>
                                      </div>
                                    )}

                                    {isWorkflowUnlockCoLockType(selectedWorkflowNode.data?.type || '') &&
                                      workflowUnlockSideReadonly &&
                                      !!workflowNodeConfig.isolationNodeUuid && (
                                      <div>
                                        <label className="block text-sm font-medium text-gray-700 mb-2">
                                          {t('isolationWork.coLocker')}
                                        </label>
                                        <Select
                                          mode="multiple"
                                          value={workflowNodeConfig.coLockPersons}
                                          onChange={(value) =>
                                            setWorkflowNodeConfig({ ...workflowNodeConfig, coLockPersons: value })
                                          }
                                          placeholder={t('isolationWork.coLockerPlaceholder')}
                                          className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!min-h-10"
                                          allowClear
                                          disabled={isViewMode || workflowUnlockSideReadonly}
                                        >
                                          {workflowColockerUsers.map((user) => (
                                            <Select.Option key={user.id} value={user.id}>
                                              {user.nickname || user.username}
                                            </Select.Option>
                                          ))}
                                        </Select>
                                      </div>
                                    )}

                                    {isWorkflowCoLockType(selectedWorkflowNode.data?.type || '') && (
                                      <>
                                        <div>
                                          <label className="block text-sm font-medium text-gray-700 mb-2">
                                            选择上锁任务{' '}
                                            <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                                          </label>
                                          <Select
                                            value={workflowNodeConfig.isolationNodeUuid || undefined}
                                            disabled={isViewMode}
                                            onChange={(value) => {
                                              setWorkflowNodeConfig((prev) => {
                                                if (!value) {
                                                  return { ...prev, isolationNodeUuid: '' };
                                                }
                                                const lockNodeDO = workflowWorkNodeDOList.find(
                                                  (item) =>
                                                    item.uuid === value && isWorkflowLockSchemeType(item.type)
                                                );
                                                if (lockNodeDO) {
                                                  let isolationNodeData: any = {};
                                                  if (lockNodeDO.data) {
                                                    try {
                                                      isolationNodeData =
                                                        typeof lockNodeDO.data === 'string'
                                                          ? JSON.parse(lockNodeDO.data)
                                                          : lockNodeDO.data;
                                                    } catch (e) {
                                                      console.error('解析上锁节点data失败:', e);
                                                    }
                                                  }
                                                  let isolationPoints: string[] = [];
                                                  if (lockNodeDO.isolationPoints) {
                                                    try {
                                                      isolationPoints =
                                                        typeof lockNodeDO.isolationPoints === 'string'
                                                          ? JSON.parse(lockNodeDO.isolationPoints)
                                                          : Array.isArray(lockNodeDO.isolationPoints)
                                                            ? lockNodeDO.isolationPoints
                                                            : [];
                                                    } catch (e) {
                                                      isolationPoints = isolationNodeData.isolationPoints || [];
                                                    }
                                                  } else {
                                                    isolationPoints = isolationNodeData.isolationPoints || [];
                                                  }
                                                  let lockPersonId: number | undefined = undefined;
                                                  if (lockNodeDO.nodeUserList && Array.isArray(lockNodeDO.nodeUserList)) {
                                                    lockNodeDO.nodeUserList.forEach((user: any) => {
                                                      if (user.type === 'jtlocker' && user.userId) {
                                                        lockPersonId =
                                                          typeof user.userId === 'number'
                                                            ? user.userId
                                                            : Number(user.userId);
                                                      }
                                                    });
                                                  }
                                                  return {
                                                    ...prev,
                                                    isolationNodeUuid: value || '',
                                                    isolationType:
                                                      lockNodeDO.isolationType !== null &&
                                                      lockNodeDO.isolationType !== undefined
                                                        ? String(lockNodeDO.isolationType)
                                                        : isolationNodeData.isolationType || '',
                                                    isolationPoints,
                                                    responsible: lockNodeDO.workerUserId
                                                      ? typeof lockNodeDO.workerUserId === 'number'
                                                        ? lockNodeDO.workerUserId
                                                        : Number(lockNodeDO.workerUserId)
                                                      : isolationNodeData.workerUserId
                                                        ? typeof isolationNodeData.workerUserId === 'number'
                                                          ? isolationNodeData.workerUserId
                                                          : Number(isolationNodeData.workerUserId)
                                                        : undefined,
                                                    lockPerson:
                                                      lockPersonId ||
                                                      (isolationNodeData.lockPerson
                                                        ? typeof isolationNodeData.lockPerson === 'number'
                                                          ? isolationNodeData.lockPerson
                                                          : Number(isolationNodeData.lockPerson)
                                                        : undefined),
                                                    coLockPersons: prev.coLockPersons,
                                                  };
                                                }
                                                const target = workflowNodes.find(
                                                  (n) =>
                                                    n.id === value && isWorkflowLockSchemeType(n.data?.type)
                                                );
                                                if (target) {
                                                  const source = target.data || {};
                                                  return {
                                                    ...prev,
                                                    isolationNodeUuid: value || '',
                                                    isolationType: source.isolationType || '',
                                                    isolationPoints: source.isolationPoints || [],
                                                    isolationNode: Array.isArray(source.isolationNode)
                                                      ? source.isolationNode
                                                      : source.isolationNode
                                                        ? [source.isolationNode]
                                                        : [],
                                                    responsible: source.workerUserId
                                                      ? typeof source.workerUserId === 'number'
                                                        ? source.workerUserId
                                                        : Number(source.workerUserId)
                                                      : undefined,
                                                    lockPerson: source.lockPerson
                                                      ? typeof source.lockPerson === 'number'
                                                        ? source.lockPerson
                                                        : Number(source.lockPerson)
                                                      : undefined,
                                                    coLockPersons: prev.coLockPersons,
                                                  };
                                                }
                                                return { ...prev, isolationNodeUuid: value || '' };
                                              });
                                            }}
                                            placeholder="请选择上锁任务"
                                            className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                            allowClear
                                          >
                                            {(() => {
                                              const currentNodeId = selectedWorkflowNode?.id;
                                              const incomingEdges = workflowEdges.filter(
                                                (edge) => String(edge.target) === String(currentNodeId)
                                              );
                                              const outgoingEdges = workflowEdges.filter(
                                                (edge) => String(edge.source) === String(currentNodeId)
                                              );
                                              const connectedSchemeNodeIds = new Set<string>();
                                              incomingEdges.forEach((edge) => {
                                                connectedSchemeNodeIds.add(String(edge.source));
                                              });
                                              outgoingEdges.forEach((edge) => {
                                                connectedSchemeNodeIds.add(String(edge.target));
                                              });
                                              const schemeNodes = workflowNodes.filter((n) =>
                                                isWorkflowLockSchemeType(n.data?.type)
                                              );
                                              let nodesToShow =
                                                connectedSchemeNodeIds.size > 0
                                                  ? schemeNodes.filter((n) =>
                                                      connectedSchemeNodeIds.has(String(n.id))
                                                    )
                                                  : schemeNodes;
                                              const selectedId = workflowNodeConfig.isolationNodeUuid;
                                              if (
                                                selectedId &&
                                                !nodesToShow.some((n) => String(n.id) === String(selectedId))
                                              ) {
                                                const sel = schemeNodes.find(
                                                  (n) => String(n.id) === String(selectedId)
                                                );
                                                if (sel) nodesToShow = [sel, ...nodesToShow];
                                              }
                                              const defaultLabel =
                                                nodeConfigs.find((c) => c.type === 'lock')?.label || '上锁';
                                              return nodesToShow.map((node) => {
                                                const nodeDO = workflowWorkNodeDOList.find(
                                                  (item) =>
                                                    item.uuid === node.id && isWorkflowLockSchemeType(item.type)
                                                );
                                                const displayName =
                                                  nodeDO?.nodeName || node.data?.label || defaultLabel;
                                                return (
                                                  <Select.Option key={node.id} value={node.id}>
                                                    {displayName}
                                                  </Select.Option>
                                                );
                                              });
                                            })()}
                                          </Select>
                                        </div>
                                        <div>
                                          <label className="block text-sm font-medium text-gray-700 mb-2">
                                            {t('isolationWork.coLocker')}
                                          </label>
                                          <Select
                                            mode="multiple"
                                            value={workflowNodeConfig.coLockPersons}
                                            onChange={(value) =>
                                              setWorkflowNodeConfig({ ...workflowNodeConfig, coLockPersons: value })
                                            }
                                            placeholder={t('isolationWork.coLockerPlaceholder')}
                                            className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!min-h-10"
                                            allowClear
                                            disabled={isViewMode}
                                          >
                                            {workflowColockerUsers.map((user) => (
                                              <Select.Option key={user.id} value={user.id}>
                                                {user.nickname || user.username}
                                              </Select.Option>
                                            ))}
                                          </Select>
                                        </div>
                                      </>
                                    )}

                                    {!isWorkflowCoLockType(selectedWorkflowNode.data?.type || '') &&
                                      !isWorkflowUnlockCoLockType(selectedWorkflowNode.data?.type || '') && (
                                      <>
                                        {/* 隔离方式 */}
                                        <div>
                                          <label className="block text-sm font-medium text-gray-700 mb-2">
                                            {t('isolationWork.isolationMethod')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                                          </label>
                                          <Select
                                            value={workflowNodeConfig.isolationType || undefined}
                                            onChange={(value) =>
                                              setWorkflowNodeConfig({ ...workflowNodeConfig, isolationType: value || '' })
                                            }
                                            placeholder={t('isolationWork.isolationMethodPlaceholder')}
                                            className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                            allowClear
                                            disabled={isViewMode || workflowUnlockSideReadonly}
                                          >
                                            {isolationTypeDictList.map((item) => (
                                              <Select.Option key={item.id} value={item.value}>
                                                {item.label}
                                              </Select.Option>
                                            ))}
                                          </Select>
                                        </div>

                                        {/* 隔离点选择（可多选） */}
                                        {workflowSchemePanelOpen && (
                                          <div>
                                            <label className="block text-sm font-medium text-gray-700 mb-2">
                                              {t('isolationWork.isolationPointSelect')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                                            </label>
                                            <Select
                                              mode="multiple"
                                              value={workflowNodeConfig.isolationPoints}
                                              onChange={(value) =>
                                                setWorkflowNodeConfig({ ...workflowNodeConfig, isolationPoints: value })
                                              }
                                              placeholder={t('isolationWork.isolationPointPlaceholder')}
                                              className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!min-h-10"
                                              allowClear
                                              disabled={isViewMode || workflowUnlockSideReadonly}
                                            >
                                              {workflowIsolationPoints.map((point: any, index) => (
                                                <Select.Option key={point.pointId || point.id || `point-${index}`} value={point.pointId || point.id}>{point.pointName}</Select.Option>
                                              ))}
                                            </Select>
                                          </div>
                                        )}

                                        {/* 盲板和拆除：显示负责人 */}
                                        {/* 字典值：0=盲板，1=上锁挂牌，2=拆除 */}
                                        {(workflowNodeConfig.isolationType === '0' || workflowNodeConfig.isolationType === '2') && (
                                          <div>
                                            <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}
                                              onChange={(value) =>
                                                setWorkflowNodeConfig({ ...workflowNodeConfig, responsible: value || undefined })
                                              }
                                              placeholder={t('isolationWork.responsiblePlaceholder')}
                                              className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                              allowClear
                                              disabled={isViewMode || workflowUnlockSideReadonly}
                                            >
                                              {workflowDrawerUsers.map(user => (
                                                <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                              ))}
                                            </Select>
                                          </div>
                                        )}

                                        {/* 上锁挂牌：显示上锁人；上锁类源节点不显示共锁人 */}
                                        {workflowNodeConfig.isolationType === '1' && (
                                          <>
                                            <div>
                                              <label className="block text-sm font-medium text-gray-700 mb-2">
                                                {t('isolationWork.locker')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                                              </label>
                                              <Select
                                                value={workflowNodeConfig.lockPerson || undefined}
                                                onChange={(value) =>
                                                  setWorkflowNodeConfig({ ...workflowNodeConfig, lockPerson: value || undefined })
                                                }
                                                placeholder={t('isolationWork.lockerPlaceholder')}
                                                className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                                allowClear
                                                disabled={isViewMode || workflowUnlockSideReadonly}
                                              >
                                                {workflowLockerUsers.map(user => (
                                                  <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                                ))}
                                              </Select>
                                            </div>
                                            {!isWorkflowLockSchemeType(selectedWorkflowNode.data?.type || '') &&
                                              !isWorkflowUnlockSchemeType(selectedWorkflowNode.data?.type || '') && (
                                              <div>
                                                <label className="block text-sm font-medium text-gray-700 mb-2">
                                                  {t('isolationWork.coLocker')}
                                                </label>
                                                <Select
                                                  mode="multiple"
                                                  value={workflowNodeConfig.coLockPersons}
                                                  onChange={(value) =>
                                                    setWorkflowNodeConfig({ ...workflowNodeConfig, coLockPersons: value })
                                                  }
                                                  placeholder={t('isolationWork.coLockerPlaceholder')}
                                                  className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!min-h-10"
                                                  allowClear
                                                  disabled={isViewMode || workflowUnlockSideReadonly}
                                                >
                                                  {workflowColockerUsers.map(user => (
                                                    <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                                  ))}
                                                </Select>
                                              </div>
                                            )}
                                          </>
                                        )}
                                      </>
                                    )}
                                  </>
                                )}
                              </div>
                            </div>
                            )}

                            {/* 通知消息 - 创建作业节点不显示 */}
                            {selectedWorkflowNode.data?.type !== 'createJob' && (
                            <div>
                              <h4 className="flex items-center gap-3 text-base font-semibold text-gray-900 mb-4">
                                <span className="w-1 h-5 bg-blue-500 rounded-full flex-shrink-0" style={{ minWidth: '4px', minHeight: '20px' }}></span>
                                {t('isolationWork.notificationSection')}
                              </h4>
                              <div className="space-y-5">
                                <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-3">
                                    {t('isolationWork.notificationMethod')}
                                  </label>
                                  <div className="bg-gray-50 p-3 rounded-lg">
                                    <div className="mb-3">
                                      <Checkbox
                                        checked={workflowNodeConfig.notificationMethods?.sms || false}
                                        onChange={(e) =>
                                          setWorkflowNodeConfig({
                                            ...workflowNodeConfig,
                                            notificationMethods: {
                                              ...workflowNodeConfig.notificationMethods,
                                              sms: e.target.checked,
                                            },
                                            smsTemplateCode: e.target.checked ? 'true' : 'false',
                                          })
                                        }
                                        disabled={isViewMode || workflowUnlockSideReadonly}
                                      >
                                        {t('isolationWork.notifySMS')}
                                      </Checkbox>
                                    </div>
                                    <div className="mb-3">
                                      <Checkbox
                                        checked={workflowNodeConfig.notificationMethods?.message || false}
                                        onChange={(e) =>
                                          setWorkflowNodeConfig({
                                            ...workflowNodeConfig,
                                            notificationMethods: {
                                              ...workflowNodeConfig.notificationMethods,
                                              message: e.target.checked,
                                            },
                                            messageTemplateCode: e.target.checked ? 'true' : 'false',
                                          })
                                        }
                                        disabled={isViewMode || workflowUnlockSideReadonly}
                                      >
                                        {t('isolationWork.notifyInbox')}
                                      </Checkbox>
                                    </div>
                                    <div className="mb-3">
                                      <Checkbox
                                        checked={workflowNodeConfig.notificationMethods?.email || false}
                                        onChange={(e) =>
                                          setWorkflowNodeConfig({
                                            ...workflowNodeConfig,
                                            notificationMethods: {
                                              ...workflowNodeConfig.notificationMethods,
                                              email: e.target.checked,
                                            },
                                            emailTemplateCode: e.target.checked ? 'true' : 'false',
                                          })
                                        }
                                        disabled={isViewMode || workflowUnlockSideReadonly}
                                      >
                                        {t('isolationWork.notifyEmail')}
                                      </Checkbox>
                                    </div>
                                    <div>
                                      <Checkbox
                                        checked={workflowNodeConfig.notificationMethods?.app || false}
                                        onChange={(e) =>
                                          setWorkflowNodeConfig({
                                            ...workflowNodeConfig,
                                            notificationMethods: {
                                              ...workflowNodeConfig.notificationMethods,
                                              app: e.target.checked,
                                            },
                                            appTemplateCode: e.target.checked ? 'true' : 'false',
                                          })
                                        }
                                        disabled={isViewMode || workflowUnlockSideReadonly}
                                      >
                                        {t('isolationWork.notifyApp')}
                                      </Checkbox>
                                    </div>
                                  </div>
                                </div>
                                <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-3">
                                    {t('isolationWork.notificationTarget')}
                                  </label>
                                  <div className="mb-3 space-y-1 text-xs text-gray-500">
                                    <div>{t('isolationWork.notificationTargetTip1')}</div>
                                    <div>{t('isolationWork.notificationTargetTip2')}</div>
                                  </div>
                                  <div className="space-y-3 bg-gray-50 p-3 rounded-lg">
                                    <div>
                                      <label className="block text-sm font-medium text-gray-700 mb-2">
                                        {t('isolationWork.ccDeptLabel')}
                                      </label>
                                      <TreeSelect
                                        multiple
                                        value={workflowNodeConfig.copyDeptIds.length ? workflowNodeConfig.copyDeptIds : undefined}
                                        onChange={(value) =>
                                          setWorkflowNodeConfig({
                                            ...workflowNodeConfig,
                                            copyDeptIds: Array.isArray(value) ? value.map(String) : value != null && value !== '' ? [String(value)] : [],
                                          })
                                        }
                                        placeholder={t('isolationWork.ccDeptPlaceholder')}
                                        treeData={workflowCcDeptTreeData}
                                        className="w-full"
                                        allowClear
                                        showSearch
                                        treeNodeFilterProp="title"
                                        treeDefaultExpandAll
                                        disabled={isViewMode || workflowUnlockSideReadonly}
                                      />
                                    </div>
                                    <div>
                                      <label className="block text-sm font-medium text-gray-700 mb-2">
                                        {t('isolationWork.ccUserLabel')}
                                      </label>
                                      <TreeSelect
                                        multiple
                                        value={workflowNodeConfig.copyUserIds.length ? workflowNodeConfig.copyUserIds : undefined}
                                        onChange={(value) =>
                                          setWorkflowNodeConfig({
                                            ...workflowNodeConfig,
                                            copyUserIds: Array.isArray(value) ? value.map(String) : value != null && value !== '' ? [String(value)] : [],
                                          })
                                        }
                                        placeholder={t('isolationWork.ccUserPlaceholder')}
                                        treeData={workflowCcUserTreeData}
                                        className="w-full"
                                        allowClear
                                        showSearch
                                        treeNodeFilterProp="title"
                                        treeDefaultExpandAll
                                        disabled={isViewMode || workflowUnlockSideReadonly}
                                      />
                                    </div>
                                  </div>
                                </div>
                                {/* <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-2">
                                    通知人
                                  </label>
                                  <Select
                                    value={workflowNodeConfig.notificationPerson || undefined}
                                    onChange={(value) =>
                                      setWorkflowNodeConfig({ ...workflowNodeConfig, notificationPerson: value || '' })
                                    }
                                    placeholder="请选择通知人"
                                    className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                    allowClear
                                    disabled={isViewMode}
                                  >
                                    <Select.Option value="taskResponsible">任务负责人</Select.Option>
                                    <Select.Option value="taskParticipant">任务参与人</Select.Option>
                                    <Select.Option value="responsibleAndParticipant">负责人和参与人</Select.Option>
                                    <Select.Option value="specifiedPerson">指定人</Select.Option>
                                  </Select>
                                </div> */}
                                {/* <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-2">
                                    通知时间
                                  </label>
                                  <Select
                                    value={workflowNodeConfig.notificationTime || undefined}
                                    onChange={(value) =>
                                      setWorkflowNodeConfig({ ...workflowNodeConfig, notificationTime: value || '' })
                                    }
                                    placeholder="请选择通知时间"
                                    className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                    allowClear
                                    disabled={isViewMode}
                                  >
                                    <Select.Option value="before">执行前（上一个节点结束后）</Select.Option>
                                    <Select.Option value="after">执行后（该节点结束后）</Select.Option>
                                    <Select.Option value="time">选择时间</Select.Option>
                                    <Select.Option value="30min">任务开始前30分钟</Select.Option>
                                    <Select.Option value="1h">任务开始前1小时</Select.Option>
                                    <Select.Option value="2h">任务开始前2小时</Select.Option>
                                    <Select.Option value="4h">任务开始前4小时</Select.Option>
                                    <Select.Option value="5h">任务开始前5小时</Select.Option>
                                    <Select.Option value="8h">任务开始前8小时</Select.Option>
                                    <Select.Option value="12h">任务开始前12小时</Select.Option>
                                    <Select.Option value="24h">任务开始前24小时</Select.Option>
                                    <Select.Option value="48h">任务开始前48小时</Select.Option>
                                  </Select>
                                </div> */}
                              </div>
                            </div>
                            )}
                          </div>
                          
                          {/* 保存按钮 */}
                          {!isViewMode && (
                            <div className="px-4 py-3 border-t border-gray-200 bg-white sticky bottom-0 z-10">
                              <Button
                                type="primary"
                                className="w-full"
                                onClick={async () => {
                                  if (!selectedWorkflowNode) {
                                    message.warning(t('common.pleaseSelectNodeToConfig'));
                                    return;
                                  }
                                  
                                  // 验证当前节点配置
                                  const isValid = validateNodeConfig(workflowNodeConfig, selectedWorkflowNode.data?.type || '');
                                  if (!isValid) {
                                    message.warning(t('common.pleaseCompleteRequiredNodeConfig'));
                                    return;
                                  }
                                  
                                  try {
                                    // 查找对应的 workflowWorkNodeDO 节点（通过uuid匹配）
                                    const nodeDO = workflowWorkNodeDOList.find(item => item.uuid === selectedWorkflowNode.id);
                                    
                                    // 在外部作用域定义，确保在自动切换节点时可以使用
                                    let mergedWorkflowWorkNodeDOList: WorkflowWorkNodeDO[] = [];
                                    let didRefreshFlowNodes = false; // 是否已用合并列表刷新过画布所有节点
                                    
                                    if (nodeDO && nodeDO.id && workflowWorkId) {
                                      // 构建节点用户信息列表
                                      const nodeUserDOList: WorkflowWorkNodeUserDO[] = [];
                                      
                                      // 解锁/解除共锁：从关联的上锁或共锁节点复制人员数据
                                      if (
                                        isWorkflowUnlockLikeValidationType(
                                          selectedWorkflowNode.data?.type || ''
                                        ) &&
                                        workflowNodeConfig.isolationNodeUuid
                                      ) {
                                        const isolationNodeDO = workflowWorkNodeDOList.find(
                                          (item) =>
                                            item.uuid === workflowNodeConfig.isolationNodeUuid &&
                                            isWorkflowUnlockParentMatch(
                                              selectedWorkflowNode.data?.type,
                                              item.type
                                            )
                                        );
                                        
                                        if (isolationNodeDO) {
                                          // 复制隔离节点的 nodeUserList（上锁人、共锁人等）
                                          if (isolationNodeDO.nodeUserList && Array.isArray(isolationNodeDO.nodeUserList)) {
                                            isolationNodeDO.nodeUserList.forEach((user: any) => {
                                              if (user.type === 'jtlocker' || user.type === 'jtcolocker') {
                                                nodeUserDOList.push({
                                                  userId: user.userId,
                                                  type: user.type,
                                                });
                                              }
                                            });
                                          }
                                        }
                                      } else {
                                        // 非解除类节点：使用原有逻辑
                                        // 如果隔离方式是"上锁挂牌"（字典值：1），添加上锁人员和共锁人员
                                        if (workflowNodeConfig.isolationType === '1') {
                                          // 添加上锁人员
                                          if (workflowNodeConfig.lockPerson) {
                                            nodeUserDOList.push({
                                              userId: Number(workflowNodeConfig.lockPerson),
                                              type: 'jtlocker',
                                            });
                                          }
                                          
                                          // 添加共锁人员（可以多选）
                                          if (workflowNodeConfig.coLockPersons && workflowNodeConfig.coLockPersons.length > 0) {
                                            workflowNodeConfig.coLockPersons.forEach((userId: string | number) => {
                                              nodeUserDOList.push({
                                                userId: Number(userId),
                                                type: 'jtcolocker',
                                              });
                                            });
                                          }
                                        }
                                      }
                                      
                                      // 调用更新节点接口
                                      const formId = workflowNodeConfig.submitForm ? Number(workflowNodeConfig.submitForm) : undefined;
                                      
                                      // 如果 formId 存在，先调用接口获取表单数据
                                      let formData: string | undefined = undefined;
                                      if (formId) {
                                        try {
                                          const formResponse = await getForm(formId);
                                          // 获取 data 字段的内容（如果接口返回的是 { code, data, message } 格式）
                                          let formDataObj: any = formResponse;
                                          if (formResponse && typeof formResponse === 'object' && 'data' in formResponse) {
                                            formDataObj = (formResponse as any).data || formResponse;
                                          }
                                          // 将整个对象内容转换成 JSON 字符串传递给 formData 字段
                                          formData = JSON.stringify(formDataObj);
                                          console.log('表单数据已转换为字符串:', formData);
                                        } catch (error) {
                                          console.error('获取表单数据失败:', error);
                                          // 即使获取失败，也继续保存节点，只是不传递 formData
                                        }
                                      }
                                      
                                      // 从 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));
                                      // 共锁人：有则传 JSON 字符串，清空时传空字符串以便后端清空
                                      const colockPersons = colockPersonIds.length > 0 ? JSON.stringify(colockPersonIds) : '';
                                      const copyDeptIdsStr = workflowCopyIdsToApiCommaString(workflowNodeConfig.copyDeptIds);
                                      const copyUserIdsStr = workflowCopyIdsToApiCommaString(workflowNodeConfig.copyUserIds);

                                      const updateParam: UpdateWorkflowWorkNodeParam = {
                                        nodeId: nodeDO.id,
                                        nodeName: workflowNodeConfig.nodeName,
                                        formId: formId,
                                        workerUserId: workflowNodeConfig.responsible ? Number(workflowNodeConfig.responsible) : undefined,
                                        isolationType: workflowNodeConfig.isolationType || undefined,
                                        isolationPoints: workflowNodeConfig.isolationPoints && Array.isArray(workflowNodeConfig.isolationPoints) && workflowNodeConfig.isolationPoints.length > 0 
                                          ? JSON.stringify(workflowNodeConfig.isolationPoints) 
                                          : undefined,
                                        // 解除类节点：传递关联方案源节点 UUID
                                        isolationNodeUuid:
                                          isWorkflowUnlockLikeValidationType(
                                            selectedWorkflowNode.data?.type || ''
                                          ) && workflowNodeConfig.isolationNodeUuid
                                            ? workflowNodeConfig.isolationNodeUuid
                                            : undefined,
                                        nodeUserDOList: nodeUserDOList.length > 0 ? nodeUserDOList : undefined,
                                        lockPerson,
                                        colockPersons:
                                          (isWorkflowLockSchemeType(selectedWorkflowNode.data?.type || '') ||
                                            isWorkflowCoLockType(selectedWorkflowNode.data?.type || '')) &&
                                          workflowNodeConfig.isolationType === '1'
                                            ? colockPersons
                                            : undefined,
                                        // 如果获取到了表单数据，将整个对象内容转换成字符串传递给 formData 字段
                                        formData: formData,
                                        // 根据选中值传递模板代码参数（字符串类型的 'true' 或 'false'）
                                        smsTemplateCode: workflowNodeConfig.smsTemplateCode || 'false',
                                        messageTemplateCode: workflowNodeConfig.messageTemplateCode || 'false',
                                        emailTemplateCode: workflowNodeConfig.emailTemplateCode || 'false',
                                        appTemplateCode: workflowNodeConfig.appTemplateCode || 'false',
                                        // 后端要求逗号分隔字符串，禁止 JSON 数组（如 [380]）
                                        copyDeptIds: copyDeptIdsStr,
                                        copyUserIds: copyUserIdsStr,
                                      };
                                      
                                      await workJobApi.updateWorkflowWorkNode(updateParam);
                                      
                                      // 上锁/共锁节点且含上锁人/共锁人：复刻到对应的解锁/解除共锁节点并刷新画布
                                      const selNodeType = selectedWorkflowNode.data?.type || '';
                                      const isLockSchemeWithLock =
                                        isWorkflowLockSchemeType(selNodeType) &&
                                        workflowNodeConfig.isolationType === '1' &&
                                        nodeUserDOList.length > 0;
                                      const isCoLockSchemeWithLock =
                                        isWorkflowCoLockType(selNodeType) &&
                                        workflowNodeConfig.isolationType === '1' &&
                                        nodeUserDOList.length > 0;
                                      if (isLockSchemeWithLock || isCoLockSchemeWithLock) {
                                        const listForSync = workflowWorkNodeDOList.map((item: WorkflowWorkNodeDO) => {
                                          const matchUnlock =
                                            isLockSchemeWithLock &&
                                            (isWorkflowUnlockSchemeType(item.type) ||
                                              item.type === '解除隔离') &&
                                            item.isolationNodeUuid === selectedWorkflowNode.id;
                                          const matchUnlockCo =
                                            isCoLockSchemeWithLock &&
                                            isWorkflowUnlockCoLockType(item.type) &&
                                            item.isolationNodeUuid === selectedWorkflowNode.id;
                                          if (matchUnlock || matchUnlockCo) {
                                            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) =>
                                              ((isLockSchemeWithLock &&
                                                (isWorkflowUnlockSchemeType(n.type) ||
                                                  n.type === '解除隔离')) ||
                                                (isCoLockSchemeWithLock &&
                                                  isWorkflowUnlockCoLockType(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 === resolveWorkflowPaletteType(String(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: resolveNotificationMethods(source, nodeDO),
                                              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 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:', nodeListFromApi);
                                            
                                            // 创建一个映射，方便查找
                                            const prevMap = new Map<string | number, WorkflowWorkNodeDO>();
                                            prev.forEach(item => {
                                              if (item.id) prevMap.set(item.id, item);
                                              if (item.uuid) prevMap.set(item.uuid, item);
                                            });
                                            
                                            const saveSchemeType = selectedWorkflowNode.data?.type || '';
                                            const saveLockSchemeWithLock =
                                              isWorkflowLockSchemeType(saveSchemeType) &&
                                              workflowNodeConfig.isolationType === '1' &&
                                              nodeUserDOList.length > 0;
                                            const saveCoLockSchemeWithLock =
                                              isWorkflowCoLockType(saveSchemeType) &&
                                              workflowNodeConfig.isolationType === '1' &&
                                              nodeUserDOList.length > 0;

                                            const updatedList = nodeListFromApi.map((newItem: WorkflowWorkNodeDO) => {
                                              const isReleaseForCurrentScheme =
                                                newItem.isolationNodeUuid === selectedWorkflowNode.id &&
                                                ((saveLockSchemeWithLock &&
                                                  (isWorkflowUnlockSchemeType(newItem.type) ||
                                                    newItem.type === '解除隔离')) ||
                                                  (saveCoLockSchemeWithLock &&
                                                    isWorkflowUnlockCoLockType(newItem.type)));
                                              if (isReleaseForCurrentScheme) {
                                                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)) || 
                                                                  null;
                                              
                                              // 如果找到现有节点，合并数据（优先使用接口返回的数据，但保留现有数据中接口没有返回的字段）
                                              if (existingItem) {
                                                const merged: WorkflowWorkNodeDO = {
                                                  ...existingItem,
                                                  ...newItem,
                                                  workerUserId: (newItem.workerUserId !== null && newItem.workerUserId !== undefined && newItem.workerUserId !== 0) 
                                                    ? newItem.workerUserId 
                                                    : existingItem.workerUserId,
                                                  formId: (newItem.formId !== null && newItem.formId !== undefined && newItem.formId !== 0) 
                                                    ? newItem.formId 
                                                    : existingItem.formId,
                                                  isolationType: (newItem.isolationType !== null && newItem.isolationType !== undefined && newItem.isolationType !== '') 
                                                    ? newItem.isolationType 
                                                    : existingItem.isolationType,
                                                  isolationPoints: (newItem.isolationPoints !== null && newItem.isolationPoints !== undefined && newItem.isolationPoints !== '') 
                                                    ? newItem.isolationPoints 
                                                    : existingItem.isolationPoints,
                                                  nodeUserList: (newItem.nodeUserList && Array.isArray(newItem.nodeUserList) && newItem.nodeUserList.length > 0)
                                                    ? newItem.nodeUserList
                                                    : (existingItem.nodeUserList || []),
                                                };
                                                return merged;
                                              }
                                              
                                              return newItem;
                                            });
                                            
                                            // 如果接口返回的列表中有新节点（不在现有列表中的），也要添加
                                            const existingUuids = new Set<string | number>();
                                            prev.forEach(item => {
                                              if (item.id) existingUuids.add(item.id);
                                              if (item.uuid) existingUuids.add(item.uuid);
                                            });
                                            
                                            const newItems = nodeListFromApi.filter((item: WorkflowWorkNodeDO) => {
                                              const itemKey = item.id || item.uuid;
                                              return itemKey && !existingUuids.has(itemKey);
                                            });
                                            
                                            mergedWorkflowWorkNodeDOList = [...updatedList, ...newItems];
                                            console.log('合并更新后的 workflowWorkNodeDOList:', mergedWorkflowWorkNodeDOList);
                                            
                                            // 更新状态
                                            setWorkflowWorkNodeDOList(mergedWorkflowWorkNodeDOList);
                                            
                                            // 清除与该隔离节点对应的解除隔离节点的配置缓存，切换节点时从最新 workflowWorkNodeDOList 拉取（显示后端已同步的上锁人/共锁人）
                                            const releaseIsolationUuids = mergedWorkflowWorkNodeDOList
                                              .filter(
                                                (n: WorkflowWorkNodeDO) =>
                                                  n.isolationNodeUuid === selectedWorkflowNode.id &&
                                                  ((saveLockSchemeWithLock &&
                                                    (isWorkflowUnlockSchemeType(n.type) ||
                                                      n.type === '解除隔离')) ||
                                                    (saveCoLockSchemeWithLock &&
                                                      isWorkflowUnlockCoLockType(n.type)))
                                              )
                                              .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 === resolveWorkflowPaletteType(String(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: resolveNotificationMethods(source, nodeDO),
                                                  notificationPerson: source.notificationPerson ?? '',
                                                  notificationTime: nodeDO.notifyTime ?? source.notificationTime ?? '',
                                                  smsTemplateCode: source.smsTemplateCode ?? (source.notificationMethods?.sms ? 'true' : 'false'),
                                                  messageTemplateCode: source.messageTemplateCode ?? (source.notificationMethods?.message ? 'true' : 'false'),
                                                  emailTemplateCode: source.emailTemplateCode ?? (source.notificationMethods?.email ? 'true' : 'false'),
                                                  appTemplateCode: source.appTemplateCode ?? (source.notificationMethods?.app ? 'true' : 'false'),
                                                  copyDeptIds: workflowCopyDeptIds(source, nodeDO),
                                                  copyUserIds: workflowCopyUserIds(source, nodeDO),
                                                  completed: isCurrent ? true : (node.data?.completed ?? false),
                                                };
                                                return { ...node, data: updatedData, selected: isCurrent ? false : node.selected };
                                              })
                                            );
                                            didRefreshFlowNodes = true;
                                          }
                                        } catch (error: any) {
                                          console.error('获取最新节点数据失败:', error);
                                          // 如果接口调用失败，仍然使用本地更新逻辑作为后备
                                          setWorkflowWorkNodeDOList(prev => prev.map(item => {
                                            if (item.id === nodeDO.id) {
                                              return {
                                                ...item,
                                                nodeName: workflowNodeConfig.nodeName,
                                                formId: workflowNodeConfig.submitForm ? Number(workflowNodeConfig.submitForm) : undefined,
                                                workerUserId: workflowNodeConfig.responsible ? Number(workflowNodeConfig.responsible) : undefined,
                                                isolationType: workflowNodeConfig.isolationType || undefined,
                                                isolationPoints: workflowNodeConfig.isolationPoints && workflowNodeConfig.isolationPoints.length > 0 
                                                  ? JSON.stringify(workflowNodeConfig.isolationPoints) 
                                                  : undefined,
                                                lockPerson: workflowNodeConfig.lockPerson ? String(workflowNodeConfig.lockPerson) : undefined,
                                                notifyTime: workflowNodeConfig.notificationTime || undefined,
                                                data: JSON.stringify((() => {
                                                  const existingData = item.data ? (typeof item.data === 'string' ? JSON.parse(item.data) : item.data) : {};
                                                  const { isolationMethod, ...restExistingData } = existingData;
                                                  return {
                                                    ...restExistingData,
                                                    label: workflowNodeConfig.nodeName,
                                                    icon: workflowNodeConfig.nodeIcon,
                                                    responsible: workflowNodeConfig.responsible ? String(workflowNodeConfig.responsible) : '',
                                                    remark: workflowNodeConfig.remark,
                                                    submitForm: workflowNodeConfig.submitForm ? String(workflowNodeConfig.submitForm) : '',
                                                    isolationType: workflowNodeConfig.isolationType,
                                                    isolationPoints: workflowNodeConfig.isolationPoints,
                                                    isolationNode: workflowNodeConfig.isolationNode,
                                                    isolationNodeUuid: workflowNodeConfig.isolationNodeUuid,
                                                    lockPerson: workflowNodeConfig.lockPerson ? String(workflowNodeConfig.lockPerson) : '',
                                                    coLockPersons: workflowNodeConfig.coLockPersons.map((id: any) => String(id)),
                                                    notificationMethods: workflowNodeConfig.notificationMethods,
                                                    notificationPerson: workflowNodeConfig.notificationPerson,
                                                    notificationTime: workflowNodeConfig.notificationTime,
                                                    smsTemplateCode: workflowNodeConfig.smsTemplateCode,
                                                    messageTemplateCode: workflowNodeConfig.messageTemplateCode,
                                                    emailTemplateCode: workflowNodeConfig.emailTemplateCode,
                                                    appTemplateCode: workflowNodeConfig.appTemplateCode,
                                                    copyDeptIds: workflowCopyIdsToApiCommaString(workflowNodeConfig.copyDeptIds),
                                                    copyUserIds: workflowCopyIdsToApiCommaString(workflowNodeConfig.copyUserIds),
                                                  };
                                                })()),
                                              };
                                            }
                                            return item;
                                          }));
                                        }
                                      }
                                    }
                                    
                                    // 缓存当前节点配置
                                    const newCache = new Map(workflowNodeConfigCache);
                                    newCache.set(selectedWorkflowNode.id, { ...workflowNodeConfig });
                                    setWorkflowNodeConfigCache(newCache);
                                    
                                    // 标记当前节点为已完成
                                    const newCompleted = new Set(completedNodeIds);
                                    newCompleted.add(selectedWorkflowNode.id);
                                    setCompletedNodeIds(newCompleted);
                                    
                                    // 更新节点保存状态缓存
                                    const newSavedStatusCache = new Map(nodeSavedStatusCache);
                                    newSavedStatusCache.set(selectedWorkflowNode.id, true);
                                    setNodeSavedStatusCache(newSavedStatusCache);
                                    
                                    // 更新节点显示（若已用详情合并列表刷新过画布则不再覆盖，避免解除隔离等节点被旧数据覆盖）
                                    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,
                                        smsTemplateCode: workflowNodeConfig.smsTemplateCode,
                                        messageTemplateCode: workflowNodeConfig.messageTemplateCode,
                                        emailTemplateCode: workflowNodeConfig.emailTemplateCode,
                                        appTemplateCode: workflowNodeConfig.appTemplateCode,
                                        copyDeptIds: workflowNodeConfig.copyDeptIds,
                                        copyUserIds: workflowNodeConfig.copyUserIds,
                                        completed: true,
                                      };
                                      setWorkflowNodes((nds) =>
                                        nds.map((node) =>
                                          node.id === selectedWorkflowNode.id
                                            ? { ...node, data: updatedData, selected: false }
                                            : node
                                        )
                                      );
                                    }
                                    
                                    // 查找下一个未完成的节点（使用新的completedSet，而不是状态中的）
                                    // 优先查找当前节点的子节点
                                    const nextNode = getNextIncompleteNode(newCompleted, selectedWorkflowNode.id);
                                    if (nextNode) {
                                      // 自动切换到下一个节点
                                      // 使用合并后的最新数据（如果有的话），否则使用状态中的数据
                                      const latestWorkflowWorkNodeDOList = mergedWorkflowWorkNodeDOList.length > 0 
                                        ? mergedWorkflowWorkNodeDOList 
                                        : workflowWorkNodeDOList;
                                      
                                      setTimeout(() => {
                                        setSelectedWorkflowNode(nextNode);
                                        const cachedConfig = newCache.get(nextNode.id);
                                        if (cachedConfig) {
                                          setWorkflowNodeConfig(cachedConfig);
                                        } else {
                                          // 从最新的 workflowWorkNodeDOList 中查找节点数据
                                          const nextNodeDO = latestWorkflowWorkNodeDOList.find(item => item.uuid === nextNode.id);
                                          if (nextNodeDO) {
                                            let nextNodeData: any = {};
                                            if (nextNodeDO.data) {
                                              try {
                                                nextNodeData = typeof nextNodeDO.data === 'string' ? JSON.parse(nextNodeDO.data) : nextNodeDO.data;
                                              } catch (e) {
                                                console.error('解析节点data失败:', e);
                                              }
                                            }
                                            const source = nextNodeData || nextNode.data || {};
                                            const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(nextNodeDO.type || source.type)));
                                            setWorkflowNodeConfig({
                                              nodeName: nextNodeDO.nodeName || source.label || config?.label || '',
                                              nodeIcon: nextNodeDO.nodeIcon || source.icon || '',
                                              responsible: (nextNodeDO.workerUserId !== null && nextNodeDO.workerUserId !== undefined && nextNodeDO.workerUserId !== 0) 
                                                ? (typeof nextNodeDO.workerUserId === 'number' ? nextNodeDO.workerUserId : Number(nextNodeDO.workerUserId)) 
                                                : (source.workerUserId && source.workerUserId !== '' && source.workerUserId !== '0') 
                                                  ? (typeof source.workerUserId === 'number' ? source.workerUserId : Number(source.workerUserId)) 
                                                  : undefined,
                                              remark: source.remark || '',
                                              submitForm: nextNodeDO.formId ? (typeof nextNodeDO.formId === 'number' ? nextNodeDO.formId : Number(nextNodeDO.formId)) : (source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined),
                                              isolationType: (nextNodeDO.isolationType !== null && nextNodeDO.isolationType !== undefined) ? String(nextNodeDO.isolationType) : (source.isolationType || ''),
                                              isolationPoints: nextNodeDO.isolationPoints ? (typeof nextNodeDO.isolationPoints === 'string' ? JSON.parse(nextNodeDO.isolationPoints) : nextNodeDO.isolationPoints) : (source.isolationPoints || []),
                                              isolationNode: source.isolationNode || [],
                                              isolationNodeUuid: nextNodeDO.isolationNodeUuid || source.isolationNodeUuid || '',
                                              lockPerson: (() => {
                                                // 优先从 nodeUserList 中提取
                                                let lockPersonId: number | undefined = undefined;
                                                if (nextNodeDO.nodeUserList && Array.isArray(nextNodeDO.nodeUserList)) {
                                                  const lockerUser = nextNodeDO.nodeUserList.find((user: any) => user.type === 'jtlocker');
                                                  if (lockerUser?.userId) {
                                                    lockPersonId = typeof lockerUser.userId === 'number' ? lockerUser.userId : Number(lockerUser.userId);
                                                  }
                                                }
                                                return lockPersonId || (source.lockPerson ? (typeof source.lockPerson === 'number' ? source.lockPerson : Number(source.lockPerson)) : undefined);
                                              })(),
                                              coLockPersons: (() => {
                                                // 优先从 nodeUserList 中提取
                                                const coLockPersonIds: number[] = [];
                                                if (nextNodeDO.nodeUserList && Array.isArray(nextNodeDO.nodeUserList)) {
                                                  nextNodeDO.nodeUserList.forEach((user: any) => {
                                                    if (user.type === 'jtcolocker' && user.userId) {
                                                      coLockPersonIds.push(typeof user.userId === 'number' ? user.userId : Number(user.userId));
                                                    }
                                                  });
                                                }
                                                return coLockPersonIds.length > 0 ? coLockPersonIds : (source.coLockPersons && Array.isArray(source.coLockPersons) ? source.coLockPersons.map((id: any) => typeof id === 'number' ? id : Number(id)) : []);
                                              })(),
                                              notificationMethods: resolveNotificationMethods(source, nextNodeDO),
                                              notificationPerson: source.notificationPerson || '',
                                              notificationTime: nextNodeDO.notifyTime || source.notificationTime || '',
                                              smsTemplateCode: source.smsTemplateCode || (source.notificationMethods?.sms ? 'true' : 'false'),
                                              messageTemplateCode: source.messageTemplateCode || (source.notificationMethods?.message ? 'true' : 'false'),
                                              emailTemplateCode: source.emailTemplateCode || (source.notificationMethods?.email ? 'true' : 'false'),
                                              appTemplateCode: source.appTemplateCode || (source.notificationMethods?.app ? 'true' : 'false'),
                                              copyDeptIds: workflowCopyDeptIds(source, nextNodeDO),
                                              copyUserIds: workflowCopyUserIds(source, nextNodeDO),
                                            });
                                          } else {
                                            const source = nextNode.data || {};
                                            const config = nodeConfigs.find((c) => c.type === resolveWorkflowPaletteType(String(source.type)));
                                            setWorkflowNodeConfig({
                                              nodeName: source.label || config?.label || '',
                                              nodeIcon: source.icon || '',
                                              responsible: source.responsible ? (typeof source.responsible === 'number' ? source.responsible : Number(source.responsible)) : undefined,
                                              remark: source.remark || '',
                                              submitForm: source.submitForm ? (typeof source.submitForm === 'number' ? source.submitForm : Number(source.submitForm)) : undefined,
                                              isolationType: source.isolationType || '',
                                              isolationPoints: source.isolationPoints || [],
                                              isolationNode: source.isolationNode || [],
                                              isolationNodeUuid: source.isolationNodeUuid || '',
                                              lockPerson: source.lockPerson || '',
                                              coLockPersons: source.coLockPersons || [],
                                              notificationMethods: resolveNotificationMethods(source),
                                              notificationPerson: source.notificationPerson || '',
                                              notificationTime: source.notificationTime || '',
                                              smsTemplateCode: source.smsTemplateCode || 'false',
                                              messageTemplateCode: source.messageTemplateCode || 'false',
                                              emailTemplateCode: source.emailTemplateCode || 'false',
                                              appTemplateCode: source.appTemplateCode || 'false',
                                              copyDeptIds: workflowCopyDeptIds(source),
                                              copyUserIds: workflowCopyUserIds(source),
                                            });
                                          }
                                        }
                                        // 高亮下一个节点
                                        setWorkflowNodes((nds) =>
                                          nds.map((node) =>
                                            node.id === nextNode.id
                                              ? { ...node, selected: true }
                                              : { ...node, selected: false }
                                          )
                                        );
                                        // 不自动聚焦，保持当前视图，让用户能看到其他节点
                                        // if (workflowReactFlowInstance) {
                                        //   workflowReactFlowInstance.fitView({ padding: 0.2, duration: 300, nodes: [nextNode] });
                                        // }
                                      }, 100);
                                      message.success(t('common.nodeConfigSaved'));
                                    } else {
                                      // 所有节点都已完成，调用检查接口
                                      if (workflowWorkId) {
                                        try {
                                          const checkResponse = await workJobApi.checkWorkById(workflowWorkId);
                                          const checkData = (checkResponse as any)?.data || checkResponse;
                                          const errorMessages = Array.isArray(checkData) ? checkData : (checkData ? [checkData] : []);
                                          
                                          // 如果返回的错误信息数组为空或null，表示所有节点配置完毕
                                          if (!errorMessages || errorMessages.length === 0) {
                                            message.success(t('common.allNodeConfigCompleted'));
                                          } else {
                                            // 有错误信息，显示弹框
                                            Modal.warning({
                                              title: t('common.nodeConfigIncomplete'),
                                              width: 500,
                                              content: (
                                                <div style={{ marginTop: 16 }}>
                                                  <p style={{ marginBottom: 12, color: '#666' }}>{t('common.nodeConfigIncompleteText')}</p>
                                                  <ul style={{ margin: 0, paddingLeft: 20 }}>
                                                    {errorMessages.map((msg: string, index: number) => (
                                                      <li key={index} style={{ marginBottom: 8, color: '#ff4d4f' }}>
                                                        {msg}
                                                      </li>
                                                    ))}
                                                  </ul>
                                                </div>
                                              ),
                                              okText: t('common.iKnow'),
                                            });
                                          }
                                          } catch (error: any) {
                                          console.error('检查作业失败:', error);
                                          message.error(error?.message || t('common.checkWorkFailed'));
                                        }
                                      } else {
                                        message.success(t('common.allNodeConfigCompleted'));
                                      }
                                    }
                                  } catch (error: any) {
                                    console.error('保存节点配置失败:', error);
                                    message.error(error?.message || t('common.saveFailed'));
                                  }
                                }}
                              >
                                {t('isolationWork.saveCurrentNode')}
                              </Button>
                            </div>
                          )}
                        </div>
                      ) : (
                        <div className="p-4">
                          <div className="text-sm text-gray-600">
                            {t('isolationWork.selectNodeToConfigure')}
                          </div>
                        </div>
                      )}
                    </div>
                  </div>
                )}

                {workJobStep === 2 && (
                  <Form
                    form={workJobPublishForm}
                    layout="vertical"
                    className="max-w-2xl"
                  >
                    <div className="mb-4">
                      <h3 className="text-base font-medium text-gray-900 mb-2">{t('isolationWork.publishSettingsTitle')}</h3>
                      <p className="text-sm text-gray-500">{t('isolationWork.publishSettingsDesc')}</p>
                    </div>

                    <Form.Item
                      label={t('isolationWork.publishMethod')}
                      name="startType"
                      required
                      rules={[{ required: true, message: t('isolationWork.publishMethodRequired') }]}
                      initialValue="0"
                    >
                      <Radio.Group disabled={isViewMode}>
                        <Radio value="0">{t('isolationWork.publishNow')}</Radio>
                        <Radio value="1">{t('isolationWork.publishScheduled')}</Radio>
                      </Radio.Group>
                    </Form.Item>

                    <Form.Item
                      noStyle
                      shouldUpdate={(prevValues, currentValues) => 
                        prevValues.startType !== currentValues.startType
                      }
                    >
                      {({ getFieldValue }) => 
                        getFieldValue('startType') === '1' ? (
                          <Form.Item
                            label={t('isolationWork.publishTime')}
                            name="planTime"
                            required
                            rules={[{ required: true, message: t('isolationWork.publishTimeRequired') }]}
                          >
                            <DatePicker
                              showTime
                              format="YYYY-MM-DD HH:mm:ss"
                              className="w-full"
                              placeholder={t('isolationWork.publishTimePlaceholder')}
                              disabled={isViewMode}
                            />
                          </Form.Item>
                        ) : null
                      }
                    </Form.Item>
                  </Form>
                )}
              </div>

              {/* 底部按钮 */}
              <div className="px-6 py-4 border-t border-gray-200 flex justify-center gap-2">
                {workJobStep === 0 && (
                  <>
                    <Button onClick={() => {
                      setShowAddModal(false);
                      setIsViewMode(false);
                      setWorkJobStep(0);
                      workJobBasicForm.resetFields();
                      workJobPublishForm.resetFields();
                      setWorkflowJson(null);
                      setWorkflowWorkId(null); // 清空作业ID
                      // 清空流程管理相关状态
                      setWorkflowNodes([]);
                      setWorkflowEdges([]);
                      setSelectedWorkflowNode(null);
                      setWorkflowNodeConfigCache(new Map());
                      setCompletedNodeIds(new Set());
                      setNodeSavedStatusCache(new Map());
                      setWorkflowWorkNodeDOList([]); // 清空节点数据列表
                      setOriginalBasicFormData(null); // 清空原始表单数据
                      // 关闭弹框时刷新列表
                      getWorkJobList();
                    }}>
                      {isViewMode ? t('common.close') : t('common.cancel')}
                    </Button>
                    {!isViewMode ? (
                      <Button
                        type="primary"
                        onClick={async () => {
                          try {
                            // 验证必填项
                            const values = await workJobBasicForm.validateFields();
                            
                            // 判断是新增还是更新
                            let currentWorkId: number | null = null;
                            if (workflowWorkId) {
                              // 已有ID，判断是否有修改
                              // 如果 originalBasicFormData 为 null，说明是新增后第一次返回，需要从服务器获取最新数据进行比较
                              let hasChanges = false;
                              if (originalBasicFormData) {
                                // 有原始数据，直接比较
                                hasChanges = (
                                  originalBasicFormData.workflowTemplate !== values.workflowTemplate ||
                                  originalBasicFormData.jobCategory !== values.jobCategory ||
                                  originalBasicFormData.jobName !== values.jobName ||
                                  originalBasicFormData.jobContent !== values.jobContent ||
                                  originalBasicFormData.urgency !== values.urgency
                                );
                              } else {
                                // 没有原始数据，从服务器获取最新数据进行比较
                                try {
                                  const detailResponse = await workJobApi.selectWorkflowWorkById(workflowWorkId);
                                  const detail = detailResponse as any;
                                  const currentFormData = {
                                    workflowTemplate: values.workflowTemplate,
                                    jobCategory: values.jobCategory,
                                    jobName: values.jobName,
                                    jobContent: values.jobContent,
                                    urgency: values.urgency,
                                  };
                                  const serverData = {
                                    workflowTemplate: detail.designId || detail.workflowTemplate,
                                    jobCategory: detail.type || detail.jobCategory,
                                    jobName: detail.name || detail.jobName,
                                    jobContent: detail.description || detail.jobContent,
                                    urgency: detail.urgencyLevel || detail.urgency,
                                  };
                                  hasChanges = (
                                    serverData.workflowTemplate !== currentFormData.workflowTemplate ||
                                    serverData.jobCategory !== currentFormData.jobCategory ||
                                    serverData.jobName !== currentFormData.jobName ||
                                    serverData.jobContent !== currentFormData.jobContent ||
                                    serverData.urgency !== currentFormData.urgency
                                  );
                                  // 设置原始数据为服务器数据
                                  setOriginalBasicFormData(serverData);
                                } catch (error: any) {
                                  console.error('获取作业详情失败:', error);
                                  // 如果获取失败，假设有变化，调用更新接口
                                  hasChanges = true;
                                }
                              }
                              
                              if (hasChanges) {
                                // 有修改，调用更新接口
                                await workJobApi.updateWorkflowWork({
                                  id: workflowWorkId, // 作业票ID
                                  name: values.jobName, // 作业名称
                                  type: values.jobCategory, // 作业分类
                                  designId: values.workflowTemplate, // 流程设计ID
                                  description: values.jobContent, // 作业内容
                                  urgencyLevel: values.urgency, // 紧急程度
                                });
                                message.success(t('common.basicInfoUpdateSuccess'));
                                // 更新原始数据
                                setOriginalBasicFormData({
                                  workflowTemplate: values.workflowTemplate,
                                  jobCategory: values.jobCategory,
                                  jobName: values.jobName,
                                  jobContent: values.jobContent,
                                  urgency: values.urgency,
                                });
                              }
                              // 无论是否有修改，都使用当前的 workflowWorkId
                              currentWorkId = workflowWorkId;
                            } else {
                              // 没有ID，调用新增接口
                              const response = await workJobApi.insertWorkflowWork({
                                name: values.jobName, // 作业名称
                                type: values.jobCategory, // 作业分类
                                designId: values.workflowTemplate, // 流程设计ID
                                description: values.jobContent, // 作业内容
                                urgencyLevel: values.urgency, // 紧急程度
                              });
                              
                              // 保存返回的作业ID
                              // 响应格式: { code: 0, data: 13, msg: "" }
                              // axios拦截器可能已经处理了数据格式，直接使用response
                              const responseData = response as any;
                              // 尝试多种方式获取ID
                              const workId = responseData?.data || responseData?.id || (typeof responseData === 'number' ? responseData : null);
                              if (workId) {
                                currentWorkId = Number(workId);
                                setWorkflowWorkId(currentWorkId);
                                console.log('保存作业ID:', workId);
                              }
                              
                              // 新增成功后，设置原始表单数据，用于后续判断是否有修改
                              setOriginalBasicFormData({
                                workflowTemplate: values.workflowTemplate,
                                jobCategory: values.jobCategory,
                                jobName: values.jobName,
                                jobContent: values.jobContent,
                                urgency: values.urgency,
                              });
                              
                              message.success(t('common.basicInfoSaveSuccess'));
                            }
                            
                            // 成功后进入下一步
                            setWorkJobStep(1);
                            
                            // 注意：节点状态初始化会在 useEffect 中自动执行（当 workJobStep === 1 且 workflowWorkId 存在时）
                            // 这里不需要手动加载，让 useEffect 统一处理
                          } catch (error: any) {
                            if (error.errorFields) {
                              // 表单验证失败
                              message.error(t('common.pleaseCompleteRequiredFields'));
                            } else {
                              // API调用失败
                              message.error(error?.message || t('common.saveFailed'));
                            }
                          }
                        }}
                      >
                        {t('common.next')}
                      </Button>
                    ) : (
                      <Button
                        type="primary"
                        onClick={() => setWorkJobStep(1)}
                      >
                        {t('common.next')}
                      </Button>
                    )}
                  </>
                )}
                {workJobStep === 1 && (
                  <div className="flex flex-col items-center w-full gap-2">
                    <div className="flex items-center gap-2">
                      <Button onClick={() => setWorkJobStep(0)}>
                        {t('common.previous')}
                      </Button>
                      {!isViewMode && (
                        <>
                      <div className="flex items-center gap-2">
                        <Button
                          type="primary"
                          disabled={hasUnsavedNodes}
                          className={!hasUnsavedNodes ? 'next-step-button-focus' : ''}
                          onClick={async () => {
                          // 调用检查接口，检查是否有未保存的节点
                          if (!workflowWorkId) {
                            message.warning(t('common.workIdNotExistsForCheck'));
                            return;
                          }
                          
                          try {
                            const checkResponse = await workJobApi.checkWorkById(workflowWorkId);
                            const checkData = (checkResponse as any)?.data || checkResponse;
                            const errorMessages = Array.isArray(checkData) ? checkData : (checkData ? [checkData] : []);
                            
                            // 如果返回的错误信息数组为空或null，表示所有节点配置完毕，可以进入下一个tab
                            if (!errorMessages || errorMessages.length === 0) {
                              message.success(t('common.allNodeConfigCompleted'));
                              // 进入下一个tab
                              setWorkJobStep(2);
                            } else {
                              // 有错误信息，显示弹框，不能进入下一个tab
                              Modal.warning({
                                title: t('common.nodeConfigIncomplete'),
                                width: 500,
                                content: (
                                  <div style={{ marginTop: 16 }}>
                                    <p style={{ marginBottom: 12, color: '#666' }}>{t('common.nodeConfigIncompleteText')}</p>
                                    <ul style={{ margin: 0, paddingLeft: 20 }}>
                                      {errorMessages.map((msg: string, index: number) => (
                                        <li key={index} style={{ marginBottom: 8, color: '#ff4d4f' }}>
                                          {msg}
                                        </li>
                                      ))}
                                    </ul>
                                  </div>
                                ),
                                okText: t('common.iKnow'),
                              });
                            }
                          } catch (error: any) {
                            console.error('检查作业失败:', error);
                            message.error(error?.message || t('common.checkWorkFailed'));
                          }
                        }}
                      >
                        {t('common.next')}
                      </Button>
                      {!hasUnsavedNodes && (
                        <img 
                          src={new URL('../assets/finger.png', import.meta.url).href}
                          alt={t('common.next')}
                          className="pointer-hint-icon"
                          style={{
                            width: '32px',
                            height: '32px',
                            animation: 'pointing 1.5s ease-in-out infinite',
                            display: 'inline-block',
                            cursor: 'pointer',
                            marginLeft: '8px',
                            objectFit: 'contain'
                          }}
                        />
                      )}
                      <style>{`
                        @keyframes focusPulse {
                          0%, 100% {
                            box-shadow: 0 0 0 0 rgba(22, 119, 255, 0.7);
                            transform: scale(1);
                          }
                          50% {
                            box-shadow: 0 0 0 10px rgba(22, 119, 255, 0);
                            transform: scale(1.05);
                          }
                        }
                        .next-step-button-focus {
                          animation: focusPulse 2s ease-in-out infinite;
                        }
                        @keyframes pointing {
                          0%, 100% {
                            transform: translateX(0);
                          }
                          25% {
                            transform: translateX(-4px);
                          }
                          50% {
                            transform: translateX(0);
                          }
                          75% {
                            transform: translateX(4px);
                          }
                        }
                        .pointer-hint-icon {
                          cursor: pointer;
                        }
                      `}</style>
                    </div>
                    {/* <Button
                      type="default"
                      onClick={async () => {
                        if (!workflowWorkId) {
                          message.warning(t('common.workIdNotExistsForCheck'));
                          return;
                        }
                        
                        try {
                          const checkResponse = await workJobApi.checkWorkById(workflowWorkId);
                          const checkData = (checkResponse as any)?.data || checkResponse;
                          const errorMessages = Array.isArray(checkData) ? checkData : (checkData ? [checkData] : []);
                          
                          // 如果返回的错误信息数组为空或null，表示所有节点配置完毕，可以跳转
                          if (!errorMessages || errorMessages.length === 0) {
                            message.success(t('common.allNodeConfigCompleted'));
                            // 延迟一下再跳转，让用户看到成功提示
                            setTimeout(() => {
                              setWorkJobStep(2);
                            }, 500);
                          } else {
                            // 有错误信息，显示弹框，不跳转
                            Modal.warning({
                              title: t('common.nodeConfigIncomplete'),
                              width: 500,
                              content: (
                                <div style={{ marginTop: 16 }}>
                                  <p style={{ marginBottom: 12, color: '#666' }}>{t('common.nodeConfigIncompleteText')}</p>
                                  <ul style={{ margin: 0, paddingLeft: 20 }}>
                                    {errorMessages.map((msg: string, index: number) => (
                                      <li key={index} style={{ marginBottom: 8, color: '#ff4d4f' }}>
                                        {msg}
                                      </li>
                                    ))}
                                  </ul>
                                </div>
                              ),
                              okText: t('common.iKnow'),
                            });
                          }
                        } catch (error: any) {
                          console.error('检查作业失败:', error);
                          message.error(error?.message || t('common.checkWorkFailed'));
                        }
                      }}
                    >
                      一键保存
                    </Button> */}
                        </>
                      )}
                      {isViewMode && (
                        <Button
                          type="primary"
                          onClick={() => setWorkJobStep(2)}
                        >
                          {t('common.next')}
                        </Button>
                      )}
                    </div>
                    <div className="flex items-center text-red-600" style={{ fontSize: '12px' }}>
                      <span className="mr-1">⚠️</span>
                      <span>{t('isolationWork.nextStepHint')}</span>
                    </div>
                  </div>
                )}
                {workJobStep === 2 && (
                  <>
                    <Button onClick={() => setWorkJobStep(1)}>
                      {t('common.previous')}
                    </Button>
                    {!isViewMode ? (
                    <Button
                      type="primary"
                      icon={<Play className="w-4 h-4" />}
                      onClick={async () => {
                        try {
                          const publishValues = await workJobPublishForm.validateFields();
                          
                          if (!workflowWorkId) {
                            message.error(t('common.workIdNotExists'));
                            return;
                          }
                          
                          // 构建发布参数
                          const updateStartWorkParam: UpdateStartWorkParam = {
                            workId: Number(workflowWorkId), // 确保是 number 类型
                            startType: publishValues.startType || '0', // 0-立即发布 1-定时发布
                          };
                          
                          // 如果是定时发布，需要传递发布时间
                          if (publishValues.startType === '1') {
                            if (!publishValues.planTime) {
                              message.error(t('common.scheduledPublishTimeRequired'));
                              return;
                            }
                            
                            // 将 DatePicker 返回的 dayjs 对象转换为字符串格式 (YYYY-MM-DD HH:mm:ss)
                            const planTime = publishValues.planTime;
                            if (planTime && typeof planTime.format === 'function') {
                              // dayjs 对象
                              updateStartWorkParam.planTime = planTime.format('YYYY-MM-DD HH:mm:ss');
                            } else if (planTime instanceof Date) {
                              // Date 对象
                              const year = planTime.getFullYear();
                              const month = String(planTime.getMonth() + 1).padStart(2, '0');
                              const day = String(planTime.getDate()).padStart(2, '0');
                              const hours = String(planTime.getHours()).padStart(2, '0');
                              const minutes = String(planTime.getMinutes()).padStart(2, '0');
                              const seconds = String(planTime.getSeconds()).padStart(2, '0');
                              updateStartWorkParam.planTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
                            } else if (typeof planTime === 'string') {
                              // 字符串格式
                              updateStartWorkParam.planTime = planTime;
                            } else {
                              message.error(t('common.publishTimeFormatError'));
                              return;
                            }
                          }
                          
                          console.log('发布作业参数:', updateStartWorkParam);
                          
                          // 调用发布作业接口
                          await workJobApi.updateStartWork(updateStartWorkParam);
                          
                          message.success(t('common.publishWorkSuccess'));
                          setShowAddModal(false);
                          setWorkJobStep(0);
                          workJobBasicForm.resetFields();
                          workJobPublishForm.resetFields();
                          setWorkflowJson(null);
                          setWorkflowWorkId(null); // 清空作业ID
                          // 清空流程管理相关状态
                          setWorkflowNodes([]);
                          setWorkflowEdges([]);
                          setSelectedWorkflowNode(null);
                          setWorkflowNodeConfigCache(new Map());
                          setCompletedNodeIds(new Set());
                          // 清除节点保存状态缓存
                          setNodeSavedStatusCache(new Map());
                          // 关闭弹框时刷新列表
                          getWorkJobList();
                        } catch (error: any) {
                          if (error.errorFields) {
                            return;
                          }
                          console.error('发布作业失败:', error);
                          message.error(error?.message || t('common.publishWorkFailed'));
                        }
                      }}
                    >
                      {t('isolationWork.confirmPublish')}
                    </Button>
                    ) : (
                      <Button onClick={() => {
                        setShowAddModal(false);
                        setIsViewMode(false);
                        setWorkJobStep(0);
                        workJobBasicForm.resetFields();
                        workJobPublishForm.resetFields();
                        setWorkflowJson(null);
                        setWorkflowWorkId(null);
                        setWorkflowNodes([]);
                        setWorkflowEdges([]);
                        setSelectedWorkflowNode(null);
                        setWorkflowNodeConfigCache(new Map());
                        setCompletedNodeIds(new Set());
                        setNodeSavedStatusCache(new Map());
                        setWorkflowWorkNodeDOList([]);
                        setOriginalBasicFormData(null);
                        getWorkJobList();
                      }}>
                        {t('common.close')}
                      </Button>
                    )}
                  </>
                )}
              </div>
            </div>
          </Modal>
        ) : null}

        {/* 编辑作业弹窗（保持原有逻辑） */}
        {subMenu === '作业管理' && showAddModal && editingItem ? (
          <Modal
            title={t('common.editWork')}
            open={showAddModal}
            onCancel={() => {
              setShowAddModal(false);
              setEditingItem(null);
              form.resetFields();
            }}
            footer={[
              <Button key="cancel" onClick={() => {
                setShowAddModal(false);
                setEditingItem(null);
                form.resetFields();
              }}>
                {t('common.cancel')}
              </Button>,
              <Button key="submit" type="primary" onClick={async () => {
                try {
                  const values = await form.validateFields();
                  await workJobApi.updateWorkflowWork({
                      id: editingItem.id!,
                      name: values.name,
                    type: values.type || editingItem.type || '',
                    designId: values.designId || editingItem.designId || editingItem.workflowDesignId || 0,
                    description: values.content || '',
                    urgencyLevel: values.urgencyLevel || editingItem.urgencyLevel || '',
                    });
                    message.success(t('common.updateWorkSuccess'));
                  setShowAddModal(false);
                  setEditingItem(null);
                  form.resetFields();
                  getWorkJobList();
                } catch (error: any) {
                  if (error.errorFields) {
                    return;
                  }
                  console.error('更新作业失败:', error);
                  message.error(error?.message || t('common.updateWorkFailed'));
                }
              }}>
                {t('common.confirm')}
              </Button>
            ]}
            width={600}
            destroyOnClose
            styles={{
              footer: {
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                padding: '16px 24px'
              }
            }}
          >
            <Form
              form={form}
              labelCol={{ span: 4 }}
              wrapperCol={{ span: 20 }}
              key={editingItem?.id || 'new'}
            >
              <Form.Item
                label={t('common.workName')}
                name="name"
                rules={[{ required: true, message: t('common.workNameRequired') }]}
              >
                <Input placeholder={t('common.workNamePlaceholder')} />
              </Form.Item>
              <Form.Item
                label={t('common.workContent')}
                name="content"
              >
                <Input.TextArea rows={4} placeholder={t('common.workContentPlaceholder')} />
              </Form.Item>
            </Form>
          </Modal>
        ) : null}
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* 表格容器 - 合并工具栏和列表 */}
      <div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm overflow-hidden">
        {/* 工具栏 */}
        <div className="p-4 border-b border-gray-200/50">
          <div className="flex items-center justify-between">
            <div className="relative w-80">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
              <input
                type="text"
                placeholder={subMenu === '流程模板' ? t('form.searchTemplate') : `搜索${subMenu}...`}
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="w-full h-10 pl-10 pr-4 bg-gray-50 border border-gray-200 rounded-xl outline-none focus:border-blue-400 focus:ring-4 focus:ring-blue-100 transition-all text-sm"
              />
            </div>

            <button
              onClick={() => {
                setEditingItem(null);
                setShowAddModal(true);
              }}
              className="flex items-center gap-2 px-4 py-2.5 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-xl hover:shadow-lg hover:shadow-blue-400/40 transition-all duration-300"
            >
              <Plus className="w-4 h-4" strokeWidth={2.5} />
              <span className="text-sm">
                {subMenu === '流程模板' && t('common.addTemplate')}
                {subMenu === 'SOP管理' && '新增SOP'}
                {subMenu === '作业管理' && t('common.addWork')}
              </span>
            </button>
          </div>
        </div>

        {/* 表格 */}
        <div className="overflow-x-auto">
          <table className="w-full">
            <thead>
              <tr className="bg-gradient-to-r from-gray-50 to-gray-100/50 border-b border-gray-200">
                <th className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider" style={{ width: '5%' }}>
                  {t('common.serialNumber')}
                </th>
                {columns.map((column) => (
                  <th
                    key={column.key}
                    className="px-6 py-4 text-left text-xs text-gray-600 uppercase tracking-wider"
                    style={{ width: column.width }}
                  >
                    {column.label}
                  </th>
                ))}
                <th className="px-6 py-4 text-center text-xs text-gray-600 uppercase tracking-wider" style={{ width: '10%' }}>
                  {t('table.operation')}
                </th>
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-100">
              {filteredData.map((row, index) => (
                <tr
                  key={row.id}
                  className={`transition-colors hover:bg-blue-50/30 ${index % 2 === 1 ? 'bg-[#f0f0f0]' : 'bg-white'}`}
                >
                  <td className="px-6 py-4 text-sm text-gray-900">
                    {index + 1}
                  </td>
                  {columns.map((column) => (
                    <td key={column.key} className="px-6 py-4 text-sm text-gray-900">
                      {column.key === 'status' ? (
                        <span
                          className={`inline-flex px-3 py-1 rounded-lg text-xs ${
                            row[column.key] === '启用' || row[column.key] === '有效' || row[column.key] === '已完成'
                              ? 'bg-green-100 text-green-700'
                              : row[column.key] === '待审批' || row[column.key] === '待审核'
                              ? 'bg-orange-100 text-orange-700'
                              : row[column.key] === '进行中'
                              ? 'bg-blue-100 text-blue-700'
                              : 'bg-gray-100 text-gray-700'
                          }`}
                        >
                          {row[column.key]}
                        </span>
                      ) : column.key === 'priority' ? (
                        <span
                          className={`inline-flex px-3 py-1 rounded-lg text-xs ${
                            row[column.key] === '紧急'
                              ? 'bg-red-100 text-red-700'
                              : row[column.key] === '重要'
                              ? 'bg-orange-100 text-orange-700'
                              : 'bg-blue-100 text-blue-700'
                          }`}
                        >
                          {row[column.key]}
                        </span>
                      ) : (
                        row[column.key]
                      )}
                    </td>
                  ))}
                  <td className="px-6 py-4">
                    <div className="flex items-center justify-center gap-2">
                      <Button
                        variant="ghost"
                        size="sm"
                        className="h-8 px-2"
                      >
                        <Eye className="w-4 h-4" />
                        <span className="ml-1">{t('table.view')}</span>
                      </Button>
                      <Button
                        variant="ghost"
                        size="sm"
                        onClick={() => handleEdit(row)}
                        className="h-8 px-2"
                      >
                        <Edit2 className="w-4 h-4" />
                        <span className="ml-1">{t('common.edit')}</span>
                      </Button>
                      <Button
                        variant="ghost"
                        size="sm"
                        onClick={() => handleDelete(row.id)}
                        className="h-8 px-2 text-red-600 hover:text-red-700"
                      >
                        <Trash2 className="w-4 h-4" />
                        <span className="ml-1">{t('common.delete')}</span>
                      </Button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

      </div>

      {/* 分页 */}
      {filteredData.length > 0 && (
        <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
          <div className="flex items-center justify-between">
            <div className="text-sm text-gray-600">
              {t('common.total')} <span className="text-blue-600 font-medium">{filteredData.length}</span> {t('common.records')}
            </div>
            <div className="flex gap-2">
              <Button
                disabled={true}
              >
                {t('common.prevPage')}
              </Button>
              <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
                1 / 1
              </span>
              <Button
                disabled={true}
              >
                {t('common.nextPage')}
              </Button>
            </div>
          </div>
        </div>
      )}

      {/* 新增/编辑弹窗 */}
      {showAddModal && (
        <div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 animate-in fade-in duration-200">
          <div className="bg-white rounded-2xl shadow-2xl w-full max-w-3xl mx-4 max-h-[90vh] overflow-y-auto animate-in zoom-in duration-200">
            {/* 弹窗标题 */}
            <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between sticky top-0 bg-white z-10">
              <h3 className="text-lg text-gray-900">
                {editingItem 
                  ? (subMenu === '流程模板' ? t('common.editTemplate') : subMenu === 'SOP管理' ? '编辑SOP' : subMenu === '作业管理' ? t('common.editWork') : subMenu === '表单管理' ? t('common.editFormManagement') : subMenu === '流程设计' ? t('common.editProcessDesign') : t('common.edit'))
                  : (subMenu === '流程模板' ? t('common.addTemplateTitle') : subMenu === 'SOP管理' ? '新增SOP' : subMenu === '作业管理' ? t('common.addWork') : subMenu === '表单管理' ? t('common.addFormManagement') : subMenu === '流程设计' ? t('common.addProcessDesign') : t('common.addNew'))
                }
              </h3>
              <button
                onClick={() => setShowAddModal(false)}
                className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
              >
                <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            </div>

            {/* 弹窗内容 */}
            <div className="px-6 py-6">
              {getFormFields()}
            </div>

            {/* 弹窗底部 */}
            <div className="px-6 py-4 bg-gray-50/50 border-t border-gray-200 flex justify-end gap-3 rounded-b-2xl">
              <button
                onClick={() => setShowAddModal(false)}
                className="px-5 py-2.5 text-sm text-gray-600 bg-white border border-gray-200 rounded-xl hover:bg-gray-50 transition-colors"
              >
                {t('common.cancel')}
              </button>
              <button
                onClick={() => {
                  console.log('保存:', editingItem);
                  setShowAddModal(false);
                }}
                className="px-5 py-2.5 text-sm text-white bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl hover:shadow-lg hover:shadow-blue-400/40 transition-all"
              >
                {editingItem ? t('common.saveChanges') : t('common.confirm')}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* 查看详情弹框（只读模式，三个tab） */}
      <Modal
        title={null}
        open={showViewModal}
        onCancel={() => {
          setShowViewModal(false);
          setViewWorkDetailData(null);
          setViewWorkJobStep(0);
          viewWorkJobBasicForm.resetFields();
          viewWorkJobPublishForm.resetFields();
          setViewWorkflowJson(null);
        }}
        footer={null}
        width={1400}
        destroyOnClose
        styles={{
          body: { padding: 0 }
        }}
      >
        <div className="flex flex-col h-[80vh]">
          {/* Tab导航 */}
          <div className="px-6 py-4 bg-white">
            <Tabs
              activeKey={String(viewWorkJobStep)}
              onChange={(key) => {
                // 查看模式下可以自由切换tab
                setViewWorkJobStep(Number(key));
              }}
              items={[
                {
                  key: '0',
                  label: (
                    <span className="flex items-center gap-2">
                      <FileText className="w-4 h-4" />
                      基本信息
                    </span>
                  ),
                },
                {
                  key: '1',
                  label: (
                    <span className="flex items-center gap-2">
                      <Workflow className="w-4 h-4" />
                      流程管理
                    </span>
                  ),
                },
                {
                  key: '2',
                  label: (
                    <span className="flex items-center gap-2">
                      <Play className="w-4 h-4" />
                      发布作业
                    </span>
                  ),
                },
              ]}
            />
          </div>

          {/* Tab内容 */}
          <div className="flex-1 overflow-y-auto px-6 py-4 bg-white">
            {viewWorkJobStep === 0 && (
              <div className="flex justify-center">
                <Form
                  form={viewWorkJobBasicForm}
                  layout="vertical"
                  className="max-w-2xl w-full"
                >
                  <Form.Item
                    label="流程模板"
                    name="workflowTemplate"
                  >
                    <Select 
                      disabled
                      placeholder="请选择流程模板"
                      options={workflowTemplateList
                        .filter(item => item.status === 1)
                        .map(item => ({
                          label: item.name,
                          value: item.id,
                        }))}
                    />
                  </Form.Item>

                  <Form.Item
                    label="作业分类"
                    name="jobCategory"
                  >
                    <Select disabled placeholder="请选择作业分类">
                      {workTypeDictList.map((item) => (
                        <Select.Option key={item.id} value={item.value}>
                          {item.label}
                        </Select.Option>
                      ))}
                    </Select>
                  </Form.Item>

                  <Form.Item
                    label="作业名称"
                    name="jobName"
                  >
                    <Input disabled placeholder="请输入作业名称" />
                  </Form.Item>

                  <Form.Item
                    label="作业内容"
                    name="jobContent"
                  >
                    <Input.TextArea 
                      disabled
                      rows={4} 
                      placeholder="请输入作业内容"
                      showCount
                      maxLength={500}
                    />
                  </Form.Item>

                  <Form.Item
                    label="紧急程度"
                    name="urgency"
                  >
                    <Radio.Group disabled>
                      {urgencyLevelDictList.length > 0 ? (
                        urgencyLevelDictList.map((item) => (
                          <Radio key={item.id} value={item.value}>
                            {item.label}
                          </Radio>
                        ))
                      ) : (
                        <span className="text-gray-400 text-sm">加载中...</span>
                      )}
                    </Radio.Group>
                  </Form.Item>
                </Form>
              </div>
            )}

            {viewWorkJobStep === 1 && (
              <div className="flex items-center justify-center h-full text-gray-400">
                {viewWorkflowJson ? '流程管理视图（只读模式）' : '暂无流程设计数据'}
              </div>
            )}

            {viewWorkJobStep === 2 && (
              <Form
                form={viewWorkJobPublishForm}
                layout="vertical"
                className="max-w-2xl"
              >
                <div className="mb-4">
                  <h3 className="text-base font-medium text-gray-900 mb-2">{t('isolationWork.publishSettingsTitle')}</h3>
                  <p className="text-sm text-gray-500">{t('isolationWork.publishSettingsDesc')}</p>
                </div>

                <Form.Item
                  label={t('isolationWork.publishMethod')}
                  name="startType"
                >
                  <Radio.Group disabled>
                    <Radio value="0">{t('isolationWork.publishNow')}</Radio>
                    <Radio value="1">{t('isolationWork.publishScheduled')}</Radio>
                  </Radio.Group>
                </Form.Item>

                <Form.Item
                  noStyle
                  shouldUpdate={(prevValues, currentValues) => 
                    prevValues.startType !== currentValues.startType
                  }
                >
                  {({ getFieldValue }) => 
                    getFieldValue('startType') === '1' ? (
                      <Form.Item
                        label={t('isolationWork.publishTime')}
                        name="planTime"
                      >
                        <DatePicker
                          disabled
                          showTime
                          format="YYYY-MM-DD HH:mm:ss"
                          className="w-full"
                          placeholder={t('isolationWork.publishTimePlaceholder')}
                        />
                      </Form.Item>
                    ) : null
                  }
                </Form.Item>
              </Form>
            )}
          </div>

          {/* 底部按钮 */}
          <div className="px-6 py-4 border-t border-gray-200 flex justify-end gap-2">
            <Button onClick={() => {
              setShowViewModal(false);
              setViewWorkDetailData(null);
              setViewWorkJobStep(0);
              viewWorkJobBasicForm.resetFields();
              viewWorkJobPublishForm.resetFields();
              setViewWorkflowJson(null);
            }}>
              {t('common.close')}
            </Button>
          </div>
        </div>
      </Modal>
    </div>
  );
}