// ===== 锁定作业登记表单（核心：A/B循环、多级校验、实时着色）=====
const {
  useState: useStateLF,
  useEffect: useEffectLF,
  useMemo: useMemoLF,
} = React;

function LockoutForm({ device, ods, onBack, onSubmit, currentUser }) {
  // 步骤：0=基本信息 1=A循环锁定 2=B循环锁定 3=拍照签字 4=完成
  const [step, setStep] = useStateLF(0);
  const [workType, setWorkType] = useStateLF('');
  const [otherWorkTypeDesc, setOtherWorkTypeDesc] = useStateLF('');
  const [operators, setOperators] = useStateLF([]); // [{id, type, name}]
  const [guardians, setGuardians] = useStateLF([]); // [{id, type, name}]
  const [remark, setRemark] = useStateLF('');

  // A循环：能源锁定状态 {lockPointId: { locked: bool, verified: bool }}
  const [energyState, setEnergyState] = useStateLF({});
  // B循环：信号锁定状态
  const [signalState, setSignalState] = useStateLF({});
  // 当前选中的能量类型
  const [activeEnergyType, setActiveEnergyType] = useStateLF(null);
  // B循环是否可用（A循环全部完成后）
  const [bUnlocked, setBUnlocked] = useStateLF(false);
  const [showOperatorPicker, setShowOperatorPicker] = useStateLF(false);
  const [showGuardianPicker, setShowGuardianPicker] = useStateLF(false);
  const [pickerSearch, setPickerSearch] = useStateLF('');
  const MAX_OPERATORS = 10;
  const MAX_GUARDIANS = 5;
  const [submitting, setSubmitting] = useStateLF(false);
  const [submitError, setSubmitError] = useStateLF(null);

  // 照片
  const [photos, setPhotos] = useStateLF([]);
  const [showCamera, setShowCamera] = useStateLF(false);

  // 签名
  const [operatorSig, setOperatorSig] = useStateLF(null);
  const [guardianSig, setGuardianSig] = useStateLF(null);

  const energyPoints = ods?.['能量信息'] || [];
  const signalPoints = ods?.['信号信息'] || [];

  // 能量类型分组
  const energyByType = useMemoLF(() => {
    const groups = {};
    energyPoints.forEach(p => {
      if (!groups[p['类型']]) groups[p['类型']] = [];
      groups[p['类型']].push(p);
    });
    return groups;
  }, [energyPoints]);

  // 初始化状态
  useEffectLF(() => {
    const initState = {};
    energyPoints.forEach(p => {
      initState[p['锁定点编号']] = { locked: false, verified: false };
    });
    setEnergyState(initState);

    const sigInitState = {};
    signalPoints.forEach(p => {
      sigInitState[p['锁定点编号']] = { locked: false, verified: false };
    });
    setSignalState(sigInitState);

    // 默认选中第一个能量类型
    const types = Object.keys(energyByType);
    if (types.length > 0) setActiveEnergyType(types[0]);
  }, [energyPoints, signalPoints]);

  // 计算A循环进度
  const aCycleProgress = useMemoLF(() => {
    const total = energyPoints.length;
    if (total === 0) return { total: 0, locked: 0, verified: 0, allDone: true };
    let locked = 0, verified = 0;
    Object.values(energyState).forEach(s => {
      if (s.locked) locked++;
      if (s.verified) verified++;
    });
    return { total, locked, verified, allDone: verified === total };
  }, [energyState, energyPoints]);

  // 计算B循环进度
  const bCycleProgress = useMemoLF(() => {
    const total = signalPoints.length;
    if (total === 0) return { total: 0, locked: 0, verified: 0, allDone: true };
    let locked = 0, verified = 0;
    Object.values(signalState).forEach(s => {
      if (s.locked) locked++;
      if (s.verified) verified++;
    });
    return { total, locked, verified, allDone: verified === total };
  }, [signalState, signalPoints]);

  // A循环完成后解锁B循环
  useEffectLF(() => {
    if (aCycleProgress.allDone && aCycleProgress.total > 0) {
      setBUnlocked(true);
    }
  }, [aCycleProgress.allDone]);

  const toggleEnergyLock = (pointId) => {
    setEnergyState(prev => {
      const next = { ...prev };
      const current = next[pointId];
      if (!current.locked) {
        // 锁定（第一次点击为锁定）
        next[pointId] = { locked: true, verified: false };
      } else if (!current.verified) {
        // 已锁定未验证 -> 验证通过
        next[pointId] = { locked: true, verified: true };
      } else {
        // 已验证 -> 重置
        next[pointId] = { locked: false, verified: false };
      }
      return next;
    });
  };

  const toggleSignalLock = (pointId) => {
    if (!bUnlocked) return;
    setSignalState(prev => {
      const next = { ...prev };
      const current = next[pointId];
      if (!current.locked) {
        next[pointId] = { locked: true, verified: false };
      } else if (!current.verified) {
        next[pointId] = { locked: true, verified: true };
      } else {
        next[pointId] = { locked: false, verified: false };
      }
      return next;
    });
  };

  const handleAddPhoto = (dataUrl) => {
    setPhotos(prev => [...prev, dataUrl]);
    setShowCamera(false);
  };

  const removePhoto = (index) => {
    setPhotos(prev => prev.filter((_, i) => i !== index));
  };

  // 校验：作业类型、至少1名作业人员且相关方/手动添加都填写了姓名
  const allOperatorNamesFilled = operators.every(o =>
    o.type === 'authorized' || (o.name && o.name.trim())
  );
  const allGuardianNamesFilled = guardians.every(g =>
    g.type === 'authorized' || (g.name && g.name.trim())
  );
  const canGoToStep2 = workType && operators.length > 0 &&
    (workType !== 'other' || otherWorkTypeDesc.trim()) &&
    allOperatorNamesFilled;
  const canGoToStep3 = aCycleProgress.allDone && (bCycleProgress.allDone || !showBCycle);
  const canSubmit = photos.length > 0 && operatorSig && guardianSig && allGuardianNamesFilled;

  const handleSubmit = async () => {
    setSubmitting(true);
    setSubmitError(null);

    try {
      const formData = {
        workType,
        otherWorkTypeDesc,
        operators,
        guardians,
        remark,
        energyState,
        signalState,
        photos,
        operatorSig,
        guardianSig,
        aCycleCompleted: aCycleProgress.allDone,
        bCycleEnabled: showBCycle,
        bCycleCompleted: showBCycle ? bCycleProgress.allDone : false,
      };

      const saved = await submitLockoutRecord(device, ods, formData);
      onSubmit(saved);
    } catch (err) {
      console.error('提交失败:', err);
      setSubmitError(err.message || '提交失败，请重试');
      setSubmitting(false);
    }
  };

  // 进度环组件
  const ProgressRing = ({ size, progress, strokeWidth = 4, color = 'var(--safety-yellow)' }) => {
    const radius = (size - strokeWidth) / 2;
    const circumference = 2 * Math.PI * radius;
    const offset = circumference - (progress / 100) * circumference;
    return (
      <svg width={size} height={size}>
        <circle
          cx={size / 2} cy={size / 2} r={radius}
          fill="none" stroke="var(--industrial-light)" strokeWidth={strokeWidth}
        />
        <circle
          cx={size / 2} cy={size / 2} r={radius}
          fill="none" stroke={color} strokeWidth={strokeWidth}
          strokeDasharray={circumference}
          strokeDashoffset={offset}
          strokeLinecap="round"
          transform={`rotate(-90 ${size / 2} ${size / 2})`}
          style={{ transition: 'stroke-dashoffset 0.4s ease' }}
        />
      </svg>
    );
  };

  const renderLockPointStatus = (pointId, state) => {
    if (state.verified) return 'verified';
    if (state.locked) return 'unverified';
    return '';
  };

  return (
    <div className="page">
      <div className="hazard-stripe" />

      <div className="page-header" style={{ paddingTop: 12 }}>
        <div className="page-header-content">
          <button className="back-btn" onClick={onBack}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
              <path d="M15 18l-6-6 6-6" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </button>
          <h1 style={{ fontSize: 16 }}>锁定作业登记</h1>
          <div style={{ fontSize: '13px', color: 'var(--text-muted)', flexShrink: 0 }}>
            {step + 1}/4
          </div>
        </div>
      </div>

      {/* 步骤指示 */}
      <div style={{ padding: '0 16px', marginTop: '12px' }}>
        <div className="steps">
          <div className={`step-item ${step >= 0 ? (step > 0 ? 'done' : 'active') : ''}`}>
            <div className="step-circle">{step > 0 ? '✓' : '1'}</div>
            <div className="step-label">基本信息</div>
          </div>
          <div className={`step-line ${step > 0 ? 'done' : ''}`} />
          <div className={`step-item ${step >= 1 ? (step > 1 ? 'done' : 'active') : ''}`}>
            <div className="step-circle">{step > 1 ? '✓' : '2'}</div>
            <div className="step-label">A/B循环</div>
          </div>
          <div className={`step-line ${step > 1 ? 'done' : ''}`} />
          <div className={`step-item ${step >= 2 ? (step > 2 ? 'done' : 'active') : ''}`}>
            <div className="step-circle">{step > 2 ? '✓' : '3'}</div>
            <div className="step-label">拍照签字</div>
          </div>
          <div className={`step-line ${step > 2 ? 'done' : ''}`} />
          <div className={`step-item ${step >= 3 ? 'active' : ''}`}>
            <div className="step-circle">4</div>
            <div className="step-label">确认提交</div>
          </div>
        </div>
      </div>

      <div className="page-body" style={{ paddingTop: 0 }}>
        {/* ===== 步骤0：基本信息 ===== */}
        {step === 0 && (
          <div>
            <div className="section-title">作业类型</div>
            <div className="option-grid">
              {WORK_TYPES.map(t => (
                <button
                  key={t.id}
                  className={`option-btn ${workType === t.id ? 'selected' : ''}`}
                  onClick={() => setWorkType(t.id)}
                >
                  <div style={{ fontWeight: 700, marginBottom: '4px' }}>{t.name}</div>
                  <div style={{ fontSize: '11px', fontWeight: 400, opacity: 0.7 }}>{t.desc}</div>
                </button>
              ))}
            </div>
            {workType === 'other' && (
              <div className="form-group" style={{ marginTop: '12px' }}>
                <label className="form-label">作业类型说明 <span style={{ color: 'var(--danger-light)' }}>*</span></label>
                <textarea
                  className="form-textarea"
                  value={otherWorkTypeDesc}
                  onChange={(e) => setOtherWorkTypeDesc(e.target.value)}
                  placeholder="请描述作业类型"
                  rows={3}
                  style={{
                    width: '100%',
                    boxSizing: 'border-box',
                    padding: '12px 14px',
                    background: 'var(--card-bg)',
                    border: '1px solid var(--border)',
                    borderRadius: '10px',
                    color: 'var(--text-primary)',
                    fontSize: '14px',
                    fontFamily: 'inherit',
                    resize: 'none',
                    outline: 'none',
                  }}
                />
              </div>
            )}

            <div className="section-title">作业人员</div>
            <div className="form-group">
              <label className="form-label" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span>作业执行人 <span style={{ color: 'var(--danger-light)' }}>*</span></span>
                <span style={{ fontSize: '11px', color: 'var(--text-muted)', fontWeight: 400 }}>{operators.length}/{MAX_OPERATORS} 人</span>
              </label>
              <div
                onClick={() => { if (operators.length < MAX_OPERATORS) setShowOperatorPicker(true); }}
                style={{
                  padding: '12px 14px',
                  background: 'var(--card-bg)',
                  border: '1px solid var(--border)',
                  borderRadius: '10px',
                  cursor: operators.length < MAX_OPERATORS ? 'pointer' : 'not-allowed',
                  minHeight: '48px',
                  boxSizing: 'border-box',
                }}
              >
                <PersonTagList
                  persons={operators}
                  onRemove={(idx) => setOperators(operators.filter((_, i) => i !== idx))}
                  onNameChange={(idx, val) => {
                    const next = [...operators];
                    next[idx] = { ...next[idx], name: val };
                    setOperators(next);
                  }}
                  avatarColor="safety-yellow"
                />
                {operators.length < MAX_OPERATORS && (
                  <div style={{
                    display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '6px',
                    padding: '8px 0 0',
                    fontSize: '13px', color: 'var(--safety-yellow)', fontWeight: 600,
                  }}>
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
                      <path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
                    </svg>
                    添加作业人员
                  </div>
                )}
              </div>
            </div>

            <div className="form-group">
              <label className="form-label" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span>监护人 <span style={{ fontSize: '11px', color: 'var(--text-muted)', fontWeight: 400 }}>可选</span></span>
                <span style={{ fontSize: '11px', color: 'var(--text-muted)', fontWeight: 400 }}>{guardians.length}/{MAX_GUARDIANS} 人</span>
              </label>
              <div
                onClick={() => { if (guardians.length < MAX_GUARDIANS) setShowGuardianPicker(true); }}
                style={{
                  padding: '12px 14px',
                  background: 'var(--card-bg)',
                  border: '1px solid var(--border)',
                  borderRadius: '10px',
                  cursor: guardians.length < MAX_GUARDIANS ? 'pointer' : 'not-allowed',
                  minHeight: '48px',
                  boxSizing: 'border-box',
                }}
              >
                <PersonTagList
                  persons={guardians}
                  onRemove={(idx) => setGuardians(guardians.filter((_, i) => i !== idx))}
                  onNameChange={(idx, val) => {
                    const next = [...guardians];
                    next[idx] = { ...next[idx], name: val };
                    setGuardians(next);
                  }}
                  avatarColor="amber"
                />
                {guardians.length < MAX_GUARDIANS && (
                  <div style={{
                    display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '6px',
                    padding: '8px 0 0',
                    fontSize: '13px', color: '#FFC107', fontWeight: 600,
                  }}>
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
                      <path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
                    </svg>
                    添加监护人
                  </div>
                )}
              </div>
            </div>

            <div className="form-group">
              <label className="form-label">作业备注</label>
              <textarea
                className="form-textarea"
                rows={3}
                placeholder="请输入作业内容描述..."
                value={remark}
                onChange={e => setRemark(e.target.value)}
                style={{ resize: 'none' }}
              />
            </div>
          </div>
        )}

        {/* ===== 步骤1：A/B循环锁定 ===== */}
        {step === 1 && (
          <div>
            {/* A循环卡片 */}
            <div className="card" style={{
              marginBottom: '16px',
              borderColor: bUnlocked ? 'var(--success)' : 'var(--danger)',
              borderWidth: '2px',
              background: aCycleProgress.allDone ? 'rgba(46,125,50,0.08)' : 'rgba(198,40,40,0.05)',
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '12px' }}>
                <span className="cycle-badge cycle-a">A</span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 700, fontSize: '16px' }}>A循环 - 能源锁定</div>
                  <div style={{ fontSize: '12px', color: 'var(--text-muted)' }}>
                    {aCycleProgress.verified}/{aCycleProgress.total} 个锁定点已验证
                  </div>
                </div>
                <div style={{ position: 'relative' }}>
                  <ProgressRing
                    size={48}
                    progress={aCycleProgress.total > 0 ? (aCycleProgress.verified / aCycleProgress.total) * 100 : 0}
                    color={aCycleProgress.allDone ? 'var(--success)' : 'var(--danger)'}
                  />
                  <div style={{
                    position: 'absolute',
                    top: '50%', left: '50%',
                    transform: 'translate(-50%, -50%)',
                    fontSize: '12px',
                    fontWeight: 700,
                  }}>
                    {aCycleProgress.total > 0 ? Math.round((aCycleProgress.verified / aCycleProgress.total) * 100) : 0}%
                  </div>
                </div>
              </div>

              {aCycleProgress.allDone && (
                <div style={{
                  display: 'flex',
                  alignItems: 'center',
                  gap: '6px',
                  padding: '8px 12px',
                  background: 'rgba(46,125,50,0.2)',
                  borderRadius: '8px',
                  fontSize: '13px',
                  fontWeight: 600,
                  color: 'var(--success-light)',
                }}>
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
                    <path d="M5 13l4 4L19 7" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                  A循环能源锁定已全部完成
                </div>
              )}
            </div>

            {/* 能量类型选择 */}
            <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', marginBottom: '16px' }}>
              {Object.keys(energyByType).map(type => {
                const points = energyByType[type];
                const doneCount = points.filter(p => energyState[p['锁定点编号']]?.verified).length;
                return (
                  <button
                    key={type}
                    onClick={() => setActiveEnergyType(type)}
                    style={{
                      padding: '8px 14px',
                      background: activeEnergyType === type ? 'var(--safety-yellow)' : 'var(--industrial-gray)',
                      color: activeEnergyType === type ? 'var(--industrial-darker)' : 'var(--text-secondary)',
                      border: 'none',
                      borderRadius: '8px',
                      fontSize: '13px',
                      fontWeight: activeEnergyType === type ? 700 : 500,
                      cursor: 'pointer',
                      fontFamily: 'inherit',
                      display: 'flex',
                      alignItems: 'center',
                      gap: '6px',
                    }}
                  >
                    {type}
                    <span style={{
                      fontSize: '11px',
                      padding: '1px 6px',
                      borderRadius: '10px',
                      background: activeEnergyType === type ? 'rgba(0,0,0,0.15)' : 'var(--industrial-light)',
                      color: activeEnergyType === type ? 'var(--industrial-darker)' : 'inherit',
                    }}>
                      {doneCount}/{points.length}
                    </span>
                  </button>
                );
              })}
            </div>

            {/* 锁定点列表 */}
            <div style={{ marginBottom: '20px' }}>
              {(energyByType[activeEnergyType] || []).map(p => {
                const state = energyState[p['锁定点编号']] || { locked: false, verified: false };
                const status = renderLockPointStatus(p['锁定点编号'], state);
                return (
                  <div
                    key={p['锁定点编号']}
                    className={`lock-point-card ${status}`}
                    onClick={() => toggleEnergyLock(p['锁定点编号'])}
                    style={{ cursor: 'pointer' }}
                  >
                    <div className="lock-point-header">
                      <span className="lock-point-id">{p['锁定点编号']}</span>
                      <span style={{
                        fontSize: '12px',
                        fontWeight: 700,
                        padding: '3px 8px',
                        borderRadius: '6px',
                        background: status === 'verified'
                          ? 'rgba(46,125,50,0.2)'
                          : status === 'unverified'
                            ? 'rgba(198,40,40,0.2)'
                            : 'var(--industrial-light)',
                        color: status === 'verified'
                          ? 'var(--success-light)'
                          : status === 'unverified'
                            ? 'var(--danger-light)'
                            : 'var(--text-muted)',
                      }}>
                        {status === 'verified' ? '✓ 已验证' : status === 'unverified' ? '待验证' : '未锁定'}
                      </span>
                    </div>
                    <div className="lock-point-detail">
                      <div>{p['控制范围']}</div>
                    </div>
                    {state.locked && (
                      <div className="lock-point-verify">
                        <span style={{
                          fontWeight: 600,
                          color: state.verified ? 'var(--success-light)' : 'var(--danger-light)',
                        }}>
                          {state.verified ? '验证通过：' : '验证方式：'}
                        </span>
                        {p['验证手段']}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>

            <div style={{ fontSize: '12px', color: 'var(--text-muted)', textAlign: 'center', marginBottom: '16px' }}>
              💡 点击锁定点切换状态：未锁定 → 已锁定 → 已验证 → 重置
            </div>

            {/* B循环开关 */}
            <div className="card" style={{
              marginBottom: '16px',
              opacity: bUnlocked ? 1 : 0.5,
              borderColor: bUnlocked ? '#1565C0' : 'var(--border)',
              borderWidth: bUnlocked ? '2px' : '1px',
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
                <span className="cycle-badge cycle-b">B</span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 700, fontSize: '15px' }}>B循环 - 信号锁定</div>
                  <div style={{ fontSize: '12px', color: 'var(--text-muted)' }}>
                    {bUnlocked
                      ? signalPoints.length > 0
                        ? `${bCycleProgress.verified}/${signalPoints.length} 个信号点已验证`
                        : '暂无信号锁定点'
                      : '完成A循环后开启'}
                  </div>
                </div>
                <label style={{
                  position: 'relative',
                  width: '48px',
                  height: '28px',
                  cursor: bUnlocked ? 'pointer' : 'not-allowed',
                  display: 'inline-block',
                }}>
                  <input
                    type="checkbox"
                    checked={showBCycle}
                    onChange={e => bUnlocked && setShowBCycle(e.target.checked)}
                    disabled={!bUnlocked}
                    style={{ opacity: 0, width: 0, height: 0 }}
                  />
                  <div style={{
                    position: 'absolute',
                    top: 0, left: 0, right: 0, bottom: 0,
                    background: showBCycle ? '#1565C0' : 'var(--industrial-light)',
                    borderRadius: '28px',
                    transition: 'background 0.2s',
                  }}>
                    <div style={{
                      position: 'absolute',
                      top: '3px',
                      left: showBCycle ? '23px' : '3px',
                      width: '22px',
                      height: '22px',
                      background: 'white',
                      borderRadius: '50%',
                      transition: 'left 0.2s',
                    }} />
                  </div>
                </label>
              </div>
            </div>

            {/* B循环锁定点（展开时显示）*/}
            {showBCycle && signalPoints.length > 0 && (
              <div style={{ marginBottom: '20px' }}>
                {signalPoints.map(p => {
                  const state = signalState[p['锁定点编号']] || { locked: false, verified: false };
                  const status = renderLockPointStatus(p['锁定点编号'], state);
                  return (
                    <div
                      key={p['锁定点编号']}
                      className={`lock-point-card ${status}`}
                      onClick={() => toggleSignalLock(p['锁定点编号'])}
                      style={{ cursor: 'pointer' }}
                    >
                      <div className="lock-point-header">
                        <span className="lock-point-id">{p['安全装置']}</span>
                        <span className="lock-point-tag tag-signal">{p['锁定点编号']}</span>
                      </div>
                      <div className="lock-point-detail">
                        <div>{p['控制范围']}</div>
                      </div>
                      {state.locked && (
                        <div className="lock-point-verify">
                          <span style={{
                            fontWeight: 600,
                            color: state.verified ? 'var(--success-light)' : 'var(--danger-light)',
                          }}>
                            {state.verified ? '验证通过：' : '验证方式：'}
                          </span>
                          {p['验证手段']}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            )}
          </div>
        )}

        {/* ===== 步骤2：拍照签字 ===== */}
        {step === 2 && (
          <div>
            <div className="section-title">
              现场照片
              <span style={{ marginLeft: 'auto', fontSize: '12px', color: 'var(--danger-light)', fontWeight: 500 }}>
                至少上传 1 张
              </span>
            </div>

            {showCamera ? (
              <CameraCapture onCapture={handleAddPhoto} onCancel={() => setShowCamera(false)} />
            ) : (
              <div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '8px' }}>
                  {photos.map((photo, i) => (
                    <div key={i} style={{
                      position: 'relative',
                      aspectRatio: '1',
                      borderRadius: '10px',
                      overflow: 'hidden',
                    }}>
                      <img src={photo} alt={`照片${i + 1}`} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                      <button
                        onClick={() => removePhoto(i)}
                        style={{
                          position: 'absolute',
                          top: '4px',
                          right: '4px',
                          width: '24px',
                          height: '24px',
                          borderRadius: '50%',
                          background: 'rgba(0,0,0,0.7)',
                          border: 'none',
                          color: 'white',
                          fontSize: '14px',
                          cursor: 'pointer',
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'center',
                        }}
                      >
                        ×
                      </button>
                    </div>
                  ))}
                  {photos.length < 6 && (
                    <button
                      onClick={() => setShowCamera(true)}
                      style={{
                        aspectRatio: '1',
                        borderRadius: '10px',
                        border: '2px dashed var(--industrial-light)',
                        background: 'transparent',
                        color: 'var(--text-muted)',
                        display: 'flex',
                        flexDirection: 'column',
                        alignItems: 'center',
                        justifyContent: 'center',
                        gap: '6px',
                        cursor: 'pointer',
                        fontFamily: 'inherit',
                      }}
                    >
                      <svg width="28" height="28" viewBox="0 0 24 24" fill="none">
                        <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" stroke="currentColor" strokeWidth="1.5" />
                        <circle cx="12" cy="13" r="4" stroke="currentColor" strokeWidth="1.5" />
                      </svg>
                      <span style={{ fontSize: '12px' }}>添加照片</span>
                    </button>
                  )}
                </div>
              </div>
            )}

            <div className="section-title">手写签名</div>

            <div className="card" style={{ marginBottom: '12px' }}>
              <SignaturePad
                label="作业执行人签名"
                onSave={(sig) => setOperatorSig(sig)}
                onClear={() => setOperatorSig(null)}
              />
              <div style={{
                marginTop: '8px',
                fontSize: '12px',
                color: operatorSig ? 'var(--success-light)' : 'var(--danger-light)',
              }}>
                {operatorSig ? '✓ 已签名' : '请执行人在此签名'}
              </div>
            </div>

            <div className="card">
              <SignaturePad
                label="监护人签名"
                onSave={(sig) => setGuardianSig(sig)}
                onClear={() => setGuardianSig(null)}
              />
              <div style={{
                marginTop: '8px',
                fontSize: '12px',
                color: guardianSig ? 'var(--success-light)' : 'var(--text-muted)',
              }}>
                {guardianSig ? '✓ 已签名' : '请监护人在此签名（如有）'}
              </div>
            </div>
          </div>
        )}

        {/* ===== 步骤3：确认提交 ===== */}
        {step === 3 && (
          <div>
            <div className="card" style={{ marginBottom: '16px' }}>
              <div style={{
                textAlign: 'center',
                padding: '20px 0 16px',
                marginBottom: '16px',
                borderBottom: '1px solid var(--border)',
              }}>
                <div style={{
                  width: '64px',
                  height: '64px',
                  borderRadius: '50%',
                  background: 'rgba(46,125,50,0.2)',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  margin: '0 auto 12px',
                }}>
                  <svg width="32" height="32" viewBox="0 0 24 24" fill="none">
                    <path d="M5 13l4 4L19 7" stroke="#4CAF50" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </div>
                <div style={{ fontSize: '18px', fontWeight: 700 }}>锁定作业完成</div>
                <div style={{ fontSize: '13px', color: 'var(--text-muted)', marginTop: '4px' }}>
                  请确认以下信息无误后提交
                </div>
              </div>

              <div style={{ display: 'grid', gap: '12px' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span style={{ color: 'var(--text-muted)', fontSize: '14px' }}>设备名称</span>
                  <span style={{ fontWeight: 600, fontSize: '14px' }}>{device.name}</span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span style={{ color: 'var(--text-muted)', fontSize: '14px' }}>作业类型</span>
                  <span style={{ fontWeight: 600, fontSize: '14px' }}>
                    {workType === 'other' ? `其它: ${otherWorkTypeDesc || ''}` : WORK_TYPES.find(t => t.id === workType)?.name}
                  </span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', gap: '10px' }}>
                  <span style={{ color: 'var(--text-muted)', fontSize: '14px', flexShrink: 0 }}>作业执行人</span>
                  <span style={{ fontWeight: 600, fontSize: '14px', textAlign: 'right', wordBreak: 'break-all' }}>
                    {operators.map((o, i) => {
                      const user = o.type === 'authorized' ? appData.authorizedUsers.find(u => u.id === o.id) : null;
                      const name = o.type === 'authorized'
                        ? (user?.name || o.id)
                        : (o.type === 'related_party' ? `相关方:${o.name || ''}` : `手动添加:${o.name || ''}`);
                      return <span key={i}>{i > 0 ? '、' : ''}{name}</span>;
                    })}
                  </span>
                </div>
                {guardians.length > 0 && (
                  <div style={{ display: 'flex', justifyContent: 'space-between', gap: '10px' }}>
                    <span style={{ color: 'var(--text-muted)', fontSize: '14px', flexShrink: 0 }}>监护人</span>
                    <span style={{ fontWeight: 600, fontSize: '14px', textAlign: 'right', wordBreak: 'break-all' }}>
                      {guardians.map((g, i) => {
                        const user = g.type === 'authorized' ? appData.authorizedUsers.find(u => u.id === g.id) : null;
                        const name = g.type === 'authorized'
                          ? (user?.name || g.id)
                          : (g.type === 'related_party' ? `相关方:${g.name || ''}` : `手动添加:${g.name || ''}`);
                        return <span key={i}>{i > 0 ? '、' : ''}{name}</span>;
                      })}
                    </span>
                  </div>
                )}
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span style={{ color: 'var(--text-muted)', fontSize: '14px' }}>A循环</span>
                  <span style={{
                    fontWeight: 600,
                    fontSize: '14px',
                    color: aCycleProgress.allDone ? 'var(--success-light)' : 'var(--danger-light)',
                  }}>
                    {aCycleProgress.allDone ? '✓ 已完成' : '未完成'}
                  </span>
                </div>
                {showBCycle && (
                  <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                    <span style={{ color: 'var(--text-muted)', fontSize: '14px' }}>B循环</span>
                    <span style={{
                      fontWeight: 600,
                      fontSize: '14px',
                      color: bCycleProgress.allDone ? 'var(--success-light)' : 'var(--danger-light)',
                    }}>
                      {bCycleProgress.allDone ? '✓ 已完成' : '未完成'}
                    </span>
                  </div>
                )}
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span style={{ color: 'var(--text-muted)', fontSize: '14px' }}>现场照片</span>
                  <span style={{ fontWeight: 600, fontSize: '14px' }}>{photos.length} 张</span>
                </div>
              </div>
            </div>

            {remark && (
              <div className="card" style={{ marginBottom: '16px' }}>
                <div style={{ fontSize: '13px', color: 'var(--text-muted)', marginBottom: '6px' }}>作业备注</div>
                <div style={{ fontSize: '14px', lineHeight: 1.6 }}>{remark}</div>
              </div>
            )}

            {/* 签名缩略 */}
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', marginBottom: '16px' }}>
              {operatorSig && (
                <div className="card" style={{ padding: '8px', textAlign: 'center' }}>
                  <div style={{ fontSize: '11px', color: 'var(--text-muted)', marginBottom: '4px' }}>执行人签名</div>
                  <img src={operatorSig} alt="签名" style={{ height: '48px', width: 'auto' }} />
                </div>
              )}
              {guardianSig && (
                <div className="card" style={{ padding: '8px', textAlign: 'center' }}>
                  <div style={{ fontSize: '11px', color: 'var(--text-muted)', marginBottom: '4px' }}>监护人签名</div>
                  <img src={guardianSig} alt="签名" style={{ height: '48px', width: 'auto' }} />
                </div>
              )}
            </div>
          </div>
        )}
      </div>

      {/* 底部按钮 */}
      <div className="bottom-action">
        {step === 0 && (
          <button
            className="btn btn-primary"
            disabled={!canGoToStep2}
            onClick={() => setStep(1)}
          >
            下一步：开始锁定
          </button>
        )}
        {step === 1 && (
          <div style={{ display: 'flex', gap: '10px' }}>
            <button className="btn btn-ghost" style={{ flex: 1 }} onClick={() => setStep(0)}>
              上一步
            </button>
            <button
              className="btn btn-primary"
              style={{ flex: 2 }}
              disabled={!canGoToStep3}
              onClick={() => setStep(2)}
            >
              下一步：拍照签字
            </button>
          </div>
        )}
        {step === 2 && (
          <div style={{ display: 'flex', gap: '10px' }}>
            <button className="btn btn-ghost" style={{ flex: 1 }} onClick={() => setStep(1)}>
              上一步
            </button>
            <button
              className="btn btn-primary"
              style={{ flex: 2 }}
              disabled={!canSubmit}
              onClick={() => setStep(3)}
            >
              下一步：确认提交
            </button>
          </div>
        )}
        {step === 3 && (
          <div>
            <div style={{ display: 'flex', gap: '10px' }}>
              <button className="btn btn-ghost" style={{ flex: 1 }} onClick={() => setStep(2)}>
                返回修改
              </button>
              <button
                className="btn btn-success"
                style={{ flex: 2 }}
                onClick={handleSubmit}
                disabled={submitting}
              >
                {submitting ? (
                  <>
                    <span style={{
                      width: '18px',
                      height: '18px',
                      border: '2px solid rgba(255,255,255,0.3)',
                      borderTopColor: 'white',
                      borderRadius: '50%',
                      animation: 'spin 0.6s linear infinite',
                      display: 'inline-block',
                    }} />
                    提交中...
                  </>
                ) : '提交记录'}
              </button>
            </div>
            {submitError && (
              <div style={{
                marginTop: '10px',
                padding: '10px 14px',
                background: 'rgba(198,40,40,0.15)',
                border: '1px solid rgba(198,40,40,0.3)',
                borderRadius: '8px',
                fontSize: '13px',
                color: 'var(--danger-light)',
                textAlign: 'center',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                gap: '6px',
              }}>
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
                  <path d="M12 9v4M12 17h.01" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
                  <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" stroke="currentColor" strokeWidth="2" />
                </svg>
                {submitError}
              </div>
            )}
          </div>
        )}
      </div>
      {/* 作业执行人选择弹窗 */}
      {showOperatorPicker && (
        <MultiPersonnelPicker
          title="选择作业执行人"
          subtitle="支持多选，最多 10 人"
          users={appData.authorizedUsers.filter(u =>
            (u.auth_types || []).includes('作业人员') && !operators.some(o => o.id === u.id)
          )}
          showAuthType="作业人员"
          showRelatedParty={true}
          showManualAdd={true}
          maxCount={MAX_OPERATORS - operators.length}
          onClose={() => { setShowOperatorPicker(false); setPickerSearch(''); }}
          onConfirm={(selected) => {
            setOperators([...operators, ...selected]);
            setShowOperatorPicker(false);
            setPickerSearch('');
          }}
          searchQuery={pickerSearch}
          onSearchChange={setPickerSearch}
        />
      )}

      {/* 监护人选择弹窗 */}
      {showGuardianPicker && (
        <MultiPersonnelPicker
          title="选择监护人"
          subtitle="支持多选，最多 5 人"
          users={appData.authorizedUsers.filter(u =>
            (u.auth_types || []).includes('监护人') && !guardians.some(g => g.id === u.id)
          )}
          showAuthType="监护人"
          showRelatedParty={true}
          showManualAdd={true}
          maxCount={MAX_GUARDIANS - guardians.length}
          onClose={() => { setShowGuardianPicker(false); setPickerSearch(''); }}
          onConfirm={(selected) => {
            setGuardians([...guardians, ...selected]);
            setShowGuardianPicker(false);
            setPickerSearch('');
          }}
          searchQuery={pickerSearch}
          onSearchChange={setPickerSearch}
        />
      )}
    </div>
  );
}

// ===== 人员标签列表（已选人员展示） =====
function PersonTagList({ persons, onRemove, onNameChange, avatarColor = 'safety-yellow' }) {
  if (persons.length === 0) {
    return (
      <div style={{
        display: 'flex', alignItems: 'center', gap: '8px',
        color: 'var(--text-muted)', fontSize: '13px',
      }}>
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
          <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
          <circle cx="9" cy="7" r="4" stroke="currentColor" strokeWidth="2" />
        </svg>
        点击选择或添加人员
      </div>
    );
  }

  const bgColors = {
    'safety-yellow': 'linear-gradient(135deg, var(--safety-yellow), #FFA000)',
    'amber': 'linear-gradient(135deg, #FFC107, #FF9800)',
    'orange': 'linear-gradient(135deg, #FF9800, #F57C00)',
  };
  const tagBg = {
    'safety-yellow': 'rgba(255, 193, 7, 0.12)',
    'amber': 'rgba(255, 193, 7, 0.12)',
    'orange': 'rgba(255, 152, 0, 0.12)',
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
      {persons.map((p, idx) => {
        const user = p.type === 'authorized' ? appData.authorizedUsers.find(u => u.id === p.id) : null;
        const displayName = p.type === 'authorized'
          ? (user?.name || p.name || '未知')
          : (p.name || (p.type === 'related_party' ? '相关方人员' : '手动添加人员'));
        const typeLabel = p.type === 'related_party' ? '相关方' : (p.type === 'manual' ? '手动添加' : null);
        const avatarBg = p.type === 'authorized' ? bgColors[avatarColor] : bgColors['orange'];
        const dept = user ? user.department : (p.type === 'related_party' ? '非系统授权' : '手动添加人员');
        return (
          <div key={idx} style={{
            display: 'flex', alignItems: 'center', gap: '10px',
            padding: '10px 12px',
            background: tagBg[avatarColor] || 'rgba(255,193,7,0.1)',
            border: '1px solid var(--border)',
            borderRadius: '10px',
          }}>
            <div style={{
              width: '32px', height: '32px', borderRadius: '50%',
              background: avatarBg,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontWeight: 700, fontSize: '12px',
              color: p.type === 'authorized' ? 'var(--industrial-darker)' : '#fff',
              flexShrink: 0,
            }}>
              {p.type === 'authorized' ? (user?.avatar || displayName.charAt(0)) : (
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
                  <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  <circle cx="9" cy="7" r="4" stroke="currentColor" strokeWidth="2" />
                </svg>
              )}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: '6px', flexWrap: 'wrap' }}>
                {p.type === 'authorized' ? (
                  <span style={{ fontWeight: 600, fontSize: '13px' }}>{displayName}</span>
                ) : (
                  <input
                    type="text"
                    value={p.name || ''}
                    onChange={(e) => onNameChange && onNameChange(idx, e.target.value)}
                    placeholder={p.type === 'related_party' ? '请输入相关方姓名' : '请输入姓名'}
                    onClick={(e) => e.stopPropagation()}
                    style={{
                      flex: 1,
                      background: 'var(--card-bg)',
                      border: '1px solid var(--border)',
                      borderRadius: '6px',
                      padding: '6px 10px',
                      color: 'var(--text-primary)',
                      fontSize: '13px',
                      fontWeight: 600,
                      outline: 'none',
                      minWidth: 0,
                    }}
                  />
                )}
                {typeLabel && (
                  <span style={{
                    fontSize: '10px',
                    padding: '1px 6px',
                    borderRadius: '3px',
                    background: 'rgba(255,152,0,0.2)',
                    color: '#FFB74D',
                  }}>
                    {typeLabel}
                  </span>
                )}
              </div>
              <div style={{ fontSize: '11px', color: 'var(--text-muted)', marginTop: '2px' }}>
                {dept}{user?.team ? ' · ' + user.team : ''}
              </div>
            </div>
            <button
              onClick={(e) => { e.stopPropagation(); onRemove && onRemove(idx); }}
              style={{
                background: 'none', border: 'none',
                color: 'var(--text-muted)', cursor: 'pointer',
                padding: '4px', flexShrink: 0,
              }}
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
                <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
              </svg>
            </button>
          </div>
        );
      })}
    </div>
  );
}

// ===== 多选人员弹窗组件 =====
function MultiPersonnelPicker({
  title, subtitle, users, onClose, onConfirm,
  searchQuery, onSearchChange,
  showAuthType, showRelatedParty, showManualAdd,
  maxCount = 10,
}) {
  const [deptFilter, setDeptFilter] = React.useState('全部');
  const [selectedIds, setSelectedIds] = React.useState([]); // authorized ids
  const [relatedSelected, setRelatedSelected] = React.useState(false);
  const [manualNames, setManualNames] = React.useState([]); // string array
  const [showManualInput, setShowManualInput] = React.useState(false);
  const [manualInputValue, setManualInputValue] = React.useState('');

  const totalSelected = selectedIds.length + (relatedSelected ? 1 : 0) + manualNames.length;
  const canAddMore = totalSelected < maxCount;

  const departments = React.useMemo(() => {
    const depts = [...new Set(users.map(u => u.department).filter(Boolean))];
    return ['全部', ...depts.sort()];
  }, [users]);

  const filteredUsers = React.useMemo(() => {
    let list = users;
    if (deptFilter !== '全部') {
      list = list.filter(u => u.department === deptFilter);
    }
    if (searchQuery && searchQuery.trim()) {
      const q = searchQuery.trim().toLowerCase();
      list = list.filter(u =>
        u.name.toLowerCase().includes(q) ||
        (u.team || '').toLowerCase().includes(q) ||
        (u.department || '').toLowerCase().includes(q)
      );
    }
    return [...list].sort((a, b) => {
      if (a.department !== b.department) return (a.department || '').localeCompare(b.department || '');
      return a.name.localeCompare(b.name);
    });
  }, [users, deptFilter, searchQuery]);

  const toggleUser = (user) => {
    const idx = selectedIds.indexOf(user.id);
    if (idx >= 0) {
      setSelectedIds(selectedIds.filter(id => id !== user.id));
    } else {
      if (!canAddMore) return;
      setSelectedIds([...selectedIds, user.id]);
    }
  };

  const addManual = () => {
    const name = manualInputValue.trim();
    if (!name) return;
    if (!canAddMore) return;
    setManualNames([...manualNames, name]);
    setManualInputValue('');
    setShowManualInput(false);
  };

  const handleConfirm = () => {
    const result = [];
    selectedIds.forEach(id => {
      result.push({ id, type: 'authorized', name: '' });
    });
    if (relatedSelected) {
      result.push({ id: 'related_party', type: 'related_party', name: '' });
    }
    manualNames.forEach(name => {
      result.push({ id: 'manual_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6), type: 'manual', name });
    });
    onConfirm && onConfirm(result);
  };

  return (
    <div
      style={{
        position: 'fixed',
        top: 0, left: 0, right: 0, bottom: 0,
        background: 'rgba(0,0,0,0.7)',
        zIndex: 200,
        display: 'flex',
        alignItems: 'flex-end',
        justifyContent: 'center',
        animation: 'fadeIn 0.2s ease',
      }}
      onClick={onClose}
    >
      <style>{`
        @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
        @keyframes slideUpPersonnel { from { transform: translateY(100%); } to { transform: translateY(0); } }
      `}</style>
      <div
        onClick={e => e.stopPropagation()}
        style={{
          width: '100%',
          maxWidth: '430px',
          background: 'var(--industrial-dark)',
          borderTopLeftRadius: '20px',
          borderTopRightRadius: '20px',
          padding: '20px 20px calc(24px + env(safe-area-inset-bottom))',
          animation: 'slideUpPersonnel 0.3s ease',
          maxHeight: '85vh',
          display: 'flex',
          flexDirection: 'column',
        }}
      >
        <div style={{
          width: '40px',
          height: '4px',
          background: 'var(--industrial-light)',
          borderRadius: '2px',
          margin: '0 auto 12px',
        }} />

        <h2 style={{ fontSize: '18px', fontWeight: 700, marginBottom: '4px', textAlign: 'center' }}>
          {title}
        </h2>
        <p style={{ fontSize: '12px', color: 'var(--text-muted)', textAlign: 'center', marginBottom: '12px' }}>
          {subtitle} · 已选 {totalSelected}/{maxCount} 人
        </p>

        {/* 已选标签滚动区 */}
        {totalSelected > 0 && (
          <div style={{
            display: 'flex', gap: '6px', overflowX: 'auto',
            paddingBottom: '10px', marginBottom: '4px',
            flexShrink: 0,
          }}>
            {selectedIds.map(id => {
              const user = users.find(u => u.id === id) || appData.authorizedUsers.find(u => u.id === id);
              return (
                <div key={id} style={{
                  display: 'flex', alignItems: 'center', gap: '4px',
                  padding: '4px 6px 4px 4px',
                  background: 'var(--safety-yellow)',
                  borderRadius: '14px',
                  fontSize: '12px',
                  color: 'var(--industrial-darker)',
                  fontWeight: 600,
                  whiteSpace: 'nowrap',
                  flexShrink: 0,
                }}>
                  <span style={{
                    width: '22px', height: '22px', borderRadius: '50%',
                    background: 'rgba(0,0,0,0.1)',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    fontSize: '11px',
                  }}>{user?.name?.charAt(0) || '?'}</span>
                  <span>{user?.name || '?'}</span>
                  <span
                    onClick={() => setSelectedIds(selectedIds.filter(x => x !== id))}
                    style={{ cursor: 'pointer', marginLeft: '2px' }}
                  >×</span>
                </div>
              );
            })}
            {relatedSelected && (
              <div style={{
                display: 'flex', alignItems: 'center', gap: '4px',
                padding: '4px 6px 4px 4px',
                background: 'rgba(255,152,0,0.8)',
                borderRadius: '14px',
                fontSize: '12px',
                color: '#fff',
                fontWeight: 600,
                whiteSpace: 'nowrap',
                flexShrink: 0,
              }}>
                <span style={{
                  width: '22px', height: '22px', borderRadius: '50%',
                  background: 'rgba(0,0,0,0.15)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: '10px',
                }}>相</span>
                <span>相关方</span>
                <span
                  onClick={() => setRelatedSelected(false)}
                  style={{ cursor: 'pointer', marginLeft: '2px' }}
                >×</span>
              </div>
            )}
            {manualNames.map((name, i) => (
              <div key={'m' + i} style={{
                display: 'flex', alignItems: 'center', gap: '4px',
                padding: '4px 6px 4px 4px',
                background: 'rgba(76, 175, 80, 0.8)',
                borderRadius: '14px',
                fontSize: '12px',
                color: '#fff',
                fontWeight: 600,
                whiteSpace: 'nowrap',
                flexShrink: 0,
              }}>
                <span style={{
                  width: '22px', height: '22px', borderRadius: '50%',
                  background: 'rgba(0,0,0,0.15)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: '10px',
                }}>手</span>
                <span>{name}</span>
                <span
                  onClick={() => setManualNames(manualNames.filter((_, idx) => idx !== i))}
                  style={{ cursor: 'pointer', marginLeft: '2px' }}
                >×</span>
              </div>
            ))}
          </div>
        )}

        {/* 搜索框 */}
        <div style={{ position: 'relative', marginBottom: '10px' }}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" style={{
            position: 'absolute', left: '14px', top: '50%', transform: 'translateY(-50%)', color: 'var(--text-muted)',
          }}>
            <circle cx="11" cy="11" r="8" stroke="currentColor" strokeWidth="2" />
            <path d="M21 21l-4.35-4.35" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
          </svg>
          <input
            type="text"
            value={searchQuery}
            onChange={e => onSearchChange(e.target.value)}
            placeholder="搜索姓名、部门或班组..."
            style={{
              width: '100%',
              padding: '12px 16px 12px 42px',
              background: 'var(--card-bg)',
              border: '1px solid var(--border)',
              borderRadius: '12px',
              color: 'var(--text-primary)',
              fontSize: '14px',
              outline: 'none',
              boxSizing: 'border-box',
            }}
          />
        </div>

        {/* 部门筛选 */}
        <div style={{
          display: 'flex', gap: '6px', overflowX: 'auto', marginBottom: '10px', paddingBottom: '2px', flexShrink: 0,
        }}>
          {departments.map(dept => (
            <div
              key={dept}
              onClick={() => setDeptFilter(dept)}
              style={{
                padding: '5px 12px',
                borderRadius: '14px',
                fontSize: '12px',
                fontWeight: deptFilter === dept ? 600 : 400,
                background: deptFilter === dept ? 'var(--safety-yellow)' : 'var(--card-bg)',
                color: deptFilter === dept ? 'var(--industrial-darker)' : 'var(--text-secondary)',
                whiteSpace: 'nowrap',
                cursor: 'pointer',
                flexShrink: 0,
                border: '1px solid',
                borderColor: deptFilter === dept ? 'var(--safety-yellow)' : 'var(--border)',
              }}
            >
              {dept}
            </div>
          ))}
        </div>

        {/* 人员列表 */}
        <div style={{ flex: 1, overflowY: 'auto', minHeight: '150px' }}>
          {filteredUsers.length === 0 ? (
            <div style={{ textAlign: 'center', padding: '40px 20px', color: 'var(--text-muted)', fontSize: '13px' }}>
              未找到匹配人员
            </div>
          ) : (
            filteredUsers.map(user => {
              const checked = selectedIds.includes(user.id);
              const disabled = !checked && !canAddMore;
              return (
                <div
                  key={user.id}
                  onClick={() => !disabled && toggleUser(user)}
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: '12px',
                    padding: '10px 14px',
                    background: checked ? 'rgba(255,193,7,0.1)' : 'var(--card-bg)',
                    border: '1px solid',
                    borderColor: checked ? 'var(--safety-yellow)' : 'var(--border)',
                    borderRadius: '10px',
                    marginBottom: '6px',
                    cursor: disabled ? 'not-allowed' : 'pointer',
                    opacity: disabled ? 0.5 : 1,
                  }}
                >
                  <div style={{
                    width: '36px', height: '36px', borderRadius: '50%',
                    background: 'linear-gradient(135deg, var(--safety-yellow), #FFA000)',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    fontWeight: 700, fontSize: '13px', color: 'var(--industrial-darker)', flexShrink: 0,
                  }}>
                    {user.avatar || user.name.charAt(0)}
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 600, fontSize: '14px', display: 'flex', alignItems: 'center', gap: '6px' }}>
                      {user.name}
                      {(user.auth_types || []).slice(0, 2).map(t => (
                        <span
                          key={t}
                          style={{
                            fontSize: '10px',
                            padding: '1px 6px',
                            borderRadius: '3px',
                            background: t === '作业人员' ? 'rgba(76,175,80,0.2)' : 'rgba(255,193,7,0.2)',
                            color: t === '作业人员' ? '#4CAF50' : '#FFC107',
                          }}
                        >
                          {t}
                        </span>
                      ))}
                    </div>
                    <div style={{
                      fontSize: '11px', color: 'var(--text-muted)', marginTop: '2px',
                      display: 'flex', gap: '6px', flexWrap: 'wrap',
                    }}>
                      {user.department && <span>{user.department}</span>}
                      {user.team && <span>· {user.team}</span>}
                    </div>
                  </div>
                  <div style={{
                    width: '22px', height: '22px',
                    borderRadius: '50%',
                    border: '2px solid',
                    borderColor: checked ? 'var(--safety-yellow)' : 'var(--industrial-light)',
                    background: checked ? 'var(--safety-yellow)' : 'transparent',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    flexShrink: 0,
                  }}>
                    {checked && (
                      <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
                        <path d="M5 13l4 4L19 7" stroke="var(--industrial-darker)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
                      </svg>
                    )}
                  </div>
                </div>
              );
            })
          )}

          {/* 相关方选项 */}
          {showRelatedParty && (
            <div
              onClick={() => {
                if (relatedSelected) {
                  setRelatedSelected(false);
                } else if (canAddMore) {
                  setRelatedSelected(true);
                }
              }}
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: '12px',
                padding: '10px 14px',
                background: relatedSelected ? 'rgba(255,152,0,0.18)' : 'rgba(255,152,0,0.08)',
                border: '1px solid',
                borderColor: relatedSelected ? '#FF9800' : 'rgba(255,152,0,0.3)',
                borderRadius: '10px',
                marginBottom: '6px',
                marginTop: '10px',
                cursor: canAddMore || relatedSelected ? 'pointer' : 'not-allowed',
                opacity: !canAddMore && !relatedSelected ? 0.5 : 1,
              }}
            >
              <div style={{
                width: '36px', height: '36px', borderRadius: '50%',
                background: 'linear-gradient(135deg, #FF9800, #F57C00)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontWeight: 700, fontSize: '14px', color: '#fff', flexShrink: 0,
              }}>
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
                  <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  <circle cx="9" cy="7" r="4" stroke="currentColor" strokeWidth="2" />
                </svg>
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 600, fontSize: '14px', color: '#FFB74D', display: 'flex', alignItems: 'center', gap: '6px' }}>
                  相关方人员
                  <span style={{
                    fontSize: '10px',
                    padding: '1px 6px',
                    borderRadius: '3px',
                    background: 'rgba(255,152,0,0.3)',
                    color: '#FFB74D',
                  }}>
                    非系统授权
                  </span>
                </div>
                <div style={{ fontSize: '11px', color: 'var(--text-muted)', marginTop: '2px' }}>
                  选择后在表单中填写姓名
                </div>
              </div>
              <div style={{
                width: '22px', height: '22px',
                borderRadius: '50%',
                border: '2px solid',
                borderColor: relatedSelected ? '#FF9800' : 'rgba(255,255,255,0.2)',
                background: relatedSelected ? '#FF9800' : 'transparent',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                flexShrink: 0,
              }}>
                {relatedSelected && (
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
                    <path d="M5 13l4 4L19 7" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                )}
              </div>
            </div>
          )}

          {/* 手动添加 */}
          {showManualAdd && !showManualInput && (
            <div
              onClick={() => canAddMore && setShowManualInput(true)}
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: '12px',
                padding: '10px 14px',
                background: 'rgba(76, 175, 80, 0.08)',
                border: '1px dashed rgba(76, 175, 80, 0.4)',
                borderRadius: '10px',
                marginBottom: '6px',
                cursor: canAddMore ? 'pointer' : 'not-allowed',
                opacity: canAddMore ? 1 : 0.5,
              }}
            >
              <div style={{
                width: '36px', height: '36px', borderRadius: '50%',
                background: 'rgba(76,175,80,0.2)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontWeight: 700, fontSize: '16px', color: '#4CAF50', flexShrink: 0,
              }}>
                +
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 600, fontSize: '14px', color: '#4CAF50' }}>
                  手动添加人员
                </div>
                <div style={{ fontSize: '11px', color: 'var(--text-muted)', marginTop: '2px' }}>
                  非系统授权人员，手动输入姓名
                </div>
              </div>
            </div>
          )}

          {showManualAdd && showManualInput && (
            <div style={{
              display: 'flex', gap: '8px', alignItems: 'center',
              padding: '10px 12px',
              background: 'rgba(76, 175, 80, 0.08)',
              border: '1px solid rgba(76, 175, 80, 0.3)',
              borderRadius: '10px',
              marginBottom: '6px',
            }}>
              <input
                type="text"
                value={manualInputValue}
                onChange={(e) => setManualInputValue(e.target.value)}
                onKeyDown={(e) => { if (e.key === 'Enter') addManual(); }}
                placeholder="请输入姓名"
                autoFocus
                style={{
                  flex: 1,
                  padding: '10px 12px',
                  background: 'var(--card-bg)',
                  border: '1px solid var(--border)',
                  borderRadius: '8px',
                  color: 'var(--text-primary)',
                  fontSize: '14px',
                  outline: 'none',
                  minWidth: 0,
                }}
              />
              <button
                onClick={addManual}
                style={{
                  padding: '10px 16px',
                  background: manualInputValue.trim() ? '#4CAF50' : 'var(--card-bg)',
                  border: 'none',
                  borderRadius: '8px',
                  color: manualInputValue.trim() ? '#fff' : 'var(--text-muted)',
                  fontSize: '13px',
                  fontWeight: 600,
                  cursor: manualInputValue.trim() ? 'pointer' : 'default',
                  flexShrink: 0,
                }}
              >
                添加
              </button>
              <button
                onClick={() => { setShowManualInput(false); setManualInputValue(''); }}
                style={{
                  padding: '10px 12px',
                  background: 'transparent',
                  border: '1px solid var(--border)',
                  borderRadius: '8px',
                  color: 'var(--text-muted)',
                  fontSize: '13px',
                  cursor: 'pointer',
                  flexShrink: 0,
                }}
              >
                取消
              </button>
            </div>
          )}
        </div>

        <div style={{
          display: 'flex', gap: '10px', marginTop: '12px', flexShrink: 0,
        }}>
          <button
            onClick={onClose}
            className="btn btn-ghost"
            style={{ flex: 1 }}
          >
            取消
          </button>
          <button
            onClick={handleConfirm}
            className="btn btn-primary"
            style={{ flex: 2 }}
            disabled={totalSelected === 0}
          >
            确认选择 ({totalSelected})
          </button>
        </div>
      </div>
    </div>
  );
}

window.LockoutForm = LockoutForm;
