<template>
|
<div class="page">
|
<div class="page-title">
|
<div><h2>错误日志</h2><p>记录程序运行中的未处理异常,便于定位和修复缺陷</p></div>
|
</div>
|
<div class="table-panel">
|
<div class="toolbar">
|
<el-input v-model="filters.keyword" clearable placeholder="账户名 / 姓名 / 请求地址 / 异常信息" style="width:280px" @keyup.enter.native="search"></el-input>
|
<el-select v-model="filters.module" clearable placeholder="模块" style="width:150px">
|
<el-option v-for="item in modules" :key="item" :label="item" :value="item"></el-option>
|
</el-select>
|
<el-input v-model="filters.exceptionType" clearable placeholder="异常类型" style="width:220px" @keyup.enter.native="search"></el-input>
|
<el-date-picker
|
v-model="filters.dates"
|
type="daterange"
|
value-format="yyyy-MM-dd"
|
range-separator="至"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
style="width:260px"
|
></el-date-picker>
|
<el-button type="primary" icon="el-icon-search" v-permission="'system:error-logs:query'" @click="search">查询</el-button>
|
<el-button icon="el-icon-refresh-left" @click="reset">重置</el-button>
|
</div>
|
<el-table v-loading="loading" :data="rows" border stripe height="calc(100vh - 250px)">
|
<el-table-column prop="errorTime" label="发生时间" width="180"></el-table-column>
|
<el-table-column prop="userName" label="账户名" width="120"></el-table-column>
|
<el-table-column prop="nickName" label="姓名" width="110"></el-table-column>
|
<el-table-column prop="module" label="模块" width="120"></el-table-column>
|
<el-table-column prop="requestMethod" label="方式" width="75" align="center"></el-table-column>
|
<el-table-column prop="requestUri" label="请求地址" min-width="230" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="exceptionType" label="异常类型" min-width="220" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="message" label="异常信息" min-width="280" show-overflow-tooltip></el-table-column>
|
<el-table-column label="操作" width="80" fixed="right">
|
<template slot-scope="{ row }">
|
<el-button type="text" v-permission="'system:error-logs:detail'" @click="openDetail(row)">详情</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<el-pagination
|
class="pager"
|
background
|
layout="total, sizes, prev, pager, next"
|
:total="total"
|
:current-page="current"
|
:page-size="size"
|
:page-sizes="[20, 50, 100]"
|
@current-change="handleCurrentChange"
|
@size-change="handleSizeChange"
|
></el-pagination>
|
</div>
|
|
<el-dialog title="错误详情" :visible.sync="detailVisible" width="900px" append-to-body>
|
<div v-loading="detailLoading">
|
<div class="detail-meta">
|
<span><b>发生时间:</b>{{ detail.errorTime }}</span>
|
<span><b>操作人:</b>{{ detail.userName || '-' }}{{ detail.nickName ? ' / ' + detail.nickName : '' }}</span>
|
<span><b>模块:</b>{{ detail.module || '-' }}</span>
|
</div>
|
<div class="detail-meta">
|
<span><b>请求:</b>{{ (detail.requestMethod || '') + ' ' + (detail.requestUri || '') }}</span>
|
</div>
|
<div class="detail-meta">
|
<span><b>异常类型:</b>{{ detail.exceptionType }}</span>
|
</div>
|
<div class="detail-meta">
|
<span><b>异常信息:</b>{{ detail.message }}</span>
|
</div>
|
<pre class="stack-trace">{{ detail.stackTrace || '无堆栈信息' }}</pre>
|
</div>
|
<template slot="footer"><el-button @click="detailVisible = false">关闭</el-button></template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
import api from '@/api'
|
export default {
|
name: 'ErrorLogManage',
|
data() {
|
return {
|
rows: [],
|
total: 0,
|
current: 1,
|
size: 20,
|
loading: false,
|
detailVisible: false,
|
detailLoading: false,
|
detail: {},
|
modules: ['故障管理', '完工管理', '完工验收', '统计报表', '用户管理', '角色管理', '菜单管理', '承修单位管理', '系统管理', '其他'],
|
filters: { keyword: '', module: '', exceptionType: '', dates: [] }
|
}
|
},
|
created() { this.load() },
|
methods: {
|
load() {
|
this.loading = true
|
const dates = this.filters.dates || []
|
api.get('/system/error-logs', {
|
params: {
|
keyword: this.filters.keyword || undefined,
|
module: this.filters.module || undefined,
|
exceptionType: this.filters.exceptionType || undefined,
|
startDate: dates[0] || undefined,
|
endDate: dates[1] || undefined,
|
current: this.current,
|
size: this.size
|
}
|
}).then(res => {
|
const data = res.data || {}
|
this.rows = data.records || []
|
this.total = data.total || 0
|
}).finally(() => { this.loading = false })
|
},
|
search() { this.current = 1; this.load() },
|
reset() { this.filters = { keyword: '', module: '', exceptionType: '', dates: [] }; this.search() },
|
openDetail(row) {
|
this.detailLoading = true
|
this.detail = {}
|
this.detailVisible = true
|
api.get('/system/error-logs/' + row.id).then(res => {
|
this.detail = res.data || {}
|
}).finally(() => { this.detailLoading = false })
|
},
|
handleCurrentChange(page) { this.current = page; this.load() },
|
handleSizeChange(size) { this.size = size; this.current = 1; this.load() }
|
}
|
}
|
</script>
|
|
<style scoped>
|
.toolbar { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
|
.pager { margin-top: 12px; text-align: right; }
|
.detail-meta { margin-bottom: 8px; color: #42566b; line-height: 22px; word-break: break-all; }
|
.detail-meta b { color: #26394d; }
|
.stack-trace {
|
max-height: 520px;
|
margin: 12px 0 0;
|
padding: 12px;
|
border: 1px solid #dce4ec;
|
border-radius: 4px;
|
color: #30445a;
|
background: #f7f9fb;
|
font-family: Consolas, "Courier New", monospace;
|
font-size: 12px;
|
line-height: 18px;
|
white-space: pre-wrap;
|
word-break: break-all;
|
overflow: auto;
|
}
|
</style>
|