import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { Eye, Search, RotateCcw } from 'lucide-react';
import { Button, Space, Table as AntdTable, Input, message, Modal, Form as AntdForm, Card, Alert, Select, DatePicker, InputNumber, Switch, Radio, Checkbox, Cascader, Upload, Image, Avatar } from 'antd';
import { UploadOutlined, LockOutlined, KeyOutlined, WarningOutlined, CheckCircleOutlined, BarcodeOutlined, SendOutlined, EnvironmentOutlined, CloseCircleOutlined } from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import { toast } from 'sonner';
import dayjs, { Dayjs } from 'dayjs';
import { taskManagementApi, MyTaskVO, MyTaskPageParam, PageResponse, MyTaskNodeDetailVO, UpdateNodeApprovalParam } from '../api/mytask';
import { fileApi } from '../api/file';
import { dateFormatter } from '../utils/formatTime';
import { DICT_TYPE, getDictLabel } from '../utils/dict';
import { setConfAndFields2, FormCreateData } from '../utils/formCreate';
import urgecy1Icon from '../assets/urgecy1.png';
import urgecy2Icon from '../assets/urgecy2.png';
import urgecy3Icon from '../assets/urgecy3.png';
import { useTranslation } from 'react-i18next';
import FormUploadField from './FormUploadField';

// 辅助函数：安全地将值转换为 dayjs 对象
const safeToDayjs = (value: any): dayjs.Dayjs | null => {
  if (!value && value !== 0) {
    return null;
  }
  
  // 如果是数字（时间戳）
  if (typeof value === 'number') {
    // dayjs 默认将数字当作毫秒级时间戳处理
    // 但如果数字小于 10000000000（10位），可能是秒级时间戳，需要转换为毫秒
    let timestamp = value;
    const originalTimestamp = timestamp;
    if (timestamp > 0 && timestamp < 10000000000) {
      // 秒级时间戳，转换为毫秒
      timestamp = timestamp * 1000;
      console.log(`时间戳转换: 秒级 -> 毫秒级`, { original: originalTimestamp, converted: timestamp });
    }
    const dayjsValue = dayjs(timestamp);
    if (dayjsValue.isValid()) {
      console.log(`时间戳解析成功:`, {
        original: value,
        timestamp,
        date: dayjsValue.format('YYYY-MM-DD HH:mm:ss'),
        year: dayjsValue.year()
      });
      return dayjsValue;
    } else {
      console.warn(`时间戳解析失败:`, { original: value, timestamp });
      return null;
    }
  }
  
  // 如果是字符串
  if (typeof value === 'string' && value.trim() !== '') {
    // 尝试判断是否为时间戳字符串
    const numValue = Number(value);
    if (!isNaN(numValue) && numValue > 0 && numValue.toString() === value.trim()) {
      // 是纯数字字符串，可能是时间戳
      // 判断是秒级还是毫秒级时间戳
      let timestamp = numValue;
      const originalTimestamp = timestamp;
      if (timestamp < 10000000000) {
        // 秒级时间戳（10位数字），转换为毫秒
        timestamp = timestamp * 1000;
        console.log(`时间戳转换: 秒级 -> 毫秒级`, { original: originalTimestamp, converted: timestamp });
      } else {
        console.log(`时间戳转换: 毫秒级时间戳`, { timestamp });
      }
      // 否则是毫秒级时间戳（13位或更多），直接使用
      const dayjsValue = dayjs(timestamp);
      if (dayjsValue.isValid()) {
        console.log(`时间戳解析成功:`, {
          original: value,
          timestamp,
          date: dayjsValue.format('YYYY-MM-DD HH:mm:ss'),
          year: dayjsValue.year()
        });
        return dayjsValue;
      } else {
        console.warn(`时间戳解析失败:`, { original: value, timestamp });
        return null;
      }
    } else {
      // 普通日期字符串
      const dayjsValue = dayjs(value);
      return dayjsValue.isValid() ? dayjsValue : null;
    }
  }
  
  // 如果已经是 dayjs 对象，检查是否有 isValid 方法
  if (value && typeof value === 'object' && typeof value.isValid === 'function') {
    try {
      return value.isValid() ? value : null;
    } catch (e) {
      // isValid 调用失败，尝试重新创建
    }
  }
  
  // 如果是对象，检查是否有 isValid 方法（可能是序列化后的 dayjs 对象）
  if (value && typeof value === 'object') {
    // 尝试重新创建 dayjs 对象
    try {
      // 如果有 $d 属性，可能是 dayjs 对象
      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) {
      // 转换失败，返回 null
      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) {
      // 解析失败，跳过
      console.warn('解析字段配置失败:', 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) {
          console.log(`日期范围字段 ${fieldName} 转换成功:`, {
            original: { start, end },
            converted: {
              start: startDayjs.format('YYYY-MM-DD HH:mm:ss'),
              end: endDayjs.format('YYYY-MM-DD HH:mm:ss')
            }
          });
          convertedValues[fieldName] = [startDayjs, endDayjs];
        } else {
          console.warn(`日期范围字段 ${fieldName} 转换失败:`, { start, end, startDayjs, endDayjs });
          convertedValues[fieldName] = undefined;
        }
      } else {
        convertedValues[fieldName] = undefined;
      }
    } else {
      // 其他类型直接使用原值
      convertedValues[fieldName] = value;
    }
  });
  
  return convertedValues;
};

export default function TaskManagement() {
  const { t } = useTranslation();
  const navigate = useNavigate();
  
  const [loading, setLoading] = useState(true);
  const [list, setList] = useState<MyTaskVO[]>([]);
  const [total, setTotal] = useState(0);
  // 从 sessionStorage 读取 status 参数
  const getInitialStatus = () => {
    const status = sessionStorage.getItem('taskManagementStatus');
    return status || undefined;
  };

  const [queryParams, setQueryParams] = useState<MyTaskPageParam>({
    pageNo: 1,
    pageSize: 10,
    key: undefined,
    status: getInitialStatus(),
  });
  const [searchOrderNo, setSearchOrderNo] = useState('');
  const [searchName, setSearchName] = useState('');
  const [approvalStatusDictList, setApprovalStatusDictList] = useState<any[]>([]);
  const [urgencyLevelDictList, setUrgencyLevelDictList] = useState<any[]>([]);
  const [jobCategoryDictList, setJobCategoryDictList] = useState<any[]>([]); // 作业分类 work_type

  // 节点详情弹框相关状态
  const [detailVisible, setDetailVisible] = useState(false);
  const [detailLoading, setDetailLoading] = useState(false);
  const [detailData, setDetailData] = useState<MyTaskNodeDetailVO | null>(null);
  const [formData, setFormData] = useState<FormCreateData>({
    rule: [],
    option: {}
  });
  const [formLoading, setFormLoading] = useState(false); // 表单加载状态
  const [originalFields, setOriginalFields] = useState<string[]>([]); // 保存原始的 fields 数组（JSON 字符串数组）
  const [originalConf, setOriginalConf] = useState<string>(''); // 保存原始的 conf（JSON 字符串）
  const [detailForm] = AntdForm.useForm();
  const [approvalComment, setApprovalComment] = useState(''); // 审核意见
  const [approvalLoading, setApprovalLoading] = useState(false); // 审核操作loading状态
  const [submitLoading, setSubmitLoading] = useState(false); // 提交操作loading状态
  // 隔离方式字典（isolation_method：0=盲板，1=上锁挂牌，2=拆除）
  const [isolationMethodDictList, setIsolationMethodDictList] = useState<any[]>([]);
  // 盲板/拆除类型时的设备编号与附件（仅隔离/方案、解除隔离且隔离方式为盲板或拆除时使用）
  const [isolationDeviceNumber, setIsolationDeviceNumber] = useState('');
  const [isolationFileList, setIsolationFileList] = useState<any[]>([]);
  const [isolationSubmitLoading, setIsolationSubmitLoading] = useState(false);
  
  // 组件挂载时打印调试信息，并从 sessionStorage 读取 status
  useEffect(() => {
    console.log('TaskManagement 组件已加载');
    const status = sessionStorage.getItem('taskManagementStatus');
    if (status) {
      console.log('从 sessionStorage 读取到 status:', status);
      setQueryParams(prev => ({
        ...prev,
        status: status,
        pageNo: 1, // 重置到第一页
      }));
      // 读取后清除 sessionStorage，避免下次进入时自动应用
      sessionStorage.removeItem('taskManagementStatus');
    }
  }, []);
  
  // 监听弹框状态变化
  useEffect(() => {
    console.log('TaskManagement: detailVisible 状态变化', detailVisible, 'detailData:', detailData);
  }, [detailVisible, detailData]);
  
  // 获取审批状态字典
  const getApprovalStatusDictList = async () => {
    try {
      const { dictDataApi } = await import('../api/DictData');
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'approval_status',
      });
      const data = (response as any)?.data || response;
      const dictList = data?.list || [];
      setApprovalStatusDictList(dictList);
      console.log('TaskManagement: 获取审批状态字典成功', dictList);
    } catch (error: any) {
      console.error('获取审批状态字典失败:', error);
    }
  };

  // 获取紧急程度字典
  const getUrgencyLevelDictList = async () => {
    try {
      const { dictDataApi } = await import('../api/DictData');
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'urgency_level',
      });
      const data = (response as any)?.data || response;
      const dictList = data?.list || [];
      setUrgencyLevelDictList(dictList);
      console.log('TaskManagement: 获取紧急程度字典成功', dictList);
    } catch (error: any) {
      console.error('获取紧急程度字典失败:', error);
    }
  };

  // 获取隔离方式字典（isolation_method）
  const getIsolationMethodDictList = async () => {
    try {
      const { dictDataApi } = await import('../api/DictData');
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'isolation_method',
      });
      const data = (response as any)?.data || response;
      const dictList = data?.list || [];
      setIsolationMethodDictList(dictList);
    } catch (error: any) {
      console.error('获取隔离方式字典失败:', error);
    }
  };

  // 获取作业分类字典（work_type）
  const getJobCategoryDictList = async () => {
    try {
      const { dictDataApi } = await import('../api/DictData');
      const response = await dictDataApi.getDictDataPage({
        pageNo: 1,
        pageSize: -1,
        dictType: 'work_type',
      });
      const data = (response as any)?.data || response;
      setJobCategoryDictList(data?.list || []);
    } catch (error: any) {
      console.error('获取作业分类字典失败:', error);
      setJobCategoryDictList([]);
    }
  };

  useEffect(() => {
    getApprovalStatusDictList();
    getUrgencyLevelDictList();
    getIsolationMethodDictList();
    getJobCategoryDictList();
  }, []);
  
  /** 查询列表 */
  const getList = async (params?: MyTaskPageParam) => {
    const searchParams = params || queryParams;
    setLoading(true);
    try {
      console.log('TaskManagement: 开始获取任务管理列表', searchParams);
      const response = await taskManagementApi.getAdminWorkPage(searchParams);
      console.log('TaskManagement: 接口响应', response);
      const data = (response as any)?.data || response;
      const pageData = (data as PageResponse<MyTaskVO>);
      console.log('TaskManagement: 解析后的数据', pageData);
      setList(pageData.list || []);
      setTotal(pageData.total || 0);
    } catch (error: any) {
      console.error('TaskManagement: 获取任务管理列表失败', error);
      toast.error(error.message || t('form.fetchTaskListFailed'));
      setList([]);
      setTotal(0);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    console.log('TaskManagement: useEffect 触发，queryParams:', queryParams);
    getList();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [queryParams.pageNo, queryParams.pageSize, queryParams.key, queryParams.status]);

  // 搜索：两个条件都通过 key 传参，值为具体输入（多个用空格拼接）
  const handleSearch = () => {
    const parts = [searchOrderNo.trim(), searchName.trim()].filter(Boolean);
    setQueryParams({
      ...queryParams,
      pageNo: 1,
      key: parts.length ? parts.join(' ') : undefined,
    });
  };

  // 重置
  const handleReset = () => {
    setSearchOrderNo('');
    setSearchName('');
    setQueryParams({
      ...queryParams,
      pageNo: 1,
      key: undefined,
      status: undefined, // 重置时也清除 status
    });
  };

  // 默认表单配置
  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 || [];
      // 优先使用 label（字段名称），如果没有则使用 cardTitle，最后使用默认值
      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) => {
                // 选择日期时，将 dayjs 对象转换为毫秒级时间戳
                if (!value) return undefined;
                if (value && typeof value === 'object' && 'valueOf' in value && typeof value.valueOf === 'function' && 'isValid' in value && typeof value.isValid === 'function') {
                  // 确保是有效的 dayjs 对象
                  if (value.isValid()) {
                    return value.valueOf(); // dayjs 的 valueOf() 返回毫秒级时间戳
                  }
                  return undefined;
                }
                return value;
              }}
              normalize={(value) => {
                // 回显时，将毫秒级时间戳转换为 dayjs 对象
                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) => {
                // 选择日期范围时，将 dayjs 对象数组转换为毫秒级时间戳数组
                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') {
                  // 确保都是有效的 dayjs 对象
                  if (start.isValid() && end.isValid()) {
                    return [start.valueOf(), end.valueOf()]; // 返回毫秒级时间戳数组
                  }
                  return undefined;
                }
                return value;
              }}
              normalize={(value) => {
                // 回显时，将毫秒级时间戳数组转换为 dayjs 对象数组
                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) => {
                // 选择日期时间时，将 dayjs 对象转换为毫秒级时间戳
                if (!value) return undefined;
                if (value && typeof value === 'object' && 'valueOf' in value) {
                  return value.valueOf(); // dayjs 的 valueOf() 返回毫秒级时间戳
                }
                return value;
              }}
              normalize={(value) => {
                // 回显时，将毫秒级时间戳转换为 dayjs 对象
                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') {
          // 如果是时间类型，使用 DatePicker
          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 {
            // 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}
                >
                  <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 handleViewDetail = async (record: MyTaskVO) => {
    console.log('TaskManagement: handleViewDetail 被调用', record);
    
    if (!record.nodeId) {
      console.warn('TaskManagement: 节点ID不存在', record);
      message.warning('节点ID不存在');
      return;
    }
    
    setDetailLoading(true);
    setDetailVisible(true); // 先打开弹框显示加载状态
    console.log('TaskManagement: 弹框状态已设置为 true (加载中)');
    
    try {
      console.log('TaskManagement: 开始获取节点详情', { nodeId: record.nodeId });
      const response = await taskManagementApi.getAdminWorkNodeDetail(record.nodeId);
      console.log('TaskManagement: 节点详情响应', 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('TaskManagement: ✅ 从 data.formId (字符串) 提取到 formId', extractedFormId);
          }
        } else if (typeof formIdValue === 'number') {
          extractedFormId = formIdValue;
          console.log('TaskManagement: ✅ 从 data.formId (数字) 提取到 formId', extractedFormId);
        }
      }
      
      console.log('TaskManagement: formId 提取结果', { 
        extractedFormId, 
        '原始 data.formId': data?.formId,
        'data.formId 类型': typeof data?.formId
      });
      
      if (extractedFormId === undefined) {
        console.warn('TaskManagement: ⚠️ 未能提取到 formId', {
          'data.formId': data?.formId,
          'data': data
        });
      }
      
      // 合并列表数据中的作业信息（作业名称、编号、负责人、时间等）
      // 直接使用第一层 data，不解析 data.data
      const detailDataWithWorkInfo: MyTaskNodeDetailVO = {
        ...(data || {}),
        workName: record.name || data?.workName || data?.name,
        orderNo: record.orderNo || data?.orderNo,
        workerUserName: record.workerUserName || data?.workerUserName,
        initiatorName: data?.initiatorName || data?.initiator || record.initiatorName || record.initiator || '',
        workTime: record.workTime || data?.workTime,
        // 确保 type 字段存在，使用第一层 data.type
        type: data?.type || data?.nodeType || '',
        nodeType: data?.nodeType || data?.type || '', // 同时设置 nodeType 作为兼容
        // 使用提取到的 formId
        formId: extractedFormId,
      };
      
      console.log('TaskManagement: 合并后的详情数据 - type 和 formId 字段', {
        'data.type': data?.type,
        'data.nodeType': data?.nodeType,
        'data.formId': data?.formId,
        'detailDataWithWorkInfo.type': detailDataWithWorkInfo.type,
        'detailDataWithWorkInfo.nodeType': detailDataWithWorkInfo.nodeType,
        'detailDataWithWorkInfo.formId': detailDataWithWorkInfo.formId,
      });
      
      console.log('TaskManagement: 合并后的详情数据', detailDataWithWorkInfo);
      console.log('TaskManagement: 节点类型', detailDataWithWorkInfo.type);
      
      // 先设置数据，确保弹框有内容显示
      setDetailData(detailDataWithWorkInfo);
      console.log('TaskManagement: detailData 已设置', detailDataWithWorkInfo);
      
      // 确保弹框是打开状态
      setDetailVisible(true);
      setDetailLoading(false);
      console.log('TaskManagement: 弹框状态设置为 true，loading 设置为 false');
      
      // 根据节点类型决定是否需要获取表单
      // isolation、releaseIsolation 和 returnLock 不需要表单，其他类型（review 和其他）需要根据 formId 获取表单
      const nodeType = detailDataWithWorkInfo.type || detailDataWithWorkInfo.nodeType || '';
      const isIsolation = nodeType === 'isolation' || nodeType === '隔离' || nodeType === '隔离/方案';
      const isReleaseIsolation = nodeType === 'releaseIsolation' || nodeType === '解除隔离';
      const isReturnLock = nodeType === 'returnLock';
      const isolationType = String(detailDataWithWorkInfo?.isolationType ?? '').trim();
      const isBlindOrDismantle = isolationType === '0' || isolationType === '2'; // 0=盲板 2=拆除
      
      // 检查任务状态是否为"已通过"
      const isApproved = detailDataWithWorkInfo.approvalStatus === 'approved';
      
      // 获取 formId（可能为 0，所以需要明确检查 undefined 和 null）
      const formId = detailDataWithWorkInfo.formId;
      // formId 可能是数字（包括 0）或字符串，只要不是 undefined、null 或空字符串，就认为有 formId
      const hasFormId = formId !== undefined && formId !== null && (
        typeof formId === 'number' || 
        (typeof formId === 'string' && formId !== '' && formId.trim() !== '')
      );
      
      // 检查是否有 formData（已提交的表单数据）
      const hasFormData = detailDataWithWorkInfo.formData && (
        (typeof detailDataWithWorkInfo.formData === 'string' && detailDataWithWorkInfo.formData.trim() !== '') ||
        (typeof detailDataWithWorkInfo.formData === 'object' && Object.keys(detailDataWithWorkInfo.formData).length > 0)
      );
      
      console.log('TaskManagement: 表单获取判断', {
        nodeType,
        isIsolation,
        isReleaseIsolation,
        isReturnLock,
        isApproved,
        hasFormData,
        formId,
        formIdType: typeof formId,
        hasFormId,
        '从formData获取': isApproved && hasFormData,
        '从formId获取': !isIsolation && !isReleaseIsolation && !isReturnLock && hasFormId && !(isApproved && hasFormData),
        'detailDataWithWorkInfo': detailDataWithWorkInfo,
      });
      
      // 当前节点无表单（无 formId 且不会从 formData 解析出表单）时清空表单 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('TaskManagement: ✅ 任务已通过，从 formData 中解析表单结构');
        setFormLoading(true);
        
        try {
          // 解析 formData（可能是 JSON 字符串或对象）
          let parsedFormData: any;
          if (typeof detailDataWithWorkInfo.formData === 'string') {
            parsedFormData = JSON.parse(detailDataWithWorkInfo.formData);
          } else {
            parsedFormData = detailDataWithWorkInfo.formData;
          }
          
          console.log('TaskManagement: 解析后的 formData', parsedFormData);
          
          // 从 formData 中提取 conf 和 fields
          const conf = parsedFormData.conf;
          const fields = parsedFormData.fields;
          
          if (conf && fields) {
            // 保存原始的 conf 和 fields（JSON 字符串格式）
            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);
            console.log('TaskManagement: 从 formData 保存原始表单数据', {
              conf: confString,
              fieldsCount: fieldsStringArray.length,
              fields: fieldsStringArray
            });
            
            // 解析 fields 中的每个字段，提取 value 值用于回显
            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('TaskManagement: 解析字段 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;
                  
                  // 如果是日期类型，转换为 dayjs 对象
                  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') {
                    // 日期范围类型，转换为 dayjs 数组
                    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('TaskManagement: 解析字段 JSON 失败', e, fieldString);
              }
            });
            
            console.log('TaskManagement: 从 formData 提取的表单值', formValues);
            
            // 设置表单配置和字段
            setConfAndFields2(setFormData, conf, fields);
            console.log('TaskManagement: 表单配置已设置（从 formData）');
            
            // 转换日期值为 dayjs 对象
            const convertedFormValues = convertDateValues(formValues, fieldsStringArray);
            
            // 回填表单值
            setTimeout(() => {
              detailForm.setFieldsValue(convertedFormValues);
              console.log('TaskManagement: 表单数据已回填（从 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,
                }))
              );
              console.log('TaskManagement: 盲板/拆除 deviceNumber/attachments 已回显', { deviceNumber: parsedFormData.deviceNumber, attachmentsCount: listInConf.length });
            }
          } else if (
            parsedFormData.deviceNumber !== undefined ||
            (() => { const a = parsedFormData.attachments; if (a == null) return false; if (Array.isArray(a)) return a.length > 0; if (typeof a === 'string' && a.trim()) { try { const p = JSON.parse(a); return Array.isArray(p) && p.length > 0; } catch { return false; } } return false; })()
          ) {
            // 盲板/拆除 仅 deviceNumber/attachments 无 conf/fields 时的回显
            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,
              }))
            );
            console.log('TaskManagement: 盲板/拆除 formData 已回显', { deviceNumber: parsedFormData.deviceNumber, attachmentsCount: listElse.length });
          } else {
            // 完成/结束等节点可能无表单内容，不提示“表单数据不完整”，有则显示、无则不显示即可
            console.warn('TaskManagement: formData 中缺少 conf 或 fields', { conf: !!conf, fields: !!fields });
          }
        } catch (e) {
          console.error('TaskManagement: 解析 formData 失败', e);
          message.error('解析表单数据失败: ' + (e instanceof Error ? e.message : String(e)));
        } finally {
          setFormLoading(false);
        }
      }
      // 有 formId 时从接口获取表单：① 审核等非隔离节点 ② 盲板/拆除节点（隔离或解除隔离且隔离方式为盲板或拆除）
      else if (hasFormId && (
        (!isIsolation && !isReleaseIsolation && !isReturnLock) ||
        ((isIsolation || isReleaseIsolation) && isBlindOrDismantle)
      )) {
        console.log('TaskManagement: ✅ 满足条件，开始获取表单', { formId, nodeType, isBlindOrDismantle });
        // 重置表单数据
        setFormData({ rule: [], option: {} });
        setOriginalFields([]);
        setOriginalConf('');
        setFormLoading(true);
        
        // 立即调用接口，不使用 setTimeout，确保接口被调用
        (async () => {
          try {
            // 确保 formId 是数字类型
            const numericFormId = typeof formId === 'string' ? parseInt(formId, 10) : formId;
            if (isNaN(numericFormId)) {
              console.error('TaskManagement: formId 不是有效数字', formId);
              message.error('表单ID无效');
              setFormLoading(false);
              return;
            }
            
            console.log('TaskManagement: 🚀 开始调用表单接口', { formId: numericFormId, nodeType, url: `/bpm/form/get?id=${numericFormId}` });
            const FormApi = await import('../api/bpm/form');
            const formDetailResponse = await FormApi.getForm(numericFormId);
            console.log('TaskManagement: ✅ 表单接口调用成功，原始响应', formDetailResponse);
            
            // 处理响应数据（可能包含 code 和 data 包装）
            let formDetail: any = formDetailResponse;
            if (formDetailResponse && typeof formDetailResponse === 'object' && 'data' in formDetailResponse) {
              // 如果响应有 data 字段，使用 data
              formDetail = (formDetailResponse as any).data || formDetailResponse;
            }
            
            console.log('TaskManagement: 处理后的表单详情', formDetail);
            
            // 获取 conf 和 fields
            const conf = formDetail?.conf || formDetail?.formConfig;
            const fields = formDetail?.fields || formDetail?.formFields;
            
            console.log('TaskManagement: 表单配置和字段', { 
              hasConf: !!conf, 
              confType: typeof conf,
              hasFields: !!fields,
              fieldsType: Array.isArray(fields) ? 'array' : typeof fields,
              fieldsLength: Array.isArray(fields) ? fields.length : 0
            });
            
            // 解析表单配置和字段
            if (conf && fields) {
              // 保存原始的 conf 和 fields（JSON 字符串格式）
              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);
              console.log('TaskManagement: 保存原始表单数据', {
                conf: confString,
                fieldsCount: fieldsStringArray.length,
                fields: fieldsStringArray
              });
              
              // setConfAndFields2 会自动处理 JSON 字符串解析
              setConfAndFields2(setFormData, conf, fields);
              console.log('TaskManagement: 表单配置已设置', { 
                conf: typeof conf === 'string' ? 'JSON字符串' : '对象',
                fieldsCount: Array.isArray(fields) ? fields.length : 0 
              });
              
              // 仅任务已完成（approved）时回显表单数据；进行中一律不回显并清空表单
              const shouldEchoFormData = detailDataWithWorkInfo.formData && isApproved;
              if (shouldEchoFormData) {
                try {
                  let formValues = typeof detailDataWithWorkInfo.formData === 'string' 
                    ? JSON.parse(detailDataWithWorkInfo.formData) 
                    : detailDataWithWorkInfo.formData;
                  
                  // 转换日期值为 dayjs 对象
                  const fieldsArray = Array.isArray(fields) ? fields : [];
                  formValues = convertDateValues(formValues, fieldsArray);
                  
                  // 清理无效的日期值，确保所有日期字段都是有效的 dayjs 对象或 undefined
                  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') {
                        // 日期、日期时间或时间选择器类型：确保是有效的 dayjs 对象或 undefined
                        if (isValidDayjs(value)) {
                          // 已经是有效的 dayjs 对象
                          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') {
                        // 日期范围类型：确保数组中的每个元素都是有效的 dayjs 对象
                        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 {
                      detailForm.setFieldsValue(cleanedFormValues);
                      console.log('TaskManagement: 表单数据已回填', cleanedFormValues);
                    } catch (e) {
                      console.error('TaskManagement: 设置表单值失败', e);
                      // 如果设置失败，尝试只设置非日期字段
                      const safeValues: any = {};
                      Object.keys(cleanedFormValues).forEach(key => {
                        const value = cleanedFormValues[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 !== 'daterange' && fieldType !== 'timepicker') {
                            safeValues[key] = value;
                          }
                        } else {
                          safeValues[key] = value;
                        }
                      });
                      detailForm.setFieldsValue(safeValues);
                    }
                  }, 100);
                } catch (e) {
                  console.error('TaskManagement: 解析表单数据失败', e);
                }
              } else if (!isApproved) {
                // 任务进行中：清空自定义表单，避免带出历史或隔离方案等填写内容
                setTimeout(() => { try { detailForm.resetFields(); } catch (_) { /* ignore */ } }, 100);
              }
              // 隔离/解除隔离完成查看详情：从 formData 或节点详情顶层回显 deviceNumber、attachments（部分解除隔离节点仅顶层有数据）
              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);
                  }
                  const hasDev = deviceNum !== undefined && deviceNum !== null;
                  if (hasDev || 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,
                      }))
                    );
                    console.log('TaskManagement: formId 分支 deviceNumber/attachments 已回显', { deviceNumber: deviceNum, attachmentsCount: listF.length });
                  }
                } catch (_) { /* ignore */ }
              }
            } else {
              console.warn('TaskManagement: 表单详情缺少配置或字段', { conf: !!conf, fields: !!fields, formDetail });
              message.warning('表单配置不完整');
            }
          } catch (e) {
            console.error('TaskManagement: 获取表单详情失败', e);
            message.error('获取表单详情失败: ' + (e instanceof Error ? e.message : String(e)));
            // 即使获取表单失败，也继续显示弹框
          } finally {
            setFormLoading(false);
          }
        })();
      } else {
        setFormLoading(false);
        // 隔离/解除隔离已完成但未走 formData 或 formId 分支时，从节点详情顶层回显 deviceNumber、attachments
        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,
                }))
              );
              console.log('TaskManagement: 隔离/解除隔离(无formId分支) deviceNumber/attachments 已从顶层回显', { deviceNumber: deviceNum, attachmentsCount: listF.length });
            }
          } catch (_) { /* ignore */ }
        }
        if (isIsolation || isReleaseIsolation || isReturnLock) {
          console.log('TaskManagement: ⚠️ 隔离类型节点，跳过表单配置获取', { nodeType, isIsolation, isReleaseIsolation, isReturnLock });
        } else if (!hasFormId) {
          console.warn('TaskManagement: ⚠️ 没有表单ID，跳过表单配置获取', { 
            formId, 
            formIdType: typeof formId,
            hasFormId,
            nodeType,
            'detailDataWithWorkInfo': detailDataWithWorkInfo 
          });
          // 不显示提示，静默处理
        } else {
          console.warn('TaskManagement: ⚠️ 未知原因未获取表单', { 
            nodeType, 
            isIsolation, 
            isReleaseIsolation,
            isReturnLock, 
            hasFormId,
            formId 
          });
        }
      }
      
      // 注意：表单数据回填已移到表单配置加载完成后，确保表单字段已渲染
      
      // 回显审核意见（如果有 approvalOpinion 字段，且不是 "pending"）
      if (detailDataWithWorkInfo.approvalOpinion && detailDataWithWorkInfo.approvalOpinion !== 'pending') {
        setApprovalComment(detailDataWithWorkInfo.approvalOpinion);
        console.log('TaskManagement: 回显审核意见', detailDataWithWorkInfo.approvalOpinion);
      } else {
        setApprovalComment(''); // 重置审核意见（包括 pending 的情况）
      }
      
      setDetailLoading(false);
      console.log('TaskManagement: 弹框已打开', { detailVisible: true, detailData: detailDataWithWorkInfo });
    } catch (error: any) {
      console.error('TaskManagement: 获取节点详情失败', error);
      toast.error(error.message || '获取节点详情失败');
      // 即使接口失败，也显示弹框（显示错误信息）
      if (!detailData) {
        setDetailData({
          id: record.nodeId,
          nodeId: record.nodeId,
          workId: record.workId,
          workName: record.name,
          orderNo: record.orderNo,
          workerUserName: record.workerUserName,
          workTime: record.workTime,
          type: '',
        } as MyTaskNodeDetailVO);
      }
      setDetailVisible(true);
    } finally {
      setDetailLoading(false);
    }
  };

  // 获取任务状态显示文本（使用 approval_status 字典）
  const getTaskStatusText = (status: string | number | undefined): string => {
    if (!status) return '未知';
    const statusStr = String(status).toLowerCase();
    const statusItem = approvalStatusDictList.find(item => String(item.value).toLowerCase() === statusStr);
    if (statusItem) {
      return statusItem.label || statusItem.name || '未知';
    }
    // 如果没有找到字典值，使用默认映射
    const statusMap: Record<string, string> = {
      'pending': '待审核',
      'approved': '已通过',
      'rejected': '已驳回',
      'unaudited': '未审核',
    };
    return statusMap[statusStr] || '未知';
  };

  // 获取任务状态样式（审批状态）
  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',
      };
    }
    // 已完成：深绿色 #15803d
    if (statusTextLower.includes('已完成') || statusTextLower.includes('已通过') || 
        statusTextLower.includes('approved') || statusTextLower.includes('完成') ||
        statusTextLower.includes('执行完成')) {
      return {
        backgroundColor: '#15803d',
        color: '#ffffff',
      };
    }
    
    // 如果没有匹配到，默认灰色
    return {
      backgroundColor: '#e5e5e5',
      color: '#333333',
    };
  };

  // 作业状态文案（workDetail.status：作业整体状态，与任务状态 approvalStatus/nodeProgress 不同）
  const getWorkStatusText = (status: string | number | undefined): string => {
    if (status == null || String(status).trim() === '') return t('workJobDetail.statusUnknown');
    const s = String(status).toLowerCase();
    // 后端可能直接返回「执行完成」「已完成」等中文文案，这里统一映射为「已完成」
    if (s.includes('执行完成') || s.includes('已完成') || s === 'completed') {
      return '已完成';
    }
    const map: Record<string, string> = {
      pending: t('workJobDetail.statusPending'),
      running: t('workJobDetail.statusRunning'),
      completed: t('workJobDetail.statusCompleted'),
      rejected: t('workJobDetail.statusRejected'),
      skipped: t('workJobDetail.statusSkipped'),
      cancelled: t('workJobDetail.statusCancelled'),
    };
    return map[s] ?? String(status) ?? t('workJobDetail.statusUnknown');
  };

  const getWorkStatusStyle = (status: string | number | undefined): React.CSSProperties => {
    const s = String(status || '').toLowerCase();
    if (['running', '2'].includes(s)) return { backgroundColor: '#1677ff', color: '#fff' };
    if (['completed', 'approved'].includes(s)) return { backgroundColor: '#15803d', color: '#fff' };
    if (['rejected', 'cancelled'].includes(s)) return { backgroundColor: '#ff4d4f', color: '#fff' };
    if (['pending', '1'].includes(s)) return { backgroundColor: '#e5e5e5', color: '#333' };
    return { backgroundColor: '#e2e8f0', color: '#64748b' };
  };

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

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

  // 表格列配置
  const columns: ColumnsType<MyTaskVO> = [
    {
      title: t('form.taskId'),
      dataIndex: 'orderNo',
      width: 180,
      align: 'center',
      render: (text: string) => text || '-',
    },
    {
      title: t('form.taskName'),
      dataIndex: 'name',
      width: 220,
      align: 'center',
      ellipsis: true,
      render: (text: string) => text || '-',
    },
    {
      title: t('form.currentTask'),
      dataIndex: 'currentNodeName',
      width: 180,
      align: 'center',
      ellipsis: true,
      render: (text: string, record: MyTaskVO) => {
        const displayText = text || record.currentNode || '-';
        if (!displayText || displayText === '-') return displayText;
        return (
          <span
            className="cursor-pointer hover:underline"
            style={{ color: '#1677ff' }}
            onMouseEnter={(e) => {
              e.currentTarget.style.textDecoration = 'underline';
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.textDecoration = 'none';
            }}
            onClick={(e) => {
              e.stopPropagation();
              e.preventDefault();
              handleViewDetail(record);
            }}
            title={displayText}
          >
            {displayText}
          </span>
        );
      },
    },
    {
      title: t('form.taskStatus'),
      dataIndex: 'approvalStatus',
      width: 120,
      align: 'center',
      render: (status: string | number | undefined, record: MyTaskVO) => {
        // 优先使用 approvalStatus，如果没有则使用其他状态字段
        const taskStatus = status || record.taskStatus || record.status;
        // 列表里“已完成/已通过”使用浅绿，弹框/详情仍保持深绿
        const baseStyle = getTaskStatusStyle(taskStatus);
        const statusTextLower = String(getTaskStatusText(taskStatus) || '').toLowerCase();
        const listStyle =
          statusTextLower.includes('已完成') ||
          statusTextLower.includes('已通过') ||
          statusTextLower.includes('approved') ||
          statusTextLower.includes('完成') ||
          statusTextLower.includes('执行完成')
            ? { ...baseStyle, backgroundColor: '#0acb57', color: '#ffffff' }
            : baseStyle;
        return (
          <span
            className="inline-flex px-3 py-1 rounded-lg text-xs"
            style={listStyle}
          >
            {getTaskStatusText(taskStatus)}
          </span>
        );
      },
    },
    {
      title: t('form.responsiblePerson'),
      dataIndex: 'workerUserName',
      width: 150,
      align: 'center',
      render: (text: string, record: MyTaskVO) => {
        // 优先使用 workerUserName，如果没有则尝试从其他字段获取
        return text || record.responsibleName || record.responsible || record.initiatorName || record.initiator || '-';
      },
    },
    {
      title: t('form.taskStartTime'),
      dataIndex: 'workTime',
      width: 180,
      align: 'center',
      render: (text: string | number | Date | undefined, record: MyTaskVO) => {
        // 优先使用 workTime，如果没有则使用其他时间字段
        const time = text || record.taskStartTime || record.initiationTime || record.initiateTime;
        return time ? dateFormatter(time) : '-';
      },
    },
    {
      title: t('form.urgencyLevel'),
      dataIndex: 'urgencyLevel',
      width: 120,
      align: 'center',
      render: (urgencyLevel: string | number | undefined, record: MyTaskVO) => {
        const urgencyValue = urgencyLevel || record.urgencyLevel;
        const urgencyItem = urgencyLevelDictList.find(item => String(item.value) === String(urgencyValue));
        const urgencyText = urgencyItem ? (urgencyItem.label || '') : (urgencyValue ? String(urgencyValue) : '-');
        
        if (!urgencyValue || urgencyValue === null || urgencyValue === undefined || urgencyValue === '') {
          return <span>-</span>;
        }
        
        const { icon, style } = getUrgencyLevelIconAndStyle(urgencyValue);
        
        return (
          <span 
            className="inline-flex items-center justify-center gap-1.5"
          >
            {icon}
            <span style={style}>{urgencyText}</span>
          </span>
        );
      },
    },
    {
      title: t('common.operation'),
      width: 120,
      align: 'center',
      fixed: 'right',
      render: (_: any, record: MyTaskVO) => {
        // 获取任务状态文本
        const statusText = getTaskStatusText(record.approvalStatus);
        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();
                handleViewDetail(record);
              }}
              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>
        );
      },
    },
  ];

  // 计算分页数据
  const totalPages = Math.ceil(total / queryParams.pageSize) || 1;

  return (
    <div className="space-y-6">
      {/* 操作栏和表格容器 */}
      <div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm overflow-hidden">
        {/* 查询与操作栏 */}
        <div className="p-4 lg:p-5 border-b border-gray-200/50">
          <div className="flex flex-wrap items-center gap-2 lg:gap-3 min-w-0">
            {/* 搜索条件：放宽到 280px，可缩小但不挤压不可见 */}
            <div className="flex items-center gap-2 lg:gap-3 w-[280px] min-w-[180px] flex-shrink">
              <span className="text-sm font-medium text-gray-700 whitespace-nowrap flex-shrink-0">{t('form.workOrderNo')}：</span>
              <Input
                value={searchOrderNo}
                onChange={(e) => setSearchOrderNo(e.target.value)}
                placeholder={t('form.workOrderNoPlaceholder')}
                allowClear
                className="min-w-0 w-full"
                onPressEnter={handleSearch}
              />
            </div>
            <div className="flex items-center gap-2 lg:gap-3 w-[280px] min-w-[180px] flex-shrink">
              <span className="text-sm font-medium text-gray-700 whitespace-nowrap flex-shrink-0">{t('form.workName')}：</span>
              <Input
                value={searchName}
                onChange={(e) => setSearchName(e.target.value)}
                placeholder={t('form.workNamePlaceholder')}
                allowClear
                className="min-w-0 w-full"
                onPressEnter={handleSearch}
              />
            </div>

            <Space size="small">
              <Button type="primary" icon={<Search className="w-4 h-4" />} onClick={handleSearch}>
                {t('common.search')}
              </Button>
              <Button icon={<RotateCcw className="w-4 h-4" />} onClick={handleReset}>
                {t('common.reset')}
              </Button>
            </Space>
          </div>
        </div>

        {/* 表格容器：不设 overflow，避免出现第二层纵向滚动条，仅用 Table 的 scroll.x 做横向滚动 */}
        <div className="min-w-0">
          <AntdTable
            loading={loading}
            columns={columns}
            dataSource={list}
            rowKey={(record) => record.id || Math.random()}
            pagination={false}
            scroll={{ x: 1200 }}
            locale={{
              emptyText: t('form.noData'),
            }}
          />
        </div>
      </div>

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

      {/* 详情弹框 */}
      <Modal
        title={null}
        open={detailVisible}
        onCancel={() => {
          console.log('TaskManagement: 弹框关闭');
          setDetailVisible(false);
          setDetailData(null);
          setFormData({ rule: [], option: {} });
          setFormLoading(false);
          setOriginalFields([]);
          setOriginalConf('');
          detailForm.resetFields();
          setApprovalComment('');
          setIsolationDeviceNumber('');
          setIsolationFileList([]);
        }}
        footer={null}
        width={1000}
        destroyOnClose
        confirmLoading={detailLoading}
        maskClosable={false}
        zIndex={1000}
        styles={{
          body: {
            minHeight: '600px',
            maxHeight: '700px',
            height: '700px',
            padding: 0,
            display: 'flex',
            flexDirection: 'column',
            overflow: 'hidden'
          }
        }}
      >
        {(() => {
          console.log('TaskManagement: Modal 内容渲染', { detailLoading, detailData, detailVisible });
          if (detailLoading) {
            return <div className="py-8 text-center">{t('form.loading')}</div>;
          }
          if (detailData) {
            return (
              <div style={{ 
                display: 'flex',
                flexDirection: 'column',
                height: '100%',
                overflow: 'hidden'
              }}>
            {/* 标题区域：左上角显示作业状态（有 workDetail 时），否则显示任务状态 */}
            <div style={{
              padding: '24px 28px 20px',
              background: 'linear-gradient(180deg, #fafbfd 0%, #ffffff 100%)',
              borderBottom: '1px solid #eef0f4',
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
                <div style={{
                  width: '4px',
                  height: '22px',
                  backgroundColor: '#2563eb',
                  borderRadius: '2px',
                  flexShrink: 0,
                }} />
                <h2 style={{ color: '#1e293b', fontSize: 20, fontWeight: 600, margin: 0, letterSpacing: '-0.02em' }}>
                  {detailData.workName || detailData.name || t('form.workDetail')}
                </h2>
                {(() => {
                  const workStatus = (detailData as any).workDetail?.status;
                  if (workStatus != null && String(workStatus).trim() !== '') {
                    const baseStyle = getWorkStatusStyle(workStatus);
                    const workText = getWorkStatusText(workStatus);
                    const isCompleted = String(workText || '').toLowerCase().includes('已完成');
                    const headerStyle = isCompleted ? { ...baseStyle, backgroundColor: '#0acb57', color: '#ffffff' } : baseStyle;
                    return (
                      <span className="inline-flex px-3 py-1 rounded-full text-xs font-medium" style={headerStyle}>
                        {workText}
                      </span>
                    );
                  }
                  return (
                    <span
                      className="inline-flex px-3 py-1 rounded-full text-xs font-medium"
                      style={(() => {
                        const s = detailData.approvalStatus ?? detailData.taskStatus ?? (detailData as any).nodeProgress;
                        const baseStyle = getTaskStatusStyle(s);
                        const textLower = String(getTaskStatusText(s) || '').toLowerCase();
                        const isCompleted =
                          textLower.includes('已完成') ||
                          textLower.includes('已通过') ||
                          textLower.includes('approved') ||
                          textLower.includes('完成') ||
                          textLower.includes('执行完成');
                        return isCompleted ? { ...baseStyle, backgroundColor: '#0acb57', color: '#ffffff' } : baseStyle;
                      })()}
                    >
                      {getTaskStatusText(detailData.approvalStatus ?? detailData.taskStatus ?? (detailData as any).nodeProgress)}
                    </span>
                  );
                })()}
              </div>
              <div className="text-sm flex flex-wrap gap-y-2" style={{ color: '#64748b', marginTop: 14 }}>
                <span>{t('form.workOrderNo')}：{detailData.orderNo || '-'}</span>
                <span style={{ paddingLeft: 16, marginLeft: 12, borderLeft: '1px solid #e2e8f0' }}>
                  {t('form.workResponsible')}：{detailData.initiatorName || '-'}</span>
                <span style={{ paddingLeft: 16, marginLeft: 12, borderLeft: '1px solid #e2e8f0' }}>
                  {t('form.taskResponsible')}：{detailData.workerUserName || '-'}</span>
                <span style={{ paddingLeft: 16, marginLeft: 12, borderLeft: '1px solid #e2e8f0' }}>
                  {t('form.initiationTime')}：{(detailData as any).workDetail?.initiationTime != null ? dateFormatter((detailData as any).workDetail.initiationTime) : (detailData.initiationTime != null ? dateFormatter(detailData.initiationTime) : (detailData.workTime ? dateFormatter(detailData.workTime) : '-'))}
                </span>
              </div>
            </div>

            {/* 内容区域 - 可滚动 */}
            <div
              style={{
                padding: '20px 24px 24px',
                flex: 1,
                overflowY: 'auto',
                minHeight: 0,
                background: '#f8fafc',
              }}
            >
              {(() => {
                // 检查节点状态是否为已通过（approved），如果是则禁用所有输入和按钮
                const isApproved = detailData?.approvalStatus === 'approved';
                
                // 从 detailData.type 或 detailData.nodeType 获取节点类型
                const nodeType = String(detailData?.type || detailData?.nodeType || '').trim();
                console.log('TaskManagement: 渲染内容区域 - 节点类型', nodeType, 'detailData:', detailData);

                // 创建作业类型节点：展示作业详情（作业类型、作业名称、作业发起人、作业分类、作业内容等）
                if (nodeType === 'createJob') {
                  const wd = (detailData as any).workDetail || {};
                  const getLabelFromList = (list: any[], val: any) => list?.find((d: any) => String(d.value) === String(val))?.label ?? val;
                  const taskStartTime = (detailData as any).startTime ?? (detailData as any).createTime ?? detailData.workTime;
                  const taskStatus = detailData.approvalStatus ?? (detailData as any).taskStatus ?? (detailData as any).nodeProgress;
                  const jobCategoryVal = (wd as any).workCategory ?? (wd as any).jobCategory ?? wd.type;
                  const jobCategoryLabel = jobCategoryVal != null ? (getLabelFromList(jobCategoryDictList, jobCategoryVal) || jobCategoryVal) : '-';
                  return (
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
                      {/* 任务概览卡片 */}
                      <div style={{
                        background: '#ffffff',
                        borderRadius: 12,
                        padding: '18px 20px',
                        boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
                        border: '1px solid #eef0f4',
                      }}>
                        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '16px 28px', alignItems: 'center' }}>
                          <span style={{ display: 'inline-flex', alignItems: 'center', fontSize: 14, color: '#64748b' }}>
                            任务名称：<span style={{ color: '#1e293b', fontWeight: 600 }}>{detailData?.nodeName ?? '-'}</span>
                            <span
                              className="inline-flex px-3 py-1 rounded-full text-xs font-medium"
                              style={(() => {
                                const baseStyle = getTaskStatusStyle(taskStatus);
                                const textLower = String(getTaskStatusText(taskStatus) || '').toLowerCase();
                                const isCompleted = textLower.includes('已完成') || textLower.includes('已通过') || textLower.includes('approved') || textLower.includes('完成') || textLower.includes('执行完成');
                                const badgeStyle = isCompleted ? { ...baseStyle, backgroundColor: '#0acb57', color: '#ffffff', marginLeft: 10 } : { ...baseStyle, marginLeft: 10 };
                                return badgeStyle;
                              })()}
                            >
                              {getTaskStatusText(taskStatus)}
                            </span>
                          </span>
                          <span style={{ fontSize: 14, color: '#64748b' }}>负责人：<span style={{ color: '#1e293b', fontWeight: 600 }}>{detailData?.workerUserName ?? '-'}</span></span>
                          <span style={{ fontSize: 14, color: '#64748b' }}>开始时间：<span style={{ color: '#1e293b', fontWeight: 600 }}>{taskStartTime != null ? dateFormatter(taskStartTime) : '-'}</span></span>
                        </div>
                      </div>
                      {/* 作业属性卡片 */}
                      <div style={{
                        background: '#ffffff',
                        borderRadius: 12,
                        padding: '20px',
                        boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
                        border: '1px solid #eef0f4',
                      }}>
                        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '20px 32px' }}>
                          <div><span style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 6 }}>作业名称</span><div style={{ fontSize: 14, color: '#1e293b', fontWeight: 500 }}>{wd.name ?? detailData.workName ?? detailData.name ?? '-'}</div></div>
                          <div><span style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 6 }}>作业分类</span><div style={{ fontSize: 14, color: '#1e293b', fontWeight: 500 }}>{jobCategoryLabel}</div></div>
                          <div><span style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 6 }}>{t('workJobDetail.workflowTemplate') || '流程模板'}</span><div style={{ fontSize: 14, color: '#1e293b', fontWeight: 500 }}>{(wd as any).designName ?? '-'}</div></div>
                          <div><span style={{ fontSize: 12, color: '#64748b', display: 'block', marginBottom: 6 }}>{t('workJobDetail.urgencyLevel') || '紧急程度'}</span><div style={{ fontSize: 14, color: '#1e293b', fontWeight: 500 }}>{(wd as any).urgencyLevel != null ? (getLabelFromList(urgencyLevelDictList, (wd as any).urgencyLevel) || (wd as any).urgencyLevel) : '-'}</div></div>
                        </div>
                      </div>
                      {/* 作业内容卡片 */}
                      <div style={{
                        background: '#ffffff',
                        borderRadius: 12,
                        padding: 20,
                        boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
                        border: '1px solid #eef0f4',
                      }}>
                        <span style={{ fontSize: 12, color: '#64748b', fontWeight: 500, display: 'block', marginBottom: 10 }}>{t('workJobDetail.jobContent') || '作业内容'}</span>
                        <div style={{ fontSize: 14, color: '#334155', lineHeight: 1.7, whiteSpace: 'pre-wrap', background: '#f8fafc', padding: 16, borderRadius: 10, border: '1px solid #eef0f4', minHeight: 60 }}>{(wd.description != null && String(wd.description).trim() !== '') ? String(wd.description).trim() : '-'}</div>
                      </div>
                    </div>
                  );
                }

                const isReview = nodeType === 'review';
                const isIsolation = nodeType === 'isolation';
                const isReleaseIsolation = nodeType === 'releaseIsolation';
                const isReturnLock = nodeType === 'returnLock';
                
                console.log('TaskManagement: 节点类型判断结果', { 
                  isReview, 
                  isIsolation, 
                  isReleaseIsolation,
                  isReturnLock,
                  nodeType,
                  'detailData.type': detailData.type,
                  'detailData.nodeType': detailData.nodeType,
                  'typeof detailData.type': typeof detailData.type,
                  'String(detailData.type)': String(detailData.type)
                });
                // 当前节点是否有表单：无 formId 的节点（如完成/结束）不应渲染自定义表单
                const hasFormIdForCurrentNode = detailData?.formId !== undefined && detailData?.formId !== null && (
                  typeof detailData.formId === 'number' || (typeof detailData.formId === 'string' && String(detailData.formId).trim() !== '')
                );

                // 隔离/方案节点、解除隔离节点和还锁节点
                if (isIsolation || isReleaseIsolation || isReturnLock) {
                  const isolationType = String(detailData?.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 = detailData?.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: 'transparent' }}>
                          <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) => {
                                        const u = f.url || f.response;
                                        return /\.(jpg|jpeg|png|gif|webp|bmp)(\?|$)/i.test(String(u || '')) || /\.(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) => {
                                      const u = f.url || f.response;
                                      return !/\.(jpg|jpeg|png|gif|webp|bmp)(\?|$)/i.test(String(u || '')) && !/\.(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>
                              {/* 盲板/拆除有 formId 时在设备编号和附件上传下方渲染自定义表单，可滚动查看 */}
                              {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">{t('form.formLoading')}</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={detailForm}
                                          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>
                    );
                  }

                  console.log('TaskManagement: ✅ 进入隔离节点渲染分支', { isIsolation, isReleaseIsolation, isReturnLock, nodeType, isolationType });

                  // 隔离/方案（上锁挂牌）节点：三步并列分栏展示
                  if (isIsolation && isLockoutTagout) {
                    const points: any[] = Array.isArray((detailData as any)?.points) ? (detailData as any).points : [];
                    const keysList: any[] = Array.isArray((detailData as any)?.keys) ? (detailData as any).keys : [];
                    const jtLockerUsers: any[] = Array.isArray((detailData as any)?.nodeUserList)
                      ? ((detailData as any).nodeUserList || []).filter((u: any) => String(u?.type || '').toLowerCase() === 'jtlocker')
                      : [];
                    const jtCoLockerUsers: any[] = Array.isArray((detailData as any)?.nodeUserList)
                      ? ((detailData as any).nodeUserList || []).filter((u: any) => String(u?.type || '').toLowerCase() === 'jtcolocker')
                      : [];
                    const lockPersons: any[] = jtLockerUsers;
                    const getPointName = (p: any) =>
                      p?.pointName ??
                      p?.name ??
                      p?.pointLabel ??
                      p?.pointCode ??
                      (p?.id != null ? `点位${p.id}` : '-');
                    const isLocked = (p: any) => Boolean(p?.lockTime) || p?.locked === true || String(p?.status || '').toLowerCase() === 'locked';
                    const lockBadgeStyle = (locked: boolean): React.CSSProperties =>
                      locked
                        ? { backgroundColor: '#15803d', color: '#ffffff' }
                        : { backgroundColor: '#e2e8f0', color: '#475569' };
                    const getKeyStatus = (k: any) => {
                      const status = String(k?.keyStatus ?? '').trim();
                      // 钥匙状态(0-待取出 1-已取出 2-已归还)
                      if (status === '0') return 'to_take';
                      if (status === '1') return 'taken';
                      if (status === '2') return 'returned';
                      return 'unknown';
                    };
                    const getUserAvatarSrc = (u: any) =>
                      u?.avatar ??
                      u?.avatarUrl ??
                      u?.headImg ??
                      u?.headImage ??
                      u?.headUrl ??
                      u?.profilePhoto ??
                      u?.photo ??
                      undefined;
                    const getUserName = (u: any) => u?.nickname ?? u?.nickName ?? u?.name ?? u?.username ?? '-';
                    const getLockerStatus = (u: any) => {
                      // 上锁人状态：0未上锁、1已上锁、2已解锁
                      const s = String(u?.status ?? '').trim();
                      if (s === '1') return 'locked';
                      if (s === '2') return 'unlocked_done';
                      if (s === '0') return 'unlocked';
                      return 'unknown';
                    };

                    return (
                      <div
                        key="isolation-lockout-tabs"
                        style={{
                          height: '100%',
                          display: 'flex',
                          flexDirection: 'column',
                          overflow: 'hidden',
                        }}
                      >
                        <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: 24, background: 'transparent' }}>
                          <Card
                            style={{
                              width: '100%',
                              borderRadius: 16,
                              boxShadow: '0 8px 28px rgba(15, 23, 42, 0.08), 0 2px 8px rgba(0,0,0,0.04)',
                              border: '1px solid #e6e8f0',
                              background: '#ffffff',
                            }}
                            bodyStyle={{ padding: 18 }}
                          >
                            <div
                              style={{
                                display: 'grid',
                                gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
                                gap: 0,
                              }}
                            >
                              {/* 第一步：取挂锁，取钥匙 */}
                              <div style={{ padding: '0 14px', borderRight: '1px solid #eef0f6', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                                <div style={{ fontSize: 14, fontWeight: 600, color: '#0f172a', marginBottom: 12, minHeight: 22 }}>
                                  第一步：取挂锁，取钥匙
                                </div>
                                <div style={{ padding: '8px 0', flex: 1 }}>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>是否上锁</div>
                                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10, marginBottom: 14 }}>
                                    {(lockPersons.length > 0 ? lockPersons : [{ __empty: true }]).map((u: any, idx: number) => {
                                      if (u.__empty) {
                                        return (
                                          <div
                                            key="empty-locker"
                                            style={{
                                              padding: '12px 12px',
                                              borderRadius: 10,
                                              border: '1px dashed #cbd5e1',
                                              background: '#f8fafc',
                                              color: '#64748b',
                                              textAlign: 'center',
                                              fontSize: 13,
                                            }}
                                          >
                                            暂无上锁人
                                          </div>
                                        );
                                      }
                                      const name = getUserName(u);
                                      const avatarSrc = getUserAvatarSrc(u);
                                      const st = getLockerStatus(u);
                                      return (
                                        <div
                                          key={u.id ?? u.userId ?? u.uid ?? idx}
                                          style={{
                                            display: 'flex',
                                            alignItems: 'center',
                                            justifyContent: 'space-between',
                                            gap: 10,
                                            padding: '10px 10px',
                                            borderRadius: 10,
                                            border: '1px solid #e6e8f0',
                                            background: '#ffffff',
                                          }}
                                        >
                                          <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
                                            <Avatar size={32} src={avatarSrc} style={{ background: '#e5e7eb', color: '#111827', flexShrink: 0 }}>
                                              {String(name || '-').slice(0, 1)}
                                            </Avatar>
                                            <div style={{ minWidth: 0 }}>
                                              <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                                                {name}
                                              </div>
                                            </div>
                                          </div>
                                          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12 }}>
                                            {st === 'unknown' ? (
                                              <>
                                                <WarningOutlined style={{ fontSize: 14, color: '#f97316' }} />
                                                <span style={{ color: '#f97316' }}>未知</span>
                                              </>
                                            ) : st === 'locked' ? (
                                              <>
                                                <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} />
                                                <span style={{ color: '#15803d' }}>已上锁</span>
                                              </>
                                            ) : st === 'unlocked_done' ? (
                                              <>
                                                <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} />
                                                <span style={{ color: '#15803d' }}>已解锁</span>
                                              </>
                                            ) : (
                                              <>
                                                <CloseCircleOutlined style={{ fontSize: 14, color: '#dc2626' }} />
                                                <span style={{ color: '#dc2626' }}>未上锁</span>
                                              </>
                                            )}
                                          </span>
                                        </div>
                                      );
                                    })}
                                  </div>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>
                                    本次能量隔离任务中需要隔离上锁的点位
                                  </div>
                                  <div style={{ width: '100%', maxWidth: 320, display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10 }}>
                                      {(points.length > 0 ? points : [{ __empty: true }]).map((p: any, idx: number) => {
                                        if (p.__empty) {
                                          return (
                                            <div
                                              key="empty"
                                              style={{
                                                padding: '14px 12px',
                                                borderRadius: 10,
                                                border: '1px dashed #cbd5e1',
                                                background: '#f8fafc',
                                                color: '#64748b',
                                                textAlign: 'center',
                                                fontSize: 13,
                                              }}
                                            >
                                              暂无点位
                                            </div>
                                          );
                                        }
                                        const locked = isLocked(p);
                                        return (
                                          <div
                                            key={p.id ?? p.pointId ?? idx}
                                            style={{
                                              display: 'flex',
                                              alignItems: 'center',
                                              gap: 10,
                                              padding: '10px 10px',
                                              borderRadius: 10,
                                              border: '1px solid #e6e8f0',
                                              background: '#ffffff',
                                            }}
                                          >
                                            <span
                                              style={{
                                                width: 32,
                                                height: 32,
                                                borderRadius: 10,
                                                background: '#f1f5ff',
                                                display: 'inline-flex',
                                                alignItems: 'center',
                                                justifyContent: 'center',
                                                flexShrink: 0,
                                              }}
                                            >
                                              <EnvironmentOutlined style={{ color: '#1677ff', fontSize: 16 }} />
                                            </span>
                                            <div style={{ minWidth: 0, flex: 1 }}>
                                              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
                                                <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                                                  {getPointName(p)}
                                                </div>
                                                <span className="inline-flex px-3 py-1 rounded-full text-xs font-medium" style={lockBadgeStyle(locked)}>
                                                  {locked ? '已上锁' : '未上锁'}
                                                </span>
                                              </div>
                                            </div>
                                          </div>
                                        );
                                      })}
                                  </div>
                                </div>
                              </div>

                              {/* 第二步：上锁后归还钥匙 */}
                              <div style={{ padding: '0 14px', borderRight: '1px solid #eef0f6', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                                <div style={{ fontSize: 14, fontWeight: 600, color: '#0f172a', marginBottom: 12, minHeight: 22 }}>
                                  第二步：上锁后归还钥匙
                                </div>
                                <div style={{ padding: '8px 0', flex: 1 }}>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>
                                    是否有待归还的钥匙
                                  </div>
                                  <div style={{ width: '100%', maxWidth: 320, display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10 }}>
                                      {(keysList.length > 0 ? keysList : [{ __empty: true }]).map((k: any, idx: number) => {
                                        if (k.__empty) {
                                          return (
                                            <div
                                              key="empty-key"
                                              style={{
                                                padding: '14px 12px',
                                                borderRadius: 10,
                                                border: '1px dashed #cbd5e1',
                                                background: '#f8fafc',
                                                color: '#64748b',
                                                textAlign: 'center',
                                                fontSize: 13,
                                              }}
                                            >
                                              暂无钥匙
                                            </div>
                                          );
                                        }
                                        const status = getKeyStatus(k);
                                        const isReturned = status === 'returned';
                                        let statusText = '未知';
                                        let statusColor = '#6b7280';
                                        if (status === 'to_take') {
                                          statusText = '待取出';
                                          statusColor = '#f97316';
                                        } else if (status === 'taken') {
                                          statusText = '已取出';
                                          statusColor = '#dc2626';
                                        } else if (isReturned) {
                                          statusText = '已归还';
                                          statusColor = '#15803d';
                                        }
                                        const returnedAt =
                                          k?.giveBackTime ??
                                          k?.returnTime ??
                                          k?.returnedTime ??
                                          k?.backTime ??
                                          k?.keyReturnTime ??
                                          k?.updateTime ??
                                          k?.returnedAt ??
                                          k?.returnAt;
                                        return (
                                          <div
                                            key={k.id ?? k.keyId ?? idx}
                                            style={{
                                              display: 'flex',
                                              alignItems: 'center',
                                              gap: 10,
                                              padding: '10px 10px',
                                              borderRadius: 10,
                                              border: '1px solid #e6e8f0',
                                              background: '#ffffff',
                                            }}
                                          >
                                            <span
                                              style={{
                                                width: 32,
                                                height: 32,
                                                borderRadius: 10,
                                                background: '#eff6ff',
                                                display: 'inline-flex',
                                                alignItems: 'center',
                                                justifyContent: 'center',
                                                flexShrink: 0,
                                              }}
                                            >
                                              <KeyOutlined style={{ color: '#2563eb', fontSize: 16 }} />
                                            </span>
                                            <div style={{ minWidth: 0, flex: 1 }}>
                                              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
                                                <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                                                  {k?.keyNfc ?? k?.keyName ?? k?.name ?? k?.code ?? '-'}
                                                </div>
                                                <span
                                                  style={{
                                                    display: 'inline-flex',
                                                    alignItems: 'center',
                                                    gap: 4,
                                                    fontSize: 12,
                                                    color: statusColor,
                                                  }}
                                                >
                                                  {status === 'returned' ? (
                                                    <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} />
                                                  ) : status === 'taken' ? (
                                                    <CloseCircleOutlined style={{ fontSize: 14, color: '#dc2626' }} />
                                                  ) : status === 'to_take' ? (
                                                    <WarningOutlined style={{ fontSize: 14, color: '#f97316' }} />
                                                  ) : (
                                                    <WarningOutlined style={{ fontSize: 14, color: '#9ca3af' }} />
                                                  )}
                                                  <span>{statusText}</span>
                                                </span>
                                              </div>
                                              <div style={{ marginTop: 4, fontSize: 12, color: '#64748b' }}>
                                                归还时间：{isReturned && returnedAt != null && String(returnedAt).trim() !== '' ? dateFormatter(returnedAt) : '-'}
                                              </div>
                                            </div>
                                          </div>
                                        );
                                      })}
                                  </div>
                                </div>
                              </div>

                              {/* 第三步：共锁人共锁 */}
                              <div style={{ padding: '0 14px', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                                <div style={{ fontSize: 14, fontWeight: 600, color: '#0f172a', marginBottom: 12, minHeight: 22 }}>
                                  第三步：共锁人共锁
                                </div>
                                <div style={{ padding: '8px 0', flex: 1 }}>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>是否共锁</div>
                                  <div style={{ width: '100%', maxWidth: 320, display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10 }}>
                                      {(jtCoLockerUsers.length > 0 ? jtCoLockerUsers : [{ __empty: true }]).map((u: any, idx: number) => {
                                        if (u.__empty) {
                                          return (
                                            <div
                                              key="empty-colocker"
                                              style={{
                                                padding: '14px 12px',
                                                borderRadius: 10,
                                                border: '1px dashed #cbd5e1',
                                                background: '#f8fafc',
                                                color: '#64748b',
                                                textAlign: 'center',
                                                fontSize: 13,
                                              }}
                                            >
                                              暂无共锁人
                                            </div>
                                          );
                                        }
                                        const name = getUserName(u);
                                        const avatarSrc = getUserAvatarSrc(u);
                                        // 共锁人状态: 0未共锁、1已共锁、2已解共锁
                                        const lockedStatus = String(u?.status ?? '').trim();
                                        const coLockStatusText = lockedStatus === '1' ? '已共锁' : lockedStatus === '2' ? '已解共锁' : '未共锁';
                                        const coLockStatusColor = lockedStatus === '1' ? '#15803d' : lockedStatus === '2' ? '#15803d' : '#dc2626';
                                        return (
                                          <div
                                            key={u.id ?? u.userId ?? u.uid ?? idx}
                                            style={{
                                              display: 'flex',
                                              alignItems: 'center',
                                              justifyContent: 'space-between',
                                              gap: 10,
                                              padding: '10px 10px',
                                              borderRadius: 10,
                                              border: '1px solid #e6e8f0',
                                              background: '#ffffff',
                                            }}
                                          >
                                            <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
                                              <Avatar
                                                size={32}
                                                src={avatarSrc}
                                                style={{ background: '#e5e7eb', color: '#111827', flexShrink: 0 }}
                                              >
                                                {String(name || '-').slice(0, 1)}
                                              </Avatar>
                                              <div style={{ minWidth: 0 }}>
                                                <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                                                  {name}
                                                </div>
                                              </div>
                                            </div>
                                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, color: coLockStatusColor }}>
                                              {lockedStatus === '1' ? (
                                                <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} />
                                              ) : lockedStatus === '2' ? (
                                                <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} />
                                              ) : (
                                                <CloseCircleOutlined style={{ fontSize: 14, color: '#dc2626' }} />
                                              )}
                                              <span>{coLockStatusText}</span>
                                            </span>
                                          </div>
                                        );
                                      })}
                                  </div>
                                </div>
                              </div>
                            </div>
                          </Card>
                        </div>
                      </div>
                    );
                  }

                  // 解除隔离（上锁挂牌）节点：三步并列分栏展示
                  if (isReleaseIsolation && isLockoutTagout) {
                    const releaseKeysList: any[] = Array.isArray((detailData as any)?.keys) ? (detailData as any).keys : [];
                    const releaseCoLockers: any[] = Array.isArray((detailData as any)?.nodeUserList)
                      ? ((detailData as any).nodeUserList || []).filter((u: any) => String(u?.type || '').toLowerCase() === 'jtcolocker')
                      : [];
                    const releaseLockPersons: any[] = Array.isArray((detailData as any)?.nodeUserList)
                      ? ((detailData as any).nodeUserList || []).filter((u: any) => String(u?.type || '').toLowerCase() === 'jtlocker')
                      : [];
                    const getReleaseKeyStatus = (k: any) => {
                      const s = String(k?.keyStatus ?? '').trim();
                      // 钥匙状态(0-待取出 1-已取出 2-已归还)
                      if (s === '0') return 'to_take';
                      if (s === '1') return 'taken';
                      if (s === '2') return 'returned';
                      return 'unknown';
                    };
                    const getReleaseUserAvatarSrc = (u: any) =>
                      u?.avatar ?? u?.avatarUrl ?? u?.headImg ?? u?.headImage ?? u?.headUrl ?? u?.profilePhoto ?? u?.photo ?? undefined;
                    const getReleaseUserName = (u: any) => u?.nickname ?? u?.nickName ?? u?.name ?? u?.username ?? '-';

                    return (
                      <div key="release-isolation-columns" style={{ height: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
                        <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: 24, background: 'transparent' }}>
                          <Card
                            style={{
                              width: '100%',
                              borderRadius: 16,
                              boxShadow: '0 8px 28px rgba(15, 23, 42, 0.08), 0 2px 8px rgba(0,0,0,0.04)',
                              border: '1px solid #e6e8f0',
                              background: '#ffffff',
                            }}
                            bodyStyle={{ padding: 18 }}
                          >
                            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 0 }}>
                              {/* 第一步：解除共锁 */}
                              <div style={{ padding: '0 14px', borderRight: '1px solid #eef0f6', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                                <div style={{ fontSize: 14, fontWeight: 600, color: '#0f172a', marginBottom: 12, minHeight: 22 }}>第一步：解除共锁</div>
                                <div style={{ padding: '8px 0', flex: 1 }}>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>是否解除共锁</div>
                                  <div style={{ width: '100%', maxWidth: 320, display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10 }}>
                                    {(releaseCoLockers.length > 0 ? releaseCoLockers : [{ __empty: true }]).map((u: any, idx: number) => {
                                      if (u.__empty) {
                                        return (
                                          <div key="empty-release-colocker" style={{ padding: '14px 12px', borderRadius: 10, border: '1px dashed #cbd5e1', background: '#f8fafc', color: '#64748b', textAlign: 'center', fontSize: 13 }}>暂无共锁人</div>
                                        );
                                      }
                                      const name = getReleaseUserName(u);
                                      const avatarSrc = getReleaseUserAvatarSrc(u);
                                      // 共锁人状态: 0未共锁、1已共锁、2已解共锁
                                      const coLockStatus = String(u?.status ?? '').trim();
                                      const coLockText = coLockStatus === '1' ? '已共锁' : coLockStatus === '2' ? '已解共锁' : '未共锁';
                                      const coLockColor = coLockStatus === '1' ? '#15803d' : coLockStatus === '2' ? '#15803d' : '#dc2626';
                                      return (
                                        <div key={u.id ?? u.userId ?? idx} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '10px 10px', borderRadius: 10, border: '1px solid #e6e8f0', background: '#ffffff' }}>
                                          <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
                                            <Avatar size={32} src={avatarSrc} style={{ background: '#e5e7eb', color: '#111827', flexShrink: 0 }}>{String(name || '-').slice(0, 1)}</Avatar>
                                            <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</div>
                                          </div>
                                          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, color: coLockColor }}>
                                            {coLockStatus === '1' ? <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} /> : coLockStatus === '2' ? <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} /> : <CloseCircleOutlined style={{ fontSize: 14, color: '#dc2626' }} />}
                                            <span>{coLockText}</span>
                                          </span>
                                        </div>
                                      );
                                    })}
                                  </div>
                                </div>
                              </div>
                              {/* 第二步：取钥匙（只显示待取出/已取出，接口若为2已归还则视为已取出） */}
                              <div style={{ padding: '0 14px', borderRight: '1px solid #eef0f6', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                                <div style={{ fontSize: 14, fontWeight: 600, color: '#0f172a', marginBottom: 12, minHeight: 22 }}>第二步：取钥匙</div>
                                <div style={{ padding: '8px 0', flex: 1 }}>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>钥匙状态</div>
                                  <div style={{ width: '100%', maxWidth: 320, display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10 }}>
                                    {(releaseKeysList.length > 0 ? releaseKeysList : [{ __empty: true }]).map((k: any, idx: number) => {
                                      if (k.__empty) {
                                        return (
                                          <div key="empty-release-key" style={{ padding: '14px 12px', borderRadius: 10, border: '1px dashed #cbd5e1', background: '#f8fafc', color: '#64748b', textAlign: 'center', fontSize: 13 }}>暂无钥匙</div>
                                        );
                                      }
                                      const status = getReleaseKeyStatus(k);
                                      // 第二步只显示两种：0待取出 / 1或2 均显示已取出（已归还说明必然已取出过）
                                      const step2Taken = status !== 'to_take';
                                      const step2StatusText = step2Taken ? '已取出' : '待取出';
                                      return (
                                        <div key={k.id ?? k.keyId ?? idx} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 10px', borderRadius: 10, border: '1px solid #e6e8f0', background: '#ffffff' }}>
                                          <span style={{ width: 32, height: 32, borderRadius: 10, background: '#eff6ff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                                            <KeyOutlined style={{ color: '#2563eb', fontSize: 16 }} />
                                          </span>
                                          <div style={{ minWidth: 0, flex: 1 }}>
                                            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
                                              <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{k?.keyNfc ?? k?.keyName ?? k?.name ?? '-'}</div>
                                              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 12, color: step2Taken ? '#15803d' : '#dc2626' }}>
                                                {step2Taken ? <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} /> : <CloseCircleOutlined style={{ fontSize: 14, color: '#dc2626' }} />}
                                                <span>{step2StatusText}</span>
                                              </span>
                                            </div>
                                          </div>
                                        </div>
                                      );
                                    })}
                                  </div>
                                </div>
                              </div>
                              {/* 第三步：还钥匙 */}
                              <div style={{ padding: '0 14px', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                                <div style={{ fontSize: 14, fontWeight: 600, color: '#0f172a', marginBottom: 12, minHeight: 22 }}>第三步：还钥匙</div>
                                <div style={{ padding: '8px 0', flex: 1 }}>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>解锁人</div>
                                  <div style={{ width: '100%', maxWidth: 320, display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10, marginBottom: 14 }}>
                                    {(releaseLockPersons.length > 0 ? releaseLockPersons : [{ __empty: true }]).map((u: any, idx: number) => {
                                      if (u.__empty) {
                                        return (
                                          <div key="empty-release-locker" style={{ padding: '12px 12px', borderRadius: 10, border: '1px dashed #cbd5e1', background: '#f8fafc', color: '#64748b', textAlign: 'center', fontSize: 13 }}>暂无解锁人</div>
                                        );
                                      }
                                      const name = getReleaseUserName(u);
                                      const avatarSrc = getReleaseUserAvatarSrc(u);
                                      // 上锁人状态: 0未上锁、1已上锁、2已解锁
                                      const lockStatus = String(u?.status ?? '').trim();
                                      const lockText = lockStatus === '1' ? '已上锁' : lockStatus === '2' ? '已解锁' : '未上锁';
                                      const lockColor = lockStatus === '1' ? '#15803d' : lockStatus === '2' ? '#15803d' : '#dc2626';
                                      return (
                                        <div key={u.id ?? u.userId ?? idx} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '10px 10px', borderRadius: 10, border: '1px solid #e6e8f0', background: '#ffffff' }}>
                                          <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
                                            <Avatar size={32} src={avatarSrc} style={{ background: '#e5e7eb', color: '#111827', flexShrink: 0 }}>{String(name || '-').slice(0, 1)}</Avatar>
                                            <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</div>
                                          </div>
                                          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, color: lockColor }}>
                                            {lockStatus === '1' ? <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} /> : lockStatus === '2' ? <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} /> : <CloseCircleOutlined style={{ fontSize: 14, color: '#dc2626' }} />}
                                            <span>{lockText}</span>
                                          </span>
                                        </div>
                                      );
                                    })}
                                  </div>
                                  <div style={{ fontSize: 13, color: '#64748b', marginBottom: 10 }}>钥匙状态</div>
                                  <div style={{ width: '100%', maxWidth: 320, display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: 10 }}>
                                    {(releaseKeysList.length > 0 ? releaseKeysList : [{ __empty: true }]).map((k: any, idx: number) => {
                                      if (k.__empty) {
                                        return (
                                          <div key="empty-release-key2" style={{ padding: '14px 12px', borderRadius: 10, border: '1px dashed #cbd5e1', background: '#f8fafc', color: '#64748b', textAlign: 'center', fontSize: 13 }}>暂无钥匙</div>
                                        );
                                      }
                                      const status = getReleaseKeyStatus(k);
                                      // 第三步显示三种状态：0待取出、1已取出、2已归还
                                      const step3StatusText = status === 'returned' ? '已归还' : status === 'taken' ? '已取出' : status === 'to_take' ? '待取出' : '未知';
                                      const step3Color = status === 'returned' ? '#15803d' : status === 'taken' ? '#f97316' : '#dc2626';
                                      const returnedAt = k?.giveBackTime ?? k?.returnTime ?? k?.returnedTime ?? k?.backTime ?? k?.keyReturnTime ?? k?.updateTime ?? k?.returnedAt ?? k?.returnAt;
                                      return (
                                        <div key={k.id ?? k.keyId ?? idx} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 10px', borderRadius: 10, border: '1px solid #e6e8f0', background: '#ffffff' }}>
                                          <span style={{ width: 32, height: 32, borderRadius: 10, background: '#eff6ff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                                            <KeyOutlined style={{ color: '#2563eb', fontSize: 16 }} />
                                          </span>
                                          <div style={{ minWidth: 0, flex: 1 }}>
                                            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
                                              <div style={{ fontSize: 13, fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{k?.keyNfc ?? k?.keyName ?? k?.name ?? '-'}</div>
                                              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 12, color: step3Color }}>
                                                {status === 'returned' ? <CheckCircleOutlined style={{ fontSize: 14, color: '#15803d' }} /> : status === 'taken' ? <CheckCircleOutlined style={{ fontSize: 14, color: '#f97316' }} /> : <CloseCircleOutlined style={{ fontSize: 14, color: '#dc2626' }} />}
                                                <span>{step3StatusText}</span>
                                              </span>
                                            </div>
                                            <div style={{ marginTop: 4, fontSize: 12, color: '#64748b' }}>归还时间：{returnedAt != null && String(returnedAt).trim() !== '' ? dateFormatter(returnedAt) : '-'}</div>
                                          </div>
                                        </div>
                                      );
                                    })}
                                  </div>
                                </div>
                              </div>
                            </div>
                          </Card>
                        </div>
                      </div>
                    );
                  }

                  const isolationContent = (
                    <div
                      key="isolation-content"
                      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%)',
                      }}
                    >
                      <Card
                        style={{
                          width: '100%',
                          maxWidth: 500,
                          textAlign: 'center',
                          borderRadius: 16,
                          boxShadow: '0 8px 32px rgba(22, 119, 255, 0.12), 0 2px 8px rgba(0,0,0,0.04)',
                          border: '1px solid rgba(22, 119, 255, 0.15)',
                          background: 'linear-gradient(180deg, #ffffff 0%, #fafcff 100%)',
                        }}
                        bodyStyle={{ padding: '48px 40px' }}
                      >
                        <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>
                      </Card>
                    </div>
                  );
                  return isolationContent;
                }

                // 审核类型节点 (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: 'transparent' }}>
                        <div style={{ width: '100%' }}>
                            {/* 自定义表单：仅当前节点有 formId 时渲染，避免完成/结束节点误展示上一节点表单 */}
                            {formLoading ? (
                              <div className="py-8 text-center text-gray-500">{t('form.formLoading')}</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={detailForm}
                                      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: '#e5e7eb', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 20 }}>
                                  <CheckCircleOutlined style={{ fontSize: 36, color: '#6b7280' }} />
                                </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 #e2e8f0' }}>
                              <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>
                  );
                }

                // 其他节点类型（录入信息等，需要根据 formId 获取表单）- 样式与创建作业弹框一致：无浅蓝背景、无底部操作按钮
                return (
                  <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
                    <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: '24px', background: 'transparent' }}>
                      <div style={{ width: '100%' }}>
                    {/* 自定义表单：仅当前节点有 formId 时渲染，避免完成/结束节点误展示上一节点表单 */}
                    {formLoading ? (
                      <div className="py-8 text-center text-gray-500">{t('form.formLoading')}</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={detailForm}
                              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={{
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'center',
                          padding: '24px 0',
                        }}
                      >
                        <div style={{ width: '100%', textAlign: 'center' }}>
                          <div style={{ marginBottom: 24 }}>
                            <span
                              style={{
                                width: 88,
                                height: 88,
                                borderRadius: 20,
                                background: '#e5e7eb',
                                display: 'inline-flex',
                                alignItems: 'center',
                                justifyContent: 'center',
                              }}
                            >
                              <CheckCircleOutlined style={{ fontSize: 42, color: '#6b7280' }} />
                            </span>
                          </div>
                          <div style={{ fontSize: 18, fontWeight: 600, color: '#1f2937', lineHeight: 1.6 }}>
                            无需操作
                          </div>
                        </div>
                      </div>
                    )}

                      </div>
                    </div>
                  </div>
                );
              })()}
            </div>

            <div
              style={{
                padding: '20px 24px 24px',
                borderTop: '1px solid #eef0f4',
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                background: '#f8fafc',
              }}
            >
              <Button
                size="large"
                type="default"
                style={{
                  minWidth: 180,
                  height: 44,
                  borderRadius: 10,
                  fontSize: 15,
                  fontWeight: 500,
                  borderColor: '#e2e8f0',
                  color: '#334155',
                  boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
                  background: '#ffffff',
                }}
                onClick={() => {
                  console.log('TaskManagement: 弹框关闭（底部关闭按钮）');
                  setDetailVisible(false);
                  setDetailData(null);
                  setFormData({ rule: [], option: {} });
                  setFormLoading(false);
                  setOriginalFields([]);
                  setOriginalConf('');
                  detailForm.resetFields();
                  setApprovalComment('');
                  setIsolationDeviceNumber('');
                  setIsolationFileList([]);
                }}
              >
                关 闭
              </Button>
            </div>
          </div>
            );
          }
          return <div className="py-8 text-center text-gray-500">{t('form.noData')}</div>;
        })()}
      </Modal>
    </div>
  );
}
