refactor: rename audit logs to operation logs and update related routes and docs

pull/48/head
hnu202326010131 1 month ago
parent 24e8e6933e
commit 4eaff06411

@ -1,17 +1,17 @@
# 审计日志后端联调指南
# 操作日志后端联调指南
本文档旨在指导后端开发人员如何对接“审计日志”页面的前端接口。
本文档旨在指导后端开发人员如何对接“操作日志”页面的前端接口。
## 1. 接口概述
审计日志页面通过 `GET` 请求从后端获取系统操作日志。该页面仅限 `admin`(管理员)角色访问。
操作日志页面通过 `GET` 请求从后端获取系统操作日志。该页面仅限 `admin`(管理员)角色访问。
## 2. 接口定义
### 获取审计日志列表
### 获取操作日志列表
- **请求方法**: `GET`
- **请求路径**: `/v1/audit-logs`
- **请求路径**: `/v1/operation-logs`
- **鉴权要求**: 需在 Header 中携带 `Authorization: Bearer <token>`
#### 响应格式 (JSON)
@ -22,7 +22,7 @@
{
"items": [
{
"id": "audit-12345",
"id": "operation-12345",
"timestamp": "2025-11-07T10:20:03Z",
"user": "admin",
"action": "用户登录",
@ -38,7 +38,7 @@
| 前端展示字段 | 推荐后端字段 | 备用适配字段 |
| :--- | :--- | :--- |
| 唯一标识 | `id` | `audit_id` |
| 唯一标识 | `id` | `operation_id` |
| 时间戳 | `timestamp` | `created_at`, `time` |
| 操作用户 | `user` | `username`, `operator` |
| 动作名称 | `action` | `operation` |
@ -53,11 +53,11 @@
## 4. 示例代码 (Axios 调用)
```typescript
const r = await api.get('/v1/audit-logs', {
const r = await api.get('/v1/operation-logs', {
headers: { Authorization: `Bearer ${token}` }
})
```
## 5. 权限说明
审计日志属于敏感数据,后端接口**必须**校验 `token` 中的角色信息,确保只有具有管理员权限的用户才能获取数据。
操作日志属于敏感数据,后端接口**必须**校验 `token` 中的角色信息,确保只有具有管理员权限的用户才能获取数据。

@ -28,8 +28,8 @@
- **执行日志 (Exec Logs)**
- **路径**: `/exec-logs`
- **功能**: 专门展示自动化脚本或运维指令的执行历史及详细输出结果。
- **审计日志 (Audit Logs)**
- **路径**: `/audit-logs` (仅管理员)
- **操作日志 (Operation Logs)**
- **路径**: `/operation-logs` (仅管理员)
- **功能**: 记录用户在系统内的所有操作行为,用于安全溯源。
## 4. 诊断与自动化

@ -119,8 +119,8 @@
<RouterLink
v-if="can([Roles.admin])"
class="sidebar__item sidebar__item--sub"
to="/audit-logs"
:class="{ 'is-active': isActive('/audit-logs') }"
to="/operation-logs"
:class="{ 'is-active': isActive('/operation-logs') }"
title="操作日志"
>
<i class="fas fa-history sidebar__icon"></i>

@ -15,7 +15,7 @@ const routes: RouteRecordRaw[] = [
{ path: '/profile', name: 'profile', component: () => import('../views/Profile.vue'), meta: { requiresAuth: true, roles: AllRoles } },
{ path: '/account', name: 'account', component: () => import('../views/Account.vue'), meta: { requiresAuth: true, roles: AllRoles } },
{ path: '/user-management', name: 'user-management', component: () => import('../views/UserManagement.vue'), meta: { requiresAuth: true, roles: [Roles.admin] } },
{ path: '/audit-logs', name: 'audit-logs', component: () => import('../views/AuditLogs.vue'), meta: { requiresAuth: true, roles: [Roles.admin] } }
{ path: '/operation-logs', name: 'operation-logs', component: () => import('../views/OperationLogs.vue'), meta: { requiresAuth: true, roles: [Roles.admin] } }
]
const router = createRouter({ history: createWebHashHistory(), routes })

@ -1,19 +1,19 @@
<template>
<section class="layout__section" aria-labelledby="audit-logs-title">
<section class="layout__section" aria-labelledby="operation-logs-title">
<header class="layout__page-header">
<div>
<h2 id="audit-logs-title" class="layout__page-title">审计日志</h2>
<h2 id="operation-logs-title" class="layout__page-title">操作日志</h2>
<p class="layout__page-subtitle">记录用户操作与系统事件</p>
</div>
<div class="layout__page-actions">
<button class="btn" @click="refresh" :disabled="loading">刷新</button>
<button class="btn btn--primary u-ml-1" disabled title="功能待实现">导出审计日志</button>
<button class="btn btn--primary u-ml-1" disabled title="功能待实现">导出操作日志</button>
</div>
</header>
<article class="layout__card">
<div class="layout__card-header">
<h3 class="layout__card-title">近期审计事件</h3>
<h3 class="layout__card-title">近期操作事件</h3>
</div>
<div class="layout__card-body u-p-0">
<div v-if="loading" class="u-p-4 u-text-center">...</div>
@ -36,7 +36,7 @@
<td class="dashboard__table-td">{{ log.detail }}</td>
</tr>
<tr v-if="logs.length === 0" class="dashboard__table-row">
<td colspan="4" class="dashboard__table-td u-text-center">暂无审计记录</td>
<td colspan="4" class="dashboard__table-td u-text-center">暂无操作记录</td>
</tr>
</tbody>
</table>
@ -51,7 +51,7 @@ import { ref, reactive, onMounted } from 'vue'
import api from '../lib/api'
import { useAuthStore } from '../stores/auth'
interface AuditLogItem {
interface OperationLogItem {
id: string
timestamp: string
user: string
@ -60,7 +60,7 @@ interface AuditLogItem {
}
const auth = useAuthStore()
const logs = reactive<AuditLogItem[]>([])
const logs = reactive<OperationLogItem[]>([])
const loading = ref(false)
const err = ref('')
@ -77,15 +77,15 @@ async function loadLogs() {
loading.value = true
err.value = ''
try {
const r = await api.get('/v1/audit-logs', {
const r = await api.get('/v1/operation-logs', {
headers: auth.token ? { Authorization: `Bearer ${auth.token}` } : undefined
})
//
const items = Array.isArray(r.data?.items) ? r.data.items : (Array.isArray(r.data?.audit_logs) ? r.data.audit_logs : [])
const items = Array.isArray(r.data?.items) ? r.data.items : (Array.isArray(r.data?.operation_logs) ? r.data.operation_logs : [])
const normalized: AuditLogItem[] = items.map((d: any) => ({
id: d.id || d.audit_id,
const normalized: OperationLogItem[] = items.map((d: any) => ({
id: d.id || d.operation_id,
timestamp: d.timestamp || d.created_at || d.time,
user: d.user || d.username || d.operator,
action: d.action || d.operation,
@ -100,15 +100,15 @@ async function loadLogs() {
if (status === 401) {
err.value = '会话已过期或未登录,请重新登录后再试。'
} else if (status === 403) {
err.value = '权限不足:只有管理员角色可以查看审计日志。'
err.value = '权限不足:只有管理员角色可以查看操作日志。'
} else if (status === 404) {
err.value = '未找到审计日志接口 (404),请联系后端开发人员确认 API 端点。'
err.value = '未找到操作日志接口 (404),请联系后端开发人员确认 API 端点。'
} else if (status === 500) {
err.value = '后端服务器内部错误 (500),请稍后重试或检查后端日志。'
} else if (status === 502 || status === 504) {
err.value = '后端网关错误或超时 (502/504),请检查后端服务是否正常运行。'
} else {
err.value = `加载审计日志失败:${detail || e.message || '请检查网络连接或后端服务状态'}`
err.value = `加载操作日志失败:${detail || e.message || '请检查网络连接或后端服务状态'}`
}
logs.splice(0, logs.length)
Loading…
Cancel
Save