Parcourir la source

Docs: 项目详细设计说明书V1(分期架构/数据库/接口/页面/后台/流程/排期)

liaoxg il y a 2 semaines
Parent
commit
c742c339f3
1 fichiers modifiés avec 541 ajouts et 0 suppressions
  1. 541 0
      docs/小程序项目详细设计说明书.md

+ 541 - 0
docs/小程序项目详细设计说明书.md

@@ -0,0 +1,541 @@
+# 爱伴 · AI之旅 训练营小程序 项目详细设计说明书
+
+> **版本**:V1.0 | **日期**:2026-09-04 | **关联文档**:《小程序需求规格说明书 V2.0》
+>
+> 依据 SRS V2.0 分期(一期课堂管理 / 二期课前准备 / 三期课后跟踪 / 新增报名·付费·裂变),结合 train-backend、train-frontend、train-web 三端现状编写。
+
+---
+
+## 目录
+
+1. [设计总览](#1-设计总览)
+2. [总体架构设计](#2-总体架构设计)
+3. [数据库详细设计](#3-数据库详细设计)
+4. [后端模块详细设计](#4-后端模块详细设计)
+5. [接口详细设计](#5-接口详细设计)
+6. [前端页面详细设计(train-frontend)](#6-前端页面详细设计train-frontend)
+7. [管理后台详细设计(train-web)](#7-管理后台详细设计train-web)
+8. [关键业务流程设计](#8-关键业务流程设计)
+9. [非功能设计](#9-非功能设计)
+10. [部署与配置](#10-部署与配置)
+11. [开发任务拆分与排期](#11-开发任务拆分与排期)
+
+---
+
+## 1. 设计总览
+
+### 1.1 设计目标
+
+在既有三端代码基础上,按 SRS V2.0 分期落地:
+
+- **一期 · 课堂管理**:固化现有课堂功能,形成最低可用闭环。
+- **二期 · 课前准备**:补齐课前资料包、提醒通知。
+- **三期 · 课后跟踪**:补齐 T+ 跟进、证书、权益发放。
+- **新增 · 报名 / 付费 / 裂变**:落地商业闭环,新增订单、报名、转介三张表及对应接口、页面、后台。
+
+### 1.2 技术栈现状
+
+| 端 | 技术栈 | 现状 |
+|---|---|---|
+| train-backend | Spring Boot 2.7.18 / Java 8 / MyBatis-Plus 3.5.3.1 | 端口 9083,48 个 @PostMapping,20 Mapper,18 实体,2 Service,4 Config |
+| train-frontend | uni-app Vue2(HBuilderX 打包) | 15 页面,4 tabBar,31 个接口调用封装 |
+| train-web | Vue2 + Element UI + vue-cli 5 | 12 路由,含 ECharts 统计 |
+
+### 1.3 设计范围映射
+
+| SRS 分期 | 涉及新增/改动 |
+|---|---|
+| 一期课堂管理 | 现状已基本具备,本文档固化设计(§6/§7 现状对齐) |
+| 二期课前准备 | 新增资料包表 + 订阅消息通知 |
+| 三期课后跟踪 | 新增证书、T+ 定时任务、权益核销 |
+| 报名/付费/裂变 | 新增 3 张表、6+ 接口、3 个前端页面、3 个后台页面 |
+
+---
+
+## 2. 总体架构设计
+
+### 2.1 系统架构(三端一库)
+
+```
+┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐
+│  train-frontend │   │   train-web     │   │   HBuilderX     │
+│  学员端小程序     │   │  管理后台        │   │  打包(微信)    │
+│  uni-app Vue2   │   │  Vue2+Element   │   └─────────────────┘
+└────────┬────────┘   └────────┬────────┘
+         │  Bearer JWT         │  Bearer admin: JWT
+         ▼                     ▼
+┌───────────────────────────────────────────────────┐
+│              train-backend (端口 9083)              │
+│  Controller(48) → Service(2) → Mapper(20)          │
+│  JwtInterceptor / WebConfig / DatabaseInitializer  │
+└───────────────────────┬───────────────────────────┘
+                        │ 单数据源(cfc 同库 zxyj)
+                        ▼
+┌───────────────────────────────────────────────────┐
+│        MySQL 192.168.16.251:3306 / zxyj           │
+│  train_* 运营表 20 张 + cfc 表(users/activities)   │
+└───────────────────────────────────────────────────┘
+```
+
+### 2.2 分层架构(后端)
+
+严格遵循 Controller → Service → Mapper 三层,禁止 Controller 直接操作 Mapper。
+
+- **Controller 层**:参数校验、调用 Service、返回 `Result<T>`(统一 `@PostMapping`)。
+- **Service 层**:业务逻辑、事务控制(`@Transactional`)、幂等控制。
+- **Mapper 层**:`BaseMapper<T>` 继承,无自定义 XML。
+- **config 层**:JWT 拦截、CORS、数据初始化。
+
+### 2.3 双 JWT 体系
+
+- **学员 token**:`JwtConfig.generateToken(userId, role)`,subject=userId,含 role claims;`Authorization: Bearer <token>`,拦截器设 `userId/role/isAdmin=false`。
+- **管理员 token**:前缀 `admin:`,拦截器解析后设 `adminId/role/isAdmin=true`。
+- 阈值:学员与管理员 token 独立,`judge` 路径按前缀区分。
+
+---
+
+## 3. 数据库详细设计
+
+### 3.1 设计规范
+
+- 金额一律**整型分**(int/Long),禁止 double/float。
+- 时间用 DATETIME / ISO 8601。
+- 编码 utf8mb4;主键 BIGINT AUTO_INCREMENT;带 `created_at` / `updated_at`。
+- 建表幂等:`CREATE TABLE IF NOT EXISTS`;存量补列用 try-catch 忽略"已存在"。
+- 同步更新 `schema.sql` 的完整 CREATE TABLE 定义。
+
+### 3.2 现存表(20 张)
+
+> 下表均已由 `schema.sql` / `DatabaseInitializer` 建立,本文档对齐到实际 Entity。
+
+| 表 | 实体 | 用途 | SRS 分期 |
+|---|---|---|---|
+| train_course | TrainCourse | 课程 L0-L4 | 一期 |
+| train_class | TrainClass | 班次 | 一期 |
+| train_user | TrainUser | 学员 | 一期 |
+| train_group | TrainGroup | 小组 | 一期 |
+| train_group_member | TrainGroupMember | 组内成员 | 一期 |
+| train_assignment | TrainAssignment | 三本账分工 | 一期 |
+| train_submission | TrainSubmission | 成果上传 | 一期 |
+| train_teaching_card | TrainTeachingCard | 五步教学卡 | 一期 |
+| train_roadmap | TrainRoadmap | 路演材料 | 一期 |
+| train_vote | TrainVote | 两轮投票 | 一期 |
+| train_score | TrainScore | 积分流水 | 一期 |
+| train_checkin | TrainCheckin | 装机打卡 | 二期 |
+| train_prep_check | TrainPrepCheck | 数据自检 | 二期 |
+| train_plan | TrainPlan | 7 天计划 | 三期 |
+| train_survey | TrainSurvey | 测评调研 | 三期 |
+| train_coupon | TrainCoupon | 卡券 | 三期 |
+| train_admin | TrainAdmin | 后台账号 | 一期 |
+| train_audit_log | TrainAuditLog | 审计日志 | 一期 |
+| users(cfc) | CfcUser | 统一会员 | 一期 |
+| activities(cfc) | CfcActivity | cfc 活动 | 一期 |
+
+### 3.3 新增表(报名 / 付费 / 裂变)
+
+#### 3.3.1 `train_enrollment` — 报名单
+
+```sql
+CREATE TABLE IF NOT EXISTS train_enrollment (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  uid BIGINT COMMENT '学员ID(登录后)',
+  class_id BIGINT COMMENT '所选班次ID',
+  name VARCHAR(50) COMMENT '姓名',
+  phone VARCHAR(11) COMMENT '手机号',
+  bring_laptop TINYINT DEFAULT 0 COMMENT '1=带电脑',
+  data_ready VARCHAR(50) COMMENT '已备数据类别(逗号分隔)',
+  top_problems TEXT COMMENT '最想解决的3个问题JSON',
+  source VARCHAR(20) DEFAULT 'scene' COMMENT '来源:scene/invite',
+  invite_code VARCHAR(50) COMMENT '邀请码(基于train_user.invite_code)',
+  status VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/paid/confirmed/cancelled',
+  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  INDEX idx_uid (uid),
+  INDEX idx_class_id (class_id),
+  INDEX idx_status (status)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='报名单';
+```
+
+#### 3.3.2 `train_order` — 支付订单
+
+```sql
+CREATE TABLE IF NOT EXISTS train_order (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  order_no VARCHAR(32) NOT NULL UNIQUE COMMENT '订单号',
+  enrollment_id BIGINT COMMENT '关联报名单',
+  uid BIGINT COMMENT '学员ID',
+  class_id BIGINT COMMENT '班次ID',
+  amount INT NOT NULL COMMENT '实付金额(分)',
+  original_amount INT COMMENT '原价(分)',
+  discount_amount INT DEFAULT 0 COMMENT '优惠(分)',
+  pay_channel VARCHAR(20) DEFAULT 'wechat' COMMENT '支付渠道',
+  status VARCHAR(20) DEFAULT 'unpaid' COMMENT 'unpaid/paid/refunded/failed/closed',
+  pay_time DATETIME,
+  wechat_txn_id VARCHAR(64) COMMENT '微信交易号',
+  prepay_id VARCHAR(64) COMMENT '预支付ID',
+  refund_amount INT DEFAULT 0 COMMENT '已退金额(分)',
+  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  INDEX idx_uid (uid),
+  INDEX idx_class_id (class_id),
+  INDEX idx_status (status),
+  INDEX idx_enrollment_id (enrollment_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付订单';
+```
+
+> **幂等键**:`order_no` UNIQUE;回调按 `order_no + status` 判定,防止重复入账。
+
+#### 3.3.3 `train_invite` — 转介绍关系
+
+```sql
+CREATE TABLE IF NOT EXISTS train_invite (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  inviter_id BIGINT NOT NULL COMMENT '邀请人(train_user.id)',
+  invitee_id BIGINT COMMENT '被邀请人(train_user.id)',
+  invite_code VARCHAR(50) COMMENT '邀请码',
+  order_id BIGINT COMMENT '被邀请人的订单ID',
+  successful TINYINT DEFAULT 0 COMMENT '1=被邀请人已完成付费',
+  reward_status VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/granted',
+  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+  INDEX idx_inviter (inviter_id),
+  INDEX idx_invitee (invitee_id),
+  UNIQUE KEY uk_code_invitee (invite_code, invitee_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='转介绍关系';
+```
+
+#### 3.3.4 `train_course_material` — 课前资料包(二期)
+
+```sql
+CREATE TABLE IF NOT EXISTS train_course_material (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  class_id BIGINT COMMENT '班次ID(为空=通用资料)',
+  title VARCHAR(100) NOT NULL,
+  file_url VARCHAR(255) COMMENT 'PDF/附件URL',
+  sort INT DEFAULT 0,
+  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+  INDEX idx_class_id (class_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课前资料包';
+```
+
+### 3.4 表关系概览
+
+```
+train_course 1─* train_class 1─* train_group 1─* train_group_member
+                              └─ train_class 1─* train_enrollment
+train_user 1─* train_enrollment 1─1 train_order
+train_user 1─* train_invite *─1 train_user (inviter/invitee)
+train_user 1─* train_assignment / train_submission / train_score / train_plan ...
+```
+
+---
+
+## 4. 后端模块详细设计
+
+### 4.1 现有模块(现状对齐)
+
+| 模块 | Controller | 职责 | Service |
+|---|---|---|---|
+| 认证 | AuthController | wechat-login / wechat-phone-login / alumni-verify | WechatService(code2Session / getPhoneNumber) |
+| 班次 | ClassController | join / info | —(直连 Mapper) |
+| 课程 | CourseController | list / current | — |
+| 分组 | GroupController | join / mine / spokesperson / assign / list | — |
+| 分工 | AssignmentController | claim / mine / group | — |
+| 计划/调研/卡券 | PlanController | submit / mine / survey / coupons | — |
+| 成果/打卡/教学卡 | SubmissionController | checkin / prep-check / upload / mylist / teaching-card | — |
+| 上传 | UploadController | file | — |
+| 路演/投票/积分榜 | VoteController | roadmap / cast / result / voted / scoreboard | ScoreService |
+| 后台认证 | AdminAuthController | login | — |
+| 后台班级/用户 | AdminClassController | createClass / classList / classDetail / createGroup / setSpokesperson / userList / setUserStatus | — |
+| 后台审核/评分 | AdminReviewController | submission/review / card/score / roadmap/score / score/manual | ScoreService |
+| 后台统计 | AdminStatsController | overview / scoreboard / user-scoreboard | — |
+
+### 4.2 积分引擎(ScoreService)— 幂等设计
+
+| 方法 | 幂等 | 说明 |
+|---|---|---|
+| `addGroupScoreIfAbsent(groupId, item, points, byUid, remark)` | ✅ 同组+同 item 只加一次 | 组维度计分 |
+| `addUserScore(uid, item, points, byUid, remark)` | ❌ 直接 insert | 个人计分(允许重复) |
+| `addUserScoreIfAbsent(uid, item, points, byUid, remark)` | ✅ | 个人计分(幂等) |
+| `addGroupScore(groupId, item, points, byUid, remark)` | ❌ 允许累加 | 组维度计分 |
+| `groupTotals(classId)` | — | 班内各组总分 |
+| `userTotal(uid)` | — | 个人累计分 |
+| `groupMemberTotal(groupId)` | — | 组内成员个人分合计 |
+
+**关键保障**:`@Transactional` + `@RequestAttribute userId`(由拦截器注入,防越权)。积分流水(train_score)带 byUid 可溯源。
+
+### 4.3 投票引擎(VoteController)
+
+- **Round 1「我学会了」**:每人 2 票,不得投本组,投两个不同组 → 入库 2 条 train_vote。
+- **Round 2「最想抄走」**:每人 1 票,可投本组 → 入库 1 条。
+- 防重复:`train_vote` 无唯一约束,靠 `voted()` 预检 + 前端置灰 + 后端 `count(voter_uid, round, class_id)` 校验。
+- 计分:`cast` 后总分累计(vote 项 +50 组分,如课纲规定)。
+
+### 4.4 支付模块(新增 `PayService` + `OrderController`)
+
+**职责**:
+1. 创建订单(先生成 `train_order`,再调微信统一下单获取 prepay_id)。
+2. 发起支付(签名 + 时间戳 + nonce 返回给前端 wx.requestPayment)。
+3. 支付回调(`/api/pay/notify` 公网回调,验签 + 幂等入账 + 更新订单为 paid)。
+4. 退款(后台触发)。
+
+**安全要点**:
+- 金额用整型分,回调验签(MD5/HMAC + 商户密钥)。
+- 回调幂等:`order_no` 已 paid 则跳过;防重复发放权益。
+- 订单关闭超时未支付订单(定时任务)。
+
+### 4.5 报名模块(新增 `EnrollmentController`)
+
+- 游客/学员填写报名表单 → 生成 `train_enrollment`(status=pending)。
+- 若带 invite_code → 记录到 `train_invite`(inviter 关系)。
+- 班次容量:`count(enrollment where class_id & status in pending/paid)` < `capacity` 才可报名。
+- 报名成功(paid)后自动进班(`train_user.class_id` 回填)。
+
+### 4.6 裂变模块(新增)
+
+- **海报/邀请码**:复用 `train_user.invite_code`;生成小程序码(微信 `getwxacodeunlimit`,scene=invite_code)作为分享海报。
+- **转介绍记录**:带参进入报名页 → 建立 `train_invite`。
+- **激励发放**:被邀请人完成付费 → `train_invite.successful=1` → 触发发卡券(private 私教 / 年会员)→ `reward_status=granted`。
+- **统计接口**:`invitational/inviter/list` 供后台看转介绍漏斗。
+
+### 4.7 通知模块(新增,二期/三期)
+
+- 微信订阅消息(一次性模板)。
+- 触发点:报名成功、课前 T-7/T-3/T-1、成果被退回、投票结果揭晓、T+ 跟进提醒。
+- 需维护 `train_message_template` 配置(模板 ID、跳转路径)。
+
+---
+
+## 5. 接口详细设计
+
+### 5.1 接口规范(全局约定)
+
+- 统一 `@PostMapping`;响应 `Result<T>`(code=200 成功 / 500 业务错误 / 401 未登录)。
+- 鉴权:拦截器注入 `@RequestAttribute userId`(学员)或 `adminId`(管理员)。
+- 分页:`page` / `size`(本期少数列表,可后续标准化)。
+
+### 5.2 现有接口清单(对齐,31 个学员端)
+
+> 均已实现,本文档作为验收对照。路径见 §4.1 各 Controller。
+
+### 5.3 新增接口定义
+
+#### 报名模块(`EnrollmentController` → `/api/enroll`)
+
+| 接口 | 方法 | 参数 | 返回 | 说明 |
+|---|---|---|---|---|
+| `POST /api/enroll/classes` | `listClasses` | `@RequestBody(required=false) Map` | `Result<List<Map>>` {id,name,time,place,capacity,num,price,memberPrice,status} | 可报名班次列表(含剩余名额/价格) |
+| `POST /api/enroll/create` | `create` | `@RequestBody Map` {classId,name,phone,bringLaptop,dataReady,topProblems,inviteCode} | `Result<EnrollmentVO>` | 创建报名单 |
+| `POST /api/enroll/mine` | `mine` | `@RequestAttribute userId` | `Result<List<Map>>` | 我的报名单列表 |
+
+#### 支付模块(`OrderController` → `/api/pay`)
+
+| 接口 | 方法 | 参数 | 返回 | 说明 |
+|---|---|---|---|---|
+| `POST /api/pay/create` | `createOrder` | `@RequestBody Map` {enrollmentId} | `Result<Map>` {orderNo, amount, prepayParams} | 创建订单并发起预支付 |
+| `POST /api/pay/status` | `status` | `@RequestBody Map` {orderNo} | `Result<Map>` {status, ...} | 查询订单状态 |
+| `POST /api/pay/cancel` | `cancel` | `@RequestBody Map` {orderNo} + `@RequestAttribute userId` | `Result<Boolean>` | 关闭/取消订单 |
+| `POST /api/pay/notify` | `notify` | `@RequestBody String xmlBody` | `String` | 微信支付回调(公网) |
+
+#### 裂变模块(`InviteController` → `/api/invite`)
+
+| 接口 | 方法 | 参数 | 返回 | 说明 |
+|---|---|---|---|---|
+| `POST /api/invite/myposter` | `myPoster` | `@RequestAttribute userId` | `Result<Map>` {inviteCode, posterUrl} | 我的专属海报+邀请码 |
+| `POST /api/invite/stats` | `stats` | `@RequestAttribute userId` | `Result<Map>` {invited, paid, rewards} | 我的转介绍统计 |
+
+#### 后台报名/订单/转介(`AdminBizController` → `/api/admin`)
+
+| 接口 | 方法 | 参数 | 返回 | 说明 |
+|---|---|---|---|---|
+| `POST /api/admin/enrollment/list` | `enrollmentList` | `@RequestBody(required=false) Map` {classId?,status?} | `Result<List<Map>>` | 报名单列表 |
+| `POST /api/admin/order/list` | `orderList` | `@RequestBody(required=false) Map` {status?,classId?} | `Result<List<Map>>` | 订单列表 |
+| `POST /api/admin/order/refund` | `refund` | `@RequestBody Map` {orderId, amount} + `@RequestAttribute adminId` | `Result<Boolean>` | 退款 |
+| `POST /api/admin/invite/funnel` | `inviteFunnel` | `@RequestBody(required=false) Map` | `Result<List<Map>>` | 转介绍漏斗 |
+| `POST /api/admin/material/list` | `materialList` | `@RequestBody(required=false) Map` {classId?} | `Result<List<Map>>` | 课前资料列表 |
+| `POST /api/admin/material/save` | `materialSave` | `@RequestBody Map` + `@RequestAttribute adminId` | `Result<Boolean>` | 保存资料 |
+
+#### 二期/三期补充接口
+
+| 接口 | 方法 | 说明 |
+|---|---|---|
+| `POST /api/class/materials` | 学员端获取课前资料包 | 校验已进班 |
+| `POST /api/plan/cert` | 生成/领取完课证书 | 校验离场验收 6 项 |
+| `POST /api/coupon/redeem` | 卡券核销 | status used |
+
+---
+
+## 6. 前端页面详细设计(train-frontend)
+
+### 6.1 页面架构与导航(现有)
+
+**TabBar(4)**:首页 index / 任务 checkin / 路演投票 vote / 我的 mine
+
+**子页面(11)**:login、verify、class、group、assignment、upload、teaching、roadmap、scoreboard、plan、survey
+
+**通用工具**:
+- `utils/api.js`:`request(url, method, data)`(自动 Bearer token,401 跳登录)+ `uploadFile(filePath)` + 各业务接口封装。
+- `utils/auth.js`:`getToken/setToken/removeToken`。
+- 注:`utils/format.js` **当前不存在**——按 SRS 时间规范应新增 `parseDate()` 等函数。
+
+### 6.2 新增页面(报名/付费/裂变)
+
+| 页面 | 路径 | 功能 | 主要接口 |
+|---|---|---|---|
+| 课程报名列表 | `pages/enroll/list` | 浏览可报名班次、选班 | `enroll/classes` |
+| 报名表单 | `pages/enroll/form` | 填报名信息(含带参邀请码) | `enroll/create` |
+| 支付页 | `pages/pay/index` | 展示订单、拉起 wx.requestPayment、轮询状态 | `pay/create` / `pay/status` |
+| 支付结果 | `pages/pay/result` | 支付成功/失败,引导进班 | `pay/status` |
+| 我的海报 | `pages/share/index` | 展示专属海报+邀请码、保存图片 | `invite/myposter` |
+| 我的邀请 | `pages/share/stats` | 转介绍统计 | `invite/stats` |
+| 课前资料包 | `pages/material/index` | 下载课前资料 | `class/materials` |
+
+### 6.3 页面状态管理(Vuex)
+
+现状:index 页用 store 管理 `isLoggedIn / alumniVerify / classId / name / nickname / role`。新增可考虑扩展 `order / enrollment / invite` 模块,但为保持轻量,建议报名/支付状态用页面本地 + 后端查询,不入全局 Store。
+
+### 6.4 前端金额/时间规范(三端通用)
+
+```js
+// 分 → 元
+function fenToYuan(fen) { return (fen / 100).toFixed(2) }
+// 时间:ISO → yyyy-MM-dd HH:mm:ss(截前 19 位 + T 替换空格)
+```
+- 小程序端禁止可选链 `?.`、CSS Grid,用 `utils/format.js` 的 `parseDate()`(需新增)。
+
+---
+
+## 7. 管理后台详细设计(train-web)
+
+### 7.1 现有页面(12 路由,现状对齐)
+
+| 路由 | 组件 | 功能 |
+|---|---|---|
+| /login | Login | 后台登录 |
+| /dashboard | Dashboard | 概览统计卡片 |
+| /classes | Classes | 班级列表+新建 |
+| /groups | Groups | 分组列表+新建+设置发言人 |
+| /users | Users | 学员管理(筛选/启停) |
+| /review/submissions | Submissions | 成果审核 |
+| /review/cards | Cards | 教学卡评分 |
+| /review/roadmaps | Roadmaps | 路演评审 |
+| /scoreboard | Scoreboard | 积分榜 |
+| /manual-score | ManualScore | 人工加减分 |
+| /stats | Stats | 统计(ECharts) |
+
+### 7.2 新增页面
+
+| 路由 | 组件 | 功能 | 主要接口 |
+|---|---|---|---|
+| /enrollments | Enrollments | 报名单管理 | `admin/enrollment/list` |
+| /orders | Orders | 订单管理(含退款) | `admin/order/list` / `admin/order/refund` |
+| /invites | Invites | 转介绍漏斗 | `admin/invite/funnel` |
+| /materials | Materials | 课前资料管理 | `admin/material/list` / `admin/material/save` |
+
+### 7.3 权限优化建议
+
+现状:角色仅区分显示名称,菜单未按角色过滤。建议:
+- 按 role 过滤菜单(admin 全量;lecturer 看审核/评分/积分榜;assistant 仅看其负责组的审核)。
+- 后端 `AdminReviewController` 已支持 `manage_group_ids` 约束,前端需对齐展示。
+
+---
+
+## 8. 关键业务流程设计
+
+### 8.1 报名 → 付费 → 进班
+
+```
+浏览班次列表 → 选择班次 → 填报名表单(可带邀请码)
+   → 创建报名单(pending) → 创建订单 → 微信支付
+   → 支付回调(paid) → 自动进班(class_id 回填)
+   → 若带邀请码:被邀请人 paid → 邀请人发卡券
+```
+
+### 8.2 课前准备(二期)
+
+```
+进班成功 → 推送课前资料包 + 课前3件事
+   → T-7/T-3/T-1 订阅消息提醒
+   → 学员装机打卡(checkin) + 数据自检(prep-check)
+   → 课堂模块二读取状态提速
+```
+
+### 8.3 课堂管理(一期,六模块)
+
+```
+破冰组队(分组/分工) → 装机通关 → 数据找茬 → 三本账分工做互教会
+   → 路演备战(教学卡/路演材料) → 终极路演+两轮投票+颁奖
+全程:成果上传→助教核验→积分流水→实时积分板
+```
+
+### 8.4 课后跟踪(三期)
+
+```
+离场验收6项 → 7天行动计划 → T+1成果合集 / T+3补齐 / T+7回访
+   → T+21复盘会 / T+30留存统计
+   → 测评调研 → 卡券/证书发放 → 续课/裂变
+```
+
+---
+
+## 9. 非功能设计
+
+### 9.1 安全设计
+
+- 金额整型分;支付回调验签、幂等、防重复支付/重复发权益。
+- JWT 双体系(学员/管理员前缀)防越权;积分操作带 byUid 溯源。
+- 用户真实数据(持仓/血压/成绩)必须 `desensitized`;案例采集需显式授权。
+
+### 9.2 性能设计
+
+- 课堂并发 ≤ 数百人;投票/积分实时刷新容忍秒级延迟(轮询/简单查询)。
+- 后台报表异步生成,避免阻塞课堂主流程。
+- 支付回调独立线程,避免与业务主事务耦合。
+
+### 9.3 幂等与并发
+
+- 支付回调:`order_no` 唯一 + `status` 状态机(unpaid→paid,禁止回退)。
+- 积分:`addXxxIfAbsent` 幂等方法,防重复计分。
+- 报名容量:`count + capacity` 校验(可加乐观锁 `version` 或 `SELECT ... FOR UPDATE` 防超卖)。
+
+### 9.4 兼容
+
+- uni-app Vue2;禁止可选链、CSS Grid。
+- 时间展示统一 `utils/format.js parseDate()`,禁止 `new Date(str).toLocaleString()`。
+
+---
+
+## 10. 部署与配置
+
+| 端 | 配置要点 |
+|---|---|
+| train-backend | 端口 9083;数据源走 `TRAIN_DB_URL/USERNAME/PASSWORD` 环境变量;JWT `JWT_SECRET` 与 cfc 对齐;`wechat.test-mode` 默认 true |
+| train-frontend | HBuilderX 导入 → 运行到微信开发者工具,产物 `unpackage/dist/dev/mp-weixin/`;**勿**用 npm `build:mp-weixin`(产物不完整) |
+| train-web | `npm run dev` / `build`;后端地址走 axios baseURL 配置 |
+
+**支付上线前置**(新增):
+- 微信支付商户号、API 密钥、证书(.p12/apiclient_key.pem)。
+- 回调域名白名单配置到微信商户平台。
+- `wechat.test-mode` 关闭后接入真实登录与支付。
+
+---
+
+## 11. 开发任务拆分与排期
+
+| 序号 | 任务 | 范围 | 依赖 | 建议 |
+|---|---|---|---|---|
+| 1 | 一期课堂管理验收上线 | 现有三端 | 无 | 现稍微修正后上线支撑首期线下课 |
+| 2 | `utils/format.js` 新增 | train-frontend | 无 | 一期并行 |
+| 3 | 新增表 DDL + schema.sql | train-backend | 1 | 一期后可先行 |
+| 4 | 报名模块(表+接口+页面+后台) | 三端 | 3 | 二期启动 |
+| 5 | 支付模块(PayService+回调+订单页) | 三端 | 4 | 与报名并行 |
+| 6 | 裂变模块(海报/邀请码/激励/漏斗) | 三端 | 4 | 报名后可接 |
+| 7 | 课前资料包 + 订阅消息通知 | 三端 | 3 | 二期 |
+| 8 | 课后证书 + T+ 定时任务 | 三端 | 3 | 三期 |
+| 9 | 后台权限菜单过滤 | train-web | 1 | 三期 |
+| 10 | 微信支付/登录生产环境联调 | 三端 | 5 | 上线前 |
+
+> **建议**:先交付 #1(一期课堂管理)+ #2(format.js),随后并行推进 #3-#6(报名/付费/裂变),再 #7-#9(二期/三期)。
+
+---
+
+*爱伴 · AI之旅 训练营小程序 · 项目详细设计说明书 V1.0 · 2026-09-04*