feat: 添加技能树路由,优化组件缓存和图片预览功能
This commit is contained in:
1 parent
431d3ce6cb
commit
f8a997aad4
23 files changed
+751
-18
No files matched your search
@@ -0,0 +1,273 @@
|
||||
<script lang="tsx" setup>
|
||||
defineOptions({ name: 'SkillPage' })
|
||||
import { ref, computed } from 'vue'
|
||||
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
|
||||
import { ImgButton } from '@/components/Button'
|
||||
import { GuideSteps } from '@/components/Guide'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const stepIndex = ref(0)
|
||||
const selected = ref(false)
|
||||
const sideStatus = ref(true)
|
||||
|
||||
const status = ref(false)
|
||||
|
||||
const selectedButton = ref('拍摄基础')
|
||||
//按钮 {key: '拍摄基础', value: '拍摄基础'}
|
||||
const buttons = ref([
|
||||
{ key: '拍摄基础', value: '拍摄基础' },
|
||||
{ key: '内容策划', value: '内容策划' },
|
||||
{ key: '拍摄执行', value: '拍摄执行' },
|
||||
{ key: '后期制作', value: '后期制作' },
|
||||
{ key: '版权伦理意识', value: '版权伦理意识' }
|
||||
])
|
||||
|
||||
// 预留:按钮选中状态(如需启用再恢复逻辑)
|
||||
|
||||
//引导步骤
|
||||
const steps = [
|
||||
{
|
||||
id: 'step1',
|
||||
content: '可以点击左右箭头切换到对应模块的知识树哦'
|
||||
}
|
||||
]
|
||||
|
||||
// 预留:模块按钮(如需启用再补充实现)
|
||||
|
||||
const currentHighlight = computed(() =>
|
||||
stepIndex.value === 0 ? '.img-switch-item--vlog' : '.work-border'
|
||||
)
|
||||
|
||||
const selectedImage = computed(() => {
|
||||
return selected.value ? 'skill/画面构图选中' : 'skill/画面构图未选中'
|
||||
})
|
||||
|
||||
interface SimpleStep {
|
||||
id: string
|
||||
content: string
|
||||
}
|
||||
|
||||
const handleStepChange = (_step: SimpleStep | null, index: number) => {
|
||||
stepIndex.value = index
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
const handleClick = () => {
|
||||
selected.value = true
|
||||
router.push({
|
||||
name: 'SkillVdieo'
|
||||
})
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
status.value = true
|
||||
}, 1000)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full relative font-semibold">
|
||||
<!-- 背景图片-center -->
|
||||
<div
|
||||
class="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||
:style="{ backgroundImage: getBackgroundImage('skill/技能树背景') }"
|
||||
></div>
|
||||
|
||||
<ImgButton class="absolute left-0 top-1/2 -translate-y-1/2" :image="'skill/左滑'"> </ImgButton>
|
||||
|
||||
<ImgButton
|
||||
@click="sideStatus = false"
|
||||
class="absolute right-0 top-1/2 -translate-y-1/2"
|
||||
:image="'skill/右滑'"
|
||||
>
|
||||
</ImgButton>
|
||||
|
||||
<!-- 周围模块标签(静态绘制) -->
|
||||
<div v-show="sideStatus" class="module module-left-bottom module-vertical">
|
||||
<div
|
||||
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
|
||||
>
|
||||
拍摄基础
|
||||
</div>
|
||||
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
|
||||
</div>
|
||||
|
||||
<div v-show="sideStatus" class="module module-left-middle module-vertical">
|
||||
<div
|
||||
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
|
||||
>
|
||||
内容策划
|
||||
</div>
|
||||
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
|
||||
</div>
|
||||
|
||||
<div v-show="!sideStatus" class="module module-right-middle module-vertical">
|
||||
<div
|
||||
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
|
||||
>
|
||||
拍摄执行
|
||||
</div>
|
||||
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
|
||||
</div>
|
||||
|
||||
<div v-show="sideStatus" class="module module-right-upper module-vertical">
|
||||
<div
|
||||
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
|
||||
>
|
||||
后期制作
|
||||
</div>
|
||||
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
|
||||
</div>
|
||||
|
||||
<div v-show="sideStatus" class="module module-right-far module-vertical">
|
||||
<div
|
||||
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
|
||||
>
|
||||
版权伦理意识
|
||||
</div>
|
||||
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
|
||||
</div>
|
||||
|
||||
<!-- 画面构图 -->
|
||||
<ImgButton
|
||||
v-show="!sideStatus"
|
||||
@click="handleClick"
|
||||
class="absolute top-[38%] left-[23%] z-10"
|
||||
:image="selectedImage"
|
||||
/>
|
||||
|
||||
<!-- 景别 -->
|
||||
<ImgButton v-show="!sideStatus" class="absolute top-[15%] left-[33%] z-10" image="skill/景别" />
|
||||
|
||||
<!-- 返回 -->
|
||||
<ImgButton
|
||||
class="absolute right-0 top-0"
|
||||
:image="IMAGE_PATHS.COMPONENTS.BACK"
|
||||
@click="handleClose"
|
||||
/>
|
||||
|
||||
<!-- 树 -->
|
||||
<div
|
||||
class="absolute top-28 left-[calc(50%-30px)] -translate-x-1/2 w-[786px] h-[875px] bg-cover bg-center bg-no-repeat"
|
||||
:style="{
|
||||
backgroundImage: status
|
||||
? getBackgroundImage('skill/技能树-亮')
|
||||
: getBackgroundImage('skill/技能树-灰')
|
||||
}"
|
||||
></div>
|
||||
|
||||
<div class="absolute bottom-28 left-1/2 -translate-x-1/2">
|
||||
<span class="blue-text tracking-[18px] text-5xl">
|
||||
{{ !sideStatus ? '技能树-vlog' : '技能树-新手启航' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="absolute bottom-10 left-1/2 -translate-x-1/2">
|
||||
<span class="red-text text-4xl">{{
|
||||
status ? '当前尚未收集任何知识点,快去学习收集知识点吧' : '当前已全部解锁'
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<!-- 引导与高亮 -->
|
||||
<GuideSteps
|
||||
v-if="status"
|
||||
:steps="steps"
|
||||
:highlight-selector="currentHighlight"
|
||||
:highlight-padding="12"
|
||||
:highlight-radius="20"
|
||||
@step-change="handleStepChange"
|
||||
position-offset-y="85%"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 强发光蓝绿主标题(图2风格) */
|
||||
.blue-text {
|
||||
/* 文字本体采用蓝绿渐变并保持白色高亮视觉 */
|
||||
background: linear-gradient(180deg, #cfffff 0%, #9ff3ff 40%, #6ee7ff 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
/* 多层发光,柔边外扩 */
|
||||
text-shadow:
|
||||
0 0 2px rgba(255, 255, 255, 0.9),
|
||||
0 0 6px rgba(79, 241, 255, 0.9),
|
||||
0 0 14px rgba(79, 241, 255, 0.8),
|
||||
0 0 28px rgba(0, 199, 255, 0.6),
|
||||
0 0 46px rgba(0, 199, 255, 0.45);
|
||||
}
|
||||
|
||||
/* 强发光白粉副标题(图2风格) */
|
||||
.red-text {
|
||||
background: linear-gradient(180deg, #ffffff 0%, #ffe9e9 55%, #ffd1d1 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
text-shadow:
|
||||
0 0 2px rgba(255, 255, 255, 0.9),
|
||||
0 0 8px rgba(255, 135, 135, 0.85),
|
||||
0 0 18px rgba(255, 135, 135, 0.65),
|
||||
0 0 32px rgba(255, 110, 110, 0.55);
|
||||
}
|
||||
|
||||
/* 模块标签基础样式 */
|
||||
.module {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 竖排布局 */
|
||||
.module-vertical {
|
||||
cursor: pointer;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.module-vertical .module-text {
|
||||
writing-mode: vertical-rl;
|
||||
text-orientation: upright;
|
||||
}
|
||||
.module-vertical .module-percent {
|
||||
transform: translateY(6px);
|
||||
}
|
||||
|
||||
.module-text {
|
||||
/* color: rgba(150, 150, 150, 0.9); */
|
||||
font-size: 36px;
|
||||
letter-spacing: 8px;
|
||||
}
|
||||
|
||||
.module-percent {
|
||||
color: #ffffff;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
/* 位置近似图2布局 */
|
||||
.module-left-bottom {
|
||||
left: 10%;
|
||||
bottom: 22%;
|
||||
}
|
||||
|
||||
.module-left-middle {
|
||||
left: 25%;
|
||||
top: 48%;
|
||||
}
|
||||
|
||||
.module-right-middle {
|
||||
right: 26%;
|
||||
top: 52%;
|
||||
}
|
||||
|
||||
.module-right-upper {
|
||||
right: 18%;
|
||||
top: 42%;
|
||||
}
|
||||
|
||||
.module-right-far {
|
||||
right: 8%;
|
||||
top: 50%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import ImgButton from '@/components/Button/ImgButton.vue'
|
||||
import { IMAGE_PATHS } from '@/utils'
|
||||
import six from '/video/新手导航_九种构图法.mp4'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const videoRef = ref()
|
||||
|
||||
const handleClose = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
const handlePlay = () => {
|
||||
if (!videoRef.value) return
|
||||
videoRef.value.muted = false
|
||||
videoRef.value.volume = 1
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full relative bg-white/10" @click="handlePlay">
|
||||
<!-- 返回 -->
|
||||
<ImgButton
|
||||
class="absolute right-0 top-0 z-10"
|
||||
:image="IMAGE_PATHS.COMPONENTS.BACK"
|
||||
@click="handleClose"
|
||||
/>
|
||||
|
||||
<video ref="videoRef" :src="six" controls></video>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* 核心:保持视频比例,多余部分被裁剪 */
|
||||
object-fit: cover;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user