# 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 `
` 与 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 `
` 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