Files
super_video/src/views/interview/midterm-shooting/equipment/index.vue
T
zhongyidianandClaude Opus 4.7 6f8252472f feat: 完善模块引导与学习进度体验
统一引导提示的持久化控制,补充学习进度入口与模块资源,避免用户返回页面时重复触发提示。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:44:59 +08:00

514 lines
12 KiB
Vue

<script lang="tsx" setup>
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import { GuideSteps, GuideStepsItem } from '@/components/Guide'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ImgButton } from '@/components/Button'
const router = useRouter()
const back = () => {
// 跳转设备准备
router.back()
}
const steps = [
{
id: 'step1',
content: '先认识 Vlog:点击右侧「1.vlog初识」继续',
highlightSelector: '.img-switch-item--vlog'
},
{
id: 'step2',
content: '这是主要内容区域的边框',
highlightSelector: '.work-border'
}
]
const hiddenbar = ref(false)
const currentIndex = ref(0)
const selectedMenuIndex = ref(0)
const equipmentItems = [
{
id: 'camera',
name: '相机 / 摄像机 / 微单',
productImages: [
getStaticImage('equipment/相机产品.png'),
getStaticImage('equipment/摄像机产品.png'),
getStaticImage('equipment/微单产品.png')
],
title: getStaticImage('equipment/相机标题.png'),
text: getStaticImage('equipment/相机内容.png')
},
{
id: 'tripod',
name: '三脚架',
productImages: [getStaticImage('equipment/三角架产品.png')],
title: getStaticImage('equipment/三脚架标题.png'),
text: getStaticImage('equipment/三脚架内容.png')
},
{
id: 'light',
name: '灯光',
productImages: [
getStaticImage('equipment/led补光灯.png'),
getStaticImage('equipment/环形灯产品.png')
],
title: getStaticImage('equipment/灯标题.png'),
text: getStaticImage('equipment/灯内容.png')
}
]
const menuItems = ref(
equipmentItems.map(item => ({ id: item.id, name: item.name, disabled: false }))
)
const currentEquipment = computed(() => equipmentItems[selectedMenuIndex.value])
const currentProductImages = computed(() => currentEquipment.value.productImages)
const hiddenbarclick = () => {
hiddenbar.value = !hiddenbar.value
}
// 选择菜单项
const selectMenuItem = (index: number, item: { id: string; name: string; disabled: boolean }) => {
if (item.disabled) {
console.log(`菜单项 "${item.name}" 已被禁用`)
return
}
selectedMenuIndex.value = index
currentIndex.value = 0
}
// 下一张图片
const nextPhone = () => {
if (currentIndex.value < currentProductImages.value.length - 1) {
currentIndex.value++
}
}
// 上一张图片
const prevPhone = () => {
if (currentIndex.value > 0) {
currentIndex.value--
}
}
</script>
<template>
<div class="equipment-index">
<!-- 背景图片 -->
<div
class="absolute inset-0 bg-cover bg-center bg-no-repeat equipment-bg"
:style="{ backgroundImage: getBackgroundImage(IMAGE_PATHS.EQUIPMENT.BG) }"
></div>
<div class="equipment-bar">
<img src="@/assets/images/equipment/侧边导航栏.png" alt="" :hidden="hiddenbar" />
<!-- 内容列表 -->
<div class="equipment-item" :hidden="hiddenbar">
<div class="menu-list">
<div
v-for="(item, index) in menuItems"
:key="item.id"
class="menu-item"
:class="{
'menu-item--active': selectedMenuIndex === index,
'menu-item--disabled': item.disabled
}"
@click="selectMenuItem(index, item)"
>
<div
class="menu-item__indicator"
v-if="selectedMenuIndex === index && !item.disabled"
></div>
<span class="menu-item__text">{{ item.name }}</span>
<div class="menu-item__status" v-if="item.disabled">
<!-- <span class="status-text">未解锁</span> -->
</div>
</div>
</div>
</div>
<!-- 设备准备按钮 -->
<div class="equipment-bt">
<img src="@/assets/images/equipment/按钮选中-设备准备.png" alt="" />
</div>
<div :class="hiddenbar ? 'equipment-unfold1' : 'equipment-unfold2'" @click="hiddenbarclick()">
<img
:src="
hiddenbar
? getStaticImage('equipment/按钮-展开.png')
: getStaticImage('equipment/按钮-收缩.png')
"
alt=""
/>
</div>
</div>
<div class="equipment-layout">
<div class="equipment-home">
<div
class="equipment-leftbutton"
@click="prevPhone"
:style="{ visibility: currentIndex > 0 ? 'visible' : 'hidden' }"
>
<img src="@/assets/images/equipment/按钮-左滑.png" alt="" />
</div>
<div class="equipment-phoneImg">
<img :src="currentProductImages[currentIndex]" alt="" />
</div>
<div
class="equipment-rightbutton"
@click="nextPhone"
:style="{
visibility: currentIndex < currentProductImages.length - 1 ? 'visible' : 'hidden'
}"
>
<img src="@/assets/images/equipment/按钮-右滑.png" alt="" />
</div>
</div>
<div class="equipment-purpose">
<div class="plate">
<img src="@/assets/images/equipment/浮空屏.png" alt="" />
</div>
<div class="title">
<img :src="currentEquipment.title" alt="" />
</div>
<div class="plate-content">
<div class="text">
<img :src="currentEquipment.text" alt="" />
</div>
</div>
</div>
</div>
<ImgButton class="absolute right-0 top-0" :image="IMAGE_PATHS.COMPONENTS.BACK" @click="back" />
<!-- 调试按钮组 -->
<!-- <div class="debug-controls">
<button @click="enableAllMenuItems" class="debug-btn">启用全部</button>
<button @click="disableAllMenuItems" class="debug-btn">禁用全部</button>
<button @click="toggleMenuItem('bluetooth-remote')" class="debug-btn">切换蓝牙遥控器</button>
</div> -->
</div>
</template>
<style lang="less" scoped>
.equipment-index {
position: relative;
width: 100%;
height: 100%;
}
.equipment-layout {
position: relative;
width: 100%;
height: 100%;
}
.equipment-bar {
position: absolute;
top: 0;
left: 0;
z-index: 10;
.equipment-bt {
position: absolute;
top: 0;
left: -135px;
width: 577px;
img {
width: 100%;
height: 100%;
}
}
.equipment-unfold1 {
position: absolute;
top: 490px;
left: -41px;
width: 150px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.equipment-unfold2 {
position: absolute;
top: 490px;
left: 268px;
width: 150px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.equipment-item {
position: absolute;
top: 0;
left: 0;
padding-top: 220px;
padding-left: 20px;
.menu-list {
display: flex;
flex-direction: column;
gap: 8px;
//background: linear-gradient(135deg, #1a2a4a 0%, #0f1a2e 100%);
border-radius: 12px;
padding: 16px 12px;
// box-shadow:
// 0 0 20px rgba(64, 150, 255, 0.3),
// inset 0 0 20px rgba(64, 150, 255, 0.1);
// backdrop-filter: blur(10px);
}
.menu-item {
position: relative;
display: flex;
align-items: center;
padding: 24px 32px;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
min-height: 44px;
&:hover {
// background: rgba(64, 150, 255, 0.1);
transform: translateX(4px);
}
&--active {
// background: rgba(64, 150, 255, 0.2);
// box-shadow: 0 0 15px rgba(64, 150, 255, 0.4);
.menu-item__text {
color: #ffffff;
text-shadow:
0 0 10px rgba(64, 150, 255, 0.8),
0 0 20px rgba(64, 150, 255, 0.6),
0 0 30px rgba(64, 150, 255, 0.4);
font-weight: 600;
}
}
&__indicator {
position: absolute;
left: 0px;
top: 45%;
transform: translateY(-50%);
width: 6px;
height: 38px;
background: #ffffff;
border-radius: 2px;
box-shadow: 0 0 16px rgba(255, 255, 255, 0.8);
}
&__text {
color: #64a5ff;
font-size: 30px;
font-weight: 800;
text-shadow: 0 0 8px rgba(64, 150, 255, 0.6);
transition: all 0.3s ease;
user-select: none;
}
&__status {
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
.status-text {
font-size: 12px;
color: #999;
background: rgba(0, 0, 0, 0.6);
padding: 2px 8px;
border-radius: 4px;
border: 1px solid #333;
}
}
// 禁用状态样式
&--disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: auto; // 保持可点击以显示禁用提示
&:hover {
transform: none;
// background: rgba(255, 0, 0, 0.1);
}
.menu-item__text {
color: #666;
text-shadow: none;
}
.menu-item__indicator {
display: none;
}
}
}
}
.guide-ui {
top: 80% !important;
}
.dragon-character {
top: 80% !important;
}
}
.equipment-home {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.equipment-leftbutton {
position: absolute;
top: 511px;
left: 350px;
width: 200px;
height: 200px;
cursor: pointer;
z-index: 10;
}
.equipment-phoneImg {
position: absolute;
top: 313px;
left: 500px;
width: 446px;
height: 484px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.equipment-rightbutton {
position: absolute;
top: 511px;
right: 770px;
width: 200px;
height: 200px;
cursor: pointer;
z-index: 10;
}
}
.equipment-purpose {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.plate {
position: absolute;
top: 30px;
left: 1200px;
width: 600px;
/* 调整为你需要的宽度 */
height: 1000px;
/* 调整为你需要的高度 */
img {
width: 100%;
height: 100%;
}
}
.plate-content {
position: absolute;
top: 144px;
right: 100px;
width: 600px;
height: 797px;
overflow: hidden;
/* 隐藏超出部分 */
object-fit: contain;
// display: flex;
flex-direction: column;
align-items: center;
overflow-y: auto;
/* 允许垂直滚动 */
scrollbar-width: none;
/* Firefox隐藏滚动条 */
-ms-overflow-style: none;
/* IE和Edge隐藏滚动条 */
perspective: 1000px;
&::-webkit-scrollbar {
display: none;
/* Chrome, Safari隐藏滚动条 */
}
}
.title {
// margin-top: 47px;
width: 400px;
z-index: 2;
position: absolute;
top: 36px;
left: 1304px;
}
.text {
position: absolute;
top: -9px;
left: 8px;
z-index: 2;
transform: rotate3d(0, 1, 0, -20deg);
img {
width: 100%;
height: auto;
}
}
}
// 调试控制按钮样式
.debug-controls {
position: absolute;
top: 20px;
left: 20px;
display: flex;
flex-direction: column;
gap: 8px;
z-index: 1000;
.debug-btn {
background: rgba(0, 0, 0, 0.8);
color: white;
border: 1px solid #333;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
transition: background 0.3s ease;
&:hover {
background: rgba(0, 0, 0, 0.9);
}
}
}
</style>