更新日志页面和统计页面
- 更新 LogsPage 和 StatsPage 组件 - 添加 taskSource 工具模块 - 更新 db/tasks.py - 重新构建前端静态资源
This commit is contained in:
@@ -4,6 +4,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
import { fetchAllUsers } from '../api/users'
|
||||
import { clearOldTaskLogs, fetchTaskLogs } from '../api/tasks'
|
||||
import { getTaskSourceMeta } from '../utils/taskSource'
|
||||
|
||||
const pageSize = 20
|
||||
|
||||
@@ -32,13 +33,8 @@ function formatDuration(seconds) {
|
||||
}
|
||||
|
||||
function sourceMeta(source) {
|
||||
const map = {
|
||||
manual: { label: '手动', type: 'success' },
|
||||
scheduled: { label: '定时', type: 'primary' },
|
||||
immediate: { label: '即时', type: 'warning' },
|
||||
resumed: { label: '恢复', type: 'info' },
|
||||
}
|
||||
return map[source] || { label: source || '手动', type: 'info' }
|
||||
const meta = getTaskSourceMeta(source)
|
||||
return { key: meta.group, label: meta.label, type: meta.type, tooltip: meta.tooltip }
|
||||
}
|
||||
|
||||
function statusMeta(status) {
|
||||
@@ -169,9 +165,12 @@ onMounted(async () => {
|
||||
<el-select v-model="sourceFilter" placeholder="来源" style="width: 120px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="手动" value="manual" />
|
||||
<el-option label="定时" value="scheduled" />
|
||||
<el-option label="即时" value="immediate" />
|
||||
<el-option label="恢复" value="resumed" />
|
||||
<el-option label="定时任务(系统)" value="scheduled" />
|
||||
<el-option label="定时任务(用户)" value="user_scheduled" />
|
||||
<el-option label="手动(批量)" value="batch" />
|
||||
<el-option label="手动(截图)" value="manual_screenshot" />
|
||||
<el-option label="手动(立即)" value="immediate" />
|
||||
<el-option label="手动(恢复)" value="resumed" />
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="userIdFilter"
|
||||
@@ -195,9 +194,17 @@ onMounted(async () => {
|
||||
<div class="table-wrap">
|
||||
<el-table :data="logs" v-loading="loading" style="width: 100%">
|
||||
<el-table-column prop="created_at" label="时间" width="180" />
|
||||
<el-table-column label="来源" width="90">
|
||||
<el-table-column label="来源" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="sourceMeta(row.source).type" effect="light">{{ sourceMeta(row.source).label }}</el-tag>
|
||||
<el-tooltip
|
||||
v-if="sourceMeta(row.source).tooltip"
|
||||
:content="sourceMeta(row.source).tooltip"
|
||||
placement="top"
|
||||
:show-after="300"
|
||||
>
|
||||
<el-tag :type="sourceMeta(row.source).type" effect="light">{{ sourceMeta(row.source).label }}</el-tag>
|
||||
</el-tooltip>
|
||||
<el-tag v-else :type="sourceMeta(row.source).type" effect="light">{{ sourceMeta(row.source).label }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="user_username" label="用户" width="140" />
|
||||
@@ -282,4 +289,3 @@ onMounted(async () => {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
|
||||
import { fetchDockerStats, fetchRunningTasks, fetchServerInfo, fetchTaskStats } from '../api/tasks'
|
||||
import { getTaskSourceMeta } from '../utils/taskSource'
|
||||
|
||||
const initialLoading = ref(true)
|
||||
const lastUpdatedAt = ref('')
|
||||
@@ -36,13 +37,6 @@ const monitor = ref({
|
||||
queuing: [],
|
||||
})
|
||||
|
||||
const sourceMap = {
|
||||
manual: { label: '手动', type: 'success' },
|
||||
scheduled: { label: '定时', type: 'primary' },
|
||||
immediate: { label: '即时', type: 'warning' },
|
||||
resumed: { label: '恢复', type: 'info' },
|
||||
}
|
||||
|
||||
const statusColorMap = {
|
||||
初始化: '#6b7280',
|
||||
正在登录: '#f59e0b',
|
||||
@@ -181,8 +175,8 @@ onBeforeUnmount(() => {
|
||||
<div v-for="t in monitor.running" :key="`r-${t.account_id}`" class="task-item">
|
||||
<div class="task-left">
|
||||
<div class="task-line">
|
||||
<el-tag :type="(sourceMap[t.source] || sourceMap.manual).type" effect="light" size="small">
|
||||
{{ (sourceMap[t.source] || sourceMap.manual).label }}
|
||||
<el-tag :type="getTaskSourceMeta(t.source).type" effect="light" size="small">
|
||||
{{ getTaskSourceMeta(t.source).label }}
|
||||
</el-tag>
|
||||
<span class="task-user">{{ t.user_username }}</span>
|
||||
<span class="app-muted">→</span>
|
||||
@@ -207,8 +201,8 @@ onBeforeUnmount(() => {
|
||||
<div v-for="t in monitor.queuing" :key="`q-${t.account_id}`" class="task-item queue">
|
||||
<div class="task-left">
|
||||
<div class="task-line">
|
||||
<el-tag :type="(sourceMap[t.source] || sourceMap.manual).type" effect="light" size="small">
|
||||
{{ (sourceMap[t.source] || sourceMap.manual).label }}
|
||||
<el-tag :type="getTaskSourceMeta(t.source).type" effect="light" size="small">
|
||||
{{ getTaskSourceMeta(t.source).label }}
|
||||
</el-tag>
|
||||
<span class="task-user">{{ t.user_username }}</span>
|
||||
<span class="app-muted">→</span>
|
||||
|
||||
43
admin-frontend/src/utils/taskSource.js
Normal file
43
admin-frontend/src/utils/taskSource.js
Normal file
@@ -0,0 +1,43 @@
|
||||
function normalizeRawSource(source) {
|
||||
return String(source || '').trim()
|
||||
}
|
||||
|
||||
function getBatchIdFromUserScheduledSource(raw) {
|
||||
if (!raw.startsWith('user_scheduled')) return ''
|
||||
if (!raw.includes(':')) return ''
|
||||
return raw.split(':', 2)[1] || ''
|
||||
}
|
||||
|
||||
export function getTaskSourceMeta(source) {
|
||||
const raw = normalizeRawSource(source)
|
||||
|
||||
if (!raw || raw === 'manual') {
|
||||
return { group: 'manual', label: '手动', type: 'success', tooltip: '' }
|
||||
}
|
||||
|
||||
if (raw === 'scheduled') {
|
||||
return { group: 'scheduled', label: '定时任务', type: 'primary', tooltip: '系统定时' }
|
||||
}
|
||||
|
||||
if (raw.startsWith('user_scheduled')) {
|
||||
const batchId = getBatchIdFromUserScheduledSource(raw)
|
||||
const batchShort = String(batchId || '').replace(/^batch_/, '')
|
||||
return {
|
||||
group: 'scheduled',
|
||||
label: '定时任务',
|
||||
type: 'primary',
|
||||
tooltip: batchShort ? `用户定时批次:${batchShort}` : '用户定时',
|
||||
}
|
||||
}
|
||||
|
||||
const manualTips = {
|
||||
batch: '手动批量',
|
||||
manual_screenshot: '手动截图',
|
||||
immediate: '立即执行',
|
||||
resumed: '断点恢复',
|
||||
}
|
||||
const tip = manualTips[raw] || raw
|
||||
|
||||
return { group: 'manual', label: '手动', type: 'success', tooltip: tip }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user