import React, { useState, useCallback, useRef, useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import ReactFlow, {
  Node,
  Edge,
  addEdge,
  Connection,
  useNodesState,
  useEdgesState,
  Controls,
  Background,
  MiniMap,
  NodeTypes,
  BackgroundVariant,
  Handle,
  Position,
  ConnectionMode,
  EdgeLabelRenderer,
  BaseEdge,
  getStraightPath,
  EdgeTypes,
} from 'reactflow';
import 'reactflow/dist/style.css';
import {
  SaveOutlined,
  ArrowLeftOutlined,
  UndoOutlined,
  RedoOutlined,
  ToolOutlined,
  CheckCircleOutlined,
  FileTextOutlined,
  EditOutlined,
  SafetyOutlined,
  UnlockOutlined,
  LockOutlined,
  CheckSquareOutlined,
  CloseOutlined,
  ZoomInOutlined,
  ZoomOutOutlined,
  // 更多图标用于选择器
  HomeOutlined,
  UserOutlined,
  TeamOutlined,
  SettingOutlined,
  FolderOutlined,
  FileOutlined,
  FolderOpenOutlined,
  DatabaseOutlined,
  CloudOutlined,
  ThunderboltOutlined,
  FireOutlined,
  RocketOutlined,
  StarOutlined,
  HeartOutlined,
  BellOutlined,
  MessageOutlined,
  PhoneOutlined,
  MailOutlined,
  CalendarOutlined,
  ClockCircleOutlined,
  SearchOutlined,
  PlusOutlined,
  MinusOutlined,
  DeleteOutlined,
  EditOutlined as EditIconOutlined,
  EyeOutlined,
  EyeInvisibleOutlined,
  DownloadOutlined,
  UploadOutlined,
  ReloadOutlined,
  PlayCircleOutlined,
  PauseCircleOutlined,
  StopOutlined,
  CheckOutlined,
  CloseCircleOutlined,
  WarningOutlined,
  InfoCircleOutlined,
  QuestionCircleOutlined,
  LinkOutlined,
  ShareAltOutlined,
  CopyOutlined,
  ScissorOutlined,
  PrinterOutlined,
  ShoppingCartOutlined,
  ShoppingOutlined,
  GiftOutlined,
  TrophyOutlined,
  CrownOutlined,
  BulbOutlined,
  ExperimentOutlined,
  BugOutlined,
  CodeOutlined,
  ApiOutlined,
  AppstoreOutlined,
  BarsOutlined,
  MenuOutlined,
  LayoutOutlined,
  TableOutlined,
  UnorderedListOutlined,
  OrderedListOutlined,
  PictureOutlined,
  VideoCameraOutlined,
  SoundOutlined,
  CustomerServiceOutlined,
  GlobalOutlined,
  EnvironmentOutlined,
  CompassOutlined,
  CarOutlined,
  BankOutlined,
  ShopOutlined,
  MedicineBoxOutlined,
  SafetyCertificateOutlined,
  InsuranceOutlined,
  FileProtectOutlined,
  FileSyncOutlined,
  FileSearchOutlined,
  FileAddOutlined,
  FileExcelOutlined,
  FilePdfOutlined,
  FileWordOutlined,
  FileImageOutlined,
  FileZipOutlined,
  FolderAddOutlined,
  FolderViewOutlined,
  ProjectOutlined,
  BuildOutlined,
  ToolOutlined as ToolIconOutlined,
  RobotOutlined,
  BugOutlined as BugIconOutlined,
  ExperimentOutlined as ExperimentIconOutlined,
  FireOutlined as FireIconOutlined,
  ThunderboltOutlined as ThunderboltIconOutlined,
} from '@ant-design/icons';
import { Button, Input, Select, Checkbox, Tabs, Modal, Dropdown, Popover, message } from 'antd';
import type { MenuProps } from 'antd';
import { toast } from 'sonner';
import { workflowDesignApi, WorkflowDesignVO } from '../api/WorkflowDesign';
import { userApi } from '../api/user';
import { UserVO } from '../types';
import { segregationPointApi, SegregationPointVO } from '../api/spm';
import { getFormPage, FormVO } from '../api/bpm/form';

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

// 可选的图标列表（用于图标选择器）
const availableIcons = [
  { name: 'ToolOutlined', component: ToolOutlined, label: '工具' },
  { name: 'CheckCircleOutlined', component: CheckCircleOutlined, label: '确认' },
  { name: 'FileTextOutlined', component: FileTextOutlined, label: '文件' },
  { name: 'EditOutlined', component: EditOutlined, label: '编辑' },
  { name: 'SafetyOutlined', component: SafetyOutlined, label: '安全' },
  { name: 'UnlockOutlined', component: UnlockOutlined, label: '解锁' },
  { name: 'LockOutlined', component: LockOutlined, label: '锁定' },
  { name: 'CheckSquareOutlined', component: CheckSquareOutlined, label: '完成' },
  { name: 'HomeOutlined', component: HomeOutlined, label: '首页' },
  { name: 'UserOutlined', component: UserOutlined, label: '用户' },
  { name: 'TeamOutlined', component: TeamOutlined, label: '团队' },
  { name: 'SettingOutlined', component: SettingOutlined, label: '设置' },
  { name: 'FolderOutlined', component: FolderOutlined, label: '文件夹' },
  { name: 'FileOutlined', component: FileOutlined, label: '文件' },
  { name: 'FolderOpenOutlined', component: FolderOpenOutlined, label: '打开文件夹' },
  { name: 'DatabaseOutlined', component: DatabaseOutlined, label: '数据库' },
  { name: 'CloudOutlined', component: CloudOutlined, label: '云' },
  { name: 'ThunderboltOutlined', component: ThunderboltOutlined, label: '闪电' },
  { name: 'FireOutlined', component: FireOutlined, label: '火焰' },
  { name: 'RocketOutlined', component: RocketOutlined, label: '火箭' },
  { name: 'StarOutlined', component: StarOutlined, label: '星星' },
  { name: 'HeartOutlined', component: HeartOutlined, label: '心形' },
  { name: 'BellOutlined', component: BellOutlined, label: '铃铛' },
  { name: 'MessageOutlined', component: MessageOutlined, label: '消息' },
  { name: 'PhoneOutlined', component: PhoneOutlined, label: '电话' },
  { name: 'MailOutlined', component: MailOutlined, label: '邮件' },
  { name: 'CalendarOutlined', component: CalendarOutlined, label: '日历' },
  { name: 'ClockCircleOutlined', component: ClockCircleOutlined, label: '时钟' },
  { name: 'SearchOutlined', component: SearchOutlined, label: '搜索' },
  { name: 'PlusOutlined', component: PlusOutlined, label: '添加' },
  { name: 'MinusOutlined', component: MinusOutlined, label: '减少' },
  { name: 'DeleteOutlined', component: DeleteOutlined, label: '删除' },
  { name: 'EyeOutlined', component: EyeOutlined, label: '查看' },
  { name: 'EyeInvisibleOutlined', component: EyeInvisibleOutlined, label: '隐藏' },
  { name: 'DownloadOutlined', component: DownloadOutlined, label: '下载' },
  { name: 'UploadOutlined', component: UploadOutlined, label: '上传' },
  { name: 'ReloadOutlined', component: ReloadOutlined, label: '刷新' },
  { name: 'PlayCircleOutlined', component: PlayCircleOutlined, label: '播放' },
  { name: 'PauseCircleOutlined', component: PauseCircleOutlined, label: '暂停' },
  { name: 'StopOutlined', component: StopOutlined, label: '停止' },
  { name: 'CheckOutlined', component: CheckOutlined, label: '勾选' },
  { name: 'CloseCircleOutlined', component: CloseCircleOutlined, label: '关闭' },
  { name: 'WarningOutlined', component: WarningOutlined, label: '警告' },
  { name: 'InfoCircleOutlined', component: InfoCircleOutlined, label: '信息' },
  { name: 'QuestionCircleOutlined', component: QuestionCircleOutlined, label: '问号' },
  { name: 'LinkOutlined', component: LinkOutlined, label: '链接' },
  { name: 'ShareAltOutlined', component: ShareAltOutlined, label: '分享' },
  { name: 'CopyOutlined', component: CopyOutlined, label: '复制' },
  { name: 'ScissorOutlined', component: ScissorOutlined, label: '剪切' },
  { name: 'PrinterOutlined', component: PrinterOutlined, label: '打印' },
  { name: 'ShoppingCartOutlined', component: ShoppingCartOutlined, label: '购物车' },
  { name: 'ShoppingOutlined', component: ShoppingOutlined, label: '商店' },
  { name: 'GiftOutlined', component: GiftOutlined, label: '礼物' },
  { name: 'TrophyOutlined', component: TrophyOutlined, label: '奖杯' },
  { name: 'CrownOutlined', component: CrownOutlined, label: '皇冠' },
  { name: 'BulbOutlined', component: BulbOutlined, label: '灯泡' },
  { name: 'ExperimentOutlined', component: ExperimentOutlined, label: '实验' },
  { name: 'BugOutlined', component: BugOutlined, label: '错误' },
  { name: 'CodeOutlined', component: CodeOutlined, label: '代码' },
  { name: 'ApiOutlined', component: ApiOutlined, label: 'API' },
  { name: 'AppstoreOutlined', component: AppstoreOutlined, label: '应用' },
  { name: 'BarsOutlined', component: BarsOutlined, label: '菜单' },
  { name: 'MenuOutlined', component: MenuOutlined, label: '菜单' },
  { name: 'LayoutOutlined', component: LayoutOutlined, label: '布局' },
  { name: 'TableOutlined', component: TableOutlined, label: '表格' },
  { name: 'UnorderedListOutlined', component: UnorderedListOutlined, label: '列表' },
  { name: 'OrderedListOutlined', component: OrderedListOutlined, label: '有序列表' },
  { name: 'PictureOutlined', component: PictureOutlined, label: '图片' },
  { name: 'VideoCameraOutlined', component: VideoCameraOutlined, label: '视频' },
  { name: 'SoundOutlined', component: SoundOutlined, label: '声音' },
  { name: 'CustomerServiceOutlined', component: CustomerServiceOutlined, label: '客服' },
  { name: 'GlobalOutlined', component: GlobalOutlined, label: '全球' },
  { name: 'EnvironmentOutlined', component: EnvironmentOutlined, label: '位置' },
  { name: 'CompassOutlined', component: CompassOutlined, label: '指南针' },
  { name: 'CarOutlined', component: CarOutlined, label: '汽车' },
  { name: 'BankOutlined', component: BankOutlined, label: '银行' },
  { name: 'ShopOutlined', component: ShopOutlined, label: '商店' },
  { name: 'MedicineBoxOutlined', component: MedicineBoxOutlined, label: '医药' },
  { name: 'SafetyCertificateOutlined', component: SafetyCertificateOutlined, label: '证书' },
  { name: 'InsuranceOutlined', component: InsuranceOutlined, label: '保险' },
  { name: 'FileProtectOutlined', component: FileProtectOutlined, label: '保护' },
  { name: 'FileSyncOutlined', component: FileSyncOutlined, label: '同步' },
  { name: 'FileSearchOutlined', component: FileSearchOutlined, label: '搜索文件' },
  { name: 'FileAddOutlined', component: FileAddOutlined, label: '添加文件' },
  { name: 'FileExcelOutlined', component: FileExcelOutlined, label: 'Excel' },
  { name: 'FilePdfOutlined', component: FilePdfOutlined, label: 'PDF' },
  { name: 'FileWordOutlined', component: FileWordOutlined, label: 'Word' },
  { name: 'FileImageOutlined', component: FileImageOutlined, label: '图片文件' },
  { name: 'FileZipOutlined', component: FileZipOutlined, label: '压缩包' },
  { name: 'FolderAddOutlined', component: FolderAddOutlined, label: '添加文件夹' },
  { name: 'FolderViewOutlined', component: FolderViewOutlined, label: '查看文件夹' },
  { name: 'ProjectOutlined', component: ProjectOutlined, label: '项目' },
  { name: 'BuildOutlined', component: BuildOutlined, label: '构建' },
  { name: 'RobotOutlined', component: RobotOutlined, label: '机器人' },
];

// 图标名称到组件的映射
const iconNameMap: Record<string, React.ComponentType<any>> = {
  ToolOutlined,
  CheckCircleOutlined,
  FileTextOutlined,
  EditOutlined,
  SafetyOutlined,
  UnlockOutlined,
  LockOutlined,
  CheckSquareOutlined,
  HomeOutlined,
  UserOutlined,
  TeamOutlined,
  SettingOutlined,
  FolderOutlined,
  FileOutlined,
  FolderOpenOutlined,
  DatabaseOutlined,
  CloudOutlined,
  ThunderboltOutlined,
  FireOutlined,
  RocketOutlined,
  StarOutlined,
  HeartOutlined,
  BellOutlined,
  MessageOutlined,
  PhoneOutlined,
  MailOutlined,
  CalendarOutlined,
  ClockCircleOutlined,
  SearchOutlined,
  PlusOutlined,
  MinusOutlined,
  DeleteOutlined,
  EyeOutlined,
  EyeInvisibleOutlined,
  DownloadOutlined,
  UploadOutlined,
  ReloadOutlined,
  PlayCircleOutlined,
  PauseCircleOutlined,
  StopOutlined,
  CheckOutlined,
  CloseCircleOutlined,
  WarningOutlined,
  InfoCircleOutlined,
  QuestionCircleOutlined,
  LinkOutlined,
  ShareAltOutlined,
  CopyOutlined,
  ScissorOutlined,
  PrinterOutlined,
  ShoppingCartOutlined,
  ShoppingOutlined,
  GiftOutlined,
  TrophyOutlined,
  CrownOutlined,
  BulbOutlined,
  ExperimentOutlined,
  BugOutlined,
  CodeOutlined,
  ApiOutlined,
  AppstoreOutlined,
  BarsOutlined,
  MenuOutlined,
  LayoutOutlined,
  TableOutlined,
  UnorderedListOutlined,
  OrderedListOutlined,
  PictureOutlined,
  VideoCameraOutlined,
  SoundOutlined,
  CustomerServiceOutlined,
  GlobalOutlined,
  EnvironmentOutlined,
  CompassOutlined,
  CarOutlined,
  BankOutlined,
  ShopOutlined,
  MedicineBoxOutlined,
  SafetyCertificateOutlined,
  InsuranceOutlined,
  FileProtectOutlined,
  FileSyncOutlined,
  FileSearchOutlined,
  FileAddOutlined,
  FileExcelOutlined,
  FilePdfOutlined,
  FileWordOutlined,
  FileImageOutlined,
  FileZipOutlined,
  FolderAddOutlined,
  FolderViewOutlined,
  ProjectOutlined,
  BuildOutlined,
  RobotOutlined,
};

// 自定义节点组件
function CustomNode({ data, selected, id }: any) {
  // 优先使用自定义图标，否则使用节点类型对应的图标
  let Icon = FileTextOutlined;
  let config = null;
  
  if (data.icon && iconNameMap[data.icon]) {
    // 使用自定义图标
    Icon = iconNameMap[data.icon];
    // 尝试找到对应的配置（保持颜色等样式）
    config = nodeConfigs.find(c => c.icon === Icon);
    if (!config) {
      // 如果找不到配置，使用默认配置
      config = nodeConfigs.find(c => c.type === data.type) || nodeConfigs[0];
    }
  } else {
    // 使用节点类型对应的图标
    config = nodeConfigs.find(c => c.type === data.type);
    Icon = config?.icon || FileTextOutlined;
  }
  // 从节点ID中提取序号，或使用data中的nodeId
  const nodeId = data.nodeId || (id ? String(parseInt(id.split('-').pop() || '0') % 1000).padStart(3, '0') : '001');
  
  return (
    <div
      className={`relative px-4 py-4 rounded-lg shadow-sm border-2 w-[180px] h-auto min-h-[140px] bg-white ${
        selected
          ? 'border-blue-500 shadow-md ring-1 ring-blue-200'
          : 'border-gray-200 hover:border-gray-300'
      } transition-all`}
    >
      {/* 连接点 - 四个方向，每个方向都有唯一的 source 和 target Handle */}
      <Handle
        id="top-source"
        type="source"
        position={Position.Top}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ top: -6, left: '50%', transform: 'translateX(-50%)' }}
        isConnectable={true}
      />
      <Handle
        id="top-target"
        type="target"
        position={Position.Top}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ top: -6, left: '50%', transform: 'translateX(-50%)' }}
        isConnectable={true}
      />
      <Handle
        id="bottom-source"
        type="source"
        position={Position.Bottom}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ bottom: -6, left: '50%', transform: 'translateX(-50%)' }}
        isConnectable={true}
      />
      <Handle
        id="bottom-target"
        type="target"
        position={Position.Bottom}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ bottom: -6, left: '50%', transform: 'translateX(-50%)' }}
        isConnectable={true}
      />
      <Handle
        id="left-source"
        type="source"
        position={Position.Left}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ left: -6, top: '50%', transform: 'translateY(-50%)' }}
        isConnectable={true}
      />
      <Handle
        id="left-target"
        type="target"
        position={Position.Left}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ left: -6, top: '50%', transform: 'translateY(-50%)' }}
        isConnectable={true}
      />
      <Handle
        id="right-source"
        type="source"
        position={Position.Right}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ right: -6, top: '50%', transform: 'translateY(-50%)' }}
        isConnectable={true}
      />
      <Handle
        id="right-target"
        type="target"
        position={Position.Right}
        className="!w-3 !h-3 !bg-green-500 !border-2 !border-white !rounded-full !shadow-sm"
        style={{ right: -6, top: '50%', transform: 'translateY(-50%)' }}
        isConnectable={true}
      />
      
      {/* 垂直布局：顶部图标、中间名称、底部ID */}
      <div className="flex flex-col items-center justify-between gap-3 h-full">
        {/* 顶部：图标 */}
        <div className={`${config?.bgColor || 'bg-gray-50'} ${config?.borderColor || 'border-gray-100'} border p-3 rounded-xl shadow-sm flex items-center justify-center flex-shrink-0`} style={{ borderRadius: '12px' }}>
          <Icon 
            className={`${config?.iconColor || 'text-gray-600'} text-2xl`} 
            style={{ color: config?.iconColorCustom || undefined }}
          />
        </div>
        {/* 中间：节点名称 */}
        <div className="font-semibold text-sm text-gray-900 leading-tight text-center break-words w-full flex-1 flex items-center justify-center px-1">
          {data.label || config?.label}
        </div>
        {/* 底部：ID */}
        <div className="text-xs text-gray-500 text-center flex-shrink-0">
          ID: {nodeId}
        </div>
      </div>
    </div>
  );
}

// 各个节点类型
function CreateJobNode(props: any) {
  return <CustomNode {...props} />;
}

function ConfirmNode(props: any) {
  return <CustomNode {...props} />;
}

function ReviewNode(props: any) {
  return <CustomNode {...props} />;
}

function InputInfoNode(props: any) {
  return <CustomNode {...props} />;
}

function IsolationNode(props: any) {
  return <CustomNode {...props} />;
}

function ReleaseIsolationNode(props: any) {
  return <CustomNode {...props} />;
}

function ReturnLockNode(props: any) {
  return <CustomNode {...props} />;
}

function CompleteNode(props: any) {
  return <CustomNode {...props} />;
}

// 自定义节点类型映射
const nodeTypes = {
  createJob: CreateJobNode,
  confirm: ConfirmNode,
  review: ReviewNode,
  inputInfo: InputInfoNode,
  isolation: IsolationNode,
  releaseIsolation: ReleaseIsolationNode,
  returnLock: ReturnLockNode,
  complete: CompleteNode,
};

// 全局变量存储删除函数（用于边组件）
let globalDeleteEdgeFn: ((id: string) => void) | null = null;

// 自定义边组件 - 定义在组件外部以确保稳定引用
function CustomEdgeWithDelete({
  id,
  sourceX,
  sourceY,
  targetX,
  targetY,
  selected,
  markerEnd,
  style,
}: any) {
  const [edgePath, labelX, labelY] = getStraightPath({
    sourceX,
    sourceY,
    targetX,
    targetY,
  });

  console.log('边组件渲染，ID:', id, 'selected:', selected, 'labelX:', labelX, 'labelY:', labelY);

  return (
    <>
      <BaseEdge
        id={id}
        path={edgePath}
        markerEnd={markerEnd}
        style={{
          ...style,
          strokeWidth: selected ? 3 : 2,
          stroke: selected ? '#3b82f6' : '#94a3b8',
        }}
      />
      {selected && (
        <EdgeLabelRenderer>
          <div
            style={{
              position: 'absolute',
              left: labelX,
              top: labelY,
              transform: 'translate(-50%, -50%)',
              pointerEvents: 'all',
              zIndex: 1000,
            }}
            className="nodrag nopan"
          >
            <button
              onClick={(e) => {
                e.stopPropagation();
                e.preventDefault();
                console.log('删除按钮被点击，连线ID:', id);
                if (globalDeleteEdgeFn) {
                  globalDeleteEdgeFn(id);
                }
              }}
              onMouseDown={(e) => {
                e.stopPropagation();
              }}
              className="bg-red-500 hover:bg-red-600 rounded-full p-1.5 shadow-lg transition-colors flex items-center justify-center w-8 h-8"
              title="删除连线"
              type="button"
              style={{ cursor: 'pointer' }}
            >
              <DeleteOutlined className="text-sm text-white" style={{ color: 'white' }} />
            </button>
          </div>
        </EdgeLabelRenderer>
      )}
    </>
  );
}

// 自定义边类型映射 - 定义在组件外部
const edgeTypes: EdgeTypes = {
  straight: CustomEdgeWithDelete,
  default: CustomEdgeWithDelete,
};


export default function ProcessDesigner() {
  const navigate = useNavigate();
  const location = useLocation();
  const [nodes, setNodes, onNodesChange] = useNodesState([]);
  const [edges, setEdges, onEdgesChange] = useEdgesState([]);
  
  // 从URL参数获取流程ID
  const workflowId = React.useMemo(() => {
    const params = new URLSearchParams(location.search);
    const id = params.get('id');
    return id ? parseInt(id, 10) : null;
  }, [location.search]);
  const [selectedNode, setSelectedNode] = useState<Node | null>(null);
  const [selectedEdge, setSelectedEdge] = useState<Edge | null>(null);
  const [activeTabKey, setActiveTabKey] = useState<string>('info');
  const reactFlowWrapper = useRef<HTMLDivElement>(null);
  const [reactFlowInstance, setReactFlowInstance] = useState<any>(null);
  const [zoom, setZoom] = useState(1);
  const [iconPickerOpen, setIconPickerOpen] = useState(false);
  // 简单缓存：将每个节点的配置持久化到 sessionStorage，key 按节点ID
  const cachePrefix = 'process_designer_node_';
  const [exportVisible, setExportVisible] = useState(false);
  const [exportContent, setExportContent] = useState('');
  const [importVisible, setImportVisible] = useState(false);
  const [importJson, setImportJson] = useState('');
  // 存储工作流详情（name、description等）
  const [workflowDetail, setWorkflowDetail] = useState<WorkflowDesignVO | null>(null);
  const [loadingDetail, setLoadingDetail] = useState(false);
  
  // 角色用户列表
  const [drawerUsers, setDrawerUsers] = useState<UserVO[]>([]); // 负责人（jtdrawer）
  const [lockerUsers, setLockerUsers] = useState<UserVO[]>([]); // 上锁人（jtlocker）
  const [colockerUsers, setColockerUsers] = useState<UserVO[]>([]); // 共锁人（jtcolocker）
  // 隔离点列表
  const [isolationPoints, setIsolationPoints] = useState<SegregationPointVO[]>([]);
  // 表单列表
  const [formList, setFormList] = useState<FormVO[]>([]);

  const loadNodeCache = useCallback((nodeId: string) => {
    try {
      const raw = sessionStorage.getItem(`${cachePrefix}${nodeId}`);
      if (!raw) return null;
      return JSON.parse(raw);
    } catch {
      return null;
    }
  }, []);

  const saveNodeCache = useCallback((nodeId: string, data: any) => {
    try {
      sessionStorage.setItem(`${cachePrefix}${nodeId}`, JSON.stringify(data));
    } catch {
      // ignore
    }
  }, []);

  // 调试：监听 edges 变化
  useEffect(() => {
    console.log('Edges 状态更新:', edges.length, edges);
  }, [edges]);

  // 加载角色用户列表和隔离点列表
  useEffect(() => {
    const loadRoleUsers = async () => {
      try {
        // 并行加载三种角色的用户
        const [drawerRes, lockerRes, colockerRes] = await Promise.all([
          userApi.getRoleUser('jtdrawer'),
          userApi.getRoleUser('jtlocker'),
          userApi.getRoleUser('jtcolocker'),
        ]);
        setDrawerUsers(drawerRes || []);
        setLockerUsers(lockerRes || []);
        setColockerUsers(colockerRes || []);
      } catch (error) {
        console.error('加载角色用户失败:', error);
      }
    };
    
    const loadIsolationPoints = async () => {
      try {
        const res = await segregationPointApi.getIsIsolationPointPage({ pageNo: 1, pageSize: -1 });
        setIsolationPoints(res.list || []);
      } catch (error) {
        console.error('加载隔离点列表失败:', error);
      }
    };
    
    const loadFormList = async () => {
      try {
        const res = await getFormPage({ pageNo: 1, pageSize: -1 });
        setFormList(res.list || []);
      } catch (error) {
        console.error('加载表单列表失败:', error);
      }
    };
    
    loadRoleUsers();
    loadIsolationPoints();
    loadFormList();
  }, []);

  // 节点配置状态
  const [nodeConfig, setNodeConfig] = useState({
    nodeName: '',
    nodeIcon: '',
    responsible: '',
    remark: '',
    submitForm: '',
    isolationMethod: '', // 隔离方式
    isolationPoints: [] as string[], // 隔离点选择（多选）
    isolationNode: [] as string[], // 隔离节点（多选）
    selectedIsolationNodeId: '', // 选择的隔离/方案节点ID（用于解除隔离节点）
    lockPerson: '', // 上锁人
    coLockPersons: [] as string[], // 共锁人（多选）
    notificationMethods: {
      sms: false,
      message: false,
      email: false,
      app: false,
    },
    notificationPerson: '',
    notificationTime: '',
  });

  // 实时缓存并更新节点配置，避免切换节点后丢失未保存的输入
  useEffect(() => {
    if (selectedNode) {
      const updatedData = {
        ...selectedNode.data,
        label: nodeConfig.nodeName,
        icon: nodeConfig.nodeIcon,
        responsible: nodeConfig.responsible,
        remark: nodeConfig.remark,
        submitForm: nodeConfig.submitForm,
        isolationMethod: nodeConfig.isolationMethod,
        isolationPoints: nodeConfig.isolationPoints,
        isolationNode: nodeConfig.isolationNode,
        selectedIsolationNodeId: nodeConfig.selectedIsolationNodeId,
        lockPerson: nodeConfig.lockPerson,
        coLockPersons: nodeConfig.coLockPersons,
        notificationMethods: nodeConfig.notificationMethods,
        notificationPerson: nodeConfig.notificationPerson,
        notificationTime: nodeConfig.notificationTime,
        nodeName: nodeConfig.nodeName,
        nodeIcon: nodeConfig.nodeIcon,
      };
      // 缓存配置
      saveNodeCache(selectedNode.id, updatedData);
      // 实时更新节点显示
      setNodes((nds) =>
        nds.map((node) =>
          node.id === selectedNode.id
            ? { ...node, data: updatedData }
            : node
        )
      );
    }
  }, [nodeConfig, selectedNode, saveNodeCache, setNodes]);

  // 历史记录（用于撤销/重做）
  const [history, setHistory] = useState<{ nodes: Node[]; edges: Edge[] }[]>([]);
  const [historyIndex, setHistoryIndex] = useState(-1);

  // 加载 JSON 数据到画布（可复用的函数）
  const loadJsonToCanvas = useCallback((jsonString: string, updateHistory: boolean = false) => {
    try {
      const data = JSON.parse(jsonString);
      
      if (!data.nodes || !Array.isArray(data.nodes)) {
        message.error('JSON 格式错误：缺少 nodes 数组');
        return false;
      }
      
      if (!data.edges || !Array.isArray(data.edges)) {
        message.error('JSON 格式错误：缺少 edges 数组');
        return false;
      }

      // 创建uuid到id的映射（导入时uuid改回id）
      const uuidToIdMap = new Map<string, string>();
      data.nodes.forEach((node: any) => {
        // 兼容处理：支持uuid字段或id字段
        const nodeId = node.uuid || node.id;
        uuidToIdMap.set(nodeId, nodeId); // 值保持不变
      });

      // 还原节点，确保 data 包含所有配置字段
      const importedNodes = data.nodes.map((node: any) => {
        const nodeData = node.data || {};
        // 兼容处理：支持uuid字段或id字段
        const nodeId = node.uuid || node.id;
        
        // 如果顶层有 nodeName 和 nodeIcon，将它们还原到 data 中
        const topLevelLabel = node.nodeName || '';
        const topLevelIcon = node.nodeIcon || '';
        
        // 确保所有字段都存在，使用默认值填充缺失的字段
        const completeData = {
          label: topLevelLabel || nodeData.label || '', // 优先使用顶层的 nodeName
          type: nodeData.type || node.type,
          nodeId: nodeData.nodeId || '',
          icon: topLevelIcon || nodeData.icon || nodeData.type || node.type, // 优先使用顶层的 nodeIcon
          responsible: nodeData.responsible || '',
          remark: nodeData.remark || '',
          submitForm: nodeData.submitForm || '',
          isolationMethod: nodeData.isolationMethod || '',
          isolationPoints: Array.isArray(nodeData.isolationPoints) ? nodeData.isolationPoints : [],
          isolationNode: Array.isArray(nodeData.isolationNode) ? nodeData.isolationNode : [],
          selectedIsolationNodeId: nodeData.selectedIsolationNodeId || '',
          lockPerson: nodeData.lockPerson || '',
          coLockPersons: Array.isArray(nodeData.coLockPersons) ? nodeData.coLockPersons : [],
          notificationMethods: nodeData.notificationMethods || {
            sms: false,
            message: false,
            email: false,
            app: false,
          },
          notificationPerson: nodeData.notificationPerson || '',
          notificationTime: nodeData.notificationTime || '',
          ...nodeData, // 保留其他可能的字段
        };
        
        return {
          id: nodeId, // 使用uuid或id作为id
          type: node.type,
          position: node.position || { x: 0, y: 0 },
          data: completeData,
        };
      });

      // 还原连接线（source和target需要从uuid映射回id）
      const importedEdges = data.edges.map((edge: any) => {
        // 兼容处理：如果source/target是uuid，映射回id；如果是id，直接使用
        const sourceId = uuidToIdMap.get(edge.source) || edge.source;
        const targetId = uuidToIdMap.get(edge.target) || edge.target;
        
        return {
          id: edge.id,
          source: sourceId,
          target: targetId,
          sourceHandle: edge.sourceHandle,
          targetHandle: edge.targetHandle,
          type: edge.type || 'straight',
          animated: false,
          style: { strokeWidth: 2, stroke: '#94a3b8' },
        };
      });

      // 更新节点和边
      setNodes(importedNodes);
      setEdges(importedEdges);

      // 缓存每个节点的配置（确保缓存包含完整数据）
      importedNodes.forEach((node: Node) => {
        if (node.data) {
          saveNodeCache(node.id, node.data);
        }
      });

      // 如果需要更新历史记录（初始化加载时）
      if (updateHistory) {
        setHistory([{ nodes: importedNodes, edges: importedEdges }]);
        setHistoryIndex(0);
      }

      return true;
    } catch (error: any) {
      console.error('加载 JSON 失败:', error);
      message.error('JSON 格式错误：' + (error?.message || '解析失败'));
      return false;
    }
  }, [saveNodeCache, setNodes, setEdges, setHistory, setHistoryIndex]);

  // 进入页面时获取工作流详情
  useEffect(() => {
    const fetchWorkflowDetail = async () => {
      if (!workflowId) {
        return;
      }

      setLoadingDetail(true);
      try {
        const detail = await workflowDesignApi.selectWorkflowDesignById(workflowId);
        setWorkflowDetail(detail);
        
        // 如果有 content，加载到画布上（初始化时更新历史记录）
        if (detail.content) {
          loadJsonToCanvas(detail.content, true);
        }
      } catch (error: any) {
        console.error('获取工作流详情失败:', error);
        message.error(error?.message || '获取工作流详情失败');
      } finally {
        setLoadingDetail(false);
      }
    };

    fetchWorkflowDetail();
  }, [workflowId, loadJsonToCanvas]);

  // 拖拽处理
  const onDragStart = (event: React.DragEvent, nodeType: string) => {
    event.dataTransfer.setData('application/reactflow', nodeType);
    event.dataTransfer.effectAllowed = 'move';
  };

  // 验证连接是否有效（允许所有连接）
  const isValidConnection = useCallback((connection: Connection) => {
    // 允许从任意方向连接到任意方向
    if (!connection.source || !connection.target) {
      return false;
    }
    // 不允许节点连接到自身
    if (connection.source === connection.target) {
      return false;
    }
    return true;
  }, []);

  // 修正 Handle 类型的辅助函数
  const fixHandleType = (handleId: string | null | undefined, isSource: boolean): string | undefined => {
    if (!handleId) return undefined;
    
    // 如果 sourceHandle 是 target 类型，转换为对应的 source Handle
    if (isSource && handleId.endsWith('-target')) {
      const position = handleId.replace('-target', '');
      return `${position}-source`;
    }
    
    // 如果 targetHandle 是 source 类型，转换为对应的 target Handle
    if (!isSource && handleId.endsWith('-source')) {
      const position = handleId.replace('-source', '');
      return `${position}-target`;
    }
    
    return handleId;
  };

  // 连接处理
  const onConnect = useCallback(
    (params: Connection) => {
      // 确保连接参数包含 sourceHandle 和 targetHandle
      console.log('连接参数:', params);
      if (!params.source || !params.target) {
        console.warn('连接参数无效:', params);
        return;
      }
      if (params.source === params.target) {
        console.warn('不能连接节点到自身');
        return;
      }
      
      // 修正 Handle 类型
      let sourceHandle = fixHandleType(params.sourceHandle, true);
      let targetHandle = fixHandleType(params.targetHandle, false);
      
      if (sourceHandle !== params.sourceHandle || targetHandle !== params.targetHandle) {
        console.log('修正 Handle 类型:', {
          sourceHandle: `${params.sourceHandle} -> ${sourceHandle}`,
          targetHandle: `${params.targetHandle} -> ${targetHandle}`
        });
      }
      
      setEdges((eds) => {
        // 检查是否已存在相同的连接（只检查 source 和 target）
        const existingEdgeIndex = eds.findIndex(
          (edge) =>
            edge.source === params.source &&
            edge.target === params.target
        );
        
        if (existingEdgeIndex !== -1) {
          console.log('连接已存在，更新连接点:', { 
            old: { sourceHandle: eds[existingEdgeIndex].sourceHandle, targetHandle: eds[existingEdgeIndex].targetHandle },
            new: { sourceHandle, targetHandle }
          });
          // 更新现有连接的 Handle
          const updatedEdges = [...eds];
          updatedEdges[existingEdgeIndex] = {
            ...updatedEdges[existingEdgeIndex],
            sourceHandle,
            targetHandle,
          };
          // 保存历史
          const newHistory = history.slice(0, historyIndex + 1);
          newHistory.push({ nodes: [...nodes], edges: [...updatedEdges] });
          setHistory(newHistory);
          setHistoryIndex(newHistory.length - 1);
          return updatedEdges;
        }
        
        const edgeId = `edge-${params.source}-${sourceHandle || 'default'}-${params.target}-${targetHandle || 'default'}-${Date.now()}`;
        const newEdge: Edge = {
          id: edgeId,
          source: params.source!,
          target: params.target!,
          sourceHandle: sourceHandle || undefined,
          targetHandle: targetHandle || undefined,
          animated: false,
          style: { strokeWidth: 2, stroke: '#94a3b8' },
          type: 'straight',
        };
        // 直接添加到数组，不使用 addEdge（因为 addEdge 可能会过滤掉某些连接）
        const newEdges = [...eds, newEdge];
        console.log('新连接已添加:', newEdge);
        console.log('当前所有连接数量:', newEdges.length);
        // 保存历史
        const newHistory = history.slice(0, historyIndex + 1);
        newHistory.push({ nodes: [...nodes], edges: [...newEdges] });
        setHistory(newHistory);
        setHistoryIndex(newHistory.length - 1);
        return newEdges;
      });
    },
    [setEdges, history, historyIndex, nodes]
  );

  // 更新连接线（拖拽边的端点重新连接）
  const onEdgeUpdate = useCallback(
    (oldEdge: Edge, newConnection: Connection) => {
      console.log('更新连接线:', { oldEdge, newConnection });
      
      if (!newConnection.source || !newConnection.target) {
        console.warn('新连接参数无效');
        return;
      }
      
      if (newConnection.source === newConnection.target) {
        console.warn('不能连接节点到自身');
        return;
      }
      
      // 修正 Handle 类型
      let sourceHandle = fixHandleType(newConnection.sourceHandle, true);
      let targetHandle = fixHandleType(newConnection.targetHandle, false);
      
      setEdges((eds) => {
        // 找到要更新的边
        const edgeIndex = eds.findIndex((edge) => edge.id === oldEdge.id);
        
        if (edgeIndex === -1) {
          console.warn('未找到要更新的边');
          return eds;
        }
        
        // 检查新连接是否与现有连接冲突（除了当前要更新的边）
        const conflictingEdge = eds.find(
          (edge, index) =>
            index !== edgeIndex &&
            edge.source === newConnection.source &&
            edge.target === newConnection.target
        );
        
        if (conflictingEdge) {
          console.warn('连接已存在，无法更新');
          return eds;
        }
        
        // 更新边的连接点
        const updatedEdges = [...eds];
        updatedEdges[edgeIndex] = {
          ...updatedEdges[edgeIndex],
          source: newConnection.source!,
          target: newConnection.target!,
          sourceHandle: sourceHandle || undefined,
          targetHandle: targetHandle || undefined,
        };
        
        console.log('连接线已更新:', updatedEdges[edgeIndex]);
        
        // 保存历史
        const newHistory = history.slice(0, historyIndex + 1);
        newHistory.push({ nodes: [...nodes], edges: [...updatedEdges] });
        setHistory(newHistory);
        setHistoryIndex(newHistory.length - 1);
        
        return updatedEdges;
      });
    },
    [history, historyIndex, nodes]
  );

  // 节点点击处理
  const onNodeClick = useCallback((event: React.MouseEvent, node: Node) => {
    setSelectedNode(node);
    setSelectedEdge(null); // 点击节点时取消连线选择
    setActiveTabKey('info'); // 切换节点时重置到第一个tab
    // 清除所有边的选中状态
    setEdges((eds) =>
      eds.map((e) => ({
        ...e,
        selected: false,
      }))
    );
    // 加载节点配置
    const nodeData = node.data || {};
    const cache = loadNodeCache(node.id);
    const source = cache || nodeData;
    const config = nodeConfigs.find(c => c.type === source.type);
    
    // 如果是解除隔离节点且已选择了隔离节点，则从隔离节点获取配置
    let isolationMethod = source.isolationMethod || '';
    let isolationPointsData = source.isolationPoints || [];
    let lockPerson = source.lockPerson || '';
    let coLockPersons = source.coLockPersons || [];
    let responsible = source.responsible || '';
    
    if (source.type === 'releaseIsolation' && source.selectedIsolationNodeId) {
      const targetNode = nodes.find(n => n.id === source.selectedIsolationNodeId && n.data?.type === 'isolation');
      if (targetNode) {
        // 优先从缓存中读取，缓存中没有则从 node.data 读取
        const targetCache = loadNodeCache(targetNode.id);
        const targetSource = targetCache || targetNode.data || {};
        isolationMethod = targetSource.isolationMethod || '';
        isolationPointsData = targetSource.isolationPoints || [];
        lockPerson = targetSource.lockPerson || '';
        coLockPersons = targetSource.coLockPersons || [];
        responsible = targetSource.responsible || '';
      }
    }
    
    setNodeConfig({
      nodeName: source.label || config?.label || '',
      nodeIcon: source.icon || source.type || '',
      responsible: responsible,
      remark: source.remark || '',
      submitForm: source.submitForm || '',
      isolationMethod: isolationMethod,
      isolationPoints: isolationPointsData,
      isolationNode: Array.isArray(source.isolationNode) ? source.isolationNode : (source.isolationNode ? [source.isolationNode] : []),
      selectedIsolationNodeId: source.selectedIsolationNodeId || '',
      lockPerson: lockPerson,
      coLockPersons: coLockPersons,
      notificationMethods: source.notificationMethods || {
        sms: false,
        message: false,
        email: false,
        app: false,
      },
      notificationPerson: source.notificationPerson || '',
      notificationTime: source.notificationTime || '',
    });
  }, [loadNodeCache, nodes, setEdges]);

  // 画布点击处理（取消选择）
  const onPaneClick = useCallback(() => {
    setSelectedNode(null);
    setSelectedEdge(null);
    // 清除所有边的选中状态
    setEdges((eds) =>
      eds.map((e) => ({
        ...e,
        selected: false,
      }))
    );
  }, [setEdges]);

  // 连线点击处理
  const onEdgeClick = useCallback((event: React.MouseEvent, edge: Edge) => {
    event.stopPropagation();
    console.log('连线被点击:', edge.id, '当前type:', edge.type);
    setSelectedEdge(edge);
    setSelectedNode(null); // 点击连线时取消节点选择
    // 更新边的选中状态，并确保类型是 straight
    setEdges((eds) => {
      const updatedEdges = eds.map((e) => ({
        ...e,
        type: 'straight', // 强制设置为 straight 类型
        selected: e.id === edge.id,
      }));
      const clickedEdge = updatedEdges.find(e => e.id === edge.id);
      console.log('更新后的边状态:', clickedEdge?.selected, 'type:', clickedEdge?.type);
      return updatedEdges;
    });
  }, [setEdges]);

  // 删除连线
  const handleDeleteEdge = useCallback((edgeId: string) => {
    console.log('删除连线:', edgeId);
    setEdges((eds) => {
      const newEdges = eds.filter((edge) => edge.id !== edgeId);
      console.log('删除后的连线数量:', newEdges.length);
      // 保存历史
      const newHistory = history.slice(0, historyIndex + 1);
      newHistory.push({ nodes: [...nodes], edges: [...newEdges] });
      setHistory(newHistory);
      setHistoryIndex(newHistory.length - 1);
      return newEdges;
    });
    setSelectedEdge(null);
  }, [history, historyIndex, nodes]);

  // 更新全局删除函数
  useEffect(() => {
    globalDeleteEdgeFn = handleDeleteEdge;
    return () => {
      globalDeleteEdgeFn = null;
    };
  }, [handleDeleteEdge]);

  // 确保所有边都使用 'straight' 类型（用于自定义边组件）
  useEffect(() => {
    setEdges((eds) => {
      const needsUpdate = eds.some(e => e.type !== 'straight');
      if (needsUpdate) {
        console.log('统一设置所有边的类型为 straight');
        return eds.map(e => ({
          ...e,
          type: 'straight',
        }));
      }
      return eds;
    });
  }, []); // 只在组件挂载时执行一次

  // 删除节点
  const handleDeleteNode = useCallback((nodeId?: string) => {
    const targetNodeId = nodeId || selectedNode?.id;
    if (!targetNodeId) return;

    Modal.confirm({
      title: '确认删除',
      content: '确定要删除这个节点吗？删除后无法恢复。',
      okText: '确定删除',
      okType: 'danger',
      cancelText: '取消',
      onOk: () => {
        setNodes((nds) => {
          const newNodes = nds.filter((node) => node.id !== targetNodeId);
          // 同时删除相关的边
          setEdges((eds) => {
            const newEdges = eds.filter(
              (edge) => edge.source !== targetNodeId && edge.target !== targetNodeId
            );
            // 保存历史
            const newHistory = history.slice(0, historyIndex + 1);
            newHistory.push({ nodes: [...newNodes], edges: [...newEdges] });
            setHistory(newHistory);
            setHistoryIndex(newHistory.length - 1);
            return newEdges;
          });
          // 保存历史
          const newHistory = history.slice(0, historyIndex + 1);
          newHistory.push({ nodes: [...newNodes], edges: [...edges] });
          setHistory(newHistory);
          setHistoryIndex(newHistory.length - 1);
          return newNodes;
        });
        if (selectedNode?.id === targetNodeId) {
          setSelectedNode(null);
        }
        toast.success('节点已删除');
      },
    });
  }, [selectedNode, setNodes, setEdges, history, historyIndex, edges]);

  // 键盘事件处理（Delete 键删除节点）
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      // 如果焦点在输入框、文本域或可编辑元素中，不触发删除节点
      const target = event.target as HTMLElement;
      const isInputElement = 
        target.tagName === 'INPUT' || 
        target.tagName === 'TEXTAREA' || 
        target.isContentEditable ||
        target.closest('input') ||
        target.closest('textarea') ||
        target.closest('[contenteditable="true"]');
      
      if (isInputElement) {
        return; // 在输入框中，不处理删除节点
      }
      
      if ((event.key === 'Delete' || event.key === 'Backspace') && selectedNode) {
        event.preventDefault();
        handleDeleteNode();
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [selectedNode, handleDeleteNode]);

  // 右键菜单处理
  const onNodeContextMenu = useCallback(
    (event: React.MouseEvent, node: Node) => {
      event.preventDefault();
      setSelectedNode(node);
    },
    []
  );

  // 撤销
  const handleUndo = useCallback(() => {
    if (historyIndex > 0) {
      const prevState = history[historyIndex - 1];
      setNodes(prevState.nodes);
      setEdges(prevState.edges);
      setHistoryIndex(historyIndex - 1);
    }
  }, [history, historyIndex, setNodes, setEdges]);

  // 重做
  const handleRedo = useCallback(() => {
    if (historyIndex < history.length - 1) {
      const nextState = history[historyIndex + 1];
      setNodes(nextState.nodes);
      setEdges(nextState.edges);
      setHistoryIndex(historyIndex + 1);
    }
  }, [history, historyIndex, setNodes, setEdges]);

  // 拖放处理
  const onDrop = useCallback(
    (event: React.DragEvent) => {
      event.preventDefault();

      const type = event.dataTransfer.getData('application/reactflow');
      if (!type || !reactFlowInstance) return;

      const position = reactFlowInstance.screenToFlowPosition({
        x: event.clientX,
        y: event.clientY,
      });

      const config = nodeConfigs.find(c => c.type === type);
      const timestamp = Date.now();
      const nodeId = `${type}-${timestamp}`;
      const nodeNumber = nodes.length + 1;
      const newNode: Node = {
        id: nodeId,
        type,
        position,
        data: {
          label: config?.label || type,
          type,
          nodeId: String(nodeNumber).padStart(3, '0'),
        },
      };

      setNodes((nds) => {
        const newNodes = nds.concat(newNode);
        // 保存历史
        const newHistory = history.slice(0, historyIndex + 1);
        newHistory.push({ nodes: [...newNodes], edges: [...edges] });
        setHistory(newHistory);
        setHistoryIndex(newHistory.length - 1);
        return newNodes;
      });
    },
    [reactFlowInstance, setNodes, history, historyIndex, edges, nodes.length]
  );

  const onDragOver = useCallback((event: React.DragEvent) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = 'move';
  }, []);

  // 更新节点配置
  const updateNodeConfig = useCallback(() => {
    if (!selectedNode) return;

    setNodes((nds) => {
      const updatedNodes = nds.map((node) => {
        if (node.id === selectedNode.id) {
          const updatedNode = {
            ...node,
            data: {
              ...node.data,
              label: nodeConfig.nodeName,
              type: nodeConfig.nodeIcon || node.data?.type, // 更新节点类型（图标）
              icon: nodeConfig.nodeIcon, // 保存图标名称
              responsible: nodeConfig.responsible,
              remark: nodeConfig.remark,
              submitForm: nodeConfig.submitForm,
              isolationMethod: nodeConfig.isolationMethod,
              isolationPoints: nodeConfig.isolationPoints,
              isolationNode: nodeConfig.isolationNode,
              selectedIsolationNodeId: nodeConfig.selectedIsolationNodeId,
              lockPerson: nodeConfig.lockPerson,
              coLockPersons: nodeConfig.coLockPersons,
              notificationMethods: nodeConfig.notificationMethods,
              notificationPerson: nodeConfig.notificationPerson,
              notificationTime: nodeConfig.notificationTime,
            },
          };
          // 缓存当前节点配置
          saveNodeCache(node.id, updatedNode.data);
          // 更新 selectedNode 的引用，以便顶部标题能显示最新值
          setSelectedNode(updatedNode);
          return updatedNode;
        }
        return node;
      });
      // 保存历史
      const newHistory = history.slice(0, historyIndex + 1);
      newHistory.push({ nodes: [...updatedNodes], edges: [...edges] });
      setHistory(newHistory);
      setHistoryIndex(newHistory.length - 1);
      return updatedNodes;
    });
    toast.success('节点配置已保存');
  }, [selectedNode, nodeConfig, setNodes, setSelectedNode, history, historyIndex, edges]);

  // 保存流程
  const handleSave = async () => {
    try {
      // 构建导出数据（与导出JSON逻辑相同）
      const adjacency: Record<string, { incoming: string[]; outgoing: string[] }> = {};
      const nodeIdMap = new Map<string, string>();
      nodes.forEach(n => {
        nodeIdMap.set(n.id, n.id);
      });

      nodes.forEach(n => {
        const uuid = nodeIdMap.get(n.id) || n.id;
        adjacency[uuid] = adjacency[uuid] || { incoming: [], outgoing: [] };
      });
      edges.forEach(e => {
        const sourceUuid = nodeIdMap.get(e.source) || e.source;
        const targetUuid = nodeIdMap.get(e.target) || e.target;
        if (!adjacency[sourceUuid]) adjacency[sourceUuid] = { incoming: [], outgoing: [] };
        if (!adjacency[targetUuid]) adjacency[targetUuid] = { incoming: [], outgoing: [] };
        adjacency[sourceUuid].outgoing.push(targetUuid);
        adjacency[targetUuid].incoming.push(sourceUuid);
      });

      const exportData = {
        generatedAt: new Date().toISOString(),
        nodeCount: nodes.length,
        edgeCount: edges.length,
        adjacency,
        nodes: nodes.map(n => {
          const cachedData = loadNodeCache(n.id);
          const mergedData = cachedData 
            ? { ...n.data, ...cachedData }
            : n.data;
          
          const nodeObj: any = {
            uuid: n.id,
            type: n.type,
            position: n.position,
            nodeName: mergedData.label || '',
            nodeIcon: mergedData.icon || mergedData.type || n.type || '',
            data: mergedData,
          };
          return nodeObj;
        }),
        edges: edges.map(e => {
          return {
            id: e.id,
            source: nodeIdMap.get(e.source) || e.source,
            target: nodeIdMap.get(e.target) || e.target,
            sourceHandle: e.sourceHandle,
            targetHandle: e.targetHandle,
            type: e.type,
          };
        }),
      };

      // 将整个 JSON 作为 content 字段传递
      const content = JSON.stringify(exportData, null, 2);
      
      // 必须有流程ID才能保存（因为新建时只传了name，设计完成后必须调用更新接口）
      if (!workflowId) {
        message.warning('无法保存：缺少流程ID，请先创建流程');
        return;
      }

      // 从暂存的详情中获取 name 和 description
      const name = workflowDetail?.name || '';
      const description = workflowDetail?.description || '';

      // 调用更新接口，传递 id、content、name、description
      await workflowDesignApi.updateWorkflowDesign({
        id: workflowId,
        content: content,
        name: name,
        description: description,
      });

      message.success('流程保存成功');
      
      // 保存成功后返回流程设计列表页面（与返回按钮逻辑相同）
      navigate('/dashboard');
    } catch (error: any) {
      console.error('保存流程失败:', error);
      message.error(error?.message || '流程保存失败');
    }
  };

  // 返回
  const handleBack = () => {
    // 导航到 dashboard，Dashboard 会从 sessionStorage 读取上次的菜单状态
    navigate('/dashboard');
  };

  // 缩放控制
  const handleZoomIn = () => {
    if (reactFlowInstance) {
      reactFlowInstance.zoomIn();
    }
  };

  const handleZoomOut = () => {
    if (reactFlowInstance) {
      reactFlowInstance.zoomOut();
    }
  };

  // 导出流程 JSON
  const handleExportJson = useCallback(() => {
    // 创建节点ID到UUID的映射（导出时id改为uuid，但值保持不变）
    const nodeIdMap = new Map<string, string>();
    nodes.forEach(n => {
      nodeIdMap.set(n.id, n.id); // 值保持不变，只是字段名改为uuid
    });

    // adjacency使用uuid作为key
    const adjacency: Record<string, { incoming: string[]; outgoing: string[] }> = {};
    nodes.forEach(n => {
      const uuid = nodeIdMap.get(n.id) || n.id;
      adjacency[uuid] = adjacency[uuid] || { incoming: [], outgoing: [] };
    });
    edges.forEach(e => {
      const sourceUuid = nodeIdMap.get(e.source) || e.source;
      const targetUuid = nodeIdMap.get(e.target) || e.target;
      if (!adjacency[sourceUuid]) adjacency[sourceUuid] = { incoming: [], outgoing: [] };
      if (!adjacency[targetUuid]) adjacency[targetUuid] = { incoming: [], outgoing: [] };
      adjacency[sourceUuid].outgoing.push(targetUuid);
      adjacency[targetUuid].incoming.push(sourceUuid);
    });

    const exportData = {
      generatedAt: new Date().toISOString(),
      nodeCount: nodes.length,
      edgeCount: edges.length,
      adjacency,
      nodes: nodes.map(n => {
        // 从缓存中读取最新配置
        const cachedData = loadNodeCache(n.id);
        // 合并缓存数据和节点数据，缓存数据优先级更高
        const mergedData = cachedData 
          ? { ...n.data, ...cachedData }
          : n.data;
        
        // 导出时将id字段改为uuid，但值保持不变
        // 将 nodeName 和 nodeIcon 从 data 中提取到顶层，方便后端识别，但保留 data 中的原始字段
        const nodeObj: any = {
          uuid: n.id, // 字段名改为uuid，值保持不变
          type: n.type,
          position: n.position,
          nodeName: mergedData.label || '', // 从 data.label 提取到顶层作为 nodeName
          nodeIcon: mergedData.icon || mergedData.type || n.type || '', // 从 data.icon 或 data.type 提取到顶层作为 nodeIcon
          data: mergedData, // 保留完整的 data，包括 label 和 icon
        };
        return nodeObj;
      }),
      edges: edges.map(e => {
        // edges的source和target也需要改为对应的uuid（值相同）
        return {
          id: e.id,
          source: nodeIdMap.get(e.source) || e.source, // 使用映射后的值
          target: nodeIdMap.get(e.target) || e.target, // 使用映射后的值
          sourceHandle: e.sourceHandle,
          targetHandle: e.targetHandle,
          type: e.type,
        };
      }),
    };
    setExportContent(JSON.stringify(exportData, null, 2));
    setExportVisible(true);
  }, [nodes, edges, loadNodeCache]);

  // 复制JSON到剪贴板
  const handleCopyJson = useCallback(async () => {
    console.log('复制按钮被点击，exportContent长度:', exportContent?.length);
    
    if (!exportContent || exportContent.trim() === '') {
      console.warn('exportContent为空');
      message.warning('没有可复制的内容');
      return;
    }

    try {
      // 优先使用现代 Clipboard API
      if (navigator.clipboard && navigator.clipboard.writeText) {
        console.log('使用 Clipboard API');
        await navigator.clipboard.writeText(exportContent);
        console.log('复制成功');
        message.success('复制成功！JSON已复制到剪贴板');
        return;
      }
      throw new Error('Clipboard API not available');
    } catch (error) {
      console.log('Clipboard API失败，使用降级方案:', error);
      // 降级方案：使用传统方法
      try {
        const textArea = document.createElement('textarea');
        textArea.value = exportContent;
        textArea.style.position = 'fixed';
        textArea.style.top = '0';
        textArea.style.left = '0';
        textArea.style.width = '2em';
        textArea.style.height = '2em';
        textArea.style.padding = '0';
        textArea.style.border = 'none';
        textArea.style.outline = 'none';
        textArea.style.boxShadow = 'none';
        textArea.style.background = 'transparent';
        textArea.style.opacity = '0';
        textArea.readOnly = true;
        textArea.setAttribute('contenteditable', 'true');
        
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();
        textArea.setSelectionRange(0, exportContent.length);
        
        const successful = document.execCommand('copy');
        document.body.removeChild(textArea);
        
        if (successful) {
          console.log('传统方法复制成功');
          message.success('复制成功！JSON已复制到剪贴板');
        } else {
          console.warn('传统方法复制失败');
          message.error('复制失败，请手动复制');
        }
      } catch (err) {
        console.error('复制失败:', err);
        message.error('复制失败，请手动复制');
      }
    }
  }, [exportContent]);

  // 导入流程 JSON
  const handleImportJson = useCallback(() => {
    try {
      const data = JSON.parse(importJson);
      
      if (!data.nodes || !Array.isArray(data.nodes)) {
        toast.error('JSON 格式错误：缺少 nodes 数组');
        return;
      }
      
      if (!data.edges || !Array.isArray(data.edges)) {
        toast.error('JSON 格式错误：缺少 edges 数组');
        return;
      }

      // 创建uuid到id的映射（导入时uuid改回id）
      const uuidToIdMap = new Map<string, string>();
      data.nodes.forEach((node: any) => {
        // 兼容处理：支持uuid字段或id字段
        const nodeId = node.uuid || node.id;
        uuidToIdMap.set(nodeId, nodeId); // 值保持不变
      });

      // 还原节点，确保 data 包含所有配置字段
      const importedNodes = data.nodes.map((node: any) => {
        const nodeData = node.data || {};
        // 兼容处理：支持uuid字段或id字段
        const nodeId = node.uuid || node.id;
        
        // 如果顶层有 nodeName 和 nodeIcon，将它们还原到 data 中
        const topLevelLabel = node.nodeName || '';
        const topLevelIcon = node.nodeIcon || '';
        
        // 确保所有字段都存在，使用默认值填充缺失的字段
        const completeData = {
          label: topLevelLabel || nodeData.label || '', // 优先使用顶层的 nodeName
          type: nodeData.type || node.type,
          nodeId: nodeData.nodeId || '',
          icon: topLevelIcon || nodeData.icon || nodeData.type || node.type, // 优先使用顶层的 nodeIcon
          responsible: nodeData.responsible || '',
          remark: nodeData.remark || '',
          submitForm: nodeData.submitForm || '',
          isolationMethod: nodeData.isolationMethod || '',
          isolationPoints: Array.isArray(nodeData.isolationPoints) ? nodeData.isolationPoints : [],
          isolationNode: Array.isArray(nodeData.isolationNode) ? nodeData.isolationNode : [],
          selectedIsolationNodeId: nodeData.selectedIsolationNodeId || '',
          lockPerson: nodeData.lockPerson || '',
          coLockPersons: Array.isArray(nodeData.coLockPersons) ? nodeData.coLockPersons : [],
          notificationMethods: nodeData.notificationMethods || {
            sms: false,
            message: false,
            email: false,
            app: false,
          },
          notificationPerson: nodeData.notificationPerson || '',
          notificationTime: nodeData.notificationTime || '',
          ...nodeData, // 保留其他可能的字段
        };
        
        return {
          id: nodeId, // 使用uuid或id作为id
          type: node.type,
          position: node.position || { x: 0, y: 0 },
          data: completeData,
        };
      });

      // 还原连接线（source和target需要从uuid映射回id）
      const importedEdges = data.edges.map((edge: any) => {
        // 兼容处理：如果source/target是uuid，映射回id；如果是id，直接使用
        const sourceId = uuidToIdMap.get(edge.source) || edge.source;
        const targetId = uuidToIdMap.get(edge.target) || edge.target;
        
        return {
          id: edge.id,
          source: sourceId,
          target: targetId,
          sourceHandle: edge.sourceHandle,
          targetHandle: edge.targetHandle,
          type: edge.type || 'straight',
          animated: false,
          style: { strokeWidth: 2, stroke: '#94a3b8' },
        };
      });

      // 更新节点和边
      setNodes(importedNodes);
      setEdges(importedEdges);

      // 缓存每个节点的配置（确保缓存包含完整数据）
      importedNodes.forEach((node: Node) => {
        if (node.data) {
          saveNodeCache(node.id, node.data);
        }
      });

      // 如果当前有选中的节点，重新加载其配置
      if (selectedNode) {
        const updatedNode = importedNodes.find(n => n.id === selectedNode.id);
        if (updatedNode) {
          const cache = loadNodeCache(updatedNode.id);
          const source = cache || updatedNode.data || {};
          const config = nodeConfigs.find(c => c.type === source.type);
          setNodeConfig({
            nodeName: source.label || config?.label || '',
            nodeIcon: source.icon || source.type || '',
            responsible: source.responsible || '',
            remark: source.remark || '',
            submitForm: source.submitForm || '',
            isolationMethod: source.isolationMethod || '',
            isolationPoints: source.isolationPoints || [],
            isolationNode: Array.isArray(source.isolationNode) ? source.isolationNode : (source.isolationNode ? [source.isolationNode] : []),
            selectedIsolationNodeId: source.selectedIsolationNodeId || '',
            lockPerson: source.lockPerson || '',
            coLockPersons: source.coLockPersons || [],
            notificationMethods: source.notificationMethods || {
              sms: false,
              message: false,
              email: false,
              app: false,
            },
            notificationPerson: source.notificationPerson || '',
            notificationTime: source.notificationTime || '',
          });
          setSelectedNode(updatedNode);
        } else {
          // 如果选中的节点不在导入的数据中，清除选择
          setSelectedNode(null);
        }
      }

      // 保存历史
      const newHistory = [{ nodes: importedNodes, edges: importedEdges }];
      setHistory(newHistory);
      setHistoryIndex(0);

      toast.success('流程导入成功');
      setImportVisible(false);
      setImportJson('');
    } catch (error: any) {
      toast.error(`导入失败：${error.message || 'JSON 格式错误'}`);
    }
  }, [importJson, setNodes, setEdges, saveNodeCache, loadNodeCache, selectedNode, nodeConfigs, setNodeConfig, setSelectedNode, history, setHistory, setHistoryIndex]);

  // 获取节点描述
  const getNodeDescription = (type: string) => {
    const descriptions: { [key: string]: string } = {
      createJob: '该节点为作业创建人员创建作业录入信息开始节点。',
      confirm: '该节点为作业确认，为"上一节点"操作分配确认模式及确认人员权限',
      review: '该节点为作业审核，为"上一节点"操作分配审核模式及审核人员权限',
      inputInfo: '该节点为作业录入提交，可提交信息或图片，主要为"信息确认"',
      isolation: '该节点为作业隔离类型选择，主要包括盲板，上锁挂牌，拆除等。',
      releaseIsolation: '该节点为作业隔离类型选择，主要包括盲板，上锁挂牌，拆除等。',
      returnLock: '该节点为还锁操作，归还钥匙，确认隔离操作完成',
      complete: '该节点为流程结束点',
    };
    return descriptions[type] || '该节点的功能描述。';
  };

  return (
    <div className="h-screen w-screen flex flex-col bg-gray-50">
      {/* 顶部工具栏 */}
      <div className="h-14 bg-white border-b border-gray-200 flex items-center justify-between px-4 shadow-sm z-10">
        <div className="flex items-center gap-2">
          <span className="text-lg font-bold text-blue-600 mr-2">流程设计器</span>
          <div className="h-5 w-px bg-gray-300 mx-1" />
        <Button
          type="primary"
          className="flex items-center gap-1.5"
          onClick={handleSave}
        >
          <SaveOutlined />
          <span>保存</span>
        </Button>
          <div className="h-5 w-px bg-gray-300 mx-1" />
          <Button 
            size="small" 
            className="flex items-center gap-1.5"
            onClick={handleBack}
          >
            <ArrowLeftOutlined />
            <span>返回</span>
          </Button>
          <div className="h-5 w-px bg-gray-300 mx-1" />
          <Button
            size="small"
            className="flex items-center gap-1.5"
            onClick={handleUndo}
            disabled={historyIndex <= 0}
          >
            <UndoOutlined />
            <span>撤销</span>
          </Button>
          <Button
            size="small"
            className="flex items-center gap-1.5"
            onClick={handleRedo}
            disabled={historyIndex >= history.length - 1}
          >
            <RedoOutlined />
            <span>重做</span>
          </Button>
          <Button
            size="small"
            className="flex items-center gap-1.5"
            onClick={handleExportJson}
          >
            <DownloadOutlined />
            <span>导出JSON</span>
          </Button>
          <Button
            size="small"
            className="flex items-center gap-1.5"
            onClick={() => setImportVisible(true)}
          >
            <UploadOutlined />
            <span>导入JSON</span>
          </Button>
          <div className="h-5 w-px bg-gray-300 mx-1" />
          <Button
            size="small"
            icon={<ZoomOutOutlined />}
            onClick={handleZoomOut}
          />
          <span className="text-sm text-gray-600 px-2 min-w-[50px] text-center">
            {Math.round(zoom * 100)}%
          </span>
          <Button
            size="small"
            icon={<ZoomInOutlined />}
            onClick={handleZoomIn}
          />
        </div>
      </div>

      {/* 主内容区 */}
      <div className="flex-1 flex overflow-hidden">
        {/* 左侧节点面板 */}
        <div className="w-56 bg-gray-50 border-r border-gray-200 overflow-y-auto">
          <div className="p-2 space-y-3">
            {nodeConfigs.map((config) => {
              const Icon = config.icon;
              return (
                <div
                  key={config.type}
                  draggable
                  onDragStart={(e) => onDragStart(e, config.type)}
                  className={`${config.bgColor} ${config.borderColor} border p-3 rounded-2xl shadow-md flex flex-col items-center justify-center gap-2 cursor-move transition-all hover:shadow-lg`}
                  style={{ 
                    borderRadius: '16px', 
                    minWidth: '80px', 
                    minHeight: '80px',
                    backgroundColor: config.bgColorCustom || undefined
                  }}
                >
                  <Icon 
                    className={`${config.iconColor} text-2xl`} 
                    style={{ color: config.iconColorCustom || undefined }}
                  />
                  <span className="text-xs font-medium text-center leading-tight" style={{ color: '#6b7280' }}>
                    {config.label}
                  </span>
                </div>
              );
            })}
          </div>
        </div>

        {/* 中间画布 */}
        <div className="flex-1 relative bg-white" ref={reactFlowWrapper}>
          <ReactFlow
            nodes={nodes}
            edges={edges}
            onNodesChange={onNodesChange}
            onEdgesChange={onEdgesChange}
            onConnect={onConnect}
            onEdgeUpdate={onEdgeUpdate}
            isValidConnection={isValidConnection}
            onNodeClick={onNodeClick}
            onNodeContextMenu={onNodeContextMenu}
            onEdgeClick={onEdgeClick}
            onPaneClick={onPaneClick}
            onDrop={onDrop}
            onDragOver={onDragOver}
            deleteKeyCode={['Delete', 'Backspace']}
            nodeTypes={nodeTypes as NodeTypes}
            edgeTypes={edgeTypes}
            fitView
            onInit={setReactFlowInstance}
            onMove={(_, viewport) => setZoom(viewport.zoom)}
            connectionMode={ConnectionMode.Loose}
            defaultEdgeOptions={{
              style: { strokeWidth: 2, stroke: '#94a3b8' },
              type: 'straight',
            }}
            edgesUpdatable={true}
            edgesFocusable={true}
            edgeUpdaterRadius={10}
          >
            <Controls className="!bg-white !border !border-gray-200 !rounded-lg !shadow-md" />
            <Background variant={BackgroundVariant.Dots} gap={16} size={1} color="#e5e7eb" />
            <MiniMap
              nodeColor={(node) => {
                const config = nodeConfigs.find(c => c.type === node.type);
                if (config?.color === 'bg-blue-500') return '#3b82f6';
                if (config?.color === 'bg-green-500') return '#10b981';
                if (config?.color === 'bg-orange-500') return '#f97316';
                if (config?.color === 'bg-red-500') return '#ef4444';
                if (config?.color === 'bg-yellow-500') return '#eab308';
                if (config?.color === 'bg-indigo-500') return '#6366f1';
                if (config?.color === 'bg-purple-500') return '#a855f7';
                return '#6b7280';
              }}
              maskColor="rgba(0, 0, 0, 0.05)"
              className="!bg-white !border !border-gray-200 !rounded-lg"
            />
          </ReactFlow>
        </div>

        {/* 右侧属性面板 */}
        <div className="w-80 bg-gray-50 border-l border-gray-200 overflow-y-auto">
          {selectedNode ? (
            <div className="h-full flex flex-col">
              {/* 头部 */}
              <div className="p-4 bg-white border-b border-gray-200 flex items-center justify-between sticky top-0 z-10 shadow-sm">
                <h3 className="text-base font-semibold text-gray-900">
                  {nodeConfig.nodeName || selectedNode.data?.label || '节点'} 设置
                </h3>
                <div className="flex items-center gap-2">
                  <Button
                    type="text"
                    danger
                    size="small"
                    onClick={() => handleDeleteNode()}
                    className="text-red-500 hover:text-red-600"
                    icon={<DeleteOutlined />}
                  />
                  <button
                    onClick={() => setSelectedNode(null)}
                    className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
                  >
                    <CloseOutlined className="text-gray-500" />
                  </button>
                </div>
              </div>

              {/* 内容 */}
              <div className="flex-1 p-4 overflow-y-auto">
                <Tabs
                  activeKey={activeTabKey}
                  onChange={setActiveTabKey}
                  className="[&_.ant-tabs-tab]:!px-4 [&_.ant-tabs-tab]:!py-2.5 [&_.ant-tabs-tab-active]:!text-blue-600 [&_.ant-tabs-tab-active]:!font-semibold [&_.ant-tabs-ink-bar]:!bg-blue-600 [&_.ant-tabs-tab]:!text-gray-600 [&_.ant-tabs-tab]:!border-b-2 [&_.ant-tabs-tab]:!border-transparent [&_.ant-tabs-tab:hover]:!text-blue-500"
                  items={[
                    {
                      key: 'info',
                      label: '节点信息',
                      children: (
                        <div className="space-y-5">
                          {/* 节点名称 */}
                          <div>
                            {/* 描述 - 创建作业、确认、审核、录入信息、隔离方案和解除隔离节点显示在节点名称顶部 */}
                            {(selectedNode.data?.type === 'createJob' || selectedNode.data?.type === 'confirm' || selectedNode.data?.type === 'review' || selectedNode.data?.type === 'inputInfo' || selectedNode.data?.type === 'isolation' || selectedNode.data?.type === 'releaseIsolation' || selectedNode.data?.type === 'returnLock' || selectedNode.data?.type === 'complete') && (
                              <div className="text-xs text-gray-500 leading-relaxed mb-2">
                                {getNodeDescription(selectedNode.data?.type || '')}
                              </div>
                            )}
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              节点名称 <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                            </label>
                            {selectedNode.data?.type !== 'createJob' && selectedNode.data?.type !== 'confirm' && (
                              <p className="text-xs text-gray-500 mb-2.5 leading-relaxed">
                                (默认名称: {nodeConfigs.find(c => c.type === selectedNode.data?.type)?.label || '节点名称'}，可根据需求调整)
                              </p>
                            )}
                            {selectedNode.data?.type === 'createJob' && (
                              <p className="text-xs text-gray-500 mb-2.5 leading-relaxed">
                                (默认名称: {nodeConfigs.find(c => c.type === selectedNode.data?.type)?.label || '节点名称'}，可根据需求调整)
                              </p>
                            )}
                            <Input
                              value={nodeConfig.nodeName || ''}
                              onChange={(e) =>
                                setNodeConfig({ ...nodeConfig, nodeName: e.target.value })
                              }
                              placeholder="请输入节点名称"
                              className="rounded-lg border-gray-200 h-10"
                            />
                          </div>

{/* 底部描述已移至顶部，不再在此显示 */}

                          {/* 显示图标 */}
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              显示图标
                            </label>
                            <Popover
                              content={
                                <div style={{ width: '300px' }}>
                                  <div className="grid grid-cols-5 gap-3 p-3" style={{ gridTemplateColumns: 'repeat(5, 1fr)' }}>
                                    {availableIcons.slice(0, 25).map((iconItem) => {
                                      const IconComponent = iconItem.component;
                                      const isSelected = nodeConfig.nodeIcon === iconItem.name || 
                                        (!nodeConfig.nodeIcon && selectedNode.data?.type && 
                                         nodeConfigs.find(c => c.type === selectedNode.data?.type)?.icon === IconComponent);
                                      return (
                                        <div
                                          key={iconItem.name}
                                          onClick={() => {
                                            setNodeConfig({ ...nodeConfig, nodeIcon: iconItem.name });
                                            setIconPickerOpen(false);
                                            // 立即更新节点显示
                                            setNodes((nds) => {
                                              return nds.map((node) => {
                                                if (node.id === selectedNode.id) {
                                                  return {
                                                    ...node,
                                                    data: {
                                                      ...node.data,
                                                      icon: iconItem.name,
                                                      // 保持原有的 type，只更新 icon
                                                    },
                                                  };
                                                }
                                                return node;
                                              });
                                            });
                                          }}
                                          className={`
                                            w-12 h-12 rounded-lg border-2 cursor-pointer transition-all
                                            flex items-center justify-center
                                            hover:border-blue-400 hover:bg-blue-50
                                            ${isSelected ? 'border-blue-500 bg-blue-50' : 'border-gray-200 bg-white'}
                                          `}
                                          title={iconItem.label}
                                          style={{ width: '48px', height: '48px' }}
                                        >
                                          <IconComponent className="text-xl text-gray-700" />
                                        </div>
                                      );
                                    })}
                                  </div>
                                </div>
                              }
                              title="选择图标"
                              trigger="click"
                              open={iconPickerOpen}
                              onOpenChange={setIconPickerOpen}
                              placement="right"
                            >
                              <div className="border border-gray-200 rounded-lg p-3 bg-white flex items-center gap-3 cursor-pointer hover:border-blue-400 transition-colors shadow-sm">
                                {(() => {
                                  // 如果设置了自定义图标，使用自定义图标
                                  let Icon = FileTextOutlined;
                                  let config = null;
                                  
                                  if (nodeConfig.nodeIcon && iconNameMap[nodeConfig.nodeIcon]) {
                                    Icon = iconNameMap[nodeConfig.nodeIcon];
                                    // 尝试找到对应的配置
                                    config = nodeConfigs.find(c => c.icon === Icon);
                                  } else {
                                    const iconType = selectedNode.data?.type;
                                    config = nodeConfigs.find(c => c.type === iconType);
                                    Icon = config?.icon || FileTextOutlined;
                                  }
                                  
                                  return (
                                    <>
                                      <div className={`${config?.bgColor || 'bg-gray-50'} ${config?.borderColor || 'border-gray-100'} border p-3 rounded-xl shadow-sm flex items-center justify-center`} style={{ borderRadius: '12px' }}>
                                        <Icon 
                                          className={`${config?.iconColor || 'text-gray-600'} text-lg`} 
                                          style={{ color: config?.iconColorCustom || undefined }}
                                        />
                                      </div>
                                      <span className="text-sm text-gray-600">选择图标</span>
                                    </>
                                  );
                                })()}
                              </div>
                            </Popover>
                          </div>

                          {/* 负责人 - 确认节点显示在图标下方 */}
                          {selectedNode.data?.type === 'confirm' && (
                            <div>
                              <label className="block text-sm font-medium text-gray-700 mb-2">
                                负责人
                              </label>
                              <Select
                                value={nodeConfig.responsible || undefined}
                                onChange={(value) =>
                                  setNodeConfig({ ...nodeConfig, responsible: value || '' })
                                }
                                placeholder="请选择负责人"
                                className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                allowClear
                              >
                                {drawerUsers.map(user => (
                                  <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                ))}
                              </Select>
                              <p className="text-xs text-gray-500 mt-1.5 leading-relaxed">
                                对该任务或步骤节点进行处理的人员，若不选则需要在创建作业时进行选择。
                              </p>
                            </div>
                          )}

                          {/* 负责人 - 审核节点显示在图标下方 */}
                          {selectedNode.data?.type === 'review' && (
                            <div>
                              <label className="block text-sm font-medium text-gray-700 mb-2">
                                负责人
                              </label>
                              <Select
                                value={nodeConfig.responsible || undefined}
                                onChange={(value) =>
                                  setNodeConfig({ ...nodeConfig, responsible: value || '' })
                                }
                                placeholder="请选择负责人"
                                className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                allowClear
                              >
                                {drawerUsers.map(user => (
                                  <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                ))}
                              </Select>
                              <p className="text-xs text-gray-500 mt-1.5 leading-relaxed">
                                对该任务或步骤节点进行处理的人员，若不选则需要在创建作业时进行选择。
                              </p>
                            </div>
                          )}

                          {/* 负责人 - 创建作业、隔离方案和解除隔离节点不显示 */}
                          {selectedNode.data?.type !== 'createJob' && selectedNode.data?.type !== 'confirm' && selectedNode.data?.type !== 'review' && selectedNode.data?.type !== 'isolation' && selectedNode.data?.type !== 'releaseIsolation' && (
                            <div>
                              <label className="block text-sm font-medium text-gray-700 mb-2">
                                负责人
                              </label>
                              <Select
                                value={nodeConfig.responsible || undefined}
                                onChange={(value) =>
                                  setNodeConfig({ ...nodeConfig, responsible: value || '' })
                                }
                                placeholder="请选择负责人"
                                className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                allowClear
                              >
                                {drawerUsers.map(user => (
                                  <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                ))}
                              </Select>
                              <p className="text-xs text-gray-500 mt-1.5 leading-relaxed">
                                对该任务或步骤节点进行处理的人员，若不选则需要在创建作业时进行选择
                              </p>
                            </div>
                          )}

                          {/* 备注 - 创建作业、确认、审核、录入信息、隔离方案、解除隔离、还锁和完成节点不显示 */}
                          {selectedNode.data?.type !== 'createJob' && selectedNode.data?.type !== 'confirm' && selectedNode.data?.type !== 'review' && selectedNode.data?.type !== 'inputInfo' && selectedNode.data?.type !== 'isolation' && selectedNode.data?.type !== 'releaseIsolation' && selectedNode.data?.type !== 'returnLock' && selectedNode.data?.type !== 'complete' && (
                            <div>
                              <label className="block text-sm font-medium text-gray-700 mb-2">
                                备注
                              </label>
                              <Input.TextArea
                                value={nodeConfig.remark || ''}
                                onChange={(e) =>
                                  setNodeConfig({ ...nodeConfig, remark: e.target.value })
                                }
                                placeholder="请输入备注"
                                rows={3}
                                className="rounded-lg border-gray-200"
                              />
                            </div>
                          )}

                          <div className="flex gap-2">
                            <Button
                              danger
                              onClick={() => handleDeleteNode()}
                              className="flex-1 rounded-lg"
                              size="large"
                            >
                              删除节点
                            </Button>
                          </div>
                        </div>
                      ),
                    },
                    {
                      key: 'form',
                      label: '提交表单',
                      children: (
                        <div className="space-y-5">
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              提交表单 <span className="text-red-500" style={{ color: '#ef4444' }}>*</span>
                            </label>
                            <Select
                              value={nodeConfig.submitForm || undefined}
                              onChange={(value) =>
                                setNodeConfig({ ...nodeConfig, submitForm: value || '' })
                              }
                              placeholder="请选择提交表单"
                              className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                              allowClear
                            >
                              {formList.map(form => (
                                <Select.Option key={form.id} value={form.id}>{form.name}</Select.Option>
                              ))}
                            </Select>
                          </div>

                          {/* 隔离/方案 和 解除隔离 节点特有的字段 */}
                          {(selectedNode.data?.type === 'isolation' || selectedNode.data?.type === 'releaseIsolation') && (
                            <>
                              {/* 解除隔离节点：选择隔离节点 */}
                              {selectedNode.data?.type === 'releaseIsolation' && (
                                <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-2">
                                    选择隔离节点
                                  </label>
                                  <Select
                                    value={nodeConfig.selectedIsolationNodeId || undefined}
                                    onChange={(value) => {
                                      setNodeConfig((prev) => {
                                        const target = nodes.find(n => n.id === value && n.data?.type === 'isolation');
                                        if (target) {
                                          // 优先从缓存中读取，缓存中没有则从 node.data 读取
                                          const cache = loadNodeCache(target.id);
                                          const source = cache || target.data || {};
                                          return {
                                            ...prev,
                                            selectedIsolationNodeId: value || '',
                                            isolationMethod: source.isolationMethod || '',
                                            isolationPoints: source.isolationPoints || [],
                                            isolationNode: Array.isArray(source.isolationNode)
                                              ? source.isolationNode
                                              : (source.isolationNode ? [source.isolationNode] : []),
                                            responsible: source.responsible || '',
                                            lockPerson: source.lockPerson || '',
                                            coLockPersons: source.coLockPersons || [],
                                          };
                                        }
                                        return { ...prev, selectedIsolationNodeId: value || '' };
                                      });
                                    }}
                                    placeholder="请选择隔离节点"
                                    className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                    allowClear
                                  >
                                    {nodes
                                      .filter(n => n.data?.type === 'isolation')
                                      .map(node => (
                                        <Select.Option key={node.id} value={node.id}>
                                          {node.data?.label || nodeConfigs.find(c => c.type === 'isolation')?.label || '隔离/方案'}
                                        </Select.Option>
                                      ))}
                                  </Select>
                                </div>
                              )}

                              {/* 隔离方式 - 隔离方案节点可编辑，解除隔离节点只读（根据选择的隔离节点自动填充） */}
                              <div>
                                <label className="block text-sm font-medium text-gray-700 mb-2">
                                  隔离方式
                                </label>
                                <Select
                                  value={nodeConfig.isolationMethod || undefined}
                                  onChange={(value) =>
                                    setNodeConfig({ ...nodeConfig, isolationMethod: value || '' })
                                  }
                                  placeholder="请选择隔离方式"
                                  className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                  allowClear
                                  disabled={selectedNode.data?.type === 'releaseIsolation'}
                                >
                                  <Select.Option value="blindPlate">盲板</Select.Option>
                                  <Select.Option value="lockTag">上锁挂牌</Select.Option>
                                  <Select.Option value="remove">拆除</Select.Option>
                                </Select>
                              </div>

                              {/* 隔离点选择（可多选）- 隔离方案节点显示，解除隔离只读展示 */}
                              {(selectedNode.data?.type === 'isolation' || selectedNode.data?.type === 'releaseIsolation') && (
                                <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-2">
                                    隔离点选择（可多选）
                                  </label>
                                  <Select
                                    mode="multiple"
                                    value={nodeConfig.isolationPoints}
                                    onChange={(value) =>
                                      setNodeConfig({ ...nodeConfig, isolationPoints: value })
                                    }
                                    placeholder="请选择隔离点"
                                    className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!min-h-10"
                                    allowClear
                                    disabled={selectedNode.data?.type === 'releaseIsolation'}
                                  >
                                    {isolationPoints.map((point: any, index) => (
                                      <Select.Option key={point.pointId || point.id || `point-${index}`} value={point.pointId || point.id}>{point.pointName}</Select.Option>
                                    ))}
                                  </Select>
                                </div>
                              )}

                              {/* 盲板和拆除：显示负责人 */}
                              {(nodeConfig.isolationMethod === 'blindPlate' || nodeConfig.isolationMethod === 'remove') && (
                                <div>
                                  <label className="block text-sm font-medium text-gray-700 mb-2">
                                    负责人
                                  </label>
                                  <Select
                                    value={nodeConfig.responsible || undefined}
                                    onChange={(value) =>
                                      setNodeConfig({ ...nodeConfig, responsible: value || '' })
                                    }
                                    placeholder="请选择负责人"
                                    className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                    allowClear
                                    disabled={selectedNode.data?.type === 'releaseIsolation'}
                                  >
                                    {drawerUsers.map(user => (
                                      <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                    ))}
                                  </Select>
                                  <p className="text-xs text-gray-500 mt-1.5 leading-relaxed">
                                    对该任务或步骤节点进行处理的人员，若不选则需要在创建作业时进行选择。
                                  </p>
                                </div>
                              )}

                              {/* 上锁挂牌：显示上锁人和共锁人 */}
                              {nodeConfig.isolationMethod === 'lockTag' && (
                                <>
                                  <div>
                                    <label className="block text-sm font-medium text-gray-700 mb-2">
                                      上锁人
                                    </label>
                                    <Select
                                      value={nodeConfig.lockPerson || undefined}
                                      onChange={(value) =>
                                        setNodeConfig({ ...nodeConfig, lockPerson: value || '' })
                                      }
                                      placeholder="请选择上锁人"
                                      className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                                      allowClear
                                      disabled={selectedNode.data?.type === 'releaseIsolation'}
                                    >
                                      {lockerUsers.map(user => (
                                        <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                      ))}
                                    </Select>
                                  </div>
                                  <div>
                                    <label className="block text-sm font-medium text-gray-700 mb-2">
                                      共锁人（可多选）
                                    </label>
                                    <Select
                                      mode="multiple"
                                      value={nodeConfig.coLockPersons}
                                      onChange={(value) =>
                                        setNodeConfig({ ...nodeConfig, coLockPersons: value })
                                      }
                                      placeholder="请选择共锁人"
                                      className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!min-h-10"
                                      allowClear
                                      disabled={selectedNode.data?.type === 'releaseIsolation'}
                                    >
                                      {colockerUsers.map(user => (
                                        <Select.Option key={user.id} value={user.id}>{user.nickname || user.username}</Select.Option>
                                      ))}
                                    </Select>
                                  </div>
                                </>
                              )}
                            </>
                          )}
                          <div className="flex gap-2">
                            <Button
                              danger
                              onClick={() => handleDeleteNode()}
                              className="flex-1 rounded-lg"
                              size="large"
                            >
                              删除节点
                            </Button>
                          </div>
                        </div>
                      ),
                    },
                    {
                      key: 'notification',
                      label: '通知消息',
                      children: (
                        <div className="space-y-5">
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-3">
                              通知方式
                            </label>
                            <div className="bg-gray-50 p-3 rounded-lg">
                              <div className="mb-3">
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.sms}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        sms: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  短信
                                </Checkbox>
                              </div>
                              <div className="mb-3">
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.message}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        message: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  站内信
                                </Checkbox>
                              </div>
                              <div className="mb-3">
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.email}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        email: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  邮件
                                </Checkbox>
                              </div>
                              <div>
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.app}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        app: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  APP通知
                                </Checkbox>
                              </div>
                            </div>
                          </div>
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              通知人
                            </label>
                            <Select
                              value={nodeConfig.notificationPerson || undefined}
                              onChange={(value) =>
                                setNodeConfig({ ...nodeConfig, notificationPerson: value || '' })
                              }
                              placeholder="请选择通知人"
                              className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                              allowClear
                            >
                              <Select.Option value="taskResponsible">任务负责人</Select.Option>
                              <Select.Option value="taskParticipant">任务参与人</Select.Option>
                              <Select.Option value="responsibleAndParticipant">负责人和参与人</Select.Option>
                              <Select.Option value="specifiedPerson">指定人</Select.Option>
                            </Select>
                          </div>
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              通知时间
                            </label>
                            <Select
                              value={nodeConfig.notificationTime || undefined}
                              onChange={(value) =>
                                setNodeConfig({ ...nodeConfig, notificationTime: value || '' })
                              }
                              placeholder="请选择通知时间"
                              className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                              allowClear
                            >
                              <Select.Option value="before">执行前（上一个节点结束后）</Select.Option>
                              <Select.Option value="after">执行后（该节点结束后）</Select.Option>
                              <Select.Option value="time">选择时间</Select.Option>
                              <Select.Option value="30min">任务开始前30分钟</Select.Option>
                              <Select.Option value="1h">任务开始前1小时</Select.Option>
                              <Select.Option value="2h">任务开始前2小时</Select.Option>
                              <Select.Option value="4h">任务开始前4小时</Select.Option>
                              <Select.Option value="5h">任务开始前5小时</Select.Option>
                              <Select.Option value="8h">任务开始前8小时</Select.Option>
                              <Select.Option value="12h">任务开始前12小时</Select.Option>
                              <Select.Option value="24h">任务开始前24小时</Select.Option>
                              <Select.Option value="48h">任务开始前48小时</Select.Option>
                            </Select>
                          </div>
                          <div className="flex gap-2">
                            <Button
                              danger
                              onClick={() => handleDeleteNode()}
                              className="flex-1 rounded-lg"
                              size="large"
                            >
                              删除节点
                            </Button>
                          </div>
                        </div>
                      ),
                    },
                    // 通知消息tab - 已隐藏但保留代码
                    {
                      key: 'notification',
                      label: '通知消息',
                      children: (
                        <div className="space-y-5">
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-3">
                              通知方式
                            </label>
                            <div className="bg-gray-50 p-3 rounded-lg">
                              <div className="mb-3">
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.sms}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        sms: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  短信
                                </Checkbox>
                              </div>
                              <div className="mb-3">
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.message}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        message: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  站内信
                                </Checkbox>
                              </div>
                              <div className="mb-3">
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.email}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        email: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  邮件
                                </Checkbox>
                              </div>
                              <div>
                                <Checkbox
                                  checked={nodeConfig.notificationMethods.app}
                                  onChange={(e) =>
                                    setNodeConfig({
                                      ...nodeConfig,
                                      notificationMethods: {
                                        ...nodeConfig.notificationMethods,
                                        app: e.target.checked,
                                      },
                                    })
                                  }
                                >
                                  APP通知
                                </Checkbox>
                              </div>
                            </div>
                          </div>
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              通知人
                            </label>
                            <Select
                              value={nodeConfig.notificationPerson || undefined}
                              onChange={(value) =>
                                setNodeConfig({ ...nodeConfig, notificationPerson: value || '' })
                              }
                              placeholder="请选择通知人"
                              className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                              allowClear
                            >
                              <Select.Option value="taskResponsible">任务负责人</Select.Option>
                              <Select.Option value="taskParticipant">任务参与人</Select.Option>
                              <Select.Option value="responsibleAndParticipant">负责人和参与人</Select.Option>
                              <Select.Option value="specifiedPerson">指定人</Select.Option>
                            </Select>
                          </div>
                          <div>
                            <label className="block text-sm font-medium text-gray-700 mb-2">
                              通知时间
                            </label>
                            <Select
                              value={nodeConfig.notificationTime || undefined}
                              onChange={(value) =>
                                setNodeConfig({ ...nodeConfig, notificationTime: value || '' })
                              }
                              placeholder="请选择通知时间"
                              className="w-full [&_.ant-select-selector]:!rounded-lg [&_.ant-select-selector]:!h-10"
                              allowClear
                            >
                              <Select.Option value="before">执行前（上一个节点结束后）</Select.Option>
                              <Select.Option value="after">执行后（该节点结束后）</Select.Option>
                              <Select.Option value="time">选择时间</Select.Option>
                              <Select.Option value="30min">任务开始前30分钟</Select.Option>
                              <Select.Option value="1h">任务开始前1小时</Select.Option>
                              <Select.Option value="2h">任务开始前2小时</Select.Option>
                              <Select.Option value="4h">任务开始前4小时</Select.Option>
                              <Select.Option value="5h">任务开始前5小时</Select.Option>
                              <Select.Option value="8h">任务开始前8小时</Select.Option>
                              <Select.Option value="12h">任务开始前12小时</Select.Option>
                              <Select.Option value="24h">任务开始前24小时</Select.Option>
                              <Select.Option value="48h">任务开始前48小时</Select.Option>
                            </Select>
                          </div>
                          <div className="flex gap-2">
                            <Button
                              danger
                              onClick={() => handleDeleteNode()}
                              className="flex-1 rounded-lg"
                              size="large"
                            >
                              删除节点
                            </Button>
                          </div>
                        </div>
                      ),
                    },
                  ].filter(item => item.key !== 'notification')}
                />
              </div>
            </div>
          ) : (
            <div className="p-4 text-center text-gray-500 mt-20">
              <p className="text-sm">请点击画布中的节点查看和编辑属性</p>
            </div>
          )}
        </div>
      </div>
      <Modal
        open={exportVisible}
        title="流程 JSON 导出"
        onCancel={() => setExportVisible(false)}
        onOk={() => setExportVisible(false)}
        width={800}
        okText="关闭"
        cancelText="取消"
        style={{ top: 20 }}
        styles={{ body: { maxHeight: 'calc(90vh - 120px)', overflowY: 'auto', overflowX: 'hidden', padding: 0 } }}
      >
        <div className="relative">
          {/* 固定在顶部的复制按钮 */}
          <div className="sticky top-0 bg-white z-10 px-6 py-3 flex justify-end">
            <Button
              type="default"
              icon={<CopyOutlined />}
              onClick={handleCopyJson}
            >
              复制JSON
            </Button>
          </div>
          {/* JSON内容区域 */}
          <div className="p-6">
            <div className="bg-gray-50 border border-gray-200 rounded-lg p-3 overflow-x-hidden">
              <pre className="text-xs text-gray-800 whitespace-pre-wrap break-words font-mono overflow-x-hidden">
                {exportContent}
              </pre>
            </div>
          </div>
        </div>
      </Modal>

      <Modal
        open={importVisible}
        title="导入流程 JSON"
        onCancel={() => {
          setImportVisible(false);
          setImportJson('');
        }}
        onOk={handleImportJson}
        width={800}
        okText="导入"
        cancelText="取消"
      >
        <div className="space-y-3">
          <p className="text-sm text-gray-600">
            请粘贴流程 JSON 数据，导入后将替换当前画布内容
          </p>
          <Input.TextArea
            value={importJson}
            onChange={(e) => setImportJson(e.target.value)}
            placeholder="请粘贴 JSON 数据..."
            rows={15}
            className="font-mono text-xs"
          />
        </div>
      </Modal>
    </div>
  );
}
