Commit 32507e88 authored by heke's avatar heke

Merge remote-tracking branch into main

parents bb064264 6653de75
......@@ -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",
......
......@@ -89,7 +89,7 @@ watch(
() => route.path,
(path) => {
indexvalue.value = routeIndexMap[path] ?? 0;
isShow.value = !!routeIndexMap[path]
isShow.value = !!routeIndexMap[path] || path === '/'
},
{ immediate: true }
);
......
......@@ -660,7 +660,6 @@ $numbers: (
}
.text-over-1 {
width: 200px;
/* 必须设置宽度 */
white-space: nowrap;
/* 强制文本不换行 */
......@@ -687,4 +686,20 @@ $numbers: (
&::-webkit-scrollbar {
display: none;
}
}
.el-dialog {
position: relative;
border-radius: 18px;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 80px;
background: linear-gradient(to bottom, #5476ff13, #ffffff00);
border-radius: 8px;
}
}
\ No newline at end of file
<template>
<el-dialog v-model="visible" width="1200" align-center>
<template #header="{ close, titleId, titleClass }">
<div class="flex-align-center justify-between gap-8 mb-10">
<span class="fs-18">{{ title }}</span>
<el-button type="primary">确认{{ modalType === 1 ? '角色' : modalType === 2 ? '场景' : '道具' }}</el-button>
</div>
</template>
<div class="pb-10">
<div class="mb-10 fs-12">当前主图</div>
<div class="rounded-10 h-400 flex-center" style="background-color: #f9fafb;">
<img src="https://res.volccdn.com/obj/volc-console-fe/dramart/static/image/PIC3.22e42366.png"
class="h-b100 img rounded-10" alt="">
</div>
<div class="mt-20 editbox pt-20 h-200">
<RichTextEditor style="width: 768px;" class="mx-auto"/>
</div>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import RichTextEditor from './RichTextEditor.vue'
const props = defineProps({
title: {
type: String,
default: '新增',
},
})
const visible = ref(false)
const imageUrl = ref('')
const modalType = ref(1) // 1:角色 2:场景 3:道具
const open = (val: number) => {
modalType.value = val
visible.value = true
}
const close = () => {
visible.value = false
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.cirir {
border: 1px solid #ccc;
}
.avatar-uploader {
width: 100%;
:deep(.el-upload) {
border: 2px dashed #ddd;
width: 100%;
height: 240px;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s;
&:hover {
border-color: #c5c5c5;
}
}
}
.editbox {
border-top: 1px solid #ddd;
}
</style>
\ No newline at end of file
<template>
<el-dialog v-model="visible" width="700" align-center>
<template #header="{ close, titleId, titleClass }">
<div class="flex-align-center gap-8 mb-10">
<div class="cirir flex-center w-48 h-48 rounded-8">
<svg t="1779679636879" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="19134" width="24" height="24">
<path
d="M296.533333 712.832a42.666667 42.666667 0 0 1 0 60.330667l-90.538666 90.538666a42.666667 42.666667 0 0 1-60.330667 0l-30.165333-30.165333a42.666667 42.666667 0 0 1 60.330666-60.373333l60.373334-60.330667a42.666667 42.666667 0 0 1 60.330666 0zM896 768a42.666667 42.666667 0 0 1 0 85.333333H426.666667a42.666667 42.666667 0 0 1 0-85.333333h469.333333zM296.533333 414.165333a42.666667 42.666667 0 0 1 0 60.330667l-90.538666 90.538667a42.666667 42.666667 0 0 1-60.330667 0l-30.165333-30.165334a42.666667 42.666667 0 0 1 60.330666-60.373333l60.373334-60.330667a42.666667 42.666667 0 0 1 60.330666 0zM896 469.333333a42.666667 42.666667 0 0 1 0 85.333334H426.666667a42.666667 42.666667 0 0 1 0-85.333334h469.333333zM296.533333 115.498667a42.666667 42.666667 0 0 1 0 60.330666L205.994667 266.368a42.666667 42.666667 0 0 1-60.330667 0l-30.165333-30.165333A42.666667 42.666667 0 0 1 175.829333 175.786667l60.373334-60.330667a42.666667 42.666667 0 0 1 60.330666 0zM896 170.666667a42.666667 42.666667 0 0 1 0 85.333333H426.666667a42.666667 42.666667 0 1 1 0-85.333333h469.333333z"
fill="#3f3f51" p-id="19135"></path>
</svg>
</div>
<span class="fs-18">批量生成</span>
</div>
</template>
<template #footer>
<div class="flex-between-center gap-8">
<el-button @click="close">全选</el-button>
<div>
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="close">
<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>876
</el-button>
</div>
</div>
</template>
<div>
<el-checkbox-group v-model="checkList" class="w-b100 flex flex-wrap gap-10">
<el-checkbox value="Value A" v-for="(item, index) in checkList" :key="index" class="itemrr rounded-8 p-10"
disabled>
<div class="flex opacity">
<img src="https://res.volccdn.com/obj/volc-console-fe/dramart/static/image/PIC3.22e42366.png"
class="w-40 h-40 rounded-6" />
<div class="ml-10 flex-1 flex flex-col">
<div class="flex-between-center text-333">
<span>林喜爱</span>
<div class="fs-12 text-over-1 w-140 px-10 py-4 rounded-40 tiptest" title="已完成设定,不支持批量生成">已完成设定,不支持批量生成
</div>
</div>
<div class="mt-10 fs-12 text-over-1 text-888" style="width: 230px">
便利店店员:细心,粗心细心,粗心细心,粗心细心,粗心细心,粗心
</div>
</div>
</div>
</el-checkbox>
</el-checkbox-group>
<div class="h-400 flex-center flex-col" v-if="checkList.length == 0">
<svg t="1779342435411" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="25486" width="64" height="64">
<path
d="M625.777778 0l341.333333 307.2v648.931556c0 37.432889-33.792 67.868444-75.320889 67.868444H132.209778C90.680889 1024 56.888889 993.564444 56.888889 956.131556V67.868444C56.888889 30.435556 90.680889 0 132.209778 0H625.777778zM476.728889 747.52h-11.491556a52.337778 52.337778 0 0 0-51.768889 52.906667c0 29.240889 23.153778 52.906667 51.768889 52.906666h11.548445a52.337778 52.337778 0 0 0 51.768889-52.906666 52.337778 52.337778 0 0 0-51.768889-52.906667zM459.377778 341.333333c-30.151111 0-57.287111 4.892444-80.497778 14.620445a147.342222 147.342222 0 0 0-55.694222 39.879111c-45.795556 53.134222-38.684444 122.026667-37.717334 129.706667a47.616 47.616 0 0 0 53.020445 41.927111 48.241778 48.241778 0 0 0 41.073778-54.215111c0-0.284444-2.844444-32.881778 14.791111-53.361778 12.401778-14.392889 34.304-21.617778 65.024-21.617778 34.702222 0 57.059556 8.817778 66.503111 26.225778a44.600889 44.600889 0 0 1-3.982222 47.616l-93.184 125.383111a49.152 49.152 0 0 0 9.102222 67.868444 46.535111 46.535111 0 0 0 66.446222-9.272889l93.184-125.383111a143.246222 143.246222 0 0 0 11.377778-153.144889C590.051556 382.805333 548.807111 341.333333 459.377778 341.333333z"
fill="#e6e6e6" p-id="25487"></path>
<path
d="M941.852444 276.48L628.280889 0v217.941333c0 32.711111 29.354667 58.481778 62.236444 58.481778l251.335111 0.056889z"
fill="#e6e6e6" fill-opacity=".5" p-id="25488"></path>
</svg>
<div class="text-888 mt-10">暂无数据</div>
</div>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const visible = ref(false)
const modalType = ref(1) // 1:角色 2:场景 3:道具
const open = (val: number) => {
modalType.value = val
visible.value = true
}
const close = () => {
visible.value = false
}
const checkList = ref([])
defineExpose({ open })
</script>
<style lang="scss" scoped>
.cirir {
border: 1px solid #ccc;
}
.active {
background: #fff;
border-radius: 8px;
}
.itemrr {
flex: 0 0 calc(50% - 5px);
border: 2px solid #eee;
width: 100%;
.tiptest {
color: #ecb132;
background-color: #fff6e2;
}
}
:deep(.el-checkbox) {
height: auto;
margin-right: 0;
&.is-disabled {
.opacity {
opacity: 0.5;
}
}
}
</style>
\ No newline at end of file
<template>
<el-dialog v-model="visible" width="700">
<template #header="{ close, titleId, titleClass }">
<div class="flex-align-center gap-8 mb-10">
<div class="cirir flex-center w-48 h-48 rounded-8">
<IconType :modalType="modalType" />
</div>
<span class="fs-18">{{ title }}选择</span>
</div>
</template>
<div>
<div v-if="title === '角色库'" class="bg-f5 h-36 flex gap-8 rounded-8 p-2 cursor-pointer" style="width: 260px;">
<div class="flex-1 flex-center" :class="typeVal === 1 ? 'active' : ''" @click="typeVal = 1">虚拟人像库</div>
<div class="flex-1 flex-center" :class="typeVal === 2 ? 'active' : ''" @click="typeVal = 2">真人人像库</div>
</div>
<div v-else class="bg-f5 h-36 flex gap-8 w-b100 rounded-8 p-4 cursor-pointer" style="width: 260px;">
<div class="flex-1 flex-center" :class="typeVal === 1 ? 'active' : ''" @click="typeVal = 1">个人资产</div>
<div class="flex-1 flex-center" :class="typeVal === 2 ? 'active' : ''" @click="typeVal = 2">团队资产</div>
</div>
<div class="min-h-400">
<div class="h-400 flex-center flex-col">
<svg t="1779342435411" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="25486" width="64" height="64">
<path
d="M625.777778 0l341.333333 307.2v648.931556c0 37.432889-33.792 67.868444-75.320889 67.868444H132.209778C90.680889 1024 56.888889 993.564444 56.888889 956.131556V67.868444C56.888889 30.435556 90.680889 0 132.209778 0H625.777778zM476.728889 747.52h-11.491556a52.337778 52.337778 0 0 0-51.768889 52.906667c0 29.240889 23.153778 52.906667 51.768889 52.906666h11.548445a52.337778 52.337778 0 0 0 51.768889-52.906666 52.337778 52.337778 0 0 0-51.768889-52.906667zM459.377778 341.333333c-30.151111 0-57.287111 4.892444-80.497778 14.620445a147.342222 147.342222 0 0 0-55.694222 39.879111c-45.795556 53.134222-38.684444 122.026667-37.717334 129.706667a47.616 47.616 0 0 0 53.020445 41.927111 48.241778 48.241778 0 0 0 41.073778-54.215111c0-0.284444-2.844444-32.881778 14.791111-53.361778 12.401778-14.392889 34.304-21.617778 65.024-21.617778 34.702222 0 57.059556 8.817778 66.503111 26.225778a44.600889 44.600889 0 0 1-3.982222 47.616l-93.184 125.383111a49.152 49.152 0 0 0 9.102222 67.868444 46.535111 46.535111 0 0 0 66.446222-9.272889l93.184-125.383111a143.246222 143.246222 0 0 0 11.377778-153.144889C590.051556 382.805333 548.807111 341.333333 459.377778 341.333333z"
fill="#e6e6e6" p-id="25487"></path>
<path
d="M941.852444 276.48L628.280889 0v217.941333c0 32.711111 29.354667 58.481778 62.236444 58.481778l251.335111 0.056889z"
fill="#e6e6e6" fill-opacity=".5" p-id="25488"></path>
</svg>
<div class="text-888 mt-10">暂无数据</div>
</div>
</div>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import IconType from './IconType.vue';
const props = defineProps({
title: {
type: String,
default: '新增',
},
})
const visible = ref(false)
const typeVal = ref(1)
const modalType = ref(1) // 1:角色 2:场景 3:道具
const open = (val: number) => {
modalType.value = val
visible.value = true
}
const close = () => {
visible.value = false
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.cirir {
border: 1px solid #ccc;
}
.active {
background: #fff;
border-radius: 8px;
}
</style>
\ No newline at end of file
This diff is collapsed.
<template>
<div>
<svg v-if="modalType === 1" t="1779678288103" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="12193" width="24" height="24">
<path
d="M512 597.333333a298.666667 298.666667 0 1 1 298.666667-298.666666 298.666667 298.666667 0 0 1-298.666667 298.666666z m0-512a213.333333 213.333333 0 1 0 213.333333 213.333334A213.333333 213.333333 0 0 0 512 85.333333z"
fill="#3f3f51" p-id="12194"></path>
<path
d="M855.04 1024H168.96a125.013333 125.013333 0 0 1-106.666667-59.946667 128 128 0 0 1-5.973333-126.08 514.773333 514.773333 0 0 1 231.893333-231.893333 84.053333 84.053333 0 0 1 97.706667 16.64L512 752l126.08-129.28a84.053333 84.053333 0 0 1 97.706667-16.64 514.773333 514.773333 0 0 1 231.893333 231.893333 128 128 0 0 1-5.973333 126.08 125.013333 125.013333 0 0 1-106.666667 59.946667zM324.693333 682.666667a436.693333 436.693333 0 0 0-192 193.706666 43.733333 43.733333 0 0 0 2.133334 42.666667 39.893333 39.893333 0 0 0 34.133333 19.626667h686.08a39.893333 39.893333 0 0 0 34.133333-19.626667 43.733333 43.733333 0 0 0 2.133334-42.666667 429.44 429.44 0 0 0-192-193.066666l-127.36 129.493333a83.413333 83.413333 0 0 1-119.893334 0z m343.893334-29.866667z"
fill="#3f3f51" p-id="12195"></path>
</svg>
<svg v-if="modalType === 2" t="1779678634023" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="13327" width="24" height="24">
<path d="M98.88 219.824a107.824 106.064 90 1 0 212.128 0 107.824 106.064 90 1 0-212.128 0Z" p-id="13328"
fill="#3f3f51"></path>
<path
d="M238.8 525.2c78.704 0 154.816 193.904 261.92 193.904 107.12 0 140.832-326.592 262.352-326.592 121.536 0 214.8 260.384 247.296 372.896 32.512 112.512-4.672 148.32-168.928 148.32-164.272 0-685.904-7.024-751.296-7.024-65.408 0-104.8-49.28-60.192-144.24 44.592-94.976 130.144-237.28 208.848-237.28z"
p-id="13329" fill="#3f3f51"></path>
</svg>
<svg v-if="modalType === 3" t="1779678737829" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="16155" width="24" height="24">
<path
d="M483.84 579.67a39.936 39.936 0 0 1 56.49 0l352 352a39.936 39.936 0 0 1-56.49 56.49l-352-352a39.936 39.936 0 0 1 0-56.49z m44.459-429.825a75.35 75.35 0 0 1 121.173 61.867l-4.95 187.904L799.66 506.197a75.35 75.35 0 0 1-21.334 134.315l-65.109 19.37a40.107 40.107 0 0 1-22.699-76.629l55.723-16.64-157.013-107.861a57.856 57.856 0 0 1-24.918-49.067l4.864-190.378-151.04 115.968a57.685 57.685 0 0 1-54.357 8.533l-179.627-63.573 63.659 179.541a57.856 57.856 0 0 1-8.704 54.443l-115.968 151.04 190.464-4.864a57.856 57.856 0 0 1 49.152 25.002L470.528 842.24l16.64-55.637a40.107 40.107 0 1 1 76.63 22.698l-19.286 64.939a75.35 75.35 0 0 1-134.315 21.333l-106.666-154.88-187.904 4.95a75.35 75.35 0 0 1-61.782-121.174l114.347-149.333-62.635-177.237-2.986-11.179a75.35 75.35 0 0 1 99.157-84.992l177.323 62.72 149.333-114.517zM894.89 289.11c0-1.45 2.218-1.45 2.218 0C903.083 320 928 344.832 958.891 350.891c1.536 0 1.536 2.218 0 2.218a78.933 78.933 0 0 0-61.782 61.782c0 1.45-2.218 1.45-2.218 0a78.933 78.933 0 0 0-61.782-61.782c-1.45 0-1.45-2.218 0-2.218a78.933 78.933 0 0 0 61.782-61.782zM798.037 1.963c0-2.56 3.926-2.56 3.926 0A138.24 138.24 0 0 0 910.08 109.995c2.56 0 2.56 3.925 0 3.925a138.24 138.24 0 0 0-108.117 108.117c0 2.56-3.926 2.56-3.926 0A138.24 138.24 0 0 0 690.005 113.92c-2.645 0-2.645-3.84 0-3.925A138.24 138.24 0 0 0 798.037 1.963z"
p-id="16156" fill="#3f3f51"></path>
</svg>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
modalType: {
type: Number,
default: 1,
},
})
</script>
\ No newline at end of file
<template>
<el-dialog v-model="visible" width="600">
<template #header="{ close, titleId, titleClass }">
<div class="flex-align-center gap-8 mb-10">
<div class="cirir flex-center w-48 h-48 rounded-8">
<IconType :modalType="modalType" />
</div>
<span class="fs-18">{{ title }}选择</span>
</div>
</template>
<template #footer>
<div class="flex-align-center justify-end">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="close">确定</el-button>
</div>
</template>
<el-upload class="avatar-uploader mt-20" action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
:show-file-list="false">
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<div v-else class="flex-center flex-col line-h24 fs-12">
<el-icon size="20">
<Plus />
</el-icon>
<span class="mt-10 text-333"> 点击或拖拽图片到此处上传 </span>
<span>仅支持 JPG, PNG 格式</span>
<span>最大文件限制在 20MB 内</span>
</div>
</el-upload>
<div class="text-center mt-20 mb-40">支持 JPG、PNG 格式,单个文件不超过 20MB</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import IconType from './IconType.vue';
const props = defineProps({
title: {
type: String,
default: '新增',
},
})
const visible = ref(false)
const imageUrl = ref('')
const modalType = ref(1) // 1:角色 2:场景 3:道具
const open = (val: number) => {
modalType.value = val
visible.value = true
}
const close = () => {
visible.value = false
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.cirir {
border: 1px solid #ccc;
}
.avatar-uploader {
width: 100%;
:deep(.el-upload) {
border: 2px dashed #ddd;
width: 100%;
height: 240px;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s;
&:hover {
border-color: #c5c5c5;
}
}
}
</style>
\ No newline at end of file
<template>
<div v-if="true" class="flex h-b100 gap-10">
<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-36 h-36 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>
</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>
</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: 74px">
</div>
</div>
<div class="">
<div class="flex-between-center">
<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>
<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-26 rounded-8"
@click="isShowtip = false">保存</el-button>
</div>
</div>
<div class="flex-align-center h-30 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>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Plus } from '@element-plus/icons-vue'
const isShowtip = ref(true)
const aiTypeVal = ref('1')
const secondVal = ref(5)
const options1 = [
{
value: '1',
label: 'DouBao-hahyha-1.0',
},
{
value: '2',
label: 'DouBao-hahyha-12.0'
},
]
const options2 = [
{
value: 1,
label: '1张',
},
{
value: 2,
label: '2张',
},
{
value: 4,
label: '4张',
},
{
value: 9,
label: '9张',
},
]
const fileList = ref([
{
name: 'food.jpeg',
url: 'https://res.volccdn.com/obj/volc-console-fe/dramart/static/image/PIC3.22e42366.png',
},
{
name: 'food1.jpeg',
url: 'https://res.volccdn.com/obj/volc-console-fe/dramart/static/image/PIC3.22e42366.png',
}
])
const delImg = (index: number) => {
fileList.value.splice(index, 1)
}
const videoIndex = ref(0)
const changeVideo = (item: any, index: number) => {
videoIndex.value = index
}
</script>
<style scoped lang="scss">
.card1 {
border: 1px solid #5252ff;
box-shadow: 0px 0px 3px 1px rgba(177, 177, 255, 1.3);
.imgbox {
.del {
display: none;
}
&:hover {
.del {
display: inline-block;
}
}
}
/* 控制上传卡片的大小 */
.custom-upload :deep(.el-upload--picture-card) {
width: 36px;
height: 36px;
--el-upload-picture-card-size: 36px;
/* 修改 Element Plus 变量 */
}
.hint {
border: 1px solid #e5e7eb;
border-radius: 8px;
}
.jinbi {
background-color: #5252ff;
&:hover {
background-color: #4747e7;
}
}
}
.bg-2b303a {
background-color: #2b303a;
}
.custom {
outline: none;
box-shadow: none;
border-color: transparent;
}
.fjitem {
border: 1px solid #ddd;
padding: 1px;
&.active {
border: 1px solid #5252ff;
}
}
:deep(.el-select__wrapper) {
min-height: 30px;
border-radius: 8px;
}
</style>
<template>
<div></div>
<section class="flex flex-col h-b100 flex-1 px-20 pt-20">
<div class="flex-1 flex flex-col h-b100 overflow-hidden">
<div class="bg-000 rounded-16 flex-center flex-1 h-b100 overflow-hidden">
<div class="h-b100 w-b100 flex-center">
<div class="h-b100 w-b100 flex-between-center bg-000 rounded-16 relative">
<div class="h-b100 w-b100 flex-center relative">
<div class="h-b100 w-b100 flex-center" style="aspect-ratio: 16 / 9;">
<video ref="videoRef" class="h-b100 bg-000" autoplay :playsinline="true" :x5-playsinline="true"
:webkit-playsinline="true" mediatype="video" :data-index="-1"
data-xgplayerid="652d97a3-98b8-485d-8e83-5768aafe0f07" src="@/static/imgs/mp4.mp4"
@timeupdate="onTimeUpdate" @loadedmetadata="onLoadedMetadata" @ended="handleEnded"></video>
</div>
</div>
<el-button class="absolute right-20 top-20" @click="$emit('next', 2)">编辑</el-button>
</div>
</div>
</div>
<div class="bg-f5 h-64 flex-center pr-100 py-12">
<div>
<span class="current-time">{{ formatTime(currentTime) }}</span> /
<span class="duration-time" style="color: #3f3f51;">{{ formatTime(duration) }}</span>
</div>
<div class="flex-center ml-20 gap-10">
<svg t="1779505622021" class="icon cursor-pointer" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="16499" width="20" height="20">
<path
d="M356.77 605.22L701.8 849.53c69.8 49.42 166.29-0.49 166.29-86.01V261.25c0-85.52-96.49-135.43-166.29-86.01L356.77 419.55c-64.02 45.34-64.02 140.34 0 185.67zM210.42 154.36c30.38 0 55 24.62 55 55v606.07c0 30.38-24.62 55-55 55s-55-24.62-55-55V209.36c0-30.38 24.62-55 55-55z"
p-id="16500" fill="#3f3f51"></path>
</svg>
<button class="ctrl-btn w-40 h-40 flex-center rounded-100 cursor-pointer" @click="togglePlay"
:title="isPlaying ? '暂停' : '播放'">
<svg v-if="isPlaying" t="1779505259978" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="4322" width="20" height="20">
<path
d="M288 768V213.333333a53.333333 53.333333 0 0 1 106.666667 0v554.666667a53.333333 53.333333 0 1 1-106.666667 0zM629.333333 768V213.333333a53.333333 53.333333 0 1 1 106.666667 0v554.666667a53.333333 53.333333 0 1 1-106.666667 0z"
fill="#ffffff" p-id="4323"></path>
</svg>
<svg v-else t="1779505357927" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="14047" width="20" height="20">
<path
d="M512-292.39808158C69.5810551-292.39808158-292.39808158 69.5810551-292.39808158 512s361.97913673 804.39808158 804.39808158 804.39808158 804.39808158-361.97913673 804.39808158-804.39808158S954.4189449-292.39808158 512-292.39808158z m0 1541.76298917C106.44930106 1249.36490759-225.36490759 917.55069894-225.36490759 512S106.44930106-225.36490759 512-225.36490759s737.36490759 331.81420868 737.36490759 737.36490759-331.81420868 737.36490759-737.36490759 737.36490759z"
p-id="14048" fill="#ffffff"></path>
<path
d="M763.37440051 401.39526378l-268.13269438-177.63791024c-90.49478419-60.32985613-167.58293419-20.10995202-167.58293265 90.49478423v402.19904074c0 110.60473622 73.73649031 150.82464031 167.58293265 90.49478421l268.13269438-177.63790864c90.49478419-67.03317396 90.49478419-167.58293419 0-227.9127903z"
p-id="14049" fill="#ffffff"></path>
</svg>
</button>
<svg t="1779505654665" class="icon cursor-pointer" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="17600" width="20" height="20">
<path
d="M665.47 417.65l-345.03-244.3c-69.8-49.42-166.29 0.49-166.29 86.01v502.27c0 85.52 96.49 135.43 166.29 86.01l345.03-244.31c64.02-45.34 64.02-140.34 0-185.68zM811.82 868.52c-30.38 0-55-24.62-55-55V207.46c0-30.38 24.62-55 55-55s55 24.62 55 55v606.07c0 30.37-24.62 54.99-55 54.99z"
p-id="17601" fill="#3f3f51"></path>
</svg>
</div>
</div>
</div>
<div class="min-h-170 mt-20 flex rounded-16 bg-fff progress p-10">
<div class="w-30 mr-10"></div>
<div class="progress-track" ref="progressTrack" @click="seekVideo" @mousemove="handleHoverMove"
@mouseleave="hoverTime = null">
<!-- 时间刻度 -->
<div class="flex">
<div class="mr-10">00:00</div>
<div class="flex-1 flex-between-center" v-for="n in 6" :key="n">
<div class="w-2 h-6 bg-888 rounded-4" v-for="k in 8" :key="k"></div>
<span class="pr-10">00:00</span>
</div>
</div>
<!-- 拖动滑块 (圆点) -->
<!-- 拖动滑块 (圆点) -->
<div class="progress-thumb" :style="{ left: progressPercentage + '%' }"></div>
<div class="flex mt-20 gap-4 pr-20">
<div v-for="n in 6" class="fjvideo rounded-8 p-10" :style="{ width: 100 / 6 + '%' }">
<div class="fs-12" style="color: #6e718c;">分镜 {{ n }} · 00:10 <span
class="tag fs-10 py-4 px-4 ml-10 rounded-4">视频</span></div>
<div class="bg-img w-b100 h-60 mt-10 rounded-8"></div>
</div>
</div>
</div>
</div>
<div class="py-10 text-888 text-center">平台内容均由人工智能模型生成,不代表平台立场</div>
</section>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped></style>
\ No newline at end of file
<script setup lang="ts">
import { ref, computed } from 'vue';
const indexVal = ref(0)
const isPlaying = ref(false)
const videoRef: any = ref(null);
const currentTime = ref(0);
const duration = ref(0);
const progressPercent = ref(0);
const hoverPercent = ref(0) // 悬停时的百分比
const hoverTime: any = ref(null) // 悬停时的时间
// 切换集数
const changeJi = (item: any, index: number) => {
indexVal.value = index
}
// ----- 计算属性 -----
const progressPercentage = computed(() => {
if (duration.value === 0) return 0
return (currentTime.value / duration.value) * 100
})
// 视频播放
const togglePlay = () => {
if (!videoRef.value) return;
if (videoRef.value.paused) {
videoRef.value.play();
isPlaying.value = true;
} else {
videoRef.value.pause();
isPlaying.value = false;
}
};
const formatTime = (seconds: number) => {
if (isNaN(seconds)) return '00:00';
const hrs = Math.floor(seconds / 3600);
const mins = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
if (hrs > 0) {
return `${hrs.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
};
// 更新进度百分比
const updateProgress = () => {
if (duration.value > 0) {
const percent = (currentTime.value / duration.value) * 100;
progressPercent.value = percent;
} else {
progressPercent.value = 0;
}
};
// 总时间
const onLoadedMetadata = () => {
if (videoRef.value) {
duration.value = videoRef.value.duration;
updateProgress();
}
};
// 当前时间
const onTimeUpdate = () => {
if (videoRef.value) {
currentTime.value = videoRef.value.currentTime;
updateProgress();
}
};
// 4. 播放结束重置
const handleEnded = () => {
isPlaying.value = false
currentTime.value = 0 // 或者保持结束位置
}
// 6. 点击进度条跳转
const seekVideo = (event: any) => {
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: any) => {
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 lang="scss" scoped>
.aside {
min-width: 60px;
border-right: 1px solid #eee;
.jj {
border: 1px solid #ddd;
&.active {
border: 1px solid #5252ff;
background: #5252ff;
color: #fff;
}
}
}
.ctrl-btn {
background: #3f3f51;
border: none;
}
/* 进度条轨道 */
.progress-track {
flex-grow: 1;
height: 6px;
/* 更细的轨道 */
// background: rgba(1, 255, 56, 0.3);
/* 半透明灰 */
border-radius: 4px;
position: relative;
cursor: pointer;
height: 100px;
}
/* 滑块 (圆点) - 核心视觉 */
.progress-thumb {
position: absolute;
top: 4px;
width: 7px;
height: 140px;
background: #ff0000;
background: url('@/static/imgs/zhen.png') no-repeat center;
background-size: 100% 100%;
transition: opacity 0.2s;
}
.progress {
border: 1px solid #eee;
}
.fjvideo {
border: 1px solid #f0f2fa;
height: 106px;
background-color: #fafbfd;
.bg-img {
background: url('@/static/imgs/bg1.png');
background-size: auto;
}
.tag {
background-color: #ebedff;
color: #5252ff;
}
}
</style>
\ No newline at end of file
<template>
<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 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' : ''">
{{ index + 1 }}</div>
<section class="flex flex-col w-b100 box">
<div class="flex-between-center py-20 px-36">
<span class="bg-fff py-6 px-14 rounded-4 boxshadow-1">分镜表</span>
<div class="flex gap-10">
<el-select v-model="aiTypeVal" placeholder="Select" style="width: 200px;">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-button class="hover">
<svg t="1779679636879" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="19134" width="16" height="16">
<path
d="M296.533333 712.832a42.666667 42.666667 0 0 1 0 60.330667l-90.538666 90.538666a42.666667 42.666667 0 0 1-60.330667 0l-30.165333-30.165333a42.666667 42.666667 0 0 1 60.330666-60.373333l60.373334-60.330667a42.666667 42.666667 0 0 1 60.330666 0zM896 768a42.666667 42.666667 0 0 1 0 85.333333H426.666667a42.666667 42.666667 0 0 1 0-85.333333h469.333333zM296.533333 414.165333a42.666667 42.666667 0 0 1 0 60.330667l-90.538666 90.538667a42.666667 42.666667 0 0 1-60.330667 0l-30.165333-30.165334a42.666667 42.666667 0 0 1 60.330666-60.373333l60.373334-60.330667a42.666667 42.666667 0 0 1 60.330666 0zM896 469.333333a42.666667 42.666667 0 0 1 0 85.333334H426.666667a42.666667 42.666667 0 0 1 0-85.333334h469.333333zM296.533333 115.498667a42.666667 42.666667 0 0 1 0 60.330666L205.994667 266.368a42.666667 42.666667 0 0 1-60.330667 0l-30.165333-30.165333A42.666667 42.666667 0 0 1 175.829333 175.786667l60.373334-60.330667a42.666667 42.666667 0 0 1 60.330666 0zM896 170.666667a42.666667 42.666667 0 0 1 0 85.333333H426.666667a42.666667 42.666667 0 1 1 0-85.333333h469.333333z"
fill="#3f3f51" p-id="19135"></path>
</svg><span class="ml-4">批量生视频</span></el-button>
</div>
</section>
<section class="flex flex-col w-b100 box">
<div class="flex-between-center py-20 px-36">
<span class="bg-fff py-6 px-14 rounded-4 boxshadow-1">分镜表</span>
<div class="flex gap-10">
<el-select v-model="aiTypeVal" placeholder="Select" style="width: 200px;">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-button :icon="DocumentCopy" class="hover">批量生成</el-button>
</div>
</div>
<div class="flex-1 overflow-y-auto px-36 hide-scrollbar">
<div class="fw-bold">第1集 凌晨的咖啡与雨</div>
<div class="fs-12 text-666 mt-4">
林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。
<el-popover placement="bottom" :width="400">
<template #reference>
<el-button text><span class="fs-12">详情</span></el-button>
</template>
<div class="max-h-200 overflow-y-auto">
<p>林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。</p>
<p>林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。</p>
<p>林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。</p>
</div>
</el-popover>
</div>
<div class="flex-1 overflow-y-auto px-36 hide-scrollbar">
<div class="fw-bold">第1集 凌晨的咖啡与雨</div>
<div class="fs-12 text-666 mt-4">
林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。
<el-popover placement="bottom" :width="400">
<template #reference>
<el-button text ><span class="fs-12">详情</span></el-button>
</template>
<div class="max-h-200 overflow-y-auto">
<p>林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。</p>
<p>林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。</p>
<p>林夏在雨夜来到便利店,与店员阿哲交谈。她倾诉人际关系的疲惫与困惑,阿哲以温和的话语给予慰藉。</p>
</div>
</el-popover>
</div>
<div v-for="(item, index) in 2" :key="index" class="pb-20">
<Episode />
</div>
</div>
</section>
<Episode />
</div>
</section>
</template>
<script setup lang="ts">
......@@ -46,7 +39,6 @@ import { ref } from 'vue';
import { DocumentCopy } from '@element-plus/icons-vue'
import Episode from './Episode.vue';
const indexVal = ref(0)
const aiTypeVal = ref('')
const options = [
......@@ -60,6 +52,12 @@ const options = [
},
]
const changeJi = (item: any, index: number) => {
indexVal.value = index
}
</script>
<style lang="scss" scoped>
.aside {
......
<template>
<section class="flex h-b100">
<section class="aside flex-align-center flex-col">
<span class="py-16">集数</span>
<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' : ''" @click="changeJi(item, index)">
{{ index + 1 }}</div>
</div>
</section>
<StepThree v-if="stepVal === 2" />
<StepFour v-if="stepVal === 3" />
</section>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import StepThree from './StepThree.vue';
import StepFour from './StepFour.vue';
const props = defineProps({
stepVal: {
type: Number,
default: 2
}
})
const indexVal = ref(0)
const changeJi = (item: any, index: number) => {
indexVal.value = index
}
</script>
<style lang="scss" scoped>
.aside {
width: 60px;
border-right: 1px solid #eee;
.jj {
border: 1px solid #ddd;
&.active {
border: 1px solid #5252ff;
background: #5252ff;
color: #fff;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="fixed top-0 left-0 w-b100 h-b100 bg-000" :style="{display: visible ? 'block': 'none'}" @click="close">
<div class="h-36 w-36 rounded-44 bg-000 flex-center cursor-pointer absolute top-30 right-30" @click="close">
<el-icon size="18" color="#fff"><Close /></el-icon>
</div>
<div class="h-b100 flex-center">
<video :src="src" controls class="vw" @click.stop></video>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { Close } from '@element-plus/icons-vue'
const props = defineProps({
src: {
type: String,
default: ''
}
})
const visible = ref(false)
const open = () => {
visible.value = true
}
const close = () => {
visible.value = false
}
defineExpose({
open,
close
})
</script>
<style scoped lang="scss">
.bg-000 {
background: rgba(0, 0, 0, 0.6);
z-index: 9999;
}
.vw {
width: 70%;
}
</style>
\ No newline at end of file
<template>
<div class="flex flex-col h-b100">
<DramaHeader @change-tab="changeTab" :indexVal="indexVal" />
<DramaHeader @change-tab="changeTab" :indexVal="stepVal" />
<div class="flex-1 overflow-y-auto">
<StepOne v-if="indexVal === 0" @next="next" />
<StepTwo v-if="indexVal === 1" @next="next" />
<StepThree v-if="indexVal === 2" />
<StepFour v-if="indexVal === 3" />
<StepOne v-if="stepVal === 0" @next="next" />
<StepTwo v-if="stepVal === 1" @next="next" />
<StepThreeFour v-if="stepVal === 2 || stepVal === 3" :stepVal="stepVal" @next="next"/>
</div>
</div>
</template>
......@@ -14,16 +13,15 @@ import { ref } from 'vue';
import DramaHeader from './components/DramaHeader.vue';
import StepOne from './components/StepOne.vue';
import StepTwo from './components/StepTwo.vue';
import StepThree from './components/StepThree.vue';
import StepFour from './components/StepFour.vue';
import StepThreeFour from './components/StepThreeFour.vue';
const indexVal = ref(2);
const stepVal = ref(1);
const changeTab = (val: number) => {
indexVal.value = val;
stepVal.value = val;
}
const next = (val: number) => {
indexVal.value = val;
stepVal.value = val;
}
......
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