feat: 添加 Goal, GoalRelation, StudentGoal 三个数据模型
- Goal: 目标表,支持存储学习目标 - GoalRelation: 目标自关联多对多表,支持 DAG 结构 - StudentGoal: 学员目标记录表,关联学员和目标
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
# 目标管理模块设计
|
||||
|
||||
> 日期:2026-04-23
|
||||
> 状态:待评审
|
||||
|
||||
## 概述
|
||||
|
||||
目标管理模块用于管理系统化的钢琴学习目标,支持目标间的多对多关联(DAG结构),以及目标与学员的关联记录。
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 1. Goal (目标)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Integer | 主键,自增 |
|
||||
| name | String(100) | 目标名称,必填 |
|
||||
| content | Text | Markdown 格式详细内容 |
|
||||
| created_at | DateTime | 创建时间 |
|
||||
| updated_at | DateTime | 更新时间 |
|
||||
|
||||
### 2. GoalRelation (目标关联 - 自关联多对多)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| parent_goal_id | Integer | 外键 → goals.id |
|
||||
| child_goal_id | Integer | 外键 → goals.id |
|
||||
| PRIMARY KEY | (parent_goal_id, child_goal_id) | 联合主键 |
|
||||
|
||||
**约束**:
|
||||
- 禁止循环引用(A→B→C→A)
|
||||
- 自关联:goal 可以是自身的父/子节点
|
||||
|
||||
### 3. StudentGoal (学员目标记录)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Integer | 主键,自增 |
|
||||
| student_id | Integer | 外键 → students.id |
|
||||
| goal_id | Integer | 外键 → goals.id |
|
||||
| status | String(20) | 状态:未开始/进行中/已完成 |
|
||||
| mastery_level | Integer | 完成度:1-5(1最少,5最精通) |
|
||||
| deadline | DateTime | 截止日期 |
|
||||
| completed_at | DateTime | 完成日期 |
|
||||
| created_at | DateTime | 创建时间 |
|
||||
|
||||
**显示规则**:
|
||||
- `mastery_level` 直接渲染为对应数量的五角星(★)
|
||||
|
||||
---
|
||||
|
||||
## API 接口
|
||||
|
||||
### 目标管理
|
||||
|
||||
```
|
||||
GET /api/goals # 获取所有目标
|
||||
POST /api/goals # 创建目标
|
||||
GET /api/goals/<id> # 获取目标详情
|
||||
PUT /api/goals/<id> # 更新目标
|
||||
DELETE /api/goals/<id> # 删除目标
|
||||
```
|
||||
|
||||
### 目标关联
|
||||
|
||||
```
|
||||
GET /api/goals/<id>/parents # 获取父目标列表
|
||||
GET /api/goals/<id>/children # 获取子目标列表
|
||||
POST /api/goals/<id>/children # 添加子目标关联
|
||||
DELETE /api/goals/<id>/children/<child_id> # 移除关联
|
||||
```
|
||||
|
||||
### 学员目标
|
||||
|
||||
```
|
||||
GET /api/students/<student_id>/goals # 获取学员的目标列表
|
||||
POST /api/students/<student_id>/goals # 为学员添加目标
|
||||
PUT /api/students/<student_id>/goals/<goal_id> # 更新学员目标状态
|
||||
DELETE /api/students/<student_id>/goals/<goal_id> # 移除学员的目标
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 循环引用检测
|
||||
|
||||
在添加关联时必须检测:
|
||||
|
||||
```python
|
||||
def has_cycle(goal_id, new_child_id):
|
||||
"""检测添加 new_child_id 作为 goal_id 的子目标是否会形成循环"""
|
||||
visited = set()
|
||||
stack = [new_child_id]
|
||||
|
||||
while stack:
|
||||
current = stack.pop()
|
||||
if current == goal_id:
|
||||
return True # 发现循环
|
||||
if current in visited:
|
||||
continue
|
||||
visited.add(current)
|
||||
# 获取 current 的所有子目标,继续检测
|
||||
for child in get_children(current):
|
||||
stack.append(child)
|
||||
|
||||
return False
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 前端页面
|
||||
|
||||
### 1. 目标管理页面 (`/goals`)
|
||||
|
||||
- 目标列表(可树状展示)
|
||||
- 创建/编辑/删除目标
|
||||
- 目标内容 Markdown 编辑器
|
||||
- 关联管理(拖拽或选择器添加关联)
|
||||
|
||||
### 2. 学员详情页目标区块
|
||||
|
||||
在现有 `student.html` 中扩展:
|
||||
- 显示学员的目标列表
|
||||
- 每项目标显示:名称、状态、★完成度、截止日期
|
||||
- 可添加/移除/编辑目标
|
||||
- 状态变更触发刷新
|
||||
|
||||
---
|
||||
|
||||
## 实现顺序
|
||||
|
||||
1. **数据模型** - goals, goal_relations, student_goals 表
|
||||
2. **目标 CRUD API** - 基础的增删改查
|
||||
3. **目标关联 API** - 关联管理 + 循环检测
|
||||
4. **学员目标 API** - 学员与目标的关联管理
|
||||
5. **目标管理页面** - 目标列表 + 关联管理
|
||||
6. **学员详情页扩展** - 目标区块
|
||||
|
||||
---
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- 无外部依赖
|
||||
- 复用现有的 Markdown 编辑器(EasyMDE)和星级组件
|
||||
Reference in New Issue
Block a user