管理系統(tǒng)設(shè)計與實現(xiàn))
1. 先把這個系統(tǒng)的邊界劃清楚1.1 班級事務(wù)管理系統(tǒng)到底管什么帶過畢業(yè)設(shè)計的人都有個共識題目里帶“管理系統(tǒng)”四個字的十個有八個最后做成了一張表加增刪改查。班級事務(wù)管理系統(tǒng)尤其容易滑向這個坑因為“班級事務(wù)”這個說法太寬了——考勤算不算事務(wù)獎助學金評定算不算班費收支算不算宿舍衛(wèi)生檢查算不算如果一開始不劃邊界做到中期你會發(fā)現(xiàn)表越加越多功能越鋪越散最后交上去的東西自己都說不清主線是什么。我的理解是班級事務(wù)管理系統(tǒng)的核心不是“記錄”而是“流轉(zhuǎn)”。一次請假申請從學生提交、班長初審、輔導員終審到銷假歸檔這條鏈路上的狀態(tài)變化才是系統(tǒng)的價值所在一次班級活動的報名、名額分配、簽到確認、活動總結(jié)也是一條鏈路。把這些鏈路抽象成統(tǒng)一的“事務(wù)單”模型配上角色權(quán)限和狀態(tài)機系統(tǒng)就有了骨架剩下的考勤、通知、統(tǒng)計都是掛在這個骨架上的枝干。所以這個項目適合誰來參考如果你是計算機相關(guān)專業(yè)正在做畢設(shè)的同學這套東西能直接給你提供需求分析、表結(jié)構(gòu)、核心代碼和開題報告寫作思路如果你是剛接觸前后端分離開發(fā)、想找一個業(yè)務(wù)不算復雜但五臟俱全的練手項目它也挺合適畢竟班級場景你天天在經(jīng)歷需求不用編。不適合的是想找高并發(fā)、分布式練手的人這個系統(tǒng)的量級撐死幾百人別硬套微服務(wù)。前100字必須把關(guān)鍵詞落地那我就直說高校班級事務(wù)管理系統(tǒng)本質(zhì)上是一個帶審批流的輕量級業(yè)務(wù)中臺服務(wù)對象是輔導員、班委和普通學生三類角色核心價值是把散落在聊天群里的通知、接龍、表格收斂成結(jié)構(gòu)化數(shù)據(jù)。1.2 三類角色決定了整個系統(tǒng)的權(quán)限骨架角色劃分這件事很多人畫用例圖的時候畫得很漂亮一寫代碼就開始偷懶搞一個role字段存?zhèn)€ 0/1/2 就完事結(jié)果做到后面發(fā)現(xiàn)“班長能審批本班但不能審批別班”這種帶數(shù)據(jù)范圍的權(quán)限根本兜不住。我的做法是角色和數(shù)據(jù)范圍分開設(shè)計。角色表里存三類身份學生、班委含班長、團支書等、輔導員。數(shù)據(jù)范圍單獨用一個字段或者一張關(guān)聯(lián)表來描述比如班委的scope_type是CLASSscope_id是本班 ID輔導員的scope_type是GRADE或者MAJORscope_id是對應的年級或?qū)I(yè) ID。這樣判斷權(quán)限的時候就是兩步先看角色能不能做這個動作再看這條數(shù)據(jù)在不在他的范圍內(nèi)。這種設(shè)計的直接好處是后面如果要加一個“學院管理員”角色不用改業(yè)務(wù)代碼只要插一條角色記錄和一個范圍記錄就行。壞處是實現(xiàn)上比單純的 if-else 麻煩一點但這點麻煩在后期聯(lián)調(diào)階段會成倍地還給你。1.3 三個最容易把項目做廢的坑第一個坑是功能貪多。開題報告里雄心壯志寫了十二個模塊做到第五個就開始復制粘貼最后交上去的代碼里有一半是沒跑通的僵尸接口。我的建議是主功能控制在五到六個每個都跑通全流程剩下的用“預留擴展”在報告里說明反而顯得你有規(guī)劃。第二個坑是權(quán)限校驗只做前端。菜單藏起來就以為安全了后端接口裸奔。答辯的時候老師隨手用接口工具一調(diào)就穿了這個場面很難看。校驗必須在后端做前端隱藏只是體驗優(yōu)化。第三個坑是不做數(shù)據(jù)初始化。交上去的系統(tǒng)打開一片空白老師第一眼就扣分。至少準備一份種子數(shù)據(jù)腳本造三個班級、幾十個學生、十幾條不同類型的事務(wù)記錄讓系統(tǒng)打開就是“活”的。2. 技術(shù)選型為什么最后落到這套組合2.1 后端為什么選 Spring Boot 而不是別的畢設(shè)場景下選后端的邏輯跟企業(yè)里不太一樣企業(yè)考慮的是團隊棧、運維成本、生態(tài)成熟度畢設(shè)考慮的是“能不能在兩個月內(nèi)跑通并且答辯時講得清楚”。Spring Boot 在這兩點上都是穩(wěn)妥解自動裝配省掉了大量 XML 配置起步一個main方法就能跑生態(tài)足夠大你遇到的九成問題網(wǎng)上都有現(xiàn)成答案分層結(jié)構(gòu)清晰Controller-Service-Mapper 三層擺出來老師一看就知道你懂分層。也有人問能不能用 Python 的 Flask 或者 Node 的 Express當然可以代碼量還更少。但答辯的時候有個現(xiàn)實問題國內(nèi)大部分院校的評審老師對 Java 技術(shù)棧更熟悉你講 Spring Boot 的攔截器、AOP、事務(wù)管理他能接得上話你講 Express 的中間件洋蔥模型他可能要愣一下。這不是技術(shù)優(yōu)劣是溝通成本。具體版本上我傾向于 JDK 8 或 JDK 11 配 Spring Boot 2.7.x。JDK 17 配 Spring Boot 3.x 也不是不行但 Spring Boot 3 把javax.*全換成了jakarta.*很多老教程的代碼直接抄會報錯對新手不友好。MyBatis-Plus 用來省掉基礎(chǔ) CRUD 的樣板代碼分頁插件直接用它的省得自己寫。MySQL 5.7 或 8.0 都行字符集統(tǒng)一utf8mb4這個別省不然學生姓名里的生僻字會變成問號。JWT 做無狀態(tài)認證配一個攔截器統(tǒng)一校驗。文件上傳單獨抽一個工具類本地存upload/目錄下數(shù)據(jù)庫只存相對路徑別把二進制往庫里塞。2.2 前端和部署方案的取舍前端選 Vue 3 加 Element Plus理由很實際組件庫現(xiàn)成表格、表單、彈窗、分頁全都有省下來的時間可以放在業(yè)務(wù)邏輯上。用 Vue 2 也行生態(tài)更老更穩(wěn)但 Vue 3 的組合式 API 在寫權(quán)限判斷這種復用邏輯的時候確實清爽。前后端分離的部署方式有兩種。一種是前端npm run build出靜態(tài)文件丟到 Nginx 里Nginx 反向代理/api到后端端口這種方式最接近生產(chǎn)環(huán)境答辯演示也穩(wěn)另一種是偷懶把打包產(chǎn)物塞進 Spring Boot 的static目錄打成一個大 jar雙擊就能跑演示方便但不夠規(guī)范。我的建議是開發(fā)期用第一種練手交付的時候額外準備一個“一鍵啟動包”作為兜底萬一現(xiàn)場網(wǎng)絡(luò)或者 Nginx 出問題不至于手忙腳亂。數(shù)據(jù)庫連接池用 HikariCPSpring Boot 默認就是它配置里把maximum-pool-size設(shè)成 10 就夠了別照抄網(wǎng)上的 50、100幾百人的系統(tǒng)用不上反而容易把本地 MySQL 的連接數(shù)打滿。2.3 項目目錄結(jié)構(gòu)建議這么切src/main/java/com/example/classaffair ├── common # 統(tǒng)一返回、異常、常量、工具 ├── config # 攔截器、跨域、MyBatis 配置 ├── controller ├── service │ └── impl ├── mapper ├── entity ├── dto # 入?yún)?├── vo # 出參 └── handler # 全局異常處理DTO 和 VO 分開這件事很多新手會嫌麻煩直接用實體類接收和返回。小項目確實能跑但一旦涉及到“創(chuàng)建事務(wù)單時不需要傳 id 和創(chuàng)建時間”或者“返回列表時不希望把密碼字段帶出去”你就得回頭改。一開始分開后面省事。3. 數(shù)據(jù)庫設(shè)計這個系統(tǒng)真正的骨架3.1 核心表與字段設(shè)計數(shù)據(jù)庫設(shè)計是這類項目里最能體現(xiàn)功底的部分。我不建議一上來就畫 E-R 圖先把幾個問題在紙上寫清楚有哪幾類“東西”需要獨立存在它們之間是一對多還是多對多哪些狀態(tài)是會變化的這個系統(tǒng)的核心實體大致是這些表名作用關(guān)鍵字段sys_user統(tǒng)一用戶表id, username, password, real_name, role, class_id, statussys_class班級id, class_name, grade, major, counselor_idbiz_affair_type事務(wù)類型字典id, type_name, need_approve, sortbiz_affair事務(wù)主表id, type_id, title, content, creator_id, class_id, status, create_timebiz_affair_flow審批流轉(zhuǎn)記錄id, affair_id, operator_id, action, remark, create_timebiz_notice通知公告id, title, content, publisher_id, scope, publish_timebiz_notice_read通知已讀記錄id, notice_id, user_id, read_timebiz_attachment附件id, biz_type, biz_id, file_name, file_path用戶表用一張sys_user統(tǒng)管所有角色靠role字段區(qū)分而不是建三張表。理由是登錄入口只有一個三張表會逼你在登錄邏輯里寫三段查詢維護起來煩。代價是學生和輔導員的字段差異比如學生有學號、輔導員有工號得放在同一張表里用字段冗余解決。這點冗余可以接受。biz_affair表的設(shè)計是重點。它把請假、活動報名、班費申請、設(shè)備借用這些業(yè)務(wù)都收進一張表靠type_id區(qū)分公共字段標題、內(nèi)容、狀態(tài)、創(chuàng)建人、所屬班級統(tǒng)一差異化字段用ext_json存 JSON 字符串。這種“寬表 JSON 擴展”的做法在業(yè)務(wù)類型不多、字段差異不大的場景下非常劃算省掉了為每種事務(wù)建一張表的麻煩。缺點是 JSON 里的字段沒法直接建索引查詢?nèi)绻硞€類型的事務(wù)需要按擴展字段篩選那就得在建表的時候單獨拆出去。3.2 狀態(tài)機的設(shè)計要提前想明白狀態(tài)機是審批流的核心。我見過太多項目把狀態(tài)存成status字段值是 0、1、2、3然后代碼里到處寫if (status 1)三個月后自己都忘了 2 代表什么。我的做法是用一個枚舉類把狀態(tài)和流轉(zhuǎn)規(guī)則都固定下來public enum AffairStatus { DRAFT(草稿, 0), PENDING(待審批, 1), APPROVED(已通過, 2), REJECTED(已駁回, 3), FINISHED(已完成, 4), CANCELED(已撤銷, 5); private final String label; private final int code; // 構(gòu)造、getter 省略 public static boolean canTransfer(int from, int to) { // 狀態(tài)流轉(zhuǎn)白名單 MapInteger, ListInteger rules new HashMap(); rules.put(0, Arrays.asList(1, 5)); rules.put(1, Arrays.asList(2, 3, 5)); rules.put(2, Arrays.asList(4)); return rules.getOrDefault(from, Collections.emptyList()).contains(to); } }有了這個白名單Service 層每次改狀態(tài)前先調(diào)一次canTransfer非法流轉(zhuǎn)直接拋業(yè)務(wù)異常。這一步能攔掉大量臟數(shù)據(jù)比如“已駁回的單子被改成已通過”或者“已完成的單子又被重新審批”。biz_affair_flow這張流轉(zhuǎn)記錄表也別省。每一次狀態(tài)變化都插一條記錄記錄操作人、動作、備注和時間。這既是審計日志也是給學生端展示“審批進度條”的數(shù)據(jù)來源。答辯時老師問“你的審批流怎么實現(xiàn)的”你把這個表一展示比講十分鐘代碼都管用。3.3 索引和查詢上的幾個實操細節(jié)數(shù)據(jù)量不大不代表不用管索引。biz_affair表上至少要有這幾個索引idx_class_status (class_id, status)用于班委查看本班待辦idx_creator (creator_id)用于學生查看自己提交的記錄idx_create_time (create_time)用于列表倒序分頁。分頁這里有個容易踩的坑MySQL 的LIMIT offset, size在 offset 很大時會變慢。雖然這個系統(tǒng)的數(shù)據(jù)量根本到不了那種程度但寫代碼的時候順手用 ID 游標分頁或者干脆限制最大頁數(shù)是個好習慣。至少別把size參數(shù)直接透傳給 SQL用戶傳個 100000 進來一次查詢就把內(nèi)存拉爆了。在 Controller 層做一次參數(shù)校驗size超過 100 就強制改成 100。還有一個細節(jié)是邏輯刪除。sys_user和biz_affair都建議加一個deleted字段用 MyBatis-Plus 的TableLogic注解刪除操作自動變成更新。物理刪除在演示階段看不出問題但一旦誤刪了數(shù)據(jù)要恢復就只能重裝數(shù)據(jù)庫。4. 核心功能落地一條完整鏈路的實現(xiàn)4.1 登錄認證與權(quán)限攔截登錄流程本身不復雜前端傳用戶名密碼后端查庫比對比對用的是 BCrypt 加密后的密文別用 MD5更別明文存。校驗通過后生成 JWTpayload 里放userId、role、classId有效期設(shè)成 2 小時前端存 localStorage每次請求帶在Authorization頭里。真正的活在于攔截器。我寫了一個AuthInterceptor實現(xiàn)HandlerInterceptor在preHandle里做三件事解析 token、把用戶信息塞進ThreadLocal、校驗當前請求路徑是否在白名單里。Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!(handler instanceof HandlerMethod)) { return true; } String token request.getHeader(Authorization); if (StringUtils.isBlank(token)) { throw new BizException(401, 未登錄); } Claims claims JwtUtil.parse(token); UserContext.set(new LoginUser( claims.get(userId, Long.class), claims.get(role, Integer.class), claims.get(classId, Long.class) )); return true; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { UserContext.remove(); // 必須清理否則線程池復用會串數(shù)據(jù) }afterCompletion里的remove()是必須的。Tomcat 的線程是復用的你不清理下一個請求可能拿到上一個用戶的身份這個 bug 詭異到能讓人查一整天。更細粒度的權(quán)限用一個自定義注解RequireRole配合 AOP 實現(xiàn)標在 Controller 方法上切面里比對當前用戶角色。數(shù)據(jù)范圍校驗放在 Service 層做因為只有 Service 才知道這條數(shù)據(jù)屬于哪個班。4.2 事務(wù)申報與審批流的實現(xiàn)這是整個系統(tǒng)的主干我按一次請假申請來拆。學生端填表單選事務(wù)類型請假填開始時間、結(jié)束時間、事由上傳證明材料點提交。后端收到后做三件事校驗時間區(qū)間合法性結(jié)束時間必須晚于開始時間且不能早于當前時間、校驗該學生在此時間段內(nèi)沒有其他未完結(jié)的請假、插入biz_affair記錄并把狀態(tài)置為PENDING。這里有個業(yè)務(wù)細節(jié)值得說請假這種事務(wù)往往有“時長閾值”的概念比如三天以內(nèi)班長批就行三天以上要輔導員批。這個規(guī)則不要硬編碼在 if-else 里做成一張biz_approve_rule配置表字段是type_id、min_days、max_days、approver_role。Service 里根據(jù)申請時長去查對應的審批角色把待辦推給對應的人。這樣以后規(guī)則變了改數(shù)據(jù)就行不用改代碼。當然畢設(shè)層面用配置類寫死也可以接受但報告里提一句“預留了規(guī)則可配置化能力”是加分項。審批人登錄后看到待辦列表列表查詢條件是status PENDING且class_id在自己的數(shù)據(jù)范圍內(nèi)。點同意后端先校驗當前狀態(tài)確實是PENDING再校驗當前用戶確實有這個權(quán)限然后更新狀態(tài)、插入流轉(zhuǎn)記錄、給學生發(fā)一條站內(nèi)通知。三個操作放在同一個Transactional方法里保證要么全成要么全敗。駁回的邏輯要多一個字段駁回原因。這個原因要寫進流轉(zhuǎn)記錄的remark里學生端能看到否則學生只知道被拒了但不知道為什么體驗極差。4.3 通知與已讀狀態(tài)的處理通知模塊看著簡單但有個經(jīng)典問題怎么知道誰讀了、誰沒讀。笨辦法是biz_notice表加一個read_user_ids字段存逗號拼接的 ID查詢的時候用FIND_IN_SET。數(shù)據(jù)量小的時候能跑但這是典型的反范式設(shè)計一旦要統(tǒng)計已讀率或者做“未讀紅點”就會很難受。正規(guī)做法是單獨一張biz_notice_read關(guān)聯(lián)表(notice_id, user_id)建唯一索引。前端拉通知列表的時候用LEFT JOIN關(guān)聯(lián)這張表read_time為 null 的就是未讀。紅點數(shù)量就是未讀條數(shù)一個count查詢解決。通知的可見范圍也要設(shè)計。scope字段存ALL、CLASS、GRADE配合scope_id。查詢時拼條件ALL的直接可見CLASS的要求scope_id等于當前用戶班級GRADE的要求年級匹配。這個條件建議寫成一個 MyBatis 的sql片段復用避免每個查詢都手寫一遍拼錯。4.4 統(tǒng)計看板與數(shù)據(jù)導出統(tǒng)計模塊是答辯時最容易出彩的地方因為它能直觀展示“系統(tǒng)產(chǎn)生了什么價值”。我做了三塊統(tǒng)計事務(wù)類型分布餅圖、近三十天事務(wù)提交趨勢折線圖、各班級事務(wù)處理及時率柱狀圖。前兩個用一條GROUP BY查詢就夠第三個稍微復雜點需要計算每條事務(wù)從PENDING到終態(tài)的時間差再按班級聚合。SELECT a.class_id, c.class_name, ROUND(AVG(TIMESTAMPDIFF(HOUR, a.create_time, f.create_time)), 1) AS avg_hours, COUNT(*) AS total FROM biz_affair a JOIN biz_affair_flow f ON f.affair_id a.id AND f.action IN (APPROVE, REJECT) JOIN sys_class c ON c.id a.class_id WHERE a.create_time DATE_SUB(NOW(), INTERVAL 30 DAY) GROUP BY a.class_id, c.class_name ORDER BY avg_hours ASC;導出功能用 EasyExcel別用 POI 原生 API那個寫起來太啰嗦。導出的時候注意兩點一是大數(shù)據(jù)量要分頁查再寫別一次selectList全撈出來二是字段名用中文表頭日期格式化好導出的表格能直接給人看才有意義。5. 開題報告怎么寫才不像模板5.1 研究背景和意義別寫成套話開題報告的第一段十份里有八份是“隨著信息技術(shù)的飛速發(fā)展高校信息化建設(shè)不斷深入……”。這種開頭評審老師一天看幾十份直接跳過。我建議從具體問題切入寫你觀察到的真實場景。比如班級事務(wù)長期依賴即時通訊群一條通知發(fā)出去回復“收到”的人刷屏真正重要的信息被淹沒請假靠私聊輔導員手機里幾百條記錄沒法歸檔班費收支用表格記錄學期末對賬費時費力。這些都是可以寫進報告的具體痛點比空泛的“提高效率”有說服力得多。研究意義分兩層寫就夠了實踐層面是解決上述具體問題理論層面是探索輕量級審批流在班級這種小規(guī)模組織中的適配方案。別硬扯“填補領(lǐng)域空白”一個班幾十人的系統(tǒng)填補不了什么空白老老實實寫“具備一定的工程實踐參考價值”反而得體。5.2 國內(nèi)外研究現(xiàn)狀的寫法這部分最容易被寫廢因為大部分同學根本沒讀過外文文獻硬編會露餡。我的建議是分三類來寫通用辦公協(xié)作平臺這類產(chǎn)品功能全但重班級場景用不上那么多、校園信息化系統(tǒng)這類系統(tǒng)通常由學校統(tǒng)一建設(shè)顆粒度到院系班級層面的個性化需求覆蓋不到、開源的學生管理系統(tǒng)這類項目往往功能齊全但技術(shù)棧陳舊或者文檔缺失二次開發(fā)成本高。每一類寫清楚“它做了什么、它沒解決什么”最后自然過渡到“所以需要一個輕量、聚焦班級場景、可自主部署的方案”。這個邏輯鏈條是站得住的而且不需要你捏造文獻。參考文獻里放幾篇國內(nèi)期刊的班級管理系統(tǒng)論文再放兩三本 Spring Boot 和 Vue 的技術(shù)書加上官方文檔鏈接足夠了。5.3 研究內(nèi)容和技術(shù)路線要能對上很多開題報告的毛病是前面說要做智能推薦、大數(shù)據(jù)分析后面的技術(shù)路線里全是 CRUD前后對不上。評審老師一眼就能看出是湊字數(shù)。我的原則是研究內(nèi)容寫幾條技術(shù)路線就對應幾條功能模塊和表結(jié)構(gòu)也能對應上。比如研究內(nèi)容第一條是“班級事務(wù)申報與多級審批流程設(shè)計”那技術(shù)路線里就要有狀態(tài)機設(shè)計、流轉(zhuǎn)記錄表設(shè)計、審批規(guī)則配置這幾項數(shù)據(jù)庫設(shè)計里就要有biz_affair、biz_affair_flow這些表。三處能對上說明你真的想清楚了。進度安排按周來排別排得太滿。留出兩周機動時間給聯(lián)調(diào)和 Bug 修復這個預留不是浪費時間是給自己留活路。答辯前一周專門用來準備演示數(shù)據(jù)和 PPT這個環(huán)節(jié)的重要性不亞于寫代碼。可行性分析分技術(shù)、經(jīng)濟、操作三個維度寫。技術(shù)可行性講技術(shù)棧成熟、資料豐富經(jīng)濟可行性講全部使用開源免費組件一臺普通電腦就能跑操作可行性講界面遵循常見交互習慣用戶不需要培訓。三個維度各寫一小段別寫太長這部分不是重點。6. 踩過的坑和排查實錄6.1 環(huán)境與依賴類問題中文亂碼是最常見的。三個地方要統(tǒng)一數(shù)據(jù)庫建庫時指定utf8mb4JDBC 連接的 URL 里加characterEncodingutf8前端請求頭設(shè)置Content-Type: application/json;charsetUTF-8。三處都對了還亂碼就檢查 Nginx 有沒有配置charset utf-8??缬騿栴}在前后端分離開發(fā)階段必現(xiàn)。開發(fā)期在配置類里加一個CorsConfig放行本地端口生產(chǎn)環(huán)境用 Nginx 同源代理就不存在跨域了。注意allowedOrigins不要圖省事寫*同時開allowCredentials瀏覽器會直接拒絕。時間字段差八小時這是時區(qū)問題。JDBC URL 里加serverTimezoneAsia/Shanghai實體類用LocalDateTime而不是DateJackson 序列化配置spring.jackson.time-zoneGMT8。這三步做完基本就不會錯了。6.2 業(yè)務(wù)邏輯類問題并發(fā)提交重復審批。兩個輔導員同時點同意可能都會通過。解決辦法是在更新狀態(tài)時加樂觀鎖SQL 寫成UPDATE biz_affair SET status ? WHERE id ? AND status ?用影響行數(shù)判斷是否更新成功返回 0 就說明被別人搶先了提示“該事務(wù)已被處理”。分頁總數(shù)不對。用 MyBatis-Plus 的分頁插件時如果 SQL 里自己寫了UNION或者復雜的子查詢總數(shù)統(tǒng)計可能出錯。遇到這種情況就把 count 查詢單獨寫一個 SQL別依賴自動生成。文件上傳后訪問 404。Spring Boot 默認不允許直接訪問項目外的目錄需要配置WebMvcConfigurer把上傳目錄映射成靜態(tài)資源路徑?;蛘吒纱喟盐募娴絩esources/static下的子目錄但這種做法在打成 jar 之后會有問題不推薦。6.3 答辯時可能被問到的問題整理了一張表提前準備比臨場發(fā)揮靠譜問題回答思路為什么不用 Redis系統(tǒng)并發(fā)量在百人級別本地緩存加數(shù)據(jù)庫索引足夠引入 Redis 會增加部署復雜度不符合輕量定位審批流怎么支持多級當前實現(xiàn)了兩級班委、輔導員流轉(zhuǎn)記錄表已按多級設(shè)計擴展時只需在規(guī)則表里增加層級配置數(shù)據(jù)安全怎么保證密碼 BCrypt 加鹽存儲接口層做 JWT 校驗和角色鑒權(quán)敏感操作記流轉(zhuǎn)日志如果班級合并了怎么辦班級表設(shè)計了年級和專業(yè)字段合并時批量更新用戶的class_id歷史事務(wù)記錄保留原class_id不受影響系統(tǒng)的瓶頸在哪在統(tǒng)計報表的聚合查詢上數(shù)據(jù)量增長后可以通過加匯總表或者定時預計算解決這些問題背后的邏輯其實就是讓你證明自己不是照著教程抄的。答不上來不可怕胡編才可怕坦誠說“這部分目前是簡化處理后續(xù)可以這樣擴展”是完全能接受的答案。7. 交付與演示的最后一步7.1 打包部署的完整流程前端在項目根目錄執(zhí)行npm run build產(chǎn)物在dist目錄。把dist整個拷到服務(wù)器Nginx 配置這樣寫server { listen 80; server_name localhost; location / { root /opt/app/dist; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }try_files那一行不能少否則前端路由刷新會 404。后端用mvn clean package -DskipTests打包產(chǎn)出的 jar 用nohup java -jar xxx.jar --spring.profiles.activeprod app.log 21 啟動。生產(chǎn)配置里把數(shù)據(jù)庫密碼、JWT 密鑰放到單獨的application-prod.yml不要提交到代碼倉庫。7.2 演示前的檢查清單演示當天出問題的項目八成倒在下面這幾條上提前挨個過一遍數(shù)據(jù)庫連接池能不能正常拿到連接重啟一次 MySQL 試試種子數(shù)據(jù)是否完整學生賬號能不能登錄待辦列表里有沒有數(shù)據(jù)上傳附件的目錄是否有寫權(quán)限瀏覽器緩存是否清過前端靜態(tài)資源版本對不對關(guān)鍵流程是否準備了第二條數(shù)據(jù)第一條演示失敗還有備份另外準備一個純靜態(tài)的演示視頻作為終極兜底五分鐘把主流程錄一遍。現(xiàn)場投影儀分辨率不對、網(wǎng)絡(luò)斷了、電腦藍屏這些事都發(fā)生過有視頻至少不會全場尬住。我個人在帶這類項目時有個習慣交稿前一周讓完全沒參與開發(fā)的同學按著使用手冊獨立操作一遍。他卡住的地方就是文檔要補的地方也是答辯時老師可能問的地方。這個笨辦法屢試不爽比自己對著一遍遍點點點有效得多。這個系統(tǒng)后續(xù)真要擴展方向其實挺清楚把審批規(guī)則做成可視化配置界面、給事務(wù)類型加自定義表單設(shè)計器、接入消息推送讓待辦不再依賴用戶主動登錄查看。但這些都是后話先把主干跑通、把報告寫實比什么都重要。