医院陪诊这块业务这两年肉眼可见地火了起来尤其是一二线城市独居老人就医、异地就诊、孕妇产检、术后复查这些场景需求非常刚性。我之前帮一家本地生活服务公司从零搭过一整套医疗陪诊系统涵盖微信小程序用户端、陪诊师端APP和后台管理面板这里把整个开发过程里踩过的坑、沉淀下来的功能模块设计思路以及源码层面的关键实现细节整理成文。如果你正准备做医院陪诊APP或小程序这篇文章应该能帮你少走不少弯路。整篇内容会按照我实际开发的顺序来走先拆清楚业务逻辑和产品形态再逐层分析用户端、陪诊师端、后台管理端的功能模块最后落到技术实现细节和常见的线上问题。每个模块我都会给出可落地的设计方案关键代码部分标注清楚实现思路方便你直接抄作业或者二次开发。1. 医疗陪诊系统开发的核心思路拆解1.1 陪诊服务到底在解决什么痛点做系统之前先得想明白陪诊服务的本质。它不是什么高端医疗服务本质上就是“时间换时间、专业换省心”的跑腿服务升级版只不过跑的是医院内部流程需要的是对医院环境、就诊流程的熟悉程度和一定的健康照护常识。典型的陪诊场景分为四类老人就医陪同子女在外地工作老人自己去医院搞不定挂号、取号、科室楼层、缴费、取药这一串流程需要有人全程跟着。异地就医向导患者从外地来大医院看病不熟悉院区分布往往连门诊楼和医技楼都分不清陪诊师能显著减少无效奔波。特定人群照护孕妇产检、术后复查、行动不便人群需要有人帮忙推轮椅、拿报告、听医嘱。业务代办跑腿代取报告、代开药、代缴费、代办出入院手续这类业务客单价低但频率高适合作为引流产品。从系统设计的角度来看这四个场景的核心链路是相同的患者发起需求 → 平台匹配陪诊师 → 按约定时间到场衔接 → 陪诊过程中进行服务记录 → 结束结算。围绕这条主链路去设计功能模块业务逻辑才不会乱。1.2 平台模式与产品形态的选型逻辑产品形态到底是做APP还是做小程序这是动工前必须定下来的事。我的建议是用户端必须优先做微信小程序陪诊师端可以上APP也可以做小程序但要做APP功能更顺手。为什么用户端选小程序理由很实际用户不需要下载安装微信里搜一下或者扫码就能用这个对中老年用户群体尤其友好他们的手机存储空间和操作习惯都偏向轻量应用。小程序天然具备微信支付的闭环能力用户支付和退款流程都是现成的不需要额外申请支付渠道。分享传播链路短子女帮父母下单后直接转发小程序卡片给老人老人点开就能看到订单信息体验非常顺。陪诊师端之所以推荐APP形态是因为陪诊师在外面跑单时需要频繁切换网络、调用摄像头拍照上传、实时上报位置还要接收订单推送。小程序有不少场景限制比如长时间后台运行时的定位频率会被压低容易被系统回收。做原生APP或者uniapp打包的APP在权限控制和后台保活方面会从容很多。后台管理端没有悬念直接做Web管理后台PC端操作。这里有个容易被忽略的点管理后台不只是给运营人员用的还要考虑客服坐席的接入订单纠纷处理、陪诊师资质审核、保险理赔记录这些功能都要在后台找到对应的入口。2. 功能模块全解析前端用户端的核心设计2.1 在线预约与陪诊师匹配模块用户端的预约流程看上去简单但实施起来比想象中复杂。本质上是一个“需求描述 → 系统拆解 → 人货匹配 → 确认支付”的过程每一步都要有对应的功能支撑。预约表单的核心字段我建议这样设计字段名是否必填说明就诊城市必填默认定位城市可手动切换医院名称必填提供医院库搜索支持首字母检索就诊科室必填该医院科室列表数据要维护准确陪诊日期必填日期选择器限制只能选未来7天开始时间必填上午/下午/具体时段患者姓名必填支持填写多个就诊人患者手机号必填下单通知用病情简述选填用于陪诊师提前了解情况服务类型必填全程陪诊/半程陪诊/代取报告/代办跑腿特殊需求选填轮椅、担架、翻译、儿童看护等这里最关键的是服务类型的划分我强烈建议在预约之前先让用户选择服务类型然后把表单动态渲染成对应的字段组合。比如用户选“代取报告”就根本不需要展示陪诊日期和开始时间只需要让用户上传就诊卡照片或填写就诊卡号再选一个期望取报告的时间窗口。表单字段跟着服务类型动态变化用户下单的路径会短很多转化率明显不一样。陪诊师匹配这块不用做得太重不建议一开始就搞复杂的推荐算法。线上跑下来的经验是用行政区 服务类型 当日空闲时段这三个维度做筛选条件拉出候选陪诊师列表按接单量排序用户可以直接看到陪诊师的姓名、照片、服务年限、接单次数和用户评价自己选。对于完全不想选的用户提供一个“平台智能推荐”按钮系统自动选排名第一的陪诊师也说得过去。2.2 订单状态机与全流程追踪模块订单状态设计是整个系统最核心的部分状态定义不清楚后面所有环节都会跟着乱套。我们线上实际跑的订单状态机是这样的待支付用户提交预约后未付款超过15分钟自动取消。待接单付款成功等待陪诊师接单。已接单陪诊师接单进入服务准备阶段。服务中陪诊师已到达医院打卡或用户确认开始服务。待完成服务已经结束等待用户确认。已完成用户确认完成订单关闭进入评价和结算环节。已取消用户或陪诊师主动取消或系统超时取消。退款中/已退款取消后触发退款流程资金原路退回。状态机的每一次跳转都要在两个端同步推送通知。比如“待接单”到“已接单”用户端要推模板消息“您的陪诊师已接单”陪诊师端要推APP推送“您有新订单请及时处理”。订单状态变更的记录不要只存在数据库表里建议单独拉一张订单状态流转日志表按时间顺序记录状态变更前后的值、操作人ID、变更原因和来源端。这张表是后面做纠纷取证和数据分析的底子别省。订单地图追踪模块做起来要注意一个细节陪诊师的位置更新频率不能一刀切。如果每3秒上报一次经纬度服务器压力会很大而且电池消耗也快。我们的方案是服务开始前10分钟高频上报每5秒一次服务中每10秒一次在分诊台、检验科这类重点区域内切到高频模式。判断“重点区域”的逻辑是后台可以手工配置的坐标围栏陪诊师进入围栏后客户端自动提高定位频率。2.3 在线支付与费用核算模块支付模块强调的是准确性和可追溯性。用户端接入微信支付已经很成熟了关键在业务层面的费用计算逻辑。费用结构我建议分成三段基础服务费按照服务类型和时长计算。比如全程陪诊4小时定价268元超时每小时加收50元。附加服务费特殊需求产生的费用比如轮椅租赁、夜间服务、跨院区陪同在订单确认前明确展示给用户。履约保证金部分服务场景需要交一笔小额保证金比如代取贵重报告、代结算费用服务完成后原路退还。线上运营中要注意一个问题陪诊师在医院代缴的费用挂号费、检查费、药费和平台服务费必须分开结算。如果混在一起对账的时候会非常痛苦。我们当时的处理方式是服平台只收取服务费用户在订单支付时只付服务相关费用陪诊师代垫的医院费用在服务完成后用户单独通过平台的“代付账单”入口支付这笔钱不走平台账户直接经过微信支付分账到陪诊师的收款账户。好处有两个平台现金流风险小如果用户拖欠医院费用纠纷主体在用户和陪诊师之间平台只做监管陪诊师垫付压力小合作意愿更高服务态度也更稳定。3. 陪诊师端与后台管理端的功能架构3.1 陪诊师接单与服务记录模块陪诊师端的第一屏应该是“接单大厅”所有待接订单按距离和时间排序展示。接单逻辑上为了避免老手抢单导致新陪诊师接不到活可以做成轮询派单队列的模式系统按照“区域匹配优先接单率高的排前当前空闲的优先”规则生成候选队列依次推送。被拒单后自动流转给队列下一位陪诊师没有主动抢单的操作只有“接受”和“放弃”两个选择。这里有个坑新开城的时候陪诊师数量少每次派单都推给同一个人时间长了陪诊师会觉得平台在压榨自己接单意愿会大幅下降。后来我们加了一条规则同一位陪诊师一天最多接6单距离超过5公里且用户未选择“优先离我最近”的订单不再推送给这位陪诊师。接单体验明显平稳了。服务记录模块承载着证据链的作用。陪诊师到达医院后需要在APP上打卡打卡方式支持GPS定位打卡和扫码打卡两种。GPS打卡要求陪诊师在医院坐标围栏范围内扫码打卡则是扫医院大厅的固定二维码扫码时要附带定位信息一起上传防止造假。服务过程中要引导陪诊师拍摄关键节点照片取号成功、排队签到、医生问诊、缴费、取药、报告出具每个节点拍一张水印时间地点自动打上。这些照片一方面作为服务完成的证据另一方面是后续用户投诉时的仲裁依据有图有真相能省掉大量扯皮成本。3.2 后台运营管理与风控模块后台管理端模块划分可以参考下面的结构订单管理中心按订单状态筛选支持按陪诊师/用户/手机号/订单号全局搜索。陪诊师管理准入审核、证照上传、服务区域设置、接单能力配置、奖惩记录。用户管理用户列表、就诊人管理、投诉记录、信用分管理。财务管理订单流水、陪诊师结算单、退款记录、发票管理。医院信息库医院列表、科室数据、院区坐标围栏、服务范围配置。消息运营中心模板消息审核、用户推送运营、优惠券配置。数据看板实时订单量、完单率、退单率、平均响应时长、GMV趋势。系统配置套餐价格、服务类型、审核规则、权限角色。风控模块是很多自研团队容易忽略的部分。陪诊业务最大的风险不是技术风险而是线下服务人员的不确定性。我把风控拆成了三块准入风控陪诊师入驻必须实名认证健康证上传无犯罪记录声明还需要上传一张本人近期照片。资质材料要过人工审核绝不能全自动通过全自动在线上跑过几轮就会发现有人拿PS过的证件蒙混过关。过程风控平台抽查陪诊师的实时轨迹连续两次抽查发现陪诊师不在医院围栏范围内且未提前报备的自动触发警告消息。跑单过程中用户取消订单或修改时间超过两次的订单会进入后台人工关注列表。售后风控用户评价里出现“迟到”“不专业”“乱收费”关键词的自动推送给客服回访。陪诊师被投诉两次以上且成立直接暂停接单重新培训考核通过后才能上线。这里特别说明一下做陪诊系统不要一上来就堆砌太重的AI风控能力人脸识别、活体检测这些东西成本不低初期用人工审核规则引擎完全够用等订单量稳定了再逐步加自动化能力。4. 技术实现细节小程序与APP的源码实践4.1 微信小程序的登录与手机号授权流程微信小程序登录这块看起来文档很清楚实操起来细节很多。一定记住当前的推荐姿势是wx.login拿到code再用code换openid和session_key整个过程在后端完成不要把session_key下发到前端。先看基础登录代码// 前端小程序端逻辑 Page({ data: { isLogined: false }, onLoad() { this.checkLoginStatus(); }, checkLoginStatus() { const token wx.getStorageSync(token); if (token) { this.setData({ isLogined: true }); return; } this.login(); }, login() { wx.login({ success: (res) { if (res.code) { // 把code传到后端后端用code去微信接口换session wx.request({ url: https://api.example.com/user/login, method: POST, data: { code: res.code }, success: (resp) { if (resp.data.code 0) { wx.setStorageSync(token, resp.data.data.token); this.setData({ isLogined: true }); } } }); } } }); } });后端处理的核心代码逻辑用Node.js示例// 后端Node.js Express const crypto require(crypto); const axios require(axios); const APPID your-appid; const SECRET your-app-secret; async function wxLogin(code) { const url https://api.weixin.qq.com/sns/jscode2session?appid${APPID}secret${SECRET}js_code${code}grant_typeauthorization_code; const response await axios.get(url); const { openid, session_key, errcode } response.data; if (errcode) { throw new Error(微信登录失败: ${errcode}); } // openid对应查数据库新用户自动注册 let user await UserModel.findOne({ openid }); if (!user) { user await UserModel.create({ openid, avatar: , nickname: 用户${openid.slice(-6)} }); } // 用session_key配合业务逻辑生成自己的登录态token const token crypto.randomBytes(32).toString(hex); user.token token; user.sessionKey session_key; await user.save(); return { token, openid }; }手机号授权方面目前微信政策调整后必须使用button组件的open-typegetPhoneNumber来触发授权不能直接调API而且要确保小程序后台已经申请了对应权限。拿到code之后后端用code换取手机号配合session_key做解密也行新接口是直接用code换手机号省掉了手动解密的过程。下面是一个带手机号绑定的完整实现// 前端获取手机号的button button classphone-btn open-typegetPhoneNumber bindgetphonenumberonGetPhoneNumber 微信一键登录 /button// 前端处理手机号授权回调 Page({ onGetPhoneNumber(e) { const { code, errMsg } e.detail; if (!code) { wx.showToast({ title: 您取消了授权, icon: none }); return; } wx.login({ success: (res) { wx.request({ url: https://api.example.com/user/bindPhone, method: POST, data: { loginCode: res.code, phoneCode: code }, success: (resp) { if (resp.data.code 0) { wx.setStorageSync(token, resp.data.data.token); wx.showToast({ title: 登录成功 }); } } }); } }); } });后端处理手机号code的代码async function bindPhone(loginCode, phoneCode) { const sessionRes await axios.get( https://api.weixin.qq.com/sns/jscode2session?appid${APPID}secret${SECRET}js_code${loginCode}grant_typeauthorization_code ); const { openid } sessionRes.data; // 用phoneCode去微信接口换手机号 const phoneRes await axios.post( https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token${getAccessToken()}, { code: phoneCode } ); if (phoneRes.data.errcode 0) { const phoneNumber phoneRes.data.phone_info.phoneNumber; // 更新用户绑定的手机号 await UserModel.updateOne({ openid }, { phone: phoneNumber }); // 生成登录态token并返回 const token crypto.randomBytes(32).toString(hex); await UserModel.updateOne({ openid }, { token }); return { token }; } throw new Error(获取手机号失败); }一个重要的提醒不要在小程序前端直接解析手机号数据。新接口返回的手机号是加密的应把code原样传到后端处理。前几年有部分开发者在前端用session_key解密新规则之后这条路已经完全堵死了。4.2 订单状态机的源码实现思路订单状态机的核心是一个有限状态模型把每个状态允许的转移动作和第二校验条件内置到代码里面。用Java或者Node.js实现都可以我摘一段我们实际使用的Node.js版本的简化代码const ORDER_STATUS { PENDING_PAY: pending_pay, // 待支付 PENDING_ACCEPT: pending_accept, // 待接单 ACCEPTED: accepted, // 已接单 IN_SERVICE: in_service, // 服务中 PENDING_COMPLETE: pending_complete, // 待完成 COMPLETED: completed, // 已完成 CANCELLED: cancelled, // 已取消 REFUNDING: refunding, // 退款中 REFUNDED: refunded // 已退款 }; const TRANSITION_RULES { [ORDER_STATUS.PENDING_PAY]: { to: [ORDER_STATUS.PENDING_ACCEPT, ORDER_STATUS.CANCELLED], validate: (ctx) { // 待支付 - 待接单必须是支付成功回调触发 if (ctx.action ! pay_success ctx.action ! pay_callback) { throw new Error(非法的状态迁移); } } }, [ORDER_STATUS.PENDING_ACCEPT]: { to: [ORDER_STATUS.ACCEPTED, ORDER_STATUS.CANCELLED], validate: (ctx) { // 待接单 - 已接单必须是指定陪诊师接单 if (ctx.action ! accept_order) { throw new Error(非法操作); } } }, [ORDER_STATUS.ACCEPTED]: { to: [ORDER_STATUS.IN_SERVICE, ORDER_STATUS.CANCELLED], validate: (ctx) { if (ctx.action start_service) { const now Date.now(); const serviceStartTime ctx.order.serviceTime; // 陪诊师只能在约定时间前后30分钟内开始服务 if (Math.abs(now - serviceStartTime) 30 * 60 * 1000) { throw new Error(不在允许的服务开始时间窗口内); } } } }, // ... 其他状态转移规则 }; function transitionOrder(order, targetStatus, ctx) { const rule TRANSITION_RULES[order.status]; if (!rule || !rule.to.includes(targetStatus)) { return { success: false, message: 状态${order.status}不可迁移到${targetStatus} }; } try { rule.validate(ctx); } catch (err) { return { success: false, message: err.message }; } order.status targetStatus; order.transitionLogs.push({ from: order.status, to: targetStatus, operator: ctx.operatorId, action: ctx.action, timestamp: Date.now() }); return { success: true, order }; }把状态转移规则集中在一个文件里好处是所有业务流程都能复用同一套校验逻辑。哪天想加一个“超时自动取消”的状态只需要在PENDING_PAY里加一条到CANCELLED的转移规则并写一个定时任务去触发不需要改动业务层代码。订单模块还有两个容易出现并发问题的场景用户端同时取消订单和陪诊师端同时接单。如果直接在数据库层面UPDATE很容易出现双方都认为操作成功的情况。解决方案有两个方向一是订单表中加版本号version字段使用乐观锁UPDATE的条件带上version二是把接单和取消的操作封装到单机的Redis锁里面同一订单ID只能串行处理。我们生产环境用的是第二种用Redis的SETNX实现分布式锁const Redis require(ioredis); const redis new Redis(); async function withOrderLock(orderId, callback, ttl 5) { const lockKey order:lock:${orderId}; const token ${Date.now()}_${Math.random()}; const result await redis.set(lockKey, token, EX, ttl, NX); if (!result) { throw new Error(订单正在处理中请勿重复操作); } try { await callback(); } finally { const currentToken await redis.get(lockKey); if (currentToken token) { await redis.del(lockKey); } } } // 使用方式 await withOrderLock(orderId, async () { await cancelOrder(orderId, operatorId); });提醒一点锁的过期时间设5秒还是10秒取决于你订单回调里要执行多少次数据库操作。太短容易出现锁提前失效太长则回调挂了锁要等很久才自动释放。压测环境下把每个关键链路的时间测一遍再给个50%余量就差不多合适了。4.3 小程序定位、导航与消息推送的接入要点定位模块是陪诊系统里隐形成本最高的部分。腾讯地图、高德地图、微信原生getLocation选择策略要提前想好。微信小程序的getLocation接口目前要求在app.json里声明requiredPrivateInfos权限字段还要在后台开通调用权限否则会报错。我们线上配置是这样的// app.json { requiredPrivateInfos: [ getLocation, chooseLocation ], permission: { scope.userLocation: { desc: 你的位置信息将用于匹配附近的陪诊师 } } }前端获取定位后要把经纬度传给后端做逆地理编码。这里注意一个点不要在前端直接调逆地理编码接口因为小程序端填reverseGeocoder接口的key如果被暴露一天的免费额度可能被打爆。正确做法是前端只把latitude和longitude传给后端后端用自己的密钥去调逆地理编码服务。导航功能不要自己做路径规划直接调腾讯地图小程序插件或者高德地图的URL API。用户点“去这里”按钮调起外部导航既保证路线准确性又省掉了大量算路引擎的开发量。消息推送这里有个容易踩的坑微信小程序的订阅消息是一次性订阅用户每次授权只能接收一次模板消息但陪诊订单的整个生命周期不止一次消息提醒。我们处理方案是在下单成功、陪诊师接单、服务开始、服务完成这些关键节点前先弹窗向用户申请一次性订阅授权。用户如果不点授权这些消息就发送失败。业务上为了让订阅率更高我们做了一个小设计下单支付完成后立即弹订阅授权文案写清楚“授权后您可以及时收到陪诊师接单和订单进度通知”实测订阅率能到60%左右。对于陪诊师APP端的推送直接对接极光推送或者个推不推荐自己做长连接。Android端要注意厂商通道的接入华为、小米、OPPO、vivo各自有独立的厂商推送SDK如果不接厂商通道App在系统省电策略下推送会有明显延迟。4.4 小程序抓包的调试经验项目开发过程中排查线上问题最常用的手段就是抓包。小程序抓包可以通过手机代理到Charles或Fiddler也可以直接使用开发者工具的“本地调试”模式。本地调试模式下小程序的request会自动指向开发环境域名配合编辑器里的调试器和Network面板看请求和响应都是全透明的日常调试效率比手机抓包高得多。如果你需要查看小程序生产环境的真实请求数据推荐用Charles做代理抓HTTPS包但需要先安装Charles根证书并且小程序开发工具里要信任该证书。实际操作中我遇到过两种典型问题一是微信小程序的https请求强制要求TLS 1.2以上Charles低版本生成的证书可能不满足连不上二是主包请求带上了public key pinning校验抓包会直接看到SSLHandshake错误。遇到这种最稳妥的排查方式还是去服务器侧看nginx日志用access_log里的请求参数反向定位。小程序在调试模式下会开启“不校验合法域名”这个功能便于联调但上线前一定要关掉。我们团队就有同事带着这个开关把build产物发到生产环境结果正式版本所有请求直接被判非法域名整整一个下午线上服务不可用。5. 开发过程中的常见问题与排查实录5.1 小程序请求超时与token过期问题现象用户反馈订单列表打开非常慢甚至直接白屏操作一段时间后所有接口开始报401。排查过程我们线上一开始用默认的wx.request没有单独设置超时时间微信小程序默认超时是60秒实际感觉就是转圈半天然后失败。后来把所有请求超时时间统一调整到10秒服务端网关层加上了性能监控明确看到个别拉取陪诊师列表的接口在高峰期要耗时2秒以上。排查发现是数据库查询里没有对city和available_status建联合索引加上之后耗时降到200毫秒以内。token过期的问题更隐蔽。我们的token有效期设置的是24小时但小程序的session_key会在用户长时间不用后失效导致手机号重新授权时各种乱。最后方案是token的有效期缩短到12小时但每次请求时在Redis里续期连续7天活跃的token自动续期到14天一旦返回401前端直接跳登录页让用户重新通过wx.login拿新code刷新token。5.2 微信小程序解手机号时的步骤误区Integrating new getPhoneNumber接口时一个很容易出错的点就是前端bindgetphonenumber拿到code之后后端用code换手机号需要服务端access_token。如果你在服务端没有维护access_token的缓存每次都重新调用https://api.weixin.qq.com/cgi-bin/token去申请接口调用频率很容易超限。微信的access_token有效期是7200秒官方建议是服务端缓存access_token全局只维护一个多实例部署的话还要考虑分布式锁避免同一个token申请多次。另一个问题是手机号授权code的有效期只有5分钟用完之后立即作废。如果用户授权后网络不稳定导致请求失败再次授权要重新弹窗。前端的兜底逻辑要写好调用接口失败时提示“请重新点击授权”而不是直接卡死在页面上。5.3 陪诊师端定位偏移与轨迹漂移问题现象后台看到的陪诊师轨迹穿过河流、隔空跨越大楼明明在医院里定位却显示几百米外。原因分析定位漂移大多来自室内场景。医院大楼钢筋密集GPS信号折射后经纬度偏移非常正常尤其是地下停车场和大型医技楼。第二个原因是部分Android机型的高精度定位设置没有打开默认用的基站定位和WiFi定位上报精度在100米到500米之间完全没法用。解决方案客户端统一使用微信小程序的wx.startLocationUpdateBackground或原生定位SDK的高精度模式内部自动把GPS、WiFi、基站数据进行融合。后端处理轨迹时加了一个简单的卡尔曼滤波算法把漂移点过滤掉。另外额外加了一条兜底规则如果陪诊师连续3个点位的平均速度超过6米/秒相当于人类跑步速度判定为漂移数据轨迹不展示给用户只记录原始数据供人工复核。// 后端简单的卡尔曼滤波示例简化版 function kalmanFilter(points) { const filtered []; const Q 0.01; // 过程噪声 const R 5; // 测量噪声 let x points[0].lat; let y points[0].lng; let p 1; filtered.push(points[0]); for (let i 1; i points.length; i) { const z { lat: points[i].lat, lng: points[i].lng }; // 预测 x x; y y; p p Q; // 更新 const k p / (p R); x x k * (z.lat - x); y y k * (z.lng - y); p (1 - k) * p; filtered.push({ lat: x, lng: y }); } return filtered; }这个滤波器说实话不算高级但对解决视觉上的轨迹跳变已经足够了。更高精度的方案要上HMM平滑工程复杂度高不少业务上完全没有必要。5.4 小程序端连接不上服务器的排查清单线上反馈“小程序打不开”是比较常见的工单类型我整理了一份排查清单按顺序执行可以快速定位问题确认小程序官方后台是否把request合法域名配置完整域名是否带https前缀证书是否过期。确认服务器安全组/防火墙有没有放行小程序服务的端口现在大部分问题反而是服务器端口被云平台安全策略拦掉。在服务器上直接curl -I https://api.example.com看响应头network层面的问题一眼就能看出来。查看nginx错误日志中是否有SSL握手错误确认证书链是否完整。检查反向代理到Java/Node服务的upstream服务是不是挂了服务进程是不是OOM了。小程序端的错误码也需要熟悉几个常见的-1为网络繁忙或无网络1005为域名未备案或证书无效1006为域名离线1015为访问被限制。遇到1005优先去查域名备案状态遇到1015优先看服务器防火墙有没有把微信服务器IP段封了别在业务代码里瞎debug半天。6. 源码交付与二次开发注意事项6.1 项目目录结构与核心依赖一个标准的陪诊系统源码工程建议拆成三个子工程weixin-client微信小程序用户端原生小程序技术栈。accompany-app陪诊师端uniapp打包成Android/iOS一套代码两套壳。admin-dashboard后台管理端Vue3 Element Plus。server后端服务Node.js或者Java都可以按团队熟悉度选择。后端工程内部的模块划分建议server/ ├── src/ │ ├── modules/ │ │ ├── user/ # 用户模块 │ │ ├── order/ # 订单模块 │ │ ├── companion/ # 陪诊师模块 │ │ ├── pay/ # 支付模块 │ │ ├── message/ # 消息推送模块 │ │ ├── hospital/ # 医院数据模块 │ │ └── audit/ # 风控审核模块 │ ├── common/ # 公共组件、工具类 │ ├── config/ # 全局配置 │ └── app.js模块划分的核心原则是依赖方向要清晰不能循环依赖。比如订单模块可以依赖用户模块拿到用户信息但用户模块绝不能反过来依赖订单模块否则排查问题的时候你会陷入循环引用的泥潭。6.2 数据库表设计要点陪诊业务的表结构其实不复杂核心表就8张左右user用户表openid、nickname、phone、avatar、credit_score。patient就诊人表关联user_id姓名、身份证、关系、病历号。companion陪诊师表实名信息、资质材料、服务区域、评分、累计单量。order订单主表订单号、用户ID、陪诊师ID、状态、服务时间、费用明细。order_status_log订单状态流转日志表。service_record服务记录表打卡信息、节点照片、服务备注。pay_record支付流水表微信支付订单号、金额、状态、回调信息。withdraw_record陪诊师提现记录表。重点说一下订单表里容易忽略的几个字段service_address服务医院的地址快照下单时从医院库读取存下来防止以后医院库更新导致旧订单查不到医院。fee_detail费用明细JSON字段存基础服务费、附加费、保证金的拆分记录。source_type订单来源区分小程序自助下单、客服代下单、渠道推广订单。first_paid_at首付款时间做支付转化率分析时用。accept_timeout_at接单超时时间超时后系统自动重新派单。费用相关字段不要用浮点类型项目重点记录使用的是整型的“分”为单位的金额避免出现0.10.2不等于0.3这类精度问题。6.3 二次开发时最容易改坏的三处地方改接口鉴权。很多二次开发的团队上来先把登录逻辑换成自己的鉴权方案结果小程序端的token刷新生效策略没对齐导致用户频繁重新登录。改鉴权一定要先梳理token的生成、校验、续期、失效四个环节缺少任何一个环节都会埋坑。改状态机。给订单加新状态或者新流转路径时只改了前端页面的按钮显隐没改后端的状态转移规则结果前端能点按钮但后端永远返回“非法状态迁移”。正确的做法是先改状态枚举和TRANSITION_RULES再改前端页面两端必须同步上线。改费用计算。动到费用计算逻辑的时候一定要检查是否有历史订单正在服务中或已完成但未结算。如果改了计价规则老订单是按旧规则还是新规则结算我们的经验是永远做“规则版本化”在订单表里存储price_version字段结算时读到哪个版本就用哪个版本计算谁也别覆盖谁。7. 上线后的运营经验与个人心得系统开发完只是第一步医生陪诊这个业务能不能跑通关键还是要看线下的服务质量和平台的运营策略。几个经验分享给大家。第一个心得是千万别在冷启动阶段撒网太多城市。我们刚开始把目标定在六个城市结果每个城市的医院库、科室数据、陪诊师招募、当地医院流程熟悉程度全都是瓶颈。后来聚焦在一个城市的两三家三甲医院把陪诊师数量控制在15人左右把每一单的服务质量打磨稳定再逐城复制反而跑得更快。第二个心得是陪诊师的排班和调度比想象中重要。系统上线的第一个月经常出现早上8点到10点订单扎堆但陪诊师只有一两个在线下午订单寥寥但陪诊师都在闲等。后来让陪诊师在后台自主设置可用时段平台再按历史数据给出建议出勤时间匹配成功率提升非常明显。这个看似简单的功能早期做进系统里能省掉运营人员大量人工协调成本。第三个心得是服务评价体系要做成双向互评。用户给陪诊师打分的同时陪诊师也可以标记用户比如“预约时间多次变动”“态度恶劣”“有传染病未提前告知”。这些标记不对外公开展示只用于平台做派单策略能有效保护陪诊师群体的利益。双向互评搞起来之后双方的规则感都会被强化纠纷率反而比单向评价时更低。四年来从第一版陪诊系统原型到线上稳定运行我最大的体会是这个系统在技术层面没有太高深的东西真正决定项目成败的往往是最基础的状态管理、费用准确性、定位可靠性和消息触达率。把这些基础细节做扎实配合可靠的服务团队这个系统就能为用户创造真实价值平台也才能可持续运转。
阅读完成 · 觉得有帮助?