Files
fquiz/memory/2026-04-17.md
T

440 lines
26 KiB
Markdown
Raw Normal View History

2026-04-17 21:55:27 +08:00
## Light Sleep
<!-- openclaw:dreaming:light:start -->
- Candidate: Work Log (2026-04-17, Phase B Closure): `web/src/app/admin/chat/page.tsx`:聊天输入从原生 `textarea` 统一为 `@/components/ui``TextArea`
- confidence: 0.00
- evidence: memory/2026-04-17.md:332-332
- recalls: 0
- status: staged
- Candidate: Possible Lasting Truths: No strong candidate truths surfaced.
- confidence: 0.00
- evidence: memory/2026-04-17.md:294-294
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase B): `npm run lint:web` 通过。; `npm run build:web` 通过(`/admin/menus``/admin/models``/admin/requirements*``/admin/users` 均出现在构建路由产物)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:323-324
- recalls: 0
- status: staged
- Candidate: Reflections: Theme: `log` kept surfacing across 124 memories.; confidence: 0.84; evidence: memory/2026-04-17.md:154-154, memory/2026-04-17.md:160-160, memory/2026-04-17.md:162-163; note: reflection
- confidence: 0.00
- evidence: memory/2026-04-17.md:288-291
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17): 背景: 用户要求停止使用 HeroUI,改用 `shadcn/ui + Radix UI`,并给出改造计划。
- confidence: 0.00
- evidence: memory/2026-04-17.md:299-299
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17): `web/package.json` / `web/package-lock.json`:移除 `@heroui/react`,新增 `@radix-ui/react-dialog``@radix-ui/react-select``class-variance-authority``clsx``tailwind-merge`。; 新增 `web/src/lib/utils.ts``cn` 工具函数)。; 新增组件:`web/src/components/ui/{button,input,textar
- confidence: 0.00
- evidence: memory/2026-04-17.md:301-304
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17): 迁移 `web/src/app/admin/todos/page.tsx``ListBox/Modal/HeroTable` 替换为 `Select/Dialog/Table`
- confidence: 0.00
- evidence: memory/2026-04-17.md:305-305
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17): `npm run lint:web` 通过。; `npm run build:web` 通过(`/admin/todos` 在构建路由中生成)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:307-308
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17): 仅首批页面迁移完成;其余后台页面若后续接入旧 API 需要按同一组件语义继续替换。
- confidence: 0.00
- evidence: memory/2026-04-17.md:310-310
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase B): 背景: 用户确认继续执行组件统一的阶段 B(表单控件统一)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:314-314
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase B): `web/src/app/admin/requirements/page.tsx`:筛选区统一为 `Input + Select`。; `web/src/app/admin/requirements/new/page.tsx`:创建表单统一为 `Input + Select + TextArea`。; `web/src/app/admin/requirements/[id]/page.tsx`:编辑区、处理动作区、评论区统一为 `Input + Select + TextArea`。; `w
- confidence: 0.00
- evidence: memory/2026-04-17.md:316-319
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase B): `web/src/app/admin/models/page.tsx`:筛选与模型/路由表单统一为 `Input + Select + TextArea`。; `web/src/app/admin/users/page.tsx`:新增用户表单统一为 `Input`
- confidence: 0.00
- evidence: memory/2026-04-17.md:320-321
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase B): 阶段 B 未处理手写弹窗统一(`/admin/models``/admin/roles` 仍为手写弹窗结构),属于阶段 C 范围。
- confidence: 0.00
- evidence: memory/2026-04-17.md:326-326
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase B Closure): 背景: 用户要求“收尾阶段 B”。
- confidence: 0.00
- evidence: memory/2026-04-17.md:330-330
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase B Closure): 扫描 `web/src/app/admin/**`:无原生 `select/textarea``className=\"control\"` 表单控件写法。; `npm run lint:web` 通过。; `npm run build:web` 通过(后台路由全部正常生成)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:334-336
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase C): 背景: 用户要求进入阶段 C(弹窗统一)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:342-342
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase C): `web/src/app/admin/roles/page.tsx`; 手写遮罩弹窗替换为 `Dialog + DialogContent`。; 弹窗表单输入统一为 `Input`(移除 `control` 输入写法)。; `web/src/app/admin/models/page.tsx`
- confidence: 0.00
- evidence: memory/2026-04-17.md:344-347
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase C): 模型维护弹窗与路由规则弹窗均替换为 `Dialog + DialogContent`。; 保留原有打开/关闭、重置表单、提交逻辑。
- confidence: 0.00
- evidence: memory/2026-04-17.md:348-349
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase C): `rg -n "fixed inset-0 z-50|role=\"dialog\"" web/src/app/admin/models/page.tsx web/src/app/admin/roles/page.tsx` 无命中。; `npm run lint:web` 通过。; `npm run build:web` 通过(`/admin/models``/admin/roles` 路由正常生成)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:351-353
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Phase C): 低风险 UI 改造;建议后续人工点测弹窗外部点击关闭与 ESC 关闭行为。
- confidence: 0.00
- evidence: memory/2026-04-17.md:355-355
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Docker compose 不更新排查): 背景: 用户反馈执行 `docker compose up -d` 后,`localhost:3000` 页面看起来没有更新。
- confidence: 0.00
- evidence: memory/2026-04-17.md:359-359
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Docker compose 不更新排查): `web` 服务在 `docker-compose.yml` 中未挂载源码目录(无 `volumes`),运行的是镜像内的 Next.js 生产构建产物。; `docker compose up -d` 默认不会触发镜像重建;只有 `docker compose up --build -d`(或先 `docker compose build`)才会把源码变更打进镜像。
- confidence: 0.00
- evidence: memory/2026-04-17.md:361-362
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Docker compose 不更新排查): `docker compose up --build -d web` 输出显示 `web` 构建步骤(含 `npm run build`)命中 `CACHED`,说明无新变更触发重编译。; 重建后 `fquiz-web` 镜像 ID/创建时间保持不变:`sha256:b927e876...` / `2026-04-17T16:29:09+08:00`。; 运行中容器 `BUILD_ID``xX7yUgf0PsryIJmCeZcPW`,与响应页面中的构建标识一致
- confidence: 0.00
- evidence: memory/2026-04-17.md:364-366
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, Docker compose 不更新排查): 前端改动后使用 `docker compose up --build -d web`(或根脚本 `npm run docker:up`)。; 若仍感觉未更新,先做浏览器强制刷新(`Ctrl+F5` / `Cmd+Shift+R`)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:368-369
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): 背景: 用户要求“改用 Radix 的主题”,希望页面配色/风格与 Radix 主题体系一致。
- confidence: 0.00
- evidence: memory/2026-04-17.md:373-373
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): `web/package.json` / `web/package-lock.json`:新增 `@radix-ui/themes` 依赖。; `web/src/app/layout.tsx`; 引入 `@radix-ui/themes/styles.css`。; 根布局注入 `<Theme accentColor="cyan" grayColor="slate" radius="medium" scaling="100%">`
- confidence: 0.00
- evidence: memory/2026-04-17.md:375-378
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): 新增 `app-theme-root` 包裹层承接主题背景与全局色彩。; `web/src/app/globals.css`; 色板改为基于 Radix token`--gray-*` / `--accent-*` / `--red-*` / `--green-*`)。; 保留既有语义类名(`surface-card``btn-*``control``table-*`),将实现切到 Radix token。
- confidence: 0.00
- evidence: memory/2026-04-17.md:379-382
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): 新增 `dialog-*``select-*``checkbox-control` 等样式类。; `web/src/components/ui/{button,checkbox,dialog,select}.tsx`; 组件 className 改为引用上述语义样式类,移除硬编码 `slate/cyan` 色值。
- confidence: 0.00
- evidence: memory/2026-04-17.md:383-385
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): `npm run build:web` 通过(Next.js 16 构建成功,`/admin/models``/admin/roles` 等路由正常生成)。
- confidence: 0.00
- evidence: memory/2026-04-17.md:387-387
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): 主题 token 变更会影响全站后台页面视觉,建议人工回归关键页面(`/admin/models``/admin/roles``/admin/requirements`)确认对比度与交互态表现。
- confidence: 0.00
- evidence: memory/2026-04-17.md:389-389
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): 追加修正(Docker Alpine 构建):; 触发问题:`docker compose up --build -d web``RUN npm run build` 阶段报错 `Cannot find module '../lightningcss.linux-x64-musl.node'`。; 原因:`web/package-lock.json` 丢失 musl 二进制锁条目(`lightningcss-linux-x64-musl` / `@tailwindcss/
- confidence: 0.00
- evidence: memory/2026-04-17.md:391-394
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 切换 Radix Theme): 结果:`docker compose up --build -d web` 成功;`fquiz-web` 容器正常启动,`/admin` 响应中可见 `radix-themes` 根节点与主题数据属性。
- confidence: 0.00
- evidence: memory/2026-04-17.md:395-395
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 主题色切换为 Indigo): 背景: 用户要求“改主题色”。
- confidence: 0.00
- evidence: memory/2026-04-17.md:399-399
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 主题色切换为 Indigo): `web/src/app/layout.tsx``Theme accentColor``cyan` 调整为 `indigo`。; 后台页面残留硬编码 `cyan` Tailwind 类统一替换为 `indigo`,覆盖文件:; `web/src/app/admin/layout.tsx`; `web/src/app/admin/page.tsx`
- confidence: 0.00
- evidence: memory/2026-04-17.md:401-404
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 主题色切换为 Indigo): `web/src/app/admin/chat/page.tsx`; `web/src/app/admin/files/page.tsx`; `web/src/app/admin/users/page.tsx`; `web/src/app/admin/requirements/[id]/page.tsx`(仅颜色相关类)
- confidence: 0.00
- evidence: memory/2026-04-17.md:405-408
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 主题色切换为 Indigo): 对应阴影色中的 `rgba(8,145,178,...)` 同步替换为 `rgba(79,70,229,...)`,避免仍呈现青色阴影。
- confidence: 0.00
- evidence: memory/2026-04-17.md:409-409
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 主题色切换为 Indigo): `npm run lint:web` 通过。; `npm run build:web` 通过。; `docker compose up --build -d web` 通过,`fquiz-web` 容器正常启动。; `curl http://localhost:3000/admin` 响应中 `data-accent-color=\"indigo\"` 生效。
- confidence: 0.00
- evidence: memory/2026-04-17.md:411-414
- recalls: 0
- status: staged
- Candidate: Work Log (2026-04-17, 主题色切换为 Indigo): 部分页面仍存在 `sky-*` 辅助渐变色(非主强调色),如需完全统一到单一主题色可在下一步继续收口。
- confidence: 0.00
- evidence: memory/2026-04-17.md:416-416
- recalls: 0
- status: staged
- Candidate: 背景: 用户确认在现有 `fquiz` 系统内先落地 AI 聊天功能(先方案确认,再开发),要求最小改动闭环。
- confidence: 0.00
- evidence: memory/2026-04-13.md:5-5
- recalls: 0
- status: staged
- Candidate: 改动: 后端新增聊天域(FastAPI + SQLAlchemy):; 新增模型:`api/app/models/chat.py`; `chat_sessions`; `chat_messages`
- confidence: 0.00
- evidence: memory/2026-04-13.md:9-12
- recalls: 0
- status: staged
- Candidate: 改动: 新增 Schema`api/app/schemas/chat.py`
- confidence: 0.00
- evidence: memory/2026-04-13.md:13-13
- recalls: 0
- status: staged
- Candidate: 改动: `api/app/services/chat_service.py`(会话/消息读写与发送主流程); `api/app/services/llm_gateway.py`(模型路由解析 + OpenAI-compatible 调用); 新增路由:`api/app/api/v1/chat.py`; `GET /api/v1/chat/sessions`
- confidence: 0.00
- evidence: memory/2026-04-13.md:15-18
- recalls: 0
- status: staged
- Candidate: 改动: `POST /api/v1/chat/sessions`; `GET /api/v1/chat/sessions/{session_id}/messages`; `POST /api/v1/chat/sessions/{session_id}/messages`
- confidence: 0.00
- evidence: memory/2026-04-13.md:19-21
- recalls: 0
- status: staged
- Candidate: 改动: `api/app/api/router.py` 挂载 `chat` 路由; `api/app/models/__init__.py``api/app/core/database.py` 注册聊天模型确保 `create_all` 生效
- confidence: 0.00
- evidence: memory/2026-04-13.md:23-24
- recalls: 0
- status: staged
- Candidate: 改动: 聊天模型与密钥策略:; 复用模型管理路由规则,解析顺序:; `CAPABILITY: chat.default`; `GLOBAL: __global__`
- confidence: 0.00
- evidence: memory/2026-04-13.md:26-29
- recalls: 0
- status: staged
- Candidate: 改动: 仅命中 `ENABLED` 且存在激活密钥记录的模型。; 运行时 key 从环境变量读取,不反解库内 hash:; `LLM_PROVIDER_API_KEYS``openai=sk-...` 或 JSON)。
- confidence: 0.00
- evidence: memory/2026-04-13.md:30-32
- recalls: 0
- status: staged
- Candidate: 背景: GitHub Actions 构建 API 镜像时,`pip install -r requirements.txt` 多次出现 `ReadTimeoutError``files.pythonhosted.org` / `pypi.org`)。
- confidence: 0.00
- evidence: memory/2026-04-12.md:5-5
- recalls: 0
- status: staged
- Candidate: 改动: 更新 `api/Dockerfile`; 新增构建参数 `PIP_INDEX_URL`(默认 `https://pypi.org/simple`)。; 新增构建参数 `PIP_DEFAULT_TIMEOUT`(默认 `120`)。; `pip install` 增加 `--retries 8 --timeout "${PIP_DEFAULT_TIMEOUT}" -i "${PIP_INDEX_URL}"`
- confidence: 0.00
- evidence: memory/2026-04-12.md:9-12
- recalls: 0
- status: staged
- Candidate: 改动: 设置 `PIP_DISABLE_PIP_VERSION_CHECK=1`。; 更新 `.github/workflows/main.yml`; API 镜像构建新增 `build-args`; `PIP_INDEX_URL=${{ secrets.PIP_INDEX_URL || vars.PIP_INDEX_URL || 'https://pypi.org/simple' }}`
- confidence: 0.00
- evidence: memory/2026-04-12.md:13-16
- recalls: 0
- status: staged
- Candidate: 改动: `PIP_DEFAULT_TIMEOUT=${{ vars.PIP_DEFAULT_TIMEOUT || '120' }}`; 更新 `api/requirements.txt`:; 从宽范围约束改为精确版本,减少 pip 解析回溯与重复下载。
- confidence: 0.00
- evidence: memory/2026-04-12.md:17-19
- recalls: 0
- status: staged
- Candidate: 验证: 本地触发 `docker build -f api/Dockerfile api --build-arg PIP_INDEX_URL=https://pypi.org/simple --build-arg PIP_DEFAULT_TIMEOUT=120`
- confidence: 0.00
- evidence: memory/2026-04-12.md:23-23
- recalls: 0
- status: staged
- Candidate: 验证: 新的 `pip install` 参数生效。; 发生网络超时时会触发 `Retry(total=...)` 重试逻辑,而非首次超时直接失败。
- confidence: 0.00
- evidence: memory/2026-04-12.md:25-26
- recalls: 0
- status: staged
- Candidate: 风险与备注: 受网络质量影响,构建时长可能显著增加。; 若目标环境访问 `pypi.org` 不稳定,需在 GitHub Secrets/Variables 配置更近的 `PIP_INDEX_URL`
- confidence: 0.00
- evidence: memory/2026-04-12.md:30-31
- recalls: 0
- status: staged
- Candidate: 追加修正(同日): 触发问题:`No matching distribution found for websockets>=10.4; extra == "standard"`。; 原因:`uvicorn[standard]` 会强依赖 `websockets`;在当前包源下解析失败。
- confidence: 0.00
- evidence: memory/2026-04-12.md:35-36
- recalls: 0
- status: staged
- Candidate: Reflections: Theme: `追加` kept surfacing across 57 memories.; confidence: 0.83; evidence: memory/2026-04-12.md:35-36, memory/2026-04-12.md:38-40, memory/2026-04-12.md:44-46; note: reflection
- confidence: 0.00
- evidence: memory/2026-04-14.md:503-506
- recalls: 0
- status: staged
- Candidate: Possible Lasting Truths: No strong candidate truths surfaced.
- confidence: 0.00
- evidence: memory/2026-04-14.md:509-509
- recalls: 0
- status: staged
- Candidate: Reflections: No strong patterns surfaced.
- confidence: 0.00
- evidence: memory/2026-04-17.md:253-253
- recalls: 0
- status: staged
<!-- openclaw:dreaming:light:end -->
## REM Sleep
<!-- openclaw:dreaming:rem:start -->
### Reflections
- Theme: `log` kept surfacing across 157 memories.
- confidence: 0.95
- evidence: memory/2026-04-17.md:154-154, memory/2026-04-17.md:160-160, memory/2026-04-17.md:162-163
- note: reflection
### Possible Lasting Truths
- No strong candidate truths surfaced.
<!-- openclaw:dreaming:rem:end -->
## Work Log (2026-04-17)
- 背景: 用户要求停止使用 HeroUI,改用 `shadcn/ui + Radix UI`,并给出改造计划。
- 改动:
- `web/package.json` / `web/package-lock.json`:移除 `@heroui/react`,新增 `@radix-ui/react-dialog``@radix-ui/react-select``class-variance-authority``clsx``tailwind-merge`
- 新增 `web/src/lib/utils.ts``cn` 工具函数)。
- 新增组件:`web/src/components/ui/{button,input,textarea,checkbox,dialog,select,table}.tsx`
- 重写 `web/src/components/ui.tsx` 为统一导出层,保持 `@/components/ui` 引用入口不变。
- 迁移 `web/src/app/admin/todos/page.tsx``ListBox/Modal/HeroTable` 替换为 `Select/Dialog/Table`
- 验证:
- `npm run lint:web` 通过。
- `npm run build:web` 通过(`/admin/todos` 在构建路由中生成)。
- 风险:
- 仅首批页面迁移完成;其余后台页面若后续接入旧 API 需要按同一组件语义继续替换。
## Work Log (2026-04-17, Phase B)
- 背景: 用户确认继续执行组件统一的阶段 B(表单控件统一)。
- 改动:
- `web/src/app/admin/requirements/page.tsx`:筛选区统一为 `Input + Select`
- `web/src/app/admin/requirements/new/page.tsx`:创建表单统一为 `Input + Select + TextArea`
- `web/src/app/admin/requirements/[id]/page.tsx`:编辑区、处理动作区、评论区统一为 `Input + Select + TextArea`
- `web/src/app/admin/menus/page.tsx`:筛选与编辑表单统一为 `Input + Select`
- `web/src/app/admin/models/page.tsx`:筛选与模型/路由表单统一为 `Input + Select + TextArea`
- `web/src/app/admin/users/page.tsx`:新增用户表单统一为 `Input`
- 验证:
- `npm run lint:web` 通过。
- `npm run build:web` 通过(`/admin/menus``/admin/models``/admin/requirements*``/admin/users` 均出现在构建路由产物)。
- 风险:
- 阶段 B 未处理手写弹窗统一(`/admin/models``/admin/roles` 仍为手写弹窗结构),属于阶段 C 范围。
## Work Log (2026-04-17, Phase B Closure)
- 背景: 用户要求“收尾阶段 B”。
- 改动:
- `web/src/app/admin/chat/page.tsx`:聊天输入从原生 `textarea` 统一为 `@/components/ui``TextArea`
- 验证:
- 扫描 `web/src/app/admin/**`:无原生 `select/textarea``className=\"control\"` 表单控件写法。
- `npm run lint:web` 通过。
- `npm run build:web` 通过(后台路由全部正常生成)。
- 结论:
- 阶段 B(表单控件统一)已完整闭环。
## Work Log (2026-04-17, Phase C)
- 背景: 用户要求进入阶段 C(弹窗统一)。
- 改动:
- `web/src/app/admin/roles/page.tsx`
- 手写遮罩弹窗替换为 `Dialog + DialogContent`
- 弹窗表单输入统一为 `Input`(移除 `control` 输入写法)。
- `web/src/app/admin/models/page.tsx`
- 模型维护弹窗与路由规则弹窗均替换为 `Dialog + DialogContent`
- 保留原有打开/关闭、重置表单、提交逻辑。
- 验证:
- `rg -n "fixed inset-0 z-50|role=\"dialog\"" web/src/app/admin/models/page.tsx web/src/app/admin/roles/page.tsx` 无命中。
- `npm run lint:web` 通过。
- `npm run build:web` 通过(`/admin/models``/admin/roles` 路由正常生成)。
- 风险:
- 低风险 UI 改造;建议后续人工点测弹窗外部点击关闭与 ESC 关闭行为。
## Work Log (2026-04-17, Docker compose 不更新排查)
- 背景: 用户反馈执行 `docker compose up -d` 后,`localhost:3000` 页面看起来没有更新。
- 结论:
- `web` 服务在 `docker-compose.yml` 中未挂载源码目录(无 `volumes`),运行的是镜像内的 Next.js 生产构建产物。
- `docker compose up -d` 默认不会触发镜像重建;只有 `docker compose up --build -d`(或先 `docker compose build`)才会把源码变更打进镜像。
- 证据:
- `docker compose up --build -d web` 输出显示 `web` 构建步骤(含 `npm run build`)命中 `CACHED`,说明无新变更触发重编译。
- 重建后 `fquiz-web` 镜像 ID/创建时间保持不变:`sha256:b927e876...` / `2026-04-17T16:29:09+08:00`
- 运行中容器 `BUILD_ID``xX7yUgf0PsryIJmCeZcPW`,与响应页面中的构建标识一致。
- 建议:
- 前端改动后使用 `docker compose up --build -d web`(或根脚本 `npm run docker:up`)。
- 若仍感觉未更新,先做浏览器强制刷新(`Ctrl+F5` / `Cmd+Shift+R`)。
## Work Log (2026-04-17, 切换 Radix Theme)
- 背景: 用户要求“改用 Radix 的主题”,希望页面配色/风格与 Radix 主题体系一致。
- 改动:
- `web/package.json` / `web/package-lock.json`:新增 `@radix-ui/themes` 依赖。
- `web/src/app/layout.tsx`
- 引入 `@radix-ui/themes/styles.css`
- 根布局注入 `<Theme accentColor="cyan" grayColor="slate" radius="medium" scaling="100%">`
- 新增 `app-theme-root` 包裹层承接主题背景与全局色彩。
- `web/src/app/globals.css`
- 色板改为基于 Radix token`--gray-*` / `--accent-*` / `--red-*` / `--green-*`)。
- 保留既有语义类名(`surface-card``btn-*``control``table-*`),将实现切到 Radix token。
- 新增 `dialog-*``select-*``checkbox-control` 等样式类。
- `web/src/components/ui/{button,checkbox,dialog,select}.tsx`
- 组件 className 改为引用上述语义样式类,移除硬编码 `slate/cyan` 色值。
- 验证:
- `npm run build:web` 通过(Next.js 16 构建成功,`/admin/models``/admin/roles` 等路由正常生成)。
- 风险:
- 主题 token 变更会影响全站后台页面视觉,建议人工回归关键页面(`/admin/models``/admin/roles``/admin/requirements`)确认对比度与交互态表现。
- 追加修正(Docker Alpine 构建):
- 触发问题:`docker compose up --build -d web``RUN npm run build` 阶段报错 `Cannot find module '../lightningcss.linux-x64-musl.node'`
- 原因:`web/package-lock.json` 丢失 musl 二进制锁条目(`lightningcss-linux-x64-musl` / `@tailwindcss/oxide-linux-x64-musl`),导致 Alpine 容器内 `npm ci` 未安装对应可选依赖。
- 处理:在 `web/package-lock.json` 补回上述 musl 包条目后重建镜像。
- 结果:`docker compose up --build -d web` 成功;`fquiz-web` 容器正常启动,`/admin` 响应中可见 `radix-themes` 根节点与主题数据属性。
## Work Log (2026-04-17, 主题色切换为 Indigo)
- 背景: 用户要求“改主题色”。
- 改动:
- `web/src/app/layout.tsx``Theme accentColor``cyan` 调整为 `indigo`
- 后台页面残留硬编码 `cyan` Tailwind 类统一替换为 `indigo`,覆盖文件:
- `web/src/app/admin/layout.tsx`
- `web/src/app/admin/page.tsx`
- `web/src/app/admin/chat/page.tsx`
- `web/src/app/admin/files/page.tsx`
- `web/src/app/admin/users/page.tsx`
- `web/src/app/admin/requirements/[id]/page.tsx`(仅颜色相关类)
- 对应阴影色中的 `rgba(8,145,178,...)` 同步替换为 `rgba(79,70,229,...)`,避免仍呈现青色阴影。
- 验证:
- `npm run lint:web` 通过。
- `npm run build:web` 通过。
- `docker compose up --build -d web` 通过,`fquiz-web` 容器正常启动。
- `curl http://localhost:3000/admin` 响应中 `data-accent-color=\"indigo\"` 生效。
- 风险:
- 部分页面仍存在 `sky-*` 辅助渐变色(非主强调色),如需完全统一到单一主题色可在下一步继续收口。
## Work Log (2026-04-17, 修复 web 构建 TypeScript onChange 类型阻断)
- 背景: 用户反馈 `docker build web``web/src/app/admin/models/page.tsx` 报错,`TextField.Root``onChange` 使用了 `ChangeEvent<HTMLTextAreaElement>` 导致类型不兼容。
- 改动:
- `web/src/app/admin/models/page.tsx`:将路由规则“备注”输入从 `TextField.Root` 改为 `TextArea`,并保留 `ChangeEvent<HTMLTextAreaElement>` 处理。
- 进一步收口同类阻断(`onChange` 参数隐式 `any`):
- `web/src/app/admin/requirements/new/page.tsx`
- `web/src/app/admin/requirements/page.tsx`
- `web/src/app/admin/requirements/[id]/page.tsx`
- `web/src/app/admin/todos/page.tsx`
- `web/src/app/admin/roles/page.tsx`
- `web/src/app/admin/users/page.tsx`
- 统一为 `ChangeEvent<HTMLInputElement>` / `ChangeEvent<HTMLTextAreaElement>`,并使用 `event.currentTarget` 取值。
- 验证:
- `npm run build:web` 通过(Next.js 16 + TypeScript 校验通过,`/admin/models``/admin/requirements*``/admin/todos``/admin/roles``/admin/users` 均在构建路由列表中)。
- 风险:
- 仅调整前端事件类型与输入组件语义,不改变接口请求结构与业务流程,风险低。