Commit c03e0d22 authored by 黄同智's avatar 黄同智

写页面

parent fe614843
......@@ -12,7 +12,8 @@
"element-plus": "^2.14.0",
"nprogress": "^0.2.0",
"vue": "^3.4.0",
"vue-router": "^4.3.0"
"vue-router": "^4.3.0",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@types/node": "20.11.0",
......@@ -1833,6 +1834,12 @@
"node": ">=10"
}
},
"node_modules/sortablejs": {
"version": "1.14.0",
"resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz",
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==",
"license": "MIT"
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
......@@ -1989,6 +1996,18 @@
"peerDependencies": {
"typescript": "*"
}
},
"node_modules/vuedraggable": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz",
"integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
"license": "MIT",
"dependencies": {
"sortablejs": "1.14.0"
},
"peerDependencies": {
"vue": "^3.0.1"
}
}
}
}
......@@ -14,7 +14,8 @@
"element-plus": "^2.14.0",
"nprogress": "^0.2.0",
"vue": "^3.4.0",
"vue-router": "^4.3.0"
"vue-router": "^4.3.0",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@types/node": "20.11.0",
......
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="208" fill="none" viewBox="0 0 12 208"><path fill="#000" d="M1 0h10v10.951a2 2 0 0 1-.731 1.547l-3 2.461a2 2 0 0 1-2.538 0l-3-2.461A2 2 0 0 1 1 10.95z"/><path stroke="#000" d="M6 13v204"/></svg>
\ No newline at end of file
<template>
<section class="box rounded-16 p-10" style="min-width: 1110px;">
<section class="box rounded-16 p-10 my-10" style="min-width: 1110px;">
<div class="flex-align-center justify-between">
<div class="flex-align-center gap-4">
<el-icon color="#333" size="12">
<Plus />
</el-icon>
<div class="tuoz flex-align-center" id="anzhu">
<img src="@/static/imgs/tuoz.png" alt="" class="h-16">
</div>
<span class="fs-12">分镜1</span>
<span class="fs-10 py-2 px-4 rounded-4 bg-e3e9ff">ID</span>
<div class="flex-align-center ml-10 bg-f4f6ff py-6 px-14 rounded-8 btnsborder gap-4">
<el-icon color="#5252ff" size="12">
<Plus />
<el-icon color="#5252ff" size="14">
<HelpFilled />
</el-icon>
<span class="fs-12">全能参考生视频</span>
</div>
......@@ -20,7 +20,7 @@
<el-button text :icon="Delete" circle />
</div>
</div>
<div class="flex gap-10 h-b100">
<div class="flex gap-10 h-b100 content">
<section class="w-400 p-14 bg-fff rounded-16 mt-10">
<div>分镜信息</div>
<div class="h-548 hide-scrollbar">
......@@ -92,29 +92,65 @@
</el-icon>
</div>
<div class="flex h-b100 mt-10 gap-10">
<div class="flex-3 flex flex-col rounded-16 p-10 card1">
<div class="flex-3 flex flex-col justify-between rounded-16 p-10 card1">
<div class="flex gap-4">
<div v-if="fileList.length > 0" class="relative w-40 h-40 rounded-4 overflow-hidden imgbox" v-for="(item, index) in fileList" :key="index" >
<div v-if="fileList.length > 0" class="relative w-40 h-40 rounded-4 overflow-hidden imgbox"
v-for="(item, index) in fileList" :key="index">
<img :src="item.url" class="w-b100 h-b100" />
<el-icon class="absolute right-2 top-2 del cursor-pointer" @click="delImg(index)"><CircleCloseFilled /></el-icon>
<el-icon class="absolute right-2 top-2 del cursor-pointer" @click="delImg(index)">
<CircleCloseFilled />
</el-icon>
</div>
<el-upload
v-model:file-list="fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
list-type="picture-card"
class="custom-upload"
:show-file-list="false"
>
<el-icon size="18"><Plus /></el-icon>
<el-upload v-model:file-list="fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" list-type="picture-card"
class="custom-upload" :show-file-list="false">
<el-icon size="18">
<Plus />
</el-icon>
</el-upload>
</div>
<div class="flex-1"></div>
<div class="">不阿斯卡斯卡</div>
<div class="flex-1 overflow-y-auto my-8 hide-scrollbar" style="max-height: 412px">
<div contenteditable="true" class="bg-f5 p-10 text-333 rounded-8 custom" style="min-height: 412px"></div>
</div>
<div class="">
<div v-if="isShowtip" class="hint flex-between-center px-10">
<div class="flex-align-center">
<el-icon color="#888">
<Warning />
</el-icon>
<span class="ml-4 text-888 fs-12">提示词内容出现修改,请注意及时保存</span>
</div>
<el-button type="primary" text size="small" class="h-32 rounded-8"
@click="isShowtip = false">保存</el-button>
</div>
<div class="flex-between-center mt-6">
<div class="flex gap-6">
<el-select v-model="aiTypeVal" placeholder="Select" style="width: 200px;">
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="secondVal" placeholder="Select" style="width: 80px;">
<el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-button size="small" class="h-32 rounded-8"
@click="isShowtip = false">@</el-button>
</div>
<div class="flex-align-center h-32 px-10 rounded-4 jinbi">
<svg t="1779335788481" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="9953" width="20" height="20">
<path
d="M408.8832 353.9968c40.7552-87.1424 61.0304-130.7648 92.7744-136.192a61.44 61.44 0 0 1 20.6848 0c31.744 5.4272 52.0192 49.0496 92.7744 136.192 7.8848 16.9984 11.8784 25.6 18.0224 32.3584a61.44 61.44 0 0 0 4.5056 4.5056c6.8608 6.144 15.36 10.1376 32.3584 18.0224 87.1424 40.7552 130.7648 61.0304 136.192 92.7744a61.44 61.44 0 0 1 0 20.6848c-5.4272 31.744-49.0496 52.0192-136.192 92.7744-16.9984 7.8848-25.6 11.8784-32.3584 18.0224a61.44 61.44 0 0 0-4.5056 4.5056c-6.144 6.8608-10.1376 15.36-18.0224 32.3584-40.7552 87.1424-61.0304 130.7648-92.7744 136.192a61.44 61.44 0 0 1-20.6848 0c-31.744-5.4272-52.0192-49.0496-92.7744-136.192-7.8848-16.9984-11.8784-25.6-18.0224-32.3584a61.44 61.44 0 0 0-4.5056-4.5056c-6.8608-6.144-15.36-10.1376-32.3584-18.0224-87.1424-40.7552-130.7648-61.0304-136.192-92.7744a61.44 61.44 0 0 1 0-20.6848c5.4272-31.744 49.0496-52.0192 136.192-92.7744 16.9984-7.8848 25.6-11.8784 32.3584-18.0224a61.44 61.44 0 0 0 4.5056-4.5056c6.144-6.8608 10.1376-15.36 18.0224-32.3584z"
p-id="9954" fill="#ffffff"></path>
</svg>
<span class="text-fff ml-4">882</span>
</div>
</div>
</div>
</div>
<div class="flex-2 flex flex-col rounded-12 card2 overflow-hidden" style="background: #fafbfd">
<video src="@/static/imgs/mp4.mp4" class="w-b100 bg-2b303a flex-1" controls></video>
<div class="flex-center gap-4 px-20 mt-10">
<div v-for="(item, index) in 2" :key="index" class="fjitem flex rounded-8 cursor-pointer" @click="changeVideo(item, index)" :class="videoIndex === index ? 'active': ''">
<div v-for="(item, index) in 2" :key="index" class="fjitem flex rounded-8 cursor-pointer"
@click="changeVideo(item, index)" :class="videoIndex === index ? 'active' : ''">
<img class="h-36 w-50 rounded-6"
src="https://res.volccdn.com/obj/volc-console-fe/dramart/static/image/PIC3.22e42366.png" alt="">
</div>
......@@ -127,17 +163,81 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Plus, DocumentCopy, CopyDocument,CircleCloseFilled, MoreFilled, Delete } from '@element-plus/icons-vue'
import { Plus, DocumentCopy, CopyDocument, CircleCloseFilled, MoreFilled, Delete, HelpFilled, Warning } from '@element-plus/icons-vue'
import Empty from './Empty.vue';
const fenjDesc = ref('')
const aiTypeVal = ref('')
const aiTypeVal = ref('1')
const isShowtip = ref(true)
const secondVal = ref(5)
const options = [
{
value: '1',
label: '林霞',
}
]
const options1 = [
{
value: '1',
label: 'DouBao-hahyha-1.0',
},
{
value: '2',
label: 'DouBao-hahyha-12.0'
},
]
const options2 = [
{
value: 4,
label: '4s',
},
{
value: 5,
label: '5s',
},
{
value: 6,
label: '6s',
},
{
value: 7,
label: '7s',
},
{
value: 8,
label: '8s',
},
{
value: 9,
label: '9s',
},
{
value: 10,
label: '10s',
},
{
value: 11,
label: '11s',
},
{
value: 12,
label: '12s',
},
{
value: 13,
label: '13s',
},
{
value: 14,
label: '14s',
},
{
value: 15,
label: '15s',
},
]
const fileList = ref([
{
name: 'food.jpeg',
......@@ -173,6 +273,7 @@ const changeVideo = (item: any, index: number) => {
.btnsborder {
border: 1px solid #eeeeff;
}
.child {
flex: 0 0 calc(50% - 5px);
}
......@@ -191,17 +292,20 @@ const changeVideo = (item: any, index: number) => {
.fjitem {
border: 1px solid #ddd;
padding: 1px;
&.active {
border: 1px solid #5252ff;
}
}
}
.imgbox {
.del {
display: none;
}
&:hover{
.del{
&:hover {
.del {
display: inline-block;
}
}
......@@ -220,7 +324,36 @@ const changeVideo = (item: any, index: number) => {
.custom-upload :deep(.el-upload--picture-card) {
width: 40px;
height: 40px;
--el-upload-picture-card-size: 40px; /* 修改 Element Plus 变量 */
--el-upload-picture-card-size: 40px;
/* 修改 Element Plus 变量 */
}
.hint {
border: 1px solid #e5e7eb;
border-radius: 8px;
}
.jinbi {
background-color: #5252ff;
&:hover {
background-color: #4747e7;
}
}
.custom {
outline: none;
box-shadow: none;
border-color: transparent;
}
.tuoz {
cursor: all-scroll;
}
.content {
display: block;
}
#anzhu:active ~ .content {
display: none;
}
</style>
\ No newline at end of file
<template>
<div class="video-wrapper" @mouseenter="showControls = true" @mouseleave="showControls = false">
<!-- 1. 视频本体 (隐藏自带控件) -->
<video
ref="videoRef"
src="https://www.w3schools.com/html/mov_bbb.mp4"
@timeupdate="handleTimeUpdate"
@loadedmetadata="handleLoadedMetadata"
@ended="handleEnded"
></video>
<!-- 2. 自定义控制层 (只在悬停时显示) -->
<div class="custom-controls" :class="{ 'visible': showControls || isPlaying }">
<!-- 底部区域:包含时间和进度条 -->
<div class="control-bottom">
<!-- 时间显示 (左) -->
<div class="time-display">
{{ formatTime(currentTime) }} / {{ formatTime(duration) }}
</div>
<!-- 进度条轨道 (中) -->
<div
class="progress-track"
ref="progressTrack"
@click="seekVideo"
@mousemove="handleHoverMove"
@mouseleave="hoverTime = null"
>
<!-- 进度填充条 -->
<div class="progress-fill" :style="{ width: progressPercentage + '%' }"></div>
<!-- 拖动滑块 (圆点) -->
<div class="progress-thumb" :style="{ left: progressPercentage + '%' }"></div>
<!-- 悬停预览气泡 (Tooltip) -->
<div
class="hover-tooltip"
v-if="hoverTime !== null"
:style="{ left: hoverPercent + '%' }"
>
{{ formatTime(hoverTime) }}
</div>
</div>
<!-- 播放/暂停按钮 (右) -->
<button class="play-btn" @click="togglePlay">
{{ isPlaying ? '⏸' : '▶' }}
</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
// ----- 状态 -----
const videoRef = ref(null)
const isPlaying = ref(false)
const currentTime = ref(0)
const duration = ref(0)
const showControls = ref(false)
// 悬停状态
const hoverTime = ref(null) // 悬停时的秒数
const hoverPercent = ref(0) // 悬停时的百分比
// ----- 计算属性 -----
const progressPercentage = computed(() => {
if (duration.value === 0) return 0
return (currentTime.value / duration.value) * 100
})
// ----- 核心逻辑 -----
// 1. 格式化时间 (00:00)
const formatTime = (seconds) => {
if (!seconds && seconds !== 0) return '00:00'
const m = Math.floor(seconds / 60)
const s = Math.floor(seconds % 60)
return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
}
// 2. 视频加载完成,获取总时长
const handleLoadedMetadata = () => {
if (videoRef.value) duration.value = videoRef.value.duration
}
// 3. 播放过程中更新进度
const handleTimeUpdate = () => {
if (videoRef.value) currentTime.value = videoRef.value.currentTime
}
// 4. 播放结束重置
const handleEnded = () => {
isPlaying.value = false
}
// 5. 切换播放/暂停
const togglePlay = () => {
if (!videoRef.value) return
if (videoRef.value.paused) {
videoRef.value.play()
isPlaying.value = true
} else {
videoRef.value.pause()
isPlaying.value = false
}
}
// 6. 点击进度条跳转
const seekVideo = (event) => {
const track = event.currentTarget
const rect = track.getBoundingClientRect()
const x = event.clientX - rect.left
const percent = Math.min(100, Math.max(0, (x / rect.width) * 100))
if (duration.value > 0) {
const newTime = (percent / 100) * duration.value
videoRef.value.currentTime = newTime
currentTime.value = newTime
}
}
// 7. 鼠标悬停计算位置和时间
const handleHoverMove = (event) => {
const track = event.currentTarget
const rect = track.getBoundingClientRect()
const x = event.clientX - rect.left
const percent = Math.min(100, Math.max(0, (x / rect.width) * 100))
hoverPercent.value = percent
if (duration.value > 0) {
hoverTime.value = (percent / 100) * duration.value
}
}
</script>
<style scoped>
/* 容器 */
.video-wrapper {
position: relative;
width: 100%;
max-width: 800px;
background: #000;
aspect-ratio: 16/9;
/* overflow: hidden; */
border-radius: 8px;
}
video {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
/* 控制层 (初始透明,悬停显示) */
.custom-controls {
/* position: absolute;
bottom: 0;
left: 0;
right: 0; */
padding: 20px;
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
/* opacity: 0; */
transition: opacity 0.3s ease;
pointer-events: none; /* 鼠标穿透 */
}
.custom-controls.visible {
opacity: 1;
pointer-events: auto;
}
/* 底部布局 */
.control-bottom {
display: flex;
align-items: center;
gap: 15px;
}
/* 时间文本 */
.time-display {
color: rgba(255,255,255,0.9);
font-size: 13px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
min-width: 70px;
}
/* 进度条轨道 */
.progress-track {
flex-grow: 1;
height: 6px; /* 更细的轨道 */
background: rgba(1, 255, 56, 0.3); /* 半透明灰 */
border-radius: 4px;
position: relative;
cursor: pointer;
height: 100px;
}
/* 填充条 */
.progress-fill {
height: 100%;
background: #ff0000; /* 纯白填充 */
border-radius: 4px;
width: 0%;
transition: width 0.1s linear;
}
/* 滑块 (圆点) - 核心视觉 */
.progress-thumb {
position: absolute;
top: 50%;
width: 12px;
height: 12px;
background: #fff;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 6px rgba(0,0,0,0.5);
opacity: 0;
transition: opacity 0.2s;
}
/* 悬停或播放时显示圆点 */
.progress-track:hover .progress-thumb,
.custom-controls.visible .progress-thumb {
opacity: 1;
}
/* 悬停气泡 (Tooltip) */
.hover-tooltip {
position: absolute;
bottom: 25px;
transform: translateX(-50%);
background: rgba(0,0,0,0.75);
color: #fff;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
font-family: sans-serif;
pointer-events: none;
}
/* 播放按钮 */
.play-btn {
background: none;
border: none;
color: #fff;
font-size: 20px;
cursor: pointer;
padding: 5px;
transition: transform 0.2s;
}
.play-btn:hover {
transform: scale(1.1);
}
</style>
\ No newline at end of file
This diff is collapsed.
......@@ -2,7 +2,7 @@
<section class="flex h-b100">
<section class="aside flex-align-center flex-col">
<span class="py-16">集数</span>
<div class="flex-1 flex-center flex-col gap-10 overflow-y-auto hide-scrollbar">
<div class="flex-1 flex-align-center flex-col gap-10 overflow-y-auto hide-scrollbar">
<div v-for="(item, index) in 100" :key="index"
class="cursor-pointer w-36 min-h-36 rounded-4 flex-center text-888 jj"
:class="indexVal === index ? 'active' : ''">
......@@ -25,7 +25,7 @@
林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。
<el-popover placement="bottom" :width="400">
<template #reference>
<el-button text ><span class="fs-12">详情</span></el-button>
<el-button text><span class="fs-12">详情</span></el-button>
</template>
<div class="max-h-200 overflow-y-auto">
<p>林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。</p>
......@@ -34,9 +34,14 @@
</div>
</el-popover>
</div>
<div v-for="(item, index) in 2" :key="index" class="pb-20">
<div v-for="(item, index) in 1" :key="index" class="pb-20">
<Episode />
</div>
<!-- <draggable v-model="list" item-key="id" class="list-group" @end="onDragEnd" handle=".tuoz">
<template #item="{ element, index }">
<Episode />
</template>
</draggable> -->
</div>
</section>
</section>
......@@ -45,7 +50,7 @@
import { ref } from 'vue';
import { DocumentCopy } from '@element-plus/icons-vue'
import Episode from './Episode.vue';
import draggable from 'vuedraggable'
const indexVal = ref(0)
const aiTypeVal = ref('')
......@@ -60,6 +65,19 @@ const options = [
},
]
const list = ref([
{ id: 1, name: '第1集 凌晨的咖啡与雨', time: '00:00:00' },
{ id: 2, name: '第2集 早餐的阳光与微笑', time: '00:00:00' },
{ id: 3, name: '第3集 午餐的温暖与关怀', time: '00:00:00' },
])
const onDragEnd = (evt:any) => {
console.log('拖拽结束', list.value)
}
</script>
<style lang="scss" scoped>
.aside {
......
......@@ -291,8 +291,6 @@ import { ref } from 'vue';
import { CloseBold, Plus, DocumentCopy, MagicStick, FolderAdd, Download, MoreFilled, Delete } from '@element-plus/icons-vue'
const isShowtip = ref(true)
const indexTab = ref(0)
const tabs = ref(['角色', '场景', '道具'])
......
......@@ -5,7 +5,7 @@
<StepOne v-if="indexVal === 0" @next="next" />
<StepTwo v-if="indexVal === 1" @next="next" />
<StepThree v-if="indexVal === 2" />
<StepFour v-if="indexVal === 3" />
<StepFour v-if="indexVal === 3" @next="next" />
</div>
</div>
</template>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment