fix: 参数选择改到参数文件
This commit is contained in:
parent
4bba35a426
commit
5ae8614b1d
|
|
@ -3,41 +3,27 @@
|
||||||
<header class="vg-hero">
|
<header class="vg-hero">
|
||||||
<div class="vg-hero-text">
|
<div class="vg-hero-text">
|
||||||
<h1 class="vg-hero-title">视频生成</h1>
|
<h1 class="vg-hero-title">视频生成</h1>
|
||||||
<p class="vg-hero-desc">文生视频、图生视频,选择模型后生成成片</p>
|
<p class="vg-hero-desc">左侧选择生成模式,编辑描述与参考素材后生成成片</p>
|
||||||
</div>
|
|
||||||
<div class="vg-type-select" @click.stop>
|
|
||||||
<span class="vg-hero-mode-label">生成模式</span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="vg-type-trigger"
|
|
||||||
:class="{ 'is-open': typeMenuOpen }"
|
|
||||||
@click.stop="typeMenuOpen = !typeMenuOpen"
|
|
||||||
:aria-expanded="typeMenuOpen">
|
|
||||||
<span class="vg-type-label">{{ videoModeLabel }}</span>
|
|
||||||
<svg class="vg-type-chevron" width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.01 7.982A1.2 1.2 0 0 1 21 9.679l-8.156 8.06a1.2 1.2 0 0 1-1.688 0L3 9.68a1.2 1.2 0 0 1 1.687-1.707L12 15.199l7.313-7.227a1.2 1.2 0 0 1 1.697.01Z" fill="currentColor" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<transition name="vg-fade">
|
|
||||||
<div v-show="typeMenuOpen" class="vg-type-dropdown">
|
|
||||||
<div class="vg-type-dropdown-bg" />
|
|
||||||
<ul class="vg-type-options" role="listbox">
|
|
||||||
<li
|
|
||||||
v-for="opt in videoModeOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:class="['vg-type-option', { active: videoMode === opt.value }]"
|
|
||||||
role="option"
|
|
||||||
@click="pickVideoMode(opt.value)">
|
|
||||||
{{ opt.label }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="vg-body">
|
<div class="vg-body">
|
||||||
<!-- 左侧:生成器 -->
|
<!-- 最左:生成模式 -->
|
||||||
|
<aside class="vg-left-rail">
|
||||||
|
<p class="vg-rail-title">生成模式</p>
|
||||||
|
<ul class="vg-mode-list" role="list">
|
||||||
|
<li
|
||||||
|
v-for="opt in videoModeOptions"
|
||||||
|
:key="opt.value"
|
||||||
|
:class="['vg-mode-item', { active: videoMode === opt.value }]"
|
||||||
|
role="listitem"
|
||||||
|
@click="pickVideoMode(opt.value)">
|
||||||
|
{{ opt.label }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- 中间:生成器 -->
|
||||||
<div class="vg-generator">
|
<div class="vg-generator">
|
||||||
<div class="vg-generator-inner">
|
<div class="vg-generator-inner">
|
||||||
<!-- 参考上传区(图生视频);文生视频时显示轻量占位 -->
|
<!-- 参考上传区(图生视频);文生视频时显示轻量占位 -->
|
||||||
|
|
@ -47,39 +33,41 @@
|
||||||
<div v-if="isImageVideoMode" class="vg-ref-content">
|
<div v-if="isImageVideoMode" class="vg-ref-content">
|
||||||
<div class="vg-ref-tilt">
|
<div class="vg-ref-tilt">
|
||||||
<div class="upload-inner">
|
<div class="upload-inner">
|
||||||
<div class="upload-title">
|
<template v-if="videoMode === 'image-reference'">
|
||||||
<div class="upload-title-left">
|
<div class="upload-title">
|
||||||
{{ imageUploadPrimaryLabel }}
|
<div class="upload-title-left">参考图</div>
|
||||||
|
<div class="upload-title-tip">
|
||||||
|
请使用下方编辑器工具栏「插入参考素材」添加图片(此处不再单独上传)
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="upload-title-tip">
|
</template>
|
||||||
{{ $t('common.uploadImageTip') || '支持PNG/JPG,最大10MB' }}
|
<template v-else>
|
||||||
</div>
|
<div class="upload-title">
|
||||||
</div>
|
<div class="upload-title-left">
|
||||||
<mf-image-upload
|
{{ imageUploadPrimaryLabel }}
|
||||||
v-if="videoMode !== 'image-reference'"
|
</div>
|
||||||
listType="picture-card"
|
<div class="upload-title-tip">
|
||||||
uploadHeight="140px"
|
{{ $t('common.uploadImageTip') || '支持PNG/JPG,最大10MB' }}
|
||||||
:show-file-list="false"
|
</div>
|
||||||
:content="$t('common.uploadFirstPlaceholder') || '点击上传'"
|
|
||||||
v-model="firstUrl" />
|
|
||||||
<mf-image-upload
|
|
||||||
v-else
|
|
||||||
listType="picture-card"
|
|
||||||
uploadHeight="140px"
|
|
||||||
:show-file-list="false"
|
|
||||||
:content="'上传参考图'"
|
|
||||||
v-model="referenceUrl" />
|
|
||||||
<div class="last-frame" v-if="videoMode === 'image-first-last-frame'">
|
|
||||||
<div class="upload-title-left">
|
|
||||||
{{ $t('common.uploadLastPlaceholder') || '尾帧(可选)' }}
|
|
||||||
</div>
|
</div>
|
||||||
<mf-image-upload
|
<mf-image-upload
|
||||||
listType="picture-card"
|
listType="picture-card"
|
||||||
uploadHeight="100px"
|
uploadHeight="140px"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:content="$t('common.uploadLastPlaceholder') || '上传尾帧'"
|
:content="$t('common.uploadFirstPlaceholder') || '点击上传'"
|
||||||
v-model="lastUrl" />
|
v-model="firstUrl" />
|
||||||
</div>
|
<div class="last-frame" v-if="videoMode === 'image-first-last-frame'">
|
||||||
|
<div class="upload-title-left">
|
||||||
|
{{ $t('common.uploadLastPlaceholder') || '尾帧(可选)' }}
|
||||||
|
</div>
|
||||||
|
<mf-image-upload
|
||||||
|
listType="picture-card"
|
||||||
|
uploadHeight="100px"
|
||||||
|
:show-file-list="false"
|
||||||
|
:content="$t('common.uploadLastPlaceholder') || '上传尾帧'"
|
||||||
|
v-model="lastUrl" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -96,31 +84,54 @@
|
||||||
|
|
||||||
<div class="vg-main-column">
|
<div class="vg-main-column">
|
||||||
<div class="rich-editor-container">
|
<div class="rich-editor-container">
|
||||||
<RichTextEditor
|
<VideoRichEditor
|
||||||
v-model="editorContent"
|
ref="videoRichEditor"
|
||||||
|
:show-toolbar="videoMode !== 'text-to-video'"
|
||||||
|
@text-change="bumpEditorVisualTick"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('common.textVideoPlaceholder') ||
|
$t('common.textVideoPlaceholder') ||
|
||||||
'描述画面与动态,例如:阳光下的女孩在海边起舞…'
|
'描述画面与动态,例如:阳光下的女孩在海边起舞…'
|
||||||
"
|
"
|
||||||
:uploaded-images="uploadedImages"
|
|
||||||
@text-change="handleTextChange"
|
|
||||||
@image-upload="handleImageUpload"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="vg-toolbar">
|
<div class="vg-toolbar">
|
||||||
<div class="vg-toolbar-settings">
|
<div class="vg-toolbar-settings">
|
||||||
<div class="vg-model-wrap">
|
<div class="vg-params-row">
|
||||||
<span class="vg-model-icon" aria-hidden="true">
|
<div class="vg-param">
|
||||||
<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<span class="vg-param-label">模型</span>
|
||||||
<path fill="currentColor" d="M11.805 5.786c1.25-.926 2.193-1.373 2.471-1.096.489.488-1.261 3.03-3.909 5.677-4.33 4.331-6.715 8.968-5.326 10.358.29.29.723.416 1.264.394.421.017.92-.07 1.48-.249-2.117.9-3.859 1.005-4.76.104-1.874-1.874.61-7.402 5.553-12.353l.022-.02c.03-.032.062-.063.093-.094l.065-.064.11-.108c.97-.95 1.96-1.804 2.937-2.549Zm5.55 11.57c1.532-1.531 3.2-2.347 3.725-1.822.525.525-.29 2.192-1.822 3.724-1.532 1.531-3.2 2.347-3.725 1.822-.524-.525.291-2.192 1.822-3.724Z" />
|
<a-select
|
||||||
</svg>
|
v-model="selectedModel"
|
||||||
</span>
|
class="vg-param-select"
|
||||||
<a-select v-model="selectedModel" class="vg-model-select">
|
placeholder="请选择模型"
|
||||||
<a-option v-for="option in modelOptions" :key="option.value" :value="option.value">
|
allow-clear>
|
||||||
{{ option.label }}
|
<a-option v-for="opt in modelOptions" :key="opt.value" :value="opt.value">
|
||||||
</a-option>
|
{{ opt.label }}
|
||||||
</a-select>
|
</a-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
<div class="vg-param">
|
||||||
|
<span class="vg-param-label">比例</span>
|
||||||
|
<a-select v-model="selectedRatio" class="vg-param-select" placeholder="画幅比例" allow-clear>
|
||||||
|
<a-option v-for="r in ratioOptions" :key="r" :value="r">{{ r }}</a-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
<div class="vg-param">
|
||||||
|
<span class="vg-param-label">时长</span>
|
||||||
|
<a-select v-model="selectedDuration" class="vg-param-select" placeholder="秒" allow-clear>
|
||||||
|
<a-option v-for="d in durationOptions" :key="d" :value="d">{{ d }} 秒</a-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
<div class="vg-param">
|
||||||
|
<span class="vg-param-label">分辨率</span>
|
||||||
|
<a-select
|
||||||
|
v-model="selectedResolution"
|
||||||
|
class="vg-param-select"
|
||||||
|
placeholder="分辨率"
|
||||||
|
allow-clear>
|
||||||
|
<a-option v-for="r in resolutionOptions" :key="r" :value="r">{{ r }}</a-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="vg-toolbar-actions">
|
<div class="vg-toolbar-actions">
|
||||||
|
|
@ -210,8 +221,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import VideoRichEditor from '@/components/VideoRichEditor.vue'
|
||||||
import RichTextEditor from '@/components/RichTextEditor.vue'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'VideoGen',
|
name: 'VideoGen',
|
||||||
|
|
@ -227,8 +237,7 @@ export default {
|
||||||
],
|
],
|
||||||
firstUrl: '',
|
firstUrl: '',
|
||||||
lastUrl: '',
|
lastUrl: '',
|
||||||
referenceUrl: '',
|
editorVisualTick: 0,
|
||||||
editorContent: '',
|
|
||||||
interval: null,
|
interval: null,
|
||||||
videoUrl: null,
|
videoUrl: null,
|
||||||
videoLoading: false,
|
videoLoading: false,
|
||||||
|
|
@ -237,29 +246,25 @@ export default {
|
||||||
showResult: false,
|
showResult: false,
|
||||||
price: null,
|
price: null,
|
||||||
id: null,
|
id: null,
|
||||||
modelOptions: [
|
modelOptions: [],
|
||||||
{ label: 'Seedance 2.0', value: 'ep-20260326165811-dlkth' },
|
ratioOptions: [],
|
||||||
{ label: 'Seedance 2.0 Fast', value: 'ep-20260326170056-dkj9m' }
|
durationOptions: [],
|
||||||
],
|
resolutionOptions: [],
|
||||||
selectedModel: 'ep-20260326165811-dlkth',
|
selectedModel: '',
|
||||||
uploadedImages: [],
|
selectedRatio: '',
|
||||||
|
selectedDuration: null,
|
||||||
|
selectedResolution: '',
|
||||||
maxPollAttempts: 40,
|
maxPollAttempts: 40,
|
||||||
typeMenuOpen: false,
|
|
||||||
taskRows: []
|
taskRows: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
RichTextEditor
|
VideoRichEditor
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['lang']),
|
|
||||||
canCancel() {
|
canCancel() {
|
||||||
return !!this.videoId && !this.videoUrl
|
return !!this.videoId && !this.videoUrl
|
||||||
},
|
},
|
||||||
videoModeLabel() {
|
|
||||||
const o = this.videoModeOptions.find((x) => x.value === this.videoMode)
|
|
||||||
return o ? o.label : '文生视频'
|
|
||||||
},
|
|
||||||
isImageVideoMode() {
|
isImageVideoMode() {
|
||||||
return this.videoMode !== 'text-to-video'
|
return this.videoMode !== 'text-to-video'
|
||||||
},
|
},
|
||||||
|
|
@ -269,7 +274,12 @@ export default {
|
||||||
return this.$t('common.uploadFirstImage') || '上传首帧'
|
return this.$t('common.uploadFirstImage') || '上传首帧'
|
||||||
},
|
},
|
||||||
posterUrl() {
|
posterUrl() {
|
||||||
const f = this.videoMode === 'image-reference' ? this.referenceUrl : this.firstUrl
|
void this.editorVisualTick
|
||||||
|
if (this.videoMode === 'image-reference') {
|
||||||
|
const url = this.firstReferenceImageUrlFromEditor()
|
||||||
|
return url || ''
|
||||||
|
}
|
||||||
|
const f = this.firstUrl
|
||||||
if (!f) return ''
|
if (!f) return ''
|
||||||
return typeof f === 'object' ? (f.url || '') : f
|
return typeof f === 'object' ? (f.url || '') : f
|
||||||
}
|
}
|
||||||
|
|
@ -277,33 +287,39 @@ export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadPriceInfo()
|
this.loadPriceInfo()
|
||||||
this.loadTaskList()
|
this.loadTaskList()
|
||||||
document.addEventListener('click', this.onDocClick)
|
this.loadVideoParams()
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
this.destroyInterval()
|
this.destroyInterval()
|
||||||
document.removeEventListener('click', this.onDocClick)
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onDocClick() {
|
plainPromptText() {
|
||||||
this.typeMenuOpen = false
|
return this.$refs.videoRichEditor?.getPlainText?.() || ''
|
||||||
},
|
},
|
||||||
|
|
||||||
|
bumpEditorVisualTick() {
|
||||||
|
this.editorVisualTick++
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 编辑器内插入的参考图 URL(与 getContentItems 一致) */
|
||||||
|
firstReferenceImageUrlFromEditor() {
|
||||||
|
const items = this.$refs.videoRichEditor?.getContentItems?.() || []
|
||||||
|
for (const i of items) {
|
||||||
|
if (i.type === 'image_url' && i.image_url?.url) {
|
||||||
|
if (!i.role || i.role === 'reference_image') return i.image_url.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
|
||||||
pickVideoMode(m) {
|
pickVideoMode(m) {
|
||||||
this.videoMode = m
|
this.videoMode = m
|
||||||
this.firstUrl = ''
|
this.firstUrl = ''
|
||||||
this.lastUrl = ''
|
this.lastUrl = ''
|
||||||
this.referenceUrl = ''
|
this.$nextTick(() => {
|
||||||
this.editorContent = ''
|
this.$refs.videoRichEditor?.clear?.()
|
||||||
this.uploadedImages = []
|
this.bumpEditorVisualTick()
|
||||||
this.typeMenuOpen = false
|
})
|
||||||
},
|
|
||||||
|
|
||||||
plainPromptText() {
|
|
||||||
if (!this.editorContent || !String(this.editorContent).trim()) return ''
|
|
||||||
const s = String(this.editorContent)
|
|
||||||
if (s.indexOf('<') < 0) return s.trim()
|
|
||||||
const d = document.createElement('div')
|
|
||||||
d.innerHTML = s
|
|
||||||
return (d.textContent || d.innerText || '').trim()
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async loadTaskList() {
|
async loadTaskList() {
|
||||||
|
|
@ -343,27 +359,53 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
handleTextChange(content) {
|
async loadVideoParams() {
|
||||||
this.editorContent = content
|
try {
|
||||||
},
|
const res = await this.$axios({
|
||||||
|
url: 'api/portal/video/options',
|
||||||
handleImageUpload(imageInfo) {
|
method: 'GET'
|
||||||
if (imageInfo && imageInfo.url) {
|
|
||||||
this.uploadedImages.push({
|
|
||||||
url: imageInfo.url,
|
|
||||||
name: imageInfo.name || 'image'
|
|
||||||
})
|
})
|
||||||
|
if (res.code !== 200 || !res.data) return
|
||||||
|
const { defaults, models, ratios, durations, resolutions } = res.data
|
||||||
|
this.modelOptions = Array.isArray(models) ? models : []
|
||||||
|
this.ratioOptions = Array.isArray(ratios) ? ratios : []
|
||||||
|
this.durationOptions = Array.isArray(durations) ? durations.map((n) => Number(n)) : []
|
||||||
|
this.resolutionOptions = Array.isArray(resolutions) ? resolutions : []
|
||||||
|
const d = defaults || {}
|
||||||
|
if (d.model) {
|
||||||
|
this.selectedModel = d.model
|
||||||
|
} else if (this.modelOptions.length) {
|
||||||
|
this.selectedModel = this.modelOptions[0].value
|
||||||
|
}
|
||||||
|
if (d.ratio && this.ratioOptions.includes(d.ratio)) {
|
||||||
|
this.selectedRatio = d.ratio
|
||||||
|
} else if (this.ratioOptions.length) {
|
||||||
|
this.selectedRatio = this.ratioOptions[0]
|
||||||
|
}
|
||||||
|
const durNum = d.duration != null ? Number(d.duration) : null
|
||||||
|
if (durNum != null && this.durationOptions.includes(durNum)) {
|
||||||
|
this.selectedDuration = durNum
|
||||||
|
} else if (this.durationOptions.length) {
|
||||||
|
this.selectedDuration = this.durationOptions[0]
|
||||||
|
}
|
||||||
|
if (d.resolution && this.resolutionOptions.includes(d.resolution)) {
|
||||||
|
this.selectedResolution = d.resolution
|
||||||
|
} else if (this.resolutionOptions.length) {
|
||||||
|
this.selectedResolution = this.resolutionOptions[0]
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
this.$message?.warning?.('加载视频参数配置失败')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
generateVideo() {
|
generateVideo() {
|
||||||
const text = this.plainPromptText() || '一个优雅的女孩在阳光下跳舞'
|
const plain = this.plainPromptText()
|
||||||
|
const text = plain || '一个优雅的女孩在阳光下跳舞'
|
||||||
|
|
||||||
if (this.isImageVideoMode) {
|
if (this.isImageVideoMode) {
|
||||||
if (this.videoMode === 'image-reference') {
|
if (this.videoMode === 'image-reference') {
|
||||||
const ref = typeof this.referenceUrl === 'object' ? this.referenceUrl?.url : this.referenceUrl
|
if (!this.firstReferenceImageUrlFromEditor()) {
|
||||||
if (!ref) {
|
this.$message.error('请通过编辑器工具栏「插入参考素材」添加参考图')
|
||||||
this.$message.error('请上传参考图')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -380,8 +422,16 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!this.plainPromptText()) {
|
} else {
|
||||||
this.$message.error('请输入视频描述文本')
|
const contentItems = this.$refs.videoRichEditor?.getContentItems?.() || []
|
||||||
|
if (!plain && (!contentItems.length || !contentItems.some((i) => i.type === 'image_url'))) {
|
||||||
|
this.$message.error('请输入视频描述文本或插入参考素材')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.selectedModel || !this.selectedRatio || this.selectedDuration == null || !this.selectedResolution) {
|
||||||
|
this.$message.error('请选择模型、比例、时长与分辨率')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -390,7 +440,17 @@ export default {
|
||||||
const params = {
|
const params = {
|
||||||
text,
|
text,
|
||||||
functionType: '21',
|
functionType: '21',
|
||||||
model: this.selectedModel
|
model: this.selectedModel,
|
||||||
|
ratio: this.selectedRatio,
|
||||||
|
duration: this.selectedDuration,
|
||||||
|
resolution: this.selectedResolution
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.videoMode === 'text-to-video') {
|
||||||
|
const contentItems = this.$refs.videoRichEditor?.getContentItems?.() || []
|
||||||
|
if (contentItems.length) {
|
||||||
|
params.content = contentItems
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const urlMap = {
|
const urlMap = {
|
||||||
|
|
@ -407,7 +467,7 @@ export default {
|
||||||
params.lastUrl = typeof this.lastUrl === 'object' ? this.lastUrl.url : this.lastUrl
|
params.lastUrl = typeof this.lastUrl === 'object' ? this.lastUrl.url : this.lastUrl
|
||||||
}
|
}
|
||||||
if (this.videoMode === 'image-reference') {
|
if (this.videoMode === 'image-reference') {
|
||||||
params.referenceUrl = typeof this.referenceUrl === 'object' ? this.referenceUrl.url : this.referenceUrl
|
params.referenceUrl = this.firstReferenceImageUrlFromEditor()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$axios({
|
this.$axios({
|
||||||
|
|
@ -573,130 +633,71 @@ export default {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-type-select {
|
|
||||||
position: relative;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 10px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-hero-mode-label {
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--vg-muted);
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-type-trigger {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 8px 14px;
|
|
||||||
margin: 0;
|
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.03));
|
|
||||||
border: 1px solid var(--vg-border);
|
|
||||||
border-radius: 12px;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 700;
|
|
||||||
font-family: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.2s, box-shadow 0.2s;
|
|
||||||
box-shadow: 0 0 0 1px rgba(0, 202, 224, 0.15);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: rgba(0, 202, 224, 0.45);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-open .vg-type-chevron {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-type-label {
|
|
||||||
background: linear-gradient(90deg, #fff, rgba(0, 202, 224, 0.95));
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-type-chevron {
|
|
||||||
width: 0.85em;
|
|
||||||
height: 0.85em;
|
|
||||||
opacity: 0.75;
|
|
||||||
transition: transform 0.2s cubic-bezier(0.15, 0.75, 0.3, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-type-dropdown {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: calc(100% + 8px);
|
|
||||||
min-width: 100%;
|
|
||||||
z-index: 50;
|
|
||||||
border-radius: 14px;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.45);
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-type-dropdown-bg {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background: rgba(18, 20, 26, 0.98);
|
|
||||||
backdrop-filter: blur(12px);
|
|
||||||
border: 1px solid var(--vg-border);
|
|
||||||
border-radius: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-type-options {
|
|
||||||
position: relative;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 6px;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-type-option {
|
|
||||||
padding: 12px 16px;
|
|
||||||
border-radius: 10px;
|
|
||||||
color: var(--vg-muted);
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 0.15s, color 0.15s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.06);
|
|
||||||
color: var(--vg-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: var(--vg-cyan);
|
|
||||||
background: rgba(0, 202, 224, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vg-fade-enter-active,
|
|
||||||
.vg-fade-leave-active {
|
|
||||||
transition: opacity 0.15s ease, transform 0.15s ease;
|
|
||||||
}
|
|
||||||
.vg-fade-enter-from,
|
|
||||||
.vg-fade-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-6px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* —— Body —— */
|
/* —— Body —— */
|
||||||
.vg-body {
|
.vg-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
gap: 20px;
|
gap: 16px;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
min-height: 420px;
|
min-height: 420px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vg-left-rail {
|
||||||
|
flex: 0 0 200px;
|
||||||
|
min-width: 176px;
|
||||||
|
padding: 18px 14px;
|
||||||
|
background: var(--vg-panel);
|
||||||
|
border: 1px solid var(--vg-border);
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.06);
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vg-rail-title {
|
||||||
|
margin: 0 0 14px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--vg-muted);
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vg-mode-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vg-mode-item {
|
||||||
|
padding: 11px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
|
color: var(--vg-muted);
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
background: rgba(0, 0, 0, 0.22);
|
||||||
|
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--vg-text);
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--vg-cyan);
|
||||||
|
border-color: rgba(0, 202, 224, 0.35);
|
||||||
|
background: rgba(0, 202, 224, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.vg-generator {
|
.vg-generator {
|
||||||
flex: 0 0 min(520px, 44vw);
|
flex: 1;
|
||||||
min-width: 300px;
|
min-width: 280px;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -809,21 +810,11 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
:deep(.rich-editor-root) {
|
:deep(.video-editor-root) {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
min-height: 280px;
|
||||||
|
|
||||||
:deep(.rich-editor) {
|
|
||||||
flex: 1;
|
|
||||||
min-height: 220px !important;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 1.7;
|
|
||||||
padding: 16px 18px;
|
|
||||||
border-radius: 14px !important;
|
|
||||||
background: rgba(0, 0, 0, 0.25) !important;
|
|
||||||
border: 1px solid var(--vg-border) !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -842,29 +833,38 @@ export default {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-model-wrap {
|
.vg-params-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex-wrap: wrap;
|
||||||
gap: 10px;
|
align-items: flex-end;
|
||||||
padding: 4px 12px;
|
gap: 12px 14px;
|
||||||
|
padding: 10px 12px;
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid var(--vg-border);
|
border: 1px solid var(--vg-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-model-icon {
|
.vg-param {
|
||||||
display: flex;
|
display: flex;
|
||||||
color: var(--vg-cyan);
|
flex-direction: column;
|
||||||
opacity: 0.85;
|
gap: 6px;
|
||||||
|
flex: 1 1 140px;
|
||||||
|
min-width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-model-select {
|
.vg-param-label {
|
||||||
flex: 1;
|
font-size: 12px;
|
||||||
min-width: 0;
|
color: var(--vg-muted);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vg-param-select {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
:deep(.arco-select-view-single) {
|
:deep(.arco-select-view-single) {
|
||||||
background: transparent !important;
|
background: rgba(0, 0, 0, 0.2) !important;
|
||||||
border: none !important;
|
border: 1px solid var(--vg-border) !important;
|
||||||
|
border-radius: 10px !important;
|
||||||
color: var(--vg-text) !important;
|
color: var(--vg-text) !important;
|
||||||
}
|
}
|
||||||
:deep(.arco-select-view-value) {
|
:deep(.arco-select-view-value) {
|
||||||
|
|
@ -999,6 +999,20 @@ export default {
|
||||||
.vg-body {
|
.vg-body {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.vg-left-rail {
|
||||||
|
flex: none;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.vg-mode-list {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.vg-mode-item {
|
||||||
|
flex: 1 1 calc(50% - 4px);
|
||||||
|
min-width: 140px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
.vg-generator {
|
.vg-generator {
|
||||||
flex: none;
|
flex: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -1007,10 +1021,6 @@ export default {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
.vg-type-select {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-task-empty {
|
.vg-task-empty {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue