简介:面向毕业设计场景的家政服务微信小程序源码,采用Java作为服务端、微信小程序作为客户端,适合计算机相关专业学生直接用于课程设计、毕业设计选题参考或二次开发。压缩包共169个文件,涵盖28个js逻辑脚本、26个wxss样式、24个wxml页面结构,以及jpg/png图片素材、json配置文件、gif演示动画等,整体大小2.33MB,目录按pages、utils、server等模块划分,清晰分离前端页面与后端接口,便于定位首页、订单、登录、会员、家政服务等核心功能。源码已通过本地编译验证,配置相应环境即可运行,业务覆盖城市选择、擦窗保洁、阿姨帮服务、VIP开通与支付流程,并配有界面预览和说明文档,可直观理解小程序前后端交互及Java接口设计思路。目前已有337人学习下载,适合需要快速搭建家政类小程序或希望借鉴完整业务逻辑的开发者。
1. 家政服务微信小程序.zip 不是安装包,是交付件
收到一个「家政服务微信小程序.zip」时,第一反应通常是解压、导入微信开发者工具、看能不能跑。但 zip 这个后缀已经暗示了交付状态:它可能是微信开发者工具导出的源码包,也可能是在小程序后台下载的线上代码包,两种情况的处理路径完全相反。家政业务又比普通展示型小程序多一层复杂度:用户、阿姨、门店运营三方角色交织,预约、支付、派单、履约是一条完整状态链。所以本文按「识别 zip 类型 → 还原工程 → 建模核心业务 → 打通支付与通知 → 提审上线」的路线,把一份压缩包变成能上线运营的微信小程序。适合接手外包交付、二次开发或自学复现的开发者,也适合准备把小程序的「家政服务」从 demo 推向生产的团队。
2. 解压前先判断:zip 里是源码工程还是发布包
2.1 用三个特征文件识别工程类型
解压前先看压缩包内部结构,别急着双击。常见的家政小程序 zip 有两种来源:开发者工具「导出」功能生成的源码压缩包,以及小程序后台「版本管理」里下载的线上代码包。前者是给人维护的,后者是给微信客户端运行的编译产物,两者目录结构差异很大。
我一般先在命令行里做一次预检:
# 列出压缩包前两层目录,不实际解压 unzip -l 家政服务微信小程序.zip | head -40 # 查看 project.config.json 是否存在,判断是不是开发者工具工程 unzip -p 家政服务微信小程序.zip project.config.json | head -c 500如果输出里能看到project.config.json、pages/、app.js、package.json,这是源码工程;如果看到app-service.js、app-wxss.js、page-frame.html这类编译后文件,则是线上发布包。对于 uniapp 或 Taro 工程,还会额外出现manifest.json或config/目录,且package.json里带@dcloudio/vue-cli-plugin-uni或@tarojs/cli依赖。把类型分清楚,后面的处理方式就完全不一样。
2.2 发布包还原:能看结构,不代表能当源码维护
线上发布包实际上是编译压缩过的,页面路径、WXML 结构、JS 逻辑都被打包进少量文件里。社区里常见的做法是用反编译工具把它还原成近似源码的结构,搜索热词里「微信小程序一键反编译下载」指的就是这类工具链。但我接手这种包时会先评估一次:反编译产物适合做参考、排查线上问题、找回丢失的版本,不适合直接作为二次开发的基线。
原因很直接:反编译出来的代码丢失了原始变量名、注释、模块拆分,uniapp 编译后的产物还混着 vue 运行时逻辑,改起来比重新写还慢。正确的做法是——从发布包里提取页面结构、接口地址、业务字段,用来反推需求文档,然后回到源码工程里改。如果 zip 里只有发布包没有源码,那就把「重建源码工程」列入任务排期,而不是在还原产物上缝缝补补。
2.3 依赖重装与损坏 zip 的常规止损
确认是源码工程后,解压、装依赖。这一步最常见的报错是热词里的error read zip archive,以及 npm 安装时提示could not find EOCD。前者说明压缩包不完整或解压工具不兼容,后者基本可以断定文件在传输过程中被截断。处理顺序是:先校验压缩包完整性,再决定重下还是修复。
# 校验 zip 是否完整 zip -T 家政服务微信小程序.zip # 只解压缺失内容,避免全量重来 unzip 家政服务微信小程序.zip 'pages/*' -d ./restore # 重装 npm 依赖,清理缓存避免复用损坏包 rm -rf node_modules package-lock.json npm cache clean --force npm installzip -T会逐个检查压缩条目,输出OK才能继续;一旦报错,直接找交付方重新打包,不要尝试用第三方修复工具强行解出文件——家政项目里通常带图片资源,静默损坏几张商品图很难发现。依赖安装时,uniapp 工程建议用npm install --registry=https://registry.npmmirror.com提速,原生小程序工程则要先打开开发者工具的「工具 - 构建 npm」,否则miniprogram_npm目录不会生成。
3. 家政订单建模:把预约-派单-履约压进数据模型
3.1 订单状态机先于页面设计
家政服务的核心不是页面漂亮,而是订单生命周期完整。用户提交预约、平台派单、阿姨接单、上门服务、用户确认、售后处理,任何一个状态缺了,小程序都会在实际运营时露馅。我设计家政类项目时,第一件事不是画页面,而是先把状态机写出来:
const ORDER_STATUS = { PENDING: 10, // 待支付 PAID: 20, // 已支付,待派单 ASSIGNED: 30, // 已派单,待服务 IN_SERVICE: 40, // 服务中(阿姨已打卡开始) COMPLETED: 50, // 已完成 CANCELED: 90, // 已取消 REFUNDING: 91, // 退款中 REFUNDED: 92 // 已退款 }; // 允许的状态流转表 const ALLOWED_TRANSITIONS = { [ORDER_STATUS.PENDING]: [ORDER_STATUS.PAID, ORDER_STATUS.CANCELED], [ORDER_STATUS.PAID]: [ORDER_STATUS.ASSIGNED, ORDER_STATUS.REFUNDING], [ORDER_STATUS.ASSIGNED]: [ORDER_STATUS.IN_SERVICE, ORDER_STATUS.CANCELED], [ORDER_STATUS.IN_SERVICE]: [ORDER_STATUS.COMPLETED], [ORDER_STATUS.COMPLETED]: [ORDER_STATUS.REFUNDING], [ORDER_STATUS.REFUNDING]: [ORDER_STATUS.REFUNDED] }; function transitionOrder(currentStatus, targetStatus) { const allowed = ALLOWED_TRANSITIONS[currentStatus] || []; if (!allowed.includes(targetStatus)) { throw new Error(`非法的订单状态流转: ${currentStatus} -> ${targetStatus}`); } return targetStatus; }这里的关键不是代码本身,而是把状态变更收敛到后端接口里,小程序端只负责展示当前状态和可执行操作。PAID到ASSIGNED之间通常有微信订阅消息的触达,状态机的每个节点都应该带updatedAt和operatorId字段,方便事后追溯:谁在什么时间把订单从待支付改成了取消。
3.2 用户、阿姨、门店的最小字段集合
家政业务有三类核心账号,zhi少需要三张表:用户表、服务人员表、门店表。用户表直接对微信小程序登录体系,服务人员表要有接单状态字段,门店表则承担「覆盖区域」的职责。以下是精简过的最小字段设计:
-- 用户表 CREATE TABLE `user` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `openid` VARCHAR(64) NOT NULL UNIQUE COMMENT '微信openid', `nickname` VARCHAR(64) DEFAULT '' COMMENT '用户昵称', `phone` VARCHAR(20) DEFAULT '' COMMENT '联系电话', `address` VARCHAR(255) DEFAULT '' COMMENT '默认服务地址', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 服务人员表 CREATE TABLE `service_provider` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(32) NOT NULL COMMENT '阿姨/技师姓名', `phone` VARCHAR(20) NOT NULL, `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1空闲 2忙碌 3休息', `service_types` VARCHAR(255) NOT NULL COMMENT '服务类型ID,逗号分隔', `rating` DECIMAL(2,1) DEFAULT 5.0 COMMENT '评分' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 门店覆盖区域表 CREATE TABLE `store_region` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `store_id` INT UNSIGNED NOT NULL, `province` VARCHAR(32) NOT NULL, `city` VARCHAR(32) NOT NULL, `district` VARCHAR(32) NOT NULL, KEY `idx_store` (`store_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;openid加唯一索引是硬要求,一个用户重复授权会产生脏数据;service_provider.status要加索引,派单逻辑里高频按状态筛选。service_types用逗号分隔是一种反规范化设计,适合阿姨技能标签这种读多写少、不需要跨表 join 的场景,但如果要做「按技能筛选阿姨」的复杂检索,还是拆关联表更稳。
3.3 服务规格与价格因子为何要拆表
家政服务不是「一个商品一个价」,而是「同一服务、不同规格、不同价格」。日常保洁 2 小时和 4 小时是不同价,深度保洁按面积计费,家电清洗按台数计费。如果把价格写死在商品表里,每调整一次价格就要改商品,运营成本很高。
我习惯拆成service_sku(服务规格)和price_factor(价格因子)两张表。前者定义「服务是什么」,后者定义「价格怎么算」。比如日常保洁的 SKU 是「日常保洁-按小时」,价格因子表里存级别=普通/深度、时长=2/4/6、面积=每10平米对应的加价。小程序端用微信小程序单选框让用户选时长和级别,提交订单时把 SKU ID 和因子 ID 传给后端,由后端计算最终金额。这样做的好处是:新增一种服务时不用改动小程序代码,运营在后台上传 SKU 和因子配置,小程序下拉刷新就能拿到新商品列表。
4. 支付与通知:家政小程序上线前的两道硬门槛
4.1 wx.requestPayment 参数与非 0 返回码
家政小程序绕不开微信支付。当前主流是微信支付 API v3,小程序端的调用入口是wx.requestPayment,它的参数不是后端随便拼的,而是后端通过「统一下单」接口拿到paySign相关字段后回传的。这里给一张参数对照表:
| 参数 | 来源 | 说明 |
|---|---|---|
timeStamp | 后端下单返回 | 下单时刻的 Unix 时间戳,字符串 |
nonceStr | 后端下单返回 | 随机字符串,每次下单不同 |
package | 后端下单返回 | 固定格式prepay_id=xxx |
signType | 后端配置 | 传RSA(v3 协议) |
paySign | 后端签名生成 | 对上述字段做 RSA-SHA256 签名 |
常见失误是把package直接填成prepay_id,漏掉=前缀,微信客户端直接报requestPayment:fail。另一个高频坑是timeStamp用数字类型,v3 要求字符串,Java 后端用 Long 返回时前端拿到的就是数字,需要String(timeStamp)转一下。支付回调返回码非 0 时,不要只弹 toast,要在fail回调里带上errMsg上报日志,因为多数支付失败发生在用户输入密码环节,和接口本身无关。
4.2 服务端下单与回调验签的接口约定
支付能不能通,关键在后端。统一下单接口需要传out_trade_no(商户订单号)、amount、payer.openid、notify_url等字段。out_trade_no必须全局唯一,我习惯用「日期 + 随机数」组合避免并发冲突,并且在订单表里加唯一索引。回调验签更是不能省——热词里反复出现的小程序微信支付v3对接,踩坑点基本都集中在验签失败和回调幂等上。
// 以 Node.js 为例,支付回调验签的核心逻辑 const crypto = require('crypto'); function verifyWechatSign({ timestamp, nonce, body, signature, publicKey }) { const message = `${timestamp}\n${nonce}\n${JSON.stringify(body)}\n`; const verify = crypto.createVerify('RSA-SHA256'); verify.update(message, 'utf8'); return verify.verify(publicKey, signature, 'base64'); } // 回调处理:先验签,再查订单,最后更新状态(幂等) async function handlePayNotify(ctx) { if (!verifyWechatSign(ctx.headers, ctx.body, WECHAT_PUBLIC_KEY)) { ctx.status = 401; return { code: 'FAIL', message: '签名验证失败' }; } const { out_trade_no, transaction_id } = ctx.body; const order = await db.findOrderByTradeNo(out_trade_no); if (order && order.status === ORDER_STATUS.PAID) { await db.updateOrderStatus(out_trade_no, ORDER_STATUS.PAID); } ctx.body = { code: 'SUCCESS', message: 'OK' }; }注意message的拼接格式:时间戳、随机串、请求体、四个部分用换行符连接,请求体必须用原始字符串,不能重新JSON.stringify——对象字段顺序不同会导致签名不一致。回调处理完必须返回{ code: 'SUCCESS' },微信规定格式,否则会重复通知。重复通知不可怕,幂等处理做好了就不会产生重复订单。
4.3 订阅消息:一次授权对应一次触达
家政场景的订阅消息集中在两个节点:派单成功时通知用户、服务完成时提醒评价。微信小程序现在是一次性订阅,用户每授权一次,后端才能推送一次。这意味着不能「下单时一次授权,后面想发几条发几条」。
我通常的做法是:用户下单页勾选「接受服务通知」,此时调用wx.requestSubscribeMessage请求order_assigned模板;支付完成后的详情页再请求一次order_finished模板。用户一次订阅弹窗里可以勾多个模板,这是微信允许的,所以把两个模板放在同一个弹窗里请求,一次授权解决两个环节的触达。要注意的是,wx.requestSubscribeMessage必须在用户点击行为里调用,直接在onLoad里调用不会弹窗,在开发者工具里也无法完整预览,必须真机测试。
4.4 上门地址:从获取地址到逆解析补全
家政服务是上门场景,地址采集不能只让用户手填。推荐链路是:wx.chooseLocation拉起地图选点 → 拿到name和address→ 展示给用户确认 → 手动补充门牌号。wx.chooseLocation需要用户手动触发,且要先声明requiredPrivateInfos里的chooseLocation权限,否则在审核阶段会被驳回。省事的替代方案是用「微信小程序内嵌 H5 + 地图 SDK」做地址搜索,适合覆盖多城市的家政平台,但要注意 webview 组件的业务域名配置,H5 页面必须在小程序后台「业务域名」里添加白名单,否则真机上白屏。
5. 从本地跑通到提审:把 zip 变成能上线的小程序
5.1 导入工程:AppID 与 npm 构建
源码工程导入微信开发者工具时,选择「导入项目」,目录指向解压后的文件夹,AppID 填写自己申请的小程序 AppID——如果 zip 里的project.config.json写了他人的 AppID,开发者工具会提示「项目不属于当前账号」,最常见原因是交付方把小程序的 AppID 留在了工程配置里。处理方式是把appid改成自己的,涉及touristappid的测试号也要同步改。
uniapp 工程导入前要先在项目根目录执行npm install和npm run dev:mp-weixin,产物输出到dist/dev/mp-weixin,导入项目时选这个目录。这一步常见报错是「文件找不到」或「app.json 解析失败」,先确认构建命令是否执行完毕、控制台有没有编译错误,再检查导入目录是不是输出目录,而不是项目根目录。原生小程序工程则要执行「工具 - 构建 npm」,否则页面里使用 npm 包时控制台会报module not found。
5.2 体验版真机自测与抓包核对
本地预览和真机差距很大,尤其是支付和订阅消息,开发者工具里只能「模拟」,不能「真跑」。把代码上传为体验版后,用体验版二维码在真机上完整走一遍流程:用户登录 → 选服务 → 填地址 → 支付 → 收到订阅消息 → 查看订单状态。繁琐,但能省掉提审驳回的返工时间。
抓包核对接口时可以借用 Charles 或系统代理工具查看小程序发出的请求,重点确认三个点:请求域名是不是 HTTPS 且已配置到「服务器域名」白名单;支付相关请求是否走了 v3 接口且带有签名头;图片和文件资源是否走了 CDN 域名。热词里的burp suite 抓取pc端微信小程序和charles抓包电脑端微信小程序属于同一条思路——在 PC 端微信里打开小程序再代理抓包。开发阶段这样做没问题,但要记住线上环境是用户手机,本地代理配置和线上域名配置要分开管理,不要为了调试方便把 IP 直连地址写死进生产代码。
5.3 提审前检查清单与常见驳回项
家政类小程序审核被驳回,九成集中在下面这张表里的问题:
| 检查项 | 常见驳回原因 | 对策 |
|---|---|---|
| 隐私协议 | 未声明收集位置、手机号信息 | 在小程序后台配置用户隐私保护指引,并让协议弹窗先于授权弹窗 |
| 服务类目 | 家政服务未匹配到正确类目 | 核对「生活服务 - 家政」类目,资质要求提前准备 |
| 支付功能 | 使用了个人小程序不支持微信支付 | 主体必须是企业/个体工商户,且开通微信支付商户号 |
| 自定义导航 | 顶部导航栏高度不适配刘海屏 | 用wx.getMenuButtonBoundingClientRect()动态计算导航栏安全区域 |
| 地图权限 | wx.chooseLocation未声明用途 | 在app.json里声明requiredPrivateInfos并在隐私协议中说明 |
最后一栏「自定义导航高度」是老生常谈但依然高频的驳回点。wx.getMenuButtonBoundingClientRect()返回胶囊按钮的位置信息,导航栏高度通常是「胶囊按钮 top × 2 + 胶囊高度 - 状态栏高度」,不要用固定的 44px,安卓和 iOS 的差异很快就教你做人。
6. 上线后继续盯的三件事:分包、zip 更新策略与回跳链路
家政小程序上线不代表结束,有三件事我一般会在发布当天就处理掉。第一是分包体积。管家政平台的服务列表、阿姨详情页经常塞满大图,主包迟早逼近 2MB 上限。用一行命令就能查出主包体积分布:
# 查看 dist 目录下各文件大小,定位大文件 du -sh dist/build/mp-weixin/* | sort -rh | head -20把非首页页面放进subPackages,主包只保留 tabBar 页面和公共组件,本地生活类项目通常能把主包压进 1MB 以内。
第二是 zip 更新策略。标题里带 zip,很容易让人想到「让小程序从服务器下载 zip 包做动态更新」——这条路走不通。微信明确禁止远程下载代码包执行,所以家政服务里涉及的活动页、富文本、服务说明,正确做法是作为静态资源放到 CDN,小程序端通过wx.downloadFile配合合法域名下载后本地缓存,但内容只用来渲染,不能作为逻辑执行。热词里「微信小程序可以下载zip文件吗」的答案就是这样:资源可以下,代码不行。真正的业务更新走小程序后台发布流程,每次提审发布都是新的体验版。
第三是回跳链路。家政平台经常在公众号、短信通知、支付完成页里引导用户回到小程序,这里要区分weixin://dl/business的两种用法:URL Scheme和URL Link。前者是老的跳转方式,需要在后端调用接口换取,有效期为 30 天;后者支持传参且能指定生效版本,更适合投放场景。无论哪种,生成后都要在真机上验证「未安装小程序」的兜底页面——跳转到 App 还是引导页,这个细节影响新用户转化率。家政平台从短信入口来的用户大概率没装过小程序,跳转失败时给一个 H5 报名页当备选,比让用户自己搜小程序更友好。
本文还有配套的精品资源,点击获取