This commit is contained in:
zhongluofeng
2026-07-23 16:03:38 +08:00
parent 95a69b0017
commit 62db8e1982
5 changed files with 374 additions and 227 deletions
-2
View File
@@ -36,7 +36,6 @@ const displayModules = computed(() => {
'bg-primary text-primary-foreground shadow-md': activeModule === module.id,
'hover:bg-secondary/50': activeModule !== module.id
}"
:title="module.name"
@click="emit('change', module.id)"
>
<component :is="getModuleIcon(module.icon)" class="h-5 w-5" />
@@ -61,7 +60,6 @@ const displayModules = computed(() => {
'bg-primary text-primary-foreground shadow-md': activeModule === 'settings',
'hover:bg-secondary/50': activeModule !== 'settings'
}"
title="常规设置"
@click="emit('change', 'settings')"
>
<Settings class="h-5 w-5" />
+18 -10
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { Search, Minus, X, Settings, ChevronRight } from '@lucide/vue'
import { Search, Settings, ChevronRight } from '@lucide/vue'
import { Input } from '@/components/ui/input'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { useSearchStore, type SearchItem } from '@/stores/searchStore'
@@ -263,7 +263,10 @@ const handleBlur = () => {
@click="minimize"
@mousedown.stop
>
<Minus class="h-4 w-4" />
<!-- 最小化水平线1:1 渲染 + 0.5 像素偏移确保锐利 -->
<svg class="w-[10px] h-[10px]" viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1" shape-rendering="geometricPrecision">
<path d="M0 5.5 H10" />
</svg>
</button>
<button
id="titlebar-maximize"
@@ -271,14 +274,16 @@ const handleBlur = () => {
@click="maximize"
@mousedown.stop
>
<!-- 最大化圆角矩形 -->
<svg v-if="!isMaximized" class="h-3 w-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="4" y="4" width="16" height="16" rx="2" />
<!-- 最大化正方形Windows 11 原生样式 -->
<svg v-if="!isMaximized" class="w-[10px] h-[10px]" viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1" shape-rendering="geometricPrecision">
<rect x="0.5" y="0.5" width="9" height="9" />
</svg>
<!-- 还原单圆角矩形 + 右上角圆角 L形顶边+右边圆角连接 -->
<svg v-else class="h-3 w-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="4" y="4" width="16" height="16" rx="2" />
<path d="M14 4H20V10" />
<!-- 还原两个重叠正方形前正方形在左下后正方形在右上Windows 11 原生样式 -->
<svg v-else class="w-[10px] h-[10px]" viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1" shape-rendering="geometricPrecision">
<!-- 后正方形右上只勾勒未被前正方形遮挡的可见轮廓 (2.5,2.5) (7.5,7.5) 交汇点停止 -->
<path d="M2.5 0.5 H9.5 V7.5 H7.5 V2.5 H2.5 Z" />
<!-- 前正方形左下完整绘制 -->
<path d="M0.5 2.5 H7.5 V9.5 H0.5 Z" />
</svg>
</button>
<button
@@ -286,7 +291,10 @@ const handleBlur = () => {
@click="close"
@mousedown.stop
>
<X class="h-4 w-4" />
<!-- 关闭X 对角线 -->
<svg class="w-[10px] h-[10px]" viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1.05" shape-rendering="geometricPrecision">
<path d="M0.5 0.5 L9.5 9.5 M9.5 0.5 L0.5 9.5" />
</svg>
</button>
</div>
</div>
+284 -182
View File
@@ -21,6 +21,7 @@ import { Switch } from '@/components/ui/switch'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { Label } from '@/components/ui/label'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
import { ScrollArea } from '@/components/ui/scroll-area'
import { Separator } from '@/components/ui/separator'
@@ -506,16 +507,20 @@ const toggleSortOrder = () => {
<!-- 工具栏筛选 / 排序 / 搜索 -->
<div class="shrink-0 flex items-center gap-2 flex-wrap">
<!-- 新建下载按钮 -->
<Button
size="sm"
class="h-8 gap-1.5"
:disabled="addingTask"
title="添加下载链接"
@click="addDialogOpen = true"
>
<Plus class="h-4 w-4" />
新建下载
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="sm"
class="h-8 gap-1.5"
:disabled="addingTask"
@click="addDialogOpen = true"
>
<Plus class="h-4 w-4" />
新建下载
</Button>
</TooltipTrigger>
<TooltipContent>添加下载链接</TooltipContent>
</Tooltip>
<!-- 状态筛选 -->
<Select v-model="statusFilter">
@@ -550,16 +555,20 @@ const toggleSortOrder = () => {
</Select>
<!-- 升降序切换 -->
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0 bg-transparent"
:title="sortOrder === 'asc' ? '升序(点击切换降序)' : '降序(点击切换升序)'"
@click="toggleSortOrder"
>
<ArrowUp v-if="sortOrder === 'asc'" class="h-4 w-4" />
<ArrowDown v-else class="h-4 w-4" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0 bg-transparent"
@click="toggleSortOrder"
>
<ArrowUp v-if="sortOrder === 'asc'" class="h-4 w-4" />
<ArrowDown v-else class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>{{ sortOrder === 'asc' ? '升序(点击切换降序)' : '降序(点击切换升序)' }}</TooltipContent>
</Tooltip>
<!-- 搜索框 -->
<div class="relative flex-1 min-w-[180px] max-w-xs">
@@ -571,16 +580,20 @@ const toggleSortOrder = () => {
/>
</div>
<Button
size="sm"
variant="outline"
class="h-8 gap-1.5 bg-transparent"
title="下载设置"
@click="downloadSettingsOpen = true"
>
<SettingsIcon class="h-4 w-4" />
下载设置
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="sm"
variant="outline"
class="h-8 gap-1.5 bg-transparent"
@click="downloadSettingsOpen = true"
>
<SettingsIcon class="h-4 w-4" />
下载设置
</Button>
</TooltipTrigger>
<TooltipContent>下载设置</TooltipContent>
</Tooltip>
<span class="text-xs text-muted-foreground ml-auto">
{{ sortedTasks.length }} 个任务
@@ -603,9 +616,14 @@ const toggleSortOrder = () => {
<div class="flex items-start justify-between gap-3 mb-3">
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2 mb-1">
<span class="font-medium truncate" :title="getFileName(task)">
{{ getFileName(task) }}
</span>
<Tooltip>
<TooltipTrigger as-child>
<span class="font-medium truncate cursor-default">
{{ getFileName(task) }}
</span>
</TooltipTrigger>
<TooltipContent>{{ getFileName(task) }}</TooltipContent>
</Tooltip>
<Badge
:variant="getTaskStatusBadge(task).variant"
class="shrink-0"
@@ -626,67 +644,85 @@ const toggleSortOrder = () => {
<Zap class="h-2.5 w-2.5" />
{{ task.segments.length }} 连接
</Badge>
<span
v-if="task.dir"
class="truncate max-w-md cursor-help"
:title="task.dir"
>
{{ truncatePath(task.dir) }}
</span>
<Tooltip v-if="task.dir">
<TooltipTrigger as-child>
<span class="truncate max-w-md cursor-default">
{{ truncatePath(task.dir) }}
</span>
</TooltipTrigger>
<TooltipContent class="max-w-[400px] break-all">{{ task.dir }}</TooltipContent>
</Tooltip>
<span v-if="task.error" class="text-destructive">
{{ task.error }}
</span>
</div>
</div>
<div class="flex items-center gap-1 shrink-0">
<Button
v-if="task.status === 'active' || task.status === 'queued'"
size="icon"
variant="ghost"
class="h-8 w-8"
:title="task.status === 'queued' ? '取消排队' : '暂停'"
@click="handlePause(task.id)"
>
<Pause class="h-4 w-4" />
</Button>
<Button
v-if="task.status === 'paused' || task.status === 'error'"
size="icon"
variant="ghost"
class="h-8 w-8"
title="继续"
@click="handleResume(task.id)"
>
<Play class="h-4 w-4" />
</Button>
<Button
size="icon"
variant="ghost"
class="h-8 w-8"
title="详细信息"
@click="handleShowDetail(task)"
>
<Info class="h-4 w-4" />
</Button>
<Button
v-if="task.dir"
size="icon"
variant="ghost"
class="h-8 w-8"
title="打开目录"
@click="handleOpenDir(task)"
>
<FolderOpen class="h-4 w-4" />
</Button>
<Button
size="icon"
variant="ghost"
class="h-8 w-8 text-destructive hover:text-destructive"
title="删除"
@click="handleRemove(task)"
>
<Trash2 class="h-4 w-4" />
</Button>
<Tooltip v-if="task.status === 'active' || task.status === 'queued'">
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8"
@click="handlePause(task.id)"
>
<Pause class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>{{ task.status === 'queued' ? '取消排队' : '暂停' }}</TooltipContent>
</Tooltip>
<Tooltip v-if="task.status === 'paused' || task.status === 'error'">
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8"
@click="handleResume(task.id)"
>
<Play class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>继续</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8"
@click="handleShowDetail(task)"
>
<Info class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>详细信息</TooltipContent>
</Tooltip>
<Tooltip v-if="task.dir">
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8"
@click="handleOpenDir(task)"
>
<FolderOpen class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>打开目录</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8 text-destructive hover:text-destructive"
@click="handleRemove(task)"
>
<Trash2 class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>删除</TooltipContent>
</Tooltip>
</div>
</div>
<Progress :model-value="getProgress(task)" class="h-1.5" />
@@ -702,51 +738,67 @@ const toggleSortOrder = () => {
<!-- 分页控件 -->
<div v-if="totalPages > 1" class="flex items-center justify-center gap-2 pt-2 pb-4">
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage <= 1"
title="第一页"
@click="currentPage = 1"
>
<ChevronLeft class="h-4 w-4" />
<ChevronLeft class="h-4 w-4 -ml-2" />
</Button>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage <= 1"
title="上一页"
@click="currentPage--"
>
<ChevronLeft class="h-4 w-4" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage <= 1"
@click="currentPage = 1"
>
<ChevronLeft class="h-4 w-4" />
<ChevronLeft class="h-4 w-4 -ml-2" />
</Button>
</TooltipTrigger>
<TooltipContent>第一页</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage <= 1"
@click="currentPage--"
>
<ChevronLeft class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>上一页</TooltipContent>
</Tooltip>
<span class="text-xs text-muted-foreground px-2">
{{ currentPage }} / {{ totalPages }}
</span>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage >= totalPages"
title="下一页"
@click="currentPage++"
>
<ChevronRight class="h-4 w-4" />
</Button>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage >= totalPages"
title="最后一页"
@click="currentPage = totalPages"
>
<ChevronRight class="h-4 w-4" />
<ChevronRight class="h-4 w-4 -ml-2" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage >= totalPages"
@click="currentPage++"
>
<ChevronRight class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>下一页</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="sm"
variant="outline"
class="h-8 w-8 p-0"
:disabled="currentPage >= totalPages"
@click="currentPage = totalPages"
>
<ChevronRight class="h-4 w-4" />
<ChevronRight class="h-4 w-4 -ml-2" />
</Button>
</TooltipTrigger>
<TooltipContent>最后一页</TooltipContent>
</Tooltip>
</div>
</ScrollArea>
</div>
@@ -781,9 +833,14 @@ const toggleSortOrder = () => {
class="font-mono text-sm"
@update:model-value="(v: string | number) => store.settings && (store.settings.downloadDir = String(v))"
/>
<Button variant="outline" size="icon" title="选择目录" @click="handleSelectSettingsDir">
<FolderOpen class="h-4 w-4" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button variant="outline" size="icon" @click="handleSelectSettingsDir">
<FolderOpen class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>选择目录</TooltipContent>
</Tooltip>
</div>
</div>
<div class="grid grid-cols-2 gap-3">
@@ -900,19 +957,28 @@ const toggleSortOrder = () => {
<div class="flex items-center justify-between gap-2">
<div class="flex flex-col gap-0.5 min-w-0">
<Label class="text-xs text-muted-foreground">API 地址</Label>
<span class="font-mono text-sm truncate" :title="store.extensionInfo.url">
{{ store.extensionInfo.url }}
</span>
<Tooltip>
<TooltipTrigger as-child>
<span class="font-mono text-sm truncate cursor-default">
{{ store.extensionInfo.url }}
</span>
</TooltipTrigger>
<TooltipContent class="max-w-[400px] break-all">{{ store.extensionInfo.url }}</TooltipContent>
</Tooltip>
</div>
<Button
size="icon"
variant="ghost"
class="h-8 w-8 shrink-0"
title="复制 API 地址"
@click="handleCopy(store.extensionInfo.url, 'API 地址')"
>
<Copy class="h-4 w-4" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8 shrink-0"
@click="handleCopy(store.extensionInfo.url, 'API 地址')"
>
<Copy class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>复制 API 地址</TooltipContent>
</Tooltip>
</div>
<div class="flex items-center justify-between gap-2">
@@ -923,27 +989,33 @@ const toggleSortOrder = () => {
</span>
</div>
<div class="flex gap-1 shrink-0">
<Button
v-if="store.extensionInfo.secret"
size="icon"
variant="ghost"
class="h-8 w-8"
:title="showSecret ? '隐藏' : '显示'"
@click="showSecret = !showSecret"
>
<Eye v-if="!showSecret" class="h-4 w-4" />
<EyeOff v-else class="h-4 w-4" />
</Button>
<Button
v-if="store.extensionInfo.secret"
size="icon"
variant="ghost"
class="h-8 w-8"
title="复制密钥"
@click="handleCopy(store.extensionInfo.secret, '密钥')"
>
<Copy class="h-4 w-4" />
</Button>
<Tooltip v-if="store.extensionInfo.secret">
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8"
@click="showSecret = !showSecret"
>
<Eye v-if="!showSecret" class="h-4 w-4" />
<EyeOff v-else class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>{{ showSecret ? '隐藏' : '显示' }}</TooltipContent>
</Tooltip>
<Tooltip v-if="store.extensionInfo.secret">
<TooltipTrigger as-child>
<Button
size="icon"
variant="ghost"
class="h-8 w-8"
@click="handleCopy(store.extensionInfo.secret, '密钥')"
>
<Copy class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>复制密钥</TooltipContent>
</Tooltip>
</div>
</div>
</div>
@@ -1002,9 +1074,14 @@ const toggleSortOrder = () => {
class="font-mono text-sm"
@update:model-value="(v: string | number) => store.settings && (store.settings.downloadDir = String(v))"
/>
<Button variant="outline" size="icon" title="选择目录" @click="handleSelectSettingsDir">
<FolderOpen class="h-4 w-4" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button variant="outline" size="icon" @click="handleSelectSettingsDir">
<FolderOpen class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>选择目录</TooltipContent>
</Tooltip>
</div>
</div>
@@ -1112,9 +1189,14 @@ const toggleSortOrder = () => {
placeholder="留空使用默认目录"
class="font-mono text-sm"
/>
<Button variant="outline" size="icon" title="选择目录" @click="handleSelectDir">
<FolderOpen class="h-4 w-4" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button variant="outline" size="icon" @click="handleSelectDir">
<FolderOpen class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>选择目录</TooltipContent>
</Tooltip>
</div>
<p v-if="store.settings?.downloadDir" class="text-xs text-muted-foreground">
当前默认
@@ -1191,9 +1273,14 @@ const toggleSortOrder = () => {
<span class="text-xs text-muted-foreground">文件名</span>
<span class="font-medium break-all">{{ detailDialogState.task.filename }}</span>
</div>
<Button size="icon" variant="ghost" class="h-7 w-7 shrink-0" title="复制文件名" @click="handleCopyText(detailDialogState.task.filename, '文件名')">
<Copy class="h-3.5 w-3.5" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button size="icon" variant="ghost" class="h-7 w-7 shrink-0" @click="handleCopyText(detailDialogState.task.filename, '文件名')">
<Copy class="h-3.5 w-3.5" />
</Button>
</TooltipTrigger>
<TooltipContent>复制文件名</TooltipContent>
</Tooltip>
</div>
<Separator />
@@ -1213,9 +1300,14 @@ const toggleSortOrder = () => {
<span class="text-xs text-muted-foreground">下载链接</span>
<span class="font-mono text-xs break-all">{{ detailDialogState.task.url }}</span>
</div>
<Button size="icon" variant="ghost" class="h-7 w-7 shrink-0" title="复制链接" @click="handleCopyText(detailDialogState.task.url, '下载链接')">
<Copy class="h-3.5 w-3.5" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button size="icon" variant="ghost" class="h-7 w-7 shrink-0" @click="handleCopyText(detailDialogState.task.url, '下载链接')">
<Copy class="h-3.5 w-3.5" />
</Button>
</TooltipTrigger>
<TooltipContent>复制链接</TooltipContent>
</Tooltip>
</div>
<Separator />
@@ -1224,12 +1316,22 @@ const toggleSortOrder = () => {
<div class="flex items-start justify-between gap-2">
<div class="flex flex-col gap-0.5 min-w-0 flex-1">
<span class="text-xs text-muted-foreground">保存位置</span>
<span class="font-mono text-xs break-all" :title="detailDialogState.task.dir">{{ detailDialogState.task.dir }}</span>
<Tooltip>
<TooltipTrigger as-child>
<span class="font-mono text-xs break-all cursor-default">{{ detailDialogState.task.dir }}</span>
</TooltipTrigger>
<TooltipContent class="max-w-[400px] break-all">{{ detailDialogState.task.dir }}</TooltipContent>
</Tooltip>
<span class="font-mono text-xs text-muted-foreground break-all">{{ detailDialogState.task.filename }}</span>
</div>
<Button size="icon" variant="ghost" class="h-7 w-7 shrink-0" title="复制完整路径" @click="handleCopyText(detailDialogState.task.dir + '\\' + detailDialogState.task.filename, '完整路径')">
<Copy class="h-3.5 w-3.5" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button size="icon" variant="ghost" class="h-7 w-7 shrink-0" @click="handleCopyText(detailDialogState.task.dir + '\\' + detailDialogState.task.filename, '完整路径')">
<Copy class="h-3.5 w-3.5" />
</Button>
</TooltipTrigger>
<TooltipContent>复制完整路径</TooltipContent>
</Tooltip>
</div>
<Separator />
+11 -6
View File
@@ -4,6 +4,7 @@ import { Switch } from '@/components/ui/switch'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Label } from '@/components/ui/label'
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { useAppStore, type Theme, type EffectType, type ModuleInfo } from '@/stores/appStore'
import { useSearchStore } from '@/stores/searchStore'
import { useProcessStore } from '@/stores/processStore'
@@ -265,12 +266,16 @@ const onDragEnd = () => {
:class="{ 'opacity-60': isModuleToggling(module.id) }"
>
<div class="flex items-center gap-3">
<div
class="drag-handle cursor-grab active:cursor-grabbing text-muted-foreground/40 hover:text-muted-foreground transition-colors"
title="拖拽排序"
>
<GripVertical class="h-4 w-4 no-native-drag" />
</div>
<Tooltip>
<TooltipTrigger as-child>
<div
class="drag-handle cursor-grab active:cursor-grabbing text-muted-foreground/40 hover:text-muted-foreground transition-colors"
>
<GripVertical class="h-4 w-4 no-native-drag" />
</div>
</TooltipTrigger>
<TooltipContent>拖拽排序</TooltipContent>
</Tooltip>
<div
class="w-9 h-9 rounded-lg flex items-center justify-center"
:class="module.enabled ? 'bg-primary/10 text-primary' : 'bg-muted text-muted-foreground'"
+61 -27
View File
@@ -22,6 +22,7 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
import { ScrollArea } from '@/components/ui/scroll-area'
import { Separator } from '@/components/ui/separator'
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { Progress } from '@/components/ui/progress'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import {
@@ -924,9 +925,14 @@ const saveSettingsForm = async () => {
</div>
<div v-if="store.kernel?.exists" class="flex items-center justify-between">
<span class="text-muted-foreground">当前版本</span>
<Badge variant="secondary" class="font-mono text-xs" :title="store.kernel?.version ?? ''">
{{ versionShort }}
</Badge>
<Tooltip>
<TooltipTrigger as-child>
<Badge variant="secondary" class="font-mono text-xs cursor-default">
{{ versionShort }}
</Badge>
</TooltipTrigger>
<TooltipContent>{{ store.kernel?.version ?? '' }}</TooltipContent>
</Tooltip>
</div>
<div v-if="kernelUpdateInfo" class="flex items-center justify-between">
<span class="text-muted-foreground">最新版本</span>
@@ -947,19 +953,33 @@ const saveSettingsForm = async () => {
<div class="flex items-center justify-between gap-3">
<span class="text-muted-foreground shrink-0">路径</span>
<div class="flex items-center gap-1.5 min-w-0">
<span
v-if="store.kernel?.exists"
class="font-mono text-xs text-right truncate"
:title="store.kernel?.path ?? ''"
>{{ pathDisplay || pathShort }}</span>
<span v-else class="font-mono text-xs text-right" :title="store.kernel?.path ?? ''">{{ pathShort }}</span>
<Tooltip>
<TooltipTrigger as-child>
<span
v-if="store.kernel?.exists"
class="font-mono text-xs text-right truncate cursor-default"
>{{ pathDisplay || pathShort }}</span>
<span v-else class="font-mono text-xs text-right cursor-default">{{ pathShort }}</span>
</TooltipTrigger>
<TooltipContent class="max-w-[400px] break-all">{{ store.kernel?.path ?? '' }}</TooltipContent>
</Tooltip>
<template v-if="store.kernel?.exists">
<Button size="icon-xs" variant="ghost" title="复制路径" @click="copyPath">
<Copy class="size-3" />
</Button>
<Button size="icon-xs" variant="ghost" title="在文件夹中显示" @click="openFolder">
<FolderOpen class="size-3" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button size="icon-xs" variant="ghost" @click="copyPath">
<Copy class="size-3" />
</Button>
</TooltipTrigger>
<TooltipContent>复制路径</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger as-child>
<Button size="icon-xs" variant="ghost" @click="openFolder">
<FolderOpen class="size-3" />
</Button>
</TooltipTrigger>
<TooltipContent>在文件夹中显示</TooltipContent>
</Tooltip>
</template>
</div>
</div>
@@ -1448,18 +1468,32 @@ const saveSettingsForm = async () => {
</p>
</div>
<div class="flex gap-1 shrink-0">
<Button size="icon-sm" variant="ghost" title="更新" @click="doUpdate(p.id)">
<RefreshCw class="size-3.5" />
</Button>
<Button
v-if="store.settings.currentProfile !== p.id"
size="icon-sm" variant="ghost" title="切换" @click="doActivate(p.id)"
>
<Check class="size-3.5" />
</Button>
<Button size="icon-sm" variant="ghost" title="删除" @click="doDelete(p.id, p.name)">
<Trash2 class="size-3.5 text-destructive" />
</Button>
<Tooltip>
<TooltipTrigger as-child>
<Button size="icon-sm" variant="ghost" @click="doUpdate(p.id)">
<RefreshCw class="size-3.5" />
</Button>
</TooltipTrigger>
<TooltipContent>更新</TooltipContent>
</Tooltip>
<Tooltip v-if="store.settings.currentProfile !== p.id">
<TooltipTrigger as-child>
<Button
size="icon-sm" variant="ghost" @click="doActivate(p.id)"
>
<Check class="size-3.5" />
</Button>
</TooltipTrigger>
<TooltipContent>切换</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger as-child>
<Button size="icon-sm" variant="ghost" @click="doDelete(p.id, p.name)">
<Trash2 class="size-3.5 text-destructive" />
</Button>
</TooltipTrigger>
<TooltipContent>删除</TooltipContent>
</Tooltip>
</div>
</div>
</div>