简介:一套完整的智慧社区管理小程序源码,面向微信小程序开发者、物业数字化项目实施人员以及相关课程设计的学生。项目采用客户端服务器架构与微信云开发,同时提供业主端与物业后台,覆盖公告、活动、投票、报事报修、房屋出租、个人中心等高频场景;业主可查看通知、参与互动、在线提交维修工单,物业端支持对业主档案、公告活动、投票结果和报修事项的统一管理。该源码包共554个文件,含201个脚本、106个样式表、89个页面模板、85个配置文件,以及60张PNG和7张JPG图片,分别对应逻辑处理、界面样式、结构布局、系统配置与视觉效果,整包13.16MB,结构清晰易于按模块学习。目前已有465人参与学习下载。随包附带开发文档和后台管理界面截图,展示了首页、报事报修管理等关键页面,便于读者对照理解项目目录、云函数调用和核心业务流,可直接导入微信开发者工具运行调试,也可作为毕业设计或二次开发的基础。
1. 智慧社区小程序源码:云开发打通报事报修与物业缴费全链路
做智慧社区小程序,最怕的不是写不出页面,而是写完页面发现业务根本闭环不了。业主真正高频用的功能就那么几个:报事报修、看公告、查缴费记录。这套“基于微信小程序的智慧社区管理小程序设计源码”我拆过一遍,值得说的是它没走传统自建后端的老路,而是用微信云开发把数据库、云函数、云存储全包了,JavaScript 写业务逻辑,小程序端直接调。对一个人要撑起一个项目、又不想买服务器配域名备案的开发者来说,这是最省成本的路线。源码里报事报修这条链路做得比较完整,从提交工单、上传图片、物业处理到状态回写都有对应代码。文章会按“工程结构 → 报修链路 → 云开发初始化 → 踩坑排查 → 扩展方向”的顺序拆,新手照步骤能把项目跑起来,熟手也能直接拿走采集参数与边界设计。
2. 源码目录与数据模型:一套能直接跑的社区小程序工程怎么组织
导入工程后的第一反应是“文件怎么这么多”。微信原生小程序的项目结构受框架约束,pages、components、utils、cloudfunctions 各有分工,不能一股脑塞在 pages 里。从这套源码的代码包来看,它按“页面-复用组件-云函数”三层切分,比把全部逻辑堆在 app.js 里好维护得多。
2.1 目录结构:pages、components、cloudfunctions 三分天下
代码包解压后是标准的微信小程序云开发工程,核心目录如下:
miniprogram/ ├── app.js # 全局逻辑:云环境初始化、登录态检查 ├── app.json # 页面路由、tabBar、window 配置 ├── app.wxss # 全局样式 ├── pages/ │ ├── index/ # 首页:公告轮播、快捷入口 │ ├── repair/ # 报事报修:提交工单页 │ ├── repair-list/ # 报修记录:工单进度列表 │ ├── payment/ # 物业缴费:账单列表 │ ├── notice/ # 公告详情页 │ └── profile/ # 我的:房屋绑定、退出登录 ├── components/ │ ├── status-tag/ # 工单状态标签组件 │ └── empty-state/ # 列表空态组件 ├── utils/ │ ├── request.js # 云函数调用封装 │ └── format.js # 日期与状态文案格式化 └── cloudfunctions/ ├── login/ # 登录云函数:获取 openid、维护用户信息 ├── repair-submit/ # 提交报修工单 ├── repair-update/ # 物业处理工单、状态流转 └── notice-publish/ # 发布公告(管理端)这种分层的核心思路是:pages 只负责界面交互和收集参数,业务逻辑尽量下沉到云函数。比如 repair 页面里不直接操作数据库,而是调 wx.cloud.callFunction 触发 repair-submit,这能防止小程序端被反编译后直接篡改数据。components 里 status-tag 在业主端和管理端都会复用,状态文案和颜色统一由组件内部维护,避免两处写法不一致。
app.json 里 tabBar 配了首页、报修、我的三个主入口。我一般会把“物业缴费”也提为 tab,但这套源码把它放在首页入口,对于功能演示而言问题不大。如果你后续要接真实支付,建议单独加一个缴费 tab,页面层级浅一点,业主的支付转化率会明显好一些。
2.2 数据库集合设计:repair、notice、house、payment 字段定义
云开发数据库是文档型,不建表,只建集合。这套源码跑起来至少需要以下集合:
| 集合名 | 主要字段 | 写入方 | 读取方 |
|---|---|---|---|
| users | _openid、name、phone、house_id、role | login 云函数 | 小程序端 |
| house | _id、building、unit、room、owner_name | 管理端导入 | 业主端 |
| repair | _openid、house_id、title、desc、images、status、timeline | repair-submit / repair-update | 业主+物业 |
| notice | title、content、cover、publish_time | notice-publish 云函数 | 所有用户 |
| payment | house_id、period、amount、status、due_time | 后台导入 | 对应业主 |
重点看 repair 集合。它除了记录报修内容和图片,还多了一个 timeline 字段,这是这套源码里一个值得保留的设计。timeline 是一个数组,每次状态变更都往里 push 一条记录,包括时间、状态、处理备注。这个设计让工单的每一步都有据可查,业主看到的不只是最终状态,而是完整流转历史。很多自己写的报修功能只存一个 status 字段,出了问题根本说不清是物业没看到还是处理中卡住了,我建议后续扩展时保住 timeline 结构。
状态值建议单独抽成常量,避免页面里到处写字符串:
// utils/repair-state.js const REPAIR_STATUS = { PENDING: 'pending', // 待派单 PROCESSING: 'processing', // 处理中 COMPLETED: 'completed', // 已完成,待业主确认 CONFIRMED: 'confirmed' // 业主已确认关闭 }; const REPAIR_STATUS_TEXT = { [REPAIR_STATUS.PENDING]: '待派单', [REPAIR_STATUS.PROCESSING]: '处理中', [REPAIR_STATUS.COMPLETED]: '待确认', [REPAIR_STATUS.CONFIRMED]: '已关闭' }; module.exports = { REPAIR_STATUS, REPAIR_STATUS_TEXT };常量抽出来以后,列表页、详情页、status-tag 组件都引用同一份定义。改文案时只改一处,不用全局搜索字符串。状态机只画四个状态,是因为对业主端筛选足够:没处理的、处理中的、完事待确认的、彻底关闭的。状态太多会增加小程序端筛选的复杂度,云函数侧的校验逻辑也会跟着膨胀,对小区物业这种低频工单场景不划算。
2.3 app.js 全局配置:云环境初始化与登录态检查
源码在 app.js 里完成云开发初始化,这是所有云能力生效的前提:
// miniprogram/app.js App({ onLaunch() { if (!wx.cloud) { console.error('基础库版本过低,请使用 2.2.3 以上'); return; } wx.cloud.init({ env: 'community-prod-xxxx', // 替换成你自己的云环境 ID traceUser: true }); this.globalData = { userInfo: null, openid: '', houseId: '' }; }, onShow() { const token = wx.getStorageSync('token'); if (!token) { // 跳转登录页,由登录页拿到 openid 后写入 storage wx.redirectTo({ url: '/pages/profile/login' }); } } });env 参数指向云环境 ID,每个环境是隔离的,不替换成自己的,所有数据库和云函数调用都会打到作者的旧环境上。traceUser 会记录用户操作日志,方便排查线上问题,默认开着没坏处。onShow 里只做登录态检查,不做用户信息拉取,因为用户可能只是随手打开小程序看公告,强制登录才能浏览会把访问量直接砍半。
这段逻辑是典型的“云开发全家桶”思路:不自己签发 token,也不维护 session,登录态靠 openid 天然隔离。每个微信用户在小程序里有唯一 openid,云函数调用 cloud.getWXContext() 能直接拿到,不需要前端传。这也意味着安全隐患集中在云函数层——前端把必要参数传过来,云函数必须自己校验 openid 归属,后面第 3 章会细讲。
3. 报事报修核心链路:从提交工单到完成回访的代码拆解
报事报修是这套智慧社区源码里最完整的业务闭环,也是业主使用频率最高的入口。其他功能几乎都是围绕它支撑的:房屋绑定是为了知道工单来自哪一户,公告是为了把停水停电这类信息同步出去,费用查询是和物业后台结算相关。所以拆代码时,先把报事报修吃透,整个项目的骨架就清楚了。
3.1 业主端提交:表单校验、图片上传与 callFunction
提交页面收集五个信息:报修标题、描述、图片、房屋编号、联系方式。前端校验只做基础拦截,真正的权限校验在云函数里:
// miniprogram/pages/repair/repair.js Page({ data: { title: '', desc: '', images: [], submitting: false }, async chooseImage() { const res = await wx.chooseMedia({ count: 3, // 最多 3 张 mediaType: ['image'], sizeType: ['compressed'], // 优先压缩图,减少上传流量 sourceType: ['album', 'camera'] }); const paths = res.tempFiles.map(f => f.tempFilePath); this.setData({ images: paths }); }, async submitRepair() { const { title, desc, images, submitting } = this.data; if (submitting) return; // 防止重复点击 if (!title.trim() || title.trim().length < 4) { wx.showToast({ title: '标题至少 4 个字', icon: 'none' }); return; } if (!desc.trim() || desc.trim().length < 5) { wx.showToast({ title: '描述至少 5 个字', icon: 'none' }); return; } this.setData({ submitting: true }); try { // 第一步:先传图片,拿到 fileID const fileIDs = []; for (const path of images) { const ext = path.match(/\.(\w+)$/)[1] || 'jpg'; const cloudPath = `repair/${Date.now()}-${Math.random().toString(36).slice(2)}.${ext}`; const uploadRes = await wx.cloud.uploadFile({ cloudPath, filePath: path }); fileIDs.push(uploadRes.fileID); } // 第二步:调云函数写入工单数据 await wx.cloud.callFunction({ name: 'repair-submit', data: { title: title.trim(), desc: desc.trim(), images: fileIDs } }); wx.showToast({ title: '提交成功' }); setTimeout(() => wx.navigateBack(), 800); } catch (e) { console.error('[repair-submit] failed:', e); wx.showToast({ title: '提交失败,请重试', icon: 'none' }); } finally { this.setData({ submitting: false }); } } });图片上传放在云函数外面,是云开发场景下的常见做法。wx.cloud.uploadFile 直接走客户端到云存储,不经过云函数中转,上传速度和稳定性都好很多。云函数只接收 fileID 字符串数组,不会因为图片体积大而触发云函数超时。cloudPath 里拼接时间戳和随机串,是为了避免不同用户上传同名文件时相互覆盖。
注意提交按钮加了 submitting 标志位。游客网络差时连续点提交会创建多条重复工单,这是报修类小程序最常见的脏数据来源。setData 在 try 外部置 true,finally 里复位,保证异常路径也能恢复按钮状态。
3.2 云函数入库:OPENID 校验与 timeline 设计
repair-submit 云函数是工单写入的入口,也是安全边界:
// cloudfunctions/repair-submit/index.js const cloud = require('wx-server-sdk'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); exports.main = async (event) => { const { OPENID } = cloud.getWXContext(); const db = cloud.database(); // 1. 校验用户是否存在且绑定了房屋 const userRes = await db.collection('users') .where({ _openid: OPENID }) .limit(1) .get(); if (userRes.data.length === 0) { return { code: 1001, msg: '用户不存在,请先登录' }; } const { houseId, name, phone } = userRes.data[0]; if (!houseId) { return { code: 1002, msg: '请先绑定房屋再报修' }; } // 2. 基础字段校验 const title = String(event.title || '').trim(); const desc = String(event.desc || '').trim(); if (title.length < 4 || desc.length < 5) { return { code: 1003, msg: '标题或描述太短' }; } // 3. 写入工单 const now = new Date(); const res = await db.collection('repair').add({ data: { _openid: OPENID, houseId, reporter: name, phone: phone || '', title, desc, images: event.images || [], status: 'pending', createTime: now, updateTime: now, timeline: [ { time: now, status: 'pending', note: '业主提交报修' } ] } }); return { code: 0, data: { id: res._id } }; };cloud.getWXContext() 是云函数获取用户身份的官方方式,前端伪造不了,因为 OPENID 由微信侧注入。这里必须用它来定位用户,而不是信任前端传的 userId。用户是否绑定房屋也放在云函数校验,防止有人绕过页面直接构造请求提交没有归属的工单。
timeline 数组初始就写入第一条记录,后续每次状态变更都是追加,不覆盖。这样业主端详情页可以直接展示进度时间线,不用额外做版本管理。createTime 和 updateTime 分开维护,刚创建时两者相等,后面每次处理只改 updateTime。
这里有个细节:数据库里的时间是 Date 对象,云函数返回给前端时会被序列化成 ISO 字符串,小程序端 new Date() 解析没问题。但如果直接 console.log 数据库查询结果,看到的是一串带 T 和 Z 的字符串,不是本地时间格式,排查时别被吓到,这只是云开发的序列化规则。
3.3 物业端状态流转:transaction 与非法流转拦截
业主提交完工单,后续状态由物业后台或管理端操作。这套源码里状态流转收敛到一个云函数,避免各处乱改:
// cloudfunctions/repair-update/index.js const cloud = require('wx-server-sdk'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); exports.main = async (event) => { const { OPENID } = cloud.getWXContext(); const db = cloud.database(); const _ = db.command; const { id, newStatus, remark } = event; if (!id || !newStatus) { return { code: 1001, msg: '缺少必要参数' }; } // 校验操作者是否为物业角色 const operatorRes = await db.collection('users') .where({ _openid: OPENID, role: 'property' }) .count(); if (operatorRes.total === 0) { return { code: 1003, msg: '无操作权限' }; } const transaction = await db.startTransaction(); try { const doc = await transaction.collection('repair').doc(id).get(); if (!doc.data) { await transaction.rollback(); return { code: 404, msg: '工单不存在' }; } // 状态机合法性校验 const allowedNext = { pending: ['processing', 'cancelled'], processing: ['completed', 'cancelled'], completed: ['confirmed'] }; if (!(allowedNext[doc.data.status] || []).includes(newStatus)) { await transaction.rollback(); return { code: 1002, msg: `当前状态不可变更为 ${newStatus}` }; } const now = new Date(); await transaction.collection('repair').doc(id).update({ data: { status: newStatus, remark: remark || '', updateTime: now, timeline: _.push({ time: now, status: newStatus, note: remark || '状态更新' }) } }); await transaction.commit(); return { code: 0, msg: '更新成功' }; } catch (e) { await transaction.rollback(); console.error('[repair-update] error:', e); return { code: 500, msg: '服务器错误' }; } };状态机用对象映射定义流转规则,每个状态只能去往明确列出的目标状态。比如 completed 只能转 confirmed,不能直接跳回 pending,这能挡住客户端乱传参数造成的状态错乱。transaction 保证读取旧状态和写入新状态是原子的,虽然小区工单并发量不大,但极端场景下两个物业同时处理同一工单,有事务保护也不会出现状态覆盖。
这里提一句角色校验:repair-update 云函数里查了 role 字段,只有值为 property 的用户才能操作。但要注意,这套源码的管理端入口比较朴素,没有做独立的后台管理系统,物业人员也是通过同一个小程序登录的。真要上线,建议把物业端页面拆成独立分包,或者至少用自定义登录态区分,别让业主也能调 repair-update 接口。
4. 云开发环境初始化:环境ID、集合权限与云函数部署
源码拿到手,直接编译大概率会报错“环境不存在”或者“collection not found”。原因很简单:源码里的云环境 ID 是作者自己的,数据库集合也不会自动创建。下面按从零到能跑的完整顺序走一遍,照着做十分钟内能跑通。
4.1 导入工程并创建专属云环境
第一步,在微信开发者工具里选择“导入项目”,目录指向解压后的工程根目录。AppID 要填自己的小程序 AppID,不要用测试号,因为云开发能力依赖真实 AppID,测试号无法开通云环境。
第二步,点击工具栏的“云开发”按钮,进入云开发控制台,创建一个新环境。环境名只能包含小写字母、数字和连字符,长度不超过 32 位。建议用项目英文名加环境后缀,比如 community-dev、community-prod,方便后续区分测试环境和生产环境。
第三步,回到 app.js,把 wx.cloud.init 里的 env 替换成自己刚创建的环境 ID。这一步最容易漏,很多人改完集合和云函数,发现数据还是读写不了,最后查了半天发现环境 ID 没换,还在连作者的老环境。
创建环境后,控制台会显示环境 ID 和配额信息。开发期用免费额度足够,但要注意云函数资源使用量、数据库读写次数、存储流量都有每日上限。真机联调加多人测试时,如果当天免费配额耗尽,云函数调用会直接失败,报错看起来像网络问题,其实是你把免费额度用完了。
4.2 创建集合与设置权限
在云开发控制台里找到“数据库”,手动创建集合。需要创建五个:users、house、repair、notice、payment。集合权限建议按下面这张表设置:
| 集合 | 建议权限 | 原因 |
|---|---|---|
| users | 仅管理端可写,所有用户可读 | 用户信息由 login 云函数写入,前端只读自己的 |
| house | 仅管理端可写,所有用户可读 | 房屋数据由物业导入,业主查询绑定需要读 |
| repair | 所有用户可读,仅管理端可写 | 列表展示需要读,写入全走云函数 |
| notice | 所有用户可读,仅管理端可写 | 公告对全员可见,写入只有物业 |
| payment | 仅创建者可读写 | 账单数据敏感,限制前端直接写 |
权限设成“仅管理端可写”之后,前端就不能直接 db.collection('repair').add() 了,所有写操作都必须通过云函数。这正是这套源码推荐的方式:小程序端只负责展示和采集,数据变更全部走云函数,权限集中管理,避免用户绕开业务逻辑直接改库。
另外在 repair 集合里建议加一个组合索引:status 升序加 createTime 降序。云数据库默认只有 _id 和 _openid 的索引,如果列表页要做“按状态筛选 + 按时间排序”,没有组合索引会报索引不存在的错误,或者查询超时。在控制台集合的“索引管理”里添加即可。
4.3 云函数部署与本地调试
cloudfunctions 目录下每个子目录都是一个独立的云函数,需要逐个部署。在开发者工具资源管理器中找到 cloudfunctions,右键每个云函数目录,选择“上传并部署:云端安装依赖”。注意选择“云端安装依赖”,这样云函数在云端自动安装 wx-server-sdk,不需要本地 node_modules。
源码里每个云函数的 package.json 结构大致如下:
{ "name": "repair-submit", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.6.3" } }部署完以后,建议先用云开发控制台的“云函数测试”跑一遍,构造测试事件,比如传入一条 test 数据,确认返回值符合预期。如果测试通过但小程序端调用失败,多半是前端 callFunction 的 name 参数和云函数目录名不一致,这个低频但典型的错误排起来很隐蔽。
本地调试时,开发者工具支持选中云函数后右键“本地调试”,能断点看变量。但本地调试和云端运行有细微差别:本地没有真实用户的 OPENID 上下文,cloud.getWXContext() 拿到的 OPENID 是工具模拟的。所以本地调试通过不代表云端校验一定通过,最终还是要以云端测试为准。
5. 从部署排查智慧社区小程序:5 个常见疑难的现象、原因与处理
这一章是血泪经验集合。社区小程序跑起来不难,但跑稳定经常要跟云开发的几个隐藏坑正面刚。每条按“现象 → 原因 → 解决”写,照排查能省半天时间。
5.1 报修图片上传一直 pending,最后报超时
现象:在开发者工具里选择图片后点提交,wx.cloud.uploadFile 一直转圈,等很久后超时失败。
原因:最常见的是云存储和云函数不在同一个环境。如果你在 app.js 里初始化的是 A 环境,但图片上传代码里又单独指定了 B 环境的 fileID,或者控制台里当前数据库环境切错了,上传链路就会异常。另外,chooseMedia 选择原图时单张可能超过 5MB,免费额度下大文件上传成功率明显下降。
解决:先确认 app.js 的 env 与云开发控制台当前环境一致。图片上传代码里不要写死 env,统一用初始化时的默认环境。选择图片时指定 sizeType: ['compressed'],源码里已经是压缩图,保持这个配置不要改成 original。如果照片确实多,拆分上传并做好重试,不要 for 循环一把梭。
5.2 真机上 callFunction 报错,开发者工具却正常
现象:开发者工具里所有功能都正常,一上真机,报修提交、登录这些调用云函数的功能全部失败,控制台报错类似Error: errCode: -501000。
原因:开发者工具默认有调试模式,会使用工具自带的网络通道,真机上则走微信客户端环境。最常见的原因是云环境 ID 不匹配:app.js 里写的是旧环境,真机访问不到这个环境的数据。另一个原因是小程序基础库版本过低,云开发要求基础库 2.2.3 以上,但真机上用户微信版本老旧时,wx.cloud 能力可能不可用。
解决:不管代码在哪台设备跑,先统一环境 ID。真机调试时打开 vConsole,看具体报错信息里有没有“environment invalid”字样,有就是环境 ID 问题。基础库版本可以在 app.json 里设置 libVersion,但不能强制用户升级微信,代码里做好 wx.cloud 存在性判断,基础库过低时给出友好提示。
5.3 云函数里能查到数据,小程序端 get 却返回空数组
现象:云函数 repair-submit 能正常写入,控制台里也能看到数据,但小程序端直接 db.collection('repair').get() 返回空数组,一条都读不出来。
原因:集合权限设置为“仅管理端可写,所有用户可读”后,前端直接读应该没问题。但如果你把权限设成了“仅创建者可读写”,那前端读取时,云开发会按 _openid 过滤数据。小程序端调用时,_openid 是客户端发起请求的微信用户,而数据是由云函数写入的,云函数写入的数据 _openid 字段可能是操作者的 openid,两边对不上,读出来自然为空。
解决:把列表页的读取全部改成走云函数,在云函数里用管理端权限读取再返回给前端。这套源码的列表页其实应该改成调一个 list 云函数,而不是前端直连集合。云函数端默认拥有管理权限,不受集合权限限制,既能统一做字段裁剪,又能避免权限错位。如果坚持前端直读,就把集合权限调成“所有用户可读”,但要接受所有业主能看到全部工单列表。
5.4 工单状态被跳过,从 pending 直接变成 confirmed
现象:业主提交报修后,物业在小程序里操作,结果工单状态直接从 pending 跳到 confirmed,中间的 processing 和 completed 都没有记录。
原因:客户端页面在“处理工单”时直接调用了 wx.cloud.callFunction 传了新状态,但云函数没有做角色校验,或者被有心的用户直接改了参数。更常见的原因是管理端页面写了个便捷按钮,把“处理中”“已完成”两步合并了,调用 repair-update 时直接传了 confirmed。
解决:云函数里已经有 allowedNext 状态机校验,确认部署的是最新代码。如果状态机逻辑存在,pending 是跳不到 confirmed 的,云函数会返回“非法状态流转”。管理端不要做这种便捷按钮,每一步操作都对应真实线下流程:接单、处理、完成、确认。状态流转必须走 repair-update 云函数,前端页面不允许直接 update 数据库。
5.5 云函数部署后报 module not found: wx-server-sdk
现象:右键云函数选择“云端安装依赖”部署成功后,一调用就报 module 错误,说找不到 wx-server-sdk。
原因:常见有两种。一是部署时选了“不上传 node_modules”,而本地又没有装依赖,云端自然没有包。二是 package.json 格式有误,依赖没写进 dependencies,而是写在了 devDependencies 里。
解决:在开发者工具里检查 package.json,保证 wx-server-sdk 在 dependencies 块里。重新右键云函数目录,选择“上传并部署:云端安装依赖”,这一步会忽略本地 node_modules,在云端执行 npm install。部署完成后打开云开发控制台,在云函数列表里点开该函数,查看文件列表确认 node_modules 存在。检查完依赖后再跑一次测试,报错消失就说明部署正常。
6. 进阶使用:把报事报修升级为工单闭环与满意度回访
这套源码的基础功能能跑通,但要真正改善物业服务质量,报事报修还需要补上最后一段:业主确认后的满意度回访。源码里状态流转到 confirmed 就结束了,而实际物业管理中,超时未处理、维修质量差是投诉高发点。我一般会在 confirmed 状态后增加一个 evaluation 字段,让业主对每次工单打分并留言。
具体做法是在 repair 集合里预设两个字段:score 和 evaluateNote,初始值为空。repair-update 云函数在状态流转到 confirmed 时,不做强制要求,只把状态写进去。然后新增一个云函数 evaluate-submit,接收工单 id 和评分参数,校验该工单属于当前 OPENID,再写入 score 和 evaluateNote。前端在报修详情页根据状态展示一个评分卡片,业主勾选 1 到 5 星并填写备注,提交时调 evaluate-submit 云函数。
云函数里更新工单时,要判断已存在 evaluateNote 就不再覆盖,防止业主重复提交改分。这个字段属于低频写入,不需要做独立集合,挂在 repair 文档上读取时一次拿到,省一次查询。
如果物业还想要超时督办,可以在云函数里再加一个定时触发器,每隔一小时扫描 status 为 processing 且 updateTime 距今超过 48 小时的工单,调用订阅消息模板推送提醒对应物业人员。订阅消息一次性模板需要业务侧先收集用户的 formId 或者使用一次性订阅授权,源码里没有这部分,属于你需要按自己主体认证后补充的功能。
从那以后,我每次接手云开发项目都会先在数据库控制台把所有集合权限截图存档,再开始改代码。云开发的权限模型虽然只分几档,但读写路径一旦交错了,排查成本极高。希望这些拆解和踩坑记录能帮到你,至少在部署这套智慧社区源码时,少走我走过的弯路。
本文还有配套的精品资源,点击获取