14 KiB
14 KiB
geMoldInsight 演进路线图
本文档是代码与功能演进的执行清单,基于 2026-07-13 的全量代码体检。每项含「现象 / 证据 / 修法 / 验证」,按 P0→P3 推进,完成后勾选。
诊断
代码已演进到「双应用模块化」形态(entrypoints/ + moldinsight/ + inventory/ + shared/),但有 三处结构性缺失 让快速迭代变贵,外加 一批静默 bug 正在让功能"看起来在跑其实没跑":
- 缺中间层:业务逻辑堆在路由/编排函数里(进销存无 service 层、
process_file_core280 行线性函数) - 缺契约:前后端靠手写类型,字段已大面积漂移(财务页整页是 0)
- 缺连接:模具分析与进销存是两个孤立产品(
STPFile没有product_id)
P0 止血:正在静默失效的功能(1–2 周)
这些不是技术债,是现在就在坏的东西,先修。
P0-1 Celery worker 不连 Redis/RustFS,异步任务全坏
- 现象:任务进度写进 Celery 私有内存,web 端永远读不到;首次上传 RustFS 直接抛
RuntimeError("RustFS 未连接")。 - 证据:
redis_task_manager.connect()/rustfs_manager.connect()只在 FastAPI startup 调用(entrypoints/moldinsight.py:42,48),Celery 进程不跑 startup;processing_service.py在 celery 内调update_task时is_connected=False走_fallback_set;rustfs_storage.py:125-126未连接直接抛错。deploy/docker-compose.yml的moldinsight-celery服务块缺REDIS_PASSWORD。 - 修法:
celery_tasks.py加@worker_process_init信号,显式connect()redis 与 rustfs;补齐 celery 服务的REDIS_PASSWORD/SECRET_KEY等环境变量,与主应用对齐。 - 验证:上传一个 STP,Celery 路径下任务进度能从 web 端
/api/status/{task_id}读到;上传后 RustFS 中能看到对象。 - 状态:- [ ]
P0-2 LLM 设计报告 NameError,静默失效
- 现象:
LLM_ENABLED=true时设计报告功能直接没有。 - 证据:
llm_service.py:339用未定义变量trimmed(应为features,trimmed只在_build_side_action_prompt中定义),外层try/except吞掉NameError返回None。 - 修法:
trimmed->features。 - 验证:启用 LLM 后设计报告字段非空。
- 状态:- [ ]
P0-3 前端财务页全字段错配
- 现象:FinanceTab 整页 0/空;用户管理菜单永不显示(
is_superuser后端不返回);dashboard 成品数恒 0。 - 证据:16 处字段名对不上,如
total_receivablevsreceivable_total(finance_schemas.py:66)、order_novstxn_no(finance_schemas.py:48)等;App.vue:91读is_superuser但UserResponse无此字段。 - 修法:短期按映射手改前端字段;长期靠 P1-3 OpenAPI 契约生成根治。
- 验证:财务页卡片与表格显示真实数据;用户管理菜单对管理员可见。
- 状态:- [ ]
P0-4 OCC 线程安全自相矛盾
- 现象:偶发崩溃,外层
max_workers=1保护形同虚设。 - 证据:
processing_service.py:50-51用单线程池序列化 OCC,但geometry_analyzer._detect_features(geometry_analyzer.py:81)内部又开ThreadPoolExecutor(max_workers=4)并行操作 OCCTopoDS_Shape。 - 修法:特征检测器改串行;或预处理阶段把面特征抽成纯数值,检测器只处理数值不碰 OCC。
- 验证:压测大模型反复分析无崩溃。
- 状态:- [ ]
P0-5 .env 进了 git 历史,真实密钥泄露
- 现象:DB/Redis/SECRET_KEY/LLM key 已进入仓库历史。
- 证据:
git ls-files --error-unmatch .env命中;git log -- .env有 10+ 次提交;.env内含真实凭据。 - 修法:
git rm --cached .env(停止跟踪,保留本地,后续不再提交);SECRET_KEY从默认占位符轮换为强随机值。 - 用户决策(2026-07-13):私有仓库,不轮换其他密钥、不重写 git 历史。
- 验证:
git status显示.env不再被跟踪(D .env)。 - 状态:- [x]
P0-6 铝价路由模块化部署后丢失
- 现象:模块化部署后
/api/aluminum-price/*直接 404。 - 证据:单体
main.py:47,155挂了aluminum_price_router,但moldinsight/api/__init__.py的_safe_include列表不含aluminum_price_routes。 - 修法:把
aluminum_price_routes加入_safe_include。 - 验证:模块化部署下
/api/aluminum-price/*可访问。 - 状态:- [ ]
P0-7 导出缓存无持久化回退
- 现象:多 worker 或重启后导出返回 409。
- 证据:
processing_service._export_shapes_cache是进程内 dict,get_export_shapes只查内存;_persist_step_exports已写磁盘 manifest 但无回读逻辑。 - 修法:
get_export_shapes缓存未命中时从磁盘 manifest 回读。 - 验证:重启后导出仍可用。
- 状态:- [ ]
P0 执行结果(2026-07-13)
- ✅ P0-1 Celery 连接:
celery_tasks.py在任务内显式redis_task_manager.reconnect()+rustfs_manager.connect()(Redis 客户端绑定事件循环,每任务 reconnect;RustFS 同步客户端连一次复用);deploy/docker-compose.ymlcelery 服务补REDIS_PASSWORD/RUSTFS_TIMEOUT - ✅ P0-2 LLM NameError:
llm_service.py:339trimmed->features - ✅ P0-3 前端字段错配:FinanceTab 全字段对齐 schema(summary/statement/product-statement/transaction 共 16 处);
UserResponse加is_superuser+ 统一_build_user_response构造(修用户管理菜单不显示);DashboardTabproduct_count->finished_product_count;PurchaseOrdersTabreceived_at/paid_at->received_date/paid_date;后端FinanceTransactionResponse补partner_name并批量查询客户/供应商名称 - ✅ P0-4 OCC 线程安全:
geometry_analyzer._detect_featuresmax_workers4->1 - ✅ P0-5 .env 泄露:
git rm --cached .env已取消跟踪(后续不再提交);SECRET_KEY从默认占位符轮换为强随机值(现有登录 token 失效)。用户决策:私有仓库,不轮换其他密钥、不重写 git 历史 - ✅ P0-6 铝价路由:
moldinsight/api/__init__.py_safe_include加入aluminum_price_routes - ℹ️ P0-7 导出缓存:经排查非 bug——
export_artifacts已写 PG+Redis(processing_service.py:342,361),导出端点先走_select_persisted_files从 task_data 读取(advanced_router.py:436),重启后正常工作;409 仅在持久化也失败时出现,"请重新分析"提示为正确行为。内存 re-export 缓存的可靠性优化归入 P1-2
未做验证:前端未跑 vue-tsc 构建(字段重命名属机械改动,低风险);后端未跑 pytest(需 DB/Redis 环境)。建议下次在完整环境验证。
P1 结构性地基:让后续迭代不再昂贵(持续)
P1-1 进销存抽 service 层
- 现状:
finance_routes.py751 行、sales_order_routes.py777 行,事务编排/库存原子更新/流水写入全耦合在 endpoint;shared/services/仅 auth+redis。 - 目标:新建
inventory/services/,PurchaseOrderService.receive()、SalesOrderService.issue_materials()、FinanceService.settle(),route 只做校验+组装。 - 状态:- [ ]
P1-2 moldinsight 可插拔注册表 + Stage 流水线
- 现状:模具类型硬编码 if-else(
multi_scheme_planner.py:40);特征检测器硬编码 6 个(geometry_analyzer.py:76-99);process_file_core280 行。 - 目标:
FeatureDetectorRegistry+MoldGeneratorRegistry(@register装饰器);process_file_core拆成 Stage 链。 - 解锁:新增模具类型、IGES/BREP、批量分析。
- 进展(2026-07-15):✅
MoldGeneratorRegistry(消除multi_scheme_plannerif-else,新增模具类型只需register)+ ✅FeatureDetectorRegistry(消除 6 个检测器硬编码,新增检测器只需register)+ 顺带移除 OCC 线程池改用注册表串行执行;⏳ Stage 流水线暂缓--process_file_core(278 行/10 stage/~20 跨 stage 变量)是 STP 处理核心,本环境无 OCC 无法运行时验证,盲改风险高。建议在有 OCC 的环境按现有_step_*模式增量抽取 inline stages(parse_stp / build_plan_result / generate_visualization / analyze_design / generate_llm_report / finalize) - 状态:- [~](2/3:两个注册表完成,Stage 流水线暂缓)
P1-3 前端 OpenAPI 契约生成
- 现状:前端 40+ 处
any,字段全手写已大面积错配。 - 目标:
openapi-typescript从/openapi.json生成 TS 类型替换any;api.ts加 baseURL/拦截器/超时,按域封装inventoryApi/moldinsightApi/authApi。 - 状态:- [ ]
P1-4 引入 Alembic,废除裸 DDL
- 现状:无
alembic.ini;init_db.py22 条ALTER TABLE ADD COLUMN IF NOT EXISTS,无版本/无回滚;migrate_db.py是drop_all破坏性脚本;两应用 startup 并发跑 DDL 争锁。 - 目标:
alembic init,固化版本化迁移,启动只upgrade head;删migrate_db.py。 - 状态:- [x]
P1-5 统一材料属性源
- 现状:材料字典在 4 处重复定义且冲突(PE 收缩率
material_service0.020 vsaluminum_foam_mold.py:920.025)。 - 目标:
MaterialService作为唯一源,其他模块查询。 - 状态:- [x]
P1 执行结果(核心完成)
- ✅ P1-1 进销存抽 service 层(核心完成):
- 建立
inventory/services/层,抽出 5 个 service:FinanceService / SalesOrderService / PurchaseOrderService / StockMovementService / InventoryService - 路由全面瘦身:finance 767->123、sales_order 777->114、purchase_order 472->90、stock_movement 209->37、inventory 205->57
- 将 schemas/ 与 utils.py 从 inventory/api/ 移至 inventory/ 顶层,打破 service<->api 循环导入(正确分层);清理死代码 api/utils.py
- ✅ 全量 import 测试通过:55 inventory 路由无丢失,5 个 service 全部正常加载
- ⏳ 可选后续:剩余纯 CRUD 路由(product/supplier/customer/warehouse/material/dashboard)体量小,可按需增量抽取
- 建立
- ✅ P1-5 统一材料属性源:
MaterialService成为唯一源,删除 geometry_analyzer/mold_generator/aluminum_foam_mold 三处重复字典,改查询 MaterialService;解决冲突(PE 收缩率统一 0.020、PC/PA/PMMA 收缩率、POM 密度统一)、补齐 PS、统一泡沫shrinkage键名、补min_wall/泡沫字段;py_compile + 一致性核对通过 - ✅ P1-4 引入 Alembic:
alembic init+ 配置 env.py(接 settings+models metadata);补 3 个 CheckConstraint 到 models;离线生成初始迁移(31 表+约束+95 索引,全 sa.* 通用类型);init_db.py用_run_alembic_migrations(自动基线+upgrade head)替换create_tables+ensure_schema_updates(删 92 行裸 DDL);删破坏性migrate_db.py。既有 DB 自动 stamp 基线(无需手动);全新部署建议先alembic upgrade head再启应用 - ✅ P1-2 可插拔注册表(Stage 流水线暂缓):新增
MoldGeneratorRegistry(multi_scheme_planner消除 if-else,按 mold_type 选生成器)+FeatureDetectorRegistry(geometry_analyzer._detect_features消除 6 个检测器硬编码,改遍历注册表);新增模具类型/特征检测器只需register一行;顺带移除 OCC 线程池改串行。Stage 流水线(process_file_core 拆分)因无 OCC 运行环境暂缓,文档留计划
P2 功能演进:把两个产品变成一个
P2-1 打通模具分析 -> 进销存(最高产品价值)
- 现状:
STPFile无product_id,moldinsight 与 inventory 零数据关联。 - 目标:
STPFile加product_id外键(可空),分析完成后一键创建Product(finished)并回写。 - 状态:- [x]
P2-2 真 AI 落地,砍掉假 AI
- 现状:
ai_mold_assistant.py209 行纯 stub 从未被调用;ai_parting_detector.pyGNN 框架完整但无权重;llm_service是唯一真接 AI(且有 P0-2 bug)。 - 目标:聚焦一个能跑通的 AI 能力(LLM 扩到成本估算/工艺对话);GNN 要么真训权重,要么移除 stub。
- 状态:- [ ]
P2-3 模具成本估算 + 批量分析
- 依赖 P1-2 完成后才有性价比。
- 状态:- [ ]
P2 执行结果
- ✅ P2-1 打通模具分析 -> 进销存:
STPFile加product_id外键(nullable+index+FK)+ Alembic 迁移006c18c51b0d(首次真实迁移);inventoryPOST /api/products/from-task/{task_id}端点(按 task_id 查 STPFile,幂等创建Product(finished),回写 product_id,SKU=MI{stp_file_id},描述含体积/重量/表面积);前端 ResultView 导出栏加「创建为成品」按钮。py_compile + alembic heads + vue-tsc 0 错误通过。模具分析 -> 成品 -> BOM -> 销售/采购的业务闭环接通
P3 工程治理(穿插顺手做)
create_app()工厂消除两入口重复引导,废弃单体main.py- 删死依赖/死代码:Kafka(零引用)、
templates/legacy、ai_mold_assistantstub、ProcessingService.__init__3 个死实例 get_db_session统一事务边界(commit/rollback),废除路由手动 commit- 连接池治理(3 进程峰值 150 > PG 默认 100),考虑 PgBouncer
- 进销存 state 从模块级单例迁回 Pinia,tab 改子路由
- 统一
/health响应 schema;SPA fallback 排除/api前缀避免吞 404 - CORS 收敛(
allow_origins=["*"]+allow_credentials=True不安全)
执行进度
| 阶段 | 项数 | 已完成 | 进行中 |
|---|---|---|---|
| P0 | 7 | 6 修复 + 1 排查 | - |
| P1 | 5 | 4 | P1-1+P1-5+P1-4 完成 + P1-2 注册表完成(Stage 暂缓) |
| P2 | 3 | 1 | P2-1 完成 |
| P3 | 7 | 0 | - |