在前端开发中,日志展示是一个常见的需求,尤其是在后台管理系统、运维平台、审计模块等场景中。本文将带你一步步构建一个功能强大的日志时间轴组件 LogTimeline,支持以下功能:
- ✅ 展示日志列表(时间轴形式)
- ✅ 点击展开/折叠日志详情
- ✅ 按日志级别筛选
- ✅ 分页加载
- ✅ 导出日志为 JSON 文件
我们将使用 Vue 3 + Element Plus 实现该组件,代码结构清晰,易于扩展。
🧱 一、组件设计思路
1. 数据结构
每条日志包含以下字段:
interface LogItem {
logId: number
logCodeName: string
logContent: string
logDate: string
loggedBy: string
logLevel: 'I' | 'D' | 'T' | 'P' | 'E'
}
2. 功能模块划分
| 模块 | 实现方式 |
|---|---|
| 日志展示 | <el-timeline> + <el-timeline-item> |
| 展开/折叠 | 使用 Set 存储展开项 ID |
| 日志级别筛选 | <el-select> + v-model |
| 分页 | <el-pagination> |
| 导出 | Blob + URL.createObjectURL() |
🧩 二、核心组件实现(LogTimeline.vue)
<template>
<div>
<!-- 筛选器 -->
<div style="margin-bottom: 16px;">
<el-select v-model="selectedLevel" placeholder="筛选日志级别" clearable style="width: 200px;">
<el-option
v-for="level in logLevelOptions"
:key="level.value"
:label="level.label"
:value="level.value"
/>
</el-select>
<el-button type="primary" @click="exportLogs" style="margin-left: 12px;">导出日志</el-button>
</div>
<!-- 时间轴 -->
<el-timeline style="max-width: 800px">
<el-timeline-item
v-for="log in paginatedLogs"
:key="log.logId"
:timestamp="formatTimestamp(log.logDate)"
:type="getLogLevelType(log.logLevel)"
placement="top"
>
<el-card>
<h4 @click="toggleExpand(log)" style="cursor: pointer;">
{{ log.logCodeName }}
<span style="float: right;">
{{ expandedLogs.has(log.logId) ? '收起' : '展开' }}
</span>
</h4>
<p>{{ log.logContent }}</p>
<p><strong>记录者:</strong>{{ log.loggedBy }}</p>
<p><strong>日志级别:</strong>{{ log.logLevel }}</p>
<!-- 展开详情 -->
</el-card>
</el-timeline-item>
</el-timeline>
<!-- 分页器 -->
<el-pagination
v-model:currentPage="currentPage"
:page-size="pageSize"
:total="filteredLogs.length"
layout="prev, pager, next"
style="margin-top: 20px;"
/>
</div>
</template>
<script setup>
import { computed, ref } from 'vue'
import JsonRenderer from './JsonRenderer.vue'
const props = defineProps({
logs: {
type: Array,
required: true
}
})
// 日志级别选项
const logLevelOptions = [
{ label: '所有', value: '' },
{ label: '信息 (I)', value: 'I' },
{ label: '调试 (D)', value: 'D' },
{ label: '追踪 (T)', value: 'T' },
{ label: '提示 (P)', value: 'P' },
{ label: '错误 (E)', value: 'E' }
]
// 筛选
const selectedLevel = ref('')
// 展开状态
const expandedLogs = ref(new Set())
// 分页
const currentPage = ref(1)
const pageSize = 5
// 筛选后的日志
const filteredLogs = computed(() => {
if (!selectedLevel.value) return props.logs
return props.logs.filter(log => log.logLevel === selectedLevel.value)
})
// 当前页日志
const paginatedLogs = computed(() => {
const start = (currentPage.value - 1) * pageSize
const end = start + pageSize
return filteredLogs.value.slice(start, end)
})
// 展开/折叠
function toggleExpand(log) {
if (expandedLogs.value.has(log.logId)) {
expandedLogs.value.delete(log.logId)
} else {
expandedLogs.value.add(log.logId)
}
}
// 格式化时间
function formatTimestamp(dateStr) {
return dateStr.replace(' ', ' / ')
}
// 日志级别颜色
function getLogLevelType(level) {
switch (level) {
case 'I': return 'primary'
case 'D': return 'success'
case 'T': return 'warning'
case 'P': return 'info'
case 'E': return 'danger'
default: return ''
}
}
// 导出日志
function exportLogs() {
const dataStr = JSON.stringify(filteredLogs.value, null, 2)
const blob = new Blob([dataStr], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'logs.json'
a.click()
URL.revokeObjectURL(url)
}
</script>
<style scoped>
h4 {
margin: 0 0 8px;
font-size: 16px;
}
p {
margin: 4px 0;
font-size: 14px;
}
</style>
🧪 四、使用示例
<template>
<LogTimeline :logs="logList" />
</template>
<script setup>
import LogTimeline from '@/components/LogTimeline.vue'
const logList = [
{
logId: 220,
logCodeName: '制单实例#制单完成',
logContent: '制单实例运行完成',
logDate: '2025-07-09 11:39:16',
loggedBy: '日志记录代理[log_agent]',
logLevel: 'I'
},
{
logId: 219,
logCodeName: '单证配置#生成单证完成',
logContent: '单证配置生成单证完成',
logDate: '2025-07-09 11:39:16',
loggedBy: '日志记录代理[log_agent]',
logLevel: 'D'
},
// ... 更多日志
]
</script>
🚀 五、可扩展方向
| 功能 | 说明 |
|---|---|
| 🔍 搜索关键词 | 输入框过滤日志内容 |
| 📅 时间范围筛选 | 使用 el-date-picker |
| 📤 导出为 CSV / Excel | 使用 xlsx 库 |
| 🎨 主题切换 | 支持暗色模式 |
| 📱 响应式布局 | 移动端适配 |
✅ 六、总结
通过本文,你学会了如何:
- 使用 Vue 3 + Element Plus 构建日志时间轴组件
- 实现展开/折叠、筛选、分页、导出等实用功能
- 保持组件结构清晰、可维护、可扩展
这个组件非常适合用于:
- 后台管理系统
- 审计日志模块
- 运维监控平台
- 用户行为追踪