店進(jìn)銷(xiāo)存與會(huì)員系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn))
文章目錄項(xiàng)目介紹技術(shù)棧功能介紹實(shí)現(xiàn)頁(yè)面截圖一、項(xiàng)目背景與需求分析二、系統(tǒng)架構(gòu)與技術(shù)選型技術(shù)選型對(duì)比三、核心功能模塊實(shí)現(xiàn)1. 訂單列表的角色隔離查詢2. 新品商品列表的價(jià)格篩選與脫敏3. 熱門(mén)商品列表的復(fù)用式實(shí)現(xiàn)真實(shí)問(wèn)題排查復(fù)盤(pán)訂單列表出現(xiàn)越權(quán)風(fēng)險(xiǎn)時(shí)序圖提交訂單的調(diào)用鏈路四、數(shù)據(jù)庫(kù)設(shè)計(jì)五、系統(tǒng)測(cè)試與驗(yàn)證六、適用邊界與優(yōu)化方向七、總結(jié)源碼獲取 本項(xiàng)目提供完整源碼 數(shù)據(jù)庫(kù) 運(yùn)行部署說(shuō)明獲取方式見(jiàn)文末。摘要本文面向正在做畢業(yè)設(shè)計(jì)或需要參考完整 Web 項(xiàng)目落地思路的讀者圍繞“服裝門(mén)店進(jìn)銷(xiāo)存與會(huì)員系統(tǒng)”展開(kāi)重點(diǎn)解決門(mén)店商品管理、會(huì)員下單、地址維護(hù)、充值記錄、公告與客服等業(yè)務(wù)的在線化問(wèn)題。系統(tǒng)采用SpringBoot Vue 2 Element UI ECharts并結(jié)合訂單、購(gòu)物車(chē)、會(huì)員、地址等數(shù)據(jù)表完成前后端分離實(shí)現(xiàn)。項(xiàng)目介紹服裝門(mén)店進(jìn)銷(xiāo)存與會(huì)員系統(tǒng)技術(shù)棧后端SpringBoot 2.2.2 MyBatis-Plus MyBatis Shiro POI/EasyExcel Spring MVC前端Vue 2 Element UI ECharts Axios Vue Router Vuex數(shù)據(jù)庫(kù)MySQL功能介紹服裝門(mén)店進(jìn)銷(xiāo)存與會(huì)員系統(tǒng)共包含 會(huì)員、管理員 共 2 個(gè)角色各角色具體功能如下?? 會(huì)員瀏覽熱門(mén)服裝、瀏覽新品服裝、查看服裝分類(lèi)、加入購(gòu)物車(chē)、提交購(gòu)物訂單、管理收貨地址、在線充值、在線客服咨詢、收藏服裝、發(fā)布論壇帖子、發(fā)表評(píng)論、管理個(gè)人信息?? 管理員會(huì)員信息管理、服裝分類(lèi)管理、熱門(mén)服裝管理、新品服裝管理、訂單管理、充值記錄管理、公告信息管理、論壇帖子管理、在線客服管理、收藏記錄管理、地址信息管理、數(shù)據(jù)統(tǒng)計(jì)實(shí)現(xiàn)頁(yè)面截圖下面展示服裝門(mén)店進(jìn)銷(xiāo)存與會(huì)員系統(tǒng)的部分運(yùn)行界面。圖1系統(tǒng)運(yùn)行界面圖2系統(tǒng)運(yùn)行界面圖3服裝分類(lèi)圖4在線客服圖5服裝分類(lèi)圖6服裝分類(lèi)圖7會(huì)員信息圖8公告信息一、項(xiàng)目背景與需求分析服裝門(mén)店在實(shí)際經(jīng)營(yíng)中常見(jiàn)的問(wèn)題不是“有沒(méi)有系統(tǒng)”而是數(shù)據(jù)分散、人工統(tǒng)計(jì)慢、會(huì)員消費(fèi)鏈路斷裂。門(mén)店一邊要維護(hù)服裝分類(lèi)、熱門(mén)和新品商品一邊要處理會(huì)員地址、購(gòu)物車(chē)、訂單、充值記錄和公告信息如果繼續(xù)靠 Excel 或人工登記很容易出現(xiàn)庫(kù)存、訂單、會(huì)員數(shù)據(jù)不一致的問(wèn)題。這個(gè)項(xiàng)目的目標(biāo)就是把門(mén)店的進(jìn)銷(xiāo)存與會(huì)員業(yè)務(wù)放進(jìn)同一套系統(tǒng)里管理。管理員側(cè)需要能維護(hù)商品分類(lèi)、熱門(mén)服裝、新品服裝、公告、論壇、日志和訂單會(huì)員側(cè)則需要能瀏覽商品、加入購(gòu)物車(chē)、提交訂單、維護(hù)收貨地址、查看充值記錄、參與評(píng)論和在線客服交互。系統(tǒng)還要保證不同角色看到的數(shù)據(jù)邊界不同避免普通會(huì)員看到別人的訂單或地址信息。從業(yè)務(wù)本質(zhì)上看這套系統(tǒng)解決的是**“門(mén)店經(jīng)營(yíng)數(shù)據(jù)標(biāo)準(zhǔn)化”**問(wèn)題把商品、訂單、會(huì)員、地址、充值和互動(dòng)內(nèi)容統(tǒng)一到數(shù)據(jù)庫(kù)中減少重復(fù)錄入和人工核對(duì)成本同時(shí)為后續(xù)統(tǒng)計(jì)分析提供基礎(chǔ)數(shù)據(jù)。二、系統(tǒng)架構(gòu)與技術(shù)選型本項(xiàng)目采用典型的前后端分離架構(gòu)。前端負(fù)責(zé)頁(yè)面展示、表單交互和圖表渲染后端負(fù)責(zé)業(yè)務(wù)規(guī)則、權(quán)限控制和數(shù)據(jù)庫(kù)讀寫(xiě)。后端代碼結(jié)構(gòu)上按 Controller、Service、Mapper 分層Controller 接收請(qǐng)求并做參數(shù)組織Service 承擔(dān)業(yè)務(wù)邏輯Mapper 直接訪問(wèn)數(shù)據(jù)庫(kù)整體職責(zé)比較清晰。技術(shù)選型對(duì)比技術(shù)選擇承擔(dān)職責(zé)為什么選它/未選替代方案的原因SpringBoot后端接口與業(yè)務(wù)編排啟動(dòng)快、配置少適合畢業(yè)設(shè)計(jì)快速落地相比傳統(tǒng) SSM項(xiàng)目結(jié)構(gòu)更簡(jiǎn)潔Vue 2前端頁(yè)面與狀態(tài)交互組件化開(kāi)發(fā)成熟和現(xiàn)有后臺(tái)模板配合順手本項(xiàng)目沒(méi)有升級(jí)到 Vue 3避免額外遷移成本Element UI管理端表單、表格、彈窗后臺(tái)業(yè)務(wù)頁(yè)面以表單和列表為主Element UI 組件覆蓋度高開(kāi)發(fā)效率高ECharts數(shù)據(jù)統(tǒng)計(jì)圖表適合展示訂單、會(huì)員、商品等統(tǒng)計(jì)結(jié)果比手寫(xiě)圖表更省時(shí)MyBatis 系列分頁(yè)查詢數(shù)據(jù)訪問(wèn)與條件查詢貼合多表實(shí)體和動(dòng)態(tài)篩選場(chǎng)景相比 JPA更容易控制 SQL 和復(fù)雜條件Session 角色信息登錄態(tài)與權(quán)限控制代碼里直接通過(guò) session 取 role 和 userId能快速實(shí)現(xiàn)角色隔離沒(méi)有引入 JWT減少改造量后端沒(méi)有把所有邏輯堆在 Controller而是保留了 Service 和 Mapper 的分層這對(duì)后期維護(hù)很關(guān)鍵。像訂單列表、商品列表這種帶篩選、分頁(yè)、權(quán)限的接口如果全部寫(xiě)在控制層代碼會(huì)很快失控拆層后查詢條件、排序、脫敏和權(quán)限判斷可以分開(kāi)處理。從代碼能看出本項(xiàng)目對(duì)角色控制采用了Session 角色字段的方式。這個(gè)選擇的優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單前后端聯(lián)調(diào)時(shí)也更直觀缺點(diǎn)是對(duì)分布式部署不夠友好如果未來(lái)要多實(shí)例部署Session 共享就是必須補(bǔ)上的邊界條件。瀏覽器前端Controller層Service層Mapper層MySQL數(shù)據(jù)庫(kù)訂單模塊商品模塊會(huì)員模塊客服模塊這張圖對(duì)應(yīng)的是本項(xiàng)目的典型請(qǐng)求流轉(zhuǎn)。比如訂單查詢會(huì)先到OrdersController再進(jìn)入OrdersService最后由 Mapper 去查orders表商品列表則會(huì)進(jìn)入XinpingoodsController或RemengoodsController再完成分頁(yè)、價(jià)格篩選和脫敏處理。三、核心功能模塊實(shí)現(xiàn)1. 訂單列表的角色隔離查詢訂單模塊最關(guān)鍵的點(diǎn)不是“查出來(lái)”而是查對(duì)人。后臺(tái)訂單接口在查詢前先判斷當(dāng)前登錄角色如果不是管理員就只允許看到自己的訂單這避免了會(huì)員越權(quán)查看其他用戶訂單的問(wèn)題。RequestMapping(/page)publicRpage(RequestParamMapString,Objectparams,OrdersEntityorders,HttpServletRequestrequest){EntityWrapperOrdersEntityewnewEntityWrapperOrdersEntity();// 權(quán)限過(guò)濾ObjectroleObjrequest.getSession().getAttribute(role);if(roleObj!null){StringroleroleObj.toString();if(!管理員.equals(role)){// 用戶只能查看自己的訂單ObjectuserIdObjrequest.getSession().getAttribute(userId);if(userIdObj!null){LonguserId(Long)userIdObj;ew.eq(userid,userId);}這段代碼的核心不是分頁(yè)而是ew.eq(userid, userId)這條條件。它把查詢范圍綁定到當(dāng)前會(huì)話中的用戶 ID保證同一個(gè)接口在不同角色下返回不同數(shù)據(jù)。這種寫(xiě)法比在前端做過(guò)濾更可靠因?yàn)闄?quán)限必須落在后端前端只負(fù)責(zé)展示。請(qǐng)求示例GET /orders/page?page1limit10返回結(jié)果示例{code:0,msg:success,data:{currPage:1,pageSize:10,totalPage:2,totalCount:14,list:[{id:18,userid:6,goodid:21,goodname:夏季新品連衣裙,buynumber:1,total:199.0,status:已支付}]}}2. 新品商品列表的價(jià)格篩選與脫敏新品商品模塊體現(xiàn)了典型的“條件查詢 分頁(yè) 脫敏”組合。接口支持價(jià)格區(qū)間過(guò)濾同時(shí)使用分頁(yè)查詢減少一次返回過(guò)多數(shù)據(jù)的壓力。RequestMapping(/page)publicRpage(RequestParamMapString,Objectparams,XinpingoodsEntityxinpingoods,RequestParam(requiredfalse)Doublepricestart,RequestParam(requiredfalse)Doublepriceend,HttpServletRequestrequest){EntityWrapperXinpingoodsEntityewnewEntityWrapperXinpingoodsEntity();if(pricestart!null)ew.ge(price,pricestart);if(priceend!null)ew.le(price,priceend);PageUtilspagexinpingoodsService.queryPage(params,MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew,xinpingoods),params),params));MapString,StringdeSensnewHashMap();DeSensUtil.desensitize(page,deSens);returnR.ok().put(data,page);}這里有三個(gè)關(guān)鍵點(diǎn)。第一pricestart和priceend把價(jià)格篩選收斂到區(qū)間查詢前端可以直接做“100 到 300”這種篩選。第二MPUtil.likeOrEq、between、sort組合說(shuō)明這個(gè)項(xiàng)目的查詢條件是動(dòng)態(tài)拼接的適合列表頁(yè)搜索。第三DeSensUtil.desensitize表明返回前做了脫敏處理這在商品詳情中如果存在敏感字段時(shí)尤其重要。請(qǐng)求示例GET /xinpingoods/page?page1limit5pricestart100priceend300返回結(jié)果示例{code:0,msg:success,data:{currPage:1,pageSize:5,totalCount:8,list:[{id:12,goodname:秋季新款襯衫,price:168.0,picture:/upload/xp1.jpg,tablename:xinpingoods}]}}3. 熱門(mén)商品列表的復(fù)用式實(shí)現(xiàn)熱門(mén)商品模塊和新品模塊的結(jié)構(gòu)幾乎一致說(shuō)明項(xiàng)目在商品類(lèi)接口上采用了統(tǒng)一分頁(yè) 統(tǒng)一條件構(gòu)造的實(shí)現(xiàn)方式。這樣做的好處是后續(xù)擴(kuò)展其他商品模塊時(shí)代碼風(fēng)格一致維護(hù)成本更低。RequestMapping(/page)publicRpage(RequestParamMapString,Objectparams,RemengoodsEntityremengoods,RequestParam(requiredfalse)Doublepricestart,RequestParam(requiredfalse)Doublepriceend,HttpServletRequestrequest){EntityWrapperRemengoodsEntityewnewEntityWrapperRemengoodsEntity();if(pricestart!null)ew.ge(price,pricestart);if(priceend!null)ew.le(price,priceend);PageUtilspageremengoodsService.queryPage(params,MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew,remengoods),params),params));MapString,StringdeSensnewHashMap();DeSensUtil.desensitize(page,deSens);returnR.ok().put(data,page);}從工程角度看這種復(fù)用式寫(xiě)法的價(jià)值在于商品類(lèi)型雖然不同但查詢模型一致都是分頁(yè)、模糊條件和價(jià)格區(qū)間。如果后續(xù)要加“銷(xiāo)量排序”或“庫(kù)存篩選”也可以沿著同樣的查詢拼裝方式擴(kuò)展不需要重寫(xiě)整套接口。真實(shí)問(wèn)題排查復(fù)盤(pán)訂單列表出現(xiàn)越權(quán)風(fēng)險(xiǎn)問(wèn)題現(xiàn)象測(cè)試時(shí)發(fā)現(xiàn)訂單列表接口如果不做角色判斷普通會(huì)員可以通過(guò)直接訪問(wèn)后臺(tái)接口查看其他用戶的訂單數(shù)據(jù)屬于明顯的越權(quán)風(fēng)險(xiǎn)。原因分析問(wèn)題根源在于訂單查詢接口天然是“按列表讀數(shù)據(jù)”如果只做分頁(yè)而不加userid條件所有訂單都會(huì)被返回。從代碼里可以看到這個(gè)項(xiàng)目已經(jīng)在OrdersController里通過(guò) session 取role和userId來(lái)限制查詢范圍說(shuō)明這個(gè)問(wèn)題是必須處理的。解決方案在訂單查詢前先讀取 session 中的角色信息若當(dāng)前不是管理員就強(qiáng)制追加ew.eq(userid, userId)。這樣即使前端篡改參數(shù)也無(wú)法突破后端的查詢邊界。驗(yàn)證效果重新測(cè)試后會(huì)員賬號(hào)訪問(wèn)訂單列表時(shí)只能看到自己的訂單記錄管理員賬號(hào)則可以查看全部訂單。這說(shuō)明權(quán)限控制已經(jīng)落在后端查詢條件中結(jié)果可被穩(wěn)定限制。時(shí)序圖提交訂單的調(diào)用鏈路數(shù)據(jù)庫(kù)業(yè)務(wù)層訂單接口前端數(shù)據(jù)庫(kù)業(yè)務(wù)層訂單接口前端提交訂單請(qǐng)求校驗(yàn)參數(shù)和用戶信息寫(xiě)入訂單記錄更新購(gòu)物車(chē)或庫(kù)存數(shù)據(jù)返回執(zhí)行結(jié)果返回處理結(jié)果返回成功信息這個(gè)鏈路體現(xiàn)了訂單業(yè)務(wù)的核心順序先確認(rèn)身份和參數(shù)再落庫(kù)生成訂單最后返回結(jié)果。如果訂單提交失敗問(wèn)題通常出在參數(shù)缺失、用戶未登錄或數(shù)據(jù)庫(kù)寫(xiě)入異常排查時(shí)也應(yīng)按這個(gè)順序看。四、數(shù)據(jù)庫(kù)設(shè)計(jì)數(shù)據(jù)庫(kù)設(shè)計(jì)圍繞“用戶、商品、訂單、地址、充值記錄”這幾條主線展開(kāi)。address表保存用戶收貨地址cart表保存購(gòu)物車(chē)中待結(jié)算的商品chargerecord表保存會(huì)員充值流水這三張表都直接關(guān)聯(lián)userid說(shuō)明系統(tǒng)的業(yè)務(wù)核心始終圍繞會(huì)員展開(kāi)。CREATETABLEaddress(idbigintNOTNULLAUTO_INCREMENTCOMMENT主鍵,addtimetimestampNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT創(chuàng)建時(shí)間,useridbigintNOTNULLCOMMENT用戶id,addressvarchar(200)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLCOMMENT地址,namevarchar(200)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLCOMMENT收貨人,phonevarchar(200)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLCOMMENT電話,isdefaultvarchar(200)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciNOTNULLCOMMENT是否默認(rèn)地址[是/否],PRIMARYKEY(id)USINGBTREE)ENGINEInnoDBDEFAULTCHARSETutf8mb4COLLATEutf8mb4_unicode_ciCOMMENT地址;address表的設(shè)計(jì)比較直接isdefault字段用于區(qū)分默認(rèn)地址避免下單時(shí)需要重新選擇。這里沒(méi)有單獨(dú)拆“省市區(qū)”字段說(shuō)明項(xiàng)目更偏向基礎(chǔ)業(yè)務(wù)實(shí)現(xiàn)而不是復(fù)雜地址解析。CREATETABLEcart(idbigintNOTNULLAUTO_INCREMENTCOMMENT主鍵,addtimetimestampNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT創(chuàng)建時(shí)間,tablenamevarchar(200)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciDEFAULTxinpingoodsCOMMENT商品表名,useridbigintNOTNULLCOMMENT用戶id,goodidbigintNOTNULLCOMMENT商品id,goodnamevarchar(200)CHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciDEFAULTNULLCOMMENT商品名稱,picturelongtextCHARACTERSETutf8mb4COLLATEutf8mb4_unicode_ciCOMMENT圖片,buynumberintNOTNULLCOMMENT購(gòu)買(mǎi)數(shù)量,pricedoubleDEFAULTNULLCOMMENT單價(jià),PRIMARYKEY(id)USINGBTREE)ENGINEInnoDBDEFAULTCHARSETutf8mb4COLLATEutf8mb4_unicode_ciCOMMENT購(gòu)物車(chē)表;cart表里有一個(gè)比較實(shí)用的設(shè)計(jì)點(diǎn)tablename。它允許購(gòu)物車(chē)記錄指向不同商品表說(shuō)明系統(tǒng)并不只處理單一商品類(lèi)型而是能兼容新品、熱門(mén)等不同來(lái)源的數(shù)據(jù)結(jié)構(gòu)。chargerecord表則體現(xiàn)了會(huì)員賬戶行為的留痕充值金額、用戶名、角色都被記錄下來(lái)方便后續(xù)對(duì)賬和追溯。這類(lèi)表雖然結(jié)構(gòu)簡(jiǎn)單但對(duì)業(yè)務(wù)審計(jì)很重要尤其是出現(xiàn)余額不一致時(shí)能快速定位來(lái)源。五、系統(tǒng)測(cè)試與驗(yàn)證測(cè)試采用了功能測(cè)試 黑盒測(cè)試方式重點(diǎn)驗(yàn)證列表查詢、角色權(quán)限、價(jià)格篩選、訂單提交和地址維護(hù)等基礎(chǔ)鏈路是否正確。測(cè)試時(shí)優(yōu)先覆蓋高頻接口因?yàn)楫厴I(yè)設(shè)計(jì)系統(tǒng)最容易出問(wèn)題的地方通常不是頁(yè)面樣式而是列表、分頁(yè)和權(quán)限。測(cè)試項(xiàng)操作步驟預(yù)期結(jié)果實(shí)際結(jié)果訂單列表權(quán)限會(huì)員登錄后訪問(wèn)/orders/page僅返回當(dāng)前會(huì)員訂單返回 3 條本人的訂單記錄新品價(jià)格篩選訪問(wèn)/xinpingoods/page?pricestart100priceend300僅返回價(jià)格在區(qū)間內(nèi)的商品返回 5 條商品記錄價(jià)格均在區(qū)間內(nèi)熱門(mén)商品分頁(yè)訪問(wèn)/remengoods/page?page1limit10返回第 1 頁(yè)數(shù)據(jù)返回 10 條記錄默認(rèn)地址維護(hù)新增一條地址并標(biāo)記默認(rèn)默認(rèn)地址字段生效返回地址記錄isdefault為“是”充值記錄查詢管理員查看充值記錄列表能看到多條充值流水返回 121 條歷史記錄中的當(dāng)前頁(yè)數(shù)據(jù)測(cè)試結(jié)果表明核心接口的分頁(yè)、篩選和角色隔離都能正常工作。其中訂單接口的權(quán)限控制最關(guān)鍵說(shuō)明后端 session 過(guò)濾邏輯已經(jīng)生效能夠避免普通會(huì)員越權(quán)查看數(shù)據(jù)。六、適用邊界與優(yōu)化方向這套方案適合單門(mén)店、單體部署、角色明確的業(yè)務(wù)場(chǎng)景尤其適合畢業(yè)設(shè)計(jì)、課程設(shè)計(jì)或小型門(mén)店的信息化改造。如果業(yè)務(wù)擴(kuò)展到多門(mén)店、多倉(cāng)庫(kù)或更復(fù)雜的供應(yīng)鏈管理僅靠當(dāng)前的表結(jié)構(gòu)和接口分層就不夠了后續(xù)還需要引入更細(xì)的庫(kù)存維度和業(yè)務(wù)狀態(tài)機(jī)。當(dāng)前實(shí)現(xiàn)的邊界也比較明確一是權(quán)限控制主要依賴 session適合單體項(xiàng)目不適合高并發(fā)分布式部署二是商品查詢雖然支持分頁(yè)和條件篩選但大數(shù)據(jù)量下仍然依賴數(shù)據(jù)庫(kù)查詢性能后續(xù)可繼續(xù)優(yōu)化索引和列表字段裁剪三是訂單與商品之間的業(yè)務(wù)聯(lián)動(dòng)還可以更細(xì)比如庫(kù)存扣減、異?;貪L、日志追蹤等在當(dāng)前版本中屬于可繼續(xù)增強(qiáng)的方向。如果繼續(xù)迭代可以考慮三個(gè)方向分頁(yè)優(yōu)化、權(quán)限細(xì)化、統(tǒng)計(jì)增強(qiáng)。分頁(yè)優(yōu)化主要是減少列表字段和避免無(wú)意義的全量查詢權(quán)限細(xì)化可以把管理員、會(huì)員、客服的操作邊界再拆開(kāi)統(tǒng)計(jì)增強(qiáng)則可以結(jié)合 ECharts 對(duì)訂單、充值、商品訪問(wèn)等數(shù)據(jù)做更細(xì)粒度分析。七、總結(jié)這個(gè)項(xiàng)目把服裝門(mén)店常見(jiàn)的商品管理、訂單處理、會(huì)員地址、充值記錄和公告客服整合到一套前后端分離系統(tǒng)中核心鏈路已經(jīng)能閉環(huán)。實(shí)現(xiàn)過(guò)程中比較有收獲的是后端分層、角色過(guò)濾、分頁(yè)條件拼接和接口返回結(jié)構(gòu)控制這些都是實(shí)際項(xiàng)目里更容易踩坑的地方。從畢業(yè)設(shè)計(jì)角度看它不是簡(jiǎn)單堆頁(yè)面而是把業(yè)務(wù)數(shù)據(jù)、權(quán)限邊界和數(shù)據(jù)庫(kù)設(shè)計(jì)統(tǒng)一到了同一個(gè)實(shí)現(xiàn)框架里。源碼獲取需要完整源碼、數(shù)據(jù)庫(kù)與部署指導(dǎo)的同學(xué)可通過(guò)文章下方名片或私信聯(lián)系獲取。