設(shè)計(jì)與實(shí)現(xiàn)全流程指南)
微信小程序訂餐系統(tǒng)這個(gè)題目這幾年在畢設(shè)和課程設(shè)計(jì)里出現(xiàn)頻率非常高。我經(jīng)手過(guò)不少類似項(xiàng)目也幫一些同學(xué)排查過(guò)源碼里的問(wèn)題。這類項(xiàng)目看上去簡(jiǎn)單——無(wú)非是點(diǎn)菜、下單、支付那幾件事但真正落地時(shí)涉及的角色劃分、狀態(tài)管理、前后端聯(lián)調(diào)、甚至論文寫作都有很多容易被忽略的坑。這篇文章就圍繞“基于微信小程序?qū)崿F(xiàn)訂餐管理系統(tǒng)”把我做這類項(xiàng)目的完整思路和關(guān)鍵細(xì)節(jié)梳理一遍給正在做設(shè)計(jì)或打算二次開發(fā)的朋友一份能直接參考的指南。1. 這個(gè)訂餐系統(tǒng)究竟要解決什么問(wèn)題1.1 核心需求與目標(biāo)用戶拆解很多同學(xué)拿到題目第一反應(yīng)是“做個(gè)小程序不就行了”但真開工就會(huì)發(fā)現(xiàn)需求邊界不清是最大的坑。訂餐系統(tǒng)不是單純把菜單搬到手機(jī)上它至少要服務(wù)兩類完全不同的人顧客和商家管理員。顧客側(cè)的需求很直觀——瀏覽菜品、查看分類、加入購(gòu)物車、提交訂單、在線支付或模擬支付、查看訂單狀態(tài)。這些功能本質(zhì)上和電商小程序是同一套邏輯。但商家側(cè)的需求容易被忽視菜品上下架、庫(kù)存調(diào)整、價(jià)格修改、訂單接單操作、查看銷售統(tǒng)計(jì)等。一套完整的訂餐系統(tǒng)必須同時(shí)覆蓋這兩條線否則演示時(shí)老師一問(wèn)“商家怎么改菜價(jià)”項(xiàng)目就露餡了。我在實(shí)際設(shè)計(jì)時(shí)會(huì)把需求拆成下面這張表給每個(gè)角色明確功能邊界角色核心功能關(guān)鍵流程顧客注冊(cè)/登錄、瀏覽菜品、購(gòu)物車、下單、支付、訂單查詢下單流程選菜 → 加購(gòu) → 結(jié)算 → 支付 → 等餐商家管理員菜品分類管理、菜品增刪改、上下架、庫(kù)存設(shè)置、訂單接單與完成接單流程收到新單 → 確認(rèn)接單 → 制作完成 → 訂單完結(jié)系統(tǒng)公共用戶鑒權(quán)、輪播圖展示、菜品搜索、訂單狀態(tài)自動(dòng)流轉(zhuǎn)數(shù)據(jù)統(tǒng)計(jì)今日訂單數(shù)、銷售額、熱銷菜品排行1.2 為什么選擇微信小程序作為前端載體選題時(shí)需要考慮一個(gè)現(xiàn)實(shí)問(wèn)題為什么這個(gè)系統(tǒng)適合用微信小程序做而不是傳統(tǒng)的Web網(wǎng)頁(yè)或原生App這里有幾個(gè)關(guān)鍵考量。最直接的原因是微信生態(tài)帶來(lái)的便利性。用戶不需要下載額外的App打開微信掃一掃或搜索小程序就能使用這對(duì)“食堂點(diǎn)餐”“校內(nèi)訂餐”這類場(chǎng)景非常友好。同時(shí)微信提供了完整的登錄體系wx.login 配合后端 code2session 就能拿到用戶唯一標(biāo)識(shí)免去了手機(jī)號(hào)注冊(cè)的繁瑣流程畢設(shè)答辯時(shí)也能省出不少篇幅。另一個(gè)重要原因是開發(fā)成本。小程序前端使用 WXML 和 WXSS語(yǔ)法和 HTML/CSS 高度類似前端基礎(chǔ)不太扎實(shí)的同學(xué)也能快速上手。后端部分完全獨(dú)立可以選 Java Spring Boot、Node.js、Python Flask 等任何熟悉的技術(shù)棧前后端通過(guò) HTTP 接口通信職責(zé)清晰寫論文也好拆章節(jié)。相比之下原生App還要考慮打包、簽名、應(yīng)用商店審核這些和訂餐系統(tǒng)的核心邏輯關(guān)系不大屬于典型的無(wú)效工作量。2. 技術(shù)選型與項(xiàng)目架構(gòu)設(shè)計(jì)2.1 前端微信小程序原生框架的結(jié)構(gòu)設(shè)計(jì)前端我建議直接用微信小程序原生框架不要一上來(lái)就上 uni-app 或 Taro。原因很簡(jiǎn)單原生框架的官方文檔最全調(diào)試工具最直接社區(qū)資料最多遇到問(wèn)題搜解決方案很容易。uni-app 的優(yōu)勢(shì)是多端復(fù)用但訂餐系統(tǒng)只跑微信端多端能力是純粹浪費(fèi)。小程序端目錄結(jié)構(gòu)按功能模塊拆分會(huì)清晰很多miniprogram/ ├── pages/ │ ├── index/ // 首頁(yè)輪播圖、推薦菜品 │ ├── menu/ // 菜單分類 菜品列表 │ ├── cart/ // 購(gòu)物車 │ ├── order/ // 訂單列表 訂單詳情 │ ├── user/ // 個(gè)人中心 │ └── admin/ // 商家管理端 ├── components/ // 可復(fù)用組件菜品卡片、數(shù)量步進(jìn)器 ├── utils/ │ ├── request.js // 統(tǒng)一請(qǐng)求封裝 │ └── auth.js // 登錄態(tài)管理 └── app.js // 全局邏輯頁(yè)面間通信和狀態(tài)同步是這類項(xiàng)目的重點(diǎn)。我的做法是用戶登錄信息放 globalData 和 Storage 雙寫購(gòu)物車數(shù)據(jù)在本地維護(hù)但提交訂單前會(huì)從后端重新核對(duì)一遍菜品價(jià)格和庫(kù)存。防止用戶在本地改一個(gè)虛假價(jià)格然后下單成功這種細(xì)節(jié)是論文里“系統(tǒng)安全性設(shè)計(jì)”章節(jié)最好的素材。2.2 后端Java Spring Boot 是更穩(wěn)妥的路徑后端技術(shù)棧我接觸過(guò)的方案里Java Spring Boot MyBatis Plus MySQL 是完成度最高、論文最好寫的組合。不是說(shuō)其他方案不行但 Spring Boot 有非常成熟的生態(tài)分頁(yè)插件、代碼生成器、安全框架都有現(xiàn)成方案能大幅縮短開發(fā)周期。技術(shù)棧組合優(yōu)點(diǎn)缺點(diǎn)適用場(chǎng)景Spring Boot MyBatis Plus MySQL資料多、穩(wěn)定、論文好寫項(xiàng)目體積相對(duì)臃腫絕大多數(shù)畢設(shè)、課設(shè)Node.js Express MongoDB輕量、前后端都是JS資料相對(duì)少、弱類型易出錯(cuò)前端基礎(chǔ)強(qiáng)、想快速出成果Python Flask MySQL代碼簡(jiǎn)潔、易讀高并發(fā)能力弱適合演示型項(xiàng)目如果是 Spring Boot項(xiàng)目結(jié)構(gòu)建議這樣組織src/main/java/com/example/order/ ├── controller/ // 接口層接收請(qǐng)求、返回結(jié)果 ├── service/ // 業(yè)務(wù)層核心邏輯 ├── mapper/ // 數(shù)據(jù)訪問(wèn)層MyBatis 接口 ├── entity/ // 實(shí)體類 ├── config/ // 全局配置攔截器、跨域 └── common/ // 統(tǒng)一返回結(jié)果、異常處理2.3 數(shù)據(jù)庫(kù)設(shè)計(jì)五張核心表必須提前理順數(shù)據(jù)庫(kù)設(shè)計(jì)是整個(gè)項(xiàng)目中我最看重的一環(huán)。很多同學(xué)一上來(lái)就建十幾張表結(jié)果關(guān)聯(lián)關(guān)系一團(tuán)亂。訂餐系統(tǒng)最核心的就是五張表用戶表、菜品表、購(gòu)物車表、訂單表、訂單明細(xì)表。分類表如果菜品不多可以直接用字符串字段替代但獨(dú)立建表更規(guī)范論文里也好畫ER圖。用戶表設(shè)計(jì)要點(diǎn)CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT, openid varchar(64) DEFAULT NULL COMMENT 微信openid, nickname varchar(50) DEFAULT NULL COMMENT 昵稱, avatar varchar(255) DEFAULT NULL COMMENT 頭像地址, phone varchar(20) DEFAULT NULL COMMENT 手機(jī)號(hào), role tinyint(1) DEFAULT 0 COMMENT 角色0-顧客1-管理員, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY idx_openid (openid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;菜品表和訂單表需要特別注意兩個(gè)設(shè)計(jì)細(xì)節(jié)。菜品表里我建議加sales字段記錄銷量方便后續(xù)做“熱銷排行”這是首頁(yè)展示的重要數(shù)據(jù)來(lái)源。訂單表必須把“訂單號(hào)”和“用戶ID”分開訂單號(hào)用時(shí)間戳加隨機(jī)數(shù)生成用戶ID只做關(guān)聯(lián)查詢用這樣在演示時(shí)更容易解釋“訂單號(hào)的唯一性”。訂單表里status字段是系統(tǒng)正常運(yùn)轉(zhuǎn)的命脈0 - 待支付 1 - 已支付待商家接單 2 - 商家已接單制作中 3 - 已完成可評(píng)價(jià) 4 - 已取消這個(gè)狀態(tài)枚舉在前后端要嚴(yán)格保持一致前端展示文案和后端邏輯判斷分離避免硬編碼。3. 核心功能模塊的實(shí)現(xiàn)思路與關(guān)鍵代碼3.1 登錄鑒權(quán)微信登錄還是模擬登錄登錄是用戶側(cè)最先被觸發(fā)的一個(gè)功能也是容易被做壞的地方。小程序的 wx.login 流程是前端調(diào)用這個(gè)接口拿 code后端拿 code 加上 AppID 和 AppSecret 去微信接口換 openid。有了 openid 就識(shí)別了用戶業(yè)務(wù)系統(tǒng)自己再發(fā)一個(gè) token 給前端。但在實(shí)際畢設(shè)場(chǎng)景里個(gè)人開發(fā)者沒有企業(yè)主體的話很多微信接口權(quán)限受限。我通常在源碼中同時(shí)提供兩種模式一種完整走微信 login 流程另一種是“模擬登錄”——用戶在登錄頁(yè)輸入昵稱和手機(jī)號(hào)即創(chuàng)建賬號(hào)。這么做的好處是演示環(huán)境不依賴微信官方接口任何場(chǎng)地都能跑起來(lái)。兩種模式通過(guò)后端配置文件一個(gè)開關(guān)切換論文里可以寫成“系統(tǒng)兼容微信授權(quán)登錄和手機(jī)號(hào)快捷登錄兩種方式”。token 的生成建議直接用 UUID 加過(guò)期時(shí)間存 Redis 或數(shù)據(jù)庫(kù)都行。畢設(shè)系統(tǒng)并發(fā)量不大存數(shù)據(jù)庫(kù)完全足夠還能少一個(gè)中間件依賴演示時(shí)少一個(gè)故障點(diǎn)。3.2 菜品瀏覽與購(gòu)物車本地緩存和遠(yuǎn)程校驗(yàn)雙軌并進(jìn)菜品瀏覽頁(yè)面看起來(lái)簡(jiǎn)單里面還是有一些設(shè)計(jì)學(xué)問(wèn)的。我的做法是首頁(yè)和菜單頁(yè)分開首頁(yè)放輪播圖、公告和推薦菜品菜單頁(yè)完整展示分類和全部菜品。兩個(gè)頁(yè)面都調(diào)用同一個(gè)菜品列表接口只是參數(shù)不同——一個(gè)傳推薦標(biāo)識(shí)一個(gè)傳分類ID。購(gòu)物的核心代碼其實(shí)不復(fù)雜但要處理好“數(shù)量加減”和“金額計(jì)算”的聯(lián)動(dòng)。每一步操作都要重新計(jì)算小計(jì)和總計(jì)而且商品數(shù)據(jù)的單位用“分”存儲(chǔ)避免 JS 浮點(diǎn)數(shù)精度問(wèn)題。很多同學(xué)踩過(guò) 0.1 0.2 不等于 0.3 的坑實(shí)際就發(fā)生在購(gòu)物車金額累加時(shí)。購(gòu)物車我采用本地存儲(chǔ)加一次性遠(yuǎn)程提交的混合方案。用戶加減菜品時(shí)直接改本地 Storage只在前端做數(shù)量校驗(yàn)用戶點(diǎn)擊“去結(jié)算”時(shí)把購(gòu)物車數(shù)據(jù)全部提交給后端后端再根據(jù)當(dāng)前數(shù)據(jù)庫(kù)里的實(shí)時(shí)價(jià)格和庫(kù)存重新計(jì)算總價(jià)。這樣既減少了接口請(qǐng)求次數(shù)又避免了惡意篡改價(jià)格的可能。3.3 訂單狀態(tài)流轉(zhuǎn)從下單到訂單完成下單接口是整個(gè)系統(tǒng)里最需要謹(jǐn)慎的一個(gè)它的邏輯鏈最長(zhǎng)接收購(gòu)物車數(shù)據(jù) → 計(jì)算金額 → 校驗(yàn)庫(kù)存 → 扣除庫(kù)存 → 生成訂單 → 寫入訂單明細(xì) → 清空購(gòu)物車 → 返回訂單號(hào)。這一步在論文里叫“事務(wù)一致性”通常用 Transactional 注解包住整個(gè)方法任何一步失敗都會(huì)整體回滾。用戶下單后訂單狀態(tài)從 0待支付開始流轉(zhuǎn)下單成功 → 用戶模擬支付/微信支付 → 狀態(tài)變?yōu)?1已支付 → 管理員在后臺(tái)點(diǎn)擊“接單” → 狀態(tài)變?yōu)?2制作中 → 管理員點(diǎn)擊“完成” → 狀態(tài)變?yōu)?3已完成商戶端和用戶端都要能實(shí)時(shí)看到訂單狀態(tài)的變更。這里有一個(gè)我很推薦的實(shí)現(xiàn)方式商戶端訂單列表使用定時(shí)輪詢每 5 秒請(qǐng)求一次新訂單接口而不是用 WebSocket 長(zhǎng)連接。輪詢?cè)诋呍O(shè)場(chǎng)景下夠用且穩(wěn)定不會(huì)出現(xiàn)連接斷開、心跳?;钸@些額外問(wèn)題論文篇幅還能省下一大節(jié)。3.4 商家管理端菜品與訂單管理的核心邏輯商家管理端往往是最后才動(dòng)工的部分但我建議提前規(guī)劃因?yàn)樗墓δ芰坎恍?。菜品管理包括添加菜品圖片上傳、價(jià)格、分類、庫(kù)存、編輯、上下架。這里的關(guān)鍵是圖片上傳處理方式通常是選擇圖片后先調(diào)后臺(tái)上傳接口拿到返回的 URL 再隨表單一起提交不要直接把本地臨時(shí)路徑存進(jìn)數(shù)據(jù)庫(kù)。訂單管理是管理員最常操作的地方。我建議訂單列表加上狀態(tài)篩選 tab——待接單、制作中、已完成、已取消每個(gè) tab 對(duì)應(yīng)一個(gè)列表請(qǐng)求。管理員點(diǎn)擊“接單”“完成”按鈕時(shí)調(diào)對(duì)應(yīng)接口成功后刷新當(dāng)前列表。銷售統(tǒng)計(jì)模塊可以放三個(gè)指標(biāo)卡片今日訂單數(shù)、今日銷售額、累計(jì)訂單數(shù)數(shù)據(jù)來(lái)自一個(gè)統(tǒng)計(jì)接口SQL 里用 COUNT 和 SUM 加 WHERE 條件就能實(shí)現(xiàn)。4. 前端關(guān)鍵頁(yè)面與接口聯(lián)調(diào)細(xì)節(jié)4.1 底部導(dǎo)航與頁(yè)面框架設(shè)計(jì)微信小程序的底部導(dǎo)航在 app.json 的 tabBar 字段里配置。訂餐系統(tǒng)通常設(shè)四個(gè)主 tab首頁(yè)、菜單、購(gòu)物車、我的。管理員入口不用單開一個(gè) tab而是在“我的”頁(yè)面里根據(jù)角色字段動(dòng)態(tài)展示入口這樣顧客端界面看起來(lái)干凈管理員端功能也沒有丟失。tabBar 圖標(biāo)是很多人的痛處。微信官方要求 tabBar 圖標(biāo)必須是本地圖片不能是網(wǎng)絡(luò)圖片而且尺寸要符合要求建議 81px * 81px。我常用 PNG 透明底圖標(biāo)避免出現(xiàn)底色方塊影響美觀。購(gòu)物車 tab 上的數(shù)量角標(biāo)可以通過(guò) wx.setTabBarBadge 動(dòng)態(tài)設(shè)置這是提升體驗(yàn)感的一個(gè)小細(xì)節(jié)論文里也可以寫一句功能亮點(diǎn)。4.2 請(qǐng)求封裝與接口地址切換接口請(qǐng)求如果不做統(tǒng)一封裝后面聯(lián)調(diào)會(huì)很痛苦。小程序原生請(qǐng)求 wx.request 是一個(gè)回調(diào)函數(shù)嵌套比較深的設(shè)計(jì)我會(huì)用 Promise 包一層讓代碼更易讀。封裝后的請(qǐng)求模塊具備三個(gè)能力自動(dòng)攜帶 token、統(tǒng)一錯(cuò)誤提示、響應(yīng)狀態(tài)碼前置判斷。開發(fā)者工具調(diào)試時(shí)接口地址用 http://localhost:8080 沒問(wèn)題但真機(jī)預(yù)覽時(shí) localhost 指的是手機(jī)本身必須改成電腦的局域網(wǎng) IP。這里有一個(gè)非常常見的坑改了地址之后要在“詳情→本地設(shè)置”里勾選“不校驗(yàn)合法域名”否則真機(jī)請(qǐng)求會(huì)被攔截。每次換網(wǎng)絡(luò)環(huán)境 IP 可能變化所以我把 baseUrl 單獨(dú)放在一個(gè) config.js 文件里方便統(tǒng)一修改。const BASE_URL http://192.168.1.100:8080 function request({ url, method GET, data {} }) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL url, method, data, header: { Content-Type: application/json, token: wx.getStorageSync(token) || }, success: (res) { if (res.statusCode 200 res.data.code 200) { resolve(res.data.data) } else if (res.statusCode 401) { wx.navigateTo({ url: /pages/login/login }) reject(new Error(登錄已過(guò)期)) } else { wx.showToast({ title: res.data.msg || 請(qǐng)求失敗, icon: none }) reject(new Error(res.data.msg)) } }, fail: (err) { wx.showToast({ title: 網(wǎng)絡(luò)異常請(qǐng)重試, icon: none }) reject(err) } }) }) }這段代碼的核心有兩點(diǎn)請(qǐng)求頭統(tǒng)一帶 token響應(yīng)統(tǒng)一判斷業(yè)務(wù)狀態(tài)碼。后續(xù)所有頁(yè)面調(diào)用不用重復(fù)寫錯(cuò)誤處理邏輯。4.3 下拉刷新、觸底加載與頁(yè)面參數(shù)傳遞菜單列表如果菜品多必須做分頁(yè)加載。我的方案是頁(yè)面 onLoad 時(shí)加載第一頁(yè)每頁(yè) 10 條頁(yè)面觸底時(shí)通過(guò) onReachBottom 加載下一頁(yè)頁(yè)碼加 1直到返回的數(shù)據(jù)條數(shù)小于每頁(yè)條數(shù)時(shí)停止。分頁(yè)條件寫在 SQL 的 LIMIT 語(yǔ)句里后端用 MyBatis Plus 的 Page 插件封裝。頁(yè)面跳轉(zhuǎn)時(shí)要注意參數(shù)傳遞。從菜單頁(yè)點(diǎn)進(jìn)菜品詳情用 URL 參數(shù)傳菜品 ID從訂單列表點(diǎn)進(jìn)訂單詳情傳訂單號(hào)。接收頁(yè)面在 onLoad(options) 里通過(guò) options 解析參數(shù)。如果參數(shù)是對(duì)象需要先 JSON.stringify 編碼再拼接 URL接收時(shí)再 JSON.parse 解碼直接用對(duì)象拼接會(huì)看到“[object Object]”的詭異輸出。下拉刷新用頁(yè)面自帶的 onPullDownRefresh在 app.json 的 window 配置里開啟 enablePullDownRefresh刷新完成后記得調(diào) wx.stopPullDownRefresh 關(guān)閉加載動(dòng)畫否則轉(zhuǎn)圈圖標(biāo)會(huì)一直顯示。5. 常見問(wèn)題與排查技巧實(shí)錄5.1 問(wèn)題速查表與解決方案這套系統(tǒng)開發(fā)過(guò)程中我記錄了一些經(jīng)典問(wèn)題整理成表格供大家排查時(shí)參考問(wèn)題現(xiàn)象根本原因解決方案真機(jī)預(yù)覽時(shí)請(qǐng)求全部失敗提示“url not in domain list”小程序合法域名限制開發(fā)者工具詳情中勾選“不校驗(yàn)合法域名”或在小程序后臺(tái)配置 request 合法域名登錄接口正常但頁(yè)面刷新后就退出登錄token 未寫入 Storage 或過(guò)期時(shí)間太短檢查 storage 寫入邏輯后端把 token 過(guò)期時(shí)間設(shè)長(zhǎng)如 7 天菜品圖片上傳后在部分手機(jī)不顯示圖片 URL 是 http 協(xié)議或本地路徑使用 https 協(xié)議圖片或確認(rèn)圖片上傳后保存的相對(duì)路徑拼接正確中文數(shù)據(jù)亂碼數(shù)據(jù)庫(kù)編碼不一致數(shù)據(jù)庫(kù)、表、字段統(tǒng)一使用 utf8mb4JDBC URL 加 characterEncodingutf8用戶重復(fù)點(diǎn)擊“提交訂單”產(chǎn)生多條訂單前端未做按鈕防抖提交按鈕增加 loading 狀態(tài)點(diǎn)擊后置灰后端按用戶時(shí)間做冪等購(gòu)物車總金額出現(xiàn)小數(shù)位誤差JS 浮點(diǎn)運(yùn)算精度問(wèn)題所有金額以“分”為單位用整數(shù)計(jì)算展示時(shí)再除以 100管理員無(wú)法同時(shí)看到新訂單前端輪詢未開啟或時(shí)間間隔不合理確認(rèn)輪詢?cè)?onShow 中啟動(dòng)、onHide 中清除間隔設(shè)為 5 秒5.2 聯(lián)調(diào)時(shí)的三個(gè)環(huán)節(jié)最容易拖延進(jìn)度前后端聯(lián)調(diào)是項(xiàng)目周期中最容易失控的階段。第一個(gè)常見卡點(diǎn)是接口字段命名不一致。后端返回的字段名是 createTime前端寫的卻是 createtime這種大小寫問(wèn)題通常不報(bào)錯(cuò)但數(shù)據(jù)永遠(yuǎn)是 undefined。我的經(jīng)驗(yàn)是有幾張核心表就用 Excel 維護(hù)一份接口字段清單前后端各執(zhí)一份從源頭對(duì)齊。第二個(gè)卡點(diǎn)是時(shí)間格式。后端默認(rèn)返回可能是時(shí)間戳或包含 T 的字符串前端在 IOS 和 Android 上對(duì)時(shí)間格式的解析還有差異。我在后端直接統(tǒng)一格式化為“年-月-日 時(shí):分:秒”字符串返回前端只做展示不做解析省掉一層轉(zhuǎn)換成本。第三個(gè)卡點(diǎn)是異常場(chǎng)景沒有兜底。比如用戶下單成功但沒有庫(kù)存了、管理員把菜品下架后用戶購(gòu)物車?yán)镞€有該菜品。這部分我在接口里都加了顯式判斷失敗時(shí)返回提示信息前端根據(jù)業(yè)務(wù)碼提示用戶“菜品已售罄”或“訂單無(wú)法支付請(qǐng)聯(lián)系商家”。這些異常路徑在答辯時(shí)會(huì)是加分項(xiàng)因?yàn)榇蠖鄶?shù)人的系統(tǒng)只有“成功路徑”。5.3 微信支付功能的現(xiàn)實(shí)取舍微信支付是小程序訂餐繞不開的話題但也是要讓同學(xué)們提前有心理準(zhǔn)備的。真實(shí)的小程序微信支付需要企業(yè)主體資質(zhì)、微信商戶號(hào)、支付證書等一系列條件個(gè)人開發(fā)者是沒法完成真實(shí)支付的。畢設(shè)項(xiàng)目中絕大多數(shù)會(huì)采用“模擬支付”下單后跳轉(zhuǎn)一個(gè)支付確認(rèn)頁(yè)點(diǎn)擊“確認(rèn)支付”直接調(diào)用后端接口把訂單狀態(tài)置為“已支付”。這個(gè)方案在答辯中完全可以自圓其說(shuō)因?yàn)檠菔鞠到y(tǒng)核心演示的是訂餐流程支付環(huán)節(jié)用一個(gè)可替換的接口模擬論文中說(shuō)明“對(duì)接真實(shí)微信支付時(shí)的改造點(diǎn)”即可。6. 源碼使用與論文寫作如何把項(xiàng)目?jī)r(jià)值講完整6.1 源碼目錄結(jié)構(gòu)與二次開發(fā)指引拿到源碼后第一步不是急著跑起來(lái)而是先看目錄結(jié)構(gòu)。前文已列出前端結(jié)構(gòu)后端部分我會(huì)特別注意 resource 目錄下的 application.yml 數(shù)據(jù)庫(kù)連接配置。不同人電腦上的 MySQL 用戶名密碼不一樣數(shù)據(jù)庫(kù)名稱也可能不同所以這一項(xiàng)是運(yùn)行環(huán)境中最先需要修改的地方。數(shù)據(jù)庫(kù)導(dǎo)入不要圖省事直接執(zhí)行整個(gè) SQL 文件先檢查版本。如果用 MySQL 8.0 及以上注意時(shí)區(qū)參數(shù)如果用了 MySQL 5.7部分語(yǔ)法有差異。我會(huì)在源碼包中附一個(gè)“環(huán)境配置說(shuō)明.txt”不僅寫數(shù)據(jù)庫(kù)賬號(hào)密碼還寫清楚 JDK 版本、Maven 鏡像、MySQL 連接參數(shù)。二次開發(fā)的話優(yōu)先級(jí)建議是先跑通訂單主流程 → 再加評(píng)價(jià)模塊 → 再考慮優(yōu)惠券。評(píng)價(jià)模塊只需要建一張?jiān)u價(jià)表關(guān)聯(lián)訂單號(hào)和用戶ID前端在訂單完成后展示評(píng)價(jià)入口和內(nèi)容工作量小但對(duì)系統(tǒng)完整度提升明顯。6.2 論文寫作的六章結(jié)構(gòu)與每章重點(diǎn)論文和代碼同步推進(jìn)才能避免最后趕工。標(biāo)準(zhǔn)結(jié)構(gòu)是緒論、需求分析、系統(tǒng)設(shè)計(jì)、系統(tǒng)實(shí)現(xiàn)、系統(tǒng)測(cè)試、總結(jié)。每個(gè)章節(jié)的內(nèi)容我都踩過(guò)一些坑這里做一個(gè)經(jīng)驗(yàn)總結(jié)緒論部分重點(diǎn)是背景和意義。不要用大量篇幅寫“隨著移動(dòng)互聯(lián)網(wǎng)的發(fā)展”這種套話而是直接寫“高校食堂在就餐高峰期排隊(duì)嚴(yán)重傳統(tǒng)人工收銀效率低由此產(chǎn)生了線上訂餐的需求”。這樣一句話就把問(wèn)題說(shuō)清楚。需求分析章節(jié)必須有三個(gè)圖用例圖、功能結(jié)構(gòu)圖、業(yè)務(wù)流程圖。可以用 ProcessOn 或者 draw.io 畫不用花錢畫完截圖粘貼到 Word 里。系統(tǒng)設(shè)計(jì)章節(jié)是論文的骨架占最大篇幅。架構(gòu)圖、功能模塊圖、數(shù)據(jù)庫(kù) ER 圖是答辯老師最愛看的東西這張圖不要含糊。重點(diǎn)寫數(shù)據(jù)庫(kù)設(shè)計(jì)把每張表的每個(gè)字段的含義都寫出來(lái)再寫清楚表與表之間的外鍵關(guān)聯(lián)。系統(tǒng)實(shí)現(xiàn)章節(jié)切忌貼大段代碼。代碼可以少量貼關(guān)鍵方法但核心要寫清楚實(shí)現(xiàn)思路和為什么這么實(shí)現(xiàn)。比如“訂單接口使用事務(wù)處理”要比直接貼題 200 行代碼效果好得多。系統(tǒng)測(cè)試章節(jié)用表格展示測(cè)試用例比較清晰。列出測(cè)試項(xiàng)、輸入、預(yù)期結(jié)果、實(shí)際結(jié)果、是否通過(guò)寫 10 組覆蓋登錄、下單、庫(kù)存校驗(yàn)等核心功能的用例就足夠了。6.3 答辯演示路徑與七個(gè)必問(wèn)題答辯演示最怕演示到中途斷掉所以路徑設(shè)計(jì)要像講故事一樣流暢。我的建議是固定演示順序先展示顧客端完整訂餐流程登錄→點(diǎn)餐→加購(gòu)→下單→支付→ 再切換管理員賬號(hào)看到新訂單→接單→完成→ 返回顧客端看到訂單狀態(tài)更新→ 展示菜品上下架和統(tǒng)計(jì)頁(yè)面。答辯老師常問(wèn)的問(wèn)題我提前給大家列一下第一個(gè)問(wèn)題是“為什么用微信小程序而不是微信公眾號(hào)或App”這個(gè)問(wèn)題本質(zhì)考你選題理解從免安裝、微信生態(tài)、輕量開發(fā)三個(gè)角度回答基本不會(huì)錯(cuò)。第二個(gè)問(wèn)題是“購(gòu)物車為什么存在本地而不存數(shù)據(jù)庫(kù)”重點(diǎn)是表達(dá)你在網(wǎng)絡(luò)開銷和用戶體驗(yàn)之間做了權(quán)衡同時(shí)說(shuō)明下單時(shí)后端會(huì)重新校驗(yàn)。第三個(gè)問(wèn)題是“訂單狀態(tài)是怎么流轉(zhuǎn)的、由誰(shuí)控制”答案要落在狀態(tài)枚舉和后端邏輯判斷上強(qiáng)調(diào)狀態(tài)變更只能通過(guò)接口完成哪怕前端改代碼也不能非法篡改。第四個(gè)問(wèn)題是“最多能支持多少用戶并發(fā)”這個(gè)問(wèn)題不要為了顯得厲害亂說(shuō)數(shù)字誠(chéng)實(shí)回答“畢設(shè)系統(tǒng)面向中小型場(chǎng)景單機(jī)部署下能支持百級(jí)并發(fā)”然后補(bǔ)充說(shuō)如果要做大規(guī)模體驗(yàn)可以引入 Redis 和集群部署。第五個(gè)問(wèn)題是“怎么防止用戶繞過(guò)支付直接改訂單狀態(tài)”這里就答先后端校驗(yàn)即可。第六個(gè)問(wèn)題是“購(gòu)物車異常退出的數(shù)據(jù)怎么恢復(fù)”這個(gè)問(wèn)題的備選答案是本地緩存的設(shè)計(jì)。第七個(gè)問(wèn)題是“登錄安全怎么做”最終落到 token 和 openid 的服務(wù)端換取邏輯上。7. 寫在最后來(lái)自實(shí)操中的幾點(diǎn)體會(huì)做完這套系統(tǒng)我最大的體會(huì)是開發(fā)同學(xué)太容易陷入“只會(huì)寫代碼”的狀態(tài)。完整跑通一條訂單鏈路、能把系統(tǒng)講清楚的人才算真正理解了項(xiàng)目。最后分享幾個(gè)從實(shí)際排錯(cuò)中學(xué)到的小技巧。后端啟動(dòng)時(shí)報(bào)端口占用先看是不是上一次調(diào)試的進(jìn)程沒關(guān)掉。Windows 下用netstat -ano | findstr 8080查出來(lái) PID然后去任務(wù)管理器關(guān)掉對(duì)應(yīng)進(jìn)程比反復(fù)重啟電腦高效得多。前后端聯(lián)調(diào)頁(yè)面顯示“網(wǎng)絡(luò)異?!睍r(shí)先用瀏覽器直接訪問(wèn)后端接口。如果瀏覽器能出數(shù)據(jù)、小程序不行問(wèn)題幾乎一定出在小程序域名校驗(yàn)或請(qǐng)求頭拼接上不要在后端代碼里找半天問(wèn)題。數(shù)據(jù)庫(kù)里已經(jīng)存了臟數(shù)據(jù)比如狀態(tài)是 5 的訂單先用 SQL 批量修正不要讓臟數(shù)據(jù)干擾后面接口測(cè)試。我經(jīng)常寫幾條規(guī)范化 SQL 備用調(diào)式數(shù)據(jù)時(shí)效率高很多。這個(gè)項(xiàng)目后面如果要擴(kuò)展可以從三個(gè)方向入手增加優(yōu)惠券模塊、引入 WebSocket 實(shí)時(shí)提醒新訂單、增加菜品評(píng)價(jià)功能。每一條路都是完整的研究課題。希望這篇文章能幫你少走一些彎路把自己的訂餐系統(tǒng)做得完整、講得清楚。