feat: 完善访谈与vlog模块页面,重组设备与图片公共资源,新增音频管理与一班对接工具

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.7 committed 2026-05-05 15:41:41 +08:00
1 parent c4c9be9d35
commit fc9633f371
159 files changed
+4823 -2535

No files matched your search

@@ -1,7 +1,7 @@
<script lang="tsx" setup>
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import { GuideSteps, GuideStepsItem, type GuideStep } from '@/components/Guide'
import { ref, computed } from 'vue'
import { getBackgroundImage, getPublicPath, getStaticImage, IMAGE_PATHS } from '@/utils'
import { GuideSteps } from '@/components/Guide'
import { onBeforeUnmount, ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import { ImgButton } from '@/components/Button'
@@ -11,39 +11,102 @@ const back = () => {
// 跳转设备准备
router.back()
}
const steps = [
{ id: 'step1', content: '先认识 Vlog:点击右侧「1.vlog初识」继续' },
{ id: 'step2', content: '这是主要内容区域的边框' }
]
const stepIndex = ref(0)
const steps = ref([
{
id: 'step1',
content:
'设备准备妥当后,我们就该走进真实场景,开启实地取景的环节啦,一起去捕捉那些适合拍摄的画面吧!',
audioSrc: getPublicPath('audio/py_2_013.MP3')
}
])
const showGuide = ref(false)
const guideTriggered = ref(false)
const guideTimer = ref<ReturnType<typeof setTimeout> | null>(null)
const viewedMenuKeys = ref<Set<string>>(new Set())
const hiddenbar = ref(false)
const currentIndex = ref(0) // 当前显示的图片索引
const selectedMenuIndex = ref(0) // 当前选中的菜单项索引
// 菜单项数据
const menuItems = ref([
{ id: 'phone', name: '手机', disabled: false },
{ id: 'phone-stand', name: '手机支架', disabled: true },
{ id: 'bluetooth-remote', name: '蓝牙遥控器', disabled: true },
{ id: 'stabilizer', name: '稳定器', disabled: true },
{ id: 'props', name: '常用道具', disabled: true },
{ id: 'phone-lens', name: '手机辅助箱头', disabled: true }
type EquipmentCategoryId = 'phone' | 'phone-stabilizer' | 'wireless-lavalier-mic'
interface EquipmentProduct {
img: string
}
interface EquipmentCategory {
id: EquipmentCategoryId
name: string
disabled: boolean
titleImg: string
contentImg: string
products: EquipmentProduct[]
}
const categories = ref<EquipmentCategory[]>([
{
id: 'phone',
name: '手机',
disabled: false,
titleImg: getStaticImage('equipment/标题-苹果.png'),
contentImg: getStaticImage('equipment/内容-苹果.png'),
products: [
{ img: getStaticImage('equipment/设备-手机1.png') },
{ img: getStaticImage('equipment/设备-手机2.png') }
]
},
{
id: 'phone-stabilizer',
name: '手机稳定器',
disabled: false,
titleImg: getStaticImage('equipment/手机稳定器标题.png'),
contentImg: getStaticImage('equipment/手机稳定器图文.png'),
products: [{ img: getStaticImage('equipment/手机稳定器.png') }]
},
{
id: 'wireless-lavalier-mic',
name: '无线领夹麦克风',
disabled: false,
titleImg: getStaticImage('equipment/无线领夹麦克风标题.png'),
contentImg: getStaticImage('equipment/无线领夹麦克风图文.png'),
products: [{ img: getStaticImage('equipment/无线领夹麦克风.png') }]
}
])
const phoneList = ref([
{ phoneImg: getStaticImage('equipment/设备-手机1.png') },
{ phoneImg: getStaticImage('equipment/设备-手机2.png') }
])
categories.value = categories.value.map(c => ({
...c,
disabled: (c.products?.length ?? 0) === 0
}))
const platetitleList = ref([
{ title: getStaticImage('equipment/标题-苹果.png') },
{ title: getStaticImage('equipment/标题-安卓小米.png') }
])
// 默认选中的菜单也算作已查看
if (categories.value[0] && !categories.value[0].disabled) {
viewedMenuKeys.value.add(categories.value[0].id)
}
const platetextList = ref([
{ text: getStaticImage('equipment/内容-苹果.png') },
{ text: getStaticImage('equipment/内容-安卓小米.png') }
])
const maybeTriggerGuide = () => {
if (guideTriggered.value) return
const enabledIds = categories.value.filter(c => !c.disabled).map(c => c.id)
if (enabledIds.length === 0) return
const allViewed = enabledIds.every(id => viewedMenuKeys.value.has(id))
if (!allViewed) return
guideTriggered.value = true
guideTimer.value = setTimeout(() => {
showGuide.value = true
guideTimer.value = null
}, 3000)
}
onBeforeUnmount(() => {
if (guideTimer.value) {
clearTimeout(guideTimer.value)
guideTimer.value = null
}
})
const currentCategory = computed(
() => categories.value[selectedMenuIndex.value] ?? categories.value[0]
)
const currentProducts = computed(() => currentCategory.value?.products ?? [])
const currentTitleImg = computed(() => currentCategory.value?.titleImg ?? '')
const currentContentImg = computed(() => currentCategory.value?.contentImg ?? '')
const hiddenbarclick = () => {
hiddenbar.value = !hiddenbar.value
}
@@ -51,15 +114,17 @@ const hiddenbarclick = () => {
// 选择菜单项
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
viewedMenuKeys.value.add(item.id)
maybeTriggerGuide()
}
// 下一张图片
const nextPhone = () => {
if (currentIndex.value < phoneList.value.length - 1) {
if (currentIndex.value < currentProducts.value.length - 1) {
currentIndex.value++
}
}
@@ -70,17 +135,9 @@ const prevPhone = () => {
currentIndex.value--
}
}
const handleStepChange = (_step: GuideStep | null, index: number) => {
stepIndex.value = index
}
const currentHighlight = computed(() =>
stepIndex.value === 0 ? '.img-switch-item--vlog' : '.work-border'
)
</script>
<template>
<div class="equipment-index">
<div class="equipment-index overflow-hidden">
<!-- 背景图片 -->
<div
class="absolute inset-0 bg-cover bg-center bg-no-repeat equipment-bg"
@@ -93,7 +150,7 @@ const currentHighlight = computed(() =>
<div class="equipment-item" :hidden="hiddenbar">
<div class="menu-list">
<div
v-for="(item, index) in menuItems"
v-for="(item, index) in categories"
:key="item.id"
class="menu-item"
:class="{
@@ -118,7 +175,10 @@ const currentHighlight = computed(() =>
<div class="equipment-bt">
<img src="@/assets/images/equipment/按钮选中-设备准备.png" alt="" />
</div>
<div :class="hiddenbar ? 'equipment-unfold1' : 'equipment-unfold2'" @click="hiddenbarclick()">
<div
:class="['cursor-pointer', hiddenbar ? 'equipment-unfold1' : 'equipment-unfold2']"
@click="hiddenbarclick()"
>
<img
:src="
hiddenbar
@@ -139,12 +199,12 @@ const currentHighlight = computed(() =>
<img src="@/assets/images/equipment/按钮-左滑.png" alt="" />
</div>
<div class="equipment-phoneImg">
<img :src="phoneList[currentIndex].phoneImg" alt="" />
<img :src="currentProducts[currentIndex]?.img" alt="" />
</div>
<div
class="equipment-rightbutton"
@click="nextPhone"
:style="{ visibility: currentIndex < phoneList.length - 1 ? 'visible' : 'hidden' }"
:style="{ visibility: currentIndex < currentProducts.length - 1 ? 'visible' : 'hidden' }"
>
<img src="@/assets/images/equipment/按钮-右滑.png" alt="" />
</div>
@@ -155,11 +215,11 @@ const currentHighlight = computed(() =>
</div>
<div class="title">
<img :src="platetitleList[currentIndex].title" alt="" />
<img :src="currentTitleImg" alt="" />
</div>
<div class="plate-content">
<div class="text">
<img :src="platetextList[currentIndex].text" alt="" />
<img :src="currentContentImg" alt="" />
</div>
</div>
</div>
@@ -175,17 +235,12 @@ const currentHighlight = computed(() =>
<!-- 引导步骤 -->
<GuideSteps
:visible="showGuide"
:steps="steps"
:highlight-selector="currentHighlight"
:highlight-padding="12"
:highlight-radius="20"
@step-change="handleStepChange"
position-offset-y="85%"
>
<GuideStepsItem>
<img src="@/assets/images/equipment/设备准备引导1.png" alt="" />
</GuideStepsItem>
</GuideSteps>
/>
</div>
</template>
<style lang="less" scoped>