實戰(zhàn):架構設計與踩坑記錄)
手里這套“Java SpringBootVue3MyBatis 疾病防控綜合系統(tǒng)”源碼我自己斷斷續(xù)續(xù)改了大概三周。做之前以為就是個普通的管理系統(tǒng)真正動手才發(fā)現(xiàn)疾病防控這個業(yè)務場景比一般的CRUD系統(tǒng)難在數(shù)據(jù)流轉(zhuǎn)和狀態(tài)管理上病例從發(fā)現(xiàn)、上報、審核、復核到轉(zhuǎn)歸每一步都有嚴格的流程要求而且報表統(tǒng)計、趨勢分析這類需求特別多。如果你正準備拿這套源碼做畢業(yè)設計、面試項目或者想自己從零搭一套前后端分離管理系統(tǒng)那這篇文章應該能幫你少踩不少坑。先說明一下整個系統(tǒng)的骨架后端是SpringBoot 2.7 MyBatis MySQL 8.0前端是Vue3 Vite Element Plus前后端完全分離通過RESTful API通信鑒權用的是JWT。這個技術棧組合在當前Java全棧項目里算比較主流既不會太老也沒有激進到會給新手造成額外負擔。這套系統(tǒng)我實際跑下來的感受是功能模塊完整度很高健康檔案、風險上報、流調(diào)記錄、物資臺賬、數(shù)據(jù)分析看板、用戶權限管理都有代碼結構也清晰適合二次開發(fā)和擴展。下面我按實際開發(fā)順序把整個系統(tǒng)的設計思路、核心實現(xiàn)和踩坑過程詳細拆開講。1. 項目整體設計與技術棧選型為什么我最終選了這套組合1.1 從需求反推技術選型先聊選型。很多人上來就糾結“SpringBoot還是SSM”“Vue3還是Vue2”但我的習慣是先看業(yè)務。疾病防控綜合系統(tǒng)這類項目核心需求可以拆成三塊一是多角色數(shù)據(jù)上報和審核二是大量病例數(shù)據(jù)的登記和檢索三是基于時間維度的統(tǒng)計分析和可視化。這三塊需求決定了技術選型的方向。后端用SpringBoot幾乎是必然選擇社區(qū)生態(tài)成熟自動配置大大減少了XML配置的繁瑣程度內(nèi)嵌Tomcat也省去了單獨部署Web服務器的步驟。MyBatis則是因為這類業(yè)務系統(tǒng)SQL復雜動態(tài)條件檢索多用MyBatis可以在XML里精細控制SQL比JPA那種“幫你生成好一切”的方式更可控也更容易排查性能問題。MySQL做數(shù)據(jù)庫不用多說開源免費、部署簡單、性能足夠。前端選Vue3而不是Vue2核心原因是Composition API在復雜業(yè)務頁面里的組織能力更強而且Vite構建速度比Webpack快一個量級開發(fā)體驗完全不一樣。Element Plus作為Vue3對應的組件庫表格、表單、日期選擇器這些后臺管理常用的組件都很齊全能省不少時間。這里順便說下這套系統(tǒng)的數(shù)據(jù)可視化看板用的是ECharts。市面上有些系統(tǒng)會集成大而全的DataV、AntV等可視化框架但ECharts按需引入后體積可控、文檔全、網(wǎng)上示例多在這個體量下性價比是最高的。1.2 前后端分離的分工與模塊規(guī)劃前后端分離這個詞很多人掛在嘴邊但真正落地時容易分不干凈。我的劃分原則很簡單后端只負責數(shù)據(jù)和業(yè)務規(guī)則前端只負責交互和展示。比如“審核病例”這個操作后端接口只接收病例ID和審核結果返回成功或失敗至于審核按鈕怎么渲染、彈窗怎么寫都是前端的事。系統(tǒng)功能模塊按業(yè)務域可以拆成這幾塊健康檔案管理人員基本信息、聯(lián)系方式、健康狀況、既往病史等基礎信息維護。風險監(jiān)測與上報疑似/確診情況的上報、審核、復核支持批量導入。流調(diào)信息管理病例活動軌跡、密切接觸者關聯(lián)、流調(diào)報告附件。物資管理防護物資、消殺物資、藥品的入庫、出庫、庫存預警。數(shù)據(jù)分析看板按地區(qū)、時間、人群維度統(tǒng)計新增、治愈、轉(zhuǎn)歸等指標。系統(tǒng)管理用戶、角色、菜單、字典、操作日志。模塊劃分清楚之后前后端并行開發(fā)就很順暢。我在實際開發(fā)時先定接口文檔前端用Mock數(shù)據(jù)先行開發(fā)后端按照接口文檔同步開發(fā)最后聯(lián)調(diào)時問題就少很多。1.3 權限模型RBAC與多角色數(shù)據(jù)隔離權限設計是這類系統(tǒng)的重頭戲。疾病防控系統(tǒng)角色天然就多系統(tǒng)管理員、疾控中心人員、醫(yī)療機構上報員、基層排查人員、只讀訪客等。我采用的是一套標準的RBAC基于角色的訪問控制模型用戶關聯(lián)角色、角色關聯(lián)菜單和操作權限同時給每個用戶掛一個數(shù)據(jù)歸屬單位字段用單位ID做數(shù)據(jù)隔離。數(shù)據(jù)隔離這塊容易踩坑。比如市級賬號應該能看到下轄區(qū)縣的數(shù)據(jù)而區(qū)縣級賬號只能看本區(qū)的數(shù)據(jù)。如果只做菜單權限就會出“越權查看”的問題。我的處理方式是在后端查詢時自動拼接單位層級條件核心SQL強制帶上WHERE unit_id IN (SELECT id FROM unit WHERE path LIKE xxx%)這類條件從接口層規(guī)避數(shù)據(jù)越權。2. 數(shù)據(jù)庫設計疾病防控系統(tǒng)的核心其實是表結構2.1 主業(yè)務表拆解與關系設計這類系統(tǒng)的技術難點不在增刪改查而在表結構能不能支撐復雜業(yè)務。我畫完ER圖之后最大的感受是業(yè)務表可以多但不能亂關鍵要理清主表和流水表的關系。以“病例”為例我先建了一張person表保存人員靜態(tài)信息包括姓名、身份證號、性別、年齡、聯(lián)系電話、現(xiàn)住址等。身份證號是天然的冪等鍵一個人只能有一條健康檔案。然后針對每次上報建一張report_record流水表記錄上報時間、上報單位、癥狀描述、檢驗結果、風險等級、審核狀態(tài)、審核意見。這樣設計的好處是一個人可以有多次上報記錄但只有一條最新狀態(tài)既保住了歷史軌跡又方便取“當前狀態(tài)”。流調(diào)信息我單獨建了trace_record表存活動軌跡表格數(shù)據(jù)時間點、地點、停留時長、接觸人員類別。每條流調(diào)記錄都關聯(lián)report_id形成一對多的關系。物資表和審批表也都是典型的流水表設計這里不展開。2.2 病例狀態(tài)機用數(shù)據(jù)庫字段管理業(yè)務流轉(zhuǎn)這是我做這個項目收獲最大的一部分。病例狀態(tài)不能靠“改個字段就完事”得設計成狀態(tài)機。我把狀態(tài)定義為待審核、已審核、待復核、已復核、已排除、已轉(zhuǎn)歸。每個流轉(zhuǎn)節(jié)點在業(yè)務代碼里都做合法性校驗比如“已排除”的病例不能直接跳到“已轉(zhuǎn)歸”必須經(jīng)過復核環(huán)節(jié)。具體到數(shù)據(jù)庫設計我的做法是在report_record表里加兩個字段status當前狀態(tài)和version樂觀鎖版本號。更新時使用UPDATE report_record SET status #{newStatus}, version version 1 WHERE id #{id} AND version #{oldVersion}這樣能防止并發(fā)操作導致狀態(tài)錯亂。這個設計在多人同時審核的場景下非常重要實戰(zhàn)中真的遇到過兩個審核員同時審同一份上報、導致舊數(shù)據(jù)覆蓋新數(shù)據(jù)的情況。2.3 查詢優(yōu)化與索引設計疾病防控系統(tǒng)的查詢有一個特點列表頁條件多但每次查詢的數(shù)據(jù)量其實有限。我建索引的原則是“先滿足等值查詢再優(yōu)化范圍查詢”。核心表索引設計供參考person表id_card建唯一索引name建普通索引unit_id建普通索引。report_record表person_id建索引report_time建復合索引(unit_id, report_time)。trace_record表report_id建普通索引activity_time建普通索引。索引不是越多越好寫多讀少的表索引多了反而拖慢插入速度。我實際測試過優(yōu)化索引后百萬級數(shù)據(jù)量下復合條件查詢基本穩(wěn)定在200ms以內(nèi)完全夠用。另外所有狀態(tài)字段我用TINYINT存數(shù)字枚舉值不用字符串這樣既能節(jié)省空間查詢也更快但需要在代碼里維護好枚舉映射關系。3. 后端實現(xiàn)SpringBoot MyBatis的落地細節(jié)3.1 工程分層與JWT認證后端工程我按標準的三層結構組織controller接口層、service業(yè)務層、mapper數(shù)據(jù)訪問層另外加entity、dto、vo三層對象模型。一個容易被忽略的細節(jié)是entity對應數(shù)據(jù)庫表結構dto接收前端參數(shù)vo返回前端數(shù)據(jù)三者不能混用。很多初學者喜歡一個實體類走天下圖省事結果頁面多一個字段就報錯后面維護起來非常痛苦。認證用的是JWT流程是登錄成功后后端生成token返回給前端前端把token存到localStorage每次請求在請求頭帶Authorization: Bearer token后端攔截器校驗token并解析出用戶信息和權限列表。JWT的過期時間我設的是12小時同時做了token續(xù)期邏輯在過期前1小時內(nèi)訪問接口就自動發(fā)新token。這里注意JWT的密鑰必須放到application.yml的獨立配置項里別硬編碼在代碼里。3.2 MyBatis動態(tài)SQL復雜查詢的殺手锏MyBatis最大的優(yōu)勢就是動態(tài)SQL。疾病防控系統(tǒng)的查詢條件極多比如病例列表要支持按姓名模糊查詢、按狀態(tài)篩選、按時間范圍篩選、按風險等級篩選而且這些條件可以任意組合。用if標簽可以很優(yōu)雅地解決select idselectReportList resultTypecom.example.vo.ReportVO SELECT r.id, p.name, p.id_card, r.status, r.risk_level, r.report_time, r.audit_status FROM report_record r LEFT JOIN person p ON r.person_id p.id where if testname ! null and name ! AND p.name LIKE CONCAT(%, #{name}, %) /if if teststatus ! null AND r.status #{status} /if if teststartTime ! null AND r.report_time gt; #{startTime} /if if testendTime ! null AND r.report_time lt; #{endTime} /if /where ORDER BY r.report_time DESC LIMIT #{offset}, #{pageSize} /select用where標簽的好處是它自動處理掉第一個條件前面的AND不用自己寫WHERE 11這種丑寫法。每次看到初學者寫WHERE 11我都會勸改掉雖然結果一樣但可讀性和執(zhí)行計劃都有差異。還有一個容易踩坑的點是if teststatus ! null判斷的是Java屬性如果入?yún)⑹前b類型一定要判斷是否為空否則MyBatis會報There is no getter for property named xxx之類的異常。另外需要先判斷狀態(tài)字段是否是空字符串時用status ! null and status ! 兩個條件都不能少。3.3 大名單上報場景下的批量插入優(yōu)化疾病防控系統(tǒng)有一個高頻操作批量上報??赡苁菐资畻l也可能是一次性上千條人員名單導入。最開始我用循環(huán)單條插入結果導入2000條數(shù)據(jù)花了將近10秒根本沒法用。后來改成MyBatis的foreach批量插入性能提升非常明顯insert idbatchInsert parameterTypelist INSERT INTO report_record ( person_id, status, risk_level, report_time, report_unit_id, symptom_desc, create_time ) VALUES foreach collectionlist itemitem separator, (#{item.personId}, #{item.status}, #{item.riskLevel}, #{item.reportTime}, #{item.reportUnitId}, #{item.symptomDesc}, NOW()) /foreach /insert2000條數(shù)據(jù)的插入時間從10秒降到了1秒左右效果立竿見影。但這里有兩個坑必須注意一是MySQL默認會校驗max_allowed_packet超過這個大小的SQL會被拒絕批量插入條數(shù)過多時需要調(diào)大該參數(shù)二是foreach拼接SQL有長度限制我實際測試單批500條比較安全數(shù)據(jù)量大時分批提交。如果你使用的是MyBatis-Plus它有內(nèi)置的saveBatch方法底層同樣走批量插入但有一個配置項需要留意JDBC連接串要加上rewriteBatchedStatementstrue否則預編譯語句不會真正合并執(zhí)行MyBatis-Plus的批量插入性能提升會大打折扣。這套源碼用的是原生MyBatis也值得了解這一點方便以后遷移。3.4 啟動項與配置文件里的幾個坑這部分要重點說因為我在這上面浪費了不少時間。SpringBoot版本問題在熱詞里頻繁出現(xiàn)確實是個高頻坑。之前遇到過SpringBoot 3.x版本配JDK 8啟動直接報錯的場景因為SpringBoot 3.0開始強制要求JDK 17以上。如果你本機裝的是JDK 8老老實實用SpringBoot 2.7.x別追新版本。版本號不是越高越好而是要和JDK版本匹配。另一個坑是首次啟動Maven依賴下載卡在downloading...不動。原因是默認走了Maven中央倉庫國內(nèi)網(wǎng)絡訪問慢。解決辦法是在settings.xml里配置阿里云鏡像倉庫mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共倉庫/name urlhttps://maven.aliyun.com/repository/public/url /mirror配置完之后依賴下載速度直接翻幾倍。還有java: OutOfMemoryError: Insufficient Memory這個問題多半是IDEA里Maven編譯時內(nèi)存不夠。解決辦法是在Help - Change Memory Settings里調(diào)大IDEA的堆內(nèi)存同時在maven的VM options里加-Xmx1024m。如果是運行SpringBoot應用爆內(nèi)存則在啟動配置的VM options里調(diào)整-Xms256m -Xmx512m能緩解大部分內(nèi)存不足的情況。3.5 自定義Banner一個提升體驗的小細節(jié)熱詞里出現(xiàn)了“springboot banner生成器”這里順帶說一個提升項目格調(diào)的小技巧。SpringBoot啟動時默認打印的那個Spring圖案太單調(diào)了你可以去網(wǎng)上搜“Spring Boot Banner Generator”在線生成一段ASCII藝術字把生成的內(nèi)容保存到src/main/resources/banner.txt里。啟動項目時就會顯示你自定義的圖案比如系統(tǒng)名稱。這個操作不復雜但要提醒一句banner.txt不要用中文部分終端對中文ASCII藝術字的顯示寬度處理不一致會出現(xiàn)錯位。我用過一次中文直接亂碼后來全換成英文才正常。4. 前端實戰(zhàn)Vue3 Element Plus的實施記錄4.1 前端工程初始化與目錄規(guī)劃前端我用Vite創(chuàng)建Vue3項目命令是npm create vitelatest frontend -- --template vue然后安裝element-plus、axios、vue-router、pinia、echarts這幾個核心依賴。Vite項目的驅(qū)動速度比Webpack快太多了熱更新基本是秒級開發(fā)體驗提升明顯。目錄規(guī)劃供參考src/ ├── api/ # 接口請求封裝 ├── assets/ # 靜態(tài)資源 ├── components/ # 通用組件 ├── layout/ # 布局組件 ├── router/ # 路由配置 ├── stores/ # pinia狀態(tài)管理 ├── utils/ # 工具函數(shù) └── views/ # 頁面組件這里有一個實操建議api目錄下每個模塊單獨建一個文件比如report.js、person.js、equipment.js文件里導出一個個方法對應后端接口。不要在頁面上直接寫axios.get(/api/xxx)否則接口一多、地址一變改起來想哭。4.2 組合式APIcomputed、watch與hooks復用Vue3開發(fā)讓我最舒服的是Composition API。以前Vue2里業(yè)務邏輯分散在data、methods、watch這些選項里遇到復雜頁面要反復上下拖動找代碼?,F(xiàn)在可以按業(yè)務維度組織script setup import { ref, computed, onMounted } from vue import { getReportList } from /api/report const loading ref(false) const tableData ref([]) const queryParams ref({ status: null, keyword: , pageNum: 1, pageSize: 10 }) const total ref(0) const isFiltering computed(() { return queryParams.value.status ! null || queryParams.value.keyword ! }) async function fetchList() { loading.value true try { const res await getReportList(queryParams.value) tableData.value res.data.records total.value res.data.total } finally { loading.value false } } async function handleReset() { queryParams.value { status: null, keyword: , pageNum: 1, pageSize: 10 } await fetchList() } onMounted(fetchList) /scriptcomputed在這里用來派生“當前是否處于篩選狀態(tài)”這種依賴其他響應式數(shù)據(jù)自動更新的邏輯在Vue2的computed里也有但配合script setup寫法整體代碼量少了很多。搜索、重置、分頁、刷新這幾個操作通過統(tǒng)一調(diào)用fetchList來更新表格邏輯鏈路很清晰。條件渲染也需要注意一點Vue3中動態(tài)表格列和表單域很多人在v-for和v-if同時用在一處時收到編譯警告。它們的優(yōu)先級在Vue3里和Vue2不一樣同元素上同時使用很容易產(chǎn)生邏輯問題。我的建議是要么拆層標簽要么用computed先過濾再遍歷不要在同一元素上同時寫。4.3 兩個高頻樣式與組件問題用Element Plus做后臺管理會遇到兩個高頻問題一是修改Tabs標簽頁樣式二是富文本編輯器兼容性。Tabs標簽頁樣式定制需要檢查瀏覽器渲染出來的class名稱在style langscss scoped里直接用:deep()穿透樣式隔離即可。比如想改Tab的選中色:deep(.el-tabs__item.is-active) { color: #2f6fed; font-weight: 600; }:deep()是Vue3處理scoped樣式穿透的標準寫法Vue2里用的/deep/和在Vue3里不建議使用。富文本編輯器這塊要重點提一下熱詞里出現(xiàn)了“vue-quill-editor vue3”這里有個很常見的坑。vue-quill-editor這個庫主要為Vue2設計在Vue3里使用會有兼容性問題。我的建議是不要硬折騰直接換用其他支持Vue3的方案。我當時采用的方案是直接封裝Quill或者換成vueup/vue-quill安裝后注冊組件直接使用省心很多import { QuillEditor } from vueup/vue-quill import vueup/vue-quill/dist/vue-quill.snow.css4.4 路由權限與動態(tài)菜單前端權限控制的通用做法是登錄成功后后端返回當前用戶的角色和菜單列表前端動態(tài)注冊路由并生成側邊欄菜單。具體實現(xiàn)是靜態(tài)路由只保留登錄頁、404頁等公共頁面業(yè)務頁面全部用router.addRoute()動態(tài)添加。這里有一個體驗優(yōu)化的細節(jié)動態(tài)添加路由后用戶直接刷新頁面會白屏因為刷新時路由還沒注冊完。我的處理是在路由守衛(wèi)里加一個“路由已初始化”的全局標記如果沒初始化先初始化再放行否則直接放行。類似這種異步路由控制邏輯寫的時候要注意防止死循環(huán)。router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (!token to.path ! /login) { next(/login) return } if (token !store.routerLoaded) { store.generateRoutes().then(() { next({ ...to, replace: true }) }) return } next() })5. 踩坑記錄與排查速查表源碼跑通前一定要看5.1 MySQL環(huán)境相關mysql安裝教程、mysql安裝配置、mysql下載官網(wǎng)安裝MySQL 8.0時去官網(wǎng)下載免安裝版或者用安裝包。安裝時務必記住root密碼安裝完成后用mysql -uroot -p測試連接。如果忘記密碼需要通過skip-grant-tables模式重置過程比較麻煩盡量一次設好。使用MySQL Workbench時連接如果報Authentication plugin caching_sha2_password錯誤是因為MySQL 8.0默認認證插件和舊客戶端不兼容。要么在Workbench連接配置里改插件要么創(chuàng)建用戶時指定mysql_native_password。這個報錯在本地開發(fā)時非常常見。導入SQL腳本時如果提示Unknown database需要先建庫再選擇庫CREATE DATABASE IF NOT EXISTS disease_control DEFAULT CHARACTER SET utf8mb4;然后USE disease_control;再執(zhí)行SOURCE導入。編碼集推薦統(tǒng)一用utf8mb4能有效避免中文亂碼。MySQL中int 5這類“字段直接參與運算”的操作要謹慎。比如統(tǒng)計累加時如果字段是INT類型直接在SQL里UPDATE table SET count count 5是沒問題的但要考慮并發(fā)場景下丟更新需要配合行鎖或樂觀鎖。mysql update語法的坑更新多表時MySQL的UPDATE JOIN語法和SQL Server、PostgreSQL不太一樣注意表別名別省略。另外更新時不小心把WHERE去掉會導致全表更新這種事故我們行業(yè)里叫“生產(chǎn)事故預制菜”寫更新語句時先確認影響行數(shù)再執(zhí)行。5.2 SpringBoot配置與啟動相關springboot版本太高再次強調(diào)JDK版本決定SpringBoot大版本。JDK 8選2.7.xJDK 17選3.x。如果已經(jīng)用了高版本且不想降就把JDK換到對應版本兩者必須匹配。springboot配置核心配置文件分application.yml和application-dev.yml開發(fā)環(huán)境和生產(chǎn)環(huán)境分開維護通過spring.profiles.activedev指定生效環(huán)境。配置數(shù)據(jù)庫連接時務必加上serverTimezoneAsia/ShanghaiuseSSLfalsecharacterEncodingutf8這些參數(shù)避免時區(qū)錯亂和SSL警告。springboot集成mybatis一直報錯最常見的原因是Mapper接口沒有被Spring容器掃描到。解決辦法是在啟動類上加MapperScan(com.example.mapper)或者在每一個Mapper接口上加Mapper注解。兩個都加也不會沖突。這個錯誤報的“No qualifying bean of type”很典型大家遇到別慌先檢查掃描路徑。eclipse里集成MyBatis報錯排查邏輯同IDEA但要注意Eclipse的JDK編譯級別默認可能比較低需要手動調(diào)成1.8。5.3 MyBatis運行期問題mybatis配置打印開發(fā)階段建議在application.yml里開啟SQL日志觀察每條SQL的執(zhí)行情況mybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl生產(chǎn)環(huán)境記得關掉否則大量日志輸出會影響性能。如果用的是MyBatis-Plus生態(tài)有l(wèi)og-easy-plus這類插件可以把參數(shù)和結果集格式化得更易讀不過原生StdOutImpl也夠用。mybatis if test indexof有朋友問if testname.indexOf(張) ! -1能不能這么寫。答案是能indexOf是Java字符串方法在OGNL表達式里可以調(diào)用。但注意如果name為null直接調(diào)用indexOf會拋NPE。安全寫法是先判空再用字符序列判斷if testname ! null and name.indexOf(張) ! -1。不過在SQL里這樣用通常沒必要直接用LIKE更高效。mybatis緩存MyBatis的一級緩存默認開啟作用域是SqlSession在Spring集成環(huán)境下多次查詢可能共用同一個SqlSession所以會出現(xiàn)“修改數(shù)據(jù)后查到的還是舊值”的假象。排查思路是檢查是不是緩存了對象引用未刷新或者在SQL日志中看是否有新的查詢語句執(zhí)行。二級緩存如果沒把握盡量不要開啟分布式部署時容易出現(xiàn)臟數(shù)據(jù)。5.4 常見問題速查表問題現(xiàn)象排查方向推薦解決方式啟動依賴下載卡在downloading倉庫訪問慢或被墻配置阿里云Mirror見上文啟動報OutOfMemoryErrorIDEA/Maven內(nèi)存不足調(diào)大IDEA設置里內(nèi)存參數(shù)接口返回401或token失效JWT過期或密鑰不一致檢查請求頭攜帶token確認前后端密鑰一致表格數(shù)據(jù)中文亂碼數(shù)據(jù)庫/連接串編碼不一致數(shù)據(jù)庫統(tǒng)一utf8mb4連接串加characterEncodingutf8POST請求跨域報錯前后端分離未配置CORS后端加CORS過濾器或CrossOrigin生產(chǎn)用Nginx反向代理同源解決批量插入報PacketTooBigmax_allowed_packet過小調(diào)大MySQL該參數(shù)并分批插入SQL查詢慢缺索引或條件未走索引EXPLAIN分析執(zhí)行計劃補充復合索引最后說幾句我個人的實操體會這套系統(tǒng)做下來我最想分享的一點是技術棧本身不難難的是把業(yè)務狀態(tài)梳理清楚。疾病防控系統(tǒng)里大量操作是“改變狀態(tài)”如果一開始沒把狀態(tài)機設計妥當后面加需求時每一次都要動核心邏輯越改越亂。所以如果你要二開這套源碼我強烈建議先把數(shù)據(jù)庫表結構和狀態(tài)流轉(zhuǎn)摸透再下手改業(yè)務代碼。還有一個小技巧前端表格里日期格式化反復用可以封裝成全局過濾器或者工具函數(shù)。包括接口統(tǒng)一的返回結構{ code, msg, data }后端封裝好之后所有接口都走同一套規(guī)范聯(lián)調(diào)效率和穩(wěn)定性都會明顯提升。另外一個實際經(jīng)驗是開發(fā)過程中把application-dev.yml里的MySQL密碼、JWT密鑰等敏感信息與代碼分開維護不要提交到公共倉庫。我見過不止一次因為源碼連帶數(shù)據(jù)庫密碼一起泄露出去的案例這個習慣越早養(yǎng)成越好。最后說個擴展方向。這套系統(tǒng)目前看板主要是桌面端我特別建議你可以往移動端適配或消息觸達方向擴展比如病例審核通過后給上報人推送一條通知這類需求在實際業(yè)務中一定會出現(xiàn)。要是能往這個方向做深整個項目的完整度和面試含金量都會提高不少。