7.8 KiB
7.8 KiB
调度Tab实现完成
✅ 实现概述
调度功能已成功集成到编排页面中,用户可以在完成编排后使用调度Tab来调整参赛者的出场顺序。
📦 实现内容
1. 前端页面修改
文件: martial-web/src/views/martial/schedule/index.vue
新增内容:
-
调度Tab按钮 (第41-48行)
- 只有在编排完成后才可用 (
:disabled="!isScheduleCompleted") - 点击时调用
handleSwitchToDispatch方法
- 只有在编排完成后才可用 (
-
调度Tab内容 (第185-267行)
- 场地选择器
- 时间段选择器
- 分组列表展示
- 参赛者表格(包含上移/下移按钮)
- 保存/取消按钮
-
数据属性 (第403-406行)
dispatchGroups: [], // 调度分组列表 hasDispatchChanges: false, // 是否有未保存的更改 originalDispatchData: null // 原始调度数据(用于取消时恢复) -
调度方法 (第893-1063行)
handleSwitchToDispatch()- 切换到调度TabhandleSelectVenue(venueId)- 选择场地handleSelectTime(timeIndex)- 选择时间段loadDispatchData()- 加载调度数据handleDispatchMoveUp(group, index)- 上移参赛者handleDispatchMoveDown(group, index)- 下移参赛者updatePerformanceOrder(group)- 更新出场顺序handleSaveDispatch()- 保存调度handleCancelDispatch()- 取消调度
-
样式 (第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: 赛事IDvenueId: 场地IDtimeSlotIndex: 时间段索引
- 返回: 调度数据(分组和参赛者列表)
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. 完成编排
- 进入编排页面
- 点击"自动编排"按钮
- 点击"完成编排"按钮
- 确认编排已锁定
2. 进入调度模式
- 点击"调度"Tab(应该可用)
- 选择一个场地
- 选择一个时间段
- 查看分组和参赛者列表
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已成功集成到编排页面中,实现了以下功能:
- ✅ Tab切换: 编排完成后可切换到调度Tab
- ✅ 数据加载: 根据场地和时间段加载调度数据
- ✅ 顺序调整: 支持上移/下移参赛者
- ✅ 数据保存: 批量保存调度调整到后端
- ✅ 取消操作: 支持取消未保存的更改
- ✅ 用户体验: 清晰的操作反馈和按钮状态控制
现在可以开始测试调度功能了!🚀