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