import React, { useState, useEffect, useMemo } from 'react';
import { ChevronDown, ChevronUp, Clock, PlayCircle, CheckCircle, AlertTriangle, List, Plus, RefreshCw, AlertCircle, FileText, Rocket, Eye } from 'lucide-react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend, AreaChart, Area } from 'recharts';
import { Card, Collapse, Modal, Form as AntdForm, Input, Button, message, Select, DatePicker, InputNumber, Switch, Radio, Checkbox, Cascader, Upload, Alert, Space, Image } from 'antd';
import { UploadOutlined, LockOutlined, CheckCircleOutlined, BarcodeOutlined, SendOutlined, KeyOutlined } from '@ant-design/icons';
const { Panel } = Collapse;
import { cockpitApi, CockpitStatisticsVO, JobVO, TaskVO } from '../api/cockpit';
import { dictDataApi, DictDataVO } from '../api/DictData';
import { taskManagementApi, MyTaskVO, MyTaskPageParam, MyTaskNodeDetailVO, UpdateNodeApprovalParam } from '../api/mytask';
import { fileApi } from '../api/file';
import { managerHomeApi, ManagerWorkCountVO, ManagerWorkItemVO, ManagerDayWorkCountVO } from '../api/managerHome';
import { dateFormatter } from '../utils/formatTime';
import { toast } from 'sonner';
import { useNavigate } from 'react-router-dom';
import dayjs, { Dayjs } from 'dayjs';
import { setConfAndFields2, FormCreateData } from '../utils/formCreate';
import { useTranslation } from 'react-i18next';
import FormUploadField from './FormUploadField';
import {
  isWorkflowCoLockType,
  isWorkflowLockSchemeType,
  isWorkflowUnlockCoLockType,
  isWorkflowUnlockSchemeType,
} from '../utils/workflowNodeTypes';

// 辅助函数：安全地将值转换为 dayjs 对象
const safeToDayjs = (value: any): dayjs.Dayjs | null => {
  if (!value && value !== 0) {
    return null;
  }
  
  // 如果是数字（时间戳）
  if (typeof value === 'number') {
    let timestamp = value;
    if (timestamp > 0 && timestamp < 10000000000) {
      timestamp = timestamp * 1000;
    }
    const dayjsValue = dayjs(timestamp);
    if (dayjsValue.isValid()) {
      return dayjsValue;
    } else {
      return null;
    }
  }
  
  // 如果是字符串
  if (typeof value === 'string' && value.trim() !== '') {
    const numValue = Number(value);
    if (!isNaN(numValue) && numValue > 0 && numValue.toString() === value.trim()) {
      let timestamp = numValue;
      if (timestamp < 10000000000) {
        timestamp = timestamp * 1000;
      }
      const dayjsValue = dayjs(timestamp);
      if (dayjsValue.isValid()) {
        return dayjsValue;
      } else {
        return null;
      }
    } else {
      const dayjsValue = dayjs(value);
      return dayjsValue.isValid() ? dayjsValue : null;
    }
  }
  
  // 如果已经是 dayjs 对象
  if (value && typeof value === 'object' && typeof value.isValid === 'function') {
    try {
      return value.isValid() ? value : null;
    } catch (e) {
      // isValid 调用失败
    }
  }
  
  // 如果是对象，检查是否有 $d 属性
  if (value && typeof value === 'object') {
    try {
      if (value.$d) {
        const dayjsValue = dayjs(value.$d);
        return dayjsValue.isValid() ? dayjsValue : null;
      }
      if (value.valueOf && typeof value.valueOf === 'function') {
        const timestamp = value.valueOf();
        if (typeof timestamp === 'number') {
          const dayjsValue = dayjs(timestamp);
          return dayjsValue.isValid() ? dayjsValue : null;
        }
      }
    } catch (e) {
      return null;
    }
  }
  
  return null;
};

// 辅助函数：验证 dayjs 对象是否有效
const isValidDayjs = (value: any): boolean => {
  if (!value) return false;
  if (typeof value !== 'object') return false;
  if (typeof value.isValid !== 'function') return false;
  try {
    return value.isValid();
  } catch (e) {
    return false;
  }
};

// 辅助函数：将表单值中的日期字符串转换为 dayjs 对象
const convertDateValues = (formValues: any, fields: any[]): any => {
  const fieldTypeMap: { [key: string]: string } = {};
  
  // 建立字段名到类型的映射
  fields.forEach((field: any) => {
    try {
      const fieldObj = typeof field === 'string' ? JSON.parse(field) : field;
      const fieldName = fieldObj.name || fieldObj.field;
      if (fieldName) {
        fieldTypeMap[fieldName] = fieldObj.type;
      }
    } catch (e) {
      // 解析失败，跳过
    }
  });
  
  // 转换日期值
  const convertedValues: any = {};
  Object.keys(formValues).forEach((fieldName) => {
    const fieldType = fieldTypeMap[fieldName];
    const value = formValues[fieldName];
    
    if (fieldType === 'date' || fieldType === 'datetime' || fieldType === 'timepicker') {
      convertedValues[fieldName] = safeToDayjs(value) || undefined;
    } else if (fieldType === 'daterange') {
      if (Array.isArray(value) && value.length === 2) {
        const [start, end] = value;
        const startDayjs = safeToDayjs(start);
        const endDayjs = safeToDayjs(end);
        
        if (startDayjs && endDayjs) {
          convertedValues[fieldName] = [startDayjs, endDayjs];
        } else {
          convertedValues[fieldName] = undefined;
        }
      } else {
        convertedValues[fieldName] = undefined;
      }
    } else {
      convertedValues[fieldName] = value;
    }
  });
  
  return convertedValues;
};

export default function Dashboard() {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const [loading, setLoading] = useState(true);
  const [expandedJobs, setExpandedJobs] = useState<Set<number>>(new Set());
  const [selectedJob, setSelectedJob] = useState<number | null>(null);
  const [jobStatusDictList, setJobStatusDictList] = useState<DictDataVO[]>([]);
  const [approvalStatusDictList, setApprovalStatusDictList] = useState<DictDataVO[]>([]);
  const [jobTaskMap, setJobTaskMap] = useState<Map<number, MyTaskVO[]>>(new Map());
  const [taskLoadingMap, setTaskLoadingMap] = useState<Map<number, boolean>>(new Map());
  const [statistics, setStatistics] = useState<CockpitStatisticsVO>({
    materialsCount: 0,
    loanMaterialsCount: 0,
    totalOperations: 0,
    totalMaterials: 0,
    borrowedMaterials: 0,
    workstationCount: 0,
    workstationDistribution: [],
    operationTypeDistribution: [],
  });
  // 管理员工作统计数据
  const [managerWorkCount, setManagerWorkCount] = useState<ManagerWorkCountVO>({});
  const [managerWorkList, setManagerWorkList] = useState<ManagerWorkItemVO[]>([]);
  const [managerDayWorkCount, setManagerDayWorkCount] = useState<ManagerDayWorkCountVO[]>([]);
  const [managerDataLoading, setManagerDataLoading] = useState(false);
  
  // 任务详情弹框相关状态
  const [taskDetailVisible, setTaskDetailVisible] = useState(false);
  const [taskDetailLoading, setTaskDetailLoading] = useState(false);
  const [taskDetailData, setTaskDetailData] = useState<MyTaskNodeDetailVO | null>(null);
  const [formData, setFormData] = useState<FormCreateData>({
    rule: [],
    option: {}
  });
  const [formLoading, setFormLoading] = useState(false);
  const [originalFields, setOriginalFields] = useState<string[]>([]);
  const [originalConf, setOriginalConf] = useState<string>('');
  const [taskDetailForm] = AntdForm.useForm();
  const [approvalComment, setApprovalComment] = useState('');
  const [approvalLoading, setApprovalLoading] = useState(false);
  const [submitLoading, setSubmitLoading] = useState(false);
  const [showOverdueJobs, setShowOverdueJobs] = useState(false); // 默认隐藏逾期作业
  const [isolationDeviceNumber, setIsolationDeviceNumber] = useState('');
  const [isolationFileList, setIsolationFileList] = useState<any[]>([]);
  const [isolationSubmitLoading, setIsolationSubmitLoading] = useState(false);

  // 获取统计数据
  const fetchStatistics = async () => {
    setLoading(true);
    try {
      const response = await cockpitApi.getHomePage();
      console.log('API原始响应:', response);
      
      // API返回格式: { code: 0, data: {...}, msg: "" }
      const data = (response && typeof response === 'object' && 'data' in response) 
        ? response.data 
        : response;
      
      console.log('提取的data:', data);
      
      // 计算总作业数
      const totalOperations = data.jobList?.length || 0;
      
      // 计算作业状态统计
      const jobList = data.jobList || [];
      let pendingCount = 0;
      let inProgressCount = 0;
      let completedCount = 0;
      let overdueCount = 0;
      
      jobList.forEach((job: any) => {
        const status = job.status || job.jobStatus || '';
        if (status === '待执行' || status === 'pending' || status === 'PENDING') {
          pendingCount++;
        } else if (status === '进行中' || status === 'in_progress' || status === 'IN_PROGRESS') {
          inProgressCount++;
        } else if (status === '已完成' || status === 'completed' || status === 'COMPLETED') {
          completedCount++;
        } else if (status === '逾期' || status === 'overdue' || status === 'OVERDUE') {
          overdueCount++;
        } else {
          // 如果没有明确状态，根据其他字段判断
          if (job.progress === 0 || !job.progress) {
            pendingCount++;
          } else if (job.progress === 100) {
            completedCount++;
          } else {
            inProgressCount++;
          }
        }
      });
      
      // 生成最近30天的趋势数据（如果API没有提供，则生成模拟数据）
      const trendData: { date: string; completedCount: number }[] = [];
      if (data.jobTrendData && Array.isArray(data.jobTrendData)) {
        // 使用API提供的数据
        trendData.push(...data.jobTrendData);
      } else {
        // 生成模拟数据（实际应该从API获取）
        for (let i = 1; i <= 30; i++) {
          trendData.push({
            date: `${i}日`,
            completedCount: Math.floor(Math.random() * 5), // 0-4之间的随机数
          });
        }
      }
      
      // 计算工作站数量（去重）
      const workstationSet = new Set<string>();
      jobList.forEach((job: any) => {
        if (job.workstationName) {
          workstationSet.add(job.workstationName);
        }
      });
      const workstationCount = workstationSet.size;
      
      // 计算工作站作业分布
      const workstationMap = new Map<string, number>();
      jobList.forEach((job: any) => {
        const workstation = job.workstationName || '未知';
        workstationMap.set(workstation, (workstationMap.get(workstation) || 0) + 1);
      });
      const workstationDistribution = Array.from(workstationMap.entries()).map(([workstation, count]) => ({
        workstation,
        count,
      }));
      
      // 计算作业类型分布
      const typeMap = new Map<string, number>();
      jobList.forEach((job: any) => {
        // 从ticketName中提取作业类型
        const ticketName = job.ticketName || '';
        let type = '未知';
        if (ticketName.includes('换产') || ticketName.includes('投产')) {
          type = '投产';
        } else if (ticketName.includes('维修')) {
          type = '维修';
        } else if (ticketName.includes('PM')) {
          type = 'PM';
        } else if (job.jobType) {
          type = job.jobType;
        }
        typeMap.set(type, (typeMap.get(type) || 0) + 1);
      });
      const typeEntries = Array.from(typeMap.entries());
      const totalJobs = typeEntries.reduce((sum, [, count]) => sum + count, 0);
      const operationTypeDistribution = typeEntries.map(([type, count]) => ({
        type,
        count,
        percentage: totalJobs > 0 ? Math.round((count / totalJobs) * 100) : 0,
      }));
      
      // 判断物料状态
      const materialStatus = data.exceptionMaterialsCount && data.exceptionMaterialsCount > 0 ? '异常' : '正常';
      
      // 判断借用状态
      const borrowedStatus = data.loanMaterialsCount && data.loanMaterialsCount > 0 ? '关注' : '正常';
      
      // 判断工作站状态
      const workstationStatus = workstationCount > 0 ? '活跃' : '非活跃';
      
      // 组装统计数据
      const statisticsData: CockpitStatisticsVO = {
        ...data,
        totalOperations,
        totalMaterials: data.materialsCount || 0,
        materialStatus,
        borrowedMaterials: data.loanMaterialsCount || 0,
        borrowedStatus,
        workstationCount,
        workstationStatus,
        workstationDistribution,
        operationTypeDistribution,
        // 作业状态统计
        pendingJobsCount: pendingCount,
        inProgressJobsCount: inProgressCount,
        completedJobsCount: completedCount,
        overdueJobsCount: overdueCount,
        // 趋势数据
        jobTrendData: trendData,
        // 物料统计
        availableMaterialsCount: data.availableMaterialsCount || (data.materialsCount || 0) - (data.loanMaterialsCount || 0) - (data.exceptionMaterialsCount || 0) - (data.returnMaterialsCount || 0),
        returnMaterialsCount: data.returnMaterialsCount || 0,
      };
      
      console.log('处理后的统计数据:', statisticsData);
      setStatistics(statisticsData);
    } catch (error: any) {
      console.error('获取驾驶舱统计数据失败:', error);
      toast.error(error.message || t('cockpit.getStatsFailed'));
    } finally {
      setLoading(false);
    }
  };

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

  // 获取审批状态字典数据
  const getApprovalStatusDictList = async () => {
    try {
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'approval_status',
      });
      const data = (response && typeof response === 'object' && 'data' in response) 
        ? response.data 
        : response;
      setApprovalStatusDictList(data?.list || []);
      console.log('Dashboard: 获取审批状态字典成功', data?.list || []);
    } catch (error: any) {
      console.error('获取审批状态字典失败:', error);
      setApprovalStatusDictList([]);
    }
  };

  // 获取管理员工作统计数据
  const fetchManagerWorkCount = async () => {
    try {
      const response = await managerHomeApi.getManagerWorkCount();
      const data = (response && typeof response === 'object' && 'data' in response) 
        ? response.data 
        : response;
      setManagerWorkCount(data || {});
    } catch (error: any) {
      console.error('获取管理员工作统计失败:', error);
      toast.error(error.message || t('cockpit.getManagerWorkStatsFailed'));
      setManagerWorkCount({});
    }
  };

  // 获取管理员工作列表
  const fetchManagerWorkList = async () => {
    try {
      const response = await managerHomeApi.getManagerWorkList({
        pageNo: 1,
        pageSize: -1,
      });
      console.log('获取管理员工作列表原始响应:', response);
      
      // 接口返回的已经是数组格式（API 层已经处理了 {code, data, msg} 格式）
      const data: ManagerWorkItemVO[] = Array.isArray(response) ? response : [];
      console.log('设置管理员工作列表:', data);
      
      setManagerWorkList(data);
      console.log('获取管理员工作列表成功，设置的数据:', data, '数据长度:', data.length);
    } catch (error: any) {
      console.error('获取管理员工作列表失败:', error);
      toast.error(error.message || t('cockpit.getManagerWorkListFailed'));
      setManagerWorkList([]);
    }
  };

  // 获取管理员每日工作统计
  const fetchManagerDayWorkCount = async () => {
    try {
      // 计算最近30天的日期范围
      const endDate = new Date();
      const startDate = new Date();
      startDate.setDate(startDate.getDate() - 30);
      
      const response = await managerHomeApi.getManagerDayWorkCount({
        startDate: startDate.toISOString().split('T')[0],
        endDate: endDate.toISOString().split('T')[0],
      });
      // API 层已经处理了 {code, data, msg} 格式，返回的已经是数组
      const data: ManagerDayWorkCountVO[] = Array.isArray(response) ? response : [];
      console.log('获取管理员每日工作统计:', data);
      setManagerDayWorkCount(data);
    } catch (error: any) {
      console.error('获取管理员每日工作统计失败:', error);
      toast.error(error.message || t('cockpit.getManagerDayStatsFailed'));
      setManagerDayWorkCount([]);
    }
  };

  // 获取所有管理员数据
  const fetchManagerData = async () => {
    setManagerDataLoading(true);
    try {
      await Promise.all([
        fetchManagerWorkCount(),
        fetchManagerWorkList(),
        fetchManagerDayWorkCount(),
      ]);
    } catch (error: any) {
      console.error('获取管理员数据失败:', error);
    } finally {
      setManagerDataLoading(false);
    }
  };

  useEffect(() => {
    fetchStatistics();
    getJobStatusDictList();
    getApprovalStatusDictList();
    fetchManagerData();
  }, []);

  // 获取作业的任务列表
  // 从作业的 workflowWorkNodeDOList 中提取任务列表并转换为 MyTaskVO 格式
  const extractTasksFromJob = (job: ManagerWorkItemVO): MyTaskVO[] => {
    if (!job.workflowWorkNodeDOList || !Array.isArray(job.workflowWorkNodeDOList)) {
      return [];
    }
    
    return job.workflowWorkNodeDOList.map((node: any) => {
      return {
        id: node.id,
        nodeId: node.id, // 节点ID作为任务ID
        workId: job.id, // 作业ID
        name: node.nodeName || node.currentNodeName || node.currentNode || '-',
        currentNodeName: node.nodeName || node.currentNodeName || node.currentNode || '-',
        currentNode: node.currentNodeName || node.currentNode || '-',
        workerUserName: node.workerUserName || node.responsibleName || node.responsible || '-',
        responsibleName: node.workerUserName || node.responsibleName || node.responsible || '-',
        responsible: node.workerUserName || node.responsibleName || node.responsible || '-',
        workTime: node.workTime || node.taskStartTime || node.initiationTime,
        taskStartTime: node.workTime || node.taskStartTime || node.initiationTime,
        initiationTime: node.workTime || node.taskStartTime || node.initiationTime,
        approvalStatus: node.approvalStatus || node.status,
        taskStatus: node.approvalStatus || node.status,
        status: node.approvalStatus || node.status,
        orderNo: job.orderNo,
        initiatorName: job.initiatorName || job.initiator || '-',
        initiator: job.initiatorName || job.initiator || '-',
      } as MyTaskVO;
    });
  };

  // 计算作业的整体进度（已完成任务数 / 总任务数）
  const calculateJobProgress = (job: ManagerWorkItemVO): number => {
    if (!job.workflowWorkNodeDOList || !Array.isArray(job.workflowWorkNodeDOList)) {
      return 0;
    }
    
    const totalTasks = job.workflowWorkNodeDOList.length;
    if (totalTasks === 0) {
      return 0;
    }
    
    // 统计已完成的任务数量
    const completedTasks = job.workflowWorkNodeDOList.filter((node: any) => {
      const status = String(node.approvalStatus || node.status || '').toLowerCase();
      // 判断任务是否已完成：状态为 'approved', 'completed', '已完成' 等
      return status === 'approved' || 
             status === 'completed' || 
             status === '已完成' ||
             status === '完成' ||
             status === 'COMPLETED';
    }).length;
    
    // 计算百分比并四舍五入
    const progress = Math.round((completedTasks / totalTasks) * 100);
    return progress;
  };

  // 切换作业展开/折叠
  const toggleJobExpand = (jobId: number) => {
    console.log('Dashboard: toggleJobExpand 被调用', { jobId, currentExpanded: Array.from(expandedJobs) });
    
    const isCurrentlyExpanded = expandedJobs.has(jobId);
    
    if (isCurrentlyExpanded) {
      // 如果当前作业已展开，则折叠它
      setExpandedJobs(new Set());
      setSelectedJob(null);
      console.log('Dashboard: 折叠作业', jobId);
    } else {
      // 展开新作业时，先清空所有已展开的作业，确保每次只展开一个
      const newExpanded = new Set<number>();
      newExpanded.add(jobId);
      setExpandedJobs(newExpanded);
      setSelectedJob(jobId); // 展开时选中
      console.log('Dashboard: 展开作业', jobId);
      
      // 从作业数据中直接提取任务列表
      const job = managerWorkList.find(j => j.id === jobId);
      console.log('Dashboard: 查找作业', { jobId, job, jobListLength: managerWorkList.length });
      
      if (job) {
        console.log('Dashboard: 从作业数据中提取任务列表', { jobId, workflowWorkNodeDOList: job.workflowWorkNodeDOList });
        const taskList = extractTasksFromJob(job);
        console.log('Dashboard: 提取的任务列表', taskList, '任务数量:', taskList.length);
        setJobTaskMap(prev => new Map(prev).set(jobId, taskList));
        // 设置加载状态为完成（因为数据已经在作业数据中了，不需要异步加载）
        setTaskLoadingMap(prev => {
          const newMap = new Map(prev);
          newMap.delete(jobId);
          return newMap;
        });
      } else {
        console.warn('Dashboard: 未找到作业', jobId);
        setJobTaskMap(prev => new Map(prev).set(jobId, []));
      }
    }
  };

  // 选中作业
  const handleJobSelect = (jobId: number) => {
    setSelectedJob(jobId);
  };

  // 处理作业行点击（选中并切换展开/折叠）
  const handleJobRowClick = (jobId: number) => {
    setSelectedJob(jobId);
    toggleJobExpand(jobId);
  };

  const defaultFormConfig = {
    name: '',
    labelPosition: 'right',
    formSize: 'middle',
    labelSuffix: '',
    labelWidth: 100,
    hideRequiredMark: false,
    showValidationError: true,
    inlineValidation: false,
    showSubmitButton: false,
    showResetButton: false,
  };

  // 渲染字段预览（支持嵌套结构）
  const renderFieldPreview = (field: any, parentSpanStyle?: React.CSSProperties): React.ReactNode => {
    const formConfig = formData.option?.formConfig || defaultFormConfig;
    const layoutColumns = formConfig.layoutColumns || 1;
    const spanStyle = parentSpanStyle || (layoutColumns > 1 ? { gridColumn: `span ${Math.min(layoutColumns, field.span || 1)}` } : undefined);

    // 处理容器类型（card 和 grid）
    if (field.type === 'card') {
      const children = field.children || [];
      const cardTitle = field.label || field.cardTitle || '卡片容器';
      return (
        <div key={field.id} style={spanStyle} className="mb-4">
          <Card title={cardTitle} className="w-full">
            <div className="space-y-4">
              {children.map((child: any) => renderFieldPreview(child))}
            </div>
          </Card>
        </div>
      );
    }

    if (field.type === 'grid') {
      const gridColumns = field.gridColumns || 2;
      const children = field.children || [];
      return (
        <div key={field.id} style={spanStyle} className="mb-4">
          <div
            style={{
              display: 'grid',
              gridTemplateColumns: `repeat(${gridColumns}, minmax(0, 1fr))`,
              gap: '16px',
            }}
          >
            {children.map((child: any) => {
              const childSpanStyle = gridColumns > 1 
                ? { gridColumn: `span ${Math.min(gridColumns, child.span || 1)}` } 
                : undefined;
              return (
                <div key={child.id} style={childSpanStyle}>
                  {renderFieldPreview(child)}
                </div>
              );
            })}
          </div>
        </div>
      );
    }

    // 处理 alert 类型
    if (field.type === 'alert') {
      const themeClass =
        field.alertTheme === 'dark'
          ? 'bg-gray-800 text-white border-gray-700'
          : '';
      return (
        <div key={field.id} className="mb-4" style={spanStyle}>
          <Alert
            message={field.alertTitle || field.label}
            description={field.alertDescription}
            type={field.alertType || 'info'}
            showIcon={field.alertShowIcon !== false}
            closable={field.alertClosable}
            closeText={field.alertCloseText}
            className={`${field.alertCentered ? 'text-center' : ''} ${themeClass}`}
            banner
            style={field.style}
          />
          {field.hint && <div className="text-xs text-gray-400 mt-1">{field.hint}</div>}
        </div>
      );
    }

    // 与表单设计器一致：每字段 labelCol/wrapperCol，避免长标签堆叠
    const getItemLayout = (f: any) => {
      const isTop = formConfig.labelPosition === 'top';
      const w = f.labelWidth ?? formConfig.labelWidth ?? 100;
      const effective = (typeof w === 'number' && w > 0) ? w : 100;
      return {
        labelCol: isTop ? undefined : { flex: `${effective}px`, style: { minWidth: `${effective}px`, textAlign: formConfig.labelPosition === 'right' ? 'right' : 'left' } },
        wrapperCol: isTop ? undefined : { flex: 'auto', style: { minWidth: 0 } },
      };
    };
    const itemLayout = getItemLayout(field);

    // 处理普通字段
    switch (field.type) {
      case 'textarea':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Input.TextArea 
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'} 
                rows={4}
                allowClear={field.showClear}
                maxLength={field.maxLength}
                readOnly={field.readOnly}
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      case 'password':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Input.Password 
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'}
                allowClear={field.showClear}
                maxLength={field.maxLength}
                readOnly={field.readOnly}
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      case 'number':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <InputNumber 
                style={{ width: '100%' }} 
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'}
                max={field.maxLength}
                readOnly={field.readOnly}
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      case 'select':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Select
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择'}
                allowClear={field.showClear}
                disabled={field.disabled}
                size={field.size || 'middle'}
              >
                {(field.options || []).map((opt: any, idx: number) => (
                  <Select.Option key={idx} value={opt.value}>{opt.label}</Select.Option>
                ))}
              </Select>
            </AntdForm.Item>
          </div>
        );
      case 'date':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
              getValueFromEvent={(value) => {
                if (!value) return undefined;
                if (value && typeof value === 'object' && 'valueOf' in value && typeof value.valueOf === 'function' && 'isValid' in value && typeof value.isValid === 'function') {
                  if (value.isValid()) {
                    return value.valueOf();
                  }
                  return undefined;
                }
                return value;
              }}
              normalize={(value) => {
                if (!value) return undefined;
                if (typeof value === 'number') {
                  const dayjsValue = dayjs(value);
                  return dayjsValue.isValid() ? dayjsValue : undefined;
                }
                if (typeof value === 'string') {
                  const numValue = Number(value);
                  if (!isNaN(numValue) && numValue > 0) {
                    const dayjsValue = dayjs(numValue);
                    return dayjsValue.isValid() ? dayjsValue : undefined;
                  }
                  const dayjsValue = dayjs(value);
                  return dayjsValue.isValid() ? dayjsValue : undefined;
                }
                if (value && typeof value === 'object' && 'isValid' in value && typeof value.isValid === 'function') {
                  return value.isValid() ? value : undefined;
                }
                return undefined;
              }}
            >
              <DatePicker 
                style={{ width: '100%' }} 
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择日期'}
                allowClear={field.showClear}
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      case 'daterange':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期范围' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
              getValueFromEvent={(value) => {
                if (!value || !Array.isArray(value) || value.length !== 2) return undefined;
                const [start, end] = value;
                if (start && typeof start === 'object' && 'valueOf' in start && typeof start.valueOf === 'function' && 'isValid' in start && typeof start.isValid === 'function' &&
                    end && typeof end === 'object' && 'valueOf' in end && typeof end.valueOf === 'function' && 'isValid' in end && typeof end.isValid === 'function') {
                  if (start.isValid() && end.isValid()) {
                    return [start.valueOf(), end.valueOf()];
                  }
                  return undefined;
                }
                return value;
              }}
              normalize={(value) => {
                if (!value) return undefined;
                if (Array.isArray(value) && value.length === 2) {
                  const [start, end] = value;
                  let startDayjs: any = null;
                  let endDayjs: any = null;
                  
                  if (typeof start === 'number') {
                    startDayjs = dayjs(start);
                    startDayjs = startDayjs.isValid() ? startDayjs : null;
                  } else if (typeof start === 'string') {
                    const numValue = Number(start);
                    if (!isNaN(numValue) && numValue > 0) {
                      startDayjs = dayjs(numValue);
                      startDayjs = startDayjs.isValid() ? startDayjs : null;
                    } else {
                      startDayjs = dayjs(start);
                      startDayjs = startDayjs.isValid() ? startDayjs : null;
                    }
                  } else if (start && typeof start === 'object' && 'isValid' in start && typeof start.isValid === 'function') {
                    startDayjs = start.isValid() ? start : null;
                  }
                  
                  if (typeof end === 'number') {
                    endDayjs = dayjs(end);
                    endDayjs = endDayjs.isValid() ? endDayjs : null;
                  } else if (typeof end === 'string') {
                    const numValue = Number(end);
                    if (!isNaN(numValue) && numValue > 0) {
                      endDayjs = dayjs(numValue);
                      endDayjs = endDayjs.isValid() ? endDayjs : null;
                    } else {
                      endDayjs = dayjs(end);
                      endDayjs = endDayjs.isValid() ? endDayjs : null;
                    }
                  } else if (end && typeof end === 'object' && 'isValid' in end && typeof end.isValid === 'function') {
                    endDayjs = end.isValid() ? end : null;
                  }
                  
                  if (startDayjs && endDayjs) {
                    return [startDayjs, endDayjs];
                  }
                }
                return undefined;
              }}
            >
              <DatePicker.RangePicker 
                style={{ width: '100%' }} 
                placeholder={Array.isArray(field.placeholder) ? field.placeholder as [string, string] : ['开始日期', '结束日期']}
                allowClear={field.showClear}
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      case 'datetime':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期时间' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
              getValueFromEvent={(value) => {
                if (!value) return undefined;
                if (value && typeof value === 'object' && 'valueOf' in value) {
                  return value.valueOf();
                }
                return value;
              }}
              normalize={(value) => {
                if (!value) return undefined;
                if (typeof value === 'number') {
                  const dayjsValue = dayjs(value);
                  return dayjsValue.isValid() ? dayjsValue : undefined;
                }
                if (typeof value === 'string') {
                  const numValue = Number(value);
                  if (!isNaN(numValue) && numValue > 0) {
                    const dayjsValue = dayjs(numValue);
                    return dayjsValue.isValid() ? dayjsValue : undefined;
                  }
                  const dayjsValue = dayjs(value);
                  return dayjsValue.isValid() ? dayjsValue : undefined;
                }
                if (value && typeof value === 'object' && 'isValid' in value && typeof value.isValid === 'function') {
                  return value.isValid() ? value : undefined;
                }
                return undefined;
              }}
            >
              <DatePicker 
                style={{ width: '100%' }} 
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择日期时间'}
                allowClear={field.showClear}
                showTime={{ format: 'HH:mm:ss' }}
                format="YYYY-MM-DD HH:mm:ss"
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      case 'switch':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
              help={field.hint}
              valuePropName="checked"
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Switch disabled={field.disabled} />
            </AntdForm.Item>
          </div>
        );
      case 'radio':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Radio.Group disabled={field.disabled}>
                {(field.options || []).map((opt: any, idx: number) => (
                  <Radio key={idx} value={opt.value}>{opt.label}</Radio>
                ))}
              </Radio.Group>
            </AntdForm.Item>
          </div>
        );
      case 'checkbox':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Checkbox.Group disabled={field.disabled}>
                {(field.options || []).map((opt: any, idx: number) => (
                  <Checkbox key={idx} value={opt.value}>{opt.label}</Checkbox>
                ))}
              </Checkbox.Group>
            </AntdForm.Item>
          </div>
        );
      case 'cascader':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Cascader
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择'}
                options={field.cascaderOptions || []}
                className="w-full"
                allowClear={field.showClear}
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      case 'upload':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请上传' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <FormUploadField
                uploadType={field.uploadType}
                maxCount={field.maxCount}
                accept={field.accept}
                disabled={field.disabled}
              />
            </AntdForm.Item>
          </div>
        );
      case 'time':
      case 'timepicker':
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择时间' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <DatePicker 
                style={{ width: '100%' }} 
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择时间'}
                allowClear={field.showClear}
                picker="time"
                format="HH:mm:ss"
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
      default:
        // 检查 inputType 是否为时间类型
        const inputType = field.inputType || field.type;
        if (inputType === 'date' || inputType === 'datetime' || inputType === 'time' || inputType === 'timepicker') {
          if (inputType === 'datetime') {
            return (
              <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
                <AntdForm.Item
                  label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
                  name={field.name || field.field}
                  required={field.required && !formConfig.hideRequiredMark}
                  rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期时间' }] : []}
                  help={field.hint}
                  labelCol={itemLayout.labelCol}
                  wrapperCol={itemLayout.wrapperCol}
                >
                  <DatePicker 
                    style={{ width: '100%' }} 
                    placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择日期时间'}
                    allowClear={field.showClear}
                    showTime={{ format: 'HH:mm:ss' }}
                    format="YYYY-MM-DD HH:mm:ss"
                    disabled={field.disabled}
                    size={field.size || 'middle'}
                  />
                </AntdForm.Item>
              </div>
            );
          } else if (inputType === 'time' || inputType === 'timepicker') {
            return (
              <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
                <AntdForm.Item
                  label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
                  name={field.name || field.field}
                  required={field.required && !formConfig.hideRequiredMark}
                  rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择时间' }] : []}
                  help={field.hint}
                  labelCol={itemLayout.labelCol}
                  wrapperCol={itemLayout.wrapperCol}
                >
                  <DatePicker 
                    style={{ width: '100%' }} 
                    placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择时间'}
                    allowClear={field.showClear}
                    picker="time"
                    format="HH:mm:ss"
                    disabled={field.disabled}
                    size={field.size || 'middle'}
                  />
                </AntdForm.Item>
              </div>
            );
          } else {
            return (
              <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
                <AntdForm.Item
                  label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
                  name={field.name || field.field}
                  required={field.required && !formConfig.hideRequiredMark}
                  rules={field.required ? [{ required: true, message: field.requiredMessage || '请选择日期' }] : []}
                  help={field.hint}
                  labelCol={itemLayout.labelCol}
                  wrapperCol={itemLayout.wrapperCol}
                >
                  <DatePicker 
                    style={{ width: '100%' }} 
                    placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请选择日期'}
                    allowClear={field.showClear}
                    disabled={field.disabled}
                    size={field.size || 'middle'}
                  />
                </AntdForm.Item>
              </div>
            );
          }
        }
        
        // 其他类型使用 Input
        return (
          <div key={field.id} style={{ ...spanStyle, backgroundColor: '#f5f5f5', padding: '12px', borderRadius: '12px', marginBottom: '12px', border: '1px solid #e0e0e0' }}>
            <AntdForm.Item
              label={(field.label || field.title || '') + (formConfig.labelSuffix || '')}
              name={field.name || field.field}
              required={field.required && !formConfig.hideRequiredMark}
              rules={field.required ? [{ required: true, message: field.requiredMessage || '请输入' }] : []}
              help={field.hint}
              labelCol={itemLayout.labelCol}
              wrapperCol={itemLayout.wrapperCol}
            >
              <Input 
                type={field.inputType || 'text'}
                placeholder={typeof field.placeholder === 'string' ? field.placeholder : '请输入'}
                allowClear={field.showClear}
                maxLength={field.maxLength}
                readOnly={field.readOnly}
                disabled={field.disabled}
                size={field.size || 'middle'}
              />
            </AntdForm.Item>
          </div>
        );
    }
  };

  // 查看任务详情（完整复刻任务管理页面的逻辑）
  const handleViewTaskDetail = async (task: MyTaskVO) => {
    console.log('Dashboard: handleViewTaskDetail 被调用', task);
    
    if (!task.nodeId) {
      console.warn('Dashboard: 节点ID不存在', task);
      message.warning(t('cockpit.nodeIdNotExist'));
      return;
    }
    
    setTaskDetailLoading(true);
    setTaskDetailVisible(true);
    console.log('Dashboard: 弹框状态已设置为 true (加载中)');
    
    try {
      console.log('Dashboard: 开始获取节点详情', { nodeId: task.nodeId });
      const response = await taskManagementApi.getAdminWorkNodeDetail(task.nodeId);
      console.log('Dashboard: 节点详情响应', response);
      
      let data: any = response;
    
      // 直接从第一层 data.formId 获取 formId
      let extractedFormId: number | undefined = undefined;
      if (data?.formId !== undefined && data?.formId !== null) {
        const formIdValue = data.formId;
        if (typeof formIdValue === 'string') {
          const parsed = parseInt(formIdValue, 10);
          if (!isNaN(parsed)) {
            extractedFormId = parsed;
            console.log('Dashboard: ✅ 从 data.formId (字符串) 提取到 formId', extractedFormId);
          }
        } else if (typeof formIdValue === 'number') {
          extractedFormId = formIdValue;
          console.log('Dashboard: ✅ 从 data.formId (数字) 提取到 formId', extractedFormId);
        }
      }
      
      if (extractedFormId === undefined) {
        console.warn('Dashboard: ⚠️ 未能提取到 formId', {
          'data.formId': data?.formId,
          'data': data
        });
      }
      
      // 合并列表数据中的作业信息
      const detailDataWithWorkInfo: MyTaskNodeDetailVO = {
        ...(data || {}),
        workName: task.name || data?.workName || data?.name,
        orderNo: task.orderNo || data?.orderNo,
        workerUserName: task.workerUserName || data?.workerUserName,
        initiatorName: task.initiatorName || data?.initiatorName || data?.initiator || task.initiator || '',
        workTime: task.workTime || data?.workTime,
        type: data?.type || data?.nodeType || '',
        nodeType: data?.nodeType || data?.type || '',
        formId: extractedFormId,
      };
      
      console.log('Dashboard: 合并后的详情数据', detailDataWithWorkInfo);
      
      // 先设置数据，确保弹框有内容显示
      setTaskDetailData(detailDataWithWorkInfo);
      setTaskDetailVisible(true);
      setTaskDetailLoading(false);
      
      // 根据节点类型决定是否需要获取表单
      const nodeType = detailDataWithWorkInfo.type || detailDataWithWorkInfo.nodeType || '';
      const isIsolation =
        isWorkflowLockSchemeType(nodeType) || isWorkflowCoLockType(nodeType);
      const isReleaseIsolation =
        isWorkflowUnlockSchemeType(nodeType) || isWorkflowUnlockCoLockType(nodeType);
      const isReturnLock = nodeType === 'returnLock';
      const isolationType = String(detailDataWithWorkInfo?.isolationType ?? '').trim();
      const isBlindOrDismantle = isolationType === '0' || isolationType === '2'; // 0=盲板 2=拆除
      const isApproved = detailDataWithWorkInfo.approvalStatus === 'approved';
      const formId = detailDataWithWorkInfo.formId;
      const hasFormId = formId !== undefined && formId !== null && (
        typeof formId === 'number' || 
        (typeof formId === 'string' && formId !== '' && formId.trim() !== '')
      );
      const hasFormData = detailDataWithWorkInfo.formData && (
        (typeof detailDataWithWorkInfo.formData === 'string' && detailDataWithWorkInfo.formData.trim() !== '') ||
        (typeof detailDataWithWorkInfo.formData === 'object' && Object.keys(detailDataWithWorkInfo.formData).length > 0)
      );
      
      // 当前节点无表单时清空表单 state，避免完成/结束节点误展示上一节点的自定义表单
      if (!hasFormId && !(isApproved && hasFormData)) {
        setFormData({ rule: [], option: {} });
        setOriginalFields([]);
        setOriginalConf('');
      }
      
      // 打开盲板/拆除详情时先清空设备编号和附件，后续若有 formData 再回填
      if (isIsolation || isReleaseIsolation) {
        const isolationType = String(detailDataWithWorkInfo.isolationType ?? '').trim();
        if (isolationType === '0' || isolationType === '2') {
          setIsolationDeviceNumber('');
          setIsolationFileList([]);
        }
      }
      
      // 如果任务状态为"已通过"且有 formData，则从 formData 中解析表单结构
      if (isApproved && hasFormData) {
        console.log('Dashboard: ✅ 任务已通过，从 formData 中解析表单结构');
        setFormLoading(true);
        
        try {
          let parsedFormData: any;
          if (typeof detailDataWithWorkInfo.formData === 'string') {
            parsedFormData = JSON.parse(detailDataWithWorkInfo.formData);
          } else {
            parsedFormData = detailDataWithWorkInfo.formData;
          }
          
          const conf = parsedFormData.conf;
          const fields = parsedFormData.fields;
          
          if (conf && fields) {
            const confString = typeof conf === 'string' ? conf : JSON.stringify(conf);
            const fieldsArray = Array.isArray(fields) ? fields : [];
            const fieldsStringArray = fieldsArray.map((field: any) => {
              return typeof field === 'string' ? field : JSON.stringify(field);
            });
            
            setOriginalConf(confString);
            setOriginalFields(fieldsStringArray);
            
            // 解析字段值用于回显
            const formValues: any = {};
            const fieldTypeMap: { [key: string]: string } = {};
            
            fieldsStringArray.forEach((fieldString: string) => {
              try {
                const fieldObj = typeof fieldString === 'string' ? JSON.parse(fieldString) : fieldString;
                const fieldName = fieldObj.name || fieldObj.field;
                if (fieldName) {
                  fieldTypeMap[fieldName] = fieldObj.type;
                }
              } catch (e) {
                console.error('Dashboard: 解析字段 JSON 失败', e, fieldString);
              }
            });
            
            fieldsStringArray.forEach((fieldString: string) => {
              try {
                const fieldObj = typeof fieldString === 'string' ? JSON.parse(fieldString) : fieldString;
                const fieldName = fieldObj.name || fieldObj.field;
                if (fieldName && fieldObj.value !== undefined && fieldObj.value !== null) {
                  const fieldType = fieldTypeMap[fieldName];
                  let value = fieldObj.value;
                  
                  if (fieldType === 'date' || fieldType === 'datetime') {
                    if (typeof value === 'string' && value.trim() !== '') {
                      const dayjsValue = dayjs(value);
                      formValues[fieldName] = dayjsValue.isValid() ? dayjsValue : undefined;
                    } else {
                      formValues[fieldName] = undefined;
                    }
                  } else if (fieldType === 'daterange') {
                    if (Array.isArray(value) && value.length === 2) {
                      const [start, end] = value;
                      const startDayjs = typeof start === 'string' && start ? dayjs(start) : null;
                      const endDayjs = typeof end === 'string' && end ? dayjs(end) : null;
                      if (startDayjs && startDayjs.isValid() && endDayjs && endDayjs.isValid()) {
                        formValues[fieldName] = [startDayjs, endDayjs];
                      } else {
                        formValues[fieldName] = undefined;
                      }
                    } else {
                      formValues[fieldName] = undefined;
                    }
                  } else {
                    formValues[fieldName] = value;
                  }
                }
              } catch (e) {
                console.error('Dashboard: 解析字段 JSON 失败', e, fieldString);
              }
            });
            
            setConfAndFields2(setFormData, conf, fields);
            const convertedFormValues = convertDateValues(formValues, fieldsStringArray);
            
            setTimeout(() => {
              taskDetailForm.setFieldsValue(convertedFormValues);
              console.log('Dashboard: 表单数据已回填（从 formData）', convertedFormValues);
            }, 100);
            // 有 conf/fields 时也回显 deviceNumber、attachments；attachments 可能是 JSON 字符串
            const normAttachments = (att: any): any[] => {
              if (att == null) return []; if (Array.isArray(att)) return att;
              if (typeof att === 'string' && att.trim()) { try { const p = JSON.parse(att); return Array.isArray(p) ? p : []; } catch { return []; } } return [];
            };
            const listInConf = normAttachments(parsedFormData.attachments).length ? normAttachments(parsedFormData.attachments) : normAttachments((detailDataWithWorkInfo as any).attachments);
            const deviceNumInConf = parsedFormData.deviceNumber ?? (detailDataWithWorkInfo as any).deviceNumber;
            const hasDeviceInConf = deviceNumInConf !== undefined && deviceNumInConf !== null;
            if (hasDeviceInConf || listInConf.length > 0) {
              setIsolationDeviceNumber(deviceNumInConf ?? '');
              setIsolationFileList(
                listInConf.map((item: any, idx: number) => ({
                  uid: `echo-${idx}-${item.url || item.name || idx}`,
                  name: item.name || `文件${idx + 1}`,
                  url: item.url || item.response,
                  status: 'done',
                  response: item.url || item.response,
                }))
              );
            }
          } else if (
            (() => { const d = parsedFormData.deviceNumber; const a = parsedFormData.attachments; if (d !== undefined && d !== null) return true; if (a == null) return false; if (Array.isArray(a) && a.length > 0) return true; if (typeof a === 'string' && a.trim()) { try { const p = JSON.parse(a); return Array.isArray(p) && p.length > 0; } catch { return false; } } return false; })()
          ) {
            const listElse = (() => { const a = parsedFormData.attachments; if (a == null) return []; if (Array.isArray(a)) return a; if (typeof a === 'string' && a.trim()) { try { const p = JSON.parse(a); return Array.isArray(p) ? p : []; } catch { return []; } } return []; })();
            setIsolationDeviceNumber(parsedFormData.deviceNumber ?? '');
            setIsolationFileList(
              listElse.map((item: any, idx: number) => ({
                uid: `echo-${idx}-${item.url || item.name || idx}`,
                name: item.name || `文件${idx + 1}`,
                url: item.url || item.response,
                status: 'done',
                response: item.url || item.response,
              }))
            );
          } else {
            console.warn('Dashboard: formData 中缺少 conf 或 fields', { conf: !!conf, fields: !!fields });
            message.warning(t('cockpit.formDataIncomplete'));
          }
        } catch (e) {
          console.error('Dashboard: 解析 formData 失败', e);
          message.error(t('cockpit.parseFormDataFailed') + ': ' + (e instanceof Error ? e.message : String(e)));
        } finally {
          setFormLoading(false);
        }
      }
      // 有 formId 时从接口获取表单：① 审核等非隔离节点 ② 盲板/拆除节点（隔离或解除隔离且隔离方式为盲板或拆除）
      else if (hasFormId && (
        (!isIsolation && !isReleaseIsolation && !isReturnLock) ||
        ((isIsolation || isReleaseIsolation) && isBlindOrDismantle)
      )) {
        console.log('Dashboard: ✅ 满足条件，开始获取表单', { formId, nodeType, isBlindOrDismantle });
        setFormData({ rule: [], option: {} });
        setOriginalFields([]);
        setOriginalConf('');
        setFormLoading(true);
        
        (async () => {
          try {
            const numericFormId = typeof formId === 'string' ? parseInt(formId, 10) : formId;
            if (isNaN(numericFormId)) {
              console.error('Dashboard: formId 不是有效数字', formId);
              message.error(t('cockpit.formIdInvalid'));
              setFormLoading(false);
              return;
            }
            
            console.log('Dashboard: 🚀 开始调用表单接口', { formId: numericFormId, nodeType });
            const FormApi = await import('../api/bpm/form');
            const formDetailResponse = await FormApi.getForm(numericFormId);
            console.log('Dashboard: ✅ 表单接口调用成功', formDetailResponse);
            
            let formDetail: any = formDetailResponse;
            if (formDetailResponse && typeof formDetailResponse === 'object' && 'data' in formDetailResponse) {
              formDetail = (formDetailResponse as any).data || formDetailResponse;
            }
            
            const conf = formDetail?.conf || formDetail?.formConfig;
            const fields = formDetail?.fields || formDetail?.formFields;
            
            if (conf && fields) {
              const confString = typeof conf === 'string' ? conf : JSON.stringify(conf);
              const fieldsArray = Array.isArray(fields) ? fields : [];
              const fieldsStringArray = fieldsArray.map((field: any) => {
                return typeof field === 'string' ? field : JSON.stringify(field);
              });
              
              setOriginalConf(confString);
              setOriginalFields(fieldsStringArray);
              
              setConfAndFields2(setFormData, conf, fields);
              
              // 仅任务已完成（approved）时回显表单数据；进行中一律不回显并清空表单
              const shouldEchoFormData = detailDataWithWorkInfo.formData && isApproved;
              if (shouldEchoFormData) {
                try {
                  let formValues = typeof detailDataWithWorkInfo.formData === 'string' 
                    ? JSON.parse(detailDataWithWorkInfo.formData) 
                    : detailDataWithWorkInfo.formData;
                  
                  formValues = convertDateValues(formValues, fieldsArray);
                  
                  const cleanedFormValues: any = {};
                  Object.keys(formValues).forEach(key => {
                    const value = formValues[key];
                    const field = fieldsArray.find((f: any) => {
                      const fieldObj = typeof f === 'string' ? JSON.parse(f) : f;
                      return (fieldObj.name || fieldObj.field) === key;
                    });
                    
                    if (field) {
                      const fieldObj = typeof field === 'string' ? JSON.parse(field) : field;
                      const fieldType = fieldObj.type;
                      
                      if (fieldType === 'date' || fieldType === 'datetime' || fieldType === 'timepicker') {
                        if (isValidDayjs(value)) {
                          cleanedFormValues[key] = value;
                        } else if (value !== null && value !== undefined) {
                          const dayjsValue = safeToDayjs(value);
                          cleanedFormValues[key] = dayjsValue || undefined;
                        } else {
                          cleanedFormValues[key] = undefined;
                        }
                      } else if (fieldType === 'daterange') {
                        if (Array.isArray(value) && value.length === 2) {
                          const [start, end] = value;
                          let startDayjs: dayjs.Dayjs | null = null;
                          if (isValidDayjs(start)) {
                            startDayjs = start;
                          } else {
                            startDayjs = safeToDayjs(start);
                          }
                          let endDayjs: dayjs.Dayjs | null = null;
                          if (isValidDayjs(end)) {
                            endDayjs = end;
                          } else {
                            endDayjs = safeToDayjs(end);
                          }
                          cleanedFormValues[key] = (startDayjs && endDayjs) ? [startDayjs, endDayjs] : undefined;
                        } else {
                          cleanedFormValues[key] = undefined;
                        }
                      } else {
                        cleanedFormValues[key] = value;
                      }
                    } else {
                      cleanedFormValues[key] = value;
                    }
                  });
                  
                  setTimeout(() => {
                    try {
                      taskDetailForm.setFieldsValue(cleanedFormValues);
                      console.log('Dashboard: 表单数据已回填', cleanedFormValues);
                    } catch (e) {
                      console.error('Dashboard: 设置表单值失败', e);
                    }
                  }, 100);
                } catch (e) {
                  console.error('Dashboard: 解析表单数据失败', e);
                }
              } else if (!isApproved) {
                // 任务进行中：清空自定义表单，避免带出历史或隔离方案等填写内容
                setTimeout(() => { try { taskDetailForm.resetFields(); } catch (_) { /* ignore */ } }, 100);
              }
              // 隔离/解除隔离完成查看详情：从 formData 回显 deviceNumber、attachments（attachments 可能是 JSON 字符串）
              if (isApproved && (isIsolation || isReleaseIsolation)) {
                try {
                  const normAtt = (att: any): any[] => { if (att == null) return []; if (Array.isArray(att)) return att; if (typeof att === 'string' && att.trim()) { try { const p = JSON.parse(att); return Array.isArray(p) ? p : []; } catch { return []; } } return []; };
                  let deviceNum: any; let listF: any[];
                  if (detailDataWithWorkInfo.formData) {
                    const parsed = typeof detailDataWithWorkInfo.formData === 'string' ? JSON.parse(detailDataWithWorkInfo.formData) : detailDataWithWorkInfo.formData;
                    listF = normAtt(parsed.attachments).length ? normAtt(parsed.attachments) : normAtt((detailDataWithWorkInfo as any).attachments);
                    deviceNum = parsed.deviceNumber ?? (detailDataWithWorkInfo as any).deviceNumber;
                  } else {
                    deviceNum = (detailDataWithWorkInfo as any).deviceNumber;
                    listF = normAtt((detailDataWithWorkInfo as any).attachments);
                  }
                  if ((deviceNum !== undefined && deviceNum !== null) || listF.length > 0) {
                    setIsolationDeviceNumber(deviceNum ?? '');
                    setIsolationFileList(listF.map((item: any, idx: number) => ({ uid: `echo-${idx}-${item.url || item.name || idx}`, name: item.name || `文件${idx + 1}`, url: item.url || item.response, status: 'done', response: item.url || item.response })));
                  }
                } catch (_) { /* ignore */ }
              }
            } else {
              console.warn('Dashboard: 表单详情缺少配置或字段', { conf: !!conf, fields: !!fields });
              message.warning(t('cockpit.formConfigIncomplete'));
            }
          } catch (e) {
            console.error('Dashboard: 获取表单详情失败', e);
            message.error(t('cockpit.getFormDetailFailed') + ': ' + (e instanceof Error ? e.message : String(e)));
          } finally {
            setFormLoading(false);
          }
        })();
      } else {
        setFormLoading(false);
        if (isApproved && (isIsolation || isReleaseIsolation)) {
          try {
            const normAtt = (att: any): any[] => { if (att == null) return []; if (Array.isArray(att)) return att; if (typeof att === 'string' && att.trim()) { try { const p = JSON.parse(att); return Array.isArray(p) ? p : []; } catch { return []; } } return []; };
            const deviceNum = (detailDataWithWorkInfo as any).deviceNumber;
            const listF = normAtt((detailDataWithWorkInfo as any).attachments);
            if ((deviceNum !== undefined && deviceNum !== null) || listF.length > 0) {
              setIsolationDeviceNumber(deviceNum ?? '');
              setIsolationFileList(listF.map((item: any, idx: number) => ({ uid: `echo-${idx}-${item.url || item.name || idx}`, name: item.name || `文件${idx + 1}`, url: item.url || item.response, status: 'done', response: item.url || item.response })));
            }
          } catch (_) { /* ignore */ }
        }
      }
      
      // 回显审核意见
      if (detailDataWithWorkInfo.approvalOpinion && detailDataWithWorkInfo.approvalOpinion !== 'pending') {
        setApprovalComment(detailDataWithWorkInfo.approvalOpinion);
      } else {
        setApprovalComment('');
      }
      
      console.log('Dashboard: 弹框已打开', { detailVisible: true, detailData: detailDataWithWorkInfo });
    } catch (error: any) {
      console.error('Dashboard: 获取节点详情失败', error);
      toast.error(error.message || t('cockpit.getNodeDetailFailed'));
      if (!taskDetailData) {
        setTaskDetailData({
          id: task.nodeId,
          nodeId: task.nodeId,
          workId: task.workId,
          workName: task.name,
          orderNo: task.orderNo,
          workerUserName: task.workerUserName,
          workTime: task.workTime,
          type: '',
        } as MyTaskNodeDetailVO);
      }
      setTaskDetailVisible(true);
    } finally {
      setTaskDetailLoading(false);
    }
  };

  // 获取任务状态文本（使用字典）
  const getTaskStatusText = (status: string | number | undefined): string => {
    if (!status) return t('cockpit.unknown');
    const statusStr = String(status).toLowerCase();
    const statusItem = approvalStatusDictList.find(item => String(item.value).toLowerCase() === statusStr);
    if (statusItem) {
      return statusItem.label || t('cockpit.unknown');
    }
    // 如果没有找到字典值，使用默认映射
    const statusMap: Record<string, string> = {
      'pending': t('cockpit.pendingAudit'),
      'approved': t('cockpit.approved'),
      'rejected': t('cockpit.rejected'),
      'unaudited': t('cockpit.unaudited'),
    };
    return statusMap[statusStr] || t('cockpit.unknown');
  };

  // 获取任务状态样式（审批状态）
  const getTaskStatusStyle = (status: string | number | undefined): React.CSSProperties => {
    if (!status) {
      return {
        backgroundColor: '#e5e5e5',
        color: '#333333',
      };
    }
    const statusStr = String(status).toLowerCase();
    
    // 先获取状态文本，根据文本判断颜色
    const statusText = getTaskStatusText(status);
    const statusTextLower = statusText.toLowerCase();
    
    // 根据状态文本判断颜色
    // 待执行、待发布：灰色 #e5e5e5
    if (statusTextLower.includes('待执行') || statusTextLower.includes('待发布') || 
        statusTextLower.includes('未开始') || statusTextLower.includes('未审核') || 
        statusTextLower.includes('待开始') || statusTextLower.includes('unaudited')) {
      return {
        backgroundColor: '#e5e5e5',
        color: '#333333',
      };
    }
    // 进行中：蓝色 #1677ff
    if (statusTextLower.includes('进行中') || statusTextLower.includes('待审核') || 
        statusTextLower.includes('pending') || statusTextLower.includes('执行中')) {
      return {
        backgroundColor: '#1677ff',
        color: '#ffffff',
      };
    }
    // 已完成：绿色 #0acb57
    if (statusTextLower.includes('已完成') || statusTextLower.includes('已通过') || 
        statusTextLower.includes('approved') || statusTextLower.includes('执行完成')) {
      return {
        backgroundColor: '#0acb57',
        color: '#ffffff',
      };
    }
    // 已退回、已驳回：橙色 #ff9500
    if (statusTextLower.includes('已退回') || statusTextLower.includes('已驳回') || 
        statusTextLower.includes('rejected')) {
      return {
        backgroundColor: '#ff9500',
        color: '#ffffff',
      };
    }
    
    // 默认样式
    return {
      backgroundColor: '#e5e5e5',
      color: '#333333',
    };
  };

  // 获取任务状态文本和样式（兼容函数）
  const getTaskStatusInfo = (status: string | number | undefined) => {
    return {
      label: getTaskStatusText(status),
      style: getTaskStatusStyle(status),
    };
  };

  // 获取作业状态标签样式
  const getStatusBadge = (status: string) => {
    const statusMap: Record<string, { label: string; className: string }> = {
      '待执行': { label: t('cockpit.pending'), className: 'bg-gray-100 text-gray-700 border-gray-200' },
      'pending': { label: t('cockpit.pending'), className: 'bg-gray-100 text-gray-700 border-gray-200' },
      'PENDING': { label: t('cockpit.pending'), className: 'bg-gray-100 text-gray-700 border-gray-200' },
      '进行中': { label: t('cockpit.inProgress'), className: 'bg-blue-100 text-blue-700 border-blue-200' },
      'in_progress': { label: t('cockpit.inProgress'), className: 'bg-blue-100 text-blue-700 border-blue-200' },
      'IN_PROGRESS': { label: t('cockpit.inProgress'), className: 'bg-blue-100 text-blue-700 border-blue-200' },
      '已完成': { label: t('cockpit.completed'), className: 'bg-green-100 text-green-700 border-green-200' },
      'completed': { label: t('cockpit.completed'), className: 'bg-green-100 text-green-700 border-green-200' },
      'COMPLETED': { label: t('cockpit.completed'), className: 'bg-green-100 text-green-700 border-green-200' },
      '逾期': { label: t('cockpit.overdue'), className: 'bg-red-100 text-red-700 border-red-200' },
      'overdue': { label: t('cockpit.overdue'), className: 'bg-red-100 text-red-700 border-red-200' },
      'OVERDUE': { label: t('cockpit.overdue'), className: 'bg-red-100 text-red-700 border-red-200' },
    };
    
    return statusMap[status] || { label: status || t('cockpit.unknown'), className: 'bg-gray-100 text-gray-700 border-gray-200' };
  };

  // 从ticketName中提取作业类型
  const getJobType = (ticketName: string): string => {
    if (ticketName.includes('换产') || ticketName.includes('投产')) {
      return t('cockpit.production');
    } else if (ticketName.includes('维修')) {
      return t('cockpit.maintenance');
    } else if (ticketName.includes('PM')) {
      return 'PM';
    }
    return t('cockpit.unknown');
  };

  // 获取作业状态显示文本和样式（从字典获取）
  const getJobStatusInfo = (status: string | number | undefined) => {
    if (!status) {
      return { label: t('cockpit.unknown'), className: 'bg-gray-100 text-gray-700 border-gray-200' };
    }
    
    // 从字典中查找状态文本
    const statusItem = jobStatusDictList.find(item => String(item.value) === String(status));
    const statusText = statusItem ? (statusItem.label || '') : String(status || t('cockpit.unknown'));
    const statusTextLower = statusText.toLowerCase();
    
    // 根据状态文本判断样式
    // 待执行、待发布：灰色
    if (statusTextLower.includes('待执行') || statusTextLower.includes('待发布') || 
        statusTextLower.includes('pending') || statusTextLower.includes('unreleased')) {
      return { label: statusText, className: 'bg-gray-100 text-gray-700 border-gray-200' };
    }
    // 进行中、执行中：蓝色
    if (statusTextLower.includes('进行中') || statusTextLower.includes('执行中') || 
        statusTextLower.includes('running') || statusTextLower.includes('in_progress')) {
      return { label: statusText, className: 'bg-blue-100 text-blue-700 border-blue-200' };
    }
    // 已完成、执行完成：绿色
    if (statusTextLower.includes('已完成') || statusTextLower.includes('执行完成') || 
        statusTextLower.includes('completed') || statusTextLower.includes('完成')) {
      return { label: statusText, className: 'bg-green-100 text-green-700 border-green-200' };
    }
    // 已退回：橙色
    if (statusTextLower.includes('已退回') || statusTextLower.includes('rejected')) {
      return { label: statusText, className: 'bg-orange-100 text-orange-700 border-orange-200' };
    }
    // 已跳过：灰色
    if (statusTextLower.includes('已跳过') || statusTextLower.includes('skipped')) {
      return { label: statusText, className: 'bg-gray-100 text-gray-700 border-gray-200' };
    }
    
    // 如果没有匹配到，使用字典中的文本，默认灰色样式
    return { label: statusText, className: 'bg-gray-100 text-gray-700 border-gray-200' };
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center h-96">
        <div className="text-gray-500">{t('cockpit.loading')}</div>
      </div>
    );
  }

  return (
    <div className="p-6 space-y-6 bg-gray-50 min-h-screen">
      <style>{`
        .custom-collapse .ant-collapse-item {
          border: none !important;
          border-bottom: 1px solid #e5e7eb !important;
        }
        .custom-collapse .ant-collapse-item:last-child {
          border-bottom: none !important;
        }
        .custom-collapse .ant-collapse-item .ant-collapse-header {
          padding: 0 !important;
          display: flex !important;
          flex-direction: row !important;
          align-items: center !important;
          position: relative !important;
        }
        .custom-collapse .ant-collapse-item .ant-collapse-header .ant-collapse-arrow {
          display: none !important;
        }
        .custom-collapse .ant-collapse-content {
          border-top: 1px solid #e5e7eb !important;
        }
      `}</style>
      {/* 作业管理部分 */}
      <div>
        {/* 作业状态统计卡片 */}
        <div className="flex mb-6 gap-8">
          {/* 待发布作业 - 灰色主题 */}
          <div 
            className="flex-1 bg-white rounded-lg border border-gray-200 p-4 shadow-sm hover:shadow-md transition-shadow relative overflow-hidden cursor-pointer"
            onClick={() => {
              // 保存status到 sessionStorage
              sessionStorage.setItem('workManagementStatus', 'unreleased');
              // 触发自定义事件切换菜单
              window.dispatchEvent(new CustomEvent('switchToMenu', {
                detail: {
                  menu: 'isolationWork',
                  subMenu: 'workManagement'
                }
              }));
            }}
          >
            <div className="flex items-start justify-between mb-3">
              <div className="text-sm text-gray-500 font-medium">{t('cockpit.pendingJobs')}</div>
              <div className="p-3 rounded-xl flex items-center justify-center flex-shrink-0" style={{ backgroundColor: 'rgba(188, 185, 183, 0.2)' }}>
                <Clock className="w-6 h-6 text-black-700" strokeWidth={2} />
              </div>
            </div>
            <div>
              <div className="text-2xl font-bold text-gray-900 leading-none">
                {managerWorkCount.unreleasedCount ?? statistics.pendingJobsCount ?? 0} <span className="text-base font-normal text-gray-500">{t('cockpit.items')}</span>
              </div>
            </div>
          </div>
          
          {/* 进行中作业 - 蓝色主题 */}
          <div 
            className="flex-1 bg-white rounded-lg border border-gray-200 p-4 shadow-sm hover:shadow-md transition-shadow relative overflow-hidden cursor-pointer"
            onClick={() => {
              // 保存status到 sessionStorage
              sessionStorage.setItem('workManagementStatus', 'running');
              // 触发自定义事件切换菜单
              window.dispatchEvent(new CustomEvent('switchToMenu', {
                detail: {
                  menu: 'isolationWork',
                  subMenu: 'workManagement'
                }
              }));
            }}
          >
            <div className="flex items-start justify-between mb-3">
              <div className="text-sm text-gray-500 font-medium">{t('cockpit.inProgressJobs')}</div>
              <div className="p-3 rounded-xl flex items-center justify-center flex-shrink-0" style={{ backgroundColor: 'rgba(59, 130, 246, 0.2)' }}>
                <PlayCircle className="w-6 h-6 text-blue-700" strokeWidth={2} />
              </div>
            </div>
            <div>
              <div className="text-2xl font-bold text-gray-900 leading-none">
                {managerWorkCount.runningCount ?? statistics.inProgressJobsCount ?? 0} <span className="text-base font-normal text-gray-500">{t('cockpit.items')}</span>
              </div>
            </div>
          </div>
          
          {/* 已完成作业 - 绿色主题 */}
          <div 
            className="flex-1 bg-white rounded-lg border border-gray-200 p-4 shadow-sm hover:shadow-md transition-shadow relative overflow-hidden cursor-pointer"
            onClick={() => {
              // 保存status到 sessionStorage
              sessionStorage.setItem('workManagementStatus', 'completed');
              // 触发自定义事件切换菜单
              window.dispatchEvent(new CustomEvent('switchToMenu', {
                detail: {
                  menu: 'isolationWork',
                  subMenu: 'workManagement'
                }
              }));
            }}
          >
            <div className="flex items-start justify-between mb-3">
              <div className="text-sm text-gray-500 font-medium">{t('cockpit.completedJobs')}</div>
              <div className="p-3 rounded-xl flex items-center justify-center flex-shrink-0" style={{ backgroundColor: 'rgba(34, 197, 94, 0.2)' }}>
                <CheckCircle className="w-6 h-6 text-green-700" strokeWidth={2} />
              </div>
            </div>
            <div>
              <div className="text-2xl font-bold text-gray-900 leading-none">
                {managerWorkCount.completedCount ?? statistics.completedJobsCount ?? 0} <span className="text-base font-normal text-gray-500">{t('cockpit.items')}</span>
              </div>
            </div>
          </div>
          
          {/* 逾期作业 - 红色主题 */}
          {showOverdueJobs && (
            <div className="flex-1 bg-white rounded-lg border border-red-200 p-4 shadow-sm hover:shadow-md transition-shadow relative overflow-hidden">
              <div className="flex items-start justify-between mb-3">
                <div className="text-sm text-gray-500 font-medium">{t('cockpit.overdueJobs')}</div>
                <div className="p-3 rounded-xl flex items-center justify-center flex-shrink-0" style={{ backgroundColor: 'rgba(239, 68, 68, 0.2)' }}>
                  <AlertTriangle className="w-6 h-6 text-red-700" strokeWidth={2} />
                </div>
              </div>
              <div className="flex items-center justify-between">
                <div>
                  <div className="text-2xl font-bold text-gray-900 leading-none">
                    {statistics.overdueJobsCount ?? 0} <span className="text-base font-normal text-gray-500">{t('cockpit.items')}</span>
                  </div>
                </div>
                <button
                  onClick={() => setShowOverdueJobs(false)}
                  className="text-red-600 text-sm font-medium hover:text-red-700 transition-colors"
                >
                  {t('cockpit.hide')}
                </button>
              </div>
            </div>
          )}
        </div>

        {/* 作业列表 */}
        <Card
          title={
            <div className="flex items-center justify-between">
              <span>{t('cockpit.jobListWithTasks')}</span>
              <button
                onClick={() => {
                  // 通过 sessionStorage 传递参数，让 Dashboard 自动切换到作业管理菜单
                  sessionStorage.setItem('navigateToMenu', JSON.stringify({
                    menu: 'isolationWork',
                    subMenu: 'workManagement'
                  }));
                  
                  // 如果当前已经在 dashboard 页面，触发自定义事件来切换菜单
                  if (window.location.pathname === '/dashboard') {
                    // 触发自定义事件，通知 Dashboard 切换菜单
                    window.dispatchEvent(new CustomEvent('switchToMenu', {
                      detail: { menu: 'isolationWork', subMenu: 'workManagement' }
                    }));
                  } else {
                    // 如果不在 dashboard 页面，导航过去
                    navigate('/dashboard');
                  }
                }}
                className="text-sm font-medium border-0 bg-transparent p-0 cursor-pointer"
                style={{ color: '#2563eb' }}
                onMouseEnter={(e) => e.currentTarget.style.color = '#1d4ed8'}
                onMouseLeave={(e) => e.currentTarget.style.color = '#2563eb'}
              >
                {t('cockpit.viewAllJobs')}
              </button>
            </div>
          }
        >
          <div className="border border-gray-200 rounded-lg overflow-hidden">
            {managerDataLoading ? (
              <div className="p-8 text-center text-gray-500">{t('cockpit.loading')}</div>
            ) : managerWorkList.length > 0 ? (
              <Collapse
                activeKey={Array.from(expandedJobs).map(id => String(id))}
                onChange={(keys) => {
                  const keyArray = Array.isArray(keys) ? keys : [keys];
                  if (keyArray.length === 0) {
                    // 全部折叠
                    setExpandedJobs(new Set());
                    setSelectedJob(null);
                  } else {
                    // 只展开一个
                    const jobId = Number(keyArray[keyArray.length - 1]);
                    const newExpanded = new Set<number>();
                    newExpanded.add(jobId);
                    setExpandedJobs(newExpanded);
                    setSelectedJob(jobId);
                    
                    // 从作业数据中直接提取任务列表
                    const job = managerWorkList.find(j => j.id === jobId);
                    if (job) {
                      console.log('Dashboard: 从作业数据中提取任务列表', { jobId, workflowWorkNodeDOList: job.workflowWorkNodeDOList });
                      const taskList = extractTasksFromJob(job);
                      console.log('Dashboard: 提取的任务列表', taskList, '任务数量:', taskList.length);
                      setJobTaskMap(prev => new Map(prev).set(jobId, taskList));
                      // 设置加载状态为完成（因为数据已经在作业数据中了，不需要异步加载）
                      setTaskLoadingMap(prev => {
                        const newMap = new Map(prev);
                        newMap.delete(jobId);
                        return newMap;
                      });
                    } else {
                      console.warn('Dashboard: 未找到作业', jobId);
                      setJobTaskMap(prev => new Map(prev).set(jobId, []));
                    }
                  }
                }}
                ghost
                style={{ background: 'transparent' }}
                className="custom-collapse"
              >
                {managerWorkList.map((job: ManagerWorkItemVO, index: number) => {
                  const isExpanded = expandedJobs.has(job.id!);
                  const isSelected = selectedJob === job.id;
                  const statusInfo = getTaskStatusInfo(job.status);
                  const jobName = job.name || job.orderNo || job.code || `作业#${job.id}`;
                  const responsiblePerson = job.initiatorName || job.initiator || t('cockpit.unassigned');
                  
                  return (
                    <Panel
                      key={String(job.id)}
                      showArrow={false}
                      header={
                        <div 
                          className="p-3 flex items-center relative w-full"
                          style={isSelected ? { backgroundColor: '#eff6ff' } : { backgroundColor: 'white' }}
                          onClick={(e) => {
                            e.stopPropagation();
                            handleJobRowClick(job.id!);
                          }}
                        >
                          {/* 作业名称 - 固定宽度100px，超出显示省略号 */}
                          <div className="flex-shrink-0 min-w-0" style={{ width: '300px' }}>
                            <span className={`text-base truncate block ${
                              isSelected ? '' : 'text-gray-900'
                            }`} style={isSelected ? { color: '#2563eb' } : { color: '#111827' }}>
                              {jobName}
                            </span>
                          </div>
                          
                          {/* 状态标签 - 固定宽度 */}
                          <div className="flex-shrink-0 ml-6" style={{ width: '80px',marginRight:'50px' }}>
                            <span className="inline-flex px-2 py-0.5 rounded text-xs font-medium whitespace-nowrap" style={statusInfo.style}>
                              {statusInfo.label}
                            </span>
                          </div>
                          
                          {/* 作业发起人 - 固定宽度 */}
                          <div className="flex-shrink-0 ml-6" style={{ width: '160px' }}>
                            <span className={`text-sm truncate block ${
                              isSelected ? '' : 'text-gray-900'
                            }`} style={isSelected ? { color: '#2563eb' } : { color: '#111827' }}>
                              <span>{t('cockpit.jobInitiator')}:</span>{responsiblePerson}
                            </span>
                          </div>
                          {/* 整体进度 - 固定宽度和位置，右对齐 */}
                          <div className="flex-shrink-0" style={{ width: '128px', textAlign: 'right' }}>
                            <span className={`text-sm whitespace-nowrap ${
                              isSelected ? '' : 'text-gray-900'
                            }`} style={isSelected ? { color: '#2563eb' } : { color: '#111827' }}>
                              <span>{t('cockpit.overallProgress')}:</span>{calculateJobProgress(job)}%
                            </span>
                          </div>
                          {/* 右侧弹性空间 */}
                          <div className="flex-1"></div>
                          
                          {/* 自定义箭头 - 最右侧 */}
                          <div className="flex-shrink-0 ml-4" style={{ width: '24px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                            {isExpanded ? (
                              <ChevronUp className="w-5 h-5 text-gray-600" />
                            ) : (
                              <ChevronDown className="w-5 h-5 text-gray-600" />
                            )}
                          </div>
                        </div>
                      }
                      className="custom-panel"
                    >
                      <div className="px-3 pb-3 pt-3 bg-white">
                        <div className="overflow-x-auto">
                          {taskLoadingMap.get(job.id!) ? (
                            <div className="px-4 py-8 text-center text-sm text-gray-500">{t('cockpit.loading')}</div>
                          ) : (
                            <table className="w-full border-collapse">
                              <thead>
                                <tr className="bg-gray-50 border-b border-gray-200">
                                  <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.taskName')}</th>
                                  <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.taskOwner')}</th>
                                  <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.startTime')}</th>
                                  <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.status')}</th>
                                  <th className="px-4 py-3 text-center text-xs font-medium text-gray-700">{t('cockpit.action')}</th>
                                </tr>
                              </thead>
                              <tbody className="bg-white">
                                {(() => {
                                  const tasks = jobTaskMap.get(job.id!);
                                  console.log('Dashboard: 渲染任务列表', { jobId: job.id, tasks, tasksLength: tasks?.length });
                                  
                                  if (tasks && tasks.length > 0) {
                                    return tasks.map((task: MyTaskVO, taskIndex: number) => {
                                      const taskStatus = task.approvalStatus || task.taskStatus || task.status;
                                      const statusInfo = getTaskStatusInfo(taskStatus);
                                      const taskName = task.currentNodeName || task.currentNode || '-';
                                      const responsiblePerson = task.workerUserName || task.responsibleName || task.responsible || '-';
                                      const startTime = task.workTime || task.taskStartTime || task.initiationTime;
                                      
                                      return (
                                        <tr key={task.id || taskIndex} className="border-b border-gray-100 hover:bg-gray-50">
                                          <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">
                                            {taskName}
                                          </td>
                                          <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">
                                            {responsiblePerson}
                                          </td>
                                          <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">
                                            {startTime ? dateFormatter(startTime) : '-'}
                                          </td>
                                          <td className="px-4 py-3 whitespace-nowrap text-sm">
                                            <span className="inline-flex px-2 py-0.5 rounded text-xs font-medium" style={statusInfo.style}>
                                              {statusInfo.label}
                                            </span>
                                          </td>
                                        <td className="px-4 py-3 whitespace-nowrap text-sm text-center">
                                          {(() => {
                                            const statusText = getTaskStatusText(taskStatus);
                                            const statusTextLower = statusText.toLowerCase();
                                            const isInProgress = statusTextLower.includes('进行中') || statusTextLower.includes('待审核') || statusTextLower.includes('pending') || statusTextLower.includes('执行中');
                                            const isCompleted = statusTextLower.includes('已完成') || statusTextLower.includes('已通过') || statusTextLower.includes('approved') || statusTextLower.includes('完成') || statusTextLower.includes('执行完成');
                                            const buttonText = isInProgress ? t('form.handleNow') : (isCompleted ? t('form.viewDetail') : t('form.viewDetail'));
                                            return (
                                              <Space size="small">
                                                <Button
                                                  type="link"
                                                  size="small"
                                                  icon={<Eye className="w-4 h-4" style={{ color: '#000000' }} />}
                                                  onClick={(e) => {
                                                    e.stopPropagation();
                                                    e.preventDefault();
                                                    handleViewTaskDetail(task);
                                                  }}
                                                  style={{ color: '#000000' }}
                                                  className="transition-colors hover:text-[#1677ff] hover:underline"
                                                  onMouseEnter={(e) => {
                                                    e.currentTarget.style.color = '#1677ff';
                                                    e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #1677ff');
                                                  }}
                                                  onMouseLeave={(e) => {
                                                    e.currentTarget.style.color = '#000000';
                                                    e.currentTarget.querySelector('svg')?.setAttribute('style', 'color: #000000');
                                                  }}
                                                >
                                                  {buttonText}
                                                </Button>
                                              </Space>
                                            );
                                          })()}
                                        </td>
                                        </tr>
                                      );
                                    });
                                  } else {
                                    return (
                                      <tr>
                                        <td colSpan={5} className="px-4 py-8 text-center text-sm text-gray-500">
                                          暂无任务明细
                                        </td>
                                      </tr>
                                    );
                                  }
                                })()}
                              </tbody>
                            </table>
                          )}
                        </div>
                      </div>
                    </Panel>
                  );
                })}
              </Collapse>
            ) : (
              <div className="p-8 text-center text-gray-500">{t('cockpit.noJobData')}</div>
            )}
          </div>
        </Card>
      </div>

      {/* 全系统作业完成趋势图表 */}
      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <h3 className="text-lg font-semibold text-gray-900 mb-6">
          {t('cockpit.systemJobCompleteTrend')}
        </h3>
        <div className="h-80">
          <ResponsiveContainer width="100%" height="100%">
            <AreaChart
              data={managerDayWorkCount.length > 0 
                ? managerDayWorkCount.map(item => ({ 
                    date: item.day || item.date || '', 
                    completedCount: item.completedCount || item.count || 0 
                  }))
                : (statistics.jobTrendData || [])
              }
              margin={{ top: 10, right: 30, left: 20, bottom: 20 }}
            >
              <defs>
                <linearGradient id="colorCompleted" x1="0" y1="0" x2="0" y2="1">
                  <stop offset="5%" stopColor="#3b82f6" stopOpacity={0.8}/>
                  <stop offset="95%" stopColor="#3b82f6" stopOpacity={0.1}/>
                </linearGradient>
              </defs>
              <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" />
              <XAxis 
                dataKey="date" 
                stroke="#6b7280"
                tick={{ fontSize: 12, fill: '#6b7280' }}
                axisLine={{ stroke: '#e5e7eb' }}
                tickFormatter={(value) => {
                  // 格式化日期显示，只显示月-日
                  if (!value) return '';
                  const date = new Date(value);
                  if (isNaN(date.getTime())) return value;
                  const month = String(date.getMonth() + 1).padStart(2, '0');
                  const day = String(date.getDate()).padStart(2, '0');
                  return `${month}-${day}`;
                }}
              />
              <YAxis 
                stroke="#6b7280"
                tick={{ fontSize: 12, fill: '#6b7280' }}
                axisLine={{ stroke: '#e5e7eb' }}
                domain={[0, 5]}
                ticks={[0, 1, 2, 3, 4, 5]}
              />
              <Tooltip 
                contentStyle={{ 
                  backgroundColor: '#fff', 
                  border: '1px solid #e5e7eb',
                  borderRadius: '6px',
                  fontSize: '12px',
                  boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
                }}
              />
              <Legend 
                wrapperStyle={{ paddingTop: '20px' }}
                iconType="square"
                align="right"
                verticalAlign="top"
                formatter={(value) => <span style={{ fontSize: '12px', color: '#6b7280' }}>□ {value}</span>}
              />
              <Area 
                type="monotone" 
                dataKey="completedCount" 
                stroke="#3b82f6" 
                strokeWidth={2}
                fill="url(#colorCompleted)"
                dot={{ fill: '#3b82f6', r: 4, strokeWidth: 2, stroke: '#fff' }}
                name={t('cockpit.dailyCompletedCount')}
              />
            </AreaChart>
          </ResponsiveContainer>
        </div>
      </div>

      {/* 物料管理部分 */}
      <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
        <h3 className="text-lg font-semibold text-gray-900 mb-4">{t('cockpit.materialManagement')}</h3>
        <div className="flex gap-4">
          {/* 可用物料 - 绿色 */}
          <div className="flex-1 bg-green-50 rounded-lg border border-green-200 p-5 text-center">
            <div className="text-3xl font-bold text-green-900 mb-2">
              {statistics.availableMaterialsCount || 0}
            </div>
            <div className="text-sm text-green-700">{t('cockpit.availableMaterials')}</div>
          </div>
          
          {/* 借用中物料 - 橙色 */}
          <div className="flex-1 bg-orange-50 rounded-lg border border-orange-200 p-5 text-center">
            <div className="text-3xl font-bold text-orange-900 mb-2">
              {statistics.loanMaterialsCount || 0}
            </div>
            <div className="text-sm text-orange-700">{t('cockpit.borrowedMaterials')}</div>
          </div>
          
          {/* 异常物料 - 红色 */}
          <div className="flex-1 bg-red-50 rounded-lg border border-red-200 p-5 text-center">
            <div className="text-3xl font-bold text-red-900 mb-2">
              {statistics.exceptionMaterialsCount || 0}
            </div>
            <div className="text-sm text-red-700">{t('cockpit.exceptionMaterials')}</div>
          </div>
          
          {/* 待归还物料 - 灰色 */}
          <div className="flex-1 bg-gray-50 rounded-lg border border-gray-200 p-5 text-center">
            <div className="text-3xl font-bold text-gray-900 mb-2">
              {statistics.returnMaterialsCount || 0}
            </div>
            <div className="text-sm text-gray-600">{t('cockpit.returnPendingMaterials')}</div>
          </div>
        </div>
      </div>

      {/* 物料状态列表 */}
      <Card
        title={
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2">
              <List className="w-5 h-5 text-gray-600" />
              <span>{t('cockpit.materialStatusList')}</span>
            </div>
            <button
              className="text-sm font-medium border-0 bg-transparent p-0 cursor-pointer"
              style={{ color: '#2563eb' }}
              onMouseEnter={(e) => e.currentTarget.style.color = '#1d4ed8'}
              onMouseLeave={(e) => e.currentTarget.style.color = '#2563eb'}
            >
              {t('cockpit.viewAllMaterials')}
            </button>
          </div>
        }
      >
        <div className="overflow-x-auto">
          <table className="w-full border-collapse">
            <thead>
              <tr className="bg-gray-50 border-b border-gray-200">
                <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.materialCode')}</th>
                <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.materialName')}</th>
                <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.materialType')}</th>
                <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.status')}</th>
                <th className="px-4 py-3 text-left text-xs font-medium text-gray-700">{t('cockpit.borrower')}</th>
                <th className="px-4 py-3 text-center text-xs font-medium text-gray-700">{t('cockpit.action')}</th>
              </tr>
            </thead>
            <tbody className="bg-white">
              {/* 示例数据 - 实际应该从API获取 */}
              <tr className="border-b border-gray-100 hover:bg-gray-50">
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">LOCK-001</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">隔离锁具 (通用型)</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">锁具</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm">
                  <span className="px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-gray-900">{t('cockpit.borrowed')}</span>
                </td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">张三</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-center">
                  <div className="flex items-center justify-center gap-2">
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#1677ff', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#0958d9'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#1677ff'}
                    >
                      {t('cockpit.view')}
                    </button>
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#fa8c16', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#d46b08'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#fa8c16'}
                    >
                      {t('cockpit.urgeReturn')}
                    </button>
                  </div>
                </td>
              </tr>
              <tr className="border-b border-gray-100 hover:bg-gray-50">
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">TAG-002</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">警示标签 (大号)</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">标签</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm">
                  <span className="px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-700">{t('cockpit.exception')}</span>
                </td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">-</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-center">
                  <div className="flex items-center justify-center gap-2">
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#1677ff', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#0958d9'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#1677ff'}
                    >
                      {t('cockpit.view')}
                    </button>
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#ff4d4f', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#cf1322'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#ff4d4f'}
                    >
                      {t('cockpit.handleException')}
                    </button>
                  </div>
                </td>
              </tr>
              <tr className="border-b border-gray-100 hover:bg-gray-50">
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">DEV-003</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">断电测试仪</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">仪器</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm">
                  <span className="px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-gray-900">{t('cockpit.available')}</span>
                </td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">-</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-center">
                  <div className="flex items-center justify-center gap-2">
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#1677ff', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#0958d9'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#1677ff'}
                    >
                      {t('cockpit.view')}
                    </button>
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#52c41a', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#389e0d'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#52c41a'}
                    >
                      {t('cockpit.claim')}
                    </button>
                  </div>
                </td>
              </tr>
              <tr className="border-b border-gray-100 hover:bg-gray-50">
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">LOCK-004</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-900">隔离锁具 (防爆型)</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">锁具</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm">
                  <span className="px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-700">{t('cockpit.returnPending')}</span>
                </td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600">李四</td>
                <td className="px-4 py-3 whitespace-nowrap text-sm text-center">
                  <div className="flex items-center justify-center gap-2">
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#1677ff', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#0958d9'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#1677ff'}
                    >
                      {t('cockpit.view')}
                    </button>
                    <button 
                      className="px-3 py-1.5 text-xs font-medium rounded transition-colors"
                      style={{ backgroundColor: '#fa8c16', color: '#ffffff' }}
                      onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#d46b08'}
                      onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#fa8c16'}
                    >
                      {t('cockpit.urgeReturn')}
                    </button>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </Card>

      {/* 任务详情弹框 */}
      <Modal
        title={null}
        open={taskDetailVisible}
        onCancel={() => {
          setTaskDetailVisible(false);
          setTaskDetailData(null);
          setFormData({ rule: [], option: {} });
          setFormLoading(false);
          setOriginalFields([]);
          setOriginalConf('');
          taskDetailForm.resetFields();
          setApprovalComment('');
          setIsolationDeviceNumber('');
          setIsolationFileList([]);
        }}
        footer={null}
        width={1000}
        destroyOnClose
        maskClosable={false}
        styles={{
          body: {
            minHeight: '600px',
            maxHeight: '700px',
            height: '700px',
            padding: 0,
            display: 'flex',
            flexDirection: 'column',
            overflow: 'hidden'
          }
        }}
      >
        {taskDetailLoading ? (
          <div className="py-8 text-center text-gray-500">加载中...</div>
        ) : taskDetailData ? (
          <div style={{ 
            display: 'flex',
            flexDirection: 'column',
            height: '100%',
            overflow: 'hidden'
          }}>
            {/* 标题区域 */}
            <div className="mb-4" style={{ padding: '20px 24px 0' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
                <div style={{ 
                  width: '3px', 
                  height: '24px', 
                  backgroundColor: '#025fff',
                  borderRadius: '2px',
                  flexShrink: 0
                }}></div>
                <h2 className="text-xl font-semibold mb-2" style={{ color: '#025fff', marginBottom: 0 }}>
                  {taskDetailData.workName || taskDetailData.name || t('cockpit.taskDetail')}
                </h2>
                <span 
                  className="inline-flex px-3 py-1 rounded-full text-xs font-medium"
                  style={getTaskStatusStyle(taskDetailData.approvalStatus || taskDetailData.taskStatus || taskDetailData.status)}
                >
                  {getTaskStatusText(taskDetailData.approvalStatus || taskDetailData.taskStatus || taskDetailData.status)}
                </span>
              </div>
              <div className="text-sm flex gap-4" style={{ color: '#898f9a', marginTop: '12px' }}>
                <span>{t('cockpit.orderNo')}：{taskDetailData.orderNo || '-'}</span>
                <span>{t('cockpit.jobInitiatorLabel')}：{taskDetailData.initiatorName || '-'}</span>
                <span>{t('cockpit.taskOwnerLabel')}：{taskDetailData.workerUserName || '-'}</span>
                <span>{t('cockpit.startTime')}：{taskDetailData.workTime ? dateFormatter(taskDetailData.workTime) : '-'}</span>
              </div>
            </div>

            {/* 内容区域 - 可滚动 */}
            <div className="mt-6" style={{ 
              padding: '0 24px',
              flex: 1,
              overflowY: 'auto',
              minHeight: 0
            }}>
              {(() => {
                const isApproved = taskDetailData?.approvalStatus === 'approved';
                const nodeType = String(taskDetailData?.type || taskDetailData?.nodeType || '').trim();
                const isReview = nodeType === 'review';
                const isIsolation =
                  isWorkflowLockSchemeType(nodeType) || isWorkflowCoLockType(nodeType);
                const isReleaseIsolation =
                  isWorkflowUnlockSchemeType(nodeType) || isWorkflowUnlockCoLockType(nodeType);
                const isReturnLock = nodeType === 'returnLock';
                const hasFormIdForCurrentNode = taskDetailData?.formId !== undefined && taskDetailData?.formId !== null && (
                  typeof taskDetailData.formId === 'number' || (typeof taskDetailData.formId === 'string' && String(taskDetailData.formId).trim() !== '')
                );

                // 隔离/方案节点、解除隔离节点和还锁节点
                if (isIsolation || isReleaseIsolation || isReturnLock) {
                  const isolationType = String(taskDetailData?.isolationType ?? '').trim();
                  const isLockoutTagout = isolationType === '1';
                  const isBlindPlate = isolationType === '0';
                  const isDismantle = isolationType === '2';
                  const showLockCabinet = isReturnLock || (isLockoutTagout && (isIsolation || isReleaseIsolation));
                  const showDeviceForm = (isIsolation || isReleaseIsolation) && (isBlindPlate || isDismantle);

                  if (showDeviceForm) {
                    const deviceLabel = isReleaseIsolation
                      ? (isBlindPlate ? t('form.releaseBlindPlateDeviceNo') : t('form.restoreDeviceNo'))
                      : (isBlindPlate ? t('form.blindPlateDeviceNo') : t('form.dismantleDeviceNo'));
                    const formIdVal = taskDetailData?.formId;
                    const hasFormIdForBlindDismantle = formIdVal !== undefined && formIdVal !== null && (
                      typeof formIdVal === 'number' || (typeof formIdVal === 'string' && String(formIdVal).trim() !== '')
                    );
                    return (
                      <div key="isolation-device-form" style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
                        <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: '24px', background: 'linear-gradient(165deg, #f0f7ff 0%, #fafbff 45%, #fff 100%)' }}>
                          <div style={{ width: '100%' }}>
                              <div style={{ marginBottom: 26 }}>
                                <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14, fontWeight: 600, color: '#1f2937', marginBottom: 12 }}>
                                  <span style={{ width: 28, height: 28, borderRadius: 8, background: '#e6f4ff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
                                    <BarcodeOutlined style={{ fontSize: 14, color: '#1677ff' }} />
                                  </span>
                                  {deviceLabel}
                                </label>
                                <Input
                                  value={isolationDeviceNumber}
                                  onChange={(e) => !isApproved && setIsolationDeviceNumber(e.target.value)}
                                  placeholder={`请输入${deviceLabel}`}
                                  maxLength={100}
                                  size="large"
                                  disabled={isApproved}
                                  prefix={<BarcodeOutlined style={{ color: '#91caff', marginRight: 8 }} />}
                                  style={{ borderRadius: 10, borderColor: '#d9e8ff', fontSize: 15 }}
                                />
                              </div>
                              <div>
                                <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14, fontWeight: 600, color: '#1f2937', marginBottom: 12 }}>
                                  <span style={{ width: 28, height: 28, borderRadius: 8, background: '#e6f4ff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
                                    <UploadOutlined style={{ fontSize: 14, color: '#1677ff' }} />
                                  </span>
                                  附件上传
                                  {!isApproved && <span style={{ marginLeft: 8, fontSize: 12, fontWeight: 400, color: '#69b1ff', background: '#e6f4ff', padding: '2px 8px', borderRadius: 6 }}>支持拖拽</span>}
                                </label>
                                {isApproved && isolationFileList.length > 0 ? (
                                  <div style={{ borderRadius: 12, padding: '32px 20px', background: 'linear-gradient(180deg, #f5faff 0%, #e8f4ff 50%, #e0efff 100%)', border: '2px solid #91caff', minHeight: 180, display: 'flex', flexWrap: 'wrap', gap: 16, alignItems: 'center', justifyContent: 'center', alignContent: 'center' }}>
                                    <Image.PreviewGroup>
                                      {isolationFileList.filter((f: any) => /\.(jpg|jpeg|png|gif|webp|bmp)(\?|$)/i.test(String((f.url || f.response) || '')) || /\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(String(f.name || ''))).map((file: any) => (
                                        <Image key={file.uid} width={160} height={160} src={file.url || file.response} style={{ objectFit: 'cover', borderRadius: 10, cursor: 'pointer', flexShrink: 0 }} alt={file.name} />
                                      ))}
                                    </Image.PreviewGroup>
                                    {isolationFileList.filter((f: any) => !/\.(jpg|jpeg|png|gif|webp|bmp)(\?|$)/i.test(String((f.url || f.response) || '')) && !/\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(String(f.name || ''))).map((file: any) => (
                                      <a key={file.uid} href={file.url || file.response} target="_blank" rel="noopener noreferrer" style={{ display: 'block', padding: '12px 16px', background: '#fff', borderRadius: 10, color: '#1677ff', border: '1px solid #91caff', maxWidth: 240, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{file.name}</a>
                                    ))}
                                  </div>
                                ) : isApproved ? (
                                  <div style={{ padding: 24, textAlign: 'center', color: '#8c8c8c', background: '#fafafa', borderRadius: 12 }}>暂无附件</div>
                                ) : (
                                  <Upload.Dragger
                                    fileList={isolationFileList}
                                    onChange={({ fileList }) => setIsolationFileList(fileList.slice(-5))}
                                    multiple
                                    showUploadList={{ showRemoveIcon: true }}
                                    customRequest={async ({ file, onSuccess, onError }) => {
                                      try {
                                        const url = await fileApi.upload(file as File);
                                        onSuccess?.(url);
                                      } catch (e: any) {
                                        onError?.(e);
                                        message.error(e?.message || '文件上传失败');
                                      }
                                    }}
                                    style={{ borderRadius: 12, padding: '32px 20px', background: 'linear-gradient(180deg, #f5faff 0%, #e8f4ff 50%, #e0efff 100%)', border: '2px dashed #91caff' }}
                                  >
                                    <p className="ant-upload-drag-icon" style={{ marginBottom: 12 }}>
                                      <span style={{ width: 64, height: 64, borderRadius: 16, background: 'linear-gradient(135deg, rgba(22,119,255,0.15) 0%, rgba(64,150,255,0.1) 100%)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
                                        <UploadOutlined style={{ fontSize: 32, color: '#1677ff' }} />
                                      </span>
                                    </p>
                                    <p className="ant-upload-text" style={{ margin: 0, color: '#0958d9', fontSize: 15, fontWeight: 500 }}>点击或拖拽文件到此区域上传</p>
                                    <p className="ant-upload-hint" style={{ margin: '8px 0 0', color: '#69b1ff', fontSize: 13 }}>最多 5 个文件，支持多选</p>
                                  </Upload.Dragger>
                                )}
                              </div>
                              {hasFormIdForBlindDismantle && (
                                <div style={{ marginTop: 24, paddingTop: 24, borderTop: '1px solid rgba(22, 119, 255, 0.12)' }}>
                                  {formLoading ? (
                                    <div className="py-6 text-center text-gray-500">表单加载中...</div>
                                  ) : formData.rule && formData.rule.length > 0 ? (
                                    (() => {
                                      const formConfig = formData.option?.formConfig || defaultFormConfig;
                                      const layoutColumns = formConfig.layoutColumns || 1;
                                      const gridStyle = layoutColumns > 1 ? {
                                        display: 'grid',
                                        gridTemplateColumns: `repeat(${layoutColumns}, minmax(0, 1fr))`,
                                        gap: '12px',
                                        rowGap: '16px',
                                      } : undefined;
                                      return (
                                        <AntdForm
                                          form={taskDetailForm}
                                          layout={formConfig.labelPosition === 'top' ? 'vertical' : formConfig.labelPosition === 'left' ? 'horizontal' : 'horizontal'}
                                          size={formConfig.formSize === 'default' ? 'middle' : formConfig.formSize}
                                          requiredMark={formConfig.hideRequiredMark ? false : undefined}
                                          labelCol={
                                            formConfig.labelPosition === 'top' || !formConfig.labelWidth
                                              ? undefined
                                              : {
                                                  flex: `${formConfig.labelWidth}px`,
                                                  style: {
                                                    minWidth: `${formConfig.labelWidth}px`,
                                                    textAlign: formConfig.labelPosition === 'right' ? 'right' : 'left',
                                                  },
                                                }
                                          }
                                          wrapperCol={formConfig.labelPosition === 'top' ? undefined : { flex: 'auto', style: { minWidth: 0 } }}
                                        >
                                          <div style={gridStyle} className={layoutColumns === 1 ? 'space-y-4' : 'form-detail-grid'}>
                                            <style>{`.form-detail-grid .ant-form-item { margin-bottom: 12px; } .form-detail-grid .ant-form-item-control { min-width: 0; }`}</style>
                                            {(formData.rule || []).map((field: any) => {
                                              const fieldWithDisabled = isApproved ? { ...field, disabled: true, readOnly: true } : field;
                                              return renderFieldPreview(fieldWithDisabled);
                                            })}
                                          </div>
                                        </AntdForm>
                                      );
                                    })()
                                  ) : null}
                                </div>
                              )}
                          </div>
                        </div>
                        <div className="flex justify-end gap-3" style={{ padding: '20px 24px', borderTop: '1px solid rgba(22, 119, 255, 0.1)', flexShrink: 0, background: 'linear-gradient(0deg, #f0f7ff 0%, #fafcff 60%, #fff 100%)' }}>
                          {!isApproved ? (
                            <Button
                              type="primary"
                              loading={isolationSubmitLoading}
                              onClick={async () => {
                                const nodeId = taskDetailData.nodeId ?? taskDetailData.id;
                                if (nodeId == null) {
                                  message.error(t('cockpit.nodeIdNotExist'));
                                  return;
                                }
                                const uploadedFiles = isolationFileList.filter((f: any) => f.status === 'done' && (f.response != null));
                                const uploadingCount = isolationFileList.filter((f: any) => f.status === 'uploading').length;
                                if (uploadingCount > 0) {
                                  message.warning('请等待文件上传完成');
                                  return;
                                }
                                if (isolationFileList.length > 0 && uploadedFiles.length === 0) {
                                  message.warning('请等待文件上传完成或移除未上传成功的文件');
                                  return;
                                }
                                if (hasFormIdForBlindDismantle && formData.rule && formData.rule.length > 0) {
                                  try {
                                    await taskDetailForm.validateFields();
                                  } catch (err: any) {
                                    if (err?.errorFields?.[0]?.errors?.[0]) {
                                      message.error(err.errorFields[0].errors[0]);
                                    } else {
                                      message.error('请完善表单内容');
                                    }
                                    return;
                                  }
                                }
                                setIsolationSubmitLoading(true);
                                try {
                                  const attachmentUrls = uploadedFiles.map((f: any) => {
                                    const url = typeof f.response === 'string' ? f.response : (f.response?.url ?? '');
                                    return { name: f.name, url };
                                  });
                                  let formDataString: string | undefined = undefined;
                                  if (hasFormIdForBlindDismantle && formData.rule && formData.rule.length > 0 && originalFields.length > 0) {
                                    try {
                                      const values = taskDetailForm.getFieldsValue();
                                      const fieldsWithValues = originalFields.map((fieldString: string) => {
                                        try {
                                          const fieldObj = JSON.parse(fieldString);
                                          const fieldName = fieldObj.name || fieldObj.field;
                                          const fieldValue = values[fieldName];
                                          fieldObj.value = fieldValue !== undefined && fieldValue !== null ? fieldValue : '';
                                          return JSON.stringify(fieldObj);
                                        } catch {
                                          return fieldString;
                                        }
                                      });
                                      const submitData = { conf: formData.option, fields: fieldsWithValues };
                                      formDataString = JSON.stringify(submitData);
                                    } catch (e) {
                                      console.error('Dashboard: 盲板/拆除 表单数据序列化失败', e);
                                    }
                                  }
                                  await taskManagementApi.updateNodeApproval({
                                    nodeId: typeof nodeId === 'number' ? nodeId : Number(nodeId),
                                    approvalStatus: 'approved',
                                    deviceNumber: isolationDeviceNumber,
                                    attachments: JSON.stringify(attachmentUrls),
                                    ...(formDataString != null ? { formData: formDataString } : {}),
                                  });
                                  message.success(t('common.submit') + t('common.success'));
                                  setTaskDetailVisible(false);
                                  setTaskDetailData(null);
                                  setIsolationDeviceNumber('');
                                  setIsolationFileList([]);
                                  fetchStatistics();
                                } catch (error: any) {
                                  message.error(error?.message || '提交失败');
                                } finally {
                                  setIsolationSubmitLoading(false);
                                }
                              }}
                              icon={<SendOutlined />}
                              style={{ minWidth: 120, height: 44, borderRadius: 10, fontSize: 15, fontWeight: 500, boxShadow: '0 4px 14px rgba(22, 119, 255, 0.35)' }}
                            >
                              {t('common.submit')}
                            </Button>
                          ) : (
                            <Button onClick={() => { setTaskDetailVisible(false); setTaskDetailData(null); setIsolationDeviceNumber(''); setIsolationFileList([]); }} style={{ minWidth: 120, height: 44, borderRadius: 10, fontSize: 15, fontWeight: 500 }}>
                              {t('common.cancel')}
                            </Button>
                          )}
                        </div>
                      </div>
                    );
                  }

                  return (
                    <div style={{ flex: 1, minHeight: 0, overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '24px', background: 'linear-gradient(165deg, #f0f7ff 0%, #fafbff 45%, #fff 100%)' }}>
                      <div style={{ width: '100%', textAlign: 'center', padding: '24px 0' }}>
                        <div style={{ marginBottom: 28 }}>
                          <span style={{ width: 88, height: 88, borderRadius: 20, background: 'linear-gradient(135deg, #1677ff 0%, #4096ff 50%, #69b1ff 100%)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 8px 24px rgba(22, 119, 255, 0.35)' }}>
                            <LockOutlined style={{ fontSize: 42, color: '#fff' }} />
                          </span>
                        </div>
                        <div style={{ fontSize: 18, fontWeight: 600, color: '#1f2937', lineHeight: 1.6, marginBottom: 8 }}>{t('form.lockCabinetTip')}</div>
                        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13, color: '#69b1ff' }}>
                          <KeyOutlined />
                          <span>完成取锁、取钥匙后，任务将自动推进</span>
                        </div>
                      </div>
                    </div>
                  );
                }

                // 审核类型节点 (review) - 表单直接放在外层，取消内置白框
                if (isReview) {
                  return (
                    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
                      <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: '24px', background: 'linear-gradient(165deg, #f0f7ff 0%, #fafbff 45%, #fff 100%)' }}>
                        <div style={{ width: '100%' }}>
                            {formLoading ? (
                              <div className="py-8 text-center text-gray-500">表单加载中...</div>
                            ) : hasFormIdForCurrentNode && formData.rule && formData.rule.length > 0 ? (
                              <div className="space-y-4">
                                {(() => {
                                  const formConfig = formData.option?.formConfig || defaultFormConfig;
                                  const layoutColumns = formConfig.layoutColumns || 1;
                                  const gridStyle = layoutColumns > 1 ? { display: 'grid', gridTemplateColumns: `repeat(${layoutColumns}, minmax(0, 1fr))`, gap: '12px', rowGap: '16px' } : undefined;
                                  return (
                                    <AntdForm form={taskDetailForm} layout={formConfig.labelPosition === 'top' ? 'vertical' : formConfig.labelPosition === 'left' ? 'horizontal' : 'horizontal'} size={formConfig.formSize === 'default' ? 'middle' : formConfig.formSize} requiredMark={formConfig.hideRequiredMark ? false : undefined} labelCol={formConfig.labelPosition === 'top' || !formConfig.labelWidth ? undefined : { flex: `${formConfig.labelWidth}px`, style: { minWidth: `${formConfig.labelWidth}px`, textAlign: formConfig.labelPosition === 'right' ? 'right' : 'left' } }} wrapperCol={formConfig.labelPosition === 'top' ? undefined : { flex: 'auto', style: { minWidth: 0 } }}>
                                      <div style={gridStyle} className={layoutColumns === 1 ? 'space-y-4' : 'form-detail-grid'}>
                                        <style>{`.form-detail-grid .ant-form-item { margin-bottom: 12px; } .form-detail-grid .ant-form-item-control { min-width: 0; }`}</style>
                                        {(formData.rule || []).map((field: any) => {
                                          const fieldWithDisabled = isApproved ? { ...field, disabled: true, readOnly: true } : field;
                                          return renderFieldPreview(fieldWithDisabled);
                                        })}
                                      </div>
                                    </AntdForm>
                                  );
                                })()}
                              </div>
                            ) : (
                              <div style={{ textAlign: 'center', padding: '32px 24px' }}>
                                <span style={{ width: 72, height: 72, borderRadius: 18, background: 'linear-gradient(135deg, #1677ff 0%, #4096ff 50%, #69b1ff 100%)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 8px 24px rgba(22, 119, 255, 0.35)', marginBottom: 20 }}>
                                  <CheckCircleOutlined style={{ fontSize: 36, color: '#fff' }} />
                                </span>
                                <div style={{ fontSize: 18, fontWeight: 600, color: '#1f2937', lineHeight: 1.6 }}>无需填写表单，直接点击底部按钮提交即可</div>
                              </div>
                            )}
                            <div className="flex items-start" style={{ gap: 16, marginTop: 24, paddingTop: 24, borderTop: '1px solid rgba(22, 119, 255, 0.12)' }}>
                              <label className="text-sm font-medium text-gray-700 whitespace-nowrap pt-2" style={{ width: defaultFormConfig.labelWidth ? `${defaultFormConfig.labelWidth - 20}px` : '80px', textAlign: defaultFormConfig.labelPosition === 'left' ? 'left' : defaultFormConfig.labelPosition === 'right' ? 'right' : 'left', flexShrink: 0 }}>{t('form.reviewComment')}</label>
                              <div className="flex-1">
                                <Input.TextArea rows={4} value={approvalComment} onChange={(e) => setApprovalComment(e.target.value)} placeholder={t('form.reviewCommentPlaceholder')} maxLength={500} showCount disabled={isApproved} readOnly={isApproved} style={{ borderRadius: 10, borderColor: '#d9e8ff' }} />
                              </div>
                            </div>
                        </div>
                      </div>
                      <div className="flex justify-end gap-3" style={{ padding: '20px 24px', borderTop: '1px solid rgba(22, 119, 255, 0.1)', flexShrink: 0, background: 'linear-gradient(0deg, #f0f7ff 0%, #fafcff 60%, #fff 100%)' }}>
                        <Button
                          danger
                          loading={approvalLoading}
                          disabled={isApproved}
                          onClick={async () => {
                            const nodeId = taskDetailData.nodeId ?? taskDetailData.id;
                            if (nodeId == null) {
                              message.error(t('cockpit.nodeIdNotExist'));
                              return;
                            }
                            const numNodeId = typeof nodeId === 'number' ? nodeId : Number(nodeId);
                            if (formData.rule && formData.rule.length > 0) {
                              try {
                                await taskDetailForm.validateFields();
                              } catch (err: any) {
                                if (err?.errorFields?.length) {
                                  message.error(err.errorFields[0]?.errors?.[0] || '请完善表单内容');
                                } else {
                                  message.error('请完善表单内容');
                                }
                                return;
                              }
                            }
                            setApprovalLoading(true);
                            try {
                              let formDataString: string | undefined;
                              if (formData.rule?.length && originalFields.length > 0) {
                                const values = taskDetailForm.getFieldsValue();
                                const fieldsWithValues = originalFields.map((fieldString: string) => {
                                  try {
                                    const fieldObj = JSON.parse(fieldString);
                                    const fieldName = fieldObj.name || fieldObj.field;
                                    const fieldValue = values[fieldName];
                                    fieldObj.value = fieldValue !== undefined && fieldValue !== null ? fieldValue : '';
                                    return JSON.stringify(fieldObj);
                                  } catch (e) {
                                    return fieldString;
                                  }
                                });
                                formDataString = JSON.stringify({
                                  id: taskDetailData.formId ?? taskDetailData.id,
                                  name: taskDetailData.nodeName || taskDetailData.workName || '未知',
                                  conf: originalConf,
                                  fields: fieldsWithValues
                                });
                              }
                              const params: UpdateNodeApprovalParam = {
                                nodeId: numNodeId,
                                approvalStatus: 'rejected',
                                approvalOpinion: approvalComment || undefined,
                                formData: formDataString,
                              };
                              await taskManagementApi.updateNodeApproval(params);
                              message.success(t('form.reviewRejectSuccess'));
                              setTaskDetailVisible(false);
                              setTaskDetailData(null);
                              setFormData({ rule: [], option: {} });
                              setFormLoading(false);
                              setOriginalFields([]);
                              setOriginalConf('');
                              taskDetailForm.resetFields();
                              setApprovalComment('');
                              fetchStatistics();
                            } catch (error: any) {
                              message.error(error?.message || t('form.reviewRejectFailed'));
                            } finally {
                              setApprovalLoading(false);
                            }
                          }}
                        >
                          {t('form.reviewReject')}
                        </Button>
                        <Button
                          type="primary"
                          loading={approvalLoading}
                          disabled={isApproved}
                          onClick={async () => {
                            const nodeId = taskDetailData.nodeId ?? taskDetailData.id;
                            if (nodeId == null) {
                              message.error(t('cockpit.nodeIdNotExist'));
                              return;
                            }
                            const numNodeId = typeof nodeId === 'number' ? nodeId : Number(nodeId);
                            if (formData.rule && formData.rule.length > 0) {
                              try {
                                await taskDetailForm.validateFields();
                              } catch (err: any) {
                                if (err?.errorFields?.length) {
                                  message.error(err.errorFields[0]?.errors?.[0] || '请完善表单内容');
                                } else {
                                  message.error('请完善表单内容');
                                }
                                return;
                              }
                            }
                            setApprovalLoading(true);
                            try {
                              let formDataString: string | undefined;
                              if (formData.rule?.length && originalFields.length > 0) {
                                const values = taskDetailForm.getFieldsValue();
                                const fieldsWithValues = originalFields.map((fieldString: string) => {
                                  try {
                                    const fieldObj = JSON.parse(fieldString);
                                    const fieldName = fieldObj.name || fieldObj.field;
                                    const fieldValue = values[fieldName];
                                    fieldObj.value = fieldValue !== undefined && fieldValue !== null ? fieldValue : '';
                                    return JSON.stringify(fieldObj);
                                  } catch (e) {
                                    return fieldString;
                                  }
                                });
                                formDataString = JSON.stringify({
                                  id: taskDetailData.formId ?? taskDetailData.id,
                                  name: taskDetailData.nodeName || taskDetailData.workName || '未知',
                                  conf: originalConf,
                                  fields: fieldsWithValues
                                });
                              }
                              const params: UpdateNodeApprovalParam = {
                                nodeId: numNodeId,
                                approvalStatus: 'approved',
                                approvalOpinion: approvalComment || undefined,
                                formData: formDataString,
                              };
                              await taskManagementApi.updateNodeApproval(params);
                              message.success(t('form.reviewApproveSuccess'));
                              setTaskDetailVisible(false);
                              setTaskDetailData(null);
                              setFormData({ rule: [], option: {} });
                              setFormLoading(false);
                              setOriginalFields([]);
                              setOriginalConf('');
                              taskDetailForm.resetFields();
                              setApprovalComment('');
                              fetchStatistics();
                            } catch (error: any) {
                              message.error(error?.message || t('form.reviewApproveFailed'));
                            } finally {
                              setApprovalLoading(false);
                            }
                          }}
                        >
                          {t('form.reviewApprove')}
                        </Button>
                      </div>
                    </div>
                  );
                }

                // 其他节点类型（录入信息等）- 与审核节点统一样式：渐变背景、无内置白框
                return (
                  <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
                    <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: '24px', background: 'linear-gradient(165deg, #f0f7ff 0%, #fafbff 45%, #fff 100%)' }}>
                      <div style={{ width: '100%' }}>
                      {/* 自定义表单：仅当前节点有 formId 时渲染 */}
                      {formLoading ? (
                        <div className="py-8 text-center text-gray-500">表单加载中...</div>
                      ) : hasFormIdForCurrentNode && formData.rule && formData.rule.length > 0 ? (
                        <div className="space-y-4">
                          {(() => {
                            const formConfig = formData.option?.formConfig || defaultFormConfig;
                            const layoutColumns = formConfig.layoutColumns || 1;
                            const gridStyle = layoutColumns > 1 ? {
                              display: 'grid',
                              gridTemplateColumns: `repeat(${layoutColumns}, minmax(0, 1fr))`,
                              gap: '12px',
                              rowGap: '16px',
                            } : undefined;
                            
                            return (
                              <AntdForm
                                form={taskDetailForm}
                                layout={formConfig.labelPosition === 'top' ? 'vertical' : formConfig.labelPosition === 'left' ? 'horizontal' : 'horizontal'}
                                size={formConfig.formSize === 'default' ? 'middle' : formConfig.formSize}
                                requiredMark={formConfig.hideRequiredMark ? false : undefined}
                                labelCol={
                                  formConfig.labelPosition === 'top' || !formConfig.labelWidth
                                    ? undefined
                                    : {
                                        flex: `${formConfig.labelWidth}px`,
                                        style: {
                                          minWidth: `${formConfig.labelWidth}px`,
                                          textAlign: formConfig.labelPosition === 'right' ? 'right' : 'left',
                                        },
                                      }
                                }
                                wrapperCol={formConfig.labelPosition === 'top' ? undefined : { flex: 'auto', style: { minWidth: 0 } }}
                              >
                                <div 
                                  style={gridStyle} 
                                  className={layoutColumns === 1 ? 'space-y-4' : 'form-detail-grid'}
                                >
                                  <style>{`
                                    .form-detail-grid .ant-form-item { margin-bottom: 12px; }
                                    .form-detail-grid .ant-form-item-control { min-width: 0; }
                                  `}</style>
                                  {(formData.rule || []).map((field: any) => {
                                    const fieldWithDisabled = isApproved ? { ...field, disabled: true, readOnly: true } : field;
                                    return renderFieldPreview(fieldWithDisabled);
                                  })}
                                </div>
                              </AntdForm>
                            );
                          })()}
                        </div>
                      ) : (
                        <div
                          style={{
                            flex: 1,
                            minHeight: 0,
                            overflow: 'hidden',
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: 'center',
                            padding: '24px',
                            background: 'linear-gradient(165deg, #f0f7ff 0%, #fafbff 45%, #fff 100%)',
                          }}
                        >
                          <div style={{ width: '100%', textAlign: 'center', padding: '24px 0' }}>
                            <div style={{ marginBottom: 24 }}>
                              <span
                                style={{
                                  width: 88,
                                  height: 88,
                                  borderRadius: 20,
                                  background: 'linear-gradient(135deg, #52c41a 0%, #73d13d 50%, #95de64 100%)',
                                  display: 'inline-flex',
                                  alignItems: 'center',
                                  justifyContent: 'center',
                                  boxShadow: '0 8px 24px rgba(82, 196, 26, 0.35)',
                                }}
                              >
                                <CheckCircleOutlined style={{ fontSize: 42, color: '#fff' }} />
                              </span>
                            </div>
                            <div style={{ fontSize: 18, fontWeight: 600, color: '#1f2937', lineHeight: 1.6 }}>
                              无需填写表单，直接点击底部按钮提交即可
                            </div>
                            <div style={{ marginTop: 12, fontSize: 13, color: '#69b1ff' }}>
                              确认无误后点击「完成」结束本节点
                            </div>
                          </div>
                        </div>
                      )}
                      </div>
                    </div>
                    {/* 底部按钮 - 取消 + 提交/完成 */}
                    <div
                      className="flex justify-end gap-3"
                      style={{
                        padding: '20px 24px',
                        borderTop: '1px solid rgba(22, 119, 255, 0.1)',
                        flexShrink: 0,
                        background: 'linear-gradient(0deg, #f0f7ff 0%, #fafcff 60%, #fff 100%)',
                      }}
                    >
                      <Button
                        onClick={() => {
                          setTaskDetailVisible(false);
                          setTaskDetailData(null);
                          setFormData({ rule: [], option: {} });
                          setOriginalFields([]);
                          setOriginalConf('');
                          taskDetailForm.resetFields();
                        }}
                        style={{ minWidth: 120, height: 44, borderRadius: 10, fontSize: 15, fontWeight: 500 }}
                      >
                        {t('common.cancel')}
                      </Button>
                      <Button
                        type="primary"
                        loading={submitLoading}
                        disabled={isApproved}
                        onClick={async () => {
                          const nodeId = taskDetailData.nodeId ?? taskDetailData.id;
                          if (nodeId == null) {
                            message.error(t('cockpit.nodeIdNotExist'));
                            return;
                          }
                          const numNodeId = typeof nodeId === 'number' ? nodeId : Number(nodeId);
                          setSubmitLoading(true);
                          try {
                            const values = formData.rule?.length ? await taskDetailForm.validateFields() : {};
                            const fieldsWithValues = originalFields.map((fieldString: string) => {
                              try {
                                const fieldObj = JSON.parse(fieldString);
                                const fieldName = fieldObj.name || fieldObj.field;
                                const fieldValue = values[fieldName];
                                fieldObj.value = fieldValue !== undefined && fieldValue !== null ? fieldValue : '';
                                return JSON.stringify(fieldObj);
                              } catch (e) {
                                return fieldString;
                              }
                            });
                            const submitData = {
                              id: taskDetailData.formId ?? taskDetailData.id,
                              name: taskDetailData.nodeName || taskDetailData.workName || '未知',
                              conf: originalConf,
                              fields: fieldsWithValues
                            };
                            const formDataString = JSON.stringify(submitData);
                            const params: UpdateNodeApprovalParam = {
                              nodeId: numNodeId,
                              approvalStatus: 'approved',
                              approvalOpinion: undefined,
                              formData: formDataString
                            };
                            await taskManagementApi.updateNodeApproval(params);
                            const nodeType = String(taskDetailData?.type || taskDetailData?.nodeType || '').trim();
                            const isComplete = nodeType === 'complete';
                            message.success(isComplete ? t('form.completeSuccess') : t('common.submit') + t('common.success'));
                            setTaskDetailVisible(false);
                            setTaskDetailData(null);
                            setFormData({ rule: [], option: {} });
                            setFormLoading(false);
                            setOriginalFields([]);
                            setOriginalConf('');
                            taskDetailForm.resetFields();
                            fetchStatistics();
                          } catch (error: any) {
                            if (error?.errorFields) {
                              message.error('请填写完整的表单内容');
                            } else {
                              message.error(error?.message || '提交失败');
                            }
                          } finally {
                            setSubmitLoading(false);
                          }
                        }}
                        style={{ minWidth: 120, height: 44, borderRadius: 10, fontSize: 15, fontWeight: 500, boxShadow: '0 4px 14px rgba(22, 119, 255, 0.35)' }}
                      >
                        {(() => {
                          const nodeType = String(taskDetailData?.type || taskDetailData?.nodeType || '').trim();
                          return nodeType === 'complete' ? t('form.complete') : t('common.submit');
                        })()}
                      </Button>
                    </div>
                  </div>
                );
              })()}
            </div>
          </div>
        ) : (
          <div className="py-8 text-center text-gray-500">暂无数据</div>
        )}
      </Modal>
    </div>
  );
}
