Files
lexgo/admin/src/audit-logs.mjs
T

57 lines
2.7 KiB
JavaScript

export const actionLabels = { create: '创建账号', enable: '启用账号', disable: '停用账号', reset_password: '重置密码', update: '更新账号' }
export const reasonLabels = { ok: '完成', invalid_input: '输入无效', invalid_credentials: '账号或密码不正确', rate_limited: '请求过于频繁', forbidden: '无操作权限', not_found: '账号不存在', conflict: '账号冲突', internal_error: '服务异常' }
export function auditQuery(kind, filters = {}) {
if (!['login', 'operation'].includes(kind)) throw new Error('日志类型无效')
const { page = 1, limit = 20, result, action, from, to } = filters
if (!Number.isInteger(page) || page < 1 || !Number.isInteger(limit) || limit < 1 || limit > 100) throw new Error('分页参数无效')
const params = new URLSearchParams({ page, limit })
const username = (filters.username || '').trim().toLowerCase()
if (username) params.set('username', username)
if (result) {
if (!['success', 'failure'].includes(result)) throw new Error('结果筛选无效')
params.set('result', result)
}
if (action) {
if (kind !== 'operation' || !Object.hasOwn(actionLabels, action)) throw new Error('操作筛选无效')
params.set('action', action)
}
for (const [key, value] of [['from', from], ['to', to]]) {
if (!value) continue
const date = new Date(value)
if (Number.isNaN(date.getTime())) throw new Error('请选择有效时间')
params.set(key, date.toISOString())
}
if (from && to && new Date(from) > new Date(to)) throw new Error('开始时间不能晚于结束时间')
return params.toString()
}
// Every page/filter change and session invalidation retires pending responses.
export function createAuditLogLoader(session, state) {
let sequence = 0
function invalidate() {
sequence++
Object.assign(state, { items: [], total: 0, loading: false, error: '' })
}
return {
invalidate,
async load(kind, filters) {
// Keep the page count stable while fetching another page; resetting total
// makes Element Plus clamp the current page to one and issue a new query.
sequence++
Object.assign(state, { items: [], loading: true, error: '' })
const current = sequence
const generation = session.state.generation
const isCurrent = () => current === sequence && generation === session.state.generation
try {
const data = await session.queryAuditLogs(kind, filters)
if (isCurrent()) Object.assign(state, { items: data.items, total: data.total })
} catch (error) {
if (isCurrent()) state.error = error.message
} finally {
if (current === sequence) state.loading = false
}
}
}
}