From fa01b1cb9704aa1a94f97814b5609720ad8b9cb3 Mon Sep 17 00:00:00 2001 From: weijuesen Date: Wed, 12 Aug 2026 16:16:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E7=9F=A5=E8=AF=86=E5=BA=93?= =?UTF-8?q?=E5=9B=BE=E8=B0=B1=E9=A2=84=E8=A7=88=E4=B8=8E=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=88CSP=20=E6=94=BE=E8=A1=8C=20S3=20?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E6=BA=90=20+=20imageUrl=20=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - server.cjs: img-src 放行 http://100.83.103.1:7480,修复编辑页预览图被 CSP 拦截 - Knowledge.tsx: 新增隐藏 Form.Item name=imageUrl,修复 validateFields 提交时丢弃图片 URL - 部署至 100.83.103.1:5174(备份 /home/pan/backups/web-20260812-1605) - 补绑白僵病 image_url(UPDATE 1),更新故障排查/开发交接/变更记录 --- web/server.cjs | 2 +- web/src/pages/Knowledge.tsx | 4 +++ 变更记录.md | 24 ++++++++++++++++ 开发交接记录.md | 27 ++++++++++++++++++ 故障排查处理记录.md | 55 +++++++++++++++++++++++++++++++++++++ 5 files changed, 111 insertions(+), 1 deletion(-) diff --git a/web/server.cjs b/web/server.cjs index 838b5dc..4a814e2 100644 --- a/web/server.cjs +++ b/web/server.cjs @@ -24,7 +24,7 @@ const SECURITY_HEADERS = { 'X-Frame-Options': 'DENY', 'Referrer-Policy': 'no-referrer', 'Content-Security-Policy': - "default-src 'self'; img-src 'self' data: blob:; media-src 'self' blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:; font-src 'self' data:; object-src 'none'; frame-ancestors 'none'", + "default-src 'self'; img-src 'self' data: blob: http://100.83.103.1:7480; media-src 'self' blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:; font-src 'self' data:; object-src 'none'; frame-ancestors 'none'", 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains', }; diff --git a/web/src/pages/Knowledge.tsx b/web/src/pages/Knowledge.tsx index b49b03a..16543da 100644 --- a/web/src/pages/Knowledge.tsx +++ b/web/src/pages/Knowledge.tsx @@ -183,6 +183,10 @@ function DiseaseTab() { )} + {/* imageUrl 通过隐藏字段注册到表单,保证 validateFields 提交时携带(修复:未注册字段会被丢弃) */} + diff --git a/变更记录.md b/变更记录.md index 9802e06..98896c1 100644 --- a/变更记录.md +++ b/变更记录.md @@ -1,5 +1,29 @@ # 变更记录 +## 2026-08-12 Web 知识库图谱预览与保存修复(故障排查 #三十二) + +### 变更背景 + +用户反馈 Web 知识库上传新症状图谱后编辑页预览图打不开、提交后图谱未保存。排查确认上传与存储正常(Ceph 对象存在、匿名 GET 200),问题在前端:CSP 拦截跨源预览 + 表单未注册 `imageUrl` 导致提交体缺失该字段。 + +### 变更内容 + +| 文件 | 变更 | +|------|------| +| `web/src/pages/Knowledge.tsx` | 新增隐藏 `Form.Item name="imageUrl"`,使 `validateFields()` 提交时携带图片 URL | +| `web/server.cjs` | CSP `img-src` 增加 `http://100.83.103.1:7480`(开发 S3 源) | + +### 部署与验证 + +- 本地:`npm run lint`(通过)、`npm run build`(通过,新 bundle `index-CSVEb7gG.js`)。 +- 部署:备份 `/home/pan/backups/web-20260812-1605/`(旧 dist、server.cjs、web.log),上传新产物并重启 node。 +- 验证:`http://localhost:5174/` 200;CSP 头含 S3 源;新 bundle 200;`/api/v1/health` 200;DB 白僵病 `image_url` 已补绑(`UPDATE 1`),图片匿名 GET 200。 + +### 回滚点 + +- 前端:恢复 `/home/pan/backups/web-20260812-1605/` 旧产物后重启 node。 +- 数据:`/home/pan/backups/diseases-20260812-1605.dump`(pg_restore),或执行反向 UPDATE 将 `image_url` 置空。 + ## 2026-08-12 知识库初始版开发与部署 ### 变更背景 diff --git a/开发交接记录.md b/开发交接记录.md index 36ca7d0..1f008e9 100644 --- a/开发交接记录.md +++ b/开发交接记录.md @@ -12,6 +12,33 @@ --- +## 2026-08-12 补充:Web 知识库图谱预览与保存修复(故障排查 #三十二) + +### 做了什么 + +- 修复 Web 知识库「蚕病百科」两个问题:编辑页图谱预览打不开(CSP 拦截跨源 S3 图片)、提交后 `imageUrl` 未保存(表单未注册该字段)。 +- `web/src/pages/Knowledge.tsx`:「症状图谱图片」后新增隐藏 `Form.Item name="imageUrl"`,保证 `form.validateFields()` 提交时携带图片 URL。 +- `web/server.cjs`:CSP `img-src` 放行 `http://100.83.103.1:7480`(开发 S3 源)。 +- 已部署并重启前端(新 bundle `index-CSVEb7gG.js`),并按用户确认直接改库把白僵病已上传的图谱 URL 补绑到 `diseases.image_url`。 + +### 思路与决策 + +- 根因定位:日志显示上传 200、PATCH 200,但 `image_url` 为空 → 定位为前端表单未注册 `imageUrl`(antd `validateFields()` 只返回已注册字段),以及 CSP 跨源拦截预览。 +- 修复方式:用隐藏 `Form.Item` 注册字段(antd 标准做法),避免手工拼请求体;CSP 采用放行开发 S3 源,生产切云 OSS/COS 时再替换为 OSS/CDN 域名或改同源代理。 +- 数据补绑:用户明确选择「直接改库」,回滚点为备份的 `diseases` 表 dump 与逐行 UPDATE 反向语句。 + +### 验证 + +- `web`:`npm run lint` 通过(仅既有无关警告)、`npm run build` 通过。 +- 机制红绿验证:用 rc-field-form 验证 `validateFields()` 会丢弃未注册的 `imageUrl`,注册/合并后可携带。 +- 部署验证:`http://localhost:5174/` 200;CSP 头含 `http://100.83.103.1:7480`;新 bundle 200;`/api/v1/health` 200;bundle 中可见 `name:"imageUrl", hidden:!0`。 +- 数据验证:`UPDATE 1`;查询确认白僵病 `image_url` 已绑定;图片匿名 GET 200(image/jpeg)。 + +### 回滚点 + +- 前端:`/home/pan/backups/web-20260812-1605/`(旧 dist、server.cjs、web.log)恢复后重启 node。 +- 数据:`diseases` 表 dump `/home/pan/backups/diseases-20260812-1605.dump`;或执行 `UPDATE diseases SET image_url=NULL, updated_at=now() WHERE id='17b1cae4-21cc-4996-9db3-96f785aef800';` + ## 2026-08-12 模块:知识库初始版(计划 #10) ### 做了什么 diff --git a/故障排查处理记录.md b/故障排查处理记录.md index 717a26d..2497291 100644 --- a/故障排查处理记录.md +++ b/故障排查处理记录.md @@ -1023,3 +1023,58 @@ APP 使用 `react-native-vector-icons` 的 `MaterialCommunityIcons` 字体渲染 - `ScrollView` 的 `style` 设置容器样式(如 flex、背景色),`contentContainerStyle` 设置内容样式(如 padding) - 仅修改 JS/TS 代码,Metro reload 即可生效,无需重新构建 APK +--- + +## 三十二、Web 知识库症状图谱预览打不开且保存不生效 + +**现象**:Web「知识库 → 蚕病百科」编辑病种时上传新的症状图谱:编辑弹窗里的预览图打不开;点击提交提示"保存成功",但重新打开/刷新后图谱仍未绑定(`image_url` 为空)。 + +**原因(两个独立问题,均为前端问题,后端与存储正常)**: + +1. **预览图打不开:CSP 拦截跨源图片** + `web/server.cjs` 的 `Content-Security-Policy` 为 `img-src 'self' data: blob:`,只允许同源图片。上传成功后返回的图片 URL 是 `http://100.83.103.1:7480/silk-images/...`(Ceph RGW,端口 7480 与页面 5174 不同源),浏览器直接拦截,图片本身可匿名访问(200 image/jpeg)。 + +2. **保存不生效:`imageUrl` 未注册到表单,提交时被丢弃** + `web/src/pages/Knowledge.tsx` 上传成功后执行 `form.setFieldValue('imageUrl', res.url)`,但「症状图谱图片」的 `Form.Item` 只有 label、没有 `name="imageUrl"`。antd 的 `form.validateFields()` 只返回已注册(有 `Form.Item name`)的字段,`imageUrl` 不在其中,因此 `PATCH /knowledge/diseases/:id` 的请求体里根本没有 `imageUrl`,后端收到 200 但 `image_url` 列不更新(`updated_at` 会变)。 + +**排查证据(开发服务器 100.83.103.1)**: +- `web/web.log`:`POST /api/v1/knowledge/images` → `PATCH /api/v1/knowledge/diseases/17b1cae4-21cc-4996-9db3-96f785aef800` → `GET /api/v1/knowledge/diseases` +- `server-go/server-go.log`(实际生效日志,非 `/home/pan/silk/server-go.log`):15:57:54 `POST images` 200;15:58:03 `PATCH` 200 +- Ceph `silk-images` 桶:存在 `knowledge/20260812/36a2bc56e466fb41.jpeg`(286608 字节,image/jpeg),匿名 GET 200 +- PostgreSQL:白僵病 `image_url` 为 NULL;全表无任何病种有 `image_url` +- 部署产物校验:服务器 `server.cjs` md5 与仓库一致(CSP 生效);新 bundle 中已含修复代码 + +**处理**: + +1. 前端修复(`web/src/pages/Knowledge.tsx`、`web/server.cjs`): + - 「症状图谱图片」后新增隐藏字段,使 `imageUrl` 注册进表单并被 `validateFields()` 返回: + ```tsx + + ``` + - CSP `img-src` 放行开发环境 S3 源:`img-src 'self' data: blob: http://100.83.103.1:7480` +2. 构建与部署(本地 `npm run lint`、`npm run build` 均通过): + - 备份旧产物:`/home/pan/backups/web-20260812-1605/`(dist、server.cjs、web.log) + - 上传新 `dist` 与 `server.cjs`,重启 node(旧 pid 3764542 → 新 pid 3803472) + - 验证:`http://localhost:5174/` 200;CSP 头含 `http://100.83.103.1:7480`;新 bundle `index-CSVEb7gG.js` 200;`/api/v1/health` 200 +3. 数据补绑(用户确认直接改库): + ```sql + UPDATE diseases + SET image_url = 'http://100.83.103.1:7480/silk-images/knowledge/20260812/36a2bc56e466fb41.jpeg', + updated_at = now() + WHERE id = '17b1cae4-21cc-4996-9db3-96f785aef800'; + ``` + 结果:`UPDATE 1`,查询确认 `image_url` 已写入;图片匿名 GET 200。 + +**验证结果**:DB 行已绑定图谱 URL;CSP 已放行;部署产物包含隐藏字段注册;lint/build 通过(详见上文)。 + +**回滚点**: +- 前端回滚:恢复 `/home/pan/backups/web-20260812-1605/` 下的旧 `dist`/`server.cjs` 并重启 node +- 数据回滚:`UPDATE diseases SET image_url = NULL, updated_at = now() WHERE id = '17b1cae4-21cc-4996-9db3-96f785aef800';` 或 `pg_restore` 恢复 `/home/pan/backups/diseases-20260812-1605.dump` + +**注意事项**: +- `/home/pan/silk` 不是 git 仓库,无法打 tag 回滚,只能依赖文件备份(本次已备份) +- 部署指南中的 `admin/admin123` 已无法登录(401 用户名或密码错误),本次 API 冒烟改用 DB 直接验证;如需 API 级冒烟请先确认当前 admin 密码 +- 已知边界:编辑页若点「移除」图片再保存,`imageUrl` 会以 `undefined` 提交(键被省略),不会清空库里已有图片;如需「移除即清空」后续应显式传 `null` +- CSP 当前放行的是开发服务器 IP;生产切云 OSS/COS 时需把 OSS/CDN 域名加入 `img-src`,或改为同源代理