肝了73小時的計算機設計賽交稿了!這3個設計決策讓我徹夜難眠
職業(yè)規(guī)劃項目總結
此項目是2025中國大學生設計大賽web開發(fā)組的一個作品。
在最開始的時候,沒有人在乎這個比賽,老師提出2個選題,其中一個就是這個,然后我回去做了一個前端的demo,給老師看了一下,沒有什么反應。我就繼續(xù)做我的項目去了,一直做,直到4.9號才開了一個會說要選擇一個題目,最終的結果就是選擇了職業(yè)規(guī)劃,其中一個人還退了,因為報了其他的組,然后老師A就一直問準備的怎么樣了...我沒話說,因為我根本就沒有去了解
項目前期
4-9
前期一直都是我在弄,我剛開始想的是設計一個數(shù)據(jù)庫出來先,我就去設計了半天,當然之后還是一直在修改一些字段。
這個項目的主要是依靠AI來進行分析簡歷之類的操作,所以我當時做了有個簡單的兩個接口,也就是登錄和注冊,我就去研究AI了。
4-10
首先我用的是SpringAI,然后我弄了半天都不知道要怎么流式輸出(讓AI輸出的字一點一點的出來),我又看到了一個第三方依賴langchain4j,然后在B站看到了一個視頻,跟著他寫完,可以流式輸出了,然后又去弄JSONPATH的問題,我記得當時是弄到了2點多,還是有點問題,就是JSONPATH的問題,第二天早上一起來我就接著干活,終于算是搞定了
JSONPATH:$.data
## 優(yōu)勢分析- **教育背景**:清華大學計算機科學與技術專業(yè)與目標崗位高度匹配- **工作經(jīng)歷**:在字節(jié)跳動任職三年,積累豐富實戰(zhàn)經(jīng)驗,參與多個大型項目- **技能描述**:熟悉多種前端框架,如JS中的Node.js, React, Vue.js,以及多種Python框架,如Django, Flask,表明技術棧廣泛## 缺點分析- **時間斷層**:2020-2021年未說明具體去向- **技能描述不清**熟悉Office應改為熟練掌握Office工具,尤其是Excel高級功能## 面試建議- **STAR法則**:在描述項目經(jīng)歷時,按照情景(Scenario)、任務(Task)、行動(Action)、結果(Result)的原則進行闡述- **崗位關聯(lián)**:確保所列技能中針對于招聘要求提及的特定工具或技術進行詳細描述,結合具體項目成果強調對應的技術能力
代碼實現(xiàn)(Controller層):
@PostMapping(value = "/send/{resumeId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> sendResume(@PathVariable("resumeId") Long resumeId) {
// TODO 之后需要添加消息隊列給出職位推薦...
return resumeService.analyzeResumeStream(resumeId)
.map(json -> "{\"data\":\"" + json + "\"}")
.timeout(Duration.ofSeconds(30)) // 防止長時間無響應
.onErrorResume(e -> {
log.debug("連接中止: " + e.getMessage());
return Flux.just("{\"data\":\"" + "已停止" + "\"}");
});
}
知道怎么調用AI進行流式輸出,我就寫了一個分析簡歷的接口,Service我就不放出來了,其實差不太多,就是保存完成之后保存在數(shù)據(jù)庫里面了。
還有根據(jù)問題答案推薦職業(yè)的接口,差不多就寫了這些。
@Override
public Result analyze(List<QuestionDTO> questionDTOList) {
//獲取總分
Question question = getRecord(questionDTOList);
if(question.getAnalyzeData() !=null){
//有數(shù)據(jù),不需要請求ai,直接返回
String analyzeData = question.getAnalyzeData().toString();
RecommendedVO recommendedVO = JSONUtil.toBean(analyzeData, RecommendedVO.class);
return Result.ok(recommendedVO);
}
String jsonStr = JSONUtil.toJsonStr(questionDTOList);
//直接寫到消息隊列中
if(sendStreamMessage(jsonStr,JOB_QUESTION_KEY,question.getScoreTotal())){
return Result.ok();
}else{
return Result.fail("請求失敗");
}
//直接返回
}
4-11
今天我沒有push到GitHub有點忘記做了啥了,我記得我是寫了一個專業(yè)測評的功能,然后提出了幾個想法,專業(yè)測評(職業(yè)測評和專業(yè)測評以下統(tǒng)稱為測評功能)就是其中一個,根據(jù)職業(yè)或者專業(yè)生成學習路徑的功能我是在設計數(shù)據(jù)庫的時候我就想好了,我還想到了一個就是給失業(yè)的人提建議的功能,但是我感覺有點難以實現(xiàn)而且不好保存,所以就沒有寫。專業(yè)測評的代碼跟職業(yè)測評的是差不多的。
4-12
今天我優(yōu)化了一下測評功能,最開始我寫的是直接去請求AI,然后我這個線程一直在堵塞,等待AI的響應,最重要的是AI返回的JSON數(shù)據(jù)可能是錯誤的,,就導致體驗非常的糟糕,想起來我學了Redis,而Redis有一個數(shù)據(jù)類型Stream,就是專門為消息隊列設計的,我就用它來寫消息隊列(當時我還不會消息隊列的中間件),把測評的代碼修改一下,就OK了。
我記得當天我還我弄了一個阿里云的API去,剛開始有一定的免費額度
項目中期
4-13
今天加了一個查看歷史評測的功能,用Redis的ZSet存儲,這里還是挺簡單的,就不多說了。
主要是給查看職業(yè)專業(yè)加了一個緩存,剛開始我設置了1天過期,我也是個人才,現(xiàn)在是20分鐘過期,給簡歷添加了一個字段,默認簡歷,為什么加這個呢,因為在后面的生成學習路徑需要用。
生成學習路徑的接口是最難寫的功能了,我覺得這個項目里面。首先是兩個接口,一個接收職業(yè)id,一個接收專業(yè)id。生成對應的路徑,因為也涉及到了AI我寫在消息隊列里面,就直接返回了。測試有很多bug
4-14
一直在弄生成學習路徑的接口...然后到晚上還是有問題...
剛開始生成學習路徑我是想著,先生成需要的技能,然后用戶點擊技能我再去請求章節(jié),點擊章節(jié)請求小結,首先是代碼實現(xiàn)起很麻煩,這個寫消息隊列吧,我都要查看章節(jié),小結了,你跟我說沒有?不寫消息隊列吧,又太慢了,所以我決定直接生成全部。解析那里的業(yè)務代碼就變得很復雜,是我目前寫過最復雜的業(yè)務代碼了
4-15
今天終于把生成學習路徑的接口搞定了,我就去寫了一下回去學習路徑的接口,根據(jù)路徑id獲取技能、根據(jù)技能id獲取章節(jié)、根據(jù)章節(jié)id獲取小結,寫了一個完成小結的接口(具體的邏輯沒有寫,只是單純的修改了一下狀態(tài))。
4-16
寫了一個分頁獲取所有專業(yè)、職業(yè)的接口,給專業(yè)、職業(yè)添加了一個字段,分類,根據(jù)分類獲取,添加模糊查找的功能。添加簡單的評論功能,舉報評論的功能,不過這里寫的有問題,用戶本人發(fā)送的評論用戶刪除不了,而且用戶可以重復舉報一個評論,這對數(shù)據(jù)庫造成了很大的壓力,還有就是刪除學習路徑?jīng)]有進行二次判斷,有安全問題。
4-17
寫了一個很關鍵的業(yè)務,就是用戶點擊完成小結,我沒有去更新學習的狀態(tài)以及進度,這里我想了很久都不知道要怎么寫,因為我不知道當前小結是屬于哪個學習路徑的,屬于哪個技能的。還有就是我不知道這個學習路徑總共有多少個小結,技能總共有多少個小結,這樣我也沒有辦法去計算他的一個進度。前端只傳遞了一個小結的id
nym可以想一想再繼續(xù)看
下面是當時表的結構
leanring_paths
學習路線表
分析簡歷之后,返回分析的內(nèi)容,用戶可以選擇某個學習路線進行學習,選擇之后存儲在
id | bigint | ||
job_id | bigint | 外鍵 | |
majors_id | bigint | 外鍵 | 不能跟job_id同時存在 |
user_id | bigint | 外鍵 | |
goal_name | varchar(20) | 目標名 | |
current_progress | tinyint | 進度 | (0-100) |
is_active | boolean | 是否完成 | 0:進行中1:已完成 |
why_recommend | varchar(400) | 為啥推薦 | |
advice_and_attention | varchar(300) | 建議和注意事項 | |
complete_harvest | varchar((200) | 完成之后的收獲 | |
create_at | date | 創(chuàng)建時間 | 時間戳 |
end | date | 完成時間 |
learning_skill
學習某個技能表
id | BIGINT | 主鍵ID | |
path_id | BIGINT | 學習路徑ID | 外鍵 |
step_name | VARCHAR(100) | 步驟名稱 | 比如:學習Java |
step_order | INT | 步驟順序 | |
current_progress | tinyint | 學習進度 | (0-100) |
status | char(1) | 學習狀態(tài) | 0未學 1學習中 2學完 |
scheduled_time | varchar(20) | 預計時間 | 例如:3-6個月 |
importance | char(20) | 重要程度 | 核心/重要/擴展 |
preknowledge | varchar(200) | 前置知識 | 可為null |
resource | json | 學習資源 | |
complete_harvest | varchar(300) | 完成之后的收獲 | |
start_date | DATETIME | 開始日期 | 時間戳 |
complete_date | DATETIME | 完成日期 |
learing_skill_chapter
學習某個技能的具體章節(jié)
id | bigint | 主鍵 | |
skill_id | bigint | 外鍵 | 表learning_skill |
name | varchar(50) | 章節(jié)名稱 | 比如:"第一章:JavaScript簡介" |
status | char(1) | 學習狀態(tài) | 0未學 1學習中 2學完 |
complete_harvest | varchar(100) | 完成收獲 | |
description | varchar(200) | 說明 | |
chapter_order | int | 順序 |
learning_skill_details
學習某個技能下章節(jié)的的詳細表格
id | bigint | 主鍵 | |
chapter_id | bigint | 外鍵 | 表learing_skill_chapter |
name | varchar(50) | 學習小節(jié)名稱 | 比如:第一個Java程序 |
status | char(1) | 學習狀態(tài) | 0未學 1學習中 2學完 |
note | text | 學習筆記 | |
description | varchar(200) | 說明 | |
nodule_order | int | 順序 |
解決辦法:我當時想的是生成學習路徑,保存小結的時候在redis里面用list保存一下整個學習路徑的小結數(shù)以及每個技能的總小結數(shù)。寫到這里我去看了一下redis,發(fā)現(xiàn)怎么那么多,學習路徑才那么點,看了一下刪除學習路徑的接口發(fā)現(xiàn)忘記刪除緩存了...
先修改一下小結表的結構,添加兩個字段路徑id,技能id,保存完成之后需要在完成小結的接口執(zhí)行一系列的業(yè)務邏輯,首先是需要讓前端傳遞路徑id 以及技能id,因為有點復雜,所以我直接寫消息隊列了。
在消息隊列里面,獲取路徑id,根據(jù)路徑的id獲取總數(shù),獲取當前技能的總數(shù),此時可以有人在想,我直接去數(shù)據(jù)庫里面查一下不就行了嗎?為啥要把總數(shù)寫在redis里面呢?這確實是可以的,我是因為當時我我去沒有想到,我寫著寫著才想到的。不過我這樣寫也沒有什么問題,因為在這里需要執(zhí)行很多更新的操作,對于數(shù)據(jù)庫來說其實壓力挺大的。之后就簡單了,首先獲取技能已完成的節(jié)點還要路徑已完成的節(jié)點,去獲取進度即可,這里還需要判斷已完成的節(jié)點是否等于全部節(jié)點,如果等于需要更新路徑,技能的狀態(tài)
4-18
優(yōu)化評論功能,用redis的Set存儲哪個用戶舉報了這個評論,在舉報時判斷一下,防止重復舉報。在刪除的相關接口(刪除簡歷,刪除學習路徑)添加一個當前登錄用戶的判斷。
4-19
修復了一下學習路徑的bug,還有就是修改了一下提示詞,之前的AI,不過我的目標是啥,返回的都是學習Java的學習路徑,加了一個mybatis的配置類,之前沒有寫,更新成功還給我返回false,老是返回錯誤的結果,我到今天才解決整個問題。
項目后期
4-20
添加cors配置,添加傳遞用戶默認簡歷的功能(之前老是生成Java的學習路徑我就把這個刪除了,現(xiàn)在又加回來了)
4-21
添加專門的測試接口,用于前端連接后端的測試,攔截器不攔截測試接口
4-22
修復配置類,不讓服務器緩存流式
其實這幾天主要在弄前端和服務器的問題,前端部署了之后是https,然后后端默認是http的,師兄就弄這個問題,還要就是因為后端是沒有域名的,導致前端請求時會屏蔽這個請求,就在前端加了一個測試的功能
項目總結
總的來說,我對redis的掌握更好了,還有就是了解了AI的基本調用方法。項目經(jīng)驗+1
放幾張圖片
體驗地址:https://marvelous-snickerdoodle-d8a4f2.netlify.app/ 第一次需要同意訪問后端!
#比賽##大一##我的失利項目復盤#