From b7b012975260dc05ac47d215233542a8518d36fd Mon Sep 17 00:00:00 2001 From: chengkml Date: Fri, 1 May 2026 16:43:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BA=BF=E8=B7=AF=E7=AE=A1=E7=90=86=E5=A1=94?= =?UTF-8?q?=E6=9D=86=E5=88=97=E8=A1=A8=E6=94=AF=E6=8C=81=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: multica-agent --- MEMORY.md | 9 ++++++ memory/2026-05-01.md | 30 ++++++++++++++++++ web/src/app/admin/power-lines/page.tsx | 43 +++++++++++++++++++++++--- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/MEMORY.md b/MEMORY.md index d3692a6..5225460 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -992,3 +992,12 @@ - `email` 入库前统一 `trim + lower`,且做唯一性校验; - `username` 入库前统一 `trim`,且做唯一性校验; - 空字符串视为非法更新(返回失败)。 + +## 线路管理塔杆分页口径(2026-05-01) + +- `web/src/app/admin/power-lines/page.tsx` 的“塔杆列表”默认启用服务端分页: + - 默认每页 20 条; + - 请求参数按 `limit/offset` 驱动; + - 总数以接口返回 `total` 为准。 +- 筛选条件(关键词/塔型/风险等级)或线路切换时,分页需自动回到第 1 页,避免落在无数据页。 +- 地图视图保留大页查询(当前 500 条)用于展示线路点位,不与表格分页参数共用同一页码。 diff --git a/memory/2026-05-01.md b/memory/2026-05-01.md index 578760b..ca9c8e9 100644 --- a/memory/2026-05-01.md +++ b/memory/2026-05-01.md @@ -270,3 +270,33 @@ - 风险与影响: - 影响范围限定在线路管理分布图前端组件,不涉及后端接口与数据结构。 - 缩放比例为相对值(基于当前线路包围球动态计算),不同线路之间 100%/0% 对应的绝对相机高度不同,属于预期行为。 + +## Work Log - 线路管理塔杆列表分页(2026-05-01) + +- 背景: + - Issue `FL-132` 要求“线路管理”的塔杆列表表格支持分页。 + - 现状是前端固定请求 `limit=500` 并关闭表格分页,数据量大时浏览与定位效率较差。 + +- 本次改动(最小闭环): + - 文件:`web/src/app/admin/power-lines/page.tsx` + - 新增塔杆列表分页状态: + - `towerPagination.current`(当前页) + - `towerPagination.pageSize`(每页条数,默认 20) + - 塔杆列表请求参数改为按视图分流: + - 表格视图:`limit=pageSize`,`offset=(current-1)*pageSize` + - 地图视图:保留 `limit=500`(保证地图仍可展示较完整线路点位) + - 表格接入 AntD 分页器: + - 使用接口返回 `total` 驱动总数展示 + - 支持切换每页条数 + - 页码与请求参数联动 + - 新增筛选/线路切换时的页码重置: + - `selectedLineId / towerKeyword / towerTypeFilter / towerRiskFilter` 变化时自动回到第 1 页,避免落在空页。 + +- 验证(未执行编译/构建,遵循任务约束): + - 代码走读确认: + - 后端 `GET /api/v1/lines/{line_id}/towers` 已支持 `limit/offset` 且返回 `total`。 + - 前端分页状态、请求参数、表格分页器三者联动一致。 + +- 风险与影响: + - 影响范围:仅前端 `线路管理 -> 塔杆列表` 视图。 + - 地图视图继续使用大页请求(500)避免点位显示回归。 diff --git a/web/src/app/admin/power-lines/page.tsx b/web/src/app/admin/power-lines/page.tsx index 637af24..a3f3f99 100644 --- a/web/src/app/admin/power-lines/page.tsx +++ b/web/src/app/admin/power-lines/page.tsx @@ -79,6 +79,9 @@ const TOWER_TYPE_OPTIONS = [ { value: "耐张", label: "耐张" }, ] as const; +const TOWER_TABLE_DEFAULT_PAGE_SIZE = 20; +const TOWER_MAP_QUERY_LIMIT = 500; + const EMPTY_LINE_FORM: LineFormValues = { code: "", name: "", @@ -125,6 +128,7 @@ export default function AdminPowerLinesPage() { const [towerKeyword, setTowerKeyword] = useState(""); const [towerTypeFilter, setTowerTypeFilter] = useState(""); const [towerRiskFilter, setTowerRiskFilter] = useState(""); + const [towerPagination, setTowerPagination] = useState({ current: 1, pageSize: TOWER_TABLE_DEFAULT_PAGE_SIZE }); const [lineModalOpen, setLineModalOpen] = useState(false); const [towerModalOpen, setTowerModalOpen] = useState(false); const [editingLine, setEditingLine] = useState(null); @@ -164,11 +168,24 @@ export default function AdminPowerLinesPage() { if (towerRiskFilter.trim()) { params.set("risk_level", towerRiskFilter.trim()); } - params.set("limit", "500"); - params.set("offset", "0"); + if (towerViewMode === "table") { + params.set("limit", String(towerPagination.pageSize)); + params.set("offset", String((towerPagination.current - 1) * towerPagination.pageSize)); + } else { + params.set("limit", String(TOWER_MAP_QUERY_LIMIT)); + params.set("offset", "0"); + } const query = params.toString(); return `/api/v1/lines/${selectedLineId}/towers?${query}`; - }, [selectedLineId, towerKeyword, towerTypeFilter, towerRiskFilter]); + }, [ + selectedLineId, + towerKeyword, + towerTypeFilter, + towerRiskFilter, + towerViewMode, + towerPagination.current, + towerPagination.pageSize, + ]); const linesQuery = useQuery({ queryKey: [lineListPath], @@ -237,6 +254,15 @@ export default function AdminPowerLinesPage() { } }, [lines, selectedLineId]); + useEffect(() => { + setTowerPagination((prev) => { + if (prev.current === 1) { + return prev; + } + return { ...prev, current: 1 }; + }); + }, [selectedLineId, towerKeyword, towerTypeFilter, towerRiskFilter]); + const saveLineMutation = useMutation({ mutationFn: async (values: LineFormValues) => { if (!canLineManage) { @@ -817,7 +843,16 @@ export default function AdminPowerLinesPage() { columns={towerColumns} dataSource={towers} loading={towersQuery.isFetching} - pagination={false} + pagination={{ + current: towerPagination.current, + pageSize: towerPagination.pageSize, + total: towersQuery.data?.total ?? 0, + showSizeChanger: true, + showTotal: (total) => `共 ${total} 条`, + onChange: (page, pageSize) => { + setTowerPagination({ current: page, pageSize }); + }, + }} scroll={{ x: 1520 }} />