# pmad **Repository Path**: daxiang2008/pmad ## Basic Information - **Project Name**: pmad - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-08 - **Last Updated**: 2026-05-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 病理辅助诊断系统(无患者隐私版)开发文档 **版本**:V1.0 **技术栈**: **适用规模**:院内 30 人内网使用 **核心约束**:完整病理诊断业务系统,**不存储患者姓名、性别、年龄、身份证等任何隐私信息**,仅用【患者编号】作为唯一标识;完整保留病例管理、影像 AI 诊断、医生诊断、审核流程、操作日志、全程追溯、诊断建议全功能 ## 目录 1. 项目概述 2. 系统角色与权限 3. 整体业务操作逻辑 4. 数据库设计(含建表 SQL) 5. 项目目录结构 6. 后端接口设计(详细) 7. 前端页面规划 8. 文件存储规范 9. 日志追溯规范 10. 审核业务流程规范 11. 开发规范 12. 部署环境与步骤 13. 常见问题与解决方案 ## 1. 项目概述 ### 1.1 项目背景 面向科室医生,搭建内网部署的病理影像 AI 辅助诊断 Web 系统,替代简易图片识别工具,实现 “病例创建 - 影像上传 - AI 辅助 - 医生诊断 - 审核归档 - 全程追溯” 的完整业务闭环,适配 30 人以内医生团队日常使用,严格遵循医疗数据隐私要求,仅保留患者编号,不涉及任何个人隐私信息。 ### 1.2 核心功能 | 功能模块 | 核心描述 | | :---------- | :----------------------------------------------------------------- | | 账号管理 | 医生登录、角色分配、账号启用 / 禁用、密码重置(管理员操作) | | 病例管理 | 仅通过患者编号创建病例、病例状态管理、病例查询与归档 | | 影像管理 | 病理图片(jpg/png/tif)单 / 多张上传、在线预览、AI 标注图展示 | | AI 辅助诊断 | 影像 AI 推理、病灶标注、诊断提示、风险等级、置信度生成与存储 | | 医生诊断 | 镜下形态描述、初步诊断、最终诊断、备注、随访 / 复检建议录入与修改 | | 审核流程 | 病例提交审核、审核医师查看、填写审核意见、审核通过 / 驳回 | | 操作追溯 | 所有操作行为(登录、创建、上传、诊断、审核等)全程日志记录,可追溯 | | 数据查询 | 按患者编号、操作时间、医生姓名多维度查询病例、影像、诊断、审核记录 | ### 1.3 技术架构 ``` 前端层:Bootstrap5 + jQuery → 页面渲染、交互、文件上传 ↓↑ 后端层:Flask → 接口开发、权限控制、业务逻辑处理 ├─ Flask-Login → 登录会话管理 ├─ Flask-SQLAlchemy → MySQL ORM操作 └─ 自定义AI调用模块 → 病理模型推理 ↓↑ 数据层:MySQL 8.0 → 存储业务数据、日志、权限信息 └─ 服务器本地存储 → 病理图片、AI标注图(仅存路径到数据库) 部署层:Nginx → 反向代理、静态资源托管、文件上传限制 ``` ### 1.4 开发目标 1. 功能完整:覆盖病理诊断辅助全流程,满足医生日常工作需求; 2. 隐私合规:全程不存储患者任何隐私信息,仅用编号关联所有数据; 3. 操作流畅:适配 30 人内网并发,无卡顿,AI 推理不阻塞页面; 4. 可追溯性:所有操作、诊断、审核记录永久留存,支持全程追溯; 5. 易维护:代码规范、结构清晰,方便后期扩展与问题排查。 --- ## 2. 系统角色与权限 ### 2.1 角色划分(3 类,适配 30 人团队) | 角色 | 数量建议 | 核心权限 | 操作范围 | | :--------- | :------- | :--------------------------------------------------------------------------------------------------- | :------------------------------------------- | | 普通医生 | 25-28 人 | 登录系统、创建病例、上传影像、发起 AI 诊断、填写诊断内容、提交审核、查看个人创建的病例及操作记录 | 仅自己创建的病例、自己的操作日志 | | 审核医师 | 1-2 人 | 包含普通医生全部权限 + 查看所有待审核病例、填写审核意见、审核通过 / 驳回病例、查看所有病例的审核记录 | 所有待审核 / 已审核病例,无账号管理权限 | | 系统管理员 | 1 人 | 医生账号新增 / 禁用 / 改密、查看全系统所有病例、查看全局操作日志、数据备份与归档、系统参数配置 | 全系统数据、账号、日志,无诊断、审核操作权限 | ### 2.2 权限控制规则 1. 权限基于角色分配,无跨角色越权操作; 2. 普通医生仅能查看、编辑自己创建的病例,无法查看其他医生的病例; 3. 审核医师仅能审核病例、填写审核意见,无法修改医生的诊断内容; 4. 管理员仅负责账号管理、数据维护,无法参与诊断、审核业务; 5. 所有权限操作均需记录日志,便于追溯。 --- ## 3. 整体业务操作逻辑(完整闭环) ### 3.1 核心业务流程(按操作顺序) ``` 登录系统 → 创建患者编号病例 → 上传病理影像 → 发起AI辅助诊断 → 医生编辑诊断内容 → 提交审核 → 审核医师处理审核 → 病例归档 → 历史查询/追溯 ``` ### 3.2 细分流程详解 #### 3.2.1 登录流程 1. 医生访问系统登录页,输入账号、密码; 2. 后端校验账号密码(密码加密存储,不明文传输); 3. 校验通过后,记录登录日志(登录人、登录时间、登录 IP); 4. 根据角色跳转对应工作台(普通医生→个人病例列表;审核医师→待审核病例列表;管理员→账号管理页); 5. 会话保持,关闭浏览器后重新登录,超时自动退出。 #### 3.2.2 病例创建流程 1. 普通医生 / 审核医师在工作台点击 “创建病例”; 2. 仅录入【患者唯一编号】(需与院内现有系统编号统一,确保唯一),无需填写任何隐私信息; 3. 系统自动生成病例信息:患者编号、创建医生 ID、创建时间、病例状态(默认 “草稿”); 4. 写入操作日志:“XXX 医生(账号 XXX)创建患者编号 XXX 病例”; 5. 跳转至病例详情页,进行后续影像上传、诊断操作。 #### 3.2.3 病理影像上传流程 1. 在病例详情页,点击 “上传影像”,选择本地病理图片(支持 jpg、png、tif 格式,单文件不超过 50MB); 2. 前端校验文件格式、大小,不符合则提示错误; 3. 后端接收文件,按 “患者编号 / 上传日期 / 文件名” 的目录结构存储到服务器本地; 4. 数据库仅记录:患者编号、上传医生 ID、原图路径、上传时间,不存储图片二进制数据; 5. 写入操作日志:“XXX 医生上传患者编号 XXX 的病理影像(文件名:XXX)”; 6. 上传完成后,前端展示原图预览,支持放大、缩小查看。 #### 3.2.4 AI 辅助诊断流程 1. 在病例详情页,选中已上传的影像,点击 “AI 诊断”; 2. 后端异步调用病理 AI 模型(避免阻塞页面),进行图像预处理、病灶识别; 3. AI 模型输出结果:病灶标注图、诊断提示(如 “疑似鳞癌、疑似炎症增生”)、风险等级(低 / 中 / 高)、置信度(百分比); 4. 后端将 AI 结果存入数据库,绑定患者编号、对应影像 ID、操作医生 ID; 5. 生成 AI 标注图,存储到服务器对应目录,数据库记录标注图路径; 6. 写入操作日志:“XXX 医生对患者编号 XXX 的影像(ID:XXX)发起 AI 辅助诊断”; 7. 前端实时刷新,展示 AI 诊断结果、标注图,供医生参考。 #### 3.2.5 医生诊断编辑流程 1. 医生结合 AI 诊断结果、影像实际情况,在病例详情页填写诊断内容: - 镜下形态描述:记录镜下细胞、组织形态特征; - 初步诊断:基于影像和 AI 提示的初步判断; - 最终诊断:医生最终确认的病理诊断结论; - 备注:记录阅片疑点、特殊情况; - 随访 / 复检建议:给出患者后续随访、复检的具体建议; 2. 支持实时保存、多次修改,每次修改均记录操作日志; 3. 诊断内容填写完成后,医生可点击 “提交审核”,将病例状态改为 “待审核”; 4. 写入操作日志:“XXX 医生提交患者编号 XXX 病例审核”。 #### 3.2.6 病例审核流程 1. 审核医师登录系统,进入 “待审核病例” 列表,查看所有提交审核的病例; 2. 点击病例,查看完整信息:患者编号、病理影像、AI 诊断结果、医生诊断内容; 3. 审核医师结合自身经验,填写审核意见(如 “诊断结论合理,同意通过”“需补充镜下细节描述,驳回修改”); 4. 选择审核结果:“通过” 或 “驳回”; - 审核通过:病例状态改为 “已通过”,可进行归档操作; - 审核驳回:病例状态改为 “已驳回”,返回给创建医生,提示修改后重新提交; 5. 写入审核日志(单独存储):审核人、审核时间、审核结果、审核意见; 6. 写入操作日志:“XXX 审核医师(账号 XXX)审核患者编号 XXX 病例,结果:XXX”; 7. 系统自动通知创建医生审核结果(前端消息提示)。 #### 3.2.7 病例归档流程 1. 病例审核通过后,创建医生或审核医师可点击 “归档”; 2. 病例状态改为 “已归档”,归档后不可修改诊断内容、影像、AI 结果; 3. 写入操作日志:“XXX 医生将患者编号 XXX 病例归档”; 4. 归档病例可通过 “历史病例查询” 功能检索、查看,不可编辑。 #### 3.2.8 全程追溯流程 1. 任何病例详情页,均有 “操作日志” 标签页,展示该病例的所有操作记录; 2. 日志包含:操作人、操作时间、操作内容、操作 IP; 3. 支持按操作时间筛选,可清晰追溯 “谁、在何时、对该病例做了什么操作”; 4. 审核记录单独展示,包含审核人、审核时间、审核结果、审核意见; 5. 所有日志、审核记录永久留存,不可删除、修改。 --- ## 4. 数据库设计(含建表 SQL) ### 4.1 数据库基础配置 - 数据库名称:`pathology_diagnosis` - 字符集:`utf8mb4` - 排序规则:`utf8mb4_general_ci` - 存储引擎:`InnoDB`(支持外键、事务,保证数据一致性) - 核心规则:所有表均包含时间戳(创建时间、更新时间),无物理删除,仅通过状态字段控制显示 / 隐藏;患者全程仅用`patient_code`关联,无任何隐私字段。 ### 4.2 表结构设计(6 张核心表,完整覆盖业务) #### 4.2.1 医生用户表(sys_user) ``` CREATE TABLE sys_user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID', username VARCHAR(50) NOT NULL UNIQUE COMMENT '登录账号(唯一)', password VARCHAR(255) NOT NULL COMMENT '加密密码(bcrypt加密)', real_name VARCHAR(50) NOT NULL COMMENT '医生真实姓名', role ENUM('doctor','auditor','admin') DEFAULT 'doctor' COMMENT '角色:普通医生/审核医师/管理员', is_active TINYINT DEFAULT 1 COMMENT '是否启用:1=启用,0=禁用', created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='医生用户表'; ``` #### 4.2.2 病例主表(case_main) ``` CREATE TABLE case_main ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID', patient_code VARCHAR(50) NOT NULL UNIQUE COMMENT '患者唯一编号(核心,无隐私)', creator_user_id INT NOT NULL COMMENT '创建医生ID(关联sys_user.id)', case_status ENUM('draft','pending','approved','rejected','archived') DEFAULT 'draft' COMMENT '病例状态:草稿/待审核/已通过/已驳回/已归档', created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', FOREIGN KEY (creator_user_id) REFERENCES sys_user(id) ON DELETE RESTRICT COMMENT '外键约束,禁止删除关联医生' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='病例主表(仅患者编号,无隐私)'; ``` #### 4.2.3 病理影像表(case_image) ``` CREATE TABLE case_image ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID', patient_code VARCHAR(50) NOT NULL COMMENT '患者编号(关联case_main.patient_code)', user_id INT NOT NULL COMMENT '上传医生ID(关联sys_user.id)', original_img_path VARCHAR(255) NOT NULL COMMENT '原图存储路径(服务器本地路径)', ai_mark_img_path VARCHAR(255) COMMENT 'AI标注图存储路径(可为空,未做AI诊断时为空)', upload_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间', FOREIGN KEY (patient_code) REFERENCES case_main(patient_code) ON DELETE CASCADE COMMENT '外键约束,病例删除时同步删除影像', FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE RESTRICT COMMENT '外键约束,禁止删除关联医生' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='病理影像表'; ``` #### 4.2.4 AI 诊断结果表(ai_results) ``` CREATE TABLE ai_results ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID', image_id INT NOT NULL COMMENT '影像ID(关联case_image.id)', patient_code VARCHAR(50) NOT NULL COMMENT '患者编号(关联case_main.patient_code)', ai_tip TEXT NOT NULL COMMENT 'AI辅助诊断提示(如:疑似炎症增生,建议进一步复核)', ai_risk_level ENUM('low','medium','high') COMMENT 'AI风险等级:低/中/高', ai_confidence FLOAT NOT NULL COMMENT 'AI诊断置信度(0-100,百分比)', ai_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'AI诊断时间', FOREIGN KEY (image_id) REFERENCES case_image(id) ON DELETE CASCADE COMMENT '外键约束,影像删除时同步删除AI结果', FOREIGN KEY (patient_code) REFERENCES case_main(patient_code) ON DELETE CASCADE COMMENT '外键约束,病例删除时同步删除AI结果' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI诊断结果表'; ``` #### 4.2.5 医生诊断结论表(case_diagnosis) ``` CREATE TABLE case_diagnosis ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID', patient_code VARCHAR(50) NOT NULL COMMENT '患者编号(关联case_main.patient_code)', user_id INT NOT NULL COMMENT '诊断医生ID(关联sys_user.id)', morphology_desc TEXT COMMENT '镜下形态描述', pre_diagnosis TEXT COMMENT '初步诊断结论', final_diagnosis TEXT NOT NULL COMMENT '最终诊断结论', remark TEXT COMMENT '阅片备注、疑点记录', follow_suggestion TEXT COMMENT '随访/复检建议', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', FOREIGN KEY (patient_code) REFERENCES case_main(patient_code) ON DELETE CASCADE COMMENT '外键约束,病例删除时同步删除诊断记录', FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE RESTRICT COMMENT '外键约束,禁止删除关联医生' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='医生诊断结论表'; ``` #### 4.2.6 审核记录表(audit_logs) ``` CREATE TABLE audit_logs ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID', patient_code VARCHAR(50) NOT NULL COMMENT '患者编号(关联case_main.patient_code)', auditor_id INT NOT NULL COMMENT '审核医师ID(关联sys_user.id)', audit_result ENUM('approved','rejected') NOT NULL COMMENT '审核结果:通过/驳回', audit_opinion TEXT COMMENT '审核意见', audit_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '审核时间', FOREIGN KEY (patient_code) REFERENCES case_main(patient_code) ON DELETE CASCADE COMMENT '外键约束,病例删除时同步删除审核记录', FOREIGN KEY (auditor_id) REFERENCES sys_user(id) ON DELETE RESTRICT COMMENT '外键约束,禁止删除关联审核医师' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='审核记录表'; ``` #### 4.2.7 操作日志表(operation_logs)(追溯核心) ``` CREATE TABLE operation_logs ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID', user_id INT NOT NULL COMMENT '操作人ID(关联sys_user.id)', patient_code VARCHAR(50) COMMENT '患者编号(可为空,如登录操作无患者编号)', operation VARCHAR(255) NOT NULL COMMENT '操作内容(如:创建病例、上传影像、提交审核)', operation_ip VARCHAR(50) COMMENT '操作IP地址', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间', FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE RESTRICT COMMENT '外键约束,禁止删除关联操作人' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表(全程追溯)'; ``` ### 4.3 索引设计(优化查询性能) ``` -- 患者编号索引(高频查询) CREATE INDEX idx_case_main_patient_code ON case_main(patient_code); CREATE INDEX idx_case_image_patient_code ON case_image(patient_code); CREATE INDEX idx_ai_results_patient_code ON ai_results(patient_code); CREATE INDEX idx_case_diagnosis_patient_code ON case_diagnosis(patient_code); CREATE INDEX idx_audit_logs_patient_code ON audit_logs(patient_code); -- 医生ID索引(权限筛选、关联查询) CREATE INDEX idx_case_main_creator ON case_main(creator_user_id); CREATE INDEX idx_case_image_user ON case_image(user_id); CREATE INDEX idx_case_diagnosis_user ON case_diagnosis(user_id); CREATE INDEX idx_audit_logs_auditor ON audit_logs(auditor_id); -- 时间索引(时间范围查询) CREATE INDEX idx_case_main_create_time ON case_main(created_at); CREATE INDEX idx_operation_logs_create_time ON operation_logs(create_time); ``` --- ## 5. 项目目录结构(Flask 项目,规范清晰,便于开发维护) ``` pathology_diagnosis/ # 项目根目录 ├── app/ # 核心应用目录 │ ├── __init__.py # Flask应用初始化(配置加载、蓝图注册、数据库初始化) │ ├── config.py # 配置文件(数据库配置、文件存储路径、密钥等) │ ├── models/ # 数据库模型(与数据表一一对应) │ │ ├── __init__.py │ │ ├── user.py # sys_user模型 │ │ ├── case.py # case_main模型 │ │ ├── image.py # case_image模型 │ │ ├── ai_result.py # ai_results模型 │ │ ├── diagnosis.py # case_diagnosis模型 │ │ ├── audit.py # audit_logs模型 │ │ └── log.py # operation_logs模型 │ ├── routes/ # 接口路由(按模块划分) │ │ ├── __init__.py │ │ ├── auth.py # 登录、退出路由 │ │ ├── case.py # 病例创建、查询、归档路由 │ │ ├── image.py # 影像上传、预览路由 │ │ ├── ai.py # AI诊断路由 │ │ ├── diagnosis.py # 诊断编辑、保存路由 │ │ ├── audit.py # 审核相关路由 │ │ ├── log.py # 日志查询路由 │ │ └── admin.py # 管理员账号管理路由 │ ├── services/ # 业务逻辑层(封装复杂业务) │ │ ├── __init__.py │ │ ├── auth_service.py # 登录校验、权限判断 │ │ ├── case_service.py # 病例相关业务 │ │ ├── image_service.py # 影像上传、存储业务 │ │ ├── ai_service.py # AI模型调用、结果处理 │ │ ├── audit_service.py # 审核业务 │ │ └── log_service.py # 操作日志记录 │ ├── static/ # 静态资源目录 │ │ ├── css/ # Bootstrap、自定义CSS │ │ ├── js/ # jQuery、自定义JS(上传、AI结果展示、交互) │ │ ├── images/ # 系统图标、默认图片 │ │ └── uploads/ # 病理图片、AI标注图存储目录(按患者编号分文件夹) │ └── templates/ # 前端模板(HTML) │ ├── base.html # 基础模板(公共头部、尾部、导航) │ ├── login.html # 登录页 │ ├── doctor/ # 普通医生页面 │ │ ├── dashboard.html # 医生工作台 │ │ ├── case_list.html # 个人病例列表 │ │ ├── case_detail.html # 病例详情页(上传、诊断、提交审核) │ │ └── history.html # 历史病例查询 │ ├── auditor/ # 审核医师页面 │ │ ├── dashboard.html # 审核工作台(待审核列表) │ │ ├── audit_detail.html # 审核详情页 │ │ └── audit_history.html # 审核历史记录 │ └── admin/ # 管理员页面 │ ├── user_manage.html # 医生账号管理 │ ├── log_manage.html # 全局日志查看 │ └── data_backup.html # 数据备份 ├── migrations/ # 数据库迁移文件(Flask-Migrate) ├── ai_model/ # AI病理模型目录 │ ├── __init__.py │ ├── model.py # 模型加载、推理逻辑 │ └── weights/ # 模型权重文件 ├── utils/ # 工具类目录 │ ├── __init__.py │ ├── encrypt.py # 密码加密、解密工具 │ ├── file_utils.py # 文件上传、处理工具 │ └── log_utils.py # 日志记录工具 ├── requirements.txt # 项目依赖包 ├── run.py # 项目启动文件 └── README.md # 项目说明文档 ``` --- ## 6. 后端接口设计(Flask 接口,RESTful 风格,适配前端调用) ### 6.1 接口通用规则 1. 接口基础路径:`/api/v1` 2. 请求方式:GET(查询)、POST(提交、创建)、PUT(修改)、DELETE(删除) 3. 响应格式(统一 JSON): ``` { "code": 200, // 状态码:200=成功,400=参数错误,401=未登录,403=权限不足,500=服务器错误 "msg": "操作成功", // 提示信息 "data": {} // 响应数据(可选) } ``` 4. 权限校验:所有接口(除登录接口)均需校验登录状态、角色权限,未登录 / 权限不足返回 401/403。 ### 6.2 具体接口设计 #### 6.2.1 登录相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :----------------------- | :------- | :----------------- | :------------------------------------- | :---------------------------------------------------------------------------------------------------- | | `/api/v1/auth/login` | POST | 医生登录 | {"username": "xxx", "password": "xxx"} | {"code":200,"msg":"登录成功","data":{"user_id":1,"username":"xxx","real_name":"xxx","role":"doctor"}} | | `/api/v1/auth/logout` | GET | 医生退出 | 无(依赖登录会话) | {"code":200,"msg":"退出成功"} | | `/api/v1/auth/reset_pwd` | POST | 重置密码(管理员) | {"user_id":1,"new_pwd":"xxx"} | {"code":200,"msg":"密码重置成功"} | #### 6.2.2 病例相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :--------------------- | :------- | :----------- | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | `/api/v1/case/create` | POST | 创建病例 | {"patient_code": "xxx"} | {"code":200,"msg":"病例创建成功","data":{"patient_code":"xxx","case_status":"draft"}} | | `/api/v1/case/list` | GET | 我的病例列表 | ?page=1&size=10&status=draft | {"code":200,"msg":"查询成功","data":{"total":10,"list":[{"patient_code":"xxx","create_time":"xxx","case_status":"draft"}]}} | | `/api/v1/case/detail` | GET | 病例详情 | ?patient_code=xxx | {"code":200,"msg":"查询成功","data":{"patient_code":"xxx","creator":"xxx","case_status":"draft","images":[],"ai_results":[],"diagnosis":{}}} | | `/api/v1/case/archive` | POST | 病例归档 | {"patient_code": "xxx"} | {"code":200,"msg":"病例归档成功"} | | `/api/v1/case/query` | GET | 病例查询 | ?patient_code=xxx&start_time=xxx&end_time=xxx | {"code":200,"msg":"查询成功","data":{}} | #### 6.2.3 影像相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :---------------------- | :------- | :----------- | :-------------------------------------------- | :----------------------------------------------------------------------------------- | | `/api/v1/image/upload` | POST | 上传病理影像 | FormData(patient_code=xxx,file = 图片文件) | {"code":200,"msg":"上传成功","data":{"img_path":"xxx","upload_time":"xxx"}} | | `/api/v1/image/preview` | GET | 预览影像 | ?img_path=xxx | 图片流(直接渲染) | | `/api/v1/image/list` | GET | 病例影像列表 | ?patient_code=xxx | {"code":200,"msg":"查询成功","data":[{"id":1,"img_path":"xxx","upload_time":"xxx"}]} | #### 6.2.4 AI 诊断相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :------------------- | :------- | :--------------- | :----------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | | `/api/v1/ai/analyze` | POST | 发起 AI 诊断 | {"image_id": 1,"patient_code":"xxx"} | {"code":200,"msg":"AI 诊断中","data":{"task_id":1}} | | `/api/v1/ai/result` | GET | 查询 AI 诊断结果 | ?task_id=1 | {"code":200,"msg":"查询成功","data":{"ai_tip":"xxx","ai_risk_level":"low","ai_confidence":85,"ai_mark_img_path":"xxx"}} | #### 6.2.5 诊断结论相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :------------------------- | :------- | :----------- | :------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------- | | `/api/v1/diagnosis/save` | POST | 保存诊断结论 | {"patient_code":"xxx","morphology_desc":"xxx","pre_diagnosis":"xxx","final_diagnosis":"xxx","remark":"xxx","follow_suggestion":"xxx"} | {"code":200,"msg":"保存成功"} | | `/api/v1/diagnosis/get` | GET | 获取诊断结论 | ?patient_code=xxx | {"code":200,"msg":"查询成功","data":{}} | | `/api/v1/diagnosis/update` | PUT | 修改诊断结论 | 同保存接口 | {"code":200,"msg":"修改成功"} | #### 6.2.6 审核相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :---------------------- | :------- | :------------- | :--------------------------------------------------------------------- | :----------------------------------------------------------------- | | `/api/v1/audit/submit` | POST | 提交审核 | {"patient_code":"xxx"} | {"code":200,"msg":"提交审核成功","data":{"case_status":"pending"}} | | `/api/v1/audit/list` | GET | 待审核病例列表 | ?page=1&size=10 | {"code":200,"msg":"查询成功","data":{"total":5,"list":[]}} | | `/api/v1/audit/do` | POST | 处理审核 | {"patient_code":"xxx","audit_result":"approved","audit_opinion":"xxx"} | {"code":200,"msg":"审核完成","data":{"case_status":"approved"}} | | `/api/v1/audit/history` | GET | 审核历史记录 | ?patient_code=xxx | {"code":200,"msg":"查询成功","data":[]} | #### 6.2.7 日志相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :------------------- | :------- | :----------------- | :-------------------------- | :-------------------------------------- | | `/api/v1/log/case` | GET | 病例操作日志 | ?patient_code=xxx | {"code":200,"msg":"查询成功","data":[]} | | `/api/v1/log/global` | GET | 全局日志(管理员) | ?page=1&size=10&user_id=xxx | {"code":200,"msg":"查询成功","data":[]} | #### 6.2.8 管理员相关接口 | 接口路径 | 请求方式 | 接口描述 | 请求参数 | 响应数据 | | :-------------------------- | :------- | :-------------- | :-------------------------------------------------------------------- | :-------------------------------------- | | `/api/v1/admin/user/add` | POST | 新增医生账号 | {"username":"xxx","password":"xxx","real_name":"xxx","role":"doctor"} | {"code":200,"msg":"新增成功"} | | `/api/v1/admin/user/list` | GET | 医生账号列表 | ?page=1&size=10 | {"code":200,"msg":"查询成功","data":[]} | | `/api/v1/admin/user/active` | PUT | 启用 / 禁用账号 | {"user_id":1,"is_active":0} | {"code":200,"msg":"操作成功"} | --- ## 7. 前端页面规划(简洁实用,适配医生操作习惯) ### 7.1 页面通用设计 1. 公共布局:顶部导航栏(系统名称、个人信息、退出登录)、左侧侧边栏(功能菜单)、右侧内容区; 2. 交互逻辑:表单提交前校验、操作成功 / 失败提示、加载状态提示(AI 诊断、文件上传时); 3. 响应式设计:适配内网常用的电脑屏幕,无需适配移动端。 ### 7.2 具体页面设计 #### 7.2.1 登录页(login.html) - 核心元素:系统 logo、账号输入框、密码输入框、登录按钮、忘记密码(管理员重置); - 校验逻辑:账号 / 密码不能为空、密码加密传输; - 跳转逻辑:登录成功后,按角色跳转对应工作台。 #### 7.2.2 普通医生页面 1. 医生工作台(dashboard.html): - 快捷入口:创建病例、上传影像、待提交审核病例、已归档病例; - 统计信息:个人创建病例数、待审核数、已通过数; - 最近操作记录:最近创建的 3-5 个病例。 2. 个人病例列表(case_list.html): - 筛选条件:病例状态(草稿 / 待审核 / 已通过 / 已驳回 / 已归档)、时间范围; - 列表展示:患者编号、创建时间、病例状态、操作(查看详情、编辑、提交审核、归档); - 分页功能:支持分页查询,每页 10 条。 3. 病例详情页(case_detail.html): - 病例基础信息:患者编号、创建时间、创建医生; - 影像上传区:文件选择、上传按钮、已上传影像预览; - AI 诊断区:AI 诊断按钮、AI 结果展示(标注图、提示、风险等级、置信度); - 诊断编辑区:富文本编辑器(镜下描述、初步诊断、最终诊断、备注、建议)、保存按钮; - 审核区:提交审核按钮、审核状态、审核意见(审核后展示); - 操作日志区:该病例的所有操作记录,按时间倒序排列。 4. 历史病例查询(history.html): - 查询条件:患者编号(精准查询)、时间范围、诊断医生; - 列表展示:患者编号、创建时间、病例状态、操作(查看详情)。 #### 7.2.3 审核医师页面 1. 审核工作台(dashboard.html): - 快捷入口:待审核病例、已审核病例、审核历史; - 统计信息:待审核病例数、今日审核数、本周审核数; - 待审核列表:最近 3-5 个待审核病例,可快速进入审核。 2. 审核详情页(audit_detail.html): - 病例完整信息:患者编号、影像、AI 诊断结果、医生诊断内容; - 审核操作区:审核结果(通过 / 驳回)、审核意见输入框、提交按钮; - 操作日志区:该病例的所有操作记录、历史审核记录。 3. 审核历史记录(audit_history.html): - 筛选条件:审核结果(通过 / 驳回)、时间范围; - 列表展示:患者编号、审核时间、审核结果、审核意见、操作(查看详情)。 #### 7.2.4 管理员页面 1. 医生账号管理(user_manage.html): - 操作功能:新增账号、编辑账号、启用 / 禁用账号、重置密码; - 列表展示:账号、医生姓名、角色、状态、创建时间、操作; - 搜索功能:按账号、医生姓名搜索。 2. 全局日志查看(log_manage.html): - 筛选条件:操作人、操作时间、操作内容、患者编号; - 列表展示:操作人、操作时间、操作内容、操作 IP、患者编号; - 分页功能:支持分页查询。 3. 数据备份(data_backup.html): - 备份功能:手动触发数据库备份、设置自动备份时间; - 备份记录:备份时间、备份大小、操作人、下载 / 删除备份文件。 --- ## 8. 文件存储规范(避免文件混乱、丢失,适配病理影像特点) ### 8.1 存储路径规范 1. 根存储目录:`app/static/uploads/`(在 config.py 中配置,可修改); 2. 子目录划分:按 “患者编号 / 上传日期” 分层存储,示例: ``` app/static/uploads/ ├── P20240001/ # 患者编号 │ ├── 20240508/ # 上传日期(YYYYMMDD) │ │ ├── original/ # 原图 │ │ │ └── img_123.jpg │ │ └── ai_mark/ # AI标注图 │ │ └── img_123_mark.jpg ├── P20240002/ │ └── 20240509/ │ ├── original/ │ └── ai_mark/ ``` 3. 文件名规范:原图命名为 “img*随机字符串。后缀”,AI 标注图命名为 “img*随机字符串\_mark. 后缀”,避免重名。 ### 8.2 文件上传规范 1. 支持格式:jpg、png、tif(病理常用格式),禁止上传其他格式文件; 2. 大小限制:单文件不超过 50MB(可在 config.py 中修改),避免过大文件占用服务器空间; 3. 重复校验:同一患者编号、同一文件名的文件,上传时自动重命名,避免覆盖; 4. 临时文件:上传过程中生成的临时文件,上传完成后自动清理。 ### 8.3 文件维护规范 1. 定期备份:每周对 uploads 目录进行备份,防止文件丢失; 2. 清理策略:对已归档病例的影像文件,保留永久存储;对草稿、已驳回病例的影像文件,保留 6 个月,到期自动清理(可配置); 3. 权限控制:服务器 uploads 目录仅开放读 / 写权限给系统进程,禁止其他用户访问,保障文件安全。 --- ## 9. 日志追溯规范(确保所有操作可追溯,符合医疗系统要求) ### 9.1 日志记录范围(所有操作必须记录) 1. 登录相关:登录成功、登录失败(账号密码错误)、退出登录; 2. 病例相关:创建病例、修改病例状态、归档病例; 3. 影像相关:上传影像、删除影像(如需); 4. AI 诊断相关:发起 AI 诊断、AI 诊断完成、AI 诊断失败; 5. 诊断相关:保存诊断、修改诊断; 6. 审核相关:提交审核、审核通过、审核驳回、修改审核意见; 7. 管理员相关:新增账号、编辑账号、启用 / 禁用账号、重置密码、数据备份。 ### 9.2 日志记录格式(统一规范,便于查询) 1. 操作内容(operation 字段)格式:“XXX(操作人)+ 操作行为 + 操作对象 + 操作结果”,示例: - 登录:“张三(账号:zhangsan)登录系统,登录成功”; - 创建病例:“张三(账号:zhangsan)创建患者编号 P20240001 病例,创建成功”; - 审核:“李四(账号:lisi)审核患者编号 P20240001 病例,审核结果:通过,审核意见:诊断合理”。 2. 日志必存字段:操作人 ID、操作内容、操作时间、操作 IP,患者编号(如有)。 ### 9.3 日志查询与维护 1. 查询功能:支持按操作人、操作时间、操作内容、患者编号多维度查询; 2. 存储期限:所有日志永久留存,不删除; 3. 权限控制:普通医生仅能查看自己的操作日志;审核医师可查看所有审核相关日志;管理员可查看全局所有日志; 4. 日志导出:管理员可导出日志(Excel 格式),用于审计。 --- ## 10. 审核业务流程规范(确保审核流程严谨,符合病理诊断工作流程) ### 10.1 审核前提 1. 病例必须完成:影像上传、AI 诊断、医生诊断内容填写(至少包含最终诊断结论); 2. 病例状态为 “草稿”,才能提交审核; 3. 提交审核后,病例状态变为 “待审核”,不可修改诊断内容、影像、AI 结果。 ### 10.2 审核标准(供审核医师参考) 1. 影像完整性:病理影像清晰、完整,可满足诊断需求; 2. AI 结果参考:结合 AI 诊断提示,判断医生诊断是否合理; 3. 诊断规范性:镜下描述详细、准确,诊断结论明确,符合病理诊断规范; 4. 建议合理性:随访 / 复检建议贴合病例实际情况。 ### 10.3 审核结果处理 1. 审核通过: - 病例状态改为 “已通过”; - 审核医师填写审核意见(如 “诊断结论合理,同意通过”); - 医生可对已通过病例进行归档操作; 2. 审核驳回: - 病例状态改为 “已驳回”; - 审核医师需明确填写驳回原因(如 “镜下描述不详细,需补充细胞形态特征”); - 创建医生收到驳回提示后,修改诊断内容,重新提交审核。 ### 10.4 审核追溯 1. 同一病例可多次提交审核、驳回,每次审核记录均单独存储; 2. 审核记录包含:审核人、审核时间、审核结果、审核意见,可在病例详情页查看; 3. 审核医师可查看自己所有审核记录,管理员可查看全院所有审核记录。 --- ## 11. 开发规范(统一开发标准,便于团队协作、后期维护) ### 11.1 后端开发规范 1. 代码风格:遵循 PEP8 规范,变量命名采用小写 + 下划线,类命名采用大驼峰,函数命名采用小写 + 下划线; 2. 接口开发:RESTful 风格,接口注释清晰(说明接口功能、请求参数、响应数据); 3. 数据库操作:所有数据库操作通过 SQLAlchemy ORM 实现,禁止直接写原生 SQL(复杂查询除外); 4. 异常处理:所有接口、函数需添加异常捕获,返回统一的错误响应,避免系统崩溃; 5. 权限控制:所有接口(除登录)需添加权限校验装饰器,按角色控制访问权限; 6. 日志记录:所有操作需调用 log_service,记录操作日志,不可遗漏。 ### 11.2 前端开发规范 1. 代码风格:HTML 结构清晰,CSS 使用 Bootstrap 类,JS 代码简洁,注释清晰; 2. 交互设计:表单提交前校验,操作后给出明确提示,加载状态显示加载动画; 3. 兼容性:适配 Chrome、Edge 等主流浏览器,确保页面正常显示、交互正常; 4. 代码复用:公共组件(如导航栏、提示框)提取为公共模板,避免重复开发; 5. 安全性:禁止直接暴露服务器路径、数据库信息,文件上传前校验格式、大小。 ### 11.3 版本控制规范 1. 使用 Git 进行版本控制,分支管理: - main:主分支,仅用于部署稳定版本; - develop:开发分支,所有开发工作在该分支进行; - feature/xxx:功能分支,开发单个功能时创建,完成后合并到 develop 分支; - bugfix/xxx:bug 修复分支,修复 bug 时创建,完成后合并到 develop 和 main 分支。 2. 提交规范:提交信息清晰,格式为 “类型:描述”,示例:“feat:新增病例创建功能”“fix:修复 AI 诊断失败 bug”。 --- ## 12. 部署环境与步骤(适配内网 30 人使用,简单易部署) ### 12.1 部署环境要求(内网服务器) - 硬件配置:CPU 4 核、内存 8G+、硬盘 SSD 100G+(系统盘)+ 机械盘 1TB+(存储病理图片); - 操作系统:CentOS 8 / Ubuntu 20.04(推荐 CentOS 8,稳定性高); - 软件环境: - Python 3.9+ - MySQL 8.0 - Nginx 1.20+ - 依赖包:见 requirements.txt ### 12.2 部署步骤 1. 服务器环境准备: - 安装 Python 3.9+、MySQL 8.0、Nginx; - 配置 MySQL,创建数据库`pathology_diagnosis`,设置字符集为 utf8mb4; - 开放服务器内网端口(如 80 端口,用于 Nginx 访问)。 2. 项目部署: - 克隆 Git 仓库到服务器(或上传项目压缩包,解压); - 进入项目根目录,创建虚拟环境:`python -m venv venv`; - 激活虚拟环境:`source venv/bin/activate`(CentOS)/ `venv\Scripts\activate`(Windows); - 安装依赖包:`pip install -r requirements.txt`; - 配置 config.py:修改数据库连接信息、文件存储路径、密钥等; - 数据库迁移:`flask db init` → `flask db migrate -m "初始化数据库"` → `flask db upgrade`; - 初始化管理员账号:运行`python utils/init_admin.py`(提前编写初始化脚本,创建 admin 账号)。 3. Nginx 配置: - 编辑 Nginx 配置文件,配置反向代理,指向 Flask 应用; - 配置静态资源托管,指向项目 static 目录; - 配置文件上传大小限制(client_max_body_size 50M)。 4. 启动项目: - 使用 Gunicorn 作为 WSGI 服务器,启动命令:`gunicorn -w 4 -b 127.0.0.1:5000 run:app`(4 个进程,适配 30 人并发); - 设置 Gunicorn 开机自启,避免服务器重启后项目停止; - 启动 Nginx:`systemctl start nginx`,设置开机自启。 5. 测试验证: - 内网浏览器访问服务器 IP,进入登录页; - 使用管理员账号登录,新增普通医生账号; - 测试病例创建、影像上传、AI 诊断、审核等功能,确认正常运行。 ### 12.3 维护与更新 1. 日常维护:定期备份数据库、uploads 目录;查看服务器日志,排查异常; 2. 项目更新: - 拉取最新代码(或上传更新包); - 激活虚拟环境,更新依赖包; - 数据库迁移(如有表结构变更); - 重启 Gunicorn:`pkill gunicorn` → 重新执行启动命令。 --- ## 13. 常见问题与解决方案 | 常见问题 | 可能原因 | 解决方案 | | :------------- | :--------------------------------------------- | :----------------------------------------------------------- | | 登录失败 | 账号密码错误、账号被禁用、会话超时 | 核对账号密码、联系管理员启用账号、重新登录 | | 影像上传失败 | 文件格式错误、文件过大、服务器存储空间不足 | 检查文件格式(jpg/png/tif)、压缩文件大小、清理服务器空间 | | AI 诊断失败 | 模型权重文件缺失、图片无法读取、服务器内存不足 | 检查 ai_model/weights 目录、确认图片路径正确、增加服务器内存 | | 审核提交失败 | 未填写诊断结论、病例状态不是草稿 | 补充完整诊断结论、将病例状态改为草稿后重新提交 | | 页面加载缓慢 | 服务器内存不足、图片过大、并发过高 | 增加服务器内存、压缩图片、优化 Gunicorn 进程数 | | 日志查询不到 | 操作未触发日志记录、查询条件错误 | 检查代码中日志调用逻辑、调整查询条件 | | 数据库连接失败 | 数据库配置错误、MySQL 服务未启动 | 核对 config.py 中数据库配置、启动 MySQL 服务 | --- ## 附录 ### 附录 1:requirements.txt(项目依赖包) ``` Flask==2.3.3 Flask-SQLAlchemy==3.1.1 Flask-Login==0.6.3 Flask-Migrate==4.0.5 gunicorn==21.2.0 PyMySQL==1.1.0 bcrypt==4.0.1 Pillow==10.1.0 opencv-python==4.8.1.78 numpy==1.26.0 ``` ### 附录 2:初始化管理员账号脚本(utils/init_admin.py) ``` from app import create_app from app.models.user import sys_user from app import db from werkzeug.security import generate_password_hash app = create_app() with app.app_context(): # 检查是否已存在admin账号 admin = sys_user.query.filter_by(username='admin').first() if not admin: # 创建管理员账号,密码:admin123(加密存储) admin = sys_user( username='admin', password=generate_password_hash('admin123'), real_name='系统管理员', role='admin', is_active=1 ) db.session.add(admin) db.session.commit() print("管理员账号创建成功:username=admin,password=admin123(请及时修改密码)") else: print("管理员账号已存在") ```