news 2026/9/8 22:56:30

Vue3+TypeScript+Uniapp构建医疗小程序全流程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3+TypeScript+Uniapp构建医疗小程序全流程实战

简介:面向使用 Vue3、TypeScript 与 Uniapp 开发跨端小程序的开发者,这份完整医疗挂号小程序案例覆盖首页、预约挂号、时段选择、个人中心、视频信息等核心业务模块,并配有类型声明、请求封装、页面路由与构建配置等工程化内容。资源共 30 个文件,以 vue 页面组件、ts 逻辑脚本、json 配置文件为主,辅以 png 图标、scss 样式、html 入口及 gitignore,压缩包仅 1.48MB,目录层级清晰,便于对照源码逐模块学习。目前已有 2257 人浏览学习。通过该案例可掌握 Vue3 组合式 API 与 TypeScript 在小程序中的具体落地方式,理解 uniapp 项目的类型约束、接口调用写法以及页面组织思路,并能直接参考其登录注册、预约流程等常见医疗场景实现,快速搭建可复用的小程序业务骨架,适合希望从零上手 uniapp 工程化开发的初中级开发者。 写这篇东西的起因很直接:我们团队要上一款医疗类小程序,功能包含预约挂号、在线问诊、报告查询和支付,需求一上来就要求“微信小程序能跑,后面 App 和 H5 也得能跟上”。技术选型时没有太多犹豫,定的是 Vue3 + TypeScript + Uniapp 这套组合。说实话,Uniapp 的 Vue3 版本刚出来那会儿我也踩过不少坑,但只要你把工程骨架、请求层、类型约束和跨端边界都提前想清楚,这套组合在医疗这种“业务重、审核严、多端要同步”的项目里,开发效率确实很能打。

这篇文章不想列 API 清单,而是按一个完整医疗小程序的落地顺序走一遍:先讲清楚为什么这么选型,再讲初始化、工程骨架、业务实现、跨端适配、上架发布,最后把一些真实踩过的坑以“排查链路”的方式放出来。适合两种人:一种是想从零开始做小程序的前端开发,另一种是已经在用 Uniapp 但想上 Vue3+TS、又怕踩坑的团队。所谓“一篇文章精通”,不是让你背会所有接口,而是让你知道一个像样的医疗小程序从头到尾是怎么拼出来的,以及每一块为什么是长这样的。

1. 先聊选型:医疗小程序为什么是 Vue3 + TS + Uniapp,而不是原生或 Taro

1.1 医疗小程序的业务复杂度决定了它不是“玩具项目”

很多人觉得小程序无非就是列表页加详情页,真做了医疗项目才发现完全不是这么回事。一个预约挂号流程就要涉及科室树、医生排班、号源余量、就诊人选择、订单状态流转;在线问诊又牵扯到会话、消息类型、图文上传、支付;报告查询还要处理 PDF、图片、不同报告类型的预览兼容。这些业务有一个共同特点:数据结构复杂、状态流转多、接口字段稳定但数量庞大

医疗项目还有一个特殊点:审核严格,上线后不能随意改版,一旦页面逻辑混乱出了问题,用户投诉和合规风险都会接踵而来。这就决定了前端代码不能是“能跑就行”的状态,必须有一套清晰的组织方式。Vue3 的组合式 API 在这种场景下优势很明显,它会强制你把一个业务的所有逻辑聚合在一起,比如“号源锁定”相关的状态、计算属性、事件处理写在一处,而不是像 Vue2 选项式那样散落在 data、created、methods、watch 各个角落。

1.2 三个核心技术选型的关键比较

先说 TypeScript。医疗数据模型的字段又多又长,一个医生对象可能包含姓名、职称、科室编码、排班列表、擅长描述、头像地址等几十个字段。如果全是 JavaScript 的普通对象,后端改一个字段名,前端只能在运行时报错才发现;有了 TypeScript 的 interface 做约束,改完字段后编译阶段就能定位到所有引用点。打个比方,JS 是口头说“这个人姓张”,TS 是递给你一张带照片、带身份证号的证件,谁冒充谁一目了然。

再说 Uniapp 的跨端能力。医疗类产品很少只做微信小程序,一般还要求支付宝小程序、公众号 H5、甚至原生 App。这里我做了一个选型对比,给当时团队讨论用:

方案多端覆盖上手成本类型安全发布渠道适用场景
原生微信小程序仅微信微信平台只做单一平台、追求极致性能
Taro微信+支付宝+H5中(React 体系)多端团队熟悉 React,愿意折腾
Uniapp微信+支付宝+H5+App低(Vue 体系)多端+应用市场多端同步、团队熟悉 Vue
FlutteriOS+Android+H5应用市场偏 App,不太适合小体量小程序

Uniapp 的另一个隐性优势是生态。虽然它的组件质量参差不齐,但像海报生成、图表、签名板这类在医疗场景里比较实用的组件,插件市场基本都能找到,省去很多造轮子的时间。云打包和本地打包能力也成熟,上架安卓各应用市场时省不少事。

1.3 这套组合的隐藏成本与边界

作为过来人,我必须把话说清楚:Uniapp 的 Vue3 版本不是没有代价。它基于 Vite 构建,对插件的兼容性要求更高,插件市场里有一部分老组件还是 Vue2 时代的写法,拿过来直接在 Vue3 里用会报错。TypeScript 在 script 里类型提示很强,但模板里的类型推断偶尔会失灵,遇到问题别钻牛角尖,该写类型断言就写类型断言。

跨端也从来不是“一次编写处处运行”那么理想。微信小程序、H5、App 在原生能力、路由表现、生命周期上都有差异,工程里必须用条件编译手段去处理这些差异。医疗项目尤其要记住一点:核心业务逻辑尽量放在公共层,只有涉及平台特有能力时才写条件编译分支,不要让#ifdef散落得到处都是,否则后期维护成本会直线上升。

2. 初始化流程:从创建项目到在微信开发者工具里跑起来

2.1 环境准备:Node、VSCode、微信开发者工具、Volar

我强烈建议别用 HBuilderX 来做 Vue3+TS 项目的日常开发,它内置的 TS 类型提示和 ESLint 支持跟 VSCode 比差距明显。正确做法是:VSCode 写代码,HBuilderX 只用来做云打包,或者干脆全部走 CLI 方案。VSCode 里必须装两样东西:Volar(Vue Language Features)和 TypeScript Vue Plugin,装完之后记得禁用旧的 Vetur,否则两个插件会打架,模板里的类型提示和格式化都会乱掉。

Node 版本建议 16 或 18 以上,Vite 对旧版 Node 支持不好。微信开发者工具也要提前装好并扫码登录,这一步很多人忽略,CLI 方式运行时如果开发者工具没有登录,命令行会一直卡住或静默失败。另外 VSCode 的终端类型尽量用 Git Bash 或 PowerShell,CMD 在 Windows 上处理 npm 脚本偶尔会出现编码问题,别在这种地方浪费时间。

2.2 两条创建项目路径,我推荐 CLI

创建 Vue3 + TypeScript 版本的 Uniapp 项目,最标准的命令是:

npx degit dcloudio/uni-preset-vue#vite-ts medical-app cd medical-app npm install npm run dev:mp-weixin

项目跑起来后,微信开发者工具选择“导入项目”,目录指向dist/dev/mp-weixin即可。这里有个细节:微信开发者工具的 AppID 可以先选择测试号,但后面要上线就必须在 manifest.json 里换成真实的小程序 AppID。

HBuilderX 的创建方式则是新建项目时选 Vue3 模板,界面操作确实简单,但它生成的是 HBuilderX 专属目录,后续想在 VSCode 里舒服地写 TS、想自己接管构建配置就会比较别扭。团队协作场景下,CLI 项目可以完整纳入 Git 管理,依赖和脚本都能统一,CI/CD 也更容易接入,所以如果条件允许,直接上 CLI 方案。

2.3 “运行到微信开发者工具上没反应”的完整排查链路

这是新手问得最多的问题。我遇到过一次,最后排查下来是开发者工具的服务端口没有打开。现在把排查链路完整写下来,按这个顺序走,基本都能解决:

  1. 确认微信开发者工具登录状态。未登录时 CLI 无法自动拉起来工具,命令行可能没有任何报错。
  2. 打开服务端口。微信开发者工具 → 设置 → 安全设置 → 服务端口,必须是开启状态,否则命令行无法通过本地 WebSocket 协议通知工具加载项目。
  3. 检查是否是新版工具的“自动打开”功能被系统拦截。macOS 或 Windows 防火墙偶尔会拦截 localhost 通信,如果开发者工具闪一下就没反应,看下防火墙是否放行。
  4. 手动导入兜底。直接在开发者工具里“导入项目”,目录选dist/dev/mp-weixin,这是最笨但最稳的方法,能区分是自动拉起的问题还是编译产物本身的问题。
  5. 确认编译产物存在。如果dist/dev/mp-weixin目录为空或者缺少app.json,说明编译失败,需要回到终端看报错,常见原因是依赖没装全、Node 版本太老。

这五步里,前两步解决了 80% 的“没反应”问题。还有一个小技巧:CLI 跑起来后终端会进入 watch 模式,改代码自动重新编译,但微信开发者工具偶尔不会自动刷新,这时手动点一下工具里的“编译”按钮就好。

3. 工程骨架搭建:请求封装、路由、状态管理和类型声明

3.1 一个可以直接复用的目录结构

项目骨架决定了后期维护的舒适度,我习惯这样组织:

src/ ├── api/ # 按业务域拆分的接口定义 │ ├── user.ts │ ├── registration.ts │ └── report.ts ├── components/ # 业务通用组件 ├── pages/ # 小程序页面 │ ├── home/ │ ├── register/ │ ├── consultation/ │ └── mine/ ├── stores/ # Pinia 状态 ├── types/ # 全局类型定义 │ ├── api.d.ts │ ├── doctor.ts │ └── order.ts ├── utils/ # 工具函数 │ ├── request.ts │ └── format.ts ├── static/ # 静态资源 ├── App.vue ├── main.ts ├── manifest.json ├── pages.json └── tsconfig.json

页面目录按业务域分而不是按类型分,这是我个人的执念。一个医疗项目页面数量动辄三四十个,如果全堆在 pages 根目录下,找人找半天;按 home、register、consultation、mine 这种业务域拆分后,一个挂号流程涉及的所有页面都在同一个文件夹里,互相引用的路径也清晰。

3.2 请求层为什么要单独封装

如果不做封装,每个页面直接调 uni.request,你会面临三个很现实的问题:第一,接口地址在十来个页面里各写各的,环境切换要改一堆文件;第二,token 过期后每个页面都要自己判断跳登录;第三,错误提示风格不统一,有的页面弹 toast,有的页面静默失败。

我封装的 request.ts 核心思路很简单:用 Promise 包裹 uni.request,结合 TypeScript 泛型,让每个接口函数都有明确的返回值类型。核心代码大概长这样:

// utils/request.ts const BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api' interface ResponseData<T> { code: number message: string data: T } export function request<T>(options: UniApp.RequestOptions): Promise<T> { return new Promise((resolve, reject) => { const token = uni.getStorageSync('token') uni.request({ url: `${BASE_URL}${options.url}`, method: options.method || 'GET', data: options.data || {}, header: { 'Content-Type': 'application/json', Authorization: token ? `Bearer ${token}` : '', ...options.header, }, success: (res) => { const response = res.data as ResponseData<T> if (response.code === 0) { resolve(response.data) } else if (response.code === 401) { // 登录态过期,清空本地登录信息,跳转登录页 uni.removeStorageSync('token') uni.removeStorageSync('userInfo') uni.navigateTo({ url: '/pages/login/index' }) reject(new Error(response.message)) } else { uni.showToast({ title: response.message, icon: 'none' }) reject(new Error(response.message)) } }, fail: (error) => { uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' }) reject(error) }, }) }) }

然后在 api 目录里定义业务接口时,泛型的好处就体现出来了:

// api/doctor.ts import { request } from '@/utils/request' export interface Doctor { id: string name: string title: string departmentId: string avatar: string } export function getDoctorList(departmentId: string) { return request<Doctor[]>({ url: `/doctor/list?departmentId=${departmentId}`, }) }

页面里调用getDoctorList后,拿到的doctors数组每一项都有完整的类型提示,后端字段变了,编译阶段就能发现哪些地方没跟上。医疗数据敏感,还有一条附加纪律:不要在拦截器或其他任何地方把 token 打到 console 里,否则一次调试忘记删,代码带着 token 日志上了生产,被用户看到就是事故。

3.3 路由与动态标题:pages.json 的配置思路

Uniapp 小程序没有 vue-router,路由体系以 pages.json 里的页面栈为核心。每个要跳转的页面都必须先在 pages.json 注册,否则跳转会报 “page not found”。tabBar 页面只能放在 pages 数组的第一层,而普通页面可以任意嵌套,这两个概念要分清。

页面跳转传参是通过 URL 查询串实现的:

uni.navigateTo({ url: `/pages/register/doctor-list?deptId=${deptId}&deptName=${encodeURIComponent(deptName)}`, })

目标页面在onLoad(options)里拿参数,注意 options 里都是字符串,需要手动转类型。为什么强调encodeURIComponent(deptName)?因为医疗场景里科室名经常带“/”“·”这类特殊符号,不编码的话参数会被截断,这是高频坑。

动态设置导航栏标题也是医疗项目里的常见需求。比如报告详情页,需要根据报告类型展示“检验报告”“影像报告”不同名称,直接在 onLoad 里调用uni.setNavigationBarTitle({ title: '检验报告' })即可。注意要在页面显示前调用,放在 onLoad 里最合适;如果页面已经被压入栈底再想改标题,就需要配合uni.$emit或事件总线了。

3.4 状态管理选 Pinia,但注意持久化

Vue3 项目状态管理没有悬念,选 Pinia。它比 Vuex 轻量、对 TypeScript 支持更友好,而且去掉了 mutations 一层,写起来少很多模板代码。医疗小程序我至少会拆两个 store:userStore 管用户信息、就诊人列表、登录态;orderStore 管挂号订单、问诊订单的状态。

在 Uniapp 里用 Pinia 有一个注意点:小程序页面销毁后内存中的 store 状态不会丢,但小程序被微信回收后,store 会被重置。所以关键状态必须持久化到 Storage。我的做法是:登录成功后把 userInfo 写进uni.setStorageSync('userInfo'),在 App.vue 的 onLaunch 里读回并写进 store,这样用户冷启动后登录态还在。也可以用插件做自动持久化,但医疗项目我对自动化的东西比较谨慎,手工管理更可控。

4. 业务页面拆解:挂号、问诊、报告,一个典型流程的完整实现

4.1 预约挂号:最典型的多步流程与参数传递

挂号流程是医疗小程序的“门面”,也是页面间通信最密集的场景。完整链路是:选择科室 → 选择医生 → 选择日期与号源 → 确认就诊人 → 提交订单 → 支付/完成。

这里最有讨论价值的是“科室 → 医生列表”这一跳的参数传递。从科室列表进入医生列表,需要带deptId(科室编码)和deptName(科室名称),科室名称用于医生列表页顶部展示。deptName 是中文,必须编码传参:

uni.navigateTo({ url: `/pages/register/doctor-list?deptId=${item.id}&deptName=${encodeURIComponent(item.name)}`, })

医生列表页接收:

onLoad(options: Record<string, string>) { this.deptId = options.deptId this.deptName = decodeURIComponent(options.deptName || '') uni.setNavigationBarTitle({ title: this.deptName }) }

这里把解码放在页面上做而不是传参前做,是因为 decode 应该在离展示最近的地方,避免某些平台自动编码导致二次编码出错。

号源选择组件是另一个坑。早上的号和下午的号往往价格不同,医生排班数据是从接口返回的数组,前端要做的是把“老年号”“普通号”“专家号”按时间段渲染成格子,并处理“约满”“停诊”几种状态。我的实现思路是:先写一个ScheduleCell组件,接收statustime两个 props,内部根据状态切换主题色和禁用态;父组件用 computed 把原始排班数据按日期分组,渲染成多行格子。医疗项目里这种“状态多、分支多”的 UI 组件,TypeScript 的联合类型特别有用:

type ScheduleStatus = 'available' | 'locked' | 'full' | 'closed' interface ScheduleCellProps { time: string status: ScheduleStatus }

4.2 在线问诊:长列表、会话窗口与消息重连

在线问诊本质是一个轻量 IM。页面结构是消息列表 + 底部输入区,关键点在于:小程序里长列表渲染大量消息时,直接用 v-for 渲染几千条会导致明显掉帧。我建议按页加载,每次加载 20 到 30 条历史消息,配合scroll-view的滚动事件做上拉加载。

消息数据模型用 TypeScript 定义好之后,渲染就不用反复判断了:

interface ChatMessage { id: string sessionId: string senderType: 'doctor' | 'patient' messageType: 'text' | 'image' | 'system' content: string createTime: number }

WebSocket 连接在医疗问诊里要格外注意心跳。小程序端网络环境复杂,断网重连频繁,我的做法是:连接建立后每 30 秒发一次 ping,超过 50 秒没收到 pong 就主动断开重连;页面 onHide 时暂停发送心跳,onShow 时检查连接状态。这套机制不复杂,但能避免新人在聊天页面遇到“消息发出去没反应”时无从下手。

4.3 报告查询:文档预览与动态标题的结合

报告查询页面是“动态标题”的典型应用场景。报告分为检验报告、检查报告、影像报告等,进入页面时根据reportType字段动态设置标题,同时内部渲染不同的预览方式:

onLoad(options: Record<string, string>) { const reportTypeMap: Record<string, string> = { lab: '检验报告', image: '影像报告', physical: '体检报告', } uni.setNavigationBarTitle({ title: reportTypeMap[options.type] || '报告详情' }) }

图片类报告用uni.previewImage实现单图/多图预览,本地路径和网络路径都可以;PDF 类报告用uni.openDocument打开,需要传 filePath。这里有一个经验:后端返回的可能是https://...pdf或 base64 字符串,如果是 base64 需要用uni.getFileSystemManager().writeFile先写成临时文件,再交给 openDocument,不能直接把 base64 塞给 openDocument,这是新手最容易踩的坑。

5. 跨端与发布:manifest配置、隐私弹窗、分享、支付签名这些老技术点

5.1 manifest.json:一份需要反复确认的清单

manifest.json 是 Uniapp 项目的“总开关”,小程序端最关心的几个配置是:appid(微信小程序 AppID)、项目名称、App 模块权限配置。如果你打算后续打包 App,需要在这里勾选用到的原生模块,比如蓝牙、相机、地图;小程序端则不需要在这里配置,而是在微信公众平台后台配置。权限申请的原则是“最小够用”,医疗类小程序尤其如此,权限越少,审核越顺,用户在授权弹窗时的恐慌感也越低。

5.2 iOS 隐私政策弹窗与“不同意就退出”的实现

如果项目要打包成 App 上架 iOS,首次启动必须弹隐私政策与用户协议弹窗。弹窗本身不难:在 App.vue 的 onLaunch 里检查是否有“已同意隐私”标记,没有就弹窗;难点在于“用户点了不同意怎么处理”。需求上通常是退出 App,响应代码很直接:

uni.showModal({ title: '提示', content: '您未同意隐私政策,无法继续使用本应用', showCancel: false, confirmText: '退出', success: (res) => { if (res.confirm) { uni.exitApp() } }, })

这里真正重要的是合规逻辑,不是代码:用户没同意之前,不能初始化统计 SDK、不能上报任何用户信息、不能调用任何涉及隐私的 API。所以隐私弹窗的同意回调里才去初始化第三方 SDK,不同意则直接退出,这个顺序不能颠倒。

5.3 onShareAppMessage 被全局方法覆盖,问题出在哪

热词里提到“uniapp onShareAppMessage 被全局方法覆盖”,这个我太熟了。常见写法是在 App.vue 的 globalData 或 mixin 里写了一个全局分享配置,希望所有页面都有分享能力,但小程序分享生命周期是页面级的,页面没定义onShareAppMessage时,右上角菜单默认可能没有分享按钮;而一旦在 mixin 里定义了全局的onShareAppMessage,又会导致所有页面都走同一套分享配置,个别页面想自定义标题和图片时发现“被覆盖了”。

我的做法:全局 mixin 提供默认配置,但页面里需要自定义时,必须在页面自身定义onShareAppMessage,并显式返回当前页面的分享配置:

onShareAppMessage() { return { title: 'XX医院在线挂号', path: '/pages/home/index', imageUrl: 'https://cdn.xxx.com/share.jpg', } }

页面自身的生命周期优先级高于 mixin,所以不会被覆盖。另外,自定义分享按钮用<button open-type="share">,这个是微信内置能力,不需要调用接口。

5.4 扫码、支付与上架那些不能跳过的验证

uni.scanCode扫码结果有时“扫出来是一串数字”,这不是 bug。扫码接口返回的是一个普通字符串,二维码、条形码都能扫,条形码结果天然就是纯数字或混合数字,关键在后端要定义好业务规则:比如工作人员扫设备上的条形码,前端把码值传给后端,后端判断是设备 ID 还是单据号。前端不要自作主张去解析,把它当普通字符串原样上报即可。

微信支付 v3 对接,前端要做的其实不多。后端统一下单后返回 5 个关键参数:timeStamp、nonceStr、package、signType、paySign,前端直接拿去调uni.requestPayment

const paymentParams = await createOrder(...) uni.requestPayment({ provider: 'wxpay', timeStamp: paymentParams.timeStamp, nonceStr: paymentParams.nonceStr, package: paymentParams.package, signType: paymentParams.signType, paySign: paymentParams.paySign, success: () => uni.showToast({ title: '支付成功' }), fail: (err) => uni.showToast({ title: '支付取消' }), })

我的原则是前端绝不参与签名,只做参数透传和结果展示。如果碰到“支付功能暂时无法使用”这类提示,先想两种可能:一是小程序后台支付权限没开通或存在违规未申诉,二是后端签名算法有问题。开发层面能做的就是确保参数完整、签名正确,而涉及违规限制,正确姿势是自查小程序内容资质、走官方申诉流程,而不是想方设法绕过,这一点在医疗领域尤其要清醒。

上架安卓应用市场,我提一下大概流程:先用 HBuilderX 做云打包或本地打包生成 apk/aab,然后准备软件著作权证书、隐私政策链接、ICP 备案信息,每个市场要求略有差异。有一个小提醒:应用市场审核比小程序更关注隐私政策文本,一定要写清楚收集哪些信息、如何使用、怎么注销账号,这些文本建议让法务或懂合规的同事审一遍再提交。

6. 一套值得带走的排查经验:软键盘、路由参数、扫码返回数字这些真实问题

6.1 微信小程序软键盘遮挡查询内容

这是一个超级常见的体验问题。搜索框在页面顶部,用户输入关键词后调起软键盘,把下方的搜索结果列表挡住,体验很差。默认情况下小程序 input 组件设置了adjust-position为 true,键盘弹起会尝试把页面整体上推,但有时候上推高度不够,或者页面本身有滚动容器,导致列表还是被盖住。

我的处理方式是双保险:第一,input 上设置confirm-type="search",让用户点击键盘搜索键时触发bindconfirm;第二,在bindfocusbindblur事件里手动调整页面滚动位置:

onInputFocus() { setTimeout(() => { uni.pageScrollTo({ scrollTop: this.scrollTarget, duration: 200, }) }, 300) }

scrollTarget是查询结果列表顶部距离页面顶部的位置,可以用uni.createSelectorQuery().select('#resultList').boundingClientRect()拿到。这样即使键盘弹出,列表也能被推到可视区域。

6.2 路由参数里的中文与特殊符号

这个问题前面已经埋过伏笔。挂号科室名、搜索关键词、报告类型这些参数,如果直接拼在 URL 里传过去,在 iOS 端偶尔能正常解析,但在部分 Android 机型或者从分享链接进入时会乱码或截断。原因是某些平台对 URL 中的非 ASCII 字符做了重新编码,前端没有统一处理就会出问题。

解决方案就是传参时统一编码、接收时统一解码,两条规则里漏一条都会出 bug。另外如果参数里带?&=这些 URL 保留字符,更要编码,否则参数会被拆开。写过一次这个 bug 之后,我的团队定了规矩:所有非数字类型的路由参数,传的时候必须 encodeURIComponent,收的时候必须 decodeURIComponent,没有例外。

6.3 关于分享方法的合并写法

前面提到全局 mixin 和页面级 onShareAppMessage 的冲突,这里给一个实用合并写法。在 mixin 里不要直接 return 死配置,可以改成判断页面是否有自定义函数,没有才用默认值:

// mixins/share.ts export default { onShareAppMessage(this: any) { const customShare = this.customShareConfig return { title: customShare?.title || '默认标题', path: customShare?.path || '/pages/home/index', imageUrl: customShare?.imageUrl || '', } }, }

页面里需要自定义分享时,定义customShareConfig即可,不需要重复写生命周期。这个方式兼顾了全局兜底和页面自定义,比直接覆盖干净得多。

6.4 技术之外的一点提醒

在你一头扎进代码之前,医疗类小程序有一个绕不开的基础:类目资质。微信公众平台对医疗类目审核很严格,在线问诊需要互联网医院执业资质,报告查询要明确数据来源合规。产品经理和运营先把类目和资质准备齐全,前端再投入开发,否则页面做完才发现类目不通过,等于白干。

安全性方面,医疗项目涉及大量敏感个人健康信息,接口必须做签名和验签,传输全程 HTTPS,敏感字段加密。我见过一些团队花很多时间去研究逆向工具,其实不如把网络层做强:参数签名、防重放、权限校验做到位,逆向成本高了,安全风险自然就低了。

我个人在这套流程里最深的体感是:医疗小程序的开发难点从来不在某个 API 不会用,而在于怎么把几十个页面、几十个接口、复杂的业务状态组织得井井有条。Vue3 + TypeScript + Uniapp 这套组合,恰好能帮你把“井井有条”这件事落到实处。遇到拿不准的平台差异时,先查官方文档,再在开发者工具和真机上各验证一遍,谨慎多一点,线上事故就少一点。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 22:55:41

嵌入式工程师成长路线图:从裸机到Linux驱动的实战跃迁

1. 这不是劝退&#xff0c;是帮你把3万元花在刀刃上 2026年了&#xff0c;嵌入式岗位招聘JD里“熟悉Linux驱动开发”“能看懂ARM Cortex-M系列寄存器手册”“有RTOS项目调试经验”这些要求没变&#xff0c;但应届生简历里“某机构嵌入式全栈班结业”出现的频率&#xff0c;正以…

作者头像 李华
网站建设 2026/9/8 22:53:41

澳洲留学材料NAATI认证翻译去哪办?国内可以办理吗?2026留学新干货

一、办理澳洲留学材料NAATI认证翻译的地点有哪些&#xff1f;方法一&#xff1a;线上慧办好翻译小程序&#xff08;微信、支付宝进入&#xff09;选择这个小程序&#xff0c;不用你“翻墙”找海外对接人&#xff0c;微信、支付宝里直接搜就能用。它家对接的都是在籍有效的NAATI…

作者头像 李华
网站建设 2026/9/8 22:51:19

如何把 BT 下载速度拉满:trackerslist 公共 Tracker 列表完整指南

如何把 BT 下载速度拉满:trackerslist 公共 Tracker 列表完整指南 【免费下载链接】trackerslist Updated list of public BitTorrent trackers 项目地址: https://gitcode.com/GitHub_Trending/tr/trackerslist BT 下载慢,多数时候不是宽带不够,而是客户端手里的 Track…

作者头像 李华