This commit is contained in:
2026-04-16 15:19:48 +08:00
commit 1c892259a9
127 changed files with 17390 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";
import apiClient from "@/api/client";
import type { SystemLog } from "@/types";
import { logLevelLabelMap } from "@/types";
const loading = ref(false);
const logs = ref<SystemLog[]>([]);
const filters = reactive({
liveRoomId: "",
recordTaskId: "",
take: 200
});
async function loadLogs() {
loading.value = true;
try {
const { data } = await apiClient.get<SystemLog[]>("/logs", {
params: {
liveRoomId: filters.liveRoomId || undefined,
recordTaskId: filters.recordTaskId || undefined,
take: filters.take
}
});
logs.value = data;
} finally {
loading.value = false;
}
}
function levelTagType(level: number) {
if (level === 3) {
return "danger";
}
if (level === 2) {
return "warning";
}
return "info";
}
function formatDate(value?: string) {
return value ? new Date(value).toLocaleString() : "-";
}
onMounted(loadLogs);
</script>
<template>
<div class="page-stack">
<div class="page-header">
<div>
<h1 class="page-title">系统日志</h1>
<p class="page-subtitle">支持按直播间或任务过滤日志便于定位解析失败巡检异常和 ffmpeg 输出问题</p>
</div>
</div>
<el-card class="surface-card filter-card" shadow="never">
<h3 class="section-title">日志过滤</h3>
<p class="section-subtitle">可选传入直播间 ID 或录制任务 ID数量默认取最近 200 </p>
<el-form class="filter-form">
<el-form-item label="直播间 ID">
<el-input v-model="filters.liveRoomId" placeholder="可选" />
</el-form-item>
<el-form-item label="任务 ID">
<el-input v-model="filters.recordTaskId" placeholder="可选" />
</el-form-item>
<el-form-item label="数量">
<el-input-number v-model="filters.take" :min="1" :max="500" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadLogs">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="surface-card table-card" shadow="never">
<h3 class="section-title">日志列表</h3>
<p class="section-subtitle">按时间倒序排列便于快速回看最近一次异常</p>
<el-table :data="logs" v-loading="loading" height="720" class="premium-table">
<el-table-column label="级别" width="100">
<template #default="{ row }">
<el-tag :type="levelTagType(row.level)">
{{ logLevelLabelMap[row.level] }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="分类" width="120" prop="category" />
<el-table-column label="消息" min-width="240" prop="message" />
<el-table-column label="详情" min-width="360">
<template #default="{ row }">
<span class="monospace log-detail">{{ row.detail || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="时间" width="180">
<template #default="{ row }">
{{ formatDate(row.createdAt) }}
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<style scoped>
.page-stack {
display: grid;
gap: 24px;
}
.filter-card :deep(.el-card__body),
.table-card :deep(.el-card__body) {
padding-top: 20px;
}
.filter-form {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px 12px;
align-items: end;
}
.filter-form :deep(.el-form-item:last-child) {
align-self: end;
}
.log-detail {
font-size: 12px;
color: #6d665b;
}
@media (max-width: 900px) {
.filter-form {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.filter-form :deep(.el-form-item:last-child) {
margin-left: 0;
}
}
@media (max-width: 640px) {
.filter-form {
grid-template-columns: 1fr;
}
}
</style>