系統(tǒng)畢設(shè):從預(yù)約到結(jié)算全鏈路設(shè)計(jì)與實(shí)現(xiàn))
1. 項(xiàng)目到底在做什么為什么值得拿來(lái)做畢設(shè)先說(shuō)結(jié)論這套“基于SpringBoot的汽車維修保養(yǎng)服務(wù)信息系統(tǒng)”本質(zhì)上是一套面向汽車后市場(chǎng)門店的業(yè)務(wù)管理平臺(tái)覆蓋了從客戶預(yù)約、到店接車、工單派工、配件領(lǐng)用、維修結(jié)算到保養(yǎng)記錄歸檔的完整業(yè)務(wù)閉環(huán)。和那種只做登錄注冊(cè)加幾個(gè)CRUD就能交差的畢設(shè)比起來(lái)它有一個(gè)很明顯的優(yōu)勢(shì)業(yè)務(wù)線足夠長(zhǎng)、角色足夠清晰、流程足夠真實(shí)老師看目錄就知道你不是在糊弄事。我在帶學(xué)生選題時(shí)發(fā)現(xiàn)選這個(gè)題目的人普遍有三個(gè)訴求。第一是技術(shù)棧主流SpringBoot加MyBatis-Plus加MySQL這套組合在Java崗位招聘里出現(xiàn)頻率極高做完這個(gè)項(xiàng)目面試聊起來(lái)不虛第二是業(yè)務(wù)不冷門汽車保有量大家都知道維修保養(yǎng)是剛需場(chǎng)景需求解釋起來(lái)毫無(wú)障礙第三是最關(guān)鍵的——它好講。論文里能畫業(yè)務(wù)流程圖、用例圖、 E-R圖、狀態(tài)圖答辯現(xiàn)場(chǎng)能現(xiàn)場(chǎng)演示“用戶預(yù)約一個(gè)保養(yǎng)然后接車開單、技師領(lǐng)料、完工結(jié)算”這條完整鏈路每一步都有界面和數(shù)據(jù)變化比干巴巴介紹一個(gè)后臺(tái)管理系統(tǒng)有說(shuō)服力得多。那這個(gè)項(xiàng)目到底是給誰(shuí)用的我建議在需求分析里就講清楚。系統(tǒng)至少要有三類角色車主用戶負(fù)責(zé)在線預(yù)約、查看車輛檔案、查詢訂單進(jìn)度和結(jié)算明細(xì)門店接待員負(fù)責(zé)接車、創(chuàng)建工單、確認(rèn)服務(wù)項(xiàng)目技師負(fù)責(zé)執(zhí)行維修保養(yǎng)、填寫工單狀態(tài)、申請(qǐng)領(lǐng)料店長(zhǎng)或管理員負(fù)責(zé)員工管理、配件庫(kù)存管理、價(jià)格折扣設(shè)置和數(shù)據(jù)統(tǒng)計(jì)。角色一多系統(tǒng)的功能矩陣就撐起來(lái)了論文里的功能模塊圖才不會(huì)畫得空。如果讓我一句話概括這個(gè)項(xiàng)目的定位它不是那種純粹的“增刪改查展示”而是一套有流程、有狀態(tài)、有單據(jù)關(guān)聯(lián)的輕量級(jí)業(yè)務(wù)系統(tǒng)。對(duì)畢設(shè)來(lái)說(shuō)這種復(fù)雜度剛剛好——既能讓評(píng)審老師看到你的設(shè)計(jì)能力又不會(huì)難到三個(gè)月做不完。2. 技術(shù)選型和項(xiàng)目骨架怎么搭才能穩(wěn)2.1 SpringBoot版本選擇千萬(wàn)別一上來(lái)就追最新很多同學(xué)下載源碼第一步就卡住了因?yàn)镾pringBoot版本太高導(dǎo)致依賴不兼容這是最最常見的坑。熱詞里能看到“springboot版本太高”這種搜索說(shuō)明踩坑的人不在少數(shù)。我個(gè)人的建議是如果老師沒有硬性要求優(yōu)先選擇2.7.x這個(gè)系列不要直接上3.x。原因很實(shí)在SpringBoot 3.x基于Java 17Spring Framework 6.x里很多配置類路徑變了比如WebMvcConfigurerAdapter沒了、javax.*換成了jakarta.*網(wǎng)上大部分舊教程和現(xiàn)成代碼片段都用不了。而2.7.x用Java 8就能跑在學(xué)校的實(shí)驗(yàn)機(jī)器和大多數(shù)云服務(wù)器上都能正常部署而且它仍然是當(dāng)前就業(yè)市場(chǎng)里很多公司實(shí)際在用的版本節(jié)奏。說(shuō)實(shí)話畢設(shè)階段展示的是你解決問(wèn)題的能力不是追新版本的能力穩(wěn)定壓倒一切。2.2 后端骨架SpringBoot加MyBatis-Plus加MySQL就夠了后端技術(shù)選型我推薦一個(gè)“最低復(fù)雜度但能撐住答辯”的組合SpringBoot做整體框架MyBatis-Plus做數(shù)據(jù)訪問(wèn)MySQL做數(shù)據(jù)存儲(chǔ)Swagger或Knife4j生成接口文檔Lombok減少樣板代碼。這個(gè)組合的好處是每一項(xiàng)都有明確的替代品可以講如果你不想用MyBatis-Plus也可以改成Spring Data JPA答辯時(shí)還能對(duì)比一下兩者適合的場(chǎng)景。分層的結(jié)構(gòu)我建議嚴(yán)格遵守Controller只做參數(shù)接收和響應(yīng)封裝Service層寫業(yè)務(wù)邏輯和事務(wù)控制Mapper層只寫SQL和查詢。不要圖省事把SQL直接甩在Controller里也不要為了炫耀技術(shù)堆一堆設(shè)計(jì)模式干凈的三層結(jié)構(gòu)在畢設(shè)評(píng)分里是最穩(wěn)的。實(shí)際代碼里我會(huì)分成這些包c(diǎn)om.example.autoservice ├── controller ├── service │ ├── impl ├── mapper ├── entity ├── dto ├── vo ├── config ├── common │ ├── result // 統(tǒng)一返回結(jié)果 │ ├── exception // 全局異常處理 │ └── enums // 訂單狀態(tài)、角色等枚舉2.3 前端怎么選模板引擎還是前后端分離前端是這個(gè)項(xiàng)目里最容易拖后腿的地方。我的建議很直接如果時(shí)間緊張就用Thymeleaf加Bootstrap或者Layui服務(wù)端渲染頁(yè)面少一點(diǎn)SpringSecurity配置一下頁(yè)面權(quán)限就完事。這樣整套項(xiàng)目一個(gè)端口直接跑起來(lái)部署簡(jiǎn)單答辯演示時(shí)也不用開兩個(gè)服務(wù)。如果基礎(chǔ)比較好或者老師明確要求前后端分離那就用Vue加Element UI或Element Plus寫管理端用戶端可以簡(jiǎn)單用Vue加Vant。前后端分離的好處是項(xiàng)目結(jié)構(gòu)更像企業(yè)真實(shí)開發(fā)但代價(jià)是要多處理跨域、Token傳遞、CORS配置這些問(wèn)題。我見過(guò)不少學(xué)生把時(shí)間耗在這上面結(jié)果核心業(yè)務(wù)反而寫得倉(cāng)促。所以選擇前端方案之前先算自己還有多少時(shí)間再?zèng)Q定要卷到什么程度。2.4 權(quán)限控制做多深取決于你想拿什么分?jǐn)?shù)權(quán)限部分我不建議一上來(lái)就用特別復(fù)雜的Spring Security加OAuth2那對(duì)畢設(shè)來(lái)說(shuō)有點(diǎn)超綱。更實(shí)用的方案是Spring Security做最基礎(chǔ)的認(rèn)證授權(quán)或者干脆用一個(gè)簡(jiǎn)單的攔截器加JWT Token。用戶、接待員、技師、管理員這四類角色各有不同的菜單和接口權(quán)限只要有基于角色的訪問(wèn)控制、能擋住“普通用戶直接訪問(wèn)管理接口”這種安全問(wèn)題就已經(jīng)足夠上答辯了。我做這套項(xiàng)目時(shí)選的是Spring Security加JWT。登錄接口校驗(yàn)用戶名密碼成功后發(fā)放Token前端每次請(qǐng)求都攜帶后端通過(guò)注解PreAuthorize(hasRole(ADMIN))控制接口權(quán)限。這樣寫在論文里能講清楚“認(rèn)證和授權(quán)是兩件事”也能在演示時(shí)現(xiàn)場(chǎng)演示越權(quán)訪問(wèn)被攔截的效果比純攔截器加分不少。3. 核心業(yè)務(wù)模塊拆解與數(shù)據(jù)庫(kù)設(shè)計(jì)思路3.1 功能模塊地圖一次講清系統(tǒng)包含哪幾個(gè)部分這個(gè)系統(tǒng)的功能模塊可以分成三大塊來(lái)講。第一塊是客戶服務(wù)端用戶注冊(cè)登錄、車輛檔案管理、保養(yǎng)項(xiàng)目瀏覽、在線預(yù)約、預(yù)約記錄查看、訂單進(jìn)度查詢、賬單明細(xì)查看。第二塊是門店運(yùn)營(yíng)端接車登記、檢修項(xiàng)目確認(rèn)、工單創(chuàng)建與派工、配件領(lǐng)用與歸還、工時(shí)費(fèi)錄入、維修結(jié)算、保養(yǎng)提醒記錄。第三塊是基礎(chǔ)管理端員工賬號(hào)管理、角色權(quán)限分配、配件類別與庫(kù)存管理、供應(yīng)商信息管理、會(huì)員折扣設(shè)置、首頁(yè)統(tǒng)計(jì)看板。如果你想讓項(xiàng)目更亮眼還可以加一個(gè)“提醒與回訪”功能根據(jù)車輛的上次保養(yǎng)時(shí)間和里程數(shù)自動(dòng)生成建議保養(yǎng)日期列表客服可以電話回訪并登記結(jié)果。這個(gè)功能不需要額外硬件但會(huì)很貼近真實(shí)門店的業(yè)務(wù)答辯時(shí)老師聽完往往能感覺到你確實(shí)理解業(yè)務(wù)場(chǎng)景而非只懂CRUD。3.2 關(guān)鍵數(shù)據(jù)表設(shè)計(jì)和字段取舍數(shù)據(jù)表是這個(gè)項(xiàng)目的心臟。按我拆出來(lái)的最小但完整的表清單大概需要十張表左右用戶表、車輛表、預(yù)約單表、維修工單表、工單明細(xì)表、配件表、配件出入庫(kù)記錄表、員工表、結(jié)算單表、保養(yǎng)記錄表。如果做會(huì)員和折扣再加會(huì)員等級(jí)表做統(tǒng)計(jì)再加一張視圖就夠不用太多冗余表。表之間最關(guān)鍵的一條業(yè)務(wù)主鏈?zhǔn)穷A(yù)約單appointment→ 維修工單repair_room用repair_order更好 → 工單明細(xì)repair_item→ 結(jié)算單settlement。其中預(yù)約單和工單之間是“先約后修”的銜接關(guān)系工單明細(xì)關(guān)聯(lián)配件表配件領(lǐng)用要寫庫(kù)存流水。每一步單據(jù)變化都建議用狀態(tài)字段來(lái)記錄而不是直接刪數(shù)據(jù)。舉幾個(gè)字段設(shè)計(jì)上的要點(diǎn)。預(yù)約表里除了預(yù)約時(shí)間必須加一個(gè)“狀態(tài)”字段取值可以是0待確認(rèn)、1已確認(rèn)、2已到店、3已取消、4已完成維修工單表里建議有order_no工單號(hào)、car_id、appointment_id、assignee_id技師、status、total_amount、remark工單明細(xì)表至少要有item_name比如機(jī)油更換、item_type工時(shí)還是配件、quantity、unit_price、amount、part_id。結(jié)算單則由工單匯總生成記錄應(yīng)收金額、優(yōu)惠金額、實(shí)收金額、支付方式。3.3 用狀態(tài)機(jī)思維串聯(lián)整個(gè)業(yè)務(wù)流程這個(gè)系統(tǒng)最值錢的設(shè)計(jì)不是表多而是狀態(tài)流轉(zhuǎn)清晰。把預(yù)約、工單、結(jié)算的狀態(tài)串起來(lái)你就擁有了一個(gè)隨時(shí)可以在紙上畫出來(lái)的業(yè)務(wù)流程。我常用的簡(jiǎn)化狀態(tài)機(jī)大概是這樣的預(yù)約單待確認(rèn) → 已確認(rèn) → 已到店 → 已完成 ↘ 已取消 維修工單待接車 → 維修中 → 待質(zhì)檢 → 已完成 → 已結(jié)算 配件領(lǐng)用申請(qǐng)中 → 已出庫(kù) → 已歸還如有剩料 結(jié)算單未支付 → 已支付 → 已開票每個(gè)狀態(tài)變更記錄一下操作人和變更時(shí)間面試和答辯都能加分。4. 從零實(shí)現(xiàn)核心流程預(yù)約、派工、領(lǐng)料、結(jié)算全鏈路4.1 預(yù)約功能參數(shù)校驗(yàn)與沖突檢測(cè)預(yù)約功能看起來(lái)簡(jiǎn)單但真正做好有幾個(gè)坑。用戶選擇服務(wù)項(xiàng)目和到店時(shí)間后后端不能只插入一條記錄就結(jié)束。第一步要校驗(yàn)車輛是否存在是不是當(dāng)前登錄用戶名下的車輛第二步要校驗(yàn)預(yù)約時(shí)間段是否在營(yíng)業(yè)時(shí)間內(nèi)第三步如果同一接待員或工位已經(jīng)有預(yù)約最好給出提示哪怕不做嚴(yán)格的沖突阻斷也要在界面上顯示可選時(shí)間段。核心代碼大概是這樣一種風(fēng)格用Transactional保證預(yù)約記錄和狀態(tài)初始提交是原子的Transactional public AppointmentDTO createAppointment(AppointmentRequest request) { // 1. 校驗(yàn)車輛歸屬 Car car carMapper.selectById(request.getCarId()); if (car null || !car.getUserId().equals(currentUserId())) { throw new BizException(車輛不存在或不屬于當(dāng)前用戶); } // 2. 校驗(yàn)時(shí)間段是否可約 long conflictCount appointmentMapper.countByTimeRange( request.getStartTime(), request.getEndTime()); if (conflictCount 0) { throw new BizException(該時(shí)間段已被預(yù)約請(qǐng)更換時(shí)間); } // 3. 創(chuàng)建預(yù)約單初始狀態(tài)為待確認(rèn) Appointment appointment new Appointment(); BeanUtils.copyProperties(request, appointment); appointment.setStatus(AppointmentStatus.PENDING_CONFIRM); appointmentMapper.insert(appointment); return convertToDTO(appointment); }注意這里用Transactional不只是為了保險(xiǎn)而是為了給論文里“數(shù)據(jù)庫(kù)事務(wù)”那一節(jié)留一個(gè)真實(shí)的例子答辯時(shí)你能直接說(shuō)出“如果第二步拋異常前一步插入的數(shù)據(jù)會(huì)自動(dòng)回滾不會(huì)產(chǎn)生臟數(shù)據(jù)”。4.2 接車和創(chuàng)建維修工單數(shù)據(jù)傳遞不能丟用戶到店后接待員在后臺(tái)找到對(duì)應(yīng)預(yù)約單點(diǎn)擊“到店接車”系統(tǒng)自動(dòng)創(chuàng)建維修工單。這里最容易犯的錯(cuò)誤是把預(yù)約單里的信息手動(dòng)重新錄入一遍然后又對(duì)不上。正確做法是工單創(chuàng)建時(shí)直接引用預(yù)約單ID初始化時(shí)把car_id、user_id、appointment_id復(fù)制過(guò)去同時(shí)生成一個(gè)格式化的工單號(hào)比如WO20250612001。接車環(huán)節(jié)我還強(qiáng)烈建議加一個(gè)“車輛當(dāng)前狀態(tài)”字段比如里程數(shù)、油量、外觀備注。雖然用戶自己看不到多重要但是這在真實(shí)門店里是避免客訴的關(guān)鍵也讓你在論文的“需求分析”里多出一條令人信服的功能點(diǎn)。錄入完畢后工單狀態(tài)從“待接車”變?yōu)椤熬S修中”這一步要記得在工單記錄表和日志表里同時(shí)寫入操作軌跡。4.3 派工與配件領(lǐng)料庫(kù)存扣減的并發(fā)控制派工就是把工單分配給某個(gè)技師更新工單的assignee_id和狀態(tài)。這里通常會(huì)遇到一個(gè)比較容易講但也很容易答不上來(lái)的問(wèn)題如果一個(gè)配件被兩個(gè)工單同時(shí)領(lǐng)用庫(kù)存該誰(shuí)先扣為了不讓庫(kù)存變成負(fù)數(shù)查詢和扣減必須放在同一個(gè)事務(wù)里并且使用原子更新SQL。UPDATE part SET stock stock - #{quantity} WHERE id #{partId} AND stock #{quantity}不要先SELECT stock在Java里判斷數(shù)量再UPDATE因?yàn)椴l(fā)條件下會(huì)出問(wèn)題。用上面這條SQL如果庫(kù)存不足受影響行數(shù)是0Service層檢測(cè)到這個(gè)結(jié)果直接拋出“庫(kù)存不足”的異常事務(wù)回滾非常干凈。這一段內(nèi)容寫進(jìn)論文的“系統(tǒng)設(shè)計(jì)細(xì)節(jié)”或者答辯時(shí)被問(wèn)到“你怎么保證數(shù)據(jù)一致性”會(huì)是非常扎實(shí)的答案。領(lǐng)料之后配件表減庫(kù)存配件出入庫(kù)記錄表加一條“出庫(kù)”流水這樣即使某天下單發(fā)現(xiàn)庫(kù)存不對(duì)也能倒查是哪張工單領(lǐng)走了配件。4.4 結(jié)算單生成工時(shí)加材料費(fèi)加會(huì)員折扣維修完工后接待員進(jìn)入結(jié)算頁(yè)面。結(jié)算單明細(xì)來(lái)自工單明細(xì)的兩部分工時(shí)項(xiàng)目item_type為工時(shí)和配件項(xiàng)目item_type為配件。金額計(jì)算要注意一個(gè)地方如果訂單里有多個(gè)配件和一個(gè)會(huì)員折扣不能簡(jiǎn)單把所有金額乘折扣因?yàn)榕浼杀就挥?jì)入會(huì)員折扣具體折扣規(guī)則應(yīng)該跟著會(huì)員等級(jí)走論文里可以把這條業(yè)務(wù)規(guī)則寫得很明確。我這里用一張匯總表來(lái)演示一個(gè)結(jié)算示例項(xiàng)目數(shù)量單價(jià)元小計(jì)元工時(shí)費(fèi)常規(guī)保養(yǎng)檢查1120120工時(shí)費(fèi)更換機(jī)油機(jī)濾18080配件全合成機(jī)油4L1320320配件機(jī)油濾芯14545會(huì)員折扣9.5折僅限工時(shí)--減10合計(jì)應(yīng)付--555建議把“工時(shí)費(fèi)”“材料費(fèi)”“折扣金額”分開三個(gè)字段存儲(chǔ)這樣后續(xù)做月度營(yíng)收統(tǒng)計(jì)時(shí)可以分別統(tǒng)計(jì)工時(shí)收入和配件收入報(bào)表維度更多論文里的數(shù)據(jù)分析章節(jié)才不會(huì)沒得寫。5. 畢設(shè)調(diào)試運(yùn)行的常見問(wèn)題我?guī)湍闩胚^(guò)雷5.1 啟動(dòng)失敗SpringBoot版本與依賴沖突不少學(xué)生拿到源碼后第一反應(yīng)是“直接啟動(dòng)”結(jié)果控制臺(tái)報(bào)一堆紅色異常。最常見的場(chǎng)景是項(xiàng)目用的SpringBoot 2.7.x本地卻裝了JDK 17或者引用了某個(gè)只適配舊版本的第三方依賴導(dǎo)致沖突。我的排查順序是先看項(xiàng)目里pom.xml聲明的SpringBoot版本再確認(rèn)本機(jī)JDK版本最后用mvn -version看Maven用的解釋器版本。提示畢設(shè)項(xiàng)目不要為了“看著新”去強(qiáng)行升級(jí)SpringBoot大版本。2.7.x在當(dāng)前生態(tài)里足夠穩(wěn)定大多數(shù)依賴比如MyBatis-Plus、Knife4j都有匹配版本網(wǎng)上問(wèn)題答案也豐富不至于一卡卡三天。5.2 數(shù)據(jù)庫(kù)連不上驅(qū)動(dòng)和時(shí)區(qū)一個(gè)都不能少體現(xiàn)項(xiàng)目能不能跑通的關(guān)鍵之一就是數(shù)據(jù)庫(kù)連接配置。用MySQL 8.0的時(shí)候application.yml里驅(qū)動(dòng)類要寫com.mysql.cj.jdbc.DriverURL要加serverTimezoneAsia/Shanghai和useUnicodetruecharacterEncodingutf8。如果這些沒寫對(duì)最常見的報(bào)錯(cuò)是Cannot create PoolableConnectionFactory和時(shí)區(qū)導(dǎo)致的日期錯(cuò)亂。另外如果本地MySQL密碼是空密碼也要確認(rèn)配置文件的密碼字段是否保持空字符串不要隨手填了一個(gè)固定的123456。5.3 用MyBatis-Plus根據(jù)實(shí)體類生成建表SQL這是很多人不知道的省事技巧。寫好了實(shí)體類之后可以把a(bǔ)pplication.yml里的ddl-auto或MyBatis-Plus的初始化策略臨時(shí)打開讓它自動(dòng)建表。不過(guò)我不建議一直開著這個(gè)配置跑正式數(shù)據(jù)因?yàn)樗赡軙?huì)動(dòng)到已有表結(jié)構(gòu)。更穩(wěn)的做法是用MyBatis-Plus的代碼生成器生成建表語(yǔ)句或者用工具比如IDEA的Database面板、Navicat手動(dòng)建表后再用代碼生成器反向生成實(shí)體類。兩種方向都有同學(xué)踩過(guò)坑正向生成容易字段類型不對(duì)反向生成更貼近真實(shí)表結(jié)構(gòu)。如果你只想快速?gòu)?fù)現(xiàn)項(xiàng)目把SQL腳本文件導(dǎo)入數(shù)據(jù)庫(kù)是最直接的。注意導(dǎo)入順序先建用戶和車輛基礎(chǔ)表再建預(yù)約單、工單這些依賴表最后建結(jié)算單。外鍵約束如果建得很嚴(yán)格導(dǎo)數(shù)據(jù)時(shí)也要注意先刪后建或者先禁約束。5.4 接口聯(lián)調(diào)不通跨域和Token最容易出問(wèn)題如果前端是獨(dú)立于后端的Vue項(xiàng)目就一定會(huì)遇到跨域問(wèn)題。后端要配置CORS下面這個(gè)是SpringBoot項(xiàng)目里非常常見的全局配置方法Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); }配置完跨域后如果前端發(fā)請(qǐng)求還報(bào)401那就要去檢查Token是不是正確放到了請(qǐng)求頭里。我見過(guò)太多人把Token放到了請(qǐng)求參數(shù)里而后端攔截器只從請(qǐng)求頭取兩邊說(shuō)不上話。統(tǒng)一在前端請(qǐng)求攔截器里加Authorization: Bearer xxx后端對(duì)應(yīng)解析這套鏈路很經(jīng)典。5.5 演示當(dāng)天翻車現(xiàn)場(chǎng)怎么救參與過(guò)幾次模擬答辯之后我總結(jié)了一個(gè)規(guī)律系統(tǒng)跑不起來(lái)很多時(shí)候不是代碼問(wèn)題而是操作順序問(wèn)題。演示前建議把服務(wù)端啟動(dòng)的依賴都列個(gè)清單包括MySQL是否啟動(dòng)、Redis是否啟動(dòng)如果用了、后臺(tái)管理賬號(hào)密碼是否記得、常見演示數(shù)據(jù)是否還在。還有一個(gè)當(dāng)事人沒說(shuō)但很常見的翻車點(diǎn)直接把IDEA保存的本地端口寫死在論文里結(jié)果現(xiàn)場(chǎng)用的是另一臺(tái)機(jī)器端口全變了。我自己的習(xí)慣是在項(xiàng)目根目錄寫一個(gè)README把啟動(dòng)步驟三句話寫清楚——初始化數(shù)據(jù)庫(kù)、改成本機(jī)配置、啟動(dòng)后端再啟動(dòng)前端。這種細(xì)節(jié)看似不起眼關(guān)鍵時(shí)刻能救命。6. 項(xiàng)目還可以往哪些方向加分?jǐn)U展做完上面這些核心功能項(xiàng)目已經(jīng)完全能畢業(yè)了但如果你還有時(shí)間想卷一下我有幾個(gè)性價(jià)比很高的擴(kuò)展方向。第一是消息提醒。用一個(gè)定時(shí)任務(wù)每天掃描待保養(yǎng)車輛列表給預(yù)約過(guò)保養(yǎng)的用戶發(fā)送短信或站內(nèi)信提醒。技術(shù)上可以用SpringBoot自帶的Scheduled定時(shí)任務(wù)不額外引入過(guò)重框架但一下子就能讓系統(tǒng)有了“主動(dòng)服務(wù)”的味道。第二是數(shù)據(jù)可視化看板。在管理端首頁(yè)放幾張統(tǒng)計(jì)圖表比如近七日工單量趨勢(shì)、工時(shí)費(fèi)與材料費(fèi)占比、熱門保養(yǎng)服務(wù)項(xiàng)目排行。前端用ECharts就夠了后端寫幾個(gè)統(tǒng)計(jì)查詢接口SQL會(huì)用到GROUP BY和DATE_FORMAT正好能在論文里展示你對(duì)聚合查詢的掌握。第三是多門店模式。如果不想只做一個(gè)單店版可以給員工表和工單表加一個(gè)store_id把所有查詢都加門店維度系統(tǒng)就升級(jí)成了連鎖門店版。這個(gè)擴(kuò)展看起來(lái)改動(dòng)不大但能在需求分析章節(jié)體現(xiàn)你對(duì)系統(tǒng)邊界的設(shè)計(jì)思考答辯時(shí)能和老師多聊幾句。如果你打算拿著這個(gè)項(xiàng)目去面試我建議重點(diǎn)準(zhǔn)備四個(gè)問(wèn)題事務(wù)隔離級(jí)別、狀態(tài)機(jī)字段設(shè)計(jì)、庫(kù)存扣減并發(fā)處理、JWT認(rèn)證流程。這四點(diǎn)都是項(xiàng)目里真實(shí)寫過(guò)的內(nèi)容而不是背面試題背出來(lái)的聊起來(lái)會(huì)很自然。最后分享一個(gè)我踩過(guò)幾次坑之后的體會(huì)做畢設(shè)項(xiàng)目第一要?jiǎng)?wù)不是炫技術(shù)而是跑通閉環(huán)。很多同學(xué)一開始就去琢磨“要不要用Redis緩存”“要不要上消息隊(duì)列”結(jié)果基礎(chǔ)流程都沒走通。先老老實(shí)實(shí)把預(yù)約到結(jié)算這條主鏈路跑順暢然后再想那些錦上添花的東西。這個(gè)項(xiàng)目最讓我滿意的地方就是它的業(yè)務(wù)鏈路是真實(shí)的——你演示給老師看的每一步都是真實(shí)門店里每天都在發(fā)生的動(dòng)作。把這條鏈路的每一個(gè)節(jié)點(diǎn)處理好你就已經(jīng)領(lǐng)先大多數(shù)畢設(shè)了。