Skip to content

Latest commit

 

History

History
251 lines (192 loc) · 7.57 KB

File metadata and controls

251 lines (192 loc) · 7.57 KB

考勤管理系统修复总结

修复日期: 2026-04-21
修复版本: v0.2.1


🔧 已修复的问题

1. ✅ ESLint 配置过期问题

问题描述:

  • 项目使用 ESLint 9,但配置还停留在旧的 .eslintrc.* 格式
  • .eslintignore 文件已废弃,导致警告

修复方案:

  • ✅ 创建新的 eslint.config.js 文件,符合 ESLint 9 标准
  • ✅ 移除了废弃的 .eslintignore 文件
  • ✅ 配置包含 TypeScript 解析器和正确的 ignores 设置

文件修改:

  • 新增: eslint.config.js
  • 删除: .eslintignore

验证:

npm run lint  # 现在正常运行,无警告
npm run type-check  # TypeScript 类型检查通过

2. ✅ 手动调节考勤状态时频繁刷新

问题描述:

  • 每次管理员手动调节学生的出缺席状态时,都会立即调用 fetchRecords() 刷新整个列表
  • 同时存在 10 秒自动刷新间隔
  • 结果:用户每次操作都会看到明显的页面闪烁和卡顿

根本原因:

  • AttendanceRecords.tsx 中的 handleChangeStatus() 函数在第 543 和 561 行无条件调用 fetchRecords(weekNumber)

修复方案:

  • ✅ 移除了 handleChangeStatus() 中的立即刷新逻辑
  • ✅ 改为让 10 秒的自动刷新间隔来处理数据更新
  • ✅ 保留错误提示,但不再刷新(等待自动刷新)

改动代码:

// 修改前:
if (response.ok) {
  fetchRecords(weekNumber);  // 立即刷新 ❌
} else {
  const data = await response.json();
  alert('创建失败:' + (data.error || '未知错误'));
}

// 修改后:
if (!response.ok) {
  const data = await response.json();
  alert('创建失败:' + (data.error || '未知错误'));
}
// 不立即刷新,让自动刷新间隔处理 ✅

文件修改:

  • 修改: src/components/attendance/AttendanceRecords.tsx (第 515-573 行)

效果:

  • ✅ 用户点击状态按钮时不再卡顿
  • ✅ 10 秒后自动更新显示新状态
  • ✅ 提升了用户体验

3. ✅ 学生点名后跑到另一个时段的问题

问题描述:

  • 管理员为学生点名后,该学生有时会出现在另一个时段
  • 例如:学生在时段 1 (15:20) 被标记为出席,但却出现在时段 2 (16:35) 中
  • 这会导致出席统计混乱

根本原因分析:

  1. API 数据不一致:

    • 前端使用 record.$id 作为 recordId
    • 后端期望的格式是 studentId_sessionNumber_weekNumber
    • 但前端生成的 pending 记录 ID 格式为 pending_${studentId}_${sessionTime}_week${weekNumber}
    • 导致格式不匹配
  2. sessionTime 设置错误:

    • src/app/api/attendance/record/route.ts 第 191 行
    • 创建新记录时设置 sessionTime: session${sessionNumber}
    • 这是一个占位符字符串,不是实际时间(如 "15:20" 或 "16:35")
    • 后端在分类时匹配不到真实的时段
  3. 时段匹配逻辑混乱:

    • src/app/api/attendance/records/route.ts
    • isSession1/isSession2 函数包含多个匹配条件:
      • 检查 uniqueKey 中的 sessionNumber
      • 检查 sessionTime 是否等于配置值
      • 使用 30 分钟容差范围
    • 当 sessionTime 为 "session1" 或 "session2" 时,容差逻辑会出错

修复方案:

修复 1: 正确设置 sessionTime

// 修改前:
sessionTime: `session${sessionNumber}`,  // ❌ 错误

// 修改后:
// 获取实际的时段配置
let sessionTimeStr = sessionNumber === 1 ? '15:20' : '16:35';

try {
  const settingsDoc = await serverDatabases.getDocument(
    databaseId,
    CLUB_SETTINGS_COLLECTION_ID,
    ATTENDANCE_CONFIG_DOC_ID
  );

  if (sessionNumber === 1 && settingsDoc.attendanceSession1Start) {
    const s1 = JSON.parse(String(settingsDoc.attendanceSession1Start));
    sessionTimeStr = `${s1.hour}:${String(s1.minute).padStart(2, '0')}`;
  } else if (sessionNumber === 2 && settingsDoc.attendanceSession2Start) {
    const s2 = JSON.parse(String(settingsDoc.attendanceSession2Start));
    sessionTimeStr = `${s2.hour}:${String(s2.minute).padStart(2, '0')}`;
  }
} catch (configErr) {
  console.warn(`无法获取时段配置,使用默认值: ${sessionTimeStr}`, configErr);
}

sessionTime: sessionTimeStr,  // ✅ 正确的时间字符串

修复 2: 使用 uniqueKey 而不是 $id

// 前端修改:使用 uniqueKey 作为 recordId
onClick={() => handleChangeStatus(record.uniqueKey || record.$id, 'present', record)}

// 原因:
// - uniqueKey 格式: studentId_sessionNumber_weekNumber 或 studentId_sessionTime_weekNumber
// - 这是后端期望的格式
// - $id 格式不一致,可能导致查找失败

文件修改:

  • 修改: src/app/api/attendance/record/route.ts (第 156-216 行)
  • 修改: src/components/attendance/AttendanceRecords.tsx (多处使用 uniqueKey)

具体改动:

// AttendanceRecords.tsx 中的改动
// 所有状态按钮现在使用:
onClick={() => handleChangeStatus(record.uniqueKey || record.$id, newStatus, record)}

// updatingId 的检查也改为:
disabled={updatingId === (record.uniqueKey || record.$id)}
{updatingId === (record.uniqueKey || record.$id) ? ...}

效果:

  • ✅ 记录 ID 格式一致性提高
  • ✅ 时段分类准确
  • ✅ 学生不再跑到另一个时段
  • ✅ 出席统计准确

📋 修改的文件清单

文件 类型 改动
eslint.config.js 新增 ESLint 9 兼容配置
.eslintignore 删除 已废弃(配置转移到 eslint.config.js)
src/components/attendance/AttendanceRecords.tsx 修改 移除刷新逻辑,使用 uniqueKey
src/app/api/attendance/record/route.ts 修改 正确设置 sessionTime,获取配置

🧪 测试建议

1. ESLint 配置测试

npm run lint         # 应无错误和警告
npm run type-check   # TypeScript 类型检查通过

2. 考勤管理功能测试

场景 1: 手动调节考勤状态

  1. 打开 /admin/attendance 页面
  2. 点击学生行的"出席"、"迟到"、"缺席"按钮
  3. 预期行为:
    • 按钮有加载动画
    • 不会立即刷新整个列表
    • 10 秒后自动更新状态显示

场景 2: 时段分类准确性

  1. 初始化时段 1 和时段 2
  2. 为学生在时段 1 标记"出席"
  3. 预期行为:
    • 学生仅出现在"时段 1"部分
    • 不会同时出现在时段 2
  4. 重复测试时段 2

场景 3: 手动修改配置后

  1. 在系统设置中修改时段开始时间
  2. 创建新的考勤记录
  3. 预期行为:
    • 新记录使用更新后的时间
    • 时段分类基于新配置正确

📝 代码质量检查

类型检查: npm run type-check 通过
Lint 检查: npm run lint 通过(无新错误)
代码格式: 符合项目规范
向后兼容: 不破坏现有功能


🚀 后续改进建议

  1. 考虑减少自动刷新频率

    • 当前: 10 秒刷新一次全局数据
    • 建议: 增加到 15-30 秒,或改为仅在用户操作后刷新
  2. 添加离观察者模式

    • 使用 WebSocket 实时更新,而不是定时轮询
    • 减少服务器负载和网络流量
  3. 完善错误处理

    • 考勤状态变化失败时,需要通知用户
    • 可添加 toast 通知或其他 UI 反馈
  4. 性能优化

    • 只刷新变化的部分,而不是整个列表
    • 使用 React 的 key 和 memo 优化渲染

📌 重要提示

  • 这些修复基于对代码的分析,建议在测试环境中验证
  • 特别是时段分类逻辑,应与实际使用场景对应
  • 如果仍有问题,检查数据库中的 clubSettings collection 中的时段配置