# 调度功能重构总结 ## ✅ 重构完成 根据您的要求,已成功将调度功能从编排页面的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 调度 ``` ```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. ✅ **用户体验**:清晰的按钮状态和操作提示 现在可以开始测试新的调度流程了!🚀