feat: 样式升级

This commit is contained in:
2026-03-16 23:54:01 +08:00
parent 110fe62404
commit 4a5fdd3961
42 changed files with 1931 additions and 1404 deletions

View File

@@ -95,19 +95,19 @@
<!-- 识别状态 -->
<div v-if="store.videoStep !== 'idle'" class="process-status" :class="store.videoStep">
<div v-if="store.videoStep === 'uploading'" class="status-row">
<a-spin size="small" />
<span class="custom-spinner"></span>
<span>正在上传视频...</span>
</div>
<div v-else-if="store.videoStep === 'recognizing'" class="status-row">
<a-spin size="small" />
<span class="custom-spinner"></span>
<span>正在识别人脸...</span>
</div>
<div v-else-if="store.videoStep === 'recognized'" class="status-row success">
<CheckCircleOutlined />
<Icon icon="lucide:check-circle" />
<span>识别成功 · 人脸时长 {{ formatDurationMs(store.faceDurationMs) }}</span>
</div>
<div v-else-if="store.videoStep === 'error'" class="status-row error">
<ExclamationCircleOutlined />
<Icon icon="lucide:alert-circle" />
<span>{{ store.error }}</span>
<button class="link-btn" @click="store.retry">重试</button>
</div>
@@ -168,18 +168,16 @@
<div class="label-row">
<label class="input-label">播报文案</label>
<button class="generate-text-btn" @click="openTextGeneratePopup">
<EditOutlined />
<Icon icon="lucide:edit-3" />
<span>AI 生成</span>
</button>
</div>
<a-textarea
v-model:value="store.text"
<Textarea
v-model="store.text"
:placeholder="placeholder"
:rows="6"
:maxlength="4000"
:show-count="true"
class="notion-textarea"
:bordered="false"
/>
<div class="input-footer">
<span>{{ store.text?.length || 0 }} </span>
@@ -207,12 +205,11 @@
<div class="input-section">
<label class="input-label">语速调节</label>
<div class="rate-control">
<a-slider
v-model:value="store.speechRate"
<Slider
v-model="store.speechRate"
:min="0.5"
:max="2.0"
:step="0.1"
:marks="rateMarks"
class="rate-slider"
/>
<span class="rate-value">{{ store.speechRate.toFixed(1) }}x</span>
@@ -241,23 +238,14 @@
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { Icon } from '@iconify/vue'
import FullWidthLayout from '@/layouts/components/FullWidthLayout.vue'
import VideoSelector from '@/components/VideoSelector.vue'
import VoiceSelector from '@/components/VoiceSelector.vue'
import TimelinePanel from './components/TimelinePanel.vue'
import TextGeneratePopup from './components/TextGeneratePopup.vue'
import {
CloudUploadOutlined,
FolderOutlined,
CheckCircleOutlined,
ExclamationCircleOutlined,
ReloadOutlined,
PlayCircleOutlined,
CheckCircleFilled,
ExclamationCircleFilled,
LoadingOutlined,
EditOutlined,
} from '@ant-design/icons-vue'
import { Textarea } from '@/components/ui/textarea'
import { Slider } from '@/components/ui/slider'
import { useDigitalHumanStore } from './stores/useDigitalHumanStore'
import { useUserStore } from '@/stores/user'
import { usePointsConfigStore } from '@/stores/pointsConfig'
@@ -707,6 +695,21 @@ onMounted(async () => {
}
}
.custom-spinner {
width: 14px;
height: 14px;
border: 2px solid rgba(59, 130, 246, 0.2);
border-top-color: @accent-blue;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.link-btn {
margin-left: auto;
padding: 0;