简介:基于 HarmonyOS SDK 6.0.0 开发的医院陪诊系统轻应用源码包,采用 Stage 模型与 ArkTS 语言编写,面向移动应用开发初学者以及希望快速上手鸿蒙生态的开发者,用于学习注册、登录、病情选择、陪诊确认等纯文字交互流程,整体适配手机和平板设备。压缩包仅 10KB,共 12 个文件,其中 ts 源码与 json/json5 配置文件占多数,另含 md 说明文档、图标和工程基础文件,文件划分清晰,便于对照查看页面逻辑与全局配置。系统采用本地模拟数据实现无后端暂存,项目结构涵盖用户数据模型、应用入口、登录注册页面、病情选择及陪诊确认页面,并用到页面路由与状态管理技术,能直观看到轻应用从入口到业务闭环的完整写法。已有 138 人学习,附带编译运行指南和常见问题解决方案,同时给出持久化存储、网络请求对接、样式优化等扩展方向,适合作为鸿蒙应用开发课程设计、毕业课题或自学起步的参考资源。 我去年接手过一个鸿蒙原生医院陪诊项目,市面上能直接参考的完整案例确实少,踩了不少坑,也沉淀了一些能复用的经验。这篇博文就把这套“鸿蒙医院陪诊系统”从需求拆解到关键技术实现完整讲一遍,代码都是我自己在真机上验证过的,适合正在做鸿蒙应用开发、或者想了解陪诊类业务怎么落地的团队参考。
1. 项目背景与方案定位
1.1 陪诊业务的完整链路梳理
医院陪诊的核心不是“陪着走”,而是帮患者解决就医过程中的信息差和操作障碍。一个完整的陪诊流程通常覆盖:挂号预约、就诊报到、排队候诊、医生问诊、缴费取药、检查检验、报告查询。每一环对患者来说都是痛点,尤其对老年人或第一次去三甲医院的人,光是找到诊室门口就要花掉大量时间。
所以鸿蒙医院陪诊系统的核心任务,就是把这条链路数字化。患者(或陪诊员)在手机上能完成大部分操作:绑定就诊人、看医生排班、挂当日号或预约号、查看当前叫号进度、接收就诊提醒、缴费、查报告。开发者要做的,是保证这些流程在鸿蒙设备上跑得流畅,同时利用鸿蒙的分布式能力和服务卡片特性,把信息主动推到用户面前,而不是等用户自己打开App去翻。
这个系统适合谁参考?如果你是做医疗健康类鸿蒙应用的开发者,或者团队正准备切入鸿蒙生态,又或者是想了解陪诊业务场景怎么从零搭建的研发人员,这篇内容都会有帮助。我会把业务逻辑、模块划分、关键技术实现、以及真机调试遇到的坑都讲清楚。
1.2 为什么选鸿蒙原生而不是跨端方案
这个话题在团队内部争论过。有人提议用Flutter或uni-app,一套代码多端复用,开发成本低。但最终我们还是选了鸿蒙原生,核心原因有三条。
第一,陪诊场景非常依赖系统级能力。比如排队叫号,如果只是App内轮询,用户切到后台就收不到更新了,体验极差。鸿蒙的推送服务和后台任务可以做到系统级通知,配合服务卡片还能在桌面实时显示叫号状态。这些能力在跨端框架里要做很多桥接,稳定性还没保证。
第二,鸿蒙应用市场的定位决定了原生应用更容易获得推荐位。医疗健康本身就是系统重点扶持的方向,而且用户对“鸿蒙专属”版本有天然信任感,这对陪诊这种涉及隐私数据的应用很重要。
第三,鸿蒙的原子化服务形态很适合陪诊这种低频刚需场景。用户不需要下载完整App,用服务卡片或碰一碰就能拉起挂号、报到等单功能模块,用完即走,转化率高。
当然,如果你是成熟团队要快速覆盖iOS和Android,跨端依然是合理选择。但就纯鸿蒙场景而言,原生开发在性能、生态贴合度和用户体验上更有优势。
1.3 技术选型与整体架构
我们的技术栈如下:
| 模块 | 选型 | 说明 |
|---|---|---|
| 开发语言 | ArkTS | 鸿蒙官方推荐,TypeScript的超集 |
| IDE | DevEco Studio 5.0 | API 12及以上版本 |
| 应用模型 | Stage模型 | 官方主推,支持多窗口和后台任务 |
| 状态管理 | @State + @Prop + @Link | 配合AppStorage管理全局数据 |
| 网络层 | @ohos.net.http | 官方HTTP库,封装了请求和响应 |
| 数据持久化 | @ohos.data.preferences | 轻量级KV存储 |
| 推送 | 鸿蒙PushKit | 用于排队提醒和报告通知 |
| 地图服务 | 高德地图鸿蒙SDK | 室内导航辅助 |
架构上分层很清晰:UI层(ArkTS页面)→ 业务逻辑层(模块化Service)→ 数据层(网络+本地存储)。模块之间通过接口通信,避免循环依赖。
2. 核心模块拆解与实现思路
2.1 就诊人管理与电子凭证
陪诊系统的第一个核心模块是就诊人管理。用户需要绑定自己和家人,每个就诊人包含姓名、身份证号、手机号、病历号等。这里有几个技术细节需要注意。
首先是身份信息的安全存储。身份证号属于敏感信息,不能明文存到Preferences里,我们用的是鸿蒙的加解密接口做AES加密后再落盘。每次读取时解密,用完立即释放内存,避免残留。
其次是电子凭证的展示。现在很多医院支持电子健康卡或医保电子凭证,鸿蒙端可以用二维码组件直接渲染。如果你需要生成二维码,推荐使用@ohos.zlib做数据压缩,配合Canvas绘制。要注意二维码的容错率,陪诊场景经常在光线杂乱的医院环境扫码,建议容错级别设为H(30%),牺牲一点密度换识别率,实测很稳。
就诊人列表页建议做成卡片式,每张卡片显示姓名、关系、就诊卡号,并提供“设为默认就诊人”的功能。这个默认值要同步到全局状态,后续挂号、报到、缴费都会用到。
2.2 号源查询与预约挂号
号源查询的设计重点不是功能多,而是响应速度和数据准确性。医院接口通常返回的是科室→医生→排班的三级结构,前端要做的就是把这些数据转换成用户容易理解的形式。
这个模块的实现分为三块:科室列表、医生排班、预约确认。科室列表建议按首字母索引,因为三甲医院科室动辄几十个,纯滚动查找效率太低。医生排班要突出“剩余号源”这个指标,余号低于5个时用红色警示,低于10个用黄色警示,这个交互细节是陪诊用户最关心的,也是产品经理反复打磨的点。
预约确认页要展示完整的就诊信息:科室、医生、时间、就诊人、费用,并在底部提供“同时添加日历提醒”的选项。鸿蒙的日历接口支持直接写入日程,对陪诊场景特别实用,患者不容易忘记预约时间。
代码上,号源列表用List组件配合LazyForEach做懒加载。医生排班数据往往有几百条,一次性渲染会卡顿,懒加载后滑动明显流畅,这块是实测优化的重点。
2.3 排队叫号与消息提醒
排队叫号是陪诊系统里技术含量最高的模块,也是最容易翻车的部分。核心难点在于:叫号数据怎么拿、怎么推、怎么展示。
数据获取有两种方案。一种是App内轮询后端接口,每5秒拉一次当前叫号;另一种是后端主动推送到鸿蒙Push。我们的方案是“轮询+推送兜底”:App在前台时用WebSocket实时接收叫号数据,性能好延迟低;退到后台后切到Push,由系统接管,用户锁屏也能看到。
这里要强调一个坑:不要在主线程做轮询。鸿蒙的@ohos.net.http本身就是异步的,但如果你的轮询逻辑里包含了UI刷新,一定要用runOnUiThread切回主线程,否则会触发卡顿甚至ANR。
叫号状态页我们做成了两栏布局:左侧是当前队列总览“前面还有X人”,右侧是最近5个被呼叫的号码。当用户号码被呼叫时,页面顶部会出现全屏强提醒,配合声音和震动,确保患者能注意到。实测下来这个功能在吵杂的候诊区非常实用。
2.4 院内导航与就诊动线
院内导航是用户评价最高但开发成本也最高的模块。陪诊过程中,用户最常问的问题是“放射科怎么走”“药房在几楼”,如果系统能给出路线指引,体感会大幅提升。
技术方案上,我们用了高德地图的鸿蒙SDK,结合GPS、Wi-Fi指纹和惯性传感器做定位。但说实话,室内定位精度受医院建筑结构影响很大,纯靠技术解决不现实。所以我们的策略是“楼层为先”:医院楼栋通常有明显标识,我们用地图SDK定位到楼栋和大概楼层,然后显示一个静态的楼层平面图,把目的地高亮标注出来,再配文字指引。
这个方案成本低、稳定,用户体验其实比勉强做一个不精确定位的室内导航更好。如果你预算有限,建议优先做“楼层+高亮标注”方案,而不是硬啃室内SLAM。
导航页还有一个细节:要提供“切换日期”的能力。因为医院的楼层分布有时候会调整,门诊和医技区在不同时段可能开放不同楼层,后台配置一个排期表,前端根据当前日期渲染对应的平面图。
2.5 缴费与报告查询
缴费模块要解决的是“合并支付”的问题。患者看一次病可能产生挂号费、检查费、药费、治疗费多个订单,如果每个都单独支付一次,体验很割裂。我们的设计是把当前就诊人所有待缴费订单汇总成一个账单,展示总金额,支持一次性合并支付。
支付集成用的是鸿蒙的IAP能力,也兼容了第三方支付SDK。这里要注意的是支付回调的幂等性:医院接口经常由于网络问题重复通知,后端要做去重逻辑,避免用户被重复扣款。前端在支付结果页也要做状态校验,以医院接口的最终状态为准,而不是支付渠道的返回。
报告查询相对简单,就是一个列表+详情页,但有几个体验优化点值得做:报告生成后主动推送通知,而不是让用户反复刷新;PDF报告支持在线预览和下载到本地;检验报告用颜色标注异常项,数值超出参考范围的上浮红标、下浮蓝标,用户一眼就能看到问题指标。
3. 工程落地与关键代码实现
3.1 工程初始化与依赖配置
新建一个鸿蒙工程,需要先确认DevEco Studio版本和HarmonyOS SDK API等级。我们用API 12作为最低兼容版本,这样能覆盖大部分存量设备,同时能使用新版Stage模型和完整PushKit能力。
工程创建后,先在module.json5里配置权限。陪诊系统需要的权限不多,包括网络访问、定位、日历写入、通知。注意ohos.permission.LOCATION要在用户首次进入定位相关页面时动态申请,不能一启动就弹窗,否则很容易被拒绝。
"requestPermissions": [ { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.LOCATION" }, { "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" } ]
3.2 页面架构与状态管理
页面架构上,我们采用单实例多页面的Stage模型。主页面是服务首页,用Tabs组件管理五个Tab:首页、就诊人、预约、消息、我的。每个Tab对应一个独立页面,但共享同一个AppStorage中的全局状态。
全局状态包括当前登录用户、默认就诊人ID、当前叫号状态。用@StorageLink绑定这些关键数据,任何页面修改后其他页面自动同步。这个设计在陪诊场景特别有用:比如用户在预约页完成了挂号,首页的“就诊提醒”卡片会立即更新,不用重新请求接口。
ArkTS状态管理的性能优化要注意:不要大范围使用@Link,父子组件之间频繁的双向绑定会带来额外的渲染开销。更推荐的方式是父组件用@State管理数据,通过@Prop单向传给子组件,只在需要回调时使用事件。
3.3 网络层与数据模型封装
网络层我们统一封装在HttpService类里,基于@ohos.net.http做了Promise化改造。所有接口请求都走这个服务,统一处理Token注入、超时重试、错误码识别。
import http from '@ohos.net.http';
export class HttpService { static baseUrl = 'https://api.your-hospital.com/v1';
static async request(path: string, method: http.RequestMethod, data?: object) { const httpRequest = http.createHttp(); const response = await httpRequest.request(${this.baseUrl}${path}, { method: method, header: { 'Content-Type': 'application/json', 'Authorization':Bearer ${AppStorage.get('token')}}, extraData: data ? JSON.stringify(data) : undefined, connectTimeout: 10000, readTimeout: 15000 } ); const result = JSON.parse(response.result as string); if (result.code !== 0) { throw new Error(result.message); } return result.data; } }
数据模型层面,每个业务对象都建了对应的类,比如PatientRecord、DoctorSchedule、QueueStatus。类里只放纯数据类型和简单的格式化方法,不做复杂逻辑,保证序列化和反序列化的性能。
3.4 服务卡片与后台任务
服务卡片是鸿蒙的特色能力,在陪诊系统里我们做了两张卡片:一张是“今日就诊”卡片,展示今天预约的科室和医生;另一张是“排队提醒”卡片,实时更新当前叫号进度。卡片更新通过FormExtensionAbility实现,后端推送叫号变化时触发卡片刷新,频率控制在5秒一次,避免资源浪费。
后台任务的实现要注意合规。鸿蒙对后台任务的限制越来越严格,如果应用退到后台长时间运行,系统会回收资源。我们采用延迟任务+通知提醒的方式:App退后台后,WebSocket连接会自动断开,此时靠PushKit维持通知能力。这样既不违反系统策略,又能保证用户收到叫号提醒。
import { reminderAgentManager } from '@kit.BackgroundTasksKit';
export function publishQueueNotification(queueNumber: number) { let reminderReq = { notification: { id: 1001, content: { notificationContentType: 0, normal: { title:请前往 ${queueNumber} 号诊室就诊, text:当前呼叫:${queueNumber}号,请尽快前往候诊区。} } }, reminderType: 1, actionButton: [ { title: '打开App', type: 1 } ] }; reminderAgentManager.publishReminder(reminderReq); }
4. 常见问题与排查技巧实录
4.1 模拟器与真机的适配问题
鸿蒙模拟器目前只支持ARM64架构,很多开发者用x86的电脑跑模拟器会直接报“运行设备不兼容”。踩过这个坑之后,我在真机调试上投入了更多精力,反而发现真机调试的启动速度也不慢,而且定位、推送这些能力在真机上才能完整测试。
如果你确实需要模拟器,建议在DevEco Studio里选用“Phone”类型的模拟器镜像,API等级和项目保持一致。实测API 12的模拟器比API 14稳定很多,后者启动时间太长,容易卡死。
4.2 地图SDK的加载失败
高德地图鸿蒙SDK第一次接入时经常遇到白屏或加载失败,原因是SDK需要在module.json5里声明meteData中的AppKey,而且这个Key必须和你注册的包名、签名证书一致。排查顺序是:先确认包名,再确认证书指纹,最后看SDK初始化日志,基本能定位。
另外,地图页面在鸿蒙上创建时要放在loadContent之后,过早初始化会导致地图画布无法获取尺寸。建议在页面onPageShow生命周期里再调用地图初始化方法。
4.3 图片压缩与上传卡顿
陪诊系统需要上传就诊人头像和检查报告图片,医院现场拍照环境差,原图动辄5MB以上,直传服务器会非常慢。我们用了鸿蒙的Canvas接口做图片压缩,在保持清晰度的前提下把图片压到500KB以内。
function compressImage(src: PixelMap, targetSize: number): PixelMap { const scale = Math.min(1, targetSize / src.getPixelMapInfo().size.width); const options = { scaleX: scale, scaleY: scale, targetWidth: src.getPixelMapInfo().size.width * scale, targetHeight: src.getPixelMapInfo().size.height * scale }; // 使用ImagePacker做JPEG编码压缩 const packer = image.createImagePacker(); const packed = packer.packing(src, { format: 'image/jpeg', quality: 80 }); return packed; }
注意压缩操作要放到Worker线程里,主线程处理大图会卡UI,用户会明显感觉到掉帧。
4.4 轮询和推送的状态同步
这个坑排了好久。我们在前台用WebSocket接收叫号,退后台后用Push接收,但两个通道的切换会出现丢消息的情况。比如用户从后台切回前台时,WebSocket刚建立连接,而最新的叫号数据正好在切换间隙推送过来,就丢了。
解决办法是在切换通道时做一次全量状态拉取。具体做法:App从后台切到前台时,先暂停Push接收,主动请求一次最新的叫号状态,同时建立WebSocket连接。这样虽然多了一次接口调用,但能保证消息不丢,体验远好于省一次请求。
4.5 真机预览与构建的日常技巧
开发过程中调试签名和发布签名一定要分开。真机预览用调试签名,上架用发布签名,开发时如果连了发布签名,部分权限和推送能力会表现异常,而且日志信息不完整,很难排查。
鸿蒙工程里经常遇到构建缓慢的问题,可以通过以下方式优化:关闭不必要的HAR依赖、开启增量编译、把DevEco Studio的构建内存调到4GB以上。实测这些配置调整后,构建时间从之前的3分钟缩短到40秒左右。
根据个人经验,做鸿蒙医疗陪诊类项目,最大的挑战不是代码本身,而是如何把鸿蒙的系统级能力(推送、卡片、分布式)和医疗业务场景深度融合。建议你在开发前把用户的核心动线梳理清楚,优先实现“挂号→排队→缴费”这条主线,其他功能后续迭代都不迟。我踩过最大的坑就是前期过度设计,做了很多边缘功能,结果核心流程反而没打磨到位。项目上线后,最受欢迎的功能往往是你最初以为是锦上添花的东西,比如服务卡片上的排队提醒,用户反馈说“看着桌面就知道该去诊室了”,这种价值是传统App给不了的。希望这篇分享能帮你少走一些弯路。
本文还有配套的精品资源,点击获取