feat: 完善视频学习进度缓存

完善新手导航和三大创作模块的视频完成缓存、未完成提示与学习进度计算,确保进度按实际学习资源完成情况更新。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.7 committed 2026-05-11 09:05:29 +08:00
1 parent 1f8723aabd
commit 6f289959be
63 files changed
+3139 -1126

No files matched your search

@@ -1,19 +1,37 @@
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { computed, onBeforeUnmount, ref } from 'vue'
import { useRouter } from 'vue-router'
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
import { ImgButton } from '@/components/Button'
import PracticeRatingModal, {
type PracticeRatingItem,
} from '@/components/PracticeRatingModal'
import { useInterviewStore } from '@/stores/modules/interview'
const router = useRouter()
const store = useInterviewStore()
type PracticeRatingScores = Record<string, number>
const applyScores = (
items: PracticeRatingItem[],
scores: PracticeRatingScores,
): PracticeRatingItem[] =>
items.map((item) => ({
...item,
score: scores[item.title] ?? item.score,
}))
const toScores = (items: PracticeRatingItem[]): PracticeRatingScores =>
Object.fromEntries(items.map((item) => [item.title, item.score]))
/** 笔记内容 */
const noteContent = ref<string>('')
const noteContent = ref<string>(store.practiceNoteContent)
/** 保存弹窗 */
const showModal = ref<boolean>(false)
const showSuccess = ref<boolean>(false)
let successTimer: number | undefined
/** 返回上一页 */
const handleBack = (): void => {
@@ -23,7 +41,7 @@ const handleBack = (): void => {
const disabled = computed<boolean>(() => noteContent.value.trim() === '')
/** 评估项目列表 */
const evaluationItems = ref<PracticeRatingItem[]>([
const defaultEvaluationItems: PracticeRatingItem[] = [
{
title: '人物表达',
description: '能清晰介绍人物身份、特点或故事,让观众认识人物',
@@ -54,11 +72,28 @@ const evaluationItems = ref<PracticeRatingItem[]>([
description: '作品完整,有真实感与感染力,具备观看吸引力',
score: 5,
},
])
]
const evaluationItems = ref<PracticeRatingItem[]>(
applyScores(defaultEvaluationItems, store.practiceSelfEvaluationScores),
)
const handleSave = (): void => {
console.log('保存笔记')
handleBack()
store.setPracticeNoteContent(noteContent.value)
showSuccess.value = true
window.clearTimeout(successTimer)
successTimer = window.setTimeout(() => {
showSuccess.value = false
}, 1500)
}
const handleSaveEvaluation = (items: PracticeRatingItem[]): void => {
store.setPracticeSelfEvaluationScores(toScores(items))
}
onBeforeUnmount(() => {
window.clearTimeout(successTimer)
})
</script>
<template>
@@ -81,6 +116,13 @@ const handleSave = (): void => {
placeholder="点击输入创作笔记"
></textarea>
<div
v-if="showSuccess"
class="absolute left-1/2 top-1/2 z-[100] -translate-x-1/2 -translate-y-1/2 rounded-2xl bg-black/70 px-16 py-8 text-5xl font-bold text-white"
>
提交成功
</div>
<div class="absolute bottom-24 left-1/2 -translate-x-1/2 flex gap-60">
<ImgButton
image="vlog/practice/保存"
@@ -95,10 +137,11 @@ const handleSave = (): void => {
<PracticeRatingModal
:visible="showModal"
:items="evaluationItems"
v-model:items="evaluationItems"
background-image="interview/practice/人物访谈短片创作-作品评分表"
top-tip="评分时要关注6个维度哦~分别是人物表达、素材拍摄、镜头语言、剪辑结构、音画关系、综合观感每个维度满分5分,能打1-5分,记得对照作品表现来打分呀~"
bottom-tip="己评价的实战作品,从封面入口就能直接看到具体评分!打了多少分一目了然,不用再点进详情页翻找啦~"
@save="handleSaveEvaluation"
@close="showModal = false"
/>
</div>