@@ -0,0 +1,332 @@
|
||||
# 调度功能重构总结
|
||||
|
||||
## ✅ 重构完成
|
||||
|
||||
根据您的要求,已成功将调度功能从编排页面的Tab移动到独立的调度页面,并添加了编排完成状态检查。
|
||||
|
||||
---
|
||||
|
||||
## 📦 修改内容
|
||||
|
||||
### 1. 编排页面 ([schedule/index.vue](../../martial-web/src/views/martial/schedule/index.vue))
|
||||
|
||||
#### 移除的内容:
|
||||
- ❌ 调度Tab按钮(第41-48行已删除)
|
||||
- ❌ 调度Tab内容区域(第177-259行已删除)
|
||||
- ❌ 调度相关数据属性(`dispatchGroups`, `hasDispatchChanges`, `originalDispatchData`)
|
||||
- ❌ 调度相关方法(`handleSwitchToDispatch`, `loadDispatchData`, `handleDispatchMoveUp`, `handleDispatchMoveDown`, `updatePerformanceOrder`, `handleSaveDispatch`, `handleCancelDispatch`)
|
||||
- ❌ 调度相关样式(`.dispatch-container`, `.dispatch-group`, `.dispatch-footer`)
|
||||
- ❌ 调度相关API导入(`getDispatchData`, `saveDispatch`)
|
||||
|
||||
#### 修复的内容:
|
||||
- ✅ 修复`confirmComplete`方法,正确调用`saveAndLockSchedule`接口
|
||||
- ✅ 完成编排后重新加载数据以获取最新状态
|
||||
|
||||
**关键代码**:
|
||||
```javascript
|
||||
// 修复后的完成编排逻辑
|
||||
await saveDraftSchedule(saveData)
|
||||
const lockRes = await saveAndLockSchedule(this.competitionId)
|
||||
this.isScheduleCompleted = true
|
||||
await this.loadScheduleData() // 重新加载数据
|
||||
```
|
||||
|
||||
### 2. 订单管理页面 ([order/index.vue](../../martial-web/src/views/martial/order/index.vue))
|
||||
|
||||
#### 新增的内容:
|
||||
- ✅ 导入`getScheduleResult` API
|
||||
- ✅ 添加`scheduleStatusMap`数据属性,存储每个赛事的编排状态
|
||||
- ✅ 添加`loadScheduleStatus()`方法,加载所有赛事的编排状态
|
||||
- ✅ 添加`isScheduleCompleted(competitionId)`方法,检查编排是否完成
|
||||
- ✅ 修改`handleDispatch`方法,添加编排完成检查
|
||||
- ✅ 调度按钮添加`:disabled`属性和`:title`提示
|
||||
|
||||
**关键代码**:
|
||||
```vue
|
||||
<!-- 调度按钮 -->
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleDispatch(scope.row)"
|
||||
:disabled="!isScheduleCompleted(scope.row.id)"
|
||||
:title="isScheduleCompleted(scope.row.id) ? '进入调度' : '请先完成编排'"
|
||||
>
|
||||
调度
|
||||
</el-button>
|
||||
```
|
||||
|
||||
```javascript
|
||||
// 检查编排是否完成
|
||||
handleDispatch(row) {
|
||||
if (!this.isScheduleCompleted(row.id)) {
|
||||
this.$message.warning('请先完成编排后再进行调度')
|
||||
return
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/martial/dispatch/list',
|
||||
query: { competitionId: row.id }
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 调度页面 ([dispatch/index.vue](../../martial-web/src/views/martial/dispatch/index.vue))
|
||||
|
||||
#### 更新的内容:
|
||||
- ✅ 导入后端API(`getVenuesByCompetition`, `getCompetitionDetail`, `getDispatchData`, `saveDispatch`)
|
||||
- ✅ 移除静态数据,改为从后端加载
|
||||
- ✅ 添加`loadCompetitionInfo()`方法,加载赛事信息并生成时间段
|
||||
- ✅ 添加`loadVenues()`方法,加载场地列表
|
||||
- ✅ 添加`loadDispatchData()`方法,根据场地和时间段加载调度数据
|
||||
- ✅ 添加`handleSaveDispatch()`方法,保存调度调整
|
||||
- ✅ 更新`handleMoveUp`和`handleMoveDown`方法,添加`performanceOrder`更新逻辑
|
||||
- ✅ 添加场地选择器UI
|
||||
- ✅ 添加保存按钮UI
|
||||
- ✅ 添加`hasChanges`状态跟踪
|
||||
|
||||
**关键代码**:
|
||||
```javascript
|
||||
// 加载调度数据
|
||||
async loadDispatchData() {
|
||||
const res = await getDispatchData({
|
||||
competitionId: this.competitionId,
|
||||
venueId: this.selectedVenueId,
|
||||
timeSlotIndex: this.selectedTime
|
||||
})
|
||||
|
||||
if (res.data.success) {
|
||||
const groups = res.data.data.groups || []
|
||||
this.dispatchGroups = groups.map(group => ({
|
||||
...group,
|
||||
viewMode: 'dispatch',
|
||||
title: group.groupName,
|
||||
items: group.participants.map(p => ({
|
||||
...p,
|
||||
schoolUnit: p.organization,
|
||||
completed: false,
|
||||
refereed: false
|
||||
}))
|
||||
}))
|
||||
this.originalData = JSON.parse(JSON.stringify(this.dispatchGroups))
|
||||
this.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
// 保存调度
|
||||
async handleSaveDispatch() {
|
||||
const adjustments = this.dispatchGroups.map(group => ({
|
||||
detailId: group.detailId,
|
||||
participants: group.items.map(p => ({
|
||||
id: p.id,
|
||||
performanceOrder: p.performanceOrder
|
||||
}))
|
||||
}))
|
||||
|
||||
const res = await saveDispatch({
|
||||
competitionId: this.competitionId,
|
||||
adjustments
|
||||
})
|
||||
|
||||
if (res.data.success) {
|
||||
this.$message.success('调度保存成功')
|
||||
this.hasChanges = false
|
||||
await this.loadDispatchData()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 功能流程
|
||||
|
||||
### 1. 编排流程
|
||||
```
|
||||
订单管理页面
|
||||
↓
|
||||
点击"编排"按钮
|
||||
↓
|
||||
进入编排页面
|
||||
↓
|
||||
点击"自动编排"
|
||||
↓
|
||||
调整分组和参赛者
|
||||
↓
|
||||
点击"完成编排"
|
||||
↓
|
||||
保存草稿 → 锁定编排 → 更新状态
|
||||
↓
|
||||
编排完成(isScheduleCompleted = true)
|
||||
```
|
||||
|
||||
### 2. 调度流程
|
||||
```
|
||||
订单管理页面
|
||||
↓
|
||||
检查编排是否完成
|
||||
↓
|
||||
如果未完成:调度按钮禁用,显示提示
|
||||
如果已完成:调度按钮可用
|
||||
↓
|
||||
点击"调度"按钮
|
||||
↓
|
||||
进入调度页面
|
||||
↓
|
||||
选择场地和时间段
|
||||
↓
|
||||
加载调度数据
|
||||
↓
|
||||
调整参赛者顺序(上移/下移)
|
||||
↓
|
||||
点击"保存调度"
|
||||
↓
|
||||
批量更新数据库
|
||||
↓
|
||||
调度完成
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 后端接口
|
||||
|
||||
### 1. 编排相关接口
|
||||
| 接口 | 方法 | 路径 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 获取编排结果 | GET | `/api/blade-martial/schedule/result` | 获取编排数据和状态 |
|
||||
| 保存草稿 | POST | `/api/blade-martial/schedule/save-draft` | 保存编排草稿 |
|
||||
| 完成编排 | POST | `/api/blade-martial/schedule/save-and-lock` | 锁定编排 |
|
||||
|
||||
### 2. 调度相关接口
|
||||
| 接口 | 方法 | 路径 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 获取调度数据 | GET | `/api/blade-martial/schedule/dispatch-data` | 获取指定场地和时间段的调度数据 |
|
||||
| 批量保存调度 | POST | `/api/blade-martial/schedule/save-dispatch` | 批量保存调度调整 |
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心特性
|
||||
|
||||
### 1. 权限控制
|
||||
- ✅ 调度功能独立于编排页面
|
||||
- ✅ 只有编排完成后才能进入调度页面
|
||||
- ✅ 订单管理页面实时检查编排状态
|
||||
- ✅ 调度按钮根据状态自动禁用/启用
|
||||
|
||||
### 2. 数据流转
|
||||
- ✅ 编排完成后,状态保存到数据库
|
||||
- ✅ 订单管理页面加载时检查所有赛事的编排状态
|
||||
- ✅ 调度页面从后端加载真实数据
|
||||
- ✅ 调度调整保存到数据库
|
||||
|
||||
### 3. 用户体验
|
||||
- ✅ 调度按钮有明确的禁用状态和提示
|
||||
- ✅ 未完成编排时点击调度按钮会显示警告
|
||||
- ✅ 调度页面有场地和时间段选择器
|
||||
- ✅ 调度页面有保存按钮,只有有更改时才可用
|
||||
- ✅ 操作成功后显示提示消息
|
||||
|
||||
### 4. 数据一致性
|
||||
- ✅ 编排完成后重新加载数据确保状态同步
|
||||
- ✅ 调度保存后重新加载数据确保数据一致
|
||||
- ✅ 使用深拷贝保存原始数据
|
||||
- ✅ 批量更新数据库而非逐条更新
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试步骤
|
||||
|
||||
### 1. 测试编排完成
|
||||
1. 进入订单管理页面
|
||||
2. 点击某个赛事的"编排"按钮
|
||||
3. 点击"自动编排"
|
||||
4. 点击"完成编排"
|
||||
5. 确认编排已锁定
|
||||
6. 返回订单管理页面
|
||||
7. **验证**:该赛事的"调度"按钮应该可用
|
||||
|
||||
### 2. 测试调度按钮禁用
|
||||
1. 进入订单管理页面
|
||||
2. 找到一个未完成编排的赛事
|
||||
3. **验证**:该赛事的"调度"按钮应该禁用
|
||||
4. 鼠标悬停在调度按钮上
|
||||
5. **验证**:应该显示"请先完成编排"提示
|
||||
6. 点击调度按钮
|
||||
7. **验证**:应该显示警告消息
|
||||
|
||||
### 3. 测试调度功能
|
||||
1. 进入订单管理页面
|
||||
2. 点击已完成编排的赛事的"调度"按钮
|
||||
3. 进入调度页面
|
||||
4. 选择一个场地
|
||||
5. 选择一个时间段
|
||||
6. **验证**:应该显示该场地和时间段的分组和参赛者
|
||||
7. 点击某个参赛者的"上移"按钮
|
||||
8. **验证**:参赛者顺序应该改变
|
||||
9. 点击"保存调度"按钮
|
||||
10. **验证**:应该显示"调度保存成功"提示
|
||||
11. 刷新页面
|
||||
12. **验证**:顺序应该保持
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 编排状态检查
|
||||
- 订单管理页面加载时会检查所有赛事的编排状态
|
||||
- 这可能会产生多个API请求,建议后端优化为批量查询
|
||||
|
||||
### 2. 数据格式
|
||||
- 调度页面期望后端返回的数据格式:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"groups": [
|
||||
{
|
||||
"groupId": 1,
|
||||
"groupName": "男子A组 长拳",
|
||||
"detailId": 101,
|
||||
"participants": [
|
||||
{
|
||||
"id": 1001,
|
||||
"organization": "北京体育大学",
|
||||
"playerName": "张三",
|
||||
"projectName": "长拳",
|
||||
"performanceOrder": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 路由参数
|
||||
- 编排页面:`/martial/schedule/list?competitionId=xxx`
|
||||
- 调度页面:`/martial/dispatch/list?competitionId=xxx`
|
||||
|
||||
---
|
||||
|
||||
## 📝 文件清单
|
||||
|
||||
### 修改的文件
|
||||
1. [martial-web/src/views/martial/schedule/index.vue](../../martial-web/src/views/martial/schedule/index.vue) - 编排页面
|
||||
2. [martial-web/src/views/martial/order/index.vue](../../martial-web/src/views/martial/order/index.vue) - 订单管理页面
|
||||
3. [martial-web/src/views/martial/dispatch/index.vue](../../martial-web/src/views/martial/dispatch/index.vue) - 调度页面
|
||||
|
||||
### 相关文档
|
||||
1. [DISPATCH_FEATURE_SUMMARY.md](./DISPATCH_FEATURE_SUMMARY.md) - 调度功能实现总结
|
||||
2. [schedule-dispatch-implementation.md](./schedule-dispatch-implementation.md) - 调度功能实现文档
|
||||
3. [DISPATCH_TAB_IMPLEMENTATION.md](./DISPATCH_TAB_IMPLEMENTATION.md) - 调度Tab实现文档(已过时)
|
||||
|
||||
---
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
调度功能已成功重构,主要改进:
|
||||
|
||||
1. ✅ **独立页面**:调度功能从编排页面的Tab移动到独立页面
|
||||
2. ✅ **权限控制**:只有编排完成后才能进入调度页面
|
||||
3. ✅ **状态检查**:订单管理页面实时检查编排状态
|
||||
4. ✅ **后端集成**:调度页面从后端加载真实数据
|
||||
5. ✅ **用户体验**:清晰的按钮状态和操作提示
|
||||
|
||||
现在可以开始测试新的调度流程了!🚀
|
||||
Reference in New Issue
Block a user