import React, { useState, useEffect, useCallback, useRef } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { 
  User, 
  CheckCircle2, 
  Settings, 
  FileText, 
  Lock, 
  Flag, 
  Star,
  ArrowLeft,
  Clock,
  List,
  Plus,
  Minus,
  Loader2,
  Unlock,
  Users,
} from 'lucide-react';
import { Timeline, Badge, Card, Collapse, Tag, Descriptions, Button } from 'antd';
import { CheckCircleOutlined, ClockCircleOutlined, SyncOutlined } from '@ant-design/icons';
import ReactFlow, {
  Node,
  Edge,
  useNodesState,
  useEdgesState,
  Controls,
  Background,
  BackgroundVariant,
  NodeTypes,
  ConnectionMode,
  Handle,
  Position,
} from 'reactflow';
import { sharedFlowEdgeTypes } from './FlowEdge';
import { getLayoutedNodes, shouldApplyLayout } from '../utils/flowLayout';
import 'reactflow/dist/style.css';
import { workJobApi, WorkJobVO, WorkflowWorkNodeDO } from '../api/WorkJob';
import { formatDateWithFormat } from '../utils/formatTime';
import { dictDataApi, DictDataVO } from '../api/DictData';
import { userApi } from '../api/user';
import { workflowDesignApi } from '../api/WorkflowDesign';
import { getFormPage } from '../api/bpm/form';
import { segregationPointApi } from '../api/spm';
import { Select, Input, Checkbox, Tabs, Tooltip } from 'antd';
import { useTranslation } from 'react-i18next';
import {
  isWorkflowCoLockType,
  isWorkflowIsolationSchemePanelType,
  isWorkflowLockSchemeType,
  isWorkflowUnlockCoLockType,
  isWorkflowUnlockParentMatch,
  isWorkflowUnlockSchemeType,
} from '../utils/workflowNodeTypes';

interface WorkflowStep {
  id: string;
  type: string;
  title: string;
  assignee?: string;
  assigneeName?: string;
  time?: string;
  status: 'completed' | 'in_progress' | 'pending';
  icon: React.ReactNode;
  hasDetail?: boolean;
}

// 流程节点数据结构
interface WorkflowNode {
  uuid: string;
  nodeName: string;
  type: string;
  status: 'completed' | 'in_progress' | 'pending';
  workNode: WorkflowWorkNodeDO;
  children: WorkflowNode[];
  isBranch: boolean; // 是否为分支节点（有多个子节点）
  branchNodes?: WorkflowNode[]; // 分支节点列表
}

// 使用 import.meta.glob 动态导入所有图标（用于节点显示）
const iconModulesForNode = (import.meta as any).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 SimpleCustomNode({ data, selected, id }: any) {
  const { t } = useTranslation();
  const nodeId = data.nodeId || (id ? String(parseInt(id.split('-').pop() || '0') % 1000).padStart(3, '0') : '001');
  
  // 获取节点状态
  const status: 'completed' | 'in_progress' | 'pending' = data.status || 'pending';
  
  // 根据状态设置边框颜色和样式
  let borderClass = 'border-gray-400';
  let borderStyle: React.CSSProperties = { borderWidth: '3px' };
  let shadowStyle: React.CSSProperties = {};
  
  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 (status === 'completed') {
      // 已完成：绿色边框
      borderClass = 'border-green-500';
      borderStyle = { borderWidth: '3px' };
      shadowStyle = { boxShadow: '0 0 0 1px rgba(34, 197, 94, 0.1)' };
    } else if (status === 'in_progress') {
      // 进行中：蓝色边框
      borderClass = 'border-blue-500';
      borderStyle = { borderWidth: '3px' };
      shadowStyle = { boxShadow: '0 0 0 1px rgba(59, 130, 246, 0.1)' };
    } else {
      // 待执行：灰色边框
      borderClass = 'border-gray-400';
      borderStyle = { borderWidth: '3px' };
      shadowStyle = {};
    }
  }
  
  // 获取状态显示文本
  const getStatusText = (s: 'completed' | 'in_progress' | 'pending'): string => {
    switch (s) {
      case 'completed':
        return t('workJobDetail.completed');
      case 'in_progress':
        return t('workJobDetail.inProgress');
      case 'pending':
        return t('workJobDetail.statusPending');
      default:
        return t('workJobDetail.statusPending');
    }
  };
  
  // 获取状态文字颜色
  const getStatusTextColor = (status: 'completed' | 'in_progress' | 'pending'): string => {
    switch (status) {
      case 'completed':
        return 'text-green-600';
      case 'in_progress':
        return 'text-blue-600';
      case 'pending':
        return 'text-gray-500';
      default:
        return 'text-gray-500';
    }
  };
  
  // 优先使用 icon 字段获取图标路径
  let iconImagePath: string | null = null;
  if (data.icon && /^\d+\.png$/.test(data.icon)) {
    // 是图片文件名，获取对应的图片路径
    iconImagePath = getIconPathByFileName(data.icon);
  }
  
  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={false}
      />
      <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={false}
      />
      <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={false}
      />
      <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={false}
      />
      <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={false}
      />
      <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={false}
      />
      <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={false}
      />
      <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={false}
      />
      
      <div className="flex flex-col items-center justify-between gap-3 h-full">
        <div className="bg-gray-50 border border-gray-100 p-3 rounded-xl shadow-sm flex items-center justify-center flex-shrink-0" 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';
              }}
            />
          ) : (
            getNodeIcon(data.type || 'createJob', status)
          )}
        </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 || data.nodeName || t('workJobDetail.node')}
        </div>
        <div className="text-xs text-gray-500 text-center flex-shrink-0">
          ID: {nodeId}
        </div>
        {/* 状态显示 */}
        <div className={`text-xs font-medium text-center flex-shrink-0 ${getStatusTextColor(status)}`}>
          {getStatusText(status)}
        </div>
      </div>
    </div>
  );
}

// 节点类型映射
const nodeTypes: NodeTypes = {
  createJob: SimpleCustomNode,
  confirm: SimpleCustomNode,
  review: SimpleCustomNode,
  inputInfo: SimpleCustomNode,
  lock: SimpleCustomNode,
  isolation: SimpleCustomNode,
  unlock: SimpleCustomNode,
  releaseIsolation: SimpleCustomNode,
  coLock: SimpleCustomNode,
  unlockCoLock: SimpleCustomNode,
  returnLock: SimpleCustomNode,
  complete: SimpleCustomNode,
};

// 获取节点图标
const getNodeIcon = (type: string, status: 'completed' | 'in_progress' | 'pending') => {
  const iconClass = status === 'completed' 
    ? 'text-green-600' 
    : status === 'in_progress' 
    ? 'text-blue-600' 
    : 'text-gray-400';
  
  switch (type) {
    case 'createJob':
      return <CheckCircle2 className={`w-5 h-5 ${iconClass}`} />;
    case 'review':
    case 'confirm':
      return <Settings className={`w-5 h-5 ${iconClass}`} />;
    case 'inputInfo':
      return <FileText className={`w-5 h-5 ${iconClass}`} />;
    case 'lock':
    case 'isolation':
      return <Lock className={`w-5 h-5 ${iconClass}`} />;
    case 'unlock':
    case 'releaseIsolation':
      return <Unlock className={`w-5 h-5 ${iconClass}`} />;
    case 'coLock':
      return <Users className={`w-5 h-5 ${iconClass}`} />;
    case 'unlockCoLock':
      return <Unlock className={`w-5 h-5 ${iconClass}`} />;
    case 'returnLock':
      return <Lock className={`w-5 h-5 ${iconClass}`} />;
    case 'complete':
      return <Flag className={`w-5 h-5 ${iconClass}`} />;
    default:
      return <FileText className={`w-5 h-5 ${iconClass}`} />;
  }
};

// 获取状态图标（圆形指示器）
const getStatusIcon = (status: 'completed' | 'in_progress' | 'pending') => {
  if (status === 'completed') {
    return (
      <div className="w-6 h-6 rounded-full bg-green-500 flex items-center justify-center flex-shrink-0">
        <CheckCircle2 className="w-4 h-4 text-white" />
      </div>
    );
  } else if (status === 'in_progress') {
    return (
      <div className="w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center flex-shrink-0">
        <Loader2 className="w-4 h-4 text-white animate-spin" />
      </div>
    );
  } else {
    return (
      <div className="w-6 h-6 rounded-full border-2 border-gray-300 flex items-center justify-center flex-shrink-0">
        <div className="w-2 h-2 rounded-full bg-gray-300" />
      </div>
    );
  }
};

// 获取节点状态（根据 approvalStatus 字段直接映射）
const getNodeStatus = (workNode: WorkflowWorkNodeDO, nodeMap: Map<string, WorkflowWorkNodeDO>): 'completed' | 'in_progress' | 'pending' => {
  if (!workNode) return 'pending';
  
  const approvalStatus = workNode.approvalStatus;
  
  // 处理字符串类型的 approvalStatus
  if (typeof approvalStatus === 'string') {
    const statusStr = approvalStatus.toLowerCase();
    if (statusStr === 'approved') {
      return 'completed';
    } else if (statusStr === 'running' || statusStr === 'in_progress') {
      return 'in_progress';
    } else if (statusStr === 'pending' || statusStr === 'unaudited') {
      // 对于 pending/unaudited，需要判断是否可以执行（父节点是否已完成）
      if (!workNode.parentUuid || workNode.parentUuid === '') {
        // 没有父节点，可能是第一个节点，状态为已完成
        return 'completed';
      }
      // 检查父节点状态
      const parentUuids = workNode.parentUuid.split(',').map(u => u.trim()).filter(u => u);
      const allParentsCompleted = parentUuids.every(parentUuid => {
        const parentNode = nodeMap.get(parentUuid);
        return parentNode && (parentNode.approvalStatus === 'approved' || parentNode.approvalStatus === 'Approved');
      });
      return allParentsCompleted ? 'in_progress' : 'pending';
    } else {
      return 'pending';
    }
  } 
  // 处理数字类型的 approvalStatus
  else if (typeof approvalStatus === 'number') {
    // 假设：1-待执行，2-进行中，3-已完成
    if (approvalStatus === 3) {
      return 'completed';
    } else if (approvalStatus === 2) {
      return 'in_progress';
    } else {
      return 'pending';
    }
  }
  
  // 默认状态为待执行
  return 'pending';
};

// 工作流渲染组件
interface WorkflowRendererProps {
  nodeList: WorkflowWorkNodeDO[];
  expandedBranchGroups: Set<string>;
  setExpandedBranchGroups: React.Dispatch<React.SetStateAction<Set<string>>>;
  getExecutorInfo: (workNode: WorkflowWorkNodeDO, type: string) => string;
  getNodeIcon: (type: string, status: 'completed' | 'in_progress' | 'pending') => React.ReactNode;
  formatDate: (date: string | number | Date) => string;
  approvalStatusDictList: DictDataVO[];
  getNodeStatusFromDict: (
    approvalStatus: string | number | null | undefined,
    approvalStatusDictList: DictDataVO[],
    workNode: WorkflowWorkNodeDO | undefined,
    nodeMap: Map<string, WorkflowWorkNodeDO>
  ) => 'completed' | 'in_progress' | 'pending';
}

const WorkflowRenderer: React.FC<WorkflowRendererProps> = ({
  nodeList,
  expandedBranchGroups,
  setExpandedBranchGroups,
  getExecutorInfo,
  getNodeIcon,
  formatDate,
  approvalStatusDictList,
  getNodeStatusFromDict,
}) => {
  // 用于控制节点依次渲染的状态
  const [visibleNodes, setVisibleNodes] = useState<Set<string>>(new Set());
  
  useEffect(() => {
    // 重置可见节点
    setVisibleNodes(new Set());
    
    // 依次显示节点，每个节点延迟 200ms
    const timers: NodeJS.Timeout[] = [];
    
    const sortedNodes = [...nodeList].sort((a, b) => {
      const aId = a.id || 0;
      const bId = b.id || 0;
      if (aId !== bId) return aId - bId;
      const aTime = a.createTime ? new Date(a.createTime).getTime() : 0;
      const bTime = b.createTime ? new Date(b.createTime).getTime() : 0;
      return aTime - bTime;
    });
    
    sortedNodes.forEach((node, index) => {
      const timer = setTimeout(() => {
        setVisibleNodes(prev => new Set([...prev, node.uuid || String(node.id || index)]));
      }, index * 200 + 100);
      timers.push(timer);
    });
    
    return () => {
      timers.forEach(timer => clearTimeout(timer));
    };
  }, [nodeList]);
  // 按 parentUuid 分组，找出同父节点的子节点
  const branchGroups = new Map<string, WorkflowWorkNodeDO[]>();
  nodeList.forEach((node) => {
    if (node.parentUuid) {
      if (!branchGroups.has(node.parentUuid)) {
        branchGroups.set(node.parentUuid, []);
      }
      branchGroups.get(node.parentUuid)!.push(node);
    }
  });

  // 调试：打印所有分组信息
  console.log('=== 节点分组信息 ===');
  branchGroups.forEach((children, parentUuid) => {
    console.log(`父节点 ${parentUuid} 有 ${children.length} 个子节点:`, children.map(c => ({ uuid: c.uuid, nodeName: c.nodeName })));
  });

  // 对每个分支组进行排序（按id或创建时间）
  branchGroups.forEach((children, parentUuid) => {
    children.sort((a, b) => {
      const aId = a.id || 0;
      const bId = b.id || 0;
      if (aId !== bId) return aId - bId;
      const aTime = a.createTime ? new Date(a.createTime).getTime() : 0;
      const bTime = b.createTime ? new Date(b.createTime).getTime() : 0;
      return aTime - bTime;
    });
  });

  // 找出有多个子节点的父节点（需要显示分支的）
  const parentNodesWithBranches = new Set<string>();
  branchGroups.forEach((children, parentUuid) => {
    if (children.length > 1) {
      parentNodesWithBranches.add(parentUuid);
    }
  });

  // 构建节点映射，方便查找父节点
  const nodeMap = new Map<string, WorkflowWorkNodeDO>();
  nodeList.forEach((node) => {
    if (node.uuid) {
      nodeMap.set(node.uuid, node);
    }
  });

  // 构建主流程节点列表
  // 逻辑：先找到头节点（创建作业节点）和尾节点（完成/结束节点）
  // 从尾节点往头节点找路径，或者从头节点往尾节点找，选择中间的路径
  // 其余相同父亲节点的全部显示到加号折叠起来的地方去，不出现在主轴上
  const mainFlowNodes: (WorkflowWorkNodeDO & { isBranchParent?: boolean; branchNodes?: WorkflowWorkNodeDO[]; branchParentUuid?: string; mainNodeUuid?: string })[] = [];
  const mainPathNodes = new Set<string>(); // 记录主路径上的节点

  // 构建子节点映射（按parentUuid分组）
  const childrenMap = new Map<string, WorkflowWorkNodeDO[]>();
  nodeList.forEach((node) => {
    if (node.parentUuid) {
      // 处理多个父节点的情况（用逗号分隔）
      const parentUuids = node.parentUuid.split(',').map(u => u.trim()).filter(u => u);
      parentUuids.forEach(parentUuid => {
        if (!childrenMap.has(parentUuid)) {
          childrenMap.set(parentUuid, []);
        }
        childrenMap.get(parentUuid)!.push(node);
      });
    }
  });

  // 对每个父节点的子节点进行排序（按id或创建时间）
  childrenMap.forEach((children, parentUuid) => {
    children.sort((a, b) => {
      const aId = a.id || 0;
      const bId = b.id || 0;
      if (aId !== bId) return aId - bId;
      const aTime = a.createTime ? new Date(a.createTime).getTime() : 0;
      const bTime = b.createTime ? new Date(b.createTime).getTime() : 0;
      return aTime - bTime;
    });
  });

  // 递归收集分支节点的所有后代节点（不在主路径上的）
  const collectAllBranchDescendants = (branchNode: WorkflowWorkNodeDO, collected: Set<string>): WorkflowWorkNodeDO[] => {
    const result: WorkflowWorkNodeDO[] = [branchNode];
    collected.add(branchNode.uuid || '');
    
    // 递归收集所有子节点
    const children = childrenMap.get(branchNode.uuid || '') || [];
    children.forEach(child => {
      if (!mainPathNodes.has(child.uuid || '') && !collected.has(child.uuid || '')) {
        result.push(...collectAllBranchDescendants(child, collected));
      }
    });
    
    return result;
  };

  // 计算节点的分支数量（包括所有后代节点）
  const countBranchNodes = (node: WorkflowWorkNodeDO, visited: Set<string> = new Set()): number => {
    if (visited.has(node.uuid || '')) {
      return 0;
    }
    visited.add(node.uuid || '');
    
    const children = childrenMap.get(node.uuid || '') || [];
    let count = children.length;
    
    children.forEach(child => {
      count += countBranchNodes(child, visited);
    });
    
    return count;
  };

  // 找到头节点（创建作业节点）
  const findHeadNode = (): WorkflowWorkNodeDO | null => {
    // 先找type为'createJob'的节点
    let headNode = nodeList.find(node => 
      node.type === 'createJob' || 
      (node.nodeName && (node.nodeName.includes('创建') || node.nodeName.includes('创建作业')))
    );
    
    // 如果没找到，找没有parentUuid的节点
    if (!headNode) {
      const rootNodes = nodeList.filter((node) => !node.parentUuid || node.parentUuid === '');
      if (rootNodes.length > 0) {
        rootNodes.sort((a, b) => {
          const aId = a.id || 0;
          const bId = b.id || 0;
          if (aId !== bId) return aId - bId;
          const aTime = a.createTime ? new Date(a.createTime).getTime() : 0;
          const bTime = b.createTime ? new Date(b.createTime).getTime() : 0;
          return aTime - bTime;
        });
        headNode = rootNodes[0];
      }
    }
    
    return headNode || null;
  };

  // 找到尾节点（完成/结束节点）
  const findTailNode = (): WorkflowWorkNodeDO | null => {
    return nodeList.find(node => 
      node.type === 'complete' || 
      (node.nodeName && node.nodeName === '完成/结束')
    ) || null;
  };

  // 从尾节点向上找路径到头节点
  const buildPathFromTail = (tailNode: WorkflowWorkNodeDO, headNode: WorkflowWorkNodeDO): WorkflowWorkNodeDO[] => {
    const path: WorkflowWorkNodeDO[] = [tailNode];
    mainPathNodes.add(tailNode.uuid || '');
    
    let currentNode = tailNode;
    const visited = new Set<string>([tailNode.uuid || '']);
    
    while (currentNode && currentNode.uuid !== headNode.uuid) {
      // 获取父节点（可能有多个，用逗号分隔）
      if (currentNode.parentUuid) {
        const parentUuids = currentNode.parentUuid.split(',').map(u => u.trim()).filter(u => u);
        
        // 如果有多个父节点，选择分支数量最少的那个
        let nextNode: WorkflowWorkNodeDO | null = null;
        if (parentUuids.length === 1) {
          nextNode = nodeMap.get(parentUuids[0]) || null;
        } else {
          // 多个父节点，计算每个父节点的分支数量，选择分支最少的
          const parentNodes = parentUuids
            .map(uuid => nodeMap.get(uuid))
            .filter(node => node && !visited.has(node.uuid || '')) as WorkflowWorkNodeDO[];
          
          if (parentNodes.length > 0) {
            // 计算每个父节点的分支数量
            const parentBranchCounts = parentNodes.map(parent => {
              const children = childrenMap.get(parent.uuid || '') || [];
              // 排除当前节点，计算其他子节点的分支数量
              const otherChildren = children.filter(child => child.uuid !== currentNode.uuid);
              let branchCount = otherChildren.length;
              otherChildren.forEach(child => {
                branchCount += countBranchNodes(child, new Set());
              });
              return { node: parent, branchCount };
            });
            
            // 选择分支数量最少的父节点
            parentBranchCounts.sort((a, b) => a.branchCount - b.branchCount);
            nextNode = parentBranchCounts[0].node;
          }
        }
        
        if (nextNode && !visited.has(nextNode.uuid || '')) {
          visited.add(nextNode.uuid || '');
          mainPathNodes.add(nextNode.uuid || '');
          path.unshift(nextNode); // 从头部插入，保持从头到尾的顺序
          currentNode = nextNode;
        } else {
          break;
        }
      } else {
        break;
      }
    }
    
    return path;
  };

  // 从头节点向下找路径到尾节点（选择分支数量最少的子节点）
  const buildPathFromHead = (headNode: WorkflowWorkNodeDO, tailNode: WorkflowWorkNodeDO): WorkflowWorkNodeDO[] => {
    const path: WorkflowWorkNodeDO[] = [headNode];
    mainPathNodes.add(headNode.uuid || '');
    
    let currentNode = headNode;
    const visited = new Set<string>([headNode.uuid || '']);
    
    while (currentNode && currentNode.uuid !== tailNode.uuid) {
      const children = childrenMap.get(currentNode.uuid || '') || [];
      
      if (children.length === 0) {
        break;
      } else if (children.length === 1) {
        // 只有一个子节点，直接使用
        const nextNode = children[0];
        if (!visited.has(nextNode.uuid || '')) {
          visited.add(nextNode.uuid || '');
          mainPathNodes.add(nextNode.uuid || '');
          path.push(nextNode);
          currentNode = nextNode;
        } else {
          break;
        }
      } else {
        // 多个子节点，选择分支数量最少的那个
        const availableChildren = children.filter(child => !visited.has(child.uuid || ''));
        
        if (availableChildren.length === 0) {
          break;
        }
        
        // 计算每个子节点的分支数量
        const childBranchCounts = availableChildren.map(child => {
          const childChildren = childrenMap.get(child.uuid || '') || [];
          let branchCount = childChildren.length;
          childChildren.forEach(grandChild => {
            branchCount += countBranchNodes(grandChild, new Set());
          });
          return { node: child, branchCount };
        });
        
        // 选择分支数量最少的子节点
        childBranchCounts.sort((a, b) => a.branchCount - b.branchCount);
        const nextNode = childBranchCounts[0].node;
        
        if (!visited.has(nextNode.uuid || '')) {
          visited.add(nextNode.uuid || '');
          mainPathNodes.add(nextNode.uuid || '');
          path.push(nextNode);
          currentNode = nextNode;
        } else {
          break;
        }
      }
    }
    
    return path;
  };

  // 找到头节点和尾节点
  const headNode = findHeadNode();
  const tailNode = findTailNode();

  console.log('头节点:', headNode ? { uuid: headNode.uuid, nodeName: headNode.nodeName } : '未找到');
  console.log('尾节点:', tailNode ? { uuid: tailNode.uuid, nodeName: tailNode.nodeName } : '未找到');

  if (headNode && tailNode) {
    // 从尾节点向上找路径
    const pathFromTail = buildPathFromTail(tailNode, headNode);
    
    // 如果从尾节点找不到完整路径，从头节点向下找
    let mainPath: WorkflowWorkNodeDO[] = [];
    if (pathFromTail.length > 0 && pathFromTail[0].uuid === headNode.uuid) {
      mainPath = pathFromTail;
    } else {
      mainPath = buildPathFromHead(headNode, tailNode);
      // 如果路径中没有尾节点，添加尾节点
      if (mainPath.length > 0 && mainPath[mainPath.length - 1].uuid !== tailNode.uuid) {
        mainPath.push(tailNode);
        mainPathNodes.add(tailNode.uuid || '');
      }
    }

    console.log('主路径节点数量:', mainPath.length);
    console.log('主路径:', mainPath.map(n => ({ uuid: n.uuid, nodeName: n.nodeName })));

    // 构建主流程节点列表，处理分支
    mainPath.forEach((node, index) => {
      const children = childrenMap.get(node.uuid || '') || [];
      const branchChildren = children.filter(child => !mainPathNodes.has(child.uuid || ''));
      
      if (branchChildren.length > 0) {
        // 有分支节点，收集所有分支节点及其后代
        const allBranchNodes: WorkflowWorkNodeDO[] = [];
        const collected = new Set<string>();
        branchChildren.forEach(child => {
          allBranchNodes.push(...collectAllBranchDescendants(child, collected));
        });

        mainFlowNodes.push({
          ...node,
          isBranchParent: true,
          branchNodes: allBranchNodes,
          branchParentUuid: node.uuid || '',
        });
      } else {
        // 没有分支节点
        mainFlowNodes.push(node);
      }
    });
  } else {
    // 如果找不到头节点或尾节点，使用原来的逻辑
    console.warn('未找到头节点或尾节点，使用备用逻辑');
    const rootNodes = nodeList.filter((node) => !node.parentUuid || node.parentUuid === '');
    if (rootNodes.length > 0) {
      rootNodes.sort((a, b) => {
        const aId = a.id || 0;
        const bId = b.id || 0;
        if (aId !== bId) return aId - bId;
        const aTime = a.createTime ? new Date(a.createTime).getTime() : 0;
        const bTime = b.createTime ? new Date(b.createTime).getTime() : 0;
        return aTime - bTime;
      });
      
      // 使用中间节点策略
      const buildMainPath = (currentNode: WorkflowWorkNodeDO) => {
        if (mainPathNodes.has(currentNode.uuid || '')) {
          return;
        }

        mainPathNodes.add(currentNode.uuid || '');
        const children = childrenMap.get(currentNode.uuid || '') || [];
        
        if (children.length === 0) {
          mainFlowNodes.push(currentNode);
          return;
        }

        if (children.length === 1) {
          mainFlowNodes.push(currentNode);
          buildMainPath(children[0]);
        } else {
          // 选择分支数量最少的子节点
          const childBranchCounts = children.map(child => {
            const childChildren = childrenMap.get(child.uuid || '') || [];
            let branchCount = childChildren.length;
            childChildren.forEach(grandChild => {
              branchCount += countBranchNodes(grandChild, new Set());
            });
            return { node: child, branchCount };
          });
          
          // 选择分支数量最少的子节点
          childBranchCounts.sort((a, b) => a.branchCount - b.branchCount);
          const mainChild = childBranchCounts[0].node;
          const otherChildren = childBranchCounts.slice(1).map(item => item.node);

          const allBranchNodes: WorkflowWorkNodeDO[] = [];
          const collected = new Set<string>();
          otherChildren.forEach(child => {
            if (!mainPathNodes.has(child.uuid || '')) {
              allBranchNodes.push(...collectAllBranchDescendants(child, collected));
            }
          });

          mainFlowNodes.push({
            ...currentNode,
            isBranchParent: true,
            branchNodes: allBranchNodes,
            branchParentUuid: currentNode.uuid || '',
          });

          buildMainPath(mainChild);
        }
      };
      
      buildMainPath(rootNodes[0]);
    }
  }

  // 验证所有节点是否都被包含（用于调试）
  const allNodeUuids = new Set(nodeList.map(n => n.uuid || '').filter(uuid => uuid));
  const includedNodeUuids = new Set<string>();
  mainFlowNodes.forEach(node => {
    includedNodeUuids.add(node.uuid || '');
    if (node.branchNodes) {
      node.branchNodes.forEach(branchNode => {
        includedNodeUuids.add(branchNode.uuid || '');
      });
    }
  });
  
  // 检查是否有遗漏的节点
  const missingNodes = nodeList.filter(node => {
    const uuid = node.uuid || '';
    return uuid && !includedNodeUuids.has(uuid);
  });
  
  if (missingNodes.length > 0) {
    console.warn('发现遗漏的节点:', missingNodes.map(n => ({ uuid: n.uuid, nodeName: n.nodeName, parentUuid: n.parentUuid })));
    
    // 将遗漏的节点添加到对应父节点的分支中
    missingNodes.forEach(node => {
      if (node.parentUuid) {
        const parentNode = nodeMap.get(node.parentUuid);
        if (parentNode) {
          // 检查父节点是否在主路径上
          if (mainPathNodes.has(parentNode.uuid || '')) {
            // 父节点在主路径上，直接添加到该节点的分支列表
            const mainFlowNodeIndex = mainFlowNodes.findIndex(n => n.uuid === parentNode.uuid);
            if (mainFlowNodeIndex >= 0) {
              const mainFlowNode = mainFlowNodes[mainFlowNodeIndex];
              const existingBranchNodes = mainFlowNode.branchNodes || [];
              
              // 检查节点是否已经在分支列表中
              if (!existingBranchNodes.some(n => n.uuid === node.uuid)) {
                // 收集这个节点及其所有后代节点
                const collected = collectAllBranchDescendants(node, new Set());
                const newBranchNodes = [...existingBranchNodes];
                collected.forEach(n => {
                  if (!newBranchNodes.find(existing => existing.uuid === n.uuid)) {
                    newBranchNodes.push(n);
                  }
                });
                
                mainFlowNodes[mainFlowNodeIndex] = {
                  ...mainFlowNode,
                  isBranchParent: true,
                  branchNodes: newBranchNodes,
                  branchParentUuid: parentNode.uuid || '',
                };
              }
            }
          } else {
            // 父节点不在主路径上，需要在所有分支节点列表中查找父节点
            // 遍历所有主流程节点，查找包含父节点的分支列表
            for (let i = 0; i < mainFlowNodes.length; i++) {
              const mainFlowNode = mainFlowNodes[i];
              if (mainFlowNode.branchNodes) {
                // 检查父节点是否在这个分支列表中
                const parentInBranch = mainFlowNode.branchNodes.find(n => n.uuid === parentNode.uuid);
                if (parentInBranch) {
                  // 找到父节点，添加遗漏节点及其后代
                  const existingBranchNodes = mainFlowNode.branchNodes;
                  if (!existingBranchNodes.some(n => n.uuid === node.uuid)) {
                    const collected = collectAllBranchDescendants(node, new Set());
                    const newBranchNodes = [...existingBranchNodes];
                    collected.forEach(n => {
                      if (!newBranchNodes.find(existing => existing.uuid === n.uuid)) {
                        newBranchNodes.push(n);
                      }
                    });
                    
                    mainFlowNodes[i] = {
                      ...mainFlowNode,
                      branchNodes: newBranchNodes,
                    };
                  }
                  break; // 找到后退出循环
                }
              }
            }
          }
        }
      }
    });
  }

  console.log('=== 最终主流程节点 ===');
  mainFlowNodes.forEach((node, index) => {
    console.log(`${index + 1}. ${node.nodeName} (${node.uuid})`, node.isBranchParent ? `[有分支: ${node.branchNodes?.length || 0}个]` : '');
  });

  // 切换分支展开/收起
  const toggleBranchGroup = (parentUuid: string) => {
    setExpandedBranchGroups((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(parentUuid)) {
        newSet.delete(parentUuid);
      } else {
        newSet.add(parentUuid);
      }
      return newSet;
    });
  };

  // 获取 Timeline 的颜色
  const getTimelineColor = (status: 'completed' | 'in_progress' | 'pending') => {
    if (status === 'completed') return 'green';
    if (status === 'in_progress') return 'blue';
    return 'gray';
  };

  // 获取 Timeline 的图标
  const getTimelineDot = (status: 'completed' | 'in_progress' | 'pending') => {
    if (status === 'completed') {
      return (
        <div style={{ 
          width: '28px', 
          height: '28px',
          minWidth: '28px',
          minHeight: '28px',
          maxWidth: '28px',
          maxHeight: '28px',
          backgroundColor: '#52c41a', 
          borderRadius: '50%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          boxShadow: '0 0 0 4px rgba(82, 196, 26, 0.15), 0 0 0 8px rgba(82, 196, 26, 0.08)',
          boxSizing: 'border-box',
          flexShrink: 0
        }}>
          <CheckCircleOutlined style={{ fontSize: '20px', color: 'white', display: 'block' }} />
        </div>
      );
    }
    if (status === 'in_progress') {
      return (
        <div style={{ 
          width: '28px', 
          height: '28px',
          minWidth: '28px',
          minHeight: '28px',
          maxWidth: '28px',
          maxHeight: '28px',
          backgroundColor: '#1890ff', 
          borderRadius: '50%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          boxShadow: '0 0 0 4px rgba(24, 144, 255, 0.15), 0 0 0 8px rgba(24, 144, 255, 0.08)',
          boxSizing: 'border-box',
          flexShrink: 0
        }}>
          <SyncOutlined spin style={{ fontSize: '20px', color: 'white', display: 'block' }} />
        </div>
      );
    }
    return (
      <div style={{ 
        width: '28px', 
        height: '28px',
        minWidth: '28px',
        minHeight: '28px',
        maxWidth: '28px',
        maxHeight: '28px',
        backgroundColor: '#d9d9d9', 
        borderRadius: '50%',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        boxShadow: '0 0 0 4px rgba(217, 217, 217, 0.15), 0 0 0 8px rgba(217, 217, 217, 0.08)',
        boxSizing: 'border-box',
        flexShrink: 0
      }}>
        <ClockCircleOutlined style={{ fontSize: '20px', color: 'white', display: 'block' }} />
      </div>
    );
  };

  // 构建 Timeline 数据
  const timelineItems = mainFlowNodes.map((node, index) => {
    // 根据字典判断节点状态
    const status = getNodeStatusFromDict(node.approvalStatus, approvalStatusDictList, node, nodeMap);

    const executorInfo = getExecutorInfo(node, node.type || '');
    const time = node.createTime || node.updateTime;
    
    // 获取分支节点列表（所有不在主路径上的兄弟节点）
    const branchNodes = node.isBranchParent && node.branchNodes 
      ? node.branchNodes.filter(branchNode => !mainPathNodes.has(branchNode.uuid || ''))
      : [];
    
    // 只有当有分支节点时才显示展开按钮
    const isBranchParent = node.isBranchParent && branchNodes.length > 0;
    const branchParentUuid = (node as any).branchParentUuid || node.parentUuid || node.uuid || '';
    const isExpanded = isBranchParent && expandedBranchGroups.has(branchParentUuid);
    const nodeKey = node.uuid || String(node.id || index);
    const isVisible = visibleNodes.has(nodeKey);

    // 构建分支节点内容
    const branchContent = isBranchParent && isExpanded && branchNodes.length > 0 ? (
      <div className="mt-3 space-y-2" style={{ width: '100%' }}>
        {branchNodes.map((branchNode, branchIndex) => {
          // 根据字典判断分支节点状态
          const branchStatus = getNodeStatusFromDict(branchNode.approvalStatus, approvalStatusDictList, branchNode, nodeMap);

          const branchExecutorInfo = getExecutorInfo(branchNode, branchNode.type || '');
          const branchTime = branchNode.createTime || branchNode.updateTime;

          return (
            <div
              key={branchNode.uuid || branchNode.id || branchIndex}
              className={`mb-2 p-3 rounded-lg border shadow-md transition-all duration-300 hover:shadow-lg ${
                branchStatus === 'completed' 
                  ? 'bg-emerald-50 border-emerald-200' 
                  : branchStatus === 'in_progress' 
                  ? 'bg-sky-50 border-sky-200' 
                  : 'bg-gray-50 border-gray-200'
              }`}
              style={{
                animationName: isVisible ? 'fadeInUp' : 'none',
                animationDuration: isVisible ? '0.5s' : '0s',
                animationTimingFunction: isVisible ? 'ease-out' : 'ease',
                animationDelay: `${(index * 200 + branchIndex * 100) / 1000}s`,
                maxWidth: '240px',
              }}
            >
              <div className="flex items-start gap-2">
                <div className="flex-shrink-0 mt-0.5">
                  {getNodeIcon(branchNode.type || '', branchStatus)}
                </div>
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-1.5 mb-1.5">
                    <span className={`font-semibold text-xs ${
                      branchStatus === 'pending' ? 'text-gray-500' : 'text-gray-900'
                    }`}>
                      {branchNode.nodeName || t('workJobDetail.unknownNode')}
                    </span>
                    <Tag 
                      color={getTimelineColor(branchStatus)}
                      className="text-xs"
                    >
                      {branchStatus === 'completed' ? t('workJobDetail.completed') : branchStatus === 'in_progress' ? t('workJobDetail.inProgress') : t('workJobDetail.pending')}
                    </Tag>
                  </div>
                  {branchExecutorInfo && (
                    <div className={`text-xs ml-6 mb-1 ${
                      branchStatus === 'pending' ? 'text-gray-400' : 'text-gray-600'
                    }`}>
                      {branchExecutorInfo}
                    </div>
                  )}
                  {branchTime && (
                    <div className="text-xs text-gray-500 ml-6 flex items-center">
                      <Clock className="w-2.5 h-2.5 mr-1" />
                      {formatDate(branchTime)}
                    </div>
                  )}
                </div>
              </div>
            </div>
          );
        })}
      </div>
    ) : null;

    return {
      key: nodeKey,
      dot: getTimelineDot(status),
      color: undefined,
      children: (
        <div 
          className={`transition-all duration-500 ${
            isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'
          }`}
          style={{
            animationName: isVisible ? 'fadeInUp' : 'none',
            animationDuration: isVisible ? '0.5s' : '0s',
            animationTimingFunction: isVisible ? 'ease-out' : 'ease',
            animationDelay: `${index * 200 / 1000}s`,
          }}
        >
          <div 
            className={`mb-3 p-4 rounded-lg border shadow-md transition-all duration-300 hover:shadow-lg ${
              status === 'completed' 
                ? 'bg-emerald-50 border-emerald-200' 
                : status === 'in_progress' 
                ? 'bg-sky-50 border-sky-200' 
                : 'bg-gray-50 border-gray-200'
            }`}
            style={{ 
              maxWidth: '100%', 
              width: '100%',
            }}
          >
            <div className="flex items-start justify-between gap-3">
              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-2 mb-2">
                  <div className="flex-shrink-0">
                    {getNodeIcon(node.type || '', status)}
                  </div>
                  <span className={`font-semibold text-sm ${
                    status === 'pending' ? 'text-gray-500' : 'text-gray-900'
                  }`}>
{node.nodeName || t('workJobDetail.unknownNode')}
                    </span>
                    <Tag 
                      color={getTimelineColor(status)}
                      className="text-xs"
                    >
                      {status === 'completed' ? t('workJobDetail.completed') : status === 'in_progress' ? t('workJobDetail.inProgress') : t('workJobDetail.pending')}
                  </Tag>
                </div>
                {executorInfo && (
                  <div className={`text-xs ml-7 mb-1.5 ${
                    status === 'pending' ? 'text-gray-400' : 'text-gray-600'
                  }`}>
                    {executorInfo}
                  </div>
                )}
                {time && (
                  <div className="text-xs text-gray-500 ml-7 flex items-center">
                    <Clock className="w-3 h-3 mr-1" />
                    {formatDate(time)}
                  </div>
                )}
              </div>
              
              {/* 分支展开按钮 */}
              {isBranchParent && (
                <button
                  onClick={() => toggleBranchGroup(branchParentUuid)}
                  className="flex items-center justify-center w-6 h-6 rounded hover:bg-gray-100 transition-colors flex-shrink-0"
                  title={isExpanded ? t('workJobDetail.collapseBranch') : t('workJobDetail.expandBranch')}
                >
                  {isExpanded ? (
                    <Minus className="w-3.5 h-3.5 text-gray-600" />
                  ) : (
                    <Plus className="w-3.5 h-3.5 text-gray-600" />
                  )}
                </button>
              )}
            </div>
          </div>
          {branchContent}
        </div>
      ),
    };
  });

  return (
    <div className="workflow-timeline">
      <style>{`
        @keyframes fadeInUp {
          from {
            opacity: 0;
            transform: translateY(20px);
          }
          to {
            opacity: 1;
            transform: translateY(0);
          }
        }
        .workflow-timeline .ant-timeline-item-content {
          min-height: 60px;
          max-width: 45%;
        }
        .workflow-timeline .ant-timeline-item-left .ant-timeline-item-content {
          text-align: right;
          padding-right: 24px;
        }
        .workflow-timeline .ant-timeline-item-left .ant-timeline-item-content > div {
          display: inline-block;
          text-align: left;
          width: 100%;
          max-width: 280px;
        }
        .workflow-timeline .ant-timeline-item-right .ant-timeline-item-content {
          text-align: left;
          padding-left: 24px;
        }
        .workflow-timeline .ant-timeline-item-right .ant-timeline-item-content > div {
          display: inline-block;
          text-align: left;
          width: 100%;
          max-width: 280px;
        }
        .workflow-timeline .ant-timeline-item-tail {
          border-left: 3px solid #1890ff;
        }
        .workflow-timeline .ant-timeline-item-head {
          width: 14px;
          height: 14px;
          border-width: 0;
          background-color: #1890ff;
          border-radius: 50%;
          box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.1);
        }
        .workflow-timeline .ant-timeline-item-head-green {
          width: 28px !important;
          height: 28px !important;
          min-width: 28px !important;
          min-height: 28px !important;
          max-width: 28px !important;
          max-height: 28px !important;
          background-color: #52c41a !important;
          border-radius: 50% !important;
          border: none !important;
          box-shadow: 0 0 0 4px rgba(82, 196, 26, 0.15), 0 0 0 8px rgba(82, 196, 26, 0.08) !important;
          display: flex !important;
          align-items: center !important;
          justify-content: center !important;
          box-sizing: border-box !important;
          flex-shrink: 0 !important;
          padding: 0 !important;
        }
        .workflow-timeline .ant-timeline-item-head-green .anticon,
        .workflow-timeline .ant-timeline-item-head-green svg {
          color: white !important;
          fill: white !important;
          font-size: 20px !important;
          width: 20px !important;
          height: 20px !important;
        }
        .workflow-timeline .ant-timeline-item-head-blue {
          width: 28px !important;
          height: 28px !important;
          min-width: 28px !important;
          min-height: 28px !important;
          max-width: 28px !important;
          max-height: 28px !important;
          background-color: #1890ff !important;
          border-radius: 50% !important;
          border: none !important;
          box-shadow: 0 0 0 4px rgba(24, 144, 255, 0.15), 0 0 0 8px rgba(24, 144, 255, 0.08) !important;
          display: flex !important;
          align-items: center !important;
          justify-content: center !important;
          box-sizing: border-box !important;
          flex-shrink: 0 !important;
          padding: 0 !important;
        }
        .workflow-timeline .ant-timeline-item-head-blue .anticon,
        .workflow-timeline .ant-timeline-item-head-blue svg {
          color: white !important;
          fill: white !important;
          font-size: 20px !important;
          width: 20px !important;
          height: 20px !important;
        }
        .workflow-timeline .ant-timeline-item-head-gray {
          width: 28px !important;
          height: 28px !important;
          min-width: 28px !important;
          min-height: 28px !important;
          max-width: 28px !important;
          max-height: 28px !important;
          background-color: #d9d9d9 !important;
          border-radius: 50% !important;
          border: none !important;
          box-shadow: 0 0 0 4px rgba(217, 217, 217, 0.15), 0 0 0 8px rgba(217, 217, 217, 0.08) !important;
          display: flex !important;
          align-items: center !important;
          justify-content: center !important;
          box-sizing: border-box !important;
          flex-shrink: 0 !important;
          padding: 0 !important;
        }
        .workflow-timeline .ant-timeline-item-head-gray .anticon,
        .workflow-timeline .ant-timeline-item-head-gray svg {
          color: white !important;
          fill: white !important;
          font-size: 20px !important;
          width: 20px !important;
          height: 20px !important;
        }
      `}</style>
      {/* 时间线内容已注释 */}
      {/* <Timeline
        mode="alternate"
        items={timelineItems}
        className="custom-timeline"
      /> */}
    </div>
  );
};

// 节点信息面板组件
interface NodeInfoPanelProps {
  node: Node;
  workflowWorkNodeDOList: WorkflowWorkNodeDO[];
  formList: any[];
  drawerUsers: any[];
  lockerUsers: any[];
  colockerUsers: any[];
  isolationTypeDictList: DictDataVO[];
  isolationPoints: any[];
  userNameMap: Map<number | string, string>;
}

const NodeInfoPanel: React.FC<NodeInfoPanelProps> = ({
  node,
  workflowWorkNodeDOList,
  formList,
  drawerUsers,
  lockerUsers,
  colockerUsers,
  isolationTypeDictList,
  isolationPoints,
  userNameMap,
}) => {
  const { t } = useTranslation();
  // 找到对应的 workflowWorkNodeDO
  const workNode = workflowWorkNodeDOList.find(n => n.uuid === node.id);
  const nodeData = node.data || {};
  
  // 如果是解除隔离节点，需要从对应的隔离方案节点获取数据
  let isolationNodeData: any = null;
  if (isWorkflowUnlockSchemeType(nodeData.type) || isWorkflowUnlockCoLockType(nodeData.type)) {
    // 优先使用从隔离方案节点复制的数据（在 loadDesignContentToReactFlow 中已处理）
    isolationNodeData = nodeData.isolationNodeData;
    
    // 如果没有复制的数据，尝试从 isolationNodeUuid 查找对应的隔离方案节点
    if (!isolationNodeData) {
      const isolationNodeUuid = workNode?.isolationNodeUuid || nodeData.isolationNodeUuid || '';
      if (isolationNodeUuid) {
        const isolationWorkNode = workflowWorkNodeDOList.find(
          (n) =>
            n.uuid === isolationNodeUuid &&
            isWorkflowUnlockParentMatch(nodeData.type, n.type)
        );
        if (isolationWorkNode) {
          isolationNodeData = {
            isolationType: isolationWorkNode.isolationType || '',
            isolationPoints: isolationWorkNode.isolationPoints 
              ? (typeof isolationWorkNode.isolationPoints === 'string' 
                  ? JSON.parse(isolationWorkNode.isolationPoints) 
                  : isolationWorkNode.isolationPoints)
              : [],
            lockPerson: isolationWorkNode.nodeUserList?.find((u: any) => u.type === 'locker' || u.type === 'jtlocker')?.userId || '',
            coLockPersons: isolationWorkNode.nodeUserList?.filter((u: any) => u.type === 'colocker' || u.type === 'jtcolocker').map((u: any) => u.userId) || [],
            formId: isolationWorkNode.formId || '',
            workerUserId: isolationWorkNode.workerUserId || '',
            points: isolationWorkNode.points || [],
            locks: isolationWorkNode.locks || [],
          };
        }
      }
    }
  }
  
  // 获取节点配置信息
  const nodeConfig = {
    nodeName: workNode?.nodeName || nodeData.label || nodeData.nodeName || '',
    responsible: isolationNodeData?.workerUserId || workNode?.workerUserId || nodeData.workerUserId || nodeData.responsible || '',
    formId: isolationNodeData?.formId || workNode?.formId || nodeData.formId || nodeData.submitForm || '',
    isolationType: isolationNodeData?.isolationType || workNode?.isolationType || nodeData.isolationType || '',
    isolationPoints: isolationNodeData?.isolationPoints || (workNode?.isolationPoints ? (typeof workNode.isolationPoints === 'string' ? JSON.parse(workNode.isolationPoints) : workNode.isolationPoints) : (nodeData.isolationPoints || [])),
    isolationNodeUuid: workNode?.isolationNodeUuid || nodeData.isolationNodeUuid || '',
    lockPerson: isolationNodeData?.lockPerson || workNode?.nodeUserList?.find((u: any) => u.type === 'locker' || u.type === 'jtlocker')?.userId || nodeData.lockPerson || '',
    coLockPersons: isolationNodeData?.coLockPersons || workNode?.nodeUserList?.filter((u: any) => u.type === 'colocker' || u.type === 'jtcolocker').map((u: any) => u.userId) || nodeData.coLockPersons || [],
    notificationMethods: nodeData.notificationMethods || {
      sms: false,
      message: false,
      email: false,
      app: false,
    },
    notificationPerson: nodeData.notificationPerson || '',
    notificationTime: workNode?.notifyTime || nodeData.notificationTime || '',
    remark: nodeData.remark || '',
    // 保存隔离方案节点的 points 和 locks 数据（用于解除隔离节点显示）
    points: isolationNodeData?.points || workNode?.points || [],
    locks: isolationNodeData?.locks || workNode?.locks || [],
  };

  // 获取负责人名称
  const getResponsibleName = () => {
    if (!nodeConfig.responsible) return '-';
    const userId = nodeConfig.responsible;
    return userNameMap.get(userId) || 
           userNameMap.get(String(userId)) || 
           userNameMap.get(Number(userId)) || 
           String(userId);
  };

  // 获取表单名称
  const getFormName = () => {
    if (!nodeConfig.formId) return '-';
    const form = formList.find(f => f.id === nodeConfig.formId);
    return form?.name || '-';
  };

  // 获取隔离方式名称
  const getIsolationTypeName = () => {
    if (!nodeConfig.isolationType) return '-';
    const item = isolationTypeDictList.find(i => i.value === nodeConfig.isolationType);
    return item?.label || nodeConfig.isolationType;
  };

  // 获取隔离点名称
  const getIsolationPointNames = () => {
    if (!nodeConfig.isolationPoints || nodeConfig.isolationPoints.length === 0) return '-';
    const pointIds = Array.isArray(nodeConfig.isolationPoints) ? nodeConfig.isolationPoints : [nodeConfig.isolationPoints];
    const names = pointIds.map((id: any) => {
      const point = isolationPoints.find((p: any) => p.pointId === id || p.id === id);
      return point?.pointName || id;
    });
    return names.join(', ');
  };

  // 获取上锁人名称
  const getLockPersonName = () => {
    if (!nodeConfig.lockPerson) return '-';
    const user = lockerUsers.find(u => u.id === nodeConfig.lockPerson);
    return user?.nickname || user?.username || String(nodeConfig.lockPerson);
  };

  // 获取共锁人名称
  const getCoLockPersonNames = () => {
    if (!nodeConfig.coLockPersons || nodeConfig.coLockPersons.length === 0) return '-';
    const names = nodeConfig.coLockPersons.map((id: any) => {
      const user = colockerUsers.find(u => u.id === id);
      return user?.nickname || user?.username || String(id);
    });
    return names.join(', ');
  };


  return (
    <div className="flex-1 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('workJobDetail.nodeInfo')}
        </h4>
        <div className="space-y-5">
          {/* 节点名称 */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              {t('workJobDetail.nodeNameLabel')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
            </label>
            <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
              {nodeConfig.nodeName || '-'}
            </div>
          </div>

          {/* 负责人 - 根据节点类型显示 */}
          {nodeData.type !== 'createJob' && !isWorkflowIsolationSchemePanelType(nodeData.type) && (
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                {t('workJobDetail.responsible')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
              </label>
              <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                {getResponsibleName()}
              </div>
              <p className="text-xs text-gray-500 mt-1.5 leading-relaxed">
                {t('workJobDetail.responsibleHint')}
              </p>
            </div>
          )}

          {/* 备注 */}
          {nodeData.type !== 'createJob' && nodeData.type !== 'confirm' && nodeData.type !== 'review' && nodeData.type !== 'inputInfo' && !isWorkflowIsolationSchemePanelType(nodeData.type) && nodeData.type !== 'returnLock' && nodeData.type !== 'complete' && (
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                {t('workJobDetail.remark')}
              </label>
              <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200 min-h-[60px]">
                {nodeConfig.remark || '-'}
              </div>
            </div>
          )}
        </div>
      </div>

      {/* 提交表单 - 创建作业节点不显示 */}
      {nodeData.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('workJobDetail.submitForm')}
          </h4>
          <div className="space-y-5">
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                {t('workJobDetail.businessForm')}
                {/* 只有确认节点、审核节点、录入信息节点显示必填标记 */}
                {['confirm', 'review', 'inputInfo'].includes(nodeData.type || '') && (
                  <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                )}
              </label>
              <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                {getFormName()}
              </div>
            </div>

            {/* 隔离/方案 和 解除隔离 节点特有的字段 */}
            {isWorkflowIsolationSchemePanelType(nodeData.type) && (
              <>
                {/* 解除隔离节点：选择隔离节点 */}
                {(isWorkflowUnlockSchemeType(nodeData.type) || isWorkflowUnlockCoLockType(nodeData.type)) &&
                  nodeConfig.isolationNodeUuid && (
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      {isWorkflowUnlockCoLockType(nodeData.type)
                        ? t('workJobDetail.selectCoLockTask')
                        : t('workJobDetail.selectLockTask')}{' '}
                      <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                    </label>
                    <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                      {(() => {
                        const isolationNode = workflowWorkNodeDOList.find(
                          (n) =>
                            n.uuid === nodeConfig.isolationNodeUuid &&
                            isWorkflowUnlockParentMatch(nodeData.type, n.type)
                        );
                        return isolationNode?.nodeName || nodeConfig.isolationNodeUuid || '-';
                      })()}
                    </div>
                  </div>
                )}

                {/* 解除共锁：选定共锁任务后仅展示共锁人 */}
                {isWorkflowUnlockCoLockType(nodeData.type) && nodeConfig.isolationNodeUuid && (
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      {t('workJobDetail.colockerPerson')}
                    </label>
                    <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                      {getCoLockPersonNames()}
                    </div>
                  </div>
                )}

                {/* 共锁节点：关联上锁任务 + 共锁人 */}
                {isWorkflowCoLockType(nodeData.type) && nodeConfig.isolationNodeUuid && (
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      {t('workJobDetail.selectLockTask')}{' '}
                      <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                    </label>
                    <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                      {(() => {
                        const lockNode = workflowWorkNodeDOList.find(
                          (n) =>
                            n.uuid === nodeConfig.isolationNodeUuid &&
                            isWorkflowLockSchemeType(n.type)
                        );
                        return lockNode?.nodeName || nodeConfig.isolationNodeUuid || '-';
                      })()}
                    </div>
                  </div>
                )}
                {isWorkflowCoLockType(nodeData.type) && (
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">
                      {t('workJobDetail.colockerPerson')}
                    </label>
                    <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                      {getCoLockPersonNames()}
                    </div>
                  </div>
                )}

                {!isWorkflowCoLockType(nodeData.type) && !isWorkflowUnlockCoLockType(nodeData.type) && (
                  <>
                    {/* 隔离方式 */}
                    <div>
                      <label className="block text-sm font-medium text-gray-700 mb-2">
                        {t('workJobDetail.isolationType')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                      </label>
                      <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                        {getIsolationTypeName()}
                      </div>
                    </div>

                    {/* 隔离点选择（可多选） */}
                    <div>
                      <label className="block text-sm font-medium text-gray-700 mb-2">
                        {t('workJobDetail.isolationPointsSelect')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                      </label>
                      <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                        {getIsolationPointNames()}
                      </div>
                    </div>

                    {/* 盲板和拆除：显示负责人 */}
                    {(nodeConfig.isolationType === '0' || nodeConfig.isolationType === '2') && (
                      <div>
                        <label className="block text-sm font-medium text-gray-700 mb-2">
                          {t('workJobDetail.responsible')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                        </label>
                        <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                          {getResponsibleName()}
                        </div>
                      </div>
                    )}

                    {/* 上锁挂牌：上锁节点不展示共锁人 */}
                    {nodeConfig.isolationType === '1' && (
                      <>
                        <div>
                          <label className="block text-sm font-medium text-gray-700 mb-2">
                            {t('workJobDetail.lockerPerson')} <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                          </label>
                          <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                            {getLockPersonName()}
                          </div>
                        </div>
                        {!isWorkflowLockSchemeType(nodeData.type) &&
                          !isWorkflowUnlockSchemeType(nodeData.type) && (
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              {t('workJobDetail.colockerPerson')}
                            </label>
                            <div className="text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
                              {getCoLockPersonNames()}
                            </div>
                          </div>
                        )}
                      </>
                    )}
                  </>
                )}
              </>
            )}
          </div>
        </div>
      )}

      {/* 通知消息 - 创建作业节点不显示 */}
      {nodeData.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('workJobDetail.notificationMessage')}
          </h4>
          <div className="space-y-5">
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-3">
                {t('workJobDetail.notificationMethod')}
              </label>
              <div className="bg-gray-50 p-3 rounded-lg">
                <div className="mb-3">
                  <Checkbox checked={nodeConfig.notificationMethods.sms} disabled>
                    {t('workJobDetail.sms')}
                  </Checkbox>
                </div>
                <div className="mb-3">
                  <Checkbox checked={nodeConfig.notificationMethods.message} disabled>
                    {t('workJobDetail.webmail')}
                  </Checkbox>
                </div>
                <div className="mb-3">
                  <Checkbox checked={nodeConfig.notificationMethods.email} disabled>
                    {t('workJobDetail.email')}
                  </Checkbox>
                </div>
                <div>
                  <Checkbox checked={nodeConfig.notificationMethods.app} disabled>
                    {t('workJobDetail.appNotify')}
                  </Checkbox>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default function WorkJobDetail() {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const jobId = searchParams.get('id');
  
  const [jobDetail, setJobDetail] = useState<WorkJobVO | null>(null);
  const [loading, setLoading] = useState(true);
  
  // 作业状态字典数据
  const [jobStatusDictList, setJobStatusDictList] = useState<DictDataVO[]>([]);
  
  // 审批状态字典数据
  const [approvalStatusDictList, setApprovalStatusDictList] = useState<DictDataVO[]>([]);
  
  // 流程树状态
  const [workflowTree, setWorkflowTree] = useState<WorkflowNode[]>([]);
  const [expandedBranches, setExpandedBranches] = useState<Set<string>>(new Set());
  
  // 展开的分支组（按 parentUuid）
  const [expandedBranchGroups, setExpandedBranchGroups] = useState<Set<string>>(new Set());
  
  // 用户ID到用户名的映射
  const [userNameMap, setUserNameMap] = useState<Map<number | string, string>>(new Map());

  // ReactFlow 状态
  const [nodes, setNodes, onNodesChange] = useNodesState([]);
  const [edges, setEdges, onEdgesChange] = useEdgesState([]);
  const reactFlowWrapper = useRef<HTMLDivElement>(null);
  const [reactFlowInstance, setReactFlowInstance] = useState<any>(null);
  const [selectedNode, setSelectedNode] = useState<Node | null>(null);

  // 节点信息相关状态
  const [formList, setFormList] = useState<any[]>([]);
  const [drawerUsers, setDrawerUsers] = useState<any[]>([]);
  const [lockerUsers, setLockerUsers] = useState<any[]>([]);
  const [colockerUsers, setColockerUsers] = useState<any[]>([]);
  const [isolationTypeDictList, setIsolationTypeDictList] = useState<DictDataVO[]>([]);
  const [isolationPoints, setIsolationPoints] = useState<any[]>([]);
  const [workflowTemplateList, setWorkflowTemplateList] = useState<any[]>([]);
  const [workTypeDictList, setWorkTypeDictList] = useState<DictDataVO[]>([]);
  const [urgencyLevelDictList, setUrgencyLevelDictList] = useState<DictDataVO[]>([]);

  // 获取作业状态字典数据
  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([]);
    }
  };

  // 加载表单列表、用户列表等数据
  useEffect(() => {
    const loadData = async () => {
      try {
        // 加载表单列表
        const formRes = await getFormPage({ pageNo: 1, pageSize: -1, status: 0 });
        setFormList(formRes.list || []);
        
        // 加载用户列表
        const [drawerRes, lockerRes, colockerRes] = await Promise.all([
          userApi.getRoleUser('jtdrawer'),
          userApi.getRoleUser('jtlocker'),
          userApi.getRoleUser('jtcolocker'),
        ]);
        setDrawerUsers(drawerRes || []);
        setLockerUsers(lockerRes || []);
        setColockerUsers(colockerRes || []);
        
        // 加载隔离点列表
        const isolationRes = await segregationPointApi.getIsIsolationPointPage({ pageNo: 1, pageSize: -1 });
        setIsolationPoints(isolationRes.list || []);
        
        // 加载隔离方式字典
        const isolationTypeRes = await dictDataApi.getDictDataPage({
          pageNo: 1,
          pageSize: -1,
          dictType: 'isolation_method',
        });
        const isolationTypeData = (isolationTypeRes as any)?.data || isolationTypeRes;
        setIsolationTypeDictList(isolationTypeData?.list || []);
        
        // 加载流程模板列表
        const templateRes = await workflowDesignApi.getWorkflowDesignPage({
          pageNo: 1,
          pageSize: -1,
        });
        const templateData = (templateRes as any)?.data || templateRes;
        setWorkflowTemplateList(templateData?.list || []);
        
        // 加载作业分类字典
        const workTypeRes = await dictDataApi.getDictDataPage({
          pageNo: 1,
          pageSize: -1,
          dictType: 'work_type',
        });
        const workTypeData = (workTypeRes as any)?.data || workTypeRes;
        setWorkTypeDictList(workTypeData?.list || []);
        
        // 加载紧急程度字典
        const urgencyRes = await dictDataApi.getDictDataPage({
          pageNo: 1,
          pageSize: -1,
          dictType: 'urgency_level',
        });
        const urgencyData = (urgencyRes as any)?.data || urgencyRes;
        setUrgencyLevelDictList(urgencyData?.list || []);
        
        // 加载审批状态字典
        const approvalStatusRes = await dictDataApi.getDictDataPage({
          pageNo: 1,
          pageSize: -1,
          dictType: 'approval_status',
        });
        const approvalStatusData = (approvalStatusRes as any)?.data || approvalStatusRes;
        setApprovalStatusDictList(approvalStatusData?.list || []);
        console.log('WorkJobDetail: 获取审批状态字典成功', approvalStatusData?.list || []);
      } catch (error: any) {
        console.error('加载数据失败:', error);
      }
    };
    
    loadData();
  }, []);

  // 获取作业详情
  useEffect(() => {
    getJobStatusDictList();
    if (jobId) {
      loadJobDetail();
    }
  }, [jobId]);

  // 批量获取用户信息
  const loadUserNames = async (userIds: (number | string)[]) => {
    if (!userIds || userIds.length === 0) return new Map<number | string, string>();
    
    const userMap = new Map<number | string, string>();
    const uniqueUserIds = Array.from(new Set(userIds.filter(id => id && !isNaN(Number(id)))));
    
    if (uniqueUserIds.length === 0) return userMap;
    
    try {
      // 逐个查询用户信息（更准确）
      const userPromises = uniqueUserIds.map(async (userId) => {
        try {
          const user = await userApi.getUser(Number(userId));
          const userData = (user as any)?.data || user;
          if (userData && userData.nickname) {
            // 同时存储数字和字符串类型的键，确保能匹配到
            return { 
              id: userId, 
              idNum: Number(userId),
              idStr: String(userId),
              nickname: userData.nickname 
            };
          }
        } catch (error: any) {
          console.error(`获取用户 ${userId} 信息失败:`, error);
        }
        return null;
      });
      
      const userResults = await Promise.all(userPromises);
      userResults.forEach((result) => {
        if (result) {
          // 同时存储多种键类型，确保能匹配到
          userMap.set(result.id, result.nickname);
          userMap.set(result.idNum, result.nickname);
          userMap.set(result.idStr, result.nickname);
        }
      });
      
      console.log('用户映射结果:', Array.from(userMap.entries()));
      console.log('查询的用户ID列表:', uniqueUserIds);
    } catch (error: any) {
      console.error('获取用户信息失败:', error);
    }
    
    return userMap;
  };

  // 根据 approvalStatus 字典值判断节点状态
  const getNodeStatusFromDict = (
    approvalStatus: string | number | null | undefined,
    approvalStatusDictList: DictDataVO[],
    workNode: WorkflowWorkNodeDO | undefined,
    nodeMap: Map<string, WorkflowWorkNodeDO>
  ): 'completed' | 'in_progress' | 'pending' => {
    if (!workNode) return 'pending';
    
    // 如果没有 approvalStatus，检查父节点状态来决定是否可以执行
    if (!approvalStatus) {
      if (!workNode.parentUuid || workNode.parentUuid === '') {
        return 'pending'; // 没有父节点且没有状态，默认为待执行
      }
      // 检查所有父节点是否都已完成
      const parentUuids = workNode.parentUuid.split(',').map(u => u.trim()).filter(u => u);
      const allParentsCompleted = parentUuids.every(parentUuid => {
        const parentNode = nodeMap.get(parentUuid);
        if (!parentNode) return false;
        const parentStatus = getNodeStatusFromDict(parentNode.approvalStatus, approvalStatusDictList, parentNode, nodeMap);
        return parentStatus === 'completed';
      });
      return allParentsCompleted ? 'in_progress' : 'pending';
    }
    
    // 在字典中查找对应的状态项（优先通过 value 匹配，其次通过 label 匹配）
    const statusStr = String(approvalStatus).toLowerCase().trim();
    const dictItem = approvalStatusDictList.find(item => {
      const itemValue = String(item.value || '').toLowerCase().trim();
      const itemLabel = String(item.label || '').toLowerCase().trim();
      return itemValue === statusStr || itemLabel === statusStr;
    });
    
    // 如果找到字典项，根据字典的 value 来映射状态
    if (dictItem) {
      const dictValue = String(dictItem.value || '').toLowerCase().trim();
      
      // 根据字典 value 直接映射状态
      // pending -> pending (待执行)
      if (dictValue === 'pending') {
        // 检查父节点状态，如果所有父节点都已完成，则可以进行中
        if (!workNode.parentUuid || workNode.parentUuid === '') {
          return 'pending';
        }
        const parentUuids = workNode.parentUuid.split(',').map(u => u.trim()).filter(u => u);
        const allParentsCompleted = parentUuids.every(parentUuid => {
          const parentNode = nodeMap.get(parentUuid);
          if (!parentNode) return false;
          const parentStatus = getNodeStatusFromDict(parentNode.approvalStatus, approvalStatusDictList, parentNode, nodeMap);
          return parentStatus === 'completed';
        });
        return allParentsCompleted ? 'in_progress' : 'pending';
      }
      // running -> in_progress (进行中)
      if (dictValue === 'running') {
        return 'in_progress';
      }
      // approved -> completed (已完成)
      if (dictValue === 'approved') {
        return 'completed';
      }
      // rejected -> completed (已完成，虽然被拒绝但也算完成状态)
      if (dictValue === 'rejected') {
        return 'completed';
      }
    }
    
    // 如果没有找到字典项，直接根据 approvalStatus 的值来映射（兼容旧代码）
    if (typeof approvalStatus === 'string') {
      const statusStrLower = approvalStatus.toLowerCase().trim();
      if (statusStrLower === 'approved') {
        return 'completed';
      } else if (statusStrLower === 'running' || statusStrLower === 'in_progress') {
        return 'in_progress';
      } else if (statusStrLower === 'rejected') {
        return 'completed'; // rejected 也表示已完成
      } else if (statusStrLower === 'pending' || statusStrLower === 'unaudited') {
        // 检查父节点状态
        if (!workNode.parentUuid || workNode.parentUuid === '') {
          return 'pending';
        }
        const parentUuids = workNode.parentUuid.split(',').map(u => u.trim()).filter(u => u);
        const allParentsCompleted = parentUuids.every(parentUuid => {
          const parentNode = nodeMap.get(parentUuid);
          if (!parentNode) return false;
          return getNodeStatusFromDict(parentNode.approvalStatus, approvalStatusDictList, parentNode, nodeMap) === 'completed';
        });
        return allParentsCompleted ? 'in_progress' : 'pending';
      }
    } else if (typeof approvalStatus === 'number') {
      // 数字类型：通常 1-待执行，2-进行中，3-已完成
      if (approvalStatus === 3) {
        return 'completed';
      } else if (approvalStatus === 2) {
        return 'in_progress';
      } else if (approvalStatus === 1) {
        // 检查父节点状态
        if (!workNode.parentUuid || workNode.parentUuid === '') {
          return 'pending';
        }
        const parentUuids = workNode.parentUuid.split(',').map(u => u.trim()).filter(u => u);
        const allParentsCompleted = parentUuids.every(parentUuid => {
          const parentNode = nodeMap.get(parentUuid);
          if (!parentNode) return false;
          return getNodeStatusFromDict(parentNode.approvalStatus, approvalStatusDictList, parentNode, nodeMap) === 'completed';
        });
        return allParentsCompleted ? 'in_progress' : 'pending';
      }
    }
    
    // 默认返回 pending
    return 'pending';
  };

  // 解析 designContent 并转换为 ReactFlow 格式
  const loadDesignContentToReactFlow = useCallback((designContent: string, workflowWorkNodeDOList: WorkflowWorkNodeDO[]) => {
    try {
      // 解析 designContent
      const jsonData = typeof designContent === 'string' 
        ? JSON.parse(designContent) 
        : designContent;
      
      if (!jsonData.nodes || !Array.isArray(jsonData.nodes)) {
        console.warn('designContent 格式错误：缺少 nodes 数组');
        return;
      }
      
      if (!jsonData.edges || !Array.isArray(jsonData.edges)) {
        console.warn('designContent 格式错误：缺少 edges 数组');
        return;
      }

      // 创建节点映射（用于匹配 workflowWorkNodeDOList）
      const nodeMap = new Map<string, WorkflowWorkNodeDO>();
      workflowWorkNodeDOList.forEach((node) => {
        if (node.uuid) {
          nodeMap.set(node.uuid, node);
        }
      });

      // 调试：打印 workflowWorkNodeDOList 数据和字典数据
      console.log('=== workflowWorkNodeDOList 数据 ===');
      workflowWorkNodeDOList.forEach((node) => {
        console.log(`节点 ${node.uuid} (${node.nodeName}): approvalStatus = ${node.approvalStatus}`, node);
      });
      console.log('=== approval_status 字典数据 ===', approvalStatusDictList);

      // 转换节点
      const convertedNodes: Node[] = jsonData.nodes.map((node: any) => {
        const nodeId = node.uuid || node.id;
        const workNode = nodeMap.get(nodeId);
        
        // 根据 approvalStatus 字典值获取节点状态
        let status: 'completed' | 'in_progress' | 'pending' = 'pending';
        if (workNode) {
          status = getNodeStatusFromDict(workNode.approvalStatus, approvalStatusDictList, workNode, nodeMap);
          
          // 调试：打印节点状态映射
          const dictItem = approvalStatusDictList.find(item => 
            String(item.value).toLowerCase() === String(workNode.approvalStatus).toLowerCase() ||
            String(item.label).toLowerCase() === String(workNode.approvalStatus).toLowerCase()
          );
          console.log(`节点 ${nodeId} (${workNode.nodeName}): approvalStatus=${JSON.stringify(workNode.approvalStatus)} -> 字典项=${dictItem?.label || '未找到'} -> status=${status}`);
        } else {
          console.warn(`未找到节点 ${nodeId} 对应的 workNode`);
        }
        
        // 优先从 workflowWorkNodeDOList 中获取节点数据，如果没有则使用 designContent 中的数据作为兜底
        const nodeData = node.data || {};
        
        // 节点名称：优先从 workNode 获取
        const nodeName = workNode?.nodeName || nodeData.label || node.nodeName || t('workJobDetail.node');
        
        // 节点类型：优先从 workNode 获取
        const nodeType = workNode?.type || node.type || 'createJob';
        
        // 节点图标：优先从 workNode 获取
        const nodeIcon = workNode?.nodeIcon || nodeData.icon || node.nodeIcon || '';
        
        // 节点ID（用于显示）：优先从 workNode 获取，如果没有则从 nodeData 获取
        const displayNodeId = workNode?.id ? String(workNode.id) : (nodeData.nodeId || '');
        
        // 解锁/解除共锁：从对应的上锁或共锁节点复制数据
        let isolationNodeData: any = null;
        if (
          isWorkflowUnlockSchemeType(nodeType) ||
          isWorkflowUnlockCoLockType(nodeType)
        ) {
          // 获取隔离节点UUID（从 workNode 或 nodeData 中获取）
          const isolationNodeUuid = workNode?.isolationNodeUuid || nodeData.isolationNodeUuid || '';
          if (isolationNodeUuid) {
            // 找到对应的方案源节点
            const isolationWorkNode = workflowWorkNodeDOList.find(
              (n) =>
                n.uuid === isolationNodeUuid &&
                isWorkflowUnlockParentMatch(nodeType, n.type)
            );
            if (isolationWorkNode) {
              // 复制隔离方案节点的数据
              isolationNodeData = {
                isolationType: isolationWorkNode.isolationType || '',
                isolationPoints: isolationWorkNode.isolationPoints 
                  ? (typeof isolationWorkNode.isolationPoints === 'string' 
                      ? JSON.parse(isolationWorkNode.isolationPoints) 
                      : isolationWorkNode.isolationPoints)
                  : [],
                lockPerson: isolationWorkNode.nodeUserList?.find((u: any) => u.type === 'locker' || u.type === 'jtlocker')?.userId || '',
                coLockPersons: isolationWorkNode.nodeUserList?.filter((u: any) => u.type === 'colocker' || u.type === 'jtcolocker').map((u: any) => u.userId) || [],
                formId: isolationWorkNode.formId || '',
                workerUserId: isolationWorkNode.workerUserId || '',
                points: isolationWorkNode.points || [],
                locks: isolationWorkNode.locks || [],
              };
              console.log(`解除隔离节点 ${nodeId} 从隔离方案节点 ${isolationNodeUuid} 复制数据:`, isolationNodeData);
            }
          }
        }
        
        return {
          id: nodeId,
          type: nodeType, // 使用从 workNode 获取的类型
          position: node.position || { x: 0, y: 0 }, // 位置信息从 designContent 获取
          data: {
            // 保留 designContent 中的其他数据作为兜底
            ...nodeData,
            // 但显示相关的内容优先使用 workNode 中的数据
            label: nodeName,
            nodeName: nodeName,
            nodeId: displayNodeId,
            icon: nodeIcon,
            type: nodeType,
            status: status,
            // 将 workNode 的完整数据也保存到 data 中，方便后续使用
            workNode: workNode,
            // 如果是解除隔离节点，添加从隔离方案节点复制的数据
            ...(isolationNodeData ? { isolationNodeData } : {}),
          },
        };
      });

      // 转换边
      const convertedEdges: Edge[] = jsonData.edges.map((edge: any) => {
        const sourceId = edge.source;
        const targetId = edge.target;
        
        return {
          id: edge.id,
          source: sourceId,
          target: targetId,
          sourceHandle: edge.sourceHandle,
          targetHandle: edge.targetHandle,
          type: edge.type || 'straight',
          animated: false,
          data: {
            fixedLength: edge.data?.fixedLength ?? 150,
            edgeType: edge.type || 'straight',
          },
          style: { strokeWidth: 2, stroke: '#000000' },
          markerStart: {
            type: 'arrowclosed' as any,
            color: '#000000',
          },
        };
      });

      const finalNodes = shouldApplyLayout(convertedNodes, convertedEdges)
        ? getLayoutedNodes(convertedNodes, convertedEdges)
        : convertedNodes;
      setNodes(finalNodes);
      setEdges(convertedEdges);
      
      // 根据流程顺序找到默认选中的节点：优先选中第一个进行中的节点，如果没有则选中第一个待执行的节点
      // 使用adjacency结构（类似编辑弹框的逻辑），按照childrenUuid顺序查找
      let defaultSelectedNode: Node | null = null;
      
      // 构建节点映射（使用最终用于渲染的节点列表）
      const nodeIdMap = new Map<string, Node>();
      finalNodes.forEach(node => {
        nodeIdMap.set(node.id, node);
      });
      
      // 构建adjacency结构（从edges或jsonData.adjacency）
      let adjacency: Record<string, { parentUuid: string[]; childrenUuid: string[] }> = {};
      
      // 如果designContent中有adjacency，直接使用
      if (jsonData.adjacency) {
        adjacency = jsonData.adjacency;
      } else {
        // 如果没有adjacency，从edges构建
        // 注意：edges中source是父节点，target是子节点
        convertedNodes.forEach(node => {
          adjacency[node.id] = { parentUuid: [], childrenUuid: [] };
        });
        
        convertedEdges.forEach(edge => {
          const sourceId = edge.source;
          const targetId = edge.target;
          if (!finalNodes.some((n) => n.id === sourceId) || !finalNodes.some((n) => n.id === targetId)) return;
          if (!adjacency[sourceId]) {
            adjacency[sourceId] = { parentUuid: [], childrenUuid: [] };
          }
          if (!adjacency[targetId]) {
            adjacency[targetId] = { parentUuid: [], childrenUuid: [] };
          }
          if (!adjacency[sourceId].childrenUuid.includes(targetId)) {
            adjacency[sourceId].childrenUuid.push(targetId);
          }
          if (!adjacency[targetId].parentUuid.includes(sourceId)) {
            adjacency[targetId].parentUuid.push(sourceId);
          }
        });
      }
      
      // 辅助函数：检查节点的所有父节点是否都已完成
      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) => {
          const parentNode = nodeIdMap.get(parentId);
          return parentNode?.data?.status === 'completed';
        });
      };
      
      // BFS遍历查找第一个进行中或待执行的节点（按照childrenUuid顺序）
      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 node = nodeIdMap.get(nodeId);
          if (node) {
            const status = node.data?.status;
            // 如果开始节点是进行中或待执行，直接返回
            if ((status === 'in_progress' || status === 'pending') && areAllParentsCompleted(nodeId)) {
              defaultSelectedNode = node;
              break;
            } else if (status === 'completed') {
              // 如果开始节点已完成，将其子节点加入队列（按childrenUuid顺序）
              if (nodeInfo.childrenUuid && nodeInfo.childrenUuid.length > 0) {
                nodeInfo.childrenUuid.forEach((childId: string) => {
                  if (!visited.has(childId)) {
                    queue.push(childId);
                    visited.add(childId);
                  }
                });
              }
            }
          }
        }
      }
      
      // 如果开始节点都已处理完，BFS遍历查找下一个进行中或待执行的节点
      if (!defaultSelectedNode) {
        while (queue.length > 0) {
          const currentNodeId = queue.shift()!;
          const currentNode = nodeIdMap.get(currentNodeId);
          
          if (!currentNode) continue;
          
          const status = currentNode.data?.status;
          
          // 如果当前节点是进行中或待执行，且所有父节点都已完成，则选中它
          if ((status === 'in_progress' || status === 'pending') && areAllParentsCompleted(currentNodeId)) {
            defaultSelectedNode = currentNode;
            break; // 找到第一个符合条件的节点就停止
          }
          
          // 如果当前节点已完成，将其子节点加入队列（按childrenUuid顺序）
          if (status === 'completed') {
            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);
                }
              });
            }
          }
        }
      }
      
      // 如果找到了默认选中的节点，标记为选中并设置状态
      if (defaultSelectedNode) {
        const selectedNodeId = defaultSelectedNode.id;
        setNodes((nds) =>
          nds.map((node) => ({
            ...node,
            selected: node.id === selectedNodeId,
          }))
        );
        setSelectedNode(defaultSelectedNode);
      }
      
      // 自动适应视图
      setTimeout(() => {
        if (reactFlowInstance) {
          reactFlowInstance.fitView({ padding: 0.2 });
        }
      }, 100);
    } catch (error: any) {
      console.error('解析 designContent 失败:', error);
    }
  }, [reactFlowInstance, setNodes, setEdges, approvalStatusDictList]);

  const loadJobDetail = async () => {
    if (!jobId) return;
    try {
      setLoading(true);
      const response = await workJobApi.selectWorkflowWorkById(Number(jobId));
      // 处理响应数据，可能包含 data 字段
      const data = (response as any)?.data || response;
      setJobDetail(data);
      console.log('作业详情数据:', data);

      // 收集所有的 workerUserId
      const userIds: (number | string)[] = [];
      if (data?.workflowWorkNodeDOList && Array.isArray(data.workflowWorkNodeDOList)) {
        data.workflowWorkNodeDOList.forEach((node: any) => {
          if (node.workerUserId) {
            userIds.push(node.workerUserId);
          }
        });
      }
      
      // 批量获取用户信息
      const userMap = await loadUserNames(userIds);
      setUserNameMap(userMap);
      
      // 构建流程树
      if (data?.workflowWorkNodeDOList && Array.isArray(data.workflowWorkNodeDOList) && data.workflowWorkNodeDOList.length > 0) {
        console.log('准备构建流程树，节点数量:', data.workflowWorkNodeDOList.length);
        buildWorkflowTree(data.workflowWorkNodeDOList);
      } else {
        console.warn('没有流程节点数据，workflowWorkNodeDOList:', data?.workflowWorkNodeDOList);
        setWorkflowTree([]);
      }

      // 加载 designContent 到 ReactFlow
      if (data?.designContent) {
        // 如果直接有 designContent，使用它
        loadDesignContentToReactFlow(data.designContent, data.workflowWorkNodeDOList || []);
      } else if (data?.designId) {
        // 如果没有 designContent，通过 designId 获取
        try {
          const designResponse = await workflowDesignApi.selectWorkflowDesignById(data.designId);
          const designData = (designResponse as any)?.data || designResponse;
          if (designData?.content) {
            loadDesignContentToReactFlow(designData.content, data.workflowWorkNodeDOList || []);
          }
        } catch (error: any) {
          console.error('获取流程设计详情失败:', error);
        }
      }
    } catch (error: any) {
      console.error('获取作业详情失败:', error);
    } finally {
      setLoading(false);
    }
  };

  // 构建流程树
  const buildWorkflowTree = useCallback((nodeList: WorkflowWorkNodeDO[]) => {
    console.log('开始构建流程树，节点列表:', nodeList);
    
    if (!nodeList || nodeList.length === 0) {
      console.warn('节点列表为空');
      setWorkflowTree([]);
      return;
    }

    // 构建节点映射
    const nodeMap = new Map<string, WorkflowWorkNodeDO>();
    nodeList.forEach((node) => {
      if (node.uuid) {
        nodeMap.set(node.uuid, node);
      }
    });

    // 构建父子关系映射
    const childrenMap = new Map<string, WorkflowWorkNodeDO[]>();
    nodeList.forEach((node) => {
      if (node.parentUuid) {
        if (!childrenMap.has(node.parentUuid)) {
          childrenMap.set(node.parentUuid, []);
        }
        childrenMap.get(node.parentUuid)!.push(node);
      }
    });

    console.log('子节点映射:', Array.from(childrenMap.entries()));

    // 找到根节点（parentUuid 为空或不在 nodeList 中的节点）
    const rootNodes = nodeList.filter((node) => !node.parentUuid || node.parentUuid === '');
    console.log('根节点:', rootNodes);

    // 递归构建节点树
    const buildNode = (workNode: WorkflowWorkNodeDO): WorkflowNode => {
      const status = getNodeStatusFromDict(workNode.approvalStatus, approvalStatusDictList, workNode, nodeMap);
      const children = childrenMap.get(workNode.uuid || '') || [];
      
      // 判断是否有分支（多个子节点）
      const isBranch = children.length > 1;
      
      // 构建子节点
      const childNodes = children.map((child) => buildNode(child));
      
      // 如果有分支，第一个子节点作为主流程，其他作为分支
      let mainChild: WorkflowNode | null = null;
      let branchNodes: WorkflowNode[] = [];
      
      if (isBranch && childNodes.length > 0) {
        mainChild = childNodes[0];
        branchNodes = childNodes.slice(1);
      } else if (childNodes.length === 1) {
        mainChild = childNodes[0];
      }

      return {
        uuid: workNode.uuid || '',
        nodeName: workNode.nodeName || t('workJobDetail.unknownNode'),
        type: workNode.type || 'createJob',
        status,
        workNode,
        children: mainChild ? [mainChild] : [],
        isBranch,
        branchNodes: branchNodes.length > 0 ? branchNodes : undefined,
      };
    };

    // 构建主流程树（从第一个根节点开始）
    if (rootNodes.length > 0) {
      const rootNode = rootNodes[0];
      const tree = [buildNode(rootNode)];
      console.log('构建完成的流程树:', tree);
      setWorkflowTree(tree);
    } else {
      console.warn('未找到根节点');
      setWorkflowTree([]);
    }
  }, [approvalStatusDictList]);

  // 切换分支展开/收起
  const toggleBranch = (nodeUuid: string) => {
    setExpandedBranches((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(nodeUuid)) {
        newSet.delete(nodeUuid);
      } else {
        newSet.add(nodeUuid);
      }
      return newSet;
    });
  };

  // 格式化状态文本（使用字典）
  const getStatusText = (status: string | number | undefined): string => {
    if (!status) return t('workJobDetail.statusUnknown');
    const statusStr = String(status).toLowerCase();
    const statusItem = jobStatusDictList.find(item => String(item.value).toLowerCase() === statusStr);
    if (statusItem) {
      return statusItem.label || t('workJobDetail.statusUnknown');
    }
    const statusMap: Record<string, string> = {
      'pending': t('workJobDetail.statusPending'),
      'running': t('workJobDetail.statusRunning'),
      'completed': t('workJobDetail.statusCompleted'),
      'rejected': t('workJobDetail.statusRejected'),
      'skipped': t('workJobDetail.statusSkipped'),
      '进行中': t('workJobDetail.statusRunning'),
      '已完成': t('workJobDetail.statusCompleted'),
      '待开始': t('workJobDetail.statusPending'),
      '已取消': t('workJobDetail.statusCancelled'),
    };
    return statusMap[statusStr] || String(status) || t('workJobDetail.statusUnknown');
  };

  // 判断状态是否为已完成
  const isStatusCompleted = (status: string | number | undefined): boolean => {
    if (!status) return false;
    
    // 直接判断是否为字符串 'completed'
    if (String(status).toLowerCase() === 'completed') {
      return true;
    }
    
    // 从字典中查找状态文本
    const statusStr = String(status).toLowerCase();
    const statusItem = jobStatusDictList.find(item => String(item.value).toLowerCase() === statusStr);
    const statusText = statusItem ? (statusItem.label || '') : String(status || '');
    const statusTextLower = statusText.toLowerCase();
    
    // 判断状态文本是否包含已完成相关的关键词
    return statusTextLower.includes('已完成') || 
           statusTextLower.includes('执行完成') || 
           statusTextLower.includes('completed') || 
           statusTextLower.includes('完成');
  };

  // 获取作业状态样式（与列表颜色一致）
  const getStatusStyle = (status: string | number | undefined): React.CSSProperties => {
    if (!status) {
      return {
        backgroundColor: '#e5e5e5',
        color: '#333333',
      };
    }
    
    // 从字典中查找状态文本
    const statusStr = String(status).toLowerCase();
    const statusItem = jobStatusDictList.find(item => String(item.value).toLowerCase() === statusStr);
    const statusText = statusItem ? (statusItem.label || '') : String(status || '');
    const statusTextLower = statusText.toLowerCase();
    
    // 根据状态文本判断颜色
    // 待执行、待发布：灰色 #e5e5e5
    if (statusTextLower.includes('待执行') || statusTextLower.includes('待发布') || 
        statusTextLower.includes('pending') || statusTextLower.includes('unreleased') ||
        statusTextLower.includes('待开始')) {
      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',
    };
  };

  // 构建工作流步骤
  const buildWorkflowSteps = (): WorkflowStep[] => {
    // 这里应该根据实际的作业数据构建步骤
    // 目前使用模拟数据，后续需要根据实际API返回的数据结构调整
    const steps: WorkflowStep[] = [
      {
        id: '1',
        type: 'initiator',
        title: '发起人',
        assigneeName: jobDetail?.initiatorName || jobDetail?.initiator || '张三',
        time: jobDetail?.initiationTime || jobDetail?.initiateTime 
          ? new Date((jobDetail.initiationTime || jobDetail.initiateTime) as string | number | Date).toLocaleString('zh-CN', {
              year: 'numeric',
              month: '2-digit',
              day: '2-digit',
              hour: '2-digit',
              minute: '2-digit',
              second: '2-digit'
            })
          : '2024-01-15 10:30:00',
        status: 'completed',
        icon: <CheckCircle2 className="w-5 h-5" />,
      },
      {
        id: '2',
        type: 'review',
        title: '审核/确认',
        assigneeName: '李四',
        time: '2024-01-15 10:35:00',
        status: 'in_progress',
        icon: <Settings className="w-5 h-5" />,
        hasDetail: true,
      },
      {
        id: '3',
        type: 'input',
        title: '录入/表单',
        assigneeName: '王五',
        status: 'pending',
        icon: <FileText className="w-5 h-5" />,
      },
      {
        id: '4',
        type: 'lock',
        title: '上锁',
        assigneeName: '赵六',
        status: 'pending',
        icon: <Lock className="w-5 h-5" />,
      },
      {
        id: '5',
        type: 'unlock',
        title: '解锁',
        assigneeName: '钱七',
        status: 'pending',
        icon: <Unlock className="w-5 h-5" />,
      },
      {
        id: '6',
        type: 'returnLock',
        title: '还锁',
        assigneeName: '孙八',
        status: 'pending',
        icon: <Lock className="w-5 h-5" />,
      },
      {
        id: '7',
        type: 'complete',
        title: '完成/结束',
        status: 'pending',
        icon: <Flag className="w-5 h-5" />,
      },
    ];
    return steps;
  };

  const workflowSteps = buildWorkflowSteps();

  // 获取任务负责人信息（组件内部函数，可以访问 userNameMap）
  const getExecutorInfo = (workNode: WorkflowWorkNodeDO, type: string): string => {
    if (!workNode) {
      // 创建作业节点如果没有数据，返回空字符串
      if (type === 'createJob') return '';
      return t('workJobDetail.pending');
    }
    
    let executorName = '';
    let isolationWorkNode: WorkflowWorkNodeDO | undefined = undefined;
    
    // 解锁/解除共锁且无执行人时，从关联方案源节点获取
    if (
      (isWorkflowUnlockSchemeType(type) || isWorkflowUnlockCoLockType(type)) &&
      !workNode.workerUserId &&
      !workNode.workerUserName
    ) {
      const isolationNodeUuid = workNode.isolationNodeUuid;
      if (isolationNodeUuid && jobDetail?.workflowWorkNodeDOList) {
        isolationWorkNode = jobDetail.workflowWorkNodeDOList.find(
          (n) =>
            n.uuid === isolationNodeUuid && isWorkflowUnlockParentMatch(type, n.type)
        );
        if (isolationWorkNode) {
          // 使用隔离方案节点的数据
          workNode = isolationWorkNode;
        }
      }
    }
    
    if (workNode.nodeUserList && Array.isArray(workNode.nodeUserList)) {
      const workerUser = workNode.nodeUserList.find((user: any) => user.type === 'worker' || !user.type);
      if (workerUser && workerUser.userName) {
        executorName = workerUser.userName;
      }
    }
    
    if (!executorName) {
      if (workNode.workerUserName) {
        executorName = workNode.workerUserName;
      } else if (workNode.initiatorName) {
        executorName = workNode.initiatorName;
      } else if (workNode.workerUserId) {
        // 从映射中获取用户名，如果没有则使用ID
        // 尝试多种键类型匹配
        const userId = workNode.workerUserId;
        const userName = userNameMap.get(userId) || 
                        userNameMap.get(String(userId)) || 
                        userNameMap.get(Number(userId));
        executorName = userName || String(userId);
      } else if (workNode.initiator) {
        executorName = workNode.initiator;
      }
    }
    
    // 创建作业节点如果没有执行人，返回空字符串
    if (!executorName) {
      if (type === 'createJob') return '';
      return t('workJobDetail.pending');
    }
    
    if (type === 'createJob') {
      return `发起人: ${executorName}`;
    } else if (type === 'review' || type === 'confirm') {
      return `审核人: ${executorName}`;
    } else if (
      isWorkflowLockSchemeType(type) ||
      isWorkflowCoLockType(type) ||
      isWorkflowUnlockSchemeType(type) ||
      isWorkflowUnlockCoLockType(type) ||
      type === 'returnLock'
    ) {
      return `操作人: ${executorName}`;
    } else {
      return `任务负责人: ${executorName}`;
    }
  };

  if (loading) {
    return (
      <div className="min-h-screen bg-gray-50 flex items-center justify-center">
        <div className="text-gray-500">{t('workJobDetail.loading')}</div>
      </div>
    );
  }

  if (!jobDetail) {
    return (
      <div className="min-h-screen bg-gray-50 flex items-center justify-center">
        <div className="text-gray-500">{t('workJobDetail.jobNotFound')}</div>
      </div>
    );
  }

  return (
    <div className="h-screen bg-gray-50 flex flex-col">
      <div className="w-full max-w-none mx-auto px-8 py-6 flex-1 flex flex-col min-h-0">
        {/* 头部区域 */}
        <div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6 flex-shrink-0" style={{ marginLeft: '20px', marginRight: '20px' }}>
          <div className="flex items-start justify-between">
            <div className="flex-1">
              {/* 标题区域 */}
              <div className="mb-4">
                <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
                  <div style={{ 
                    width: '3px', 
                    height: '24px', 
                    backgroundColor: '#025fff',
                    borderRadius: '2px',
                    flexShrink: 0
                  }}></div>
                  <h2 className="text-xl font-semibold mb-2" style={{ color: '#025fff', marginBottom: 0 }}>
                    {jobDetail?.name || t('workJobDetail.title')}
                  </h2>
                  <span 
                    className="inline-flex px-3 py-1 rounded-full text-xs font-medium"
                    style={getStatusStyle(jobDetail?.status)}
                  >
                    {getStatusText(jobDetail?.status)}
                  </span>
                </div>
                <div className="text-sm flex gap-4" style={{ color: '#898f9a', marginTop: '12px' }}>
                  <span>{t('workJobDetail.orderNo')}：{jobDetail?.orderNo || jobDetail?.code || '-'}</span>
                  <span>{t('workJobDetail.jobInitiator')}：{jobDetail?.initiatorName || jobDetail?.initiator || '-'}</span>
                  <span>{t('workJobDetail.initiationTime')}：{jobDetail?.initiationTime ? formatDateWithFormat(jobDetail.initiationTime as string | number | Date) : '-'}</span>
                </div>
              </div>
            </div>
            
            <div className="flex items-center gap-2 flex-shrink-0">
              {isStatusCompleted(jobDetail?.status) && (
                <Button
                  type="primary"
                  onClick={() => navigate(`/work-job/archive${jobId ? `?id=${jobId}` : ''}`)}
                >
                  {t('workJobDetail.archiveInfo')}
                </Button>
              )}
              <button
                onClick={() => {
                  // 设置菜单信息到 sessionStorage，以便 Dashboard 恢复菜单状态
                  sessionStorage.setItem('navigateToMenu', JSON.stringify({
                    menu: 'isolationWork',
                    subMenu: 'workManagement'
                  }));
                  navigate('/dashboard');
                }}
                className="flex items-center justify-center gap-1.5 px-3 h-10 rounded-lg border border-gray-300 hover:bg-gray-50 hover:border-gray-400 transition-colors"
                title={t('workJobDetail.backToWorkManagement')}
              >
                <ArrowLeft className="w-5 h-5 text-gray-600 flex-shrink-0" />
                <span className="text-gray-700">{t('common.back')}</span>
              </button>
            </div>
          </div>
        </div>

        {/* 任务详情和执行记录区域 - 左右两栏布局 */}
        <div className="flex-1 flex gap-8 mb-6 min-h-0 overflow-hidden">
          {/* 左侧：作业流程 - 最大 1400px，随屏幕缩小可收缩 */}
          <div 
            className="bg-white rounded-xl shadow-sm border border-gray-200 flex flex-col min-h-0" 
            style={{ 
              marginLeft: '20px', 
              maxHeight: '790px', 
              maxWidth: '1400px',
              flex: '0 1 1400px',
              minWidth: 0
            }}
          >
            <div className="px-6 py-4 border-b border-gray-200">
              <h2 className="text-lg font-semibold text-blue-600 flex items-center gap-2">
                <FileText className="w-5 h-5" />
                {t('workJobDetail.jobFlow')}
              </h2>
            </div>
            <div className="flex-1 overflow-hidden" ref={reactFlowWrapper} style={{ minHeight: '600px' }}>
              {nodes.length > 0 ? (
                <>
                  <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;
                    }
                    .react-flow__attribution {
                      display: none !important;
                    }
                  `}</style>
                  <ReactFlow
                    nodes={nodes}
                    edges={edges}
                    onNodesChange={onNodesChange}
                    onEdgesChange={onEdgesChange}
                    nodeTypes={nodeTypes}
                    edgeTypes={sharedFlowEdgeTypes}
                    fitView
                    onInit={setReactFlowInstance}
                    connectionMode={ConnectionMode.Loose}
                    snapToGrid={true}
                    snapGrid={[16, 16]}
                    connectionRadius={40}
                    defaultEdgeOptions={{
                      style: { strokeWidth: 2, stroke: '#000000' },
                      markerStart: {
                        type: 'arrowclosed' as any,
                        color: '#000000',
                      },
                    }}
                    nodesDraggable={false}
                    nodesConnectable={false}
                    elementsSelectable={true}
                    onNodeClick={(event, node) => {
                      setSelectedNode(node);
                    }}
                  >
                    <Controls 
                      className="!bg-white !border !border-gray-200 !rounded-lg !shadow-md" 
                      style={{ position: 'absolute', top: '10px', right: '10px', bottom: 'auto', left: 'auto' }}
                    />
                    <Background variant={BackgroundVariant.Lines} gap={16} size={1} color="#e5e7eb" />
                  </ReactFlow>
                </>
              ) : (
                <div className="text-center text-gray-400 py-8">{t('workJobDetail.noFlowData')}</div>
              )}
            </div>
          </div>

          {/* 右侧：作业信息 + 当前任务 - 固定最小宽度，小屏时仍能完整看到 */}
          <div 
            className="flex-1 flex gap-4 min-h-0 overflow-hidden" 
            style={{ marginRight: '20px', maxHeight: '790px', flexDirection: 'column', minWidth: 380 }}
          >
            {/* 作业信息 + 当前任务 组合区域 */}
            <div 
              className="flex flex-col gap-4 min-h-0 overflow-hidden" 
              style={{ flex: '1 1 auto' }}
            >
            {/* 上部分卡片：作业信息 */}
            <div className="bg-white rounded-xl shadow-sm border border-gray-200 flex-shrink-0">
              <div className="px-6 py-4 border-b border-gray-200">
                <h2 className="text-lg font-semibold text-blue-600 flex items-center gap-2">
                  <FileText className="w-5 h-5" />
                  {t('workJobDetail.jobInfo')}
                </h2>
              </div>
              <div className="p-4">
                <style>{`
                  .job-info-descriptions .ant-descriptions-item-label {
                    width: 100px !important;
                    min-width: 100px !important;
                    max-width: 100px !important;
                    flex: 0 0 100px !important;
                  }
                  .job-info-descriptions .ant-descriptions-item-content {
                    width: 300px !important;
                    min-width: 300px !important;
                    max-width: 300px !important;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                  }
                `}</style>
                <Descriptions 
                  column={1} 
                  bordered 
                  size="small"
                  className="job-info-descriptions"
                  labelStyle={{ 
                    width: '100px',
                    minWidth: '100px',
                    maxWidth: '100px',
                    flex: '0 0 100px'
                  }}
                >
                  <Descriptions.Item 
                    label={t('workJobDetail.workflowTemplate')}
                  >
                    <Tooltip title={(() => {
                      const template = workflowTemplateList.find(t => t.id === jobDetail?.designId);
                      return template?.name || '-';
                    })()}>
                      <div style={{ width: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {(() => {
                          const template = workflowTemplateList.find(t => t.id === jobDetail?.designId);
                          return template?.name || '-';
                        })()}
                      </div>
                    </Tooltip>
                  </Descriptions.Item>
                  
                  <Descriptions.Item 
                    label={t('workJobDetail.jobCategory')}
                  >
                    <Tooltip title={(() => {
                      const item = workTypeDictList.find(i => i.value === jobDetail?.type);
                      return item?.label || jobDetail?.type || '-';
                    })()}>
                      <div style={{ width: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {(() => {
                          const item = workTypeDictList.find(i => i.value === jobDetail?.type);
                          return item?.label || jobDetail?.type || '-';
                        })()}
                      </div>
                    </Tooltip>
                  </Descriptions.Item>
                  
                  <Descriptions.Item 
                    label={t('workJobDetail.jobName')}
                  >
                    <Tooltip title={jobDetail?.name || '-'}>
                      <div style={{ width: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {jobDetail?.name || '-'}
                      </div>
                    </Tooltip>
                  </Descriptions.Item>
                  
                  <Descriptions.Item 
                    label={t('workJobDetail.jobContent')}
                  >
                    <Tooltip title={jobDetail?.description || jobDetail?.content || '-'}>
                      <div style={{ width: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {jobDetail?.description || jobDetail?.content || '-'}
                      </div>
                    </Tooltip>
                  </Descriptions.Item>
                  
                  <Descriptions.Item label={t('workJobDetail.urgencyLevel')}>
                    <Tooltip title={(() => {
                      const item = urgencyLevelDictList.find(i => String(i.value) === String(jobDetail?.urgencyLevel || ''));
                      return item?.label || '-';
                    })()}>
                      <div style={{ width: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {(() => {
                          const item = urgencyLevelDictList.find(i => String(i.value) === String(jobDetail?.urgencyLevel || ''));
                          return item?.label || '-';
                        })()}
                      </div>
                    </Tooltip>
                  </Descriptions.Item>
                </Descriptions>
              </div>
            </div>

            {/* 下部分卡片：当前任务 */}
            <div className="bg-white rounded-xl shadow-sm border border-gray-200 flex-1 flex flex-col min-h-0 overflow-hidden">
              <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between">
                <h2 className="text-lg font-semibold text-blue-600 flex items-center gap-2">
                  <Clock className="w-5 h-5" />
                  {t('workJobDetail.currentTask')}
                </h2>
              </div>
              <div className="flex-1 overflow-y-auto p-4">
                {selectedNode ? (
                  <NodeInfoPanel 
                    node={selectedNode}
                    workflowWorkNodeDOList={jobDetail?.workflowWorkNodeDOList || []}
                    formList={formList}
                    drawerUsers={drawerUsers}
                    lockerUsers={lockerUsers}
                    colockerUsers={colockerUsers}
                    isolationTypeDictList={isolationTypeDictList}
                    isolationPoints={isolationPoints}
                    userNameMap={userNameMap}
                  />
                ) : (
                  <div className="text-center text-gray-400 py-8">
                    <p className="text-sm">{t('workJobDetail.clickNodeToViewInfo')}</p>
                  </div>
                )}
              </div>
            </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

