add log store and types
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { api } from '@/utils/request'
|
||||
import type {
|
||||
PaginatedData,
|
||||
OperationLogRecord,
|
||||
OperationLogFilters,
|
||||
} from '@/types/api'
|
||||
|
||||
export type { OperationLogRecord }
|
||||
|
||||
interface UserLookup {
|
||||
id: number
|
||||
username: string
|
||||
}
|
||||
|
||||
export const useOperationLogStore = defineStore('operationLog', () => {
|
||||
const logs = ref<OperationLogRecord[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
total: 0,
|
||||
})
|
||||
const filters = reactive<OperationLogFilters>({
|
||||
user_id: undefined,
|
||||
action: undefined,
|
||||
target_type: undefined,
|
||||
created_at_range: null,
|
||||
})
|
||||
|
||||
const users = ref<UserLookup[]>([])
|
||||
const userMap = computed(
|
||||
() => new Map(users.value.map((u) => [u.id, u.username])),
|
||||
)
|
||||
|
||||
async function loadLookups() {
|
||||
try {
|
||||
const data = await api.get<PaginatedData<UserLookup>>('/api/v1/users', {
|
||||
per_page: 200,
|
||||
})
|
||||
users.value = data.items
|
||||
} catch (err: unknown) {
|
||||
console.warn('加载用户列表失败', err)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchLogs() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await api.get<PaginatedData<OperationLogRecord>>(
|
||||
'/api/v1/logs/operations',
|
||||
{
|
||||
page: pagination.page,
|
||||
per_page: pagination.per_page,
|
||||
user_id: filters.user_id || undefined,
|
||||
action: filters.action || undefined,
|
||||
target_type: filters.target_type || undefined,
|
||||
created_at_from: filters.created_at_range?.[0] || undefined,
|
||||
created_at_to: filters.created_at_range?.[1] || undefined,
|
||||
},
|
||||
)
|
||||
logs.value = data.items
|
||||
pagination.total = data.total
|
||||
pagination.page = data.page
|
||||
} catch (err: unknown) {
|
||||
logs.value = []
|
||||
pagination.total = 0
|
||||
const msg = err instanceof Error ? err.message : '获取操作日志列表失败'
|
||||
message.error(msg)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
filters.user_id = undefined
|
||||
filters.action = undefined
|
||||
filters.target_type = undefined
|
||||
filters.created_at_range = null
|
||||
pagination.page = 1
|
||||
}
|
||||
|
||||
return {
|
||||
logs,
|
||||
loading,
|
||||
pagination,
|
||||
filters,
|
||||
users,
|
||||
userMap,
|
||||
loadLookups,
|
||||
fetchLogs,
|
||||
resetFilters,
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,96 @@
|
||||
import { api } from '@/utils/request'
|
||||
import type {
|
||||
PaginatedData,
|
||||
RequestLogRecord,
|
||||
RequestLogFilters,
|
||||
} from '@/types/api'
|
||||
|
||||
export type { RequestLogRecord }
|
||||
|
||||
interface UserLookup {
|
||||
id: number
|
||||
username: string
|
||||
}
|
||||
|
||||
export const useRequestLogStore = defineStore('requestLog', () => {
|
||||
const logs = ref<RequestLogRecord[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
total: 0,
|
||||
})
|
||||
const filters = reactive<RequestLogFilters>({
|
||||
user_id: undefined,
|
||||
method: undefined,
|
||||
path: '',
|
||||
status_code: undefined,
|
||||
created_at_range: null,
|
||||
})
|
||||
|
||||
const users = ref<UserLookup[]>([])
|
||||
const userMap = computed(
|
||||
() => new Map(users.value.map((u) => [u.id, u.username])),
|
||||
)
|
||||
|
||||
async function loadLookups() {
|
||||
try {
|
||||
const data = await api.get<PaginatedData<UserLookup>>('/api/v1/users', {
|
||||
per_page: 200,
|
||||
})
|
||||
users.value = data.items
|
||||
} catch (err: unknown) {
|
||||
console.warn('加载用户列表失败', err)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchLogs() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await api.get<PaginatedData<RequestLogRecord>>(
|
||||
'/api/v1/logs/requests',
|
||||
{
|
||||
page: pagination.page,
|
||||
per_page: pagination.per_page,
|
||||
user_id: filters.user_id || undefined,
|
||||
method: filters.method || undefined,
|
||||
path: filters.path || undefined,
|
||||
status_code: filters.status_code || undefined,
|
||||
created_at_from: filters.created_at_range?.[0] || undefined,
|
||||
created_at_to: filters.created_at_range?.[1] || undefined,
|
||||
},
|
||||
)
|
||||
logs.value = data.items
|
||||
pagination.total = data.total
|
||||
pagination.page = data.page
|
||||
} catch (err: unknown) {
|
||||
logs.value = []
|
||||
pagination.total = 0
|
||||
const msg = err instanceof Error ? err.message : '获取请求日志列表失败'
|
||||
message.error(msg)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
filters.user_id = undefined
|
||||
filters.method = undefined
|
||||
filters.path = ''
|
||||
filters.status_code = undefined
|
||||
filters.created_at_range = null
|
||||
pagination.page = 1
|
||||
}
|
||||
|
||||
return {
|
||||
logs,
|
||||
loading,
|
||||
pagination,
|
||||
filters,
|
||||
users,
|
||||
userMap,
|
||||
loadLookups,
|
||||
fetchLogs,
|
||||
resetFilters,
|
||||
}
|
||||
})
|
||||
@@ -253,6 +253,57 @@ export interface DashboardBreakdownParams {
|
||||
data_type?: string
|
||||
}
|
||||
|
||||
/** ─── 请求日志 ─── */
|
||||
|
||||
export interface RequestLogRecord {
|
||||
id: number
|
||||
user_id: number | null
|
||||
method: string
|
||||
path: string
|
||||
status_code: number
|
||||
ip: string
|
||||
response_code: number
|
||||
duration_ms: number
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface RequestLogDetail extends RequestLogRecord {
|
||||
user_agent: string | null
|
||||
request_body: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
export interface RequestLogFilters {
|
||||
user_id: number | undefined
|
||||
method: string | undefined
|
||||
path: string
|
||||
status_code: number | undefined
|
||||
created_at_range: [string, string] | null
|
||||
}
|
||||
|
||||
/** ─── 操作日志 ─── */
|
||||
|
||||
export interface OperationLogRecord {
|
||||
id: number
|
||||
user_id: number | null
|
||||
action: string
|
||||
target_type: string
|
||||
target_id: number
|
||||
description: string
|
||||
ip: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface OperationLogDetail extends OperationLogRecord {
|
||||
detail: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
export interface OperationLogFilters {
|
||||
user_id: number | undefined
|
||||
action: string | undefined
|
||||
target_type: string | undefined
|
||||
created_at_range: [string, string] | null
|
||||
}
|
||||
|
||||
/** 业务异常 */
|
||||
export class ApiError extends Error {
|
||||
code: number
|
||||
|
||||
Reference in New Issue
Block a user