- 添加典型方案采纳功能 (POST /api/plans/<id>/adopt) - 添加推荐方案列表 (GET /api/students/<id>/recommended-plans) - PracticePlan 新增 created_by/updated_by/updated_at 审计字段 - 方案编辑/详情页导航优化 (bfcache 处理、pageshow 事件) - 方案列表支持删除功能 - 学员列表'暂无方案/问题'样式统一 - 更新文档:问题文件已废弃(迁移到数据库) - 更新部署脚本和验证清单
17 KiB
API 接口文档
基础信息
- Base URL:
http://127.0.0.1:5001 - Content-Type:
application/json
认证接口
检查登录状态
GET /api/check-login
响应示例:
{
"logged_in": true,
"username": "admin",
"role": "admin"
}
登录
POST /api/login
请求体:
{
"username": "admin",
"password": "Admin@123"
}
响应示例:
{
"message": "登录成功"
}
登出
POST /api/logout
初始设置(首次)
GET /setup
初始设置提交
POST /api/setup
请求体:
{
"username": "admin",
"password": "Admin@123",
"confirm_password": "Admin@123"
}
修改当前用户密码
POST /api/users/change-password
请求体:
{
"old_password": "Old@123",
"new_password": "New@123",
"confirm_password": "New@123"
}
用户管理(仅管理员)
获取用户列表
GET /api/users
响应示例:
[
{
"id": 1,
"username": "admin",
"name": "管理员",
"role": "admin",
"created_at": "2026-04-17 10:00"
},
{
"id": 2,
"username": "teacher1",
"name": "张老师",
"role": "user",
"created_at": "2026-04-18 10:00"
}
]
新增用户
POST /api/users
请求体:
{
"username": "newuser",
"password": "User@123",
"role": "user"
}
角色选项: admin, user
编辑用户
PUT /api/users/<id>
请求体:
{
"name": "新姓名",
"role": "user"
}
⚠️
username不可修改,密码通过单独接口修改
重置用户密码
POST /api/users/<id>/reset-password
请求体:
{
"new_password": "Reset@123"
}
删除用户
DELETE /api/users/<id>
班级管理
获取班级列表
GET /api/classes
权限: 登录用户
响应示例:
[
{
"id": 1,
"name": "钢琴初级班",
"level": "入门",
"description": "入门学员",
"teacher_id": 2,
"teacher_name": "张老师",
"student_count": 5,
"active": true,
"created_at": "2026-04-17 10:00"
}
]
新增班级
POST /api/classes
权限: 管理员
请求体:
{
"name": "钢琴中级班",
"level": "入门",
"description": "进阶学员",
"teacher_id": 2
}
编辑班级
PUT /api/classes/<id>
权限: 管理员
请求体:
{
"name": "钢琴中级班(2026)",
"level": "入门",
"description": "进阶学员",
"teacher_id": 2,
"active": true
}
删除班级
DELETE /api/classes/<id>
权限: 管理员
获取班级学员列表
GET /api/classes/<id>/students
权限: 登录用户
响应示例:
[
{
"id": 1,
"name": "张三",
"phone": "13800138000",
"practice_time": "30分钟"
}
]
分配学员到班级
POST /api/classes/<id>/assign
权限: 登录用户
请求体:
{
"student_ids": [1, 2, 3]
}
批量分配目标给班级学员
POST /api/classes/<id>/goals
权限: 登录用户
请求体:
{
"goal_id": 1,
"assessment_days": "30",
"assessment_date": null,
"start_date": null,
"start_now": true
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| goal_id | int | 是 | 目标ID |
| assessment_days | string | 否 | 评估天数(15/30/60/90/180) |
| assessment_date | string | 否 | 评估日期(YYYY-MM-DD),与 assessment_days 二选一 |
| start_date | string | 否 | 开始日期(YYYY-MM-DD) |
| start_now | bool | 否 | 是否立即开始(默认true) |
响应示例:
{
"message": "成功分配 5 个学员",
"assigned": 5,
"skipped": ["李四", "王五"],
"skipped_count": 2
}
学员管理
获取学员列表
GET /api/students
权限: 登录用户
响应示例:
[
{
"id": 1,
"name": "张三",
"phone": "13800138000",
"wechat_nickname": "小张",
"practice_time": "30分钟",
"class_id": 1,
"class_name": "钢琴初级班",
"notes": "",
"problem_count": 2,
"plan_count": 1,
"created_at": "2026-04-17 10:00"
}
]
创建学员
POST /api/students
权限: 登录用户
请求体:
{
"name": "学员姓名",
"phone": "手机号",
"wechat_nickname": "微信昵称",
"practice_time": "30分钟",
"class_id": 1,
"notes": "备注信息"
}
获取学员详情
GET /api/students/<id>
更新学员
PUT /api/students/<id>
权限: 登录用户
请求体:
{
"name": "新姓名",
"phone": "新手机号",
"wechat_nickname": "新昵称",
"practice_time": "45分钟",
"class_id": 2,
"notes": "新备注"
}
删除学员
DELETE /api/students/<id>
问题记录
获取学员的问题列表
GET /api/students/<student_id>/problems
添加问题
POST /api/students/<student_id>/problems
请求体:
{
"problem_id": "01_手小",
"problem_name": "手小",
"severity": "中等",
"level": "入门"
}
严重程度选项: 轻微, 中等, 严重
级别选项: 启蒙, 入门, 进阶, 熟练, 精通
删除问题
DELETE /api/students/<student_id>/problems/<problem_id>
方案生成
生成练习方案
POST /api/generate-plan
请求体:
{
"student_id": 1,
"use_ai": true,
"template_id": 1
}
参数说明:
student_id: 学员IDuse_ai: 是否使用AI生成个性化报告(默认true)template_id: AI提示词模板ID(可选,不传则使用排序第一的默认模板)
AI提示词模板参数:
| 参数 | 说明 |
|---|---|
{student_name} |
学员姓名 |
{practice_time} |
每日练习时间 |
{problems} |
学员问题列表(含严重程度、级别、建议练习时间) |
{student_goals} |
学员未达成的目标内容(Markdown格式) |
{schedule_table} |
响应: SSE 流,包含进度信息
SSE 事件说明:
| step | 说明 |
|---|---|
| collecting | 收集问题数据 |
| basic | 生成基础练习方案 |
| basic_done | 基础方案生成完成 |
| ai_config | AI配置信息 |
| ai_start | 开始调用AI |
| ai_problems | 发送给AI的问题摘要 |
| ai_request | 等待AI响应 |
| ai_prompt | AI提示词已生成(含字数) |
| ai_generating | AI报告生成中 |
| ai_response | AI响应已接收 |
| ai_done | AI报告生成完成 |
| saved | 方案已保存 |
| complete | 全部完成 |
complete 事件包含:
{
"step": "complete",
"prompt_length": 1234,
"ai_report_length": 567,
"plan_id": 1
}
预览提示词
POST /api/generate-plan/preview
功能: 根据学员ID和模板生成提示词,但不保存方案。用于在生成前预览提示词内容。
请求体:
{
"student_id": 1,
"template_id": 1
}
响应示例:
{
"prompt": "根据学员张三的每日练习时间30分钟和以下问题,为其生成个性化练习方案...\n\n问题列表:\n1. 手小(中等)\n...",
"prompt_length": 1234,
"student_goals_length": 200,
"problems_length": 150
}
SSE 事件说明:
| step | 说明 |
|---|---|
| collecting | 收集数据 |
| prompt_generated | 提示词已生成(含字数统计) |
| complete | 预览完成 |
获取方案详情
GET /api/plans/<plan_id>
响应示例:
{
"id": 1,
"student_id": 1,
"student_name": "张三",
"template_name": "默认模板",
"is_typical": false,
"created_at": "2026-04-17 10:30",
"updated_at": "2026-04-27 15:00",
"updated_by_name": "管理员",
"content": {
"student_name": "张三",
"practice_time": "30分钟",
"total_daily_minutes": 30,
"problems": [
{"name": "手小", "level": "入门", "severity": "中等"}
],
"ai_report": "..."
}
}
注意:
updated_at和updated_by_name仅在方案被编辑过后才会有值。
获取学员方案列表
GET /api/students/<student_id>/plans
获取推荐方案列表
GET /api/students/<student_id>/recommended-plans
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| filter | string | 筛选条件:all(全部)或 mine(我的) |
响应示例:
[
{
"id": 5,
"student_name": "李四",
"template_name": "默认模板",
"is_typical": true,
"created_at": "2026-04-20 10:00",
"problem_names": ["手小", "识谱慢"],
"can_adopt": true,
"adopted": false
}
]
采纳典型方案
POST /api/plans/<plan_id>/adopt
请求体:
{
"student_id": 1
}
响应:
{
"message": "方案已采纳",
"plan_id": 6
}
更新方案内容
PUT /api/plans/<plan_id>/content
功能: 编辑方案后保存内容
请求体:
{
"content": "{\"ai_report\": \"...\", \"daily_schedule\": [...]}"
}
响应:
{
"message": "保存成功"
}
设为典型方案
POST /api/plans/<plan_id>/typical
响应:
{
"success": true,
"is_typical": true
}
删除方案
DELETE /api/plans/<plan_id>
导出PDF
GET /api/plans/<plan_id>/pdf
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| template_id | int | 报告模板ID(可选,不传则使用排序第一的默认模板) |
返回: PDF文件下载
导出Markdown
GET /api/plans/<plan_id>/md
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| template_id | int | 报告模板ID(可选,不传则使用排序第一的默认模板) |
返回: Markdown文件下载
微信卡片展示
GET /plans/<plan_id>/wechat
返回: HTML页面,用于微信分享
问题配置(仅管理员)
获取问题列表
GET /api/problems
获取问题详情
GET /api/problems/<problem_id>
创建问题
POST /api/problems
更新问题
PUT /api/problems/<problem_id>
删除问题
DELETE /api/problems/<problem_id>
API设置(仅管理员)
获取API配置
GET /api/config
更新API配置
POST /api/config
测试API连接
POST /api/config/test
目标管理 API
GET /api/goals
获取所有目标
响应:
[
{
"id": 1,
"name": "掌握基本音阶",
"content": "...",
"created_at": "2026-04-23T10:00:00",
"updated_at": "2026-04-23T10:00:00"
}
]
POST /api/goals
创建新目标
请求体:
{
"name": "目标名称",
"content": "目标内容(Markdown)"
}
GET /api/goals/{id}
获取单个目标
PUT /api/goals/{id}
更新目标
DELETE /api/goals/{id}
删除目标(仅管理员)
权限: 仅管理员
依赖检查:如果存在以下依赖关系,禁止删除:
- 已被学员分配的目标
- 作为父目标或子目标被其他目标关联
错误响应示例:
{"error": "无法删除:已被 3 名学员分配, 有 2 个子目标关联"}
GET /api/goals/{id}/children
获取目标的子目标
GET /api/goals/{id}/parents
获取目标的父目标
POST /api/goals/{id}/children
添加子目标关联(含循环检测)
请求体:
{
"child_goal_id": 2
}
DELETE /api/goals/{id}/children/{child_id}
移除子目标关联
学员目标 API
GET /api/students/{id}/goals
获取学员的所有目标
响应:
[
{
"id": 1,
"student_id": 1,
"goal_id": 1,
"goal_name": "掌握基本音阶",
"goal_content": "目标详细描述内容(Markdown)...",
"goal_level": "入门",
"goal_category": "演奏能力",
"status": "进行中",
"start_date": "2026-04-01T00:00:00",
"assessment_date": "2026-05-01T00:00:00",
"mastery_level": 3,
"achievement_date": null,
"comment": null,
"created_at": "2026-04-01T10:00:00"
}
]
排序:按状态(进行中→未开始→已结束),再按评估日期倒序
POST /api/students/{id}/goals
为学员分配目标
请求体:
{
"goal_id": 1,
"assessment_days": 30,
"assessment_date": "2026-05-01",
"start_date": "2026-04-01",
"start_now": true
}
| 字段 | 类型 | 说明 |
|---|---|---|
| goal_id | Integer | 目标ID,必填 |
| assessment_days | Integer | 评估天数(15/30/60/90/180),与 assessment_date 二选一 |
| assessment_date | String | 具体评估日期(ISO格式),与 assessment_days 二选一 |
| start_date | String | 开始日期(ISO格式),可选 |
| start_now | Boolean | 设为 true 表示立即开始(默认当前时间) |
PUT /api/students/{id}/goals/{goal_id}
更新学员目标
请求体:
{
"start_date": "2026-04-01",
"assessment_date": "2026-05-01",
"mastery_level": 4,
"achievement_date": "2026-05-01",
"comment": "表现优秀,已掌握"
}
| 字段 | 类型 | 说明 |
|---|---|---|
| start_date | String | 开始日期(ISO格式) |
| assessment_date | String | 评估日期(ISO格式) |
| mastery_level | Integer | 掌握程度 1-5 |
| achievement_date | String | 达成日期(ISO格式) |
| comment | String | 评语 |
DELETE /api/students/{id}/goals/{goal_id}
移除学员的目标(仅管理员,会级联删除关联的评估记录)
权限: 仅管理员
学员目标评估 API
GET /api/students/{id}/evaluations
获取学员的所有评估记录
响应:
[
{
"id": 1,
"student_goal_id": 1,
"goal_name": "掌握基本音阶",
"evaluator_id": 1,
"evaluator_name": "管理员",
"assessment_date": "2026-04-15",
"mastery_level": 3,
"comment": "进步明显",
"is_final": false,
"created_at": "2026-04-15T10:00:00"
}
]
POST /api/students/{id}/evaluations
创建评估记录
请求体:
{
"student_goal_id": 1,
"assessment_date": "2026-04-15",
"mastery_level": 3,
"comment": "进步明显",
"is_final": false
}
| 字段 | 类型 | 说明 |
|---|---|---|
| student_goal_id | Integer | 学员目标ID |
| assessment_date | String | 评估日期(YYYY-MM-DD) |
| mastery_level | Integer | 掌握程度 1-5 |
| comment | String | 评语 |
| is_final | Boolean | 是否为最终评估 |
PUT /api/evaluations/{id}
更新评估记录
请求体:
{
"assessment_date": "2026-04-16",
"mastery_level": 4,
"comment": "已完全掌握",
"is_final": true
}
DELETE /api/evaluations/{id}
删除评估记录
模板管理 API
GET /templates/templates
获取所有模板(按sort_order排序)
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| type | string | 可选,按类型筛选(ai_prompt/report) |
响应:
[
{
"id": 1,
"name": "AI提示词模板",
"type": "ai_prompt",
"description": "生成练习方案时发送给AI的提示词",
"content": "...",
"sort_order": 0,
"created_at": "2026-04-23T10:00:00"
},
{
"id": 2,
"name": "报告导出模板",
"type": "report",
"description": "导出方案时使用的Markdown模板",
"content": "...",
"sort_order": 0,
"created_at": "2026-04-23T10:00:00"
}
]
GET /templates/templates/{id}
获取单个模板
POST /templates/templates
创建模板
请求体:
{
"name": "新模板名称",
"type": "ai_prompt",
"content": "模板内容...",
"description": "模板描述",
"sort_order": 1
}
| 字段 | 类型 | 说明 |
|---|---|---|
| name | String | 模板名称 |
| type | String | 类型:ai_prompt(AI提示词)或 report(报告导出) |
| content | String | 模板内容(Markdown格式) |
| description | String | 描述 |
| sort_order | Integer | 排序序号(越小越靠前) |
PUT /templates/templates/{id}
更新模板
DELETE /templates/templates/{id}
删除模板
POST /templates/templates/{type}/render
渲染模板预览
参数: type 为 ai_prompt 或 report
请求体:用于替换模板中的变量
{
"student_name": "张三",
"practice_time": "30分钟",
"problems": "...",
"student_goals": "..."
}
响应:
{
"rendered": "渲染后的内容..."
}
权限说明
| 接口 | 管理员 | 普通用户 |
|---|---|---|
| 用户管理 | ✅ | ❌ |
| 班级增删改 | ✅ | ❌ |
| 班级查询/分配学员 | ✅ | ✅ |
| 学员管理 | ✅ | ✅ |
| 问题记录 | ✅ | ✅ |
| 方案生成/预览 | ✅ | ✅ |
| 模板管理 | ✅ | ❌ |
| 系统设置 | ✅ | ❌ |
| 修改自己密码 | ✅ | ✅ |
错误响应
所有接口的错误响应格式:
{
"error": "错误信息描述"
}
状态码:
400- 请求参数错误401- 未登录或认证失败403- 权限不足404- 资源不存在500- 服务器内部错误