UI改版测试V0
This commit is contained in:
@@ -3,144 +3,45 @@
|
||||
{% block title %}错误日志 - 机器人管理后台{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- 错误日志 -->
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover">
|
||||
<div slot="header">
|
||||
<span>错误日志</span>
|
||||
</div>
|
||||
<el-table {% raw %}:data="errorLogs"{% endraw %} style="width: 100%" border>
|
||||
<el-table-column prop="plugin_name" label="插件名称"></el-table-column>
|
||||
<el-table-column prop="command" label="命令"></el-table-column>
|
||||
<el-table-column prop="error_message" label="错误信息" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column prop="created_at" label="时间"></el-table-column>
|
||||
<el-table-column label="用户">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.user_id">
|
||||
{% raw %}{{ scope.row.user_name || scope.row.user_id }} ({{ scope.row.user_id }}){% endraw %}
|
||||
</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="群组">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.group_id">
|
||||
{% raw %}{{ scope.row.group_name || scope.row.group_id }} ({{ scope.row.group_id }}){% endraw %}
|
||||
</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="primary" @click="viewErrorDetail(scope.row)">查看详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-container" style="margin-top: 20px; text-align: right;">
|
||||
<el-pagination
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="currentPage"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="totalErrors">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<div class="page-shell logs-page">
|
||||
<div class="page-hero"><div class="page-hero-copy"><div class="page-eyebrow">Error Center</div><h1>错误日志</h1><p>统一查看插件异常、用户上下文与错误详情,方便快速定位问题来源。</p></div></div>
|
||||
<el-row :gutter="16" class="overview-grid">
|
||||
<el-col :span="8"><el-card class="overview-card overview-card--primary"><div class="overview-label">错误总数</div><div class="overview-value">{% raw %}{{ totalErrors }}{% endraw %}</div><div class="overview-note">当前分页查询结果对应总量</div></el-card></el-col>
|
||||
<el-col :span="8"><el-card class="overview-card"><div class="overview-label">当前页日志数</div><div class="overview-value">{% raw %}{{ errorLogs.length }}{% endraw %}</div><div class="overview-note">本页已加载的错误记录</div></el-card></el-col>
|
||||
<el-col :span="8"><el-card class="overview-card overview-card--soft"><div class="overview-label">分页大小</div><div class="overview-value">{% raw %}{{ pageSize }}{% endraw %}</div><div class="overview-note">每页可查看的错误条目</div></el-card></el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 错误详情对话框 -->
|
||||
<el-card class="workspace-card" shadow="hover">
|
||||
<div slot="header" class="workspace-header"><div><h3>错误列表</h3><p>查看插件、命令、错误摘要以及相关用户/群组上下文。</p></div></div>
|
||||
<el-table :data="errorLogs" style="width:100%">
|
||||
<el-table-column prop="plugin_name" label="插件名称" width="140"></el-table-column>
|
||||
<el-table-column prop="command" label="命令" width="120"></el-table-column>
|
||||
<el-table-column prop="error_message" label="错误信息" min-width="320" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column prop="created_at" label="时间" width="170"></el-table-column>
|
||||
<el-table-column label="用户" min-width="180"><template slot-scope="scope"><span v-if="scope.row.user_id">{% raw %}{{ scope.row.user_name || scope.row.user_id }} ({{ scope.row.user_id }}){% endraw %}</span><span v-else>-</span></template></el-table-column>
|
||||
<el-table-column label="群组" min-width="180"><template slot-scope="scope"><span v-if="scope.row.group_id">{% raw %}{{ scope.row.group_name || scope.row.group_id }} ({{ scope.row.group_id }}){% endraw %}</span><span v-else>-</span></template></el-table-column>
|
||||
<el-table-column label="操作" width="120" align="center"><template slot-scope="scope"><el-button size="mini" type="primary" plain @click="viewErrorDetail(scope.row)">查看详情</el-button></template></el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-container"><el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[10,20,50,100]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="totalErrors"></el-pagination></div>
|
||||
</el-card>
|
||||
<el-dialog title="错误详情" :visible.sync="errorDetailVisible" width="70%">
|
||||
<div>
|
||||
<p><strong>插件名称:</strong> {% raw %}{{ errorDetail.plugin_name }}{% endraw %}</p>
|
||||
<p><strong>命令:</strong> {% raw %}{{ errorDetail.command }}{% endraw %}</p>
|
||||
<p><strong>用户ID:</strong> {% raw %}{{ errorDetail.user_id }}{% endraw %}</p>
|
||||
<p><strong>群组ID:</strong> {% raw %}{{ errorDetail.group_id || '无' }}{% endraw %}</p>
|
||||
<p><strong>时间:</strong> {% raw %}{{ errorDetail.created_at }}{% endraw %}</p>
|
||||
<p><strong>错误信息:</strong> {% raw %}{{ errorDetail.error_message }}{% endraw %}</p>
|
||||
<div v-if="errorDetail.stack_trace">
|
||||
<p><strong>堆栈跟踪:</strong></p>
|
||||
<pre>{% raw %}{{ errorDetail.stack_trace }}{% endraw %}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="插件名称">{% raw %}{{ errorDetail.plugin_name }}{% endraw %}</el-descriptions-item>
|
||||
<el-descriptions-item label="命令">{% raw %}{{ errorDetail.command }}{% endraw %}</el-descriptions-item>
|
||||
<el-descriptions-item label="用户ID">{% raw %}{{ errorDetail.user_id }}{% endraw %}</el-descriptions-item>
|
||||
<el-descriptions-item label="群组ID">{% raw %}{{ errorDetail.group_id || '无' }}{% endraw %}</el-descriptions-item>
|
||||
<el-descriptions-item label="时间">{% raw %}{{ errorDetail.created_at }}{% endraw %}</el-descriptions-item>
|
||||
<el-descriptions-item label="错误信息">{% raw %}{{ errorDetail.error_message }}{% endraw %}</el-descriptions-item>
|
||||
<el-descriptions-item label="堆栈跟踪" v-if="errorDetail.stack_trace"><pre class="stack-trace">{% raw %}{{ errorDetail.stack_trace }}{% endraw %}</pre></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
mixins: [baseApp],
|
||||
data() {
|
||||
return {
|
||||
errorLogs: [],
|
||||
errorDetail: {},
|
||||
errorDetailVisible: false,
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
totalErrors: 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.currentView = '5';
|
||||
this.loadData();
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
const days = parseInt(this.timeRange);
|
||||
this.loadErrorLogs(days);
|
||||
},
|
||||
loadErrorLogs(days) {
|
||||
axios.get(`/api/error_logs?days=${days}&limit=${this.pageSize}&offset=${(this.currentPage - 1) * this.pageSize}`)
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
this.errorLogs = response.data.data.logs || [];
|
||||
this.totalErrors = response.data.data.total || 0;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载错误日志出错:', error);
|
||||
this.$message.error('加载错误日志出错');
|
||||
});
|
||||
},
|
||||
viewErrorDetail(error) {
|
||||
// 如果已有错误ID,直接加载详情
|
||||
if (error.id) {
|
||||
this.loadErrorDetail(error.id);
|
||||
} else {
|
||||
// 否则直接显示当前行的数据
|
||||
this.errorDetail = error;
|
||||
this.errorDetailVisible = true;
|
||||
}
|
||||
},
|
||||
loadErrorDetail(errorId) {
|
||||
axios.get(`/api/error_detail/${errorId}`)
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
this.errorDetail = response.data.data || {};
|
||||
this.errorDetailVisible = true;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载错误详情出错:', error);
|
||||
this.$message.error('加载错误详情出错');
|
||||
});
|
||||
},
|
||||
handleSizeChange(size) {
|
||||
this.pageSize = size;
|
||||
this.currentPage = 1; // 重置到第一页
|
||||
this.loadData();
|
||||
},
|
||||
handleCurrentChange(page) {
|
||||
this.currentPage = page;
|
||||
this.loadData();
|
||||
}
|
||||
}
|
||||
});
|
||||
new Vue({ el:'#app', mixins:[baseApp], data(){ return { errorLogs:[], errorDetail:{}, errorDetailVisible:false, currentPage:1, pageSize:20, totalErrors:0 } }, mounted(){ this.currentView='5'; this.loadData(); }, methods:{ loadData(){ this.loadErrorLogs(parseInt(this.timeRange)); }, loadErrorLogs(days){ axios.get(`/api/error_logs?days=${days}&limit=${this.pageSize}&offset=${(this.currentPage - 1) * this.pageSize}`).then(r=>{ if(r.data.success){ this.errorLogs=r.data.data.logs||[]; this.totalErrors=r.data.data.total||0; } }).catch(e=>{ console.error('加载错误日志出错:',e); this.$message.error('加载错误日志出错'); }); }, viewErrorDetail(error){ if(error.id){ this.loadErrorDetail(error.id);} else { this.errorDetail=error; this.errorDetailVisible=true; } }, loadErrorDetail(id){ axios.get(`/api/error_detail/${id}`).then(r=>{ if(r.data.success){ this.errorDetail=r.data.data||{}; this.errorDetailVisible=true; } }).catch(e=>{ console.error('加载错误详情出错:',e); this.$message.error('加载错误详情出错'); }); }, handleSizeChange(size){ this.pageSize=size; this.currentPage=1; this.loadData(); }, handleCurrentChange(page){ this.currentPage=page; this.loadData(); } } });
|
||||
</script>
|
||||
{% endblock %}
|
||||
<style>
|
||||
.page-shell{display:flex;flex-direction:column;gap:16px}.page-hero{padding:24px 26px;border-radius:24px;background:linear-gradient(135deg, rgba(79,70,229,.10), rgba(59,130,246,.08), rgba(255,255,255,.9));border:1px solid rgba(148,163,184,.16);box-shadow:0 18px 40px rgba(15,23,42,.06)}.page-eyebrow{font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:#6366f1;font-weight:700;margin-bottom:8px}.page-hero-copy h1{font-size:30px;line-height:1.1;margin-bottom:10px;color:#0f172a}.page-hero-copy p{color:#64748b;font-size:14px}.overview-grid .el-col{margin-bottom:16px}.overview-card{min-height:112px}.overview-card--primary{background:linear-gradient(180deg, rgba(79,70,229,.10), rgba(255,255,255,.94)) !important}.overview-card--soft{background:linear-gradient(180deg, rgba(59,130,246,.08), rgba(255,255,255,.94)) !important}.overview-label{font-size:13px;color:#64748b;margin-bottom:14px}.overview-value{font-size:30px;font-weight:700;color:#0f172a;margin-bottom:10px}.overview-note{font-size:12px;color:#94a3b8}.workspace-header{display:flex;align-items:center;justify-content:space-between;gap:16px}.workspace-header h3{font-size:18px;margin-bottom:4px}.workspace-header p{font-size:13px;color:#64748b}.pagination-container{margin-top:20px;text-align:right}.stack-trace{white-space:pre-wrap;word-break:break-word;background:rgba(248,250,252,.85);border:1px solid rgba(148,163,184,.12);border-radius:14px;padding:14px;color:#334155}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user