1224 lines
62 KiB
Markdown
1224 lines
62 KiB
Markdown
|
|
## Work Log - 修复后台页面刷新后误判未登录(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 反馈“切菜单后刷新当前页面,会提示 `请先登录后再访问后台`”。
|
|||
|
|
|
|||
|
|
- 根因:
|
|||
|
|
- 前端 `AuthProvider.refreshAccessToken()` 未做并发去重。
|
|||
|
|
- 页面刷新阶段可能触发并发 refresh(例如初始化 bootstrap 与其他请求链路重叠)。
|
|||
|
|
- 后端 refresh 会旋转 refresh token;并发请求中后发请求会带旧 token 命中失败,最终覆盖为未登录态。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/components/auth-provider.tsx`
|
|||
|
|
- 新增 `refreshPromiseRef`(in-flight Promise 引用)。
|
|||
|
|
- `refreshAccessToken()` 改为 single-flight:
|
|||
|
|
- 有进行中的 refresh 时直接复用;
|
|||
|
|
- 无进行中时创建请求并在 `finally` 中安全释放引用。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响前端鉴权刷新并发控制,不改接口契约与权限判定逻辑。
|
|||
|
|
- 该修复会降低页面刷新阶段误判登出概率,并减少重复 refresh 请求。
|
|||
|
|
|
|||
|
|
## Work Log - 打包发布镜像并更新容器(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求“打包发布镜像并更新容器”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- 在仓库根目录执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
- 发布后检查:
|
|||
|
|
- `docker compose ps`
|
|||
|
|
- `docker compose logs --tail=80 api`
|
|||
|
|
- `docker compose logs --tail=80 web`
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`
|
|||
|
|
|
|||
|
|
- 验证结果:
|
|||
|
|
- `api`、`web` 容器均已重建并启动。
|
|||
|
|
- `api` 健康检查通过(`/health` 返回 200,`{"status":"ok","service":"fquiz-api","version":"0.1.0"}`)。
|
|||
|
|
- `web` 首页返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅为镜像重建与容器滚动重启,不涉及代码改动或数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 修复 localhost 刷新后丢登录态(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户反馈:登录后进入 `http://localhost:3000/dashboard`,刷新页面后提示“请先登录后再访问后台”。
|
|||
|
|
|
|||
|
|
- 根因:
|
|||
|
|
- `.env` 的前端 API 基址为 `http://127.0.0.1:8000`,而页面访问 host 为 `localhost`。
|
|||
|
|
- 浏览器在 `localhost -> 127.0.0.1` 场景下会形成跨站 cookie 语义,`refresh_token` 无法稳定参与刷新链路,导致硬刷新后 `AuthProvider` bootstrap refresh 失败并清空登录态。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/lib/api.ts`
|
|||
|
|
- 调整 `getApiBaseUrl()` 的 loopback 重写条件:
|
|||
|
|
- 只要配置 host 是 loopback,且与当前页面 host 不同(例如 `127.0.0.1` vs `localhost`),就自动重写到当前页面 host,端口保持原配置(默认 `8000`)。
|
|||
|
|
- 使用 `URL` 对象回写 `hostname`,兼容 IPv6 场景。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `docker compose build web && docker compose up -d web` -> 成功。
|
|||
|
|
- `docker compose ps` -> `web/api/db` 均为 Up(api/db healthy)。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/dashboard` -> 200(路由重写正常)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响前端运行时 API 基址解析,不改后端接口、cookie 配置和鉴权协议。
|
|||
|
|
- 对 `localhost/127.0.0.1` 混用访问更稳健,可避免刷新阶段误判未登录。
|
|||
|
|
|
|||
|
|
## Work Log - 后台顶部信息容器改为滚动时固定(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求:当页面内容过多出现纵向滚动条时,顶部用户信息/主题切换区域不要随内容一起滚动。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- 将主内容区“后台管理标题 + 用户信息”横向容器改为 `sticky`,固定在顶部导航(64px)下方:
|
|||
|
|
- `sticky top-16 z-40`
|
|||
|
|
- 增加半透明背景、底边框与 `backdrop-blur`,避免滚动时内容穿透影响可读性。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `docker compose build web && docker compose up -d web` -> 成功。
|
|||
|
|
- `docker compose ps` -> `web/api/db` 均为 Up(api/db healthy)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响后台页顶部视觉与滚动行为,不涉及接口、鉴权和数据逻辑。
|
|||
|
|
|
|||
|
|
## Work Log - 新增线路与杆塔管理模块(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 需要基于 `test.csv` 的输电线路数据,落地“线路实体 + 杆塔实体”并提供后台管理能力。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 后端模型与接口:
|
|||
|
|
- 新增模型:
|
|||
|
|
- `api/app/models/line.py`(`power_line`)
|
|||
|
|
- `api/app/models/line_tower.py`(`power_line_tower`)
|
|||
|
|
- 新增 Schema:
|
|||
|
|
- `api/app/schemas/line.py`
|
|||
|
|
- 新增服务:
|
|||
|
|
- `api/app/services/line_service.py`
|
|||
|
|
- 线路 CRUD
|
|||
|
|
- 杆塔 CRUD
|
|||
|
|
- CSV 导入(UTF-8/GBK 兼容、表头额外列兼容、`-1` 归一化)
|
|||
|
|
- CSV 导出
|
|||
|
|
- 新增路由:
|
|||
|
|
- `api/app/api/v1/lines.py`
|
|||
|
|
- `/api/v1/lines*`
|
|||
|
|
- `/api/v1/lines/{line_id}/towers*`
|
|||
|
|
- `/api/v1/lines/towers/{tower_id}`
|
|||
|
|
- 接入总路由:
|
|||
|
|
- `api/app/api/router.py`
|
|||
|
|
- 接入模型初始化:
|
|||
|
|
- `api/app/models/__init__.py`
|
|||
|
|
- `api/app/core/database.py`
|
|||
|
|
|
|||
|
|
- 权限与菜单:
|
|||
|
|
- `api/app/services/seed_service.py` 新增权限:
|
|||
|
|
- `line.read` / `line.manage`
|
|||
|
|
- `tower.read` / `tower.manage`
|
|||
|
|
- admin 角色默认授予上述权限。
|
|||
|
|
- 新增后台菜单:
|
|||
|
|
- `admin.power_lines` -> `/admin/power-lines`
|
|||
|
|
- admin 默认菜单绑定新增 `admin.power_lines`。
|
|||
|
|
- 前端菜单管理保护集合新增 `admin.power_lines`:
|
|||
|
|
- `web/src/app/admin/menus/page.tsx`
|
|||
|
|
- 后端受保护菜单集合同步新增 `admin.power_lines`(防止误删):
|
|||
|
|
- `api/app/services/admin_service.py`
|
|||
|
|
- `api/app/services/legacy_admin_rbac_service.py`
|
|||
|
|
|
|||
|
|
- 前端页面:
|
|||
|
|
- 新增:
|
|||
|
|
- `web/src/app/admin/power-lines/page.tsx`
|
|||
|
|
- 功能:
|
|||
|
|
- 线路列表/筛选/新建/编辑/删除
|
|||
|
|
- 杆塔列表/筛选/新建/编辑/删除
|
|||
|
|
- 杆塔 CSV 导入与导出
|
|||
|
|
- 类型补充:
|
|||
|
|
- `web/src/types/auth.ts` 新增线路/杆塔相关类型定义
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- 后端语法:
|
|||
|
|
- `python3 -m py_compile api/app/models/line.py api/app/models/line_tower.py api/app/schemas/line.py api/app/services/line_service.py api/app/api/v1/lines.py api/app/api/router.py api/app/core/database.py api/app/services/seed_service.py` -> 通过
|
|||
|
|
- `python3 -m compileall api/app` -> 通过
|
|||
|
|
- 前端类型与构建:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过
|
|||
|
|
- `npm run build:web` -> 通过(包含 `/admin/power-lines` 路由产物)
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- `power_line*` 为新表,`create_all` 模式下可自动创建,但不覆盖既有表结构;后续演进建议补 Alembic 迁移。
|
|||
|
|
- CSV 导入对“超出表头的额外列”做了兼容落库(`raw_extra_json`),避免因源文件列漂移中断导入。
|
|||
|
|
|
|||
|
|
## Work Log - 更正滚动需求:固定顶部导航栏(Avatar/主题按钮)(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户澄清:需要固定的是“最顶部导航栏(包含 Avatar 与主题切换)”,不是主内容区标题栏。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- 顶部导航栏从 `fixed` 调整为 `sticky top-0 z-50`,保证随页面纵向滚动始终固定在视口顶部。
|
|||
|
|
- 对应移除内容容器为 fixed 预留的 `pt-[64px]`,避免多余上边距。
|
|||
|
|
- 回退主内容区标题栏为普通流布局(不再 sticky)。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `docker compose build web && docker compose up -d web` -> 成功。
|
|||
|
|
- `docker compose ps` -> `web/api/db` 均为 Up(api/db healthy)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响后台布局滚动行为与间距,不涉及业务逻辑与接口。
|
|||
|
|
|
|||
|
|
## Work Log - 去掉外层左侧 padding 使导航贴边(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户反馈左侧导航距离左边界约 24px,确认是外层容器 `px-*` 导致。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- 将后台主栅格容器从统一 `px-*` 改为左右分离:
|
|||
|
|
- 左侧:`md` 及以上固定 `pl-0`(移除左 padding)
|
|||
|
|
- 右侧:保持响应式 `pr-3 sm:pr-4 xl:pr-6`
|
|||
|
|
- 目标:在桌面端让左侧导航贴到左边界,同时不改变右侧留白。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `docker compose build web && docker compose up -d web` -> 成功。
|
|||
|
|
- `docker compose ps` -> `web/api/db` 均为 Up(api/db healthy)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响后台横向边距与视觉布局,不涉及业务逻辑、接口和权限。
|
|||
|
|
|
|||
|
|
## Work Log - 重新打包发布镜像并更新容器(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求重新执行一次完整发布流程(构建镜像 + 更新容器)。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db` 均为 Up,`api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=60 api`:启动完成,`/health` 200。
|
|||
|
|
- `docker compose logs --tail=60 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅容器重建与滚动重启,存在短时服务切换窗口,不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 移除后台页面通用“后台管理/用户邮箱”头信息(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求去掉每个页面顶部重复出现的“后台管理、系统管理员、admin@asiainfo.com”信息。
|
|||
|
|
|
|||
|
|
## Work Log - 新增 Wine 执行器与实时测试日志(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求开发“通过 Wine 调用 Windows exe”的功能,执行时能实时看到日志,并提供测试能力。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 后端:
|
|||
|
|
- 新增 `api/app/schemas/wine.py`:Wine 状态与执行请求 schema。
|
|||
|
|
- 新增 `api/app/services/wine_service.py`:
|
|||
|
|
- 检测 `wine --version`。
|
|||
|
|
- 通过 `asyncio.create_subprocess_exec` 调用 Wine,不走 shell。
|
|||
|
|
- `stdout/stderr` 合并为 SSE 事件实时输出。
|
|||
|
|
- 支持超时终止、客户端断开时终止进程。
|
|||
|
|
- EXE 与工作目录限制在 `WINE_ALLOWED_ROOT` 下,避免任意路径执行。
|
|||
|
|
- 新增 `api/app/api/v1/wine.py`:
|
|||
|
|
- `GET /api/v1/wine/status`
|
|||
|
|
- `POST /api/v1/wine/test/stream`
|
|||
|
|
- `POST /api/v1/wine/run/stream`
|
|||
|
|
- `api/app/api/router.py` 注册 Wine 路由。
|
|||
|
|
- `api/app/core/config.py` / `.env.example` / `docker-compose.yml` 新增配置:
|
|||
|
|
- `WINE_BINARY_PATH`
|
|||
|
|
- `WINE_ALLOWED_ROOT`
|
|||
|
|
- `WINE_DEFAULT_TIMEOUT_SECONDS`
|
|||
|
|
- `WINE_MAX_TIMEOUT_SECONDS`
|
|||
|
|
- 权限与菜单:
|
|||
|
|
- 新增 `wine.read` / `wine.manage`。
|
|||
|
|
- 新增菜单 `admin.wine_runner` -> `/admin/wine-runner`。
|
|||
|
|
- 同步 admin 默认菜单绑定、受保护菜单集合、legacy 权限映射。
|
|||
|
|
|
|||
|
|
- 前端:
|
|||
|
|
- 新增 `web/src/app/admin/wine-runner/page.tsx`:
|
|||
|
|
- Wine 状态检测。
|
|||
|
|
- EXE 路径、工作目录、参数、超时配置。
|
|||
|
|
- 执行测试/停止。
|
|||
|
|
- 使用 `fetchWithAuth` 读取后端流式响应并实时追加日志。
|
|||
|
|
- 后台首页新增 “Wine执行器” 入口。
|
|||
|
|
- 菜单管理保护集合新增 `admin.wine_runner`。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `python3 -m py_compile api/app/schemas/wine.py api/app/services/wine_service.py api/app/api/v1/wine.py api/app/api/router.py api/app/core/config.py api/app/services/seed_service.py api/app/services/legacy_authz_service.py api/app/services/admin_service.py api/app/services/legacy_admin_rbac_service.py` -> 通过。
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- 直接运行 Wine 状态服务验证未完成:宿主 Python 环境未安装 FastAPI 依赖,`python3 -c ...` 报 `ModuleNotFoundError: No module named 'fastapi'`。
|
|||
|
|
- Ant Design CLI 查询尝试未完成:默认 npm cache 在沙箱内只读;切换 `/tmp/npm-cache` 后 CLI 安装/执行未稳定返回,已停止该尝试。前端以 TypeScript 作为有效门禁。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 后端执行 EXE 属于高风险能力,当前仅允许 `wine.manage` 权限调用,并限制路径在 `WINE_ALLOWED_ROOT` 下。
|
|||
|
|
- Docker API 镜像默认未安装 Wine;部署环境需自行安装 Wine 或通过 `WINE_BINARY_PATH` 指向可执行文件,否则状态检测会显示不可用。
|
|||
|
|
- 停止操作会终止当前 Wine 进程;若 Windows 程序自行派生子进程,仍可能需要部署侧进一步加进程组/容器隔离策略。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- 删除主内容区通用头块(`后台管理` 标题 + 当前用户名/邮箱)。
|
|||
|
|
- 清理关联无用代码:
|
|||
|
|
- 移除 `Heading`/`Flex` 引入;
|
|||
|
|
- 移除 `flattenMenuTree` 与 `flatMenus/currentTitle` 计算。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `docker compose build web && docker compose up -d web` -> 成功。
|
|||
|
|
- `docker compose ps` -> `web/api/db` 均为 Up(api/db healthy)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响后台页面展示层,不涉及接口、权限和数据逻辑。
|
|||
|
|
|
|||
|
|
## Work Log - 全局滚动条样式改造成 Ant 风格(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求将页面滚动条改造成接近 Ant Design 文档站风格。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/globals.css`
|
|||
|
|
- 新增全局滚动条样式:
|
|||
|
|
- Firefox:`scrollbar-width: thin` + `scrollbar-color`
|
|||
|
|
- WebKit:`::-webkit-scrollbar` / `::-webkit-scrollbar-thumb` / `::-webkit-scrollbar-track`
|
|||
|
|
- 颜色基于 Ant token 变量(含回退值),避免主题切换时风格割裂。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- 容器构建与更新成功(见下条日志)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响前端视觉层滚动条样式,不涉及业务逻辑。
|
|||
|
|
|
|||
|
|
## Work Log - 修复 web 镜像构建链路(postinstall 脚本缺失)(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 重新构建 `web` 镜像时,`npm ci` 触发 `postinstall` 报错:`Cannot find module /app/scripts/sync-cesium-assets.mjs`。
|
|||
|
|
|
|||
|
|
- 根因:
|
|||
|
|
- `web/Dockerfile` 在 `npm ci` 前仅复制 `package.json/package-lock.json`,未复制 `scripts/` 目录。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/Dockerfile`
|
|||
|
|
- 在 `npm ci` 前补充:`COPY scripts ./scripts`。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `docker compose build web && docker compose up -d web` -> 成功。
|
|||
|
|
- `docker compose ps` -> `web/api/db` 均为 Up(api/db healthy)。
|
|||
|
|
- `docker compose logs --tail=40 web` -> Next.js Ready。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响 web 镜像构建阶段文件准备,不改变运行时业务逻辑。
|
|||
|
|
|
|||
|
|
## Work Log - 线路 Cesium 展示可行性评估(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户询问“当前杆塔/线路管理是否可用 Cesium 展示线路,并给出方案或缺失项”。
|
|||
|
|
|
|||
|
|
- 评估结论:
|
|||
|
|
- 可行。现有数据模型已具备线路可视化最小条件:杆塔经纬度 + 海拔 + 序号。
|
|||
|
|
- 当前前端尚未接入任何地图引擎,`web` 依赖中无 `cesium`。
|
|||
|
|
|
|||
|
|
- 证据定位:
|
|||
|
|
- 后端杆塔模型已包含 `longitude` / `latitude` / `altitude_m` 与 `seq_no`(可拼线路折线):
|
|||
|
|
- `api/app/models/line_tower.py`
|
|||
|
|
- 线路杆塔查询按 `seq_no asc` 返回,适合前端直接生成 polyline:
|
|||
|
|
- `api/app/services/line_service.py` -> `list_line_towers`
|
|||
|
|
- `api/app/api/v1/lines.py` -> `GET /api/v1/lines/{line_id}/towers`
|
|||
|
|
- 前端线路页已能拿到杆塔坐标并展示表格,但未做地图渲染:
|
|||
|
|
- `web/src/app/admin/power-lines/page.tsx`
|
|||
|
|
|
|||
|
|
- 缺失项(接入前建议补齐):
|
|||
|
|
- 坐标系元数据(WGS84/GCJ-02/CGCS2000)未显式存储,可能导致地图偏移难以排查。
|
|||
|
|
- 当前塔列表接口单次 `limit` 上限为 `1000`,前端页面固定请求 `500`;超长线路会被截断,地图需补全分页拉取或专用几何接口。
|
|||
|
|
- 目前 schema 未限制经纬度范围(仅 `float`),建议加范围校验避免脏坐标影响渲染。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `rg -n "cesium|Cesium|mapbox|leaflet|openlayers|maplibre|deck\\.gl" web api package.json web/package.json` -> 无结果(当前未接入地图引擎)。
|
|||
|
|
- `python3` 抽样读取 `test.csv`:34 条杆塔记录,经纬度有效 34 条,满足 Cesium MVP 展示条件。
|
|||
|
|
|
|||
|
|
## Work Log - 线路 Cesium MVP 实施(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求“先实现 MVP 版本”。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 前端依赖与构建链路:
|
|||
|
|
- `web/package.json`
|
|||
|
|
- 新增依赖 `cesium`
|
|||
|
|
- 新增脚本:
|
|||
|
|
- `postinstall`: `node scripts/sync-cesium-assets.mjs`
|
|||
|
|
- `prebuild`: `node scripts/sync-cesium-assets.mjs`
|
|||
|
|
- 新增脚本 `web/scripts/sync-cesium-assets.mjs`:
|
|||
|
|
- 兼容 workspace hoist(优先 `web/node_modules`,回退 `../node_modules`)
|
|||
|
|
- 将 `Cesium` 的 `Assets/ThirdParty/Workers/Widgets` 同步到 `web/public/cesium`
|
|||
|
|
- `web/.gitignore` 增加 `public/cesium`(避免提交生成资产)
|
|||
|
|
- `web/src/app/layout.tsx` 增加 Cesium Widgets 全局样式导入
|
|||
|
|
- `web/src/types/antd.d.ts` 增加 Cesium css 模块声明
|
|||
|
|
|
|||
|
|
- 页面能力:
|
|||
|
|
- 新增组件 `web/src/components/power-line-cesium-map.tsx`:
|
|||
|
|
- 基于 Cesium `Viewer` 渲染线路折线(按 `seq_no` 排序)
|
|||
|
|
- 渲染杆塔点位(带风险等级颜色)
|
|||
|
|
- 默认显示起止塔号标签(点位 <=30 时显示全量标签)
|
|||
|
|
- 空数据与初始化失败提示
|
|||
|
|
- 改造 `web/src/app/admin/power-lines/page.tsx`:
|
|||
|
|
- 新增“表格/地图”视图切换
|
|||
|
|
- 地图视图复用当前筛选后的杆塔数据(塔号/模型/塔型/风险等级)
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `npm run build:web` -> 通过(`/admin/power-lines` 页面产物正常生成,`prebuild` 触发 Cesium 资产同步)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 当前为 MVP:仅实现线路折线 + 杆塔点位,不含杆塔 3D 模型与地形分析。
|
|||
|
|
- 若单条线路点位非常大(>500)仍受现有页面查询口径影响;后续建议补分页全量拉取或专用几何接口。
|
|||
|
|
|
|||
|
|
## Work Log - 新增雷电流数据管理模块(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 需要将原始雷电流序列转化为可用于防雷计算的特征参数,并具备后台可管理能力(导入、查询、统计、预览)。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 后端数据模型:
|
|||
|
|
- 新增 `api/app/models/lightning_event.py`(`lightning_current_event`)
|
|||
|
|
- 事件元数据(地域/设备/天气/合成标记)
|
|||
|
|
- 特征参数(`peak_current_ka`、`wavefront_time_t1_us`、`half_value_time_t2_us`、`steepness_ka_per_us`、`action_integral_j_ohm`、`wave_shape`、`polarity`、`stroke_count`)
|
|||
|
|
- 新增 `api/app/models/lightning_sample.py`(`lightning_current_sample`)
|
|||
|
|
- 采样点时序(`seq_no`、`time_us`、`current_ka`)
|
|||
|
|
- 后端能力:
|
|||
|
|
- 新增 schema:`api/app/schemas/lightning.py`
|
|||
|
|
- 新增服务:`api/app/services/lightning_service.py`
|
|||
|
|
- 原始 TXT/CSV 序列解析
|
|||
|
|
- 时间轴构建(显式 time 列或采样间隔)
|
|||
|
|
- 特征提取(T1/T2、陡度、I²t、波形分类、多回击识别)
|
|||
|
|
- 事件 CRUD、采样分页查询、峰值超越概率(P 曲线)
|
|||
|
|
- 新增路由:`api/app/api/v1/lightning.py`
|
|||
|
|
- `GET /api/v1/lightning-currents`
|
|||
|
|
- `POST /api/v1/lightning-currents/import`
|
|||
|
|
- `GET /api/v1/lightning-currents/stats/exceedance`
|
|||
|
|
- `GET/PATCH/DELETE /api/v1/lightning-currents/{event_id}`
|
|||
|
|
- `GET /api/v1/lightning-currents/{event_id}/samples`
|
|||
|
|
- 接入总路由:`api/app/api/router.py`
|
|||
|
|
- 接入模型预加载:`api/app/models/__init__.py`、`api/app/core/database.py`
|
|||
|
|
- 权限与菜单:
|
|||
|
|
- `api/app/services/seed_service.py` 新增权限:
|
|||
|
|
- `lightning.read`
|
|||
|
|
- `lightning.manage`
|
|||
|
|
- admin 默认角色授予上述权限。
|
|||
|
|
- 新增默认菜单:`admin.lightning_currents` -> `/admin/lightning-currents`。
|
|||
|
|
- 前端页面:
|
|||
|
|
- 新增 `web/src/app/admin/lightning-currents/page.tsx`
|
|||
|
|
- 导入原始序列并提取特征
|
|||
|
|
- 事件筛选列表
|
|||
|
|
- 事件详情(核心防雷参数)
|
|||
|
|
- 采样点预览(前 200)
|
|||
|
|
- 峰值超越概率表(P 曲线)
|
|||
|
|
- 首页卡片接入:`web/src/app/admin/page.tsx`
|
|||
|
|
- 菜单保护集合接入:`web/src/app/admin/menus/page.tsx`
|
|||
|
|
- 类型补充:`web/src/types/auth.ts`
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- 后端语法:
|
|||
|
|
- `python3 -m py_compile api/app/models/lightning_event.py api/app/models/lightning_sample.py api/app/schemas/lightning.py api/app/services/lightning_service.py api/app/api/v1/lightning.py api/app/api/router.py api/app/core/database.py api/app/services/seed_service.py api/app/models/__init__.py` -> 通过。
|
|||
|
|
- `python3 -m compileall api/app` -> 通过。
|
|||
|
|
- 前端类型与构建:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `npm run build:web` -> 通过(包含 `/admin/lightning-currents` 路由产物)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 采样点按关系型表存储(`lightning_current_sample`),超大序列导入会增加写入耗时与存储占用。
|
|||
|
|
- 当前 T1/T2、多回击识别采用工程化自动提取算法(可用于工程筛查),如需严格对齐特定实验标准可在后续版本引入可配置算法参数。
|
|||
|
|
|
|||
|
|
## Work Log - 雷电流模块文案更名(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求将功能模块名称改为“雷电幅值统计”。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `api/app/services/seed_service.py`
|
|||
|
|
- 默认菜单 `admin.lightning_currents` 的 `name` 从“雷电流管理”调整为“雷电幅值统计”。
|
|||
|
|
- `web/src/app/admin/page.tsx`
|
|||
|
|
- 后台首页卡片标题同步改为“雷电幅值统计”。
|
|||
|
|
- `web/src/app/admin/lightning-currents/page.tsx`
|
|||
|
|
- 页面登录提示与主卡片标题文案同步为“雷电幅值统计”。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅文案调整,不涉及接口路径、权限码与数据结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并发布更新(含 Next.js 页面导出修复)(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求“打包镜像并发布更新”。
|
|||
|
|
|
|||
|
|
- 发布过程与问题:
|
|||
|
|
- 首次执行 `docker compose build` 时,`web` 在 `next build` 的 TypeScript 阶段失败:
|
|||
|
|
- `src/app/admin/models/page.tsx` 默认导出带自定义 props(`scene`),不符合 App Router `page.tsx` 导出约束。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 前端修复:
|
|||
|
|
- 新增 `web/src/app/admin/models/models-page-content.tsx` 承载可复用页面主体。
|
|||
|
|
- `web/src/app/admin/models/page.tsx` 改为无参默认导出包装,仅渲染 `scene="models"`。
|
|||
|
|
- `web/src/app/admin/mcp-server/page.tsx` 与 `web/src/app/admin/orchestration/page.tsx` 改为复用 `models-page-content.tsx`。
|
|||
|
|
- 发布执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `docker compose ps` -> `api/web/db` 均为 Up,`api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=80 api` -> 启动完成,`/health` 200。
|
|||
|
|
- `docker compose logs --tail=80 web` -> Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health` -> `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/` -> `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 发布包含前端页面导出结构修复,影响范围限定在 `models/mcp-server/orchestration` 三个页面的组件复用入口,不改变接口契约。
|
|||
|
|
- 容器更新存在短时切换窗口;本次不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 下线文件管理功能(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求删除当前系统中的文件管理功能。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 后端:
|
|||
|
|
- 移除文件管理 API 路由挂载:
|
|||
|
|
- 删除 `api/app/api/v1/admin_files.py`
|
|||
|
|
- `api/app/api/router.py` 不再 include `admin_files_router`
|
|||
|
|
- 删除文件管理服务与存储驱动实现:
|
|||
|
|
- 删除 `api/app/services/file_service.py`
|
|||
|
|
- 删除 `api/app/services/storage_driver.py`
|
|||
|
|
- 删除 `api/app/schemas/file_storage.py`
|
|||
|
|
- 清理权限/菜单默认配置:
|
|||
|
|
- `api/app/services/seed_service.py` 移除 `file.read`/`file.manage`
|
|||
|
|
- 移除默认菜单 `admin.files`(`/admin/knowledge-set`)
|
|||
|
|
- `admin` 默认菜单绑定移除 `admin.files`
|
|||
|
|
- 移除默认文件存储 backend/mount 初始化逻辑(`_seed_file_storage`)
|
|||
|
|
- 清理鉴权与订阅映射:
|
|||
|
|
- `api/app/services/legacy_authz_service.py` 移除 `file.*` 权限与 `admin.files` 映射
|
|||
|
|
- `api/app/services/topic_registry.py` 移除 `admin.files` 主题规则
|
|||
|
|
- `api/app/services/admin_service.py` 与 `api/app/services/legacy_admin_rbac_service.py` 取消 `admin.files` 受保护状态(并在 legacy removed 列表中标记为移除菜单)
|
|||
|
|
- 前端:
|
|||
|
|
- 删除文件管理页面:
|
|||
|
|
- 删除 `web/src/app/admin/files/page.tsx`
|
|||
|
|
- 删除 `web/src/app/admin/knowledge-set/page.tsx`
|
|||
|
|
- `web/src/app/admin/page.tsx` 移除“知识集管理”入口卡片
|
|||
|
|
- `web/src/app/admin/menus/page.tsx` 受保护菜单集合移除 `admin.files`
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- 后端语法:
|
|||
|
|
- `python3 -m py_compile api/app/api/router.py api/app/services/legacy_authz_service.py api/app/services/topic_registry.py api/app/services/admin_service.py api/app/services/legacy_admin_rbac_service.py api/app/services/seed_service.py` -> 通过。
|
|||
|
|
- 前端类型:
|
|||
|
|
- 首次执行 `npm --workspace web exec tsc --noEmit --pretty false` 因 `.next/types` 缓存残留已删除页面引用失败;
|
|||
|
|
- 清理缓存后执行:
|
|||
|
|
- `rm -rf web/.next`
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 现网数据库若已存在 `admin.files` 菜单记录,本次代码不会直接删库;在 legacy 菜单树策略下该菜单会被过滤为移除项。
|
|||
|
|
- 本次仅下线文件管理能力,不触及既有文件存储表结构(`file_storage_*`)数据。
|
|||
|
|
|
|||
|
|
## Work Log - 参考 modo-next 迁移并恢复文件管理(FastAPI 实现,2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求“参考 `/root/.openclaw/workspace/modo-next` 的文件管理功能,迁移到当前系统,后端用 py 实现”。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 后端(FastAPI):
|
|||
|
|
- 恢复文件管理主链路(挂载点 + 目录索引 + 文件操作):
|
|||
|
|
- `api/app/api/v1/admin_files.py`
|
|||
|
|
- `api/app/services/file_service.py`
|
|||
|
|
- `api/app/services/storage_driver.py`
|
|||
|
|
- `api/app/schemas/file_storage.py`
|
|||
|
|
- 总路由接回:
|
|||
|
|
- `api/app/api/router.py` 重新 include `admin_files_router`
|
|||
|
|
- 权限、菜单、topic、鉴权映射恢复:
|
|||
|
|
- `api/app/services/seed_service.py` 恢复 `file.read` / `file.manage`、`admin.files` 菜单、默认 VFS/S3 存储后端与挂载点初始化;
|
|||
|
|
- `api/app/services/legacy_authz_service.py` 恢复 `admin.files` -> `file.*` 映射;
|
|||
|
|
- `api/app/services/topic_registry.py` 恢复 `admin.files` 订阅规则;
|
|||
|
|
- `api/app/services/admin_service.py` / `api/app/services/legacy_admin_rbac_service.py` 将 `admin.files` 恢复为受保护菜单。
|
|||
|
|
- 参考 modo-next 增强点(目录打包下载):
|
|||
|
|
- 新增 `GET /api/v1/admin/files/download-zip`;
|
|||
|
|
- `file_service` 新增目录递归读取 + 内存 zip 打包能力。
|
|||
|
|
- 前端:
|
|||
|
|
- 恢复文件管理页面与知识集入口:
|
|||
|
|
- `web/src/app/admin/files/page.tsx`
|
|||
|
|
- `web/src/app/admin/knowledge-set/page.tsx`
|
|||
|
|
- `web/src/app/admin/page.tsx` 恢复“知识集管理”卡片;
|
|||
|
|
- `web/src/app/admin/menus/page.tsx` 恢复 `admin.files` 受保护项。
|
|||
|
|
- 对齐增强点:
|
|||
|
|
- 文件管理页面目录行新增“下载目录”按钮,调用 `/api/v1/admin/files/download-zip`。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- 后端语法:
|
|||
|
|
- `python3 -m py_compile api/app/api/router.py api/app/api/v1/admin_files.py api/app/schemas/file_storage.py api/app/services/file_service.py api/app/services/storage_driver.py api/app/services/seed_service.py api/app/services/legacy_authz_service.py api/app/services/topic_registry.py api/app/services/admin_service.py api/app/services/legacy_admin_rbac_service.py` -> 通过。
|
|||
|
|
- 前端类型:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次为“恢复 + 增强”改动,重新启用了 `file.read/file.manage` 与 `admin.files` 链路;若依赖最小权限策略,需确认角色权限配置是否符合预期。
|
|||
|
|
- 目录 zip 下载采用内存打包,大目录大文件场景会占用较多 API 内存;后续可按需升级为临时文件流式下载方案。
|
|||
|
|
|
|||
|
|
## Work Log - 统一系统滚动条样式到主页面基线(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户反馈系统内滚动条样式不统一,要求与主页面滚动条样式一致。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/globals.css`
|
|||
|
|
- 新增全局滚动条 token:`--fquiz-scrollbar-thumb`、`--fquiz-scrollbar-thumb-hover`。
|
|||
|
|
- 将 `scrollbar-width/scrollbar-color` 从 `html, body` 扩展为 `*`,统一所有滚动容器(尤其 Firefox)。
|
|||
|
|
- 统一 `*::-webkit-scrollbar*` 使用同一套 token。
|
|||
|
|
- `scrollbar-antd` 类仅保留 `scrollbar-gutter: stable`,移除重复的颜色/尺寸定义,避免局部与全局样式漂移。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响前端滚动条视觉样式,不涉及业务逻辑、接口与权限。
|
|||
|
|
- 在 Firefox 中,之前未显式声明滚动条样式的局部滚动容器也会统一为主页面风格。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并发布更新(2026-04-25,晚间重发)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求再次执行“打包镜像并发布更新”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db` 均为 Up,且 `api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=80 api`:API 启动完成,健康检查请求返回 200。
|
|||
|
|
- `docker compose logs --tail=80 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅镜像重建与容器滚动更新,不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 修复 Cesium SPZ 依赖导致的前端 chunk 语法错误(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 浏览器报错:`Uncaught SyntaxError: Octal escape sequences are not allowed in template strings`。
|
|||
|
|
- 报错 chunk:`2117a04a.ddf56f789729a94a.js`。
|
|||
|
|
|
|||
|
|
- 根因:
|
|||
|
|
- Cesium `1.140.0` 依赖链中的 `@spz-loader/core@0.3.1` 把 SPZ WASM 二进制以内联模板字符串打进前端 chunk。
|
|||
|
|
- 该模板字符串中包含 `\00` / `\001` 等八进制转义形态,浏览器解析阶段直接报错。
|
|||
|
|
- 当前业务地图仅使用 Cesium Viewer/Entity/Polyline/Point,不使用 SPZ/Gaussian splats。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/lib/spz-loader-core-shim.ts`
|
|||
|
|
- 新增 `loadSpz` / `loadSpzFromUrl` 轻量 shim。
|
|||
|
|
- 若未来实际加载 SPZ 内容,显式抛出 `SPZ Gaussian splat decoding is disabled in this build.`。
|
|||
|
|
- `web/next.config.ts`
|
|||
|
|
- 增加 webpack alias,将 `@spz-loader/core` 指向本地 shim,避免问题依赖进入浏览器 chunk。
|
|||
|
|
- 为恢复构建门禁,顺手修复现有 AntD + React 19 类型阻断:
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- `web/src/app/admin/page.tsx`
|
|||
|
|
- `web/src/app/admin/menus/page.tsx`
|
|||
|
|
- `web/src/app/admin/roles/page.tsx`
|
|||
|
|
- `web/src/app/admin/users/page.tsx`
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `npm run build:web` -> 通过。
|
|||
|
|
- 本地构建产物检查:
|
|||
|
|
- `rg -l --text '@spz-loader/core|load_spz|couldn.t allocate memory' web/.next/static/chunks` -> 无匹配。
|
|||
|
|
- `rg -l --text 'SPZ Gaussian splat decoding is disabled' web/.next/static/chunks` -> 命中本地 shim chunk。
|
|||
|
|
- `node --check web/.next/static/chunks/4912.c2dc9fb5bf5449a0.js` -> 通过。
|
|||
|
|
- Docker 发布:
|
|||
|
|
- `docker compose build web` -> 通过。
|
|||
|
|
- `docker compose up -d web` -> 成功。
|
|||
|
|
- 运行中容器验证:
|
|||
|
|
- `docker compose ps`:`web` Up,`api/db/redis` healthy。
|
|||
|
|
- `docker compose logs --tail=60 web`:Next.js Ready。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/` -> `HTTP/1.1 200 OK`。
|
|||
|
|
- `curl -sS -I http://127.0.0.1:3000/_next/static/chunks/2117a04a.ddf56f789729a94a.js` -> `HTTP/1.1 404 Not Found`。
|
|||
|
|
- 容器内 `grep -R -l 'load_spz\|@spz-loader/core\|couldn.t allocate memory' .next/static/chunks` -> 无匹配。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 常规 Cesium 地图能力保留。
|
|||
|
|
- 如果后续需要加载 SPZ/Gaussian splats,需要移除 shim 并改为上游依赖修复或单独的安全 WASM 加载方案。
|
|||
|
|
|
|||
|
|
## Work Log - 拆出雷电分布统计独立菜单入口(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户指出《雷电数据.txt》对应能力应该有基于该数据开发的页面。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 前端:
|
|||
|
|
- 新增独立路由 `web/src/app/admin/lightning-distribution/page.tsx`,访问地址 `/admin/lightning-distribution`。
|
|||
|
|
- 调整 `web/src/app/admin/lightning-currents/page.tsx`:
|
|||
|
|
- 在 `/admin/lightning-distribution` 下只展示分布统计相关能力;
|
|||
|
|
- 保留分布导入、Ng/网格热力、Cesium 散点地图、杆塔缓冲区、实测/合成对比、周/月报、P 曲线;
|
|||
|
|
- 隐藏雷电流幅值页专属的原始序列导入、事件列表、事件详情与采样预览。
|
|||
|
|
- `web/src/app/admin/page.tsx` 新增“雷电分布统计”首页入口卡片。
|
|||
|
|
- `web/src/app/admin/menus/page.tsx` 新增受保护菜单 `admin.lightning_distribution`。
|
|||
|
|
- 后端:
|
|||
|
|
- `api/app/services/seed_service.py` 新增默认菜单:
|
|||
|
|
- `admin.lightning_distribution` -> `/admin/lightning-distribution`,权限 `lightning.read`。
|
|||
|
|
- admin 默认菜单绑定新增 `admin.lightning_distribution`。
|
|||
|
|
- `admin_service` / `legacy_admin_rbac_service` / `legacy_authz_service` 同步补充保护集合、权限映射与 legacy admin 默认权限。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `python3 -m py_compile api/app/services/seed_service.py api/app/services/admin_service.py api/app/services/legacy_admin_rbac_service.py api/app/services/legacy_authz_service.py` -> 通过。
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `npm run build:web` -> 通过,构建产物包含 `/admin/lightning-distribution`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅新增入口并复用现有雷电分布统计接口与页面底座,不新增数据表和接口契约。
|
|||
|
|
- 已运行容器若要看到新菜单,需要重新构建/重启前后端服务并触发默认菜单种子同步。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并发布更新(2026-04-25,连续重发)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户再次要求执行“打包镜像并发布更新”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db/minio` 均为 Up,`api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=80 api`:API 启动完成,`/health` 请求返回 200。
|
|||
|
|
- `docker compose logs --tail=80 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 构建提示:
|
|||
|
|
- Next.js 构建仍提示 `middleware` 文件约定已 deprecated,建议后续迁移到 `proxy`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅镜像重建与容器滚动更新,不涉及数据库结构变更。
|
|||
|
|
- `api` 日志包含 `InsecureKeyLengthWarning`(JWT HMAC key 长度低于建议值),不影响本次发布成功,但建议后续将 `JWT_SECRET_KEY` 升级为至少 32 字节。
|
|||
|
|
|
|||
|
|
## Work Log - 修复 Next.js chunk 丢失导致页面白屏(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 本地访问 `http://localhost:3000` 出现报错:
|
|||
|
|
- `Loading chunk 5782 failed. (missing: .../_next/static/chunks/*.js)`。
|
|||
|
|
- 该类问题通常由浏览器缓存中的旧 chunk 清单与当前构建产物不一致触发。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/lib/chunk-error.ts`
|
|||
|
|
- 新增 chunk 错误识别与恢复工具:
|
|||
|
|
- 识别 `Loading chunk ... failed` / `ChunkLoadError` / 动态 import 失败等模式;
|
|||
|
|
- 提供“一次性自动刷新”逻辑,防止无限刷新循环。
|
|||
|
|
- `web/src/components/chunk-load-recovery.tsx`
|
|||
|
|
- 新增全局监听组件:监听 `window error` 与 `unhandledrejection`,命中 chunk 错误时自动刷新一次。
|
|||
|
|
- `web/src/app/layout.tsx`
|
|||
|
|
- 接入 `ChunkLoadRecovery`,让所有页面共享该容错能力。
|
|||
|
|
- `web/src/app/error.tsx`
|
|||
|
|
- 新增路由级错误边界 UI;chunk 失配时自动刷新,并提供“重试/刷新页面”手动恢复按钮。
|
|||
|
|
- `web/src/app/global-error.tsx`
|
|||
|
|
- 新增全局错误边界 UI,覆盖 root layout 级异常场景。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `npm run build:web` -> 通过(Next.js 16 构建完成,路由产物正常)。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响前端异常恢复链路,不涉及接口契约、权限与数据库。
|
|||
|
|
- 若用户浏览器禁用 sessionStorage,则“防重复刷新标记”为 best-effort;仍可通过错误页按钮手动刷新恢复。
|
|||
|
|
|
|||
|
|
## Work Log - 修复页面滚动后 Modal 顶部遮挡(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户反馈:页面滚动到底部时打开 Modal,弹窗在顶部被屏幕遮挡。
|
|||
|
|
|
|||
|
|
- 根因:
|
|||
|
|
- `web/src/app/globals.css` 的 `快乐工作特效` 对 `body` 使用了 `filter` 动画。
|
|||
|
|
- `filter` 会改变 `position: fixed` 的定位上下文,导致挂载到 `body` 的 AntD `Modal` 在滚动场景出现错位/遮挡。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/globals.css`
|
|||
|
|
- 保留 `:root.fquiz-happy-work body` 动画开关。
|
|||
|
|
- 将关键帧从 `filter` 动画改为 `background-color` 轻微脉冲(`color-mix`),避免影响 fixed 定位。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响“快乐工作特效”视觉表现;不涉及业务逻辑、接口与权限。
|
|||
|
|
- Modal 定位恢复为相对视口,滚动场景下不再被顶部裁切。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并发布更新(2026-04-25,夜间重发)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求执行“打包镜像并发布更新”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db` 均为 Up,且 `api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=80 api`:API 启动完成,`/health` 请求返回 200。
|
|||
|
|
- `docker compose logs --tail=80 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅镜像重建与容器滚动更新,不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 修复线路地图 Chunk 失败不自动恢复(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 线路管理地图视图出现 `地图加载失败`,错误为 `Loading chunk ... failed`。
|
|||
|
|
- 根因是 Cesium `import("cesium")` 在组件内被 `try/catch` 捕获,导致全局 chunk 恢复监听未触发。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/components/power-line-cesium-map.tsx`
|
|||
|
|
- 在 `import("cesium")` 失败的 `catch` 分支里接入 `reloadOnceOnChunkError(error)`;
|
|||
|
|
- 命中 chunk 错误时先触发自动刷新恢复,再兜底展示错误。
|
|||
|
|
- `web/src/components/chunk-load-recovery.tsx`
|
|||
|
|
- 移除挂载时清理 marker 的逻辑,避免持续 chunk 失败时反复刷新。
|
|||
|
|
- `web/src/lib/chunk-error.ts`
|
|||
|
|
- 单次刷新标记改为“带时间戳冷却窗口”(2 分钟),避免刷新死循环,同时保留后续恢复能力。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- `npm run build:web` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响前端异常恢复策略,不涉及接口契约、权限和数据库。
|
|||
|
|
- 若 chunk 在冷却窗口内持续不可用,将停止自动刷新并保留页面错误提示,避免无限重载。
|
|||
|
|
|
|||
|
|
## Work Log - 新增雷电分布统计模块(空间统计 + 资产关联 + 报表,2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求基于《雷电数据.txt》(经纬度 + 电流幅值)落地“雷电分布统计”能力,覆盖:
|
|||
|
|
- 网格化地闪密度(Ng)
|
|||
|
|
- 电流极值/均值与极性占比
|
|||
|
|
- 雷电热力图 + 散点分布 + P 曲线
|
|||
|
|
- 杆塔缓冲区风险分析
|
|||
|
|
- 实测/合成分布对比
|
|||
|
|
- 周报/月报汇总
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环,前后端联动):
|
|||
|
|
- 后端(FastAPI + SQLAlchemy)
|
|||
|
|
- 新增分布导入接口(TXT/CSV 经纬度电流)与清洗逻辑:
|
|||
|
|
- `POST /api/v1/lightning-currents/import-distribution`
|
|||
|
|
- 自动过滤非法行/非法坐标,落库到 `lightning_current_event`(无波形样本)
|
|||
|
|
- 新增空间统计接口:
|
|||
|
|
- `GET /api/v1/lightning-currents/stats/distribution`
|
|||
|
|
- 返回网格统计(Ng/Imax/Iavg/正极占比)、散点数据、P 曲线、极性统计、来源统计
|
|||
|
|
- 新增资产关联接口:
|
|||
|
|
- `GET /api/v1/lightning-currents/stats/tower-buffer`
|
|||
|
|
- 支持 tower_id 或自定义坐标 + 半径(km)缓冲区分析,输出风险等级与建议
|
|||
|
|
- 新增合成对比接口:
|
|||
|
|
- `GET /api/v1/lightning-currents/stats/compare-synthetic`
|
|||
|
|
- 输出实测/合成统计与网格余弦相似度
|
|||
|
|
- 新增周期报表接口:
|
|||
|
|
- `GET /api/v1/lightning-currents/reports/distribution?period=week|month`
|
|||
|
|
- 输出近 7 天/30 天雷击次数、Imax/Iavg、Ng、最严重事件
|
|||
|
|
- 主要文件:
|
|||
|
|
- `api/app/schemas/lightning.py`
|
|||
|
|
- `api/app/services/lightning_service.py`
|
|||
|
|
- `api/app/api/v1/lightning.py`
|
|||
|
|
|
|||
|
|
- 前端(Next.js + AntD)
|
|||
|
|
- `web/src/app/admin/lightning-currents/page.tsx` 扩展为“雷电分布统计工作台”:
|
|||
|
|
- 分布筛选(经纬度范围、网格尺寸、年限、阈值)
|
|||
|
|
- 分布导入按钮(调用 import-distribution)
|
|||
|
|
- 分布摘要指标(Ng、Imax/Iavg、极性与来源)
|
|||
|
|
- 网格热力表(按雷击次数着色)
|
|||
|
|
- 杆塔缓冲区分析表单 + 风险结果 + 命中事件表
|
|||
|
|
- 实测/合成对比 + 周/月报卡片
|
|||
|
|
- P 曲线优先展示空间统计返回结果
|
|||
|
|
- 新增 Cesium 地图组件:
|
|||
|
|
- `web/src/components/lightning-distribution-map.tsx`
|
|||
|
|
- 支持热力网格(矩形半透明着色)+ 雷击散点(按电流幅值分色)
|
|||
|
|
- 补充类型定义:
|
|||
|
|
- `web/src/types/auth.ts`
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- 后端语法:
|
|||
|
|
- `python3 -m py_compile api/app/schemas/lightning.py api/app/services/lightning_service.py api/app/api/v1/lightning.py` -> 通过
|
|||
|
|
- 前端类型:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过
|
|||
|
|
- 前端构建:
|
|||
|
|
- `npm run build:web` -> 通过(含 `/admin/lightning-currents`)
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 当前空间统计采用经纬度近似换算(非 PostGIS 精确地理计算);在高纬或超大范围场景误差会增大。
|
|||
|
|
- `import-distribution` 为高吞吐导入,超大文件建议分批导入以降低单次事务压力。
|
|||
|
|
- 杆塔缓冲区分析当前为查询结果级风险判定(返回风险等级与建议),如需“自动写回杆塔风险字段”可在后续补充持久化开关与审计策略。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并发布更新(2026-04-25,深夜重发)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求再次执行“打包镜像并发布更新”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db` 均为 Up,且 `api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=80 api`:API 启动完成,`/health` 请求返回 200。
|
|||
|
|
- `docker compose logs --tail=80 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅镜像重建与容器更新,不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - Docker Compose 接入 MinIO 并切换文件管理默认后端(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求为系统增加 MinIO 组件,并让文件管理功能连接 MinIO。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `docker-compose.yml`
|
|||
|
|
- 新增 `minio` 服务(API `9000` + Console `9001`)。
|
|||
|
|
- 新增 `minio-init` 服务(使用 `minio/mc` 自动创建 `MINIO_BUCKET`)。
|
|||
|
|
- `api` 服务新增 MinIO 环境变量,并依赖 `minio` 与 `minio-init`。
|
|||
|
|
- 新增数据卷 `fquiz_minio_data`。
|
|||
|
|
- `api/app/core/config.py`
|
|||
|
|
- 新增 MinIO 配置项:`minio_enabled/minio_endpoint/minio_access_key/minio_secret_key/minio_bucket/minio_region`。
|
|||
|
|
- `api/app/services/seed_service.py`
|
|||
|
|
- 文件存储种子改为按 `MINIO_ENABLED` 动态切换默认后端:
|
|||
|
|
- 开启时:`files.s3.default` 启用且设为默认,`main` 挂载指向 S3。
|
|||
|
|
- 关闭时:回退 `files.vfs.default`。
|
|||
|
|
- 对已存在后端记录也会更新 `status/is_default/config_json`,保证切换生效。
|
|||
|
|
- `.env` / `.env.example`
|
|||
|
|
- 增加 MinIO 相关变量与端口/镜像默认值。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `python3 -m py_compile api/app/core/config.py api/app/services/seed_service.py` -> 通过。
|
|||
|
|
- `docker compose config` -> 通过。
|
|||
|
|
- `docker compose up -d minio minio-init api` + `docker compose up --build -d api` -> 成功。
|
|||
|
|
- `docker compose ps -a` -> `minio` 运行中,`minio-init` `Exited (0)`。
|
|||
|
|
- `docker compose logs --tail=80 minio-init` -> bucket 创建成功(`Bucket created successfully local/fquiz-files`)。
|
|||
|
|
- 数据库校验(`postgres` 库):
|
|||
|
|
- `file_storage_backends`:`files.s3.default` 为 `enabled + is_default=true`,`files.vfs.default` 为 `disabled`。
|
|||
|
|
- `file_storage_mounts.main`:`backend_code=files.s3.default`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 当前使用默认凭据 `minioadmin/minioadmin`,仅适合开发环境;生产需替换强口令并限制端口暴露。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并更新重启(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求执行“打包镜像并更新重启”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db/minio` 均为 `Up`,`api/db` 为 `healthy`。
|
|||
|
|
- `docker compose logs --tail=80 api`:API 启动完成,`/health` 持续返回 200。
|
|||
|
|
- `docker compose logs --tail=80 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次为镜像重建与容器滚动重启,存在短时服务切换窗口,不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 用户管理新增用户表单迁移到 Modal(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求将“用户管理”页面的新增用户表单从页面内联区域改为弹窗输入。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/users/page.tsx`
|
|||
|
|
- 新增 `createUserModalOpen` 状态与打开/关闭处理。
|
|||
|
|
- 原“新增用户”卡片内联 `Form` 改为提示文案 + `新增用户` 按钮触发。
|
|||
|
|
- 新增“新增用户”`Modal`,内部复用原有创建表单字段、校验规则与提交逻辑。
|
|||
|
|
- 创建成功后自动关闭弹窗并刷新用户/角色列表;创建中禁止关闭弹窗。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅调整前端交互承载位置,不涉及接口契约、权限和数据库。
|
|||
|
|
|
|||
|
|
## Work Log - 菜单管理页面去掉顶部统计区块(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求菜单管理页面移除顶部“总菜单数/启用/禁用/顶级菜单”统计展示。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/menus/page.tsx`
|
|||
|
|
- 删除顶部统计区块渲染(四个 `Statistic` 卡片)。
|
|||
|
|
- 清理未使用的 `Statistic` 引入与 `stats` 计算逻辑。
|
|||
|
|
- 保留筛选表单、菜单列表与新建/编辑弹窗能力不变。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅影响页面展示,不涉及接口、权限和数据逻辑。
|
|||
|
|
|
|||
|
|
## Work Log - 全部去掉外层间距并去掉圆角(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求“全部去掉外层间距,去掉圆角”。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- 顶栏容器去掉 `max-width` 与外层左右 padding。
|
|||
|
|
- 主栅格容器去掉 `max-width` 与外层左右 padding。
|
|||
|
|
- 主内容容器由 `py-4 md:px-6` 调整为 `py-0 px-0`(去掉外层间距)。
|
|||
|
|
- 进入后台时给 `body` 增加 `fquiz-admin-flat` 类,离开后台移除。
|
|||
|
|
- `web/src/app/globals.css`
|
|||
|
|
- 新增 `body.fquiz-admin-flat` 作用域:对元素与伪元素统一 `border-radius: 0 !important`,去掉后台页面与弹窗圆角。
|
|||
|
|
- `web/src/components/ui-antd.tsx`
|
|||
|
|
- `Theme` 默认 `radius` 由 `medium` 调整为 `none`。
|
|||
|
|
- AntD token `borderRadius` fallback 调整为 `RADIUS_MAP.none`。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 后台视觉风格将显著变为“直角 + 贴边”,包括头像/标签/弹窗等圆角元素。
|
|||
|
|
- 仅影响前端样式,不涉及接口、权限与数据逻辑。
|
|||
|
|
|
|||
|
|
## Work Log - 角色管理页面支持搜索(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求角色管理页面支持搜索。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/admin/roles/page.tsx`
|
|||
|
|
- 新增搜索状态 `searchKeyword`。
|
|||
|
|
- 新增 `filteredRoles`,基于关键词对角色进行前端过滤,匹配字段包括:
|
|||
|
|
- 角色编码 `code`
|
|||
|
|
- 角色名称 `name`
|
|||
|
|
- 权限编码列表 `permission_codes`
|
|||
|
|
- 菜单名称/编码(通过 `menu_ids` 映射)
|
|||
|
|
- 页面新增搜索输入框(支持清空),位于角色列表头部。
|
|||
|
|
- 列表统计文案改为“总数 + 匹配数”。
|
|||
|
|
- 无匹配时显示“未找到匹配角色,请调整搜索关键词”。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次为前端本地过滤,不改变后端接口契约和权限逻辑。
|
|||
|
|
- 当角色规模极大时,本地过滤性能可能下降;若后续角色数增长明显,可再升级为后端关键词查询。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并发布更新(2026-04-25,夜间再次重发)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求执行“打包镜像并发布更新”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db/minio` 均为 Up,`api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=80 api`:API 启动完成,`/health` 请求返回 200。
|
|||
|
|
- `docker compose logs --tail=80 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅镜像重建与容器滚动更新,不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 恢复后台圆角(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求“恢复圆角”。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- `web/src/app/globals.css`
|
|||
|
|
- 移除 `body.fquiz-admin-flat` 下全局强制 `border-radius: 0 !important` 的规则。
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- 移除进入后台时给 `body` 增加 `fquiz-admin-flat` 的逻辑。
|
|||
|
|
- 保留已调整的贴边布局与外层间距策略。
|
|||
|
|
- `web/src/components/ui-antd.tsx`
|
|||
|
|
- `Theme` 默认 `radius` 恢复为 `medium`。
|
|||
|
|
- AntD token `borderRadius` fallback 恢复为 `RADIUS_MAP.medium`。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `rg -n "fquiz-admin-flat|admin-flat-ui|borderRadius: RADIUS_MAP\\[radius\\] \\?\\? RADIUS_MAP\\.none|radius = \\"none\\"" web/src` -> 无匹配。
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 仅恢复前端视觉圆角,不涉及接口、权限、数据结构。
|
|||
|
|
- 外层贴边/去外层间距布局未回退。
|
|||
|
|
|
|||
|
|
## Work Log - 打包镜像并发布更新(2026-04-25,再次执行)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求执行“打包镜像并发布更新”。
|
|||
|
|
|
|||
|
|
- 本次执行:
|
|||
|
|
- `docker compose build`
|
|||
|
|
- `docker compose up -d`
|
|||
|
|
|
|||
|
|
- 发布后验证:
|
|||
|
|
- `docker compose ps`:`api/web/db/minio` 均为 Up,`api/db` healthy。
|
|||
|
|
- `docker compose logs --tail=80 api`:API 启动完成,`/health` 请求返回 200。
|
|||
|
|
- `docker compose logs --tail=80 web`:Next.js Ready。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health`:返回 `{"status":"ok","service":"fquiz-api","version":"0.1.0"}`。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/`:返回 `HTTP/1.1 200 OK`。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 本次仅镜像重建与容器滚动更新,不涉及数据库结构变更。
|
|||
|
|
|
|||
|
|
## Work Log - 接入 Redis + Celery + Beat 后端调度(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户明确要求“加 redis 组件,上 Celery + Beat”。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 依赖:
|
|||
|
|
- `api/requirements.txt` 新增 `celery[redis]==5.5.3`。
|
|||
|
|
- `api/pyproject.toml` 新增 `celery[redis]>=5.5.0,<6.0.0`。
|
|||
|
|
- 后端配置:
|
|||
|
|
- `api/app/core/config.py` 新增 `CELERY_BROKER_URL`、`CELERY_RESULT_BACKEND`、`CELERY_TIMEZONE`、`SCHEDULER_EXPIRE_INTERVAL_SECONDS` 配置。
|
|||
|
|
- 新增 `api/app/core/celery_app.py`,统一配置 Celery app、Redis broker/result backend 与 Beat schedule。
|
|||
|
|
- 任务模块:
|
|||
|
|
- 新增 `api/app/tasks/`。
|
|||
|
|
- 新增任务 `app.tasks.schedule_tasks.expire_overdue_schedule_items`。
|
|||
|
|
- `api/app/services/calendar_event_service.py` 将日程过期逻辑公开为 `expire_overdue_events()`。
|
|||
|
|
- `api/app/services/todo_service.py` 新增 `expire_overdue_todos()`。
|
|||
|
|
- Compose:
|
|||
|
|
- `docker-compose.yml` 新增 `redis`、`celery-worker`、`celery-beat` 服务。
|
|||
|
|
- `.env.example` 新增 Redis/Celery/调度间隔配置项。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `python3 -m py_compile api/app/core/config.py api/app/core/celery_app.py api/app/tasks/__init__.py api/app/tasks/schedule_tasks.py api/app/services/calendar_event_service.py api/app/services/todo_service.py` -> 通过。
|
|||
|
|
- `docker compose config` -> 通过,能渲染 `redis`、`celery-worker`、`celery-beat`。
|
|||
|
|
- `docker compose build api celery-worker celery-beat` -> 通过,`celery-5.5.3` 与 `redis-5.2.1` 安装成功。
|
|||
|
|
- `docker compose up -d redis api celery-worker celery-beat` -> 成功。
|
|||
|
|
- `docker compose ps --status running` -> `api/celery-worker/celery-beat/redis/db/minio/web` 均为 running,`api/db/redis` healthy。
|
|||
|
|
- `docker exec fquiz-redis redis-cli ping` -> `PONG`。
|
|||
|
|
- `docker exec fquiz-celery-worker celery -A app.core.celery_app.celery_app inspect registered` -> 已注册 `app.tasks.schedule_tasks.expire_overdue_schedule_items`。
|
|||
|
|
- 手动投递 `expire_overdue_schedule_items` -> worker 执行成功,返回 `{'expired_calendar_events': 0, 'expired_todos': 0}`。
|
|||
|
|
- Beat 日志显示已周期投递 `expire-overdue-schedule-items`。
|
|||
|
|
- `curl -fsS http://127.0.0.1:8000/health` -> API 健康。
|
|||
|
|
- `curl -I -fsS http://127.0.0.1:3000/` -> Web 首页 200。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 新增 Redis 数据卷 `fquiz_redis_data` 与端口 `6379`。
|
|||
|
|
- `celery-worker` 当前以容器 root 用户运行,Celery 会输出安全警告;生产环境建议后续在 API Dockerfile 中新增非 root 用户并为 worker/beat 指定用户。
|
|||
|
|
- 当前 Beat schedule 使用本地文件 `/tmp/celerybeat-schedule`,适合当前单 Beat 实例;不要横向启动多个 Beat 实例,避免重复投递。
|
|||
|
|
|
|||
|
|
## Work Log - 按 Ant Design 规范改造后台 UI(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户明确要求“按照 ant design 的设计规范改造当前系统,不要最小改动,要严格按照 ant design 的设计规范改造”。
|
|||
|
|
|
|||
|
|
- 本次改动(系统级前端改造):
|
|||
|
|
- AntD 主题与 Provider:
|
|||
|
|
- `web/src/components/ui-antd.tsx`
|
|||
|
|
- `Theme` 改为 `ConfigProvider + App` 包裹,接入 `zh_CN` locale。
|
|||
|
|
- 默认强调色恢复 AntD 蓝色体系(`blue/#1677ff`)。
|
|||
|
|
- 圆角 token 调整到 AntD 常规基线(`medium=6`、`large=8`)。
|
|||
|
|
- 增加 AntD token CSS 变量桥接:背景、圆角、间距、阴影等。
|
|||
|
|
- 增加 Layout/Menu/Card/Table component token 配置。
|
|||
|
|
- 主题偏好 localStorage 初始化改为 microtask,避免 React lint 的同步 effect setState 告警。
|
|||
|
|
- `web/src/app/layout.tsx`
|
|||
|
|
- 根 Theme 默认 `accentColor` 改为 `blue`。
|
|||
|
|
|
|||
|
|
- 后台布局:
|
|||
|
|
- `web/src/app/admin/layout.tsx`
|
|||
|
|
- 从自绘 header/grid/aside 改为 AntD `Layout/Header/Sider/Content`。
|
|||
|
|
- 增加桌面侧边栏收起/展开。
|
|||
|
|
- 增加移动端 `Drawer` 菜单入口。
|
|||
|
|
- 增加 Breadcrumb + 页面标题 + 描述的 AntD 页面头。
|
|||
|
|
- 账号区和主题区统一为 AntD `Dropdown/Button/Avatar`。
|
|||
|
|
- `web/src/app/globals.css`
|
|||
|
|
- 增加 `admin-design-*` 布局类,统一 64px Header、24px 内容区留白、Sider 粘性高度、移动端 16px 内容留白。
|
|||
|
|
- 不使用全局 `.ant-*` 覆盖,布局样式通过项目自有 class + AntD token 变量表达。
|
|||
|
|
|
|||
|
|
- 工作台与核心页面:
|
|||
|
|
- `web/src/app/admin/page.tsx`
|
|||
|
|
- 改为 AntD `Statistic` 汇总 + `Row/Col/Card/Tag/Avatar` 模块入口。
|
|||
|
|
- 模块入口 URL 改为公开路径(如 `/users`),减少 `/admin/*` 重定向依赖。
|
|||
|
|
- 增加 `Wine执行器` 入口。
|
|||
|
|
- `web/src/app/admin/roles/page.tsx`
|
|||
|
|
- 从自绘 table/dialog/input/checkbox 迁移为 AntD `Card/Table/Form/Modal/Select/Input/App message/modal`。
|
|||
|
|
- 权限点和可见菜单改为 `Select mode="multiple"`。
|
|||
|
|
- 保留角色搜索、创建、编辑、删除能力。
|
|||
|
|
- `web/src/app/admin/users/page.tsx`
|
|||
|
|
- 列表 Card 直接使用 AntD Card,并将“新增用户”动作收口到列表 Card extra,减少单按钮卡片。
|
|||
|
|
- `web/src/app/admin/menus/page.tsx`
|
|||
|
|
- 使用 AntD `App.useApp()` message,去掉独立 message context holder。
|
|||
|
|
- 列表 Card 直接使用 AntD Card。
|
|||
|
|
- `web/src/components/row-action-menu.tsx`
|
|||
|
|
- 从 Radix 兼容 `DropdownMenu` 改为 AntD `Dropdown + Button`。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
- 针对本次改动文件执行:
|
|||
|
|
- `npx eslint src/app/admin/layout.tsx src/app/admin/page.tsx src/app/admin/roles/page.tsx src/app/admin/users/page.tsx src/app/admin/menus/page.tsx src/components/row-action-menu.tsx src/components/ui-antd.tsx` -> 通过。
|
|||
|
|
- `npm run build:web` -> 通过(Next.js 16 构建完成,33 个 app routes 生成成功)。
|
|||
|
|
- `git diff --check -- <本次改动文件>` -> 通过。
|
|||
|
|
|
|||
|
|
- 说明:
|
|||
|
|
- 尝试按 `ant-design` 技能要求运行官方 CLI:
|
|||
|
|
- `npx antd info ... --format json` -> 失败(不是官方 CLI 可执行包)。
|
|||
|
|
- `npx @ant-design/cli info ... --format json` -> 下载后长时间卡住,已终止卡住进程。
|
|||
|
|
- 因 CLI 在当前环境不可用,本次以官方 AntD 组件 API 类型、本地 TypeScript、Next build 和 AntD 设计规范口径兜底。
|
|||
|
|
- `npm --workspace web run lint` 全量仍失败,主要来自 `web/public/cesium` 生成资产与历史页面 hook/any 问题;本次改动文件的 targeted lint 已通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 后台视觉与交互范围变更较大:恢复 AntD 内容区留白、页面标题、Breadcrumb、Sider 折叠和移动端 Drawer。
|
|||
|
|
- 这是前端 UI 改造,不涉及后端接口、权限码和数据库结构。
|
|||
|
|
- 因全局后台 layout 改造覆盖所有后台页面,建议发布前做一次浏览器人工走查:桌面、移动端、浅色/暗黑/紧凑主题。
|
|||
|
|
|
|||
|
|
## Work Log - 新增任务监控模块(2026-04-25)
|
|||
|
|
|
|||
|
|
- 背景:
|
|||
|
|
- 用户要求“补充任务监控功能”。
|
|||
|
|
|
|||
|
|
- 本次改动(最小闭环):
|
|||
|
|
- 后端:
|
|||
|
|
- 新增 `api/app/schemas/task_monitor.py`:任务监控聚合响应 schema。
|
|||
|
|
- 新增 `api/app/services/task_monitor_service.py`:
|
|||
|
|
- 聚合 `Requirement` 与 `Todo` 的状态/优先级分布。
|
|||
|
|
- 输出关键指标:需求总量/活跃/完成、待办总量/活跃/完成/超期。
|
|||
|
|
- 输出风险清单:高优先级需求、滞留需求、超期待办。
|
|||
|
|
- 按权限分层返回(有哪类权限返回哪类数据)。
|
|||
|
|
- 新增 `api/app/api/v1/task_monitor.py`:`GET /api/v1/admin/task-monitor/overview`。
|
|||
|
|
- 路由注册:`api/app/api/router.py` 接入 `task_monitor_router`。
|
|||
|
|
|
|||
|
|
- 菜单与权限映射:
|
|||
|
|
- `api/app/services/seed_service.py`:新增默认菜单 `admin.task_monitor`(`/admin/task-monitor`)并加入 admin 默认菜单绑定。
|
|||
|
|
- `api/app/services/legacy_authz_service.py`:新增 `admin.task_monitor` 权限映射(`requirement.read` + `todo.read`)与 legacy synthetic 菜单兜底。
|
|||
|
|
- `api/app/services/legacy_admin_rbac_service.py`:将 `admin.task_monitor` 加入受保护菜单集合。
|
|||
|
|
- `web/src/app/admin/menus/page.tsx`:受保护菜单集合新增 `admin.task_monitor`,避免误删。
|
|||
|
|
|
|||
|
|
- 前端:
|
|||
|
|
- 新增 `web/src/app/admin/task-monitor/page.tsx`:
|
|||
|
|
- 监控参数(风险项上限、滞留阈值小时)可调。
|
|||
|
|
- 展示指标卡、分布标签、风险表格(高优先级需求/滞留需求/超期待办)。
|
|||
|
|
- 无权限与未登录态提示完整。
|
|||
|
|
- `web/src/app/admin/page.tsx`:新增“任务监控”工作台入口卡片。
|
|||
|
|
|
|||
|
|
- 验证:
|
|||
|
|
- 后端语法:
|
|||
|
|
- `python3 -m py_compile api/app/schemas/task_monitor.py api/app/services/task_monitor_service.py api/app/api/v1/task_monitor.py api/app/api/router.py api/app/services/legacy_authz_service.py api/app/services/legacy_admin_rbac_service.py api/app/services/seed_service.py` -> 通过。
|
|||
|
|
- 前端类型:
|
|||
|
|
- `rm -rf .next`(清理过期类型产物)
|
|||
|
|
- `npm --workspace web exec tsc --noEmit --pretty false` -> 通过。
|
|||
|
|
|
|||
|
|
- 风险与影响:
|
|||
|
|
- 任务监控为聚合读接口,不改原有需求/待办 CRUD 链路。
|
|||
|
|
- 需求数据当前无独立 `due_at` 持久字段,滞留判断基于 `update_date` 与阈值小时。
|
|||
|
|
- 菜单通过 seed + legacy synthetic 双路径兜底,老库与新库均可显示“任务监控”入口。
|