diff --git a/memory/2026-06-20.md b/memory/2026-06-20.md index aaa4ff4..957184c 100644 --- a/memory/2026-06-20.md +++ b/memory/2026-06-20.md @@ -327,3 +327,27 @@ - 风险与关注点: - 改动涉及 `GET /api/v1/tower-models` 列表分页契约,未改变响应字段、CRUD 字段、权限码或图片上传/预览接口。 + +## Follow-up - 系统日志筛选交互细节对齐(FL-160) + +- 背景: + - 评审继续指出系统日志页仍保留“查询/重置筛选”按钮,和用户管理页的 500ms 防抖自动搜索模式不一致。 + +- 本次处理: + - 移除系统日志页桌面端和移动端的“查询”“重置筛选”按钮,筛选完全依赖输入框 500ms 防抖自动触发。 + - 移动端保留多个筛选字段的 label,但移除按钮组,并将末尾表单项 `marginBottom` 对齐为 0。 + - 表格 loading 从 `logsQuery.isFetching` 改为 `logsQuery.isLoading`,对齐用户管理页初次加载态口径。 + - 表格分页补齐 `showSizeChanger: true` 与 `[10, 20, 50, 100]`,并让请求 `limit` 跟随分页 pageSize。 + - 表格和移动卡片空态文案统一为“未找到符合筛选条件的日志记录。”。 + +- 验证: + - 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/syslog/page.tsx` 通过,仅用户页存在 1 条既有 unused eslint-disable warning。 + - 基线:`npm --workspace web exec tsc --noEmit --pretty false` 失败,失败点均在既有 `src/app/admin/elevation-records/page.tsx`,与系统日志页无关。 + - 修改后:`npm --workspace web exec eslint src/app/admin/syslog/page.tsx --max-warnings=0` 通过。 + - 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/syslog/page.tsx` 通过,仍仅用户页 1 条既有 warning。 + - 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 仍失败于既有 `src/app/admin/elevation-records/page.tsx`。 + - 修改后:`npm run build:web` 编译通过后在 TypeScript 阶段失败于同一既有 `src/app/admin/elevation-records/page.tsx:91`。 + +- 风险与关注点: + - 改动仅影响 `/admin/syslog` 前端筛选交互、分页展示和空态文案,不改变 `/api/v1/admin/audit-logs` 字段或权限语义。 + - 当前 dev 分支存在 unrelated `elevation-records` TypeScript 错误,会阻断全量 `tsc` 与 `next build`。 diff --git a/web/src/app/admin/syslog/page.tsx b/web/src/app/admin/syslog/page.tsx index 5b82fca..708e781 100644 --- a/web/src/app/admin/syslog/page.tsx +++ b/web/src/app/admin/syslog/page.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { Button, Card, Col, Empty, Form, Input, Row, Space, Spin, Table, Tag, Typography, type CardProps } from "antd"; +import { Card, Col, Empty, Form, Input, Row, Space, Spin, Table, Tag, Typography, type CardProps } from "antd"; import type { ColumnsType } from "antd/es/table"; import type { CSSProperties, ComponentType, RefAttributes } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; @@ -44,6 +44,7 @@ export default function AdminSyslogPage() { const isMobile = useMobileDetection(); const [offset, setOffset] = useState(0); + const [pageSize, setPageSize] = useState(PAGE_SIZE); const [draftFilters, setDraftFilters] = useState(EMPTY_FILTERS); const [filters, setFilters] = useState(EMPTY_FILTERS); const [error, setError] = useState(""); @@ -103,7 +104,7 @@ export default function AdminSyslogPage() { const logsPath = useMemo(() => { const params = new URLSearchParams(); - params.set("limit", String(PAGE_SIZE)); + params.set("limit", String(pageSize)); params.set("offset", String(offset)); if (filters.action.trim()) { params.set("action", filters.action.trim()); @@ -112,7 +113,7 @@ export default function AdminSyslogPage() { params.set("user_id", filters.user_id.trim()); } return `/api/v1/admin/audit-logs?${params.toString()}`; - }, [filters.action, filters.user_id, offset]); + }, [filters.action, filters.user_id, offset, pageSize]); const loadLogs = useCallback(async () => { const response = await fetchWithAuth(logsPath); @@ -139,7 +140,7 @@ export default function AdminSyslogPage() { const total = logsQuery.data?.total ?? 0; const queryError = logsQuery.error instanceof Error ? logsQuery.error.message : ""; const anyError = error || queryError; - const currentPage = Math.floor(offset / PAGE_SIZE) + 1; + const currentPage = Math.floor(offset / pageSize) + 1; useToastFeedback({ errorMessage: anyError, @@ -198,14 +199,14 @@ export default function AdminSyslogPage() { if (loadedCount < total) { setIsLoadingMore(true); setCardViewPage((prev) => prev + 1); - setOffset((prev) => prev + PAGE_SIZE); + setOffset((prev) => prev + pageSize); } } }; cardBody.addEventListener("scroll", handleScroll); return () => cardBody.removeEventListener("scroll", handleScroll); - }, [viewMode, isLoadingMore, logsQuery.isLoading, total, allLoadedLogs.length]); + }, [viewMode, isLoadingMore, logsQuery.isLoading, total, allLoadedLogs.length, pageSize]); // Reset card view state when filters change useEffect(() => { @@ -414,7 +415,7 @@ export default function AdminSyslogPage() { > {viewMode === "card" ? (
- + handleActionChange(event.target.value)} /> - + handleUserIdChange(event.target.value)} /> - - - - - - ) : (
@@ -474,31 +450,6 @@ export default function AdminSyslogPage() { onChange={(event) => handleUserIdChange(event.target.value)} /> - - - - - -
)} @@ -512,21 +463,24 @@ export default function AdminSyslogPage() { rowKey={(record) => String(record.id)} columns={columns} dataSource={logs} - loading={logsQuery.isFetching} + loading={logsQuery.isLoading} tableLayout="fixed" pagination={{ current: currentPage, - pageSize: PAGE_SIZE, + pageSize, total: Math.max(total, 1), - onChange: (page) => setOffset((page - 1) * PAGE_SIZE), - showSizeChanger: false, - showQuickJumper: false, + onChange: (page, nextPageSize) => { + setPageSize(nextPageSize); + setOffset((page - 1) * nextPageSize); + }, + showSizeChanger: true, + pageSizeOptions: [10, 20, 50, 100], showTotal: () => `共 ${total} 条`, hideOnSinglePage: false, style: { marginBottom: 0 }, }} locale={{ - emptyText: , + emptyText: , }} scroll={{ y: tableScrollY }} /> @@ -541,7 +495,7 @@ export default function AdminSyslogPage() {
) : (