Files
fquiz/memory/2026-06-20.md
T
2026-06-20 22:44:44 +08:00

596 lines
45 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 - 菜单管理页面一致性优化(FL-151)
- 背景:
- 菜单管理页需要继续对齐用户管理页的消息反馈、筛选表单、空态与表格滚动配置规范。
- 本次处理:
- 移除菜单管理页对 `App.useApp()` 的依赖,创建、编辑、删除结果统一走 `error` / `success` state + `useToastFeedback`
- 桌面筛选表单项由 Tailwind `min-w-*` 改为与用户管理页一致的 `style={{ width: ... }}`
- 表格空态 `Empty` 属性顺序调整为 `image` 在前、`description` 在后。
- 移除菜单表格 `scroll.x`,仅保留纵向滚动配置,与用户管理页保持一致。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/menus/page.tsx` 通过。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/menus/page.tsx` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 风险与关注点:
- 改动仅影响菜单管理页前端展示与提示机制,不改变菜单接口、字段结构或权限语义。
# Work Log - 登录/注册页暗黑背景适配(FL-221)
- 背景:
- 登录页与注册页都使用 `--fquiz-theme-bg-layout` 作为页面背景,但暗黑主题下该语义变量未显式覆盖,可能在主题 token 初始化前或切换时出现背景色不协调。
- 本次处理:
-`web/src/app/globals.css``:root[data-fquiz-theme="dark"]` 中显式覆盖 `--fquiz-theme-bg-layout`,与现有暗黑主题 shell/elevated 背景 token 保持同一套 `color-mix` 规则。
- 登录页与注册页已复用该语义变量,无需额外修改页面组件。
- 验证:
- 基线:`npm --workspace web run lint` 因既有 Cesium 静态资源与部分页面 lint 问题失败。
- 基线:`npm --workspace web run build` 在生产编译阶段被环境杀死,退出码 137。
- 修改后:`npm --workspace web exec eslint src/app/login/page.tsx src/app/register/page.tsx` 通过,仍有既有 3 条 warning。
- 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 修改后:`git diff --check` 通过。
- 修改后:`graphify update .` 通过。
- 风险与关注点:
- 改动仅影响暗黑主题下依赖 `--fquiz-theme-bg-layout` 的背景色;亮色主题变量链保持不变。
# Work Log - 菜单禁用访问控制修复(FL-220)
- 背景:
- 菜单状态设为 disabled 后,侧边栏依赖 WebSocket 推送刷新,推送丢失时可能继续显示;直接访问对应页面/API 时也缺少菜单状态防护。
- 本次处理:
- 后台 layout 的 `/api/v1/admin/me/menus` 改为 React Query 共享查询,并在 `admin.menus` / `auth` 推送后统一失效刷新。
- 菜单管理页创建、编辑、删除、启用/禁用成功后显式失效 `/api/v1/admin/me/menus`,确保侧边栏立即同步。
- 后台 layout 增加基于启用菜单树的路由 403 防护,当前路径不在可见菜单树时不再渲染页面内容。
- 后端新增菜单路由守卫,将菜单对应 API 前缀映射到菜单 path;命中 disabled/hidden 菜单时直接返回 403。
- 现代菜单树过滤改为 admin 与普通角色都排除 disabled/hidden 菜单。
- 新增 `api/tests/test_menu_route_guard.py` 覆盖禁用菜单隐藏、API 403、启用菜单继续放行、隐藏菜单 403。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/layout.tsx src/app/admin/menus/page.tsx --max-warnings=0` 通过但存在既有 layout `<img>` 与 unused callback warning。
- 基线:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 基线:`python3 -m unittest api.tests.test_seed_defaults_contract api.tests.test_role_pagination_contract` 因本地解释器缺少 SQLAlchemy / PYTHONPATH 不满足失败。
- 修改后:`python3 -m py_compile ...` 覆盖本次改动后端文件与新增测试,通过。
- 修改后:`UV_CACHE_DIR=/tmp/fquiz-uv-cache UV_PYTHON_INSTALL_DIR=/tmp/fquiz-uv-python /home/ck/.local/bin/uv run --python 3.11 --with pytest --with fastapi --with pydantic-settings --with sqlalchemy --with PyJWT --with argon2-cffi --with email-validator --with python-multipart --with psycopg[binary] --with bcrypt --with 'celery[redis]' pytest api/tests/test_menu_route_guard.py` 通过,4 passed,存在既有 SQLAlchemy relationship warning。
- 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/layout.tsx src/app/admin/menus/page.tsx --max-warnings=0` 仍仅有既有 layout `<img>` warning。
- 修改后:`git diff --check` 通过。
- 修改后:`graphify update .` 通过并更新 `graphify-out`
- 风险与关注点:
- 后端菜单路由守卫以明确 API 前缀映射菜单 path;新增菜单页若后续引入独立 API,需要同步补充映射。
- 菜单管理 API 本身未加禁用守卫,保留为恢复入口,避免禁用菜单管理后无法重新启用。
## Follow-up - 菜单管理页 React Query 架构对齐(FL-151
- 背景:
- 评审继续指出菜单管理页仍使用手动 `useState` + `loadMenus` 数据管理,与用户管理页 React Query 架构不一致。
- 本次处理:
- 菜单列表查询改为 `useQuery`,由 `menusQuery` 承接 loading、error、数据与 total。
- 创建、编辑、删除、启用/禁用改为 `useMutation`,并通过 `queryClient.refetchQueries` 刷新菜单数据。
- `activeKeyword` 统一命名为 `searchKeyword`,移除手动 `loading` / `saving` / `menus` / `menuTotal` state。
- 实时订阅改为 `queryClient.invalidateQueries({ queryKey: ["admin.menus"] })`
- 错误反馈改为组合本地错误与 `menusQuery.error` 后交给 `useToastFeedback`
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/menus/page.tsx` 通过。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/menus/page.tsx` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 风险与关注点:
- 改动仅迁移菜单管理页前端数据管理架构,不改变 `/api/v1/admin/menus*` 接口路径、请求字段或权限语义。
## Follow-up - 菜单管理页细节一致性补齐(FL-151)
- 背景:
- 复查继续指出菜单管理页在筛选宽度、移动卡片间距、编辑弹窗标题、导入顺序、表格列类型、状态命名和筛选语义等细节上仍未完全对齐用户管理页。
- 本次处理:
- 菜单页 import 顺序调整为 React Query、Ant Design、Icons、`antd/es/table` 类型、Next Link、React hooks 的顺序。
- 表格列类型改为 `ColumnsType<MenuItem>`,并将 `columns``useMemo` 改为普通常量数组。
- 关键词输入 state 从 `keyword` 改为 `keywordInput`,桌面关键词宽度改为 `260px`
- 状态筛选改为 `undefined` 表示“全部”,对齐用户页的 `statusFilter` 语义。
- 移动端卡片容器移除显式 `mt-4`,对齐用户页间距处理。
- 编辑菜单弹窗标题补充当前菜单名称和 ID;移动端删除确认改为下拉项内联 `Modal.confirm`
- 权限变量定义顺序调整为先 `canManage`,后 `canRead`
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/menus/page.tsx` 通过。
- 基线:`npm --workspace web exec tsc --noEmit` 因既有 `src/app/admin/elevation-records/page.tsx` 类型错误失败,菜单页无报错。
- 修改后:`npm --workspace web exec eslint src/app/admin/menus/page.tsx` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 仍仅因既有 `src/app/admin/elevation-records/page.tsx` 类型错误失败,菜单页无报错。
- 风险与关注点:
- 改动仅涉及菜单管理页前端一致性细节,不改变后端接口、权限判断或菜单 CRUD 请求语义。
# Work Log - 角色管理页对齐用户管理页规范(FL-152)
- 背景:
- 角色管理页需对齐用户管理页的后台列表页布局、移动卡片、操作区换行和反馈规范。
- 本次处理:
- 角色表格操作区改为与用户管理页一致的 `Space wrap`,避免小屏或窄列下按钮挤压。
- 角色移动卡片标题改为名称 + 编码横向信息结构,并补齐“角色编码 / 角色名称 / 菜单”字段网格,视觉和信息密度对齐用户移动卡片。
- 角色菜单多选保留现有接口与字段结构,不改动后端 RBAC 合约。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/roles/page.tsx` 通过,仅用户页存在 1 条既有 unused eslint-disable warning。
- 修改后:`npm --workspace web exec eslint src/app/admin/roles/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/roles/page.tsx` 通过,仍仅用户页 1 条既有 warning。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 风险与关注点:
- 改动仅影响角色管理页前端展示与交互排布,不改变接口路径、请求/响应字段、权限判断或角色 CRUD 语义。
## Follow-up - 角色管理页细节一致性补齐(FL-152)
- 背景:
- 评审继续指出角色管理页在搜索文案、角色编码校验、移动端操作丰富度等方面仍与用户管理页存在细节差异。
- 本次处理:
- 搜索占位文案统一为“按角色编码/名称/菜单搜索”,对齐用户管理页“按...搜索”的表达方式。
- 新建角色表单新增角色编码格式校验、500ms 防抖重复检查和提交前重复检查,复用现有 `/api/v1/admin/roles` 列表接口做精确 code 命中判断。
- 角色移动卡片更多菜单补齐“编辑”和“查看菜单”,删除仍使用 `Modal.confirm`,保持与用户卡片的操作入口组织方式一致。
- 确认角色 schema 仅包含 `code/name/permission_codes/menu_ids`,无 `status` 字段,因此未新增状态筛选器,避免引入未支持的数据模型语义。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/roles/page.tsx` 通过,仅用户页存在 1 条既有 unused eslint-disable warning。
- 修改后:`npm --workspace web exec eslint src/app/admin/roles/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/roles/page.tsx` 通过,仍仅用户页 1 条既有 warning。
- 风险与关注点:
- 角色编码重复检查依赖现有角色列表 keyword 查询做前端预检查;服务端创建接口和数据库唯一约束仍是最终一致性保护。
- 改动仅影响角色管理页前端,不改变后端接口、schema 或权限语义。
# Work Log - 系统参数管理页一致性优化(FL-153)
- 背景:
- 系统参数管理页需要对齐用户管理页的列表布局、权限呈现、移动卡片、反馈校验与分页交互规范。
- 本次处理:
- 系统参数页新建入口改为仅 `system_param.manage` 权限可见,保持只读权限下的页面呈现与实际操作权限一致。
- 表格配置对齐用户管理页:`tableLayout="fixed"`、仅纵向滚动、空态属性顺序、加载态和分页最小 total 处理保持一致。
- 移动卡片状态 Tag 文案与颜色对齐用户管理页,并补齐 card view 数据累积的 `requestAnimationFrame` 时序处理。
- 新建/编辑弹窗补齐 `autoComplete="off"`、字段长度规则、参数键防抖重复检查和提交前重复检查。
- 后端系统参数列表接口补齐 `limit/offset` 查询参数并在 service 层实际分页,修复前端分页参数此前未生效的问题。
- 新增 `api/tests/test_system_param_service.py` 覆盖系统参数列表分页与筛选后分页行为。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/system-params/page.tsx` 通过,仅用户页存在 1 条既有 unused eslint-disable warning。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/system-params/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`python3 -m py_compile api/app/api/v1/system_params.py api/app/services/system_param_service.py api/tests/test_system_param_service.py` 通过。
- 修改后:`UV_PYTHON_INSTALL_DIR=/tmp/fquiz-uv-python uv run --cache-dir /tmp/fquiz-uv-cache --python 3.11 --with fastapi --with pydantic-settings --with sqlalchemy --with PyJWT --with argon2-cffi --with email-validator --with bcrypt -m unittest api.tests.test_system_param_service` 通过。
- 风险与关注点:
- 改动涉及系统参数列表接口分页契约,但不改变请求/响应字段结构、权限码或 CRUD 语义。
- 当前本机 `python3` 为 3.7.9,不满足 `api/pyproject.toml``requires-python >=3.10`;后端单测使用 `uv` 管理的 Python 3.11 环境验证。
# Work Log - 系统消息页面一致性优化(FL-154)
- 背景:
- 系统消息页面需对齐用户管理页的后台列表页布局、动态表格高度、移动卡片视图和无限滚动交互。
- 本次处理:
- 系统消息页补齐表格 body 最小高度 CSS 钩子,动态 `scroll.y` 对应的 CSS 变量现已生效。
- 移动端卡片视图改为与用户管理页一致的容器、空态、卡片视觉和字段网格样式,移除卡片字段内散落的内联间距。
- 移动卡片累积列表改为 `requestAnimationFrame` 内更新,避免 React hooks lint 的同步 effect 更新错误;筛选切换直接重置卡片分页和累积数据。
- 系统消息列表 API 增加可选 `message_type` 查询参数,服务端按类型/未读状态返回匹配 `items``total`,保证移动端无限滚动的 total 与当前筛选一致;`unread_count` 仍保持用户全局未读数。
- 补充系统消息服务层测试覆盖类型筛选后的 total 行为。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/system-messages/page.tsx` 失败,系统消息页存在 2 个 `react-hooks/set-state-in-effect` 既有错误;用户页存在 1 条既有 unused eslint-disable warning。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 基线:`python -m pytest api/tests/test_system_message_service.py api/tests/test_system_message_schema.py` 因系统 `python` 缺少 pytest 无法执行。
- 修改后:`npm --workspace web exec eslint src/app/admin/system-messages/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/system-messages/page.tsx` 通过,仍仅用户页 1 条既有 warning。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`UV_CACHE_DIR=/tmp/fquiz-uv-cache UV_PYTHON_INSTALL_DIR=/tmp/fquiz-uv-python /home/jenkins/.local/bin/uv run --python 3.11 --with pytest --with fastapi --with pydantic-settings --with sqlalchemy --with PyJWT --with argon2-cffi --with email-validator --with python-multipart --with psycopg[binary] pytest api/tests/test_system_message_service.py api/tests/test_system_message_schema.py` 通过,4 passed,存在 1 条既有 SQLAlchemy relationship warning。
- 风险与关注点:
- `/api/v1/system-messages/me` 新增可选 `message_type` 参数,未传参时保持原列表语义;前端不再做本地类型过滤,分页 total 与服务端过滤结果一致。
- 改动影响系统消息列表展示与筛选,不改变创建、删除、标记已读接口字段。
# Work Log - 菜单管理页面最终细节对齐(FL-155)
- 背景:
- 菜单管理页需要补齐启用/禁用 mutation 组织、移动卡片字段列宽和加载完成提示条件三处细节,与用户管理页保持一致。
- 本次处理:
- 菜单启用/禁用移除独立 `updateMenuStatusMutation`,改为复用 `updateMenuMutation` 通过 `PATCH /api/v1/admin/menus/{menuId}` 提交 `{ status }`
- `.admin-menus-menu-card-field` 标签列宽从 `72px` 调整为 `64px`
- 移动卡片“已加载全部”提示条件简化为 `allLoadedMenus.length >= menuTotal && allLoadedMenus.length > 0`
- 验证:
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/menus/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 风险与关注点:
- 改动仅影响菜单管理页前端数据 mutation 组织和移动端展示条件,不改变接口路径、请求/响应字段或权限语义。
# Work Log - Worker监控页面一致性优化(FL-157)
- 背景:
- Worker监控页需对齐用户管理页的后台列表页外层卡片、筛选表单、表格空态、移动端卡片和反馈规范。
- 本次处理:
- Worker监控页外层容器改为与用户管理页一致的 `page-card` flex 布局,筛选项改为固定宽度表单项,自动刷新与刷新操作收口到标题右侧。
- 桌面表格对齐用户页:启用 `tableLayout="fixed"`、统一 loading / pagination / Empty 写法,仅保留纵向动态滚动。
- 新增移动端卡片视图,按用户页卡片规范展示执行节点、状态、队列、并发/预取、任务统计、累计处理、注册任务和最近心跳。
- 错误反馈改为 `useToastFeedback`,并复用任务监控展示工具统一任务状态、来源、队列名、运行时长和 Flower 错误文案。
- Worker 任务明细抽屉保留原有分组和数据来源,仅统一表头文案、任务标签和空态。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/workers/page.tsx` 通过,仅用户页存在 1 条既有 unused eslint-disable warning。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/workers/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 风险与关注点:
- 改动仅影响 `/admin/workers` 前端展示与交互排布,不改变 Flower 代理接口路径、请求/响应字段或 `celery.read/celery.manage` 权限语义。
## Follow-up - Worker监控移动卡片间距对齐(FL-157)
- 背景:
- 复审指出 `.admin-workers-card-view``.admin-users-card-view` 多了 `margin-top: 16px`,导致移动端卡片视图顶部间距不一致。
- 本次处理:
- 删除 `.admin-workers-card-view``margin-top: 16px`,使 Worker 监控移动端卡片容器与用户管理页完全一致。
- 验证:
- 修改后:`git diff --check` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/workers/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/workers/page.tsx` 通过,仍仅用户页 1 条既有 unused eslint-disable warning。
- 修改后:`npm --workspace web exec tsc --noEmit` 未通过;失败均来自当前 `dev` 上未改动的 `src/app/admin/elevation-records/page.tsx` 类型错误,与本次 CSS 间距修复无关。
- 风险与关注点:
- 改动仅移除 Worker 监控移动卡片容器的额外顶部间距,不影响接口、权限、表格、抽屉或数据筛选逻辑。
# Work Log - 高程文件记录服务导入修复(FL-213)
- 背景:
- API 容器启动时报 `elevation_file_record_service` 无法从 `elevation_service` 导入 `_build_dataset_or_400`,导致容器反复重启。
- 本次处理:
- 移除 `api/app/services/elevation_file_record_service.py` 中未使用且不存在的 `_build_dataset_or_400` 导入。
- 新增 `api/tests/test_elevation_file_record_service_imports.py`,用 AST 检查 `elevation_file_record_service``elevation_service` 导入的符号均在目标模块作用域存在,防止同类启动期 ImportError 回归。
- 验证:
- 基线:`PYTHONPATH=api python3 -c 'from app.services import elevation_file_record_service'` 因本地未安装 `sqlalchemy` 提前失败;随后使用 `uv` 准备完整 API 依赖时耗时过长,未作为有效基线。
- 修改后:`python3 -m unittest api.tests.test_elevation_file_record_service_imports` 通过。
- 修改后:`python3 -m py_compile api/app/services/elevation_file_record_service.py api/app/services/elevation_service.py api/tests/test_elevation_file_record_service_imports.py` 通过。
- 修改后:`git diff --check` 通过。
- 风险与关注点:
- 改动仅删除未使用导入并补充静态回归测试,不改变高程文件记录接口、任务派发、分析或地形瓦片生成逻辑。
# Work Log - 任务监控页面一致性优化(FL-156)
- 背景:
- 任务监控页需要按用户管理页的后台列表页规范补齐布局、筛选、反馈、空态、表格和移动端呈现一致性。
- 本次处理:
- 任务监控页接入 `useMobileDetection`,桌面保留表格视图,移动端切换为与用户管理页一致的卡片视图和字段网格。
- 错误提示由页面内 `Alert` 改为 `useToastFeedback`,对齐用户管理页的消息反馈方式。
- 桌面筛选表单项由 Tailwind `min-w-*` 改为固定 `style={{ width: ... }}`,并保持移动端纵向筛选。
- 表格配置补齐 `tableLayout="fixed"`、loading、统一空态属性顺序,并移除强制横向滚动,继续使用动态纵向滚动高度。
- 全局样式补齐任务监控页面卡片、移动卡片、暗色主题和字段列宽规范,与用户管理页保持一致。
- 补齐 `web` workspace 的 Linux arm64 Tailwind/lightningcss 原生可选依赖锁定,并同步 `web/package-lock.json`,修复当前 arm64 环境下 `npm run build:web` 缺少 `lightningcss.linux-arm64-gnu.node` 的构建问题。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/task-monitor/page.tsx` 通过,仅用户页存在 1 条既有 unused eslint-disable warning。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 基线:`node --experimental-strip-types web/src/lib/task-monitor-display.test.js` 通过,4 passed,存在既有 MODULE_TYPELESS_PACKAGE_JSON warning。
- 修改后:`npm --workspace web exec eslint src/app/admin/task-monitor/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`node --experimental-strip-types web/src/lib/task-monitor-display.test.js` 通过,4 passed,仍存在既有 MODULE_TYPELESS_PACKAGE_JSON warning。
- 修改后:`npm run build:web` 通过;过程中仍有既有 Next workspace root / middleware deprecation warning。
- 风险与关注点:
- 改动仅影响任务监控页前端展示、筛选布局、错误反馈和移动端呈现,不改变 `/api/v1/admin/flower/*` 接口路径、请求/响应字段或权限语义。
- `web/package-lock.json` 此次同步了 `web/package.json` 已有依赖条目,变动较大但不改变业务代码。
## Follow-up - 任务监控页分页和空态细节对齐(FL-156)
- 背景:
- 复核发现任务监控页表格分页、移动卡片顶部间距和筛选空态文案仍与用户管理页存在细节差异。
- 本次处理:
- 任务监控页新增与用户管理页一致的表格分页 state,默认 `pageSize` 调整为 20,并补齐 `current``total``onChange`
- 表格分页选项改为 `[10, 20, 50, 100]``showTotal` 改为读取筛选后的任务总数。
- 筛选项变更和重置筛选时将表格分页复位到第一页。
- 移除 `.admin-task-monitor-card-view``margin-top: 16px`,与 `.admin-users-card-view` 对齐。
- 表格和卡片筛选空态文案统一为“未找到符合筛选条件的任务。”。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/task-monitor/page.tsx --max-warnings=0` 通过。
- 基线:`npm --workspace web exec tsc --noEmit` 失败于既有 `src/app/admin/elevation-records/page.tsx` 类型错误。
- 修改后:`npm --workspace web exec eslint src/app/admin/task-monitor/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/task-monitor/page.tsx` 通过,仍仅用户页 1 条既有 unused eslint-disable warning。
- 修改后:`node --experimental-strip-types web/src/lib/task-monitor-display.test.js` 通过,4 passed,仍有既有 MODULE_TYPELESS_PACKAGE_JSON warning。
- 修改后:`npm run build:web` 编译通过但类型检查失败,失败点仍为既有 `src/app/admin/elevation-records/page.tsx``useAuth().api` 等类型错误。
- 风险与关注点:
- 改动仅影响任务监控页前端分页、筛选复位、空态文案和卡片间距,不改变接口、权限或任务数据转换逻辑。
# Work Log - ATP 模型管理页面一致性优化(FL-158)
- 背景:
- ATP 模型管理页需要对齐用户管理页的反馈机制、表格分页、移动卡片和操作入口规范。
- 本次处理:
- ATP 模型页移除 `App.useApp()` 与页面内 `Alert`,统一改为 `error/success` state + `useToastFeedback`
- ATP 资产列表接口补齐 `limit/offset` 查询参数,服务层在筛选后分页并保持 `total` 为当前筛选总数。
- ATP 资产服务补齐 `arrester_config` 的创建、更新与序列化,保证页面必填字段能被持久化和回显。
- 表格对齐用户管理页:`tableLayout="fixed"`、仅纵向滚动、服务端分页、空态文案、状态 Tag 展示和操作列宽度。
- 移动端卡片对齐用户管理页:搜索表单布局、卡片标题状态、右上角编辑/更多菜单、字段网格、累积加载与已加载全部提示。
- 新增 `test_list_assets_paginates_after_filtering` 覆盖 ATP 资产列表筛选后分页行为。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/atp-models/page.tsx` 通过,仅存在用户页 1 条既有 unused eslint-disable warningATP 页有 6 条既有 warning。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 基线:`python3 -m py_compile api/app/api/v1/atp_assets.py api/app/services/atp_asset_service.py api/tests/test_atp_asset_service.py` 通过。
- 基线:`python3 -m pytest api/tests/test_atp_asset_service.py` 因系统 Python 缺少 `fastapi` 无法收集测试。
- 修改后:`npm --workspace web exec eslint src/app/admin/atp-models/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`python3 -m py_compile api/app/api/v1/atp_assets.py api/app/services/atp_asset_service.py api/tests/test_atp_asset_service.py` 通过。
- 修改后:`UV_CACHE_DIR=/tmp/fquiz-uv-cache UV_PYTHON_INSTALL_DIR=/tmp/fquiz-uv-python /home/jenkins/.local/bin/uv run --python 3.11 --with pytest --with fastapi --with pydantic-settings --with sqlalchemy --with PyJWT --with argon2-cffi --with email-validator --with python-multipart --with psycopg[binary] pytest api/tests/test_atp_asset_service.py` 通过,5 passed,存在 1 条既有 SQLAlchemy relationship warning。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/atp-models/page.tsx` 通过,仍仅用户页 1 条既有 warning。
- 风险与关注点:
- `/api/v1/atp/assets` 新增可选 `limit/offset` 参数;未传参默认返回前 50 条,响应字段不变。
- ATP 资产创建/更新现在会按既有 schema 持久化 `arrester_config`,修复此前前端提交但服务层丢弃该字段的问题。
- 改动不改变 ATP 模型删除、版本、运行接口字段或权限语义。
## Follow-up - 角色管理页弹窗与分页细节对齐(FL-152)
- 背景:
- 评审继续指出角色管理页 Modal 宽度、分页 total 处理方式仍与用户管理页存在可消除的实现差异。
- 本次处理:
- 移除角色管理页 Modal 的 `width={760}`,恢复 AntD 默认宽度,与用户管理页弹窗保持一致。
- 角色表格分页 `total` 改为 `Math.max(rolesQuery.data?.roles_total ?? 0, 1)``showTotal` 改为读取查询 total,与用户管理页现有实现一致。
- 复核角色卡片下拉菜单顺序,当前为“查看菜单 → 删除”,删除已在最后,无需额外调整。
- 验证:
- 修改后:`npm --workspace web exec eslint src/app/admin/roles/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/roles/page.tsx` 通过,仍仅用户页 1 条既有 unused eslint-disable warning。
- 风险与关注点:
- 改动仅影响角色管理页前端弹窗尺寸和分页展示逻辑,不改变接口、schema、权限或 CRUD 语义。
# Work Log - 系统日志页面一致性优化(FL-160)
- 背景:
- 系统日志页面需要严格对齐用户管理页的页面外层卡片、筛选表单、表格滚动和移动端卡片规范。
- 本次处理:
- 系统日志页外层容器改为与用户管理页一致的 `min-h-0 flex-1` 页面结构,并补齐 `.admin-syslog-page-card` flex 布局样式。
- 桌面筛选表单项由 Tailwind `min-w-*` 改为固定 `style={{ width: 260 }}`,与用户管理页筛选布局口径一致。
- 表格配置补齐 `tableLayout="fixed"`、分页最小 total 处理,并移除横向滚动,仅保留动态纵向滚动。
- 移动端日志卡片补齐与用户卡片一致的卡片头、标题信息、字段网格、详情省略提示和卡片头部主题样式。
- 验证:
- 基线:`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` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/syslog/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/syslog/page.tsx` 通过,仍仅用户页 1 条既有 warning。
- 风险与关注点:
- 改动仅影响 `/admin/syslog` 前端展示、筛选排布、表格滚动和移动卡片视觉,不改变 `/api/v1/admin/audit-logs` 接口路径、请求/响应字段或权限语义。
# Work Log - 杆塔模型管理页面一致性优化(FL-159)
- 背景:
- 杆塔模型管理页需要对齐用户管理页的列表布局、筛选分页、反馈提示、移动卡片和表格滚动规范。
- 本次处理:
- 杆塔模型列表接口补齐 `limit/offset` 查询参数,service 层按筛选条件统计 `total` 后再分页返回 `items`
- 前端 `/admin/tower-models` 列表请求改为由关键词、状态筛选和分页状态共同驱动,移动端无限滚动改为服务端分页累积数据。
- 成功/失败提示统一走 `success/error` state + `useToastFeedback`,移除页面内直接调用 `App.useApp().message` 的分散反馈方式。
- 表格对齐用户管理页:`tableLayout="fixed"`、仅纵向滚动、180px 最小表格体高度、操作区 `Space wrap`、状态 Tag 颜色统一为 `green/default`
- 移动卡片字段列宽从 `72px` 调整为 `64px`,模型图片预览缩略图切换为 AntD `Image` 包装以消除页面级 `<img>` lint 警告。
- 新增 `api/tests/test_tower_model_service.py` 覆盖杆塔模型列表分页与筛选后分页行为。
- 为通过全量 Next build 类型门禁,同步补齐后台页面 AntD `Card` 包装组件的 ref 类型,并修正线路参数页少量 JSX 展示值类型。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/tower-models/page.tsx` 通过,存在用户页 1 条既有 unused eslint-disable warning 与塔模型页 1 条既有 no-img-element warning。
- 基线:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/tower-models/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/tower-models/page.tsx` 通过,仍仅用户页 1 条既有 warning。
- 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 修改后:`UV_CACHE_DIR=/tmp/fquiz-uv-cache UV_PYTHON_INSTALL_DIR=/tmp/fquiz-uv-python /home/jenkins/.local/bin/uv run --python 3.11 --with fastapi --with pydantic-settings --with sqlalchemy --with PyJWT --with argon2-cffi --with email-validator --with python-multipart --with psycopg[binary] -m unittest api.tests.test_tower_model_service` 通过,存在 1 条既有 SQLAlchemy relationship warning。
- 修改后:`npm run build:web` 通过,仍输出既有 multiple lockfiles 与 middleware/proxy 迁移提示。
- 风险与关注点:
- 改动涉及 `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`
## Follow-up - 系统参数状态修改交互对齐(FL-153)
- 背景:
- 复核指出系统参数页状态修改仍在编辑弹窗内完成,而用户管理页状态修改通过行内 Dropdown 独立完成。
- 本次处理:
- 系统参数编辑弹窗移除“状态”字段,编辑保存仅更新参数名称、参数值和说明。
- 表格行与移动卡片的更多菜单补齐“启用/禁用”独立操作,状态切换走单独 PATCH 请求和行级 loading。
- 新建参数仍默认创建为 `enabled`,保持原创建语义不变。
- 验证:
- 修改后:`npm --workspace web exec eslint src/app/admin/system-params/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 风险与关注点:
- 改动仅影响系统参数页前端交互组织方式,不改变后端接口字段、权限码或参数状态语义。
# Work Log - 高程文件记录页构建修复(FL-212)
- 背景:
- CI 在 `web/src/app/admin/elevation-records/page.tsx` TypeScript 阶段失败,原因是页面仍按旧接口读取 `useAuth().api`
- 本次处理:
- 高程文件记录页请求链路改为使用当前 `AuthContextValue` 暴露的 `fetchWithAuth`
- 将高程记录、线路列表、上传、删除、分析、地形生成、回填和预览请求统一对齐 `/api/v1/...` 路径。
- 补齐页面内响应类型、错误处理 helper,并修正同页残留的 AntD `Card` / `Select.Option` / Cesium 预览 props 类型问题。
- 验证:
- 基线:`npm run build:web` 复现失败,错误为 `Property 'api' does not exist on type 'AuthContextValue'`
- 修改后:`npm --workspace web exec eslint src/app/admin/elevation-records/page.tsx --max-warnings=0` 通过。
- 修改后:`npm run build:web` 通过,仍仅输出既有 multiple lockfiles 与 middleware/proxy 迁移提示。
- 风险与关注点:
- 改动仅影响 `/admin/elevation-records` 前端请求与类型适配,不改变后端接口字段、权限码或数据模型。
## Follow-up - 角色管理页分页交互与 effect 顺序对齐(FL-152
- 背景:
- 评审继续指出角色管理页表格分页 `onChange` 混入卡片视图状态更新,且清理 effect 顺序与用户管理页不同。
- 本次处理:
- 表格分页 `onChange` 仅保留 `setPagination({ current: page, pageSize })`,移除 `setCardViewPage(page)``setAllLoadedRoles([])`,避免表格分页触发卡片视图状态更新。
- 将角色页 timeout cleanup effect 移到 resize/ResizeObserver effect 之前,对齐用户管理页 hook 排列。
- 复核角色卡片更多菜单,当前仍为“查看菜单 → 删除”,删除已位于最后,无需改动。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/roles/page.tsx` 通过,仅用户页 1 条既有 unused eslint-disable warning。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/roles/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/users/page.tsx src/app/admin/roles/page.tsx` 通过,仍仅用户页 1 条既有 unused eslint-disable warning。
- 风险与关注点:
- 改动仅影响角色管理页前端表格分页回调和 hook 组织顺序,不改变接口、schema、权限或 CRUD 语义。
## Follow-up - 任务监控页移动端无限滚动对齐(FL-156)
- 背景:
- 复核指出任务监控页移动端卡片一次性渲染全部筛选任务,缺少与用户管理页一致的卡片分页累积、滚动加载和加载更多状态。
- 本次处理:
- 任务监控页补齐 `cardViewPage``allLoadedTasks``isLoadingMore``pageCardRef`,与用户管理页移动卡片基础设施对齐。
- 移动端卡片视图改为按当前 pageSize 分页累积渲染,滚动到卡片容器底部时自动追加下一页。
- 卡片视图补齐“加载更多...”指示器,并仅在已加载全部筛选任务时显示“已加载全部 X 条数据”。
- 筛选条件变更和重置筛选时同步重置表格分页、卡片页码、累积任务和加载更多状态。
- 移动端筛选 `Form.Item``marginBottom` 统一调整为 0,对齐用户管理页表单样式口径。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/task-monitor/page.tsx --max-warnings=0` 通过。
- 基线:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/task-monitor/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit` 通过。
- 修改后:`node --experimental-strip-types web/src/lib/task-monitor-display.test.js` 通过,4 passed,仍有既有 MODULE_TYPELESS_PACKAGE_JSON warning。
- 风险与关注点:
- 任务监控数据仍来自既有 Flower 批量接口,本次只改变移动端前端渲染批次和滚动加载交互,不改变接口字段、权限或任务筛选规则。
# Work Log - 防雷分析页面 UI/交互重构(FL-214)
- 背景:
- `/admin/fl-analysis` 页面原先将创建表单、任务选择、详情、结果表和 4 类弹窗全部集中在单个 `page.tsx` 内,初始页面负载过重。
- 本次处理:
- 新增 `web/src/components/fl-analysis/` 组件目录,拆出创建表单、任务卡片列表、任务详情面板、结果表、详情弹窗、措施推荐/复算/报告弹窗和共享类型/格式化函数。
- 创建表单改为默认收起,由“新建任务”按钮打开 Drawer;创建成功后关闭 Drawer 并选中新任务。
- 任务选择从 Select 改为卡片网格,展示状态、任务类型、线路、创建/完成时间和杆塔统计。
- 任务详情操作按钮按“执行 / 下游任务 / 导出下载”分组展示。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/fl-analysis/page.tsx --max-warnings=0` 通过。
- 基线:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/fl-analysis/page.tsx src/components/fl-analysis --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 风险与关注点:
- 改动仅影响 `/admin/fl-analysis` 前端视图组织与交互入口,不改变后端接口、请求/响应字段、权限判断或任务创建/启动语义。
# Work Log - 菜单管理页暗黑主题适配(FL-216)
- 背景:
- `/admin/menus` 移动卡片相关 `admin-menus-*` 自定义样式缺少暗黑主题覆盖,暗色模式下与用户管理页视觉不一致。
- 本次处理:
-`.admin-menus-menu-card`、卡片头部和卡片主体并入现有用户/Worker 卡片暗黑主题覆盖,统一边框、渐变背景、头部背景和阴影。
-`.admin-menus-card-view``.admin-menus-card-view-content``.admin-menus-card-view-state` 补充暗色主题下的容器与状态色覆盖。
- 验证:
- 基线:`npm run lint:web` 未通过,失败来自既有 `web/public/cesium` 产物、`admin/lightning-currents``use-mobile-detection` 等非本次改动文件。
- 基线:`npm --workspace web exec eslint src/app/admin/menus/page.tsx --max-warnings=0` 通过。
- 修改后:`git diff --check` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/menus/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 修改后:`npm run build:web` 未通过,`next build --webpack` 阶段被系统 `Killed`,退出码 137。
- 风险与关注点:
- 改动仅影响 `[data-fquiz-theme="dark"]` 下菜单管理页卡片相关 CSS,不改变亮色主题、接口、权限或页面业务逻辑。
# Work Log - 角色列表接口 keyword SQL 修复(FL-218
- 背景:
- `/api/v1/admin/roles-with-menus``/api/v1/admin/roles` 在 PostgreSQL/psycopg 下因 `_load_role_page()` 使用 `:keyword IS NULL OR ... LIKE :keyword` 触发参数类型推断失败,角色管理页列表与搜索返回 500。
- 本次处理:
- `legacy_admin_rbac_service._load_role_page()` 改为仅在 keyword 非空时拼接角色/菜单搜索条件,空 keyword 列表查询不再生成 `:keyword IS NULL`
- `removed_menu_codes` expanding bind 仅在 keyword 搜索子查询需要菜单过滤时绑定,避免空列表查询携带无用 bind。
- `api/tests/test_role_pagination_contract.py` 补充 legacy/modern 两套角色源的 SQL 构造回归测试,覆盖空 keyword 与带 keyword 两种路径。
- 验证:
- 基线:`UV_CACHE_DIR=/tmp/fquiz-uv-cache UV_PYTHON_INSTALL_DIR=/tmp/fquiz-uv-python uv run --python 3.11 --with pytest --with fastapi --with pydantic-settings --with sqlalchemy --with PyJWT --with argon2-cffi --with email-validator --with python-multipart --with psycopg[binary] --with bcrypt pytest api/tests/test_role_pagination_contract.py` 通过,2 passed。
- 修改后:同命令通过,4 passed。
- 修改后:`python3 -m py_compile api/app/services/legacy_admin_rbac_service.py api/tests/test_role_pagination_contract.py` 通过。
- 修改后:`git diff --check` 通过。
- 风险与关注点:
- 改动仅影响角色列表/搜索 SQL 生成,不改变接口路径、响应字段、分页参数、角色 CRUD 或权限语义。
# Work Log - 文件管理页 Card 标题栏暗黑主题对齐(FL-222)
- 背景:
- `/admin/files` 主 Card 标题栏显式覆盖 `background: var(--fquiz-theme-bg-elevated)`,暗黑主题下与 Ant Design Card 默认标题栏背景存在色差。
- 本次处理:
- 移除文件管理页主 Card `styles.header.background` 覆盖,保留边框和内边距,让 Ant Design 按当前主题自动适配标题栏背景。
- 验证:
- 基线:`npm --workspace web exec eslint src/app/admin/files/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec eslint src/app/admin/files/page.tsx --max-warnings=0` 通过。
- 修改后:`npm --workspace web exec tsc --noEmit --pretty false` 通过。
- 修改后:`git diff --check` 通过。
- 风险与关注点:
- 改动仅影响文件管理页主 Card 标题栏背景来源,不改变接口、权限、上传下载或文件列表业务逻辑。