Files
thebet365/apps/admin/src/views/Audit.vue
Mars 27580b2479 feat(admin,player,api): 优胜冠军通用管理与界面精简
管理端新增冠军盘列表/编辑、展开懒加载与 ECharts 修复;各列表页去掉重复标题。玩家端支持多赛事冠军盘、分批加载与语言切换刷新。API 扩展 outright CRUD 与列表性能优化。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 09:17:01 +08:00

124 lines
3.3 KiB
Vue

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useAdminLocale } from '../composables/useAdminLocale';
import api from '../api';
const { t, locale, localeTag } = useAdminLocale();
function auditActionLabel(action: string) {
const key = `audit.action.${action}`;
const label = t(key);
return label === key ? action : label;
}
function auditModuleLabel(module: string) {
const key = `audit.module.${module}`;
const label = t(key);
return label === key ? module : label;
}
interface AuditRow {
action: string;
module: string;
targetId: string | null;
createdAt: string;
}
const logs = ref<AuditRow[]>([]);
const total = ref(0);
const page = ref(1);
const pageSize = ref(10);
const filterModule = ref('');
onMounted(load);
async function load() {
const { data } = await api.get('/admin/audit-logs', {
params: {
page: page.value,
pageSize: pageSize.value,
module: filterModule.value.trim() || undefined,
},
});
logs.value = (data.data.items ?? []) as AuditRow[];
total.value = data.data.total ?? 0;
}
function onPageChange(p: number) {
page.value = p;
load();
}
function onSizeChange(size: number) {
pageSize.value = size;
page.value = 1;
load();
}
function formatTime(v: string) {
return new Date(v).toLocaleString(localeTag.value, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
});
}
</script>
<template>
<div class="admin-list-page">
<el-card class="filter-card" shadow="never">
<el-form inline>
<el-form-item :label="t('common.module')">
<el-input
v-model="filterModule"
:placeholder="t('audit.module_ph')"
clearable
style="width: 160px"
@keyup.enter="load"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="load">{{ t('common.search') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="data-card" shadow="never">
<div class="table-wrap">
<el-table :key="locale" :data="logs" stripe>
<el-table-column :label="t('audit.col.action')" min-width="140">
<template #default="{ row }">{{ auditActionLabel(row.action) }}</template>
</el-table-column>
<el-table-column :label="t('audit.col.module')" width="120">
<template #default="{ row }">{{ auditModuleLabel(row.module) }}</template>
</el-table-column>
<el-table-column prop="targetId" :label="t('audit.col.target_id')" min-width="100" />
<el-table-column :label="t('audit.col.time')" min-width="160">
<template #default="{ row }">{{ formatTime(row.createdAt) }}</template>
</el-table-column>
</el-table>
</div>
<div class="pager">
<el-pagination
v-model:current-page="page"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next"
background
@current-change="onPageChange"
@size-change="onSizeChange"
/>
</div>
</el-card>
</div>
</template>
<style scoped>
.filter-card { border-radius: 12px; }
.data-card { border-radius: 12px; }
</style>