農(nóng)產(chǎn)品交易小程序開發(fā)實踐)
簡介本資源是一套完整的云浮市特色農(nóng)產(chǎn)品交易微信小程序畢業(yè)設(shè)計項目面向計算機(jī)專業(yè)本科生、自學(xué)開發(fā)者及工程實訓(xùn)學(xué)習(xí)者解決農(nóng)產(chǎn)品線上交易系統(tǒng)從需求分析到部署落地的全流程實踐問題。壓縮包共含可運(yùn)行源碼、SQL建表腳本與配套文檔三類核心文件總大小38.34MB其中Spring Boot后端JDK8Tomcat7MySQL5.7提供RESTful接口UniAppVue前端實現(xiàn)跨平臺小程序界面與交互邏輯代碼經(jīng)調(diào)試可直接運(yùn)行。已有80人學(xué)習(xí)下載適合作為課程設(shè)計、大作業(yè)或畢設(shè)基礎(chǔ)框架支持二次開發(fā)與功能擴(kuò)展。資源結(jié)構(gòu)清晰包含完整前后端分離架構(gòu)、數(shù)據(jù)庫初始化腳本及部署說明便于理解電商類系統(tǒng)的技術(shù)選型與模塊劃分特別適合掌握J(rèn)ava全棧開發(fā)與小程序跨端實踐的學(xué)習(xí)者快速上手。 說實話看到“基于微信小程序的云浮市特色農(nóng)產(chǎn)品交易”這個題目時我第一反應(yīng)是這不就是一個農(nóng)產(chǎn)品版的電商小程序嗎SpringBoot做后端、Vue做管理后臺、uniapp做小程序端三件套一搭頁面一比劃功能一填這事就成了。但真動手做下來才發(fā)現(xiàn)這類項目表面上是把幾個框架串起來實際上破事比想象中多得多。我是把它當(dāng)成一個真正要上線的云浮特產(chǎn)電商平臺來做的。云浮的特產(chǎn)——羅定稻米、新興涼果、郁南無核黃皮、砂糖橘——都是有地域標(biāo)簽的農(nóng)產(chǎn)品不是工業(yè)流水線上的標(biāo)準(zhǔn)品這就決定了它在商品管理、庫存單位、訂單履約上都和普通的電商模板有差別。這篇文章把整個項目的設(shè)計思路和實現(xiàn)過程完整理一遍包括為什么選uniapp而不是原生小程序、三端之間的數(shù)據(jù)流怎么設(shè)計、數(shù)據(jù)庫里的訂單狀態(tài)機(jī)怎么流轉(zhuǎn)、以及真機(jī)聯(lián)調(diào)時那些讓人抓狂的坑希望能給正在做同類項目的朋友一些實際參考。1. 從“三端分離”看技術(shù)選型uniapp、SpringBoot、Vue各自解決什么問題1.1 為什么不是原生微信小程序而是uniapp這個項目雖然標(biāo)題是“基于微信小程序”但我最終選擇用uniapp來做小程序端。原因很簡單uniapp寫一套代碼能同時編譯成微信小程序、H5和Android/iOS的App。云浮特產(chǎn)這種項目通常做完小程序之后下一步就是想要一個給農(nóng)戶用的App端或者想在公眾號里嵌一個H5商城。如果一開始用原生微信小程序后面這些擴(kuò)展都得重新寫一遍用uniapp大部分代碼可以復(fù)用。但這不代表uniapp沒有代價。最明顯的就是uniapp編譯到微信小程序時它是在運(yùn)行時套了一層框架部分原生組件、基礎(chǔ)庫API的行為會有差異。比如微信原生的wx.getMenuButtonBoundingClientRect在uniapp里得用條件編譯#ifdef MP-WEIXIN包一層才能拿到膠囊按鈕的位置。這類跨端適配問題后面章節(jié)會詳細(xì)說。1.2 SpringBoot后端不是“寫接口”那么簡單SpringBoot在這個項目里是純后端API服務(wù)但它的職責(zé)比“提供幾個增刪改查接口”要重得多。農(nóng)產(chǎn)品交易平臺涉及小程序端用戶、農(nóng)戶/商家端、平臺管理員三類角色登錄態(tài)怎么維持、訂單狀態(tài)怎么流轉(zhuǎn)、支付回調(diào)怎么處理、文件上傳怎么管理全都要在后端做統(tǒng)一設(shè)計。技術(shù)棧上我選了SpringBoot 2.7.x MyBatis-Plus MySQL。這里有個很實際的版本陷阱SpringBoot 3.x要求JDK17很多教程和舊版依賴比如某些版本的MyBatis-Plus、Druid連接池不兼容啟動直接報錯。我做項目時吃過這個虧后來老老實實回到2.7.x資料多網(wǎng)上的坑基本都有答案對于交付周期短的項目來說穩(wěn)定比新版本重要。1.3 Vue管理后臺工作量不比小程序少很多人覺得管理后臺就是幾個表格頁面隨便寫寫就行。實際上這個項目里管理后臺是運(yùn)營的核心工具商品審核、上下架、訂單發(fā)貨、退款處理、數(shù)據(jù)統(tǒng)計全在后臺完成。Vue端遇到的高頻問題反而不是框架本身而是和業(yè)務(wù)相關(guān)的狀態(tài)管理、權(quán)限控制、跨域聯(lián)調(diào)。管理后臺采用Vue3 Vite Element Plus。如果參考的課程設(shè)計資料都是Vue2 Element UI的老教程也可以選Vue2.7不建議兩頭搖擺。管理端頁面功能相對固定能否跑通業(yè)務(wù)閉環(huán)比技術(shù)棧新舊重要得多。2. 農(nóng)產(chǎn)品交易系統(tǒng)的業(yè)務(wù)模型設(shè)計不是普通電商的縮小版2.1 用戶角色與核心業(yè)務(wù)流云浮特色農(nóng)產(chǎn)品交易平臺的核心角色分三類普通消費(fèi)者、農(nóng)戶/商家、平臺管理員。普通消費(fèi)者在小程序端逛商品、下單、支付、評價農(nóng)戶在小程序端或后臺維護(hù)商品、處理訂單、發(fā)貨管理員在Vue后臺審核商品、管理用戶、看數(shù)據(jù)。這三類角色的功能差異直接在菜單和接口權(quán)限上體現(xiàn)出來。小程序端給消費(fèi)者用不做商家入駐功能商家管理功能放在管理后臺的獨立模塊里管理員擁有全部權(quán)限。角色權(quán)限用SpringBoot攔截器 JWT實現(xiàn)Vue端再用路由守衛(wèi)控制頁面訪問兩層都要做不能只靠前端隱藏菜單。核心業(yè)務(wù)流是瀏覽商品 → 加入購物車 → 提交訂單 → 支付 → 商家發(fā)貨 → 確認(rèn)收貨 → 評價。農(nóng)產(chǎn)品交易比普通電商多一個“發(fā)貨時效”問題因為生鮮類商品對物流要求高所以訂單在“待發(fā)貨”狀態(tài)要顯示發(fā)貨倒計時超時后用戶可申請平臺介入這是農(nóng)產(chǎn)品平臺的常見需求。2.2 數(shù)據(jù)庫表設(shè)計的幾個關(guān)鍵決策數(shù)據(jù)庫設(shè)計是整個項目的地基。核心表包括用戶表、商品表、商品分類表、購物車表、訂單表、訂單明細(xì)表、收貨地址表、輪播圖表、公告表、評價表。有幾個關(guān)鍵點值得單獨說。第一個是庫存單位。農(nóng)產(chǎn)品的庫存單位不是統(tǒng)一的“件”而是斤、箱、份、袋。比如羅定稻米按袋賣郁南無核黃皮按斤賣新興涼果按盒賣。如果商品表只存一個stock字段下單時很難判斷“5斤黃皮”和“1箱涼果”哪個庫存充足。我的做法是在商品表加一個unit字段下單數(shù)量統(tǒng)一在業(yè)務(wù)層做換算前端商品詳情頁根據(jù)單位展示價格和購買數(shù)量。第二個是訂單狀態(tài)機(jī)。訂單狀態(tài)不能只用幾個字符串字段隨意改要在后端定義明確的狀態(tài)流轉(zhuǎn)規(guī)則。我用的狀態(tài)枚舉是待支付(0) → 已支付/待發(fā)貨(1) → 已發(fā)貨(2) → 已完成(3)加上已取消(4)和退款中(5)。每個狀態(tài)的可達(dá)狀態(tài)在代碼里寫死比如“待支付”只能轉(zhuǎn)“已支付”或“已取消”“已發(fā)貨”不能直接改成“已完成”而不走“確認(rèn)收貨”。這樣能避免很多臟數(shù)據(jù)。當(dāng)前狀態(tài)允許跳轉(zhuǎn)狀態(tài)觸發(fā)動作待支付已支付、已取消支付成功回調(diào) / 用戶取消或超時已支付已發(fā)貨商家發(fā)貨已發(fā)貨已完成用戶確認(rèn)收貨已完成無不可逆已取消無不可逆第三個是收貨地址冗余。小程序端可以用微信的收貨地址能力獲取用戶地址但正式下單時要把省市區(qū)和詳細(xì)地址冗余存儲到訂單表里。為什么因為用戶后續(xù)修改默認(rèn)地址時歷史訂單的收貨信息不應(yīng)該跟著變。如果訂單表只存address_id一旦用戶改地址歷史訂單的發(fā)貨地址全亂了。這是做電商項目非常容易忽略的坑。第四個是商品圖片。農(nóng)產(chǎn)品需要多圖展示比如果實特寫、產(chǎn)地實拍、包裝圖。我的方案是商品表存一個主圖URL字段另外建一張product_image表存多圖列表。也可以用JSON字段直接存URL數(shù)組但后期如果要做圖片懶加載、縮略圖裁剪還是獨立表更靈活。3. 小程序端實現(xiàn)細(xì)節(jié)頁面骨架、視頻播放、地圖選型和分享邏輯3.1 tabBar頁面結(jié)構(gòu)與頂部導(dǎo)航欄適配小程序端頁面結(jié)構(gòu)是這樣規(guī)劃的底部tabBar四個頁面——“首頁”“分類”“購物車”“我的”其余頁面如商品詳情、搜索、結(jié)算、訂單列表全部作為普通頁面跳轉(zhuǎn)。頁面結(jié)構(gòu)定了先做的是導(dǎo)航欄適配。微信小程序的導(dǎo)航欄分為默認(rèn)導(dǎo)航和自定義導(dǎo)航兩種。如果想讓首頁更美觀把搜索框和輪播圖做得更有設(shè)計感就需要自定義導(dǎo)航欄這時候必須處理一個經(jīng)典問題頂部導(dǎo)航欄高度。自定義導(dǎo)航欄時navigationStyle設(shè)為custom之后要在頁面里手動留出狀態(tài)欄和導(dǎo)航欄高度。計算方式如下// #ifdef MP-WEIXIN const info uni.getSystemInfoSync() const menu wx.getMenuButtonBoundingClientRect() // 狀態(tài)欄高度 const statusBarHeight info.statusBarHeight // 導(dǎo)航欄高度 (膠囊頂部 - 狀態(tài)欄高度) * 2 膠囊高度 const navHeight (menu.top - statusBarHeight) * 2 menu.height // #endif這個公式很多人不理解簡單解釋微信膠囊按鈕的垂直位置和導(dǎo)航欄高度不是簡單的“上下留白”。狀態(tài)欄到膠囊按鈕頂部的距離等于膠囊按鈕底部到導(dǎo)航欄底部的距離所以導(dǎo)航欄高度 膠囊按鈕高度 上下兩個等距留白。我在iPhone 14和某些安卓機(jī)上實測過這個公式計算出來的高度基本是準(zhǔn)的。真機(jī)上還有底部安全區(qū)問題尤其iPhone的Home Indicator。頁面底部留白要加padding-bottom: env(safe-area-inset-bottom)否則“提交訂單”按鈕會被手勢條擋住。3.2 商品詳情頁的圖片、視頻與PDF預(yù)覽農(nóng)產(chǎn)品詳情頁的信息密度比普通商品高除了主圖、價格、規(guī)格、庫存還要展示產(chǎn)地實拍、果樹生長過程、檢測報告。這里會涉及到三類文件的預(yù)覽。圖片預(yù)覽最簡單uniapp里用uni.previewImage傳一個圖片URL數(shù)組支持左右滑動查看大圖不用自己寫縮放邏輯。視頻這塊要特別注意。微信小程序的video組件支持HLSm3u8播放所以產(chǎn)地果園的實時監(jiān)控或宣傳視頻如果服務(wù)端能輸出m3u8流小程序端可以直接播放。但rtsp流不行微信小程序沒有原生rtsp播放能力。我做項目時試過直接用video組件播rtsp的地址結(jié)果在開發(fā)者工具里就有兼容性提示真機(jī)上完全黑屏。解決方案是后端用ffmpeg把rtsp流轉(zhuǎn)成hls切片ffmpeg -i rtsp://your_camera_stream -c:v copy -c:a copy -f hls -hls_time 4 -hls_list_size 10 stream.m3u8如果只是做演示不用實時監(jiān)控那就更簡單直接把.mp4文件傳到服務(wù)器video組件就能播。PDF預(yù)覽是另一個高頻需求農(nóng)產(chǎn)品的農(nóng)藥殘留檢測報告、綠色食品認(rèn)證一般都導(dǎo)出成PDF。小程序端不能用iframe直接嵌網(wǎng)頁我用的方案是uni.downloadFile下載PDF到臨時目錄再用uni.openDocument打開。注意uni.openDocument只支持打開本地文件路徑不能直接傳遠(yuǎn)程URL。3.3 地圖組件內(nèi)置map、騰訊地圖SDK還是天地圖這個項目的商品詳情和自提點頁面需要地圖展示比如展示產(chǎn)地位置、配送范圍。我一開始直接用微信小程序內(nèi)置的map組件在開發(fā)者工具里一切正常但真機(jī)上問題來了map是原生組件層級高于普通組件頁面里的彈窗、下拉框、懸浮按鈕都會被地圖蓋住。安卓機(jī)上尤其明顯地圖直接遮擋住商品詳情頁的價格欄。解決方案有三個方向用cover-view和cover-image覆蓋在map上層。但cover-view的樣式支持有限復(fù)雜布局很難實現(xiàn)。在新版本基礎(chǔ)庫中map組件的同層渲染能力有所改善但不是所有機(jī)型都穩(wěn)定。放棄內(nèi)置map改用地圖服務(wù)商的小程序SDK。比如騰訊位置服務(wù)的小程序SDK它提供的是普通組件不存在原生組件層級遮擋問題能直接渲染到頁面上樣式控制也更自由。關(guān)于天地圖確實有用戶問“微信小程序可以使用天地圖畫地圖組件嗎”。天地圖主要提供Web端API微信小程序沒有內(nèi)置天地圖組件。想用的話一般是通過web-view嵌入天地圖的Web頁面但這樣和原生頁面交互不方便而且web-view里的地圖圖層是網(wǎng)頁渲染性能和體驗都打折。實際做項目展示產(chǎn)地位置、配送范圍這類輕量需求我更推薦騰訊地圖或高德地圖的小程序SDK。華為鴻蒙端的兼容性也要提前看部分地圖SDK的鴻蒙適配晚于安卓開發(fā)前要確認(rèn)版本。3.4 分包加載、自定義分享與社交裂變場景小程序主包體積限制是2MB超過就必須分包。這個項目把商品詳情、商品搜索、結(jié)算頁面、訂單列表放到了分包里主包只保留tabBar頁面和公共組件。如果用到分包異步化——也就是在某個分包中的自定義組件被另一個分包引用時異步加載——要注意基礎(chǔ)庫版本要求是2.20.2以上。開發(fā)者工具里看著沒問題真機(jī)上如果基礎(chǔ)庫版本過低分包異步化的組件會加載失敗頁面直接白屏。分享功能對農(nóng)產(chǎn)品電商特別重要。云浮特產(chǎn)有很強(qiáng)的社交屬性用戶買到好吃的黃皮大概率會分享給朋友。自定義分享可以用onShareAppMessage實現(xiàn)返回標(biāo)題、圖片路徑、跳轉(zhuǎn)路徑。我在跳轉(zhuǎn)路徑里帶了一個inviterId參數(shù)用戶從分享鏈接進(jìn)入小程序后后端能識別推薦人做“好友助力”“拼團(tuán)優(yōu)惠”這類裂變玩法。這個設(shè)計在答辯時是很加分的亮點。4. SpringBoot后端接口設(shè)計、登錄態(tài)、文件上傳與部署問題4.1 統(tǒng)一響應(yīng)體和全局異常搭一個能長期維護(hù)的接口框架三端聯(lián)調(diào)時接口返回格式不統(tǒng)一是大坑。小程序端、Vue后臺、還有可能對接的第三方物流接口如果每個接口返回結(jié)構(gòu)都不一樣前端解析邏輯會寫得非常痛苦。我的做法是定義統(tǒng)一響應(yīng)體public class ResultT { private Integer code; private String msg; private T data; // getter/setter 省略 }成功返回code200業(yè)務(wù)失敗返回code400未登錄返回code401服務(wù)器異常返回code500。controller層不直接返回Map或裸數(shù)據(jù)全部包裝成Result。配合全局異常處理器把參數(shù)校驗異常、業(yè)務(wù)異常、未知異常統(tǒng)一攔截這樣前端只需要看code字段就能知道請求狀態(tài)不需要每個接口單獨判斷。接口文檔我用的是Knife4jSwagger的增強(qiáng)版。生成接口文檔后小程序端和Vue端可以并行開發(fā)不用等后端寫完再聯(lián)調(diào)。這里有個經(jīng)驗接口文檔不僅給團(tuán)隊看等答辯或?qū)懳臋n時把接口截圖放進(jìn)說明書里能省很多事。4.2 登錄態(tài)與接口安全JWT到底怎么用小程序端登錄不能直接用賬號密碼微信生態(tài)的標(biāo)準(zhǔn)流程是小程序端wx.login拿到code后端用appid和secret去微信的code2session接口換取openid再用openid生成本系統(tǒng)的token返回給前端。后續(xù)請求在請求頭里帶上token后端攔截器校驗。token我這里用的是JWT而不是傳統(tǒng)session原因是管理后臺和小程序端都可能要用JWT無狀態(tài)適合接口分離架構(gòu)。JWT里只放userId和角色信息不存敏感信息過期時間設(shè)置7天。攔截器做一個白名單配置登錄接口、商品瀏覽接口、輪播圖接口放行其他接口全部校驗token。管理后臺的登錄是獨立的一套賬號密碼體系登錄成功后同樣簽發(fā)JWT。Vue端用路由守衛(wèi)判斷本地有沒有token沒有就跳登錄頁。這里提醒一句前端路由守衛(wèi)只是用戶體驗層面的控制真正的權(quán)限校驗必須在后端做否則別人直接調(diào)接口繞過頁面限制數(shù)據(jù)就裸奔了。接口安全還有一個場景如果平臺要和第三方物流系統(tǒng)或支付系統(tǒng)對接可以用API Key 時間戳 簽名的機(jī)制。每次請求帶上appKey、timestamp和signsign HMAC-MD5(appKey timestamp secret)。服務(wù)端用同樣的算法算一次簽名比對一致才放行。簽名里必須帶時間戳并校驗過期時間防重放攻擊。4.3 農(nóng)產(chǎn)品圖片上傳、PDF的XSS風(fēng)險與搜索分詞商品圖片上傳是基礎(chǔ)功能。上傳到本地服務(wù)器時要注意三點一是在application.yml里配置靜態(tài)資源映射否則上傳后訪問不到文件二是限制上傳大小和文件類型圖片只允許jpg、png、webp三是對文件名做重命名避免用戶上傳的文件名包含特殊字符。PDF預(yù)覽功能涉及XSS風(fēng)險。如果后臺允許上傳PDF并且前端用web-view直接預(yù)覽惡意PDF里可以嵌入JavaScript腳本。在這個項目里我的做法是上傳PDF時校驗文件類型和魔數(shù)存儲時給PDF文件設(shè)置獨立的訪問目錄并配置Content-Disposition: attachment讓瀏覽器優(yōu)先下載而不是在頁面內(nèi)渲染。預(yù)覽時用uni.openDocument獨立打開不嵌入業(yè)務(wù)頁面。搜索功能如果只用SQL的LIKE %黃皮%用戶搜索“無核黃皮”時能匹配但搜索“黃皮果”可能就匹配不到。要提升搜索體驗可以集成HanLP分詞庫。在SpringBoot里引入hanlp依賴后對商品名稱做分詞把分詞結(jié)果存到一個搜索索引字段用戶搜索時先分詞再匹配。當(dāng)然這個項目如果數(shù)據(jù)量不大LIKE模糊查詢基本夠用分詞功能屬于進(jìn)階優(yōu)化。4.4 Linux部署從jar包到Nginx反向代理開發(fā)環(huán)境和部署環(huán)境是兩碼事。開發(fā)時用的application-dev.yml可以直連本地數(shù)據(jù)庫但部署到Linux服務(wù)器時要用application-prod.yml區(qū)分環(huán)境。數(shù)據(jù)庫密碼不能明文寫死在配置文件里用環(huán)境變量注入spring: datasource: url: jdbc:mysql://${DB_HOST}:3306/yunfu_shop?useUnicodetruecharacterEncodingutf8mb4useSSLfalse username: ${DB_USERNAME} password: ${DB_PASSWORD}啟動命令是經(jīng)典的nohup java -jar yunfu-shop-0.0.1.jar --spring.profiles.activeprod app.log 21 前端這邊Vue后臺構(gòu)建后生成dist目錄放到Nginx的html目錄下。Nginx配置兩個關(guān)鍵點一個是try_files處理Vue路由的history模式否則刷新頁面會404另一個是接口反向代理將/api前綴的請求轉(zhuǎn)發(fā)到SpringBoot端口server { listen 443 ssl; server_name yourdomain.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }日志排查方面SpringBoot用logback按天滾動日志每次接口報錯先看app.log里有沒有堆棧。做一次完整部署比看十篇部署教程都管用。5. Vue管理后臺商品、訂單和農(nóng)戶數(shù)據(jù)的可視化管理5.1 Vue3和Vue2怎么選管理后臺的技術(shù)選型我的建議很簡單如果你熟悉組合式API和現(xiàn)代前端生態(tài)用Vue3 Vite Element Plus如果你參考的老教程、老項目都是Vue2 Element UI直接用Vue2.7不要為了追新而兩頭踩坑。為什么管理后臺的核心價值是業(yè)務(wù)功能完整不是技術(shù)棧新。你花兩天時間在Vue3的生態(tài)適配問題上不如把這兩天用來把商品管理、訂單流程做扎實。我在項目里用Vue3主要原因是Element Plus的組件質(zhì)量和后續(xù)維護(hù)性更好而且和Vite的構(gòu)建速度搭配很舒服。5.2 管理端核心頁面拆解管理后臺的主要頁面按重要程度排序商品管理。商品列表、上下架、編輯、審核。列表頁要支持按商品名稱、分類、狀態(tài)篩選表格里能直接改庫存和價格。商品上架前有審核流程審核通過才在小程序端展示。訂單管理。訂單列表、訂單詳情、發(fā)貨操作、退款處理。列表要按狀態(tài)Tab切換方便運(yùn)營快速看到待發(fā)貨訂單。發(fā)貨操作需要填寫物流公司、物流單號。用戶管理。區(qū)分普通用戶和農(nóng)戶。普通用戶列表展示注冊信息、訂單數(shù)量農(nóng)戶列表展示入駐狀態(tài)、在售商品數(shù)。管理員可以對違規(guī)用戶禁用賬號。數(shù)據(jù)統(tǒng)計。一個Dashboard頁面展示今日訂單數(shù)、交易金額、商品銷量Top10、訂單趨勢折線圖。這個頁面是答辯時的視覺亮點建議用ECharts實現(xiàn)。5.3 computed與watch的正確姿勢一個價格計算的實例Vue端一個很經(jīng)典的業(yè)務(wù)場景運(yùn)營在后臺設(shè)置農(nóng)產(chǎn)品活動價要同時填寫原價、折扣率、實際售價三個字段。用戶改原價或折扣率后實際售價自動計算如果實際售價低于成本價要給出提示。這個場景正好能用computed和watch的對比來說明。實際售價應(yīng)該用computed計算因為它是由原價和折扣率派生出來的狀態(tài)computed有緩存依賴的原價或折扣率變化時才重新計算。而watch適合用來處理“價格低于成本價時彈出警告”這種副作用場景// price為一個響應(yīng)式對象 const finalPrice computed(() { return (price.original * price.discount / 10).toFixed(2) }) watch(() price.original, (newVal) { if (newVal price.costPrice) { ElMessage.warning(原價不能低于成本價) } })這個例子在面試和答辯時很好用因為很多人說不清楚computed和watch的區(qū)別。一句話總結(jié)computed根據(jù)已有的響應(yīng)式數(shù)據(jù)派生出新值watch監(jiān)聽已有數(shù)據(jù)的變化再去做一件事。6. 跨端聯(lián)調(diào)與部署的高頻坑點白屏、手勢返回、地圖遮擋和抓包調(diào)試6.1 同樣一套代碼為什么開發(fā)者工具和真機(jī)表現(xiàn)不一樣我在做這個項目的過程中遇到過“uniapp在手機(jī)上預(yù)覽沒問題但在微信開發(fā)者工具里白屏”的情況。注意這里和常見的“真機(jī)白屏”相反但同樣值得排查。開發(fā)者工具白屏最常見的原因是這兩個第一個是基礎(chǔ)庫版本不一致。開發(fā)者工具默認(rèn)使用較新版本的基礎(chǔ)庫但如果你給某個頁面配置了低版本兼容或者使用了高版本才支持的API工具里可能直接渲染失敗。這時候先在“詳情-本地設(shè)置”里切換基礎(chǔ)庫版本找到能正常顯示的那個版本。第二個是配置文件編譯問題。uniapp項目在開發(fā)者工具里白屏很多情況下是pages.json的頁面路徑配置有誤或者某個頁面文件里引入了不存在的組件。開發(fā)者工具的編譯錯誤日志不一定顯眼但打開控制臺看運(yùn)行時錯誤基本能找到線索。真機(jī)白屏的常見原因則不同90%是因為小程序后臺的request合法域名沒配置。開發(fā)者工具有“不校驗合法域名”的開關(guān)所以工具里能請求接口真機(jī)上請求直接被攔截頁面數(shù)據(jù)拿不到看起來就是白屏。6.2 安卓手勢返回導(dǎo)致應(yīng)用退出的排查鏈路這是另一個讓我印象深刻的坑uniapp編譯成App后在部分安卓手機(jī)上從二級頁面手勢返回時應(yīng)用直接退出了。用戶重新打開再手勢返回又退出反復(fù)幾次后頁面才恢復(fù)正常。這個問題的根因在于uniapp在小程序端維護(hù)自己的頁面棧但編譯成App后安卓系統(tǒng)的手勢返回會和頁面棧的pop行為產(chǎn)生沖突。如果二級頁面是直接用uni.redirectTo跳轉(zhuǎn)的頁面棧里沒有留下可返回的頁面系統(tǒng)手勢返回時找不到上一頁就觸發(fā)了應(yīng)用級退出。解決辦法是統(tǒng)一頁面跳轉(zhuǎn)規(guī)范頁面跳轉(zhuǎn)盡量用uni.navigateTo不要用uni.redirectTo除非確實不需要返回。對tabBar頁面監(jiān)聽onBackPress生命周期攔截返回操作。在manifest.json的App模塊配置里檢查Android的返回行為設(shè)置。排查這個問題的過程也讓我理解了為什么uniapp官方文檔反復(fù)強(qiáng)調(diào)生命周期管理。頁面棧概念聽起來抽象但實際踩坑時就是“為什么返回按鈕能退出應(yīng)用”這種直白的問題。6.3 地圖組件遮擋從內(nèi)置map到地圖SDK的遷移前面提到過內(nèi)置map組件在真機(jī)上會遮擋頁面其他元素。這個坑的具體表現(xiàn)是商品詳情頁有地圖展示地圖下方有個“立即購買”的懸浮按鈕安卓真機(jī)上按鈕被地圖蓋住點擊無響應(yīng)。排查過程是這樣的先懷疑是層級問題把按鈕的z-index調(diào)到9999沒用把按鈕改成cover-view能點了但樣式和普通view有差異圓角、投影效果都受限。最終方案是換用騰訊位置服務(wù)的小程序SDK。SDK提供的是正常渲染的普通組件沒有原生組件層級問題懸浮按鈕、彈窗都能正常顯示。這個坑提醒我在項目初期做技術(shù)選型時如果頁面有地圖需求就要預(yù)判到原生組件的層級限制。不管是騰訊地圖還是高德地圖優(yōu)先用SDK組件而不是內(nèi)置map。6.4 抓包調(diào)試的合規(guī)思路看清自己應(yīng)用的接口流向聯(lián)調(diào)階段最需要的就是抓包。微信小程序開發(fā)中抓包的主要方式有兩種一是直接在微信開發(fā)者工具的Network面板看請求二是把手機(jī)或工具的代理指向本地的抓包工具比如Reqable、Charles抓取HTTPS請求時需要安裝對應(yīng)的CA證書。這里必須強(qiáng)調(diào)合規(guī)邊界。抓包調(diào)試只應(yīng)該針對自己開發(fā)的應(yīng)用、自己的測試環(huán)境。小程序發(fā)布后線上版本有完整的安全校驗機(jī)制不要嘗試對他人線上應(yīng)用做越權(quán)分析也不要使用抓包工具繞過任何驗證邏輯。做開發(fā)時在小程序后臺開啟“調(diào)試模式”配合代理工具排查自己接口的請求參數(shù)和響應(yīng)數(shù)據(jù)是完全正當(dāng)?shù)摹N以趯嶋H排查接口問題時通常先在開發(fā)者工具里看請求頭、請求體和響應(yīng)體確認(rèn)是前端參數(shù)傳錯還是后端邏輯錯誤。如果開發(fā)者工具里請求正常真機(jī)上不行就檢查域名白名單和TLS證書配置。這種排查鏈路比盲改代碼高效得多。7. 項目交付前必須處理的合規(guī)與發(fā)布事項7.1 軟著申請的材料準(zhǔn)備如果項目要上架應(yīng)用市場或參與評審軟件著作權(quán)登記是繞不開的。軟著申請需要的材料主要有軟件著作權(quán)登記申請表源代碼文檔通常要求前后各30頁或40頁每頁50行左右PDF格式用戶操作手冊或設(shè)計說明書包含系統(tǒng)首頁、功能截圖、操作說明身份證明文件源代碼文檔有個容易忽略的細(xì)節(jié)代碼頁要有頁碼并且要包含完整的項目名稱、版本號信息。記得在提交前建一個docs目錄把答辯用的演示PPT、設(shè)計說明書、源代碼文檔、數(shù)據(jù)庫SQL腳本統(tǒng)一歸檔。軟著審批周期通常需要1-2個月如果項目要急著上架提前規(guī)劃申請時間。7.2 小程序和安卓應(yīng)用市場上架的檢查清單小程序上架前有一堆細(xì)節(jié)列個自查清單小程序類目要選對。如果做農(nóng)產(chǎn)品銷售涉及食品類目一般需要營業(yè)執(zhí)照和食品經(jīng)營許可證。純畢設(shè)項目如果沒證可以先用“工具-信息查詢”類目演示或者只做開發(fā)版預(yù)覽。所有網(wǎng)絡(luò)請求必須使用HTTPS并在小程序后臺配置request合法域名。設(shè)置隱私政策說明用戶信息收集范圍和使用方式。小程序名稱和logo不能侵權(quán)。如果要把uniapp代碼編譯成安卓App上架應(yīng)用市場還需要軟著證書、隱私政策、應(yīng)用簽名文件。上架前要在manifest.json里配置App圖標(biāo)、啟動圖、包名、版本號。上架華為、小米、OPPO、vivo、應(yīng)用寶等應(yīng)用市場時各個市場的審核標(biāo)準(zhǔn)略有差異最好先準(zhǔn)備一份通用的隱私政策和用戶協(xié)議。7.3 演示和答辯中如何把“云浮特色”講出亮點同樣是農(nóng)產(chǎn)品電商項目很多組做出來千篇一律。想要讓答辯老師或評審覺得有特色關(guān)鍵不在于展示了多少頁面而在于能否把“云浮特色農(nóng)產(chǎn)品”這個地域標(biāo)簽真正融入功能設(shè)計。我的經(jīng)驗是準(zhǔn)備三條演示主線第一條完整下單鏈路。從首頁進(jìn)入時令推薦專區(qū)選擇郁南無核黃皮查看產(chǎn)地溯源信息加入購物車提交訂單模擬支付訂單狀態(tài)流轉(zhuǎn)。這條鏈路展示了核心業(yè)務(wù)閉環(huán)。第二條管理后臺運(yùn)營流。管理員審核農(nóng)戶提交的商品設(shè)置活動價商家發(fā)貨填物流單號用戶確認(rèn)收貨后評價。這條鏈路展示了角色協(xié)同。第三條技術(shù)亮點講解。JWT登錄態(tài)、訂單狀態(tài)機(jī)、地圖配送范圍展示、自定義分享帶推薦人參數(shù)、uniapp一套代碼編譯多端。每講一個亮點對應(yīng)說明解決了什么問題。我發(fā)現(xiàn)演示時最打動人心的不是花哨的動畫而是“你注意到了別人沒注意的業(yè)務(wù)細(xì)節(jié)”。比如你能解釋清楚為什么歷史訂單要冗余收貨地址、為什么生鮮商品的訂單狀態(tài)機(jī)里有發(fā)貨倒計時這比一句“我用了SpringBoot Vue”強(qiáng)得多。做一個農(nóng)產(chǎn)品交易項目和做一個純技術(shù)Demo最大的區(qū)別就在這里。技術(shù)棧只是工具真正考驗的是對業(yè)務(wù)場景的理解。把云浮特產(chǎn)的季節(jié)性問題、庫存單位問題、產(chǎn)地信任問題想清楚了系統(tǒng)自然就有靈魂。希望這篇記錄能幫你少走點彎路。本文還有配套的精品資源點擊獲取