57 lines
2.7 KiB
JavaScript
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
|
|
}
|
|
}
|
|
}
|
|
}
|