ui层级修复
This commit is contained in:
@@ -753,7 +753,7 @@ input:checked+.slider:before {
|
|||||||
grid-template-columns: auto 1fr auto;
|
grid-template-columns: auto 1fr auto;
|
||||||
gap: var(--spacing-sm);
|
gap: var(--spacing-sm);
|
||||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
|
||||||
z-index: 2000;
|
z-index: 1001;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-back {
|
.nav-back {
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ onUnmounted(() => {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
top: 4.5rem;
|
top: 4.5rem;
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
z-index: 1000;
|
z-index: 1002;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +554,7 @@ onUnmounted(() => {
|
|||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-value.success + .stat-label {
|
.stat-value.success+.stat-label {
|
||||||
color: #047857;
|
color: #047857;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +570,7 @@ onUnmounted(() => {
|
|||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-value.error + .stat-label {
|
.stat-value.error+.stat-label {
|
||||||
color: #b91c1c;
|
color: #b91c1c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="registry-widget">
|
<div class="registry-widget" :class="{ 'panel-open': isOpen }">
|
||||||
<!-- 注册表管理按钮 -->
|
<!-- 注册表管理按钮 -->
|
||||||
<button @click="togglePanel" class="registry-toggle" :class="{ active: isOpen }" title="下载注册表管理">
|
<button @click="togglePanel" class="registry-toggle" :class="{ active: isOpen }" title="下载注册表管理">
|
||||||
<SvgIcon name="down" class="registry-icon" />
|
<SvgIcon name="down" class="registry-icon" />
|
||||||
@@ -82,9 +82,11 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="storage-option" :class="{ active: selectedStorageMode === 'database', disabled: !databaseConnected }">
|
<div class="storage-option"
|
||||||
|
:class="{ active: selectedStorageMode === 'database', disabled: !databaseConnected }">
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" v-model="selectedStorageMode" value="database" :disabled="migrationLoading || !databaseConnected" />
|
<input type="radio" v-model="selectedStorageMode" value="database"
|
||||||
|
:disabled="migrationLoading || !databaseConnected" />
|
||||||
<div class="option-content">
|
<div class="option-content">
|
||||||
<div class="option-header">
|
<div class="option-header">
|
||||||
<SvgIcon name="database" class="option-icon" />
|
<SvgIcon name="database" class="option-icon" />
|
||||||
@@ -144,22 +146,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
<button
|
<button @click="applyStorageModeConfig" class="btn btn-enhanced btn-primary"
|
||||||
@click="applyStorageModeConfig"
|
:disabled="migrationLoading || !hasStorageModeChanges || (selectedStorageMode === 'database' && !databaseConnected)">
|
||||||
class="btn btn-enhanced btn-primary"
|
|
||||||
:disabled="migrationLoading || !hasStorageModeChanges || (selectedStorageMode === 'database' && !databaseConnected)"
|
|
||||||
>
|
|
||||||
<SvgIcon name="save" class="btn-icon" />
|
<SvgIcon name="save" class="btn-icon" />
|
||||||
{{ migrationLoading ? '应用中...' : getApplyButtonText() }}
|
{{ migrationLoading ? '应用中...' : getApplyButtonText() }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button @click="resetStorageModeConfig" class="btn btn-enhanced btn-secondary"
|
||||||
@click="resetStorageModeConfig"
|
:disabled="migrationLoading || !hasStorageModeChanges">
|
||||||
class="btn btn-enhanced btn-secondary"
|
|
||||||
:disabled="migrationLoading || !hasStorageModeChanges"
|
|
||||||
>
|
|
||||||
<SvgIcon name="refresh" class="btn-icon" />
|
<SvgIcon name="refresh" class="btn-icon" />
|
||||||
重置
|
重置
|
||||||
</button>
|
</button>
|
||||||
@@ -167,11 +163,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="database-actions">
|
<div class="database-actions">
|
||||||
<button @click="openDatabaseConfig" class="btn btn-enhanced btn-secondary" :disabled="migrationLoading">
|
<button @click="openDatabaseConfig" class="btn btn-enhanced btn-secondary"
|
||||||
|
:disabled="migrationLoading">
|
||||||
<SvgIcon name="settings" class="btn-icon" />
|
<SvgIcon name="settings" class="btn-icon" />
|
||||||
数据库配置
|
数据库配置
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div v-if="migrationLoading" class="migration-status">
|
<div v-if="migrationLoading" class="migration-status">
|
||||||
<LoadingSpinner text="数据迁移中..." />
|
<LoadingSpinner text="数据迁移中..." />
|
||||||
</div>
|
</div>
|
||||||
@@ -240,12 +237,14 @@
|
|||||||
<div class="action-group">
|
<div class="action-group">
|
||||||
<div class="action-group-title">基础操作</div>
|
<div class="action-group-title">基础操作</div>
|
||||||
<div class="action-buttons basic-actions">
|
<div class="action-buttons basic-actions">
|
||||||
<button @click="refreshStats" class="btn btn-enhanced btn-secondary" :disabled="loading || isRebuildingRegistry">
|
<button @click="refreshStats" class="btn btn-enhanced btn-secondary"
|
||||||
|
:disabled="loading || isRebuildingRegistry">
|
||||||
<SvgIcon name="refresh" class="btn-icon" />
|
<SvgIcon name="refresh" class="btn-icon" />
|
||||||
刷新统计
|
刷新统计
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button @click="exportRegistry" class="btn btn-enhanced btn-primary" :disabled="loading || isRebuildingRegistry">
|
<button @click="exportRegistry" class="btn btn-enhanced btn-primary"
|
||||||
|
:disabled="loading || isRebuildingRegistry">
|
||||||
<SvgIcon name="download" class="btn-icon" />
|
<SvgIcon name="download" class="btn-icon" />
|
||||||
导出注册表
|
导出注册表
|
||||||
</button>
|
</button>
|
||||||
@@ -263,12 +262,14 @@
|
|||||||
<div class="action-group">
|
<div class="action-group">
|
||||||
<div class="action-group-title">高级操作</div>
|
<div class="action-group-title">高级操作</div>
|
||||||
<div class="action-buttons advanced-actions">
|
<div class="action-buttons advanced-actions">
|
||||||
<button @click="rebuildRegistry" class="btn btn-enhanced btn-warning" :disabled="loading || isRebuildingRegistry">
|
<button @click="rebuildRegistry" class="btn btn-enhanced btn-warning"
|
||||||
|
:disabled="loading || isRebuildingRegistry">
|
||||||
<SvgIcon name="rebuild" class="btn-icon" />
|
<SvgIcon name="rebuild" class="btn-icon" />
|
||||||
{{ isRebuildingRegistry ? '同步中...' : '同步文件系统' }}
|
{{ isRebuildingRegistry ? '同步中...' : '同步文件系统' }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button @click="cleanupRegistry" class="btn btn-enhanced btn-danger" :disabled="loading || isRebuildingRegistry">
|
<button @click="cleanupRegistry" class="btn btn-enhanced btn-danger"
|
||||||
|
:disabled="loading || isRebuildingRegistry">
|
||||||
<SvgIcon name="clean" class="btn-icon" />
|
<SvgIcon name="clean" class="btn-icon" />
|
||||||
清理注册表
|
清理注册表
|
||||||
</button>
|
</button>
|
||||||
@@ -284,7 +285,7 @@
|
|||||||
取消
|
取消
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress-content">
|
<div class="progress-content">
|
||||||
<div class="progress-stats">
|
<div class="progress-stats">
|
||||||
<div class="progress-stat">
|
<div class="progress-stat">
|
||||||
@@ -304,19 +305,19 @@
|
|||||||
<span class="stat-value">{{ rebuildProgress.skippedArtworks || 0 }}</span>
|
<span class="stat-value">{{ rebuildProgress.skippedArtworks || 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="rebuildProgress.currentArtist" class="current-status">
|
<div v-if="rebuildProgress.currentArtist" class="current-status">
|
||||||
<span class="status-label">当前处理:</span>
|
<span class="status-label">当前处理:</span>
|
||||||
<span class="status-value">{{ rebuildProgress.currentArtist }}</span>
|
<span class="status-value">{{ rebuildProgress.currentArtist }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress-bar-container">
|
<div class="progress-bar-container">
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<div class="progress-fill" :style="{ width: progressPercentage + '%' }"></div>
|
<div class="progress-fill" :style="{ width: progressPercentage + '%' }"></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="progress-text">{{ progressPercentage.toFixed(1) }}%</span>
|
<span class="progress-text">{{ progressPercentage.toFixed(1) }}%</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="time-info">
|
<div class="time-info">
|
||||||
<span class="elapsed-time">已用时: {{ formatElapsedTime(rebuildStartTime) }}</span>
|
<span class="elapsed-time">已用时: {{ formatElapsedTime(rebuildStartTime) }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -327,11 +328,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 数据库配置模态框 -->
|
<!-- 数据库配置模态框 -->
|
||||||
<DatabaseConfigModal
|
<DatabaseConfigModal :visible="showDatabaseConfig" @close="closeDatabaseConfig"
|
||||||
:visible="showDatabaseConfig"
|
@saved="handleDatabaseConfigSaved" />
|
||||||
@close="closeDatabaseConfig"
|
|
||||||
@saved="handleDatabaseConfigSaved"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -419,7 +417,7 @@ const exportRegistry = async () => {
|
|||||||
if (result.success) {
|
if (result.success) {
|
||||||
const modeText = useDatabase ? '数据库' : 'JSON文件';
|
const modeText = useDatabase ? '数据库' : 'JSON文件';
|
||||||
showSuccess(`注册表导出成功(${modeText}模式)`);
|
showSuccess(`注册表导出成功(${modeText}模式)`);
|
||||||
|
|
||||||
// 创建下载链接
|
// 创建下载链接
|
||||||
const blob = new Blob([JSON.stringify(result.data, null, 2)], { type: 'application/json' });
|
const blob = new Blob([JSON.stringify(result.data, null, 2)], { type: 'application/json' });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
@@ -443,7 +441,7 @@ const handleFileImport = async (event: Event) => {
|
|||||||
// 读取文件内容
|
// 读取文件内容
|
||||||
const fileContent = await file.text();
|
const fileContent = await file.text();
|
||||||
const registryData = JSON.parse(fileContent);
|
const registryData = JSON.parse(fileContent);
|
||||||
|
|
||||||
const useDatabase = storageMode.value === 'database';
|
const useDatabase = storageMode.value === 'database';
|
||||||
const result = await registryStore.importRegistry(registryData, useDatabase);
|
const result = await registryStore.importRegistry(registryData, useDatabase);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@@ -471,7 +469,7 @@ const rebuildRegistry = async () => {
|
|||||||
rebuildTaskId.value = result.data.taskId;
|
rebuildTaskId.value = result.data.taskId;
|
||||||
isRebuildingRegistry.value = true;
|
isRebuildingRegistry.value = true;
|
||||||
rebuildStartTime.value = Date.now();
|
rebuildStartTime.value = Date.now();
|
||||||
|
|
||||||
// 重置进度
|
// 重置进度
|
||||||
rebuildProgress.value = {
|
rebuildProgress.value = {
|
||||||
scannedArtists: 0,
|
scannedArtists: 0,
|
||||||
@@ -480,7 +478,7 @@ const rebuildRegistry = async () => {
|
|||||||
skippedArtworks: 0,
|
skippedArtworks: 0,
|
||||||
currentArtist: ''
|
currentArtist: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
// 开始轮询进度
|
// 开始轮询进度
|
||||||
startProgressPolling();
|
startProgressPolling();
|
||||||
showSuccess('文件系统同步已开始,请等待完成...');
|
showSuccess('文件系统同步已开始,请等待完成...');
|
||||||
@@ -498,15 +496,15 @@ const startProgressPolling = () => {
|
|||||||
if (progressPollingInterval.value) {
|
if (progressPollingInterval.value) {
|
||||||
clearInterval(progressPollingInterval.value);
|
clearInterval(progressPollingInterval.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
progressPollingInterval.value = setInterval(async () => {
|
progressPollingInterval.value = setInterval(async () => {
|
||||||
if (!rebuildTaskId.value) return;
|
if (!rebuildTaskId.value) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const statusResult = await downloadService.getRegistryRebuildStatus(rebuildTaskId.value);
|
const statusResult = await downloadService.getRegistryRebuildStatus(rebuildTaskId.value);
|
||||||
if (statusResult.success && statusResult.data) {
|
if (statusResult.success && statusResult.data) {
|
||||||
const status = statusResult.data;
|
const status = statusResult.data;
|
||||||
|
|
||||||
// 更新进度信息
|
// 更新进度信息
|
||||||
if (status.progress) {
|
if (status.progress) {
|
||||||
rebuildProgress.value = {
|
rebuildProgress.value = {
|
||||||
@@ -517,17 +515,17 @@ const startProgressPolling = () => {
|
|||||||
currentArtist: status.progress.currentArtist || ''
|
currentArtist: status.progress.currentArtist || ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查任务状态
|
// 检查任务状态
|
||||||
if (status.status === 'completed') {
|
if (status.status === 'completed') {
|
||||||
stopProgressPolling();
|
stopProgressPolling();
|
||||||
isRebuildingRegistry.value = false;
|
isRebuildingRegistry.value = false;
|
||||||
rebuildTaskId.value = null;
|
rebuildTaskId.value = null;
|
||||||
|
|
||||||
const addedCount = rebuildProgress.value.addedArtworks;
|
const addedCount = rebuildProgress.value.addedArtworks;
|
||||||
const skippedCount = rebuildProgress.value.skippedArtworks;
|
const skippedCount = rebuildProgress.value.skippedArtworks;
|
||||||
showSuccess(`文件系统同步完成!新增 ${addedCount} 个作品,跳过 ${skippedCount} 个已存在作品`);
|
showSuccess(`文件系统同步完成!新增 ${addedCount} 个作品,跳过 ${skippedCount} 个已存在作品`);
|
||||||
|
|
||||||
// 刷新统计信息
|
// 刷新统计信息
|
||||||
refreshStats();
|
refreshStats();
|
||||||
} else if (status.status === 'failed') {
|
} else if (status.status === 'failed') {
|
||||||
@@ -560,11 +558,11 @@ const stopProgressPolling = () => {
|
|||||||
// 取消重建任务
|
// 取消重建任务
|
||||||
const cancelRebuild = async () => {
|
const cancelRebuild = async () => {
|
||||||
if (!rebuildTaskId.value) return;
|
if (!rebuildTaskId.value) return;
|
||||||
|
|
||||||
if (!confirm('确定要取消文件系统同步吗?')) {
|
if (!confirm('确定要取消文件系统同步吗?')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await downloadService.cancelRegistryRebuild(rebuildTaskId.value);
|
const result = await downloadService.cancelRegistryRebuild(rebuildTaskId.value);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@@ -584,11 +582,11 @@ const cancelRebuild = async () => {
|
|||||||
// 格式化已用时间
|
// 格式化已用时间
|
||||||
const formatElapsedTime = (startTime: number): string => {
|
const formatElapsedTime = (startTime: number): string => {
|
||||||
if (!startTime) return '00:00';
|
if (!startTime) return '00:00';
|
||||||
|
|
||||||
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
||||||
const minutes = Math.floor(elapsed / 60);
|
const minutes = Math.floor(elapsed / 60);
|
||||||
const seconds = elapsed % 60;
|
const seconds = elapsed % 60;
|
||||||
|
|
||||||
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -722,11 +720,11 @@ const applyStorageModeConfig = async () => {
|
|||||||
// 根据迁移模式生成不同的确认消息
|
// 根据迁移模式生成不同的确认消息
|
||||||
let confirmMessage = '';
|
let confirmMessage = '';
|
||||||
if (migrationMode.value === 'switch-only') {
|
if (migrationMode.value === 'switch-only') {
|
||||||
confirmMessage = selectedStorageMode.value === 'database'
|
confirmMessage = selectedStorageMode.value === 'database'
|
||||||
? '确定要切换到数据库存储模式吗?这将仅改变读取方式,不会迁移现有数据。'
|
? '确定要切换到数据库存储模式吗?这将仅改变读取方式,不会迁移现有数据。'
|
||||||
: '确定要切换到JSON文件存储模式吗?这将仅改变读取方式,不会迁移现有数据。';
|
: '确定要切换到JSON文件存储模式吗?这将仅改变读取方式,不会迁移现有数据。';
|
||||||
} else {
|
} else {
|
||||||
confirmMessage = selectedStorageMode.value === 'database'
|
confirmMessage = selectedStorageMode.value === 'database'
|
||||||
? '确定要迁移数据并切换到数据库存储模式吗?这将把JSON数据迁移到数据库并覆盖数据库中的现有数据。'
|
? '确定要迁移数据并切换到数据库存储模式吗?这将把JSON数据迁移到数据库并覆盖数据库中的现有数据。'
|
||||||
: '确定要迁移数据并切换到JSON文件存储模式吗?这将把数据库数据迁移到JSON文件并覆盖JSON文件中的现有数据。';
|
: '确定要迁移数据并切换到JSON文件存储模式吗?这将把数据库数据迁移到JSON文件并覆盖JSON文件中的现有数据。';
|
||||||
}
|
}
|
||||||
@@ -737,7 +735,7 @@ const applyStorageModeConfig = async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
migrationLoading.value = true;
|
migrationLoading.value = true;
|
||||||
|
|
||||||
if (migrationMode.value === 'migrate-data') {
|
if (migrationMode.value === 'migrate-data') {
|
||||||
// 执行数据迁移
|
// 执行数据迁移
|
||||||
if (selectedStorageMode.value === 'database') {
|
if (selectedStorageMode.value === 'database') {
|
||||||
@@ -765,10 +763,10 @@ const applyStorageModeConfig = async () => {
|
|||||||
const modeText = selectedStorageMode.value === 'database' ? '数据库存储' : 'JSON文件存储';
|
const modeText = selectedStorageMode.value === 'database' ? '数据库存储' : 'JSON文件存储';
|
||||||
showSuccess(`已切换到${modeText}模式,数据读取方式已更改`);
|
showSuccess(`已切换到${modeText}模式,数据读取方式已更改`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存存储模式配置到后端
|
// 保存存储模式配置到后端
|
||||||
await saveStorageModeConfig(selectedStorageMode.value);
|
await saveStorageModeConfig(selectedStorageMode.value);
|
||||||
|
|
||||||
// 刷新统计信息
|
// 刷新统计信息
|
||||||
await refreshStats();
|
await refreshStats();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -859,6 +857,11 @@ watch(config, () => {
|
|||||||
bottom: 1rem;
|
bottom: 1rem;
|
||||||
left: 1rem;
|
left: 1rem;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
transition: z-index 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.registry-widget.panel-open {
|
||||||
|
z-index: 1002;
|
||||||
}
|
}
|
||||||
|
|
||||||
.registry-toggle {
|
.registry-toggle {
|
||||||
@@ -1148,7 +1151,7 @@ watch(config, () => {
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: radial-gradient(circle at 20% 80%, rgba(59, 130, 246, 0.03), transparent 50%),
|
background: radial-gradient(circle at 20% 80%, rgba(59, 130, 246, 0.03), transparent 50%),
|
||||||
radial-gradient(circle at 80% 20%, rgba(16, 185, 129, 0.03), transparent 50%);
|
radial-gradient(circle at 80% 20%, rgba(16, 185, 129, 0.03), transparent 50%);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1790,6 +1793,7 @@ watch(config, () => {
|
|||||||
0% {
|
0% {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
@@ -1821,9 +1825,12 @@ watch(config, () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% {
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
@@ -1941,20 +1948,20 @@ watch(config, () => {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: linear-gradient(90deg,
|
background: linear-gradient(90deg,
|
||||||
rgba(255, 255, 255, 0.1) 0%,
|
rgba(255, 255, 255, 0.1) 0%,
|
||||||
rgba(255, 255, 255, 0.3) 50%,
|
rgba(255, 255, 255, 0.3) 50%,
|
||||||
rgba(255, 255, 255, 0.1) 100%);
|
rgba(255, 255, 255, 0.1) 100%);
|
||||||
animation: shimmer 2s infinite;
|
animation: shimmer 2s infinite;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-fill {
|
.progress-fill {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: linear-gradient(90deg,
|
background: linear-gradient(90deg,
|
||||||
var(--color-success, #16a34a) 0%,
|
var(--color-success, #16a34a) 0%,
|
||||||
var(--color-info, #06b6d4) 50%,
|
var(--color-info, #06b6d4) 50%,
|
||||||
var(--color-warning, #f59e0b) 100%);
|
var(--color-warning, #f59e0b) 100%);
|
||||||
border-radius: var(--radius-full, 9999px);
|
border-radius: var(--radius-full, 9999px);
|
||||||
transition: width 0.5s ease-out;
|
transition: width 0.5s ease-out;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -1968,10 +1975,10 @@ watch(config, () => {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: linear-gradient(90deg,
|
background: linear-gradient(90deg,
|
||||||
transparent 0%,
|
transparent 0%,
|
||||||
rgba(255, 255, 255, 0.3) 50%,
|
rgba(255, 255, 255, 0.3) 50%,
|
||||||
transparent 100%);
|
transparent 100%);
|
||||||
animation: progressShine 1.5s ease-in-out infinite;
|
animation: progressShine 1.5s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1979,6 +1986,7 @@ watch(config, () => {
|
|||||||
0% {
|
0% {
|
||||||
transform: translateX(-100%);
|
transform: translateX(-100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
@@ -2183,9 +2191,12 @@ watch(config, () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% {
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
@@ -2242,15 +2253,15 @@ watch(config, () => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.migration-status {
|
.migration-status {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.storage-config-actions .action-buttons {
|
.storage-config-actions .action-buttons {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.storage-config-actions .btn {
|
.storage-config-actions .btn {
|
||||||
flex: none;
|
flex: none;
|
||||||
}
|
}
|
||||||
@@ -2262,34 +2273,34 @@ watch(config, () => {
|
|||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
gap: var(--spacing-xs, 0.25rem);
|
gap: var(--spacing-xs, 0.25rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-stat {
|
.progress-stat {
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-stat .stat-label {
|
.progress-stat .stat-label {
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-stat .stat-value {
|
.progress-stat .stat-value {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.current-status {
|
.current-status {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: var(--spacing-xs, 0.25rem);
|
gap: var(--spacing-xs, 0.25rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-value {
|
.status-value {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar-container {
|
.progress-bar-container {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--spacing-sm, 0.5rem);
|
gap: var(--spacing-sm, 0.5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-text {
|
.progress-text {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
@@ -2299,17 +2310,17 @@ watch(config, () => {
|
|||||||
.rebuild-progress {
|
.rebuild-progress {
|
||||||
padding: var(--spacing-md, 0.75rem);
|
padding: var(--spacing-md, 0.75rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-header {
|
.progress-header {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: var(--spacing-sm, 0.5rem);
|
gap: var(--spacing-sm, 0.5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-stats {
|
.progress-stats {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-small {
|
.btn-small {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="settings-widget">
|
<div class="settings-widget" :class="{ 'panel-open': isOpen }">
|
||||||
<!-- 设置按钮 -->
|
<!-- 设置按钮 -->
|
||||||
<button @click="toggleSettings" class="settings-toggle" :class="{ active: isOpen }" title="设置">
|
<button @click="toggleSettings" class="settings-toggle" :class="{ active: isOpen }" title="设置">
|
||||||
<SvgIcon name="settings" class="settings-icon" />
|
<SvgIcon name="settings" class="settings-icon" />
|
||||||
@@ -511,13 +511,13 @@ const restartServer = async () => {
|
|||||||
try {
|
try {
|
||||||
restarting.value = true;
|
restarting.value = true;
|
||||||
error.value = null;
|
error.value = null;
|
||||||
|
|
||||||
// 调用重启接口
|
// 调用重启接口
|
||||||
const response = await apiService.post('/api/system/restart');
|
const response = await apiService.post('/api/system/restart');
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
showSuccess('服务器重启请求已发送,页面将在几秒后自动刷新...');
|
showSuccess('服务器重启请求已发送,页面将在几秒后自动刷新...');
|
||||||
|
|
||||||
// 延迟刷新页面,给服务器时间重启
|
// 延迟刷新页面,给服务器时间重启
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
@@ -569,6 +569,11 @@ onMounted(() => {
|
|||||||
bottom: 2rem;
|
bottom: 2rem;
|
||||||
right: 2rem;
|
right: 2rem;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
transition: z-index 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-widget.panel-open {
|
||||||
|
z-index: 1002;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-toggle {
|
.settings-toggle {
|
||||||
|
|||||||
@@ -575,7 +575,7 @@ watch(() => route.fullPath, () => {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
top: 4.5rem;
|
top: 4.5rem;
|
||||||
left: 1rem;
|
left: 1rem;
|
||||||
z-index: 1000;
|
z-index: 1002;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ const handleSave = () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 1000;
|
z-index: 1002;
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const handleSave = () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 1000;
|
z-index: 1002;
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ const handleFileImport = async (event: Event) => {
|
|||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
||||||
z-index: 100;
|
z-index: 1002;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -3,16 +3,15 @@
|
|||||||
<div class="progress-header">
|
<div class="progress-header">
|
||||||
<h4 class="progress-title">{{ getTaskTitle(task) }}</h4>
|
<h4 class="progress-title">{{ getTaskTitle(task) }}</h4>
|
||||||
<div class="progress-actions">
|
<div class="progress-actions">
|
||||||
<button v-if="task.status === 'downloading' || task.status === 'pausing'" @click="pauseTask" class="btn btn-sm btn-secondary"
|
<button v-if="task.status === 'downloading' || task.status === 'pausing'" @click="pauseTask"
|
||||||
:disabled="loading || task.status === 'pausing'">
|
class="btn btn-sm btn-secondary" :disabled="loading || task.status === 'pausing'">
|
||||||
{{ task.status === 'pausing' ? '暂停中...' : '暂停' }}
|
{{ task.status === 'pausing' ? '暂停中...' : '暂停' }}
|
||||||
</button>
|
</button>
|
||||||
<button v-if="task.status === 'paused' || task.status === 'resuming'" @click="resumeTask" class="btn btn-sm btn-primary"
|
<button v-if="task.status === 'paused' || task.status === 'resuming'" @click="resumeTask"
|
||||||
:disabled="loading || task.status === 'resuming'">
|
class="btn btn-sm btn-primary" :disabled="loading || task.status === 'resuming'">
|
||||||
{{ task.status === 'resuming' ? '恢复中...' : '恢复' }}
|
{{ task.status === 'resuming' ? '恢复中...' : '恢复' }}
|
||||||
</button>
|
</button>
|
||||||
<button @click="cancelTask" class="btn btn-sm btn-danger"
|
<button @click="cancelTask" class="btn btn-sm btn-danger" :disabled="loading || task.status === 'cancelling'">
|
||||||
:disabled="loading || task.status === 'cancelling'">
|
|
||||||
{{ task.status === 'cancelling' ? '取消中...' : '取消' }}
|
{{ task.status === 'cancelling' ? '取消中...' : '取消' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -192,6 +191,7 @@ const cancelTask = async () => {
|
|||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
z-index: 1002;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-header {
|
.progress-header {
|
||||||
@@ -514,7 +514,7 @@ const cancelTask = async () => {
|
|||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-value.success + .stat-label {
|
.stat-value.success+.stat-label {
|
||||||
color: #047857;
|
color: #047857;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +530,7 @@ const cancelTask = async () => {
|
|||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-value.error + .stat-label {
|
.stat-value.error+.stat-label {
|
||||||
color: #b91c1c;
|
color: #b91c1c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
@page-change="currentImagePage = $event" />
|
@page-change="currentImagePage = $event" />
|
||||||
|
|
||||||
<!-- 右侧信息面板组件 -->
|
<!-- 右侧信息面板组件 -->
|
||||||
<ArtworkInfoPanel :artwork="artwork" :downloading="downloading" :deleting="deleting" :is-downloaded="isDownloaded"
|
<ArtworkInfoPanel :artwork="artwork" :downloading="downloading" :deleting="deleting"
|
||||||
:current-task="currentTask" :loading="loading" :show-navigation="showNavigation"
|
:is-downloaded="isDownloaded" :current-task="currentTask" :loading="loading" :show-navigation="showNavigation"
|
||||||
:previous-artwork="previousArtwork" :next-artwork="nextArtwork" :canNavigatePrevious="canNavigateToPrevious"
|
:previous-artwork="previousArtwork" :next-artwork="nextArtwork" :canNavigatePrevious="canNavigateToPrevious"
|
||||||
:canNavigateNext="canNavigateToNext" :selected-tags="selectedTags" :show-recommendations="showRecommendations"
|
:canNavigateNext="canNavigateToNext" :selected-tags="selectedTags" :show-recommendations="showRecommendations"
|
||||||
:show-caption="showCaption" @download="handleDownload" @delete="handleDelete" @go-back="goBackToArtist"
|
:show-caption="showCaption" @download="handleDownload" @delete="handleDelete" @go-back="goBackToArtist"
|
||||||
@@ -122,7 +122,7 @@ const checkMobileDevice = () => {
|
|||||||
// 触摸开始事件
|
// 触摸开始事件
|
||||||
const handleTouchStart = (event: TouchEvent) => {
|
const handleTouchStart = (event: TouchEvent) => {
|
||||||
if (!showNavigation.value || loading.value) return;
|
if (!showNavigation.value || loading.value) return;
|
||||||
|
|
||||||
const touch = event.touches[0];
|
const touch = event.touches[0];
|
||||||
touchStartX.value = touch.clientX;
|
touchStartX.value = touch.clientX;
|
||||||
touchStartY.value = touch.clientY;
|
touchStartY.value = touch.clientY;
|
||||||
@@ -132,11 +132,11 @@ const handleTouchStart = (event: TouchEvent) => {
|
|||||||
// 触摸移动事件
|
// 触摸移动事件
|
||||||
const handleTouchMove = (event: TouchEvent) => {
|
const handleTouchMove = (event: TouchEvent) => {
|
||||||
if (!showNavigation.value || loading.value) return;
|
if (!showNavigation.value || loading.value) return;
|
||||||
|
|
||||||
const touch = event.touches[0];
|
const touch = event.touches[0];
|
||||||
const deltaX = Math.abs(touch.clientX - touchStartX.value);
|
const deltaX = Math.abs(touch.clientX - touchStartX.value);
|
||||||
const deltaY = Math.abs(touch.clientY - touchStartY.value);
|
const deltaY = Math.abs(touch.clientY - touchStartY.value);
|
||||||
|
|
||||||
// 如果水平滑动距离大于垂直滑动距离,且超过阈值,则激活滑动状态
|
// 如果水平滑动距离大于垂直滑动距离,且超过阈值,则激活滑动状态
|
||||||
if (deltaX > deltaY && deltaX > 30) {
|
if (deltaX > deltaY && deltaX > 30) {
|
||||||
isSwipeActive.value = true;
|
isSwipeActive.value = true;
|
||||||
@@ -147,18 +147,18 @@ const handleTouchMove = (event: TouchEvent) => {
|
|||||||
// 触摸结束事件
|
// 触摸结束事件
|
||||||
const handleTouchEnd = (event: TouchEvent) => {
|
const handleTouchEnd = (event: TouchEvent) => {
|
||||||
if (!showNavigation.value || loading.value) return;
|
if (!showNavigation.value || loading.value) return;
|
||||||
|
|
||||||
const touch = event.changedTouches[0];
|
const touch = event.changedTouches[0];
|
||||||
touchEndX.value = touch.clientX;
|
touchEndX.value = touch.clientX;
|
||||||
touchEndY.value = touch.clientY;
|
touchEndY.value = touch.clientY;
|
||||||
|
|
||||||
const deltaX = touchEndX.value - touchStartX.value;
|
const deltaX = touchEndX.value - touchStartX.value;
|
||||||
const deltaY = Math.abs(touchEndY.value - touchStartY.value);
|
const deltaY = Math.abs(touchEndY.value - touchStartY.value);
|
||||||
|
|
||||||
// 检查是否为有效的水平滑动
|
// 检查是否为有效的水平滑动
|
||||||
const minSwipeDistance = 80; // 最小滑动距离
|
const minSwipeDistance = 80; // 最小滑动距离
|
||||||
const maxVerticalDistance = 100; // 最大垂直偏移
|
const maxVerticalDistance = 100; // 最大垂直偏移
|
||||||
|
|
||||||
if (Math.abs(deltaX) > minSwipeDistance && deltaY < maxVerticalDistance) {
|
if (Math.abs(deltaX) > minSwipeDistance && deltaY < maxVerticalDistance) {
|
||||||
if (deltaX > 0 && canNavigateToPrevious.value) {
|
if (deltaX > 0 && canNavigateToPrevious.value) {
|
||||||
// 向右滑动 - 上一个作品
|
// 向右滑动 - 上一个作品
|
||||||
@@ -168,14 +168,14 @@ const handleTouchEnd = (event: TouchEvent) => {
|
|||||||
navigateToNext();
|
navigateToNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isSwipeActive.value = false;
|
isSwipeActive.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 显示滑动提示
|
// 显示滑动提示
|
||||||
const showSwipeHintTemporarily = () => {
|
const showSwipeHintTemporarily = () => {
|
||||||
if (!isMobile.value || !showNavigation.value) return;
|
if (!isMobile.value || !showNavigation.value) return;
|
||||||
|
|
||||||
showSwipeHint.value = true;
|
showSwipeHint.value = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showSwipeHint.value = false;
|
showSwipeHint.value = false;
|
||||||
@@ -454,7 +454,7 @@ const handleDelete = async () => {
|
|||||||
if (response.success) {
|
if (response.success) {
|
||||||
// 删除成功后更新本地状态
|
// 删除成功后更新本地状态
|
||||||
isDownloaded.value = false;
|
isDownloaded.value = false;
|
||||||
|
|
||||||
// 显示成功提示(非阻塞)
|
// 显示成功提示(非阻塞)
|
||||||
const successMessage = document.createElement('div');
|
const successMessage = document.createElement('div');
|
||||||
successMessage.textContent = '作品删除成功';
|
successMessage.textContent = '作品删除成功';
|
||||||
@@ -471,21 +471,21 @@ const handleDelete = async () => {
|
|||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
`;
|
`;
|
||||||
document.body.appendChild(successMessage);
|
document.body.appendChild(successMessage);
|
||||||
|
|
||||||
// 3秒后自动移除提示
|
// 3秒后自动移除提示
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (successMessage.parentNode) {
|
if (successMessage.parentNode) {
|
||||||
successMessage.parentNode.removeChild(successMessage);
|
successMessage.parentNode.removeChild(successMessage);
|
||||||
}
|
}
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
// 不退出页面,保持在当前页面
|
// 不退出页面,保持在当前页面
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.error || '删除失败');
|
throw new Error(response.error || '删除失败');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const errorMessage = err instanceof Error ? err.message : '删除作品失败';
|
const errorMessage = err instanceof Error ? err.message : '删除作品失败';
|
||||||
|
|
||||||
// 显示错误提示(非阻塞)
|
// 显示错误提示(非阻塞)
|
||||||
const errorDiv = document.createElement('div');
|
const errorDiv = document.createElement('div');
|
||||||
errorDiv.textContent = '删除失败: ' + errorMessage;
|
errorDiv.textContent = '删除失败: ' + errorMessage;
|
||||||
@@ -502,14 +502,14 @@ const handleDelete = async () => {
|
|||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
`;
|
`;
|
||||||
document.body.appendChild(errorDiv);
|
document.body.appendChild(errorDiv);
|
||||||
|
|
||||||
// 3秒后自动移除提示
|
// 3秒后自动移除提示
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (errorDiv.parentNode) {
|
if (errorDiv.parentNode) {
|
||||||
errorDiv.parentNode.removeChild(errorDiv);
|
errorDiv.parentNode.removeChild(errorDiv);
|
||||||
}
|
}
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
console.error('删除作品失败:', err);
|
console.error('删除作品失败:', err);
|
||||||
} finally {
|
} finally {
|
||||||
deleting.value = false; // 重置删除状态
|
deleting.value = false; // 重置删除状态
|
||||||
@@ -906,7 +906,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 检测移动设备
|
// 检测移动设备
|
||||||
checkMobileDevice();
|
checkMobileDevice();
|
||||||
|
|
||||||
// 监听窗口大小变化
|
// 监听窗口大小变化
|
||||||
window.addEventListener('resize', checkMobileDevice);
|
window.addEventListener('resize', checkMobileDevice);
|
||||||
|
|
||||||
@@ -927,7 +927,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 初始化 Caption 开关状态
|
// 初始化 Caption 开关状态
|
||||||
initializeCaptionState();
|
initializeCaptionState();
|
||||||
|
|
||||||
// 延迟显示滑动提示(仅在移动端且有导航时)
|
// 延迟显示滑动提示(仅在移动端且有导航时)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showSwipeHintTemporarily();
|
showSwipeHintTemporarily();
|
||||||
@@ -994,18 +994,21 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.artwork-page {
|
.artwork-page {
|
||||||
padding: 1rem 0 0 0; /* 移除底部内边距 */
|
padding: 1rem 0 0 0;
|
||||||
|
/* 移除底部内边距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
margin-bottom: 0; /* 移除底部外边距 */
|
margin-bottom: 0;
|
||||||
|
/* 移除底部外边距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.artwork-content {
|
.artwork-content {
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||||
padding-bottom: 0; /* 确保没有额外的底部内边距 */
|
padding-bottom: 0;
|
||||||
|
/* 确保没有额外的底部内边距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.artwork-content.swiping {
|
.artwork-content.swiping {
|
||||||
@@ -1026,7 +1029,7 @@ onUnmounted(() => {
|
|||||||
border-radius: 2rem;
|
border-radius: 2rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
z-index: 1000;
|
z-index: 1002;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|||||||
Reference in New Issue
Block a user