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

@@ -0,0 +1,33 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { ImgButton } from '@/components/Button'
import { Video } from '@/components'
import { IMAGE_PATHS, getPublicPath } from '@/utils'
const router = useRouter()
const playing = ref(false)
const handleBack = () => {
router.back()
}
</script>
<template>
<div class="relative w-full h-full overflow-hidden bg-black">
<Video
class="w-full h-full"
:src="getPublicPath('video/editing/yingxiao_batch.mp4')"
v-model="playing"
:muted="false"
:volume="1"
:controls="true"
:hideNativeControls="true"
/>
<ImgButton
class="absolute right-0 top-0 z-20"
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleBack"
/>
</div>
</template>
@@ -0,0 +1,38 @@
<script lang="ts" setup>
import { IMAGE_PATHS, getStaticImage } from '@/utils'
import { ImgButton } from '@/components/Button'
import { useRouter } from 'vue-router'
import { GuideSteps, GuideStepsItem } from '@/components/Guide'
const router = useRouter()
const back = () => {
router.back()
}
</script>
<template>
<div class="relative w-full h-full overflow-hidden">
<ImgButton
class="absolute right-0 top-0 z-20"
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="back"
/>
<img class="absolute inset-0" :src="getStaticImage('img/背景.png')" alt="" />
<img class="absolute top-5 z-10" :src="getStaticImage('img/调色-标题.png')" alt="" />
<div class="relative h-full pt-28 overflow-y-scroll">
<img :src="getStaticImage('interview/img/调色实践.png')" alt="" />
<ImgButton
class="absolute top-[1180px] left-[51.5%] -translate-x-1/2"
image="after-editing/color/调色实践"
@click="router.push({ name: 'InterviewColor' })"
/>
</div>
<GuideSteps :visible="true" position-offset-y="85%">
<GuideStepsItem>这份长图文干货满满,滚动鼠标查看完整内容吧</GuideStepsItem>
</GuideSteps>
</div>
</template>
+12 -7
View File
@@ -5,7 +5,6 @@ import { ImgButton } from '@/components/Button'
import { Overlay } from '@/components/Overlay'
import { ref } from 'vue'
import ImageFilter from '@/components/ImageFilter/ImageFilter.vue'
import { useInterviewStore } from '@/stores'
const selected = ref<number | undefined>(1)
const btnState = ref(false)
@@ -25,11 +24,11 @@ const adjustmentList = ref([
const colorBarList = ref([
{ id: 1, name: '原图', filter: 'none' },
{ id: 2, name: '暖阳', filter: 'sepia(0.3) contrast(1.1) brightness(1.1)' },
{ id: 2, name: '暖阳', filter: 'saturate(2.5) contrast(2.1)' },
{ id: 3, name: '冷调', filter: 'hue-rotate(180deg) contrast(0.9)' },
{ id: 4, name: '复古', filter: 'sepia(0.6) contrast(1.2) brightness(0.9)' },
{ id: 5, name: '黑白', filter: 'grayscale(1)' },
{ id: 6, name: '鲜艳', filter: 'saturate(1.5) contrast(1.1)' }
{ id: 6, name: '鲜艳', filter: 'sepia(0.1) saturate(2.5) contrast(2.1) brightness(1)' }
])
// 获取指定参数的值
@@ -117,10 +116,8 @@ const handleTryOther = () => {
}
const handleFinish = () => {
useInterviewStore().setInterviewUnlockProgress(4)
router.push({
name: 'Interview'
name: 'Film'
})
}
@@ -157,7 +154,7 @@ const changeColor = (item: { id: number; name: string }) => {
class="relative w-[1273px] h-[732px] bg-no-repeat bg-cover mt-10 p-2 pb-[26px] pr-[26px]"
:style="{ backgroundImage: getBackgroundImage('after-editing/color/图片框.png') }"
>
<ImageFilter ref="imageFilterRef" :src="getStaticImage('after-editing/color/图片')" />
<ImageFilter ref="imageFilterRef" :src="getStaticImage('after-editing/color/film_img')" />
<!-- 开启对比 -->
<ImgButton
@@ -258,6 +255,14 @@ const changeColor = (item: { id: number; name: string }) => {
<!-- title -->
<img class="absolute top-0 left-0" :src="getStaticImage('after-editing/color/标题-调色实践')" />
<!-- 回到顶部按钮 - 最后一页显示 -->
<p class="absolute left-40 bottom-10 flex items-center">
<img class="rotate-0 w-28 mr-4" src="@/assets/svg/deng.svg" />
<span class="text-white text-2xl font-bold">
推荐参数:亮度 90、对比度 100、饱和度 100、曝光 - 90、色调 0、锐化 100、模糊 0
</span>
</p>
<!-- 保存图片弹窗 -->
<Overlay :visible="showModal" @close="handleModalClose">
<div class="relative w-[1000px] h-[600px] flex items-center justify-center">
+71 -66
View File
@@ -1,69 +1,63 @@
<script lang="ts" setup>
import { onMounted, ref, watch } from 'vue'
import { nextTick, ref } from 'vue'
import { useRouter } from 'vue-router'
import ImgButton from '@/components/Button/ImgButton.vue'
// import { GuideSteps } from '@/components/Guide'
import { StepNavigation } from '@/components/Guide'
import { IMAGE_PATHS } from '@/utils'
import { Video } from '@/components'
const router = useRouter()
// 导入视频文件
import videoBasic from '/video/vlog_zhizuobianjiaojing_jichujianji.mp4'
import videoSoundeffect from '/video/vlog_renwuqujing_yingxiaochuli.mp4'
import videoPackaging from '/video/vlog_renwuqujing_baozhuang.mp4'
import videoCopyright from '/video/vlog_renwuqujing_banquanguifan.mp4'
const videoList = [videoBasic, videoSoundeffect, videoPackaging, videoCopyright]
const videoRef = ref<HTMLVideoElement>()
const navigationSteps = [
{
id: 'step1',
label: '后期制作',
content: '声画剪辑流程',
type: 'post' as const
},
{
id: 'step2',
label: '后期制作',
content: 'J-cut/L-cut运用',
type: 'post' as const
},
{
id: 'step3',
label: '后期制作',
content: '【Q3】节奏剪辑技巧',
type: 'post' as const
}
]
const currentVideoIndex = ref(0)
const playing = ref(false)
const showStepNavigation = ref(false)
onMounted(() => {
// 确保视频元素加载并自动播放
if (videoRef.value) {
videoRef.value.src = videoList[currentVideoIndex.value]
videoRef.value.load()
// 尝试自动播放
const playPromise = videoRef.value.play()
if (playPromise !== undefined) {
playPromise.catch(error => {
// 自动播放失败,可能是浏览器策略阻止,需要用户交互
console.log('自动播放被阻止:', error)
})
}
// 监听视频结束事件
videoRef.value.addEventListener('ended', playNextVideo)
}
})
// 播放下一个视频
const playNextVideo = () => {
if (currentVideoIndex.value < videoList.length - 1) {
currentVideoIndex.value++
if (videoRef.value) {
videoRef.value.src = videoList[currentVideoIndex.value]
videoRef.value.load()
// 自动播放下一个视频
const playPromise = videoRef.value.play()
if (playPromise !== undefined) {
playPromise.catch(error => {
console.log('自动播放被阻止:', error)
})
}
}
if (currentVideoIndex.value >= videoList.length - 1) {
playing.value = false
return
}
currentVideoIndex.value++
nextTick(() => {
playing.value = true
})
}
// 监听当前视频索引变化
watch(currentVideoIndex, newIndex => {
if (videoRef.value) {
videoRef.value.src = videoList[newIndex]
videoRef.value.load()
}
})
const handleStepClick = (index: number) => {
currentVideoIndex.value = index
// showStepNavigation.value = false
nextTick(() => {
playing.value = true
})
}
const handleClose = () => {
router.back()
@@ -71,29 +65,40 @@ const handleClose = () => {
</script>
<template>
<div>
<!--使用动态绑定和ref-->
<video
ref="videoRef"
<div class="relative w-full h-full overflow-hidden bg-black">
<Video
:src="videoList[currentVideoIndex]"
type="video/mp4"
controls
preload="auto"
class="video-player"
autoplay
></video>
v-model="playing"
:muted="false"
:volume="1"
@ended="playNextVideo"
/>
<ImgButton
class="absolute right-0 top-0 z-10"
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleClose"
/>
<button
class="absolute right-4 top-1/2 z-10 flex h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full bg-blue-500/80 text-white transition-all duration-200 hover:bg-blue-500"
title="步骤导航"
@click="showStepNavigation = true"
>
<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>
<StepNavigation
:visible="showStepNavigation"
:background-image="''"
:steps="navigationSteps"
:current-step-index="currentVideoIndex"
@step-click="handleStepClick"
@close="showStepNavigation = false"
/>
</div>
</template>
<style scoped>
.video-player {
width: 100%;
height: 100%;
object-fit: contain;
}
</style>
@@ -0,0 +1,33 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { ImgButton } from '@/components/Button'
import { Video } from '@/components'
import { IMAGE_PATHS, getPublicPath } from '@/utils'
const router = useRouter()
const playing = ref(false)
const handleBack = () => {
router.back()
}
</script>
<template>
<div class="relative w-full h-full overflow-hidden bg-black">
<Video
class="w-full h-full"
:src="getPublicPath('video/on-site/dygmk_zlsxhbj.mp4')"
v-model="playing"
:muted="false"
:volume="1"
:controls="true"
:hideNativeControls="true"
/>
<ImgButton
class="absolute right-0 top-0 z-20"
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleBack"
/>
</div>
</template>