feat: add log page status filter
This commit is contained in:
@@ -21,6 +21,7 @@ func (lc *LogController) GetLogs(c *gin.Context) {
|
|||||||
p := utils.ParsePagination(c)
|
p := utils.ParsePagination(c)
|
||||||
taskID, _ := strconv.Atoi(c.DefaultQuery("task_id", "0"))
|
taskID, _ := strconv.Atoi(c.DefaultQuery("task_id", "0"))
|
||||||
taskName := c.DefaultQuery("task_name", "")
|
taskName := c.DefaultQuery("task_name", "")
|
||||||
|
status := c.DefaultQuery("status", "")
|
||||||
|
|
||||||
var logs []models.TaskLog
|
var logs []models.TaskLog
|
||||||
var total int64
|
var total int64
|
||||||
@@ -29,6 +30,9 @@ func (lc *LogController) GetLogs(c *gin.Context) {
|
|||||||
if taskID > 0 {
|
if taskID > 0 {
|
||||||
query = query.Where("task_id = ?", taskID)
|
query = query.Where("task_id = ?", taskID)
|
||||||
}
|
}
|
||||||
|
if status != "" {
|
||||||
|
query = query.Where("status = ?", status)
|
||||||
|
}
|
||||||
|
|
||||||
// 按任务名称过滤
|
// 按任务名称过滤
|
||||||
if taskName != "" {
|
if taskName != "" {
|
||||||
|
|||||||
@@ -98,12 +98,13 @@ export const api = {
|
|||||||
results: () => request('/execute/results')
|
results: () => request('/execute/results')
|
||||||
},
|
},
|
||||||
logs: {
|
logs: {
|
||||||
list: (params?: { page?: number; page_size?: number; task_id?: number; task_name?: string }) => {
|
list: (params?: { page?: number; page_size?: number; task_id?: number; task_name?: string; status?: string }) => {
|
||||||
const query = new URLSearchParams()
|
const query = new URLSearchParams()
|
||||||
if (params?.page) query.set('page', String(params.page))
|
if (params?.page) query.set('page', String(params.page))
|
||||||
if (params?.page_size) query.set('page_size', String(params.page_size))
|
if (params?.page_size) query.set('page_size', String(params.page_size))
|
||||||
if (params?.task_id) query.set('task_id', String(params.task_id))
|
if (params?.task_id) query.set('task_id', String(params.task_id))
|
||||||
if (params?.task_name) query.set('task_name', params.task_name)
|
if (params?.task_name) query.set('task_name', params.task_name)
|
||||||
|
if (params?.status) query.set('status', params.status)
|
||||||
return request<LogListResponse>(`/logs?${query}`)
|
return request<LogListResponse>(`/logs?${query}`)
|
||||||
},
|
},
|
||||||
get: (id: number) => request<LogDetail>(`/logs/${id}`),
|
get: (id: number) => request<LogDetail>(`/logs/${id}`),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const statItems = [
|
|||||||
{ key: 'envs', label: '环境变量', icon: Variable, route: '/environments' },
|
{ key: 'envs', label: '环境变量', icon: Variable, route: '/environments' },
|
||||||
{ key: 'logs', label: '日志总数', icon: ScrollText, route: '/history' },
|
{ key: 'logs', label: '日志总数', icon: ScrollText, route: '/history' },
|
||||||
{ key: 'scheduled', label: '调度注册', icon: Clock, route: '/tasks' },
|
{ key: 'scheduled', label: '调度注册', icon: Clock, route: '/tasks' },
|
||||||
{ key: 'running', label: '正在运行', icon: Play, route: '/tasks' },
|
{ key: 'running', label: '正在运行', icon: Play, route: '/history?status=running' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const isDark = ref(document.documentElement.classList.contains('dark'))
|
const isDark = ref(document.documentElement.classList.contains('dark'))
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { TASK_STATUS, TASK_TYPE } from '@/constants'
|
|||||||
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 Pagination from '@/components/Pagination.vue'
|
import Pagination from '@/components/Pagination.vue'
|
||||||
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
|
||||||
import LogViewer from './LogViewer.vue'
|
import LogViewer from './LogViewer.vue'
|
||||||
import {
|
import {
|
||||||
RefreshCw, X, Search, Maximize2, GitBranch, Terminal,
|
RefreshCw, X, Search, Maximize2, GitBranch, Terminal,
|
||||||
@@ -33,6 +34,7 @@ const logs = ref<TaskLog[]>([])
|
|||||||
const selectedLog = ref<TaskLog | null>(null)
|
const selectedLog = ref<TaskLog | null>(null)
|
||||||
const filterKeyword = ref('')
|
const filterKeyword = ref('')
|
||||||
const filterTaskId = ref<number | undefined>(undefined)
|
const filterTaskId = ref<number | undefined>(undefined)
|
||||||
|
const filterStatus = ref<string | undefined>(undefined)
|
||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ const decompressedOutput = computed(() => {
|
|||||||
|
|
||||||
async function loadLogs() {
|
async function loadLogs() {
|
||||||
try {
|
try {
|
||||||
const params: { page: number; page_size: number; task_id?: number; task_name?: string } = {
|
const params: { page: number; page_size: number; task_id?: number; task_name?: string; status?: string } = {
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
page_size: pageSize.value
|
page_size: pageSize.value
|
||||||
}
|
}
|
||||||
@@ -70,6 +72,9 @@ async function loadLogs() {
|
|||||||
if (filterKeyword.value.trim()) {
|
if (filterKeyword.value.trim()) {
|
||||||
params.task_name = filterKeyword.value.trim()
|
params.task_name = filterKeyword.value.trim()
|
||||||
}
|
}
|
||||||
|
if (filterStatus.value && filterStatus.value !== 'all') {
|
||||||
|
params.status = filterStatus.value
|
||||||
|
}
|
||||||
const response = await api.logs.list(params)
|
const response = await api.logs.list(params)
|
||||||
logs.value = response.data
|
logs.value = response.data
|
||||||
total.value = response.total
|
total.value = response.total
|
||||||
@@ -86,6 +91,11 @@ function handleSearch() {
|
|||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleStatusChange() {
|
||||||
|
currentPage.value = 1
|
||||||
|
loadLogs()
|
||||||
|
}
|
||||||
|
|
||||||
function handlePageChange(page: number) {
|
function handlePageChange(page: number) {
|
||||||
currentPage.value = page
|
currentPage.value = page
|
||||||
loadLogs()
|
loadLogs()
|
||||||
@@ -278,20 +288,25 @@ function getTaskTypeTitle(type: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 从 URL 读取 task_id 参数
|
// 从 URL 读取参数
|
||||||
const taskIdParam = route.query.task_id
|
const taskIdParam = route.query.task_id
|
||||||
if (taskIdParam) {
|
if (taskIdParam) {
|
||||||
filterTaskId.value = Number(taskIdParam)
|
filterTaskId.value = Number(taskIdParam)
|
||||||
}
|
}
|
||||||
|
const statusParam = route.query.status
|
||||||
|
if (statusParam) {
|
||||||
|
filterStatus.value = String(statusParam)
|
||||||
|
}
|
||||||
loadLogs()
|
loadLogs()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听路由变化
|
// 监听路由变化
|
||||||
watch(() => route.query.task_id, (newTaskId) => {
|
watch(() => route.query, (newQuery) => {
|
||||||
filterTaskId.value = newTaskId ? Number(newTaskId) : undefined
|
filterTaskId.value = newQuery.task_id ? Number(newQuery.task_id) : undefined
|
||||||
|
filterStatus.value = newQuery.status ? String(newQuery.status) : undefined
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
loadLogs()
|
loadLogs()
|
||||||
})
|
}, { deep: true })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -304,9 +319,24 @@ watch(() => route.query.task_id, (newTaskId) => {
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div class="relative flex-1 sm:flex-none">
|
<div class="relative flex-1 sm:flex-none">
|
||||||
<Search class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
<Search class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
||||||
<Input v-model="filterKeyword" placeholder="搜索任务..." class="h-9 pl-9 w-full sm:w-56 text-sm"
|
<Input v-model="filterKeyword" placeholder="搜索任务..." class="h-9 pl-9 w-full sm:w-40 md:w-56 text-sm"
|
||||||
@input="handleSearch" />
|
@input="handleSearch" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="relative flex-1 sm:flex-none">
|
||||||
|
<Select v-model="filterStatus" @update:model-value="handleStatusChange">
|
||||||
|
<SelectTrigger class="h-9 w-full sm:w-28 text-sm">
|
||||||
|
<SelectValue placeholder="状态" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="all">所有状态</SelectItem>
|
||||||
|
<SelectItem value="running">正在运行</SelectItem>
|
||||||
|
<SelectItem value="success">成功</SelectItem>
|
||||||
|
<SelectItem value="failed">失败</SelectItem>
|
||||||
|
<SelectItem value="timeout">超时</SelectItem>
|
||||||
|
<SelectItem value="cancelled">取消</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<Button variant="outline" size="icon" class="h-9 w-9 shrink-0" @click="loadLogs" title="刷新">
|
<Button variant="outline" size="icon" class="h-9 w-9 shrink-0" @click="loadLogs" title="刷新">
|
||||||
<RefreshCw class="h-4 w-4" />
|
<RefreshCw class="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user