diff --git a/README.md b/README.md index 45ae28d..d845c29 100644 --- a/README.md +++ b/README.md @@ -61,19 +61,13 @@ docker compose ps ### 快速构建(开发迭代) -如果已经手动编译过 JAR,可以使用快速构建: - ```bash -# 先编译 martial-tool(首次) -cd ../martial-tool && mvn clean install -DskipTests - -# 编译 martial-master -cd ../martial-master && mvn clean package -DskipTests - -# 使用快速构建 Dockerfile -docker compose build martial-api --build-arg DOCKERFILE=Dockerfile.quick +# 本地编译后构建镜像 +mvn clean package -DskipTests && docker-compose up --build ``` +> 详细的 Docker 部署说明请参考 [Docker 部署指南](docs/guides/docker-deployment.md) + ## 项目结构 ``` diff --git a/docker-compose.yml b/docker-compose.yml index 3f5fa12..1f04b1f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,11 +82,11 @@ services: networks: - martial-network - # 后端应用(完整构建模式) + # 后端应用(快速构建模式) martial-api: build: context: . - dockerfile: Dockerfile + dockerfile: Dockerfile.quick container_name: martial-api restart: always environment: diff --git a/docs/DATABASE_STRUCTURE_EVALUATION.md b/docs/DATABASE_STRUCTURE_EVALUATION.md deleted file mode 100644 index 8ba738f..0000000 --- a/docs/DATABASE_STRUCTURE_EVALUATION.md +++ /dev/null @@ -1,454 +0,0 @@ -# Martial 武术比赛评分系统 - 数据库表结构评估报告 - -**评估日期**: 2026-01-18 -**评估人**: Droid (Google Database Engineer) -**数据库**: martial_db (MySQL 8.0) -**评估范围**: 34 个 martial_ 核心业务表 - ---- - -## 📊 执行摘要 - -### 数据库概况 - -| 指标 | 数值 | -|------|------| -| **核心业务表** | 34 个 | -| **系统表** | 40+ 个 (blade_*) | -| **数据库引擎** | InnoDB | -| **字符集** | utf8mb4 | -| **排序规则** | utf8mb4_0900_ai_ci | - -### 评估结论 - -| 评估项 | 评分 | 说明 | -|--------|------|------| -| **表结构设计** | ⭐⭐⭐⭐ (4/5) | 整体设计合理,有改进空间 | -| **索引设计** | ⭐⭐⭐⭐ (4/5) | 核心索引完善,部分可优化 | -| **数据类型** | ⭐⭐⭐⭐⭐ (5/5) | 数据类型选择恰当 | -| **命名规范** | ⭐⭐⭐⭐⭐ (5/5) | 命名清晰一致 | -| **扩展性** | ⭐⭐⭐⭐ (4/5) | 支持多租户,扩展性良好 | - ---- - -## 🗂️ 表结构分析 - -### 核心业务表分类 - -#### 1. 赛事管理 (5 tables) -- `martial_competition` - 赛事信息表 -- `martial_project` - 比赛项目表 -- `martial_venue` - 场地信息表 -- `martial_banner` - 横幅广告表 -- `martial_info_publish` - 信息发布表 - -#### 2. 参赛者管理 (3 tables) -- `martial_athlete` - 参赛选手表 -- `martial_team` - 团队表 -- `martial_team_member` - 团队成员关联表 - -#### 3. 裁判管理 (3 tables) -- `martial_judge` - 裁判信息表 -- `martial_judge_invite` - 裁判邀请表 -- `martial_judge_project` - 裁判项目分配表 - -#### 4. 评分系统 (3 tables) -- `martial_score` - 评分记录表 -- `martial_result` - 成绩表 -- `martial_deduction_item` - 扣分项表 - -#### 5. 赛程编排 (10 tables) -- `martial_schedule` - 赛程编排表 -- `martial_schedule_group` - 赛程编排分组表 -- `martial_schedule_detail` - 赛程编排明细表 -- `martial_schedule_participant` - 赛程编排参赛者关联表 -- `martial_schedule_athlete` - 赛程选手关联表 -- `martial_schedule_plan` - 赛程计划表 -- `martial_schedule_slot` - 时间槽表 -- `martial_schedule_athlete_slot` - 选手时间槽关联表 -- `martial_schedule_conflict` - 赛程冲突表 -- `martial_schedule_adjustment_log` - 赛程调整日志表 -- `martial_schedule_status` - 赛程状态表 - -#### 6. 报名管理 (2 tables) -- `martial_registration_order` - 报名订单表 -- `martial_contact` - 联系人表 - -#### 7. 其他功能 (8 tables) -- `martial_activity_schedule` - 活动日程表 -- `martial_competition_attachment` - 赛事附件表 -- `martial_competition_rules_*` - 竞赛规则相关表 (3 tables) -- `martial_exception_event` - 异常事件表 -- `martial_live_update` - 实时更新表 - ---- - -## ✅ 优点分析 - -### 1. 表结构设计优秀 - -#### 1.1 多租户支持 -```sql --- 所有表都包含租户字段 -tenant_id varchar(12) DEFAULT '000000' - --- 复合索引支持租户隔离 -KEY `idx_tenant_status` (`tenant_id`,`status`) -``` - -**优点**: -- ✅ 支持 SaaS 多租户架构 -- ✅ 数据隔离安全 -- ✅ 便于扩展 - -#### 1.2 软删除机制 -```sql -is_deleted int DEFAULT '0' -``` - -**优点**: -- ✅ 数据可恢复 -- ✅ 审计追踪 -- ✅ 避免误删除 - -#### 1.3 审计字段完整 -```sql -create_user bigint -create_dept bigint -create_time datetime DEFAULT CURRENT_TIMESTAMP -update_user bigint -update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -``` - -**优点**: -- ✅ 完整的审计追踪 -- ✅ 自动时间戳 -- ✅ 支持部门级权限 - -### 2. 索引设计合理 - -#### 2.1 主键索引 -```sql -PRIMARY KEY (`id`) USING BTREE -``` - -**优点**: -- ✅ 使用 bigint 支持大数据量 -- ✅ BTREE 索引性能优秀 - -#### 2.2 唯一索引 -```sql --- martial_competition -UNIQUE KEY `uk_code` (`competition_code`) - --- martial_result -UNIQUE KEY `uk_competition_athlete` (`competition_id`, `athlete_id`, `project_id`) -``` - -**优点**: -- ✅ 防止数据重复 -- ✅ 业务约束清晰 - -#### 2.3 复合索引 -```sql --- martial_competition -KEY `idx_tenant_status` (`tenant_id`,`status`) - --- martial_schedule_detail -KEY `idx_venue_time` (`venue_id`, `schedule_date`, `time_slot`) -``` - -**优点**: -- ✅ 支持多条件查询 -- ✅ 覆盖常用查询场景 - -### 3. 数据类型选择恰当 - -#### 3.1 精确数值类型 -```sql --- 金额使用 decimal -price decimal(10,2) DEFAULT '0.00' -total_amount decimal(10,2) DEFAULT '0.00' - --- 分数使用 decimal(10,3) -score decimal(10,3) NOT NULL -total_score decimal(10,3) -``` - -**优点**: -- ✅ 避免浮点数精度问题 -- ✅ 适合金融和评分场景 - -#### 3.2 文本类型合理 -```sql --- 短文本使用 varchar -player_name varchar(50) -competition_name varchar(200) - --- 长文本使用 text -introduction text -rules text -``` - -**优点**: -- ✅ 节省存储空间 -- ✅ 性能优化 - -#### 3.3 JSON 存储 -```sql -poster_images varchar(1000) COMMENT '宣传图片(JSON数组)' -attachments varchar(1000) COMMENT '附件(JSON数组)' -deduction_items varchar(500) COMMENT '选中的扣分项ID(JSON数组)' -``` - -**优点**: -- ✅ 灵活存储数组数据 -- ✅ 避免额外关联表 - -### 4. 命名规范统一 - -#### 4.1 表名规范 -``` -martial_{业务模块} -例如: martial_competition, martial_athlete, martial_score -``` - -#### 4.2 字段名规范 -``` -- 主键: id -- 外键: {表名}_id (如 competition_id, athlete_id) -- 时间: {动作}_time (如 create_time, score_time) -- 状态: status, {业务}_status -- 标识: is_{属性} (如 is_deleted, is_final) -``` - -**优点**: -- ✅ 命名清晰易懂 -- ✅ 一致性强 -- ✅ 便于维护 - ---- - -## ⚠️ 问题与改进建议 - -### 问题 1: 缺少外键约束 - -#### 现状 -```sql --- martial_athlete 表 -competition_id bigint DEFAULT NULL COMMENT '赛事ID' -project_id bigint DEFAULT NULL COMMENT '项目ID' - --- 没有外键约束 -``` - -#### 问题 -- ❌ 数据完整性无法保证 -- ❌ 可能存在孤儿记录 -- ❌ 级联删除需要应用层处理 - -#### 建议 -```sql --- 添加外键约束 -ALTER TABLE martial_athlete -ADD CONSTRAINT fk_athlete_competition -FOREIGN KEY (competition_id) -REFERENCES martial_competition(id) -ON DELETE RESTRICT ON UPDATE CASCADE; - -ALTER TABLE martial_athlete -ADD CONSTRAINT fk_athlete_project -FOREIGN KEY (project_id) -REFERENCES martial_project(id) -ON DELETE RESTRICT ON UPDATE CASCADE; -``` - -**优先级**: 🟡 中等 -**影响**: 数据完整性 -**工作量**: 2-3 小时 - ---- - -### 问题 2: 部分索引可优化 - -#### 2.1 martial_score 表缺少复合索引 - -**现状**: -```sql -KEY `idx_competition` (`competition_id`) -KEY `idx_athlete` (`athlete_id`) -KEY `idx_judge` (`judge_id`) -``` - -**问题**: -- ❌ 查询 "某赛事某选手的所有评分" 需要两次索引查找 -- ❌ 查询 "某裁判对某选手的评分" 效率不高 - -**建议**: -```sql --- 添加复合索引 -ALTER TABLE martial_score -ADD KEY `idx_competition_athlete` (`competition_id`, `athlete_id`); - -ALTER TABLE martial_score -ADD KEY `idx_athlete_judge` (`athlete_id`, `judge_id`); -``` - -**优先级**: 🟡 中等 -**影响**: 查询性能 -**工作量**: 30 分钟 - -#### 2.2 martial_result 表缺少排名索引 - -**现状**: -```sql -KEY `idx_ranking` (`ranking`) -``` - -**问题**: -- ❌ 查询 "某赛事某项目的排名" 需要全表扫描 - -**建议**: -```sql --- 添加复合索引 -ALTER TABLE martial_result -ADD KEY `idx_competition_project_ranking` (`competition_id`, `project_id`, `ranking`); -``` - -**优先级**: 🟢 低 -**影响**: 查询性能 -**工作量**: 15 分钟 - ---- - -### 问题 3: 赛程编排表结构复杂 - -#### 现状 -赛程编排相关表多达 10 个,关系复杂: -``` -martial_schedule -martial_schedule_group -martial_schedule_detail -martial_schedule_participant -martial_schedule_athlete -martial_schedule_plan -martial_schedule_slot -martial_schedule_athlete_slot -martial_schedule_conflict -martial_schedule_adjustment_log -``` - -#### 问题 -- ❌ 表关系复杂,理解成本高 -- ❌ 查询需要多表 JOIN -- ❌ 数据一致性维护困难 - -#### 建议 - -**方案 1: 简化表结构** (推荐) -```sql --- 合并 martial_schedule 和 martial_schedule_group --- 合并 martial_schedule_athlete 和 martial_schedule_athlete_slot --- 减少到 6-7 个表 -``` - -**方案 2: 添加视图** -```sql --- 创建常用查询视图 -CREATE VIEW v_schedule_full AS -SELECT - sg.id as group_id, - sg.group_name, - sd.venue_name, - sd.schedule_date, - sd.time_slot, - sp.player_name, - sp.performance_order -FROM martial_schedule_group sg -JOIN martial_schedule_detail sd ON sg.id = sd.schedule_group_id -JOIN martial_schedule_participant sp ON sd.id = sp.schedule_detail_id -WHERE sg.is_deleted = 0 - AND sd.is_deleted = 0 - AND sp.is_deleted = 0; -``` - -**优先级**: 🟡 中等 -**影响**: 代码复杂度、维护成本 -**工作量**: 1-2 天 - ---- - -## 📋 优化优先级总结 - -### 高优先级 (立即执行) - -| 优化项 | 优先级 | 预期收益 | 工作量 | -|--------|--------|---------|--------| -| 无 | - | - | - | - -### 中优先级 (1-2 周内) - -| 优化项 | 优先级 | 预期收益 | 工作量 | -|--------|--------|---------|--------| -| 添加外键约束 | 🟡 中 | 数据完整性 | 2-3 小时 | -| 优化 martial_score 索引 | 🟡 中 | 查询性能 20-30% | 30 分钟 | -| 简化赛程编排表结构 | 🟡 中 | 降低复杂度 | 1-2 天 | - -### 低优先级 (长期优化) - -| 优化项 | 优先级 | 预期收益 | 工作量 | -|--------|--------|---------|--------| -| 状态字段改为 ENUM | 🟢 低 | 可读性 | 2-3 小时 | -| 添加分区表 | 🟢 低 | 长期性能 | 1 天 | -| 数据归档策略 | 🟢 低 | 长期性能 | 2-3 小时 | - ---- - -## 🎯 总体评价 - -### 优点 ⭐⭐⭐⭐ (4/5) - -1. ✅ **表结构设计合理**: 业务模型清晰,表关系明确 -2. ✅ **索引设计完善**: 核心查询都有索引支持 -3. ✅ **多租户支持**: 完善的租户隔离机制 -4. ✅ **审计追踪**: 完整的创建/更新记录 -5. ✅ **软删除**: 数据安全可恢复 -6. ✅ **命名规范**: 统一清晰的命名风格 - -### 改进空间 - -1. ⚠️ **缺少外键约束**: 数据完整性依赖应用层 -2. ⚠️ **赛程表结构复杂**: 10 个表关系复杂 -3. ⚠️ **部分索引可优化**: 复合索引覆盖不全 - -### 建议 - -**短期 (1-2 周)**: -1. 添加关键外键约束 -2. 优化 martial_score 表索引 -3. 启用慢查询日志监控 - -**中期 (1-2 月)**: -1. 简化赛程编排表结构 -2. 添加常用查询视图 -3. 实施 Redis 缓存策略 - -**长期 (3-6 月)**: -1. 评估分区表需求 -2. 制定数据归档策略 -3. 优化状态字段类型 - ---- - -## 📚 相关文档 - -- [CODE_PERFORMANCE_ANALYSIS.md](./CODE_PERFORMANCE_ANALYSIS.md) - 后端代码性能分析 -- [PERFORMANCE_OPTIMIZATION_SUMMARY.md](./PERFORMANCE_OPTIMIZATION_SUMMARY.md) - 性能优化总结 -- [DATABASE_PERFORMANCE_ANALYSIS.md](./DATABASE_PERFORMANCE_ANALYSIS.md) - 数据库性能分析 - ---- - -**评估完成时间**: 2026-01-18 -**下次评估建议**: 3 个月后或数据量增长 10 倍时 - -*"Good database design is the foundation of a scalable system." - Database Engineering Best Practices* diff --git a/docs/DISPATCH_FEATURE_SUMMARY.md b/docs/DISPATCH_FEATURE_SUMMARY.md deleted file mode 100644 index bc1ada3..0000000 --- a/docs/DISPATCH_FEATURE_SUMMARY.md +++ /dev/null @@ -1,418 +0,0 @@ -# 🎯 调度功能实现总结 - -## ✅ 功能已全部完成! - -调度功能已经按照设计方案完整实现,包括后端、前端和数据库的所有必要组件。 - ---- - -## 📦 交付清单 - -### 1. 后端代码(已完成) - -#### DTO类(3个) -- ✅ [DispatchDataDTO.java](../src/main/java/org/springblade/modules/martial/pojo/dto/DispatchDataDTO.java) - 调度数据查询DTO -- ✅ [AdjustOrderDTO.java](../src/main/java/org/springblade/modules/martial/pojo/dto/AdjustOrderDTO.java) - 调整顺序DTO -- ✅ [SaveDispatchDTO.java](../src/main/java/org/springblade/modules/martial/pojo/dto/SaveDispatchDTO.java) - 保存调度DTO - -#### VO类(1个) -- ✅ [DispatchDataVO.java](../src/main/java/org/springblade/modules/martial/pojo/vo/DispatchDataVO.java) - 调度数据视图对象 - -#### Service层 -- ✅ [IMartialScheduleService.java](../src/main/java/org/springblade/modules/martial/service/IMartialScheduleService.java) - 添加3个调度方法 -- ✅ [MartialScheduleServiceImpl.java](../src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleServiceImpl.java) - 实现调度逻辑 - -#### Controller层 -- ✅ [MartialScheduleArrangeController.java](../src/main/java/org/springblade/modules/martial/controller/MartialScheduleArrangeController.java) - 添加3个调度接口 - -### 2. 前端代码(已完成) - -#### API接口 -- ✅ [activitySchedule.js](../../martial-web/src/api/martial/activitySchedule.js) - 添加3个调度API - -#### 页面实现 -- ✅ 调度功能集成方案(详见 [schedule-dispatch-implementation.md](./schedule-dispatch-implementation.md)) - -### 3. 数据库脚本(已完成) - -- ✅ [create_dispatch_log_table.sql](../database/martial-db/create_dispatch_log_table.sql) - 调度日志表(可选) - -### 4. 文档(已完成) - -- ✅ [schedule-dispatch-implementation.md](./schedule-dispatch-implementation.md) - 详细实现文档 -- ✅ [DISPATCH_FEATURE_SUMMARY.md](./DISPATCH_FEATURE_SUMMARY.md) - 本文档 - ---- - -## 🔌 后端接口列表 - -| 接口 | 方法 | 路径 | 说明 | -|------|------|------|------| -| 获取调度数据 | GET | `/api/blade-martial/schedule/dispatch-data` | 获取指定场地和时间段的调度数据 | -| 调整出场顺序 | POST | `/api/blade-martial/schedule/adjust-order` | 调整单个参赛者的出场顺序 | -| 批量保存调度 | POST | `/api/blade-martial/schedule/save-dispatch` | 批量保存所有调度调整 | - ---- - -## 💻 核心功能实现 - -### 1. 获取调度数据 - -**Service层实现**(第454-521行): -```java -@Override -public DispatchDataVO getDispatchData(Long competitionId, Long venueId, Integer timeSlotIndex) { - // 1. 查询指定场地和时间段的编排明细 - // 2. 查询每个明细下的所有参赛者 - // 3. 转换为VO并返回 -} -``` - -**关键逻辑**: -- 根据场地ID和时间段索引查询编排明细 -- 关联查询分组信息和参赛者信息 -- 按 `performance_order` 排序 - -### 2. 调整出场顺序 - -**Service层实现**(第523-585行): -```java -@Override -@Transactional(rollbackFor = Exception.class) -public boolean adjustOrder(AdjustOrderDTO dto) { - // 1. 查询当前参赛者 - // 2. 查询同一明细下的所有参赛者 - // 3. 根据动作(move_up/move_down/swap)调整顺序 - // 4. 批量更新所有参赛者的顺序 -} -``` - -**支持的操作**: -- `move_up`: 上移一位 -- `move_down`: 下移一位 -- `swap`: 交换到指定位置 - -### 3. 批量保存调度 - -**Service层实现**(第587-606行): -```java -@Override -@Transactional(rollbackFor = Exception.class) -public boolean saveDispatch(SaveDispatchDTO dto) { - // 批量更新所有参赛者的出场顺序 - for (DetailAdjustment adjustment : dto.getAdjustments()) { - for (ParticipantOrder po : adjustment.getParticipants()) { - // 更新 performance_order 字段 - } - } -} -``` - ---- - -## 🎨 前端页面集成 - -### 页面结构 - -``` -编排页面 -├── Tab切换 -│ ├── 竞赛分组(编排完成后禁用) -│ ├── 场地(编排完成后禁用) -│ └── 调度(只有编排完成后可用)⭐ -│ -└── 调度Tab内容 - ├── 场地选择器 - ├── 时间段选择器 - ├── 分组列表 - │ ├── 分组1 - │ │ └── 参赛者列表(带上移/下移按钮) - │ ├── 分组2 - │ │ └── 参赛者列表(带上移/下移按钮) - │ └── ... - └── 保存/取消按钮 -``` - -### 核心方法 - -| 方法 | 说明 | -|------|------| -| `handleSwitchToDispatch()` | 切换到调度Tab | -| `loadDispatchData()` | 加载调度数据 | -| `handleMoveUp(group, index)` | 上移参赛者 | -| `handleMoveDown(group, index)` | 下移参赛者 | -| `handleSaveDispatch()` | 保存调度 | -| `handleCancelDispatch()` | 取消调度 | - ---- - -## 🔑 关键特性 - -### 1. 权限控制 - -```javascript -// 调度Tab只有在编排完成后才可用 -:disabled="!isScheduleCompleted" -``` - -### 2. 数据一致性 - -- ✅ 每次切换场地或时间段都重新加载数据 -- ✅ 保存成功后重新加载数据 -- ✅ 取消时恢复到原始数据 - -### 3. 用户体验 - -- ✅ 第一个不能上移(按钮禁用) -- ✅ 最后一个不能下移(按钮禁用) -- ✅ 有未保存更改时,取消需要确认 -- ✅ 保存成功后显示提示 - -### 4. 性能优化 - -- ✅ 使用深拷贝保存原始数据 -- ✅ 只在有更改时才允许保存 -- ✅ 批量更新数据库 - ---- - -## 📊 数据流转 - -``` -用户操作 - ↓ -前端:点击上移/下移 - ↓ -前端:交换数组位置 - ↓ -前端:更新 performanceOrder - ↓ -前端:标记 hasDispatchChanges = true - ↓ -用户:点击保存 - ↓ -前端:调用 saveDispatch API - ↓ -后端:批量更新数据库 - ↓ -后端:返回成功 - ↓ -前端:重新加载数据 - ↓ -前端:显示成功提示 -``` - ---- - -## 🚀 部署步骤 - -### 1. 后端部署 - -```bash -# 1. 编译后端代码 -cd martial-master -mvn clean compile - -# 2. 重启后端服务 -mvn spring-boot:run -``` - -### 2. 数据库升级(可选) - -```bash -# 创建调度日志表(可选,用于记录调整历史) -mysql -h localhost -P 3306 -u root -proot blade < database/martial-db/create_dispatch_log_table.sql -``` - -### 3. 前端部署 - -```bash -# 1. 前端代码已经修改完成 -# 2. 刷新浏览器即可看到调度Tab -``` - ---- - -## 🧪 测试步骤 - -### 1. 完成编排 - -1. 进入编排页面 -2. 点击"自动编排"按钮 -3. 点击"完成编排"按钮 -4. 确认编排已锁定 - -### 2. 进入调���模式 - -1. 点击"调度"Tab(应该可用) -2. 选择一个场地 -3. 选择一个时间段 -4. 查看分组列表 - -### 3. 调整顺序 - -1. 找到一个分组 -2. 点击某个参赛者的"上移"按钮 -3. 观察顺序变化 -4. 点击"下移"按钮 -5. 观察顺序变化 - -### 4. 保存调度 - -1. 点击"保存调度"按钮 -2. 等待保存成功提示 -3. 刷新页面 -4. 验证顺序是否保持 - -### 5. 取消操作 - -1. 进行一些调整 -2. 点击"取消"按钮 -3. 确认弹出提示 -4. 点击"确定" -5. 验证数据恢复 - ---- - -## ⚠️ 注意事项 - -### 1. 权限控制 - -- ✅ 只有编排完成后才能使用调度功能 -- ✅ 编排完成后,编排Tab和场地Tab应该禁用 - -### 2. 数据安全 - -- ✅ 使用事务确保数据一致性 -- ✅ 保存前验证数据有效性 -- ✅ 异常时回滚事务 - -### 3. 用户体验 - -- ✅ 提供清晰的操作反馈 -- ✅ 防止误操作(确认对话框) -- ✅ 按钮状态正确(禁用/启用) - -### 4. 性能优化 - -- ✅ 避免频繁的数据库查询 -- ✅ 批量更新而非逐条更新 -- ✅ 前端使用深拷贝避免引用问题 - ---- - -## 📝 API测试示例 - -### 1. 获取调度数据 - -```bash -curl -X GET "http://localhost:8123/api/blade-martial/schedule/dispatch-data?competitionId=1&venueId=1&timeSlotIndex=0" -``` - -**预期响应**: -```json -{ - "code": 200, - "success": true, - "data": { - "groups": [ - { - "groupId": 1, - "groupName": "男子A组 长拳", - "detailId": 101, - "projectType": 1, - "participants": [ - { - "id": 1001, - "participantId": 501, - "organization": "北京体育大学", - "playerName": "张三", - "projectName": "长拳", - "category": "成年组", - "performanceOrder": 1 - } - ] - } - ] - } -} -``` - -### 2. 调整出场顺序 - -```bash -curl -X POST "http://localhost:8123/api/blade-martial/schedule/adjust-order" \ - -H "Content-Type: application/json" \ - -d '{ - "detailId": 101, - "participantId": 1001, - "action": "move_up" - }' -``` - -### 3. 批量保存调度 - -```bash -curl -X POST "http://localhost:8123/api/blade-martial/schedule/save-dispatch" \ - -H "Content-Type: application/json" \ - -d '{ - "competitionId": 1, - "adjustments": [ - { - "detailId": 101, - "participants": [ - {"id": 1001, "performanceOrder": 2}, - {"id": 1002, "performanceOrder": 1} - ] - } - ] - }' -``` - ---- - -## 🎯 功能验证清单 - -- [ ] 后端编译成功 -- [ ] 后端服务启动成功 -- [ ] 调度Tab在编排完成前禁用 -- [ ] 调度Tab在编排完成后可用 -- [ ] 可以选择场地和时间段 -- [ ] 可以查看分组和参赛者列表 -- [ ] 上移按钮功能正常 -- [ ] 下移按钮功能正常 -- [ ] 第一个不能上移(按钮禁用) -- [ ] 最后一个不能下移(按钮禁用) -- [ ] 保存调度功能正常 -- [ ] 取消调度功能正常 -- [ ] 数据持久化正常 - ---- - -## 🎉 总结 - -调度功能已经完整实现,包括: - -1. ✅ **后端完成**:DTO、VO、Service、Controller 全部实现 -2. ✅ **前端API**:封装了3个调度相关接口 -3. ✅ **页面方案**:提供了完整的集成方案和代码 -4. ✅ **数据库**:可选的调度日志表 -5. ✅ **文档齐全**:实现文档、测试指南、API文档 - -**核心特性**: -- 🔐 权限控制:只有编排完成后才能使用 -- 🎯 简单易用:上移/下移按钮,操作直观 -- 💾 数据安全:事务保证,批量更新 -- 🎨 用户友好:清晰反馈,防止误操作 - -现在可以开始部署和测试了!🚀 - ---- - -## 📞 技术支持 - -如有问题,请参考: -- [详细实现文档](./schedule-dispatch-implementation.md) -- [移动功能分析](./schedule-move-group-analysis.md) - -祝使用愉快!✨ diff --git a/docs/DISPATCH_REFACTOR_SUMMARY.md b/docs/DISPATCH_REFACTOR_SUMMARY.md deleted file mode 100644 index 8be5aea..0000000 --- a/docs/DISPATCH_REFACTOR_SUMMARY.md +++ /dev/null @@ -1,332 +0,0 @@ -# 调度功能重构总结 - -## ✅ 重构完成 - -根据您的要求,已成功将调度功能从编排页面的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. ✅ **用户体验**:清晰的按钮状态和操作提示 - -现在可以开始测试新的调度流程了!🚀 diff --git a/docs/DISPATCH_TAB_IMPLEMENTATION.md b/docs/DISPATCH_TAB_IMPLEMENTATION.md deleted file mode 100644 index c582c2c..0000000 --- a/docs/DISPATCH_TAB_IMPLEMENTATION.md +++ /dev/null @@ -1,313 +0,0 @@ -# 调度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 - - 调度 - -``` - -### 2. 上移/下移按钮 -```vue - - 上移 - -``` - -### 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) diff --git a/docs/QUICK_TEST_GUIDE.md b/docs/QUICK_TEST_GUIDE.md deleted file mode 100644 index 2ed038d..0000000 --- a/docs/QUICK_TEST_GUIDE.md +++ /dev/null @@ -1,329 +0,0 @@ -# 评委邀请码管理功能 - 快速测试指南 - -## 🚀 快速开始 - -### 1. 数据库准备 - -执行以下SQL脚本(按顺序): - -```bash -# 1. 升级表结构(添加新字段) -mysql -h localhost -P 3306 -u root -proot blade < database/martial-db/upgrade_judge_invite_table.sql - -# 2. 插入测试数据(可选) -mysql -h localhost -P 3306 -u root -proot blade < database/martial-db/insert_test_judge_invite_data.sql -``` - -或者直接在MySQL客户端中执行: - -```sql --- 连接数据库 -USE blade; - --- 添加新字段 -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS invite_status INT DEFAULT 0 COMMENT '邀请状态(0-待回复,1-已接受,2-已拒绝,3-已取消)'; -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS invite_time DATETIME COMMENT '邀请时间'; -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS reply_time DATETIME COMMENT '回复时间'; -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS reply_note VARCHAR(500) COMMENT '回复备注'; -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS contact_phone VARCHAR(20) COMMENT '联系电话'; -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS contact_email VARCHAR(100) COMMENT '联系邮箱'; -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS invite_message VARCHAR(1000) COMMENT '邀请消息'; -ALTER TABLE martial_judge_invite ADD COLUMN IF NOT EXISTS cancel_reason VARCHAR(500) COMMENT '取消原因'; - --- 添加索引 -ALTER TABLE martial_judge_invite ADD INDEX IF NOT EXISTS idx_invite_status (invite_status); -ALTER TABLE martial_judge_invite ADD INDEX IF NOT EXISTS idx_competition_status (competition_id, invite_status); -``` - -### 2. 后端服务 - -后端服务已经在运行(端口8123),如果没有运行,执行: - -```bash -cd martial-master -mvn spring-boot:run -``` - -### 3. 前端服务 - -前端服务应该已经在运行,访问: - -``` -http://localhost:3000/martial/judgeInvite -``` - -## ✅ 测试步骤 - -### 测试1: 查看邀请列表 - -1. 打开浏览器访问评委邀请码管理页面 -2. 选择一个赛事(如果有测试数据,会自动选择第一个赛事) -3. 应该能看到: - - ✅ 统计卡片显示数据(总数、待回复、已接受、已拒绝) - - ✅ 表格显示邀请列表 - - ✅ 邀请码显示为橙色标签 - -**预期结果**: -- 统计卡片显示正确的数字 -- 表格显示5条测试数据 -- 邀请码列显示橙色标签 - -### 测试2: 邀请码复制功能 ⭐ - -1. 找到表格中的"邀请码"列 -2. 点击任意一个橙色的邀请码标签(例如:INV2025001) -3. 应该看到成功提示:"邀请码已复制: INV2025001" -4. 打开记事本,按 Ctrl+V 粘贴 -5. 应该能看到邀请码内容 - -**预期结果**: -- ✅ 点击后显示成功提示 -- ✅ 剪贴板中有邀请码内容 -- ✅ 可以粘贴到其他应用 - -### 测试3: 搜索和筛选 - -1. **按姓名搜索**: - - 在"评委姓名"输入框输入"张三" - - 点击"搜索"按钮 - - 应该只显示张三的邀请记录 - -2. **按等级筛选**: - - 选择"评委等级"为"国家级" - - 点击"搜索"按钮 - - 应该只显示国家级评委的邀请 - -3. **按状态筛选**: - - 选择"邀请状态"为"待回复" - - 点击"搜索"按钮 - - 应该只显示待回复的邀请 - -4. **重置**: - - 点击"重置"按钮 - - 所有筛选条件清空,显示全部数据 - -**预期结果**: -- ✅ 搜索功能正常 -- ✅ 筛选功能正常 -- ✅ 重置功能正常 - -### 测试4: 统计卡片 - -1. 查看统计卡片的数字 -2. 切换不同的赛事 -3. 统计数字应该随之变化 - -**预期结果**: -- ✅ 总邀请数 = 5 -- ✅ 待回复 = 2 -- ✅ 已接受 = 2 -- ✅ 已拒绝 = 1 - -### 测试5: 操作按钮 - -1. **重发按钮**(待回复状态): - - 找到状态为"待回复"的记录 - - 点击"重发"按钮 - - 应该显示"重发成功" - -2. **提醒按钮**(待回复状态): - - 找到状态为"待回复"的记录 - - 点击"提醒"按钮 - - 应该显示"提醒发送成功" - -3. **确认按钮**(已接受状态): - - 找到状态为"已接受"的记录 - - 点击"确认"按钮 - - 应该弹出确认对话框 - - 点击"确认"后显示"确认成功" - -**预期结果**: -- ✅ 按钮根据状态显示/隐藏 -- ✅ 操作成功后显示提示 -- ✅ 列表自动刷新 - -### 测试6: 分页功能 - -1. 如果数据超过10条,应该显示分页器 -2. 点击"下一页"按钮 -3. 应该显示下一页的数据 -4. 修改"每页条数" -5. 数据应该重新加载 - -**预期结果**: -- ✅ 分页器显示正确 -- ✅ 翻页功能正常 -- ✅ 每页条数切换正常 - -## 🔍 API测试 - -### 使用Postman或curl测试 - -#### 1. 获取邀请列表 - -```bash -curl -X GET "http://localhost:8123/api/blade-martial/judgeInvite/list?current=1&size=10&competitionId=1" -``` - -**预期响应**: -```json -{ - "code": 200, - "success": true, - "data": { - "records": [...], - "total": 5, - "size": 10, - "current": 1 - } -} -``` - -#### 2. 获取统计信息 - -```bash -curl -X GET "http://localhost:8123/api/blade-martial/judgeInvite/statistics?competitionId=1" -``` - -**预期响应**: -```json -{ - "code": 200, - "success": true, - "data": { - "totalInvites": 5, - "pendingCount": 2, - "acceptedCount": 2, - "rejectedCount": 1 - } -} -``` - -## 🐛 常见问题排查 - -### 问题1: 前端页面报错 "Failed to resolve import" - -**解决方案**: -- 检查是否有不存在的导入 -- 已修复:删除了 `import { getJudgeList } from '@/api/martial/judge'` - -### 问题2: 后端启动失败 "Port 8123 was already in use" - -**解决方案**: -- 端口已被占用,说明服务已经在运行 -- 或者杀掉占用端口的进程: - ```bash - # Windows - netstat -ano | findstr :8123 - taskkill /PID <进程ID> /F - ``` - -### 问题3: 数据库连接失败 - -**解决方案**: -- 检查MySQL服务是否启动 -- 检查配置文件中的数据库连接信息 -- 确认数据库名称为 `blade` - -### 问题4: 表格没有数据 - -**解决方案**: -1. 检查是否执行了数据库升级脚本 -2. 检查是否插入了测试数据 -3. 检查浏览器控制台是否有错误 -4. 检查后端日志是否有异常 - -### 问题5: 邀请码复制失败 - -**解决方案**: -- 检查浏览器是否支持Clipboard API -- 如果是HTTP环境,可能需要HTTPS -- 会自动降级到 document.execCommand('copy') - -## 📊 测试数据说明 - -测试数据包含5条邀请记录: - -| ID | 评委姓名 | 等级 | 邀请码 | 状态 | 说明 | -|----|---------|------|--------|------|------| -| 1 | 张三 | 国家级 | INV2025001 | 待回复 | 刚发送的邀请 | -| 2 | 李四 | 一级 | INV2025002 | 待回复 | 刚发送的邀请 | -| 3 | 王五 | 二级 | INV2025003 | 已接受 | 已回复接受 | -| 4 | 赵六 | 国家级 | INV2025004 | 已接受 | 裁判长,已接受 | -| 5 | 钱七 | 三级 | INV2025005 | 已拒绝 | 已回复拒绝 | - -## ✨ 核心功能验证清单 - -- [ ] 页面正常加载 -- [ ] 统计卡片显示正确 -- [ ] 表格数据显示正确 -- [ ] **邀请码显示为橙色标签** ⭐ -- [ ] **点击邀请码可以复制** ⭐ -- [ ] 搜索功能正常 -- [ ] 筛选功能正常 -- [ ] 分页功能正常 -- [ ] 操作按钮显示正确 -- [ ] 重发功能正常 -- [ ] 提醒功能正常 -- [ ] 确认功能正常 - -## 🎯 重点测试项 - -### 最重要的功能:邀请码复制 ⭐⭐⭐ - -这是本次开发的核心功能,必须确保: - -1. ✅ 邀请码显示为**橙色深色标签** -2. ✅ 标签使用**等宽粗体字体**(monospace, bold) -3. ✅ 鼠标悬停时显示**手型光标**(cursor: pointer) -4. ✅ 点击后**自动复制到剪贴板** -5. ✅ 显示**成功提示消息**:"邀请码已复制: XXX" -6. ✅ 支持**现代浏览器和旧浏览器** - -### 测试浏览器兼容性 - -- [ ] Chrome/Edge(现代浏览器) -- [ ] Firefox(现代浏览器) -- [ ] Safari(现代浏览器) -- [ ] IE11(旧浏览器,降级方案) - -## 📝 测试报告模板 - -``` -测试日期:2025-12-12 -测试人员:[姓名] -测试环境: -- 操作系统:Windows 10 -- 浏览器:Chrome 120 -- 后端版本:4.0.1.RELEASE -- 前端版本:Vue 3 - -测试结果: -✅ 页面加载正常 -✅ 邀请码复制功能正常 -✅ 统计卡片显示正确 -✅ 搜索筛选功能正常 -✅ 操作按钮功能正常 - -问题记录: -无 - -建议: -无 -``` - -## 🎉 测试通过标准 - -所有以下条件都满足,即可认为测试通过: - -1. ✅ 页面无报错,正常加载 -2. ✅ 邀请码显示为橙色标签 -3. ✅ 点击邀请码可以复制 -4. ✅ 统计数据正确 -5. ✅ 搜索筛选功能正常 -6. ✅ 操作按钮功能正常 -7. ✅ 后端接口返回正确数据 - ---- - -**祝测试顺利!** 🚀 diff --git a/docs/README.md b/docs/README.md index 7fe0ae1..4239f36 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,142 +1,15 @@ -# 项目文档索引 +# 项目文档 -## 📚 开发文档 +## 指南 -### 1. [前后端架构说明.md](./前后端架构说明.md) 🆕 -**理解 BladeX 完整系统架构和前后端分离** +| 文档 | 说明 | +|------|------| +| [开发指南](guides/开发指南.md) | 本地开发环境搭建与开发规范 | +| [架构说明](guides/架构说明.md) | 系统架构与模块设计 | +| [Docker 部署指南](guides/docker-deployment.md) | Docker 构建与部署方式详解 | +| [CI/CD 部署总结](guides/CI-CD部署总结.md) | 持续集成与部署配置 | +| [数据库迁移](guides/DATABASE_MIGRATION.md) | Flyway 数据库迁移说明 | -- BladeX 完整系统架构(后端 + 前端 Saber) -- Saber 前端管理系统介绍 -- 前后端交互流程 -- 如何在没有前端的情况下开发 -- 单体架构 vs 微服务架构 -- 模块启动管理说明 +## 其他资源 -**适合阅读时机**: -- ✅ 想了解完整的系统架构时 -- ✅ 疑惑"管理界面在哪里"时 -- ✅ 需要配置前后端联调时 -- ✅ 想了解如何获取前端源码时 - ---- - -### 2. [架构说明.md](./架构说明.md) -**理解 BladeX 后端框架的架构设计** - -- 为什么这个项目的结构看起来"乱"? -- BladeX 架构 vs 传统 Spring Boot 架构对比 -- common、modules、job 目录的职责划分 -- 架构设计理念分析 -- 与标准架构的映射关系 - -**适合阅读时机**: -- ✅ 刚接触项目,对后端架构感到困惑时 -- ✅ 想理解为什么要这样设计时 -- ✅ 需要向团队解释项目结构时 - ---- - -### 3. [开发指南.md](./开发指南.md) -**在 BladeX 框架下高效开发的实用指南** - -包含内容: -- 📖 快速开始:环境准备、核心目录 -- 🔧 标准开发流程:完整的功能开发步骤(从数据库到API) -- 📝 代码规范:命名、注解、包结构 -- 💡 常见场景:查询、分页、关联、事务等实战示例 -- ✅ 最佳实践:Service、Controller、异常处理、缓存 -- 🐛 调试技巧:VS Code 调试、日志、SQL 调试 -- ❓ 常见问题:继承选择、Mapper 配置、分页等 - -**适合阅读时机**: -- ✅ 准备开始开发新功能时 -- ✅ 遇到具体技术问题时 -- ✅ 需要参考代码示例时 - ---- - -## 🎯 快速导航 - -### 我想... - -| 需求 | 推荐文档 | 章节 | -|------|---------|------| -| 了解完整系统架构(前端+后端) | [前后端架构说明.md](./前后端架构说明.md) | 一、BladeX 完整系统架构 | -| 管理界面在哪里? | [前后端架构说明.md](./前后端架构说明.md) | 二、前端管理系统 - Saber | -| 如何获取/配置前端 | [前后端架构说明.md](./前后端架构说明.md) | 四、当前项目的使用方式 | -| 理解后端架构设计 | [架构说明.md](./架构说明.md) | 二、目录结构对比 | -| 理解为什么架构"乱" | [架构说明.md](./架构说明.md) | 三、架构特点分析 | -| 知道代码应该放哪里 | [架构说明.md](./架构说明.md) | 八、实际开发时如何思考 | -| 开发一个新功能 | [开发指南.md](./开发指南.md) | 二、标准开发流程 | -| 学习代码规范 | [开发指南.md](./开发指南.md) | 三、代码规范 | -| 查看查询示例 | [开发指南.md](./开发指南.md) | 四、常见开发场景 | -| 学习最佳实践 | [开发指南.md](./开发指南.md) | 五、最佳实践 | -| 调试代码 | [开发指南.md](./开发指南.md) | 六、调试技巧 | -| 解决常见问题 | [开发指南.md](./开发指南.md) | 七、常见问题 | - ---- - -## 📋 其他文档 - -### 项目配置与说明 - -- [CLAUDE.md](../CLAUDE.md) - 项目整体说明、技术栈、构建命令 -- [.vscode/DEBUG_GUIDE.md](../.vscode/DEBUG_GUIDE.md) - VS Code 调试配置指南 - -### 数据库文档 - -- [sql/mysql/martial-competition-tables.sql](./sql/mysql/martial-competition-tables.sql) - 武术比赛表结构 -- [sql/mysql/martial-competition-menu.sql](./sql/mysql/martial-competition-menu.sql) - 菜单权限配置 - ---- - -## 🚀 新人入门路径 - -### 第一天:环境准备 -1. 阅读 [CLAUDE.md](../CLAUDE.md) 了解项目概况 -2. 配置开发环境(JDK、Maven、MySQL、Redis) -3. 启动项目,访问 https://martial-doc.johnsion.club(生产环境)或 http://localhost:8123/doc.html(本地开发) - -### 第二天:理解架构 -1. 阅读 [前后端架构说明.md](./前后端架构说明.md) 了解完整系统 -2. 阅读 [架构说明.md](./架构说明.md) 理解后端设计 -3. 浏览项目目录结构 -4. 查看现有代码示例(`modules/system/`) - -### 第三天:动手开发 -1. 阅读 [开发指南.md](./开发指南.md) -2. 按照"标准开发流程"完成一个简单的 CRUD 功能 -3. 测试接口 - -### 第四天:深入学习 -1. 学习复杂查询、关联查询 -2. 掌握调试技巧 -3. 解决遇到的问题 - ---- - -## 💡 学习建议 - -### 对于初学者 -- 先看 **开发指南** 的"快速开始"和"标准开发流程" -- 边看边实践,动手写一个 CRUD 功能 -- 遇到问题查看"常见问题"章节 - -### 对于有经验的开发者 -- 快速浏览 **架构说明**,理解 BladeX 的特点 -- 重点关注 **开发指南** 的"最佳实践" -- 参考"常见场景"进行复杂功能开发 - -### 对于团队 Leader -- 使用 **架构说明** 向团队解释项目结构 -- 制定基于 **开发指南** 的团队规范 -- 组织 Code Review 时参考"代码规范" - ---- - -## 🔄 文档更新 - -本文档会根据项目实际情况持续更新。如有问题或建议,请及时反馈。 - -**最后更新**:2025-11-29 -**维护者**:开发团队 +- [sql/](sql/) - 数据库 SQL 脚本 diff --git a/docs/RESTART_BACKEND.md b/docs/RESTART_BACKEND.md deleted file mode 100644 index 808ab67..0000000 --- a/docs/RESTART_BACKEND.md +++ /dev/null @@ -1,57 +0,0 @@ -# 后端服务重启指南 - -## 问题说明 -修改了 `MartialScheduleArrangeServiceImpl.java` 文件添加了空值检查,需要重启后端服务以加载新代码。 - -## 修改的文件 -- `src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleArrangeServiceImpl.java` - - 第 394-398 行:集体项目空值检查 - - 第 430-434 行:个人项目空值检查 - -## 重启步骤 - -### 1. 停止当前运行的后端服务 -在当前运行后端服务的命令行窗口中按 `Ctrl+C` 停止服务。 - -### 2. 重新编译项目(可选,推荐) -```bash -cd D:\workspace\31.比赛项目\project\martial-master -mvn clean compile -``` - -### 3. 重启后端服务 -使用之前启动后端的相同命令重新启动。通常是以下之一: - -**选项A - 使用 Maven 直接运行:** -```bash -mvn spring-boot:run -``` - -**选项B - 使用已打包的 JAR 文件:** -```bash -java -jar target/blade-martial-*.jar -``` - -**选项C - 在 IDE (如 IntelliJ IDEA 或 Eclipse) 中:** -右键点击主类 `Application.java` → Run - -### 4. 验证服务启动成功 -等待服务启动完成(看到类似 "Started Application in X seconds" 的日志)。 - -### 5. 重新测试 API -```bash -curl -X POST "http://localhost:8123/martial/schedule/auto-arrange" -H "Content-Type: application/json" -d "{\"competitionId\": 200}" -``` - -## 预期结果 -修复后应该不再出现 NPE 错误,会返回以下情况之一: -1. **成功**: `{"code":200,"success":true,...}` - 自动编排成功 -2. **警告日志**: 后端日志中会显示 "项目不存在, projectId: XXX, 跳过该分组" 如果有参赛者关联了不存在的项目 - -## 如果仍有问题 -请执行数据验证脚本检查数据完整性: -```bash -mysql -uroot -proot123 martial_db < database/martial-db/debug_check.sql -``` - -查看是否所有参赛者都有有效的 project_id 关联。 diff --git a/docs/SCHEDULE_COMPLETION_REPORT.md b/docs/SCHEDULE_COMPLETION_REPORT.md deleted file mode 100644 index 483fee0..0000000 --- a/docs/SCHEDULE_COMPLETION_REPORT.md +++ /dev/null @@ -1,292 +0,0 @@ -# 赛程编排系统开发完成报告 - -## ✅ 项目完成状态 - -**开发时间**: 2025-12-08 -**项目状态**: 已完成 -**代码质量**: 生产就绪 - ---- - -## 📋 完成清单 - -### 1. 数据库层 ✅ -- [x] 创建 4 张数据库表 -- [x] 定义索引和约束 -- [x] 编写测试数据脚本 - -**文件**: -- `database/martial-db/create_schedule_tables.sql` - -### 2. 实体层 ✅ -- [x] MartialScheduleGroup.java -- [x] MartialScheduleDetail.java -- [x] MartialScheduleParticipant.java -- [x] MartialScheduleStatus.java - -### 3. 数据访问层 ✅ -- [x] 4 个 Mapper 接口 -- [x] 4 个 Mapper XML 文件 - -### 4. 业务逻辑层 ✅ -- [x] IMartialScheduleArrangeService.java (接口) -- [x] MartialScheduleArrangeServiceImpl.java (实现, 600+ 行) -- [x] 自动分组算法实现 -- [x] 负载均衡算法实现 -- [x] 项目类型查询优化 -- [x] 字段名错误修复 - -**关键修复**: -1. **项目类型查询**: 通过 MartialProjectMapper 查询项目信息,避免 N+1 查询 -2. **字段名修正**: 修正 getScheduleResult 方法中的字段名错误 (line 233) - -### 5. 控制器层 ✅ -- [x] MartialScheduleArrangeController.java -- [x] 3 个 REST API 接口 - -### 6. 定时任务 ✅ -- [x] ScheduleAutoArrangeProcessor.java -- [x] PowerJob 集成 -- [x] 每 10 分钟自动编排 - -### 7. 文档 ✅ -- [x] SCHEDULE_DEPLOYMENT.md - 部署指南 -- [x] SCHEDULE_DEVELOPMENT_SUMMARY.md - 开发总结 -- [x] SCHEDULE_DEPLOYMENT_CHECKLIST.md - 部署检查清单 -- [x] SCHEDULE_COMPLETION_REPORT.md - 完成报告(本文档) - ---- - -## 🔧 已修复的问题 - -### 问题 1: MartialAthlete 缺少 projectType 字段 -**状态**: ✅ 已修复 - -**解决方案**: 通过 MartialProjectMapper 查询项目表获取项目类型和名称 - -```java -// 在 Service 中注入 -private final MartialProjectMapper projectMapper; - -// 查询并缓存项目信息 -Map projectMap = new HashMap<>(); -for (Long projectId : projectIds) { - MartialProject project = projectMapper.selectById(projectId); - if (project != null) { - projectMap.put(projectId, project); - } -} - -// 使用缓存的项目信息 -MartialProject project = projectMap.get(athlete.getProjectId()); -Integer projectType = project.getType(); -String projectName = project.getProjectName(); -``` - -### 问题 2: getScheduleResult 方法字段名错误 -**状态**: ✅ 已修复 - -**位置**: MartialScheduleArrangeServiceImpl.java, line 233 - -**修复内容**: -```java -// 修复前: -pDetailWrapper.eq(MartialScheduleDetail::getScheduleDetailId, p.getScheduleDetailId()) - -// 修复后: -pDetailWrapper.eq(MartialScheduleDetail::getId, p.getScheduleDetailId()) -``` - -### 问题 3: 测试数据表名不一致 -**状态**: ✅ 已修复 - -**问题**: 测试数据脚本使用 `martial_participant` 表,但代码使用 `martial_athlete` 表 - -**修复内容**: -1. 批量替换 `martial_participant` → `martial_athlete` -2. 批量替换 `created_time` → `create_time` -3. 文件: `martial-web/test-data/create_100_team_participants.sql` - ---- - -## ⚠️ 待确认项 - -**所有问题已解决!** ✅ - -之前的表名一致性问题已通过修改测试数据脚本解决: -- 修改前: 测试数据插入 `martial_participant` 表 -- 修改后: 测试数据插入 `martial_athlete` 表(与代码一致) -- 同时修正字段名: `created_time` → `create_time` - ---- - -## 🚀 部署步骤 - -### 1. 数据库初始化 -```bash -mysql -u root -p martial_competition < database/martial-db/create_schedule_tables.sql -``` - -### 2. 导入测试数据(可选) -```bash -# 在前端项目的 test-data 目录下 -mysql -u root -p martial_competition < test-data/create_100_team_participants.sql -``` - -### 3. 编译部署后端 -```bash -cd martial-master -mvn clean package -DskipTests -java -jar target/martial-master.jar -``` - -### 4. 配置 PowerJob 定时任务 -- 访问: `http://localhost:7700` -- 任务名称: 赛程自动编排 -- 处理器: `org.springblade.job.processor.ScheduleAutoArrangeProcessor` -- Cron: `0 */10 * * * ?` -- 最大实例数: 1 - -### 5. 前端部署 -```bash -cd martial-web -npm run dev -``` - ---- - -## 🧪 测试流程 - -### 1. API 测试 - -#### 测试 1: 手动触发编排 -```bash -curl -X POST http://localhost/api/martial/schedule/auto-arrange \ - -H "Content-Type: application/json" \ - -d '{"competitionId": 200}' -``` - -**预期结果**: `{"code":200,"success":true,"msg":"自动编排完成"}` - -#### 测试 2: 获取编排结果 -```bash -curl http://localhost/api/martial/schedule/result?competitionId=200 -``` - -**预期结果**: 返回完整的编排数据结构 - -#### 测试 3: 保存并锁定 -```bash -curl -X POST http://localhost/api/martial/schedule/save-and-lock \ - -H "Content-Type: application/json" \ - -d '{"competitionId": 200}' -``` - -**预期结果**: `{"code":200,"success":true,"msg":"编排已保存并锁定"}` - -### 2. 前端测试 - -访问: `http://localhost:3000/martial/schedule?competitionId=200` - -**检查项**: -- [ ] 页面正常加载 -- [ ] 显示编排状态标签 -- [ ] 竞赛分组 Tab 可切换 -- [ ] 场地 Tab 可切换 -- [ ] 集体项目按单位分组显示 -- [ ] 个人项目直接列出参赛者 -- [ ] 保存编排按钮可用 - -### 3. 定时任务测试 - -#### 查看编排状态 -```sql -SELECT * FROM martial_schedule_status WHERE competition_id = 200; -``` - -#### 查看 PowerJob 日志 -在 PowerJob 控制台查看任务执行日志 - ---- - -## 📊 核心算法说明 - -### 1. 自动分组算法 - -**规则**: -1. 加载所有项目信息(MartialProject) -2. 分离集体项目(type=2 或 3)和个人项目(type=1) -3. 按"项目 ID + 组别"进行分组 -4. 集体项目统计队伍数(按单位分组) -5. 计算预计时长: - - 集体: 队伍数 × 5 分钟 + 间隔时间 - - 个人: (人数 / 6) × 8 分钟 - -### 2. 负载均衡算法 - -**策略**: 贪心算法 - -**步骤**: -1. 初始化场地 × 时间段负载表 -2. 按预计时长降序排序分组(优先安排长时间项目) -3. 为每个分组寻找负载最小且容量足够的位置 -4. 更新负载表 - -**容量配置**: -- 上午(08:30-11:30): 150 分钟 -- 下午(13:30-17:30): 210 分钟 - ---- - -## 📈 代码统计 - -- **新增代码**: 约 2000 行 -- **修改代码**: 约 700 行(前端) -- **新增文件**: 24 个 -- **数据库表**: 4 张 -- **API 接口**: 3 个 -- **定时任务**: 1 个 -- **文档文件**: 4 个 - ---- - -## 🎯 技术特性 - -1. **后端驱动编排**: 定时任务自动编排,减轻前端压力 -2. **智能分组**: 集体项目优先,按项目和组别自动分组 -3. **负载均衡**: 贪心算法实现场地和时间段均衡分配 -4. **锁定机制**: 保存后锁定编排,防止意外修改 -5. **性能优化**: 项目信息缓存,避免 N+1 查询问题 -6. **分布式任务**: PowerJob 框架支持分布式调度 - ---- - -## 📝 后续建议 - -1. **单元测试**: 编写 Service 层和 Controller 层单元测试 -2. **集成测试**: 端到端测试整个编排流程 -3. **性能测试**: 测试 1000+ 参赛者的编排性能 -4. **监控告警**: 添加编排失败告警机制 -5. **日志优化**: 完善关键操作日志记录 -6. **表名确认**: 确认 martial_athlete 和 martial_participant 表的关系 - ---- - -## ✨ 总结 - -赛程编排系统后端开发已全部完成,所有已知问题已修复,代码已达到生产就绪状态。系统采用后端驱动的架构设计,实现了智能分组和负载均衡算法,具备良好的扩展性和维护性。 - -**核心优势**: -- ✅ 完整的分层架构 -- ✅ 成熟的编排算法 -- ✅ 自动化定时任务 -- ✅ 完善的文档体系 -- ✅ 生产就绪代码 - -**下一步**: 按照部署指南进行部署和测试 - ---- - -**文档版本**: v1.0 -**完成时间**: 2025-12-08 -**开发人员**: Claude Code Assistant diff --git a/docs/SCHEDULE_DEPLOYMENT.md b/docs/SCHEDULE_DEPLOYMENT.md deleted file mode 100644 index ef35b75..0000000 --- a/docs/SCHEDULE_DEPLOYMENT.md +++ /dev/null @@ -1,305 +0,0 @@ -# 赛程编排系统后端部署指南 - -## 📋 部署步骤 - -### 1. 数据库初始化 - -执行数据库表创建脚本: - -```bash -mysql -u root -p martial_competition < database/martial-db/create_schedule_tables.sql -``` - -或者在MySQL客户端中直接执行 `database/martial-db/create_schedule_tables.sql` - -### 2. 导入测试数据(可选) - -如果需要测试编排功能,可以导入测试数据: - -```bash -# 在前端项目的test-data目录下 -mysql -u root -p martial_competition < test-data/create_100_team_participants.sql -``` - -这将创建: -- 100个集体项目队伍(500人) -- 5个集体项目类型 -- 配合原有个人项目,总计1500人 - -### 3. 编译后端项目 - -```bash -cd martial-master -mvn clean package -DskipTests -``` - -### 4. 启动后端服务 - -```bash -java -jar target/martial-master.jar -``` - -### 5. 配置PowerJob定时任务 - -#### 5.1 访问PowerJob控制台 - -默认地址: `http://localhost:7700` - -#### 5.2 创建定时任务 - -在PowerJob控制台中配置: - -- **任务名称**: 赛程自动编排 -- **任务描述**: 每10分钟自动编排未锁定的赛事 -- **执行类型**: BASIC -- **处理器**: `org.springblade.job.processor.ScheduleAutoArrangeProcessor` -- **Cron表达式**: `0 */10 * * * ?` (每10分钟执行一次) -- **最大实例数**: 1 (避免并发) -- **运行超时时间**: 600000 (10分钟) - -#### 5.3 启动任务 - -在PowerJob控制台中启动该任务 - ---- - -## 🔧 API接口说明 - -### 1. 获取编排结果 - -```http -GET /api/martial/schedule/result?competitionId={id} -``` - -**响应示例**: - -```json -{ - "code": 200, - "success": true, - "data": { - "scheduleStatus": 1, - "lastAutoScheduleTime": "2025-12-08 10:00:00", - "totalGroups": 45, - "totalParticipants": 1500, - "scheduleGroups": [ - { - "id": 1, - "groupName": "太极拳集体 成年组", - "projectType": 2, - "displayOrder": 1, - "totalParticipants": 10, - "totalTeams": 2, - "organizationGroups": [ - { - "organization": "少林寺武校", - "participants": [ - {"playerName": "张三"}, - {"playerName": "李四"} - ], - "scheduleDetails": [ - { - "venueId": 1, - "venueName": "一号场地", - "scheduleDate": "2025-11-06", - "timeSlot": "08:30", - "timePeriod": "morning" - } - ] - } - ] - } - ] - } -} -``` - -### 2. 保存并锁定编排 - -```http -POST /api/martial/schedule/save-and-lock -Content-Type: application/json - -{ - "competitionId": 200 -} -``` - -**响应示例**: - -```json -{ - "code": 200, - "success": true, - "msg": "编排已保存并锁定" -} -``` - -### 3. 手动触发自动编排(测试用) - -```http -POST /api/martial/schedule/auto-arrange -Content-Type: application/json - -{ - "competitionId": 200 -} -``` - ---- - -## 📊 数据库表说明 - -### 1. martial_schedule_group (编排分组表) - -存储自动分组结果,包括集体项目和个人项目的分组信息。 - -### 2. martial_schedule_detail (编排明细表) - -存储场地时间段分配结果,记录每个分组被分配到哪个场地和时间段。 - -### 3. martial_schedule_participant (参赛者关联表) - -存储参赛者与编排的关联关系,记录每个参赛者的出场顺序。 - -### 4. martial_schedule_status (编排状态表) - -存储每个赛事的编排状态: -- 0: 未编排 -- 1: 编排中 -- 2: 已保存锁定 - ---- - -## 🧪 测试流程 - -### 1. 准备测试数据 - -```bash -# 执行测试数据脚本 -mysql -u root -p martial_competition < test-data/create_100_team_participants.sql -``` - -### 2. 手动触发编排 - -使用API测试工具(Postman/Apifox)调用: - -```http -POST http://localhost/api/martial/schedule/auto-arrange -Content-Type: application/json - -{ - "competitionId": 200 -} -``` - -### 3. 查看编排结果 - -```http -GET http://localhost/api/martial/schedule/result?competitionId=200 -``` - -### 4. 前端测试 - -访问前端页面: - -``` -http://localhost:3000/martial/schedule?competitionId=200 -``` - -应该能看到: -- 竞赛分组Tab: 按时间段显示分组 -- 场地Tab: 按场地显示分组 -- 集体项目按单位分组显示 -- 个人项目直接列出参赛者 - -### 5. 保存并锁定 - -在前端页面点击"保存编排"按钮,或调用API: - -```http -POST http://localhost/api/martial/schedule/save-and-lock -Content-Type: application/json - -{ - "competitionId": 200 -} -``` - -锁定后,定时任务将不再自动编排该赛事。 - ---- - -## 🔍 故障排查 - -### 问题1: 编排结果为空 - -**原因**: -- 赛事没有参赛者 -- 赛事没有配置场地 -- 赛事时间未设置 - -**解决**: -- 检查 `martial_athlete` 表是否有该赛事的参赛者 -- 检查 `martial_venue` 表是否有该赛事的场地 -- 检查 `martial_competition` 表的 `competition_start_time` 和 `competition_end_time` - -### 问题2: 定时任务未执行 - -**原因**: -- PowerJob服务未启动 -- 任务未启动 -- Worker未连接 - -**解决**: -- 检查PowerJob控制台任务状态 -- 查看Worker日志 -- 确认Cron表达式正确 - -### 问题3: 场地容量不足 - -**原因**: -- 参赛人数过多 -- 时间段容量不够 - -**解决**: -- 增加比赛天数 -- 增加场地数量 -- 调整时间段容量配置 - ---- - -## 📝 注意事项 - -1. **定时任务执行频率**: 默认每10分钟执行一次,可以根据需要调整Cron表达式 - -2. **锁定机制**: 一旦保存并锁定,定时任务将不再自动编排该赛事 - -3. **容量检查**: 编排算法会自动检查时间段容量,超出容量的分组会报警 - -4. **项目类型**: - - type=1: 个人项目 - - type=2: 双人项目 - - type=3: 集体项目 - -5. **时间段容量**: - - 上午(08:30-11:30): 150分钟 - - 下午(13:30-17:30): 210分钟 - ---- - -## 🚀 性能优化建议 - -1. **数据库索引**: 已自动创建必要索引,无需额外优化 - -2. **批量插入**: Service层使用批量插入,提升性能 - -3. **缓存**: 可以考虑使用Redis缓存编排结果(可选) - -4. **并发控制**: PowerJob任务设置最大实例数为1,避免并发冲突 - ---- - -**版本**: v1.0 -**创建时间**: 2025-12-08 -**维护人**: 开发团队 diff --git a/docs/SCHEDULE_DEPLOYMENT_CHECKLIST.md b/docs/SCHEDULE_DEPLOYMENT_CHECKLIST.md deleted file mode 100644 index 0ffb9a5..0000000 --- a/docs/SCHEDULE_DEPLOYMENT_CHECKLIST.md +++ /dev/null @@ -1,203 +0,0 @@ -# 赛程编排系统部署检查清单 - -## ✅ 部署前检查 - -### 1. 数据库检查 -- [ ] 已执行数据库表创建脚本: `create_schedule_tables.sql` -- [ ] 已导入测试数据(可选): `create_100_team_participants.sql` -- [ ] 数据库连接配置正确 -- [ ] 确认表名一致性: - - 代码使用: `martial_athlete` - - 测试数据插入: `martial_participant` - - **需要确认**: 是否为同一张表(可能是表名重构导致) - -### 2. 后端代码检查 -- [x] 4个实体类已创建 -- [x] 4个Mapper接口及XML已创建 -- [x] Service接口和实现已创建 -- [x] Controller已创建 -- [x] 定时任务处理器已创建 -- [x] Service层项目查询逻辑已修复 - -### 3. 前端代码检查 -- [x] 页面布局已修改 -- [x] API接口已集成 -- [x] 集体/个人项目差异化显示已实现 -- [x] 编排状态和锁定机制已添加 - -### 4. 配置检查 -- [ ] PowerJob服务已启动 -- [ ] PowerJob定时任务已配置 -- [ ] Cron表达式设置为: `0 */10 * * * ?` -- [ ] 处理器类名正确: `org.springblade.job.processor.ScheduleAutoArrangeProcessor` - ---- - -## ⚠️ 已知问题和解决方案 - -### 问题1: 表名不一致 ✅ 已修复 - -**现象**: 测试数据脚本插入的是 `martial_participant` 表,但代码查询的是 `martial_athlete` 表 - -**解决方案**: 已将测试数据脚本修改为使用正确的表名 `martial_athlete` - -**修复内容**: -1. 批量替换 `martial_participant` → `martial_athlete` -2. 批量替换 `created_time` → `create_time` (统一字段名) - -**验证方法**: -```sql --- 导入测试数据后检查 -SELECT COUNT(*) FROM martial_athlete WHERE competition_id = 200; --- 应返回500条记录(100个队伍 × 5人) -``` - -### 问题2: getScheduleResult方法中的字段名错误 ✅ 已修复 - -**位置**: `MartialScheduleArrangeServiceImpl.java` 第233行 - -**问题**: `MartialScheduleDetail` 没有 `scheduleDetailId` 字段,应该使用主键 `id` - -**修复**: 已将查询条件修正为使用正确的字段名 - -```java -pDetailWrapper.eq(MartialScheduleDetail::getId, p.getScheduleDetailId()) -``` - ---- - -## 🔍 部署后测试流程 - -### 1. 后端API测试 - -#### 测试1: 手动触发编排 -```bash -curl -X POST http://localhost/api/martial/schedule/auto-arrange \ - -H "Content-Type: application/json" \ - -d '{"competitionId": 200}' -``` - -**预期结果**: 返回 `{"code":200,"success":true,"msg":"自动编排完成"}` - -#### 测试2: 获取编排结果 -```bash -curl http://localhost/api/martial/schedule/result?competitionId=200 -``` - -**预期结果**: 返回编排数据,包含 `scheduleGroups` 数组 - -#### 测试3: 保存并锁定 -```bash -curl -X POST http://localhost/api/martial/schedule/save-and-lock \ - -H "Content-Type: application/json" \ - -d '{"competitionId": 200}' -``` - -**预期结果**: 返回 `{"code":200,"success":true,"msg":"编排已保存并锁定"}` - -### 2. 前端页面测试 - -访问: `http://localhost:3000/martial/schedule?competitionId=200` - -**检查项**: -- [ ] 页面正常加载 -- [ ] 显示编排状态标签(未编排/编排中/已锁定) -- [ ] 竞赛分组Tab可切换 -- [ ] 场地Tab可切换 -- [ ] 集体项目按单位分组显示 -- [ ] 个人项目直接列出参赛者 -- [ ] 点击场地时间段按钮弹出详情对话框 -- [ ] 保存编排按钮可点击且生效 - -### 3. 定时任务测试 - -#### 检查定时任务执行 -```sql --- 查看编排状态表 -SELECT * FROM martial_schedule_status WHERE competition_id = 200; - --- 检查last_auto_schedule_time字段是否更新 -``` - -#### 查看PowerJob日志 -在PowerJob控制台查看任务执行日志,确认: -- 任务正常执行 -- 日志中显示编排成功 -- 没有异常错误 - ---- - -## 🛠️ 待修复项 - -**所有已知问题已修复!** ✅ - -系统已达到生产就绪状态,可以开始部署测试。 - ---- - -## 📊 性能测试建议 - -### 测试场景1: 小规模数据 -- 参赛人数: 100人 -- 场地数: 4个 -- 比赛天数: 2天 - -**预期结果**: 编排耗时 < 1秒 - -### 测试场景2: 中规模数据 -- 参赛人数: 1000人 -- 场地数: 5个 -- 比赛天数: 5天 - -**预期结果**: 编排耗时 < 5秒 - -### 测试场景3: 大规模数据 -- 参赛人数: 5000人 -- 场地数: 10个 -- 比赛天数: 7天 - -**预期结果**: 编排耗时 < 10秒 - ---- - -## 📝 部署日志模板 - -### 部署记录 - -**部署时间**: _______________ - -**部署人员**: _______________ - -**部署环境**: □ 开发环境 □ 测试环境 □ 生产环境 - -**执行步骤**: -- [ ] 1. 数据库表创建 -- [ ] 2. 测试数据导入 -- [ ] 3. 后端服务部署 -- [ ] 4. PowerJob任务配置 -- [ ] 5. 前端服务部署 -- [ ] 6. API接口测试 -- [ ] 7. 前端页面测试 -- [ ] 8. 定时任务测试 - -**遇到的问题**: -_________________________________ -_________________________________ -_________________________________ - -**解决方案**: -_________________________________ -_________________________________ -_________________________________ - -**部署结果**: □ 成功 □ 失败 - -**备注**: -_________________________________ -_________________________________ - ---- - -**文档版本**: v1.0 -**创建时间**: 2025-12-08 -**维护人**: 开发团队 diff --git a/docs/SCHEDULE_DEVELOPMENT_SUMMARY.md b/docs/SCHEDULE_DEVELOPMENT_SUMMARY.md deleted file mode 100644 index dcf5515..0000000 --- a/docs/SCHEDULE_DEVELOPMENT_SUMMARY.md +++ /dev/null @@ -1,254 +0,0 @@ -# 赛程编排系统开发总结 - -## ✅ 已完成工作 - -### 1. 前端开发 (martial-web) - -#### 1.1 页面重构 -- **文件**: `src/views/martial/schedule/index.vue` -- **改动**: 700+行代码重写 -- **核心变化**: - - 移除所有前端编排算法 - - 改为从后端API获取编排结果 - - 实现集体/个人项目差异化显示 - - 添加编排状态标签和锁定机制 - -#### 1.2 API集成 -- **文件**: `src/api/martial/activitySchedule.js` -- **新增接口**: - - `getScheduleResult(competitionId)` - 获取编排结果 - - `saveAndLockSchedule(competitionId)` - 保存并锁定 - -### 2. 后端开发 (martial-master) - -#### 2.1 数据库设计 -- **文件**: `database/martial-db/create_schedule_tables.sql` -- **表结构**: - - `martial_schedule_group` - 编排分组表 - - `martial_schedule_detail` - 编排明细表 - - `martial_schedule_participant` - 参赛者关联表 - - `martial_schedule_status` - 编排状态表 - -#### 2.2 实体类 (Entity) -创建4个实体类: -- `MartialScheduleGroup.java` -- `MartialScheduleDetail.java` -- `MartialScheduleParticipant.java` -- `MartialScheduleStatus.java` - -#### 2.3 数据访问层 (Mapper) -创建4个Mapper接口及XML: -- `MartialScheduleGroupMapper.java` + XML -- `MartialScheduleDetailMapper.java` + XML -- `MartialScheduleParticipantMapper.java` + XML -- `MartialScheduleStatusMapper.java` + XML - -#### 2.4 业务逻辑层 (Service) -- **接口**: `IMartialScheduleArrangeService.java` -- **实现**: `MartialScheduleArrangeServiceImpl.java` (600+行) -- **核心算法**: - - 自动分组算法: 按"项目+组别"分组 - - 负载均衡算法: 贪心算法分配场地时间段 - - 容量检查: 确保不超过时间段容量 - -#### 2.5 控制器层 (Controller) -- **文件**: `MartialScheduleArrangeController.java` -- **接口**: - - `GET /api/martial/schedule/result` - 获取编排结果 - - `POST /api/martial/schedule/save-and-lock` - 保存锁定 - - `POST /api/martial/schedule/auto-arrange` - 手动触发(测试用) - -#### 2.6 定时任务 (Job) -- **文件**: `ScheduleAutoArrangeProcessor.java` -- **功能**: 每10分钟自动编排未锁定的赛事 -- **框架**: PowerJob分布式任务调度 - -#### 2.7 文档 -- **部署指南**: `docs/SCHEDULE_DEPLOYMENT.md` -- **包含内容**: - - 部署步骤 - - API接口说明 - - 测试流程 - - 故障排查 - - 性能优化建议 - -### 3. 测试数据 (martial-web/test-data) -- **文件**: `create_100_team_participants.sql` -- **内容**: 100个集体队伍(500人) + 1000个个人项目参赛者 - ---- - -## 🎯 核心特性 - -### 1. 后端驱动编排 -- 定时任务每10分钟自动编排 -- 前端只负责展示结果 -- 减轻前端计算压力 - -### 2. 智能分组 -- 集体项目优先编排 -- 按"项目+组别"自动分组 -- 集体项目按单位分组展示 - -### 3. 负载均衡 -- 贪心算法: 优先分配到负载最小的时间段 -- 容量检查: 确保不超过时间段容量 -- 时间优化: 优先安排时长长的分组 - -### 4. 锁定机制 -- 保存后锁定编排 -- 锁定后不再自动更新 -- 防止意外修改 - ---- - -## 📂 文件清单 - -### 前端文件 (martial-web) -``` -src/views/martial/schedule/index.vue (修改, 700+行) -src/api/martial/activitySchedule.js (新增2个接口) -doc/schedule-system-design.md (设计文档) -test-data/create_100_team_participants.sql (测试数据) -``` - -### 后端文件 (martial-master) -``` -database/martial-db/create_schedule_tables.sql (数据库表) -src/main/java/org/springblade/modules/martial/pojo/entity/ - - MartialScheduleGroup.java (实体类) - - MartialScheduleDetail.java - - MartialScheduleParticipant.java - - MartialScheduleStatus.java - -src/main/java/org/springblade/modules/martial/mapper/ - - MartialScheduleGroupMapper.java + XML (Mapper) - - MartialScheduleDetailMapper.java + XML - - MartialScheduleParticipantMapper.java + XML - - MartialScheduleStatusMapper.java + XML - -src/main/java/org/springblade/modules/martial/service/ - - IMartialScheduleArrangeService.java (Service接口) - - impl/MartialScheduleArrangeServiceImpl.java (Service实现, 600+行) - -src/main/java/org/springblade/modules/martial/controller/ - - MartialScheduleArrangeController.java (Controller) - -src/main/java/org/springblade/job/processor/ - - ScheduleAutoArrangeProcessor.java (定时任务) - -docs/SCHEDULE_DEPLOYMENT.md (部署文档) -``` - ---- - -## 🚀 部署流程 - -### 1. 数据库初始化 -```bash -mysql -u root -p martial_competition < database/martial-db/create_schedule_tables.sql -``` - -### 2. 导入测试数据 -```bash -mysql -u root -p martial_competition < test-data/create_100_team_participants.sql -``` - -### 3. 启动后端服务 -```bash -cd martial-master -mvn clean package -DskipTests -java -jar target/martial-master.jar -``` - -### 4. 配置PowerJob定时任务 -- 访问PowerJob控制台: `http://localhost:7700` -- 创建定时任务 -- 处理器: `org.springblade.job.processor.ScheduleAutoArrangeProcessor` -- Cron: `0 */10 * * * ?` - -### 5. 启动前端服务 -```bash -cd martial-web -npm run dev -``` - -### 6. 测试 -访问: `http://localhost:3000/martial/schedule?competitionId=200` - ---- - -## ⚠️ 注意事项 - -### 1. Service层已优化 ✅ - -**已完成**: `MartialScheduleArrangeServiceImpl.java` 中的项目类型查询逻辑已修复 - -通过关联查询 `martial_project` 表获取项目类型: - -```java -// 在Service中注入 MartialProjectMapper -private final MartialProjectMapper projectMapper; - -// 在 autoGroupParticipants 方法中 -Map projectMap = new HashMap<>(); -for (MartialAthlete athlete : athletes) { - if (!projectMap.containsKey(athlete.getProjectId())) { - MartialProject project = projectMapper.selectById(athlete.getProjectId()); - projectMap.put(athlete.getProjectId(), project); - } -} - -// 使用projectMap获取项目类型 -Integer projectType = projectMap.get(athlete.getProjectId()).getType(); -``` - -**已完成**: `getScheduleResult` 方法中的字段名已修正 (line 233) - -```java -// 修正前: -pDetailWrapper.eq(MartialScheduleDetail::getScheduleDetailId, p.getScheduleDetailId()) - -// 修正后: -pDetailWrapper.eq(MartialScheduleDetail::getId, p.getScheduleDetailId()) -``` - -### 2. 测试数据字段映射 ✅ 已修复 - -**问题**: 测试数据脚本 `create_100_team_participants.sql` 插入的是 `martial_participant` 表,但代码中使用的是 `martial_athlete` 表 - -**解决方案**: 已将测试数据脚本修改为使用正确的表名和字段名 - -**修复内容**: -1. 批量替换 `martial_participant` → `martial_athlete` -2. 批量替换 `created_time` → `create_time` -3. 文件位置: `martial-web/test-data/create_100_team_participants.sql` - ---- - -## 📊 统计信息 - -- **新增代码**: 约2000行 -- **修改代码**: 约700行 -- **新增文件**: 20+个 -- **数据库表**: 4张 -- **API接口**: 3个 -- **定时任务**: 1个 - ---- - -## 📝 后续工作建议 - -1. **单元测试**: 编写Service层和Controller层的单元测试 -2. **集成测试**: 端到端测试整个编排流程 -3. **性能测试**: 测试1000+参赛者的编排性能 -4. **监控告警**: 添加编排失败告警机制 -5. **日志优化**: 完善关键操作日志记录 - -**所有已知问题已修复,系统已达到生产就绪状态!** ✅ - ---- - -**开发时间**: 2025-12-08 -**开发人员**: Claude Code Assistant -**文档版本**: v1.0 diff --git a/docs/SCHEDULE_FINAL_STATUS.md b/docs/SCHEDULE_FINAL_STATUS.md deleted file mode 100644 index f1c9e36..0000000 --- a/docs/SCHEDULE_FINAL_STATUS.md +++ /dev/null @@ -1,270 +0,0 @@ -# 赛程编排系统最终状态报告 - -## ✅ 项目状态: 生产就绪 - -**完成时间**: 2025-12-09 -**最终验证**: 所有已知问题已修复 -**代码状态**: 可部署到生产环境 - ---- - -## 📋 完成工作清单 - -### 1. 后端开发 (100% 完成) - -#### 数据库层 ✅ -- [x] 4张核心表设计与创建 -- [x] 索引和约束优化 -- [x] 表名一致性验证 - -#### 实体层 ✅ -- [x] 4个实体类(Entity) -- [x] 使用标准注解(@TableName, @Schema) -- [x] 继承TenantEntity实现多租户 - -#### 数据访问层 ✅ -- [x] 4个Mapper接口 -- [x] 4个MyBatis XML文件 -- [x] 标准CRUD操作 - -#### 业务逻辑层 ✅ -- [x] Service接口定义 -- [x] Service实现(600+行核心算法) -- [x] 自动分组算法 -- [x] 负载均衡算法 -- [x] 项目类型查询优化 -- [x] N+1查询问题优化 - -#### 控制器层 ✅ -- [x] REST API控制器 -- [x] 3个核心接口 -- [x] 参数验证 -- [x] 异常处理 - -#### 定时任务 ✅ -- [x] PowerJob处理器 -- [x] 定时编排逻辑 -- [x] 任务日志记录 - -### 2. 测试数据 (100% 完成) - -#### 测试数据脚本 ✅ -- [x] 100个集体队伍(500人) -- [x] 5个项目类型 -- [x] 表名一致性修正 -- [x] 字段名统一修正 - -### 3. 文档 (100% 完成) - -#### 技术文档 ✅ -- [x] 部署指南(SCHEDULE_DEPLOYMENT.md) -- [x] 开发总结(SCHEDULE_DEVELOPMENT_SUMMARY.md) -- [x] 部署检查清单(SCHEDULE_DEPLOYMENT_CHECKLIST.md) -- [x] 完成报告(SCHEDULE_COMPLETION_REPORT.md) -- [x] 最终状态报告(本文档) - ---- - -## 🔧 修复记录 - -### 修复 #1: 项目类型查询优化 -- **问题**: MartialAthlete实体缺少projectType字段 -- **影响**: 无法区分集体/个人项目 -- **解决**: 通过MartialProjectMapper查询项目表 -- **优化**: 实现项目信息缓存,避免N+1查询 -- **状态**: ✅ 已修复并优化 - -### 修复 #2: 字段名错误 -- **问题**: getScheduleResult方法使用不存在的scheduleDetailId字段 -- **位置**: MartialScheduleArrangeServiceImpl.java:233 -- **解决**: 改为使用正确的id字段 -- **状态**: ✅ 已修复 - -### 修复 #3: 测试数据表名不一致 -- **问题**: 测试数据使用martial_participant表,代码使用martial_athlete表 -- **影响**: 测试数据无法正确导入 -- **解决**: 批量修正测试数据脚本 - - martial_participant → martial_athlete - - created_time → create_time -- **状态**: ✅ 已修复 - ---- - -## 🎯 核心功能验证 - -### 功能 #1: 自动编排算法 ✅ -- **分组策略**: 按"项目+组别"自动分组 -- **优先级**: 集体项目优先 -- **时长计算**: - - 集体: 队伍数 × 5分钟 + 间隔 - - 个人: (人数/6) × 8分钟 -- **状态**: 逻辑完整,算法正确 - -### 功能 #2: 负载均衡 ✅ -- **算法**: 贪心算法 -- **策略**: 优先分配到负载最小的时间段 -- **容量检查**: 自动验证时间段容量 -- **时间优化**: 先安排长时段项目 -- **状态**: 算法验证通过 - -### 功能 #3: 定时任务 ✅ -- **框架**: PowerJob分布式调度 -- **频率**: 每10分钟执行 -- **查询**: 自动获取未锁定赛事 -- **处理**: 批量执行编排 -- **日志**: 完整的执行日志 -- **状态**: 集成完成 - -### 功能 #4: 锁定机制 ✅ -- **保存锁定**: 防止自动覆盖 -- **状态管理**: 0未编排/1编排中/2已锁定 -- **用户记录**: 记录锁定操作人 -- **时间记录**: 记录锁定时间 -- **状态**: 机制完整 - ---- - -## 📊 代码质量指标 - -### 代码规模 -- **新增代码**: ~2000行 -- **修改代码**: ~700行(前端) -- **新增文件**: 24个 -- **文档文件**: 5个 - -### 代码质量 -- **注释覆盖**: 100% (所有类和方法) -- **命名规范**: 遵循Java驼峰命名 -- **异常处理**: 完整的try-catch和事务回滚 -- **日志记录**: 关键操作均有日志 - -### 性能优化 -- **N+1查询**: 已优化(项目信息缓存) -- **批量操作**: 使用批量插入 -- **索引优化**: 关键字段已建索引 -- **容量检查**: 编排前验证容量 - ---- - -## 🚀 部署准备 - -### 数据库准备 ✅ -- [x] 表创建脚本已就绪 -- [x] 测试数据脚本已修正 -- [x] 索引已优化 - -### 代码准备 ✅ -- [x] 所有代码已编写 -- [x] 所有bug已修复 -- [x] 代码已通过静态检查 - -### 文档准备 ✅ -- [x] 部署文档完整 -- [x] API文档齐全 -- [x] 测试流程清晰 - -### 环境准备 (待确认) -- [ ] PowerJob服务 -- [ ] MySQL数据库 -- [ ] 后端应用服务器 -- [ ] 前端Web服务器 - ---- - -## 📝 部署步骤(快速参考) - -### 1. 数据库初始化 -```bash -mysql -u root -p martial_competition < database/martial-db/create_schedule_tables.sql -``` - -### 2. 导入测试数据 -```bash -mysql -u root -p martial_competition < martial-web/test-data/create_100_team_participants.sql -``` - -### 3. 编译部署后端 -```bash -cd martial-master -mvn clean package -DskipTests -java -jar target/martial-master.jar -``` - -### 4. 配置PowerJob -- 控制台: `http://localhost:7700` -- 处理器: `org.springblade.job.processor.ScheduleAutoArrangeProcessor` -- Cron: `0 */10 * * * ?` - -### 5. 部署前端 -```bash -cd martial-web -npm run dev -``` - -### 6. 验证测试 -- 手动触发: `POST /api/martial/schedule/auto-arrange` -- 查看结果: `GET /api/martial/schedule/result?competitionId=200` -- 前端访问: `http://localhost:3000/martial/schedule?competitionId=200` - ---- - -## ⚠️ 注意事项 - -### 1. 数据一致性 -- 确保martial_athlete表存在 -- 确保martial_project表有测试数据 -- 确保martial_venue表已配置场地 - -### 2. PowerJob配置 -- 确保PowerJob服务已启动 -- 确保Worker已连接 -- 确保任务配置正确 - -### 3. 时间配置 -- 默认上午: 08:30-11:30 (150分钟) -- 默认下午: 13:30-17:30 (210分钟) -- 可根据实际情况调整Service层配置 - -### 4. 性能考虑 -- 建议参赛人数 < 5000人/赛事 -- 建议场地数 >= 5个 -- 建议比赛天数 >= 3天 - ---- - -## 🎉 项目亮点 - -### 技术亮点 -1. **后端驱动**: 自动编排,减轻前端压力 -2. **智能算法**: 贪心算法实现负载均衡 -3. **分布式任务**: PowerJob支持高可用 -4. **性能优化**: 缓存优化,避免N+1查询 -5. **完整文档**: 5份文档覆盖全流程 - -### 业务亮点 -1. **自动化**: 无需手动编排,节省时间 -2. **智能化**: 自动分组,智能分配 -3. **可靠性**: 锁定机制防止误操作 -4. **可扩展**: 支持大规模赛事编排 - ---- - -## ✅ 最终结论 - -**赛程编排系统后端开发已全部完成,所有已知问题已修复,代码已达到生产就绪状态。** - -**系统特点**: -- ✅ 架构清晰,分层明确 -- ✅ 算法完整,逻辑正确 -- ✅ 代码规范,质量高 -- ✅ 文档齐全,易部署 -- ✅ 零已知缺陷 - -**建议**: 可以开始部署到测试环境进行集成测试。 - ---- - -**文档版本**: v1.0 Final -**完成时间**: 2025-12-09 -**开发团队**: Claude Code Assistant -**项目状态**: ✅ 生产就绪 diff --git a/docs/SCHEDULE_SYSTEM_TEST_REPORT.md b/docs/SCHEDULE_SYSTEM_TEST_REPORT.md deleted file mode 100644 index f832d7d..0000000 --- a/docs/SCHEDULE_SYSTEM_TEST_REPORT.md +++ /dev/null @@ -1,223 +0,0 @@ -# 赛程自动编排系统 - 测试报告 - -## 测试时间 -2025-12-09 - -## 测试环境 -- 后端服务: http://localhost:8123 -- 数据库: martial_db -- 测试赛事ID: 200 - -## 系统架构 - -### 数据库表结构 (新系统 - 4张表) -1. **martial_schedule_status** - 赛程状态表 - - 记录每个赛事的编排状态 (0=未编排, 1=已编排, 2=已锁定) - -2. **martial_schedule_group** - 赛程分组表 - - 存储自动生成的分组信息 - - 按"项目ID_组别"进行分组 - -3. **martial_schedule_detail** - 赛程详情表 - - 存储每个分组分配的场地和时间段 - -4. **martial_schedule_participant** - 赛程参赛者表 - - 记录每个参赛者所属的分组和表演顺序 - -### 核心算法 -1. **自动分组算法** (`autoGroupParticipants`) - - 集体项目: 按"项目ID_组别"分组,统计队伍数 - - 个人项目: 按"项目ID_组别"分组 - - 计算预计时长: - - 集体: 队伍数 × 5分钟 + 间隔 - - 个人: (人数/6向上取整) × 8分钟 - -2. **负载均衡算法** (`assignVenueAndTimeSlot`) - - 贪心算法: 优先分配给负载最低的场地×时间段 - - 按预计时长降序排序(先安排长项目) - - 检查容量限制 - -## 测试过程 - -### 1. 数据库初始化 -```sql --- 执行脚本: upgrade_schedule_system.sql --- 创建4张新表,与旧表共存 -``` - -**结果**: ✅ 成功创建所有表 - -### 2. 测试数据准备 -```sql --- 执行脚本: init_test_data.sql --- 赛事ID: 200 --- 场地数: 4个 --- 项目数: 5个 (集体项目) --- 参赛者: 20人 (4个队伍) -``` - -**结果**: ✅ 测试数据创建成功 - -### 3. 代码BUG修复 - -#### Bug 1: NPE - 项目信息缺失 -**位置**: `MartialScheduleArrangeServiceImpl.java:394, 430` - -**问题**: 当参赛者的project_id在项目表中不存在时,访问project对象导致NPE - -**修复**: -```java -// 跳过没有项目信息的分组 -if (project == null) { - log.warn("项目不存在, projectId: {}, 跳过该分组", first.getProjectId()); - continue; -} -``` - -**结果**: ✅ 已修复 - -#### Bug 2: 逻辑错误 - 删除数据顺序错误 -**位置**: `MartialScheduleArrangeServiceImpl.java:527-546` - -**问题**: 先删除父表(scheduleGroup),再查询已删除的数据构建子表删除条件,导致空列表传入`.in()`方法 - -**修复**: -```java -// 先查询出所有分组ID,然后再删除 -List groupIds = scheduleGroupMapper.selectList(groupWrapper).stream() - .map(MartialScheduleGroup::getId) - .collect(Collectors.toList()); - -// 删除参赛者关联(必须在删除分组之前) -if (groupIds != null && !groupIds.isEmpty()) { - LambdaQueryWrapper participantWrapper = new LambdaQueryWrapper<>(); - participantWrapper.in(MartialScheduleParticipant::getScheduleGroupId, groupIds); - scheduleParticipantMapper.delete(participantWrapper); -} - -// 最后删除分组 -scheduleGroupMapper.delete(groupWrapper); -``` - -**结果**: ✅ 已修复 - -### 4. API测试 - -#### 4.1 自动编排 API -```bash -curl -X POST "http://localhost:8123/martial/schedule/auto-arrange" \ - -H "Content-Type: application/json" \ - -d '{"competitionId": 200}' -``` - -**响应**: -```json -{ - "code": 200, - "success": true, - "data": {}, - "msg": "自动编排完成" -} -``` - -**结果**: ✅ 成功 - -#### 4.2 查询编排结果 API -```bash -curl -X GET "http://localhost:8123/martial/schedule/result?competitionId=200" -``` - -**响应摘要**: -```json -{ - "code": 200, - "success": true, - "data": { - "scheduleStatus": 1, - "totalGroups": 7, - "totalParticipants": 1000, - "scheduleGroups": [...] - } -} -``` - -**结果**: ✅ 成功 -- 生成了7个分组 -- 1000名参赛者全部分配完成 -- 每个参赛者都有场地和时间段信息 - -### 5. 定时任务处理器 -**类**: `ScheduleAutoArrangeProcessor` -- 使用 PowerJob 框架 -- Cron: `0 */10 * * * ?` (每10分钟执行) -- 功能: 自动查询未锁定赛事并执行编排 - -**结果**: ✅ 代码正确,需在PowerJob控制台配置 - -## 测试结果 - -### 成功项 ✅ -1. 数据库表创建成功,新旧表共存 -2. 自动分组算法正常工作 -3. 负载均衡算法正确分配场地和时间 -4. API接口响应正常 -5. 1000名参赛者全部成功编排 -6. 代码BUG已全部修复 - -### 编排数据验证 -- **分组逻辑**: 按"项目_组别"正确分组 -- **场地分配**: 负载均衡,使用了4个场地 -- **时间分配**: 分散在3天 (2025-11-06 至 2025-11-08) -- **时段分配**: 包含上午和下午时段 -- **参赛者关联**: 每个参赛者都有完整的场地时间信息 - -## 待完成事项 -1. 在 PowerJob 控制台配置定时任务 -2. 实现"保存并锁定"功能的前端页面 -3. 添加编排结果导出功能 (Excel/PDF) -4. 前端展示优化 (可视化时间轴) - -## 结论 -✅ **赛程自动编排系统核心功能测试通过!** - -系统已具备: -- 自动分组能力 -- 负载均衡调度能力 -- 大规模数据处理能力 (1000+参赛者) -- 完整的API接口 -- 数据持久化和查询能力 - ---- - -## API文档 - -### 1. 触发自动编排 -```http -POST /martial/schedule/auto-arrange -Content-Type: application/json - -{ - "competitionId": 200 -} -``` - -### 2. 查询编排结果 -```http -GET /martial/schedule/result?competitionId=200 -``` - -### 3. 保存并锁定编排 -```http -POST /martial/schedule/save-and-lock -Content-Type: application/json - -{ - "competitionId": 200, - "userId": "xxx" -} -``` - -### 4. 查询未锁定赛事列表 -```http -GET /martial/schedule/unlocked-competitions -``` diff --git a/docs/SCHEDULE_TABLES_COMPLEXITY_ANALYSIS.md b/docs/SCHEDULE_TABLES_COMPLEXITY_ANALYSIS.md deleted file mode 100644 index 4e64077..0000000 --- a/docs/SCHEDULE_TABLES_COMPLEXITY_ANALYSIS.md +++ /dev/null @@ -1,399 +0,0 @@ -# 赛程编排表结构复杂性深度分析 - -**分析日期**: 2026-01-18 -**分析人**: Droid (Google Database Engineer) -**问题**: 10 个赛程编排表关系复杂,维护困难 - ---- - -## 📊 当前表结构全景 - -### 10 个表的职责分析 - -| 表名 | 核心职责 | 字段数 | 关键关系 | 问题评级 | -|------|---------|--------|---------|---------| -| **martial_schedule** | 赛程主表(旧) | 24 | competition_id, venue_id, project_id | 🔴 冗余 | -| **martial_schedule_group** | 分组信息 | 19 | competition_id, project_id | 🟢 合理 | -| **martial_schedule_detail** | 场地时间分配 | 22 | schedule_group_id, venue_id | 🟢 合理 | -| **martial_schedule_participant** | 参赛者关联 | 19 | schedule_detail_id, participant_id | 🟢 合理 | -| **martial_schedule_athlete** | 选手赛程关联(旧) | 14 | schedule_id, athlete_id | 🔴 冗余 | -| **martial_schedule_plan** | 编排方案 | 21 | competition_id | 🟡 可选 | -| **martial_schedule_slot** | 时间槽 | 17 | plan_id, venue_id, project_id | 🟡 重复 | -| **martial_schedule_athlete_slot** | 选手时间槽 | 16 | slot_id, athlete_id | 🟡 重复 | -| **martial_schedule_conflict** | 冲突记录 | 16 | plan_id | 🟢 辅助 | -| **martial_schedule_adjustment_log** | 调整日志 | 16 | plan_id | 🟢 辅助 | -| **martial_schedule_status** | 编排状态 | 16 | competition_id (UNIQUE) | 🟢 合理 | - ---- - -## 🔍 核心问题剖析 - -### 问题 1: 三套并行的编排体系 ⚠️⚠️⚠️ - -#### 体系 A: 旧版编排(2 表) -``` -martial_schedule (赛程主表) - ↓ -martial_schedule_athlete (选手关联) -``` - -**字段内容**: -- martial_schedule: group_title, venue_id, project_id, schedule_date, time_slot -- martial_schedule_athlete: schedule_id, athlete_id, order_num - -#### 体系 B: 新版编排(3 表) -``` -martial_schedule_group (分组) - ↓ -martial_schedule_detail (场地时间) - ↓ -martial_schedule_participant (参赛者) -``` - -**字段内容**: -- martial_schedule_group: group_name, project_id, display_order -- martial_schedule_detail: venue_id, schedule_date, time_slot -- martial_schedule_participant: participant_id, performance_order - -#### 体系 C: 方案编排(3 表) -``` -martial_schedule_plan (方案) - ↓ -martial_schedule_slot (时间槽) - ↓ -martial_schedule_athlete_slot (选手时间槽) -``` - -**字段内容**: -- martial_schedule_plan: plan_name, status, rules -- martial_schedule_slot: venue_id, slot_date, start_time -- martial_schedule_athlete_slot: athlete_id, appearance_order - -### 🔴 严重问题:三套体系功能重叠! - -| 功能 | 体系A (旧) | 体系B (新) | 体系C (方案) | -|------|-----------|-----------|-------------| -| **分组信息** | martial_schedule.group_title | martial_schedule_group.group_name | - | -| **场地分配** | martial_schedule.venue_id | martial_schedule_detail.venue_id | martial_schedule_slot.venue_id | -| **时间安排** | martial_schedule.time_slot | martial_schedule_detail.time_slot | martial_schedule_slot.start_time | -| **选手关联** | martial_schedule_athlete | martial_schedule_participant | martial_schedule_athlete_slot | -| **出场顺序** | martial_schedule_athlete.order_num | martial_schedule_participant.performance_order | martial_schedule_athlete_slot.appearance_order | - -**结论**: 同一个业务逻辑被实现了 3 次! - ---- - -### 问题 2: 字段冗余严重 - -#### 2.1 martial_schedule_group 的冗余 - -```sql -project_id bigint NOT NULL -project_name varchar(100) -- 冗余!可以从 martial_project 表获取 -category varchar(50) -- 冗余!可以从 martial_project 表获取 -``` - -#### 2.2 martial_schedule_detail 的冗余 - -```sql -venue_name varchar(100) -- 冗余!可以从 martial_venue 表获取 -``` - -#### 2.3 martial_schedule_participant 的冗余 - -```sql -organization varchar(200) -- 冗余!可以从 martial_athlete 表获取 -player_name varchar(100) -- 冗余!可以从 martial_athlete 表获取 -project_name varchar(100) -- 冗余!可以从 martial_project 表获取 -category varchar(50) -- 冗余!可以从 martial_project 表获取 -``` - -**问题**: -- ❌ 数据不一致风险(athlete 表更新了姓名,这里没更新) -- ❌ 存储空间浪费 -- ❌ 更新维护成本高 - ---- - -### 问题 3: martial_schedule_plan 体系的必要性存疑 - -#### 当前设计意图 -``` -martial_schedule_plan (编排方案) - ↓ -martial_schedule_slot (时间槽) - ↓ -martial_schedule_athlete_slot (选手时间槽) -``` - -#### 🤔 与现有体系的重复 - -| 功能 | martial_schedule_slot | martial_schedule_detail | -|------|----------------------|------------------------| -| 场地 | venue_id | venue_id ✅ | -| 日期 | slot_date | schedule_date ✅ | -| 时间 | start_time/end_time | time_slot ✅ | -| 项目 | project_id | (通过 group_id 关联) ✅ | -| 排序 | sort_order | sort_order ✅ | - -| 功能 | martial_schedule_athlete_slot | martial_schedule_participant | -|------|------------------------------|----------------------------| -| 选手 | athlete_id | participant_id ✅ | -| 顺序 | appearance_order | performance_order ✅ | -| 签到 | check_in_status | check_in_status ✅ | -| 状态 | performance_status | status ✅ | - -**结论**: martial_schedule_plan 体系与 martial_schedule_group/detail/participant 体系功能 90% 重复! - ---- - -### 问题 4: 查询复杂度高 - -#### 场景 1: 查询某赛事的完整赛程 - -**使用新体系**: -```sql -SELECT - sg.group_name, - sd.venue_name, - sd.schedule_date, - sd.time_slot, - sp.player_name, - sp.performance_order -FROM martial_schedule_group sg -JOIN martial_schedule_detail sd ON sg.id = sd.schedule_group_id -JOIN martial_schedule_participant sp ON sd.id = sp.schedule_detail_id -WHERE sg.competition_id = ? - AND sg.is_deleted = 0 - AND sd.is_deleted = 0 - AND sp.is_deleted = 0 -ORDER BY sd.schedule_date, sd.time_slot, sp.performance_order; -``` - -**问题**: 需要 3 次 JOIN - -#### 场景 2: 查询某选手的所有赛程 - -**如果使用旧体系**: -```sql -SELECT * FROM martial_schedule_athlete WHERE athlete_id = ?; -``` - -**如果使用新体系**: -```sql -SELECT * FROM martial_schedule_participant WHERE participant_id = ?; -``` - -**如果使用方案体系**: -```sql -SELECT * FROM martial_schedule_athlete_slot WHERE athlete_id = ?; -``` - -**问题**: -- ❌ 不知道该查哪个表 -- ❌ 数据可能分散在多个表中 -- ❌ 需要 UNION 查询 - ---- - -### 问题 5: 数据一致性维护困难 - -#### 场景: 修改某选手的出场时间 - -**需要更新的表**: -1. martial_schedule_athlete (如果使用旧体系) -2. martial_schedule_participant (如果使用新体系) -3. martial_schedule_athlete_slot (如果使用方案体系) -4. martial_schedule_detail (可能需要调整时间段) -5. martial_schedule_adjustment_log (记录调整日志) - -**问题**: -- ❌ 需要在应用层保证多表事务一致性 -- ❌ 容易遗漏某个表的更新 -- ❌ 回滚困难 - ---- - -## 💡 优化方案 - -### 方案 1: 统一到新体系(推荐)⭐⭐⭐⭐⭐ - -#### 保留的表(4 个核心表) - -``` -martial_schedule_group (分组信息) - ↓ -martial_schedule_detail (场地时间分配) - ↓ -martial_schedule_participant (参赛者关联) - ↓ -martial_schedule_status (编排状态) -``` - -#### 辅助表(2 个) - -``` -martial_schedule_conflict (冲突记录 - 可选) -martial_schedule_adjustment_log (调整日志 - 可选) -``` - -#### 废弃的表(4 个) - -``` -❌ martial_schedule (旧体系,功能被 group+detail 替代) -❌ martial_schedule_athlete (旧体系,功能被 participant 替代) -❌ martial_schedule_plan (方案体系,功能重复) -❌ martial_schedule_slot (方案体系,功能被 detail 替代) -❌ martial_schedule_athlete_slot (方案体系,功能被 participant 替代) -``` - -#### 优化后的表结构 - -**martial_schedule_group** (去除冗余字段) -```sql -CREATE TABLE martial_schedule_group ( - id bigint NOT NULL AUTO_INCREMENT, - competition_id bigint NOT NULL, - group_name varchar(200) NOT NULL, - project_id bigint NOT NULL, - -- 删除 project_name (冗余) - -- 删除 category (冗余) - project_type tinyint(1) NOT NULL DEFAULT 1, - display_order int NOT NULL DEFAULT 0, - total_participants int DEFAULT 0, - total_teams int DEFAULT 0, - estimated_duration int DEFAULT 0, - -- 标准字段 - create_user bigint, - create_dept bigint, - create_time datetime DEFAULT CURRENT_TIMESTAMP, - update_user bigint, - update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - status int DEFAULT 1, - is_deleted int DEFAULT 0, - tenant_id varchar(12) DEFAULT '000000', - PRIMARY KEY (id), - KEY idx_competition (competition_id), - KEY idx_project (project_id), - KEY idx_display_order (display_order) -) COMMENT='赛程编排分组表'; -``` - -**martial_schedule_detail** (去除冗余字段) -```sql -CREATE TABLE martial_schedule_detail ( - id bigint NOT NULL AUTO_INCREMENT, - schedule_group_id bigint NOT NULL, - competition_id bigint NOT NULL, - venue_id bigint NOT NULL, - -- 删除 venue_name (冗余) - schedule_date date NOT NULL, - time_period varchar(20) NOT NULL, - time_slot varchar(20) NOT NULL, - time_slot_index int DEFAULT 0, - estimated_start_time datetime, - estimated_end_time datetime, - estimated_duration int DEFAULT 0, - participant_count int DEFAULT 0, - sort_order int DEFAULT 0, - -- 标准字段 - create_user bigint, - create_dept bigint, - create_time datetime DEFAULT CURRENT_TIMESTAMP, - update_user bigint, - update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - status int DEFAULT 1, - is_deleted int DEFAULT 0, - tenant_id varchar(12) DEFAULT '000000', - PRIMARY KEY (id), - KEY idx_group (schedule_group_id), - KEY idx_competition (competition_id), - KEY idx_venue_time (venue_id, schedule_date, time_slot) -) COMMENT='赛程编排明细表'; -``` - -**martial_schedule_participant** (去除冗余字段) -```sql -CREATE TABLE martial_schedule_participant ( - id bigint NOT NULL AUTO_INCREMENT, - schedule_detail_id bigint NOT NULL, - schedule_group_id bigint NOT NULL, - participant_id bigint NOT NULL, - -- 删除 organization (冗余) - -- 删除 player_name (冗余) - -- 删除 project_name (冗余) - -- 删除 category (冗余) - performance_order int DEFAULT 0, - check_in_status varchar(20) DEFAULT '未签到', - schedule_status varchar(20) DEFAULT 'draft', - -- 标准字段 - create_user bigint, - create_dept bigint, - create_time datetime DEFAULT CURRENT_TIMESTAMP, - update_user bigint, - update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - status int DEFAULT 1, - is_deleted int DEFAULT 0, - tenant_id varchar(12) DEFAULT '000000', - PRIMARY KEY (id), - KEY idx_detail (schedule_detail_id), - KEY idx_group (schedule_group_id), - KEY idx_participant (participant_id) -) COMMENT='赛程编排参赛者关联表'; -``` - -#### 优化效果 - -| 指标 | 优化前 | 优化后 | 改善 | -|------|--------|--------|------| -| **表数量** | 10 个 | 4 个核心 + 2 个辅助 | ⬇️ 40% | -| **冗余字段** | 8 个 | 0 个 | ⬇️ 100% | -| **JOIN 层级** | 3-4 层 | 2-3 层 | ⬇️ 25% | -| **数据一致性** | 困难 | 简单 | ⬆️ 80% | -| **查询复杂度** | 高 | 中 | ⬆️ 50% | - ---- - -## 🎯 总结 - -### 核心问题 - -1. **三套并行体系**: 旧体系、新体系、方案体系功能重叠 90% -2. **字段冗余严重**: 8 个冗余字段,数据一致性风险高 -3. **查询复杂度高**: 不知道该查哪个表,需要多次 JOIN -4. **维护成本高**: 修改一个数据需要更新多个表 - -### 推荐方案 - -**统一到新体系(方案 1)**: -- ✅ 保留 4 个核心表 + 2 个辅助表 -- ✅ 废弃 4 个冗余表 -- ✅ 去除 8 个冗余字段 -- ✅ 降低 40% 复杂度 - -### 预期收益 - -| 指标 | 改善幅度 | -|------|---------| -| **表数量** | ⬇️ 40% (10→6) | -| **代码复杂度** | ⬇️ 50% | -| **查询性能** | ⬆️ 30% | -| **维护成本** | ⬇️ 60% | -| **数据一致性** | ⬆️ 80% | - -### 工作量评估 - -| 阶段 | 工作量 | 风险 | -|------|--------|------| -| 数据迁移 | 1-2 天 | 🟢 低 | -| 代码重构 | 3-5 天 | 🟡 中 | -| 测试验证 | 2-3 天 | 🟢 低 | -| 灰度发布 | 1 周 | 🟡 中 | -| 清理旧表 | 1 天 | 🟢 低 | -| **总计** | **2-3 周** | **🟡 中** | - ---- - -**分析完成时间**: 2026-01-18 - -*"Simplicity is the ultimate sophistication." - Leonardo da Vinci* diff --git a/docs/TEST_PLAN.md b/docs/TEST_PLAN.md deleted file mode 100644 index cb6f134..0000000 --- a/docs/TEST_PLAN.md +++ /dev/null @@ -1,290 +0,0 @@ -# 武术比赛评分系统 - 测试规划文档 - -## 一、测试现状分析 - -### 1.1 现有测试类(4个) -| 测试类 | 覆盖模块 | 测试数量 | 状态 | -|--------|----------|----------|------| -| MartialAthleteServiceTest | 运动员服务 | 15 | 基础 | -| MartialScoreServiceTest | 评分服务 | 10 | 基础 | -| MartialResultServiceTest | 成绩服务 | - | 待检查 | -| MartialSchedulePlanServiceTest | 赛程计划 | - | 待检查 | - -### 1.2 待测试模块(24个Service) -| 优先级 | 模块 | 复杂度 | 业务重要性 | -|--------|------|--------|------------| -| P0 | MartialCompetitionService | 高 | 核心 | -| P0 | MartialProjectService | 高 | 核心 | -| P0 | MartialScoreService | 高 | 核心 | -| P0 | MartialResultService | 高 | 核心 | -| P0 | MartialScheduleArrangeService | 高 | 核心 | -| P1 | MartialAthleteService | 中 | 重要 | -| P1 | MartialRegistrationOrderService | 中 | 重要 | -| P1 | MartialJudgeService | 中 | 重要 | -| P1 | MartialTeamService | 中 | 重要 | -| P1 | MartialVenueService | 低 | 重要 | -| P2 | MartialSchedulePlanService | 中 | 一般 | -| P2 | MartialScheduleAthleteService | 中 | 一般 | -| P2 | MartialDeductionItemService | 低 | 一般 | -| P2 | MartialExceptionEventService | 低 | 一般 | -| P3 | MartialBannerService | 低 | 辅助 | -| P3 | MartialInfoPublishService | 低 | 辅助 | -| P3 | MartialLiveUpdateService | 低 | 辅助 | -| P3 | MartialContactService | 低 | 辅助 | -| P3 | MartialActivityScheduleService | 低 | 辅助 | -| P3 | MartialCompetitionAttachmentService | 低 | 辅助 | -| P3 | MartialCompetitionRulesService | 低 | 辅助 | -| P3 | MartialJudgeInviteService | 低 | 辅助 | -| P3 | MartialJudgeProjectService | 低 | 辅助 | -| P3 | MartialScheduleService | 低 | 辅助 | - -## 二、测试策略 - -### 2.1 测试金字塔 -``` - /\ - / \ E2E Tests (5%) - /----\ - API集成测试 - / \ - /--------\ Integration Tests (20%) - / \ - Service层集成测试 - /------------\- 数据库交互测试 - / \ - /----------------\ Unit Tests (75%) - - Service单元测试 - - 工具类测试 - - 验证逻辑测试 -``` - -### 2.2 测试类型 -1. **单元测试 (Unit Tests)** - - 使用 Mockito 模拟依赖 - - 测试业务逻辑正确性 - - 测试边界条件和异常处理 - -2. **集成测试 (Integration Tests)** - - 使用 @SpringBootTest - - 测试数据库交互 - - 测试事务处理 - -3. **API测试 (Controller Tests)** - - 使用 MockMvc - - 测试请求/响应格式 - - 测试权限验证 - -## 三、测试规范 - -### 3.1 命名规范 -``` -测试类命名: - {被测类名}Test.java - 单元测试 - {被测类名}IntegrationTest.java - 集成测试 - {Controller名}ApiTest.java - API测试 - -测试方法命名: - test_{方法名}_{场景}_{预期结果}() - -示例: - test_calculateScore_validInput_returnsCorrectScore() - test_submitScore_duplicateSubmit_throwsException() -``` - -### 3.2 测试结构 (AAA模式) -```java -@Test -@DisplayName("描述测试场景") -void test_methodName_scenario_expectedResult() { - // Arrange - 准备测试数据 - - // Act - 执行被测方法 - - // Assert - 验证结果 -} -``` - -### 3.3 断言规范 -- 使用 AssertJ 或 JUnit5 断言 -- 每个测试方法只测试一个场景 -- 断言信息要清晰明确 - -## 四、实施计划 - -### Phase 1: P0 核心模块测试 (Week 1) -| 任务 | 测试类 | 测试用例数 | 状态 | -|------|--------|------------|------| -| 1.1 | MartialCompetitionServiceTest | 20+ | 待开发 | -| 1.2 | MartialProjectServiceTest | 15+ | 待开发 | -| 1.3 | MartialScoreServiceTest | 25+ | 增强 | -| 1.4 | MartialResultServiceTest | 20+ | 增强 | -| 1.5 | MartialScheduleArrangeServiceTest | 30+ | 待开发 | - -### Phase 2: P1 重要模块测试 (Week 2) -| 任务 | 测试类 | 测试用例数 | 状态 | -|------|--------|------------|------| -| 2.1 | MartialAthleteServiceTest | 25+ | 增强 | -| 2.2 | MartialRegistrationOrderServiceTest | 20+ | 待开发 | -| 2.3 | MartialJudgeServiceTest | 15+ | 待开发 | -| 2.4 | MartialTeamServiceTest | 15+ | 待开发 | -| 2.5 | MartialVenueServiceTest | 10+ | 待开发 | - -### Phase 3: P2 一般模块测试 (Week 3) -| 任务 | 测试类 | 测试用例数 | 状态 | -|------|--------|------------|------| -| 3.1 | MartialSchedulePlanServiceTest | 15+ | 增强 | -| 3.2 | MartialScheduleAthleteServiceTest | 15+ | 待开发 | -| 3.3 | MartialDeductionItemServiceTest | 10+ | 待开发 | -| 3.4 | MartialExceptionEventServiceTest | 10+ | 待开发 | - -### Phase 4: P3 辅助模块 + 集成测试 (Week 4) -| 任务 | 测试类 | 测试用例数 | 状态 | -|------|--------|------------|------| -| 4.1 | 辅助模块单元测试 | 50+ | 待开发 | -| 4.2 | Controller API测试 | 30+ | 待开发 | -| 4.3 | 集成测试 | 20+ | 待开发 | - -## 五、测试用例设计 - -### 5.1 MartialCompetitionServiceTest (赛事管理) -``` -创建赛事: - - test_createCompetition_validData_success - - test_createCompetition_duplicateCode_throwsException - - test_createCompetition_invalidDateRange_throwsException - - test_createCompetition_missingRequiredFields_throwsException - -更新赛事: - - test_updateCompetition_validData_success - - test_updateCompetition_notFound_throwsException - - test_updateCompetition_statusLocked_throwsException - -查询赛事: - - test_getCompetitionById_exists_returnsCompetition - - test_getCompetitionById_notExists_returnsNull - - test_listCompetitions_withPagination_returnsPage - - test_listCompetitions_byStatus_filtersCorrectly - -赛事状态: - - test_startCompetition_validState_success - - test_startCompetition_alreadyStarted_throwsException - - test_endCompetition_validState_success - - test_endCompetition_notStarted_throwsException - -统计功能: - - test_getCompetitionStats_returnsCorrectCounts - - test_getTotalParticipants_calculatesCorrectly -``` - -### 5.2 MartialScoreServiceTest (评分管理) -``` -提交评分: - - test_submitScore_validScore_success - - test_submitScore_outOfRange_throwsException - - test_submitScore_duplicateSubmit_throwsException - - test_submitScore_invalidJudge_throwsException - - test_submitScore_invalidAthlete_throwsException - -评分计算: - - test_calculateFinalScore_normalCase_success - - test_calculateFinalScore_removeHighLow_success - - test_calculateFinalScore_withDifficultyCoefficient_success - - test_calculateFinalScore_withDeductions_success - -异常检测: - - test_detectAnomaly_largeDeviation_flagged - - test_detectAnomaly_normalDeviation_notFlagged - - test_detectAnomaly_allSameScore_flagged - -评分修改: - - test_modifyScore_withinTimeLimit_success - - test_modifyScore_exceedTimeLimit_throwsException - - test_modifyScore_requiresApproval_pendingStatus -``` - -### 5.3 MartialScheduleArrangeServiceTest (赛程编排) -``` -自动编排: - - test_autoArrange_validInput_generatesSchedule - - test_autoArrange_conflictDetection_resolvesConflicts - - test_autoArrange_venueCapacity_respectsLimits - - test_autoArrange_timeSlots_noOverlap - -分组逻辑: - - test_groupAthletes_byProject_correctGroups - - test_groupAthletes_maxPerGroup_respectsLimit - - test_groupAthletes_balancedDistribution_success - -冲突处理: - - test_detectConflict_sameAthleteOverlap_detected - - test_detectConflict_venueOverbook_detected - - test_resolveConflict_autoReassign_success - -调整功能: - - test_adjustSchedule_swapSlots_success - - test_adjustSchedule_changeVenue_success - - test_adjustSchedule_logChanges_recorded -``` - -## 六、测试覆盖率目标 - -| 模块类型 | 行覆盖率 | 分支覆盖率 | 方法覆盖率 | -|----------|----------|------------|------------| -| P0 核心模块 | >= 80% | >= 70% | >= 90% | -| P1 重要模块 | >= 70% | >= 60% | >= 85% | -| P2 一般模块 | >= 60% | >= 50% | >= 80% | -| P3 辅助模块 | >= 50% | >= 40% | >= 70% | -| **整体目标** | **>= 70%** | **>= 60%** | **>= 85%** | - -## 七、测试工具和依赖 - -### 7.1 已有依赖 -- JUnit 5 (Jupiter) -- Mockito -- Spring Boot Test - -### 7.2 建议添加 -```xml - - - org.assertj - assertj-core - test - - - - - org.testcontainers - mysql - test - - - - - org.jacoco - jacoco-maven-plugin - -``` - -## 八、执行和报告 - -### 8.1 运行测试 -```bash -# 运行所有测试 -mvn test - -# 运行特定测试类 -mvn test -Dtest=MartialScoreServiceTest - -# 生成覆盖率报告 -mvn test jacoco:report -``` - -### 8.2 CI/CD 集成 -- 每次 PR 自动运行测试 -- 测试失败阻止合并 -- 覆盖率低于阈值警告 - ---- - -**文档版本**: 1.0 -**创建日期**: 2026-01-16 -**作者**: QA Team diff --git a/docs/CI-CD部署总结.md b/docs/guides/CI-CD部署总结.md similarity index 100% rename from docs/CI-CD部署总结.md rename to docs/guides/CI-CD部署总结.md diff --git a/docs/DATABASE_MIGRATION.md b/docs/guides/DATABASE_MIGRATION.md similarity index 100% rename from docs/DATABASE_MIGRATION.md rename to docs/guides/DATABASE_MIGRATION.md diff --git a/docs/guides/docker-deployment.md b/docs/guides/docker-deployment.md new file mode 100644 index 0000000..4c21a76 --- /dev/null +++ b/docs/guides/docker-deployment.md @@ -0,0 +1,160 @@ +# Docker 部署指南 + +本项目提供三种 Docker 构建方式,适用于不同场景。 + +## 构建方式对比 + +| 方式 | Dockerfile | 适用场景 | 构建速度 | 依赖条件 | +|------|------------|----------|----------|----------| +| 快速构建 | `Dockerfile.quick` | 本地开发迭代 | 最快 | 本地已编译 JAR | +| 离线构建 | `Dockerfile` | CI/CD 离线环境 | 中等 | 需要 `.m2-repo` 目录 | +| 完整构建 | `Dockerfile.fullbuild` | 全新环境 | 最慢 | 需要 martial-tool 源码 | + +--- + +## 方式一:快速构建(推荐日常开发) + +适用于本地开发,需要先在本地编译项目。 + +```bash +# 1. 本地编译 +mvn clean package -DskipTests + +# 2. 构建镜像并启动 +docker-compose up --build +``` + +或一条命令: + +```bash +mvn clean package -DskipTests && docker-compose up --build +``` + +**前提条件**: +- 本地已安装 JDK 17+ 和 Maven 3.9+ +- martial-tool 依赖已安装到本地 Maven 仓库 + +**docker-compose.yml 配置**: +```yaml +martial-api: + build: + context: . + dockerfile: Dockerfile.quick +``` + +--- + +## 方式二:离线构建 + +适用于 CI/CD 环境或无法访问 Maven 仓库的场景。 + +```bash +# 1. 准备离线依赖(首次或依赖变更时执行) +cp -r ~/.m2/repository .m2-repo + +# 2. 构建镜像并启动 +docker-compose up --build +``` + +**前提条件**: +- 本地 `~/.m2/repository` 包含所有项目依赖 +- `.m2-repo` 目录已复制到项目根目录 + +**docker-compose.yml 配置**: +```yaml +martial-api: + build: + context: . + dockerfile: Dockerfile +``` + +**注意**:`.m2-repo` 目录较大(通常几百MB),建议添加到 `.gitignore`。 + +--- + +## 方式三:完整构建 + +适用于全新环境,从零开始构建整个项目(包括 BladeX 框架)。 + +```bash +# 需要在包含 martial-tool 和 martial-master 的父目录执行 +cd /path/to/parent-directory +docker build -f martial-master/Dockerfile.fullbuild -t martial-api:latest . +``` + +**目录结构要求**: +``` +parent-directory/ +├── martial-tool/ # BladeX 框架源码 +└── martial-master/ # 本项目 +``` + +**特点**: +- 完全自包含,不依赖本地环境 +- 构建时间最长(需编译两个项目) +- 适合首次部署或 CI/CD 完整构建 + +--- + +## 常用命令 + +```bash +# 启动所有服务 +docker-compose up -d + +# 重新构建并启动 +docker-compose up -d --build + +# 强制重新创建容器 +docker-compose up -d --force-recreate + +# 查看日志 +docker logs -f martial-api + +# 停止所有服务 +docker-compose down + +# 停止并删除数据卷(慎用,会清除数据库数据) +docker-compose down -v +``` + +--- + +## 环境变量 + +可在 `docker-compose.yml` 中配置以下环境变量: + +| 变量 | 说明 | 默认值 | +|------|------|--------| +| `SPRING_PROFILE` | Spring 配置文件 | `docker` | +| `JAVA_OPTS` | JVM 参数 | `-Xms512m -Xmx1024m -XX:+UseG1GC` | +| `SPRING_DATASOURCE_URL` | 数据库连接 | 见 docker-compose.yml | +| `SPRING_DATA_REDIS_HOST` | Redis 地址 | `redis` | + +--- + +## 故障排查 + +### 1. JAR 文件不存在 +``` +COPY target/blade-api.jar: not found +``` +**解决**:先执行 `mvn clean package -DskipTests` + +### 2. .m2-repo 目录不存在 +``` +COPY .m2-repo: not found +``` +**解决**:执行 `cp -r ~/.m2/repository .m2-repo` 或改用 `Dockerfile.quick` + +### 3. martial-tool 目录不存在 +``` +COPY martial-tool: not found +``` +**解决**:确保在正确的父目录执行,或改用其他构建方式 + +### 4. Flyway 迁移失败 +``` +Migration checksum mismatch +``` +**解决**:执行 `mvn flyway:repair` 修复迁移记录 diff --git a/docs/开发指南.md b/docs/guides/开发指南.md similarity index 100% rename from docs/开发指南.md rename to docs/guides/开发指南.md diff --git a/docs/架构说明.md b/docs/guides/架构说明.md similarity index 100% rename from docs/架构说明.md rename to docs/guides/架构说明.md diff --git a/docs/judge-invite-feature.md b/docs/judge-invite-feature.md deleted file mode 100644 index 34d98b9..0000000 --- a/docs/judge-invite-feature.md +++ /dev/null @@ -1,277 +0,0 @@ -# 评委邀请码管理功能说明 - -## 功能概述 - -评委邀请码管理功能用于管理武术比赛中的评委邀请流程,包括发送邀请、跟踪邀请状态、管理评委回复等。 - -## 数据库升级 - -### 1. 执行升级脚本 - -在执行新功能之前,需要先升级数据库表结构: - -```bash -mysql -h localhost -P 3306 -u root -p blade < database/martial-db/upgrade_judge_invite_table.sql -``` - -### 2. 插入测试数据(可选) - -如果需要测试数据,可以执行: - -```bash -mysql -h localhost -P 3306 -u root -p blade < database/martial-db/insert_test_judge_invite_data.sql -``` - -## 新增字段说明 - -| 字段名 | 类型 | 说明 | -|--------|------|------| -| invite_status | INT | 邀请状态(0-待回复,1-已接受,2-已拒绝,3-已取消) | -| invite_time | DATETIME | 邀请时间 | -| reply_time | DATETIME | 回复时间 | -| reply_note | VARCHAR(500) | 回复备注 | -| contact_phone | VARCHAR(20) | 联系电话 | -| contact_email | VARCHAR(100) | 联系邮箱 | -| invite_message | VARCHAR(1000) | 邀请消息 | -| cancel_reason | VARCHAR(500) | 取消原因 | - -## 后端接口 - -### 1. 分页查询邀请列表 - -**接口地址**: `GET /api/blade-martial/judgeInvite/list` - -**请求参数**: -- `current`: 当前页码(默认1) -- `size`: 每页条数(默认10) -- `competitionId`: 赛事ID(必填) -- `judgeName`: 裁判姓名(可选,模糊查询) -- `judgeLevel`: 裁判等级(可选) -- `inviteStatus`: 邀请状态(可选) - -**响应示例**: -```json -{ - "code": 200, - "success": true, - "data": { - "records": [ - { - "id": 1, - "competitionId": 1, - "judgeId": 1, - "judgeName": "张三", - "judgeLevel": "国家级", - "inviteCode": "INV2025001", - "contactPhone": "13800138001", - "contactEmail": "zhangsan@example.com", - "inviteStatus": 0, - "inviteTime": "2025-12-12 00:00:00", - "replyTime": null, - "replyNote": null - } - ], - "total": 5, - "size": 10, - "current": 1 - } -} -``` - -### 2. 获取邀请统计 - -**接口地址**: `GET /api/blade-martial/judgeInvite/statistics` - -**请求参数**: -- `competitionId`: 赛事ID(必填) - -**响应示例**: -```json -{ - "code": 200, - "success": true, - "data": { - "totalInvites": 5, - "pendingCount": 2, - "acceptedCount": 2, - "rejectedCount": 1 - } -} -``` - -### 3. 新增或修改邀请 - -**接口地址**: `POST /api/blade-martial/judgeInvite/submit` - -**请求体**: -```json -{ - "competitionId": 1, - "judgeId": 1, - "inviteCode": "INV2025001", - "role": "judge", - "contactPhone": "13800138001", - "contactEmail": "zhangsan@example.com", - "inviteMessage": "诚邀您担任本次武术比赛的裁判", - "inviteStatus": 0, - "inviteTime": "2025-12-12 00:00:00", - "expireTime": "2025-01-12 00:00:00" -} -``` - -## 前端页面 - -### 页面路径 -`src/views/martial/judgeInvite/index.vue` - -### 主要功能 - -#### 1. 搜索和筛选 -- 选择赛事 -- 按评委姓名搜索 -- 按评委等级筛选 -- 按邀请状态筛选 - -#### 2. 统计卡片 -显示以下统计信息: -- 总邀请数 -- 待回复数量 -- 已接受数量 -- 已拒绝数量 - -#### 3. 数据表格 -显示以下信息: -- 评委姓名 -- 评委等级(彩色标签) -- **邀请码**(橙色标签,点击可复制) -- 联系电话 -- 联系邮箱 -- 邀请状态(彩色标签) -- 邀请时间 -- 回复时间 -- 回复备注 - -#### 4. 操作按钮 -- **重发**: 重新发送邀请(仅待回复状态) -- **提醒**: 发送提醒消息(仅待回复状态) -- **取消**: 取消邀请(仅待回复状态) -- **查看**: 查看详情 -- **确认**: 确认接受(仅已接受状态) - -#### 5. 工具栏 -- 发送邀请 -- 批量邀请 -- 从评委库导入 -- 导出数据 -- 刷新 - -### 邀请码复制功能 - -点击表格中的邀请码(橙色标签),会自动复制到剪贴板,并显示成功提示。 - -支持两种复制方式: -1. 现代浏览器:使用 Clipboard API -2. 旧浏览器:使用 document.execCommand('copy') 降级方案 - -## 使用流程 - -### 1. 发送邀请 -1. 进入评委邀请码管理页面 -2. 选择赛事 -3. 点击"发送邀请"或"批量邀请" -4. 填写评委信息和邀请消息 -5. 系统自动生成邀请码 -6. 发送邀请给评委 - -### 2. 评委回复 -评委收到邀请后,使用邀请码登录小程序: -1. 输入邀请码 -2. 查看邀请详情 -3. 选择接受或拒绝 -4. 填写回复备注(可选) - -### 3. 管理邀请 -1. 查看邀请列表和统计 -2. 对待回复的邀请进行重发或提醒 -3. 确认已接受的邀请 -4. 取消不需要的邀请 - -## 状态说明 - -| 状态值 | 状态名称 | 标签颜色 | 说明 | -|--------|---------|---------|------| -| 0 | 待回复 | 橙色 | 邀请已发送,等待评委回复 | -| 1 | 已接受 | 绿色 | 评委已接受邀请 | -| 2 | 已拒绝 | 红色 | 评委已拒绝邀请 | -| 3 | 已取消 | 灰色 | 主办方已取消邀请 | - -## 注意事项 - -1. **邀请码唯一性**: 每个邀请码必须唯一,建议使用格式:`INV + 年份 + 序号` -2. **过期时间**: 邀请码应设置合理的过期时间,建议30天 -3. **联系方式**: 确保填写正确的联系电话和邮箱,便于后续沟通 -4. **状态流转**: - - 待回复 → 已接受/已拒绝(评委操作) - - 待回复 → 已取消(主办方操作) - - 已接受 → 已取消(主办方操作) - -## 技术实现 - -### 后端 -- **实体类**: `MartialJudgeInvite` -- **VO类**: `MartialJudgeInviteVO`(包含关联的裁判信息) -- **Mapper**: `MartialJudgeInviteMapper`(支持关联查询) -- **Service**: `IMartialJudgeInviteService` -- **Controller**: `MartialJudgeInviteController` - -### 前端 -- **框架**: Vue 3 + Element Plus -- **API**: `src/api/martial/judgeInvite.js` -- **页面**: `src/views/martial/judgeInvite/index.vue` - -### 数据库 -- **主表**: `martial_judge_invite` -- **关联表**: - - `martial_judge`(裁判信息) - - `martial_competition`(赛事信息) - -## 待完善功能 - -以下功能目前显示"开发中"提示,可以后续添加: - -1. **发送邀请对话框**: 完整的邀请发送表单 -2. **批量邀请对话框**: 批量选择评委并发送邀请 -3. **从评委库导入**: 从裁判库中选择评委并自动生成邀请 -4. **取消邀请对话框**: 填写取消原因 -5. **查看详情对话框**: 显示邀请的完整信息 -6. **导出功能**: 导出邀请名单为Excel文件 - -## 测试建议 - -1. **单元测试**: 测试Service层的业务逻辑 -2. **集成测试**: 测试Controller层的接口 -3. **前端测试**: 测试页面交互和数据展示 -4. **端到端测试**: 测试完整的邀请流程 - -## 常见问题 - -### Q1: 邀请码复制失败? -A: 检查浏览器是否支持Clipboard API,或者是否在HTTPS环境下。如果都不满足,会自动使用降级方案。 - -### Q2: 统计数据不准确? -A: 确保数据库中的invite_status字段值正确,并且is_deleted字段为0。 - -### Q3: 关联查询性能问题? -A: 已为competition_id和invite_status字段添加索引,如果数据量很大,可以考虑添加更多索引或使用缓存。 - -## 更新日志 - -### 2025-12-12 -- ✅ 创建评委邀请码管理页面 -- ✅ 实现邀请码展示和复制功能 -- ✅ 添加邀请状态管理 -- ✅ 实现统计卡片 -- ✅ 支持搜索和筛选 -- ✅ 创建数据库升级脚本 -- ✅ 实现后端关联查询 -- ✅ 添加邀请统计接口 diff --git a/docs/schedule-dispatch-implementation.md b/docs/schedule-dispatch-implementation.md deleted file mode 100644 index 5d7c103..0000000 --- a/docs/schedule-dispatch-implementation.md +++ /dev/null @@ -1,485 +0,0 @@ -# 调度功能实现文档 - -## 📋 实现总结 - -调度功能已经完成后端和前端API的开发,现在需要在前端页面中集成调度功能。 - ---- - -## 🎯 前端页面修改方案 - -### 方案:在编排页面添加调度Tab - -修改 `src/views/martial/schedule/index.vue` 文件,在现有的"竞赛分组"和"场地"Tab基础上,添加"调度"Tab。 - ---- - -## 💻 前端代码实现 - -### 1. 在 `