You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
12 KiB

6 months ago
  1. # 前端开发对接文档
  2. ## 1. 简介
  3. 本文档旨在为前端开发人员提供与后端API交互所需的所有信息。
  4. - **技术栈**: 前端 (Vue) + 后端 (FastAPI)
  5. - **API基础路径**: 所有API路由都以 `/api/v3` 为前缀 (具体URL需根据部署情况配置)。
  6. - **认证**: 系统采用JWT (JSON Web Token) 进行认证。
  7. ---
  8. ## 2. 核心流程
  9. ### 2.1 认证流程
  10. 1. **注册/登录**:
  11. - 新用户通过 `POST /api/v3/register` 接口进行注册。
  12. - 已注册用户通过 `POST /api/v3/login` 接口进行登录。
  13. 2. **获取Token**: 注册或登录成功后,后端会返回一个 `access_token``user_info` 对象。
  14. 3. **存储Token**: 前端需要安全地存储 `access_token` (例如,使用 `localStorage`、`sessionStorage` 或 `cookie`)。
  15. 4. **发送认证请求**: 对于需要认证的接口,前端必须在HTTP请求头中携带 `access_token`
  16. ```
  17. Authorization: Bearer {your_access_token}
  18. ```
  19. ### 2.2 关键数据对象:`user_info`
  20. 注册或登录成功后,前端会收到一个 `user_info` 对象,建议将其保存在全局状态管理器中 (如 Pinia/Vuex),以便在各个页面和组件中使用。
  21. ```json
  22. "user_info": {
  23. "user_id": "user-abc-123", // 用户的唯一、固定ID,安全
  24. "medical_record_number": "J0012345", // 就诊号,用于登录
  25. "name": "张三",
  26. "gender": "男",
  27. "dominant_hand": "右",
  28. "diagnosis": "无",
  29. "dob": "1960-01-15",
  30. "height_cm": 175,
  31. "weight_kg": 70,
  32. "contact": "13800138000",
  33. "inpatient_number": "Z67890",
  34. "bed_number": "503",
  35. "education_level": "本科",
  36. "education_years": 16,
  37. "remarks": ""
  38. }
  39. ```
  40. ### 2.3 错误处理
  41. API会返回标准化的错误响应,前端可以根据 `code``error_details.type` 来实现精细化的错误提示。
  42. ```json
  43. // 示例:参数验证失败
  44. {
  45. "status": "error",
  46. "code": 400,
  47. "message": "Invalid Parameters",
  48. "error_details": {
  49. "type": "validation_error",
  50. "description": "参数验证失败",
  51. "fields": {
  52. "field_name": "错误描述"
  53. }
  54. }
  55. }
  56. ```
  57. ---
  58. ## 3. API 接口参考
  59. ### 页面1: 用户注册 (扫码)
  60. #### `POST /api/v3/register`
  61. - **说明**: 创建一个新患者用户。
  62. - **认证**: 无需
  63. - **请求体**:
  64. ```json
  65. {
  66. "medical_record_number": "string", // 就诊号, 将作为登录用户名
  67. "id_last_six": "string", // 身份证后六位, 将作为登录密码
  68. "name": "string",
  69. "gender": "string",
  70. "dominant_hand": "string",
  71. "diagnosis": "string",
  72. "dob": "string", // 格式: YYYY-MM-DD
  73. "height_cm": "number",
  74. "weight_kg": "number",
  75. "contact": "string",
  76. "inpatient_number": "string", // 可选
  77. "bed_number": "string", // 可选
  78. "education_level": "string", // 可选
  79. "education_years": "number", // 可选
  80. "remarks": "string" // 可选
  81. }
  82. ```
  83. - **成功响应 (200 OK)**: 返回 `access_token``user_info`
  84. ```json
  85. {
  86. "status": "success",
  87. "code": 200,
  88. "data": {
  89. "access_token": "...",
  90. "token_type": "Bearer",
  91. "is_admin": false,
  92. "user_info": { ... }
  93. },
  94. "message": "注册成功并自动登录"
  95. }
  96. ```
  97. ---
  98. ### 页面2: 登录
  99. #### `POST /api/v3/login`
  100. - **说明**: 用户登录。
  101. - **认证**: 无需
  102. - **请求体**:
  103. ```json
  104. {
  105. "username": "string", // medical_record_number 或管理员用户名
  106. "password": "string" // id_last_six 或管理员密码
  107. }
  108. ```
  109. - **成功响应 (200 OK)**:
  110. - **普通用户**: 返回 `access_token``user_info`
  111. - **管理员**: 返回 `access_token``is_admin: true`
  112. ---
  113. ### 页面3: 基本信息确认
  114. - **说明**: 纯前端页面,用于展示从登录/注册接口获取的 `user_info`。用户确认后,前端负责路由跳转到下一页。
  115. ---
  116. ### 页面4: 姿态识别
  117. #### `POST /api/v3/streams` (开始推流)
  118. - **说明**: 启动姿态识别服务,并获取WebSocket连接地址。
  119. - **认证**: **需要**
  120. - **成功响应 (200 OK)**:
  121. ```json
  122. {
  123. "status": "success",
  124. "code": 200,
  125. "data": {
  126. "stream_id": "stream_123456",
  127. "ws_url": "ws://{host}/api/v3/ws/streams/{stream_id}?token={access_token}",
  128. "message": "推流服务已启动,请建立WebSocket连接"
  129. }
  130. }
  131. ```
  132. - **前端工作**: 前端获取 `ws_url` 后,立即建立WebSocket连接。
  133. #### `DELETE /api/v3/streams/{stream_id}` (停止推流)
  134. - **说明**: 停止指定的姿态识别流。
  135. - **认证**: **需要**
  136. #### WebSocket 通信
  137. - **地址**: 由 `POST /api/v3/streams` 接口返回。
  138. - **后端 -> 前端**: 后端会持续推送视频分析数据。
  139. ```json
  140. {
  141. "video_frame": "base64_encoded_image", // Base64编码的视频帧
  142. "timestamp": "...",
  143. "stream_id": "...",
  144. "analysis_data": {
  145. "stage": "stand_up" // 当前阶段标识
  146. }
  147. }
  148. ```
  149. - **前端职责**: 接收到新的 `stage` 后,根据该标识显示对应的提示文本和播放语音。所有提示内容(文本、音频文件)预置在前端。
  150. ---
  151. ### 页面5: 视频交互
  152. #### `GET /api/v3/videos` (获取视频及问卷列表)
  153. - **说明**: 一次性获取所有视频及其关联的问题。
  154. - **认证**: **需要**
  155. - **成功响应 (200 OK)**:
  156. ```json
  157. {
  158. "status": "success",
  159. "code": 200,
  160. "data": {
  161. "videos": [
  162. {
  163. "video_id": "video_123456",
  164. "title": "...",
  165. "description": "...",
  166. "questions": [ ... ]
  167. }
  168. ]
  169. }
  170. }
  171. ```
  172. #### `GET /api/v3/videos/{video_id}.mp4` (获取视频文件)
  173. - **说明**: 用于HTML `<video>` 标签的 `src` 属性,播放视频。
  174. - **认证**: 无需
  175. #### 多模态实时交互 (WebSocket)
  176. - **说明**: 此页面的眼动、面部表情、手写数据采集是并行的。前端主要通过WebSocket与 **手写服务** 交互。
  177. - **WebSocket URL**: 由 `POST /api/v3/video-sessions` 接口动态返回(**注意:此API尚未在文档中明确定义,需与后端确认**)。
  178. - **前端 -> 后端**:
  179. - 发送手写数据: `{"type": "handwriting_stroke", "payload": ...}`
  180. - 结束会话: `{"command": "end_session"}`
  181. ---
  182. ### 页面6: 语音交互 (异步流程)
  183. 此页面交互是异步的,前端需要使用 **SSE (Server-Sent Events)** 来接收实时进度。
  184. #### 1. `POST /api/v3/audio-sessions` (开始会话)
  185. - **说明**: 创建一个语音交互会话。
  186. - **认证**: **需要**
  187. - **成功响应 (200 OK)**: 返回 `session_id`
  188. #### 2. `POST /api/v3/audio-sessions/{session_id}/interact` (上传音频并发起处理)
  189. - **说明**: 上传用户录音,这是一个异步接口,会立即返回。
  190. - **认证**: **需要**
  191. - **请求**: `multipart/form-data`,包含名为 `audio` 的文件。
  192. - **成功响应 (202 Accepted)**:
  193. ```json
  194. {
  195. "status": "accepted",
  196. "code": 202,
  197. "data": {
  198. "request_id": "req_abc123",
  199. "events_url": "/api/v3/audio-sessions/{session_id}/events/{request_id}",
  200. "message": "请求已接收,请连接到events_url获取实时进度"
  201. }
  202. }
  203. ```
  204. #### 3. `GET /api/v3/audio-sessions/{session_id}/events/{request_id}` (监听事件)
  205. - **说明**: 前端使用上一步返回的 `events_url` 建立SSE连接。
  206. - **协议**: `text/event-stream`
  207. - **服务端推送事件**:
  208. - **语音识别(ASR)完成**:
  209. ```
  210. event: asr_result
  211. data: {"status": "success", "text": "用户说的话"}
  212. ```
  213. - **AI回复完成**:
  214. ```
  215. event: ai_result
  216. data: {"status": "success", "text": "AI的回复文本"}
  217. ```
  218. - **语音合成(TTS)完成**:
  219. ```
  220. event: tts_result
  221. data: {"status": "success", "audio_url": "/api/v3/audios/audio_xyz.wav"}
  222. ```
  223. - **任务结束**:
  224. ```
  225. event: done
  226. data: {"status": "success", "message": "处理完成"}
  227. ```
  228. - **错误**:
  229. ```
  230. event: error
  231. data: {"status": "error", "stage": "asr", "message": "ASR处理失败"}
  232. ```
  233. #### 4. `GET /api/v3/audios/{audio_id}.wav` (获取音频文件)
  234. - **说明**: 用于播放TTS合成的语音。
  235. - **认证**: 无需
  236. ---
  237. ### 页面7: 历史测试记录查询
  238. #### `GET /api/v3/admin/logs`
  239. - **说明**: 获取所有历史测试记录的批次列表。仅管理员可访问。
  240. - **认证**: **需要**
  241. - **成功响应 (200 OK)**:
  242. ```json
  243. {
  244. "status": "success",
  245. "code": 200,
  246. "data": {
  247. "tables": [
  248. {
  249. "table_name": "test_20240315_1",
  250. "created_at": "2024-03-15T14:30:00Z",
  251. "description": "2024年3月15日第一次测试"
  252. },
  253. {
  254. "table_name": "test_20240315_2",
  255. "created_at": "2024-03-15T16:30:00Z",
  256. "description": "2024年3月15日第二次测试"
  257. }
  258. ]
  259. }
  260. }
  261. ```
  262. ---
  263. ### 页面8: 单次测试记录列表
  264. #### `GET /api/v3/admin/logs/{table_name}`
  265. - **说明**: 查询指定批次下的所有测试者记录。
  266. - **认证**: **需要**
  267. - **Query参数**:
  268. - `page` (number, optional, default: 1): 页码
  269. - `page_size` (number, optional, default: 50): 每页数量
  270. - **成功响应 (200 OK)**:
  271. ```json
  272. {
  273. "status": "success",
  274. "code": 200,
  275. "data": {
  276. "total": 100,
  277. "total_pages": 2,
  278. "current_page": 1,
  279. "page_size": 50,
  280. "records": [
  281. {
  282. "log_id": 1,
  283. "medical_record_number": "J0012345",
  284. "name": "张三",
  285. "created_at": "2024-03-15T08:30:00Z",
  286. "status": "completed"
  287. }
  288. ]
  289. }
  290. }
  291. ```
  292. - **`status` 字段说明**:
  293. - `initialized`: 已初始化
  294. - `processing`: 数据处理中
  295. - `pending_review`: 待专家审核
  296. - `completed`: 已完成
  297. ---
  298. ### 页面9: 分析模块详情与编辑
  299. 所有此部分的API都需要认证,并使用路径参数 `/api/v3/admin/logs/{table_name}/{log_id}/...`
  300. #### 步态分析 (Gait)
  301. - **`GET .../gait`**: 获取步态分析数据(包含事件、分段和计算指标)。
  302. - **`POST .../gait/events`**: 提交修正后的事件标记,后端将重新计算并返回更新后的数据。
  303. - **请求体**:
  304. ```json
  305. {
  306. "events": [
  307. { "event": "stand_up", "frame": 85 },
  308. { "event": "walk_start", "frame": 180 },
  309. { "event": "walk_end", "frame": 840 }
  310. ]
  311. }
  312. ```
  313. #### 面部表情分析 (Facial)
  314. - **`GET .../facial`**: 获取面部表情视频URL及当前UPDRS评级。
  315. - **`POST .../facial/rating`**: 提交或更新UPDRS评级。
  316. - **请求体**: `{"rating": 2}` (评级范围: 0-4)
  317. #### 眼动分析 (Eyetracking)
  318. - **`GET .../eyetracking`**: 获取眼动分析视频URL及当前评级。
  319. - **`POST .../eyetracking/rating`**: 提交或更新评级。
  320. - **请求体**: `{"rating": 3}` (评级范围: 0-4)
  321. #### 手写笔迹分析 (Handwriting)
  322. - **`GET .../handwriting`**: 获取手写数据视频URL及当前评级。
  323. - **`POST .../handwriting/rating`**: 提交或更新评级。
  324. - **请求体**: `{"rating": 1}` (评级范围: 0-4)
  325. #### 语音分析 (Speech)
  326. - **`GET .../speech`**: 获取语音样本URL及当前评级。
  327. - **`POST .../speech/rating`**: 提交或更新评级。
  328. - **请求体**: `{"rating": 3}` (评级范围: 0-4)
  329. #### 语义分析 (Semantics)
  330. - **`GET .../semantics`**: 获取文本内容及当前评级。
  331. - **`POST .../semantics/rating`**: 提交或更新评级。
  332. - **请求体**: `{"rating": 1}` (评级范围: 0-4)
  333. #### 原始数据下载
  334. - **`GET .../raw`**: 下载原始时序数据 (CSV文件)。
  335. - **说明**: 后端直接返回文件流,前端需处理下载。
  336. - **响应头**: `Content-Type: text/csv`, `Content-Disposition: attachment; filename="..."`