线路管理塔杆列表支持分页

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
2026-05-01 16:43:21 +08:00
parent ce25a03369
commit b7b0129752
3 changed files with 78 additions and 4 deletions
+9
View File
@@ -992,3 +992,12 @@
- `email` 入库前统一 `trim + lower`,且做唯一性校验; - `email` 入库前统一 `trim + lower`,且做唯一性校验;
- `username` 入库前统一 `trim`,且做唯一性校验; - `username` 入库前统一 `trim`,且做唯一性校验;
- 空字符串视为非法更新(返回失败)。 - 空字符串视为非法更新(返回失败)。
## 线路管理塔杆分页口径(2026-05-01)
- `web/src/app/admin/power-lines/page.tsx` 的“塔杆列表”默认启用服务端分页:
- 默认每页 20 条;
- 请求参数按 `limit/offset` 驱动;
- 总数以接口返回 `total` 为准。
- 筛选条件(关键词/塔型/风险等级)或线路切换时,分页需自动回到第 1 页,避免落在无数据页。
- 地图视图保留大页查询(当前 500 条)用于展示线路点位,不与表格分页参数共用同一页码。
+30
View File
@@ -270,3 +270,33 @@
- 风险与影响: - 风险与影响:
- 影响范围限定在线路管理分布图前端组件,不涉及后端接口与数据结构。 - 影响范围限定在线路管理分布图前端组件,不涉及后端接口与数据结构。
- 缩放比例为相对值(基于当前线路包围球动态计算),不同线路之间 100%/0% 对应的绝对相机高度不同,属于预期行为。 - 缩放比例为相对值(基于当前线路包围球动态计算),不同线路之间 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)避免点位显示回归。
+39 -4
View File
@@ -79,6 +79,9 @@ const TOWER_TYPE_OPTIONS = [
{ value: "耐张", label: "耐张" }, { value: "耐张", label: "耐张" },
] as const; ] as const;
const TOWER_TABLE_DEFAULT_PAGE_SIZE = 20;
const TOWER_MAP_QUERY_LIMIT = 500;
const EMPTY_LINE_FORM: LineFormValues = { const EMPTY_LINE_FORM: LineFormValues = {
code: "", code: "",
name: "", name: "",
@@ -125,6 +128,7 @@ export default function AdminPowerLinesPage() {
const [towerKeyword, setTowerKeyword] = useState(""); const [towerKeyword, setTowerKeyword] = useState("");
const [towerTypeFilter, setTowerTypeFilter] = useState(""); const [towerTypeFilter, setTowerTypeFilter] = useState("");
const [towerRiskFilter, setTowerRiskFilter] = useState(""); const [towerRiskFilter, setTowerRiskFilter] = useState("");
const [towerPagination, setTowerPagination] = useState({ current: 1, pageSize: TOWER_TABLE_DEFAULT_PAGE_SIZE });
const [lineModalOpen, setLineModalOpen] = useState(false); const [lineModalOpen, setLineModalOpen] = useState(false);
const [towerModalOpen, setTowerModalOpen] = useState(false); const [towerModalOpen, setTowerModalOpen] = useState(false);
const [editingLine, setEditingLine] = useState<LineSummary | null>(null); const [editingLine, setEditingLine] = useState<LineSummary | null>(null);
@@ -164,11 +168,24 @@ export default function AdminPowerLinesPage() {
if (towerRiskFilter.trim()) { if (towerRiskFilter.trim()) {
params.set("risk_level", towerRiskFilter.trim()); params.set("risk_level", towerRiskFilter.trim());
} }
params.set("limit", "500"); if (towerViewMode === "table") {
params.set("offset", "0"); 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(); const query = params.toString();
return `/api/v1/lines/${selectedLineId}/towers?${query}`; return `/api/v1/lines/${selectedLineId}/towers?${query}`;
}, [selectedLineId, towerKeyword, towerTypeFilter, towerRiskFilter]); }, [
selectedLineId,
towerKeyword,
towerTypeFilter,
towerRiskFilter,
towerViewMode,
towerPagination.current,
towerPagination.pageSize,
]);
const linesQuery = useQuery({ const linesQuery = useQuery({
queryKey: [lineListPath], queryKey: [lineListPath],
@@ -237,6 +254,15 @@ export default function AdminPowerLinesPage() {
} }
}, [lines, selectedLineId]); }, [lines, selectedLineId]);
useEffect(() => {
setTowerPagination((prev) => {
if (prev.current === 1) {
return prev;
}
return { ...prev, current: 1 };
});
}, [selectedLineId, towerKeyword, towerTypeFilter, towerRiskFilter]);
const saveLineMutation = useMutation({ const saveLineMutation = useMutation({
mutationFn: async (values: LineFormValues) => { mutationFn: async (values: LineFormValues) => {
if (!canLineManage) { if (!canLineManage) {
@@ -817,7 +843,16 @@ export default function AdminPowerLinesPage() {
columns={towerColumns} columns={towerColumns}
dataSource={towers} dataSource={towers}
loading={towersQuery.isFetching} 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 }} scroll={{ x: 1520 }}
/> />
</div> </div>