svg统一管理

This commit is contained in:
2025-09-25 11:06:49 +08:00
parent b3dd41ec44
commit a9dcbc2578
25 changed files with 193 additions and 282 deletions
+2 -8
View File
@@ -47,10 +47,7 @@ onMounted(async () => {
<div class="nav-container">
<div class="nav-brand">
<RouterLink to="/" class="brand-link">
<svg viewBox="0 0 24 24" fill="currentColor" class="brand-icon">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="home2" class="brand-icon" />
<span class="brand-text">Pixiv Manager</span>
</RouterLink>
</div>
@@ -78,10 +75,7 @@ onMounted(async () => {
<!-- GitHub 链接 -->
<a href="https://github.com/kjqwer/pixiv-D" target="_blank" rel="noopener noreferrer" class="github-link"
title="查看项目源码">
<svg viewBox="0 0 24 24" fill="currentColor" class="github-icon">
<path
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
<SvgIcon name="github" class="github-icon" />
</a>
</div>
</div>
+24
View File
@@ -0,0 +1,24 @@
// 操作相关图标
export const actionIcons = {
'download': 'M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z',
'settings': 'M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z',
'user': 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z',
'edit': 'M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z',
'delete': 'M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z',
'save': 'M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z',
'close': 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
'success': 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z',
'check-circle': 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z',
'arrow-left': 'M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z',
'arrow-left2': 'M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z',
'arrow-next': 'M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z',
'arrow-right': 'M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z',
'error': 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z',
'sort-desc': 'M3 12l2-2 7 7 10-10 2 2L12 21z',
'sort-asc': 'M12 3l10 10-2 2-7-7-7 7-2-2z',
'empty': 'M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z',
'empty2': 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
'refresh': 'M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z',
'cleanup': 'M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z',
}
+6
View File
@@ -0,0 +1,6 @@
// 品牌相关图标
export const brandIcons = {
'home2': 'M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7 12h2v5H7zm4-3h2v8h-2zm4-3h2v11h-2z',
'home3': 'M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z',
'github': 'M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z'
}
+29
View File
@@ -0,0 +1,29 @@
// 导入各类图标
import { brandIcons } from './brand'
import { navigationIcons } from './navigation'
import { actionIcons } from './actions'
// 自动合并所有分类图标到统一注册表
export const iconRegistry: Record<string, string> = {
...brandIcons,
...navigationIcons,
...actionIcons
}
// 类型定义
export type IconName = keyof typeof iconRegistry
// 添加新图标的辅助函数
export const addIcon = (name: string, pathData: string) => {
iconRegistry[name] = pathData
}
// 检查图标是否存在
export const hasIcon = (name: string): boolean => {
return name in iconRegistry
}
// 获取所有图标名称
export const getAllIconNames = (): string[] => {
return Object.keys(iconRegistry)
}
+20
View File
@@ -0,0 +1,20 @@
// 导航相关图标
export const navigationIcons = {
'home': 'M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z',
'search': 'M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z',
'ranking': 'M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4 4 6.3-6.29L22 12V6z',
'bookmark': 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z',
'bookmark-empty': 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
'eye': 'M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z',
'folder': 'M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z',
'settings': 'M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z',
'update': 'M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z',
'update-spinning': 'M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z',
'info': 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
'watchlist': 'M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM10 17l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
'watchlist-update': 'M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z',
'add': 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z',
'cleanup-history': 'M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z',
'cleanup-history2': 'M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z',
'loading': 'M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z',
}
+2 -8
View File
@@ -25,17 +25,11 @@
<div class="artwork-stats">
<span class="stat">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
</svg>
<SvgIcon name="bookmark" />
{{ artwork.total_bookmarks }}
</span>
<span class="stat">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" />
</svg>
<SvgIcon name="eye" />
{{ artwork.total_view }}
</span>
</div>
+7 -24
View File
@@ -22,9 +22,7 @@
<!-- 下载状态提示 -->
<div v-if="isDownloaded && !currentTask" class="download-status">
<div class="status-indicator">
<svg viewBox="0 0 24 24" fill="currentColor" class="status-icon">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
<SvgIcon name="check-circle" class="status-icon" />
<span>已下载到本地</span>
</div>
</div>
@@ -50,49 +48,34 @@
<!-- 作品导航 -->
<div v-if="showNavigation" class="artwork-navigation">
<button @click="$emit('goBack')" class="nav-btn nav-back" title="返回作者页面(快捷键: Esc / ↑ )">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
</svg>
<SvgIcon name="arrow-left" />
<span>返回 <span class="keyboard-hint">(Esc)</span></span>
</button>
<button @click="$emit('navigatePrevious')" class="nav-btn nav-prev"
:disabled="!canNavigatePrevious || loading"
:title="canNavigatePrevious ? (previousArtwork ? `上一个(快捷键: ←): ${previousArtwork.title}` : '加载上一页') : '没有上一个作品'">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
</svg>
<SvgIcon name="arrow-left2" />
<span>{{ loading ? '切换中...' : '上一个' }} </span>
</button>
<button @click="$emit('navigateNext')" class="nav-btn nav-next" :disabled="!canNavigateNext || loading"
:title="canNavigateNext ? (nextArtwork ? `下一个(快捷键: →): ${nextArtwork.title}` : '加载下一页') : '没有下一个作品'">
<span>{{ loading ? '切换中...' : '下一个' }} </span>
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" />
</svg>
<SvgIcon name="arrow-next" />
</button>
</div>
<!-- 作品统计 -->
<div class="artwork-stats">
<div class="stat">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
</svg>
<SvgIcon name="bookmark" />
<span>{{ artwork.total_bookmarks }}</span>
</div>
<div class="stat">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" />
</svg>
<SvgIcon name="eye" />
<span>{{ artwork.total_view }}</span>
</div>
<div class="stat">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z" />
</svg>
<SvgIcon name="folder" />
<span>{{ artwork.width }} × {{ artwork.height }}</span>
</div>
</div>
@@ -3,12 +3,8 @@
<!-- 小圆点指示器 -->
<div class="widget-indicator" @click="toggleExpanded" :class="indicatorClass">
<div class="indicator-icon">
<svg v-if="activeTasks.length === 0" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<svg v-else viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon v-if="activeTasks.length === 0" name="bookmark-empty" />
<SvgIcon v-else name="bookmark-empty" />
</div>
<div v-if="activeTasks.length > 0" class="task-count">{{ activeTasks.length }}</div>
</div>
@@ -18,9 +14,7 @@
<div class="panel-header">
<h3>下载进度</h3>
<button @click="toggleExpanded" class="close-btn">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" />
</button>
</div>
@@ -31,9 +25,7 @@
</div>
<div v-else-if="activeTasks.length === 0" class="empty-section">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="bookmark-empty" class="empty-icon" />
<span>暂无下载任务</span>
</div>
+2 -6
View File
@@ -1,18 +1,14 @@
<template>
<div v-if="error" class="error-message" :class="type">
<div class="error-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
<SvgIcon name="bookmark-empty" />
</div>
<div class="error-content">
<div class="error-title">{{ title }}</div>
<div class="error-text">{{ error }}</div>
</div>
<button v-if="dismissible" @click="$emit('dismiss')" class="error-close">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
</svg>
<SvgIcon name="close" />
</button>
</div>
</template>
+3 -11
View File
@@ -2,10 +2,7 @@
<div class="settings-widget">
<!-- 设置按钮 -->
<button @click="toggleSettings" class="settings-toggle" :class="{ active: isOpen }" title="设置">
<svg viewBox="0 0 24 24" fill="currentColor" class="settings-icon">
<path
d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z" />
</svg>
<SvgIcon name="settings" class="settings-icon" />
</button>
<!-- 设置面板 -->
@@ -13,10 +10,7 @@
<div class="settings-header">
<h3>设置</h3>
<button @click="toggleSettings" class="close-btn" title="关闭">
<svg viewBox="0 0 24 24" fill="currentColor" class="close-icon">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" class="close-icon" />
</button>
</div>
@@ -36,9 +30,7 @@
<!-- 成功提示 -->
<div v-if="successMessage" class="success-message">
<div class="success-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="success-icon">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
<SvgIcon name="success" class="success-icon" />
<span>{{ successMessage }}</span>
</div>
</div>
+25
View File
@@ -0,0 +1,25 @@
<template>
<svg :viewBox="viewBox" :fill="fill" v-bind="$attrs">
<path v-if="iconData" :d="iconData" />
</svg>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { iconRegistry } from '@/assets/icons'
interface Props {
name: string
viewBox?: string
fill?: string
}
const props = withDefaults(defineProps<Props>(), {
viewBox: '0 0 24 24',
fill: 'currentColor'
})
const iconData = computed(() => {
return iconRegistry[props.name] || ''
})
</script>
+7 -27
View File
@@ -5,13 +5,8 @@
:class="{ 'has-update': hasUpdate, 'checking': isChecking }" :title="hasUpdate ? '发现新版本!' : '检查更新'">
<!-- 更新提示小红点 -->
<span v-if="hasUpdate" class="update-dot"></span>
<svg v-if="!isChecking" viewBox="0 0 24 24" fill="currentColor" class="update-icon">
<path
d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" />
</svg>
<svg v-else viewBox="0 0 24 24" fill="currentColor" class="update-icon spinning">
<path d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" />
</svg>
<SvgIcon v-if="!isChecking" name="update" class="update-icon" />
<SvgIcon v-else name="update" class="update-icon spinning" />
<span v-if="!hasUpdate">{{ isChecking ? '检查中...' : '检查更新' }}</span>
<span v-else class="update-available">有新版本</span>
</button>
@@ -22,17 +17,11 @@
<div class="modal-content" @click.stop>
<div class="modal-header">
<h3 class="modal-title">
<svg viewBox="0 0 24 24" fill="currentColor" class="modal-icon">
<path
d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" />
</svg>
<SvgIcon name="update" class="modal-icon" />
版本检查结果
</h3>
<button @click="closeModal" class="modal-close">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" class="modal-close" />
</button>
</div>
@@ -52,10 +41,7 @@
<div v-if="updateInfo?.hasUpdate" class="update-available-section">
<div class="update-status">
<svg viewBox="0 0 24 24" fill="currentColor" class="status-icon success">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="success" class="status-icon success" />
<span class="status-text">发现新版本</span>
</div>
@@ -99,20 +85,14 @@
<div v-else-if="updateInfo && !updateInfo.hasUpdate" class="no-update-section">
<div class="update-status">
<svg viewBox="0 0 24 24" fill="currentColor" class="status-icon info">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" />
</svg>
<SvgIcon name="info" class="status-icon info" />
<span class="status-text">您使用的已是最新版本</span>
</div>
</div>
<div v-if="error" class="error-section">
<div class="update-status">
<svg viewBox="0 0 24 24" fill="currentColor" class="status-icon error">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" />
</svg>
<SvgIcon name="error" class="status-icon error" />
<span class="status-text">检查更新失败</span>
</div>
<div class="error-message">{{ error }}</div>
+22 -60
View File
@@ -2,10 +2,7 @@
<div class="watchlist-widget">
<!-- 待看名单按钮 -->
<button @click="toggleWatchlist" class="watchlist-toggle" :class="{ active: isOpen }" title="待看名单">
<svg viewBox="0 0 24 24" fill="currentColor" class="watchlist-icon">
<path
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM10 17l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="watchlist" class="watchlist-icon" />
<div v-if="itemCount > 0" class="item-count">{{ itemCount }}</div>
</button>
@@ -15,19 +12,17 @@
loading: addLoading,
update: hasSameAuthorDifferentPage && !isCurrentPageAdded
}" :disabled="addLoading" :title="getAddButtonTitle()">
<svg v-if="!addLoading" viewBox="0 0 24 24" fill="currentColor" class="add-icon">
<!-- 加载状态显示加载图标 -->
<SvgIcon v-if="addLoading" name="loading" class="loading-icon" />
<!-- 非加载状态根据条件显示不同图标 -->
<template v-else>
<!-- 已添加显示勾选图标 -->
<path v-if="isCurrentPageAdded" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
<SvgIcon v-if="isCurrentPageAdded" name="success" class="add-icon" />
<!-- 更新模式显示更新图标 -->
<path v-else-if="hasSameAuthorDifferentPage"
d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z" />
<SvgIcon v-else-if="hasSameAuthorDifferentPage" name="watchlist-update" class="add-icon" />
<!-- 添加模式显示加号图标 -->
<path v-else d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</svg>
<svg v-else viewBox="0 0 24 24" fill="currentColor" class="loading-icon">
<path
d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z" />
</svg>
<SvgIcon v-else name="add" class="add-icon" />
</template>
</button>
<!-- 待看名单面板 -->
@@ -37,15 +32,10 @@
<div class="header-actions">
<span class="item-count-text">{{ itemCount }} </span>
<button @click="showAddModal" class="add-btn" title="手动添加">
<svg viewBox="0 0 24 24" fill="currentColor" class="add-icon">
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</svg>
<SvgIcon name="add" class="add-icon" />
</button>
<button @click="toggleWatchlist" class="close-btn" title="关闭">
<svg viewBox="0 0 24 24" fill="currentColor" class="close-icon">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" class="close-icon" />
</button>
</div>
</div>
@@ -53,24 +43,16 @@
<!-- 搜索和排序控制区域 -->
<div class="watchlist-controls">
<div class="search-box">
<svg viewBox="0 0 24 24" fill="currentColor" class="search-icon">
<path
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
</svg>
<SvgIcon name="search" class="search-icon" />
<input v-model="searchQuery" type="text" placeholder="搜索标题或URL..." class="search-input" />
<button v-if="searchQuery" @click="clearSearch" class="clear-search-btn" title="清除搜索">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" class="close-icon" />
</button>
</div>
<div class="sort-controls">
<button @click="toggleSortOrder" class="sort-btn" :title="sortOrder === 'desc' ? '切换为升序' : '切换为降序'">
<svg viewBox="0 0 24 24" fill="currentColor" class="sort-icon">
<path v-if="sortOrder === 'desc'" d="M3 12l2-2 7 7 10-10 2 2L12 21z" />
<path v-else d="M12 3l10 10-2 2-7-7-7 7-2-2z" />
</svg>
<SvgIcon v-if="sortOrder === 'desc'" name="sort-desc" class="sort-icon" />
<SvgIcon v-else name="sort-asc" class="sort-icon" />
<span class="sort-text">{{ sortOrder === 'desc' ? '最新' : '最旧' }}</span>
</button>
</div>
@@ -83,28 +65,19 @@
</div>
<div v-else-if="error" class="error">
<svg viewBox="0 0 24 24" fill="currentColor" class="error-icon">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="bookmark-empty" class="error-icon" />
<span>{{ error }}</span>
<button @click="fetchItems" class="retry-btn">重试</button>
</div>
<div v-else-if="filteredAndSortedItems.length === 0 && searchQuery" class="empty">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
</svg>
<SvgIcon name="search" class="empty-icon" />
<span>没有找到匹配的项目</span>
<p>尝试调整搜索词或清除搜索条件</p>
</div>
<div v-else-if="items.length === 0" class="empty">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z" />
</svg>
<SvgIcon name="empty" class="empty-icon" />
<span>暂无待看项目</span>
<p>点击右侧的 + 按钮添加当前页面</p>
</div>
@@ -126,15 +99,10 @@
<div class="item-actions">
<button @click="editItem(item)" class="action-btn edit-btn" title="编辑">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
</svg>
<SvgIcon name="edit" class="edit-icon" />
</button>
<button @click="deleteItemById(item.id)" class="action-btn delete-btn" title="删除">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
</svg>
<SvgIcon name="delete" class="delete-icon" />
</button>
</div>
</div>
@@ -148,10 +116,7 @@
<div class="modal-header">
<h4>编辑待看项目</h4>
<button @click="cancelEdit" class="close-btn">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" class="close-icon" />
</button>
</div>
<div class="modal-content">
@@ -177,10 +142,7 @@
<div class="modal-header">
<h4>添加待看项目</h4>
<button @click="cancelAdd" class="close-btn">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" class="close-icon" />
</button>
</div>
<div class="modal-content">
@@ -25,10 +25,7 @@
<div v-else-if="recommendations.length === 0" class="empty-section">
<div class="empty-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="empty2" class="empty-icon" />
<p class="empty-text">暂无推荐内容</p>
<p class="empty-subtext">关注一些作者后这里会显示他们的最新作品</p>
</div>
@@ -5,9 +5,7 @@
class="page-btn"
:disabled="currentPage <= 1"
>
<svg viewBox="0 0 24 24" fill="currentColor" class="page-icon">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
</svg>
<SvgIcon name="arrow-left2" class="page-icon" />
上一页
</button>
@@ -29,9 +27,7 @@
:disabled="currentPage >= totalPages"
>
下一页
<svg viewBox="0 0 24 24" fill="currentColor" class="page-icon">
<path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z"/>
</svg>
<SvgIcon name="arrow-next" class="page-icon" />
</button>
</div>
</template>
+2 -8
View File
@@ -6,10 +6,7 @@
<input v-model="searchKeyword" type="text" placeholder="输入作者名称或账号搜索..." class="search-input"
@keyup.enter="handleSearch" />
<button @click="handleSearch" class="search-btn" :disabled="loading">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
</svg>
<SvgIcon name="search" />
</button>
</div>
@@ -47,10 +44,7 @@
<div v-else-if="hasSearched" class="empty-section">
<div class="empty-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
</svg>
<SvgIcon name="user" class="empty-icon" />
<h3>未找到相关作者</h3>
<p>尝试使用不同的关键词搜索</p>
</div>
+2
View File
@@ -9,12 +9,14 @@ import router from './router'
// 导入全局组件
import ErrorMessage from '@/components/common/ErrorMessage.vue'
import LoadingSpinner from '@/components/common/LoadingSpinner.vue'
import SvgIcon from '@/components/common/SvgIcon.vue'
const app = createApp(App)
// 注册全局组件
app.component('ErrorMessage', ErrorMessage)
app.component('LoadingSpinner', LoadingSpinner)
app.component('SvgIcon', SvgIcon)
app.use(createPinia())
app.use(router)
+5 -15
View File
@@ -12,9 +12,7 @@
<!-- 下载成功提示 -->
<div v-if="downloadSuccess" class="success-message">
<div class="success-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="success-icon">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
<SvgIcon name="success" class="success-icon" />
<span>{{ downloadSuccess }}</span>
</div>
</div>
@@ -91,16 +89,12 @@
<!-- 顶部分页导航 -->
<div v-if="totalPages > 1 && artworks.length > 0" class="simple-pagination">
<button @click="goToPage(currentPage - 1)" class="simple-page-btn" :disabled="currentPage <= 1">
<svg viewBox="0 0 24 24" fill="currentColor" class="simple-page-icon">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
</svg>
<SvgIcon name="arrow-left2" class="simple-page-icon" />
</button>
<span class="simple-page-info">{{ currentPage }} / {{ totalPages }}</span>
<button @click="goToPage(currentPage + 1)" class="simple-page-btn"
:disabled="currentPage >= totalPages">
<svg viewBox="0 0 24 24" fill="currentColor" class="simple-page-icon">
<path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" />
</svg>
<SvgIcon name="arrow-right" class="simple-page-icon" />
</button>
</div>
</div>
@@ -122,9 +116,7 @@
<div v-if="totalPages > 1 && artworks.length > 0" class="pagination">
<button @click="goToPage(currentPage - 1)" class="page-btn" :disabled="currentPage <= 1"
:title="`上一页(快捷键: ←)`">
<svg viewBox="0 0 24 24" fill="currentColor" class="page-icon">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
</svg>
<SvgIcon name="arrow-left2" class="page-icon" />
上一页
</button>
@@ -138,9 +130,7 @@
<button @click="goToPage(currentPage + 1)" class="page-btn" :disabled="currentPage >= totalPages"
:title="`下一页(快捷键: →)`">
下一页
<svg viewBox="0 0 24 24" fill="currentColor" class="page-icon">
<path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z" />
</svg>
<SvgIcon name="arrow-right" class="page-icon" />
</button>
</div>
+6 -22
View File
@@ -22,10 +22,7 @@
</button>
</div>
<button @click="handleRefresh" class="btn btn-secondary" :disabled="artistStore.loading">
<svg viewBox="0 0 24 24" fill="currentColor" class="refresh-icon">
<path
d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
</svg>
<SvgIcon name="refresh" class="refresh-icon" />
刷新
</button>
</div>
@@ -46,16 +43,11 @@
<h2 class="section-title">关注的作者</h2>
<div v-if="artistStore.hasFollowingArtists" class="cache-indicator">
<span v-if="artistStore.isDataStale" class="cache-status stale">
<svg viewBox="0 0 24 24" fill="currentColor" class="cache-icon">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="empty2" class="cache-icon" />
数据已过期
</span>
<span v-else class="cache-status fresh">
<svg viewBox="0 0 24 24" fill="currentColor" class="cache-icon">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
<SvgIcon name="success" class="cache-icon" />
数据已缓存
</span>
</div>
@@ -74,10 +66,7 @@
<div v-else class="empty-section">
<div class="empty-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
</svg>
<SvgIcon name="user" class="empty-icon" />
<h3>暂无关注的作者</h3>
<p>关注喜欢的作者在这里管理他们</p>
<div v-if="!artistStore.loading && artistStore.hasFollowingArtists" class="cache-note">
@@ -95,10 +84,7 @@
<div class="modal-header">
<h3>下载作品</h3>
<button @click="closeDownloadDialog" class="modal-close">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" class="modal-close-icon" />
</button>
</div>
@@ -142,9 +128,7 @@
<!-- 下载成功提示 -->
<div v-if="downloadSuccess" class="success-message">
<div class="success-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="success-icon">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
<SvgIcon name="success" class="success-icon" />
<span>{{ downloadSuccess }}</span>
</div>
</div>
+1 -4
View File
@@ -23,10 +23,7 @@
<div v-else-if="artworks.length === 0" class="empty-section">
<div class="empty-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="empty2" class="empty-icon" />
<h3>暂无收藏作品</h3>
<p>你还没有收藏任何作品</p>
<router-link to="/search" class="btn btn-primary">
+5 -18
View File
@@ -5,22 +5,15 @@
<h1>下载管理</h1>
<div class="header-actions">
<button @click="refreshData" class="btn btn-primary" :disabled="loading">
<svg viewBox="0 0 24 24" fill="currentColor" class="btn-icon">
<path
d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
</svg>
<SvgIcon name="refresh" class="btn-icon" />
刷新
</button>
<button @click="cleanupTasks" class="btn btn-secondary" :disabled="loading">
<svg viewBox="0 0 24 24" fill="currentColor" class="btn-icon">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
</svg>
<SvgIcon name="cleanup" class="btn-icon" />
清理任务
</button>
<button @click="cleanupHistory" class="btn btn-secondary" :disabled="loading">
<svg viewBox="0 0 24 24" fill="currentColor" class="btn-icon">
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z" />
</svg>
<SvgIcon name="cleanup-history2" class="btn-icon" />
清理历史
</button>
</div>
@@ -48,10 +41,7 @@
<div v-else-if="activeTasks.length === 0" class="empty-section">
<div class="empty-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z" />
</svg>
<SvgIcon name="empty" class="empty-icon" />
<h3>暂无下载任务</h3>
<p>开始下载作品后任务将显示在这里</p>
</div>
@@ -153,10 +143,7 @@
<div v-else-if="history.length === 0" class="empty-section">
<div class="empty-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z" />
</svg>
<SvgIcon name="cleanup-history" class="empty-icon" />
<h3>暂无下载历史</h3>
<p>下载完成后历史记录将显示在这里</p>
</div>
+6 -25
View File
@@ -48,10 +48,7 @@ onMounted(async () => {
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
</svg>
<SvgIcon name="search" />
</div>
<h3 class="feature-title">作品搜索</h3>
<p class="feature-description">
@@ -61,10 +58,7 @@ onMounted(async () => {
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z" />
</svg>
<SvgIcon name="ranking" />
</div>
<h3 class="feature-title">热门榜单</h3>
<p class="feature-description">
@@ -74,10 +68,7 @@ onMounted(async () => {
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="download" />
</div>
<h3 class="feature-title">一键下载</h3>
<p class="feature-description">
@@ -87,10 +78,7 @@ onMounted(async () => {
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
</svg>
<SvgIcon name="user" />
</div>
<h3 class="feature-title">作者管理</h3>
<p class="feature-description">
@@ -100,11 +88,7 @@ onMounted(async () => {
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z" />
<path d="M7 12h2v5H7zm4-3h2v8h-2zm4-3h2v11h-2z" />
</svg>
<SvgIcon name="download" />
</div>
<h3 class="feature-title">下载管理</h3>
<p class="feature-description">
@@ -114,10 +98,7 @@ onMounted(async () => {
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z" />
</svg>
<SvgIcon name="folder" />
</div>
<h3 class="feature-title">仓库管理</h3>
<p class="feature-description">
+1 -4
View File
@@ -15,10 +15,7 @@
<div class="login-status" v-if="isLoggedIn">
<div class="status-success">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<SvgIcon name="empty2" class="sort-icon" />
<div class="status-content">
<h3>已登录</h3>
<p>欢迎回来{{ username }}</p>
+1 -3
View File
@@ -12,9 +12,7 @@
<!-- 下载成功提示 -->
<div v-if="downloadSuccess" class="success-message">
<div class="success-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="success-icon">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
<SvgIcon name="success" class="success-icon" />
<span>{{ downloadSuccess }}</span>
</div>
</div>
+3 -12
View File
@@ -29,10 +29,7 @@
<input v-model="searchKeyword" type="text" placeholder="输入关键词搜索作品..." class="search-input"
@keyup.enter="() => handleSearch()" />
<button @click="() => handleSearch()" class="search-btn" :disabled="loading">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
</svg>
<SvgIcon name="search" />
</button>
</div>
@@ -52,10 +49,7 @@
<span v-for="(tag, index) in searchTags" :key="index" class="tag-item">
{{ tag }}
<button @click="removeTag(index)" class="tag-remove" title="移除标签">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>
<SvgIcon name="close" />
</button>
</span>
</div>
@@ -177,10 +171,7 @@
<div v-else-if="hasSearched" class="empty-section">
<div class="empty-content">
<svg viewBox="0 0 24 24" fill="currentColor" class="empty-icon">
<path
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
</svg>
<SvgIcon name="search" class="empty-icon" />
<h3>未找到相关作品</h3>
<p>尝试使用不同的关键词或调整搜索条件</p>
</div>