Browse Source

首次提交

master
ywn2008 6 months ago
commit
690bd7e7db
4 changed files with 2129 additions and 0 deletions
  1. +413
    -0
      前端开发对接文档.md
  2. +262
    -0
      数据库框架.md
  3. +247
    -0
      注册路由说明.md
  4. +1207
    -0
      软件框架V2.md

+ 413
- 0
前端开发对接文档.md View File

@ -0,0 +1,413 @@
# 前端开发对接文档
## 1. 简介
本文档旨在为前端开发人员提供与后端API交互所需的所有信息。
- **技术栈**: 前端 (Vue) + 后端 (FastAPI)
- **API基础路径**: 所有API路由都以 `/api/v3` 为前缀 (具体URL需根据部署情况配置)。
- **认证**: 系统采用JWT (JSON Web Token) 进行认证。
---
## 2. 核心流程
### 2.1 认证流程
1. **注册/登录**:
- 新用户通过 `POST /api/v3/register` 接口进行注册。
- 已注册用户通过 `POST /api/v3/login` 接口进行登录。
2. **获取Token**: 注册或登录成功后,后端会返回一个 `access_token``user_info` 对象。
3. **存储Token**: 前端需要安全地存储 `access_token` (例如,使用 `localStorage`、`sessionStorage` 或 `cookie`)。
4. **发送认证请求**: 对于需要认证的接口,前端必须在HTTP请求头中携带 `access_token`
```
Authorization: Bearer {your_access_token}
```
### 2.2 关键数据对象:`user_info`
注册或登录成功后,前端会收到一个 `user_info` 对象,建议将其保存在全局状态管理器中 (如 Pinia/Vuex),以便在各个页面和组件中使用。
```json
"user_info": {
"user_id": "user-abc-123", // 用户的唯一、固定ID,安全
"medical_record_number": "J0012345", // 就诊号,用于登录
"name": "张三",
"gender": "男",
"dominant_hand": "右",
"diagnosis": "无",
"dob": "1960-01-15",
"height_cm": 175,
"weight_kg": 70,
"contact": "13800138000",
"inpatient_number": "Z67890",
"bed_number": "503",
"education_level": "本科",
"education_years": 16,
"remarks": ""
}
```
### 2.3 错误处理
API会返回标准化的错误响应,前端可以根据 `code``error_details.type` 来实现精细化的错误提示。
```json
// 示例:参数验证失败
{
"status": "error",
"code": 400,
"message": "Invalid Parameters",
"error_details": {
"type": "validation_error",
"description": "参数验证失败",
"fields": {
"field_name": "错误描述"
}
}
}
```
---
## 3. API 接口参考
### 页面1: 用户注册 (扫码)
#### `POST /api/v3/register`
- **说明**: 创建一个新患者用户。
- **认证**: 无需
- **请求体**:
```json
{
"medical_record_number": "string", // 就诊号, 将作为登录用户名
"id_last_six": "string", // 身份证后六位, 将作为登录密码
"name": "string",
"gender": "string",
"dominant_hand": "string",
"diagnosis": "string",
"dob": "string", // 格式: YYYY-MM-DD
"height_cm": "number",
"weight_kg": "number",
"contact": "string",
"inpatient_number": "string", // 可选
"bed_number": "string", // 可选
"education_level": "string", // 可选
"education_years": "number", // 可选
"remarks": "string" // 可选
}
```
- **成功响应 (200 OK)**: 返回 `access_token``user_info`
```json
{
"status": "success",
"code": 200,
"data": {
"access_token": "...",
"token_type": "Bearer",
"is_admin": false,
"user_info": { ... }
},
"message": "注册成功并自动登录"
}
```
---
### 页面2: 登录
#### `POST /api/v3/login`
- **说明**: 用户登录。
- **认证**: 无需
- **请求体**:
```json
{
"username": "string", // medical_record_number 或管理员用户名
"password": "string" // id_last_six 或管理员密码
}
```
- **成功响应 (200 OK)**:
- **普通用户**: 返回 `access_token``user_info`
- **管理员**: 返回 `access_token``is_admin: true`
---
### 页面3: 基本信息确认
- **说明**: 纯前端页面,用于展示从登录/注册接口获取的 `user_info`。用户确认后,前端负责路由跳转到下一页。
---
### 页面4: 姿态识别
#### `POST /api/v3/streams` (开始推流)
- **说明**: 启动姿态识别服务,并获取WebSocket连接地址。
- **认证**: **需要**
- **成功响应 (200 OK)**:
```json
{
"status": "success",
"code": 200,
"data": {
"stream_id": "stream_123456",
"ws_url": "ws://{host}/api/v3/ws/streams/{stream_id}?token={access_token}",
"message": "推流服务已启动,请建立WebSocket连接"
}
}
```
- **前端工作**: 前端获取 `ws_url` 后,立即建立WebSocket连接。
#### `DELETE /api/v3/streams/{stream_id}` (停止推流)
- **说明**: 停止指定的姿态识别流。
- **认证**: **需要**
#### WebSocket 通信
- **地址**: 由 `POST /api/v3/streams` 接口返回。
- **后端 -> 前端**: 后端会持续推送视频分析数据。
```json
{
"video_frame": "base64_encoded_image", // Base64编码的视频帧
"timestamp": "...",
"stream_id": "...",
"analysis_data": {
"stage": "stand_up" // 当前阶段标识
}
}
```
- **前端职责**: 接收到新的 `stage` 后,根据该标识显示对应的提示文本和播放语音。所有提示内容(文本、音频文件)预置在前端。
---
### 页面5: 视频交互
#### `GET /api/v3/videos` (获取视频及问卷列表)
- **说明**: 一次性获取所有视频及其关联的问题。
- **认证**: **需要**
- **成功响应 (200 OK)**:
```json
{
"status": "success",
"code": 200,
"data": {
"videos": [
{
"video_id": "video_123456",
"title": "...",
"description": "...",
"questions": [ ... ]
}
]
}
}
```
#### `GET /api/v3/videos/{video_id}.mp4` (获取视频文件)
- **说明**: 用于HTML `<video>` 标签的 `src` 属性,播放视频。
- **认证**: 无需
#### 多模态实时交互 (WebSocket)
- **说明**: 此页面的眼动、面部表情、手写数据采集是并行的。前端主要通过WebSocket与 **手写服务** 交互。
- **WebSocket URL**: 由 `POST /api/v3/video-sessions` 接口动态返回(**注意:此API尚未在文档中明确定义,需与后端确认**)。
- **前端 -> 后端**:
- 发送手写数据: `{"type": "handwriting_stroke", "payload": ...}`
- 结束会话: `{"command": "end_session"}`
---
### 页面6: 语音交互 (异步流程)
此页面交互是异步的,前端需要使用 **SSE (Server-Sent Events)** 来接收实时进度。
#### 1. `POST /api/v3/audio-sessions` (开始会话)
- **说明**: 创建一个语音交互会话。
- **认证**: **需要**
- **成功响应 (200 OK)**: 返回 `session_id`
#### 2. `POST /api/v3/audio-sessions/{session_id}/interact` (上传音频并发起处理)
- **说明**: 上传用户录音,这是一个异步接口,会立即返回。
- **认证**: **需要**
- **请求**: `multipart/form-data`,包含名为 `audio` 的文件。
- **成功响应 (202 Accepted)**:
```json
{
"status": "accepted",
"code": 202,
"data": {
"request_id": "req_abc123",
"events_url": "/api/v3/audio-sessions/{session_id}/events/{request_id}",
"message": "请求已接收,请连接到events_url获取实时进度"
}
}
```
#### 3. `GET /api/v3/audio-sessions/{session_id}/events/{request_id}` (监听事件)
- **说明**: 前端使用上一步返回的 `events_url` 建立SSE连接。
- **协议**: `text/event-stream`
- **服务端推送事件**:
- **语音识别(ASR)完成**:
```
event: asr_result
data: {"status": "success", "text": "用户说的话"}
```
- **AI回复完成**:
```
event: ai_result
data: {"status": "success", "text": "AI的回复文本"}
```
- **语音合成(TTS)完成**:
```
event: tts_result
data: {"status": "success", "audio_url": "/api/v3/audios/audio_xyz.wav"}
```
- **任务结束**:
```
event: done
data: {"status": "success", "message": "处理完成"}
```
- **错误**:
```
event: error
data: {"status": "error", "stage": "asr", "message": "ASR处理失败"}
```
#### 4. `GET /api/v3/audios/{audio_id}.wav` (获取音频文件)
- **说明**: 用于播放TTS合成的语音。
- **认证**: 无需
---
### 页面7: 历史测试记录查询
#### `GET /api/v3/admin/logs`
- **说明**: 获取所有历史测试记录的批次列表。仅管理员可访问。
- **认证**: **需要**
- **成功响应 (200 OK)**:
```json
{
"status": "success",
"code": 200,
"data": {
"tables": [
{
"table_name": "test_20240315_1",
"created_at": "2024-03-15T14:30:00Z",
"description": "2024年3月15日第一次测试"
},
{
"table_name": "test_20240315_2",
"created_at": "2024-03-15T16:30:00Z",
"description": "2024年3月15日第二次测试"
}
]
}
}
```
---
### 页面8: 单次测试记录列表
#### `GET /api/v3/admin/logs/{table_name}`
- **说明**: 查询指定批次下的所有测试者记录。
- **认证**: **需要**
- **Query参数**:
- `page` (number, optional, default: 1): 页码
- `page_size` (number, optional, default: 50): 每页数量
- **成功响应 (200 OK)**:
```json
{
"status": "success",
"code": 200,
"data": {
"total": 100,
"total_pages": 2,
"current_page": 1,
"page_size": 50,
"records": [
{
"log_id": 1,
"medical_record_number": "J0012345",
"name": "张三",
"created_at": "2024-03-15T08:30:00Z",
"status": "completed"
}
]
}
}
```
- **`status` 字段说明**:
- `initialized`: 已初始化
- `processing`: 数据处理中
- `pending_review`: 待专家审核
- `completed`: 已完成
---
### 页面9: 分析模块详情与编辑
所有此部分的API都需要认证,并使用路径参数 `/api/v3/admin/logs/{table_name}/{log_id}/...`
#### 步态分析 (Gait)
- **`GET .../gait`**: 获取步态分析数据(包含事件、分段和计算指标)。
- **`POST .../gait/events`**: 提交修正后的事件标记,后端将重新计算并返回更新后的数据。
- **请求体**:
```json
{
"events": [
{ "event": "stand_up", "frame": 85 },
{ "event": "walk_start", "frame": 180 },
{ "event": "walk_end", "frame": 840 }
]
}
```
#### 面部表情分析 (Facial)
- **`GET .../facial`**: 获取面部表情视频URL及当前UPDRS评级。
- **`POST .../facial/rating`**: 提交或更新UPDRS评级。
- **请求体**: `{"rating": 2}` (评级范围: 0-4)
#### 眼动分析 (Eyetracking)
- **`GET .../eyetracking`**: 获取眼动分析视频URL及当前评级。
- **`POST .../eyetracking/rating`**: 提交或更新评级。
- **请求体**: `{"rating": 3}` (评级范围: 0-4)
#### 手写笔迹分析 (Handwriting)
- **`GET .../handwriting`**: 获取手写数据视频URL及当前评级。
- **`POST .../handwriting/rating`**: 提交或更新评级。
- **请求体**: `{"rating": 1}` (评级范围: 0-4)
#### 语音分析 (Speech)
- **`GET .../speech`**: 获取语音样本URL及当前评级。
- **`POST .../speech/rating`**: 提交或更新评级。
- **请求体**: `{"rating": 3}` (评级范围: 0-4)
#### 语义分析 (Semantics)
- **`GET .../semantics`**: 获取文本内容及当前评级。
- **`POST .../semantics/rating`**: 提交或更新评级。
- **请求体**: `{"rating": 1}` (评级范围: 0-4)
#### 原始数据下载
- **`GET .../raw`**: 下载原始时序数据 (CSV文件)。
- **说明**: 后端直接返回文件流,前端需处理下载。
- **响应头**: `Content-Type: text/csv`, `Content-Disposition: attachment; filename="..."`

+ 262
- 0
数据库框架.md View File

@ -0,0 +1,262 @@
# 数据库表结构定义
## `user_info`
用于存储管理员用户的基本信息、认证凭据和权限。**注意:此表只存储管理员用户,患者用户存储在 `patient_info` 表中。**
### 表结构 (SQL DDL)
```sql
CREATE TABLE user_info (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
hashed_password VARCHAR(255) NOT NULL,
department VARCHAR(100),
position VARCHAR(100),
is_admin BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
### 字段说明
| 字段名 | 类型 | 约束 | 说明 |
| --------------- | ------------- | --------------- | ---------------------------------------- |
| `id` | SERIAL | PRIMARY KEY | 管理员唯一标识,自增主键。 |
| `username` | VARCHAR(50) | UNIQUE, NOT NULL| 管理员用户名,用于登录,必须唯一。 |
| `email` | VARCHAR(255) | UNIQUE, NOT NULL| 管理员邮箱,必须唯一。 |
| `hashed_password` | VARCHAR(255) | NOT NULL | 使用 bcrypt 哈希算法加密后的密码。 |
| `department` | VARCHAR(100) | | 管理员所属部门。 |
| `position` | VARCHAR(100) | | 管理员职位。 |
| `is_admin` | BOOLEAN | DEFAULT TRUE | 标识用户是否为管理员,默认为 `TRUE`。 |
| `created_at` | TIMESTAMPTZ | DEFAULT NOW() | 记录创建时间。 |
| `updated_at` | TIMESTAMPTZ | DEFAULT NOW() | 记录最后更新时间。 |
### 示例数据
为了方便测试,可以插入以下数据:
```sql
-- 密码: admin123
INSERT INTO user_info (username, email, hashed_password, department, position, is_admin)
VALUES ('admin', 'admin@example.com', '$2b$12$EixZaYVK1eCjG4n6b5D1zuR8yA5d1E0n.3Jd9G.Yk.H8zJ.p7.wI.', '系统管理', '管理员', TRUE);
-- 密码: manager123
INSERT INTO user_info (username, email, hashed_password, department, position, is_admin)
VALUES ('manager', 'manager@example.com', '$2b$12$xG.Vn2G7f2wJdDGkQxGjA.w0q.K6.Qj3S.h2Z/d.aY5q.w2K.X5U.', '医疗管理', '主管', TRUE);
```
## `patient_info`
用于存储患者用户的基本信息和认证凭据。患者通过扫码注册,使用就诊号+身份证后六位登录。
### 表结构 (SQL DDL)
```sql
CREATE TABLE patient_info (
id SERIAL PRIMARY KEY,
user_id VARCHAR(50) UNIQUE NOT NULL,
medical_record_number VARCHAR(50) UNIQUE NOT NULL,
id_last_six VARCHAR(6) NOT NULL,
name VARCHAR(100) NOT NULL,
gender VARCHAR(10) NOT NULL,
dominant_hand VARCHAR(10) NOT NULL,
diagnosis TEXT,
dob DATE,
height_cm INTEGER,
weight_kg DECIMAL(5,2),
contact VARCHAR(20),
inpatient_number VARCHAR(50),
bed_number VARCHAR(20),
education_level VARCHAR(50),
education_years INTEGER,
remarks TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
### 字段说明
| 字段名 | 类型 | 约束 | 说明 |
| --------------------- | ------------- | --------------- | ---------------------------------------- |
| `id` | SERIAL | PRIMARY KEY | 患者唯一标识,自增主键。 |
| `user_id` | VARCHAR(50) | UNIQUE, NOT NULL| 系统生成的用户ID,用于内部标识。 |
| `medical_record_number` | VARCHAR(50) | UNIQUE, NOT NULL| 就诊号,用作登录用户名,必须唯一。 |
| `id_last_six` | VARCHAR(6) | NOT NULL | 身份证后六位,用作登录密码。 |
| `name` | VARCHAR(100) | NOT NULL | 患者姓名。 |
| `gender` | VARCHAR(10) | NOT NULL | 性别(男/女)。 |
| `dominant_hand` | VARCHAR(10) | NOT NULL | 利手(左/右)。 |
| `diagnosis` | TEXT | | 诊断信息。 |
| `dob` | DATE | | 出生日期(格式:YYYY-MM-DD)。 |
| `height_cm` | INTEGER | | 身高(厘米)。 |
| `weight_kg` | DECIMAL(5,2) | | 体重(公斤)。 |
| `contact` | VARCHAR(20) | | 联系方式。 |
| `inpatient_number` | VARCHAR(50) | | 住院号(可选)。 |
| `bed_number` | VARCHAR(20) | | 床号(可选)。 |
| `education_level` | VARCHAR(50) | | 教育程度(可选)。 |
| `education_years` | INTEGER | | 教育年数(可选)。 |
| `remarks` | TEXT | | 备注信息(可选)。 |
| `created_at` | TIMESTAMPTZ | DEFAULT NOW() | 记录创建时间。 |
| `updated_at` | TIMESTAMPTZ | DEFAULT NOW() | 记录最后更新时间。 |
### 示例数据
```sql
INSERT INTO patient_info (
user_id, medical_record_number, id_last_six, name, gender, dominant_hand,
diagnosis, dob, height_cm, weight_kg, contact, inpatient_number,
bed_number, education_level, education_years, remarks
) VALUES (
'user-abc123', 'J0012345', '123456', '张三', '男', '右',
'无', '1960-01-15', 175, 70.5, '13800138000', 'Z67890',
'503', '本科', 16, '测试患者'
);
```
## `logs_metadata`
用于记录所有历史日志表的元信息。管理员通过查询此表来获取历史日志列表。**此表在管理员登录时由系统自动更新。**
### 表结构 (SQL DDL)
```sql
CREATE TABLE logs_metadata (
id SERIAL PRIMARY KEY,
table_name VARCHAR(100) UNIQUE NOT NULL,
description TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
### 字段说明
| 字段名 | 类型 | 约束 | 说明 |
| ------------ | ----------- | --------------- | ---------------------------------------- |
| `id` | SERIAL | PRIMARY KEY | 元数据记录的唯一标识。 |
| `table_name` | VARCHAR(100)| UNIQUE, NOT NULL| 实际存储日志数据的表名。 |
| `description`| TEXT | | 对该日志的描述。 |
| `created_at` | TIMESTAMPTZ | DEFAULT NOW() | 记录创建的时间,默认为当前时间。 |
| `updated_at` | TIMESTAMPTZ | DEFAULT NOW() | 记录最后更新时间。 |
### 示例数据
```sql
INSERT INTO logs_metadata (table_name, description, created_at) VALUES
('log_20240315_1', '2024年3月15日第一次交互日志', '2024-03-15T14:30:00Z'),
('log_20240315_2', '2024年3月15日第二次交互日志', '2024-03-15T16:30:00Z');
```
## 动态测试日志表 (`log_...` 表)
这种表由系统在管理员登录时动态创建,用于存储一个特定测试批次的所有用户测试数据。表名格式为 `log_YYYYMMDD_N` (例如 `log_20240401_1`)。
### 表结构 (SQL DDL)
```sql
CREATE TABLE log_YYYYMMDD_N (
log_id SERIAL PRIMARY KEY,
user_id VARCHAR(255) UNIQUE NOT NULL,
medical_record_number VARCHAR(100) UNIQUE NOT NULL,
name VARCHAR(100),
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(50) DEFAULT 'initialized',
gait_analysis JSONB,
facial_expression INTEGER,
eye_tracking INTEGER,
handwriting INTEGER,
speech_analysis INTEGER,
semantic_analysis INTEGER,
raw_data_path VARCHAR(255)
);
```
### 字段说明
| 字段名 | 类型 | 说明 |
| --------------------- | ------------- | ------------------------------------------------------------ |
| `log_id` | SERIAL | 本次测试日志的唯一ID,主键。 |
| `user_id` | VARCHAR(255) | 患者的用户ID,关联 `patient_info` 表。 |
| `medical_record_number`| VARCHAR(100) | 患者就诊号。 |
| `name` | VARCHAR(100) | 患者姓名。 |
| `created_at` | TIMESTAMPTZ | 记录创建时间。 |
| `status` | VARCHAR(50) | 测试日志的状态。默认为 `initialized` (已初始化)。流程: `initialized` -> `processing` (数据处理中) -> `pending_review` (待专家审核) -> `completed` (已完成确认)。 |
| `gait_analysis` | JSONB | 存储步态分析结果的JSON对象。 |
| `facial_expression` | INTEGER | 存储面部表情的UPDRS评级(0-4),可为空。 |
| `eye_tracking` | INTEGER | 存储眼动功能的UPDRS评级(0-4),可为空。 |
| `handwriting` | INTEGER | 存储手写功能的UPDRS评级(0-4),可为空。 |
| `speech_analysis` | INTEGER | 存储言语功能的UPDRS评级(0-4),可为空。 |
| `semantic_analysis` | INTEGER | 存储认知与语义连贯性的评级(0-4),可为空。 |
| `raw_data_path` | VARCHAR(255) | 指向原始时序数据文件(如CSV)的路径。 |
### 示例数据
```sql
-- 此表示例数据为概念性展示,实际数据结构嵌套在JSONB字段中
INSERT INTO log_20240401_1 (user_id, medical_record_number, name, status, gait_analysis, facial_expression) VALUES
('user-abc123', 'J0012345', '张三', 'completed', '{
"procedural_events": [{"event": "stand_up", "frame": 85}],
"walk_segments": [{"segment_id": 1, "gait_speed": 1.2}]
}', 2);
```
## `questions`
用于存储视频问卷的所有问题。
### 表结构 (SQL DDL)
```sql
CREATE TABLE questions (
id SERIAL PRIMARY KEY,
type VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
required BOOLEAN DEFAULT TRUE,
max_length INTEGER,
-- 可以增加一个 category 字段,用于关联特定的视频或场景
category VARCHAR(100)
);
```
### 字段说明
| 字段名 | 类型 | 说明 |
| ---------- | ----------- | -------------------------------------------------- |
| `id` | SERIAL | 问题的唯一ID。 |
| `type` | VARCHAR(50) | 问题类型,例如 `text`。 |
| `content` | TEXT | 问题的主要内容。 |
| `required` | BOOLEAN | 该问题是否为必答题,默认为 `TRUE`。 |
| `max_length`| INTEGER | 答案的最大长度限制。 |
| `category` | VARCHAR(100)| 问题分类,可用于从特定类别的题库中抽题。 |
### 示例数据
```sql
INSERT INTO questions (type, content, required, max_length, category) VALUES
('text', '请描述视频中展示的主要问题是什么?', TRUE, 500, 'general'),
('text', '您认为应该如何解决这个问题?', TRUE, 1000, 'general'),
('text', '您对这个解决方案有什么建议?', FALSE, 800, 'general'),
('text', '视频中的场景让您联想到了什么?', TRUE, 500, 'emotion'),
('text', '您是否在现实生活中遇到过类似的情况?', FALSE, 1000, 'experience'),
('text', '如果您是视频中的主角,您会怎么做?', TRUE, 1000, 'decision'),
('text', '这个事件对您的触动是什么?', TRUE, 800, 'emotion'),
('text', '请用三个词来形容您的观看感受。', TRUE, 100, 'emotion');
```
## 用户类型说明
### 管理员用户 (user_info表)
- **注册方式**: 管理后台创建
- **登录方式**: 用户名 + 密码
- **权限**: 管理员权限,可查看所有测试记录
- **特点**: 使用bcrypt加密密码,支持邮箱验证
### 患者用户 (patient_info表)
- **注册方式**: 扫码自助注册
- **登录方式**: 就诊号 + 身份证后六位
- **权限**: 普通用户权限,可进行测试
- **特点**: 使用就诊号作为用户名,身份证后六位作为密码

+ 247
- 0
注册路由说明.md View File

@ -0,0 +1,247 @@
# 患者注册路由说明
## 概述
根据软件框架V2文档的要求,我们为第一个页面(用户注册页面-扫码)创建了独立的路由。这个路由专门处理患者的自助注册功能,适用于现场排队等候的场景。
**重要说明**:系统中只有两种用户类型:
- **患者用户**:通过扫码注册,使用就诊号+身份证后六位登录
- **管理员用户**:通过管理后台创建,用于系统管理
## 路由信息
- **路由**: `/api/v3/register`
- **方法**: POST
- **文件位置**: `app/routers/register.py`
## 功能特点
### 1. 独立的路由系统
- 患者注册功能完全独立于管理员注册
- 使用独立的数据库表 `patient_info`
- 独立的JWT令牌生成和验证
### 2. 完整的患者信息字段
根据软件框架V2文档,支持以下字段:
**必需字段**:
- `medical_record_number`: 就诊号(将作为登录用户名)
- `id_last_six`: 身份证后六位(将作为登录密码)
- `name`: 姓名
- `gender`: 性别
- `dominant_hand`: 利手
- `diagnosis`: 诊断
- `dob`: 出生年月(格式: YYYY-MM-DD)
- `height_cm`: 身高(cm)
- `weight_kg`: 体重(kg)
- `contact`: 联系方式
**可选字段**:
- `inpatient_number`: 住院号
- `bed_number`: 床号
- `education_level`: 教育程度
- `education_years`: 教育年数
- `remarks`: 备注
### 3. 数据验证
- 必需字段验证
- 数据类型验证(数字、日期格式)
- 重复注册检查(就诊号唯一性)
### 4. 自动登录
- 注册成功后自动生成JWT令牌
- 返回完整的用户信息
- 无需额外登录步骤
## 数据库设计
### patient_info 表结构
```sql
CREATE TABLE patient_info (
id SERIAL PRIMARY KEY,
user_id VARCHAR(50) UNIQUE NOT NULL,
medical_record_number VARCHAR(50) UNIQUE NOT NULL,
id_last_six VARCHAR(6) NOT NULL,
name VARCHAR(100) NOT NULL,
gender VARCHAR(10) NOT NULL,
dominant_hand VARCHAR(10) NOT NULL,
diagnosis TEXT,
dob DATE,
height_cm INTEGER,
weight_kg DECIMAL(5,2),
contact VARCHAR(20),
inpatient_number VARCHAR(50),
bed_number VARCHAR(20),
education_level VARCHAR(50),
education_years INTEGER,
remarks TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
### user_info 表结构(简化后)
```sql
CREATE TABLE user_info (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
hashed_password VARCHAR(255) NOT NULL,
department VARCHAR(100),
position VARCHAR(100),
is_admin BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
## 用户类型说明
### 患者用户
- **注册方式**: 扫码自助注册
- **登录方式**: 就诊号 + 身份证后六位
- **数据存储**: `patient_info`
- **权限**: 普通用户权限,可进行测试
### 管理员用户
- **注册方式**: 管理后台创建
- **登录方式**: 用户名 + 密码
- **数据存储**: `user_info` 表(简化后只存储管理员)
- **权限**: 管理员权限,可查看所有测试记录
## 登录支持
患者用户可以通过以下方式登录:
- **用户名**: 就诊号
- **密码**: 身份证后六位
登录接口 `/api/v3/login` 已更新,支持患者用户登录。
## 响应格式
### 成功响应
```json
{
"status": "success",
"code": 200,
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"is_admin": false,
"user_info": {
"user_id": "user-abc-123",
"medical_record_number": "J0012345",
"name": "张三",
"gender": "男",
"dominant_hand": "右",
"diagnosis": "无",
"dob": "1960-01-15",
"height_cm": 175,
"weight_kg": 70.5,
"contact": "13800138000",
"inpatient_number": "Z67890",
"bed_number": "503",
"education_level": "本科",
"education_years": 16,
"remarks": ""
}
},
"message": "注册成功并自动登录"
}
```
### 错误响应示例
**重复注册**:
```json
{
"status": "error",
"code": 400,
"message": "Username Already Exists",
"error_details": {
"type": "duplicate_username",
"description": "该就诊号已被注册"
}
}
```
**参数验证失败**:
```json
{
"status": "error",
"code": 400,
"message": "Invalid Parameters",
"error_details": {
"type": "validation_error",
"description": "参数验证失败",
"fields": {
"dob": "出生日期格式必须是 YYYY-MM-DD",
"height_cm": "身高必须是数字"
}
}
}
```
## 测试
使用提供的测试脚本 `test_register.py` 可以验证注册功能:
```bash
python test_register.py
```
测试包括:
1. 患者注册功能
2. 患者登录功能
3. 重复注册检查
## 集成说明
### 1. 路由注册
`app/main.py` 中已添加:
```python
from app.routers import register
app.include_router(register.router, prefix="/api/v3")
```
### 2. 数据库初始化
在应用启动时会自动初始化患者数据库表:
```python
await register.init_register_database()
```
### 3. 登录支持
`app/routers/auth.py` 中的登录接口已更新,支持患者用户登录。
## 数据库架构优势
### 1. 表结构分离
- `user_info` 表:专门存储管理员用户,结构简化
- `patient_info` 表:专门存储患者用户,包含完整的医疗信息
### 2. 安全性提升
- 管理员和患者数据完全分离
- 不同的认证方式(bcrypt vs 身份证后六位)
- 独立的权限管理
### 3. 维护性增强
- 表结构清晰,职责明确
- 便于后续功能扩展
- 数据查询和统计更方便
## 注意事项
1. **安全性**: 身份证后六位作为密码,在生产环境中应考虑更安全的认证方式
2. **数据验证**: 前端应进行适当的数据验证,后端提供二次验证
3. **错误处理**: 所有错误都有详细的错误信息,便于前端处理
4. **令牌管理**: JWT令牌有效期为7天,可根据需要调整
5. **用户类型**: 系统中只有患者和管理员两种用户类型,概念要清晰
6. **数据库**: 确保两个表都正确创建和初始化
## 后续开发
1. 可以考虑添加患者信息的更新接口
2. 可以添加患者信息的查询接口(管理员权限)
3. 可以添加患者数据的导出功能
4. 可以添加更复杂的密码策略
5. 可以添加患者和管理员之间的关联查询

+ 1207
- 0
软件框架V2.md
File diff suppressed because it is too large
View File


Loading…
Cancel
Save