微信小程序源碼:繳費(fèi)報修訪客登記完整前端工程)
簡介這是一套面向小區(qū)業(yè)主、業(yè)委會與物業(yè)三方協(xié)同場景的智慧物業(yè)微信小程序完整源碼適合具備一定小程序開發(fā)基礎(chǔ)、希望快速搭建社區(qū)服務(wù)平臺的開發(fā)者參考。它針對物業(yè)事務(wù)繁雜、業(yè)主加班難跑腿的痛點(diǎn)把報修報檢、重大事項(xiàng)投票、活動報名、公告通知、業(yè)委會公示及租售信息查詢等功能集中到線上免去往返物業(yè)中心的麻煩。資源包共559個文件以js業(yè)務(wù)邏輯、wxss樣式、wxml頁面結(jié)構(gòu)、json配置為主另含png、jpg等圖片素材與說明文檔壓縮包約8.4MB采用騰訊小程序云開發(fā)方案無需自備服務(wù)器和域名。目前已有193人學(xué)習(xí)下載。讀者可從中獲得前后端完整代碼、云開發(fā)數(shù)據(jù)調(diào)用思路與頁面組織方式便于二次開發(fā)或作為社區(qū)類小程序的學(xué)習(xí)范本。1. 智慧物業(yè)微信小程序源碼一套能跑通繳費(fèi)、報修、訪客登記的完整前端工程如果你正在接社區(qū)或園區(qū)數(shù)字化的小活大概率繞不開一個需求業(yè)主打開微信就能繳費(fèi)、報修、叫訪客通行。這套智慧物業(yè)微信小程序源碼就是圍繞這三條主線搭起來的前端工程包含頁面結(jié)構(gòu)、組件封裝、接口請求層和本地模擬數(shù)據(jù)。它適合兩類人一類是剛接私活、需要快速交付一個能演示的物業(yè)端小程序另一類是想拆解小程序工程化寫法、看看真實(shí)業(yè)務(wù)頁面怎么組織的中級開發(fā)者。源碼本身不綁定后端接口層做了統(tǒng)一封裝你換成自己的服務(wù)地址就能聯(lián)調(diào)。下面按“先看懂結(jié)構(gòu)、再動手跑起來、最后避開幾個高頻翻車點(diǎn)”的順序拆一遍中間會給出關(guān)鍵配置和代碼片段照著改就能復(fù)現(xiàn)。2. 工程結(jié)構(gòu)與技術(shù)選型為什么用原生小程序而不是跨端框架2.1 目錄分層與頁面職責(zé)拿到源碼先別急著改花十分鐘把目錄過一遍后面改起來才不迷路。這套工程采用原生小程序結(jié)構(gòu)沒有引入 uni-app 或 Taro原因是物業(yè)類小程序頁面數(shù)量有限、交互不復(fù)雜原生方案在包體積和啟動速度上更穩(wěn)也省去跨端編譯的玄學(xué)問題。核心目錄大致是這樣pages/下按業(yè)務(wù)拆分index首頁聚合、pay繳費(fèi)、repair報修、visitor訪客、mine個人中心components/放復(fù)用組件比如card、empty、step-barutils/放請求封裝request.js、格式化工具format.js、常量config.jsmock/放本地模擬數(shù)據(jù)方便沒后端時先跑通頁面每個頁面基本遵循index.js / index.json / index.wxml / index.wxss四件套。index.json里聲明usingComponents和導(dǎo)航欄標(biāo)題index.js里管data、生命周期和事件。理解這個分層后你要加一個新頁面就是復(fù)制一套四件套、在app.json的pages數(shù)組里注冊路徑再在utils/config.js里補(bǔ)接口地址。2.2 請求層封裝與配置項(xiàng)原生小程序直接調(diào)wx.request會寫得很散這套源碼在utils/request.js里做了一層 Promise 封裝統(tǒng)一處理 baseURL、超時、錯誤提示和 token 注入。關(guān)鍵代碼長這樣// utils/request.js const config require(./config.js) function request(options) { return new Promise((resolve, reject) { wx.request({ url: config.baseURL options.url, // 統(tǒng)一拼接域名 method: options.method || GET, data: options.data || {}, header: { content-type: application/json, Authorization: wx.getStorageSync(token) || // 登錄后寫入 }, timeout: 10000, // 超時 10 秒物業(yè)接口普遍不快 success(res) { if (res.statusCode 200 res.data.code 0) { resolve(res.data.data) } else { wx.showToast({ title: res.data.msg || 請求失敗, icon: none }) reject(res.data) } }, fail(err) { wx.showToast({ title: 網(wǎng)絡(luò)異常, icon: none }) reject(err) } }) }) } module.exports request邏輯說明config.baseURL是唯一需要你改的地方指向自己的服務(wù)地址code 0是這套源碼約定的成功碼如果你的后端用200表示成功把判斷改掉即可。參數(shù)上timeout設(shè) 10 秒是因?yàn)槲飿I(yè)繳費(fèi)接口常要查第三方賬單設(shè)太短容易誤報失敗。Authorization從本地緩存取登錄頁寫入 token 后后續(xù)請求自動帶上不用每個頁面手動傳。2.3 本地模擬數(shù)據(jù)怎么切換沒有后端時mock/目錄下的數(shù)據(jù)文件可以直接被頁面引用。切換方式是改utils/config.js里的一個開關(guān)// utils/config.js module.exports { baseURL: https://your-domain.com/api, // 換成你的服務(wù)地址 useMock: true // true 走本地模擬false 走真實(shí)接口 }頁面里判斷useMock決定是require模擬數(shù)據(jù)還是調(diào)request。這個設(shè)計的好處是演示階段不用等后端先把頁面和交互跑通聯(lián)調(diào)時把開關(guān)一關(guān)就行。注意模擬數(shù)據(jù)的字段結(jié)構(gòu)要和真實(shí)接口保持一致否則切換時會冒出一堆undefined。3. 繳費(fèi)與報修模塊從頁面交互到接口聯(lián)調(diào)的完整鏈路3.1 繳費(fèi)頁的賬單渲染與支付調(diào)用繳費(fèi)是物業(yè)小程序里最核心也最容易出問題的模塊。這套源碼的繳費(fèi)頁分兩塊賬單列表和支付按鈕。賬單數(shù)據(jù)從接口拉取后按status字段區(qū)分“待繳”和“已繳”渲染時用wx:if控制按鈕顯隱。核心邏輯如下// pages/pay/index.js const request require(../../utils/request.js) Page({ data: { billList: [], total: 0 }, onLoad() { this.fetchBills() }, fetchBills() { request({ url: /property/bills, method: GET }) .then(list { const total list .filter(item item.status unpaid) .reduce((sum, item) sum item.amount, 0) // 匯總待繳金額 this.setData({ billList: list, total }) }) .catch(() {}) }, onPay(e) { const billId e.currentTarget.dataset.id request({ url: /property/pay, method: POST, data: { billId } }) .then(res { // res 里應(yīng)包含 wx.requestPayment 所需參數(shù) wx.requestPayment({ timeStamp: res.timeStamp, nonceStr: res.nonceStr, package: res.package, signType: MD5, paySign: res.paySign, success: () { wx.showToast({ title: 繳費(fèi)成功, icon: success }) this.fetchBills() // 重新拉取刷新狀態(tài) }, fail: () { wx.showToast({ title: 支付取消, icon: none }) } }) }) } })邏輯說明fetchBills拉取賬單后用filter加reduce算出待繳總額避免在 wxml 里做復(fù)雜計算。onPay先請求后端下單接口拿到支付參數(shù)再調(diào)wx.requestPayment。參數(shù)上signType常見是MD5或HMAC-SHA256要和后端簽名方式一致不一致會報“支付簽名驗(yàn)證失敗”。支付成功后重新拉賬單而不是本地改狀態(tài)防止和后端數(shù)據(jù)不一致。3.2 報修工單的表單校驗(yàn)與圖片上傳報修模塊的難點(diǎn)在表單校驗(yàn)和圖片上傳。源碼里報修頁包含報修類型選擇、描述輸入、圖片上傳三部分。圖片上傳用wx.chooseImage加wx.uploadFile先傳到文件服務(wù)拿到 URL再隨工單一起提交。關(guān)鍵片段// pages/repair/index.js Page({ data: { typeIndex: 0, types: [水電, 門窗, 電梯, 其他], desc: , imgList: [] }, chooseImage() { wx.chooseImage({ count: 3, // 最多 3 張物業(yè)工單夠用 sizeType: [compressed], // 壓縮圖省流量 success: res { this.setData({ imgList: this.data.imgList.concat(res.tempFilePaths) }) } }) }, submit() { if (!this.data.desc.trim()) { wx.showToast({ title: 請?zhí)顚憜栴}描述, icon: none }) return } // 先上傳圖片再提交工單 const uploadTasks this.data.imgList.map(path { return new Promise((resolve, reject) { wx.uploadFile({ url: https://your-domain.com/api/upload, filePath: path, name: file, success: res resolve(JSON.parse(res.data).url), fail: reject }) }) }) Promise.all(uploadTasks).then(urls { return request({ url: /property/repair, method: POST, data: { type: this.data.types[this.data.typeIndex], desc: this.data.desc, images: urls } }) }).then(() { wx.showToast({ title: 提交成功, icon: success }) wx.navigateBack() }) } })邏輯說明count: 3限制圖片數(shù)量避免用戶傳十幾張導(dǎo)致上傳超時。sizeType: [compressed]用壓縮圖物業(yè)場景不需要原圖。提交時先用Promise.all并發(fā)上傳所有圖片拿到 URL 數(shù)組后再提交工單保證工單里存的是可訪問的圖片地址而不是本地臨時路徑。參數(shù)上name: file要和后端接收字段名一致不一致后端收不到文件。3.3 訪客登記與通行碼生成訪客模塊相對輕核心是生成一個帶時效的通行碼。源碼里用時間戳加隨機(jī)數(shù)拼一個碼展示在頁面上同時提交給后端記錄。這里要注意的是通行碼的有效期常見做法是設(shè) 24 小時過期后頁面提示失效。實(shí)現(xiàn)上onLoad時請求后端生成碼頁面用setInterval倒計時刷新剩余時間離開頁面時clearInterval否則會內(nèi)存泄漏。4. 避坑與排查這套源碼落地時最容易翻車的五個點(diǎn)4.1 域名未配置導(dǎo)致請求全部失敗現(xiàn)象真機(jī)預(yù)覽時所有接口報“網(wǎng)絡(luò)異常”開發(fā)者工具里卻正常。原因小程序正式環(huán)境要求請求域名在后臺白名單里開發(fā)者工具可以勾選“不校驗(yàn)合法域名”繞過真機(jī)不行。解決把baseURL的域名加到小程序后臺的 request 合法域名列表注意必須是 HTTPS且不能帶端口號除非是 443。4.2 支付簽名參數(shù)對不上現(xiàn)象調(diào)wx.requestPayment報“支付簽名驗(yàn)證失敗”。原因后端簽名用的signType和前端傳的不一致或者timeStamp類型不對有的后端返回數(shù)字小程序要求字符串。解決確認(rèn)前后端signType統(tǒng)一timeStamp用String()轉(zhuǎn)一下package字段格式是prepay_idxxx別漏了前綴。4.3 圖片上傳后路徑失效現(xiàn)象工單提交成功但詳情頁圖片打不開。原因上傳接口返回的是臨時路徑或者前端把tempFilePaths直接存進(jìn)了數(shù)據(jù)庫。解決上傳接口必須返回可長期訪問的 URL前端提交前確認(rèn)拿到的是這個 URL 而不是本地臨時路徑。常見做法是上傳后JSON.parse(res.data)取url字段。4.4 setData 頻繁調(diào)用導(dǎo)致頁面卡頓現(xiàn)象賬單列表滾動時明顯掉幀。原因在循環(huán)里頻繁setData或者一次setData的數(shù)據(jù)量過大。解決把多次setData合并成一次列表渲染用wx:key指定唯一字段避免整個列表重繪。數(shù)據(jù)量大時考慮分頁加載別一次性渲染幾百條。4.5 本地緩存 token 過期未處理現(xiàn)象用戶登錄一段時間后所有接口報 401但頁面沒跳登錄。原因請求層沒處理 401 狀態(tài)碼token 過期后直接失敗。解決在request.js的success里判斷statusCode 401清除本地 token 并跳轉(zhuǎn)登錄頁。這個邏輯要放在統(tǒng)一封裝里別每個頁面寫一遍。5. 進(jìn)階技巧用分包和骨架屏把首屏體驗(yàn)拉起來源碼默認(rèn)是單包結(jié)構(gòu)頁面一多主包體積容易超限。小程序主包限制 2MB物業(yè)類項(xiàng)目加上圖片資源很容易頂?shù)缴舷?。進(jìn)階做法是把報修、訪客這類非首屏頁面拆到分包里主包只留首頁、繳費(fèi)和個人中心。配置在app.json里加subpackages字段每個分包聲明root和pages。拆完后主包體積能降三成左右啟動速度肉眼可見變快。另一個技巧是骨架屏。物業(yè)首頁要等接口返回才能渲染白屏?xí)r間長了用戶會以為卡死。源碼里首頁預(yù)留了骨架屏結(jié)構(gòu)接口返回前顯示灰色占位塊返回后替換成真實(shí)內(nèi)容。實(shí)現(xiàn)方式是用一個loading狀態(tài)控制wx:if切換骨架屏的 wxml 就是幾個灰色view加animation做呼吸效果。這個改動不大但演示時觀感提升明顯。驗(yàn)證分包是否生效可以在開發(fā)者工具的“代碼依賴分析”里看主包和分包體積。驗(yàn)證骨架屏把useMock關(guān)掉、接口故意延遲幾秒看首頁是不是先出灰塊再出內(nèi)容。這兩個點(diǎn)做完這套源碼的完成度就夠拿去給客戶演示了。從那以后我每次拿到小程序源碼都先跑一遍分包體積分析和首屏白屏?xí)r間這兩個指標(biāo)不過關(guān)后面功能寫得再全也白搭。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取