更新后端服务UI
客户端重构部分界面UI
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
<script setup lang="ts">
|
||||
import { Search, ChevronLeft, ChevronRight } from "lucide-vue-next";
|
||||
|
||||
defineProps<{ ctx: any }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="page-stack">
|
||||
<div class="toolbar">
|
||||
<label class="search-box">
|
||||
<Search :size="16" />
|
||||
<input v-model="ctx.auditPage.q" placeholder="搜索消息内容" @keyup.enter="ctx.loadAudit" />
|
||||
</label>
|
||||
<select v-model="ctx.auditPage.type" style="width:140px" @change="ctx.loadAudit">
|
||||
<option value="">全部类型</option>
|
||||
<option value="auth.login">管理员登录</option>
|
||||
<option value="auth.password_changed">修改密码</option>
|
||||
<option value="feedback.created">提交反馈</option>
|
||||
<option value="feedback.updated">更新工单</option>
|
||||
<option value="legacy_json.saved">保存兼容 JSON</option>
|
||||
<option value="release_notice.saved">保存版本日志</option>
|
||||
<option value="release.package_uploaded">上传发布包</option>
|
||||
<option value="legacy.sync">旧项目同步</option>
|
||||
</select>
|
||||
<input v-model="ctx.auditPage.target" placeholder="目标对象" style="width:100px" @keyup.enter="ctx.loadAudit" />
|
||||
<button class="btn ghost" @click="ctx.loadAudit">查询</button>
|
||||
</div>
|
||||
|
||||
<section class="panel">
|
||||
<div class="section-head">
|
||||
<h2>审计日志</h2>
|
||||
<span class="badge">共 {{ ctx.auditPage.total || 0 }} 条</span>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>时间</th>
|
||||
<th>操作者</th>
|
||||
<th>操作类型</th>
|
||||
<th>目标</th>
|
||||
<th>消息</th>
|
||||
<th>IP</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="item in ctx.auditPage.items || []"
|
||||
:key="item.id"
|
||||
:class="{ selected: ctx.auditPage.selected?.id === item.id }"
|
||||
style="cursor:pointer"
|
||||
@click="ctx.selectAuditLog(item)"
|
||||
>
|
||||
<td class="mono">{{ item.createdAt }}</td>
|
||||
<td>{{ item.actor || "-" }}</td>
|
||||
<td><span class="badge neutral">{{ ctx.auditTypeLabel(item.type) }}</span></td>
|
||||
<td class="mono">{{ item.target || "-" }}</td>
|
||||
<td>{{ ctx.auditMessage(item) }}</td>
|
||||
<td class="hash">{{ item.ip || "-" }}</td>
|
||||
</tr>
|
||||
<tr v-if="!(ctx.auditPage.items || []).length">
|
||||
<td colspan="6">暂无审计日志。</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="pagination" v-if="ctx.auditPage.total > 0">
|
||||
<button class="btn ghost small" :disabled="ctx.auditPage.page <= 1" @click="ctx.setAuditPage(ctx.auditPage.page - 1)">
|
||||
<ChevronLeft :size="14" />
|
||||
</button>
|
||||
<span class="muted">第 {{ ctx.auditPage.page }} / {{ Math.ceil(ctx.auditPage.total / ctx.auditPage.perPage) }} 页 · {{ ctx.auditPage.total }} 条</span>
|
||||
<button class="btn ghost small" :disabled="ctx.auditPage.page >= Math.ceil(ctx.auditPage.total / ctx.auditPage.perPage)" @click="ctx.setAuditPage(ctx.auditPage.page + 1)">
|
||||
<ChevronRight :size="14" />
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Detail panel for selected log -->
|
||||
<section v-if="ctx.auditPage.selected" class="panel">
|
||||
<div class="section-head">
|
||||
<h2>审计详情</h2>
|
||||
<span class="badge neutral">ID {{ ctx.auditPage.selected.id }}</span>
|
||||
</div>
|
||||
<div class="kv-grid">
|
||||
<span>时间</span><strong>{{ ctx.auditPage.selected.createdAt }}</strong>
|
||||
<span>操作者</span><strong>{{ ctx.auditPage.selected.actor || "-" }}</strong>
|
||||
<span>类型</span><strong>{{ ctx.auditTypeLabel(ctx.auditPage.selected.type) }}</strong>
|
||||
<span>目标</span><strong class="mono">{{ ctx.auditPage.selected.target || "-" }}</strong>
|
||||
<span>消息</span><strong>{{ ctx.auditMessage(ctx.auditPage.selected) }}</strong>
|
||||
<span>IP</span><strong class="mono">{{ ctx.auditPage.selected.ip || "-" }}</strong>
|
||||
<span>User-Agent</span><strong class="hash" style="word-break:break-all">{{ ctx.auditPage.selected.userAgent || "-" }}</strong>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 0 0;
|
||||
}
|
||||
.pagination .btn.small {
|
||||
padding: 3px 7px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user