chore: bypass pre-commit for now

This commit is contained in:
zhongyingmin committed 2025-09-26 00:11:15 +08:00
1 parent 10e97670a5
commit c4ba322e32
76 files changed
+2253 -218

No files matched your search

+172
View File
@@ -0,0 +1,172 @@
<script lang="ts" setup>
import router from '@/router'
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import { ImgButton } from '@/components/Button'
import { Overlay } from '@/components/Overlay'
import { computed, ref } from 'vue'
const selected = ref<number | undefined>()
const showColorBar = ref(false)
const btnState = ref(false)
const screenshot = ref()
const showModal = ref(false)
const colorBarList = ref([
{
id: 1,
name: '智能调色',
image: getStaticImage('afterditing/color/智能调色.png'),
Screenshot: getStaticImage('afterditing/color/卡片-智能调色.png')
},
{
id: 2,
name: '滤镜-冬日物语',
image: getStaticImage('afterditing/color/冬日物语.jpg'),
Screenshot: getStaticImage('afterditing/color/卡片-冬日物语.png')
},
{
id: 3,
name: '滤镜-日落电影',
image: getStaticImage('afterditing/color/落日余晖.jpg'),
Screenshot: getStaticImage('afterditing/color/卡片-落日余晖.png')
}
])
const selectedImage = computed(() => {
return !btnState.value && colorBarList.value.find(v => v.id === selected.value)?.image
})
const changeOriginalImgae = () => {
btnState.value = !btnState.value
}
const handleSave = () => {
screenshot.value = colorBarList.value.find(v => v.id === selected.value)?.Screenshot
showModal.value = true
}
const handleModalClose = () => {
showModal.value = false
screenshot.value = null
}
const handleTryOther = () => {
showModal.value = false
}
const handleFinish = () => {
router.push({
name: 'afterditing',
query: { step: 4 }
})
}
const handleClose = () => {
router.back()
}
const changeColor = (item: { id: number; name: string }) => {
selected.value = item.id
}
</script>
<template>
<div class="w-full h-full relative">
<!-- 返回 -->
<ImgButton
class="absolute right-0 top-0 z-10"
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleClose"
/>
<!-- 背景图片-center -->
<div
class="absolute inset-0 bg-cover bg-center bg-no-repeat"
:style="{
backgroundImage: `url(${selectedImage || getStaticImage('afterditing/color/原图')})`
}"
></div>
<!-- 分段控制器 -->
<div class="absolute top-10 left-1/2 transform -translate-x-1/2 z-20" v-if="!showColorBar">
<div
class="flex justify-between w-[800px] bg-white/60 backdrop-blur-sm border-[3px] border-white rounded-[50px] px-4 py-4 text-xl font-bold tracking-[4px]"
>
<!-- 后期制作选项 -->
<button :class="['px-12 py-3 rounded-[50px] bg-teal-500 text-white shadow-lg']">
后期制作
</button>
<!-- 智能调色和滤镜选项 -->
<button :class="['px-4 rounded-[50px] text-[#2F5A84] text-2xl']">智能调色和滤镜</button>
</div>
</div>
<!-- title -->
<div
class="absolute top-0 left-0 w-[332px] h-[153px] bg-cover bg-center bg-no-repeat"
:style="{
backgroundImage: showColorBar
? getBackgroundImage('afterditing/color/标题-调色实践')
: getBackgroundImage('afterditing/color/标题-调色')
}"
></div>
<!-- 调色栏 -->
<div class="absolute bottom-0 flex justify-center w-full" v-if="showColorBar">
<div class="flex">
<div
v-for="item in colorBarList"
:key="item.id"
:style="{
backgroundImage:
selected == item.id
? getBackgroundImage('afterditing/color/按钮-调色选中')
: getBackgroundImage('afterditing/color/按钮-调色未选中')
}"
class="w-[449px] h-[170px] text-white text-3xl font-bold flex items-center justify-center cursor-pointer bg-no-repeat bg-cover"
@click="changeColor(item)"
>
<span>{{ item.name }}</span>
</div>
</div>
<ImgButton
class="flex-[0_0_200px]"
@click="changeOriginalImgae"
:image="
btnState ? 'afterditing/color/开启对比 - 可开启' : 'afterditing/color/开启对比 - 不可开启'
"
></ImgButton>
</div>
<!-- 保存 -->
<ImgButton
v-if="selected"
class="absolute right-0 top-1/2 -translate-y-1/2 z-10"
image="afterditing/color/按钮-保存"
@click="handleSave"
/>
<!-- 调色栏显示隐藏按钮 -->
<ImgButton
v-if="!showColorBar"
class="absolute bottom-0 right-0"
image="afterditing/color/调色实践"
@click="showColorBar = true"
></ImgButton>
<!-- 保存图片弹窗 -->
<Overlay :visible="showModal" @close="handleModalClose">
<div class="relative w-[1000px] h-[600px] flex items-center justify-center">
<img :src="screenshot" alt="调色结果" class="max-w-full max-h-full object-contain" />
<!-- 操作按钮 -->
<div class="absolute bottom-1/2 -left-1/3 translate-y-1/2">
<ImgButton image="afterditing/color/按钮-试试其他调色" @click="handleTryOther" />
</div>
<div class="absolute bottom-1/2 -right-1/3 translate-y-1/2">
<ImgButton image="afterditing/color/按钮-结束调色实践" @click="handleFinish" />
</div>
</div>
</Overlay>
</div>
</template>
+15 -9
View File
@@ -1,17 +1,19 @@
<script lang="tsx" setup>
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import { ImgButton } from '@/components/Button'
import { ref } from 'vue'
import { onMounted, ref } from 'vue'
import { ProgressBar } from '@/components'
import { useRouter } from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const currentStep = ref(1)
const currentPage = ref(2)
const route = useRoute()
// 当前步骤
const currentStep = ref(3)
const highlightShow = ref(true)
const handleComplete = () => {
console.log('完成前置条件')
window.open('http://101.132.152.157/dspdr/vlog.html', '_self')
}
const handleStepChange = (step: number) => {
@@ -27,6 +29,11 @@ const navigateTo = (routeName: string) => {
console.log('任务取景按钮点击')
router.push({ name: routeName })
}
onMounted(() => {
// 页面加载时的逻辑
currentStep.value = Number(route.query.step) || 3
})
</script>
<template>
@@ -58,7 +65,7 @@ const navigateTo = (routeName: string) => {
<!-- 中期拍摄底板 -->
<div v-if="highlightShow" class="absolute right-90 ml-[135px]" style="z-index: 998">
<ImgButton :image="IMAGE_PATHS.AFTEREDITING.MIDTERM" />
<img :src="getStaticImage(IMAGE_PATHS.AFTEREDITING.MIDTERM)" />
</div>
<!-- 进度百分比 -->
@@ -77,7 +84,7 @@ const navigateTo = (routeName: string) => {
<!-- 后期准备按钮文字 -->
<div
v-if="highlightShow"
class="absolute left-[21%] top-[9%] -translate-x-1/2"
class="absolute left-[21%] top-[9%] -translate-x-1/2 space-y-[-30px]"
style="z-index: 998; margin-top: 120px"
>
<ImgButton
@@ -87,7 +94,7 @@ const navigateTo = (routeName: string) => {
/>
<ImgButton
:image="IMAGE_PATHS.AFTEREDITING.ADJUSTMENTCOLOR"
@click="navigateTo('adjustmentColor')"
@click="navigateTo('Color')"
class="ml-[40px]"
/>
</div>
@@ -115,7 +122,6 @@ const navigateTo = (routeName: string) => {
:current-step="currentStep"
@complete="handleComplete"
@step-change="handleStepChange"
:current-page="currentPage"
/>
</div>
</div>
+1 -1
View File
@@ -90,7 +90,7 @@ onMounted(() => {
<!-- 电视机 -->
<div
class="absolute w-[765px] h-[768px] right-0 top-0 z-[5] transition-opacity duration-200 cursor-pointer"
class="absolute w-[765px] h-[768px] right-0 top-0 z-[5] transition-all duration-300 hover:scale-105 hover:brightness-110 cursor-pointer"
:class="{ 'opacity-50': isImageLoading }"
:style="{ backgroundImage: selectedImage }"
@click.stop="handleClick"
@@ -1,7 +1,11 @@
<template>
<div
:style="{ backgroundImage: getBackgroundImage(currentImage) }"
:class="['module-btn', module.className, { selected: isSelected }]"
:class="[
'module-btn transition-all duration-300 hover:scale-105 hover:brightness-110',
module.className,
{ selected: isSelected }
]"
>
<div :class="['btn-mask', module.maskConfig.className]" @click="$emit('click')"></div>
</div>
@@ -54,7 +58,7 @@ const currentImage = computed(() => {
transition:
transform 0.2s ease,
z-index 0.2s ease;
z-index: 1;
z-index: 8;
pointer-events: none;
}
@@ -72,7 +72,14 @@ const moduleConfigs: ModuleConfig[] = [
selectedImage: IMAGE_PATHS.ACTION.SELECTED_BTN2,
className: 'w-[1087px] h-[822px] left-[calc(50%+50px)] -translate-x-1/2 -bottom-4',
maskConfig: {
className: 'left-[16em] bottom-[50px] w-[500px] h-[100px]',
/**
* width: 200px;
height: 173px;
background-color: #fbbf24;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
*/
className:
'left-[6em] bottom-[60px] w-[850px] h-[153px] bg-transparent [clip-path:polygon(50%_0%,_0%_100%,_100%_100%)]',
position: 'left-[16em] bottom-[50px]',
size: 'w-[500px] h-[100px]',
transform: ''
@@ -84,7 +91,7 @@ const moduleConfigs: ModuleConfig[] = [
selectedImage: IMAGE_PATHS.ACTION.SELECTED_BTN3,
className: 'w-[943px] h-[822px] right-[320px] -bottom-4',
maskConfig: {
className: 'right-[0em] bottom-[200px] w-[420px] h-[100px] rotate-[15deg]',
className: 'right-[0em] bottom-[100px] w-[520px] h-[400px] rotate-[19deg]',
position: 'right-[0em] bottom-[200px]',
size: 'w-[420px] h-[100px]',
transform: 'rotate-[15deg]'
+286 -83
View File
@@ -4,89 +4,109 @@
<div
class="absolute inset-0 bg-cover bg-center bg-no-repeat equipment-bg"
:style="{ backgroundImage: getBackgroundImage(IMAGE_PATHS.EQUIPMENT.BG) }"
>
<div class="equipment-bar">
<img src="@/assets/images/equipment/侧边导航栏.png" alt="" :hidden="hiddenbar" />
<div class="equipment-item" :hidden="hiddenbar">
<span>
<img src="@/assets/images/equipment/选中按钮.png" alt="" />
<img src="@/assets/images/equipment/手机-亮.png" alt="" />
</span>
<div>
<img src="@/assets/images/equipment/设备列表合图.png" alt="" />
</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="phoneList[currentIndex].phoneImg" alt="" />
</div>
<div
class="equipment-rightbutton"
@click="nextPhone"
:style="{ visibility: currentIndex < phoneList.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>
<div class="title">
<img :src="platetitleList[currentIndex].title" alt="" />
</div>
<div class="plate-content">
<div class="text">
<img :src="platetextList[currentIndex].text" alt="" />
<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="shooting-return">
<img src="@/assets/images/shooting/返回.png" alt="" @click="back" />
</div>
<!-- 引导步骤 -->
<GuideSteps
: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 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="phoneList[currentIndex].phoneImg" alt="" />
</div>
<div
class="equipment-rightbutton"
@click="nextPhone"
:style="{ visibility: currentIndex < phoneList.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="platetitleList[currentIndex].title" alt="" />
</div>
<div class="plate-content">
<div class="text">
<img :src="platetextList[currentIndex].text" alt="" />
</div>
</div>
</div>
</div>
<div class="absolute right-0 top-0">
<img src="@/assets/images/shooting/返回.png" alt="" @click="back" />
</div>
<!-- 调试按钮组 -->
<!-- <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> -->
<!-- 引导步骤 -->
<GuideSteps
: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>
<script lang="tsx" setup>
@@ -108,6 +128,17 @@ const steps = [
const stepIndex = ref(0)
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 }
])
const phoneList = ref([
{ phoneImg: getStaticImage('equipment/设备-手机1.png') },
@@ -127,6 +158,58 @@ 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
}
// 启用菜单项
const enableMenuItem = (id: string) => {
const item = menuItems.value.find(item => item.id === id)
if (item) {
item.disabled = false
console.log(`菜单项 "${item.name}" 已启用`)
}
}
// 禁用菜单项
const disableMenuItem = (id: string) => {
const item = menuItems.value.find(item => item.id === id)
if (item) {
item.disabled = true
console.log(`菜单项 "${item.name}" 已禁用`)
}
}
// 切换菜单项状态
const toggleMenuItem = (id: string) => {
const item = menuItems.value.find(item => item.id === id)
if (item) {
item.disabled = !item.disabled
console.log(`菜单项 "${item.name}" 状态已切换为: ${item.disabled ? '禁用' : '启用'}`)
}
}
// 启用所有菜单项
const enableAllMenuItems = () => {
menuItems.value.forEach(item => {
item.disabled = false
})
console.log('所有菜单项已启用')
}
// 禁用所有菜单项
const disableAllMenuItems = () => {
menuItems.value.forEach(item => {
item.disabled = true
})
console.log('所有菜单项已禁用')
}
// 下一张图片
const nextPhone = () => {
if (currentIndex.value < phoneList.value.length - 1) {
@@ -156,14 +239,11 @@ const currentHighlight = computed(() =>
</script>
<style lang="less">
.equipment-index {
position: relative;
width: 100%;
height: 100%;
}
.equipment-bg {
// display: flex;
}
.equipment-layout {
position: relative;
width: 100%;
@@ -221,8 +301,105 @@ const currentHighlight = computed(() =>
padding-top: 220px;
padding-left: 20px;
span {
.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;
}
}
}
}
@@ -307,8 +484,8 @@ const currentHighlight = computed(() =>
.plate-content {
position: absolute;
bottom: 144px;
left: 1235px;
top: 144px;
right: 100px;
width: 600px;
height: 797px;
overflow: hidden;
@@ -352,4 +529,30 @@ const currentHighlight = computed(() =>
}
}
}
// 调试控制按钮样式
.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>
+3 -5
View File
@@ -1,5 +1,5 @@
<script lang="tsx" setup>
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import { ImgButton } from '@/components/Button'
import { ref } from 'vue'
@@ -8,7 +8,7 @@ import { useRouter } from 'vue-router'
const router = useRouter()
const currentStep = ref(1)
const currentStep = ref(2)
const handleComplete = () => {
console.log('完成前置条件')
@@ -34,7 +34,6 @@ const shooting = () => {
// 跳转实地取景
router.push({ name: 'shooting' })
}
const currentPage = ref(1)
const highlightShow = ref(true)
</script>
@@ -66,7 +65,7 @@ const highlightShow = ref(true)
</div>
<!-- 中期拍摄底板 -->
<div v-if="highlightShow" class="absolute right-90 ml-[135px]" style="z-index: 998">
<ImgButton :image="IMAGE_PATHS.VLOG.Midterm" />
<img :src="getStaticImage(IMAGE_PATHS.VLOG.Midterm)" />
</div>
<!-- 进度百分比 -->
<div
@@ -116,7 +115,6 @@ const highlightShow = ref(true)
<div class="absolute bottom-0 w-full bright">
<ProgressBar
:current-step="currentStep"
:current-page="currentPage"
@complete="handleComplete"
@step-change="handleStepChange"
/>
+219 -4
View File
@@ -1,9 +1,65 @@
<script lang="ts" setup>
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
import shootingtitle from '@/assets/images/shooting/标题-实地取景.png'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { GuideSteps, GuideStepsItem } from '@/components/Guide'
import { Overlay } from '@/components/Overlay'
import { ImgButton } from '@/components/Button'
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import shootingtitle from '@/assets/images/shooting/标题-实地取景.png'
import videoSrc from '/video/新手导航_九种构图法.mp4'
type Btn = {
key: string
name: string
image: string
desc: string
}
const router = useRouter()
const showModal = ref(false)
const showModal2 = ref(false)
const showModal3 = ref(false)
const currentItem = ref<Btn>({
key: '',
name: '',
image: '',
desc: ''
})
const showBoxLine = ref(false)
const btnList = ref<Btn[]>([
{
key: '1',
name: '居中构图',
image: 'shooting/居中构图底板',
desc: '居中构图就是主体放在画面中心,让画面更稳定主体更突出,拍摄时需避免选取杂乱的背景,可以用大光圈或者长焦距让背景虚化使主体从背景中跳出来适合拍摄单个主体,操作比较简单,非常适合新手使用'
},
{
key: '2',
name: '三分法构图',
image: 'shooting/三分法构图底板',
desc: '三分法构图又称九宫格构图,就是把拍摄主体置于九宫格的任意一条三分位置,三分构图法是比较常见的构图法可以视觉上让整体画面更加生动,使用三分构图法拍摄人像时,尽量占据画面的下2格比例和重心会更协调'
},
{
key: '3',
name: '对角线构图',
image: 'shooting/对角线构图底板',
desc: '对角线构图属于引导线构图的一种,所以也是借助引导线的视觉引导效果来突出强调主体。另外对角线构图在画面中制造出对角线的走向即可。'
}
])
const handleModalClose = () => {
showModal.value = false
}
const handleClick = (item: any) => {
currentItem.value = item
showModal2.value = true
}
const handleClickA = () => {
// 跳转设备准备
router.push({ name: 'filmingLocation-a' })
@@ -37,12 +93,171 @@ const back = () => {
<img src="@/assets/images/shooting/按钮-取景地B.png" alt="" @click="handleClickB" />
</div>
<div class="shooting-composition">
<img src="@/assets/images/shooting/构图指南.png" alt="" />
<img
class="mybutton cursor-pointer"
src="@/assets/images/shooting/构图指南.png"
alt=""
@click="showModal = true"
/>
</div>
</div>
<!-- 引导步骤 -->
<GuideSteps
:highlight-selector="'.mybutton'"
:highlight-padding="12"
:highlight-radius="20"
position-offset-y="70%"
>
<GuideStepsItem> 在走进拍摄场景之前,我们先来查看一下构图指南。 </GuideStepsItem>
</GuideSteps>
<!-- 保存图片弹窗 -->
<Overlay
:visible="showModal"
:clickable="false"
:customStyle="{
backgroundImage: getBackgroundImage('shooting/构图指南底图')
}"
customClass="inset-0 bg-cover bg-center bg-no-repeat"
contentClass="relative w-full h-full"
>
<!-- 返回 -->
<ImgButton
class="absolute right-0 top-0 z-10"
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleModalClose"
/>
<!-- 新手导航视频 -->
<ImgButton
class="absolute left-28 top-[calc(50%-40px)] -translate-y-1/2"
image="shooting/新手导航-视频回顾"
@click="showModal3 = true"
/>
<div class="absolute top-[30%] right-10">
<ImgButton
v-for="item in btnList"
:key="item.key"
:image="item.image"
@click="handleClick(item)"
/>
</div>
<!-- 知识卡片 -->
<Overlay :visible="showModal2" :clickable="false">
<div
class="relative w-[1752px] h-[932px]"
:style="{
backgroundImage: getBackgroundImage('shooting/知识卡片底板')
}"
>
<div
class="absolute top-4 left-1/2 -translate-x-1/2 text-[45px] text-white font-bold tracking-[2px] drop-shadow-[2px_2px_4px_rgba(0,0,139,0.8)]"
>
{{ currentItem.name }}
</div>
<div
class="absolute w-full h-[38px] top-32 left-1/2 -translate-x-1/2 bg-no-repeat bg-center"
:style="{
backgroundImage: getBackgroundImage('shooting/文案1')
}"
></div>
<div
class="absolute w-[191px] h-[131px] top-[30px] left-[120px] bg-no-repeat bg-center"
:style="{
backgroundImage: getBackgroundImage('shooting/示意图-三分法')
}"
></div>
<div class="absolute top-[calc(50%-30px)] left-1/2 -translate-x-1/2 -translate-y-1/2">
<ImgButton
class="absolute right-6 top-6 z-10"
:image="showBoxLine ? 'shooting/辅助线开' : 'shooting/辅助线关'"
@click="showBoxLine = !showBoxLine"
/>
<div class="relative">
<img :src="getStaticImage('shooting/图片待定1')" alt="" />
<!-- 构图辅助线 -->
<div v-if="showBoxLine" class="absolute inset-0 pointer-events-none p-[18px]">
<div class="relative w-full h-full overflow-hidden">
<!-- 居中构图 - 十字线 -->
<div v-if="currentItem.key === '1'" class="absolute inset-0">
<!-- 垂直中心线 -->
<div
class="absolute top-0 left-1/2 w-0.5 h-full bg-white opacity-80 -translate-x-1/2"
></div>
<!-- 水平中心线 -->
<div
class="absolute left-0 top-1/2 w-full h-0.5 bg-white opacity-80 -translate-y-1/2"
></div>
</div>
<!-- 三分法构图 - 九宫格线 -->
<div v-else-if="currentItem.key === '2'" class="absolute inset-0">
<!-- 垂直三分线 -->
<div
class="absolute top-0 left-1/3 w-0.5 h-full bg-white opacity-80 -translate-x-1/2"
></div>
<div
class="absolute top-0 left-2/3 w-0.5 h-full bg-white opacity-80 -translate-x-1/2"
></div>
<!-- 水平三分线 -->
<div
class="absolute left-0 top-1/3 w-full h-0.5 bg-white opacity-80 -translate-y-1/2"
></div>
<div
class="absolute left-0 top-2/3 w-full h-0.5 bg-white opacity-80 -translate-y-1/2"
></div>
</div>
<!-- 对角线构图 - 对角线 -->
<div v-else-if="currentItem.key === '3'" class="absolute inset-0">
<!-- 对角线:从左上到右下 -->
<div class="absolute top-0 left-0 w-full h-full">
<div
class="absolute top-0 left-0 h-0.5 bg-white opacity-80"
style="width: 141.42%; transform: rotate(33deg); transform-origin: left top"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="absolute w-full px-20 bottom-32 left-1/2 -translate-x-1/2 text-[#395E66] text-3xl font-bold indent-14 leading-[50px]"
>
{{ currentItem.desc }}
</div>
<!-- 返回 -->
<ImgButton
class="absolute right-2 top-4 translate-x-1/2 -translate-y-1/2 z-10"
:image="IMAGE_PATHS.COMPONENTS.CLOSE"
@click="showModal2 = false"
/>
</div>
</Overlay>
<!-- 视频 -->
<Overlay :visible="showModal3" :clickable="false">
<video :src="videoSrc" controls></video>
<!-- 返回 -->
<ImgButton
class="absolute right-0 top-0 z-10"
:image="IMAGE_PATHS.COMPONENTS.CLOSE"
@click="showModal3 = false"
/>
</Overlay>
</Overlay>
</div>
</template>
<style lang="less">
<style lang="less" scoped>
.shooting-bg {
position: absolute;
+5 -6
View File
@@ -1,12 +1,12 @@
<script lang="tsx" setup>
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import { ImgButton } from '@/components/Button'
import { ref, computed } from 'vue'
import { ProgressBar } from '@/components'
import { useRouter } from 'vue-router'
import { GuideSteps } from '@/components/Guide'
import { GuideSteps, GuideStepsItem } from '@/components/Guide'
const steps = [
{
id: 'step1',
@@ -87,11 +87,11 @@ const currentPage = ref(0)
class="absolute left-24 top-24"
:style="{ backgroundImage: getBackgroundImage(IMAGE_PATHS.VLOG.TASK_CAMERA) }"
>
<ImgButton :image="IMAGE_PATHS.VLOG.TASK_BTN" @click="handleWorkClick" />
<ImgButton :image="IMAGE_PATHS.VLOG.TASK_BTN_OK" />
</div>
<!-- 前期准备底板 -->
<div v-if="highlightShow" class="absolute right-90 ml-[135px]">
<ImgButton :image="IMAGE_PATHS.VLOG.PREPARE" />
<img :src="getStaticImage(IMAGE_PATHS.VLOG.PREPARE)" />
</div>
<!-- 脚本撰写按钮 -->
<div v-if="highlightShow" class="absolute left-[13%] top-1/3">
@@ -141,7 +141,6 @@ const currentPage = ref(0)
<div class="absolute bottom-0 w-full">
<ProgressBar
:current-step="currentStep"
:current-page="currentPage"
@complete="handleComplete"
@step-change="handleStepChange"
/>
@@ -163,7 +162,7 @@ const currentPage = ref(0)
v-if="highlightShow"
class="absolute right-0 top-0"
style="z-index: 998; cursor: pointer"
@click="highlightShow = false"
@click="router.back()"
>
<img src="@/assets/images/midterm/叉.png" alt="" />
</div>
+2 -9
View File
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { IMAGE_PATHS } from '@/utils'
import { IMAGE_PATHS, getStaticImage } from '@/utils'
import { ImgButton } from '@/components/Button'
import { useRouter } from 'vue-router'
import { ref } from 'vue'
@@ -45,14 +45,7 @@ const hiddenbarclick = () => {
<ImgButton :image="IMAGE_PATHS.VLOG.SCRIPTINGTITLE" />
</div>
<div :class="hiddenbar ? 'writing-unfold1' : 'writing-unfold2'" @click="hiddenbarclick()">
<img
:src="
hiddenbar
? '/src/assets/images/equipment/按钮-展开.png'
: '/src/assets/images/equipment/按钮-收缩.png'
"
alt=""
/>
<ImgButton :image="hiddenbar ? 'equipment/按钮-展开' : 'equipment/按钮-收缩'" />
</div>
</div>
+22 -9
View File
@@ -5,7 +5,7 @@
class="absolute inset-0 bg-cover bg-center bg-no-repeat writing-bg"
:style="{ backgroundImage: getBackgroundImage(IMAGE_PATHS.VLOG.BIAOGEBG) }"
>
<div v-if="showDoubao">
<div>
<div class="writing-title">
<img src="@/assets/images/vlog/标题栏-中间.png" alt="" class="titledibu" />
<img
@@ -26,7 +26,7 @@
</div>
</div>
<div v-else>
<!-- <div v-else>
<div class="writing-title">
<img src="@/assets/images/vlog/标题栏-中间.png" alt="" class="titledibu" />
<img
@@ -46,10 +46,11 @@
<div class="shooting-return">
<img src="@/assets/images/shooting/返回.png" alt="" @click="back" />
</div>
</div>
</div> -->
<!-- 引导步骤 -->
<GuideSteps
v-if="showDoubao"
:steps="steps"
:highlight-selector="currentHighlight"
:highlight-padding="12"
@@ -66,10 +67,12 @@
</div>
</template>
<script lang="tsx" setup>
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
import { GuideSteps, GuideStepsItem } from '@/components/Guide'
import { ref, computed } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ImagePreview } from '@/components'
import { useScale } from '@/composables/useScale'
const router = useRouter()
const showDoubao = ref(false)
const steps = [
@@ -81,9 +84,6 @@ const stepIndex = ref(1)
const back = () => {
router.back()
}
const deletebiaoge = () => {
showDoubao.value = true
}
interface SimpleStep {
id: string
@@ -101,8 +101,21 @@ const currentHighlight = computed(() =>
const clickdoubao = () => {
router.push('midterm')
}
const { scale, offsetX, offsetY } = useScale()
onMounted(() => {
ImagePreview({
images: [getStaticImage('vlog/脚本切图/我的志愿者手记拍摄脚本.png')],
startIndex: 0,
maskClosable: true,
getScaleMetrics: () => ({ scale: scale.value, offsetX: offsetX.value, offsetY: offsetY.value }),
onClose: () => {
showDoubao.value = true
}
})
})
</script>
<style lang="less">
<style lang="less" scoped>
.writing-index {
width: 100%;
height: 100%;
+4 -6
View File
@@ -13,9 +13,10 @@
class="titletext"
/>
</div>
<div class="shooting-return">
<video :src="fourth" controls></video>
<!-- <div class="shooting-return">
<img src="@/assets/images/shooting/返回.png" alt="" @click="back" />
</div>
</div> -->
<!-- 引导步骤 -->
<!-- <GuideSteps :steps="steps" :highlight-selector="currentHighlight" :highlight-padding="12"
:highlight-radius="20" @step-change="handleStepChange" position-offset-y="85%" hidden:false>
@@ -32,16 +33,13 @@ import { GuideSteps, GuideStepsItem } from '@/components/Guide'
import { ref, computed } from 'vue'
import { ImgButton } from '@/components/Button'
import { useRouter } from 'vue-router'
import fourth from '/video/Vlog模块_任务取景框_专业剖析_脚本策划.mp4'
const router = useRouter()
const back = () => {
// 跳转设备准备
router.back()
}
const steps = [
{ id: 'step1', content: '先认识 Vlog:点击右侧「1.vlog初识」继续' },
{ id: 'step2', content: '这是主要内容区域的边框' }
]
const stepIndex = ref(0)
const hiddenbar = ref(false)
+243 -34
View File
@@ -13,17 +13,156 @@ 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 selectedModule = ref(1)
const selectedCategory = ref('') // 新增:选中的分类
// 预留:按钮选中状态(如需启用再恢复逻辑)
// 新增:分类配置类型定义
interface CategoryConfig {
icons: string[]
positions: { top: string; left: string }[]
}
// 新增:模块配置类型定义
interface ModuleConfig {
name: string
value: number
categories: Record<string, CategoryConfig>
}
const moduleList = ref<ModuleConfig[]>([
{
name: '技能书-新手启航',
value: 1,
categories: {
拍摄基础: {
icons: ['skill/画面构图选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
内容策划: {
icons: ['skill/画面构图选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
拍摄执行: {
icons: ['skill/画面构图选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
后期制作: {
icons: ['skill/画面构图选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
版权伦理意识: {
icons: ['skill/画面构图选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
}
}
},
{
name: '技能书-vlog',
value: 2,
categories: {
拍摄基础: {
icons: ['skill/画面构图选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
内容策划: {
icons: ['skill/画面构图选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
拍摄执行: {
icons: ['skill/画面构图选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
后期制作: {
icons: ['skill/画面构图选中', 'skill/三分法构图', 'skill/居中构图', 'skill/对角线构图'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
},
版权伦理意识: {
icons: ['skill/画面构图选中', 'skill/景别', 'skill/运镜技巧', 'skill/光线运用'],
positions: [
{ top: '25%', left: '25%' },
{ top: '15%', left: '34%' },
{ top: '20%', left: '45%' },
{ top: '28%', left: '58%' }
]
}
}
}
])
const currentModule = computed(() => {
return moduleList.value.find(item => item.value === selectedModule.value) || moduleList.value[0]
})
const nextModule = () => {
if (selectedModule.value === moduleList.value.length) {
selectedModule.value = 1
} else {
selectedModule.value++
}
// 切换模块时重置分类选择
if (selectedCategory.value) {
selectedCategory.value = ''
sideStatus.value = true
}
}
const prevModule = () => {
if (selectedModule.value === 1) {
selectedModule.value = moduleList.value.length
} else {
selectedModule.value--
}
// 切换模块时重置分类选择
if (selectedCategory.value) {
selectedCategory.value = ''
sideStatus.value = true
}
}
//引导步骤
const steps = [
@@ -39,9 +178,9 @@ const currentHighlight = computed(() =>
stepIndex.value === 0 ? '.img-switch-item--vlog' : '.work-border'
)
const selectedImage = computed(() => {
return selected.value ? 'skill/画面构图选中' : 'skill/画面构图未选中'
})
// const selectedImage = computed(() => {
// return selected.value ? 'skill/画面构图选中' : 'skill/画面构图未选中'
// })
interface SimpleStep {
id: string
@@ -53,7 +192,13 @@ const handleStepChange = (_step: SimpleStep | null, index: number) => {
}
const handleClose = () => {
router.back()
// 如果当前在分类选中状态,则退出选中回到主视图
if (selectedCategory.value) {
handleBackToMain()
} else {
// 否则退出页面
router.back()
}
}
const handleClick = () => {
@@ -63,6 +208,29 @@ const handleClick = () => {
})
}
// 新增:处理分类点击事件
const handleCategoryClick = (categoryName: string) => {
selectedCategory.value = categoryName
sideStatus.value = false // 隐藏其他模块标签
}
// 新增:返回主视图
const handleBackToMain = () => {
selectedCategory.value = ''
sideStatus.value = true
}
// 新增:获取当前分类的配置
const currentCategoryConfig = computed(() => {
if (!selectedCategory.value) return null
return currentModule.value.categories[selectedCategory.value] || null
})
// 新增:返回按钮提示文本
const backButtonTooltip = computed(() => {
return selectedCategory.value ? '返回主视图' : '退出页面'
})
setTimeout(() => {
status.value = true
}, 1000)
@@ -76,17 +244,26 @@ setTimeout(() => {
:style="{ backgroundImage: getBackgroundImage('skill/技能树背景') }"
></div>
<ImgButton class="absolute left-0 top-1/2 -translate-y-1/2" :image="'skill/左滑'"> </ImgButton>
<ImgButton
@click="prevModule"
class="absolute left-0 top-1/2 -translate-y-1/2"
:image="'skill/左滑'"
>
</ImgButton>
<ImgButton
@click="sideStatus = false"
@click="nextModule"
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
v-show="sideStatus || selectedCategory === '拍摄基础'"
class="module module-left-bottom module-vertical"
@click="handleCategoryClick('拍摄基础')"
>
<div
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
>
@@ -95,7 +272,11 @@ setTimeout(() => {
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
</div>
<div v-show="sideStatus" class="module module-left-middle module-vertical">
<div
v-show="sideStatus || selectedCategory === '内容策划'"
class="module module-left-middle module-vertical"
@click="handleCategoryClick('内容策划')"
>
<div
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
>
@@ -104,7 +285,11 @@ setTimeout(() => {
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
</div>
<div v-show="!sideStatus" class="module module-right-middle module-vertical">
<div
v-show="sideStatus || selectedCategory === '拍摄执行'"
class="module module-right-middle module-vertical"
@click="handleCategoryClick('拍摄执行')"
>
<div
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
>
@@ -113,7 +298,11 @@ setTimeout(() => {
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
</div>
<div v-show="sideStatus" class="module module-right-upper module-vertical">
<div
v-show="sideStatus || selectedCategory === '后期制作'"
class="module module-right-upper module-vertical"
@click="handleCategoryClick('后期制作')"
>
<div
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
>
@@ -122,7 +311,11 @@ setTimeout(() => {
<div :class="['module-percent', status ? 'red-text' : 'blue-text']">0%</div>
</div>
<div v-show="sideStatus" class="module module-right-far module-vertical">
<div
v-show="sideStatus || selectedCategory === '版权伦理意识'"
class="module module-right-far module-vertical"
@click="handleCategoryClick('版权伦理意识')"
>
<div
:class="['module-text blue-text', status ? 'text-white' : 'text-[#969696e6_!important]']"
>
@@ -131,21 +324,27 @@ setTimeout(() => {
<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"
/>
<!-- 动态显示分类对应的icon -->
<template v-if="currentCategoryConfig">
<ImgButton
v-for="(icon, index) in currentCategoryConfig.icons"
:key="index"
v-show="!sideStatus"
@click="handleClick"
class="absolute z-10"
:style="{
top: currentCategoryConfig.positions[index].top,
left: currentCategoryConfig.positions[index].left
}"
:image="icon"
/>
</template>
<!-- 景别 -->
<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"
:title="backButtonTooltip"
@click="handleClose"
/>
@@ -161,12 +360,16 @@ setTimeout(() => {
<div class="absolute bottom-28 left-1/2 -translate-x-1/2">
<span class="blue-text tracking-[18px] text-5xl">
{{ !sideStatus ? '技能树-vlog' : '技能树-新手启航' }}
{{ selectedCategory || currentModule.name }}
</span>
</div>
<div class="absolute bottom-10 left-1/2 -translate-x-1/2">
<span class="red-text text-4xl">{{
status ? '当前尚未收集任何知识点,快去学习收集知识点吧' : '当前已全部解锁'
!status
? '当前尚未收集任何知识点,快去学习收集知识点吧'
: selectedCategory
? `当前${selectedCategory}模块已全部解锁`
: '当前已全部解锁'
}}</span>
</div>
@@ -219,6 +422,12 @@ setTimeout(() => {
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
.module:hover {
transform: scale(1.05);
filter: brightness(1.2);
}
/* 竖排布局 */
+1
View File
@@ -0,0 +1 @@
+85 -3
View File
@@ -2,7 +2,7 @@
import { computed, nextTick, onMounted, ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import ImgButton from '@/components/Button/ImgButton.vue'
import { GuideSteps } from '@/components/Guide'
import { GuideSteps, StepNavigation } from '@/components/Guide'
import { getStaticImage, IMAGE_PATHS } from '@/utils'
import second from '/video/Vlog模块_任务取景框_专业剖析_基础景别运用.mp4'
import third from '/video/Vlog模块_任务取景框_专业剖析_画面构图.mp4'
@@ -24,6 +24,44 @@ const steps = ref([
}
])
// 步骤导航数据
const navigationSteps = ref([
{
id: 'step1',
label: '拍摄执行',
content: '基础景别应用',
type: 'shooting' as const
},
{
id: 'step2',
label: '拍摄执行',
content: '画面构图',
type: 'shooting' as const
},
{
id: 'step3',
label: '内容策划',
content: '简单脚本策划',
type: 'planning' as const
},
{
id: 'step4',
label: '拍摄执行',
content: '动态事件跟拍与抓拍',
type: 'shooting' as const
},
{
id: 'step5',
label: '后期制作',
content: '素材导入、剪辑拼接',
type: 'post' as const
}
])
// 步骤导航相关状态
const showStepNavigation = ref(false)
const currentNavigationStep = ref(1) // 对应视频索引,从0开始
// 视频列表
const videoList = [second, third, fourth, five, six]
const currentVideoIndex = ref(0)
@@ -33,6 +71,7 @@ const currentVideo = computed(() => videoList[currentVideoIndex.value])
const handleVideoChange = () => {
if (currentVideoIndex.value < videoList.length - 1) {
currentVideoIndex.value++
currentNavigationStep.value = currentVideoIndex.value
} else {
status.value = true
steps.value = [
@@ -80,14 +119,30 @@ const handleComplete = () => {
})
} else {
router.push({
name: 'midterm',
name: 'Prepare',
query: {
key: 'midterm'
key: 'prepare'
}
})
}
}
// 步骤导航事件处理
const handleStepClick = (index: number) => {
currentVideoIndex.value = index
currentNavigationStep.value = index
nextTick(() => {
if (!videoRef.value) return
videoRef.value.muted = false
videoRef.value.volume = 1
videoRef.value.play()
})
}
const handleStepNavigationClose = () => {
showStepNavigation.value = false
}
onMounted(() => {
if (key.value === 'idea') {
status.value = true
@@ -103,6 +158,23 @@ onMounted(() => {
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleClose"
/>
<!-- 步骤导航按钮 -->
<button
v-if="key === 'profession'"
class="absolute right-4 top-1/2 z-10 -translate-y-1/2 w-12 h-12 bg-blue-500/80 hover:bg-blue-500 rounded-full flex items-center justify-center text-white transition-all duration-200"
@click="showStepNavigation = true"
title="步骤导航"
>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<path
d="M3 4H17M3 8H17M3 12H17M3 16H17"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
/>
</svg>
</button>
<div v-if="key === 'vlog'" :src="image">
<img :src="getStaticImage('work/vlog背景全屏待定')" alt="" />
</div>
@@ -129,6 +201,16 @@ onMounted(() => {
<!-- 引导与高亮 -->
<GuideSteps v-if="status" :steps="steps" position-offset-y="85%" @complete="handleComplete" />
<!-- 步骤导航抽屉 -->
<StepNavigation
:visible="showStepNavigation && key === 'profession'"
:background-image="getStaticImage('work/vlog背景全屏待定')"
:steps="navigationSteps"
:current-step-index="currentNavigationStep"
@step-click="handleStepClick"
@close="handleStepNavigationClose"
/>
</template>
<style scoped>
+1 -1
View File
@@ -35,7 +35,7 @@ const sideSwitcherItems = ref([
{
key: 'vlog',
description: '记录身边的美好',
image: 'work/vlog初识框'
image: 'work/vlog背景全屏待定'
},
{
key: 'case',