Files
fquiz/memory/2026-05-01.md
T
2026-05-01 19:56:54 +08:00

548 lines
30 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 - 修复 API 启动阶段 users 主键列兼容问题(2026-05-01
- 背景:
- 启动报错 `psycopg.errors.UndefinedColumn: column users.user_id does not exist`,触发点在 `seed_defaults -> _seed_permissions` 的关系加载 SQL。
- 当前 ORM 与外键约定统一使用 `users.user_id`,但历史库可能残留 `users.id` 主键列命名。
- 本次改动:
- `api/app/core/database.py`
- 新增 `_ensure_user_pk_column_compatibility()`
-`init_db()` 执行 `Base.metadata.create_all()` 前,针对 PostgreSQL 做一次兼容检查:
-`users` 表存在,且检测到仅有 `id` 而没有 `user_id`,自动执行:`ALTER TABLE users RENAME COLUMN id TO user_id`
- 其余情况不改动(已是 `user_id` 或两者都不存在时直接跳过)。
- 验证:
-`fquiz-api` 容器内执行 `init_db()``init_db_ok`
-`fquiz-api` 容器内执行查询,确认当前数据库 `users` 列包含 `user_id`
- 风险与影响:
- 影响范围:仅 PostgreSQL 且仅触发于“存在 `users.id` 且缺少 `users.user_id`”的历史库。
- 该变更属于启动期一次性 DDL 兼容动作;对已规范为 `users.user_id` 的库无行为变化。
## Work Log - 修复 API 启动时报 users.user_name / users.username 列不一致(2026-05-01
- 背景:
- API 启动阶段在 `seed_defaults -> _seed_permissions` 查询中触发 ORM 关系预加载,SQL 使用了 `users.user_name`,但当前 PostgreSQL `users` 表实际字段为 `username`,导致 `psycopg.errors.UndefinedColumn`,服务启动失败。
- 本次改动(最小闭环):
- 文件:`api/app/core/config.py`
- 新增配置 `user_username_column`(环境变量 `USER_USERNAME_COLUMN`),可选值 `username` / `user_name`,默认 `username`
- 文件:`api/app/models/user.py`
- `User.username` 列改为基于 `settings.user_username_column` 动态映射,兼容两类历史库结构。
- 文件:`docker-compose.yml`
-`api` / `celery-worker` / `celery-beat` 注入 `USER_USERNAME_COLUMN` 环境变量透传。
- 文件:`.env.example`
- 新增 `USER_USERNAME_COLUMN=username` 示例配置。
- 验证:
- `python3 -m py_compile api/app/core/config.py api/app/models/user.py api/app/services/seed_service.py` -> 通过。
- `USER_USERNAME_COLUMN=user_name POSTGRES_PORT=5434 docker compose up -d --no-deps api` -> 启动成功。
- `USER_USERNAME_COLUMN=user_name POSTGRES_PORT=5434 docker compose ps api` -> `Up (healthy)`
- `curl -fsS http://127.0.0.1:8000/health` -> `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`
- 风险与影响:
- 影响面集中在 `User` 模型用户名字段映射。
- 运行环境需明确 `USER_USERNAME_COLUMN` 与目标数据库实际字段一致;配置错误会在启动阶段继续抛 `UndefinedColumn`
## Work Log - GitHub Actions 部署分支切换为 dev2026-05-01
- 背景:
- 当前 workflow 仅监听 `main` push,且 deploy job 条件写死为 `refs/heads/main`,导致 `dev` 推送不触发自动部署。
- 本次改动(最小改动):
- 文件:`.github/workflows/main.yml`
- `on.push.branches``main` 改为 `dev`
- `deploy.if``github.ref == 'refs/heads/main'` 改为 `github.ref == 'refs/heads/dev'`
- 预期行为:
- `git push origin dev`:自动触发构建,并在构建成功后执行 deploy。
- `main` 分支 push:不再触发该 workflow 自动部署链路。
- 风险与影响:
- 生产发布入口从 `main` 切换到 `dev`,需确认团队分支策略已同步。
- `workflow_dispatch` 若在非 `dev` 分支触发,deploy job 会被 `if` 条件跳过。
## Work Log - 修复 docker db 端口 5433 冲突并改为 54342026-05-01
- 背景:
- `docker compose` 启动 `db` 报错:`Bind for 0.0.0.0:5433 failed: port is already allocated`
- 现有默认口径为宿主机映射 `5433->5432`,与本机已占用端口冲突。
- 本次改动(最小闭环):
- 文件:`docker-compose.yml`
- `db.ports` 默认映射从 `${POSTGRES_PORT:-5433}:5432` 改为 `${POSTGRES_PORT:-5434}:5432`
- 文件:`.env.example`
- `POSTGRES_PORT` 默认值从 `5433` 改为 `5434`
- 本机直连 `DB_PORT` 默认值从 `5433` 改为 `5434`
- 文件:`api/app/core/config.py`
- `db_port` 默认值从 `5433` 改为 `5434`,与环境模板和 compose 默认保持一致。
- 文件:`README.md`
- 本地 PostgreSQL 示例端口从 `localhost:5433` 更新为 `localhost:5434`
- 文件:`MEMORY.md`
- 宿主机默认 `POSTGRES_PORT` 与本机直连 `DB_PORT` 长期口径同步更新为 `5434`
- 验证:
- `POSTGRES_PORT=5434 docker compose up -d db` -> `fquiz-db` 启动成功。
- `docker compose ps -a` -> `fquiz-db` 状态 `Up ... (healthy)`
- `docker inspect fquiz-db --format '{{json .HostConfig.PortBindings}}'` -> `5432/tcp` 映射 `HostPort=5434`
- 风险与影响:
- 影响范围:本地/部署侧依赖默认 `5433` 的连接配置需同步为 `5434`,否则会出现连接失败。
- 容器内服务间连接不受影响,仍通过 `db:5432` 通信。
## Work Log - 统一 GitHub 发布默认 PostgreSQL 端口为 54342026-05-01
- 背景:
- 仓库本地 `docker-compose.yml` 默认端口已是 `5434`,但 GitHub Actions 发布脚本内联的 `docker-compose.prod.yml` 与首次生成 `.env` 仍使用 `5433`,存在口径不一致。
- 本次改动(最小改动):
- 文件:`.github/workflows/main.yml`
- 将发布脚本中 `db.ports` 默认映射从 `${POSTGRES_PORT:-5433}:5432` 改为 `${POSTGRES_PORT:-5434}:5432`
- 将首次初始化 `.env` 模板中的 `POSTGRES_PORT=5433` 改为 `POSTGRES_PORT=5434`
- 验证:
- `rg -n "POSTGRES_PORT:-5434|POSTGRES_PORT=5434" .github/workflows/main.yml` 命中两处,未发现 workflow 内 `5433` 残留。
- 风险与影响:
- 影响范围:仅 GitHub 发布脚本默认值,不影响已存在且手工维护的服务器 `.env`
- 若线上环境明确依赖 `5433`,需在服务器 `.env` 显式保留 `POSTGRES_PORT=5433`
## Work Log - 修复 API 启动时报 users.password 列不存在(2026-05-01
- 背景:
- 启动报错 `psycopg.errors.UndefinedColumn: column users.password does not exist`
- 触发点在 `seed_defaults -> _seed_permissions` 的查询过程中,SQLAlchemy 关系预加载 `Role.users` 时会查询 `users` 全字段;当前 ORM 将 `password_hash` 绑定到 `users.password`,但目标库字段为 `password_hash`
- 本次改动(最小闭环):
- 文件:`api/app/core/config.py`
- 新增配置 `user_password_column`(环境变量 `USER_PASSWORD_COLUMN`),可选值 `password` / `password_hash`,默认 `password_hash`
- 文件:`api/app/models/user.py`
- `User.password_hash` 改为基于 `settings.user_password_column` 动态映射,兼容两类历史库结构。
- 文件:`docker-compose.yml`
-`api` / `celery-worker` / `celery-beat` 注入 `USER_PASSWORD_COLUMN` 环境变量透传。
- 文件:`.env.example`
- 新增 `USER_PASSWORD_COLUMN=password_hash` 示例配置。
- 验证:
- `python3 -m py_compile api/app/core/config.py api/app/models/user.py api/app/services/seed_service.py` -> 通过。
- `rg -n "USER_PASSWORD_COLUMN|user_password_column" ...` 命中配置、模型、compose、env 示例,映射链路完整。
- 风险与影响:
- 影响面集中在 `User` 模型密码字段映射。
- 运行环境需确保 `USER_PASSWORD_COLUMN` 与目标数据库实际字段一致;若配置错误,启动阶段仍可能抛 `UndefinedColumn`
## Work Log - 修复 API 启动时报 users.state 列不存在(2026-05-01
- 背景:
- 启动报错 `psycopg.errors.UndefinedColumn: column users.state does not exist`
- 触发点同样在 `seed_defaults -> _seed_permissions` 的关系预加载过程中,ORM 查询 `users` 全字段时固定引用了 `state`,但目标库实际字段为 `status`
- 本次改动(最小闭环):
- 文件:`api/app/core/config.py`
- 新增配置 `user_status_column`(环境变量 `USER_STATUS_COLUMN`),可选值 `status` / `state`,默认 `status`
- 文件:`api/app/models/user.py`
- `User.status` 列改为基于 `settings.user_status_column` 动态映射,兼容两类历史库结构。
- 文件:`docker-compose.yml`
-`api` / `celery-worker` / `celery-beat` 注入 `USER_STATUS_COLUMN` 环境变量透传。
- 文件:`.env.example`
- 新增 `USER_STATUS_COLUMN=status` 示例配置。
- 验证:
- `rg -n "USER_STATUS_COLUMN|user_status_column"` 命中配置、模型、compose、env 示例,映射链路完整。
- `git diff` 检查仅包含本次预期的 4 个文件改动。
- 风险与影响:
- 影响面集中在 `User` 模型状态字段映射。
- 运行环境需确保 `USER_STATUS_COLUMN` 与目标数据库实际字段一致;若配置错误,启动阶段仍可能抛 `UndefinedColumn`
## Work Log - 修复 API 启动时报 users.create_user / users.update_user 列不存在(2026-05-01
- 背景:
- 发布部署日志报错 `psycopg.errors.UndefinedColumn: column users.create_user does not exist`,容器持续重启。
- 触发点在 `init_db -> seed_defaults``Role.users` 关系预加载会查询 `users` 全字段;当历史库缺失 `create_user/update_user` 时,启动阶段直接失败。
- 本次改动(最小闭环):
- 文件:`api/app/core/database.py`
- 新增 `_ensure_user_audit_column_compatibility()` 并在 `init_db()` 中接入(位于 `Base.metadata.create_all()` 前执行)。
- 兼容策略:
- 若存在历史列 `create_by/created_by`,自动重命名为 `create_user`
- 若存在历史列 `update_by/updated_by`,自动重命名为 `update_user`
- 若目标列仍缺失,自动补齐 nullable 列:
- `ALTER TABLE users ADD COLUMN IF NOT EXISTS create_user VARCHAR(64)`
- `ALTER TABLE users ADD COLUMN IF NOT EXISTS update_user VARCHAR(64)`
- 验证:
- `git diff` 检查改动仅落在 `api/app/core/database.py` 与记忆文档。
- 启动期兼容逻辑为 PostgreSQL 定向执行;仅在 `users` 表存在且列不一致时触发 DDL,已对齐环境不会产生变更。
- 风险与影响:
- 影响面限定在 PostgreSQL 的 `users` 表审计字段兼容处理。
- 该兼容动作为启动期一次性 DDL,可能短暂持有 `users` 表 DDL 锁;对已有规范列名的库无行为变化。
## Work Log - 修复 /api/v1/admin/roles 在缺失 user_role 表时返回 5002026-05-01
- 背景:
- 复现路径:登录后调用 `GET /api/v1/admin/roles`,接口返回 `500`
- 根因:`legacy_admin_rbac_service.list_roles` 固定查询 legacy 表 `user_role`,当库仅存在 modern RBAC 表(`roles/user_roles/role_menus`)时触发 `psycopg.errors.UndefinedTable`
- 本次改动(最小闭环):
- 文件:`api/app/services/legacy_admin_rbac_service.py`
- 新增 `user_role` 存在性探测:`_legacy_role_table_exists()`
- `list_roles` 增加双链路读取:
- legacy 存在时保持原有 `user_role + role_menu_rela + menu` 查询;
- legacy 缺失时自动回退 `roles + role_menus + menus + role_permissions + permissions`
- `get_role_by_id``list_role_menu_ids` 同步支持 modern 回退(兼容按 `id``code` 查角色)。
- 新增辅助函数:
- `_load_role_rows(..., role_source=...)`
- `_load_role_permission_codes_map(..., role_source=...)`
- 扩展辅助函数以支持 modern 回退:
- `_load_role_menu_ids_map(..., role_source=...)`
- `_load_menus_map(..., role_source=...)`
- 验证:
- `python3 -m py_compile api/app/services/legacy_admin_rbac_service.py` -> 通过。
- `git push origin HEAD:dev` -> 成功(提交 `2c3ad31`)。
- 风险与影响:
- 影响范围限定在后台角色读取接口(`/api/v1/admin/roles*`)查询链路。
- 对 legacy 表完整的数据库行为保持不变;仅在 `user_role` 缺失时触发 modern 回退逻辑。
## Work Log - 用户管理优化(编辑/检索/分页)(2026-05-01
- 背景:
- Issue `FL-121` 要求用户管理支持:用户信息修改、用户检索、用户表格分页。
- 本次改动(最小闭环):
- 后端 `users` 列表接口增强(检索 + 分页参数联动):
- 文件:`api/app/api/v1/users.py`
- `GET /api/v1/users` 新增查询参数:
- `keyword`:按 `user_id/email/username` 模糊检索
- `status`:按启用/禁用状态过滤
## Work Log - 菜单管理页面表格高度自适应与固定表头(2026-05-01)
- 背景:
- Issue `FL-142` 需要菜单管理页面表格高度随页面自适应,纵向滚动条仅出现在表格内部,并保持表头固定。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/menus/page.tsx`
- 新增动态高度状态与锚点:
- `tableScrollY``tableScrollAnchorRef`
- 常量 `MENU_TABLE_MIN_SCROLL_Y``MENU_TABLE_BOTTOM_RESERVE`
- 新增 `updateTableScrollY()`
- 基于表格锚点 `getBoundingClientRect().top``window.innerHeight` 计算可用高度
- 对高度变化做 2px 阈值抑制,避免频繁抖动重渲染
- 新增监听:
- `window.resize` 触发重算
- `ResizeObserver` 监听锚点尺寸变化(筛选区换行、布局变化)触发重算
- 表格滚动改造:
- `scroll``{ x: 1200 }` 调整为 `{ x: 1200, y: tableScrollY }`
- 让纵向滚动收敛到表格体内,并由 AntD 自动固定表头
- 验证:
- 未执行编译/测试(按任务约束:不做编译检查、不安装依赖)。
- 代码检查确认改动仅涉及菜单管理页单文件逻辑。
- 风险与影响:
- 影响范围仅 `web/src/app/admin/menus/page.tsx` 的表格渲染高度计算逻辑。
- 极端小视口下表格最小高度受 `MENU_TABLE_MIN_SCROLL_Y=220` 限制,避免表格区域塌陷。
## Work Log - 菜单管理页表格高度二次修复(2026-05-01)
- 背景:
- 用户反馈菜单管理页“表格高度还是太高,页面出现了纵向滚动条”。
- 原实现使用固定底部预留常量估算 `scroll.y`,在部分视口和分页高度组合下仍可能偏大。
- 本次改动(最小闭环):
- 文件:`web/src/app/admin/menus/page.tsx`
- 高度计算改为“实时测量”:
- 读取 `.ant-table-wrapper``.ant-table-body` 的真实高度,动态计算 `nonBodyHeight`(表头/分页等非表体高度)。
-`window.innerHeight - anchorTop - topGap - nonBodyHeight - viewportGap` 反推 `scroll.y`,避免固定常量误差。
- 兜底策略:
- 保留 `MENU_TABLE_FALLBACK_RESERVE` 作为初始/异常场景的回退计算。
- 最小高度下限调整为 `MENU_TABLE_MIN_SCROLL_Y=180`,减少小屏溢出概率。
- 渲染细节:
- 表格顶部间距从 `Table className mt-4` 调整到锚点容器 `className=\"mt-4\"`,避免 margin 参与高度计算时产生偏差。
- 触发重算条件补充:
-`filteredMenus.length``loading` 变化时同步重算,覆盖分页和筛选引发的高度变化。
- 验证:
- 未执行编译/测试(按任务约束:不做编译检查、不安装依赖)。
- 代码检查确认改动仅涉及菜单页面单文件高度计算逻辑。
- 风险与影响:
- 影响范围仅 `web/src/app/admin/menus/page.tsx`
- 新逻辑依赖 AntD 现有 DOM 类名(`.ant-table-wrapper` / `.ant-table-body`);若后续升级 AntD 结构变化,需要同步调整选择器。
- 后端用户服务增强:
- 文件:`api/app/services/user_service.py`
- `list_users(...)` 支持 `keyword/status` 条件查询并对 `total` 同步计数。
- `update_user(...)` 支持修改 `email``username`
- 统一 trim/归一化
- 重复值冲突校验
- 空值保护
- 用户更新请求模型补齐:
- 文件:`api/app/schemas/user.py`
- `UserUpdateRequest` 新增可选字段 `email`
- 前端用户管理页增强:
- 文件:`web/src/app/admin/users/page.tsx`
- 新增“用户检索”区:关键字输入 + 状态筛选 + 搜索/重置。
- 用户列表请求改为受查询条件驱动(query key 包含分页/筛选参数)。
- 表格接入分页器(页码、每页条数、总数联动后端)。
- 新增“编辑用户”弹窗,支持修改邮箱/用户名/状态。
- 编辑提交仅传变更字段,避免无效更新。
- 验证(未执行编译/构建,遵循当前任务约束):
- 代码走读与关键路径自检:
- `GET /api/v1/users` -> 支持 `limit/offset/keyword/status`
- `PATCH /api/v1/users/{id}` -> 支持 `email/username/status` 更新。
- 前端列表查询参数与分页状态联动一致。
- 风险与影响:
- 影响范围集中在用户管理模块(`/admin/users``/api/v1/users*`)。
- 旧调用方不传 `keyword/status` 时行为保持兼容。
- 更新失败错误提示文案仍共用“not found or email/username exists”,后续如需更精确错误码可再拆分。
## Work Log - 线路管理分布图加入缩放 Slider 与比例显示(2026-05-01
- 背景:
- Issue `FL-131` 要求“线路管理页面分布图优化:加入 slider 显示缩放比例”。
- 本次改动(最小闭环):
- 文件:`web/src/components/power-line-cesium-map.tsx`
- 新增地图缩放 `Slider`(竖向),置于已有 `+/-/居中` 控件上方。
- 新增“缩放比例 xx%”文本展示。
- 新增缩放比例与相机高度的双向映射函数(对数映射),解决不同尺度下线性感知不均问题。
- 监听 `viewer.camera.changed`,实现鼠标滚轮/按钮缩放时比例实时同步。
- 拖动 Slider 时调用相机 `flyTo` 调整高度,保持当前位置不变,仅修改缩放。
- 新增防抖动状态控制(`sliderChangingRef`)与无效 setState 保护,减少高频相机事件导致的重复渲染。
- 验证:
- 本次遵循任务约束,未执行编译/安装。
- 通过代码走读确认:
- `+/-` 按钮、鼠标滚轮、居中重置都会同步刷新缩放比例。
- Slider 拖动可直接驱动地图缩放。
- 风险与影响:
- 影响范围限定在线路管理分布图前端组件,不涉及后端接口与数据结构。
- 缩放比例为相对值(基于当前线路包围球动态计算),不同线路之间 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)避免点位显示回归。
## Work Log - 线路管理分布图移除 Slider2026-05-01
- 背景:
- 用户在 Issue `FL-131` 新评论要求:去掉 slider。
- 本次改动(最小改动):
- 文件:`web/src/components/power-line-cesium-map.tsx`
- 移除右上角竖向缩放 Slider。
- 移除“缩放比例 xx%”文本展示。
- 清理 slider 配套的缩放百分比状态、相机监听与映射函数。
- 保留原有 `+ / - / 居中重置` 缩放按钮能力不变。
- 验证:
- 遵循任务约束,未执行编译检查、未安装依赖。
- 代码走读确认变更范围仅限 slider 相关逻辑。
- 风险与影响:
- 影响范围仅为线路管理分布图控件区 UI 与交互;后端接口和数据结构无影响。
## Work Log - 新增高程数据管理功能(2026-05-01)
- 背景:
- 目标是支撑线路走向图高程渲染,提供“高程数据集管理 + 杆塔高程回填任务”闭环能力。
- 约束:最小改动优先,不引入重型 GDAL 依赖,先落可运行方案。
- 本次改动(最小闭环):
- 后端模型与任务:
- 新增 `api/app/models/elevation.py`
- `elevation_dataset`:存高程数据集元信息(挂载、文件路径、分辨率、样本统计、bbox、状态)。
- `elevation_apply_job`:存线路回填任务(模式、进度统计、状态、错误信息)。
- 新增 `api/app/tasks/elevation_tasks.py`
- Celery 任务 `apply_elevation_for_line_job`,异步执行指定 job。
- `api/app/core/celery_app.py`
- Celery include 扩展:加入 `app.tasks.elevation_tasks`
- 后端 API 与服务:
- 新增 `api/app/schemas/elevation.py`dataset/job 请求与响应模型)。
- 新增 `api/app/services/elevation_service.py`,提供:
- 数据集列表/创建/更新/分析;
- 回填任务列表/详情/创建;
- 回填执行逻辑(最近邻采样 CSV 点,写回 `power_line_tower.altitude_m`)。
- 回填结果写入 `raw_extra_json.elevation`(数据集来源、采样距离、时间)。
- 新增 `api/app/api/v1/elevation.py`
- `GET /api/v1/elevation/datasets`
- `POST /api/v1/elevation/datasets`
- `PATCH /api/v1/elevation/datasets/{dataset_id}`
- `POST /api/v1/elevation/datasets/{dataset_id}/analyze`
- `GET /api/v1/elevation/jobs`
- `GET /api/v1/elevation/jobs/{job_id}`
- `POST /api/v1/elevation/jobs/apply-line`
- `api/app/api/router.py` 注册 elevation 路由。
- `api/app/core/database.py` + `api/app/models/__init__.py` 注册新模型,确保 `init_db` 自动建表。
- 权限/菜单/订阅:
- `api/app/services/seed_service.py`
- 新增权限:`elevation.read` / `elevation.manage`
- 新增后台菜单:`admin.elevation` -> `/admin/elevation`
- admin 默认菜单绑定新增 `admin.elevation`
- `api/app/services/legacy_authz_service.py`
- admin 默认权限加入 elevation 权限。
- `MENU_CODE_PERMISSION_MAP` 增加 `admin.elevation`
- legacy synthetic 菜单补齐 `admin.elevation`
- `api/app/services/topic_registry.py`
- 新增 topic 规则:`admin.elevation`
- `api/app/services/admin_service.py` / `legacy_admin_rbac_service.py`
-`admin.elevation` 设为受保护菜单(不可误删)。
- 前端页面与类型:
- 新增 `web/src/app/admin/elevation/page.tsx`
- 高程数据集管理(创建、分析、列表)。
- 回填任务管理(创建、进度/结果查看)。
- 支持跳转文件管理上传 CSV(复用现有文件系统)。
- `web/src/types/auth.ts` 增加 elevation 相关类型定义。
- `web/src/app/admin/page.tsx` 新增“高程数据管理”卡片入口。
- `web/src/app/admin/menus/page.tsx``admin.elevation` 加入前端受保护菜单编码集合。
- 验证:
- 后端语法编译:
- `python3 -m compileall api/app` -> 通过。
- 前端构建:
- `npm run build:web` -> 通过。
- 构建产物中已包含路由:`/admin/elevation`
- 风险与影响:
- 当前实现使用 CSV 点集“最近邻采样”,适合先跑通管理与回填流程;不是严格栅格插值方案。
- 未引入 GDAL/rasterio,部署更稳,但精度依赖 CSV 样本密度与坐标质量。
- 回填默认允许 `overwrite_all`,存在覆盖人工高程风险;前端默认展示“仅填空(推荐)”。
## Work Log - 高程管理支持 IMG/TIF 导入与回填(2026-05-01
- 背景:
- 用户上传的高程数据为 `.img`(栅格),现有实现仅支持 CSV 点集,无法直接用于高程回填任务。
- 本次改动(最小闭环):
- 后端服务能力扩展(文件格式识别 + 栅格采样):
- 文件:`api/app/services/elevation_service.py`
- 数据集创建时按扩展名自动识别并落库 `file_format`(支持 `.csv/.img/.tif/.tiff`)。
- 新增“按格式分流”执行:
- `csv`:沿用现有最近邻点集采样逻辑。
- `img/tif/tiff`:新增栅格像元采样逻辑,按杆塔经纬度写回 `power_line_tower.altitude_m`
- 新增栅格分析逻辑:
- 从栅格读取 `width/height/bounds` 回写 `sample_count/bbox`
- 对非 WGS84 CRS 增加告警,并在回填时自动执行坐标转换(WGS84 -> 栅格 CRS)。
- 回填溯源扩展:
- `raw_extra_json.elevation.sample_method` 对栅格标记为 `raster_pixel`
- 增加 `sample_distance_source` 字段(CSV 为 `computed`,栅格为 `pixel_lookup`)。
- 依赖补齐:
- 文件:`api/requirements.txt`,新增 `rasterio==1.4.3`
- 文件:`api/pyproject.toml`,新增 `rasterio>=1.4.0,<2.0.0`
- 前端文案更新:
- 文件:`web/src/app/admin/elevation/page.tsx`
- 页面提示更新为支持 `CSV/IMG/TIF/TIFF`,空态与示例路径同步为栅格可用口径。
- 验证:
- `python3 -m compileall api/app` -> 通过。
- `npm run build:web` -> 通过。
- 构建产物包含路由 `/admin/elevation`
- 风险与影响:
- `.img/.tif` 回填依赖 `rasterio`(及底层 GDAL 运行时),部署环境需确保镜像能成功安装该依赖。
- 栅格 bbox 直接来自源栅格 CRS;非经纬度坐标系场景会返回告警,便于识别与后续治理。
## Work Log - 去掉角色权限点与菜单权限码配置(2026-05-01)
- 背景:
- Issue `FL-139` 要求“去掉角色管理的权限点配置,菜单的权限码配置”。
- 本次改动(最小闭环):
- 角色管理页面:`web/src/app/admin/roles/page.tsx`
- 移除权限点配置入口与相关请求链路:
- 移除 `permissions` 状态与 `/api/v1/admin/permissions` 加载请求。
- 新建/编辑角色表单移除 `permission_codes` 字段,仅保留 `code/name/menu_ids`
- 角色更新请求不再提交 `permission_codes`
- 列表展示移除“权限”列,仅展示“角色编码/角色名称/菜单/操作”。
- 搜索口径同步调整为“角色编码、名称、菜单”。
- 菜单管理页面:`web/src/app/admin/menus/page.tsx`
- 移除菜单权限码配置入口:
- 菜单表单移除 `permission_code` 字段。
- 新建/编辑菜单提交 payload 不再包含 `permission_code`
- 列表展示移除“权限码”列。
- 搜索口径移除权限码匹配,关键词仅匹配“编码/名称/路径”。
- 后台首页文案:`web/src/app/admin/page.tsx`
- 角色管理说明改为“配置角色并分配菜单可见范围”。
- 菜单管理说明改为“维护后台导航结构、菜单层级与展示状态”。
- 验证(遵循任务约束,未执行编译检查):
- `git diff` 已确认改动仅涉及上述三个前端文件。
- 代码扫描确认上述页面不再包含 `permission_codes` / `permission_code` 配置与展示逻辑。
- 风险与影响:
- 影响范围限定在前端管理页交互层;后端接口仍保持兼容,可继续返回权限相关字段但前端不再暴露配置入口。
- 若后续需彻底下线该能力(含后端字段/持久化),需单独评估接口契约与历史数据兼容。
## Work Log - 登录页面还原最简洁样式并保留记住密码(2026-05-01)
- 背景:
- Issue `FL-144` 要求将登录页还原为最简洁样式,保留“登录、记住密码”功能,并将标题改为“防雷计算”。
- 本次改动(最小闭环):
- 文件:`web/src/app/page.tsx`
- 去除登录页注册模式相关状态与 UI`mode/register/username/切换按钮`),仅保留登录流程。
- 页面主标题改为 `防雷计算`
- 视觉样式收敛为简洁白底 + 居中卡片布局,移除装饰性图标块、渐变、复杂文案。
- 新增“记住密码”复选框:
- 勾选后登录成功时将用户 ID 与密码写入 `localStorage`
- 未勾选时清理本地缓存;
- 页面加载时若已记住则自动回填账号密码并默认勾选。
- 验证:
- 代码路径自检:登录仍走 `useAuth().login` 既有链路,未改动鉴权接口与路由跳转逻辑。
- 按任务约束未执行编译/安装依赖。
- 风险与影响:
- 影响范围:仅前端登录页 `web/src/app/page.tsx`
- 风险:记住密码当前使用浏览器 `localStorage` 明文存储,存在本机安全暴露风险(符合需求但需知悉)。
## Work Log - 用户管理页面去掉权限列(2026-05-01)
- 背景:
- Issue `FL-145` 要求“用户管理页面去掉权限列”。
- 本次改动(最小改动):
- 文件:`web/src/app/admin/users/page.tsx`
- 在用户列表 `columns` 配置中移除“权限”列(`dataIndex: permission_codes`)及对应渲染逻辑。
- 其余列与用户管理交互(角色分配、状态切换、编辑、重置密码、删除)保持不变。
- 验证:
- 代码走读确认:页面不再渲染权限列,且仅改动单文件单处表格列定义。
- 按任务约束未执行编译/安装依赖。
- 风险与影响:
- 影响范围仅前端用户管理页面展示层,不涉及后端接口与权限模型。