Files
fquiz/memory/2026-05-03.md
T
Admin 345860af14 通用三页表格防坍塌
Co-authored-by: multica-agent <github@multica.ai>
2026-05-03 23:00:51 +08:00

568 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Work Log - 修复文件管理页面删除无响应(2026-05-03)
- 背景:
- Issue `FL-174` 反馈“文件管理页面文件删除点了没反应”。
- 前端删除入口位于 `web/src/app/admin/files/page.tsx` 的下拉菜单“更多 -> 删除”。
- 根因:
- 页面使用了 `Modal.confirm` 静态方法触发确认框;在当前 React 19 + Antd 5 组合下,该静态调用在部分页面上下文中可能不稳定,表现为点击删除无确认弹窗、无后续请求。
- 同页面存在一次遗留调用:`setSuccessMessage("")`,对应状态已移除,存在潜在运行时错误风险。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/files/page.tsx`
- 将删除确认弹窗从 `Modal.confirm({...})` 改为 `const { modal } = App.useApp(); modal.confirm({...})`
- 同步补充 `handleDelete` 的依赖项:`[deleteMutation, modal]`
- 删除遗留的 `setSuccessMessage("")` 调用,避免运行时异常影响交互链路。
- 验证:
- 代码路径核对:删除操作仍走原有 `deleteMutation -> /api/v1/admin/files/delete`,仅调整确认框触发方式,不改接口契约。
- Git 提交:`c56f307`(已推送到 `origin/dev`)。
- 风险与影响:
- 影响面仅文件管理页前端交互层。
- 后端接口、权限校验、删除请求参数与刷新逻辑保持不变。
## Work Log - 新增高程数据Cesium预览(2026-05-03
- 背景:
- Issue `FL-178` 需要“新增一个高程数据预览功能,用 Cesium 图渲染”。
- 现有 `/admin/elevation` 仅支持数据集管理与回填任务,不具备高程点位可视化入口。
- 本次改动:
- 后端新增高程预览接口:
- `GET /api/v1/elevation/datasets/{dataset_id}/preview?max_points=1500`
- 文件:`api/app/api/v1/elevation.py`
- 响应:数据集信息 + 预览点位(经纬度/高程)+ 告警信息。
- 后端新增预览 schema 与服务逻辑:
- 文件:`api/app/schemas/elevation.py`
- 新增 `ElevationDatasetPreviewPoint``ElevationDatasetPreviewResponse`
- 文件:`api/app/services/elevation_service.py`
- 新增 `preview_dataset(...)`
- CSV 预览:按步长抽样,避免一次返回全量点。
- IMG/TIF 预览:网格步进抽样,自动过滤 nodata、无效值,并在非 WGS84 时转换到 WGS84 坐标输出。
- 前端新增 Cesium 预览组件与入口:
- 新文件:`web/src/components/elevation-preview-cesium-map.tsx`
- 渲染高程采样点,颜色按高程梯度(低蓝高红),点击点位可查看经纬度与高程。
- 页面接入:`web/src/app/admin/elevation/page.tsx`
- 数据集列表“操作”新增“预览”。
- 点击后拉取预览接口并在弹窗内展示 Cesium 地图。
- 类型补充:`web/src/types/auth.ts`
- 新增预览响应类型定义。
- 结果:
- 已完成提交并推送到 `dev`
- Commit: `8672f4b`
- Message: `新增高程数据Cesium预览功能`
- 风险与影响:
- 预览为采样结果,不等同于全量像元/点集展示;用于可视化核验分布与高程层级,不用于精确统计。
- 栅格数据在大范围/高分辨率场景下,预览点位受 `max_points` 控制(默认 1500),避免接口与前端负载过高。
## Work Log - 高程预览改造为地形网格渲染(2026-05-03)
- 背景:
- 用户反馈“预览应直接基于高程数据展示区域地形高低,与杆塔无关”。
- 旧实现以采样点云为主,语义偏“数据采样校验”,不符合地形预览预期。
- 本次改造:
- 后端预览响应扩展为双模式:
- `preview_mode = point_cloud | terrain_grid`
- 新增 `cells`(网格单元边界 + 高程)字段
- 文件:`api/app/schemas/elevation.py`
- 栅格预览改造为地形网格输出(默认):
- 栅格按步长下采样后输出网格单元边界(WGS84)和单元高程
- 保留 `points` 作为兼容信息,但前端优先用 `cells` 渲染色带
- 告警文案去除“回填/杆塔”语境,改为“预览渲染自动转 WGS84”
- 文件:`api/app/services/elevation_service.py`
- 前端 Cesium 组件改造:
- 栅格数据优先渲染 `rectangle` 地形网格色带(蓝低红高)
- 点云模式作为 CSV/兜底展示
- 文件:`web/src/components/elevation-preview-cesium-map.tsx`
- 预览弹窗文案与模式展示更新:
- 明确显示当前模式“地形网格/点云”
- 页面提示改为“IMG/TIF/TIFF 预览为地形网格高低色带(与杆塔无关)”
- 文件:`web/src/app/admin/elevation/page.tsx`
- 前端类型同步:
- `web/src/types/auth.ts`
- 交付:
- 提交:`556da5c`
- 信息:`改造高程预览为地形网格渲染`
- 已推送到 `origin/dev`
## Work Log - 新增高程预览诊断信息面板(2026-05-03)
- 背景:
- 用户要求在预览弹窗补充“诊断信息”面板,便于快速定位“未提取到有效地形网格”的根因。
- 本次改动:
- 后端预览响应扩展 `diagnostics` 字段:
- 文件:`api/app/schemas/elevation.py`
- 新增模型:`ElevationDatasetPreviewDiagnostics`
- 字段覆盖:
- 源数据信息:`source_crs`、源边界(min/max x/y
- WGS84 边界:`wgs84_bounds_*`
- 采样参数:`target_samples``sampling_step`
- 统计:`scanned_candidates``valid_preview_count`
- 跳过计数:读失败、masked、nodata、非有限值、样本/网格坐标转换失败、越界
- 后端预览逻辑补充诊断采集:
- 文件:`api/app/services/elevation_service.py`
- CSV 模式:返回基础范围与采样统计。
- 栅格模式:返回 CRS/边界(含可转换时的 WGS84 边界)与逐类跳过计数。
- 前端新增诊断面板展示:
- 文件:`web/src/app/admin/elevation/page.tsx`
- 在预览弹窗中新增“诊断信息”卡片(`Descriptions`),展示上述关键字段。
- 前端类型同步:
- 文件:`web/src/types/auth.ts`
- 新增 `ElevationDatasetPreviewDiagnostics` 并挂载到 `ElevationDatasetPreviewResponse.diagnostics`
- 交付:
- 提交:`ba1b83f`rebase 后推送到 `dev` 的提交为 `4b0c7ed`
- 信息:`新增高程预览诊断信息面板`
## Work Log - 高程数据集支持删除(2026-05-03)
- 背景:
- Issue `FL-180` 需要“高程数据集支持删除”。
- 现有高程管理仅支持创建/更新/分析/预览,缺少删除闭环。
- 本次改动:
- 后端新增数据集删除能力:
- 文件:`api/app/services/elevation_service.py`
- 新增 `delete_dataset(db, dataset_id)`
- 数据集不存在返回 `False`
- 存在运行中回填任务时返回 `409`,避免删除过程中任务写入异常;
- 删除前先清理关联 `elevation_apply_job` 记录,再删除数据集;
- 发布 `elevation.dataset.deleted` 主题事件,触发前端数据刷新。
- 后端新增删除接口:
- 文件:`api/app/api/v1/elevation.py`
- 新增 `DELETE /api/v1/elevation/datasets/{dataset_id}`(权限:`elevation.manage`)。
- 前端高程管理页新增删除入口:
- 文件:`web/src/app/admin/elevation/page.tsx`
- 数据集操作列新增“删除”;
- 使用 `App.useApp().modal.confirm` 二次确认;
- 删除成功后提示并刷新数据集/任务列表,同时清理预览弹窗状态。
- 风险与影响:
- 删除数据集会同时删除其关联的回填任务记录(仅记录,不会回滚已写入杆塔的高程值)。
- 若数据集存在运行中任务,接口会拒绝删除并提示先等待任务结束。
## Work Log - 高程数据管理支持批量导入(2026-05-03)
- 背景:
- Issue `FL-182` 要求“高程数据管理要支持批量导入”。
- 现有能力仅支持单条新建数据集,不适合一次导入多条高程数据集元信息。
- 本次改动(最小闭环):
- 后端新增批量导入 API
- 文件:`api/app/api/v1/elevation.py`
- 新增 `POST /api/v1/elevation/datasets/import`(权限:`elevation.manage``multipart/form-data` 上传 CSV)。
- 后端新增批量导入服务逻辑:
- 文件:`api/app/services/elevation_service.py`
- 新增 `import_datasets_from_csv(...)`
- 解析 CSV 行级导入,支持中英文列名:`code/编码``name/名称``mount_code/挂载编码``file_path/文件路径``source/来源``resolution_m/分辨率``notes/备注`
- 复用现有 `create_dataset` 校验(格式识别、文件存在性检查、编码唯一性)。
- 对导入成功的数据集自动触发 `analyze_dataset`,补齐样本数和边界框。
- 返回导入统计(新增/分析/跳过/告警)与成功导入的数据集清单。
- 新增辅助函数:CSV 编码解码、列名取值、分辨率解析校验。
- 后端 schema 扩展:
- 文件:`api/app/schemas/elevation.py`
- 新增 `ElevationDatasetBatchImportResponse`
- 前端高程管理页接入批量导入入口:
- 文件:`web/src/app/admin/elevation/page.tsx`
- 在“高程数据集”卡片右上新增“批量导入”按钮(上传 CSV)。
- 调用 `/api/v1/elevation/datasets/import`,导入后提示统计结果并刷新数据。
- 页面提示文案补充“支持通过批量导入上传数据集元数据 CSV”。
- 前端类型补充:
- 文件:`web/src/types/auth.ts`
- 新增 `ElevationDatasetBatchImportResponse`
- 验证:
- 后端语法编译:`python3 -m compileall api/app` 通过。
- 遵循任务约束,未执行前端构建检查、未安装依赖。
- 风险与影响:
- 批量导入 CSV 仅导入“数据集元信息”,不会上传实际高程文件;文件需先在文件管理中准备到目标挂载路径。
- 单行存在字段/路径/编码问题时按行跳过并返回告警,不会中断整个批次。
## Work Log - 修复 Flower 监控接口 5022026-05-03
- 背景:
- 前端报错:`GET /api/v1/admin/flower/workers?forceRefresh=false 502 (Bad Gateway)`
- `api` 日志显示该接口持续返回 502。
- 根因:
- Flower 代理链路为:`web -> api(/admin/flower/*) -> flower(/api/*)`
- `api` 容器读取 `FLOWER_BASIC_AUTH=admin:change_me`,而 `flower` 容器实际以 `--basic-auth=admin:admin` 运行。
- `api -> flower` 返回 401,后端代理服务按设计映射为 502,最终前端表现为 502。
- 本次改动(最小闭环):
- 文件:`deploy/pro-deploy/compose.yml`
-`api.environment` 增加:
- `FLOWER_BASIC_AUTH: ${FLOWER_BASIC_AUTH}`
- 文件:`deploy/dev-deploy/compose.yml`
- 同步在 `api.environment` 增加:
- `FLOWER_BASIC_AUTH: ${FLOWER_BASIC_AUTH}`
- 文件:`MEMORY.md`
- 增加 Flower 代理鉴权一致性长期口径,要求 `api``flower` 显式使用同一来源凭据。
- 验证:
- 容器内直连验证(现网):
- `http://flower:5555/api/workers?refresh=false` 使用 `admin:change_me` 返回 401。
- 同接口使用 `admin:admin` 返回 200`{}`)。
- 配置校验:
- `deploy/pro-deploy/compose.yml` 已确认包含 `api.environment.FLOWER_BASIC_AUTH`
- 风险与影响:
- 影响范围:仅 Flower 代理鉴权配置注入,不改业务代码与数据。
- 若部署环境仍存在多层 env 覆盖(例如 `.images.env`),需确保最终生效值在 `api``flower` 一致。
## Work Log - 修复 Redis MISCONF 导致 Celery 写入失败(2026-05-03
- 背景:
- Issue `FL-181` 报错:`redis.exceptions.ResponseError: MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk`
- 该错误会触发 Redis 写保护,导致 Celery 控制命令与任务相关写入失败。
- 根因:
- 部署配置使用 `redis-server --appendonly yes`,默认仍启用 RDB 快照。
- 当宿主磁盘/权限导致 RDB 持久化失败时,Redis 默认 `stop-writes-on-bgsave-error=yes` 会拒绝写请求,连带 Celery 报 `kombu.exceptions.OperationalError`
- 本次改动(最小闭环):
- 文件:`deploy/dev-deploy/compose.yml`
- 文件:`deploy/pro-deploy/compose.yml`
- 将 Redis 启动参数调整为:
- `appendonly yes`(保留 AOF 持久化)
- `save ""`(关闭 RDB 快照)
- `stop-writes-on-bgsave-error no`(避免快照异常触发全局写阻断)
- 文件:`.env.example`
- 补充 Redis 持久化策略说明,明确上述运行口径。
- 风险与影响:
- 影响面:仅 Redis 容器启动参数与部署说明。
- 风险:关闭 RDB 后,Redis 数据恢复主要依赖 AOF;当前场景下可避免 Celery 因 RDB 异常整体不可写。
## Work Log - 修复 Worker 监控页未显示已启动容器(2026-05-03)
- 背景:
- Issue `FL-184` 反馈“worker 容器显示启动,但 Worker 监控页面没显示,且预期 worker 启动会自动注册”。
- 当前监控页数据源为 Flower 代理接口(`/api/v1/admin/flower/*`),并非直接读取 `worker_registry` 表。
- 根因:
- 自动注册链路存在 worker 名归一化问题:`heartbeat_sent` 信号 sender 常为 `Heart` 对象,直接 `str(sender)` 可能得到对象描述字符串,导致注册表写入异常 worker_name。
- 监控页默认请求 `forceRefresh=false`,Flower 在冷缓存阶段可能返回空 worker 列表,形成“容器已起但页面为空”的观感。
- 本次改动(最小闭环):
- 文件:`api/app/core/worker_signals.py`
- 增强 worker 名提取逻辑:优先取 `hostname/eventer.hostname/consumer.hostname`,并增加 `name@host` 正则兜底,避免写入对象 repr。
- 文件:`api/app/services/flower_monitor_service.py`
- `build_workers_overview(force_refresh=False)` 增加一次自愈刷新:当 `workers_map` 为空且 `status_map` 非空时,自动补拉 `refresh=true`
- 文件:`web/src/app/admin/workers/page.tsx`
- Worker 列表与单 worker 任务请求均改为 `forceRefresh=true`,页面默认拉取实时数据。
## Work Log - 菜单管理页面表格高度优化(2026-05-03)
- 背景:
- Issue `FL-192` 反馈菜单管理页面表格过高,导致页面整体出现纵向滚动条。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/menus/page.tsx`
- 优化表格滚动高度计算逻辑:
- 保留原有基于视口和表头/分页高度的动态 `scroll.y` 计算;
- 新增页面级溢出修正:若检测到 `document.documentElement.scrollHeight > window.innerHeight`,自动回收对应高度并增加缓冲,确保优先由表格内部滚动承载内容。
- 结果:
- 菜单管理页不再出现整体纵向滚动条,超出内容由表格内部滚动区域承载。
- 提交并推送到 `dev``2fa0fb3`
## Work Log - 菜单管理支持删除(2026-05-03
- 背景:
- Issue `FL-185` 反馈“菜单管理要支持删除”。
- 前端已有删除入口,但后端删除逻辑主要按 legacy 表(`menu` / `role_menu_rela`)执行,在 modern 表结构(`menus` / `role_menus`)下会删除失败。
- 本次改动(最小闭环):
- 文件:`api/app/services/legacy_admin_rbac_service.py`
- `delete_menu` 增加数据源分支:
- legacy:保留原有删除流程(`menu` + `role_menu_rela`);
- modern:新增 `menus` + `role_menus` 删除路径,支持按 `id``code` 解析菜单。
- 新增 `_legacy_menu_table_exists`,通过 `to_regclass('public.menu')` 判断是否走 legacy 分支。
- 扩展 `_get_users_with_menu_access`,支持按 `role_source` 查询 legacy/modern 角色菜单关联,确保删除后权限缓存刷新用户范围正确。
- 保持既有保护规则不变:
- 受保护菜单编码仍禁止删除;
- 存在子菜单时仍禁止删除;
- 删除后继续发布 `admin.menus` 变更事件,前端列表与侧边菜单自动刷新。
- 风险与影响:
- 影响面仅后台菜单删除服务层;菜单新增、编辑、查询与权限模型未改。
- 若目标菜单存在子菜单或在保护名单中,行为仍与历史一致(返回不可删除)。
- 验证:
- 代码路径校对:前端监控页 -> `/api/v1/admin/flower/workers` -> Flower `/api/workers` 代理链路保持不变,仅调整刷新策略与容错。
- 自动注册路径校对:`worker_ready/heartbeat_sent/worker_shutdown` 仍通过 `worker_registry_service` 入库,仅修正 worker 名标准化逻辑。
- 风险与影响:
- 影响面:Worker 监控与 worker_registry 自动注册链路;不涉及业务任务执行逻辑。
- `forceRefresh=true` 会增加 Flower 端查询频次,但当前页面已 5s 轮询,影响可控。
## Work Log - 高程数据集优化(FL-1832026-05-03
- 背景:
- 需求要求高程数据集支持多文件、目录自动生成、增加使用状态、创建后支持批量导入 csv/img/zip,并在导入后自动分析。
- 本次改动:
- 后端模型与兼容:
- 文件:`api/app/models/elevation.py`
- `elevation_dataset` 新增字段:`dataset_dir``usage_status`,并增加 `usage_status` 索引。
- 文件:`api/app/core/database.py`
- 启动兼容逻辑新增 `_ensure_elevation_dataset_column_compatibility()`
- 若缺 `dataset_dir`,自动加列并按 `/elevation/datasets/{code}` 回填;
- 若缺 `usage_status`,自动加列并回填 `idle`
- 数据集创建逻辑改造:
- 文件:`api/app/schemas/elevation.py`
- `ElevationDatasetCreateRequest``file_path` 调整为可选 `file_name`(兼容“先建后传”)。
- `ElevationDatasetSummary` 新增 `dataset_dir``usage_status`
- 文件:`api/app/services/elevation_service.py`
- 数据集目录不再人工填写,固定根目录 `/elevation/datasets`,数据集目录自动为 `/elevation/datasets/{code}`
- 若创建时未给 `file_name`,允许仅创建元数据,不强制校验文件存在。
- 批量元数据导入兼容新旧列:`file_name``file_path`(从 path 自动提取文件名)。
- 批量导入高程数据文件(多文件):
- 文件:`api/app/api/v1/elevation.py`
- 新增接口:`POST /api/v1/elevation/datasets/{dataset_id}/data/import``files[]`)。
- 文件:`api/app/services/elevation_service.py`
- 新增 `import_dataset_data_files(...)`,支持:
- 直接上传:`csv/img/tif/tiff`
- 压缩包:`zip`(解压后仅导入 csv/img/tif/tiff
- 导入文件统一写入数据集目录 `/elevation/datasets/{code}`
- 自动选择优先文件作为当前数据集文件(优先 `img/tif/tiff`,其次 `csv`)。
- 导入后自动调用分析;失败时返回告警,不中断导入结果返回。
- 文件:`api/app/schemas/elevation.py`
- 新增 `ElevationDatasetDataImportResponse`
- 使用状态闭环:
- 文件:`api/app/services/elevation_service.py`
- 新增 `_refresh_dataset_usage_status()`,按任务状态汇总:
- 存在 `pending/running` 任务 => `in_use`
- 否则 => `idle`
- 在任务创建、运行、成功、失败路径同步更新 `usage_status` 并发布刷新事件。
- 前端高程管理页面改造:
- 文件:`web/src/app/admin/elevation/page.tsx`
- 新建数据集弹窗移除手填“挂载编码/文件路径”,改为仅填元数据;
- 列表新增 `dataset_dir``usage_status` 展示;
- 操作列新增“导入数据”,支持多选上传 `csv/img/tif/tiff/zip`
- 导入完成显示“上传数/解压数/可用数/告警数”统计。
- 文件:`web/src/types/auth.ts`
- 同步新增 `dataset_dir``usage_status``ElevationDatasetDataImportResponse` 类型。
- 验证:
- `python3 -m py_compile api/app/services/elevation_service.py api/app/api/v1/elevation.py api/app/schemas/elevation.py api/app/core/database.py api/app/models/elevation.py` 通过。
- 前端 lint 未执行(本环境缺少 `eslint`,命令报 `eslint: command not found`)。
- 风险与影响:
- 导入多个数据文件时,系统会选定一个“当前数据集文件”用于分析/回填(优先栅格),其余文件保留在数据集目录中。
- `usage_status` 依赖任务状态汇总,若历史任务状态异常(例如未正确收尾)可能导致状态滞后,需要运维侧修正任务状态。
## Work Log - 修复容器巡检发现的监控与鉴权兼容问题(2026-05-03)
- 背景:
- 容器巡检发现两类持续异常:
- `GET /api/v1/admin/flower/worker-tasks` 间歇 `502`
- PostgreSQL 持续报 `relation "user_role_rela" does not exist` / `relation "menu" does not exist`
- 同时发现开发 compose 默认脚本指向 `deploy/dev-deploy/.env`,但仓库缺失该文件,导致 `docker compose ...` 命令报 `invalid compose project`
- 根因:
- Flower 侧对 `/api/workers?...&workername=...` 在当前版本会返回 `404 Unknown worker`,即使 `/api/tasks?workername=...``/api/workers?status=true` 正常,后端代理将其映射为 `502`
- 鉴权服务优先走 legacy 表(`user_role_rela/menu/role_menu_rela`),在 modern-only 库(仅 `users/roles/menus/user_roles/role_menus`)下会触发缺表 SQL 错误并回滚。
- dev 部署环境文件命名缺失 `deploy/dev-deploy/.env`
- 本次改动(最小闭环):
- 文件:`api/app/services/flower_monitor_service.py`
- `build_worker_task_overview` 不再调用会 404 的 `workers?workername=...`
- 改为读取 `workers?refresh=...` 全量快照,再本地筛选 worker。
- 文件:`api/app/services/legacy_authz_service.py`
- 新增 `_legacy_table_exists`
- 在 legacy 角色、权限、菜单、菜单授权查询前先判表存在,不存在直接回退空结果,避免持续 SQL 报错。
- 文件:`deploy/dev-deploy/.env`
- 新增默认 env,补齐 `docker:up/down/logs` 脚本依赖的 compose 变量,恢复 dev compose 命令可用性。
- 验证:
- 语法验证:`python3 -m compileall api/app` 通过。
- compose 验证:`docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml config --services` 通过。
- 运行验证(当前 fquiz 容器):
- API 日志中 `/api/v1/admin/flower/worker-tasks` 已连续返回 `200`,未再出现 `502/Unknown worker`
-`get_user_authorization` 触发鉴权路径后,DB 日志窗口内未出现 `user_role_rela/menu does not exist`
- 风险与影响:
- Flower 修复仅调整查询路径,不改变响应 schema 与前端调用方式。
- legacy 鉴权改动是“缺表短路”策略:当 legacy 表不存在时更快回退 modern 逻辑,避免日志噪音和事务回滚开销。
- 新增 `deploy/dev-deploy/.env` 为默认开发口径,若团队有自定义值仍可通过本地覆盖文件管理。
## Work Log - 线路创建“电压等级”改为下拉选(2026-05-03)
- 背景:
- 用户要求将当前系统“创建线路”的电压等级输入改为下拉选择。
- 选项需对齐旧 `fl` 工程 `FormCreateXianLu` 的 14 个预设值。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/power-lines/page.tsx`
- 变更点:
- 线路表单字段由 `voltage_kv: number | null` 调整为 `voltage_level: string | null`(仅前端表单态)。
- 新增旧系统同款 14 个电压等级下拉选项(直流/交流 + 四回路文案)。
- 新增“下拉选项 -> `voltage_kv` 整数”的提交映射,接口仍按现有后端契约提交 `voltage_kv`
- 新增“`voltage_kv` -> 默认下拉选项”的编辑回填映射,保证编辑弹窗可回显。
- 页面“新建/编辑线路”弹窗中的电压输入控件由 `InputNumber` 改为 `Select`
- 验证:
- 执行:`npm run lint -- src/app/admin/power-lines/page.tsx`
- 结果:命中该文件既有 React Hooks 规则问题(`set-state-in-effect``preserve-manual-memoization` 等),本次改动未新增独立报错类型;电压等级改造相关代码可通过语法解析。
- 风险与影响:
- 后端 `Line` 模型当前仅存储 `voltage_kv` 数值,不存“交流/直流/四回路文案”维度,因此:
- `500/800/1000``110/220` 四回路等在持久化后会折叠为同一数值;
- 编辑回显时仅能按默认映射回一个选项(当前优先映射到 `dc_500/dc_800/dc_1000``ac_110/ac_220`)。
## Work Log - 杆塔模型管理闭环与初始化数据兜底(2026-05-03)
- 背景:
- 用户要求在当前系统新增“杆塔模型管理”,并明确要求初始化数据(模型+默认参数+图片)随功能一并落地,不留人工处理。
- 前一版改动已覆盖主链路,但存在两处阻塞:
- 前端 `tower-models` 页面 `Card` 组件类型报错,`tsc` 无法通过;
- 后端老系统默认值解析函数存在作用域错误,可能导致初始化时模型默认参数构建失败。
- 本次修复:
- 文件:`web/src/app/admin/tower-models/page.tsx`
- `Card` 改为使用项目统一封装 `@/components/ui-antd`,消除 Antd `CardInterface` 在 React 19 下的 JSX 类型不兼容。
- 初始化确认弹窗增加 `closable: false``maskClosable: false``keyboard: false`,避免误触关闭导致初始化分支被误走。
- 文件:`api/app/services/tower_model_service.py`
- 修复 `derive_tower_model_default_values_from_legacy_row``default_raw_json` 的缩进/作用域问题:
- 变量改为始终构建,避免在接地电阻有值时出现未定义风险;
- 保证 `raw_json`(含相序、避雷器、几何参数、雷电结果)稳定写入 `tower_model.default_raw_json`
- 验证:
- 后端语法:`python3 -m compileall api/app` 通过。
- 前端类型:`./web/node_modules/.bin/tsc -p web/tsconfig.json --noEmit` 通过。
- 前端生产构建:`npm run build:web` 通过(含 `/admin/tower-models` 页面产物)。
- 风险与影响:
- 影响范围限定在“杆塔模型管理页 + 老系统初始化默认值解析”,未改动既有业务接口契约。
- 初始化导入仍依赖老系统目录存在:
- `fl/执行目录-2025-11-20/Primary/LP_Setting.txt`
- `fl/执行目录-2025-11-20/Primary/LP_GanTa.txt`
- `fl/执行目录-2025-11-20/Models`
- 若运行环境无上述目录,`/api/v1/tower-models/seed/legacy` 将按设计返回 404 提示缺失来源。
## Work Log - 角色管理页面优化(2026-05-03
- 背景:
- Issue `FL-196` 要求优化角色管理页面展示:
- 去掉“共 X 个角色”统计文案;
- 菜单列不要多行,超长需展示数量后省略;
- 表格高度对齐菜单管理页,避免页面出现总线滚动条。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/roles/page.tsx`
- 调整点:
- 删除角色列表顶部“共 X 个角色/匹配 X 个”文案。
- 将“菜单”列由 `Tag` 多行换行展示改为单行文本展示:
- 最多显示前 2 个菜单名;
- 超过 2 个时展示为“前2项 + 等N个...”;
- 保留 `title` 完整文本用于悬浮查看。
- 角色页表格高度参数与菜单管理页对齐:
- `ROLE_TABLE_VIEWPORT_GAP``8` 调整为 `40`
- 分页增加 `style: { marginBottom: 0 }`,减少底部多余留白。
- 风险与影响:
- 影响范围仅 `角色管理` 页面前端展示层,不涉及后端接口与数据结构。
- 菜单列文本改为汇总展示后,可读性更聚焦;完整菜单明细可通过悬浮提示查看。
## Work Log - 菜单管理页面支持删除(2026-05-03)
- 背景:
- Issue `FL-195` 要求“菜单管理页面支持删除”。
- 当前分支后端已具备删除接口与 modern/legacy 删除能力,本次补齐前端交互闭环,确保页面可直接发起删除。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/menus/page.tsx`
- 变更点:
- 删除操作确认交互从行内 `Popconfirm` 调整为 `App.useApp().modal.confirm`,统一与当前项目 React 19 + Antd 交互口径。
- 取消前端硬编码受保护菜单拦截(`PROTECTED_MENU_CODES`),所有行统一展示“删除”按钮;受保护/有子菜单等约束交由后端删除接口统一判定并返回错误提示。
- 删除进行中仅锁定当前行按钮,避免并发重复提交。
- 验证:
- 变更已通过代码路径核对:删除仍走 `/api/v1/admin/menus/{id}` 的既有后端接口。
- 本地未执行前端编译校验:
- `npm --workspace web exec tsc --noEmit --pretty false` 在当前环境报 `EROFS`npm 缓存目录只读)。
- 风险与影响:
- 影响范围仅菜单管理页删除交互,不改后端数据模型与接口契约。
- 删除是否允许由后端统一裁决:受保护菜单或存在子菜单时会返回失败提示,行为与后端规则保持一致。
## Work Log - 系统日志页面优化(2026-05-03
- 背景:
- Issue `FL-197` 要求对 `/admin/syslog` 页面做四项样式优化:
1) 去掉“共 xx 条,当前第 x 页”;2) 去掉说明文案;3) 去掉右上角常见动作提示;
4) 参考菜单管理页面设置表格高度,避免页面出现纵向滚动条。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/syslog/page.tsx`
- 去除卡片右上角 `extra` 的“常见动作”提示。
- 去除卡片内二级说明文案“查看鉴权与会话类审计日志...”
- 去除表格上方“共 xx 条,当前第 x 页 / 刷新中...”信息行(保留分页组件内 `showTotal`)。
- 参考 `/admin/menus` 的实现补齐表格动态高度:
- 新增 `tableScrollY` 状态 + `tableScrollAnchorRef`
- 新增 `updateTableScrollY`,按视口高度与表格非 body 区域动态计算 `scroll.y`
- 监听窗口 `resize` 与容器 `ResizeObserver`,变化时重新计算;
- 表格启用 `scroll={{ x: 980, y: tableScrollY }}`,分页追加 `style: { marginBottom: 0 }`,收敛页面外层纵向滚动。
- 验证:
- 代码核对:四项需求对应文案与布局均已落盘,筛选、分页与查询参数逻辑未改。
- 风险与影响:
- 影响面仅 `/admin/syslog` 前端展示层。
- 由于 `/admin/diary` 目前目录不存在,本次变更仅作用于系统日志页面,不影响其它管理页面。
## Work Log - 用户/角色管理页表格防坍塌(2026-05-03)
- 背景:
- 在菜单管理页完成“筛选少量数据时表格高度不坍塌”后,新增需求要求将同类体验同步到用户管理与角色管理页面。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/users/page.tsx`
- 新增与菜单/角色页一致的表格动态高度计算(`tableScrollY` + `ResizeObserver` + `resize` 监听)。
- 表格滚动由 `scroll={{ x: 1500 }}` 调整为 `scroll={{ x: 1500, y: tableScrollY }}`
- 表格外层新增 `admin-users-table-anchor`,并通过 CSS 变量注入动态 `min-height`
- 分页补齐 `style: { marginBottom: 0 }`,统一底部留白策略。
- 文件:`web/src/app/admin/roles/page.tsx`
- 在已有动态 `scroll.y` 基础上,表格外层新增 `admin-roles-table-anchor`,并注入动态 `min-height` CSS 变量。
- 文件:`web/src/app/globals.css`
- 新增两条局部样式:
- `.admin-users-table-anchor .ant-table-body`
- `.admin-roles-table-anchor .ant-table-body`
- 两者均使用页面注入变量作为 `min-height`,确保筛选后数据较少时表格区域不坍塌。
- 风险与影响:
- 影响范围限定在 `/admin/users``/admin/roles` 页面样式行为,不涉及接口、权限与数据写入链路。
- 样式作用域使用页面专用 class,避免影响其他 AntD 表格。
## Work Log - 系统参数/系统日志/文件管理页表格防坍塌(2026-05-03)
- 背景:
- 在菜单、用户、角色页完成“筛选数据较少时表格高度不坍塌”后,新增需求要求将该体验同步到系统参数、系统日志、文件管理页面。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/system-params/page.tsx`
- 表格外层新增 `admin-system-params-table-anchor`,注入动态 `min-height` 变量。
- 分页补齐 `style: { marginBottom: 0 }`,收敛底部留白。
- 文件:`web/src/app/admin/syslog/page.tsx`
- 表格外层新增 `admin-syslog-table-anchor`,注入动态 `min-height` 变量。
- 文件:`web/src/app/admin/files/page.tsx`
- 新增与其他管理页一致的动态表格高度计算(`tableScrollY` + `ResizeObserver` + `resize` 监听)。
- 表格滚动从 `scroll={{ x: 1100 }}` 调整为 `scroll={{ x: 1100, y: tableScrollY }}`
- 表格外层新增 `admin-files-table-anchor`,注入动态 `min-height` 变量。
- 文件:`web/src/app/globals.css`
- 新增三个局部样式:
- `.admin-system-params-table-anchor .ant-table-body`
- `.admin-syslog-table-anchor .ant-table-body`
- `.admin-files-table-anchor .ant-table-body`
- 三者均使用页面注入变量作为 `min-height`,保证少量数据时表格不坍塌。
- 风险与影响:
- 影响范围限定在上述三页的前端展示层,不涉及接口契约和后端逻辑。
- 样式均使用页面专用作用域,避免对其他页面表格产生副作用。