feat: 样式升级
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user