2025-12-01 22:27:50 +08:00
|
|
|
|
<template>
|
2026-01-17 19:54:57 +08:00
|
|
|
|
<FullWidthLayout :show-padding="false">
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="digital-human-page">
|
|
|
|
|
|
<!-- 左侧配置区 -->
|
|
|
|
|
|
<section class="config-panel">
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 步骤1:输入文案 -->
|
|
|
|
|
|
<div class="config-card">
|
|
|
|
|
|
<div class="step-indicator">1</div>
|
|
|
|
|
|
<h3 class="card-title">输入播文案</h3>
|
|
|
|
|
|
|
|
|
|
|
|
<a-textarea
|
|
|
|
|
|
v-model:value="ttsText"
|
|
|
|
|
|
:placeholder="textareaPlaceholder"
|
|
|
|
|
|
:rows="4"
|
|
|
|
|
|
:maxlength="maxTextLength"
|
|
|
|
|
|
:show-count="true"
|
|
|
|
|
|
class="text-input"
|
|
|
|
|
|
:bordered="false"
|
|
|
|
|
|
/>
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="input-meta">
|
|
|
|
|
|
<span>当前字数:{{ ttsText?.length || 0 }}字</span>
|
2026-01-17 19:54:57 +08:00
|
|
|
|
</div>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
</div>
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<!-- 步骤2:语音设置 -->
|
|
|
|
|
|
<div class="config-card">
|
|
|
|
|
|
<div class="step-indicator">2</div>
|
|
|
|
|
|
<h3 class="card-title">语音设置</h3>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="voice-settings">
|
|
|
|
|
|
<div class="setting-group">
|
|
|
|
|
|
<label class="setting-label">选择音色</label>
|
|
|
|
|
|
<VoiceSelector
|
|
|
|
|
|
:synth-text="ttsText"
|
|
|
|
|
|
:speech-rate="speechRate"
|
|
|
|
|
|
@select="handleVoiceSelect"
|
|
|
|
|
|
/>
|
2025-12-01 22:27:50 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="setting-group">
|
|
|
|
|
|
<label class="setting-label">合成模型等级</label>
|
|
|
|
|
|
<div class="model-options">
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="model-btn"
|
|
|
|
|
|
:class="{ 'model-btn--active': speechRate <= 1 }"
|
|
|
|
|
|
>
|
|
|
|
|
|
标准版 (1x积分)
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="model-btn model-btn--pro"
|
|
|
|
|
|
:class="{ 'model-btn--active': speechRate > 1 }"
|
|
|
|
|
|
>
|
|
|
|
|
|
Pro 旗舰版 (3x积分)
|
|
|
|
|
|
<CrownFilled class="pro-icon" />
|
|
|
|
|
|
</button>
|
2026-01-17 19:54:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-01-17 19:54:57 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<!-- 步骤3:上传视频 -->
|
|
|
|
|
|
<div class="config-card">
|
|
|
|
|
|
<div class="step-indicator">3</div>
|
|
|
|
|
|
<h3 class="card-title">上传/选择视频素材</h3>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="video-options">
|
|
|
|
|
|
<!-- 上传新视频 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="video-option-card"
|
|
|
|
|
|
:class="{ 'video-option-card--selected': videoState.videoSource === 'upload' }"
|
|
|
|
|
|
@click="handleSelectUpload"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="video-option-icon">
|
|
|
|
|
|
<CloudUploadOutlined />
|
2025-12-28 00:19:17 +08:00
|
|
|
|
</div>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="video-option-content">
|
|
|
|
|
|
<h4>点击上传新视频</h4>
|
|
|
|
|
|
<p>支持 MP4、MOV (需 >3秒)</p>
|
2025-12-28 00:19:17 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<!-- 从素材库选择 -->
|
2025-12-28 00:19:17 +08:00
|
|
|
|
<div
|
2026-02-12 23:35:39 +08:00
|
|
|
|
class="video-option-card"
|
|
|
|
|
|
:class="{ 'video-option-card--selected': videoState.videoSource === 'select' }"
|
|
|
|
|
|
@click="handleSelectFromLibrary"
|
2025-12-28 00:19:17 +08:00
|
|
|
|
>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="video-option-icon">
|
|
|
|
|
|
<PictureOutlined />
|
2025-12-28 00:19:17 +08:00
|
|
|
|
</div>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="video-option-content">
|
|
|
|
|
|
<h4>从素材库选择</h4>
|
|
|
|
|
|
<p>选择已上传的视频</p>
|
2025-12-28 00:19:17 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<!-- 已选择视频预览 -->
|
|
|
|
|
|
<div v-if="videoState.selectedVideo" class="selected-video">
|
|
|
|
|
|
<div class="video-preview-thumb">
|
|
|
|
|
|
<img
|
|
|
|
|
|
:src="getVideoPreviewUrl(videoState.selectedVideo)"
|
|
|
|
|
|
:alt="videoState.selectedVideo.fileName"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="video-preview-info">
|
|
|
|
|
|
<div class="video-name">{{ videoState.selectedVideo.fileName }}</div>
|
|
|
|
|
|
<div class="video-meta">{{ formatDuration(videoState.selectedVideo.duration) }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<button class="change-video-btn" @click="replaceVideo">更换</button>
|
|
|
|
|
|
</div>
|
2025-12-28 00:19:17 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<!-- 上传区域 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="videoState.videoSource === 'upload'"
|
|
|
|
|
|
class="upload-zone"
|
|
|
|
|
|
:class="{ 'upload-zone--dragover': dragOver }"
|
|
|
|
|
|
@drop.prevent="handleDrop"
|
|
|
|
|
|
@dragover.prevent="dragOver = true"
|
|
|
|
|
|
@dragleave.prevent="dragOver = false"
|
|
|
|
|
|
>
|
|
|
|
|
|
<input ref="fileInput" type="file" accept=".mp4,.mov" class="file-input" @change="handleFileSelectWrapper" />
|
|
|
|
|
|
|
|
|
|
|
|
<div v-if="!videoState.uploadedVideo" class="upload-placeholder">
|
|
|
|
|
|
<CloudUploadOutlined class="upload-icon" />
|
|
|
|
|
|
<span class="upload-text">点击上传新视频</span>
|
|
|
|
|
|
<span class="upload-hint">支持 MP4、MOV (需 >3秒)</span>
|
|
|
|
|
|
<button class="select-file-btn" @click="triggerFileSelect">选择文件</button>
|
|
|
|
|
|
</div>
|
2026-02-04 01:46:55 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div v-else class="upload-preview">
|
|
|
|
|
|
<video :src="videoState.uploadedVideo" controls class="preview-video-player"></video>
|
|
|
|
|
|
<p class="upload-filename">{{ videoState.videoFile?.name }}</p>
|
|
|
|
|
|
<button class="change-video-btn" @click="replaceVideo">更换</button>
|
2025-12-28 00:19:17 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
</div>
|
2025-12-02 01:55:57 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<!-- Pipeline 进度 -->
|
|
|
|
|
|
<PipelineProgress
|
|
|
|
|
|
v-if="isPipelineBusy || isPipelineReady || isPipelineFailed || isPipelineCompleted"
|
|
|
|
|
|
:state="pipelineState"
|
|
|
|
|
|
:progress="pipelineProgress"
|
|
|
|
|
|
:is-busy="isPipelineBusy"
|
|
|
|
|
|
:is-ready="isPipelineReady"
|
|
|
|
|
|
:is-failed="isPipelineFailed"
|
|
|
|
|
|
:is-completed="isPipelineCompleted"
|
|
|
|
|
|
:error="pipelineError"
|
|
|
|
|
|
@retry="retryPipeline"
|
|
|
|
|
|
@reset="resetPipeline"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 操作按钮 -->
|
|
|
|
|
|
<div class="action-section">
|
|
|
|
|
|
<a-button
|
2026-02-24 21:47:21 +08:00
|
|
|
|
v-if="!isPipelineCompleted"
|
2026-02-12 23:35:39 +08:00
|
|
|
|
type="primary"
|
|
|
|
|
|
size="large"
|
|
|
|
|
|
:disabled="!canGenerate"
|
|
|
|
|
|
:loading="isPipelineBusy"
|
|
|
|
|
|
block
|
|
|
|
|
|
@click="generateAudio"
|
|
|
|
|
|
class="action-btn"
|
|
|
|
|
|
>
|
2026-02-24 21:47:21 +08:00
|
|
|
|
{{ isPipelineBusy ? pipelineStateLabel + '...' : '生成数字人视频' }}
|
2026-02-12 23:35:39 +08:00
|
|
|
|
</a-button>
|
|
|
|
|
|
|
2026-02-24 21:47:21 +08:00
|
|
|
|
<div v-else class="completed-tip">
|
|
|
|
|
|
<span>任务已提交成功</span>
|
|
|
|
|
|
<a-button @click="resetPipeline" class="reset-btn">重新生成</a-button>
|
|
|
|
|
|
</div>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
</div>
|
2026-02-04 01:18:16 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 右侧预览区 -->
|
|
|
|
|
|
<aside class="preview-panel">
|
|
|
|
|
|
<div class="preview-card">
|
|
|
|
|
|
<h3 class="preview-title">合成预览</h3>
|
2025-12-02 01:55:57 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="preview-screen">
|
|
|
|
|
|
<ResultPanel @videoLoaded="handleVideoLoaded" />
|
2025-12-02 01:55:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
<div class="preview-meta">
|
|
|
|
|
|
<div class="meta-row">
|
|
|
|
|
|
<span class="meta-label">预计消耗积分</span>
|
|
|
|
|
|
<span class="meta-value">150 积分</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="meta-row">
|
|
|
|
|
|
<span class="meta-label">当前余额</span>
|
2026-02-24 22:11:30 +08:00
|
|
|
|
<span class="meta-value">{{ userStore.remainingPoints.toLocaleString() }} 积分</span>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</aside>
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
|
|
|
|
|
</div>
|
2026-02-12 23:35:39 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 视频选择器弹窗 -->
|
|
|
|
|
|
<VideoSelector v-model:open="videoState.selectorVisible" @select="handleVideoSelect" />
|
2026-01-17 19:54:57 +08:00
|
|
|
|
</FullWidthLayout>
|
2025-12-01 22:27:50 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
2025-12-28 13:49:45 +08:00
|
|
|
|
<script setup lang="ts">
|
2026-02-12 23:35:39 +08:00
|
|
|
|
import { ref } from 'vue'
|
|
|
|
|
|
import { CloudUploadOutlined, CrownFilled } from '@ant-design/icons-vue'
|
2025-12-01 22:27:50 +08:00
|
|
|
|
import { useVoiceCopyStore } from '@/stores/voiceCopy'
|
2026-02-24 22:11:30 +08:00
|
|
|
|
import { useUserStore } from '@/stores/user'
|
2025-12-28 00:19:17 +08:00
|
|
|
|
import VideoSelector from '@/components/VideoSelector.vue'
|
|
|
|
|
|
import VoiceSelector from '@/components/VoiceSelector.vue'
|
|
|
|
|
|
import ResultPanel from '@/components/ResultPanel.vue'
|
2026-01-17 19:54:57 +08:00
|
|
|
|
import FullWidthLayout from '@/layouts/components/FullWidthLayout.vue'
|
2026-02-04 01:18:16 +08:00
|
|
|
|
import PipelineProgress from '@/components/PipelineProgress.vue'
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
2025-12-28 13:49:45 +08:00
|
|
|
|
// Controller Hook
|
|
|
|
|
|
import { useIdentifyFaceController } from './hooks/useIdentifyFaceController'
|
2025-12-22 00:15:02 +08:00
|
|
|
|
|
2025-12-28 13:49:45 +08:00
|
|
|
|
const voiceStore = useVoiceCopyStore()
|
2026-02-24 22:11:30 +08:00
|
|
|
|
const userStore = useUserStore()
|
2025-12-28 00:19:17 +08:00
|
|
|
|
const dragOver = ref(false)
|
|
|
|
|
|
|
2025-12-28 13:49:45 +08:00
|
|
|
|
// ==================== 初始化 Controller ====================
|
|
|
|
|
|
|
|
|
|
|
|
// Controller 内部直接创建和管理两个子 Hook
|
|
|
|
|
|
const controller = useIdentifyFaceController()
|
|
|
|
|
|
|
|
|
|
|
|
// 解构 controller 以简化模板调用
|
|
|
|
|
|
const {
|
|
|
|
|
|
// 语音生成相关
|
|
|
|
|
|
ttsText,
|
|
|
|
|
|
speechRate,
|
|
|
|
|
|
generateAudio,
|
|
|
|
|
|
|
|
|
|
|
|
// 数字人生成相关
|
|
|
|
|
|
videoState,
|
|
|
|
|
|
getVideoPreviewUrl,
|
|
|
|
|
|
|
|
|
|
|
|
// 计算属性
|
|
|
|
|
|
canGenerate,
|
|
|
|
|
|
maxTextLength,
|
|
|
|
|
|
textareaPlaceholder,
|
2026-02-04 01:18:16 +08:00
|
|
|
|
audioDurationSec,
|
|
|
|
|
|
|
2026-02-04 01:46:55 +08:00
|
|
|
|
// Pipeline 状态(单一状态源)
|
2026-02-04 01:18:16 +08:00
|
|
|
|
pipelineState,
|
2026-02-24 21:47:21 +08:00
|
|
|
|
pipelineStateLabel,
|
2026-02-04 01:18:16 +08:00
|
|
|
|
isPipelineBusy,
|
|
|
|
|
|
isPipelineReady,
|
|
|
|
|
|
isPipelineFailed,
|
|
|
|
|
|
isPipelineCompleted,
|
|
|
|
|
|
pipelineProgress,
|
|
|
|
|
|
pipelineError,
|
|
|
|
|
|
retryPipeline,
|
|
|
|
|
|
resetPipeline,
|
2025-12-28 13:49:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 事件处理方法
|
|
|
|
|
|
handleVoiceSelect,
|
|
|
|
|
|
handleDrop,
|
|
|
|
|
|
handleSelectUpload,
|
|
|
|
|
|
handleSelectFromLibrary,
|
|
|
|
|
|
handleVideoSelect,
|
|
|
|
|
|
handleVideoLoaded,
|
|
|
|
|
|
replaceVideo,
|
|
|
|
|
|
|
|
|
|
|
|
// UI 辅助方法
|
|
|
|
|
|
formatDuration,
|
|
|
|
|
|
} = controller
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 生命周期 ====================
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 引用 fileInput 用于手动触发点击
|
|
|
|
|
|
const fileInput = ref<HTMLInputElement | null>(null)
|
|
|
|
|
|
|
|
|
|
|
|
// 触发文件选择
|
|
|
|
|
|
const triggerFileSelect = () => {
|
|
|
|
|
|
fileInput.value?.click()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 覆盖 controller 中的方法,使用 ref
|
|
|
|
|
|
const handleFileSelectWrapper = (e: Event) => {
|
|
|
|
|
|
controller.handleFileSelect(e)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 生命周期 ====================
|
|
|
|
|
|
|
|
|
|
|
|
import { onMounted } from 'vue'
|
2025-12-01 22:27:50 +08:00
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
await voiceStore.refresh()
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
2025-12-28 13:49:45 +08:00
|
|
|
|
<style scoped lang="less">
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.digital-human-page {
|
2026-01-18 00:34:04 +08:00
|
|
|
|
min-height: 100vh;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
background: #F8FAFC;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
gap: 24px;
|
|
|
|
|
|
padding: 24px;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 布局容器
|
|
|
|
|
|
.config-panel {
|
|
|
|
|
|
flex: 1;
|
2026-02-13 00:21:21 +08:00
|
|
|
|
padding:0 20px;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
max-width: 100%;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-panel {
|
|
|
|
|
|
width: 400px;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-left: 1px solid #E2E8F0;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
flex-shrink: 0;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
@media (max-width: 1200px) {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
border-left: none;
|
|
|
|
|
|
border-top: 1px solid #E2E8F0;
|
|
|
|
|
|
order: -1;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 配置卡片
|
|
|
|
|
|
.config-card {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid #E2E8F0;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
overflow: hidden;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.step-indicator {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
width: 32px;
|
|
|
|
|
|
height: 32px;
|
|
|
|
|
|
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
border-radius: 8px 0 12px 0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
font-size: 14px;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.card-title {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #1E293B;
|
|
|
|
|
|
margin: 0 0 12px 12px;
|
|
|
|
|
|
padding-left: 44px;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 文案输入
|
|
|
|
|
|
.text-input {
|
|
|
|
|
|
width: 100%;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
|
|
|
|
|
:deep(.ant-input) {
|
|
|
|
|
|
border: none;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
padding: 16px 12px;
|
|
|
|
|
|
background: #F8FAFC;
|
|
|
|
|
|
|
|
|
|
|
|
&:focus {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
box-shadow: 0 0 0 1px #E2E8F0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.ant-input-textarea-show-count) {
|
|
|
|
|
|
bottom: 8px;
|
|
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
2025-12-01 22:27:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.input-meta {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #94A3B8;
|
|
|
|
|
|
margin-top: 12px;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.meta-value {
|
2025-12-01 22:27:50 +08:00
|
|
|
|
font-weight: 600;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
color: #1E293B;
|
2025-12-01 22:27:50 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 语音设置
|
|
|
|
|
|
.voice-settings {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 640px) {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
2025-12-01 22:27:50 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.setting-group {
|
2025-12-01 22:27:50 +08:00
|
|
|
|
display: flex;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 8px;
|
2025-12-01 22:27:50 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.setting-label {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #64748B;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.model-options {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
background: #F1F5F9;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
padding: 2px;
|
|
|
|
|
|
gap: 2px;
|
2025-12-01 22:27:50 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.model-btn {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
padding: 8px 10px;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #64748B;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
background: transparent;
|
2025-12-01 22:27:50 +08:00
|
|
|
|
cursor: pointer;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 4px;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&--active {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
color: #22C55E;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pro-icon {
|
2025-12-01 22:27:50 +08:00
|
|
|
|
font-size: 12px;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
color: #EAB308;
|
2025-12-01 22:27:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 视频选项
|
|
|
|
|
|
.video-options {
|
2025-12-28 00:19:17 +08:00
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: 1fr 1fr;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
gap: 12px;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
margin-bottom: 16px;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2025-12-28 00:19:17 +08:00
|
|
|
|
.video-option-card {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
gap: 12px;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
padding: 14px 16px;
|
|
|
|
|
|
border: 2px dashed #E2E8F0;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
background: #F8FAFC;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
cursor: pointer;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
transition: all 0.2s ease;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
|
|
|
|
|
&:hover {
|
2026-02-13 00:21:21 +08:00
|
|
|
|
border-color: #3B82F6;
|
|
|
|
|
|
background: #EFF6FF;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
&--selected {
|
|
|
|
|
|
border-style: solid;
|
2026-02-13 00:21:21 +08:00
|
|
|
|
border-color: #2563EB;
|
|
|
|
|
|
background: #EFF6FF;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.video-option-icon {
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
color: #94A3B8;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
width: 36px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 6px;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
flex-shrink: 0;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.video-option-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.video-option-content h4 {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #1E293B;
|
|
|
|
|
|
margin: 0 0 4px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.video-option-content p {
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
color: #94A3B8;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 已选择视频
|
|
|
|
|
|
.selected-video {
|
2025-12-28 00:19:17 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
background: #F1F5F9;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
}
|
2026-02-12 23:35:39 +08:00
|
|
|
|
|
|
|
|
|
|
.video-preview-thumb {
|
|
|
|
|
|
width: 70px;
|
|
|
|
|
|
height: 40px;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
overflow: hidden;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
background: #1E293B;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
flex-shrink: 0;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
|
|
|
|
|
|
img {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2026-02-12 23:35:39 +08:00
|
|
|
|
|
|
|
|
|
|
.video-preview-info {
|
2025-12-28 00:19:17 +08:00
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
}
|
2026-02-12 23:35:39 +08:00
|
|
|
|
|
|
|
|
|
|
.video-name {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #1E293B;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
2026-02-12 23:35:39 +08:00
|
|
|
|
|
2025-12-28 00:19:17 +08:00
|
|
|
|
.video-meta {
|
2026-02-12 23:35:39 +08:00
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
color: #94A3B8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.change-video-btn {
|
|
|
|
|
|
padding: 4px 10px;
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
color: #64748B;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
2026-02-13 00:21:21 +08:00
|
|
|
|
color: #3B82F6;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 上传区域
|
2025-12-28 13:49:45 +08:00
|
|
|
|
.upload-zone {
|
2026-02-12 23:35:39 +08:00
|
|
|
|
min-height: 160px;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
border: 2px dashed #E2E8F0;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
background: #F8FAFC;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&--dragover {
|
2026-02-13 00:21:21 +08:00
|
|
|
|
border-color: #3B82F6;
|
|
|
|
|
|
background: #EFF6FF;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.file-input {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-28 13:49:45 +08:00
|
|
|
|
.upload-placeholder {
|
2026-01-18 00:34:04 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
gap: 8px;
|
|
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.upload-icon {
|
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
|
color: #94A3B8;
|
|
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.upload-text {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #1E293B;
|
|
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.upload-hint {
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
color: #94A3B8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.select-file-btn {
|
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
padding: 6px 16px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 500;
|
2026-02-13 00:21:21 +08:00
|
|
|
|
color: #3B82F6;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
border: none;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
cursor: pointer;
|
2026-02-13 00:21:21 +08:00
|
|
|
|
border: 1px solid #3B82F6;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
2026-02-13 00:21:21 +08:00
|
|
|
|
background: rgba(59, 130, 246, 0.1);
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.upload-preview {
|
2026-01-18 00:34:04 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 12px;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-video-player {
|
2025-12-28 13:49:45 +08:00
|
|
|
|
width: 100%;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
max-height: 140px;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.upload-filename {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #64748B;
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
padding: 6px 10px;
|
|
|
|
|
|
background: #F1F5F9;
|
|
|
|
|
|
border-radius: 6px;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 操作按钮区
|
|
|
|
|
|
.action-section {
|
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
|
padding-top: 16px;
|
|
|
|
|
|
border-top: 1px solid #E2E8F0;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.action-btn {
|
|
|
|
|
|
height: 44px;
|
|
|
|
|
|
font-size: 15px;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
font-weight: 600;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
border-radius: 8px;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
&.ant-btn-primary {
|
2026-02-13 00:21:21 +08:00
|
|
|
|
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
|
2026-02-12 23:35:39 +08:00
|
|
|
|
border: none;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover:not(:disabled) {
|
2026-02-13 00:21:21 +08:00
|
|
|
|
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.35);
|
2026-02-12 23:35:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:disabled {
|
|
|
|
|
|
background: #D1D5DB;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-24 21:47:21 +08:00
|
|
|
|
.completed-tip {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
|
background: #F0FDF4;
|
|
|
|
|
|
border: 1px solid #86EFAC;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
color: #166534;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
|
|
|
|
|
|
.reset-btn {
|
|
|
|
|
|
padding: 4px 12px;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #3B82F6;
|
|
|
|
|
|
border: 1px solid #3B82F6;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.2s;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(59, 130, 246, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 预览面板
|
|
|
|
|
|
.preview-card {
|
|
|
|
|
|
position: sticky;
|
|
|
|
|
|
top: 24px;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-title {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #1E293B;
|
|
|
|
|
|
margin: 0 0 16px 0;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-screen {
|
|
|
|
|
|
aspect-ratio: 9/16;
|
|
|
|
|
|
background: #1E293B;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
position: relative;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
display: flex;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2025-12-28 00:19:17 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
&::after {
|
|
|
|
|
|
content: '预览画面不可用';
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
inset: 0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.6);
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
:deep(.result-panel) {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-meta {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
background: #F8FAFC;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.meta-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
font-size: 12px;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.meta-label {
|
|
|
|
|
|
color: #64748B;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.meta-row .meta-value {
|
2026-01-18 00:34:04 +08:00
|
|
|
|
font-weight: 600;
|
2026-02-12 23:35:39 +08:00
|
|
|
|
color: #1E293B;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2026-01-18 00:34:04 +08:00
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
// 响应式
|
2025-12-28 13:49:45 +08:00
|
|
|
|
@media (max-width: 1024px) {
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.digital-human-page {
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.config-panel {
|
|
|
|
|
|
max-width: 100%;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
padding: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-panel {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
border-left: none;
|
|
|
|
|
|
border-top: 1px solid #E2E8F0;
|
|
|
|
|
|
order: -1;
|
|
|
|
|
|
padding: 16px;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-card {
|
|
|
|
|
|
position: static;
|
2026-01-18 00:34:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-12 23:35:39 +08:00
|
|
|
|
.preview-screen {
|
|
|
|
|
|
min-height: 200px;
|
2025-12-28 13:49:45 +08:00
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
}
|
2025-12-01 22:27:50 +08:00
|
|
|
|
</style>
|