- Go 56.2%
- TypeScript 30.4%
- HTML 7.4%
- CSS 3.8%
- Python 0.8%
- Other 1.4%
| .gitea/workflows | ||
| backend/api | ||
| client | ||
| deploy | ||
| design | ||
| docs | ||
| readme-assets | ||
| scripts | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| README.md | ||
DentaFlow 齿程牙科协同系统
面向两家营业网点的牙科诊所协同系统。当前仓库以架构、需求拆分、实施协作说明和阶段验收标准为主,后续实现时按客户端、小程序、后端 API、独立服务分别推进。
项目定位
DentaFlow 采用“中心业务 API + 多端入口 + 独立存储节点 + 独立 Provider Adapter 服务”的架构。
核心设计原则:
- 两个网点平级管理,员工登录后以“当前网点”作为权限和业务数据过滤边界。
- 患者档案全局共享,预约、就诊、收费、耗材、牙椅、文件等业务行为按网点归属。
- 叫号和牙椅状态既能在桌面客户端工作台内显示,也保留独立 Display Client API 供后续大屏扩展。
- 分院 / 网点界面和报表支持当前网点、授权网点和可选择合并院所视图。
- 删除操作默认软删除,已删除条目红色标记,管理员可按权限恢复。
- 管理员可查看审计、在线员工状态和员工历史操作时间线。
- 文件二进制由独立 Docker 存储节点保存,Core API 负责权限判断、上传下载中转、审计和元数据管理。
- 支付、短信、邮件、预览、外部厂家工作流、设备采集等厂家对接能力通过独立 Provider Adapter 服务扩展。
- 后台可管理启用、停用、删除存储池、支付接口、通信池、预览 Provider、外部工作流和适配服务。
- 任何阶段测试案例不通过或验收标准不达标,不进入下一阶段。
负责人快速阅读
如果你只是要把项目派发给不同 agent 实施,建议按这个顺序阅读:
- 本 README: 先看三张全局图,确认整体边界。
- docs/agent-guide/how-to-run-agents.md: 复制每阶段话术给 agent。
- docs/progress/progress.md: 每个功能完成和验收后更新状态。
- docs/architecture/gap-review.md: 回归检查哪些点容易遗漏。
- 对应阶段的
docs/quality/stage-gates/*/test-plan.md: 测试不过不进入下一阶段。
项目架构图
这张图用于说明系统的全局部署边界:
- 客户端入口包括员工桌面端、患者小程序 / H5、叫号屏 / 牙椅屏 Display Client 和移动网关。
- 中心业务区包括 Core API、PostgreSQL、Redis、Worker、Provider Adapter Services。
- 网点 A 与网点 B 平级,各自可接入工作站、牙椅设备和本地存储节点。
- 后台统一管理支付、通信、预览、外部工作流、存储池、权限和审计。
- OpenAPI、数据保留、导出审批、威胁建模、真实设备样例库和种子数据作为全局治理门禁。
调用流程图
这张图用于说明核心调用链:
- 员工端 / 小程序请求进入 Core API 后,先完成登录态、当前网点、权限和审计处理。
- 文件上传由 Core API 创建上传会话,并通过 API 中转分片到存储节点,完成 sha256 校验后写入文件元数据。
- 文件下载由 Core API 判断权限后签发短期访问或中转下载,存储节点不直接承担业务鉴权。
- Provider Adapter 独立注册并发送心跳,后台可以启用、停用、删除,Core API 只保存配置、状态和审计。
- Display Client 使用屏幕 token 独立注册和心跳,不复用员工 token。
- 新接口必须通过 OpenAPI 契约、权限、审计、软删除和数据治理检查。
业务流程图
这张图用于说明诊所主业务闭环:
- 患者建档后可在任意网点预约,就诊业务按实际当前网点生效。
- 到院签到后进入排队 / 叫号,再进入牙椅就诊。
- 治疗过程中产生治疗方案、病历记录、影像、口内照、口扫、采集标记和文件预览。
- 收费默认支持现金支付,后续支付方式通过独立支付 Provider 接入。
- 厂家 / 技工所流转支持受控文件包,也支持外部 case 引用。
- 复诊提醒通过通信池发送,报表 / 日结按网点聚合并保留权限审计。
- 患者详情页作为个人信息大类入口,聚合预约、排队、病例、影像、口扫、收费、复诊和审计摘要。
- 文件回收、数据导出、合并院所报表和管理员恢复都必须按权限和审计串联。
目录入口
| 路径 | 用途 |
|---|---|
docs/system-architecture.md |
总体架构设计 |
docs/architecture/recommendations.md |
架构建议和治理补充 |
docs/architecture/common-api-surfaces.md |
公共 API / Provider 化能力清单 |
docs/backend/shared/openapi-contract.md |
OpenAPI 契约、前后端类型生成和破坏性变更控制 |
docs/backend/shared/clinic-scope-permissions.md |
网点范围、分院界面和合并视图权限 |
docs/backend/shared/audit-session.md |
审计、在线会话和员工操作追踪 |
docs/backend/shared/soft-delete-restore.md |
软删除、红色标记和恢复 |
docs/backend/api/modules/05-treatment-record/treatment-workflow.md |
流程节点排期、即时结清、逾期随访和改期闭环 |
docs/backend/api/modules/07-finance/billing-and-pricing.md |
价目表、耗材计费、优惠和节点结清组装 |
docs/quality/device-sample-library.md |
真实设备样例库规范,用于影像、口扫和厂家包验收 |
docs/security/threat-model.md |
威胁建模基线 |
docs/security/compliance-baseline.md |
等保 / 个保法 / 数据出境 / 病历年限 / 处方麻精上线门禁 |
docs/data/retention-policy.md |
数据保留年限、归档和文件回收边界 |
docs/data/export-approval.md |
数据导出审批、水印、短链和审计 |
docs/data/seed-demo-data.md |
种子数据与演示数据规范 |
docs/agent-guide/how-to-run-agents.md |
每阶段如何安排 Agent 工作的话术和会话建议 |
docs/project/notes-handbook.md |
全局注意手册: 待确认事项、关键决定和实现防漏点(含等保定级) |
docs/progress/progress.md |
实施进度表,完成和验收后持续标注 |
docs/quality/README.md |
阶段测试门禁总说明 |
docs/backend/README.md |
后端拆分入口 |
docs/client/README.md |
员工客户端需求入口 |
docs/mini-program/README.md |
患者小程序需求入口 |
readme-assets/ |
本 README 绑定的全局说明图片 |
一键部署与客户端下载
部署后服务器自带一个固定网址的「客户端下载页」,用户访问网址直接下载安装包,免去手工拷贝:
- 生成安装包:在仓库根运行
scripts/publish-client.ps1,构建客户端并放入deploy/download-site/DentalFlow-Setup.exe(固定文件名)。 - 启动栈:
docker compose -f backend/api/docker-compose.yml up -d(含client-download服务,nginx 只读托管deploy/download-site/)。 - 下载客户端:浏览器访问
http://<host>:<CLIENT_DOWNLOAD_PORT>/(默认端口 8090)下载。
下载端口与其余服务端口一样由单一来源 deploy/config/app.config.json 驱动,可用 deploy/webtool Web 部署工具(浏览器配置 + 一键部署)修改后生成 deploy/config/deploy.env。详见 deploy/download-site/README.md。
后端实施边界
后端初期建议保持 Core API 为模块化单体,降低两网点 MVP 的部署复杂度。以下能力作为独立服务运行:
storage-node: 文件存储节点,负责落盘、校验、读取、删除和心跳。worker: 异步任务、定时任务、文件后处理、通知发送。mobile-gateway: 移动端或员工移动入口网关。provider-adapter: 支付、通信、预览、外部工作流、设备采集等厂家适配服务。
实施代码目录不使用 01、02 这类序号前缀,使用 auth、patient、appointment、mediafile、paymentprovider 等语义化目录。
阶段门禁
每个阶段必须满足:
- 功能点完成并在
docs/progress/progress.md标注状态。 - 对应测试计划全部通过。
- 权限、审计、数据迁移、隐私和发布影响已评审。
- 验收标准不达标时,继续修改当前阶段,不进入下一阶段。
主要阶段测试入口:
docs/quality/stage-gates/foundation/test-plan.mddocs/quality/stage-gates/identity-access/test-plan.mddocs/quality/stage-gates/clinic-patient/test-plan.mddocs/quality/stage-gates/appointment-flow/test-plan.mddocs/quality/stage-gates/treatment-files-finance/test-plan.mddocs/quality/stage-gates/operations-public/test-plan.mddocs/quality/stage-gates/reporting-production/test-plan.md
当前重点能力
- 文件上传、下载、删除和存储节点替换。
- X 光、CBCT、口内照、口扫、CAD、厂家私有包的统一文件分类。
- 设备不支持上传时的手工采集标记。
- 3D / DICOM / 厂家 Viewer 的预览 Provider 化。
- 支付 Provider 化,默认现金支付,外部支付通过独立适配服务接入。
- 邮件池、短信 / 电话池、业务路由、微软 Graph / Exchange OAuth 等通信管理。
- 厂家 / 技工所文件流转与外部 case 引用。
- 独立叫号屏 / 牙椅屏注册、心跳、后台在线状态、启停删除和脱敏展示。
- 网点范围选择、合并院所报表、跨网点审计。
- 管理员审计、在线会话、员工操作时间线。
- 全业务软删除和管理员恢复。
- 文件回收策略: 管理员可筛选大文件,按患者聚合标记回收,等待期内撤销,到期清理。
- 牙周图友好提示、快捷标注、修订和打印预览。
- 治疗流程节点排期: 当天 / 医生指定日期 / 等厂家制作回厂后再约三种时间类型,节点即时结清,到期前按通信池可用渠道提醒患者,逾期生成前台随访代办并可电话或小程序改期。
- 计费: 价目表(服务收费项 + 网点价)、耗材按耗材库售价计费的用量单、节点默认耗材、优惠折扣,节点即时结清在同一事务内扣库存并收款;不做会员 / 套餐 / 储值 / 挂账 / 预收。
- 患者档案合并、预约改约与爽约率、统一分页与并发乐观锁契约。
- 合规基线: 等保定级、个人信息保护法告知同意与未成年监护同意、数据出境评估、病历法定年限、处方与麻精药品台账纳入上线门禁。
- Provider Adapter 注册、心跳、启停、删除、密钥轮换和审计。
- OpenAPI 契约生成、接口变更门禁和前后端类型同步。
- 真实设备样例库驱动文件上传、预览、回收和外发验收。
- 数据保留年限、导出审批、水印、短链下载和威胁建模纳入上线门禁。
目标架构 — 平台再架构(2026-06,设计中)
本节是正在推进的目标态(非当前实现),用于评审。已确认基线见各阶段说明。 核心变化:客户端只连 agent(不直连中心)、agent 下发 UI、部署工具拆分 + 全系统/单节点、 中心 active-active 集群 + 各层切换方案、dashboard 不挂单点。
拓扑图(目标态)
flowchart TB
Static["静态资源服务器"]
C["多客户端(薄壳)"]
subgraph AG["地区 agent"]
A1["agent A"]
A2["agent B"]
end
subgraph CEN["中心节点集群 main-service"]
M1["实例1"]
M2["实例2"]
M3["实例3"]
end
subgraph PG["PostgreSQL 集群 Patroni"]
HAP["HAProxy 写端口"]
L[("Leader")]
R[("Replica")]
end
subgraph ST["文件上传集群 MinIO"]
S1["节点1"]
S2["节点2"]
end
TOOL["服务部署工具 / dashboard"]
C -->|登录与业务| A1
C --> A2
Static -.同步UI.-> A1
Static -.-> A2
C -.下载安装包.-> Static
A1 -->|多中心地址+健康探测 故障转移| M1
A2 --> M2
M1 -->|多HAProxy DATABASE_URL read-write| HAP
HAP --> L
L <-->|流复制| R
C -.E2E直传.-> S1
M3 -.选点与状态.-> S2
S1 -.心跳.-> M2
TOOL -->|多端点失败转移 超管| M1
图例 — 各组件
- 多客户端(薄壳):只内嵌失败页;业务 UI 全部从所连 agent 加载;运行时可配 agent 地址(localStorage 覆盖 /
dentalflow://deep-link)。 - 地区 agent(每网点一个,一身二职):① 反代鉴权——把客户端请求注入节点鉴权头、透明反代到中心;② UI 下发——从静态资源服务器拉取并缓存业务 UI 包对外提供。配多中心地址 + 健康探测,中心实例挂时自动切到活的。
- 静态资源服务器(可冗余):存业务 UI 包(带版本 + SHA256 校验)与客户端安装包;变更经定时拉取 / webhook 通知 agent 同步。
- 中心节点集群 main-service(active-active 对等):实例间无真主从,都连同一 HA 库、共享同一份 ES256 签名私钥(P0 已落地);每实例都对接 agent / 服务部署工具 / dashboard;自注册并心跳到
control_plane_instances。 - PostgreSQL 集群(Patroni 真主从):etcd 选主,leader 挂自动选新,HAProxy 写端口跟随;中心经多 HAProxy 的
DATABASE_URL+target_session_attrs=read-write自动连 leader、切主后自动重连。 - 文件上传集群 storage/MinIO(池化):节点自注册入池,中心选点(最少占用),离线节点 503 绕过;客户端与节点 E2E 直传,文件不经中心。
- 服务部署工具 / dashboard(带外,同一工具两模式):超管密码 + TOTP 接入;多端点失败转移连任一活中心实例;模式 = 部署完整服务 / 增加单节点 + 控制管理(dashboard 不挂单点)。
图例 — 关键连线
- 客户端 → agent:登录与业务请求(实线);客户端 ⇢ 静态资源:下载安装包(虚线)。
- 静态资源 ⇢ agent:定时拉取 / webhook 同步 UI(虚线)。
- agent → 中心:多中心地址 + 健康探测、故障转移(实线)。
- 中心 → PG HAProxy:多 HAProxy
DATABASE_URL、read-write(实线);Leader ⇄ Replica:流复制。 - 中心 ⇢ 存储:选点 / 状态;客户端 ⇢ 存储:E2E 直传;各节点 ⇢ 中心:心跳上报;中心 ⇢ PG:状态写 HA 库(均虚线)。
- 工具 → 中心:多端点失败转移、超管认证。
- 接入认证:agent = 6 位确认码;服务节点 / dashboard = 超管密码 + TOTP → 中心自动下发密钥。部署顺序:文件上传 → postgres → 中心 → agent。
部署工具与接入认证
- 拆两个工具包(本地代码复用、打包两份):① 服务部署工具(文件上传/postgres/中心 + 控制/迁移,含 dashboard 模式)② 网点 agent 部署工具。
- 服务部署工具首页二选一:部署完整服务(文件上传≥1 + postgres≥1 + 中心≥1,按有序流程)/ 增加单节点(+1 文件上传 / +1 postgres / +1 中心)。增加单节点先填 中心地址 + 超管密码 + TOTP,中心校验后自动下发授权/密钥(免人工码)。
- 中心对接面 = agent(6 位确认码)+ 服务部署工具(超管)+ dashboard(超管);后两者密钥经超管登录自动下发。
- 部署顺序:文件上传 → postgres → 中心 → agent(storage 容器可先起、入池 enroll 待中心起后完成)。
- 一台 IP 主机可部署多个资源(同机多实例端口须各异);文件上传/DB 可浏览选服务器路径做卷映射。
集群管理 / 切换方案
A. 中心节点集群(应用层)— active-active,"切换"= 流量调度,非选主
| 操作 | 做法 |
|---|---|
| 加节点 | 服务工具「增加单节点(中心)」→ 超管+TOTP → 中心自动下发密钥 → 新实例连同一 HA 库 + 拿同一份 ES256 签名私钥 → 自注册心跳 |
| 节点掉线接管 | agent/工具配中心地址列表+健康探测,失联自动切活实例;掉的实例心跳超时→dashboard 标 offline(免 keepalived/VIP) |
| 下线/排空 drain | dashboard 标 draining → 从对外地址列表剔除 → 等在途请求完 → 停容器 |
| 灰度升级 | 部署新版实例 → 小流量(金丝雀)→ 看健康/错误率 → 全量切新版 → drain 旧版 → 逐台滚动 |
⚠️ active-active 共享库,灰度时新旧版本同时连库 → DB 迁移必须扩展式(expand-contract)向后兼容。
B. PostgreSQL 集群 — 真主从(Patroni)
| 操作 | 做法 |
|---|---|
| 自动故障切换 | leader 挂 → Patroni+etcd 自动选新 → HAProxy 跟随 → 中心连接池自动重连(无人工) |
| 手动 switchover | 计划内(升级主机):dashboard 调 Patroni REST /switchover 指定新 leader,平滑切 |
| 加节点 | 服务工具「增加单节点(postgres)」→ 新 Patroni 节点从 leader 克隆 → 成为新 replica |
| 换主/摘节点 | 加新 replica → 同步追上 → switchover 到它 → 摘旧节点 |
C. 文件上传集群 — 池化,无主从
| 操作 | 做法 |
|---|---|
| 加节点 | 服务工具「增加单节点(文件上传)」→ 超管授权入池 → 立即参与负载 |
| 节点掉线 | 心跳超时→标 offline→选点绕过(仅全员离线才上传 503) |
| 迁移/替换 | 复用 storage-node-replacements:新节点入池 → 对象再分布 → 旧节点清空 → 摘除 |
无痛迁移总流程(贯穿三层)
flowchart LR
S1["① 服务工具 增加单节点<br/>新机部署同类节点"] --> S2["② dashboard 选 源→目标<br/>发起迁移"]
S2 --> S3["③ 后台迁移<br/>中心:drain 切流量<br/>DB:加 replica + switchover<br/>存储:re-replicate"]
S3 --> S4["④ 完成 → 邮件通知管理员"]
S4 --> S5["⑤ 观察期正常 → 通知可关旧节点<br/>管理员确认 → drain + 停"]
适配"原本中心 + DB + 存储挤一台 → 逐个迁出拆分"的场景。SMTP:正式部署填主机/账号/密码 + 测连;本地测试用 Mailpit。
- 两网点种子数据和演示数据用于联调、培训和验收复现。


