fix: PayPal payment_method column length issue; add image model selection for storyboard; remove task restore popups; sync UserWork status on task failure
This commit is contained in:
@@ -190,12 +190,7 @@
|
||||
<el-button circle size="small" text><el-icon><MoreFilled /></el-icon></el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="download_with_watermark">{{ t('works.downloadWithWatermark') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="download_without_watermark">
|
||||
{{ t('works.downloadWithoutWatermark') }}
|
||||
<el-tag type="primary" size="small" style="margin-left: 8px;">{{ t('works.memberOnly') }}</el-tag>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="rename" divided>{{ t('works.rename') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="rename">{{ t('works.rename') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="delete">{{ t('common.delete') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
@@ -232,16 +227,23 @@
|
||||
<el-dialog
|
||||
v-model="detailDialogVisible"
|
||||
:title="selectedItem?.title"
|
||||
width="60%"
|
||||
width="70vw"
|
||||
:before-close="handleClose"
|
||||
class="detail-dialog"
|
||||
class="work-detail-dialog"
|
||||
:modal="true"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="true"
|
||||
:close-on-press-escape="true"
|
||||
align-center
|
||||
>
|
||||
<div class="detail-content" v-if="selectedItem">
|
||||
<div class="detail-left">
|
||||
<div class="video-container">
|
||||
<!-- 自定义关闭按钮 -->
|
||||
<div class="dialog-close-btn" @click="handleClose">
|
||||
<el-icon><Close /></el-icon>
|
||||
</div>
|
||||
|
||||
<div class="detail-content" :class="{ 'vertical-content': isVerticalVideo }" v-if="selectedItem">
|
||||
<div class="detail-left" :class="{ 'vertical-left': isVerticalVideo }">
|
||||
<div class="video-container" :class="{ 'vertical-container': isVerticalVideo }">
|
||||
<!-- 视频加载失败提示 -->
|
||||
<div v-if="detailVideoError" class="video-error-overlay">
|
||||
<div class="error-content">
|
||||
@@ -280,7 +282,15 @@
|
||||
:alt="selectedItem.title"
|
||||
/>
|
||||
|
||||
<!-- 视频文字叠加 已移除(用户要求) -->
|
||||
<!-- 悬浮操作按钮 -->
|
||||
<div class="overlay-actions">
|
||||
<button class="icon-btn" @click="downloadWork" :title="t('common.download')">
|
||||
<el-icon><Download /></el-icon>
|
||||
</button>
|
||||
<button class="icon-btn delete" @click="deleteFailedWork" :title="t('common.delete')">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -295,42 +305,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 标签页 -->
|
||||
<div class="tabs">
|
||||
<div class="tab" :class="{ active: activeDetailTab === 'detail' }" @click="activeDetailTab = 'detail'">{{ t('profile.workDetail') }}</div>
|
||||
<div class="tab" :class="{ active: activeDetailTab === 'category' }" @click="activeDetailTab = 'category'">{{ selectedItem.category }}</div>
|
||||
<!-- 详情标题行 -->
|
||||
<div class="detail-title-row">
|
||||
<h3>{{ t('works.videoDetail') }}</h3>
|
||||
<span class="category-badge">{{ selectedItem.category }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 提示词区域 -->
|
||||
<div class="description-section" v-if="activeDetailTab === 'detail'">
|
||||
<h3 class="section-title">{{ t('video.prompt') }}</h3>
|
||||
<p class="description-text">{{ getDescription(selectedItem) }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 参考图特殊内容 -->
|
||||
<div class="reference-content" v-if="activeDetailTab === 'category' && selectedItem.category === '参考图'">
|
||||
<div class="input-details-section">
|
||||
<h3 class="section-title">{{ t('profile.inputDetails') }}</h3>
|
||||
<div class="input-images">
|
||||
<div class="input-image-item">
|
||||
<img :src="selectedItem.cover" :alt="selectedItem.title" class="input-thumbnail" />
|
||||
</div>
|
||||
<div class="input-image-item">
|
||||
<img :src="selectedItem.cover" :alt="selectedItem.title" class="input-thumbnail" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 描述区域 -->
|
||||
<div class="description-section">
|
||||
<div class="section-header">
|
||||
<span class="section-label">{{ t('works.description') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="description-section">
|
||||
<h3 class="section-title">{{ t('video.prompt') }}</h3>
|
||||
<p class="description-text">{{ t('works.referenceImagePrompt') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 其他分类的内容 -->
|
||||
<div class="description-section" v-if="activeDetailTab === 'category' && selectedItem.category !== '参考图'">
|
||||
<h3 class="section-title">{{ t('video.prompt') }}</h3>
|
||||
<p class="description-text">{{ getDescription(selectedItem) }}</p>
|
||||
<p class="description-text">
|
||||
{{ getDescription(selectedItem) }}
|
||||
<el-icon class="copy-icon" @click="copyPrompt" :title="t('common.copy')"><CopyDocument /></el-icon>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 元数据区域 -->
|
||||
@@ -341,34 +330,26 @@
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="label">{{ t('profile.workId') }}</span>
|
||||
<span class="value">{{ selectedItem.id }}</span>
|
||||
<span class="value">{{ selectedItem.taskId }}</span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="label">{{ t('profile.date') }}</span>
|
||||
<span class="value">{{ selectedItem.date }}</span>
|
||||
</div>
|
||||
<div class="metadata-item" v-if="selectedItem.type === 'video'">
|
||||
<span class="label">{{ t('profile.duration') }}</span>
|
||||
<span class="value">{{ formatDuration(selectedItem.duration) || t('profile.unknown') }}</span>
|
||||
</div>
|
||||
<div class="metadata-item" v-if="selectedItem.type === 'video'">
|
||||
<span class="label">{{ t('profile.quality') }}</span>
|
||||
<span class="value">{{ selectedItem.quality || t('profile.unknown') }}</span>
|
||||
<span class="value">{{ formatDuration(selectedItem.duration) || '5s' }}</span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="label">{{ t('profile.category') }}</span>
|
||||
<span class="value">{{ selectedItem.category }}</span>
|
||||
<span class="label">{{ t('profile.quality') }}</span>
|
||||
<span class="value">{{ selectedItem.quality || '1080p' }}</span>
|
||||
</div>
|
||||
<div class="metadata-item" v-if="selectedItem.type === 'video'">
|
||||
<div class="metadata-item">
|
||||
<span class="label">{{ t('profile.aspectRatio') }}</span>
|
||||
<span class="value">{{ selectedItem.aspectRatio || t('profile.unknown') }}</span>
|
||||
<span class="value">{{ selectedItem.aspectRatio || '16:9' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<!-- 底部操作按钮 -->
|
||||
<div class="action-section">
|
||||
<button class="create-similar-btn" @click="createSimilar">
|
||||
{{ t('profile.createSimilar') }}
|
||||
<button class="create-similar-btn full-width" @click="createSimilar(selectedItem)">
|
||||
{{ t('works.createSimilar') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -428,7 +409,7 @@
|
||||
import { ref, onMounted, onActivated, computed, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Star, User, Compass, Document, VideoPlay, Picture, Film, Search, MoreFilled, Loading, ArrowUp, VideoCamera, Refresh, Delete } from '@element-plus/icons-vue'
|
||||
import { Star, User, Compass, Document, VideoPlay, Picture, Film, Search, MoreFilled, Loading, ArrowUp, VideoCamera, Refresh, Delete, CopyDocument, Download, Close } from '@element-plus/icons-vue'
|
||||
import { getMyWorks, getWorkDetail, deleteWork, recordDownload, getWorkFileUrl } from '@/api/userWorks'
|
||||
import { getCurrentUser } from '@/api/auth'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
@@ -485,6 +466,13 @@ const activeDetailTab = ref('detail')
|
||||
const detailVideoError = ref(false)
|
||||
const detailVideoRef = ref(null)
|
||||
|
||||
// 判断是否是竖版视频(9:16)
|
||||
const isVerticalVideo = computed(() => {
|
||||
if (!selectedItem.value) return false
|
||||
const ratio = selectedItem.value.aspectRatio
|
||||
return ratio === '9:16' || ratio === '9/16' || ratio === '3:4' || ratio === '4:5'
|
||||
})
|
||||
|
||||
const page = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const loading = ref(false)
|
||||
@@ -496,6 +484,10 @@ const failedUrls = ref(new Set()) // 记录加载失败的URL
|
||||
// 处理URL,确保相对路径正确
|
||||
const processUrl = (url) => {
|
||||
if (!url) return null
|
||||
// data: 协议(Base64 图片等)直接返回,避免被当成相对路径错误加前缀
|
||||
if (url.startsWith('data:')) {
|
||||
return url
|
||||
}
|
||||
// 如果已经是完整URL(http/https),直接返回
|
||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||
return url
|
||||
@@ -525,6 +517,7 @@ const transformWorkData = (work) => {
|
||||
|
||||
return {
|
||||
id: work.id?.toString() || work.taskId || '',
|
||||
taskId: work.taskId || work.id?.toString() || '',
|
||||
title: work.title || work.prompt || '未命名作品',
|
||||
cover: cover,
|
||||
resultUrl: resultUrl || '',
|
||||
@@ -1061,10 +1054,7 @@ const download = async (item) => {
|
||||
}
|
||||
|
||||
const moreCommand = async (cmd, item) => {
|
||||
if (cmd === 'download_with_watermark' || cmd === 'download_without_watermark') {
|
||||
// 两种下载模式都调用同一个下载函数(暂时不区分水印)
|
||||
await download(item)
|
||||
} else if (cmd === 'rename') {
|
||||
if (cmd === 'rename') {
|
||||
ElMessage.info(t('works.renameDevMsg'))
|
||||
} else if (cmd === 'delete') {
|
||||
try {
|
||||
@@ -1191,6 +1181,27 @@ const onVideoLoaded = (event) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 复制提示词
|
||||
const copyPrompt = async () => {
|
||||
const prompt = getDescription(selectedItem.value)
|
||||
if (!prompt || prompt === t('profile.noPrompt')) return
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(prompt)
|
||||
ElMessage.success(t('common.copySuccess'))
|
||||
} catch (err) {
|
||||
console.error('复制失败:', err)
|
||||
ElMessage.error(t('common.copyFailed'))
|
||||
}
|
||||
}
|
||||
|
||||
// 下载当前作品
|
||||
const downloadWork = () => {
|
||||
if (selectedItem.value) {
|
||||
download(selectedItem.value)
|
||||
}
|
||||
}
|
||||
|
||||
// 视频加载失败处理
|
||||
const onVideoError = (event) => {
|
||||
const video = event.target
|
||||
@@ -1918,153 +1929,149 @@ onActivated(() => {
|
||||
}
|
||||
|
||||
/* 模态框样式 */
|
||||
:deep(.detail-dialog .el-dialog) {
|
||||
background: #0a0a0a !important;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #333;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.8);
|
||||
:deep(.work-detail-dialog) {
|
||||
--el-dialog-margin-top: 5vh;
|
||||
--el-dialog-bg-color: transparent;
|
||||
--el-dialog-border-radius: 12px;
|
||||
}
|
||||
|
||||
:deep(.detail-dialog .el-dialog__header) {
|
||||
background: #0a0a0a !important;
|
||||
border-bottom: 1px solid #333;
|
||||
padding: 16px 20px;
|
||||
:deep(.work-detail-dialog .el-dialog) {
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
border: none !important;
|
||||
margin: 0 auto;
|
||||
max-width: 95vw;
|
||||
}
|
||||
|
||||
:deep(.detail-dialog .el-dialog__title) {
|
||||
color: #fff !important;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
:deep(.work-detail-dialog .el-dialog__header) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:deep(.detail-dialog .el-dialog__headerbtn) {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
:deep(.detail-dialog .el-dialog__body) {
|
||||
background: #0a0a0a !important;
|
||||
:deep(.work-detail-dialog .el-dialog__body) {
|
||||
padding: 0 !important;
|
||||
background: transparent !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:deep(.detail-dialog .el-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
/* 遮罩层样式 */
|
||||
:deep(.el-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.85) !important;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
/* 强制覆盖Element Plus默认样式 */
|
||||
:deep(.el-dialog) {
|
||||
background: #0a0a0a !important;
|
||||
/* 自定义关闭按钮 */
|
||||
.dialog-close-btn {
|
||||
position: absolute;
|
||||
top: -50px;
|
||||
right: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__wrapper) {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
.dialog-close-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
display: flex;
|
||||
height: 50vh;
|
||||
background: #0a0a0a;
|
||||
height: 80vh;
|
||||
max-height: 800px;
|
||||
min-height: 500px;
|
||||
background: #1a1a1a;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.8);
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.detail-left {
|
||||
flex: 2;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #000;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.video-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.video-error-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
color: #f56c6c;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.error-content h3 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin: 16px 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.error-content p {
|
||||
font-size: 14px;
|
||||
color: #9ca3af;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.error-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.detail-video, .detail-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
/* overlay 样式已移除(不再使用) */
|
||||
|
||||
.detail-right {
|
||||
flex: 1;
|
||||
background: #0a0a0a;
|
||||
padding: 16px;
|
||||
width: 280px;
|
||||
flex: none;
|
||||
background: #1a1a1a;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
overflow-y: auto;
|
||||
border-left: 1px solid #333;
|
||||
}
|
||||
|
||||
/* 竖版视频(9:16)特殊布局 */
|
||||
.vertical-content {
|
||||
height: 85vh;
|
||||
max-height: 900px;
|
||||
}
|
||||
|
||||
.vertical-left {
|
||||
flex: none;
|
||||
width: 45%;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.vertical-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.vertical-content .detail-right {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
border: 2px solid #333;
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
@@ -2074,113 +2081,88 @@ onActivated(() => {
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
.detail-title-row {
|
||||
display: flex;
|
||||
gap: 0;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 8px 16px;
|
||||
background: transparent;
|
||||
color: #9ca3af;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
background: #409eff;
|
||||
.detail-title-row h3 {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tab:hover:not(.active) {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #fff;
|
||||
.category-badge {
|
||||
padding: 3px 8px;
|
||||
background: rgba(64, 158, 255, 0.15);
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.description-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
.section-label {
|
||||
font-size: 13px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: #d1d5db;
|
||||
color: #ccc;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 参考图特殊内容样式 */
|
||||
.reference-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
.copy-icon {
|
||||
margin-left: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.input-details-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.input-images {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.input-image-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.input-thumbnail {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
object-fit: cover;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #333;
|
||||
.copy-icon:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.metadata-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
gap: 6px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.metadata-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #9ca3af;
|
||||
.metadata-item .label {
|
||||
font-size: 13px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
.metadata-item .value {
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.action-section {
|
||||
margin-top: auto;
|
||||
padding-top: 20px;
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.create-similar-btn {
|
||||
@@ -2189,46 +2171,50 @@ onActivated(() => {
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 12px 24px;
|
||||
font-size: 16px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.create-similar-btn:hover {
|
||||
background: #337ecc;
|
||||
background: #66b1ff;
|
||||
}
|
||||
|
||||
/* 悬浮操作按钮 */
|
||||
.overlay-actions {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.icon-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.create-similar-btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* 更强制性的样式覆盖 */
|
||||
:deep(.detail-dialog) {
|
||||
background: #0a0a0a !important;
|
||||
}
|
||||
|
||||
:deep(.detail-dialog .el-dialog__wrapper) {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
}
|
||||
|
||||
:deep(.detail-dialog .el-overlay-dialog) {
|
||||
background: #0a0a0a !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* 全局模态框样式覆盖 */
|
||||
:deep(.el-dialog__wrapper) {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
}
|
||||
|
||||
:deep(.el-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.8) !important;
|
||||
}
|
||||
|
||||
/* 回到顶部按钮样式 */
|
||||
.back-to-top {
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user