# min_App_doctor 转 UniApp 迁移实施文档

## 1. 目标与范围

- 目标：将 `min_App_doctor`（微信原生小程序）迁移为 UniApp（Vue3 + uni-ui/uv-ui 可选）工程，优先保证微信小程序端可运行，再扩展 H5 / App。
- 范围：覆盖当前 `app.json` 已注册的 58 个页面、公共组件、网络层、登录态、IM（TIM）、音视频（TRTC）、处方/录入业务流程。
- 输出目录：`min_App_doctor_uniapp/`。

## 2. 现状盘点（源项目）

- 路由：主包 + 3 个分包（`myConsultRoom`、`entryWrite`、`oneselfCenter`）。
- 依赖：
  - `@vant/weapp`
  - `tim-wx-sdk`
  - `cos-wx-sdk-v5`
  - `weui-miniprogram`
- 核心特征：
  - 大量 `wx.*` 平台 API 调用（登录、存储、路由、权限、网络、系统信息）。
  - `Page/Component/Behavior` 组织方式。
  - 统一请求入口：`config/https.js`（含 session 注入、错误码处理、加解密分支）。
  - IM 逻辑集中在 `utils/message.js`（TIM 登录、收消息、发送业务事件消息）。

## 3. 迁移技术方案

## 3.1 UniApp 技术栈建议

- 框架：`uni-app x` 或 `uni-app`（推荐先用 `uni-app + Vue3 + Vite`）。
- 语言：`Vue3 + <script setup> + TypeScript`（可先 JS 后 TS）。
- 状态：`Pinia`。
- 请求：`uni.request` 二次封装（兼容原 `$http.post` 语义）。
- UI：
  - 原生标签 + 自定义组件优先；
  - 表单复杂处可选 `uv-ui`；
  - 不建议继续强依赖 `@vant/weapp`。
- IM：继续使用腾讯 IM SDK（选择 UniApp/小程序可用版本）。
- 音视频：TRTC 需按 UniApp + 微信小程序能力重新接入（优先保留微信端能力）。

## 3.2 目录重构建议

```text
min_App_doctor_uniapp/
  src/
    App.vue
    main.ts
    pages.json
    manifest.json
    uni.scss
    pages/
      tabBar/
      components/
      myConsultRoom/
      entryWrite/
      oneselfCenter/
    components/
    store/
    api/
      http.ts
      modules/
    utils/
      auth.ts
      message.ts
      common.ts
      crypto/
  package.json
```

## 4. 路由迁移（app.json -> pages.json）

## 4.1 迁移原则

- `app.json.pages` -> `pages.json.pages`。
- `app.json.subPackages` -> `pages.json.subPackages`。
- `tabBar` 原样迁移到 `pages.json.tabBar`。
- 路由跳转统一替换为 `uni.navigateTo / uni.redirectTo / uni.switchTab / uni.reLaunch`。

## 4.2 pages.json 模板（可直接落地）

```json
{
  "pages": [
    { "path": "pages/tabBar/home/home", "style": { "navigationBarTitleText": "工作台" } },
    { "path": "pages/tabBar/login/login", "style": { "navigationBarTitleText": "我的" } },
    { "path": "pages/tabBar/personalcenter/personalcenter", "style": { "navigationBarTitleText": "个人中心" } },
    { "path": "pages/tabBar/messageCenter/messageCenter", "style": { "navigationBarTitleText": "消息" } },
    { "path": "pages/components/searchSelect/searchSelect", "style": {} },
    { "path": "pages/components/mesicalRcordSelect/mesicalRcordSelect", "style": {} },
    { "path": "pages/tabBar/personalcenter/locList/locList", "style": {} },
    { "path": "pages/tabBar/personalcenter/doctorCard/doctorCard", "style": {} },
    { "path": "pages/tabBar/faceLogin/faceLogin", "style": {} },
    { "path": "pages/components/gallery/gallery", "style": {} }
  ],
  "subPackages": [
    {
      "root": "pages/myConsultRoom",
      "pages": [
        { "path": "page/MyLoc/MyLoc", "style": {} },
        { "path": "page/allPatient/allPatient", "style": {} },
        { "path": "page/searchPatient/searchPatient", "style": {} },
        { "path": "page/treatment/treatment", "style": {} },
        { "path": "page/treatment/messageTemplate/messageTemplate", "style": {} },
        { "path": "page/graphic/graphic", "style": {} },
        { "path": "page/graphicDateil/graphicDateil", "style": {} },
        { "path": "page/refusal/refusal", "style": {} },
        { "path": "page/treatmentrecord/treatmentrecord", "style": {} },
        { "path": "page/trtcRoom/trtcRoom", "style": {} },
        { "path": "page/trtc-room/trtc-room", "style": {} },
        { "path": "page/historyTreatment/historyTreatment", "style": {} },
        { "path": "page/InviteDoctor/InviteDoctor", "style": {} }
      ]
    },
    {
      "root": "pages/entryWrite",
      "pages": [
        { "path": "page/Entry/Entry", "style": {} },
        { "path": "page/Entry/diagnostic/diagnostic", "style": {} },
        { "path": "page/Entry/diagnostic/addDiagnostic/addDiagnostic", "style": {} },
        { "path": "page/Entry/diagnostic/addDiagnostic/customDiagnostics/customDiagnostics", "style": {} },
        { "path": "page/Entry/diagnostic/addDiagnostic/historicalDiagnosis/historicalDiagnosis", "style": {} },
        { "path": "page/Entry/diagnostic/addDiagnostic/templateDiagnostic/templateDiagnostic", "style": {} },
        { "path": "page/Entry/prescription/prescription", "style": {} },
        { "path": "page/Entry/prescription/addPrescription/addPrescription", "style": {} },
        { "path": "page/Entry/medicalRecord/medicalRecord", "style": {} },
        { "path": "page/Entry/prescription/addPrescription/customDiagnostics/grass/grassPush/grassPush", "style": {} },
        { "path": "page/Entry/prescription/prescDetail/prescDetail", "style": {} },
        { "path": "page/Entry/prescription/prescAuditDetail/prescAuditDetail", "style": {} },
        { "path": "page/Entry/prescription/handlePrescAudit/handlePrescAudit", "style": {} },
        { "path": "page/Entry/prescription/prescProcess/prescProcess", "style": {} },
        { "path": "page/Entry/prescription/addExamine/addExamine", "style": {} },
        { "path": "page/Entry/prescription/addExamine/completeExamine/completeExamine", "style": {} },
        { "path": "page/Entry/prescription/addInspection/addInspection", "style": {} },
        { "path": "page/Entry/prescription/addInspection/completeInspection/completeInspection", "style": {} }
      ]
    },
    {
      "root": "pages/oneselfCenter",
      "pages": [
        { "path": "page/help/help", "style": {} },
        { "path": "page/history/history", "style": {} },
        { "path": "page/scheduling/scheduling", "style": {} },
        { "path": "page/schedulingHandle/schedulingHandle", "style": {} },
        { "path": "page/schedulingQuery/schedulingQuery", "style": {} },
        { "path": "page/comprehensiveScore/comprehensiveScore", "style": {} },
        { "path": "page/finishAdmRecord/finishAdmRecord", "style": {} },
        { "path": "page/feedback/feedback", "style": {} },
        { "path": "page/feedbackSuc/feedbackSuc", "style": {} },
        { "path": "page/helppdf/helppdf", "style": {} },
        { "path": "page/replyTemplate/replyTemplate", "style": {} },
        { "path": "page/replyTemplateHand/replyTemplateHand", "style": {} },
        { "path": "page/schedulingRange/schedulingRange", "style": {} },
        { "path": "page/notice/notice", "style": {} },
        { "path": "page/addNotice/addNotice", "style": {} },
        { "path": "page/batchScheduling/batchScheduling", "style": {} },
        { "path": "page/batchSchedullingHandle/batchSchedullingHandle", "style": {} }
      ]
    }
  ],
  "tabBar": {
    "color": "#666666",
    "selectedColor": "#1C86EE",
    "borderStyle": "white",
    "backgroundColor": "#fff",
    "list": [
      { "pagePath": "pages/tabBar/home/home", "text": "工作台", "iconPath": "static/images/workbench.png", "selectedIconPath": "static/images/workbenchS.png" },
      { "pagePath": "pages/tabBar/messageCenter/messageCenter", "text": "消息", "iconPath": "static/images/message.png", "selectedIconPath": "static/images/messageS.png" },
      { "pagePath": "pages/tabBar/login/login", "text": "我的", "iconPath": "static/images/mine.png", "selectedIconPath": "static/images/mineS.png" }
    ]
  },
  "globalStyle": {
    "navigationBarBackgroundColor": "#ffffff",
    "navigationBarTextStyle": "black",
    "backgroundTextStyle": "light"
  }
}
```

## 5. 代码级迁移规则

## 5.1 生命周期

- `App({ onLaunch/onShow/onHide })` -> `App.vue` + `onLaunch/onShow/onHide`。
- `Page({...})` -> `Vue SFC` 的 `onLoad/onShow/onHide/onUnload`。
- `Component({...})` -> `Vue 组件`（`props + emits + ref`）。
- `Behavior` -> `composables`（如 `useSafeArea/useEventsMixin`）。

## 5.2 API 替换清单（重点）

- `wx.request` -> `uni.request`
- `wx.navigateTo` -> `uni.navigateTo`
- `wx.switchTab` -> `uni.switchTab`
- `wx.reLaunch` -> `uni.reLaunch`
- `wx.getStorageSync/setStorageSync/removeStorageSync` -> `uni.getStorageSync/setStorageSync/removeStorageSync`
- `wx.showToast/showModal/showLoading/hideLoading` -> `uni.showToast/showModal/showLoading/hideLoading`
- `wx.getSystemInfoSync/getWindowInfo` -> `uni.getSystemInfoSync`
- `wx.login` -> `uni.login`（微信小程序端）
- `wx.setNavigationBarTitle` -> `uni.setNavigationBarTitle`

## 5.3 条件编译建议

```ts
// #ifdef MP-WEIXIN
uni.login({ provider: 'weixin', success: () => {} })
// #endif
```

- 对 IM、TRTC、摄像头、人脸、授权等高平台耦合能力必须加条件编译。

## 6. 网络层迁移（原 $http.post）

## 6.1 保持行为一致

- 入参保持：`code + data + success + fail`。
- 自动注入 `session`（来自 `userData`）。
- 保留错误码拦截：
  - 未登录码跳转登录页。
  - token/session 失效清理缓存。
  - 网络错误统一提示。
- 保留加密分支（`urlAddress` 含 `Encrypt` 时 AES 加解密）。

## 6.2 建议实现结构

- `src/api/http.ts`：通用 `post(code, data, options)`。
- `src/api/modules/*.ts`：按业务拆分（登录、问诊、录入、排班、公告等）。
- `src/store/auth.ts`：维护 `userData / appInfo / TIMInfo / patientData`。

## 7. IM/TRTC 迁移要点

- `utils/message.js` 迁到 `src/utils/message.ts`，保留：
  - TIM 初始化、登录、登出；
  - 消息接收回调；
  - 业务消息发送（I/B/D/F/P 等事件）。
- TRTC 页面（`trtcRoom`、`trtc-room`）建议优先迁微信小程序端版本，H5/App 作为二期。
- 登录被踢、邀请会诊、消息落库逻辑需回归测试。

## 8. UI 组件迁移策略

- 原 `wxml/wxss/js` 三件套 -> 单文件组件 `.vue`。
- 页面级迁移顺序（建议）：
  1. 登录/个人中心/工作台
  2. 图文咨询 + 问诊会话
  3. 录入模块（Entry）
  4. 排班/公告/模板运营页
- 原 `@vant/weapp` 组件：
  - 能替换为 `uni-ui/uv-ui` 的直接替换；
  - 高度定制组件改写为本地 Vue 组件。

## 9. 分阶段实施计划

## Phase 1：工程初始化（1-2 天）

- 创建 UniApp 项目骨架。
- 搭建 `pages.json/tabBar/subPackages`。
- 建立 `api/store/utils/components` 基础目录。

## Phase 2：底座能力迁移（2-4 天）

- 完成 `http.ts`、鉴权、缓存、全局错误处理。
- 迁移 `app.js` 的启动逻辑（`getAppInfo/autoUpdate`）。
- 建立 IM 基础连接与登录流程。

## Phase 3：核心业务迁移（7-15 天）

- 首页、消息、我的、图文问诊、录入主流程。
- 完成关键组件：navbar、患者列表、诊断/处方编辑。

## Phase 4：长尾页面迁移（5-10 天）

- 排班、公告、帮助反馈、模板、历史记录等。
- 未注册但源码存在的 9 个页面按业务确认是否纳入。

## Phase 5：联调与发布（3-5 天）

- 全链路回归（登录 -> 问诊 -> 录入 -> 完成/消息回流）。
- 性能与分包体积优化。
- 灰度发布。

## 10. 风险与规避

- 风险 1：TRTC/IM 在 UniApp 多端差异大。
  - 规避：先锁定 MP-WEIXIN 端打通，再扩端。
- 风险 2：原有 `Behavior/selectComponent` 强耦合。
  - 规避：以 composable + provide/inject 重构。
- 风险 3：历史页面很多，迁移成本高。
  - 规避：按主流程优先，长尾页面批次迁移。
- 风险 4：隐式全局状态（`getApp()` + storage）难维护。
  - 规避：迁移时统一收敛到 Pinia。

## 11. 验收标准（必须满足）

- 路由：58 个已注册页面可进入，tabBar 可用。
- 业务主链路：
  - 登录成功并维持会话；
  - 图文咨询可进入问诊；
  - 录入（病历/诊断/医嘱）可保存；
  - 消息收发、邀请会诊正常；
  - 个人中心排班/公告/模板关键操作可用。
- 稳定性：网络异常、登录失效、权限拒绝均有可见兜底提示。

## 12. 迁移执行清单（可直接勾选）

- [ ] 初始化 UniApp 项目与依赖
- [ ] 建立 `pages.json`（主包 + 3 分包 + tabBar）
- [ ] 完成 `http.ts`（session、错误码、加密）
- [ ] 完成登录态与全局状态（Pinia）
- [ ] 迁移 `home/login/messageCenter/personalcenter`
- [ ] 迁移 `myConsultRoom` 主流程页
- [ ] 迁移 `entryWrite` 主流程页
- [ ] 迁移 `oneselfCenter` 页面
- [ ] 迁移 IM/TIM 逻辑并联调
- [ ] 迁移 TRTC 页面并联调
- [ ] 完成全量回归测试
- [ ] 输出上线说明与回滚方案

