feat(logs): 日志管理增加筛选维度(操作人/角色/请求方法)
- 后端 querySystemLogs 支持 role/method 过滤;新增 distinctRoles/distinctActors - 关键词搜索补充 target_name 匹配 - /api/system-logs 返回 roles 与 actors 供前端下拉 - 前端独立筛选工具条:操作人/角色/动作/方法/结果/日期范围 + 清除筛选 - 结束日期改为当日 23:59:59 含当天
This commit is contained in:
@@ -43,6 +43,8 @@ export interface SystemLogQuery {
|
||||
offset: number;
|
||||
actorId?: string;
|
||||
action?: string;
|
||||
role?: string;
|
||||
method?: string;
|
||||
q?: string;
|
||||
from?: string;
|
||||
to?: string;
|
||||
@@ -58,13 +60,15 @@ export async function querySystemLogs(
|
||||
const params: unknown[] = [];
|
||||
if (opts.actorId !== undefined && opts.actorId !== '') { params.push(opts.actorId); where.push(`actor_id = $${params.length}`); }
|
||||
if (opts.action !== undefined && opts.action !== '') { params.push(opts.action); where.push(`action = $${params.length}`); }
|
||||
if (opts.role !== undefined && opts.role !== '') { params.push(opts.role); where.push(`role = $${params.length}`); }
|
||||
if (opts.method !== undefined && opts.method !== '') { params.push(opts.method); where.push(`method = $${params.length}`); }
|
||||
if (opts.success !== undefined) { params.push(opts.success); where.push(`success = $${params.length}`); }
|
||||
if (opts.from !== undefined && opts.from !== '') { params.push(opts.from); where.push(`ts >= $${params.length}`); }
|
||||
if (opts.to !== undefined && opts.to !== '') { params.push(opts.to); where.push(`ts <= $${params.length}`); }
|
||||
if (opts.q !== undefined && opts.q.trim() !== '') {
|
||||
params.push(`%${opts.q.trim()}%`);
|
||||
const i = params.length;
|
||||
where.push(`(path ILIKE $${i} OR actor_name ILIKE $${i} OR action ILIKE $${i} OR target_id ILIKE $${i})`);
|
||||
where.push(`(path ILIKE $${i} OR actor_name ILIKE $${i} OR action ILIKE $${i} OR target_id ILIKE $${i} OR target_name ILIKE $${i})`);
|
||||
}
|
||||
const whereSql = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
|
||||
|
||||
@@ -105,3 +109,20 @@ export async function distinctActions(pool: pg.Pool): Promise<string[]> {
|
||||
const res = await pool.query('SELECT DISTINCT action FROM system_logs ORDER BY action');
|
||||
return (res.rows as Array<{ action: string }>).map((r) => String(r.action));
|
||||
}
|
||||
|
||||
/** 已出现过的角色(供筛选下拉)。 */
|
||||
export async function distinctRoles(pool: pg.Pool): Promise<string[]> {
|
||||
const res = await pool.query("SELECT DISTINCT role FROM system_logs WHERE role IS NOT NULL AND role <> '' ORDER BY role");
|
||||
return (res.rows as Array<{ role: string }>).map((r) => String(r.role));
|
||||
}
|
||||
|
||||
/** 已出现过的操作人(id+姓名,供筛选下拉)。 */
|
||||
export async function distinctActors(pool: pg.Pool): Promise<Array<{ id: string; name: string }>> {
|
||||
const res = await pool.query(
|
||||
"SELECT actor_id, actor_name FROM system_logs WHERE actor_id IS NOT NULL AND actor_name IS NOT NULL GROUP BY actor_id, actor_name ORDER BY actor_name",
|
||||
);
|
||||
return (res.rows as Array<{ actor_id: string; actor_name: string }>).map((r) => ({
|
||||
id: String(r.actor_id),
|
||||
name: String(r.actor_name),
|
||||
}));
|
||||
}
|
||||
|
||||
+13
-3
@@ -77,6 +77,8 @@ import {
|
||||
insertSystemLog,
|
||||
querySystemLogs,
|
||||
distinctActions,
|
||||
distinctRoles,
|
||||
distinctActors,
|
||||
getApprovalConfig,
|
||||
saveApprovalConfig,
|
||||
ensureApprovalConfig,
|
||||
@@ -1425,12 +1427,14 @@ app.delete('/api/users/:id', requireRole('系统管理员'), async (c) => {
|
||||
|
||||
/** 分页查询系统操作日志(系统管理员)。 */
|
||||
app.get('/api/system-logs', requireRole('系统管理员'), async (c) => {
|
||||
if (pool === null) return c.json({ items: [], total: 0, page: 1, pageSize: 20, actions: [] });
|
||||
if (pool === null) return c.json({ items: [], total: 0, page: 1, pageSize: 20, actions: [], roles: [], actors: [] });
|
||||
const page = Math.max(1, Number(c.req.query('page') ?? 1) || 1);
|
||||
const pageSize = Math.max(1, Math.min(Number(c.req.query('pageSize') ?? 20) || 20, 200));
|
||||
const successQ = c.req.query('success');
|
||||
const fActor = c.req.query('actorId');
|
||||
const fAction = c.req.query('action');
|
||||
const fRole = c.req.query('role');
|
||||
const fMethod = c.req.query('method');
|
||||
const fQ = c.req.query('q');
|
||||
const fFrom = c.req.query('from');
|
||||
const fTo = c.req.query('to');
|
||||
@@ -1439,13 +1443,19 @@ app.get('/api/system-logs', requireRole('系统管理员'), async (c) => {
|
||||
offset: (page - 1) * pageSize,
|
||||
...(fActor ? { actorId: fActor } : {}),
|
||||
...(fAction ? { action: fAction } : {}),
|
||||
...(fRole ? { role: fRole } : {}),
|
||||
...(fMethod ? { method: fMethod } : {}),
|
||||
...(fQ ? { q: fQ } : {}),
|
||||
...(fFrom ? { from: fFrom } : {}),
|
||||
...(fTo ? { to: fTo } : {}),
|
||||
...(successQ === 'true' || successQ === 'false' ? { success: successQ === 'true' } : {}),
|
||||
});
|
||||
const actions = await distinctActions(pool).catch(() => []);
|
||||
return c.json({ items, total, page, pageSize, actions });
|
||||
const [actions, roles, actors] = await Promise.all([
|
||||
distinctActions(pool).catch(() => []),
|
||||
distinctRoles(pool).catch(() => []),
|
||||
distinctActors(pool).catch(() => []),
|
||||
]);
|
||||
return c.json({ items, total, page, pageSize, actions, roles, actors });
|
||||
});
|
||||
|
||||
/* ------------------------------------------------------------------ *
|
||||
|
||||
Reference in New Issue
Block a user