- Align the backend seeded default surgery template with the report editor's default report content. - Add backend demo defaults for the default template, Kimi provider, and Xunfei speech proxy configuration. - Change system reset into a super-admin demo mode factory reset that clears reports, audit logs, files, custom templates, and non-default users. - Keep only the default admin, manager, doctor, and default surgery template after demo reset. - Replace the old local-only reset all data button with a two-confirmation backend reset flow. - Add tests covering demo default alignment and database-backed demo reset behavior. - Update docs to describe demo mode reset semantics and production credential cautions.
17 KiB
API 契约草案
本文档定义后端化时的接口语义和权限边界。当前项目已实现认证、报告、模板、用户/部门、设置和签名文件接口,其余接口仍用于指导后续后端化。
当前后端骨架已实现:
GET /api/healthPOST /api/auth/loginGET /api/auth/mePOST /api/auth/logoutGET /api/reportsPOST /api/reportsGET /api/reports/:idPATCH /api/reports/:idDELETE /api/reports/:idGET /api/templatesPOST /api/templatesGET /api/templates/:idPATCH /api/templates/:idDELETE /api/templates/:idGET /api/usersPOST /api/usersGET /api/users/:idPATCH /api/users/:idDELETE /api/users/:idGET /api/departmentsPOST /api/departmentsPATCH /api/departments/:idDELETE /api/departments/:idPATCH /api/departments/:id/template-permissionsGET /api/settings/systemPATCH /api/settings/systemPOST /api/settings/system/resetPOST /api/users/:id/signatureDELETE /api/users/:id/signatureGET /api/files/:id/contentGET /api/ai/modelsPOST /api/ai/chatGET /api/speech/iatWebSocketGET /api/library/fieldsPATCH /api/library/fieldsGET /api/filesPOST /api/filesDELETE /api/files/:id
报告媒体关系表、数据库 Session 和第一版审计日志已实现;审计日志查询 API 已提供给超级管理员和管理员使用;第三方调用摘要和后端导出接口仍是后续项。
通用约定
Base URL
/api
认证
建议使用短期 Access Token + HttpOnly Refresh Cookie,或完整 HttpOnly Session Cookie。前端不应保存密码、完整用户列表或第三方服务密钥。
响应格式
成功:
{
"data": {},
"requestId": "req_xxx"
}
失败:
{
"error": {
"code": "FORBIDDEN",
"message": "无权访问该资源"
},
"requestId": "req_xxx"
}
常用状态码
| 状态码 | 含义 |
|---|---|
200 |
请求成功。 |
201 |
创建成功。 |
204 |
删除或无响应体操作成功。 |
400 |
请求参数错误。 |
401 |
未登录或登录态失效。 |
403 |
已登录但无权限。 |
404 |
资源不存在,或当前用户无权感知该资源。 |
409 |
唯一约束或状态冲突。 |
422 |
业务校验失败。 |
核心类型
User
type UserRole = 'super' | 'admin' | 'doctor';
interface UserDTO {
id: string;
username: string;
role: UserRole;
name: string;
departmentId: string;
departmentName?: string;
department?: string;
status: 'active' | 'inactive';
phone?: string;
email?: string;
signatureFileId?: string;
signature?: string;
visibleTemplates?: string[];
manageableTemplates?: string[];
createdAt: string;
updatedAt: string;
}
后端不得返回 password_hash。
Report
interface ReportDTO {
id: string;
title: string;
patientName: string;
hospitalId: string;
departmentId: string;
departmentName: string;
authorId: string;
authorName: string;
status: 'draft' | 'completed';
revision: number;
content: string;
videos?: Array<{
id: string;
name: string;
url: string;
duration: number;
fileId?: string;
}>;
capturedFrames?: Array<{
id: number;
videoIndex: number;
videoName: string;
time: number;
timeFormatted: string;
dataUrl: string;
fileId?: string;
}>;
createdAt: string;
updatedAt: string;
}
已完成报告再次修改时,后端必须递增 revision 并创建历史版本。videos 和 capturedFrames 是前端兼容 DTO 字段,后端持久化到 ReportMedia 并关联 FileResource。
Template
interface TemplateDTO {
id: string;
name: string;
description?: string;
scope: 'department' | 'personal';
departmentId?: string;
ownerUserId?: string;
content: string;
fields: FormFieldDTO[];
canUse: boolean;
canManage: boolean;
createdAt: string;
updatedAt: string;
}
医生个人模板必须只对本人可见和可用。
Auth API
POST /api/auth/login
请求:
{
"username": "0001",
"password": "123456"
}
响应:
{
"data": {
"user": {
"id": "usr_0001",
"username": "0001",
"role": "doctor",
"name": "张医生",
"departmentId": "dept_surgery",
"departmentName": "外科",
"status": "active"
}
}
}
规则:
- 禁用用户返回
403 FORBIDDEN。 - 用户名或密码错误返回
401 UNAUTHORIZED。 - 前端通过 HttpOnly Session Cookie 维持登录态,不保存 access token。
GET /api/auth/me
返回当前登录用户。前端启动后用它恢复登录态,并把后端 doctor 角色映射为当前前端兼容类型 user。
POST /api/auth/logout
清除服务端会话或 refresh cookie。
Reports API
GET /api/reports
查询参数:
q?: string
status?: draft | completed
dateRange?: today | week | month
page?: number
pageSize?: number
权限过滤:
- 超级管理员:返回全部报告。
- 管理员:只返回本部门报告。
- 医生:只返回本人报告。
响应:
{
"data": {
"items": [],
"total": 0,
"page": 1,
"pageSize": 20
}
}
POST /api/reports
创建报告。后端写入 authorId、departmentId、revision = 1。
当前实现接收前端兼容 Report 对象,核心字段进入 Report 表,视频/关键帧引用进入 ReportMedia 表,其他扩展字段进入 metadata。
GET /api/reports/:id
权限:
- 超级管理员可读所有报告。
- 管理员可读本部门报告。
- 医生可读本人报告。
无权限当前返回 403。
PATCH /api/reports/:id
规则:
- 超级管理员可编辑任何报告。
- 管理员可编辑本部门报告。
- 医生可编辑本人报告。
- 如果原报告状态为
completed,每次保存递增revision。 - 每次保存创建历史版本。
POST /api/reports/:id/complete
把报告标记为完成。完成前必须校验患者姓名、住院号等必填字段。
当前实现暂未单独开放该接口,前端通过 PATCH /api/reports/:id 传入 status = completed 完成报告。
DELETE /api/reports/:id
规则:
- 超级管理员可删除全部报告。
- 管理员可删除本部门报告。
- 医生可删除本人报告,包括已完成报告。
建议先做软删除。
当前实现已做软删除,写入 deletedAt 和 deletedBy。
GET /api/reports/:id/history
返回报告历史版本:
{
"data": [
{
"id": "hist_1",
"revision": 1,
"content": "<p>旧内容</p>",
"updatedBy": "张医生",
"updatedAt": "2026-05-01T08:00:00.000Z",
"action": "complete_report"
}
]
}
GET /api/reports/:id/export.json
返回结构化报告 JSON。权限与查看报告一致。当前确定不需要水印、导出原因、审批或专门导出审计;现阶段仍主要由前端 Blob 导出。
Templates API
GET /api/templates
权限过滤:
- 超级管理员:全部模板。
- 管理员:本部门模板和被授权模板。
- 医生:本部门授权模板和自己的个人模板。
当前实现支持查询参数 access=use | manage,分别返回当前用户可使用或可管理的模板。
POST /api/templates
创建模板。
规则:
- 超级管理员可创建部门模板并授权给部门。
- 管理员可创建或修改本部门模板。
- 医生只能创建个人模板,
scope必须为personal,ownerUserId必须是本人。
当前实现由后端根据 Session 用户写入归属部门或归属用户;前端不能伪造 ownerUserId。
PATCH /api/templates/:id
规则:
- 超级管理员可编辑任何模板。
- 管理员可编辑本部门模板。
- 医生只能编辑自己的个人模板。
DELETE /api/templates/:id
规则同编辑模板。删除部门模板时需确认是否已有报告引用;建议软删除。
当前实现会先把引用该模板的报告 templateId 置空,再删除模板。
POST /api/templates/:id/copy
医生复制部门模板为个人模板。
请求:
{
"name": "我的腹腔镜模板"
}
响应返回新的 TemplateDTO,scope = personal。
Users API
GET /api/users
权限:
- 超级管理员:全部用户。
- 管理员:自己和本部门医生。
- 医生:只返回自己。
当前实现返回前端兼容 User 结构,其中后端 doctor 会映射为前端历史角色 user,并带上由部门模板授权计算出来的 visibleTemplates/manageableTemplates。
POST /api/users
规则:
- 只有超级管理员可创建管理员。
- 一个部门只能有一个管理员,冲突返回
409。 - 管理员只能创建本部门医生。
- 创建医生前,该部门必须已有启用管理员。
- 后端使用 Argon2 保存密码哈希,不返回明文密码。
PATCH /api/users/:id
规则:
- 超级管理员可改任何用户。
- 管理员可改本部门医生的基础信息、密码和状态。
- 医生只能改自己的基础资料。
- 只有超级管理员可修改角色、部门和管理员模板授权。
DELETE /api/users/:id
规则:
- 禁止删除当前登录用户。
- 禁止删除默认超级管理员
admin。 - 有报告、模板、审计等业务关联时返回
409,建议改为禁用账号。
Departments API
GET /api/departments
权限:
- 超级管理员:全部部门。
- 管理员和医生:本人所在部门。
POST /api/departments
只有超级管理员可创建部门。
PATCH /api/departments/:id
只有超级管理员可修改部门名称或编码。
DELETE /api/departments/:id
只有超级管理员可删除无业务关联的部门;不能删除当前登录用户所在部门。
PATCH /api/departments/:id/template-permissions
请求:
{
"visibleTemplates": ["tpl_a"],
"manageableTemplates": ["tpl_b"]
}
规则:
- 只有超级管理员可维护部门模板授权。
manageableTemplates会自动包含使用权。- 后端写入
template_department_permissions.canUse/canManage。
Settings API
GET /api/settings/system
返回当前用户可用的系统设置。当前实现会合并全局设置和个人默认模板,并返回前端兼容 SystemSettings 对象。
注意:AI 对话和讯飞语音均已改为后端代理。普通用户读取设置时不返回 AI Key、讯飞 APIKey 或讯飞 APISecret;超级管理员仍可在设置页维护全局共用 Provider Key 和语音配置。
PATCH /api/settings/system
规则:
- 超级管理员可修改全局设置、AI Provider、语音配置。
- 医生可修改个人默认模板。
- 管理员可修改个人默认模板。
- 非超级管理员提交的其他字段会被忽略或拒绝,只保留个人默认模板。
POST /api/settings/system/reset
只有超级管理员可执行演示模式恢复出厂设置。当前实现不只是重置系统设置,而是把当前租户恢复为 demo mode:
- 用户只保留默认
admin、manager、0001三个账号,并重置为默认角色、部门、状态和密码。 - 报告、报告历史、报告媒体、文件资源和审计日志会被清空。
- 模板只保留默认“腹腔镜胆囊切除术报告”,模板 HTML 与图文报告生成的默认报告内容保持一致。
- 系统设置恢复为演示默认值,包含默认模板、抽帧策略、Kimi Provider 和讯飞语音代理配置。
前端必须做二次确认。该接口面向演示/测试环境,不应作为生产数据恢复或备份机制。
Signature Files API
POST /api/users/:id/signature
请求:
{
"dataUrl": "data:image/jpeg;base64,...",
"filename": "signature.jpg"
}
规则:
- 用户本人、本部门管理员、超级管理员可上传或替换签名。
- 当前支持 JPG、PNG、WebP,大小限制 1MB。
- 后端写入
FileResource.kind = SIGNATURE,并把User.signatureFileId指向新文件。
响应:
{
"data": {
"file": {
"id": "file_xxx",
"url": "/api/files/file_xxx/content",
"mimeType": "image/jpeg",
"size": 12345
}
}
}
DELETE /api/users/:id/signature
清除用户签名并删除后端文件资源。权限同上传。
GET /api/files/:id/content
返回文件二进制内容。当前已实现签名文件读取权限:
- 本人可读自己的签名。
- 本部门管理员可读本部门用户签名。
- 超级管理员可读全部签名。
- 报告相关文件预留继承报告权限。
AI API
GET /api/ai/models
后端读取全局共用 AI Provider 配置,请求 OpenAI 兼容 /models 并返回模型 ID 列表。前端“测试连接”使用该接口,不再直接携带 API Key 请求第三方服务。
POST /api/ai/chat
规则:
- 后端托管第三方模型密钥。
- 请求上下文只能包含当前报告内容和当前报告内用户有权访问的图片/关键帧。
- 不允许跨部门检索报告作为上下文。
- 当前实现接收 OpenAI 兼容
messages、温度等参数,后端会用全局 Provider 的modelName覆盖请求中的model,所有用户共用同一套 key。
Speech API
GET /api/speech/iat WebSocket
浏览器通过当前登录 Session Cookie 发起 WebSocket upgrade。后端使用同一套 Session 中间件校验登录态,读取 Settings API 中的 xfSpeechConfig,连接讯飞 IAT WebSocket 并转发音频帧和识别结果。
客户端发送的首帧只需要包含音频 data:
{
"data": {
"status": 0,
"format": "audio/L16;rate=16000",
"encoding": "raw",
"audio": "base64-pcm"
}
}
后端会在首帧补齐:
{
"common": { "app_id": "server-side-app-id" },
"business": { "language": "zh_cn", "domain": "iat", "accent": "mandarin" }
}
规则:
- 未登录的 upgrade 返回
401。 - 未配置 APPID/APIKey/APISecret 时,代理向客户端返回错误消息并关闭连接。
- 前端不得保存或拼接讯飞鉴权 URL。
- 上游讯飞返回的识别消息原样转发给客户端。
Files API
GET /api/files
查询参数:
kind?: TEMPLATE_ASSET | VIDEO | FRAME | REPORT_EXPORT
返回当前租户内可读文件。TEMPLATE_ASSET 当前作为模板图片资源,登录用户可读取。
POST /api/files
通用文件上传接口。当前已用于模板图片资源、视频和关键帧,后续继续承载报告图片和导出文件。
请求:
{
"kind": "TEMPLATE_ASSET",
"filename": "logo.png",
"dataUrl": "data:image/png;base64,...",
"reportId": "optional_report_id"
}
返回:
{
"data": {
"file": {
"id": "file_xxx",
"filename": "logo.png",
"mimeType": "image/png",
"size": 1234,
"url": "/api/files/file_xxx/content",
"createdAt": "2026-05-02T00:00:00.000Z"
}
}
}
DELETE /api/files/:id
删除当前用户可管理的文件。超级管理员可删全部,同 owner 可删自己的文件,管理员可删除模板图片资源。
Library API
GET /api/library/fields
返回字段库:
interface FieldLibraryDTO {
formFields: FormField[];
customTimeFormats: string[];
multiSelectOptions: Record<string, string[]>;
anesthesiaOptions: string[];
}
PATCH /api/library/fields
保存字段库。当前第一版保存为租户全局 SystemSetting.key = fieldLibrary,前端仍会同步本地兼容缓存。
文件权限继承业务对象:
- 报告文件继承报告权限。
- 模板图片资源当前登录用户可读取,删除权限限制为超级管理员、管理员或 owner。
- 签名文件已先行通过
POST /api/users/:id/signature实现。
Audit API
GET /api/audit-logs
查询审计日志。超级管理员可查看当前租户全部日志;管理员可查看本部门或自己作为操作者的日志;医生不可访问。
查询参数:
page=1
pageSize=50
action=report.complete
targetType=Report
actor=admin
返回:
{
"data": {
"items": [
{
"id": "log_xxx",
"actorUsername": "admin",
"actorName": "超级管理员",
"actorRole": "super",
"action": "report.complete",
"targetType": "Report",
"targetId": "report_xxx",
"departmentId": "dept_xxx",
"metadata": { "title": "报告标题" },
"createdAt": "2026-05-02T00:00:00.000Z"
}
],
"total": 1,
"page": 1,
"pageSize": 50
}
}
后续测试落点
后端骨架建立后,应把本文档转为真实测试:
- Auth/HTTP 集成测试。
- RBAC policy 单元测试。
- Reports API 按角色过滤测试。
- Report revision 递增测试。
- Templates API 部门模板和个人模板测试。
- Settings API 保存和默认模板测试。
- Signature Files API 上传和读取权限测试。
- Library API 字段库保存测试。
- Generic Files API 上传、列表和删除测试。
- AI 代理上下文隔离测试。
- Speech WebSocket 未登录拒绝、首帧注入和上游错误转发测试。