fix: logs viewer page style

This commit is contained in:
engigu
2026-02-13 21:38:07 +08:00
parent 2d90d0921a
commit e270d6c260
2 changed files with 66 additions and 28 deletions
+30 -10
View File
@@ -200,6 +200,25 @@ function formatDuration(ms: number): string {
return `${(ms / 60000).toFixed(1)}分钟` return `${(ms / 60000).toFixed(1)}分钟`
} }
function getStatusBadgeClass(status: string) {
switch (status) {
case TASK_STATUS.SUCCESS:
return 'bg-green-500/10 text-green-700 border-green-200/50 dark:bg-green-500/20 dark:text-green-400 dark:border-green-900/50'
case TASK_STATUS.FAILED:
return 'bg-red-500/10 text-red-700 border-red-200/50 dark:bg-red-500/20 dark:text-red-400 dark:border-red-900/50'
case TASK_STATUS.RUNNING:
return 'bg-blue-500/10 text-blue-700 border-blue-200/50 dark:bg-blue-500/20 dark:text-blue-400 dark:border-blue-900/50'
case TASK_STATUS.PENDING:
return 'bg-amber-500/10 text-amber-700 border-amber-200/50 dark:bg-amber-500/20 dark:text-amber-400 dark:border-amber-900/50'
case TASK_STATUS.TIMEOUT:
return 'bg-orange-500/10 text-orange-700 border-orange-200/50 dark:bg-orange-500/20 dark:text-orange-400 dark:border-orange-900/50'
case TASK_STATUS.CANCELLED:
return 'bg-muted text-muted-foreground border-transparent'
default:
return 'bg-secondary text-secondary-foreground border-transparent'
}
}
function getTaskTypeTitle(type: string) { function getTaskTypeTitle(type: string) {
return type === TASK_TYPE.REPO ? '仓库同步' : '普通任务' return type === TASK_TYPE.REPO ? '仓库同步' : '普通任务'
} }
@@ -380,18 +399,19 @@ watch(() => route.query.task_id, (newTaskId) => {
</div> </div>
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="text-muted-foreground">状态</span> <span class="text-muted-foreground">状态</span>
<Badge <Badge variant="outline" :class="[
:variant="selectedLog.status === TASK_STATUS.SUCCESS ? 'default' : selectedLog.status === TASK_STATUS.FAILED ? 'destructive' : 'secondary'" 'capitalize px-3 py-1 font-semibold rounded-full border shadow-sm transition-all duration-300',
class="capitalize px-4 py-0.5"> getStatusBadgeClass(selectedLog.status)
]">
<div class="flex items-center gap-1.5"> <div class="flex items-center gap-1.5">
<CheckCircle2 v-if="selectedLog.status === TASK_STATUS.SUCCESS" class="h-3 w-3" /> <CheckCircle2 v-if="selectedLog.status === TASK_STATUS.SUCCESS" class="h-3.5 w-3.5" />
<XCircle v-else-if="selectedLog.status === TASK_STATUS.FAILED" class="h-3 w-3" /> <XCircle v-else-if="selectedLog.status === TASK_STATUS.FAILED" class="h-3.5 w-3.5" />
<Zap v-else-if="selectedLog.status === TASK_STATUS.RUNNING" <Zap v-else-if="selectedLog.status === TASK_STATUS.RUNNING"
class="h-3 w-3 fill-current animate-pulse" /> class="h-3.5 w-3.5 fill-current animate-pulse text-blue-500" />
<Clock v-else-if="selectedLog.status === TASK_STATUS.PENDING" class="h-3 w-3" /> <Clock v-else-if="selectedLog.status === TASK_STATUS.PENDING" class="h-3.5 w-3.5" />
<AlertCircle v-else-if="selectedLog.status === TASK_STATUS.TIMEOUT" class="h-3 w-3" /> <AlertCircle v-else-if="selectedLog.status === TASK_STATUS.TIMEOUT" class="h-3.5 w-3.5" />
<Ban v-else-if="selectedLog.status === TASK_STATUS.CANCELLED" class="h-3 w-3" /> <Ban v-else-if="selectedLog.status === TASK_STATUS.CANCELLED" class="h-3.5 w-3.5" />
{{ selectedLog.status }} <span class="text-xs tracking-wide uppercase">{{ selectedLog.status }}</span>
</div> </div>
</Badge> </Badge>
</div> </div>
+30 -12
View File
@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, watch } from 'vue' import { ref, computed, watch, onUnmounted } from 'vue'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { X, Search } from 'lucide-vue-next' import { X, Search } from 'lucide-vue-next'
@@ -31,31 +31,49 @@ function close() {
emit('update:open', false) emit('update:open', false)
} }
// 打开时重置搜索 // 统一控制 Body 滚动
function toggleBodyScroll(lock: boolean) {
if (lock) {
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = ''
}
}
// 监听打开状态
watch(() => props.open, (val) => { watch(() => props.open, (val) => {
if (val) searchKeyword.value = '' if (val) {
searchKeyword.value = ''
toggleBodyScroll(true)
} else {
toggleBodyScroll(false)
}
}, { immediate: true })
// 确保组件卸载时恢复滚动
onUnmounted(() => {
toggleBodyScroll(false)
}) })
</script> </script>
<template> <template>
<Teleport to="body"> <Teleport to="body">
<div v-if="open" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-2 sm:p-4"
@click.self="close">
<div <div
v-if="open" class="bg-background rounded-lg shadow-lg flex flex-col w-full sm:w-[90vw] md:w-[80vw] max-w-5xl h-[90vh] sm:h-[85vh]">
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-2 sm:p-4" <div
@click.self="close" class="flex flex-col sm:flex-row sm:items-center justify-between px-3 sm:px-4 py-2 sm:py-3 border-b shrink-0 gap-2">
>
<div class="bg-background rounded-lg shadow-lg flex flex-col w-full sm:w-[90vw] md:w-[80vw] max-w-5xl h-[90vh] sm:h-[85vh]">
<div class="flex flex-col sm:flex-row sm:items-center justify-between px-3 sm:px-4 py-2 sm:py-3 border-b shrink-0 gap-2">
<div class="flex items-center gap-3 min-w-0"> <div class="flex items-center gap-3 min-w-0">
<span class="text-sm font-medium truncate">{{ title }}</span> <span class="text-sm font-medium truncate">{{ title }}</span>
<div v-if="status" <div v-if="status"
class="flex items-center gap-1.5 px-2 py-0.5 rounded text-[10px] font-bold uppercase transition-colors shrink-0" class="flex items-center gap-1.5 px-2 py-0.5 rounded text-[10px] font-bold uppercase transition-colors shrink-0"
:class="status === 'success' ? 'bg-green-500/10 text-green-500 border border-green-500/20' : :class="status === 'success' ? 'bg-green-500/10 text-green-500 border border-green-500/20' :
status === 'failed' ? 'bg-red-500/10 text-red-500 border border-red-500/20' : status === 'failed' ? 'bg-red-500/10 text-red-500 border border-red-500/20' :
'bg-yellow-500/10 text-yellow-500 border border-yellow-500/20'" 'bg-yellow-500/10 text-yellow-500 border border-yellow-500/20'">
>
<span v-if="status === 'running'" class="relative flex h-1.5 w-1.5 mr-0.5"> <span v-if="status === 'running'" class="relative flex h-1.5 w-1.5 mr-0.5">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-yellow-400 opacity-75"></span> <span
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-yellow-400 opacity-75"></span>
<span class="relative inline-flex rounded-full h-1.5 w-1.5 bg-yellow-500"></span> <span class="relative inline-flex rounded-full h-1.5 w-1.5 bg-yellow-500"></span>
</span> </span>
{{ status === 'success' ? '成功' : status === 'failed' ? '失败' : '执行中' }} {{ status === 'success' ? '成功' : status === 'failed' ? '失败' : '执行中' }}