11 KiB
经验记录
本文件用于记录项目修改过程中的关键问题与解决方案。每条经验使用四段式结构。
2026-05-04-02-38-48 建立代码编纂工作流
A. 具体问题
当前项目尚无统一的需求分析、实现方案、测试方案、经验沉淀和备份提交流程,后续修改容易缺少可追溯记录。
B. 产生问题原因
项目仍处于早期建设阶段,已有前端工程和医学影像数据资产,但尚未建立工程治理文档与固定执行规范。
C. 解决问题方案
创建 工程分析/ 目录,新增工程整体分析、代码编纂工作流、本次需求分析、实现方案、测试方案和经验记录文档。后续项目修改必须先写文档,并在实现方案和测试方案阶段等待用户二次人工审核确认。
D. 后续如何避免问题
每次项目修改前先记录时间戳并阅读 工程分析/工程整体分析.md 与 工程分析/经验记录.md。修改前写入需求、实现和测试文档,确认后再执行,完成后追加经验记录并提交 Gitea 备份。
2026-05-04-02-38-48 Gitea 推送后的本地凭据清理
A. 具体问题
使用带账号信息的一次性推送地址完成 Gitea push 后,本地 branch.main.remote 曾记录为带账号信息的 URL。
B. 产生问题原因
git push -u <url> main 会把该 <url> 记录为当前分支上游,而不是只使用已配置的 origin 名称。
C. 解决问题方案
将 origin 保持为不含账号信息的仓库地址,并把 branch.main.remote 改回 origin、branch.main.merge 改为 refs/heads/main。
D. 后续如何避免问题
后续推送时优先使用已配置好的 origin。如果必须临时带认证信息推送,推送后立即检查 git config --get-regexp 'branch\\.main|remote\\.origin',确保本地配置中没有保存账号密码。
2026-05-04-02-38-48 开发服务端口占用
A. 具体问题
本项目默认 Vite 端口 3000 已被 /home/wkmgc/Desktop/Seg_Server 的 node 服务占用,无法直接作为本项目部署端口。
B. 产生问题原因
同一机器上已有其他项目服务监听 0.0.0.0:3000。
C. 解决问题方案
不停止既有服务,改用 3001 端口启动当前项目的 Vite 服务,并通过 curl -I http://127.0.0.1:3001/ 验证返回 HTTP/1.1 200 OK。
D. 后续如何避免问题
部署前先使用 ss -ltnp 检查目标端口。如果默认端口被占用,优先选择相邻可用端口并在测试方案执行结果中记录实际访问地址。
2026-05-04-02-38-48 后台部署进程托管
A. 具体问题
使用普通 nohup 后台启动 Vite 时进程会静默退出,无法稳定保留服务。
B. 产生问题原因
当前命令执行环境会回收普通后台子进程,导致 nohup 方式没有形成稳定部署。
C. 解决问题方案
使用 tmux new-session -d -s revoxelseg-dicom 托管 Vite 服务,使开发服务脱离当前命令执行会话独立运行。
D. 后续如何避免问题
需要保留长时间运行的开发服务时,优先使用 tmux 会话托管,并用 tmux capture-pane -pt <session> 查看启动日志,用 curl 验证 HTTP 响应。
2026-05-04-03-08-20 附件 logo 落盘与静态资源引用
A. 具体问题
用户要求将 title 图标、登录页 logo 和左上角 logo 都替换为对话中提供的图片,需要把附件图片变为前端可稳定访问的静态资源。
B. 产生问题原因
前端组件不能直接引用对话附件,必须先将图片保存到项目静态资源目录,再通过固定 URL 引用。
C. 解决问题方案
确认 /tmp/logo_check.png 与用户提供的 logo 一致后,将其复制到 WebSite/public/logo.png。index.html favicon、登录页和侧边栏统一通过 /logo.png 引用。
D. 后续如何避免问题
后续涉及用户上传图片替换项目资源时,先在本地确认附件是否已落盘;优先放入 WebSite/public/ 并使用根路径引用,避免组件间重复存放资源。
2026-05-04-03-08-20 指定端口重新部署
A. 具体问题
用户要求将项目部署到 http://192.168.3.11:4000/,需要从原先 3001 端口切换到 4000。
B. 产生问题原因
项目早前使用 tmux 会话 revoxelseg-dicom 托管在 3001,本次需求指定了新的访问端口。
C. 解决问题方案
先检查 4000 端口是否空闲,然后关闭旧 revoxelseg-dicom 会话,使用同名 tmux 会话启动 Vite:node ./node_modules/vite/bin/vite.js --host 0.0.0.0 --port 4000 --strictPort。随后用本机地址和内网地址分别验证 HTTP 200。
D. 后续如何避免问题
每次调整部署端口前先检查端口占用和现有 tmux 会话;部署后同时验证 127.0.0.1 与目标内网 IP,并把实际访问地址写入测试方案执行结果。
2026-05-04-03-21-40 从纯前端演示升级为前后端协调系统
A. 具体问题
原系统登录、项目列表、用户列表、出厂重置和导出都是前端静态假数据,不同浏览器之间无法共享状态。
B. 产生问题原因
项目初始形态是 Vite/React 前端演示,没有后端 API、共享状态存储和统一部署入口。
C. 解决问题方案
新增 Express 后端 server.ts,用同一 4000 端口服务 API 和前端页面。后端通过 WebSite/data/state.json 维护演示状态,前端通过 /api/session 轮询同步登录状态,并将项目、用户、概况、重置和导出功能全部接入 API。
D. 后续如何避免问题
新增跨浏览器共享功能时,默认先判断状态是否必须由后端维护;涉及多浏览器一致性的功能不要放在组件静态数组或浏览器本地状态中。
2026-05-04-03-21-40 默认医学数据项目载入
A. 具体问题
项目列表需要默认载入 Head_CT_DICOM 和 Head_CT_ReConstruct,恢复演示环境出厂设置后也必须恢复这两个默认数据目录。
B. 产生问题原因
旧项目列表使用硬编码医疗项目示例,和当前仓库中的 DICOM/STL 数据资产没有建立关系。
C. 解决问题方案
后端启动和读取状态时扫描 Head_CT_DICOM 的 .dcm 数量与 Head_CT_ReConstruct 的 .stl 文件列表,生成默认项目 head-ct-demo。POST /api/demo/reset 使用同一逻辑重建默认项目。
D. 后续如何避免问题
演示数据入口统一放在后端默认项目构建函数中,避免多个页面分别硬编码 DICOM/STL 路径或数量。
2026-05-04-03-21-40 NIfTI 导出闭环
A. 具体问题
逆向工作区需要最终生成 nii 或 nii.gz 格式的分割 mask,而旧界面只有导出按钮,没有后端文件生成能力。
B. 产生问题原因
项目尚未实现真实 STL 到 DICOM 空间的体素化算法,也没有文件导出 API。
C. 解决问题方案
新增 POST /api/projects/:projectId/export-mask,后端生成 NIfTI-1 单文件 mask,并按请求输出 .nii 或 .nii.gz。.nii.gz 使用 Node zlib.gzipSync 压缩,并通过 Content-Disposition 触发下载。
D. 后续如何避免问题
导出类功能需要先定义后端接口、文件格式和校验命令。后续实现真实体素化时,可替换当前演示 mask 生成函数,但保留 API 和下载流程。
2026-05-04-03-21-40 Vite 中间件 HMR 端口冲突
A. 具体问题
Express + Vite 中间件启动时,默认 HMR WebSocket 端口 24678 被其他服务占用,日志出现端口冲突。
B. 产生问题原因
同一机器同时运行多个 Vite 服务,默认 HMR 端口可能重复。
C. 解决问题方案
在 createViteServer 中指定 server.hmr.port = 24679,使本项目后端服务使用独立 HMR 端口。
D. 后续如何避免问题
多项目并行部署时,除了业务端口外,也检查 Vite HMR 端口;发现冲突时为每个项目分配独立 HMR 端口。
2026-05-04-03-50-07 概况统计语义误导
A. 具体问题
项目总数只有 1 时,“已处理项目总数”也显示 1,容易让用户误解为系统已经完成真实处理。
B. 产生问题原因
旧统计把 status === completed 直接当作已处理项目,而默认演示项目为了表示数据可用被标记为 completed。
C. 解决问题方案
将概况卡片语义改为“已导出 Mask 项目”,后端按 exportedMaskCount > 0 统计;默认项目初始为 0,只有实际触发 mask 导出后才计入。
D. 后续如何避免问题
统计卡片必须反映明确业务事件,不要把演示数据可用状态和处理完成状态混在一起。
2026-05-04-03-50-07 DICOM 预览解析
A. 具体问题
项目库 DICOM 影像页看不到真实影像,只显示占位图形。
B. 产生问题原因
前端没有读取 DICOM 像素数据,后端也没有提供切片预览 API。
C. 解决问题方案
新增 GET /api/projects/:projectId/dicom-preview,后端解析当前 Little Endian DICOM 的 Rows、Columns、Window、Rescale 和 Pixel Data,返回 base64 灰度像素,前端用 canvas 绘制真实切片。
D. 后续如何避免问题
医学影像可视化应优先验证真实像素是否进入浏览器。后续扩展更多 DICOM 传输语法时,应把解析器替换为成熟 DICOM 库或 Python 预处理服务。
2026-05-04-03-50-07 STL 模型真实渲染
A. 具体问题
项目库 3D 模型页显示的是占位立方体,不是 Head_CT_ReConstruct 中的真实 STL。
B. 产生问题原因
前端没有 STLLoader,后端也没有安全暴露 STL 文件。
C. 解决问题方案
新增 GET /api/projects/:projectId/models/:fileName,仅允许读取项目 STL 列表中的文件;前端使用 Three.js STLLoader、Bounds 和 Center 加载并自动居中显示模型。
D. 后续如何避免问题
三维模型视图必须加载真实模型文件,不能长期使用占位几何体;后端文件服务要限制文件名和项目白名单,避免任意路径读取。
2026-05-04-03-50-07 Recharts 容器尺寸警告
A. 具体问题
控制台出现 Recharts 警告:图表宽高为 -1,需要检查容器尺寸。
B. 产生问题原因
图表在布局尚未稳定时渲染,ResponsiveContainer 从父容器拿到异常宽高。
C. 解决问题方案
为图表外层设置 min-w-0、固定高度和 min-h,并在 chartData 存在后再渲染 ResponsiveContainer,高度使用明确数值 300。
D. 后续如何避免问题
使用 Recharts 时保证父容器有稳定尺寸;在异步数据未到达前不要提前渲染响应式图表。
2026-05-04-03-50-07 Python 环境引入边界
A. 具体问题
用户提出如果需要 Python 可新建 conda 环境,但本次需求可以在现有 Node/React/Three.js 技术栈中完成。
B. 产生问题原因
DICOM/STL/Mask 功能既可以由前端演示链路实现,也可能进入 Python 医学影像算法链路,需要判断当前阶段是否真的需要 Python。
C. 解决问题方案
本次不创建 conda 环境,避免增加不必要复杂度;README 中说明当前构建方式和后续真实体素化阶段的 conda 环境建议。
D. 后续如何避免问题
只有当需要真实 DICOM 空间解析、STL 体素填充、NIfTI 精确写入或批处理算法时,再引入 Python/conda,并把环境文件纳入项目文档。