From 527ad7c7a3988aa69beaad238c3a9617bd2cf5dd Mon Sep 17 00:00:00 2001 From: TheBreeze <3246119723@qq.com> Date: Mon, 25 May 2026 11:38:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E5=9C=A8=E8=A7=86=E9=A2=91=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=A2=9E=E5=8A=A0=E7=9B=B8=E5=85=B3=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=8E=A8=E8=8D=90=EF=BC=8C=E4=BB=A5=E5=8F=8A=E9=A2=98=E7=9B=AE?= =?UTF-8?q?=E6=8E=A8=E8=8D=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/modules/video.js | 5 + .../components/KnowledgeGraph/NodeDetail.vue | 57 +++++ frontend/src/views/VideoPlayer/index.vue | 197 +++++++++++++++++- .../controller/VideoController.java | 5 + .../learningplatform/dto/VideoResponse.java | 1 + .../service/GraphService.java | 96 +++++++++ .../service/VideoService.java | 100 +++++++++ 7 files changed, 456 insertions(+), 5 deletions(-) diff --git a/frontend/src/api/modules/video.js b/frontend/src/api/modules/video.js index a686971..1fc72f0 100644 --- a/frontend/src/api/modules/video.js +++ b/frontend/src/api/modules/video.js @@ -14,6 +14,11 @@ export function getVideoDetail(id) { return http.get(`/video/${id}`) } +/** 根据知识图谱关联关系推荐相关视频。 */ +export function getRecommendedVideos(id) { + return http.get(`/video/${id}/recommendations`) +} + /** 查询当前用户在某个视频上的观看记录。 */ export function getWatchRecord(videoId) { return http.get(`/video/watch-record/${videoId}`, { diff --git a/frontend/src/components/KnowledgeGraph/NodeDetail.vue b/frontend/src/components/KnowledgeGraph/NodeDetail.vue index 226ee08..942bf4d 100644 --- a/frontend/src/components/KnowledgeGraph/NodeDetail.vue +++ b/frontend/src/components/KnowledgeGraph/NodeDetail.vue @@ -59,6 +59,36 @@ + +
+
相关视频
+
+ +
+
+ +
+
配套习题
+
+ +
+
@@ -176,6 +206,33 @@ const corePointList = computed(() => { if (!props.node?.corePoints) return [] return props.node.corePoints.split(/[、,,]/).map((s) => s.trim()).filter(Boolean) }) + +const openVideo = (id) => { + router.push({ name: 'VideoPlayer', query: { videoId: id } }) +} + +const openExercise = (exercise) => { + if (!exercise?.id) return + if (['SINGLE_CHOICE', 'MULTIPLE_CHOICE'].includes(exercise.type)) { + router.push({ path: `/exercise/choice/${exercise.id}` }) + return + } + if (exercise.type === 'FILL_BLANK') { + router.push({ path: `/exercise/fill/${exercise.id}` }) + return + } + router.push({ path: `/exercise/${exercise.id}` }) +} + +const exerciseTypeLabel = (type) => { + const map = { + SINGLE_CHOICE: '单选', + MULTIPLE_CHOICE: '多选', + FILL_BLANK: '填空', + PROGRAMMING: '编程', + } + return map[type] || '习题' +}