# BrownPanda-LIMS **Repository Path**: Gianttrees/brown-panda-lims ## Basic Information - **Project Name**: BrownPanda-LIMS - **Description**: 棕熊猫LIMS实验室信息管理系统 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2026-07-02 - **Last Updated**: 2026-07-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LIMS 实验室信息管理系统 · 系统说明书 > LIMS (Laboratory Information Management System) > 版本:v0.6 · 最后更新:2026-07-01 ![输入图片说明](database/S02_登录成功_主页.png) ![输入图片说明](database/24_%E5%AE%9E%E9%AA%8C%E5%91%98_iPhone_%E7%99%BB%E5%BD%95%E9%A1%B5.png) --- ![输入图片说明](database/28_%E5%AE%9E%E9%AA%8C%E5%91%98_iPhone_%E5%A4%96%E5%8C%85%E5%8D%95%E5%88%97%E8%A1%A8.png) ## 目录 1. [系统简介](#1-系统简介) 2. [角色与权限](#2-角色与权限) 3. [技术栈](#3-技术栈) 4. [目录结构](#4-目录结构) 5. [业务流程](#5-业务流程) 6. [模块功能](#6-模块功能) 7. [接口约定](#7-接口约定) 8. [数据完整性(ALCOA+ & 21 CFR Part 11)](#8-数据完整性alcoa--21-cfr-part-11) 9. [响应式移动端设计](#9-响应式移动端设计) 10. [本地开发](#10-本地开发) 11. [部署到 Ubuntu 服务器](#11-部署到-ubuntu-服务器) 12. [E2E 测试](#12-e2e-测试) 13. [常见问题](#13-常见问题) --- ## 1. 系统简介 LIMS 是面向环境检测实验室的业务管理系统,覆盖**环境样本全生命周期**、**资源/试剂管理**、**CRO 第三方检测业务**与**检测分包与供应商管理(ISO 17025 合规)**四大主线,并严格遵循 **FDA 21 CFR Part 11** 电子签名与审计追踪合规要求。系统同时提供**响应式移动端自适应设计**,完美适配实验员与采样员用手机进行现场操作(接样、录入、外发)。 **核心价值**: - **职责分离** —— 录入、复核、批准三权分立,符合实验室 ISO 17025 要求 - **电子签名(21 CFR Part 11)** —— 复核/批准/驳回等关键操作强制二次密码校验 + 签字原因,签名记录不可篡改 - **审计追溯** —— 全生命周期操作留痕(登记/采样/复核/批准/驳回/偏差调查/电子签名),符合 ALCOA+ Attributable 原则 - **OOS 偏差调查** —— 超标结果自动触发偏差调查流程,未关闭偏差前禁止放行 - **OOT 智能预警** —— 趋势分析图表 + 警戒限/行动限参考线 + 连续递增/超警戒自动预警 - **流程闭环** —— 样本状态机:登记 → 采样 → 收样 → 录入结果 → 复核 → 批准 → 报告 - **动态权限** —— 前端按钮与后端接口双重 RBAC 控制,按角色隐藏/启停接口 - **CRO 合同驱动** —— 客户 → 合同 → 合同测试清单(动态采样点 + 检测项目字典引用)→ 样本登记全链路贯通 - **检测分包合规(ISO 17025)** —— 分包商名录 + 资质有效期预警 + 外发分包单工作流(PENDING_SEND → SENT → RESULT_RECEIVED)+ PDF 报告分包项目星号标识 + 合规备注声明 - **主数据字典** —— 检测大类 + 检测项目字典统一维护,支持 Excel 批量导入(Upsert + 自动建大类) - **标准化报价基础** —— 检测项目字典内置指导价、默认警戒限/行动限,合同引用时自动带出 - **响应式移动端** —— 桌面/手机双端自适应,手机端汉堡抽屉导航 + 卡片列表视图 + 拍照上传附件,满足现场操作需求 **典型用户**: - 实验员:登记样本、录入检测结果、现场接样与外发分包(手机端) - 采样员:现场采样确认、拍照上传分包报告(手机端) - 主管:复核实验员提交的结果 - QA(质量保证):批准放行报告 - 业务员:维护客户与合同,选择检测项目字典 - 系统管理员:用户与权限管理、主数据字典维护 --- ## 2. 角色与权限 ### 2.1 四类基础角色 | 角色 | 代码 | 描述 | |---|---|---| | 管理员 | `ADMIN` | 用户管理、所有数据可见、全部操作 | | 实验员 | `ANALYST` | 登记样本、录入结果、外发分包 | | 主管 | `SUPERVISOR` | 复核/驳回实验员提交的结果 | | 质量保证 | `QA` | 批准放行报告 | ### 2.2 权限矩阵 | 操作 | ADMIN | ANALYST | SUPERVISOR | QA | |---|:-:|:-:|:-:|:-:| | 登记新样本 | ✓ | ✓ | ✓ | ✗ | | 录入检测结果 | ✓ | ✓ | ✓ | ✗ | | 复核通过(需电子签名) | ✓ | ✗ | ✓ | ✗ | | 驳回(需电子签名) | ✓ | ✗ | ✓ | ✓ | | 批准放行(需电子签名) | ✓ | ✗ | ✗ | ✓ | | 发起偏差调查 | ✓ | ✗ | ✓ | ✓ | | 关闭偏差单 | ✓ | ✗ | ✗ | ✓ | | 分包商名录管理 | ✓ | ✓ | ✓ | ✓ | | 外发分包单管理 | ✓ | ✓ | ✓ | ✓ | | 客户/合同/主数据管理 | ✓ | ✓ | ✓ | ✓ | | 用户管理 | ✓ | ✗ | ✗ | ✗ | ### 2.3 默认账号 启动时自动 seed(密码已 bcrypt 哈希): | 用户名 | 密码 | 角色 | |---|---|---| | `admin` | `admin123` | ADMIN | | `analyst01` | `analyst123` | ANALYST | | `supervisor01` | `super123` | SUPERVISOR | | `qa01` | `qa123` | QA | > **生产环境务必修改默认密码**(`backend/.env` + `UserService.ensure_default_admin`)。 --- ## 3. 技术栈 ### 后端 - **Python 3.11+** + **FastAPI**(异步) - **SQLAlchemy 2.0**(async ORM)+ **asyncpg** - **PostgreSQL 14+** - **Pydantic v2**(请求/响应 schema 校验) - **python-jose**(JWT 编解码,HS256) - **bcrypt 5.x**(密码哈希) - **openpyxl 3.1+**(Excel 模板生成与批量导入解析) - **OAuth2PasswordBearer** 标准 token 流 ### 前端 - **React 18** + **Vite 5** - **React Router v6**(含 `ProtectedRoute` 路由守卫) - **Recharts 3.x**(OOT 趋势分析图表库) - **Context API**(全局 AuthContext) - **原生 CSS**(深色/浅色兼容变量 + `@media` 响应式媒体查询) - **Axios**(请求拦截器自动注入 Bearer Token) - **HTML5 `capture="camera"`**(移动端拍照上传) ### 测试 - **Playwright**(E2E 端到端测试,支持 iPhone 视口模拟) ### 部署 - **Ubuntu 24.04 LTS** - **systemd**(后端服务管理) - **Nginx**(反向代理 + 前端静态托管) - **PostgreSQL 14+**(apt 安装) --- ## 4. 目录结构 ``` Lims/ ├── backend/ # 后端 FastAPI │ ├── app/ │ │ ├── api/ # 路由层 │ │ │ ├── auth.py # 登录 / 当前用户 / 电子签名校验 │ │ │ ├── users.py # 用户管理 (ADMIN) │ │ │ ├── em_sample.py # 环境样本台账 + 审计时间轴 + 发起偏差 │ │ │ ├── em_result.py # 检测结果录入 │ │ │ ├── em_deviation.py # 偏差调查管理 (CRUD + 状态流转) │ │ │ ├── em_schedule.py # 采样计划 │ │ │ ├── em_location.py # 监测点位 │ │ │ ├── equipment.py # 仪器设备 │ │ │ ├── reagent_batch.py# 试剂批次 │ │ │ ├── location.py # 基础位置 │ │ │ ├── dashboard.py # 仪表盘聚合 │ │ │ ├── trends.py # OOT 趋势分析(时序聚合 + 智能预警) │ │ │ ├── customer.py # 客户管理 (CRO 业务) │ │ │ ├── contract.py # 合同管理 + 合同测试清单 (CRO 业务) │ │ │ ├── test_item.py # 检测大类 + 检测项目字典 + 级联树 + Excel 导入 │ │ │ ├── subcontractor.py# 分包商管理 + 外发分包单工作流 (ISO 17025) │ │ │ └── audit_log.py # 审计日志 │ │ ├── core/ # 配置 / 安全 / DB │ │ ├── models/ # SQLAlchemy 模型 + UserRole / DeviationStatus / ContractStatus 枚举 │ │ ├── schemas/ # Pydantic 请求/响应 │ │ │ ├── em_sample.py # 样本相关 schema │ │ │ ├── em_result.py # 结果录入 schema │ │ │ ├── deviation.py # 偏差调查 schema │ │ │ ├── customer.py # 客户/合同/合同测试清单 schema │ │ │ ├── test_item.py # 检测大类/项目字典/级联树/导入结果 schema │ │ │ ├── subcontractor.py# 分包商/外发分包单 schema │ │ │ ├── electronic_signature.py # 电子签名 schema │ │ │ └── audit_log.py # 审计日志 + 时间轴 schema │ │ ├── services/ # 业务逻辑层 │ │ │ ├── em_sample.py # 样本服务(含审计写入 + 合同关联) │ │ │ ├── em_result.py # 结果录入服务(含审计写入 + 合同规格优先级) │ │ │ ├── em_deviation.py # 偏差调查服务(含合规拦截) │ │ │ └── auth.py # 认证服务 │ │ ├── deps.py # get_current_user / require_roles │ │ └── main.py # FastAPI 应用入口 │ ├── Dockerfile │ ├── requirements.txt │ ├── seed.py │ └── lims_test.py # Playwright E2E 测试脚本 │ ├── frontend/ # 前端 React │ ├── src/ │ │ ├── api/client.js # Axios + JWT 拦截器 │ │ ├── contexts/ │ │ │ └── AuthContext.jsx # 全局 currentUser + token │ │ ├── components/ │ │ │ ├── Layout.jsx # 侧边栏 + 顶栏 + 用户卡 + 移动端汉堡抽屉 │ │ │ ├── ProtectedRoute.jsx │ │ │ ├── ElectronicSignatureModal.jsx # 21 CFR Part 11 电子签名弹窗 │ │ │ └── ErrorBoundary.jsx │ │ ├── pages/ │ │ │ ├── Login.jsx │ │ │ ├── Dashboard.jsx │ │ │ ├── EmSampleLedger.jsx # 样本台账(含电子签名 + 审计时间轴 + 合同关联 + 移动端卡片视图) │ │ │ ├── EmResultEntry.jsx │ │ │ ├── DeviationManagement.jsx # 偏差与调查管理 │ │ │ ├── OotTrendAnalysis.jsx # OOT 趋势分析(Recharts 图表 + 智能预警) │ │ │ ├── EmScheduleManagement.jsx │ │ │ ├── EmLocationManagement.jsx │ │ │ ├── EquipmentManagement.jsx │ │ │ ├── ReagentBatchManagement.jsx │ │ │ ├── CustomerManagement.jsx # 客户管理 (CRO 业务) │ │ │ ├── ContractManagement.jsx # 合同管理(动态测试清单 + 级联选择器) │ │ │ ├── TestCategoryManagement.jsx # 检测大类管理 │ │ │ ├── TestItemDictionary.jsx # 检测项目字典(Switch 开关 + Excel 批量导入) │ │ │ ├── SubcontractorManagement.jsx # 分包商名录(资质预警 + CRUD) │ │ │ ├── OutsourcingOrderManagement.jsx # 外发分包单(工作流 + 拍照上传) │ │ │ ├── UserManagement.jsx │ │ │ ├── Forbidden.jsx │ │ │ └── EMReportTemplate.jsx # PDF 报告模板(分包项目星号标识 + 合规备注声明) │ │ ├── App.jsx # 路由 + ProtectedRoute 包裹 │ │ ├── App.css # 含桌面端 + 移动端响应式样式 │ │ └── main.jsx │ ├── index.html │ ├── package.json │ └── vite.config.js │ ├── database/ # 数据库脚本 │ ├── init.sql # 建表 DDL(含 ENUM) │ ├── seed_em.sql # EM 业务基础数据 │ ├── migration_deviation.sql # 偏差调查表 + has_active_deviation 字段 │ ├── migration_*.sql # 增量迁移(按字母序执行) │ ├── backup.sh / restore.sh # 备份恢复 │ └── migrate.sh │ ├── deploy/ # 部署脚本(Linux) │ ├── READ_ME.md # 部署说明 │ ├── install.sh # Ubuntu 一键安装 │ ├── install-services.sh # 注册 systemd │ └── start.sh # 服务启停 │ ├── docker-compose.yml └── README.md # ← 本文档 ``` --- ## 5. 业务流程 ### 5.1 环境样本状态机 ``` ┌──────┐ 采样 ┌─────────┐ 收样 ┌─────────────┐ │ LOGGED├──────────►│SAMPLING ├──────────►│ RECEIVED │ └──┬───┘ └────┬────┘ └──────┬──────┘ │ │ │ │ (登记) │ │ 录入结果 │ │ ▼ │ │ ┌───────────┐ │ │ │IN_PROGRESS│ │ │ └─────┬─────┘ │ │ │ 提交 │ │ ▼ │ │ ┌───────────┐ │ │ │ COMPLETED │ (待复核) │ │ └─────┬─────┘ │ │ ┌─────────┴────────┐ │ │ 复核通过 驳回 │ │ 🔐电子签名 🔐电子签名 │ │ ▼ ▼ │ │ ┌──────────┐ ┌──────────┐ │ │ │ REVIEWED │ │ REJECTED │ │ │ └────┬─────┘ └─────┬────┘ │ │ │ 批准 │ 重新录入 │ │ 🔐电子签名 │ │ │ ▼ │ │ │ ┌──────────┐ │ │ │ │ APPROVED │ │ │ │ └────┬─────┘ │ │ │ ▼ │ │ │ ┌──────────┐ │ │ │ │ 报告生成 │ │ │ │ └──────────┘ │ ``` > 🔐 标记 = 该操作需要 21 CFR Part 11 电子签名(二次密码校验 + 签字原因) ### 5.2 OOS 偏差调查流程 当样本检测结果出现 OOS(超标)时,系统强制执行偏差调查: ``` 检测结果 OOS │ ▼ ┌──────────────┐ 未关闭偏差 ┌──────────────┐ │ 发起偏差调查 ├──────────────────►│ 批准放行 403 │ │ (OPEN) │ │ 合规拦截 │ └──────┬───────┘ └──────────────┘ │ ▼ ┌──────────────┐ │ 填写根因调查 │ │ (INVESTIGATING)│ └──────┬───────┘ │ ▼ ┌──────────────┐ 偏差已关闭 ┌──────────────┐ │ QA 关闭偏差 ├──────────────────►│ 批准放行 200 │ │ (CLOSED) │ │ 允许放行 │ └──────────────┘ └──────────────┘ ``` **关键规则**: - 样本存在 OOS 结果且无 `CLOSED` 状态偏差单 → `POST /approve` 返回 **403** - 偏差编号格式:`DEV-YYYY-NNN`(如 `DEV-2026-001`),自动递增 - 关闭偏差后 `has_active_deviation` 自动置为 `False` ### 5.3 CRO 合同驱动业务流程 ``` ┌──────────┐ 1:N ┌──────────┐ 1:N ┌──────────────────┐ │ 客户 ├──────────►│ 合同 ├──────────►│ 合同测试清单 │ │ Customer │ │ Contract │ │ ContractTestItem │ └──────────┘ └──────────┘ └────────┬─────────┘ │ 引用 ▼ ┌──────────────────┐ │ 检测项目字典 │ │ TestItem │ │ ├─ 检验标准 │ │ ├─ 指导价 │ │ ├─ 默认警戒限 │ │ ├─ 默认行动限 │ │ └─ 是否允许分包 │ └────────┬─────────┘ │ 登记样本时关联 ▼ ┌──────────────────┐ │ 环境样本 │ │ Sample │ │ ├─ contract_id │ │ ├─ contract_test_│ │ │ item_id │ │ └─ 自动继承限度 │ └──────────────────┘ ``` **合同测试清单动态表格**: - 业务员在合同新建/编辑表单中动态添加测试项行 - 每行包含:客户采样点名称(手填)+ 检测项目(级联选择器引用字典)+ 警戒限 + 行动限 + 检验标准 - 选中检测项目后自动带出 `test_standard`(检验标准)和 `standard_price`(指导价参考) - 登记样本时选择合同测试项,自动继承采样点名称与判定限度 ### 5.4 检测分包工作流(ISO 17025 合规) ``` ┌──────────────┐ │ 样本检测中 │ │ (IN_PROGRESS) │ └──────┬───────┘ │ 部分项目需外发分包 │ (TestItem.is_subcontractable = True) ▼ ┌──────────────────────────────────────┐ │ 1. 创建外发分包单 (PENDING_SEND) │ │ POST /api/outsourcing/create │ │ ├─ 选择样本 + 检测项目 │ │ ├─ 选择已批准分包商 │ │ │ (Subcontractor.is_approved=True)│ │ └─ 校验检测项目可分包 │ └──────┬───────────────────────────────┘ │ 物理送样 ▼ ┌──────────────────────────────────────┐ │ 2. 标记已发出 (SENT) │ │ PATCH /api/outsourcing/{id}/status│ └──────┬───────────────────────────────┘ │ 等待分包商回传结果 ▼ ┌──────────────────────────────────────┐ │ 3. 录入分包结果 (RESULT_RECEIVED) │ │ POST /api/outsourcing/{id}/ │ │ record-result │ │ ├─ 分包商反馈测试数值 │ │ ├─ 原始报告附件(支持拍照上传) │ │ └─ 备注 │ └──────┬───────────────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ 4. PDF 报告合规标识 │ │ ├─ 分包项目标记星号 (*) │ │ ├─ 自动生成分包备注声明 │ │ └─ 注明分包商名称与分包单号 │ └──────────────────────────────────────┘ ``` **关键规则**: - 创建外包单前置条件:`TestItem.is_subcontractable=True` + `Subcontractor.is_approved=True` + 资质未过期 - 分包商资质有效期 30 天内 → 橙色预警;已过期 → 红色预警 + 选择列表禁用 - 外包单状态机:`PENDING_SEND` → `SENT` → `RESULT_RECEIVED`(单向流转) - 样本全局状态不阻塞自检项目,但需分包结果回传后方可最终 QA 批准 ### 5.5 角色流转示例 | 步骤 | 角色 | 操作 | 接口 | |---|---|---|---| | 1 | 业务员 | 维护客户 | `POST /api/customers` | | 2 | 业务员 | 创建合同 + 测试清单 | `POST /api/contracts` | | 3 | 实验员 | 登记样本(关联合同测试项) | `POST /api/em-samples` | | 4 | 实验员 | 录入检测结果 | `POST /api/em-samples/{id}/results` | | 4b | 实验员 | 发起外发分包(如需) | `POST /api/outsourcing/create` | | 4c | 实验员 | 录入分包结果 | `POST /api/outsourcing/{id}/record-result` | | 5 | 实验员 | 提交完成 | `POST /api/em-samples/{id}/submit-results` | | 6 | 主管 | 复核通过(🔐电子签名) | `POST /api/em-samples/{id}/review` | | 6b | 主管/QA | 驳回(🔐电子签名) | `POST /api/em-samples/{id}/reject` | | 7 | QA | 批准放行(🔐电子签名) | `POST /api/em-samples/{id}/approve` | | 7b | 主管/QA | 发起偏差调查(OOS 时) | `POST /api/em-samples/{id}/initiate-deviation` | | 8 | 系统 | 生成报告(含分包标识) | `GET /api/em-samples/{id}/report` | | 9 | 任意 | 查看审计时间轴 | `GET /api/em-samples/{id}/audit-trail` | 每一步都会写入审计日志(操作人 + 时间 + 备注),复核/批准/驳回需先通过电子签名校验。 --- ## 6. 模块功能 ### 6.1 智能控制台(Dashboard) - 4 个 KPI 卡片:待录入 / 待复核 / 待批准 / 异常预警 - **按角色着重显示**: - 实验员 → 「待录入」 - 主管 → 「待复核」 - QA → 「待批准」 - 管理员 → 「异常预警」 - KPI 卡片可点击跳转 ### 6.2 环境样本台账(EM Sample Ledger) - 列表展示所有样本(含状态徽章、OOS 标记、偏差状态、合同关联) - 筛选:状态、时间范围、点位、批次 - 按钮按当前用户角色 + 样本状态动态显示 - **21 CFR Part 11 电子签名拦截**:复核/批准/驳回按钮点击后先弹签名弹窗 - **OOS 偏差调查**:OOS + 无活跃偏差 → 红色「⚠ 发起偏差调查」按钮 - **CRO 合同关联**:样本可关联客户/合同/合同测试项,展示 `test_item_name`(检测项目名称) - **外发分包入口**:样本卡片/行内提供「外发分包」按钮,直接跳转分包单创建 - **详情抽屉双 Tab**: - 📋 基本信息与测试结果 - 🕒 审计追踪 / 生命周期(时间轴可视化,含偏差事件跳转) - **移动端卡片视图**:<768px 自动切换为卡片列表,含状态徽章、检测项目、采样点位、登记人等关键字段,操作按钮纵向排列 ### 6.3 检测结果录入(EM Result Entry) - 录入各检测项的数值、单位、检测方法 - 自动计算是否超标(依据规格配置) - **OOS 判定优先级**:合同测试清单项 > EMLocation 主数据规格 - 提交后状态由 `IN_PROGRESS` → `COMPLETED` ### 6.4 监测点位管理(EM Location Management) - 点位信息:编号、名称、类型、坐标、所属区域 - 检测规格配置(每点位支持的检测项 + 标准限值) ### 6.5 采样计划(EM Schedule Management) - 周/月/季度计划编制 - 自动生成待采样任务 - 软删除(保留历史轨迹) ### 6.6 仪器设备管理(Equipment) - 设备台账、校准记录、维护记录 - 与检测结果关联(自动追溯仪器状态) ### 6.7 试剂批次管理(Reagent Batch) - 试剂入库、有效期预警、用量统计 - 与检测结果关联(试剂失效/过期自动告警) ### 6.8 用户管理(仅 ADMIN) - 用户的增删改查 - 重置密码、启停账号 - 角色分配 ### 6.9 审计日志 - 关键操作全留痕(CREATE/COLLECT/RECEIVE/RESULT_ENTRY/REVIEW/APPROVE/REJECT/DEVIATION_INIT/DEVIATION_CLOSE/SIGN_OK/SIGN_FAIL) - 不可修改,仅可查询 - **审计时间轴 API**:`GET /api/em-samples/{id}/audit-trail` 返回样本 + 关联偏差的完整事件流 ### 6.10 偏差与调查管理(Deviation Management) - 偏差调查单列表(含状态卡片:OPEN / INVESTIGATING / CLOSED) - 调查抽屉:填写根本原因、纠正措施、预防措施 - 状态流转:OPEN → INVESTIGATING → CLOSED - **合规拦截**:OOS 样本未关闭偏差前禁止批准放行(403) - 自动编号:`DEV-YYYY-NNN` ### 6.11 OOT 趋势分析(OOT Trend Analysis) - **控制面板**:采样点位下拉框 + 测试项目下拉框(联动加载)+ 日期区间选择 + 查询按钮 - **趋势折线图**(Recharts): - X 轴:时间(Date) - Y 轴:测试数值(Value) - 主折线:实际测试结果数据 - 橙色虚线参考线:警戒限(Alert Limit) - 红色虚线参考线:行动限(Action Limit) - 红色菱形散点:OOS 超标点 - **自定义 Tooltip**:悬浮显示采样日期、数值、样本条码、OOS/超警戒状态 - **OOT 智能预警条**(基础版规则引擎): - 规则 1:最新 3 个数据点严格单调递增(v3 > v2 > v1)→ 黄/橙色预警 - 规则 2:连续 3 个数据点触碰或高于警戒限 → 预警 - 预警文案示例:"⚠️ 智能预警:该点位近期呈现上升趋势(OOT),建议排查空调系统或消毒程序。" - **数据明细表**:日期、样本条码、数值、警戒限、行动限、状态(正常/超警戒/OOS超标) - **后端聚合接口**: - `GET /api/trends/locations` — 获取活跃点位列表 - `GET /api/trends/location-parameters` — 获取点位下参数列表(含规格限) - `GET /api/trends/em-data` — 时序趋势数据 + OOT 预警结果 ### 6.12 电子签名(21 CFR Part 11) - **二次密码校验**:`POST /api/auth/verify-signature`,比对当前用户哈希密码 - **签字原因**:支持预设下拉 + 自定义输入 - **审计留痕**:签名成功写 `SIGN_OK`,失败写 `SIGN_FAIL`,均记录 reason - **前端拦截**:复核/批准/驳回按钮 → 弹出 `ElectronicSignatureModal` → 校验通过后调业务接口 ### 6.13 客户管理(CRO 业务) - 客户台账:编号、名称、联系人、电话、邮箱、地址、启停状态 - 客户下合同列表查询:`GET /api/customers/{id}/contracts` - 用于 CRO 第三方检测实验室业务的客户主数据维护 ### 6.14 合同管理(CRO 业务) - 合同台账:合同编号、归属客户、项目名称、合同金额、签订日期、状态(草稿/已签订/已完成/已取消) - 状态流转:DRAFT → SIGNED → COMPLETED(或 CANCELLED) - **核心:合同测试清单动态表格**: - 业务员可动态添加/删除测试项行 - 每行:客户采样点名称(手填)+ 检测项目(**级联选择器**引用字典)+ 警戒限 + 行动限 + 检验标准 - 选中检测项目后**自动带出** `test_standard`(检验标准)和 `standard_price`(指导价参考) - 数据源调用 `GET /api/test-items/tree` 级联树接口 - 合同测试清单独立查询:`GET /api/contracts/{id}/test-items` ### 6.15 检测大类管理(主数据字典) - 检测大类台账:大类编号、大类名称、排序权重、启停状态 - 删除前校验:大类下有检测项目时拒绝删除 - 用于检测项目字典的一级分类(如:理化检测、微生物检测) ### 6.16 检测项目字典(主数据字典) - 检测项目台账:项目编号、项目名称、所属大类、检验标准、指导价、默认警戒限、默认行动限、是否允许分包、启停状态 - **Switch 开关快速切换**:表格内直接切换"是否允许分包"和"启用/停用"状态 - **筛选**:按大类、关键字(编号/名称/标准)、分包状态 - **Excel 批量导入**(详见 §6.18) - **级联树接口**:`GET /api/test-items/tree` 供合同表单级联选择器使用 - **默认限度联动**:合同引用检测项目时可带出默认警戒限/行动限,为后续标准化报价奠基 ### 6.17 Excel 批量导入(检测项目字典) - **模板下载**:`GET /api/test-items/export-template` - 动态生成 `.xlsx` 文件,含 8 列表头(项目编号/检测大类/项目名称/检验标准/指导价/默认警戒限/默认行动限/允许分包) - 含 2 行示例数据 + 第二个 Sheet"填写说明" - 支持中文文件名(RFC5987 编码) - **批量上传**:`POST /api/test-items/import` - 接收 `UploadFile`,仅支持 `.xlsx` 格式(非 Excel 返回 400) - **Upsert 逻辑**:按项目编号查询,存在则更新,不存在则新增 - **自动建大类**:检测大类不存在时自动创建(智能容错) - **错误收集**:缺必填项的行不中断流程,记录行号和原因 - 返回汇总报告:`{success_count, inserted_count, updated_count, created_categories_count, errors}` - **前端交互**: - 顶部操作区两个按钮:⬇️ 下载导入模板 / ⬆️ 批量导入数据 - 上传 Modal 支持拖拽上传 + 点击选择 - 结果展示:绿色成功卡片(成功/新增/更新/新建大类数量)+ 红色错误列表(逐行错误详情) ### 6.18 分包商名录(ISO 17025 合规) - 分包商台账:名称、资质编号(如 CNAS L1234)、联系人、电话、邮箱、地址、资质有效期、是否批准、启停状态 - **资质有效期预警**: - 资质有效期 30 天内 → 橙色预警徽章 - 资质已过期 → 红色预警徽章 + 选择列表中禁用 - **批准状态管理**:仅 `is_approved=True` 的分包商可被选用于外发分包单 - **CRUD 接口**:`/api/subcontractors`(列表/新建/更新/删除) - **选项接口**:`/api/subcontractors/options`(下拉列表专用,支持 `only_approved` 参数过滤) - **唯一性校验**:分包商名称不可重复 ### 6.19 外发分包单管理(ISO 17025 合规) - 分包单台账:分包单号、样本条码、检测项目、分包商、状态、发出时间、结果回传时间、测试数值 - **状态机**:`PENDING_SEND`(待发出)→ `SENT`(已发出)→ `RESULT_RECEIVED`(结果已回传) - **创建前置校验**: - 检测项目 `is_subcontractable=True` - 分包商 `is_approved=True` - 分包商资质未过期 - **操作按钮**(按状态动态显示): - `PENDING_SEND` → 「标记已发出」 - 非 `RESULT_RECEIVED` → 「录入分包结果」 - `RESULT_RECEIVED` → 「✓ 已完成」 - **结果录入 Modal**: - 分包商反馈测试数值(必填) - 原始报告附件(选填,**移动端支持拍照上传** `capture="camera"`) - 备注 - **筛选区**:按状态筛选 + 查询/重置 - **移动端卡片视图**:<768px 自动切换为卡片列表,含状态徽章、分包单号、样本条码、分包商等关键字段 ### 6.20 PDF 报告模板(EMReportTemplate) - 检测报告渲染:样本信息、检测方法分组、结果数据、电子签名 - **分包合规标识**(ISO 17025): - 分包项目参数标记星号 `*` - 自动生成合规备注声明:"* 该项目由分包商 {分包商名称} 检测,分包单号:{分包单号}" - **合同关联信息**:CRO 业务时展示客户名称、合同名称、动态采样点位 - **电子签名区块**:录入人 / 复核人 / 批准人(姓名 + 时间) --- ## 7. 接口约定 ### 7.1 鉴权 **登录**: ```http POST /api/auth/login Content-Type: application/json { "username": "admin", "password": "admin123" } ``` **响应**: ```json { "access_token": "eyJhbGciOi...", "token_type": "bearer" } ``` **所有业务接口** 需在 Header 携带: ``` Authorization: Bearer ``` **Token 有效期**:8 小时(`ACCESS_TOKEN_EXPIRE_MINUTES=480`) ### 7.2 错误响应统一格式 ```json { "detail": "未提供认证凭证" } ``` | 状态码 | 含义 | |---|---| | 400 | 业务校验失败(如编号重复、文件格式错误) | | 401 | 未认证 / Token 失效 | | 403 | 已认证但角色不足 / OOS 未关闭偏差 | | 404 | 资源不存在 | | 422 | 请求参数校验失败(`detail` 为数组,含 `loc`/`msg`/`type`) | | 500 | 服务器内部错误 | > **422 错误处理约定**:前端需将 `detail` 数组展开为可读文本(`字段名: 错误信息`),避免直接 `alert(error)` 显示 `[object Object]`。 ### 7.3 主要接口列表 #### 认证与用户 | 方法 | 路径 | 角色 | 用途 | |---|---|---|---| | POST | `/api/auth/login` | 公开 | 登录 | | GET | `/api/auth/me` | 已登录 | 当前用户信息 | | POST | `/api/auth/verify-signature` | 已登录 | 21 CFR Part 11 电子签名校验 | | GET | `/api/users` | ADMIN | 用户列表 | | POST | `/api/users` | ADMIN | 新建用户 | #### 环境样本与偏差 | 方法 | 路径 | 角色 | 用途 | |---|---|---|---| | GET | `/api/dashboard/summary` | 已登录 | 仪表盘聚合 | | GET | `/api/em-samples` | 已登录 | 样本台账 | | POST | `/api/em-samples` | A/S/AD | 新建样本(可关联合同测试项) | | POST | `/api/em-samples/{id}/submit-results` | A/S/AD | 提交结果 | | POST | `/api/em-samples/{id}/review` | S/AD | 复核通过(🔐电子签名) | | POST | `/api/em-samples/{id}/reject` | S/Q/AD | 驳回(🔐电子签名) | | POST | `/api/em-samples/{id}/approve` | Q/AD | 批准放行(🔐电子签名,OOS 时需先关闭偏差) | | POST | `/api/em-samples/{id}/initiate-deviation` | S/Q/AD | 发起偏差调查 | | GET | `/api/em-samples/{id}/audit-trail` | 已登录 | 审计时间轴 | | GET | `/api/em-samples/{id}/report` | 已登录 | 检测报告(含分包标识) | | GET | `/api/deviations` | 已登录 | 偏差调查列表 | | PATCH | `/api/deviations/{id}/investigation` | S/Q/AD | 更新调查(根因/纠正/预防) | | POST | `/api/deviations/{id}/close` | Q/AD | 关闭偏差单 | #### 分包商与外发分包(ISO 17025) | 方法 | 路径 | 角色 | 用途 | |---|---|---|---| | GET | `/api/subcontractors` | 已登录 | 分包商列表 | | GET | `/api/subcontractors/options` | 已登录 | 分包商下拉选项(支持 `only_approved` 过滤) | | POST | `/api/subcontractors` | 已登录 | 新建分包商 | | PATCH | `/api/subcontractors/{id}` | 已登录 | 更新分包商 | | DELETE | `/api/subcontractors/{id}` | 已登录 | 删除分包商 | | GET | `/api/outsourcing` | 已登录 | 外发分包单列表(支持状态筛选) | | POST | `/api/outsourcing/create` | A/S/AD | 创建外发分包单(校验可分包 + 已批准 + 资质有效) | | PATCH | `/api/outsourcing/{id}/status` | A/S/AD | 更新分包单状态(PENDING_SEND → SENT) | | POST | `/api/outsourcing/{id}/record-result` | A/S/AD | 录入分包商回传结果 | | GET | `/api/outsourcing/by-sample/{sample_id}` | 已登录 | 按样本查询分包单 | #### CRO 客户与合同 | 方法 | 路径 | 角色 | 用途 | |---|---|---|---| | GET | `/api/customers` | 已登录 | 客户列表 | | POST | `/api/customers` | 已登录 | 新建客户 | | PATCH | `/api/customers/{id}` | 已登录 | 更新客户 | | DELETE | `/api/customers/{id}` | 已登录 | 删除客户 | | GET | `/api/customers/{id}/contracts` | 已登录 | 客户下合同列表 | | GET | `/api/contracts` | 已登录 | 合同列表(支持状态筛选) | | POST | `/api/contracts` | 已登录 | 新建合同(含测试清单) | | PATCH | `/api/contracts/{id}` | 已登录 | 更新合同 | | GET | `/api/contracts/{id}/test-items` | 已登录 | 合同测试清单 | #### 检测项目主数据字典 | 方法 | 路径 | 角色 | 用途 | |---|---|---|---| | GET | `/api/test-categories` | 已登录 | 检测大类列表 | | POST | `/api/test-categories` | 已登录 | 新建大类 | | PATCH | `/api/test-categories/{id}` | 已登录 | 更新大类 | | DELETE | `/api/test-categories/{id}` | 已登录 | 删除大类(无关联项目时) | | GET | `/api/test-items` | 已登录 | 检测项目列表(支持大类/关键字/分包筛选) | | POST | `/api/test-items` | 已登录 | 新建项目 | | PATCH | `/api/test-items/{id}` | 已登录 | 更新项目 | | DELETE | `/api/test-items/{id}` | 已登录 | 删除项目 | | GET | `/api/test-items/tree` | 已登录 | 级联树(按大类分组,供合同表单使用) | | GET | `/api/test-items/export-template` | 已登录 | 下载 Excel 导入模板 | | POST | `/api/test-items/import` | 已登录 | 批量导入(Upsert + 自动建大类) | #### OOT 趋势分析 | 方法 | 路径 | 角色 | 用途 | |---|---|---|---| | GET | `/api/trends/locations` | 已登录 | 趋势分析-活跃点位列表 | | GET | `/api/trends/location-parameters` | 已登录 | 趋势分析-点位参数列表(含规格限) | | GET | `/api/trends/em-data` | 已登录 | 趋势分析-时序数据 + OOT 预警 | > 角色简写:A=ANALYST, S=SUPERVISOR, Q=QA, AD=ADMIN --- ## 8. 数据完整性(ALCOA+ & 21 CFR Part 11) LIMS 设计严格遵循 ALCOA+ 原则与 FDA 21 CFR Part 11 电子签名/审计追踪要求,关键保障: | 原则 | 实现 | |---|---| | **Attributable**(可归因) | 所有审计字段(登记人/采样人/复核人/批准人/驳回人/签名人)= 当前登录用户 ID,后端用 `current_user.id` 覆盖前端传入值,**不可伪造** | | **Legible**(可读) | API 响应里同时返回 `logged_by_name`/`reviewed_by_name` 等人类可读字段 | | **Contemporaneous**(同步) | 每个时间戳用数据库 `default=utcnow` 或后端 `datetime.utcnow()` 写入 | | **Original**(原始) | 原始记录保存在 `sample` / `result` / `audit_log` / `deviation` 表中 | | **Accurate**(准确) | 数值字段用 Pydantic 校验 + 数据库 `Numeric` 类型 | ### 8.1 21 CFR Part 11 电子签名合规 | 要求 | 实现 | |---|---| | **签名不可伪造** | 后端 `verify-signature` 接口比对 bcrypt 哈希密码,前端无法绕过 | | **签名不可重用** | 每次签名生成唯一 `signed_at` 时间戳,写入 `audit_log` | | **签名失败可检测** | 密码错误写 `SIGN_FAIL` 审计记录,含尝试原因 | | **签字原因留痕** | `reason` 字段写入 `audit_log.reason`,支持预设下拉 + 自定义 | | **审计追踪完整** | 样本全生命周期事件(CREATE→COLLECT→RECEIVE→RESULT_ENTRY→REVIEW→APPROVE + 偏差事件 + 签名事件)均可通过 `audit-trail` API 查询 | ### 8.2 OOS 偏差调查合规 | 要求 | 实现 | |---|---| | **超标结果必须调查** | `approve` 接口检查 OOS 结果,无 CLOSED 偏差单 → 403 拦截 | | **偏差编号可追溯** | 自动生成 `DEV-YYYY-NNN` 编号,关联 `sample_id` | | **调查过程可审计** | OPEN→INVESTIGATING→CLOSED 每步写 `audit_log`,含根因/纠正/预防措施 | | **偏差关闭后放行** | `has_active_deviation` 双向同步,关闭偏差后自动置 False | ### 8.3 ISO 17025 分包合规 | 要求 | 实现 | |---|---| | **分包商资质管理** | 记录资质编号、有效期;过期自动禁用选择;30 天内橙色预警 | | **分包前置校验** | 创建外包单时校验 `is_subcontractable` + `is_approved` + 资质有效期 | | **分包结果追溯** | 分包单状态机 PENDING_SEND → SENT → RESULT_RECEIVED,每步含时间戳 | | **报告合规标识** | PDF 报告中分包项目标记星号 + 自动生成备注声明(含分包商名称 + 分包单号) | **双层防护**: - 前端 UI 按角色隐藏按钮(默认 UX) - 后端接口加 `require_roles` 依赖(纵深防御) - 关键审计字段在 service 层用 `current_user.id` 强制覆盖(防前端伪造) - 电子签名在业务操作前强制校验(防未授权审批) --- ## 9. 响应式移动端设计 为满足实验员和采样员用手机进行现场操作(接样、录入、外发)的需求,系统在不破坏电脑端既有功能的前提下,对前端进行响应式(Responsive)改造,完美适配手机浏览器(H5/微信内打开)。 ### 9.1 全局响应式导航 - **桌面端(≥768px)**:固定左侧侧边栏导航 - **移动端(<768px)**:顶部工具栏 + 汉堡抽屉菜单 - 点击 ☰ 按钮展开侧边栏抽屉 - 点击遮罩层或导航项自动关闭抽屉 - 顶部工具栏显示系统标题 + 当前用户头像 ### 9.2 样本台账移动端卡片视图 - **桌面端**:传统表格视图(含状态徽章、操作按钮列) - **移动端**:卡片列表视图,每张卡片包含: - 头部:样本条码 + 状态徽章 - 主体:检测项目、采样点位、物料、批号、来源、登记人、登记时间、测试数 - 操作区:采样确认 / 直接收样 / 接收样本 / 录入结果 / 外发分包 / 录入分包结果 / 详情 / 复核 / 批准 / 偏差调查 / 生成报告 ### 9.3 分包模块移动端优化 - **分包商名录**:卡片化展示,资质预警徽章醒目 - **外发分包单**:卡片化展示,状态徽章 + 操作按钮 - **拍照上传附件**:结果录入 Modal 中附件上传支持 `capture="camera"`,唤起手机摄像头拍照 - 拍照后实时预览 - 兼容桌面端文件选择 ### 9.4 移动端表单优化 - 表单输入框 `width: 100%` + `min-height: 44px`(iOS 推荐点击区域) - Modal 全屏化(`width: 100%` + `height: 100%` + `border-radius: 0`) - 筛选区纵向排列(`.filter-bar` 类,移动端 `flex-direction: column`) - 按钮纵向堆叠,避免横向滚动 ### 9.5 双端视图切换实现 - **CSS 类互斥控制**: - `.desktop-only`:桌面端显示,移动端 `display: none !important` - `.mobile-only`:移动端显示,桌面端 `display: none` - **媒体查询断点**:`@media (max-width: 768px)` - **无 UI 框架依赖**:纯原生 CSS + React 条件渲染,无额外依赖 ### 9.6 移动端测试账号 | 用户名 | 密码 | 角色 | 典型场景 | |---|---|---|---| | `analyst01` | `analyst123` | ANALYST | 现场接样、录入结果、外发分包 | | `supervisor01` | `super123` | SUPERVISOR | 现场复核、查看报表 | --- ## 10. 本地开发 ### 10.1 准备环境 - Python 3.11+ - Node.js 20+ - PostgreSQL 14+(本地或 Docker) - Git ### 10.2 启动后端 ```bash cd backend python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install -r requirements.txt pip install openpyxl # Excel 导入功能依赖 # 启动(确保 .env 或环境变量已配置 DATABASE_URL) python -m uvicorn app.main:app --host 0.0.0.0 --port 8002 --reload ``` 后端启动时会自动: 1. 创建数据库表(依赖 `init.sql` + `migration_*.sql` 已执行) 2. 调用 `UserService.ensure_default_admin` seed 4 个测试账号 > **注意**:新增的 `test_category`、`test_item`、`customer`、`contract`、`contract_test_item`、`subcontractor`、`outsourcing_order` 表由 `Base.metadata.create_all` 自动创建。若需在已有库上增量迁移,用 postgres 超级用户执行: > ```sql > ALTER TABLE contract_test_item ADD COLUMN IF NOT EXISTS test_item_id UUID REFERENCES test_item(id); > ALTER TABLE contract_test_item DROP COLUMN IF EXISTS parameter_name; > ALTER TABLE test_item ADD COLUMN IF NOT EXISTS default_alert_limit NUMERIC(18,4); > ALTER TABLE test_item ADD COLUMN IF NOT EXISTS default_action_limit NUMERIC(18,4); > ``` ### 10.3 启动前端 ```bash cd frontend npm install npm run dev # 默认 http://localhost:5173 ``` `vite.config.js` 已配置代理:`/api/*` 转发到 `http://localhost:8002` ### 10.4 浏览器访问 打开 `http://localhost:5173`,用 `admin / admin123` 登录。 **移动端调试**: - Chrome DevTools → Toggle device toolbar → 选择 iPhone 12/14 - 或直接用手机浏览器访问局域网 IP(需配置 host 为 `0.0.0.0`) --- ## 11. 部署到 Ubuntu 服务器 ### 11.1 一键安装(推荐) ```bash # 1. 上传代码到服务器 scp -r ./linux/* user@your-server:/opt/lims/ # 2. SSH 登录 ssh user@your-server # 3. 一键安装(自动:装依赖、建库、初始化、注册 systemd、配 Nginx) cd /opt/lims/deploy sudo ./install.sh ``` 完成后访问 `http://<服务器IP>`,默认 80 端口(Nginx 反代)。 ### 11.2 Docker 部署 ```bash cd /opt/lims docker-compose up -d ``` ### 11.3 日常管理 ```bash # 服务启停 sudo /opt/lims/deploy/start.sh start|stop|restart|status # 查日志 sudo journalctl -u lims-backend -f tail -f /opt/lims/logs/backend.log # 数据库备份 cd /opt/lims/database ./backup.sh # 输出到 /opt/lims/backups/ ./restore.sh --latest # 从最新备份恢复 ``` ### 11.4 端口与目录 | 项目 | 路径 / 端口 | |---|---| | 项目目录 | `/opt/lims` | | 后端端口 | 8002(开发)/ 8001(生产) | | 前端开发端口 | 5173 | | 生产入口 | 80 (Nginx) | | 数据库 | PostgreSQL 5432,DB=`lims_db`,User=`lims_user` | | 日志 | `/opt/lims/logs/backend.log` | --- ## 12. E2E 测试 系统配套 Playwright E2E 端到端测试脚本,覆盖所有成功与失败场景。 ### 12.1 测试脚本 - **位置**:`backend/lims_test.py` - **截图目录**:`D:\pic`(自动创建,测试前自动清空旧截图) ### 12.2 测试覆盖范围 #### 桌面端 admin(21 个场景) - 登录测试:登录页加载、错误密码失败、admin 登录成功 - 核心模块:仪表盘、分包商名录、外发分包单、环境样本台账、检测项目字典、检测大类管理 - 业务流程:新增分包商成功、新增分包商失败(名称重复)、创建样本失败(必填项为空) - 其他模块:采样计划、采样点位、偏差管理、OOT 趋势、设备管理、试剂耗材、客户管理、合同管理 - PDF 报告生成入口验证 #### iPhone 实验员 analyst01(6 个场景) - 登录成功、样本台账、分包商名录、外包单列表、检测项目字典 - **失败场景**:用户管理权限拦截(403 生效) #### iPhone 主管 supervisor01(11 个场景) - **登录失败**:错误密码 - **登录成功**:supervisor01 登录 - **模块访问**:样本台账、分包商名录、外包单列表、偏差管理、OOT 趋势、设备管理、客户管理、合同管理、检测项目字典 #### 登录失败场景补充(3 个场景) - 不存在的用户登录失败 - 空用户名(浏览器原生 required 校验) - 未登录直接访问受保护页面 → 重定向到登录页 ### 12.3 iPhone 浏览器模拟配置 ```python IPHONE_VIEWPORT = {"width": 390, "height": 844} # iPhone 12/14 尺寸 IPHONE_UA = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) ..." # 上下文配置 context = browser.new_context( viewport=IPHONE_VIEWPORT, user_agent=IPHONE_UA, locale="zh-CN", device_scale_factor=3, is_mobile=True, has_touch=True, ) ``` ### 12.4 运行测试 ```bash cd backend python lims_test.py ``` 测试完成后: - 控制台输出详细测试报告(总场景数 / 通过 / 失败 / 通过率) - 截图保存至 `D:\pic`,文件名按 `序号_场景描述.png` 命名 ### 12.5 最近一次测试结果 - **总场景数**:41 - **通过**:41 - **失败**:0 - **通过率**:100.0% - **截图数量**:45 张 --- ## 13. 常见问题 ### Q1: 登录提示"Invalid or expired token" - 检查服务器是否重启(重启会重新加载 `SECRET_KEY`,所有 token 失效) - 用 `/api/auth/login` 重新获取 token ### Q2: 前端访问某页 403 - 该接口要求特定角色,确认当前登录账号角色匹配 - 角色对照见 [§2.2 权限矩阵](#22-权限矩阵) ### Q3: 提交时提示 `password cannot be longer than 72 bytes` - bcrypt 算法限制:密码最大 72 字节 - 后端 `security.py` 已自动截断 UTF-8 编码的前 72 字节 - 若用户密码超过 72 字节,请用更短密码 ### Q4: 修改了代码但前端不生效 - 前端 Vite 默认 HMR,应自动刷新 - 若仍无变化,强制刷新 `Ctrl+Shift+R`(清浏览器缓存) - 必要时 `npm run build` 重新构建生产产物 ### Q5: 数据库迁移失败(`permission denied for table`) - 当前数据库用户不是表 owner - 解决方案:用 `postgres` 超级用户登录后执行 `ALTER TABLE OWNER TO lims_user;` - 或授予 DDL 权限:`GRANT ALL ON SCHEMA public TO lims_user;` ### Q6: 忘记了 admin 密码 ```sql -- 在 psql 中直接重置(替换为新密码的 bcrypt hash) UPDATE user_credential SET hashed_password = '' WHERE user_id = (SELECT id FROM user_account WHERE username = 'admin'); ``` 可用 Python 生成 hash: ```python import bcrypt print(bcrypt.hashpw(b"new_password", bcrypt.gensalt()).decode()) ``` ### Q7: Excel 导入提示"仅支持 .xlsx 格式的 Excel 文件" - 系统仅接受 `.xlsx` 或 `.xlsm` 格式 - 旧版 `.xls` 格式不支持,请用 Excel 另存为 `.xlsx` - 建议先点击"⬇️ 下载导入模板"获取标准模板 ### Q8: 前端页面显示"暂无数据"但后端有数据 - 检查 `vite.config.js` 的 proxy target 是否指向正确的后端端口 - 开发环境后端默认 8002,生产环境 8001 - 确认后端服务已启动:`curl http://localhost:8002/api/auth/login` - **检查后端接口是否返回 500**:前端 catch 后会显示空列表,需查看后端日志定位 500 根因(常见:SQLAlchemy `MissingGreenlet` 错误 = 查询未预加载关系字段) ### Q9: 合同测试清单的检测项目下拉框为空 - 需先到【检测项目字典】页面维护大类与项目 - 或点击"⬆️ 批量导入数据"通过 Excel 快速初始化 ### Q10: 创建外发分包单失败 - 检查检测项目是否勾选"允许分包"(`TestItem.is_subcontractable=True`) - 检查分包商是否已批准(`Subcontractor.is_approved=True`) - 检查分包商资质是否已过期(过期分包商在选择列表中被禁用) ### Q11: 登记样本时 alert 显示 `[object Object]` - 原因:后端返回 422 校验错误,`detail` 为数组对象,直接 `alert()` 显示为 `[object Object]` - 已修复:前端提交前过滤空字符串 UUID 字段,422 错误时将 `detail` 数组展开为 `字段名: 错误信息` 格式 - 若仍出现,检查 `EmSampleLedger.jsx` 的 `handleCreate` 函数是否包含 422 错误处理逻辑 ### Q12: 移动端页面布局异常 - 确认浏览器视口宽度 <768px(Chrome DevTools 设备模拟或真实手机) - 检查是否使用了 `.desktop-only` / `.mobile-only` 类控制双端视图 - Modal 在移动端应全屏化(检查 `.modal-content` 的 `@media` 样式) - 筛选区应纵向排列(使用 `.filter-bar` 类而非内联 `flex`) --- ## 附录 A · 完整 API 列表 启动后端后访问 `http://localhost:8002/docs` 查看 Swagger UI(交互式文档)。 ## 附录 B · 数据库 ER 概览 主要表(按业务域): - **用户与权限**:`user_account`, `user_credential` - **CRO 业务**:`customer`, `contract`, `contract_test_item` - **主数据字典**:`test_category`, `test_item` - **分包管理(ISO 17025)**:`subcontractor`, `outsourcing_order` - **环境样本**:`sample`, `sample_test`, `result` - **偏差调查**:`deviation`(状态:OPEN / INVESTIGATING / CLOSED) - **点位与计划**:`location`, `location_specification`, `location_test_setup`, `em_schedule` - **设备与试剂**:`equipment`, `reagent_batch` - **基础数据**:`item`, `test_method`, `parameter`, `specification` - **审计**:`audit_log`(含 SIGN_OK / SIGN_FAIL 电子签名审计) 外键勾稽重点: - `customer.id` ← `contract.customer_id` (1:N) - `contract.id` ← `contract_test_item.contract_id` (1:N, ON DELETE CASCADE) - `test_item.id` ← `contract_test_item.test_item_id` (引用字典,nullable) - `test_category.id` ← `test_item.category_id` (1:N, ON DELETE RESTRICT) - `sample.contract_test_item_id` → `contract_test_item.id` (样本关联合同测试项) - `sample.logged_by_id` → `user_account.id` (NOT NULL) - `sample.reviewed_by_id` / `approved_by_id` → `user_account.id` (nullable, 流程完成后回填) - `deviation.sample_id` → `sample.id` (ON DELETE CASCADE) - `deviation.investigator_id` / `qa_approver_id` → `user_account.id` - `audit_log.changed_by_id` → `user_account.id` - `subcontractor.id` ← `outsourcing_order.subcontractor_id` (1:N) - `sample.id` ← `outsourcing_order.sample_id` (1:N) - `test_item.id` ← `outsourcing_order.test_item_id` (引用字典) - 详见 `database/init.sql` + `database/migration_deviation.sql` --- **版本说明** | 版本 | 日期 | 变更 | |---|---|---| | 0.1.0 | 2026-06-10 | 初版:含 RBAC、Dashboard、样本全流程、设备/试剂管理、审计日志 | | 0.2.0 | 2026-06-13 | OOS 偏差调查工作流:deviation 表 + 合规拦截(403)+ 偏差管理页 + 样本台账联动 | | 0.3.0 | 2026-06-14 | 21 CFR Part 11 电子签名 + 审计时间轴:verify-signature 接口 + ElectronicSignatureModal + audit-trail API + 全生命周期审计补齐 | | 0.4.0 | 2026-06-17 | OOT 趋势分析:trends API(时序聚合 + 智能预警)+ OotTrendAnalysis 页面(Recharts 折线图 + 警戒限/行动限参考线 + OOT 预警条)+ E2E 端到端测试 45/45 通过 + Playwright UI 测试 55/55 通过 | | 0.5.0 | 2026-06-19 | CRO 合同业务 + 检测项目主数据字典:Customer/Contract/ContractTestItem 模型 + TestCategory/TestItem 字典 + 合同测试清单级联选择器(引用字典,自动带出检验标准/指导价)+ Excel 批量导入(Upsert + 自动建大类 + 错误收集)+ 样本台账/报告展示 test_item.item_name + Playwright UI 测试 21 场景通过 | | 0.6.0 | 2026-07-01 | 检测分包与供应商管理(ISO 17025)+ 响应式移动端自适应设计:Subcontractor/OutsourcingOrder 模型 + 分包商名录页(资质预警)+ 外发分包单工作流页(PENDING_SEND→SENT→RESULT_RECEIVED)+ PDF 报告分包项目星号标识 + 合规备注声明 + 移动端汉堡抽屉导航 + 样本台账卡片视图 + 分包单卡片化 + 拍照上传附件(capture="camera")+ 修复 [object object] bug + 修复 list_samples MissingGreenlet 错误 + Playwright E2E 测试 41 场景 100% 通过 | --- > 文档维护者:LIMS 项目组 · 联系:7273289@qq.com > 仓库地址:gitee.com/beam66/brown-panda-lims