mirror of
https://github.com/Moe-Sakura/frontend.git
synced 2026-04-25 22:29:50 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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[]>([])
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user