Enhance component visuals and functionality across multiple files

- Updated CommentsModal.vue to include additional icons and improved title display for better user engagement.
- Enhanced KeyboardHelpPanel.vue by adding icons next to navigation and operation shortcuts for improved clarity.
- Refactored ResultItem.vue to include a copy link feature with visual feedback, enhancing user interaction.
- Improved SearchHistoryModal.vue by adding icons and additional text for better user guidance on search history.
- Updated StatsCorner.vue to replace the gamepad icon and add status indicators for online/offline status.
- Refactored icons management in icons.ts for better organization and maintainability.
This commit is contained in:
AdingApkgg
2025-12-27 07:10:49 +08:00
parent ccd87d06be
commit 9e45db827d
6 changed files with 736 additions and 51 deletions

View File

@@ -29,10 +29,17 @@
<!-- 标题 -->
<div class="flex items-center gap-2 md:ml-0">
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-[#ff1493] to-[#d946ef] flex items-center justify-center shadow-lg shadow-pink-500/30">
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-[#ff1493] to-[#d946ef] flex items-center justify-center shadow-lg shadow-pink-500/30 relative">
<MessageCircle :size="16" class="text-white" />
<Send :size="8" class="text-white/80 absolute -bottom-0.5 -right-0.5" />
</div>
<div>
<h1 class="text-base sm:text-lg font-bold text-gray-800 dark:text-white flex items-center gap-1.5">
评论区
<Sparkles :size="14" class="text-amber-400" />
</h1>
<p class="text-xs text-gray-500 dark:text-slate-400 hidden md:block">欢迎留下你的想法 💬</p>
</div>
<h1 class="text-base sm:text-lg font-bold text-gray-800 dark:text-white">评论区</h1>
</div>
<!-- 右侧按钮组 -->
@@ -67,7 +74,7 @@ import { watch, onMounted, onUnmounted, nextTick } from 'vue'
import { useUIStore } from '@/stores/ui'
import { playTransitionUp, playTransitionDown } from '@/composables/useSound'
import Artalk from 'artalk/dist/Artalk.mjs'
import { MessageCircle, ChevronLeft, X } from 'lucide-vue-next'
import { MessageCircle, ChevronLeft, X, Sparkles, Send } from 'lucide-vue-next'
interface ArtalkInstance {
destroy(): void

View File

@@ -42,34 +42,58 @@
<div class="px-5 py-4 max-h-[60vh] overflow-y-auto custom-scrollbar">
<!-- 导航 -->
<div class="mb-4">
<h3 class="text-xs font-semibold text-gray-400 dark:text-slate-500 uppercase tracking-wider mb-2">导航</h3>
<h3 class="text-xs font-semibold text-gray-400 dark:text-slate-500 uppercase tracking-wider mb-2 flex items-center gap-1.5">
<Navigation :size="12" />
导航
</h3>
<div class="space-y-2">
<div class="shortcut-row">
<span>关闭当前面板</span>
<span class="flex items-center gap-2">
<X :size="14" class="text-gray-400" />
关闭当前面板
</span>
<kbd>Esc</kbd>
</div>
<div class="shortcut-row">
<span>返回首页</span>
<span class="flex items-center gap-2">
<Home :size="14" class="text-blue-400" />
返回首页
</span>
<kbd>H</kbd>
</div>
<div class="shortcut-row">
<span>打开/关闭设置</span>
<span class="flex items-center gap-2">
<Settings :size="14" class="text-gray-400" />
打开/关闭设置
</span>
<kbd>,</kbd>
</div>
<div class="shortcut-row">
<span>打开/关闭评论</span>
<span class="flex items-center gap-2">
<MessageSquare :size="14" class="text-pink-400" />
打开/关闭评论
</span>
<kbd>C</kbd>
</div>
<div class="shortcut-row">
<span>打开/关闭作品介绍</span>
<span class="flex items-center gap-2">
<BookOpen :size="14" class="text-purple-400" />
打开/关闭作品介绍
</span>
<kbd>V</kbd>
</div>
<div class="shortcut-row">
<span>打开/关闭搜索历史</span>
<span class="flex items-center gap-2">
<History :size="14" class="text-amber-400" />
打开/关闭搜索历史
</span>
<kbd>Y</kbd>
</div>
<div class="shortcut-row">
<span>站点导航</span>
<span class="flex items-center gap-2">
<Grid3x3 :size="14" class="text-cyan-400" />
站点导航
</span>
<kbd>N</kbd>
</div>
</div>
@@ -77,14 +101,23 @@
<!-- 操作 -->
<div class="mb-4">
<h3 class="text-xs font-semibold text-gray-400 dark:text-slate-500 uppercase tracking-wider mb-2">操作</h3>
<h3 class="text-xs font-semibold text-gray-400 dark:text-slate-500 uppercase tracking-wider mb-2 flex items-center gap-1.5">
<Zap :size="12" />
操作
</h3>
<div class="space-y-2">
<div class="shortcut-row">
<span>聚焦搜索框</span>
<span class="flex items-center gap-2">
<Search :size="14" class="text-green-400" />
聚焦搜索框
</span>
<kbd>/</kbd>
</div>
<div class="shortcut-row">
<span>显示/隐藏快捷键帮助</span>
<span class="flex items-center gap-2">
<HelpCircle :size="14" class="text-indigo-400" />
显示/隐藏快捷键帮助
</span>
<kbd>?</kbd>
</div>
</div>
@@ -92,18 +125,30 @@
<!-- 滚动 -->
<div>
<h3 class="text-xs font-semibold text-gray-400 dark:text-slate-500 uppercase tracking-wider mb-2">滚动</h3>
<h3 class="text-xs font-semibold text-gray-400 dark:text-slate-500 uppercase tracking-wider mb-2 flex items-center gap-1.5">
<Command :size="12" />
滚动
</h3>
<div class="space-y-2">
<div class="shortcut-row">
<span>回到顶部</span>
<span class="flex items-center gap-2">
<ArrowUp :size="14" class="text-rose-400" />
回到顶部
</span>
<kbd>T</kbd>
</div>
<div class="shortcut-row">
<span>上一个平台</span>
<span class="flex items-center gap-2">
<ChevronLeft :size="14" class="text-orange-400" />
上一个平台
</span>
<kbd>[</kbd>
</div>
<div class="shortcut-row">
<span>下一个平台</span>
<span class="flex items-center gap-2">
<ChevronRight :size="14" class="text-orange-400" />
下一个平台
</span>
<kbd>]</kbd>
</div>
</div>
@@ -119,7 +164,12 @@
import { ref } from 'vue'
import { useUIStore } from '@/stores/ui'
import { playTransitionDown } from '@/composables/useSound'
import { Keyboard, X } from 'lucide-vue-next'
import {
Keyboard, X,
Home, Settings, MessageSquare, BookOpen, History, Grid3x3, Search, HelpCircle,
ArrowUp, ChevronLeft, ChevronRight,
Navigation, Command, Zap
} from 'lucide-vue-next'
const uiStore = useUIStore()
const panelRef = ref<HTMLElement | null>(null)

View File

@@ -1,5 +1,7 @@
<script setup lang="ts">
import { Link as LinkIcon } from 'lucide-vue-next'
import { Link as LinkIcon, ExternalLink, FileText, Copy, Check } from 'lucide-vue-next'
import { ref } from 'vue'
import { playTap, playNotification } from '@/composables/useSound'
defineProps<{
index: number
@@ -9,6 +11,8 @@ defineProps<{
}
}>()
const copied = ref(false)
// 从URL中提取路径
function extractPath(url: string): string {
try {
@@ -18,6 +22,21 @@ function extractPath(url: string): string {
return url
}
}
// 复制链接
async function copyLink(url: string) {
playTap()
try {
await navigator.clipboard.writeText(url)
playNotification()
copied.value = true
setTimeout(() => {
copied.value = false
}, 2000)
} catch {
// 静默处理
}
}
</script>
<template>
@@ -30,22 +49,42 @@ function extractPath(url: string): string {
>
<!-- 标题行 -->
<div class="flex items-start gap-2 sm:gap-3">
<span class="text-theme-primary dark:text-theme-accent text-sm font-bold mt-0.5 shrink-0 opacity-60 group-hover:opacity-100">
{{ index + 1 }}.
</span>
<!-- 序号 + 文件图标 -->
<div class="flex items-center gap-1.5 shrink-0 mt-0.5">
<FileText :size="14" class="text-theme-primary/60 dark:text-theme-accent/60 group-hover:text-theme-primary dark:group-hover:text-theme-accent transition-colors" />
<span class="text-theme-primary dark:text-theme-accent text-sm font-bold opacity-60 group-hover:opacity-100 transition-opacity">
{{ index + 1 }}
</span>
</div>
<!-- 标题链接 -->
<a
:href="source.url"
target="_blank"
rel="noopener noreferrer"
class="text-gray-800 dark:text-slate-200 group-hover:text-theme-primary dark:group-hover:text-theme-accent font-semibold flex-1 text-sm sm:text-base break-words leading-relaxed"
class="flex-1 flex items-start gap-1.5 text-gray-800 dark:text-slate-200 group-hover:text-theme-primary dark:group-hover:text-theme-accent font-semibold text-sm sm:text-base break-words leading-relaxed transition-colors"
>
{{ source.title }}
<span class="flex-1">{{ source.title }}</span>
<ExternalLink :size="14" class="shrink-0 mt-1 opacity-0 group-hover:opacity-70 transition-opacity" />
</a>
<!-- 复制按钮 -->
<button
class="shrink-0 p-1.5 rounded-lg opacity-0 group-hover:opacity-100
text-gray-400 hover:text-theme-primary dark:hover:text-theme-accent
hover:bg-theme-primary/10 dark:hover:bg-theme-accent/10
transition-all"
:class="{ '!opacity-100 !text-green-500': copied }"
:title="copied ? '已复制' : '复制链接'"
@click.stop="copyLink(source.url)"
>
<component :is="copied ? Check : Copy" :size="14" />
</button>
</div>
<!-- 资源相对路径从URL中提取 -->
<div v-if="source.url" class="flex items-center gap-2 mt-2 ml-6 sm:ml-8">
<LinkIcon :size="12" class="text-theme-primary/50 dark:text-theme-accent/50" />
<div v-if="source.url" class="flex items-center gap-2 mt-2 ml-7 sm:ml-9">
<LinkIcon :size="12" class="text-theme-primary/50 dark:text-theme-accent/50 shrink-0" />
<span class="text-xs text-gray-500 dark:text-slate-400 break-all font-mono bg-gray-100/80 dark:bg-slate-800/80 px-2 py-1 rounded">
{{ extractPath(source.url) }}
</span>

View File

@@ -57,11 +57,14 @@
class="flex flex-col items-center justify-center py-8 text-center"
>
<div class="w-12 h-12 rounded-xl bg-amber-50 dark:bg-amber-900/20 flex items-center justify-center mb-3">
<History :size="24" class="text-amber-400/50" />
<Clock :size="24" class="text-amber-400/50" />
</div>
<p class="text-sm text-gray-500 dark:text-gray-400">
暂无搜索历史
</p>
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1">
搜索后会自动记录
</p>
</div>
<!-- 历史记录列表 -->
@@ -86,29 +89,35 @@
@keydown.enter="handleSelectHistory(item)"
@keydown.space.prevent="handleSelectHistory(item)"
>
<!-- 模式标签 -->
<!-- 模式标签 + 图标 -->
<span
class="text-[10px] font-bold px-1.5 py-0.5 rounded uppercase tracking-wide flex-shrink-0"
class="flex items-center gap-1 text-[10px] font-bold px-1.5 py-0.5 rounded uppercase tracking-wide flex-shrink-0"
:class="item.mode === 'game'
? 'bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400'
: 'bg-amber-100 text-amber-600 dark:bg-amber-900/30 dark:text-amber-400'"
>
<component :is="item.mode === 'game' ? Gamepad2 : Wrench" :size="10" />
{{ item.mode === 'game' ? '游戏' : '补丁' }}
</span>
<!-- 搜索关键词 -->
<span
v-text-scroll
class="flex-1 text-sm font-medium text-gray-700 dark:text-slate-200 text-left group-hover:text-amber-600 dark:group-hover:text-amber-400 transition-colors"
>
{{ item.query }}
</span>
<!-- 搜索图标 + 关键词 -->
<div class="flex-1 flex items-center gap-1.5 min-w-0">
<Search :size="12" class="text-gray-400 dark:text-slate-500 shrink-0 group-hover:text-amber-500 transition-colors" />
<span
v-text-scroll
class="flex-1 text-sm font-medium text-gray-700 dark:text-slate-200 text-left group-hover:text-amber-600 dark:group-hover:text-amber-400 transition-colors"
>
{{ item.query }}
</span>
</div>
<!-- 结果数 -->
<!-- 结果数 + 图标 -->
<span
v-if="item.resultCount"
class="text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0"
class="flex items-center gap-1 text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0"
:title="`${item.resultCount} 条结果`"
>
<Hash :size="10" />
{{ item.resultCount }}
</span>
@@ -135,7 +144,7 @@ import { ref, watch, onMounted, onUnmounted } from 'vue'
import { useUIStore } from '@/stores/ui'
import { loadSearchHistory, clearSearchHistory as clearHistoryStorage, type SearchHistory } from '@/utils/persistence'
import { playSelect, playTap, playCaution, playTransitionUp, playTransitionDown } from '@/composables/useSound'
import { History, Trash2, X } from 'lucide-vue-next'
import { History, Trash2, X, Gamepad2, Wrench, Hash, Clock, Search } from 'lucide-vue-next'
const uiStore = useUIStore()
const history = ref<SearchHistory[]>([])

View File

@@ -3,7 +3,7 @@
<div class="fixed top-4 left-4 z-40 flex items-center gap-2">
<!-- Gamepad 图标 - 品牌标识 -->
<div class="glassmorphism-card rounded-2xl shadow-lg p-2.5 flex items-center justify-center">
<GamepadDirectional
<Gamepad2
:size="22"
class="text-theme-primary dark:text-theme-accent"
/>
@@ -23,6 +23,19 @@
: 'text-red-600 dark:text-red-400'
]"
>
<!-- 状态图标 -->
<component
:is="statusOnline === null ? Activity : statusOnline ? Wifi : WifiOff"
:size="14"
:class="[
statusOnline === null ? 'animate-pulse' : '',
statusOnline === null
? 'text-gray-400'
: statusOnline
? 'text-green-500'
: 'text-red-500'
]"
/>
<span
class="w-2 h-2 rounded-full"
:class="[
@@ -45,15 +58,17 @@
>
<div class="stats-card glassmorphism-card rounded-2xl shadow-lg px-4 py-3 flex flex-col gap-2">
<!-- 访问量 -->
<div class="flex items-center gap-2">
<div class="flex items-center gap-2" title="总访问量">
<Eye :size="16" class="text-theme-primary dark:text-theme-accent" />
<span class="text-xs text-gray-500 dark:text-slate-400">PV</span>
<span id="busuanzi_value_site_pv" class="font-semibold text-gray-800 dark:text-slate-100">0</span>
</div>
<!-- 分隔线 -->
<div class="h-px bg-gray-300 dark:bg-slate-600" />
<div class="h-px bg-gray-300/50 dark:bg-slate-600/50" />
<!-- 访客数 -->
<div class="flex items-center gap-2">
<div class="flex items-center gap-2" title="独立访客">
<Users :size="16" class="text-theme-primary dark:text-theme-accent" />
<span class="text-xs text-gray-500 dark:text-slate-400">UV</span>
<span id="busuanzi_value_site_uv" class="font-semibold text-gray-800 dark:text-slate-100">0</span>
</div>
</div>
@@ -62,7 +77,7 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { GamepadDirectional, Eye, Users } from 'lucide-vue-next'
import { Gamepad2, Eye, Users, Activity, Wifi, WifiOff } from 'lucide-vue-next'
const statusOnline = ref<boolean | null>(null)
const showStats = ref(false)