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 目录重构建议
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 模板(可直接落地)
{
"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 条件编译建议
// #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。
- 页面级迁移顺序(建议):
- 登录/个人中心/工作台
- 图文咨询 + 问诊会话
- 录入模块(Entry)
- 排班/公告/模板运营页
- 原
@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)难维护。
11. 验收标准(必须满足)
- 路由:58 个已注册页面可进入,tabBar 可用。
- 业务主链路:
- 登录成功并维持会话;
- 图文咨询可进入问诊;
- 录入(病历/诊断/医嘱)可保存;
- 消息收发、邀请会诊正常;
- 个人中心排班/公告/模板关键操作可用。
- 稳定性:网络异常、登录失效、权限拒绝均有可见兜底提示。
12. 迁移执行清单(可直接勾选)