老監(jiān)護(hù)平臺(tái)畢設(shè)全攻略:從設(shè)計(jì)到部署)
每年到了畢業(yè)設(shè)計(jì)季總有一大批同學(xué)被“XX管理系統(tǒng)”這類題目壓得喘不過(guò)氣。尤其是“智慧養(yǎng)老監(jiān)護(hù)管理平臺(tái)”這種帶著智慧二字、又涉及物聯(lián)網(wǎng)感的題目聽(tīng)起來(lái)要上天實(shí)際上拿到手里卻不知道怎么落地。前后臺(tái)怎么寫(xiě)硬件怎么模擬數(shù)據(jù)庫(kù)怎么設(shè)計(jì)才夠答辯老師眼前一亮部署文檔又該寫(xiě)到什么程度才不會(huì)被答辯追問(wèn)卡殼我自己做過(guò)這個(gè)真實(shí)題目也幫朋友改了無(wú)數(shù)版類似的代碼。這篇就把SpringBootVueMySQL的社區(qū)智慧養(yǎng)老監(jiān)護(hù)管理平臺(tái)從立項(xiàng)到答辯的完整鏈路講透包括技術(shù)選型思路、模塊拆分、核心表結(jié)構(gòu)設(shè)計(jì)、告警流程閉環(huán)以及部署時(shí)會(huì)踩的坑。內(nèi)容基本是按工程項(xiàng)目的思路來(lái)梳理的不管你是打算自己從頭寫(xiě)還是手里已經(jīng)有一套源碼想弄懂它的邏輯都能用得上。1. 這個(gè)畢業(yè)設(shè)計(jì)到底要解決什么需求分析與模塊邊界先說(shuō)清楚一件事很多同學(xué)拿到“智慧養(yǎng)老監(jiān)護(hù)管理平臺(tái)”的題目第一反應(yīng)是“我要做硬件”然后開(kāi)始糾結(jié)樹(shù)莓派、傳感器、藍(lán)牙通信。這是個(gè)非常典型的誤區(qū)。社區(qū)智慧養(yǎng)老監(jiān)護(hù)平臺(tái)的本質(zhì)不是做IoT設(shè)備而是做數(shù)據(jù)管理、狀態(tài)監(jiān)控、服務(wù)流轉(zhuǎn)的軟件系統(tǒng)。硬件數(shù)據(jù)可以通過(guò)模擬器來(lái)生成整個(gè)系統(tǒng)的核心在于把養(yǎng)老社區(qū)里的老人、護(hù)工、家屬、管理員這幾類角色的業(yè)務(wù)串起來(lái)。1.1 核心業(yè)務(wù)模型誰(shuí)在用這個(gè)平臺(tái)任何管理系統(tǒng)都是為人服務(wù)的。我在設(shè)計(jì)時(shí)就列了四類角色對(duì)應(yīng)了四種完全不同的操作界面和權(quán)限邊界系統(tǒng)管理員管人、管設(shè)備、管全局統(tǒng)計(jì)負(fù)責(zé)整個(gè)平臺(tái)的配置和日常運(yùn)維。護(hù)工/管家負(fù)責(zé)老人照護(hù)任務(wù)執(zhí)行、健康指標(biāo)復(fù)測(cè)、告警事件確認(rèn)處理。老人家屬查看老人的健康趨勢(shì)、接收異常告警需要的是一個(gè)簡(jiǎn)單的可查看窗口。老人本人在智慧養(yǎng)老場(chǎng)景下老人通常是被監(jiān)護(hù)方系統(tǒng)里甚至不需要給他們?cè)O(shè)計(jì)登錄入口他們的數(shù)據(jù)由設(shè)備和護(hù)工錄入。這個(gè)角色劃分非常重要因?yàn)楹竺娴牟藛卧O(shè)計(jì)、數(shù)據(jù)權(quán)限、接口粒度全都取決于它。比如家屬只能看到自己綁定老人的數(shù)據(jù)管理員能看到全部護(hù)工只能處理自己負(fù)責(zé)樓棟或護(hù)理區(qū)的工單。很多畢業(yè)設(shè)計(jì)做到最后頁(yè)面混亂不堪就是因?yàn)闆](méi)在前期把“誰(shuí)能看什么、誰(shuí)能干什么”定死。1.2 功能模塊選型不是頁(yè)面越多越好而是鏈路完整在設(shè)計(jì)功能的時(shí)候我用了一個(gè)很實(shí)際的篩選標(biāo)準(zhǔn)能不能形成一個(gè)業(yè)務(wù)閉環(huán)。比如設(shè)備上報(bào)異常心跳數(shù)據(jù) → 系統(tǒng)產(chǎn)生告警 → 護(hù)工確認(rèn)告警并生成處理工單 → 工單完成后回填處理記錄 → 家屬端看到告警已處理。這個(gè)鏈路包含采集或模擬采集、判斷、通知、處理、反饋五個(gè)環(huán)節(jié)比單純做10個(gè)獨(dú)立的CRUD頁(yè)面有說(shuō)服力得多。我最終敲定的核心模塊如下表模塊名稱核心功能說(shuō)明老人檔案管理新增/編輯/查詢老人基礎(chǔ)信息、入住狀態(tài)、健康檔案作為全系統(tǒng)的數(shù)據(jù)底座床位與設(shè)備管理管理護(hù)養(yǎng)區(qū)房間、床位號(hào)、設(shè)備編號(hào)設(shè)備必須綁定床位再間接關(guān)聯(lián)老人健康數(shù)據(jù)監(jiān)測(cè)定時(shí)/實(shí)時(shí)接收心率、血壓、血氧、體溫?cái)?shù)據(jù)展示趨勢(shì)報(bào)表兼容模擬器和真實(shí)設(shè)備上報(bào)告警中心規(guī)則引擎判斷異常指標(biāo)生成告警記錄可根據(jù)閾值自定義規(guī)則工單管理告警確認(rèn)、任務(wù)派發(fā)、處理結(jié)果回填與告警形成閉環(huán)家屬端查看綁定老人查看健康數(shù)據(jù)和告警狀態(tài)簡(jiǎn)單只讀界面系統(tǒng)管理用戶管理、角色管理、日志管理、數(shù)據(jù)統(tǒng)計(jì)后臺(tái)基礎(chǔ)能力這套模塊復(fù)雜度適中工作量足夠撐起一篇本科畢業(yè)設(shè)計(jì)系統(tǒng)結(jié)構(gòu)又足夠完整論文也好寫(xiě)——每個(gè)模塊都能對(duì)應(yīng)到需求分析、系統(tǒng)設(shè)計(jì)、功能實(shí)現(xiàn)、系統(tǒng)測(cè)試四大章節(jié)里去。1.3 技術(shù)選型為什么是SpringBootVueMySQL的黃金三角這個(gè)組合在畢業(yè)設(shè)計(jì)里幾乎是統(tǒng)治級(jí)的原因很實(shí)在SpringBoot負(fù)責(zé)讓“后端開(kāi)發(fā)”這件事變得簡(jiǎn)單。不需要繁瑣的XML配置內(nèi)嵌Tomcat一個(gè)jar包就能跑起來(lái)這對(duì)學(xué)生黨太友好了。SpringBoot 2.7.x是當(dāng)前最穩(wěn)妥的版本配合MyBatis-Plus做ORM分頁(yè)查詢和條件構(gòu)造器都是現(xiàn)成的能省掉至少30%的數(shù)據(jù)庫(kù)操作代碼。Vue負(fù)責(zé)讓“前端開(kāi)發(fā)”這件事有技術(shù)含量。Vue 2搭配Element UI是當(dāng)年的經(jīng)典組合現(xiàn)在新項(xiàng)目我更建議直接用Vue 3 Vite Element Plus。組件化開(kāi)發(fā)模式讓頁(yè)面復(fù)用意想不到的方便而且Vue的那套生命周期、組件通信、路由守衛(wèi)答辯的時(shí)候都有話可說(shuō)。MySQL負(fù)責(zé)數(shù)據(jù)存儲(chǔ)免費(fèi)、資料多、老師熟悉。5.7或8.0都可以建議8.0因?yàn)槟J(rèn)字符集utf8mb4比較省心JSON類型支持也好用。這里需要插一句有些同學(xué)會(huì)糾結(jié)“要不要用Redis做緩存”“要不要用RabbitMQ做消息隊(duì)列”“要不要上Spring Cloud微服務(wù)”。我的回答是畢業(yè)設(shè)計(jì)的底線是分?jǐn)?shù)不是簡(jiǎn)歷。如果為了面試可以寫(xiě)技術(shù)亮點(diǎn)但為了系統(tǒng)穩(wěn)定和可控性越簡(jiǎn)單的架構(gòu)越不容易翻車。我在項(xiàng)目里只在查詢頻率高的健康指標(biāo)上加了Spring Cache緩存再多了真沒(méi)必要。2. 數(shù)據(jù)庫(kù)設(shè)計(jì)五張核心表的關(guān)聯(lián)關(guān)系與會(huì)話推演數(shù)據(jù)庫(kù)設(shè)計(jì)是答辯時(shí)老師必問(wèn)的環(huán)節(jié)。與其把表堆到二十多張然后自己都說(shuō)不清楚不如精雕細(xì)琢核心表。我按業(yè)務(wù)閉環(huán)設(shè)計(jì)了十二張表但真正撐起系統(tǒng)的是下面這五張它們的關(guān)聯(lián)關(guān)系搞懂了整體思路就通了。2.1 老人檔案表業(yè)務(wù)的索引中心老人表是整個(gè)系統(tǒng)里最基礎(chǔ)的一張表幾乎所有的業(yè)務(wù)都要JOIN它。建議字段如下elder_id主鍵elder_name、gender、birth_date、id_card身份證號(hào)用于唯一性校驗(yàn)和敏感脫敏展示phone、emergency_contact緊急聯(lián)系人及電話room_id關(guān)聯(lián)床位表說(shuō)明住在哪nursing_level護(hù)理等級(jí)自理/半自理/全護(hù)理這個(gè)字段在設(shè)置告警閾值時(shí)很有用admission_date、status在住/退住medical_history既往病史用JSON格式存多條也沒(méi)問(wèn)題這張表的經(jīng)驗(yàn)點(diǎn)在于不要把床位信息、監(jiān)護(hù)人信息直接寫(xiě)成字段而是用外鍵關(guān)聯(lián)方便后續(xù)被工單表、家屬綁定表引用。我在幫別人改代碼的時(shí)候見(jiàn)過(guò)把家屬電話直接塞在老人表里的最后做家屬端時(shí)又拆出來(lái)重寫(xiě)白白返工。2.2 設(shè)備與床位綁定數(shù)據(jù)歸屬的橋梁設(shè)備表設(shè)計(jì)得很簡(jiǎn)單device_id設(shè)備編號(hào)用于模擬器上報(bào)數(shù)據(jù)時(shí)識(shí)別身份device_type手環(huán)/血壓計(jì)/血氧儀/體溫槍等room_id、bed_no綁定到具體床位elder_id綁定到老人status在線/離線/維修中l(wèi)ast_report_time最近一次上報(bào)時(shí)間用于判定設(shè)備在線狀態(tài)這里有個(gè)容易被忽略的細(xì)節(jié)設(shè)備上報(bào)數(shù)據(jù)時(shí)要帶上device_id后端通過(guò)device_id去映射elder_id而不是讓老人直接拿設(shè)備上報(bào)。這樣做的好處是設(shè)備維修、更換時(shí)不需要改動(dòng)歷史數(shù)據(jù)換綁關(guān)系即可。2.3 健康指標(biāo)記錄表寫(xiě)多讀少注意索引健康數(shù)據(jù)表是數(shù)據(jù)量增長(zhǎng)最快的表如果做真實(shí)平臺(tái)必須考慮歸檔和分表。畢業(yè)設(shè)計(jì)雖然數(shù)據(jù)量不大但設(shè)計(jì)思想上要體現(xiàn)出來(lái)record_iddevice_id、elder_idheart_rate、blood_pressure_high、blood_pressure_low、blood_oxygen、temperature各指標(biāo)字段允許為NULLrecord_time數(shù)據(jù)產(chǎn)生時(shí)間source_type模擬器/真實(shí)設(shè)備/手動(dòng)錄入排查性能問(wèn)題時(shí)要注意查詢健康趨勢(shì)圖畫(huà)的是“某老人最近N天的心率變化”那查詢條件就是elder_id record_time所以聯(lián)合索引(elder_id, record_time)是必須的。我在項(xiàng)目里特意把這條索引寫(xiě)到數(shù)據(jù)庫(kù)初始化腳本里論文的數(shù)據(jù)庫(kù)設(shè)計(jì)章節(jié)里也能提一嘴顯得專業(yè)。2.4 告警記錄表規(guī)則引擎的結(jié)果落地告警表的字段核心alarm_idelder_idalarm_type心率異常/血壓偏高/血氧偏低/體溫異常/設(shè)備離線alarm_level提示/普通/緊急——由觸發(fā)規(guī)則的偏離程度決定alarm_content記錄具體的指標(biāo)值和閾值status待處理/已確認(rèn)/已處理/誤報(bào)create_timehandle_person、handle_time、handle_result處理人、處理時(shí)間、處理意見(jiàn)告警的判定邏輯我放在后端Service層。每小時(shí)由定時(shí)任務(wù)掃描最近一條健康數(shù)據(jù)如果超出該老人護(hù)理等級(jí)對(duì)應(yīng)的閾值就寫(xiě)入告警表。這里要注意不是每次讀數(shù)異常都立刻生成告警連續(xù)2次異常才觸發(fā)能有效減少誤報(bào)率。這個(gè)邏輯是加分項(xiàng)可以在論文里作為“抗干擾設(shè)計(jì)”單獨(dú)寫(xiě)一節(jié)。2.5 工單表與家屬綁定表服務(wù)閉環(huán)的最后兩環(huán)工單表字段包括work_order_id、alarm_id關(guān)聯(lián)告警、elder_id、order_type、assignee派給哪位護(hù)工、status、create_time、finish_time、feedback。家屬綁定表就兩個(gè)關(guān)鍵字段user_id綁定系統(tǒng)用戶賬號(hào)、elder_id綁定老人。一個(gè)家屬可綁定多位老人一位老人也可有多個(gè)家屬這就是經(jīng)典的多對(duì)多關(guān)聯(lián)通過(guò)中間表處理。2.6 數(shù)據(jù)庫(kù)腳本的交付標(biāo)準(zhǔn)畢業(yè)設(shè)計(jì)提交的sql文件我建議包含四部分內(nèi)容建庫(kù)建表語(yǔ)句帶ENGINEInnoDB DEFAULT CHARSETutf8mb4基礎(chǔ)字典數(shù)據(jù)角色、權(quán)限、系統(tǒng)配置演示數(shù)據(jù)至少3位老人、綁定設(shè)備、最近7天的健康指標(biāo)記錄、若干條告警和工單索引和關(guān)鍵約束演示數(shù)據(jù)好不好直接影響演示效果。很多同學(xué)系統(tǒng)一打開(kāi)全是空的老師看著都沒(méi)興趣。我自己的做法是寫(xiě)了一小段MySQL存儲(chǔ)過(guò)程循環(huán)生成兩周的健康數(shù)據(jù)樹(shù)圖、趨勢(shì)圖、告警列表全都有內(nèi)容演示效果非常飽滿。3. 后端實(shí)現(xiàn)的關(guān)鍵鏈路登錄鑒權(quán)、數(shù)據(jù)模擬采集與告警閉環(huán)后端我用的是SpringBoot MyBatis-Plus Spring Security JWT的組合。技術(shù)難度適中但有幾個(gè)點(diǎn)實(shí)現(xiàn)起來(lái)需要?jiǎng)幽X子我就說(shuō)我的做法和踩過(guò)的坑。3.1 登錄鑒權(quán)JWT為什么比Session省事很多教程會(huì)讓你用Spring Security JWT搭建認(rèn)證。我建議畢業(yè)設(shè)計(jì)別被Security的過(guò)濾器鏈繞暈直接用一個(gè)輕量方案自定義一個(gè)LoginInterceptor攔截器。用戶登錄成功后用io.jsonwebtoken.JJWT生成token把userId、userName、角色放進(jìn)去設(shè)置24小時(shí)過(guò)期。前端登錄后把token存到localStorageaxios請(qǐng)求攔截器在Header中攜帶token。后端攔截器校驗(yàn)token解析用戶信息放到ThreadLocal里后續(xù)業(yè)務(wù)直接用。代碼大致就幾十行比配Spring Security省心得多。這里要提醒大家JWT的密鑰不能寫(xiě)在代碼里哪怕是畢業(yè)設(shè)計(jì)也要養(yǎng)成好習(xí)慣放application.yml里。還有一點(diǎn)token過(guò)期后前端要能識(shí)別401狀態(tài)碼自動(dòng)跳回登錄頁(yè)不然就會(huì)出現(xiàn)“頁(yè)面還能打開(kāi)保存時(shí)報(bào)錯(cuò)”的尷尬情況。MyBatis-Plus是我強(qiáng)烈推薦的。不用手寫(xiě)大量的XML文件BaseMapper提供CRUDLambdaQueryWrapper做條件拼接非常順手。條件構(gòu)造器一定要用lambda的寫(xiě)法比如eq(Elder::getStatus, 1)這樣字段名寫(xiě)錯(cuò)時(shí)編譯期就能發(fā)現(xiàn)而不是運(yùn)行時(shí)才報(bào)錯(cuò)。3.2 模擬設(shè)備數(shù)據(jù)上報(bào)沒(méi)有硬件也能演示的絕活沒(méi)有真實(shí)手環(huán)和床墊傳感器怎么演示數(shù)據(jù)采集我的方案是后端提供一個(gè)模擬上報(bào)接口。接口路徑為POST /api/monitor/report接收J(rèn)SON體{ deviceId: HB001, heartRate: 88, bloodPressureHigh: 125, bloodPressureLow: 78, bloodOxygen: 97, temperature: 36.5 }后端處理邏輯是三步先根據(jù)device_id查出設(shè)備及綁定的elder_id再校驗(yàn)數(shù)據(jù)是否落在合理區(qū)間然后寫(xiě)入health_record表最后觸發(fā)一次告警規(guī)則校驗(yàn)如果在單位時(shí)間內(nèi)連續(xù)異常則落告警。為了演示效果更好我還加了一個(gè)定時(shí)任務(wù)用Scheduled注解每30秒自動(dòng)生成一組隨機(jī)數(shù)據(jù)模擬設(shè)備周期性上報(bào)。數(shù)據(jù)生成時(shí)故意做了一些套路調(diào)整每隔幾輪出現(xiàn)一次異常值這樣演示的時(shí)候屏幕上會(huì)時(shí)不時(shí)跳出告警場(chǎng)面非常生動(dòng)。這個(gè)性格在答辯時(shí)尤其有用——你不用主動(dòng)去解釋系統(tǒng)的告警流程告警自己會(huì)彈出來(lái)證明自己。3.3 告警規(guī)則引擎閾值不是寫(xiě)死的而是可配置的告警閾值我抽成了系統(tǒng)配置表管理員在后臺(tái)可以修改各指標(biāo)的上限下限。這比在代碼里硬編碼兩個(gè)數(shù)字高檔得多論文里還能寫(xiě)“基于可配置規(guī)則的動(dòng)態(tài)閾值策略”。判斷時(shí)機(jī)上也做了優(yōu)化不是每次上報(bào)都判斷而是做二次確認(rèn)機(jī)制。即最近連續(xù)兩條數(shù)據(jù)都超閾值才正式生成告警首條超閾值數(shù)據(jù)落到健康表里并在緩存中標(biāo)記。這么做能過(guò)濾掉偶發(fā)性誤差如實(shí)測(cè)中老人動(dòng)了一下導(dǎo)致的心率瞬間飆升就不會(huì)誤告警了。生成告警后系統(tǒng)的通知鏈路是前端頁(yè)面頂部通過(guò)WebSocket推送一條“新告警”氣泡。家屬端可配置是否接受郵件通知用JavaMail實(shí)現(xiàn)但發(fā)信頻率做了限制防止頻繁打擾。告警落入告警中心列表狀態(tài)為“待處理”。3.4 工單閉環(huán)從告警到處理再到回訪護(hù)工端看到待處理告警后點(diǎn)擊“確認(rèn)處理”系統(tǒng)會(huì)自動(dòng)生成一張工單并指派給當(dāng)前護(hù)工。護(hù)工去現(xiàn)場(chǎng)核實(shí)處理后填寫(xiě)處理結(jié)果上傳照片可選工單狀態(tài)變?yōu)椤耙淹瓿伞标P(guān)聯(lián)告警狀態(tài)同步更新為“已處理”。這條鏈路設(shè)計(jì)成了一條數(shù)據(jù)流告警表au→ 工單表work→ 處理記錄handle。不建議在一個(gè)表里塞所有狀態(tài)字段分開(kāi)反而好查詢好統(tǒng)計(jì)。工作量統(tǒng)計(jì)時(shí)“某護(hù)工本月處理了多少單”直接查工單表按人分組就出來(lái)了。4. 前端頁(yè)面設(shè)計(jì)與Vue實(shí)現(xiàn)細(xì)節(jié)前端的角色劃分很清楚后臺(tái)管理平臺(tái)用Vue Element Plus做桌面端界面家屬端我用Vue做了一套專為手機(jī)屏幕優(yōu)化的H5頁(yè)面。4.1 頁(yè)面路由設(shè)計(jì)按角色劃分路由與權(quán)限拿到手里的源碼如果路由和權(quán)限做得好能省下大量改代碼的時(shí)間。前端我用動(dòng)態(tài)路由的思路登錄后從后端拉取當(dāng)前用戶的菜單權(quán)限用router.addRoute動(dòng)態(tài)添加路由而不是把所有頁(yè)面都寫(xiě)死在靜態(tài)路由里。// 路由守衛(wèi)核心邏輯 router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (!token to.path ! /login) { next(/login) return } if (token !store.state.userInfo) { store.dispatch(fetchUserInfo).then(menus { // 動(dòng)態(tài)注冊(cè)菜單路由再放行 next({ ...to, replace: true }) }) return } next() })這個(gè)做法的好處是管理員登錄看到系統(tǒng)管理菜單護(hù)工登錄看不到家屬端只跳轉(zhuǎn)到綁定老人健康頁(yè)。前端不是把按鈕藏起來(lái)而是路由級(jí)別就不存在安全性高一個(gè)檔次。4.2 數(shù)據(jù)中心大屏答辯的視覺(jué)焦點(diǎn)數(shù)據(jù)大屏是最能直觀體現(xiàn)“智慧”的頁(yè)面。我用ECharts做了三個(gè)常用組件老年人狀態(tài)分布餅圖按自理、半自理、全護(hù)理分類。健康指標(biāo)趨勢(shì)折線圖支持選擇心率/血壓/血氧/體溫按時(shí)間范圍展示。告警實(shí)時(shí)列表滾動(dòng)列表展示最新告警及處理狀態(tài)。大屏頁(yè)面需要在進(jìn)入時(shí)拉取全量統(tǒng)計(jì)接口再通過(guò)WebSocket實(shí)時(shí)刷新。ECharts的圖表更新只需給對(duì)應(yīng)的圖表實(shí)例調(diào)用setOption不需要整頁(yè)刷新關(guān)鍵代碼就三五行socket.onmessage function (event) { const data JSON.parse(event.data) if (data.type alarm) { updateAlarmList(data.payload) refreshStatistic() } }大屏地址設(shè)為/dashboard答辯時(shí)把瀏覽器窗口一放大視覺(jué)效果直接拉滿。4.3 家屬端H5輕量、只讀、定位清晰家屬端的核心需求是“讓我放心”所以界面非常簡(jiǎn)單首頁(yè)顯示綁定老人的核心指標(biāo)卡片心率/血壓/血氧用不同顏色標(biāo)識(shí)正常與否。健康趨勢(shì)頁(yè)用ECharts畫(huà)最近30天曲線。告警記錄頁(yè)展示歷史告警和處理狀態(tài)。這里需要注意一個(gè)問(wèn)題家屬端不推薦復(fù)用后臺(tái)管理端的完整布局因?yàn)樽烂娑私M件在手機(jī)上體驗(yàn)很差。我用Vant組件庫(kù)重寫(xiě)了一套移動(dòng)端UI底部TabBar三個(gè)入口代碼量不大但整體體驗(yàn)完全不同。這在論文里可以寫(xiě)成“多端適配設(shè)計(jì)”是一個(gè)非常值得一提的差異化亮點(diǎn)。5. 部署與驗(yàn)收從開(kāi)發(fā)機(jī)到答辯電腦的完整流程到這一步系統(tǒng)代碼基本寫(xiě)完了接下來(lái)最實(shí)際也最容易翻車的環(huán)節(jié)是部署。我就直接給出我建議的部署流程和容易踩坑的清單。5.1 本地開(kāi)發(fā)環(huán)境搭建的三件套后端和數(shù)據(jù)庫(kù)跑在本機(jī)前端跑在dev-server開(kāi)發(fā)模式。這個(gè)模式下聯(lián)調(diào)最方便改動(dòng)前端代碼能熱更新后端用spring-boot:run插件或IDE直接啟動(dòng)都行。步驟順序別搞錯(cuò)先裝MySQL 8.0用Navicat或命令行執(zhí)行sql腳本建庫(kù)導(dǎo)入演示數(shù)據(jù)。后端項(xiàng)目改application.yml的數(shù)據(jù)源配置為你的MySQL賬號(hào)密碼。啟動(dòng)后端能訪問(wèn)localhost:8080/api/login接口返回JSON說(shuō)明SpringBoot起來(lái)了。前端項(xiàng)目執(zhí)行npm install裝依賴再執(zhí)行npm run dev訪問(wèn)localhost:5173。前后端聯(lián)調(diào)注意前端的Vite配置里要設(shè)置代理把/api轉(zhuǎn)發(fā)到localhost:8080避免跨域問(wèn)題。Vite的代理配置在vite.config.js里server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }這里有一個(gè)高頻問(wèn)題前端訪問(wèn)后端接口時(shí)報(bào)“CORS”跨域錯(cuò)絕大多數(shù)是因?yàn)榇頉](méi)生效或者地址寫(xiě)錯(cuò)而不是后端沒(méi)有配跨域。我第一次做的時(shí)候在后端配了CrossOrigin前端又配了代理結(jié)果兩套機(jī)制疊加反而把OPTIONS預(yù)檢請(qǐng)求搞亂了。最后我只保留代理方案后端不處理跨域邏輯更清晰。5.2 打包成可交付的產(chǎn)物答辯現(xiàn)場(chǎng)有兩種常見(jiàn)場(chǎng)景一種是用自己的電腦演示另一種是臨時(shí)換一臺(tái)電腦用U盤拷貝項(xiàng)目現(xiàn)場(chǎng)跑。如果是第一種場(chǎng)景直接用IDE啟動(dòng)最省事。如果是第二種我建議打兩個(gè)包后端執(zhí)行mvn clean package -DskipTests生成一個(gè)xxx.jar在裝有JDK的機(jī)器上用java -jar xxx.jar直接啟動(dòng)。前端執(zhí)行npm run build生成dist目錄里面是純靜態(tài)文件。前端打包后訪問(wèn)時(shí)需要把dist目錄放到Nginx里并配置代理或直接借助后端把dist目錄作為SpringBoot的靜態(tài)資源目錄。我在項(xiàng)目里選擇的是后一種方案把dist復(fù)制到后端resources/static目錄打包進(jìn)jar這樣只跑一個(gè)jar就能同時(shí)提供后端接口和前端頁(yè)面部署demo成本降到最低。雖然這種做法在大型項(xiàng)目里不夠規(guī)范但特別適配畢業(yè)設(shè)計(jì)答辯場(chǎng)景——一臺(tái)電腦、一個(gè)jar包演示完摔電腦跑路都行。5.3 部署文檔要寫(xiě)到什么程度部署文檔不是給老師看的設(shè)計(jì)說(shuō)明書(shū)而是給答辯現(xiàn)場(chǎng)的“你自己”準(zhǔn)備的救命手冊(cè)。我的文檔結(jié)構(gòu)是這樣的環(huán)境清單JDK版本、Node版本、MySQL版本盡量貼具體大版本如JDK 1.8或17、MySQL 8.0.33。初始化數(shù)據(jù)庫(kù)步驟執(zhí)行SQL腳本的命令行示例和Navicat操作截圖。啟動(dòng)后端步驟修改配置文件、執(zhí)行啟動(dòng)命令、驗(yàn)證接口是否通。啟動(dòng)前端步驟npm install、npm run dev、訪問(wèn)面板。常見(jiàn)問(wèn)題排查表端口占用、MySQL密碼錯(cuò)、Node模塊版本不兼容、Redis沒(méi)啟動(dòng)。這個(gè)排查表極為重要現(xiàn)場(chǎng)緊張的時(shí)候大腦容易空白看了排查表能快速恢復(fù)。重要到我覺(jué)得必須單獨(dú)列一節(jié)說(shuō)明。6. 部署與運(yùn)行常見(jiàn)問(wèn)題深度排查從根因到解法我整理一下自己做項(xiàng)目和幫人改項(xiàng)目時(shí)碰到的高頻問(wèn)題都是實(shí)打?qū)嵅冗^(guò)的坑。6.1 MySQL連接失敗的幾種原因報(bào)錯(cuò)Access denied for user rootlocalhost密碼錯(cuò)了或用戶權(quán)限受限。我建議單獨(dú)建一個(gè)演示用戶比如elder_user只授權(quán)指定庫(kù)。這樣做還有一個(gè)好處不至于因?yàn)檎`操作把整個(gè)MySQL玩壞。報(bào)錯(cuò)Could not create connection to database server多半是MySQL驅(qū)動(dòng)版本不匹配。SpringBoot 2.7.x對(duì)應(yīng)的mysql-connector-j就用8.0.x不少同學(xué)項(xiàng)目是從舊版本改來(lái)的混入5.1.x驅(qū)動(dòng)就會(huì)出這問(wèn)題。報(bào)錯(cuò)Public Key Retrieval is not allowed連接串加參數(shù)allowPublicKeyRetrievaltrueuseSSLfalse。這個(gè)坑在MySQL 8.0上相當(dāng)常見(jiàn)不清楚原理的同學(xué)卡一整晚都沒(méi)搞定。6.2 前端npm install失敗的幾類情況Node版本過(guò)高或過(guò)低Vite 5要求Node 18老項(xiàng)目Vue2配的Webpack可能和Node新版沖突。我的建議是裝nvm答辯電腦上隨時(shí)切換Node版本。網(wǎng)絡(luò)問(wèn)題裝到一半卡住用國(guó)內(nèi)鏡像源npm config set registry https://registry.npmmirror.com。node_modules損壞直接刪掉重裝rm -rf node_modules package-lock.json npm install。6.3 端口被占用后端8080端口起不來(lái)Windows上我先找出占用進(jìn)程netstat -ano | findstr 8080 taskkill /PID 進(jìn)程號(hào) /FMac或Linux就用lsof -i:8080和kill -9。這個(gè)說(shuō)實(shí)話不是什么技術(shù)難題但答辯現(xiàn)場(chǎng)會(huì)嚇出一身汗。6.4 接口通了但列表數(shù)據(jù)加載不出來(lái)先打開(kāi)瀏覽器F12看Network面板如果是401多半是token沒(méi)帶上或已過(guò)期。如果是500看后端控制臺(tái)打印的堆棧日志最常見(jiàn)的坑是數(shù)據(jù)表字段映射不上。MyBatis-Plus默認(rèn)駝峰轉(zhuǎn)下劃線寫(xiě)實(shí)體類屬性時(shí)和數(shù)據(jù)庫(kù)字段保持一致join查詢的別名也得對(duì)應(yīng)。如果接口返回“未知異常”把日志級(jí)別改成DEBUG再看具體錯(cuò)誤。7. 論文怎么寫(xiě)才能撐得起這個(gè)系統(tǒng)論文是畢業(yè)設(shè)計(jì)另一個(gè)半場(chǎng)。代碼寫(xiě)得再好論文像流水賬一樣也是白搭。我按我們學(xué)校本科論文的章節(jié)結(jié)構(gòu)給個(gè)參考邏輯也分享一些我實(shí)際寫(xiě)過(guò)的段落思路。7.1 研究背景與意義從老齡化社會(huì)切入講社區(qū)養(yǎng)老模式的人性化、智能化補(bǔ)位。寫(xiě)這段的時(shí)候不要大段粘貼新聞和數(shù)據(jù)只引一兩個(gè)權(quán)威跟緊的數(shù)據(jù)然后快速落到“社區(qū)養(yǎng)老機(jī)構(gòu)在日常管理中面臨的人力不足、數(shù)據(jù)孤島、告警滯后問(wèn)題”讓背景敘述自然導(dǎo)向系統(tǒng)開(kāi)發(fā)。千萬(wàn)別落空不要把背景寫(xiě)得像政策報(bào)告而是要說(shuō)明為什么需要一個(gè)軟件平臺(tái)來(lái)承接管理需求。7.2 需求分析需求分析不能只抄別人的功能列表。我用結(jié)構(gòu)化方式寫(xiě)出業(yè)務(wù)流程圖把四類角色的用例以文字表格結(jié)合的形式寫(xiě)清角色、功能、前置條件、基本流程、異常流程。表格式的需求條目答辯時(shí)老師掃一眼就知道你認(rèn)真做過(guò)分析。7.3 系統(tǒng)設(shè)計(jì)架構(gòu)設(shè)計(jì)要畫(huà)一張邏輯架構(gòu)圖、部署圖和技術(shù)架構(gòu)圖。圖片我強(qiáng)調(diào)一下不要直接照抄網(wǎng)上教程的架構(gòu)圖里面經(jīng)常帶的組件名和數(shù)據(jù)流和你的系統(tǒng)對(duì)不上。用PPT或draw.io自己畫(huà)一遍把SpringBoot、Vue、MySQL、WebSocket這些組件畫(huà)出來(lái)連線標(biāo)清楚老師問(wèn)起來(lái)你也能答出自己的邏輯。數(shù)據(jù)庫(kù)設(shè)計(jì)部分是論文的硬核環(huán)節(jié)。需要貼一張完整的E-R圖再逐個(gè)表用三線表講解字段、類型、約束。這里的表格建議不少于8張表覆蓋核心業(yè)務(wù)。我在論文里還有一個(gè)巧招加了一個(gè)“數(shù)據(jù)庫(kù)優(yōu)化設(shè)計(jì)”小節(jié)詳細(xì)說(shuō)明聯(lián)合索引、查詢優(yōu)化、演示數(shù)據(jù)存儲(chǔ)策略。本來(lái)平平無(wú)奇的設(shè)計(jì)因?yàn)榧恿诉@一節(jié)答辯時(shí)老師明顯更有興趣。7.4 系統(tǒng)實(shí)現(xiàn)不用每頁(yè)代碼都貼。我選了三個(gè)關(guān)鍵實(shí)現(xiàn)來(lái)詳細(xì)展開(kāi)JWT登錄鑒權(quán)的攔截邏輯。模擬上報(bào)接口與健康數(shù)據(jù)的入庫(kù)流程。告警規(guī)則判定與工單閉環(huán)的數(shù)據(jù)流轉(zhuǎn)。每個(gè)實(shí)現(xiàn)用“需求背景 → 核心代碼 → 運(yùn)行效果截圖 → 設(shè)計(jì)說(shuō)明”四段結(jié)構(gòu)完整讀下來(lái)正好對(duì)應(yīng)系統(tǒng)的三個(gè)技術(shù)亮點(diǎn)。7.5 系統(tǒng)測(cè)試測(cè)試這塊普遍寫(xiě)得很敷衍動(dòng)不動(dòng)就是“系統(tǒng)運(yùn)行正?!?。我建議至少寫(xiě)功能測(cè)試表用例編號(hào)、用例描述、預(yù)期結(jié)果、實(shí)際結(jié)果。三到五條正常人會(huì)問(wèn)的異常用例非法登錄、越權(quán)訪問(wèn)、異常心率導(dǎo)入、并發(fā)上報(bào)、token過(guò)期。在實(shí)測(cè)環(huán)節(jié)我寫(xiě)了一個(gè)并發(fā)模擬測(cè)試用Postman同時(shí)向模擬上報(bào)接口發(fā)100條記錄觀察數(shù)據(jù)庫(kù)是否能完整落庫(kù)、告警是否重復(fù)生成。這個(gè)測(cè)試結(jié)果既可以當(dāng)“系統(tǒng)穩(wěn)定性驗(yàn)證”的證據(jù)也能發(fā)現(xiàn)一個(gè)常見(jiàn)bug同步處理上報(bào)和告警會(huì)導(dǎo)致重復(fù)告警解決方法是給告警生成做一個(gè)冪等校驗(yàn)用elder_id和最近告警時(shí)間的間隔來(lái)控制。這個(gè)思路寫(xiě)進(jìn)論文答辯時(shí)可以說(shuō)出“我在測(cè)試中發(fā)現(xiàn)并修復(fù)了一個(gè)告警并發(fā)重復(fù)生成問(wèn)題”非常加分。8. 每次做系統(tǒng)前真該想清楚的事時(shí)間規(guī)劃與工作量分配很多人畢業(yè)設(shè)計(jì)從頭到尾拖了三個(gè)月最后兩周瘋狂熬夜其實(shí)不是能力問(wèn)題是時(shí)間規(guī)劃出了大問(wèn)題。我復(fù)盤了一下自己做這套平臺(tái)的節(jié)奏按經(jīng)驗(yàn)給出一份時(shí)間參考階段時(shí)間周期產(chǎn)出物需求分析與選題拆解第1周功能清單、角色劃分、初步表結(jié)構(gòu)技術(shù)棧學(xué)習(xí)補(bǔ)全第1-2周跑通一個(gè)HelloWorld級(jí)別的前后端聯(lián)調(diào)數(shù)據(jù)庫(kù)設(shè)計(jì)與初始化第2周完整SQL腳本、演示數(shù)據(jù)后端核心功能開(kāi)發(fā)第3-4周登錄、老人檔案、健康上報(bào)、告警鏈路前端后臺(tái)界面開(kāi)發(fā)第4-5周頁(yè)面全部可交互家屬端H5頁(yè)面第5周移動(dòng)端頁(yè)面硬件模擬調(diào)試第5-6周模擬數(shù)據(jù)流穩(wěn)定、告警準(zhǔn)確論文初稿第6周開(kāi)始同步寫(xiě)完成需求、設(shè)計(jì)、實(shí)現(xiàn)章節(jié)部署測(cè)試與完善第7-8周打包運(yùn)行、排查問(wèn)題、提交文檔答辯準(zhǔn)備最后一周演示腳本、問(wèn)題預(yù)演這個(gè)安排的前提取決于你每天能擠出2-3小時(shí)。如果前面學(xué)技術(shù)?;ㄌ煤竺嬲撐臅r(shí)間就會(huì)被擠壓。技術(shù)棧不太熟的同學(xué)我建議先用官方文檔快速把SpringBoot和Vue的基本模板跑起來(lái)不要試圖系統(tǒng)性啃完再動(dòng)手邊做邊查效率反而高。工作量分配我的建議是后端60%、前端30%、論文10%??雌饋?lái)論文時(shí)間少但其實(shí)前面的數(shù)據(jù)和模塊設(shè)計(jì)做好了論文只是把已有東西系統(tǒng)敘述一遍寫(xiě)起來(lái)并不慢。真正產(chǎn)量低的是在需求階段就急著寫(xiě)頁(yè)面后面改動(dòng)導(dǎo)致大范圍重寫(xiě)。別問(wèn)我怎么知道的。9. 拿到別人源碼時(shí)該怎么快速吃透拆解順序與驗(yàn)證技巧現(xiàn)在網(wǎng)上這類題目“源碼數(shù)據(jù)庫(kù)論文部署文檔”的全套資源非常多很多同學(xué)買來(lái)之后卻面對(duì)一堆文件無(wú)從下手甚至跑不起來(lái)就放棄了。我教一個(gè)我驗(yàn)證過(guò)很多次的順序。第一步先看數(shù)據(jù)庫(kù)腳本。打開(kāi)sql文件看建了幾個(gè)庫(kù)、幾張表、表之間怎么關(guān)聯(lián)、演示數(shù)據(jù)里有哪些角色賬號(hào)。你大概花二十分鐘就能判斷這套源碼是完整工程還是殘次品。第二步跑通后端。改數(shù)據(jù)源配置啟動(dòng)后端用Postman調(diào)用登錄接口。能拿到token說(shuō)明后端基礎(chǔ)鏈路通。再翻接口文檔或代碼里的Controller列表把核心接口挨個(gè)測(cè)一遍看哪些報(bào)錯(cuò)哪些通過(guò)。第三步跑通前端。npm install、npm run dev登錄進(jìn)去點(diǎn)一遍頁(yè)面和接口一一對(duì)應(yīng)。如果某個(gè)頁(yè)面請(qǐng)求的接口后端不存在那就是典型的“頁(yè)面與后端分離品”要么幫它補(bǔ)齊要么直接換一套資源。第四步從頭到尾走一遍主流程。新建老人檔案 → 模擬上報(bào) → 觸發(fā)告警 → 護(hù)工處理 → 家屬查看。這條流程走通了系統(tǒng)就算真正能吃透。內(nèi)部人視角也應(yīng)該明白很多所謂的“全套源碼”實(shí)際是從博客或開(kāi)源社區(qū)拼湊出來(lái)再打包售賣的搞不好數(shù)據(jù)庫(kù)腳本和后端代碼根本對(duì)不上。所以拿到任何源碼先做上面的四步驗(yàn)證再往下改。我有一次幫人看一套源碼數(shù)據(jù)庫(kù)里建了16張表后端卻只寫(xiě)了8張表的Mapper前端還多出3個(gè)頁(yè)面完全三個(gè)不同來(lái)源拼的花了一整天才理完。預(yù)判了這些問(wèn)題能在開(kāi)始做畢設(shè)之前就避免大量無(wú)意義的時(shí)間投入。10. 寫(xiě)在最后的心里話這個(gè)項(xiàng)目從0到1做完最大的收獲不是技術(shù)上的突飛猛進(jìn)而是學(xué)會(huì)了如何把一個(gè)模糊的“智慧養(yǎng)老”概念拆解成清晰的業(yè)務(wù)模塊再一步步用前后端代碼落實(shí)。真正工作以后你會(huì)發(fā)現(xiàn)大部分工程里最難的從來(lái)不是某個(gè)技術(shù)點(diǎn)而是理解清楚業(yè)務(wù)邏輯并在代碼中保持它的一致性。這套系統(tǒng)里周期性的數(shù)據(jù)上報(bào)、告警的閉環(huán)、角色權(quán)限的邊界每一條都訓(xùn)練了這個(gè)能力。如果你正在做這個(gè)題目或者手上有一套源碼但不知道從哪下手不妨按我上面的順序走一遍先理清角色和模塊再看數(shù)據(jù)庫(kù)表關(guān)系跑通主流程最后回到論文。你會(huì)發(fā)現(xiàn)那些原本看起來(lái)復(fù)雜到爆炸的業(yè)務(wù)文檔在真正理解工程后不過(guò)是對(duì)你已經(jīng)做出來(lái)的系統(tǒng)做一次清晰的自述罷了。這篇文章里的表結(jié)構(gòu)、判定邏輯和部署排查方法都是我在多個(gè)版本迭代后確認(rèn)穩(wěn)定可復(fù)用的方案。希望你的畢設(shè)季能少一點(diǎn)焦慮多一點(diǎn)從容。