forked from zhongyidian/super_video
完善课程资源、学习进度与技能树解锁体验,统一视频播放与引导相关交互。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
169 lines
4.6 KiB
Vue
169 lines
4.6 KiB
Vue
<script lang="ts" setup>
|
||
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>(store.practiceNoteContent)
|
||
|
||
/** 保存弹窗 */
|
||
const showModal = ref<boolean>(false)
|
||
const showSuccess = ref<boolean>(false)
|
||
let successTimer: number | undefined
|
||
|
||
/** 返回上一页 */
|
||
const handleBack = (): void => {
|
||
router.back()
|
||
}
|
||
|
||
const disabled = computed<boolean>(() => noteContent.value.trim() === '')
|
||
|
||
/** 评估项目列表 */
|
||
const defaultEvaluationItems: PracticeRatingItem[] = [
|
||
{
|
||
title: '人物表达',
|
||
description: '能清晰介绍人物身份、特点或故事,让观众认识人物',
|
||
score: 0,
|
||
},
|
||
{
|
||
title: '素材拍摄',
|
||
description: '画面包含必要人物镜头、环境镜头与细节素材,内容较丰富',
|
||
score: 0,
|
||
},
|
||
{
|
||
title: '镜头语言',
|
||
description: '合理使用移动镜头、特写、跟拍等方式增强表现力',
|
||
score: 0,
|
||
},
|
||
{
|
||
title: '剪辑结构',
|
||
description: '结构完整清晰,段落顺畅,内容有起承转合',
|
||
score: 0,
|
||
},
|
||
{
|
||
title: '音画关系',
|
||
description: '画面与配音/环境音基本匹配,能辅助理解内容',
|
||
score: 0,
|
||
},
|
||
{
|
||
title: '综合观感',
|
||
description: '作品完整,有真实感与感染力,具备观看吸引力',
|
||
score: 0,
|
||
},
|
||
]
|
||
|
||
const evaluationItems = ref<PracticeRatingItem[]>(
|
||
applyScores(defaultEvaluationItems, store.practiceSelfEvaluationScores),
|
||
)
|
||
|
||
const handleSave = (): void => {
|
||
const content = noteContent.value.trim()
|
||
if (!content) return
|
||
|
||
store.setPracticeNoteContent(noteContent.value)
|
||
store.markViewed('InterviewPractice')
|
||
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>
|
||
<div
|
||
class="w-full h-full bg-no-repeat bg-cover px-8 pt-[400px]"
|
||
:style="{
|
||
backgroundImage: getBackgroundImage('interview/practice/我的创作笔记'),
|
||
}"
|
||
>
|
||
<ImgButton
|
||
class="absolute top-0 right-0"
|
||
:image="IMAGE_PATHS.COMPONENTS.CLOSE"
|
||
@click="handleBack"
|
||
/>
|
||
|
||
<textarea
|
||
v-model="noteContent"
|
||
class="w-full h-[300px]"
|
||
name="myNotes"
|
||
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/保存"
|
||
:disabled="disabled"
|
||
@click="handleSave"
|
||
/>
|
||
<ImgButton
|
||
image="vlog/practice/自评"
|
||
:disabled="disabled"
|
||
@click="showModal = true"
|
||
/>
|
||
</div>
|
||
|
||
<PracticeRatingModal
|
||
:visible="showModal"
|
||
v-model:items="evaluationItems"
|
||
background-image="interview/practice/人物访谈短片创作-作品评分表"
|
||
top-tip="评分时要关注6个维度哦!分别是人物表达、素材拍摄、镜头语言、剪辑结构、音画关系、综合观感每个维度满分5分,能打1-5分,记得对照作品表现来打分呀~"
|
||
bottom-tip="己评价的实战作品,从封面入口就能直接看到具体评分!打了多少分一目了然,不用再点进详情页翻找啦~"
|
||
@save="handleSaveEvaluation"
|
||
@close="showModal = false"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
textarea {
|
||
border: none;
|
||
outline: none;
|
||
resize: none;
|
||
font-size: 36px;
|
||
background-color: transparent;
|
||
}
|
||
|
||
textarea::placeholder {
|
||
color: #5d5b5b;
|
||
font-weight: 700;
|
||
}
|
||
</style>
|