270 lines
24 KiB
Markdown
270 lines
24 KiB
Markdown
# clinical-web
|
||
|
||
医签通医护端 Web 应用,面向医生、护士、科室人员和系统管理人员。
|
||
|
||
## 使用场景
|
||
|
||
- 电脑浏览器;
|
||
- 电子病历 iframe 嵌入;
|
||
- 护士站电脑;
|
||
- 后续可适配医院平板;
|
||
- 电脑连接外接签字板。
|
||
|
||
签字板是医护端的一种硬件签署渠道,不是独立的移动端应用。
|
||
|
||
## 核心职责
|
||
|
||
### 医生端
|
||
|
||
- 从电子病历中发起知情同意;
|
||
- 自动带入患者、就诊和医嘱信息;
|
||
- 选择文书模板;
|
||
- 确认已完成病情解释;
|
||
- 发送手机签署或打开现场签署。
|
||
|
||
### 护士/现场端
|
||
|
||
- 调出待签署任务;
|
||
- 协助患者使用签字板;
|
||
- 查看签署结果和异常状态。
|
||
|
||
护士可以协助操作,但不应被系统误记为病情解释人员。
|
||
|
||
### 管理端
|
||
|
||
- 文书模板和版本管理;
|
||
- 用户、角色和文档权限;
|
||
- 签署记录查询;
|
||
- 统计和报表;
|
||
- 设备及系统配置。
|
||
|
||
## 重点业务流程
|
||
|
||
```text
|
||
电子病历中选择患者
|
||
→ 选择就诊/医嘱/项目
|
||
→ 选择或生成文书
|
||
→ 医生完成解释并发起
|
||
→ 手机、二维码或签字板签署
|
||
→ 查看状态
|
||
→ 回传电子病历
|
||
```
|
||
|
||
## 需要支持的异常
|
||
|
||
- 患者拒绝签署;
|
||
- 患者或家属无法联系;
|
||
- 实际陪同人和登记手机号不一致;
|
||
- 签署链接过期;
|
||
- 文书需要动态追加;
|
||
- 急诊抢救紧急例外;
|
||
- 签署成功但回传失败。
|
||
|
||
## 当前技术栈
|
||
|
||
```text
|
||
Vue 3
|
||
TypeScript
|
||
Vite
|
||
Vue Router
|
||
Pinia
|
||
Element Plus
|
||
Axios
|
||
```
|
||
|
||
TanStack Vue Query、PDF 预览、报表图表、自动化测试和签字板适配器暂不接入,等真实接口和业务流程稳定后再按需要增加。
|
||
|
||
签字板调用应通过独立的 `signature-adapter` 或本地桥接服务封装,业务页面不直接绑定具体厂商 SDK。
|
||
|
||
## 非目标
|
||
|
||
- 不在前端自行判断最终签署法律效力;
|
||
- 不在医护端直接修改已经签署的正式文书;
|
||
- 不把患者完整病历发送到患者手机端。
|
||
|
||
## 当前状态
|
||
|
||
已完成 Vite 基础初始化、路由、Pinia、原型主题 CSS、登录页、首页、签署工作台、签署记录查询、文档库管理页面和「报表分析」四个菜单(签署总览 / 签署量分析 / 签署时效分析 / 患者结构分析)。角色权限与系统设置中的菜单设置已接入 MEDISIGN RBAC 接口;导航、路由和页面操作按授权资源树控制,角色数据范围在角色配置中维护,员工页面只负责绑定角色。组织架构页按机构→院区→科室分组展示员工列表,新增院区默认归属“新华院区”,支持节点筛选、员工维护和组织节点维护。系统参数卡片仍保留 Mock,真实签字板/线上签名回调和打印服务仍需设备或后端能力。
|
||
|
||
文档库管理的真实模式已打通「模板 → 版本 → 正文」三段:
|
||
|
||
- 列表读 `GET /api/v1/templates`(自动翻完所有页),再把扁平的模板列表组织成页面需要的「科室 → 分类 → 文书」树;
|
||
- 正文不在列表接口里(`TemplateResponseDto` 只给 `templateContentSha256`,不给正文),预览、编辑、发起签署前都要再取一次版本详情 `GET /api/v1/templates/{id}/versions/{versionId}` 拿 `contentHtml`。取不到正文时页面如实报错,不展示空壳模板;
|
||
- 新建走「建模板 + 建首版」两步,编辑走「建新版本 + 更新模板」;版本号由后端按并发安全序号生成。列表和详情分别使用最新维护版本与当前发布版本指针,审核编辑不会误操作旧发布版,发起签署也不会误用待审核草稿。模板没有 DELETE 接口,页面上的「删除」实际是归档动作(`POST .../versions/{versionId}/archive`),保留历史留痕链。
|
||
|
||
签署工作台的真实模式同样依赖正文:`GET /api/v1/templates/available-versions` 只返回 `contentSha256`,签署端用这个哈希当缓存键去换回正文快照(同一哈希命中同一份正文,版本更新后哈希变化即自动失效),避免版本更新后仍按旧正文签署。取不到正文时任务详情如实提示并给出占位版式,不退化成「看起来像真文书」的假纸样。
|
||
|
||
自测与演示:显式开启 `VITE_MOCK_DOCUMENTS=true` 或 `VITE_MOCK_SIGNING=true` 时,文档库和签署任务的演示数据会镜像到 localStorage(见 `utils/mock-storage.ts`),刷新页面后仍可继续,不必每次重建文书、重发签署;文档库页头的「重置演示数据」可清空这些本地数据回到初始状态(该按钮只在演示模式下出现)。文档库缺省使用真实接口,签署工作台与签署记录查询暂时缺省使用演示数据;持久化只针对演示数据,不涉及登录态与真实患者信息。本地建议在 `.env.development.local` 里显式写出开关,不要依赖缺省值。
|
||
|
||
签署记录查询的演示数据不走 localStorage:它按「距今天数」现场生成(见 `api/workbench/records.ts` 的 `MOCK_RECORD_SEEDS`),每次打开都落在今日/近 3 天/近 7 天/近 30 天这些窗口内,演示时筛选条件不会因为数据过期而全部落空。
|
||
|
||
## 当前路由结构
|
||
|
||
```text
|
||
公开页
|
||
└─ /login 登录页
|
||
|
||
ClinicalLayout(实际导航和页面路由由授权菜单资源树提供)
|
||
├─ /dashboard 首页
|
||
├─ /sign/workbench 签署工作台
|
||
├─ /sign/records 签署记录查询
|
||
├─ /system/org 组织架构 / 员工角色绑定
|
||
├─ /system/role 角色权限与数据范围
|
||
├─ /doc/library 文档库管理
|
||
├─ /report/index 报表分析(签署报表与导出任务,走 reports/signing/* 接口)
|
||
├─ /report/sign/overview 报表分析 / 签署总览
|
||
├─ /report/sign/volume 报表分析 / 签署量分析
|
||
├─ /report/sign/timeliness 报表分析 / 签署时效分析
|
||
├─ /report/patient/structure 报表分析 / 患者结构分析
|
||
└─ /system/setting 系统设置 / 菜单设置
|
||
```
|
||
|
||
注意 `/report/index` 与另外四个报表页是**两套菜单、两套后端面**:前者是「系统管理 → 报表分析」下的签署报表与导出任务(真实接口已接入,见 [reports-api.md](./docs/reports-api.md));后者是「报表分析」目录下的四个独立菜单,后端目前没有任何分析聚合接口,因此只有演示数据(`VITE_MOCK_REPORT_ANALYTICS`)。两者的路由与 `componentPath` 都以后端菜单资源树为准,不要照抄原型里的 `MENU_TREE`(原型写的是 `/report/overview` 等,与后端不一致)。
|
||
|
||
布局拆分为 `Menu`、`Header` 和 `Container` 三个公共组件,页面内容由各自的 View 负责。
|
||
|
||
页面目录按业务域组织:`auth` 保留登录页;工作台页面位于 `views/workbench`;管理页面位于 `views/management`。每个具体页面目录都有 `index.vue` 入口和 `components` 目录,用于继续拆分当前页面组件。
|
||
|
||
跨页面复用的业务组件和 composable 不放在具体 View 目录中:
|
||
|
||
- `components/signing/NewSigningTaskDialog.vue`:新增签署任务公共弹窗,供签署工作台和文档库管理复用;
|
||
- `components/signing/SigningDocumentInteractive.vue`:签署态文书的交互化渲染(填写项回显、签名图回填、勾选收集),签署工作台详情与签署记录详情共用;
|
||
- `components/signing/SigningDocumentPreview.vue`:正文取不到时的占位版式,不冒充真文书;
|
||
- `components/signing/TaskAuditTimeline.vue`:操作留痕时间线,签署工作台详情与签署记录详情共用;
|
||
- `composables/useSigningTaskForm.ts`:封装患者定位、就诊选择、模板选择、签署方式、校验和任务提交状态;
|
||
- `utils/signing-document.ts`:把文书定稿 HTML 变换为签署态 HTML 的渲染管线(占位符填充、签名域、勾选与行内选项识别),签署工作台的任务详情和文档库「签署预览」共用同一份实现;
|
||
- `utils/signing-editor-marks.ts`:编辑区里把占位符与勾选框渲染成带类型角标的胶囊,只改渲染不改数据(见下「文书编写约定」)。
|
||
|
||
## 文书编写约定
|
||
|
||
科室在文档库的 Word 编辑器中维护文书,签署时需要交互化的内容按下面的写法即可,系统在签署和「签署预览」时自动转换:
|
||
|
||
- 占位符分两类,写法都是 `{…}`:
|
||
- **系统预填项**:`{患者姓名}`、`{性别}`、`{年龄}`、`{就诊号}`、`{签署日期}`、`{患者签名}`、`{医师签名}` 等,字段键与取值来源固定,由签署任务的患者与就诊快照填充,目录见 `utils/signing-fields.ts` 的 `SIGNING_FIELD_PRESETS`;
|
||
- **通用文本项**:现场手填的输入框,默认写 `{文本框}`,签署时渲染成一个空文本框。**每个占位符各自是一个填写项**,字段键按出现位置编号(`custom:名称`、第 2 个起是 `custom:名称#2`……),所以同一份文书里放几个文本框就是几份取值,不需要为了区分而改名字;名称只决定文书里显示的文字,直接把正文里的「文本框」改成「与患者关系」「受托人姓名」即可(仅为可读性,不影响取值归属)。
|
||
- 只有上面那类系统预填项按字段键去重、同名共用一份取值——页眉的患者姓名、每页的签名位反复出现,取值本来就该是同一个。
|
||
- 勾选表:做成表格,第一行表头写「勾选」,另设一列写「项目」作为勾选条目名,签署时「勾选」列每个单元格变成复选框;
|
||
- 行内选项:正文里直接写方框符号,如 `□否 □是`、`□同意 □不同意`。同一段落或同一单元格内出现两个及以上方框时按二选一(互斥单选)处理,只有一个方框时保持独立复选框语义。
|
||
|
||
编辑器弹窗顶部提供「插入勾选框」「二选一」按钮,以及插入通用文本项的「文本框」按钮(虚线圈出的那一个,点一下插入 `{文本框}`,把「文本框」三个字改成实际名称即可)。光标停在表格单元格内时插入内容会落进该单元格,不需要科室自己找符号面板。导入(.docx / 粘贴)阶段只做格式转换,不做勾选识别;识别统一在签署渲染时进行。
|
||
|
||
识别规则集中在 `utils/signing-document.ts`,调整后签署端与「签署预览」会同步生效。
|
||
|
||
### 编辑区与签署态的呈现差异
|
||
|
||
**编辑区**(`utils/signing-editor-marks.ts`)把 `{…}` 与 `□` 渲染成带类型角标的胶囊,让科室一眼分出「正文」和「待签署的内容」。这是**只读投影**:靠 wangEditor 的 `decorate` 把文本切成叶子再挂样式,`editor.getHtml()` 输出一字未变,保存与签署链路的口径不受影响。
|
||
|
||
**签署态**(`utils/signing-document.ts`)把占位符就地换成可交互控件。其中**签名位**(`kind=signature`)在任务处于可签署状态时渲染成「✍ 点击签名」的可点击入口:点一下就打开签字板,签完的图就地回显到该签名位,只回填这一个字段,**不会结束签署任务**——任务级的「签署完成」仍由主签名位(`{患者签名}`)通过「手写板签署 / 线上签署」触发。
|
||
|
||
签名位之间互不覆盖:主签名位存在任务的 `signatureDataUrl`(提交时由接口固定落到 `signature` 字段),其余签名位(医师签名等)各自存在 `fieldAnswers` 里。
|
||
|
||
签名图只作为渲染结果里的 `<img src>` 存在,**不写进模板正文**:它是 base64 大字符串,进正文会让模板哈希随签名变化、缓存键跟着失效。
|
||
|
||
## API 与类型约定
|
||
|
||
API 模块与页面按业务域对应。工作台页面使用 `api/workbench` 下的页面文件,管理页面使用 `api/management` 下的直接文件:
|
||
|
||
- `api/workbench/home.ts`
|
||
- `api/workbench/signing.ts`
|
||
- `api/workbench/artifacts.ts`
|
||
- `api/workbench/deliveries.ts`
|
||
- `api/management/documents.ts`
|
||
- `api/management/reports.ts`
|
||
- `api/management/users.ts`
|
||
- `api/management/roles.ts`
|
||
- `api/management/permissions.ts`
|
||
- `api/management/organization.ts`
|
||
- `api/management/document-permissions.ts`
|
||
- `api/management/audit.ts`
|
||
- `api/management/settings.ts`
|
||
|
||
所有接口统一使用 `utils/request.ts` 导出的单例请求实例。登录接口已接入 MEDISIGN 后端:
|
||
|
||
- `POST /api/v1/auth/login`:账号密码登录;
|
||
- `GET /api/v1/auth/captcha`:获取按需启用的图形验证码;
|
||
- `GET /api/v1/auth/me`:查询当前用户;
|
||
- `POST /api/v1/auth/password/change`:修改当前用户密码;首次登录必须完成修改,成功后旧 Token 失效并重新登录;
|
||
- `POST /api/v1/auth/logout`:注销当前会话;
|
||
- 后续请求自动携带 `X-Token` 请求头。
|
||
|
||
路由、侧栏和页面操作均按后端授权资源控制;窗口重新聚焦、或页面重新可见(`visibilitychange`)时刷新当前授权,角色、菜单资源或员工角色绑定变更后也会主动刷新。**这里不再有周期性轮询**:早期版本用 15 秒定时器刷新,实测一个闲置可见标签页会稳定产生约 240 次/小时请求(`/v1/authorization/me`),而权限变更本身是低频的管理员操作,因此改为只在「用户重新回到页面」时收敛。用户长时间停留且不切窗口时,切路由仍会经路由守卫的 `ensureCurrentUser()`(10 秒 TTL + 并发去重)顺带收敛。角色权限从菜单资源树配置目录、菜单和按钮,员工角色绑定通过独立用户角色接口保存。菜单资源维护使用真实接口;系统参数卡片仍是演示数据,最终授权始终以后端校验为准。
|
||
|
||
按钮级权限统一用全局指令 `v-permission` 声明(实现见 `src/directives/permission.ts`):`v-permission="'doc:template:edit'"` 无权限时隐藏,`v-permission.disable="'doc:template:edit'"` 无权限时置灰;权限码必须与菜单资源树里 BUTTON 节点的 `code` 完全一致,前端不再维护别名映射。指令只负责体验,按钮背后的处理函数仍要用同一套权限码自行校验。文档库管理(`views/management/documents`)是本轮先落地的页面,其余页面沿用旧的 `hasPermission` 写法,待逐个统计按钮后迁移。
|
||
|
||
签署工作台已接入的真实接口包括:
|
||
|
||
- `GET /api/v1/patients`、`GET /api/v1/patients/{id}`:患者定位;
|
||
- `GET /api/v1/patients/{id}/visits`、`GET /api/v1/visits`:就诊关联;
|
||
- `GET /api/v1/templates/available-versions`:可发起模板版本;
|
||
- `GET /api/v1/sign-tasks`、`GET /api/v1/sign-tasks/{id}`:任务列表和详情;
|
||
- `POST /api/v1/sign-tasks`、`POST /api/v1/sign-tasks/{id}/prepare-send`:创建任务和准备投递;
|
||
- `POST /api/v1/sign-tasks/{id}/void`、`/resend`、`/reopen`:作废、短信重发和重新开启;
|
||
- `GET /api/v1/sign-tasks/{id}/events`:操作审计事件。
|
||
|
||
已接入或封装的扩展接口包括:
|
||
|
||
- `GET /api/v1/sign-artifacts/task/{taskId}`、`GET /api/v1/sign-artifacts/task/{taskId}/{artifactId}`:签署文件索引;
|
||
- `GET /api/v1/sign-artifacts/{artifactId}/download`:原始 PDF、签署后 PDF、签名原图下载;
|
||
- `POST /api/v1/sign-deliveries/{taskId}/sms/resend`:短信重发,自动携带幂等键;
|
||
- `GET/POST /api/v1/templates`、`GET /api/v1/templates/{id}`:模板列表、详情;
|
||
- `PUT /api/v1/templates/{id}`:更新模板元数据;
|
||
- `GET/POST /api/v1/templates/{id}/versions`、`GET /api/v1/templates/{id}/versions/{versionId}`:版本列表、创建与版本详情(**正文 `contentHtml` 只在这个详情接口里返回**);
|
||
- `POST /api/v1/templates/{id}/versions/{versionId}/{action}`(submit-review / reject / approve / publish / disable / archive):版本工作流,模板「删除」即走 archive;
|
||
- `GET /api/v1/users`、`POST /api/v1/users`、`GET/PUT /api/v1/users/{id}`:员工列表、资料创建和资料更新;
|
||
- `GET /api/v1/users/{id}/roles`、`PUT /api/v1/users/{id}/roles`:单独查询和替换员工角色;用户资料接口不再同时保存角色或个人数据范围;
|
||
- `POST /api/v1/users/{id}/password/reset`、`POST /api/v1/users/import/preview`、`POST /api/v1/users/import/commit`、`GET /api/v1/users/import/jobs/{jobId}`:管理员重置密码和用户导入流程;
|
||
- `GET /api/v1/roles`、`GET /api/v1/roles/assignable`、`POST /api/v1/roles`、`PUT /api/v1/roles/{id}`、`PUT /api/v1/roles/{id}/status`、`DELETE /api/v1/roles/{id}`:角色列表与角色维护;
|
||
- `GET /api/v1/roles/permission-tree`、`GET/PUT /api/v1/roles/{id}/permissions`、`GET/PUT /api/v1/roles/{id}/data-scope`:基于菜单资源树配置角色权限和数据范围;
|
||
- `GET/POST /api/v1/menu-resources`、`PUT /api/v1/menu-resources/{id}`、`PUT /api/v1/menu-resources/{id}/status`、`PUT /api/v1/menu-resources/{id}/sort`、`DELETE /api/v1/menu-resources/{id}`:菜单资源树维护;
|
||
- `GET /api/v1/authorization/me`:当前用户权限、数据范围和可访问导航;
|
||
- `GET /api/v1/templates/permission-config`:按权限配置范围分页查询模板;
|
||
- `GET /api/v1/templates/permissions/matrix`、`POST /api/v1/templates/permissions/batch`:跨模板权限矩阵查询和批量新增/撤销;
|
||
- `GET/POST/DELETE /api/v1/templates/{id}/permissions`:单模板权限兼容接口,其中前端使用 GET 补充用户继承预览;
|
||
- `GET /api/v1/audit-logs`:全局审计日志查询 API。
|
||
|
||
用户与权限页面的接口核验结果、当前缺口和后端接口建议见 [`docs/users-permissions-api.md`](./docs/users-permissions-api.md)。
|
||
|
||
文档权限页面的新接口契约、继承规则、批量保存行为和联调验收标准见 [`docs/document-permissions-api.md`](./docs/document-permissions-api.md)。
|
||
|
||
报表页真实模式已接入签署报表的 options、overview、tasks 和异步 export-jobs 接口,支持权限范围内的动态筛选、服务端分页、趋势/科室聚合和完整结果导出;Mock 模式仍可用于演示。接口矩阵、时间口径和联调验收见 [reports-api.md](./docs/reports-api.md),后端联调要求见 [reports-backend-requirements.md](./docs/reports-backend-requirements.md)。首页真实模式已接入 workbench overview。
|
||
|
||
首页真实模式已接入 GET /api/v1/workbench/overview;接口口径、字段映射和验收标准见 [docs/workbench-home-api.md](./docs/workbench-home-api.md)。
|
||
|
||
## 签署记录查询
|
||
|
||
`views/workbench/records` 是「工作台 → 签署记录查询」(`/sign/records`,菜单资源 `sign/record/index`)的实现:工作台只保留当天的签署操作,历史记录的检索、核对与导出统一放在这里。页面只读——已签署的正式文书不可直接修改,需要追加内容时回签署工作台新建签署任务。
|
||
|
||
**接口现状与边界**(后端还没有「按条件检索历史签署记录」的专用接口):
|
||
|
||
- 真实模式复用 `GET /api/v1/sign-tasks` 的筛选能力(见 `api/workbench/records.ts` 的 `toTaskQuery`),映射口径与签署工作台保持一致,不另造一套;
|
||
- 因此**「文档类别」在真实模式下不可筛**,筛选条会禁用该字段并给出原因(title 提示),而不是让它静默失效——一个「选了不生效」的筛选项比没有这个筛选项更误导人;
|
||
- 类别字段签署任务接口不返回,列表与详情都按空值展示,只有演示数据带类别;
|
||
- 导出是前端按当前筛选条件取全量后生成 CSV(UTF-8 带 BOM、CRLF 换行,Excel 直接打开不乱码)。**后端提供导出任务后应改为服务端导出**:导出范围与导出人都要写进审计日志,这一步在浏览器里做不到;
|
||
- 详情弹窗复用签署工作台的文书渲染与留痕组件(`components/signing/`),签署后 PDF 优先取服务端产物(`sign-artifacts` 里的 `SIGNED_PDF`);演示环境没有文件服务时,按页面上当前渲染结果现场生成一份。
|
||
|
||
演示数据缺省开启(`VITE_MOCK_SIGN_RECORDS`),且与签署工作台**分开开关**:两者共用一个开关会导致「关掉工作台的演示数据」把记录页一起带进空态。
|
||
|
||
## 报表分析(签署总览 / 签署量分析 / 签署时效分析 / 患者结构分析)
|
||
|
||
四个菜单共用一套数据源与筛选条件:
|
||
|
||
- `api/workbench/report-analytics.ts`:数据集。**后端没有任何分析聚合接口**,真实模式返回 `{ tasks: [], available: false }` 而不抛错,页面据此显示「后端尚未提供报表分析接口」的说明,不渲染一张全 0 的假报表。
|
||
- `views/reports/aggregate.ts`:全部聚合逻辑,纯函数(不依赖 DOM 与 Vue),可用 Node 直跑断言。
|
||
- `views/reports/filter-store.ts`:**四个菜单共用一份筛选条件**(模块级 `reactive`)。原型里它们是同一筛选条下的四个页签,各存一份会导致切页时筛选被重置、四个页面的数字看起来互相矛盾。
|
||
- `views/reports/components/ReportPageShell.vue`:标题 + 筛选条 + 数据可用性闸门 + 导出弹窗,四个页面共用;页面只填自己的图表内容。
|
||
- 图表是手写内联 SVG(`ReportBarChart` / `ReportBarList`),不引图表库:只需要柱状图与横向条形榜两种形态,引库要多几百 KB 且读不到主题 CSS 变量。渐变 id 用 `useId()` 取每实例唯一值。
|
||
|
||
**演示数据的两条硬约束**:① 用固定种子的 PRNG(mulberry32),不用 `Math.random` —— 否则每次刷新数字都在跳,截图对不上、断言写不了;② 时间锚定「距今天数」,不写死日期 —— 写死之后过几天再打开,近 7 天 / 近 14 天 / 本月全是空的,看起来像筛选坏了。
|
||
|
||
**边界**:① 时效指标只统计**已签署**任务(未完成任务不是「签得快」而是「还没签完」,计入会稀释均值),样本为 0 时显示「—」而不是 0;② 患者结构统计的是**人次**而非人数,同一患者多次签署会重复计数,页面上已写明;③ 导出是前端按条件生成 CSV(UTF-8 带 BOM、CRLF),与签署记录查询共用 `utils/csv-export.ts`。**后端提供导出任务后应改为服务端导出**:导出范围与导出人必须进审计日志,浏览器里做不到。真实接入聚合接口时,后端应按页面出四个聚合接口,**不要**照搬现在的形状把全量任务明细拉到浏览器里算。
|
||
|
||
演示数据缺省开启(`VITE_MOCK_REPORT_ANALYTICS`,与 `/report/index` 的 `VITE_MOCK_REPORTS` 分开)。
|
||
|
||
API 请求和响应类型按业务域放在 `api/workbench/types.ts`、`api/management/types.ts`;页面展示和交互类型放在对应 View 目录的 `types.ts`;全局复用类型放在 `types/common.ts`。页面提交模型会在 API 边界转换为后端 DTO,不向后端发送患者快照、文档名称或明文手机号等页面字段。
|
||
|
||
开发环境默认使用 `/api` 作为同源接口前缀,Vite 会将 `/api` 转发到 `https://ipad.shenynet.com`,因此浏览器不会直接跨域请求后端。代理配置位于 `vite.config.ts`,不改写 `/api/v1/...` 路径。修改代理或环境变量后需要重启 Vite 开发服务。
|
||
|
||
生产环境不会使用 Vite 的开发代理,需要在 Nginx 或其他网关中配置同样的 `/api` 反向代理。Mock 开关按业务模块(对齐菜单)拆分,缺省使用演示数据的只有签署侧(签署工作台 `VITE_MOCK_SIGNING`、签署记录查询 `VITE_MOCK_SIGN_RECORDS`)与「报表分析」目录下的四个菜单(`VITE_MOCK_REPORT_ANALYTICS`,后端没有分析聚合接口),其余模块直接调用真实后端;各开关的环境变量名与缺省值见 `src/utils/mock-flags.ts`,需要临时切换时在本地 `.env.*.local` 里覆盖即可。使用本地开发代理时,`VITE_API_BASE_URL` 应填写 `/api`;如果改为直连后端,则需要后端配置允许当前前端源的 CORS。
|
||
|
||
当前尚未接入的签署能力包括手写板设备桥接、线上签署页面/签名回调和打印服务。签署投递、一次性 Token 消费和真实 PNG 上传 API 已完成封装,但页面不能用 Canvas 演示数据冒充真实签名;需要接入设备适配器或患者 H5 回调后再启用。短信初次发送接口需要完整手机号,而患者查询只返回脱敏手机号,因此真实模式会要求当前操作人员确认完整投递地址;生产环境也可以改为由后端根据患者 ID 解析投递地址。签署工作台缺省即使用演示数据(`VITE_MOCK_SIGNING`),需要走真实投递时把它设为 `false`。
|