Files
martial-master/docs/DISPATCH_TAB_IMPLEMENTATION.md
宅房 1ca0f6a7f6
All checks were successful
continuous-integration/drone/push Build is passing
fix bugs
2025-12-12 13:49:00 +08:00

7.8 KiB
Raw Blame History

调度Tab实现完成

实现概述

调度功能已成功集成到编排页面中用户可以在完成编排后使用调度Tab来调整参赛者的出场顺序。


📦 实现内容

1. 前端页面修改

文件: martial-web/src/views/martial/schedule/index.vue

新增内容:

  1. 调度Tab按钮 (第41-48行)

    • 只有在编排完成后才可用 (:disabled="!isScheduleCompleted")
    • 点击时调用 handleSwitchToDispatch 方法
  2. 调度Tab内容 (第185-267行)

    • 场地选择器
    • 时间段选择器
    • 分组列表展示
    • 参赛者表格(包含上移/下移按钮)
    • 保存/取消按钮
  3. 数据属性 (第403-406行)

    dispatchGroups: [],        // 调度分组列表
    hasDispatchChanges: false, // 是否有未保存的更改
    originalDispatchData: null // 原始调度数据(用于取消时恢复)
    
  4. 调度方法 (第893-1063行)

    • handleSwitchToDispatch() - 切换到调度Tab
    • handleSelectVenue(venueId) - 选择场地
    • handleSelectTime(timeIndex) - 选择时间段
    • loadDispatchData() - 加载调度数据
    • handleDispatchMoveUp(group, index) - 上移参赛者
    • handleDispatchMoveDown(group, index) - 下移参赛者
    • updatePerformanceOrder(group) - 更新出场顺序
    • handleSaveDispatch() - 保存调度
    • handleCancelDispatch() - 取消调度
  5. 样式 (第1268-1314行)

    • .dispatch-container - 调度容器样式
    • .dispatch-group - 调度分组样式
    • .dispatch-footer - 底部按钮样式

2. API导入

文件: martial-web/src/api/martial/activitySchedule.js

已导入的API函数

  • getDispatchData - 获取调度数据
  • saveDispatch - 批量保存调度

🎯 功能特性

1. 权限控制

  • 调度Tab只有在编排完成后才可用
  • 编排完成前调度Tab按钮禁用并显示灰色

2. 数据加载

  • 切换到调度Tab时自动加载数据
  • 切换场地或时间段时重新加载对应数据
  • 保存成功后重新加载数据确保同步

3. 顺序调整

  • 上移按钮:将参赛者向上移动一位
  • 下移按钮:将参赛者向下移动一位
  • 第一个参赛者的上移按钮自动禁用
  • 最后一个参赛者的下移按钮自动禁用
  • 每次移动后自动更新 performanceOrder 字段

4. 数据保存

  • 只有有更改时才允许保存(保存按钮启用)
  • 批量保存所有调整到后端
  • 保存成功后显示提示并重新加载数据

5. 取消操作

  • 有未保存更改时,取消需要确认
  • 确认后恢复到原始数据
  • 无更改时直接切换回竞赛分组Tab

6. 用户体验

  • 操作成功后显示提示消息
  • 按钮状态正确(禁用/启用)
  • 使用图标按钮,操作直观
  • 数据加载时显示loading状态

🔌 后端接口

1. 获取调度数据

  • URL: GET /api/blade-martial/schedule/dispatch-data
  • 参数:
    • competitionId: 赛事ID
    • venueId: 场地ID
    • timeSlotIndex: 时间段索引
  • 返回: 调度数据(分组和参赛者列表)

2. 批量保存调度

  • URL: POST /api/blade-martial/schedule/save-dispatch
  • 参数:
    {
      "competitionId": 1,
      "adjustments": [
        {
          "detailId": 101,
          "participants": [
            {"id": 1001, "performanceOrder": 1},
            {"id": 1002, "performanceOrder": 2}
          ]
        }
      ]
    }
    
  • 返回: 保存结果

📊 数据流程

1. 用户完成编排
   ↓
2. 点击"调度"Tab
   ↓
3. 检查编排是否完成 (isScheduleCompleted)
   ↓
4. 加载调度数据 (loadDispatchData)
   ↓
5. 显示分组和参赛者列表
   ↓
6. 用户点击上移/下移按钮
   ↓
7. 交换数组位置
   ↓
8. 更新 performanceOrder
   ↓
9. 标记 hasDispatchChanges = true
   ↓
10. 用户点击"保存调度"
    ↓
11. 调用 saveDispatch API
    ↓
12. 后端批量更新数据库
    ↓
13. 返回成功
    ↓
14. 重新加载数据
    ↓
15. 显示成功提示

🧪 测试步骤

1. 完成编排

  1. 进入编排页面
  2. 点击"自动编排"按钮
  3. 点击"完成编排"按钮
  4. 确认编排已锁定

2. 进入调度模式

  1. 点击"调度"Tab应该可用
  2. 选择一个场地
  3. 选择一个时间段
  4. 查看分组和参赛者列表

3. 调整顺序

  1. 找到一个分组
  2. 点击某个参赛者的"上移"按钮
  3. 观察顺序变化和成功提示
  4. 点击"下移"按钮
  5. 观察顺序变化和成功提示
  6. 验证第一个不能上移(按钮禁用)
  7. 验证最后一个不能下移(按钮禁用)

4. 保存调度

  1. 进行一些调整
  2. 观察"保存调度"按钮变为可用
  3. 点击"保存调度"按钮
  4. 等待保存成功提示
  5. 刷新页面
  6. 验证顺序是否保持

5. 取消操作

  1. 进行一些调整
  2. 点击"取消"按钮
  3. 确认弹出提示
  4. 点击"确定"
  5. 验证数据恢复到原始状态

⚠️ 注意事项

1. 权限控制

  • 调度Tab只有在 isScheduleCompleted === true 时才可用
  • 编排完成后编排Tab和场地Tab会被禁用

2. 数据一致性

  • 每次切换场地或时间段都重新加载数据
  • 保存前检查是否有未保存的更改
  • 使用深拷贝保存原始数据,避免引用问题

3. 用户体验

  • 有未保存更改时,取消操作需要确认
  • 第一个不能上移,最后一个不能下移
  • 保存成功后显示提示并刷新数据
  • 操作按钮使用图标,更加直观

4. 性能优化

  • 使用深拷贝保存原始数据
  • 只在有更改时才允许保存
  • 批量更新数据库而非逐条更新

📝 代码关键点

1. Tab切换逻辑

<el-button
  size="small"
  :type="activeTab === 'dispatch' ? 'primary' : ''"
  @click="handleSwitchToDispatch"
  :disabled="!isScheduleCompleted">
  调度
</el-button>

2. 上移/下移按钮

<el-button
  type="text"
  size="small"
  :disabled="$index === 0"
  @click="handleDispatchMoveUp(group, $index)">
  <img src="/img/图标 3@3x.png" class="move-icon" alt="上移" />
</el-button>

3. 数据交换逻辑

handleDispatchMoveUp(group, index) {
  if (index === 0) return
  const participants = group.participants
  // 交换位置
  const temp = participants[index]
  participants[index] = participants[index - 1]
  participants[index - 1] = temp
  // 更新顺序号
  this.updatePerformanceOrder(group)
  this.hasDispatchChanges = true
}

4. 保存调度逻辑

async handleSaveDispatch() {
  const adjustments = this.dispatchGroups.map(group => ({
    detailId: group.detailId,
    participants: group.participants.map(p => ({
      id: p.id,
      performanceOrder: p.performanceOrder
    }))
  }))

  const res = await saveDispatch({
    competitionId: this.competitionId,
    adjustments
  })

  if (res.data.success) {
    this.$message.success('调度保存成功')
    await this.loadDispatchData()
  }
}

🎉 总结

调度Tab已成功集成到编排页面中实现了以下功能

  1. Tab切换: 编排完成后可切换到调度Tab
  2. 数据加载: 根据场地和时间段加载调度数据
  3. 顺序调整: 支持上移/下移参赛者
  4. 数据保存: 批量保存调度调整到后端
  5. 取消操作: 支持取消未保存的更改
  6. 用户体验: 清晰的操作反馈和按钮状态控制

现在可以开始测试调度功能了!🚀


📞 相关文档