314 lines
7.8 KiB
Markdown
314 lines
7.8 KiB
Markdown
# 调度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行)
|
||
```javascript
|
||
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`
|
||
- **参数**:
|
||
```json
|
||
{
|
||
"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切换逻辑
|
||
```vue
|
||
<el-button
|
||
size="small"
|
||
:type="activeTab === 'dispatch' ? 'primary' : ''"
|
||
@click="handleSwitchToDispatch"
|
||
:disabled="!isScheduleCompleted">
|
||
调度
|
||
</el-button>
|
||
```
|
||
|
||
### 2. 上移/下移按钮
|
||
```vue
|
||
<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. 数据交换逻辑
|
||
```javascript
|
||
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. 保存调度逻辑
|
||
```javascript
|
||
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. ✅ **用户体验**: 清晰的操作反馈和按钮状态控制
|
||
|
||
现在可以开始测试调度功能了!🚀
|
||
|
||
---
|
||
|
||
## 📞 相关文档
|
||
|
||
- [调度功能实现文档](./schedule-dispatch-implementation.md)
|
||
- [调度功能总结](./DISPATCH_FEATURE_SUMMARY.md)
|
||
- [后端Controller](../src/main/java/org/springblade/modules/martial/controller/MartialScheduleArrangeController.java)
|
||
- [前端API](../../martial-web/src/api/martial/activitySchedule.js)
|
||
- [前端页面](../../martial-web/src/views/martial/schedule/index.vue)
|