Files
piano-plan/docs/API.md
T
hmo e50a9207b4 feat: v1.4.0 - 典型方案采纳、推荐方案列表、审计字段、导航优化
- 添加典型方案采纳功能 (POST /api/plans/<id>/adopt)
- 添加推荐方案列表 (GET /api/students/<id>/recommended-plans)
- PracticePlan 新增 created_by/updated_by/updated_at 审计字段
- 方案编辑/详情页导航优化 (bfcache 处理、pageshow 事件)
- 方案列表支持删除功能
- 学员列表'暂无方案/问题'样式统一
- 更新文档:问题文件已废弃(迁移到数据库)
- 更新部署脚本和验证清单
2026-04-27 02:01:22 +08:00

17 KiB
Raw Blame History

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: 学员ID
  • use_ai: 是否使用AI生成个性化报告(默认true)
  • template_id: AI提示词模板ID(可选,不传则使用排序第一的默认模板)

AI提示词模板参数:

参数 说明
{student_name} 学员姓名
{practice_time} 每日练习时间
{problems} 学员问题列表(含严重程度、级别、建议练习时间)
{student_goals} 学员未达成的目标内容(Markdown格式)
{schedule_table} 每日练习安排表(已废弃,AI报告已包含)

响应: 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_atupdated_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_promptAI提示词)或 report(报告导出)
content String 模板内容(Markdown格式)
description String 描述
sort_order Integer 排序序号(越小越靠前)

PUT /templates/templates/{id}

更新模板

DELETE /templates/templates/{id}

删除模板

POST /templates/templates/{type}/render

渲染模板预览

参数: typeai_promptreport

请求体:用于替换模板中的变量

{
  "student_name": "张三",
  "practice_time": "30分钟",
  "problems": "...",
  "student_goals": "..."
}

响应

{
  "rendered": "渲染后的内容..."
}

权限说明

接口 管理员 普通用户
用户管理
班级增删改
班级查询/分配学员
学员管理
问题记录
方案生成/预览
模板管理
系统设置
修改自己密码

错误响应

所有接口的错误响应格式:

{
  "error": "错误信息描述"
}

状态码:

  • 400 - 请求参数错误
  • 401 - 未登录或认证失败
  • 403 - 权限不足
  • 404 - 资源不存在
  • 500 - 服务器内部错误