diff --git a/README.md b/README.md index 8bd6e91..cc961d0 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,19 @@ -geMoldInsight 是一个面向模具制造场景的综合系统,围绕 **STP/STEP 模型分析、模具方案生成、分析结果沉淀、成品创建、BOM/库存/采购/销售闭环** 展开。 +geMoldInsight 是一个面向模具制造场景的综合系统,围绕 **STEP/STP 模型分析、模具方案生成、分析结果沉淀、成品创建、BOM/库存/采购/销售闭环** 展开。 + +> **当前实现状态**:见 [docs/STATUS.md](docs/STATUS.md) +> **当前架构与边界**:见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) +> **本文是唯一文档导航入口**:请按角色或主题跳转到对应主文档 + +--- + +## 项目概览 当前项目已经从早期单体演进为: -- **gemold(moldinsight)模块**:模具分析、几何处理、批量分析、成本估算、结果导出 +- **moldinsight 模块**:模具分析、几何处理、批量分析、成本估算、结果导出 - **inventory 模块**:产品、BOM、库存、采购、销售、财务 - **frontend 模块**:Vue 3 前端工程 - **shared 平台层**:配置、数据库、认证、日志、应用工厂 @@ -24,7 +32,98 @@ geMoldInsight 是一个面向模具制造场景的综合系统,围绕 **STP/ST > **单仓库 + 单数据库 + 多模块 + 可独立部署** -详细重构方向见:[BACKEND_MODULARIZATION_BLUEPRINT.md](docs/BACKEND_MODULARIZATION_BLUEPRINT.md) +更详细的结构说明见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)。 + +--- + +## 快速开始(三步) + +### 1. 安装依赖 + +```bash +pip install -r requirements.txt +``` + +前端开发需要: + +```bash +cd frontend +npm install +``` + +### 2. 配置环境变量 + +复制并编辑: + +- [`.env.example`](.env.example) +- 部署场景可参考 [deploy/.env.example](deploy/.env.example) + +### 3. 启动 + +推荐先查看部署入口: +- [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) + +本地常见方式: + +```bash +docker compose --profile full up -d +``` + +如需直接运行: + +```bash +uvicorn src.entrypoints.moldinsight:app --reload --host 0.0.0.0 --port 8000 +uvicorn src.entrypoints.inventory:app --reload --host 0.0.0.0 --port 8001 +``` + +> 如需 OCC 几何分析能力,请准备 PythonOCC 运行环境。项目中通常通过 conda 提供,而不是仅靠 pip 安装。 + +--- + +## 目录概览 + +```text +geMoldInsight/ +├── src/ +│ ├── entrypoints/ # 独立部署入口 +│ ├── shared/ # 当前共享平台层 +│ ├── moldinsight/ # 模具分析模块 +│ ├── inventory/ # 进销存模块 +│ ├── celery_app.py # Celery app +│ └── celery_tasks.py # moldinsight 异步任务 +├── frontend/ # 独立前端工程 +├── alembic/ # 数据库迁移 +├── deploy/ # 镜像、Nginx、部署辅助文件 +├── docs/ +├── tests/ +├── requirements.txt +└── .env.example +``` + +--- + +## 文档导航(唯一入口) + +### 按主题阅读 + +| 文档 | 解决什么问题 | +|---|---| +| [docs/STATUS.md](docs/STATUS.md) | 当前实现状态、当前推荐方案、近期完成项 | +| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | 当前架构、模块边界、结构原则 | +| [docs/ROADMAP.md](docs/ROADMAP.md) | 后续演进路线与阶段计划 | +| [docs/TECH_DEBT.md](docs/TECH_DEBT.md) | 当前活跃技术债与治理计划 | +| [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) | 部署主题入口与部署文档分工 | +| [docs/deployment/LINUX_SETUP.md](docs/deployment/LINUX_SETUP.md) | Linux 环境下的详细部署步骤 | +| [docs/archive/BACKEND_MODULARIZATION_BLUEPRINT.md](docs/archive/BACKEND_MODULARIZATION_BLUEPRINT.md) | 模块化蓝图档案与补充设计讨论 | + +### 按角色阅读 + +| 你是 | 建议阅读顺序 | +|---|---| +| 第一次了解项目 | 本文 → [docs/STATUS.md](docs/STATUS.md) → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | +| 开发者 / 改代码 | 本文 → [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) → [docs/TECH_DEBT.md](docs/TECH_DEBT.md) → 相关专题文档 | +| 运维 / 部署 | 本文 → [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) → [docs/deployment/LINUX_SETUP.md](docs/deployment/LINUX_SETUP.md) | +| 规划 / 重构 | 本文 → [docs/ROADMAP.md](docs/ROADMAP.md) → [docs/TECH_DEBT.md](docs/TECH_DEBT.md) | --- @@ -32,7 +131,7 @@ geMoldInsight 是一个面向模具制造场景的综合系统,围绕 **STP/ST | 模块 | 能力 | |---|---| -| gemold | STP/STEP 上传、几何分析、特征识别、模具方案、批量分析、成本估算、结果导出 | +| moldinsight | STEP/STP 上传、几何分析、特征识别、模具方案、批量分析、成本估算、结果导出 | | inventory | 成品/物料、BOM、库存、库存流水、采购订单、销售订单、财务、采购建议 | | integration | 分析结果一键创建成品,打通“模具分析 → 成品 → BOM → 销售/采购/库存” | | platform | 用户、角色、权限、JWT 鉴权、数据库连接、日志、健康检查 | @@ -42,399 +141,35 @@ geMoldInsight 是一个面向模具制造场景的综合系统,围绕 **STP/ST ## 技术栈 ### 后端 -- **FastAPI** -- **SQLAlchemy 2.0** -- **PostgreSQL** -- **Alembic** -- **Redis** -- **Celery** -- **PythonOCC / trimesh / pyvista** -- **RustFS / MinIO 兼容对象存储** +- FastAPI +- SQLAlchemy 2.0 +- PostgreSQL +- Alembic +- Redis +- Celery +- PythonOCC / trimesh / pyvista +- RustFS / MinIO 兼容对象存储 ### 前端 -- **Vue 3** -- **Vite** -- **TypeScript** -- **Pinia** -- **Vue Router** -- **TDesign Vue Next** +- Vue 3 +- Vite +- TypeScript +- Pinia +- Vue Router +- TDesign Vue Next ### 基础设施 -- **Docker / Docker Compose** -- **结构化日志 / request_id** -- **OpenAPI → TypeScript 类型生成** +- Docker / Docker Compose +- 结构化日志 / request_id +- OpenAPI → TypeScript 类型生成 --- -## 当前项目结构 +## 当前代码入口 -> 下述结构反映的是**当前代码现状**,不是历史单体结构。 - -```text -geMoldInsight/ -├── src/ -│ ├── entrypoints/ # 独立部署入口 -│ │ ├── moldinsight.py # gemold-only 入口 -│ │ └── inventory.py # inventory-only 入口 -│ │ -│ ├── shared/ # 共享平台层(当前形态) -│ │ ├── app_factory.py # FastAPI 应用工厂 -│ │ ├── config/ # 配置 -│ │ ├── database/ # DB engine / session / init -│ │ ├── models/ # 共享 ORM 模型(当前最大耦合点) -│ │ ├── services/ # 认证、Redis 等共享服务 -│ │ └── utils/ # 日志、文件、HTML 工具 -│ │ -│ ├── moldinsight/ # gemold 模块 -│ │ ├── api/ -│ │ ├── core/ -│ │ ├── services/ -│ │ └── storage/ -│ │ -│ ├── inventory/ # inventory 模块 -│ │ ├── api/ -│ │ ├── schemas/ -│ │ └── services/ -│ │ -│ ├── celery_app.py # Celery app -│ ├── celery_tasks.py # gemold 异步任务 -│ └── main.py # 旧统一入口(兼容/过渡) -│ -├── frontend/ # 独立前端工程 -│ ├── src/ -│ │ ├── modules/ -│ │ │ ├── moldinsight/ -│ │ │ ├── inventory/ -│ │ │ ├── login/ -│ │ │ ├── users/ -│ │ │ └── home/ -│ │ ├── router/ -│ │ ├── shared/ -│ │ ├── stores/ -│ │ └── types/ -│ └── package.json -│ -├── alembic/ # Alembic migrations -├── deploy/ # 镜像构建、Nginx 配置与部署辅助文件 -│ ├── Dockerfile.base -│ ├── Dockerfile.moldinsight -│ ├── Dockerfile.inventory -│ ├── Dockerfile.celery -│ ├── Dockerfile.frontend -│ └── nginx/ -│ -├── docs/ -├── tests/ -├── requirements.txt -└── .env.example -``` - ---- - -## 模块说明 - -### 1. gemold(moldinsight) - -主要负责: -- STP/STEP 上传与任务管理 -- 几何分析与特征识别 -- 模具方案、型腔/型芯/工艺建议 -- 批量分析 -- 成本估算 -- 导出与结果查询 -- Celery 异步处理 - -关键目录: -- [src/moldinsight/](src/moldinsight/) -- [src/celery_app.py](src/celery_app.py) -- [src/celery_tasks.py](src/celery_tasks.py) - -### 2. inventory - -主要负责: -- 成品/物料管理 -- BOM -- 库存与库存流水 -- 采购订单 / 销售订单 -- 财务与对账 -- 采购建议推导 - -关键目录: -- [src/inventory/](src/inventory/) - -### 3. frontend - -主要负责: -- 模具分析页面 -- 进销存页面 -- 登录/用户管理 -- 统一路由与状态管理 -- 基于 OpenAPI 生成类型的前端 API 调用 - -关键目录: -- [frontend/](frontend/) - -### 4. shared(当前平台层) - -主要负责: -- 配置 -- 数据库连接与 session -- 认证与权限 -- 日志与 request_id -- 应用工厂与通用中间件 - -关键目录: -- [src/shared/](src/shared/) - -> 说明:后续会逐步将 `shared` 收敛为更清晰的 `platform` 语义,见 [BACKEND_MODULARIZATION_BLUEPRINT.md](docs/BACKEND_MODULARIZATION_BLUEPRINT.md)。 - ---- - -## 部署模式 - -当前项目设计上支持三种模式: - -### 1. unified(当前推荐) -一个统一后端同时挂载 gemold + inventory,并作为前端同域反代的默认 backend。 - -适合: -- 本地开发 -- 集成环境 -- 小团队统一部署 -- 前端独立部署 + 单 upstream 反代 - -### 2. gemold-only -只部署模具分析后端。 - -适合: -- 单独开放分析能力 -- 分析任务独立扩容 -- 文件处理与异步任务独立部署 - -入口参考: -- [src/entrypoints/moldinsight.py](src/entrypoints/moldinsight.py) - -### 3. inventory-only -只部署进销存后端。 - -适合: -- 仅使用 ERP / 库存能力 -- 与 gemold 分开部署节奏 - -入口参考: -- [src/entrypoints/inventory.py](src/entrypoints/inventory.py) - ---- - -## 快速开始 - -## 1. 环境要求 - -- Python 3.12 -- PostgreSQL 15+(服务器已部署或自行提供) -- Redis(服务器已部署或自行提供) -- 对象存储(MinIO / RustFS 兼容;gemold 模块需要,服务器已部署或自行提供) -- Node.js 20+(前端开发需要) -- 推荐使用 `docker-compose.yml` 仅启动项目自身服务,复用服务器已有 PostgreSQL / Redis / 对象存储 - ---- - -## 2. 安装后端依赖 - -```bash -pip install -r requirements.txt -``` - -如果需要几何分析能力,还需确保 PythonOCC 运行环境可用。项目中已说明其通常通过 conda 提供,而不是直接由 pip 安装。 - ---- - -## 3. 配置环境变量 - -复制并编辑: - -- [`.env.example`](.env.example) -- 部署场景也可参考 [deploy/.env.example](deploy/.env.example) - -最少需要关注: - -```env -HOST=0.0.0.0 -PORT=8000 - -DB_HOST=localhost -DB_PORT=5432 -DB_NAME=moldinsight -DB_USER=moldinsight_user -DB_PASSWORD=moldinsight_password - -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD= - -SECRET_KEY=change-me -ADMIN_USERNAME=admin -ADMIN_PASSWORD=change-me - -RUSTFS_ENDPOINT=http://localhost:9000 -RUSTFS_ACCESS_KEY=your-access-key -RUSTFS_SECRET_KEY=your-secret-key -``` - -更多配置项见: -- [settings.py](src/shared/config/settings.py) -- [.env.example](.env.example) - ---- - -## 4. 初始化数据库 - -项目当前使用 Alembic 管理迁移。应用启动时也会执行初始化逻辑,但首次部署建议显式执行迁移流程。 - -如需查看初始化实现,可参考: -- [init_db.py](src/shared/database/init_db.py) - ---- - -## 5. 启动方式 - -### 方式 A:使用根目录 Compose(推荐) - -当前唯一 Compose 入口: -- [docker-compose.yml](docker-compose.yml) - -该 compose 文件会启动: -- `frontend`(独立前端 Nginx 静态站点) -- `backend`(unified backend,当前推荐) -- `moldinsight-celery` -- 可选保留:`moldinsight` / `inventory`(模块独立部署 profile) - -其中: -- 前端通过同域反代把 `/api`、`/health`、`/html` 转发给 unified backend -- PostgreSQL / Redis / RustFS / MinIO 兼容对象存储仍由服务器现有服务提供 - -示例: - -```bash -docker compose --profile full up -d -``` - -可选 profile: -- `full` -- `frontend` -- `unified` -- `moldinsight` -- `inventory` - -> 说明:根目录 `docker-compose.yml` 是当前唯一 Compose 入口;前端已独立部署,并默认反代到 unified backend。 - -### 方式 B:直接启动后端入口 - -gemold-only: - -```bash -uvicorn src.entrypoints.moldinsight:app --reload --host 0.0.0.0 --port 8000 -``` - -inventory-only: - -```bash -uvicorn src.entrypoints.inventory:app --reload --host 0.0.0.0 --port 8001 -``` - -### 方式 C:单独启动前端开发服务器 - -```bash -cd frontend -npm install -npm run dev -``` - -生产构建: - -```bash -cd frontend -npm run build -``` - ---- - -## 健康检查与接口 - -### 健康检查 - -两类后端都通过共享 app factory 暴露健康检查: - -- `GET /health` -- `POST /health` - -参考实现: -- [app_factory.py](src/shared/app_factory.py) - -### 认证接口 - -- `POST /api/auth/login` -- `POST /api/auth/logout` -- `GET /api/auth/me` - -### gemold 典型接口 - -- `POST /api/upload` -- `POST /api/batch-upload` -- `GET /api/status/{task_id}` -- `GET /api/history` -- `POST /api/cost-estimate` - -### inventory 典型接口 - -- `GET /api/products` -- `GET /api/inventory` -- `GET /api/purchase-orders` -- `GET /api/sales-orders` -- `GET /api/finance/*` - -统一契约输出可参考: -- [openapi.json](openapi.json) -- [frontend/src/types/api.ts](frontend/src/types/api.ts) - ---- - -## 当前架构重点说明 - -### 1. gemold 与 inventory 已基本模块化 - -当前代码层面,`src/moldinsight/` 与 `src/inventory/` 已基本无直接互相依赖,说明业务边界已经初步成型。 - -### 2. 当前最大耦合点在 shared + 共享 ORM - -需要特别注意: - -- [src/shared/models/database.py](src/shared/models/database.py) 同时定义了 identity、gemold、inventory 的 ORM 模型 -- [src/shared/app_factory.py](src/shared/app_factory.py) 仍承担较多平台与模块组合职责 - -这也是下一阶段重构的重点。 - -### 3. 单数据库是刻意选择 - -项目不是把 gemold 与 inventory 拆成两个数据库,而是保留一个共享数据库,用于支撑完整业务闭环: - -- 分析结果 -- 创建成品 -- 成品 BOM -- 销售 / 采购 / 库存 - -典型桥接点: -- `STPFile.product_id -> Product.id` - ---- - -## 开发与演进文档 - -推荐先阅读: - -- [BACKEND_MODULARIZATION_BLUEPRINT.md](docs/BACKEND_MODULARIZATION_BLUEPRINT.md) — 当前模块化重构蓝图 -- [EVOLUTION_ROADMAP.md](docs/EVOLUTION_ROADMAP.md) — 历史演进与阶段任务 -- [docs/deployment/](docs/deployment/) — 现有部署文档(部分仍在对齐中) +- moldinsight-only: [src/entrypoints/moldinsight.py](src/entrypoints/moldinsight.py) +- inventory-only: [src/entrypoints/inventory.py](src/entrypoints/inventory.py) +- 当前 Compose 入口: [docker-compose.yml](docker-compose.yml) --- @@ -442,8 +177,8 @@ npm run build - 新增业务逻辑优先放入对应业务模块,不要继续堆进 `shared` - 新增 API 时优先考虑模块归属,而不是“能放就放” -- 前端优先通过域 API client 调用接口,而不是散落裸 `/api/...` 路径 -- 数据模型改动要同时考虑表归属与 Alembic 迁移影响 +- 文档状态统一维护在 [docs/STATUS.md](docs/STATUS.md) +- 部署方式变化统一更新 [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) --- diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..ebcbf56 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,221 @@ +# geMoldInsight 架构与边界(ARCHITECTURE) + +> 文档定位:**当前架构、模块边界与结构原则的权威文档**。 +> 本文描述“现在的系统结构是什么、边界如何划分、目标形态是什么”;不负责维护当前实现进度,当前状态见 [STATUS.md](STATUS.md),部署见 [DEPLOYMENT.md](DEPLOYMENT.md),演进路线见 [ROADMAP.md](ROADMAP.md)。 +> 如需追溯模块化设计蓝图与扩展讨论,见 [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](archive/BACKEND_MODULARIZATION_BLUEPRINT.md)。 + +--- + +## 1. 架构目标 + +geMoldInsight 的目标架构不是微服务,也不是继续维持历史单体,而是: + +> **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith** + +这意味着: + +- 保持同一 Git 仓库 +- 保持同一 PostgreSQL 数据库 +- 按模块组织业务代码与部署入口 +- 在不拆库、不拆仓的前提下,明确业务边界与部署边界 + +--- + +## 2. 当前模块划分 + +### 2.1 moldinsight + +目录: +- [src/moldinsight/](../src/moldinsight/) + +职责: +- STEP/STP 上传与任务管理 +- 几何分析与特征识别 +- 模具方案生成 +- 批量分析 +- 成本估算 +- 导出与结果查询 +- 结合 Celery 执行异步分析链路 + +### 2.2 inventory + +目录: +- [src/inventory/](../src/inventory/) + +职责: +- 成品/物料管理 +- BOM 管理 +- 库存与库存流水 +- 采购订单 / 销售订单 +- 财务与对账 +- 采购建议推导 + +### 2.3 frontend + +目录: +- [frontend/](../frontend/) + +职责: +- 模具分析页面 +- 进销存页面 +- 登录/用户管理 +- 统一路由与状态管理 +- 基于 OpenAPI 类型生成的前端调用 + +### 2.4 shared(当前平台层) + +目录: +- [src/shared/](../src/shared/) + +职责: +- 配置 +- 数据库连接与 session +- 认证与权限 +- 日志与 request_id +- 应用工厂与共用中间件 + +说明: +- `shared` 当前仍是“共享平台层 + 历史耦合区”的混合体 +- 后续会继续向更清晰的 platform 语义收敛,但当前仓库结构仍以 `shared` 为事实名称 + +--- + +## 3. 当前代码结构 + +当前核心结构如下: + +```text +geMoldInsight/ +├── src/ +│ ├── entrypoints/ +│ │ ├── moldinsight.py +│ │ └── inventory.py +│ ├── shared/ +│ ├── moldinsight/ +│ ├── inventory/ +│ ├── celery_app.py +│ └── celery_tasks.py +├── frontend/ +├── alembic/ +├── deploy/ +├── docs/ +└── tests/ +``` + +这反映的是**当前实际代码组织**,不是历史单体结构。 + +--- + +## 4. 部署边界 + +当前设计上支持三种部署模式: + +### 4.1 unified + +一个统一后端同时承载 moldinsight + inventory,并作为前端默认反代目标。 + +适合: +- 本地开发 +- 集成环境 +- 小团队统一部署 + +### 4.2 moldinsight-only + +只部署模具分析后端。 + +适合: +- 单独开放分析能力 +- 异步任务与文件处理独立扩容 + +入口: +- [src/entrypoints/moldinsight.py](../src/entrypoints/moldinsight.py) + +### 4.3 inventory-only + +只部署进销存后端。 + +适合: +- 独立使用 ERP / 库存能力 +- 与 moldinsight 分开部署节奏 + +入口: +- [src/entrypoints/inventory.py](../src/entrypoints/inventory.py) + +部署操作与当前推荐方案见 [DEPLOYMENT.md](DEPLOYMENT.md)。 + +--- + +## 5. 关键架构原则 + +### 5.1 单数据库是刻意设计 + +项目不是把 moldinsight 与 inventory 强拆成两个数据库,而是保留共享数据库,以支撑完整业务闭环: + +- 分析结果 +- 创建成品 +- 成品 BOM +- 销售 / 采购 / 库存 + +典型桥接关系示例: +- `STPFile.product_id -> Product.id` + +### 5.2 模块边界优先于“临时方便” + +新增逻辑时,应优先放入对应业务模块,而不是继续堆进 `shared`。 + +原则上: +- moldinsight 业务进入 `src/moldinsight/` +- inventory 业务进入 `src/inventory/` +- 只有真正跨模块复用的基础能力才进入 `src/shared/` + +### 5.3 前端是独立工程,不是后端静态附属 + +前端已是独立 Vite/Vue 工程,部署上可与后端组合,但在代码组织上应视为独立模块,而不是后端 `static/` 的扩展。 + +--- + +## 6. 当前主要耦合点 + +虽然模块化已经成型,但仍有几个关键耦合点需要持续关注: + +### 6.1 共享 ORM 模型 + +当前 [src/shared/models/database.py](../src/shared/models/database.py) 同时承载 identity、moldinsight、inventory 三类模型,是当前最强耦合点之一。 + +### 6.2 app factory 组合职责偏重 + +当前 [src/shared/app_factory.py](../src/shared/app_factory.py) 仍承担较多平台与模块组合职责,是后续平台层收敛的重点。 + +### 6.3 文档与结构尚未完全同步 + +代码结构已明显模块化,但历史文档中仍保留不少阶段性叙述、旧部署语义与重复说明,这也是本轮文档整理要解决的问题之一。 + +--- + +## 7. 专题文档与主骨架的关系 + +以下文档仍可作为专题补充参考,但不再承担默认入口职责: + +- AI / FreeCAD 方向: + - [topics/ai/AI_ENGINE_DESIGN.md](topics/ai/AI_ENGINE_DESIGN.md) + - [topics/ai/AI_FREECAD_INTEGRATION.md](topics/ai/AI_FREECAD_INTEGRATION.md) +- 存储方向: + - [topics/storage/RUSTFS_STORAGE.md](topics/storage/RUSTFS_STORAGE.md) + - [topics/storage/STORAGE_SETUP.md](topics/storage/STORAGE_SETUP.md) +- 铝泡沫模具专题: + - [topics/aluminum-foam/SPEC_ALUMINUM_FOAM_MOLD.md](topics/aluminum-foam/SPEC_ALUMINUM_FOAM_MOLD.md) +- 性能专题: + - [topics/performance/PERFORMANCE_SCALABILITY_PLAN.md](topics/performance/PERFORMANCE_SCALABILITY_PLAN.md) + - [topics/performance/PERFORMANCE_BENCHMARKS.md](topics/performance/PERFORMANCE_BENCHMARKS.md) + +阶段性任务清单、迁移计划、历史总结等文档会逐步迁入 [archive/README.md](archive/README.md)。 + +--- + +## 8. 与相关文档的边界 + +- 想看“当前做到哪一步”:看 [STATUS.md](STATUS.md) +- 想看“后面还要往哪演进”:看 [ROADMAP.md](ROADMAP.md) +- 想看“当前有哪些活跃技术债”:看 [TECH_DEBT.md](TECH_DEBT.md) +- 想看“怎么部署”:看 [DEPLOYMENT.md](DEPLOYMENT.md) +- 想看“模块化蓝图与更完整设计讨论”:看 [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](archive/BACKEND_MODULARIZATION_BLUEPRINT.md) diff --git a/docs/BACKEND_MODULARIZATION_BLUEPRINT.md b/docs/BACKEND_MODULARIZATION_BLUEPRINT.md deleted file mode 100644 index d44f59a..0000000 --- a/docs/BACKEND_MODULARIZATION_BLUEPRINT.md +++ /dev/null @@ -1,908 +0,0 @@ -# geMoldInsight 后端模块化重构蓝图 - -> 目标:在**同一 Git 仓库**、**同一数据库**前提下,将当前代码结构整理为**可独立部署的多模块架构**,明确 gemold、inventory、frontend 的边界与演进路径。本文档是后续实施的权威蓝图,不是历史记录。 - ---- - -## 1. 背景与目标 - -当前项目已经从早期单体演进为“双应用 + 共享层”的形态: - -- 业务模块:`src/moldinsight/`、`src/inventory/` -- 共享层:`src/shared/` -- 部署入口:`src/entrypoints/moldinsight.py`、`src/entrypoints/inventory.py` -- 前端工程:`frontend/` - -从代码现状看,`moldinsight` 与 `inventory` 已基本无直接互引,说明模块边界已经初步形成;但同时,数据库模型、认证、配置、应用工厂等仍集中在 `shared/`,导致当前更接近“**模块化中的单体**”,而不是“**可独立部署的模块化单体**”。 - -本次蓝图的目标不是拆库、拆仓、微服务化,而是: - -1. 保持**单仓库(monorepo)** -2. 保持**单数据库** -3. 将后端正式整理为多个模块: - - **gemold**(模具分析 / moldinsight) - - **inventory**(进销存) - - **identity / platform**(共享基础设施与认证) -4. 保持前端为**独立模块工程**,并增强其对多部署模式的兼容 -5. 支持三种部署模式: - - **unified**:gemold + inventory 同时部署 - - **gemold-only**:仅部署 gemold - - **inventory-only**:仅部署 inventory - ---- - -## 2. 范围与非目标 - -### 2.1 本次蓝图覆盖范围 - -- 后端模块边界 -- 共享层职责重新定义 -- 单数据库下的模型归属与表所有权 -- 独立部署模式设计 -- 前端 API 边界强化策略 -- 分阶段迁移路径 -- 风险与验证方法 - -### 2.2 非目标 - -本蓝图**不包含**以下方向: - -- 多 Git 仓库拆分 -- 多数据库拆分 -- 分布式微服务重构 -- 全量 DDD 重写 -- 全量前端重构 -- 事件驱动或消息总线主导的跨服务通信改造 - -换句话说,目标架构是: - -> **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith** - -而不是微服务系统。 - ---- - -## 3. 当前架构快照 - -### 3.1 后端现状 - -当前核心目录结构如下: - -```text -src/ - entrypoints/ - moldinsight.py - inventory.py - shared/ - app_factory.py - config/ - database/ - models/ - services/ - utils/ - moldinsight/ - api/ - core/ - services/ - storage/ - inventory/ - api/ - schemas/ - services/ -``` - -其中: - -- [app_factory.py](../src/shared/app_factory.py) 已统一 CORS、日志中间件、startup/shutdown、认证路由、健康检查与 SPA fallback。 -- [moldinsight.py](../src/entrypoints/moldinsight.py) 与 [inventory.py](../src/entrypoints/inventory.py) 已提供独立入口。 -- [database.py](../src/shared/models/database.py) 同时包含 identity、moldinsight、inventory 三类模型,是当前最强耦合点。 - -### 3.2 前端现状 - -前端已是独立 Vite/Vue 工程: - -```text -frontend/ - src/ - modules/ - moldinsight/ - inventory/ - login/ - users/ - home/ - router/ - shared/ - stores/ - types/ -``` - -特点: - -- 已按页面/业务模块组织 -- 已有共享 API 层雏形:[api-client.ts](../frontend/src/shared/api-client.ts) -- 已接入 OpenAPI 生成类型:[api.ts](../frontend/src/types/api.ts) -- 当前仍有大量相对路径 `/api/...` 与 raw `fetch()` 的同源假设 - -### 3.3 现状判断 - -当前架构可概括为: - -> **HTTP 入口已分离,业务代码已分组,但平台层与数据层仍共享。** - -因此,它适合继续朝“可独立部署的模块化单体”演进,而不适合直接跳到微服务。 - ---- - -## 4. 目标架构:可独立部署的模块化单体 - -### 4.1 架构原则 - -目标态采用以下原则: - -1. **组合优先于复制**:不同部署模式通过组合不同模块得到,而不是复制多套代码。 -2. **平台与业务分离**:`platform` 只承载技术性共享能力,不继续承载业务逻辑。 -3. **模块所有权清晰**:每张表、每条 API、每个服务类都应有明确归属。 -4. **单数据库但显式边界**:允许共享 DB,但不允许“共享数据库 = 没有边界”。 -5. **统一前端,兼容多后端部署形态**:前端继续是一套工程,通过 API client 适配 unified / split deployment。 - -### 4.2 架构定位 - -目标架构不是“多个服务各自拥有数据库”的微服务,而是: - -- 同一个仓库 -- 同一个数据库 -- 多个模块 -- 多个部署入口 -- 同一套迁移历史 -- 同一套共享基础设施能力 - -这是一种适合当前项目阶段的**治理性重构**,而不是组织级拆分。 - ---- - -## 5. 目标目录结构 - -以下结构是**目标态**,不要求一次性到位: - -```text -src/ - platform/ - app/ - app_factory.py - lifecycle.py - middleware/ - config/ - auth/ - database/ - engine.py - session.py - migrations/ - observability/ - contracts/ - api/ - events/ - shared_kernel/ - types/ - exceptions/ - utils/ - - modules/ - moldinsight/ - application/ - services/ - use_cases/ - domain/ - models/ - policies/ - repositories/ - infrastructure/ - persistence/ - storage/ - adapters/ - interfaces/ - api/ - schemas/ - module.py - - inventory/ - application/ - services/ - use_cases/ - domain/ - models/ - policies/ - repositories/ - infrastructure/ - persistence/ - adapters/ - interfaces/ - api/ - schemas/ - module.py - - identity/ - application/ - domain/ - infrastructure/ - interfaces/ - module.py - - compositions/ - unified_app.py - gemold_app.py - inventory_app.py - - legacy/ - main.py -``` - -### 5.1 当前目录到目标目录的映射 - -| 当前路径 | 目标路径 | 说明 | -|---|---|---| -| `src/shared/*` | `src/platform/*` | 共享基础设施重新命名与归位 | -| `src/moldinsight/*` | `src/modules/moldinsight/*` | gemold 业务模块 | -| `src/inventory/*` | `src/modules/inventory/*` | inventory 业务模块 | -| `src/entrypoints/*` | `src/compositions/*` | 部署组合层 | -| `src/main.py` | `src/legacy/main.py` | 过渡期兼容入口 | - -### 5.2 为什么要引入 `compositions/` - -当前 [entrypoints/](../src/entrypoints/) 已经承担“部署入口”角色,但语义更偏“启动文件”。 - -引入 `compositions/` 的意义是明确: - -- 它不是业务模块 -- 它不是平台能力 -- 它是“**按部署模式装配模块**”的组合层 - -例如: - -- `gemold_app.py`:平台 + identity + moldinsight -- `inventory_app.py`:平台 + identity + inventory -- `unified_app.py`:平台 + identity + moldinsight + inventory - ---- - -## 6. 模块职责边界 - -### 6.1 platform - -`platform` 是技术共享层,只承载**跨模块公共基础设施能力**。 - -#### 归属范围 -- app factory / middleware / 生命周期 -- config -- 数据库 engine / session / Alembic 接线 -- auth / JWT / 权限 -- 日志 / request_id / observability -- 通用 contracts / utilities - -#### 可复用现有实现 -- [app_factory.py](../src/shared/app_factory.py) -- [settings.py](../src/shared/config/settings.py) -- [database.py](../src/shared/database/database.py) -- [auth_service.py](../src/shared/services/auth_service.py) -- [auth_routes.py](../src/shared/services/auth_routes.py) - -#### 规则 -`platform` 不得继续吸收业务规则代码,否则新的 `platform` 会变成旧的 `shared`。 - ---- - -### 6.2 moldinsight(gemold) - -`moldinsight` 模块负责模具分析、几何处理和分析结果生命周期。 - -#### 归属范围 -- 上传、任务、历史、批量分析、成本估算、CAM、分析结果 -- 几何分析、特征检测、模具方案、报告 -- RustFS / 对象存储接入 -- Celery 异步处理链路 - -#### 可复用现有实现 -- [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py) -- [processing_service.py](../src/moldinsight/services/processing_service.py) -- [task_query_service.py](../src/moldinsight/services/task_query_service.py) -- [moldinsight/core/](../src/moldinsight/core/) -- [celery_app.py](../src/celery_app.py) -- [celery_tasks.py](../src/celery_tasks.py) - ---- - -### 6.3 inventory - -`inventory` 模块负责 ERP / 进销存类业务流程。 - -#### 归属范围 -- 产品、物料、供应商、客户、仓库 -- 库存、库存流水 -- 销售订单、采购订单、财务、采购建议 -- BOM / 采购需求推导 - -#### 可复用现有实现 -- [inventory/api/__init__.py](../src/inventory/api/__init__.py) -- [inventory_service.py](../src/inventory/services/inventory_service.py) -- [sales_order_service.py](../src/inventory/services/sales_order_service.py) -- [purchase_order_service.py](../src/inventory/services/purchase_order_service.py) -- [finance_service.py](../src/inventory/services/finance_service.py) - ---- - -### 6.4 identity - -`identity` 负责用户、角色、权限与认证授权。 - -#### 归属范围 -- User / Role / Permission -- 登录、鉴权、管理员接口 -- 统一授权能力 - -在物理目录上,identity 可以先靠近 platform;但逻辑上应从一开始就被视为独立边界,而不是“moldinsight 的一部分”或“inventory 的一部分”。 - ---- - -## 7. 允许的依赖方向 - -这是本蓝图最重要的治理规则之一。 - -### 7.1 依赖规则 - -```text -compositions -> platform -compositions -> modules/* - -platform -> 不依赖业务模块 - -modules/*/interfaces -> modules/*/application -modules/*/application -> modules/*/domain -modules/*/infrastructure -> modules/*/domain - -modules/*/interfaces -> platform -modules/*/infrastructure -> platform -``` - -### 7.2 跨模块约束 - -- `inventory` 不能直接 import `moldinsight.api` / `moldinsight.services` -- `moldinsight` 不能直接 import `inventory.api` / `inventory.services` -- `platform` 不得依赖任一业务模块 -- 跨模块协作只能通过: - - 显式 contract / query service - - composition wiring - - 受控的共享数据库引用 - -### 7.3 当前代码与规则的差距 - -从代码检查看,当前 `moldinsight` 与 `inventory` 基本没有直接互引,这说明上述规则在业务代码层**已经接近成立**。 - -当前主要问题集中在: - -- [database.py](../src/shared/models/database.py) 集中承载所有 ORM 模型 -- [app_factory.py](../src/shared/app_factory.py) 同时知道通用平台逻辑与 moldinsight 专属 startup 行为 - -因此,后续实施的重点不是“切断业务模块互引”,而是“**把共享层与数据层的边界拉直**”。 - ---- - -## 8. 单数据库下的模型与表归属策略 - -### 8.1 核心原则 - -数据库继续保持为**一个 PostgreSQL 数据库**,但代码中的模型归属必须显式化。 - -也就是说: - -> **数据库不拆,模型归属要拆。** - -### 8.2 当前最强耦合点 - -当前 [database.py](../src/shared/models/database.py) 同时包含: - -- identity / 平台相关模型 -- moldinsight 业务模型 -- inventory 业务模型 - -这会带来两个问题: - -1. 代码层看不出模型所有权 -2. 开发者更容易跨模块直接访问整套 ORM 图谱 - -因此,后续实施应优先将这个文件按归属拆分。 - -### 8.3 推荐表归属矩阵 - -#### platform / identity-owned -- users -- roles -- permissions -- user_roles -- role_permissions -- (可选)system_logs - -#### moldinsight-owned -- stp_files -- geometry_data -- mesh_data -- html_files -- processing_tasks -- mold_cavity_data -- feature_detections -- design_recommendations -- analysis_metrics - -#### inventory-owned -- products -- product_materials -- material_price_history -- material_suppliers -- suppliers -- customers -- warehouses -- inventory -- stock_movements -- purchase_orders -- purchase_order_items -- sales_orders -- sales_order_items -- finance_transactions -- finance_allocations - -### 8.4 目标代码形态 - -推荐逐步演进到: - -```text -platform/database/base.py -modules/identity/infrastructure/persistence/models.py -modules/moldinsight/infrastructure/persistence/models.py -modules/inventory/infrastructure/persistence/models.py -``` - -同时保持: - -- 同一个 SQLAlchemy `Base` -- 同一个 metadata -- 同一条 Alembic 历史链 -- 同一个数据库连接 - -### 8.5 跨模块 FK 的处理策略 - -当前存在真实跨模块业务桥: - -- `STPFile.product_id -> Product.id` - -这是合理的,因为它反映了真实业务关系:模具分析结果可以创建成品,并与 inventory 中的产品建立连接。 - -原则上允许保留这类稳定 FK,但应遵守: - -1. 跨模块 FK 是**业务桥**,不是“任意跨模块查询”的许可 -2. 模块之间应逐步通过 query service / repository contract 暴露需要的读取能力 -3. 避免一个模块直接依赖另一个模块的整套 ORM 图谱 - ---- - -## 9. 部署模式设计 - -本项目必须支持三种部署模式。 - -### 9.1 unified - -#### 组成 -- platform + identity + moldinsight + inventory - -#### 适用场景 -- 本地开发 -- 小团队部署 -- 集成环境 -- 一体化业务场景 - -#### 说明 -新的 unified 组合层应接替旧 [main.py](../src/main.py) 的语义,但应通过 `compositions/unified_app.py` 的方式实现,而不是继续维持旧单体式入口。 - ---- - -### 9.2 gemold-only - -#### 组成 -- platform + identity + moldinsight - -#### 适用场景 -- 仅开放模具分析能力 -- 分析服务独立扩容 -- 单独部署算法/文件处理能力 - -#### 说明 -- 只暴露 gemold 路由 -- 可保留对共享数据库中 `products` 的受控引用 -- RustFS / Celery 等专属基础设施只在该模式启用 - -当前入口基线: -- [moldinsight.py](../src/entrypoints/moldinsight.py) - ---- - -### 9.3 inventory-only - -#### 组成 -- platform + identity + inventory - -#### 适用场景 -- 仅提供 ERP / 进销存能力 -- 不需要模具分析链路的后台场景 - -#### 说明 -- 只暴露 inventory 路由 -- 不要求启动 RustFS 等 moldinsight 专属基础设施 - -当前入口基线: -- [inventory.py](../src/entrypoints/inventory.py) - ---- - -### 9.4 当前共享工厂的边界问题 - -需要特别指出:当前 [app_factory.py](../src/shared/app_factory.py) 通过 `mount_html=True` 分支初始化 RustFS,这说明共享工厂仍然知道 moldinsight 模块专属基础设施。 - -这意味着: - -- `shared` / `platform` 还不够纯 -- 模块专属 startup hook 还没有完全从平台层剥离 - -后续实施时,这应是**优先解决的问题之一**: - -> app factory 只负责通用平台装配;模块专属生命周期应由 module hook 或 composition layer 决定。 - ---- - -## 10. 前端 API 边界策略 - -### 10.1 设计原则 - -前端已经是独立工程,不需要再拆目录或拆仓。后续重点应放在: - -- 强化域 API 边界 -- 消除对单一同源 `/api/...` 的强依赖 -- 兼容 unified / split deployment - -### 10.2 当前可复用基础 - -当前前端已经具备良好基础: - -- 域客户端入口:[api-client.ts](../frontend/src/shared/api-client.ts) -- 生成类型:[api.ts](../frontend/src/types/api.ts) -- 模块目录:[frontend/src/modules/moldinsight/](../frontend/src/modules/moldinsight/) 与 [frontend/src/modules/inventory/](../frontend/src/modules/inventory/) - -因此,后续策略应是“**边界强化**”,不是“前端重写”。 - -### 10.3 建议的客户端边界 - -应继续收敛为: - -- `authApi` -- `moldinsightApi` -- `inventoryApi` - -并要求: - -- 页面/组件尽量不直接写裸 `/api/...` 字符串 -- multipart upload / download / export 也尽量通过域客户端封装 -- 统一利用 OpenAPI 生成类型,而不是额外维护平行手写类型 - -### 10.4 支持两类部署配置 - -#### unified 模式 -- `VITE_API_BASE_URL` - -#### split 模式 -- `VITE_AUTH_API_BASE_URL` -- `VITE_MOLDINSIGHT_API_BASE_URL` -- `VITE_INVENTORY_API_BASE_URL` - -客户端实现上应支持: - -- unified 下三个 client 指向同一个 base URL -- split 下各 client 指向不同服务 - -### 10.5 capability-aware UI - -在 gemold-only 或 inventory-only 部署模式下,前端不应假设所有模块总是存在。 - -因此建议: - -- 后端通过 `/health` 或单独 capability endpoint 暴露已启用模块信息 -- 前端根据 capability 隐藏未部署模块入口或禁用对应页面 - -这样可避免“前端路由还在,但后端根本没部署”的硬失败场景。 - ---- - -## 11. 分阶段迁移计划 - -### Phase 0:蓝图冻结 - -目标:冻结目标结构与边界规则,防止迁移过程中继续长出新的耦合。 - -动作: -- 确认模块边界 -- 确认依赖规则 -- 确认三种部署模式 -- 确认 shared/platform 的使用边界 - ---- - -### Phase 1:组合层标准化 - -目标:将部署模式从“若干入口脚本”升级为“正式的 composition layer”。 - -动作: -- 将 `entrypoints/*` 升级为 `compositions/*` -- 定义 `unified_app.py` / `gemold_app.py` / `inventory_app.py` -- 将 module-specific startup hooks 从通用 app factory 中迁出 - -重点问题: -- 当前 `mount_html -> RustFS connect` 属于模块专属逻辑,必须从 shared factory 中剥离 - ---- - -### Phase 2:platform 与业务代码分治 - -目标:把“共享基础设施”从“共享杂项”中真正分离出来。 - -动作: -- 从 `shared` 语义切换到更清晰的 `platform` -- 归位 config / auth / db / observability / utils -- 禁止新业务逻辑继续沉积到 `shared` - ---- - -### Phase 3:ORM 按归属拆分 - -目标:解决当前最大的代码耦合源。 - -动作: -- 拆分 [database.py](../src/shared/models/database.py) -- 保持单 Base / 单 Alembic / 单 DB -- 先完成代码层归属拆分,再处理更深层的业务隔离 - -这是整个重构中最关键的一步。 - ---- - -### Phase 4:模块内部继续分层 - -目标:让每个模块内部的“路由 / 服务 / 领域 / 基础设施”边界更清晰。 - -动作: -- inventory:从现有 service 层继续向 `application / domain / infrastructure / interfaces` 拉开 -- moldinsight:逐步理顺 `api / services / core / storage` 的边界 - -原则: -- 不要求一步完成 DDD 化 -- 先把层次职责清楚,再考虑更纯粹的领域对象抽象 - ---- - -### Phase 5:建立跨模块集成规则 - -目标:把当前 ad hoc 跨表访问逐步收敛成显式桥接能力。 - -动作: -- 定义跨模块 query services / repository contracts -- 明确“从分析创建成品”等桥接能力的正式入口 -- 收敛直接穿透跨模块 ORM 图谱的做法 - -重点桥接场景: -- `STPFile.product_id` -- [product_routes.py](../src/inventory/api/product_routes.py) 中的“按 task 创建产品”逻辑 - ---- - -### Phase 6:前端边界加固 - -目标:让前端真正适配 unified / split deployment。 - -动作: -- 强制域 API client 收口 -- 支持 per-module base URL -- 支持 capability-aware UI -- 减少页面中裸 `fetch('/api/...')` - ---- - -### Phase 7:部署与文档收尾 - -目标:使架构蓝图与部署事实一致。 - -动作: -- 固化 unified / gemold-only / inventory-only 部署说明 -- 更新 README / deployment docs / frontend docs -- 明确旧入口、旧 Dockerfile、旧部署说明的地位(兼容 / 历史 / 废弃) - ---- - -## 12. 风险与缓解措施 - -### 风险 1:共享模型文件继续隐藏领域归属 - -**现象**:所有模型集中在 [database.py](../src/shared/models/database.py) - -**风险**:边界无法落实,任何模块都能自然跨领域访问 - -**缓解**: -- 先产出表归属矩阵 -- 再拆 ORM 文件 -- 拆归属优先于改业务逻辑 - ---- - -### 风险 2:`shared` 继续变成杂物间 - -**风险**:shared/platform 成为“不知道放哪就放这里”的位置 - -**缓解**: -- 以 `platform` 重新定义共享层 -- 明确只有技术性共享能力可进入 platform -- 代码 review 中禁止新增业务逻辑进入 platform - ---- - -### 风险 3:模块专属启动逻辑继续留在 app factory - -**现象**:当前 `mount_html` 分支控制 RustFS 连接 - -**风险**:平台层继续了解业务模块内部基础设施 - -**缓解**: -- module lifecycle hook -- composition 层控制模块 startup/shutdown -- 通用 app factory 保持纯平台化 - ---- - -### 风险 4:独立部署后,前端仍假设所有模块存在 - -**风险**:前端路由可见,但后端未部署,造成运行时错误 - -**缓解**: -- capability metadata -- feature gating -- 前端按模块部署形态动态隐藏入口 - ---- - -### 风险 5:单数据库导致开发者随意跨模块查表 - -**风险**:虽然数据库未拆,但代码边界被绕开 - -**缓解**: -- 表归属规则文档化 -- code review 要求说明跨模块访问理由 -- 逐步通过 query services 收口 - ---- - -### 风险 6:大爆炸式目录迁移导致 import churn - -**风险**:一次性移动所有目录,修改面过大,回归成本高 - -**缓解**: -- 分阶段迁移 -- 保留兼容 import 过渡层 -- 先稳定组合层与模型层,再做深层目录调整 - ---- - -## 13. 验证清单 - -### 13.1 结构验证 - -- `platform` 不 import 业务模块 -- `moldinsight` / `inventory` 无直接 api/services 互引 -- ORM 文件已按归属拆分,或至少表归属矩阵已文档化并被遵守 - -### 13.2 运行验证 - -#### unified -- 两类路由都能正常挂载 -- 统一 health / auth / request-id 机制生效 - -#### gemold-only -- inventory 路由未挂载 -- gemold 路由可用 -- RustFS / Celery 等专属依赖正常初始化 - -#### inventory-only -- moldinsight 路由未挂载 -- inventory 路由可用 -- 不依赖 moldinsight 专属基础设施即可启动 - -### 13.3 数据验证 - -- 三种部署模式使用同一 migration head -- 单数据库中的跨模块 FK 保持有效 -- Alembic 无分叉历史 - -### 13.4 前端验证 - -- unified 模式下,一个 base URL 即可跑通 -- split 模式下,各模块 base URL 可独立配置 -- 未部署模块能被隐藏或优雅失败 - ---- - -## 14. 文档联动更新计划 - -本蓝图批准后,以下文档应逐步对齐: - -- [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md) -- [LINUX_SETUP.md](./deployment/LINUX_SETUP.md) -- [DEPLOY_PORT.md](./deployment/DEPLOY_PORT.md) -- [PORT_CONFIG.md](./deployment/PORT_CONFIG.md) -- [PORT_REFACTOR_SUMMARY.md](./deployment/PORT_REFACTOR_SUMMARY.md) -- `README.md` -- `frontend/README.md` - -其中需要特别注意: - -- `README.md` 当前仍主要描述旧单体结构,与当前实际代码已有明显漂移。 -- 本文档应作为“当前目标架构”的权威蓝图,路线图与部署文档随后对齐。 - ---- - -## 15. 附录:实施热点文件 - -以下文件是后续实际重构时最关键的热点: - -### 平台与组合层 -- [app_factory.py](../src/shared/app_factory.py) -- [settings.py](../src/shared/config/settings.py) -- [database.py](../src/shared/database/database.py) -- [init_db.py](../src/shared/database/init_db.py) -- [moldinsight.py](../src/entrypoints/moldinsight.py) -- [inventory.py](../src/entrypoints/inventory.py) -- [main.py](../src/main.py) - -### 模型与边界 -- [database.py](../src/shared/models/database.py) -- [product_routes.py](../src/inventory/api/product_routes.py) - -### gemold 模块 -- [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py) -- [processing_service.py](../src/moldinsight/services/processing_service.py) -- [task_query_service.py](../src/moldinsight/services/task_query_service.py) - -### inventory 模块 -- [inventory/api/__init__.py](../src/inventory/api/__init__.py) -- [inventory_service.py](../src/inventory/services/inventory_service.py) -- [sales_order_service.py](../src/inventory/services/sales_order_service.py) -- [purchase_order_service.py](../src/inventory/services/purchase_order_service.py) -- [finance_service.py](../src/inventory/services/finance_service.py) - -### 前端边界 -- [api-client.ts](../frontend/src/shared/api-client.ts) -- [api.ts](../frontend/src/types/api.ts) - -### 演进与部署参考 -- [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md) -- [docker-compose.yml](../docker-compose.yml) - ---- - -## 16. 最终结论 - -本项目当前最适合的演进路径不是微服务,而是: - -> **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith** - -它既能保留当前业务闭环(模具分析 → 成品 → BOM → 销售/采购/库存),又能逐步降低共享层和模型层的结构耦合。 - -后续实施时,应优先按以下顺序推进: - -1. 固化组合层(deployment composition) -2. 纯化 platform/shared 边界 -3. 拆分共享 ORM 文件 -4. 再继续模块内部细分层次 -5. 最后收口前端 API 与部署文档 - -这条路径风险最低、收益最大,也最符合当前代码现状与团队演进成本。 \ No newline at end of file diff --git a/docs/CHECKLIST_ALUMINUM_FOAM_MOLD.md b/docs/CHECKLIST_ALUMINUM_FOAM_MOLD.md deleted file mode 100644 index 642d687..0000000 --- a/docs/CHECKLIST_ALUMINUM_FOAM_MOLD.md +++ /dev/null @@ -1,390 +0,0 @@ -# 铝制家电包装泡沫模具分模功能开发检查清单 - -## 文档信息 - -| 项目 | 内容 | -|------|------| -| **文档名称** | 铝制家电包装泡沫模具分模功能开发检查清单 | -| **版本** | 1.0 | -| **日期** | 2026-03-13 | -| **项目** | geMoldInsight 模具分模功能增强 | - ---- - -## 检查清单说明 - -本文档包含铝制家电包装泡沫模具分模功能开发的完整检查清单,用于跟踪开发进度和验收标准。 - ---- - -## 第一阶段:基础框架搭建 - -### 任务 1.1:创建铝泡沫模具参数类 - -- [ ] 创建 `AluminumFoamMoldParams` 数据类 -- [ ] 添加发泡倍率参数 (`expansion_ratio`) -- [ ] 添加目标密度参数 (`target_density`) -- [ ] 添加成型温度参数 (`molding_temp`) -- [ ] 添加收缩率参数 (`shrinkage_rate`) -- [ ] 实现参数验证方法 -- [ ] 设置合理的默认值 - -### 任务 1.2:创建铝泡沫材料数据库 - -- [ ] 创建 `FoamMaterialDatabase` 类 -- [ ] 添加 AlSi10Mg 材料数据 -- [ ] 添加 AlSi12 材料数据 -- [ ] 添加纯铝泡沫材料数据 -- [ ] 实现材料查询方法 -- [ ] 实现材料参数获取方法 - -### 任务 1.3:扩展现有模具生成器 - -- [ ] 修改 `MoldCavityGenerator` 构造函数 -- [ ] 添加铝泡沫参数支持 -- [ ] 添加 `set_foam_material()` 方法 -- [ ] 更新 `generate_mold_cavities()` 流程 -- [ ] 适配收缩补偿计算 -- [ ] 适配拔模角计算 - -### 任务 1.4:创建参数配置 API 接口 - -- [ ] 添加获取默认参数 API -- [ ] 添加设置参数 API -- [ ] 添加参数验证 API -- [ ] 添加模板保存 API -- [ ] 添加模板加载 API -- [ ] 实现请求参数解析 - -### 任务 1.5:前端参数面板开发 - -- [ ] 创建参数配置组件 -- [ ] 添加分模参数输入控件 -- [ ] 添加铝泡沫参数输入控件 -- [ ] 添加拔模参数输入控件 -- [ ] 添加高级参数折叠面板 -- [ ] 实现参数提交功能 -- [ ] 实现参数加载功能 - -### 任务 1.6:参数模板功能 - -- [ ] 创建预设模板(快速模式) -- [ ] 创建预设模板(经济模式) -- [ ] 创建预设模板(高精度模式) -- [ ] 实现模板保存功能 -- [ ] 实现模板加载功能 -- [ ] 实现模板列表功能 - -### 任务 1.7:参数验证逻辑 - -- [ ] 实现分型精度范围验证 -- [ ] 实现型腔匹配度验证 -- [ ] 实现拔模角范围验证 -- [ ] 实现收缩率范围验证 -- [ ] 实现温度范围验证 -- [ ] 返回详细错误信息 - -### 任务 1.8:阶段一集成测试 - -- [ ] 测试参数设置功能 -- [ ] 测试参数获取功能 -- [ ] 测试参数验证 -- [ ] 测试模板保存/加载 -- [ ] 测试前端参数面板 -- [ ] 测试 API 接口响应 -- [ ] 无阻塞性 bug - ---- - -## 第二阶段:分模算法优化 - -### 任务 2.1:改进法向量分析算法 - -- [ ] 添加高斯权重计算 -- [ ] 实现多点采样 -- [ ] 优化主方向识别 -- [ ] 处理法向量突变 -- [ ] 测试复杂几何产品 - -### 任务 2.2:实现多分型面检测 - -- [ ] 设计多分型面数据结构 -- [ ] 实现分型面优先级排序 -- [ ] 实现分型面序列生成 -- [ ] 处理分型面交叠 -- [ ] 测试 2 分型面案例 -- [ ] 测试 3+ 分型面案例 - -### 任务 2.3:倒扣区域检测 - -- [ ] 分析产品几何特征 -- [ ] 实现倒扣识别算法 -- [ ] 标记倒扣位置 -- [ ] 生成倒扣报告 -- [ ] 提供处理建议 - -### 任务 2.4:改进拔模角计算 - -- [ ] 集成 BRepOffsetAPI_DraftAngle -- [ ] 实现拔模方向检测 -- [ ] 实现拔模干涉检测 -- [ ] 处理拔模失败情况 -- [ ] 验证拔模后尺寸 - -### 任务 2.5:铝泡沫收缩补偿 - -- [ ] 基于发泡倍率计算收缩 -- [ ] 实现多向收缩 -- [ ] 补偿后尺寸验证 -- [ ] 处理不均匀收缩 - -### 任务 2.6:型腔分离优化 - -- [ ] 优化布尔运算参数 -- [ ] 处理复杂几何 -- [ ] 添加分离结果验证 -- [ ] 处理分离失败回退 - -### 任务 2.7:模具块生成 - -- [ ] 计算模具尺寸 -- [ ] 添加安全余量 -- [ ] 生成 A/B 板结构 -- [ ] 添加模架结构 -- [ ] 验证模具强度 - -### 任务 2.8:分型线平滑处理 - -- [ ] 实现 B 样条拟合 -- [ ] 处理尖角 -- [ ] 保持几何精度 -- [ ] 验证平滑效果 - -### 任务 2.9:算法性能优化 - -- [ ] 添加并行计算 -- [ ] 优化缓存策略 -- [ ] 性能测试 < 30 秒 -- [ ] 内存测试 < 1GB - -### 任务 2.10:阶段二集成测试 - -- [ ] 测试典型产品分模 -- [ ] 测试复杂产品分模 -- [ ] 测试多分型面产品 -- [ ] 测试算法稳定性 -- [ ] 性能达标 - ---- - -## 第三阶段:质量检测模块 - -### 任务 3.1:创建质量检测器类 - -- [ ] 创建 `MoldQualityInspector` 类 -- [ ] 定义检测接口 -- [ ] 设计结果数据结构 -- [ ] 实现批量检测 - -### 任务 3.2:分模面平滑度检测 - -- [ ] 实现曲率分析 -- [ ] 实现凹凸检测 -- [ ] 计算平滑度评分 -- [ ] 标记问题区域 - -### 任务 3.3:分模面连续性检测 - -- [ ] 实现边界检查 -- [ ] 实现间隙检测 -- [ ] 实现完整性验证 -- [ ] 报告问题位置 - -### 任务 3.4:模具结构合理性检测 - -- [ ] 实现模具尺寸检查 -- [ ] 实现壁厚检查 -- [ ] 实现干涉检查 -- [ ] 生成改进建议 - -### 任务 3.5:生产可行性评估 - -- [ ] 计算注塑压力 -- [ ] 计算锁模力 -- [ ] 估算成型周期 -- [ ] 评估生产成本 - -### 任务 3.6:质量报告生成 - -- [ ] 汇总检测结果 -- [ ] 生成文字说明 -- [ ] 添加图表 -- [ ] 支持 PDF 导出 -- [ ] 报告格式规范 - ---- - -## 第四阶段:可视化和交互 - -### 任务 4.1:分型面可视化增强 - -- [ ] 设置分型面颜色 -- [ ] 调整透明度 -- [ ] 边缘高亮 -- [ ] 与产品对比度 - -### 任务 4.2:分型线可视化增强 - -- [ ] 设置线条颜色 -- [ ] 调整线条粗细 -- [ ] 添加端点标记 -- [ ] 动态绘制效果 - -### 任务 4.3:交互式分型面调整 - -- [ ] 实现鼠标拖拽 -- [ ] 实时更新模型 -- [ ] 实现撤销功能 -- [ ] 实现重做功能 - -### 任务 4.4:交互式参数调整 - -- [ ] 实现滑块实时更新 -- [ ] 参数变化动画 -- [ ] 效果对比视图 - -### 任务 4.5:剖视图功能 - -- [ ] 实现剖切算法 -- [ ] 显示内部结构 -- [ ] 剖面切换动画 -- [ ] 多方向剖视 - -### 任务 4.6:测量工具 - -- [ ] 实现距离测量 -- [ ] 实现角度测量 -- [ ] 测量结果标注 -- [ ] 测量精度验证 - -### 任务 4.7:视角控制增强 - -- [ ] 添加预设视角 -- [ ] 实现动画过渡 -- [ ] 实现自动对准 - -### 任务 4.8:导出视图功能 - -- [ ] 实现 PNG 导出 -- [ ] 支持高清截图 -- [ ] 批量导出支持 - ---- - -## 第五阶段:数据接口和测试 - -### 任务 5.1:STEP 导出接口 - -- [ ] 实现 STEP 导出 -- [ ] 验证导出文件 -- [ ] 测试 CAD 兼容性 - -### 任务 5.2:JSON 数据导出 - -- [ ] 实现 JSON 导出 -- [ ] 包含完整参数 -- [ ] 包含几何数据 -- [ ] 包含质量报告 - -### 任务 5.3:PDF 报告导出 - -- [ ] 实现 PDF 生成 -- [ ] 添加质量报告内容 -- [ ] 添加图表 -- [ ] 格式规范美观 - -### 任务 5.4:IGES 格式支持 - -- [ ] 实现 IGES 导入 -- [ ] 实现 IGES 导出 -- [ ] 验证 CAM 兼容性 - -### 任务 5.5:集成测试 - -- [ ] 功能测试通过 -- [ ] 性能测试通过 -- [ ] 兼容性测试通过 -- [ ] 压力测试通过 - -### 任务 5.6:用户验收测试 - -- [ ] 功能演示完成 -- [ ] 用户反馈收集 -- [ ] 问题修复完成 -- [ ] 用户验收签字 - ---- - -## 功能验收检查表 - -### 核心功能 - -- [ ] 自动分模算法正常运行 -- [ ] 分型面检测准确 -- [ ] 分型线计算正确 -- [ ] 拔模角处理正确 -- [ ] 收缩补偿正确 - -### 参数系统 - -- [ ] 所有参数可配置 -- [ ] 参数验证正确 -- [ ] 参数模板可用 -- [ ] 参数保存成功 - -### 可视化 - -- [ ] 3D 模型正确显示 -- [ ] 分型面可视化 -- [ ] 分型线可视化 -- [ ] 型腔/型芯可视化 -- [ ] 交互操作流畅 - -### 质量检测 - -- [ ] 平滑度检测正常 -- [ ] 连续性检测正常 -- [ ] 结构检测正常 -- [ ] 可行性评估正常 -- [ ] 报告生成正常 - -### 数据接口 - -- [ ] STEP 导出正常 -- [ ] JSON 导出正常 -- [ ] PDF 导出正常 -- [ ] IGES 导出正常 - ---- - -## 性能验收检查表 - -- [ ] 分模时间 < 30 秒 -- [ ] 渲染帧率 > 30 FPS -- [ ] 内存占用 < 2 GB -- [ ] 支持 5 用户并发 - ---- - -## 代码质量检查表 - -- [ ] 代码符合 PEP 8 规范 -- [ ] 包含类型注解 -- [ ] 包含文档字符串 -- [ ] 单元测试覆盖 -- [ ] 无安全漏洞 -- [ ] 无硬编码密码 - ---- - -**文档结束** diff --git a/docs/DELIVERABLES.md b/docs/DELIVERABLES.md deleted file mode 100644 index 1be059a..0000000 --- a/docs/DELIVERABLES.md +++ /dev/null @@ -1,37 +0,0 @@ -# 交付物清单(本次产出) - -## 1. 分析报告(Markdown) - -- `docs/MOLD_ERP_ANALYSIS_REPORT.md` -- `docs/ZERO_FINISHED_INVENTORY_CERTIFICATE.md` -- `docs/PERFORMANCE_SCALABILITY_PLAN.md` -- `docs/PERFORMANCE_BENCHMARKS.md` -- `docs/UAT_CHECKLIST.md` -- `docs/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md` -- `docs/CONFLUENCE_ARCHIVE_STRUCTURE.md` - -## 2. 数据库脚本(PostgreSQL) - -- 冻结交付后模具订单(头+明细):`scripts/db/001_freeze_delivered_sales_orders.sql` -- 约束与索引补齐:`scripts/db/002_indexes_and_constraints.sql` -- 数据修复示例(状态归一):`scripts/db/003_data_fixups.sql` -- 分区模板(按月):`scripts/db/010_partitioning_template.sql` -- RLS 模板(按 org_id):`scripts/db/011_rls_template.sql` -- 审计追溯(old/new + 操作者/IP/UA):`scripts/db/020_audit_trail.sql` -- 审计留存清理(180 天):`scripts/db/021_audit_retention.sql` -- 慢 SQL 采样(pg_stat_statements):`scripts/db/030_pg_stat_statements.sql` - -## 3. 自动化测试(pytest) - -- 交付后冻结:`tests/test_sales_order_delivered_freeze.py` -- 订单/采购/库存主链路用例(参数化 ≥30):`tests/test_api_inventory_orders.py` - -## 4. 代码加固点(已落地) - -- 交付后冻结:应用层拒绝更新/删除/改状态/领料(`status=delivered`)。 -- 状态一致性:避免写入未允许的 `pending` 状态。 -- 性能优化:BOM 需求计算去 N+1;库存扣减使用原子更新降低并发超卖风险。 - -## 5. Word + PDF 导出建议 - -- 建议使用 pandoc 将 `docs/MOLD_ERP_ANALYSIS_REPORT.md` 导出为 docx/pdf,并将生成物作为 CI 产物归档。 diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 0000000..4faf282 --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,117 @@ +# geMoldInsight 部署总览(DEPLOYMENT) + +> 文档定位:**唯一的部署主题入口文档**。 +> 本文负责说明当前推荐部署模式、部署文档分工与历史文档去向;不承担全部 Linux 操作细节。详细 Linux 部署步骤见 [deployment/LINUX_SETUP.md](deployment/LINUX_SETUP.md),当前状态见 [STATUS.md](STATUS.md),架构边界见 [ARCHITECTURE.md](ARCHITECTURE.md)。 + +--- + +## 1. 当前推荐部署模式 + +当前推荐模式为: + +- **unified**:frontend + unified backend + moldinsight celery + +原因: +- 适合本地开发与集成环境 +- 前端同域反代可以面对单一 backend +- 比按路径把前端网关分流到两套后端更易维护 + +当前 Compose 入口: +- [docker-compose.yml](../docker-compose.yml) + +详细 Linux 部署步骤: +- [deployment/LINUX_SETUP.md](deployment/LINUX_SETUP.md) + +--- + +## 2. 支持的部署模式 + +### 2.1 unified + +一个统一后端同时挂载 moldinsight + inventory。 + +适合: +- 本地开发 +- 测试/集成环境 +- 小团队统一部署 + +### 2.2 moldinsight-only + +只部署模具分析后端。 + +适合: +- 独立开放分析能力 +- 异步任务与文件处理独立扩容 + +### 2.3 inventory-only + +只部署进销存后端。 + +适合: +- 独立部署 ERP / 库存能力 +- 与 moldinsight 分开发布节奏 + +部署模式的结构含义见 [ARCHITECTURE.md](ARCHITECTURE.md)。 + +--- + +## 3. 部署文档分工 + +### 3.1 当前权威文档 + +- [DEPLOYMENT.md](DEPLOYMENT.md) + - 部署入口与文档导航 +- [deployment/LINUX_SETUP.md](deployment/LINUX_SETUP.md) + - Linux 环境下的详细部署操作说明 + +### 3.2 端口与配置说明 + +以下文档当前仍保留,但后续会继续收敛: +- [deployment/DEPLOY_PORT.md](deployment/DEPLOY_PORT.md) +- [deployment/PORT_CONFIG.md](deployment/PORT_CONFIG.md) + +它们描述的是端口与环境配置细节,不应替代部署入口文档。 + +### 3.3 历史/阶段性部署材料 + +以下材料属于迁移期或历史说明,不应再视为当前部署权威: +- [archive/PORT_REFACTOR_SUMMARY.md](archive/PORT_REFACTOR_SUMMARY.md) +- [archive/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md](archive/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md) + +这些材料已迁入 `docs/archive/`。 + +--- + +## 4. 当前部署事实 + +当前部署上的几个关键事实: + +- 项目保持单仓库、单数据库 +- frontend 是独立前端工程 +- 后端支持模块化入口 +- moldinsight 的异步分析链路依赖 celery +- PostgreSQL / Redis / 对象存储通常复用服务器已有服务,而不是必须由项目 compose 自带 + +这些事实的当前版本以 [STATUS.md](STATUS.md) 和 [deployment/LINUX_SETUP.md](deployment/LINUX_SETUP.md) 为准。 + +--- + +## 5. 相关专题文档 + +以下文档可作为部署/存储方向的补充参考,但不替代部署入口文档: + +- [deployment/DEPLOY_PORT.md](deployment/DEPLOY_PORT.md) +- [deployment/PORT_CONFIG.md](deployment/PORT_CONFIG.md) +- [topics/storage/RUSTFS_STORAGE.md](topics/storage/RUSTFS_STORAGE.md) +- [topics/storage/STORAGE_SETUP.md](topics/storage/STORAGE_SETUP.md) + +--- + +## 6. 后续整理原则 + +部署文档后续将遵循以下规则: + +- 部署入口信息只在本文维护 +- 操作步骤只在 [deployment/LINUX_SETUP.md](deployment/LINUX_SETUP.md) 维护 +- 历史迁移说明与阶段计划迁入 `docs/archive/` +- README 只保留最短启动说明,不再承担部署手册职责 diff --git a/docs/EVOLUTION_ROADMAP.md b/docs/EVOLUTION_ROADMAP.md deleted file mode 100644 index a7cf3ca..0000000 --- a/docs/EVOLUTION_ROADMAP.md +++ /dev/null @@ -1,258 +0,0 @@ -# geMoldInsight 演进路线图 - -> 本文档是代码与功能演进的执行清单,基于 2026-07-13 的全量代码体检。每项含「现象 / 证据 / 修法 / 验证」,按 P0→P3 推进,完成后勾选。 - -## 诊断 - -代码已演进到「双应用模块化」形态(`entrypoints/` + `moldinsight/` + `inventory/` + `shared/`),但有 **三处结构性缺失** 让快速迭代变贵,外加 **一批静默 bug** 正在让功能"看起来在跑其实没跑": - -- **缺中间层**:业务逻辑堆在路由/编排函数里(进销存无 service 层、`process_file_core` 280 行线性函数) -- **缺契约**:前后端靠手写类型,字段已大面积漂移(财务页整页是 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` 未连接直接抛错。`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_receivable` vs `receivable_total`(`finance_schemas.py:66`)、`order_no` vs `txn_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)` 并行操作 OCC `TopoDS_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 同步客户端连一次复用);`docker-compose.yml` celery 服务补 `REDIS_PASSWORD`/`RUSTFS_TIMEOUT` -- ✅ **P0-2 LLM NameError**:`llm_service.py:339` `trimmed` -> `features` -- ✅ **P0-3 前端字段错配**:FinanceTab 全字段对齐 schema(summary/statement/product-statement/transaction 共 16 处);`UserResponse` 加 `is_superuser` + 统一 `_build_user_response` 构造(修用户管理菜单不显示);DashboardTab `product_count`->`finished_product_count`;PurchaseOrdersTab `received_at/paid_at`->`received_date/paid_date`;后端 `FinanceTransactionResponse` 补 `partner_name` 并批量查询客户/供应商名称 -- ✅ **P0-4 OCC 线程安全**:`geometry_analyzer._detect_features` `max_workers` 4->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.py` 751 行、`sales_order_routes.py` 777 行,事务编排/库存原子更新/流水写入全耦合在 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_core` 280 行。 -- **目标**:`FeatureDetectorRegistry` + `MoldGeneratorRegistry`(`@register` 装饰器);`process_file_core` 拆成 Stage 链。 -- **解锁**:新增模具类型、IGES/BREP、批量分析。 -- **进展(2026-07-15)**:✅ `MoldGeneratorRegistry`(消除 `multi_scheme_planner` if-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`。 -- **状态**:- [x](见 P4-1) - -### P1-4 引入 Alembic,废除裸 DDL -- **现状**:无 `alembic.ini`;`init_db.py` 22 条 `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_service` 0.020 vs `aluminum_foam_mold.py:92` 0.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.py` 209 行纯 stub 从未被调用;`ai_parting_detector.py` GNN 框架完整但无权重;`llm_service` 是唯一真接 AI(且有 P0-2 bug)。 -- **目标**:聚焦一个能跑通的 AI 能力(LLM 扩到成本估算/工艺对话);GNN 要么真训权重,要么移除 stub。 -- **进展(2026-07-27)**:✅ `ai_mold_assistant.py` stub 已删除(P3-3 死代码清理);✅ LLM 成本估算已落地(`llm_service.estimate_cost` + `POST /api/cost-estimate`);✅ 规则式兜底(`cost_estimate_service.py`,LLM 未启用时自动降级);⏳ GNN `ai_parting_detector.py` 仍无权重,待决策保留或移除 -- **状态**:- [~](成本估算完成,GNN 待决策) - -### P2-3 模具成本估算 + 批量分析 -- 依赖 P1-2 完成后才有性价比。 -- **进展(2026-07-27)**: - - ✅ **P2-3a 前端成本估算 UI**:ResultView 新增「💰 成本估算」按钮 + 锚点导航 + 成本卡片(模具造价/单件成本/估算假设/置信度) - - ✅ **P2-3b 规则式兜底**:`cost_estimate_service.py`(模具钢材料单价表 + 加工复杂度系数 + 侧向机构附加费),LLM 未启用时 `advanced_router` 自动调用规则引擎 - - ✅ **P2-3c 批量上传后端**:`batch_router.py`(多文件 `POST /api/batch-upload` + Redis batch_id→task_ids 映射 24h TTL + `GET /api/batch/{batch_id}` 聚合查询),复用现有 `processing_service` + Celery 并发 - - ✅ **P2-3d 批量前端 UI**:`BatchView.vue`(拖拽多文件上传 + 进度看板 + 轮询 + 任务表格),MoldInsightView 入口按钮 -- **状态**:- [x] - -### P2 执行结果 - -- ✅ **P2-1 打通模具分析 -> 进销存**:`STPFile` 加 `product_id` 外键(nullable+index+FK)+ Alembic 迁移 `006c18c51b0d`(首次真实迁移);inventory `POST /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 -> 销售/采购的业务闭环接通** -- ✅ **P2-2 真 AI 落地(部分)**:删除 `ai_mold_assistant.py` 死代码;LLM 成本估算 + 规则兜底双路径已上线 -- ✅ **P2-3 成本估算 + 批量分析(全部完成)**:前端成本卡片 + 规则式兜底 + 批量上传后端 + 批量进度看板 - ---- - -## P3 工程治理(穿插顺手做) - -- [x] `create_app()` 工厂消除两入口重复引导,废弃单体 `main.py` → `shared/app_factory.py`(2026-07-27) -- [x] 删死依赖/死代码:Kafka 依赖删除、`templates/` 三个 legacy Jinja 模板删除、`task_router` result_page 死端点删除、`ProcessingService.__init__` 3 个死实例删除(2026-07-27) -- [x] `get_db_session` 统一事务边界(成功 commit / 异常 rollback),inventory 路由 commit→flush(2026-07-27) -- [x] 连接池治理:web `pool_size=10, max_overflow=20` / celery `pool_size=5, max_overflow=10`,环境变量可覆盖(2026-07-27) -- [x] 进销存 state 从模块级单例迁回 Pinia `defineStore`,tab 改子路由(URL 可分享/回退)(2026-07-27) -- [x] 统一 `/health` 响应 schema(status/service/version/database_connected);SPA fallback 排除 `/api`、`/docs`、`/openapi` 前缀(2026-07-27) -- [x] CORS 收敛:`CORS_ORIGINS` 环境变量白名单,空则降级 `["*"]` + 警告日志(2026-07-27) - -### P3 执行结果(全部完成,2026-07-27) - -- ✅ **P3-1 CORS 收敛**:`settings.py` 新增 `CORS_ORIGINS` 解析;`app_factory.py` 从白名单创建 CORS,空则 `["*"]` + warning -- ✅ **P3-2 /health + SPA fallback**:`app_factory.py` 统一 GET+POST /health(含 database_connected 检测);catch-all 排除 `api/`/`docs`/`openapi` 前缀 -- ✅ **P3-3 删除死代码**:`requirements.txt` + `deploy/requirements-moldinsight.txt` 删 `kafka-python`;删除 `templates/*.html` 三个 legacy 模板;`task_router.py` 删 `result_page` 端点;`processing_service.py` 删 3 个死实例 + 死 import -- ✅ **P3-4 事务边界**:`database.py` 的 `get_db_session` 统一 commit/rollback;inventory 5 个路由共 25 处 `commit()` → `flush()` -- ✅ **P3-5 连接池**:`database.py` 按角色分层 `_get_pool_config()`,web/celery 分别配置;`celery_tasks.py` 初始化 celery 角色引擎 -- ✅ **P3-6 app_factory**:新建 `shared/app_factory.py`(CORS/日志中间件/静态文件/startup/shutdown/health/SPA fallback);两入口各 ~30 行 -- ✅ **P3-7 Pinia + 子路由**:新建 `stores/inventory.ts`(defineStore);`useInventory.ts` 改为薄壳委托;10 个 Tab 子路由懒加载;Sidebar 改 `router.push` - ---- - -## 执行进度 - -| 阶段 | 项数 | 已完成 | 进行中 | -|------|------|--------|--------| -| P0 | 7 | 6 修复 + 1 排查 | - | -| P1 | 5 | 5 | P1-1~P1-5 全部完成(P1-2 Stage 流水线暂缓) | -| P2 | 3 | 3 | P2-1+P2-2(部分)+P2-3 全部完成 | -| P3 | 7 | 7 | 全部完成 | -| P4 | 10 | 4 | P4-1 OpenAPI 契约 + P4-4 采购需求推导 + P4-6 集成测试 + P4-7 结构化日志 | - ---- - -## P4 后续演进方向(待规划) - -### 方向 A:前端工程化加固(低风险、高收益) - -#### P4-1 OpenAPI 契约自动生成 ✅ -- **现状**:前端 `any` 泛滥,字段靠手写已多次错配(P0-3 教训) -- **目标**:`openapi-typescript` 从 `/openapi.json` 生成 TS interface,替换 `types/schemas.ts` 中的 `any`;`api.ts` 按域封装 `inventoryApi` / `moldinsightApi` / `authApi` -- **体量**:~1 天 -- **完成(2026-07-27)**:`openapi.json` 双服务统一(70 paths / 76 schemas);`types/api.ts` 自动生成(5500+ 行);`api-client.ts` 按域封装(authApi/inventoryApi/moldinsightApi);`stores/inventory.ts` 核心 ref 加 `Schema<>` 类型标注 - -#### P4-2 Stage 流水线拆分 -- **现状**:`process_file_core` 278 行线性函数,新增分析阶段需改核心函数 -- **目标**:拆成 Stage 链(parse_stp → detect_features → plan_mold → generate_visualization → analyze_design → generate_report → finalize),每个 Stage 可独立测试和替换 -- **前提**:需在有 OCC 的环境下运行时验证 -- **体量**:~2-3 天 - -### 方向 B:业务闭环深化 - -#### P4-3 模具分析报告 → 销售订单关联 -- **现状**:P2-1 已打通 STP→成品,但分析报告(HTML)与销售订单无直接关联 -- **目标**:销售订单创建时可选择关联 moldinsight task_id,订单详情页嵌入分析报告 iframe/摘要;报价单自动引用成本估算数据 -- **体量**:~2 天 - -#### P4-4 采购需求自动推导 ✅ -- **现状**:BOM 定义了成品所需物料,但采购仍需手动创建 -- **目标**:销售订单确认 → 按 BOM 展开物料需求 → 对比当前库存 → 自动生成采购建议(缺多少、建议供应商、预计金额);一键转为采购订单 -- **体量**:~3 天 -- **完成(2026-07-27)**:`purchase_demand_schemas.py`(Request/ItemResponse/Response)+ `purchase_demand_service.py`(6 步算法:批量查询订单→BOM 展开含损耗率→聚合需求→库存对比→主供应商推荐→按缺口降序排列)+ `purchase_demand_routes.py`(薄路由 `POST /api/purchase-demands/calculate`)+ 前端「采购建议」按钮 + 对话框(多选销售订单 + 结果表格含缺口/供应商/交期) - -#### P4-5 GNN 分型面检测(决策项) -- **现状**:`ai_parting_detector.py` 有框架无权重,从未被调用 -- **选择**:(a) 投入训权重(需标注数据集 + GPU);(b) 改为规则式分型面推荐(利用已识别的 Undercut/Pocket 特征 + 几何启发式);(c) 彻底移除,减少维护负担 -- **建议**:短期选 (b) 或 (c),等数据积累后再考虑 (a) - -### 方向 C:可靠性与可观测性 - -#### P4-6 集成测试覆盖 ✅ -- **现状**:`tests/` 仅 2 个测试文件,核心业务流程无回归保障 -- **目标**:关键路径 pytest 覆盖——STP 上传→分析→创建成品→销售订单→采购→库存变动;mock OCC 外部依赖 -- **体量**:~2-3 天 -- **完成(2026-07-27)**:`conftest.py` 重构(SQLite + aiosqlite + FK 逆序清空 + 每测试重新播种);`test_purchase_demand.py` 5 个用例(正常推导/缺货/无效订单/无BOM/空请求);`test_api_inventory_orders.py` 32 个用例(库存/采购/销售/物料/StockMovement CRUD + 校验);`test_sales_order_delivered_freeze.py` 2 个用例(交付冻结/非交付可改);`sales_order_service.py` 补 delivered 状态守卫 bug 修复;39 测试全通过 - -#### P4-7 结构化日志 + 请求追踪 ✅ -- **现状**:`app_factory.py` 有请求日志中间件,但无 request_id 贯穿、无结构化 JSON 输出 -- **目标**:中间件注入 `X-Request-ID`;日志格式改 JSON(timestamp/level/request_id/service/path/duration_ms);接入 Prometheus `/metrics` 端点(请求计数/延迟/错误率) -- **体量**:~1 天 -- **完成(2026-07-27)**:`logger.py` 升级为 JSON 结构化日志(`JSONFormatter` + `TextFormatter`)+ `contextvars` request_id 跨 async 传播;`app_factory.py` 中间件升级(自动生成/提取 `X-Request-ID`、注入响应头、全请求结构化日志含 method/path/status/duration_ms/client_ip);支持 `LOG_FORMAT`/`LOG_LEVEL` 环境变量切换;Prometheus `/metrics` 端点归入后续 P4-8 或独立任务 - -#### P4-8 Celery 任务可靠性 -- **现状**:任务失败无自动重试;无死信队列;批量任务进度仅靠 Redis TTL -- **目标**:`@task(autoretry_for, retry_backoff)` 自动重试;死信队列记录永久失败任务;批量任务完成后写 PG 持久化(不依赖 Redis TTL 过期) -- **体量**:~1-2 天 - -### 方向 D:格式扩展与性能 - -#### P4-9 IGES / BREP 格式支持 -- **现状**:仅支持 STP/STEP,注册表模式已就绪(P1-2) -- **目标**:`IgesParserStage` + `BrepParserStage` 注册到流水线;前端上传组件扩展 accept 列表 -- **前提**:依赖 P4-2 Stage 流水线完成 -- **体量**:~1-2 天(流水线就绪后) - -#### P4-10 大文件分析性能优化 -- **现状**:大模型(>1000 面)分析耗时线性增长,点云采样全量处理 -- **目标**:自适应采样(按曲率密度分配采样点);LOD 分级(远距低模 + 近距高模);分析结果增量更新(仅重算变更区域) -- **体量**:~3-5 天 diff --git a/docs/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md b/docs/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md deleted file mode 100644 index af96892..0000000 --- a/docs/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md +++ /dev/null @@ -1,315 +0,0 @@ -# 前端独立部署 + 统一后端入口实施计划 - -> 目标:在已经切换到“前端独立部署 + 同域反代”的基础上,进一步取消前端 Nginx 对 `/api` 的路径级分流,改为反代到一个真正的 **unified backend**,一次性解决长期维护成本。 - ---- - -## 1. 背景 - -当前项目已经完成了两项关键演进: - -1. 前端从历史 `static/` 托管模式中抽离,开始走独立构建与独立部署 -2. 前端通过同域 Nginx 反代访问后端 API 与分析产物 - -但当前 Nginx 仍然承担了“后端路由所有权判断”的职责: - -- 一部分 `/api/...` 被转发到 `moldinsight` -- 另一部分 `/api/...` 被转发到 `inventory` - -这虽然能跑通当前功能,但长期存在明显问题: - -- 每新增一个 gemold API,Nginx 都要同步改配置 -- Nginx 配置承担了业务边界知识,维护成本高 -- `/health` 只能代表某一套后端,而不是统一入口 -- 与“unified / gemold-only / inventory-only”三种部署模式的目标不完全一致 - -因此,本轮改造的目标是: - -> 把前端入口反代逻辑从“按路径分流到两套后端”升级为“统一反代到一个 unified backend”。 - ---- - -## 2. 目标状态 - -### 浏览器视角 - -浏览器始终只访问一个同域入口: - -- `/` → 前端静态页面 -- `/api/*` → unified backend -- `/health` → unified backend -- `/html/*` → unified backend(由 unified backend 再提供 gemold 产物访问) - -### Nginx 视角 - -Nginx 不再负责理解 gemold / inventory 的业务边界。 - -它只做两件事: - -1. 提供前端静态文件与 SPA fallback -2. 把 `/api`、`/health`、`/html` 统一转发给一个 backend upstream - -### 后端视角 - -后端新增一个统一入口,负责组合: - -- auth -- moldinsight routes -- inventory routes -- `/health` -- `/html` - -同时继续保留: - -- `moldinsight-only` -- `inventory-only` - -以满足模块独立部署场景。 - ---- - -## 3. 设计决策 - -### 3.1 为什么要引入 unified backend - -因为前端与网关层最适合面对的是一个统一后端,而不是两套需要网关手工分流的内部模块。 - -收益: - -- Nginx 配置显著简化 -- 新增 API 不需要修改网关规则 -- 文档和运维认知更简单 -- 前端保持统一 `/api` 契约 -- 更符合模块化蓝图中对 `unified` 模式的定义 - -### 3.2 为什么不直接把 split 模式删掉 - -因为: - -- `gemold-only` 和 `inventory-only` 仍然有独立部署价值 -- 当前仓库已经形成了清晰模块边界 -- 统一入口应该成为**前端同域反代的默认方案**,而不是抹掉模块部署模式 - -所以最终保留三类入口: - -- `src/entrypoints/unified.py` -- `src/entrypoints/moldinsight.py` -- `src/entrypoints/inventory.py` - ---- - -## 4. 需要改动的核心文件 - -## 4.1 新增 unified 入口 - -新增: -- `src/entrypoints/unified.py` - -职责: -- 基于 `shared.app_factory.create_app()` 创建应用 -- 统一挂载: - - `moldinsight.api.router`(prefix=`/api`) - - `inventory.api.inventory_router` -- 使用: - - `mount_html=True` - - `serve_frontend_static=False` -- 不额外挂载 auth(交给 `app_factory`) -- 不手工重复定义 `/health` - -## 4.2 简化前端 Nginx - -修改: -- `deploy/nginx/frontend.conf` - -从当前: -- 双 upstream:`moldinsight` / `inventory` -- 多个 `location /api/...` 手工分流 - -改成: -- 单 upstream:例如 `gemold_backend_upstream` -- 统一转发: - - `/api/` → unified backend - - `/health` → unified backend - - `/html/` → unified backend - -保留: -- `/` 的 SPA fallback -- `/assets/` 的静态缓存策略 - -## 4.3 调整 Compose - -修改: -- `docker-compose.yml` - -目标: -- 增加 unified backend 服务 -- `frontend` 只依赖 unified backend -- 保留 `moldinsight-celery` -- 按需保留 split backend 入口作为独立 profile - -建议最终 profile 语义: - -- `full`:frontend + unified + celery -- `frontend`:仅前端入口 -- `moldinsight`:仅 gemold-only -- `inventory`:仅 inventory-only -- (可选)`unified`:仅 unified backend - -## 4.4 视实现需要调整 Dockerfile - -可能新增: -- `deploy/Dockerfile.unified` - -或复用已有: -- `deploy/Dockerfile.moldinsight` - -取决于是否希望 unified backend 使用单独镜像名。 - -统一要求: -- unified backend 镜像必须包含: - - `src/moldinsight/` - - `src/inventory/` - - `src/shared/` - - `src/entrypoints/unified.py` - -## 4.5 文档同步 - -需要更新: -- `README.md` -- `frontend/README.md` -- `docs/deployment/LINUX_SETUP.md` -- `docs/deployment/DEPLOY_PORT.md` -- `docs/deployment/PORT_CONFIG.md` - -重点改动: -- 当前推荐部署方式改为“frontend + unified backend + celery” -- 说明 split 模式仍保留,但不再是前端同域反代默认方式 -- 端口说明中要区分: - - 前端入口端口 - - unified backend 内部/对外端口 - - gemold-only / inventory-only 模块端口 - ---- - -## 5. 路由与冲突评估 - -根据当前代码结构,unified 模式可行,主要原因: - -- inventory 所有业务路由都挂在 `/api` 下,并且以独立业务前缀区分 -- moldinsight 业务路由同样挂在 `/api` 下,但使用不同子路径 -- auth 路由使用 `/api/auth` -- top-level `/health` 由 `app_factory` 提供 -- moldinsight 内部还有 `/api/health`,与 top-level `/health` 不冲突 -- `/html` 只有 moldinsight 需要 - -关键约束: - -1. unified 入口中不要重复 include auth -2. unified 入口中不要手工再定义 top-level `/health` -3. unified 入口必须 `mount_html=True` - ---- - -## 6. 风险与控制 - -### 风险 1:统一入口与现有 split 入口行为不一致 -**控制:** -- 保留现有 `moldinsight.py` 与 `inventory.py` -- 只把 unified 作为前端默认 upstream - -### 风险 2:`/health` 语义变化 -当前前端只请求一个 `/health`,但 split 时代它实际上只代表某个后端。 - -**控制:** -- unified 上的 `/health` 明确作为“前端默认 backend 健康入口” -- 文档中明确其语义 - -### 风险 3:`/html` 丢失或不可达 -**控制:** -- unified backend 继续 `mount_html=True` -- 前端 Nginx 保留 `/html/` 反代 - -### 风险 4:Compose、Nginx、文档不同步 -**控制:** -- 先写本计划文档 -- 再改 unified 入口、Nginx、Compose -- 最后统一 README 与 deployment docs - ---- - -## 7. 验证方案 - -## 7.1 路由验证 - -unified backend 启动后应验证: - -- `/api/auth/login` -- `/api/auth/me` -- `/api/upload` -- `/api/status/{task_id}` -- `/api/history` -- `/api/cost-estimate` -- `/api/products` -- `/api/inventory` -- `/api/dashboard` -- `/api/finance/*` -- `/health` -- `/html/...` - -## 7.2 前端验证 - -前端同域访问应验证: - -- `/login` -- `/moldinsight` -- `/inventory` -- `/moldinsight/result/:taskId` - -关键交互: - -- 登录 -- 模具上传 -- 任务轮询 -- 成本估算 -- 产品/库存/订单页面加载 -- `/html` 分析结果页访问 - -## 7.3 Compose 验证 - -完整系统: - -```bash -docker compose --profile full up -d -``` - -应满足: -- `frontend` 正常提供页面 -- `frontend` 只反代一个 unified backend -- `moldinsight-celery` 正常运行 -- 不再依赖 Nginx 路径级业务分流 - ---- - -## 8. 实施顺序 - -1. 新增 `docs/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md` -2. 新增 `src/entrypoints/unified.py` -3. 修改 `deploy/nginx/frontend.conf` -4. 修改 `docker-compose.yml` -5. 按需要修改 Dockerfile / 构建脚本 -6. 更新 README 与 deployment docs -7. 做一致性验证 - ---- - -## 9. 最终预期 - -完成后,系统对外部署形态将变成: - -- 前端:独立 Nginx 静态站点 -- 网关:同域同入口 -- 后端:一个 unified backend 作为前端默认 upstream -- worker:保留 gemold Celery 异步处理 -- split 模式:继续作为模块独立部署能力保留 - -这能一次性解决当前“前端入口依赖 Nginx 路径级业务分流”的长期维护问题。 \ No newline at end of file diff --git a/docs/MOLDINSIGHT_TECH_DEBT_PLAN.md b/docs/MOLDINSIGHT_TECH_DEBT_PLAN.md deleted file mode 100644 index 942a28d..0000000 --- a/docs/MOLDINSIGHT_TECH_DEBT_PLAN.md +++ /dev/null @@ -1,127 +0,0 @@ -# moldinsight 模块技术债务分析与重构计划 - -> 日期:2026-08-31 · 基线 commit:`3ea5955`(模块拆分 init) -> 状态标记:`[ ]` 待办 / `[x]` 已完成 / `[~]` 部分完成 - ---- - -## 一、问题清单(按严重程度) - -### A. 安全漏洞(P0) - -| # | 问题 | 位置 | 影响 | -|---|------|------|------| -| S1 | `/api/debug/tasks` 无鉴权,全量 dump 所有用户任务(含 geometry_data、analysis_result、文件名、LLM 报告)及 Redis 拓扑信息 | `api/debug_router.py:9-20` | 跨用户数据泄露 | -| S2 | `/api/history` 与 `/api/history/{filename}` 无鉴权,且 `get_all_file_groups()` 未传 user_id(参数形同虚设) | `api/history_router.py:25-40`、`services/storage_integration_rustfs.py:698-704` | 跨用户文件清单泄露 | -| S3 | `_ensure_task_access` 对 `owner_id is None` 的无主数据直接放行 | `api/advanced_router.py:87-89` | 任意登录用户可下载历史无主任务的导出文件 | - -### B. 静默失败(P0) - -| # | 问题 | 位置 | 影响 | -|---|------|------|------| -| F1 | `/api/detect-undercuts` 传 `shape=None`,OCC 异常被兜底 except 吞掉,**永远返回"无倒扣"的假 DFM 结论** | `api/advanced_router.py:293-302`、`core/side_action_designer.py:205-218` | 功能性错误,用户拿到 200 + 错误工程结论 | -| F2 | `asyncio.wait_for` 超时无法杀死 OCC 线程;`_occ_executor` 为 `max_workers=1`,一个病态文件可**永久堵死全部分析队列**直到重启 | `services/processing_service.py:44-45,74-82` | 服务级可用性风险 | -| F3 | `asyncio.create_task(...)` 未持有引用(GC 可回收任务)且无并发上限 | `api/upload_router.py:99-108`、`api/batch_router.py:114-121` | 后台任务静默消失 / 内存失控 | - -### C. 性能与资源(P1) - -| # | 问题 | 位置 | 影响 | -|---|------|------|------| -| P1 | 已完成任务每次状态轮询都从 RustFS 全量拉取 geometry + 多方案型腔 JSON + 网格 + 完整 HTML,无缓存 | `services/task_query_service.py:54-58` | 轮询 5s 一次 = 每次几十 MB 对象存储流量 | -| P2 | `_export_shapes_cache` 缓存 OCC TopoDS_Shape(C++ 原生内存),按 task_id 无上限增长,无 LRU/TTL | `services/processing_service.py:43` | 原生内存泄漏 | -| P3 | `save_html_file` 双写:完整 HTML 既入 RustFS 又塞 PG 行(`html_content`) | `services/storage_integration_rustfs.py:448-462` | PG 表膨胀 + 双份数据一致性负担 | -| P4 | `get_all_file_groups` 每文件组单独一次 count 查询(N+1) | `services/storage_integration_rustfs.py:745-751` | history 接口放大 100 倍查询 | -| P5 | `update_task` 为 get->merge->set 三步非原子,后台流程与 export-mold 端点并发写同一任务会**丢更新**;且每次进度 tick 全量重写整个 blob | `shared/services/redis_task_manager.py:138-146` | 竞态丢数据 + 写放大 | -| P6 | 服务重启后 `_export_shapes_cache` 清空,STL 等格式的重导出直接 409 | `api/advanced_router.py:477-481` | 用户体验缺陷 | -| P7 | `get_task_view` 已 joinedload `html_file` 后又单独查询 HTMLFile;`llm_service._chat` 每次新建 httpx client 且无重试 | `services/task_query_service.py:76-81`、`services/llm_service.py:517-531` | 小浪费 × 高频 | - -### D. 架构与死代码(P2) - -| # | 问题 | 位置 | 影响 | -|---|------|------|------| -| D1 | ~1000 行死代码:`storage_integration.py`(MinIO版,376行,零引用)、`storage/object_storage.py`(361行,仅被死文件引用)、`storage_service.py`(295行,零引用,仍用已弃用列)、`src/main.py`(废弃单体,~230行) | 详见各文件 | 认知负担 + 误用风险 | -| D2 | **根 Dockerfile 仍在运行旧单体** `python src/main.py`,在仓库根目录 `docker build .` 会部署出错误服务 | `Dockerfile:28` | 部署陷阱 | -| D3 | planner 调用 generator 13 个 `_` 前缀私有方法,私有方法成为事实契约;公共 API `generate_mold_cavities` 反而无人使用 | `core/multi_scheme_planner.py:38,102-165` | core 边界糊化,重构即炸 | -| D4 | `REDIS_HOST` 两处读取两个默认值,其一为硬编码个人主机名 `szcjw`;settings 在 **import 时**因缺 DB 配置直接 raise | `shared/services/redis_task_manager.py:38`、`shared/config/settings.py:50-51` | 配置漂移 + 模块不可导入即不可测 | -| D5 | upload/batch 约 50 行复制粘贴(参数归一化 + Celery/asyncio 分派);`process_file_with_storage` 与 `process_file_core` 异常处理两份拷贝 | `api/upload_router.py:43-49` vs `api/batch_router.py:62-68` | 漂移风险 | -| D6 | moldinsight 测试覆盖为零;唯一测试 `temp_test_injection_p0.py` 因无 `test_` 前缀不被收集,且用黑加载规避 settings 导入期失败 | `tests/` | 回归无保障 | -| D7 | 铝价服务返回模拟数据但未在任何层面标注 | `services/aluminum_price_service.py` | 产品诚信问题 | - ---- - -## 二、实施方案 - -### P0:安全 + 静默失败(先做) - -- [x] **① 补鉴权(修 S1/S2/S3)** - - `history_router` 两个端点加 `get_current_active_user` 依赖,显式传 `user_id=current_user.id` - - `debug_router` 加鉴权,且仅在 `settings.DEBUG` 下注册 - - `_ensure_task_access` 改为 `owner_id != user_id` 即 403(无主数据同样拒绝) - -- [x] **② 统一后台分派(修 F3,消 D5 一半)** - - 新建 `services/task_dispatcher.py`:Celery 可用走 `process_stp_task.delay`;否则 `asyncio.create_task` 并持有强引用(`_background_tasks` set + done_callback 回收) - - upload/batch 路由统一调用;`asyncio.Semaphore` 限制 API 进程内并发处理数 - -- [x] **③ 超时后重置 OCC executor(修 F2)** - - `asyncio.TimeoutError` 分支调用 `_reset_occ_executor()`:新建 executor、旧 executor `shutdown(wait=False)` - - 泄漏 1 个挂死线程远好于全队列堵死;生产环境确认 celery worker 必配(进程隔离天然免疫) - -- [x] **④ shape_loader 重建几何(修 F1)** - - 新建 `services/shape_loader.py`:task_id -> PG 查 object_key -> RustFS 下载 STP -> 临时文件 -> occ executor 内 `stp_parser.load_step_file` - - `/detect-undercuts` 用真实 shape 调 `analyze_and_design`,补 `_ensure_task_access` - - `/cost-estimate` 的任务数据源从 Redis 直读迁移到 `TaskQueryService.get_task_view`(完成态走 PG+RustFS 组装,语义正确) - -- [x] **⑤ Redis 哈希原子更新 + 配置收敛 + 完成态瘦身(修 P5/D4 部分)** - - `redis_task_manager` 改为 Hash 存储:`HSET task:{id} field value` 字段级原子更新,无读改写竞态,进度 tick 不再全量重写 blob - - 兼容读旧 string 格式(过渡期);`redis_client` 属性保留供 batch_router 使用 - - 连接参数统一读 `settings.*`,删除硬编码 `szcjw` - - 完成态任务 Redis 只存摘要字段(去掉 geometry_data/analysis_result 大对象,完成态视图本就由 PG+RustFS 组装) - -### P1:性能与资源 - -- [x] **⑤ 任务视图 TTL 缓存(修 P1/P7 部分)** - - `TaskQueryService.get_task_view` 对 PG 路径(completed/failed)加进程内 TTL 缓存(60s) - - export-mold / cam 写参数后显式失效;删除重复的 HTMLFile 单独查询 - -- [x] **⑥ export_shapes_cache 改 LRU(修 P2)** - - OrderedDict LRU,`maxsize=32`,命中 `move_to_end`,满则逐出最旧(连原生 OCC shape 一起释放) - -- [x] **⑦ 重启后 STEP->STL 现场转换(修 P6/F1 根因延伸)** - - 分析期已持久化各方案 cavity/core/分型面 STEP;重启后 cache miss 时下载已持久化的 STEP -> OCC 读取 -> 三角化 -> 写 STL - - `export-mold` 的 409 分支前新增此兜底,用户不再需要重新分析 - -- [x] **⑧ 收尾(修 P3/P4/P7)** - - `save_html_file` 停止向 PG 写 `html_content`(RustFS 为准,PG 只存 key 与文件名) - - `get_all_file_groups` 的 N+1 count 改为单条 `GROUP BY` 聚合 - - `llm_service._chat` 加一次瞬态错误重试(保持 per-call client:celery 每任务新循环,模块级 AsyncClient 会跨循环失效,与 redis 同理) - -### P2:架构清理 - -- [x] **⑨ 删死代码(修 D1/D2)** - - 删除:`services/storage_integration.py`、`storage/object_storage.py`、`services/storage_service.py`、`src/main.py`、根 `Dockerfile` - - 删前 `grep -r` 确认零引用(动态引用也排查) - -- [x] **⑪ 配置收敛(修 D4 后半)** - - `settings` 改惰性校验:DB 配置缺失不在 import 时 raise,改为首次访问 `DATABASE_URL` 时报清晰错误 - - 解锁 `import shared.*` 无 env 场景(测试环境) - -- [x] **⑫ 测试建设(修 D6,本阶段做低风险部分)** - - `temp_test_injection_p0.py` -> `test_injection_p0.py`,改包路径导入 - - 补纯逻辑单测:PartingSchemeScorer / PartingCandidateGenerator / MaterialService / cost_estimate_service / `_determine_mold_structure` / redis_task_manager 序列化 - -- [ ] **⑩ Generator 公共接口提取(修 D3)** —— 13 个 `_` 方法提为公共 API,需排期单独做(纯机械重命名,但触及 core 三个文件,建议独立 PR + 集成测试保护) -- [ ] **⑬ 顺手项(修 D7 等)** —— advanced_router 拆分 + Pydantic 模型;铝价响应加 `"source": "simulated"` 并前端标注 - ---- - -## 三、验证方式 - -1. `python -m pytest tests/ -x`(inventory 既有测试不回归 + 新增单测通过) -2. `python -c "import ..."` 冒烟:dispatcher / shape_loader / redis_task_manager / task_query_service 可导入 -3. 部署面:`docker-compose.yml` 仅引用 `deploy/Dockerfile.*`,根 Dockerfile 删除后无引用(grep 验证) - -## 四、风险与回滚 - -- Redis Hash 改造保留旧 string 读取兼容:升级期间在途任务可读;新写入一律 Hash。回滚版本读到 Hash 会 `get_task` 返回 None -> 走 PG 组装路径(TaskQueryService 兜底),不会 500 -- `_ensure_task_access` 收紧 owner=None 后,如确有管理员查看无主历史数据的需求,后续走 admin 角色专用端点,而非放开普通用户 -- `html_content` 停写后,历史行中的旧数据仍可读(列保留),仅新行不再写入 diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..558fbd5 --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,142 @@ +# geMoldInsight 演进路线图(ROADMAP) + +> 文档定位:**未来演进路线与阶段计划的权威文档**。 +> 本文回答“下一步准备往哪里演进、按什么阶段推进”;不负责维护当前实现状态,当前状态见 [STATUS.md](STATUS.md)。架构边界见 [ARCHITECTURE.md](ARCHITECTURE.md),当前活跃技术债见 [TECH_DEBT.md](TECH_DEBT.md)。 +> 本文基于历史归档 [archive/EVOLUTION_ROADMAP.md](archive/EVOLUTION_ROADMAP.md) 收敛整理而来。 + +--- + +## 1. 演进背景 + +geMoldInsight 已从历史单体逐步演进为“双业务模块 + 共享平台层 + 独立前端”的结构,但要让后续迭代成本继续下降,仍需要在以下方向持续推进: + +- 继续收敛模块边界 +- 继续减少 shared 的历史耦合 +- 让部署、文档、契约与代码结构保持一致 +- 让 moldinsight 与 inventory 的协作关系更稳定、可维护 + +当前事实与最近完成项见 [STATUS.md](STATUS.md)。 + +--- + +## 2. 当前演进主线 + +### 2.1 主线一:模块化架构收口 + +目标: +- 继续巩固 `moldinsight / inventory / frontend / shared` 的边界 +- 减少历史单体遗留语义 +- 让 README、架构文档、部署文档与代码结构一致 + +重点方向: +- 继续收敛 `shared` 的职责 +- 逐步明确 identity / platform 的边界语义 +- 收敛历史文档与旧部署叙事 + +### 2.2 主线二:moldinsight 工程化增强 + +目标: +- 让 STEP/STP 分析链路更稳定 +- 让导出、批量分析、成本估算、任务状态等链路更可靠 +- 继续提高 OCC 相关处理的可维护性与可测试性 + +重点方向: +- `advanced_router` 拆分与请求模型规范化 +- 模具分析链路的结构继续收口 +- OCC 依赖场景下的契约测试/集成测试继续补齐 + +### 2.3 主线三:inventory 业务层继续沉淀 + +目标: +- 让 inventory 从“可用”继续走向“可扩展” +- 继续将路由中的业务逻辑下沉为 service 层 +- 保持与 moldinsight 的桥接模型清晰 + +重点方向: +- 业务 service 复用强化 +- 数据模型归属进一步清晰化 +- 前后端契约持续减少手写漂移 + +### 2.4 主线四:部署与运维一致性 + +目标: +- 让推荐部署模式、Compose 入口、运维文档、Nginx/端口说明不再冲突 +- 让前端、后端、异步任务链路在部署说明上形成单一叙事 + +重点方向: +- 继续收口部署文档 +- 把历史部署迁移方案移入归档 +- 保持同域前端 + unified backend 的默认认知清晰 + +--- + +## 3. 下一阶段优先项 + +### P0:文档与边界对齐 + +- 建立 `STATUS / ARCHITECTURE / ROADMAP / TECH_DEBT / DEPLOYMENT` 主骨架 +- 将 README 收敛为唯一导航入口 +- 收口部署重复文档并建立 archive + +### P1:moldinsight API 结构整理 + +- 拆分 `advanced_router` +- 为高频接口引入 Pydantic 请求模型 +- 继续减少 `request.json()` 风格手动解析 + +### P2:shared/platform 边界继续收敛 + +- 梳理共享 ORM 与业务模型的归属 +- 继续减少 shared 直接承担业务组合逻辑 +- 为后续平台层命名与目录调整准备条件 + +### P3:专项能力继续规范化 + +- 铝价模拟数据增加显式 `source: "simulated"` +- 补专题文档的定位/边界说明 +- 清理历史 checklist / tasks / report 文档的展示层级 + +--- + +## 4. 中长期方向 + +### 4.1 平台层语义收敛 + +长期仍建议将 `shared` 逐步收敛为更清晰的平台层语义,但这应建立在: +- 当前模块边界稳定 +- 共享职责分层足够清晰 +- 文档与部署已经同步收口 + +### 4.2 文档体系持续治理 + +后续文档治理原则: +- README 只做入口 +- 当前状态只在 [STATUS.md](STATUS.md) +- 历史材料统一入 `docs/archive/` +- 每个主题只有一篇默认权威文档 + +### 4.3 测试能力继续增强 + +重点继续放在: +- OCC 相关集成验证 +- 跨模块关键链路回归测试 +- 关键契约的自动化保护 + +--- + +### 4.4 专题文档持续分级 + +后续还会继续把专题文档区分为三类: +- 当前仍有参考价值的专题文档(保留并补定位) +- 纯阶段性任务/检查单/迁移计划(迁入 archive) +- 可被主骨架吸收的重复说明(逐步收口) + +--- + +## 5. 与相关文档的边界 + +- 当前项目处于什么状态:看 [STATUS.md](STATUS.md) +- 当前架构与边界是什么:看 [ARCHITECTURE.md](ARCHITECTURE.md) +- 当前有哪些技术债:看 [TECH_DEBT.md](TECH_DEBT.md) +- 当前部署方式怎么做:看 [DEPLOYMENT.md](DEPLOYMENT.md) +- 更完整的模块化蓝图讨论:看 [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](archive/BACKEND_MODULARIZATION_BLUEPRINT.md) diff --git a/docs/STATUS.md b/docs/STATUS.md new file mode 100644 index 0000000..821dbc5 --- /dev/null +++ b/docs/STATUS.md @@ -0,0 +1,149 @@ +# geMoldInsight 项目状态(STATUS) + +> 文档定位:**唯一的“当前实现状态 / 当前推荐方案”文档**。 +> README 只做导航,不重复维护状态;架构细节见 [ARCHITECTURE.md](ARCHITECTURE.md),演进路线见 [ROADMAP.md](ROADMAP.md),技术债见 [TECH_DEBT.md](TECH_DEBT.md),部署入口见 [DEPLOYMENT.md](DEPLOYMENT.md)。 +> 最后更新:2026-09-01。 + +--- + +## 1. 当前项目状态总览 + +geMoldInsight 当前已从早期单体演进为: + +- `moldinsight`:模具分析、STEP/STP 处理、批量分析、导出、成本估算 +- `inventory`:成品/物料/BOM/库存/采购/销售/财务 +- `frontend`:Vue 3 独立前端工程 +- `shared`:配置、数据库、认证、日志、应用工厂等共享平台层 + +当前架构形态可概括为: + +> **单仓库 + 单数据库 + 多模块 + 可独立部署** + +详细结构与边界见 [ARCHITECTURE.md](ARCHITECTURE.md)。 + +--- + +## 2. 当前推荐方案 + +### 2.1 推荐部署模式 + +当前推荐部署模式为: + +- **unified**:frontend + unified backend + moldinsight celery + +适用场景: +- 本地开发 +- 集成环境 +- 小团队统一部署 +- 前端同域反代到单一 backend + +详细部署说明见 [DEPLOYMENT.md](DEPLOYMENT.md) 与 [deployment/LINUX_SETUP.md](deployment/LINUX_SETUP.md)。 + +### 2.2 当前代码入口 + +当前后端已存在独立部署入口: +- [src/entrypoints/moldinsight.py](../src/entrypoints/moldinsight.py) +- [src/entrypoints/inventory.py](../src/entrypoints/inventory.py) + +当前 Compose 入口: +- [docker-compose.yml](../docker-compose.yml) + +--- + +## 3. 当前模块化进展 + +### 3.1 已经成型的部分 + +- `src/moldinsight/` 与 `src/inventory/` 已具备相对清晰的业务目录边界 +- 前端已独立为 `frontend/` 工程,不再是后端静态目录的附属 +- 部署入口已按模块拆分到 `src/entrypoints/` +- 基础认证、配置、数据库、日志等能力已集中到 `shared` + +### 3.2 当前主要耦合点 + +当前最大的剩余耦合点主要是: + +- `shared` 仍承担较多平台与组合职责 +- 共享 ORM 模型仍集中在 `shared.models.database` +- 部分历史文档与当前模块化事实尚未完全收口 + +这些内容的结构化说明见 [ARCHITECTURE.md](ARCHITECTURE.md)。 + +--- + +## 4. 最近已完成的重要整理 + +### 4.1 moldinsight 技术债治理(本轮已完成) + +已完成的重点治理包括: + +- 安全收口:debug/history 权限补齐、任务访问控制收紧 +- 静默失败修复:`detect-undercuts` 基于真实 shape 重建分析 +- OCC 超时后 executor 重建,避免单个任务毒化全队列 +- 后台任务统一分派,避免 fire-and-forget 丢失 +- Redis 任务状态改为 Hash 原子更新,并兼容旧 string 格式 +- 完成态任务视图增加缓存,减少 RustFS 高频回读 +- 导出缓存与持久化链路收口,支持重启后再导出 +- 删除旧入口与死代码,修正部署陷阱 +- Generator 公共接口提取完成,并补充契约测试 + +详细治理记录见 [TECH_DEBT.md](TECH_DEBT.md)。 + +### 4.2 测试状态 + +当前已验证: + +- 本地 pip 环境:**47 passed, 1 skipped** +- gemold conda + OCC 环境:**88 passed** + +说明: +- 无 OCC 环境下,依赖 pythonocc 的契约测试会自动 skip +- inventory 侧仍有少量既有 deprecation warnings,但不影响本轮通过状态 + +--- + +## 5. 当前仍在推进 / 尚未完成的重点 + +### 5.1 文档体系整理 + +本轮正在进行: +- 将 README 收敛为唯一文档导航入口 +- 建立 `STATUS / ARCHITECTURE / ROADMAP / TECH_DEBT / DEPLOYMENT` 主骨架 +- 收口部署文档与历史文档 + +### 5.2 仍未完成的功能/结构项 + +当前仍明确未完成或待下一步推进的重点: + +- `advanced_router` 拆分 + Pydantic 请求模型 +- 铝价模拟数据增加 `source: "simulated"` 标注,并同步前端展示 +- 进一步收敛 shared/platform 边界 +- 继续清理当前文档中“现状 / 规划 / 历史”混放问题 + +更长周期的演进方向见 [ROADMAP.md](ROADMAP.md)。 + +--- + +## 6. 报告、模板与归档文档说明 + +以下文档仍可能被保留用于专题说明、验收、模板复用或历史追溯,但不再承担当前状态入口职责: + +- 业务/专题报告: + - [archive/MOLD_ERP_ANALYSIS_REPORT.md](archive/MOLD_ERP_ANALYSIS_REPORT.md) + - [archive/ZERO_FINISHED_INVENTORY_CERTIFICATE.md](archive/ZERO_FINISHED_INVENTORY_CERTIFICATE.md) +- 验收/模板文档: + - [templates/UAT_CHECKLIST.md](templates/UAT_CHECKLIST.md) + - [templates/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md](templates/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md) +- 历史材料归档: + - [archive/README.md](archive/README.md) + +--- + +## 7. 文档维护规则 + +- 当前实现状态只在本文维护 +- README 只做导航与最短入门,不重复状态细节 +- 架构边界改动更新 [ARCHITECTURE.md](ARCHITECTURE.md) +- 规划变更更新 [ROADMAP.md](ROADMAP.md) +- 技术债状态变更更新 [TECH_DEBT.md](TECH_DEBT.md) +- 部署方式变化更新 [DEPLOYMENT.md](DEPLOYMENT.md) 与 [deployment/LINUX_SETUP.md](deployment/LINUX_SETUP.md) diff --git a/docs/TASKS_ALUMINUM_FOAM_MOLD.md b/docs/TASKS_ALUMINUM_FOAM_MOLD.md deleted file mode 100644 index 49ef73c..0000000 --- a/docs/TASKS_ALUMINUM_FOAM_MOLD.md +++ /dev/null @@ -1,827 +0,0 @@ -# 铝制家电包装泡沫模具分模功能开发任务清单 - -## 文档信息 - -| 项目 | 内容 | -|------|------| -| **文档名称** | 铝制家电包装泡沫模具分模功能开发任务清单 | -| **版本** | 1.0 | -| **日期** | 2026-03-13 | -| **项目** | geMoldInsight 模具分模功能增强 | - ---- - -## 任务总览 - -| 阶段 | 任务数 | 预计工期 | -|------|--------|----------| -| 第一阶段:基础框架 | 8 | 2 周 | -| 第二阶段:分模算法 | 10 | 2 周 | -| 第三阶段:质量检测 | 6 | 2 周 | -| 第四阶段:可视化和交互 | 8 | 2 周 | -| 第五阶段:数据接口和测试 | 6 | 1 周 | -| **总计** | **38** | **9 周** | - ---- - -## 第一阶段:基础框架搭建 (1-2 周) - -### 任务 1.1:创建铝泡沫模具参数类 - -**任务描述**:创建专门针对铝泡沫材料的参数配置类 - -**详细说明**: -- 在 `src/core/mold_generator.py` 中添加 `AluminumFoamMoldParams` 类 -- 定义铝泡沫专用参数(发泡倍率、目标密度、成型温度等) -- 实现参数验证和默认值设置 - -**验收标准**: -- 参数类包含所有铝泡沫专用参数 -- 参数验证通过 - -**预计工时**:4 小时 - -**依赖任务**:无 - ---- - -### 任务 1.2:创建铝泡沫材料数据库 - -**任务描述**:建立铝泡沫材料数据库,包含常用材料参数 - -**详细说明**: -- 创建材料数据库类 `FoamMaterialDatabase` -- 添加 AlSi10Mg、AlSi12、纯铝泡沫等常用材料 -- 支持材料查询和参数获取 - -**验收标准**: -- 数据库包含至少 5 种铝泡沫材料 -- 支持按名称查询材料参数 - -**预计工时**:4 小时 - -**依赖任务**:1.1 - ---- - -### 任务 1.3:扩展现有模具生成器 - -**任务描述**:扩展 `MoldCavityGenerator` 类支持铝泡沫参数 - -**详细说明**: -- 添加铝泡沫参数到构造函数 -- 添加材料设置方法 `set_foam_material()` -- 适配现有的分模流程 - -**验收标准**: -- 可以使用铝泡沫参数创建生成器 -- 参数正确传递给分模流程 - -**预计工时**:4 小时 - -**依赖任务**:1.1, 1.2 - ---- - -### 任务 1.4:创建参数配置 API 接口 - -**任务描述**:添加前端参数配置 API - -**详细说明**: -- 在 `src/api/routes.py` 中添加参数相关路由 -- 实现参数获取、设置、验证接口 -- 支持参数模板保存和加载 - -**验收标准**: -- API 可以获取和设置分模参数 -- 参数验证正确返回错误信息 - -**预计工时**:4 小时 - -**依赖任务**:1.3 - ---- - -### 任务 1.5:前端参数面板开发 - -**任务描述**:在 Web 界面中添加分模参数配置面板 - -**详细说明**: -- 在 `static/vue-app.js` 中添加参数配置组件 -- 实现滑块、输入框、选择框等控件 -- 支持参数实时预览 - -**验收标准**: -- 界面显示所有可配置参数 -- 参数修改正确提交到后端 - -**预计工时**:8 小时 - -**依赖任务**:1.4 - ---- - -### 任务 1.6:参数模板功能 - -**任务描述**:实现参数模板保存和加载功能 - -**详细说明**: -- 创建预设参数模板(快速、经济、高精度等) -- 支持用户保存自定义模板 -- 模板存储到数据库 - -**验收标准**: -- 至少 3 个预设模板可用 -- 用户可以保存和加载模板 - -**预计工时**:4 小时 - -**依赖任务**:1.4, 1.5 - ---- - -### 任务 1.7:参数验证逻辑 - -**任务描述**:实现参数合法性验证 - -**详细说明**: -- 验证数值范围(角度、容差等) -- 验证参数组合合法性 -- 返回详细的验证错误信息 - -**验收标准**: -- 所有参数都有验证逻辑 -- 错误信息清晰明了 - -**预计工时**:4 小时 - -**依赖任务**:1.1 - ---- - -### 任务 1.8:阶段一集成测试 - -**任务描述**:测试参数系统的完整性 - -**详细说明**: -- 测试参数设置和获取 -- 测试参数验证 -- 测试前端交互 - -**验收标准**: -- 所有功能正常运行 -- 无明显 bug - -**预计工时**:4 小时 - -**依赖任务**:1.1-1.7 - ---- - -## 第二阶段:分模算法优化 (3-4 周) - -### 任务 2.1:改进法向量分析算法 - -**任务描述**:改进分型面检测的法向量分析算法 - -**详细说明**: -- 添加高斯权重计算 -- 支持多点采样 -- 识别主分型方向 - -**验收标准**: -- 算法能正确处理复杂几何产品 -- 分型方向准确率 > 90% - -**预计工时**:8 小时 - -**依赖任务**:无 - ---- - -### 任务 2.2:实现多分型面检测 - -**任务描述**:支持复杂产品的多个分型面 - -**详细说明**: -- 识别需要多次分模的区域 -- 正确处理分型面优先级 -- 生成有序的分型面列表 - -**验收标准**: -- 能正确检测 2 个以上分型面 -- 分型面顺序正确 - -**预计工时**:12 小时 - -**依赖任务**:2.1 - ---- - -### 任务 2.3:倒扣区域检测 - -**任务描述**:自动识别产品倒扣区域 - -**详细说明**: -- 分析产品几何特征 -- 标记倒扣区域位置 -- 提供处理建议 - -**验收标准**: -- 能识别常见的倒扣类型 -- 提供准确的倒扣位置 - -**预计工时**:8 小时 - -**依赖任务**:2.1 - ---- - -### 任务 2.4:改进拔模角计算 - -**任务描述**:实现完整的拔模角计算和应用 - -**详细说明**: -- 使用 OpenCASCADE 拔模功能 -- 支持不同拔模方向 -- 处理拔模干涉 - -**验收标准**: -- 拔模角正确应用到模型 -- 无明显变形或错误 - -**预计工时**:12 小时 - -**依赖任务**:无 - ---- - -### 任务 2.5:铝泡沫收缩补偿 - -**任务描述**:针对铝泡沫实现特殊的收缩补偿 - -**详细说明**: -- 基于发泡倍率计算收缩 -- 多向收缩补偿 -- 补偿后尺寸验证 - -**验收标准**: -- 收缩补偿量准确 -- 补偿后模型无异常 - -**预计工时**:8 小时 - -**依赖任务**:1.2 - ---- - -### 任务 2.6:型腔分离优化 - -**任务描述**:改进型腔和型芯的分离算法 - -**详细说明**: -- 精确的布尔运算 -- 处理复杂几何 -- 分离结果验证 - -**验收标准**: -- 型腔/型芯分离正确 -- 分离过程无错误 - -**预计工时**:8 小时 - -**依赖任务**:无 - ---- - -### 任务 2.7:模具块生成 - -**任务描述**:生成完整的模具块结构 - -**详细说明**: -- 计算模具尺寸 -- 添加余量 -- 生成 A/B 板结构 - -**验收标准**: -- 模具块尺寸合理 -- 包含必要的结构元素 - -**预计工时**:8 小时 - -**依赖任务**:2.6 - ---- - -### 任务 2.8:分型线平滑处理 - -**任务描述**:对分型线进行平滑处理 - -**详细说明**: -- B 样条曲线拟合 -- 尖角处理 -- 平滑度验证 - -**验收标准**: -- 分型线平滑无毛刺 -- 保持原始几何精度 - -**预计工时**:6 小时 - -**依赖任务**:2.2 - ---- - -### 任务 2.9:算法性能优化 - -**任务描述**:优化分模算法性能 - -**详细说明**: -- 并行计算支持 -- 缓存优化 -- 增量计算 - -**验收标准**: -- 分模时间 < 30 秒 -- 内存占用 < 1GB - -**预计工时**:8 小时 - -**依赖任务**:2.1-2.8 - ---- - -### 任务 2.10:阶段二集成测试 - -**任务描述**:测试分模算法的完整流程 - -**详细说明**: -- 使用测试产品验证 -- 对比不同参数结果 -- 性能测试 - -**验收标准**: -- 算法稳定运行 -- 结果准确合理 - -**预计工时**:8 小时 - -**依赖任务**:2.1-2.9 - ---- - -## 第三阶段:质量检测模块 (5-6 周) - -### 任务 3.1:创建质量检测器类 - -**任务描述**:创建 `MoldQualityInspector` 质量检测类 - -**详细说明**: -- 设计检测器架构 -- 定义检测接口 -- 实现结果数据结构 - -**验收标准**: -- 类结构完整 -- 接口定义清晰 - -**预计工时**:4 小时 - -**依赖任务**:无 - ---- - -### 任务 3.2:分模面平滑度检测 - -**任务描述**:检测分模面的平滑度 - -**详细说明**: -- 曲率分析 -- 凹凸检测 -- 评分计算 - -**验收标准**: -- 正确识别不平滑区域 -- 给出评分 (0-100) - -**预计工时**:8 小时 - -**依赖任务**:3.1 - ---- - -### 任务 3.3:分模面连续性检测 - -**任务描述**:检测分模面的连续性 - -**详细说明**: -- 边界检查 -- 间隙检测 -- 完整性验证 - -**验收标准**: -- 能识别间隙和断点 -- 报告位置和大小 - -**预计工时**:6 小时 - -**依赖任务**:3.1 - ---- - -### 任务 3.4:模具结构合理性检测 - -**任务描述**:检测模具结构的合理性 - -**详细说明**: -- 模具尺寸检查 -- 壁厚检查 -- 干涉检查 - -**验收标准**: -- 识别所有结构问题 -- 提供修改建议 - -**预计工时**:8 小时 - -**依赖任务**:3.1 - ---- - -### 任务 3.5:生产可行性评估 - -**任务描述**:评估模具的生产可行性 - -**详细说明**: -- 注塑压力计算 -- 锁模力计算 -- 成型周期估算 - -**验收标准**: -- 估算值在合理范围 -- 提供改进建议 - -**预计工时**:8 小时 - -**依赖任务**:3.1 - ---- - -### 任务 3.6:质量报告生成 - -**任务描述**:生成完整的质量检测报告 - -**详细说明**: -- 汇总各项检测结果 -- 生成 PDF 格式报告 -- 支持导出 - -**验收标准**: -- 报告内容完整 -- 格式规范 - -**预计工时**:6 小时 - -**依赖任务**:3.2-3.5 - ---- - -## 第四阶段:可视化和交互 (5-6 周) - -### 任务 4.1:分型面可视化增强 - -**任务描述**:改进分型面的可视化效果 - -**详细说明**: -- 分型面颜色和透明度设置 -- 边缘高亮 -- 动态效果 - -**验收标准**: -- 分型面清晰可见 -- 与产品形成对比 - -**预计工时**:4 小时 - -**依赖任务**:无 - ---- - -### 任务 4.2:分型线可视化增强 - -**任务描述**:改进分型线的可视化 - -**详细说明**: -- 线条颜色和粗细 -- 端点标记 -- 动态绘制效果 - -**验收标准**: -- 分型线清晰可见 -- 便于观察细节 - -**预计工时**:4 小时 - -**依赖任务**:无 - ---- - -### 任务 4.3:交互式分型面调整 - -**任务描述**:支持用户拖拽调整分型面 - -**详细说明**: -- 鼠标拖拽事件 -- 实时更新模型 -- 撤销/重做支持 - -**验收标准**: -- 拖拽响应流畅 -- 模型正确更新 - -**预计工时**:12 小时 - -**依赖任务**:4.1 - ---- - -### 任务 4.4:交互式参数调整 - -**任务描述**:支持实时调整参数并预览效果 - -**详细说明**: -- 滑块实时更新 -- 参数变化动画 -- 效果对比 - -**验收标准**: -- 调整流畅无延迟 -- 效果正确显示 - -**预计工时**:8 小时 - -**依赖任务**:1.5 - ---- - -### 任务 4.5:剖视图功能 - -**任务描述**:添加剖视图功能 - -**详细说明**: -- 沿分型面剖切 -- 内部结构显示 -- 剖面编辑 - -**验收标准**: -- 剖视图正确显示 -- 切换流畅 - -**预计工时**:8 小时 - -**依赖任务**:4.1 - ---- - -### 任务 4.6:测量工具 - -**任务描述**:添加测量工具 - -**详细说明**: -- 距离测量 -- 角度测量 -- 测量结果标注 - -**验收标准**: -- 测量结果准确 -- 操作便捷 - -**预计工时**:8 小时 - -**依赖任务**:无 - ---- - -### 任务 4.7:视角控制增强 - -**任务描述**:改进视角控制 - -**详细说明**: -- 预设视角 -- 动画过渡 -- 自动对准 - -**验收标准**: -- 视角切换流畅 -- 自动对准准确 - -**预计工时**:4 小时 - -**依赖任务**:无 - ---- - -### 任务 4.8:导出视图功能 - -**任务描述**:支持导出当前视图 - -**详细说明**: -- PNG 图片导出 -- 高清截图 -- 报告插图 - -**验收标准**: -- 导出图片清晰 -- 格式正确 - -**预计工时**:4 小时 - -**依赖任务**:4.1-4.7 - ---- - -## 第五阶段:数据接口和测试 (7-8 周) - -### 任务 5.1:STEP 导出接口 - -**任务描述**:实现 STEP 格式导出 - -**详细说明**: -- 使用 PythonOCC 导出 STEP -- 包含分模后模型 -- 验证导出正确性 - -**验收标准**: -- 导出文件可被 CAD 打开 -- 几何正确 - -**预计工时**:8 小时 - -**依赖任务**:无 - ---- - -### 任务 5.2:JSON 数据导出 - -**任务描述**:实现 JSON 格式导出 - -**详细说明**: -- 导出分模参数 -- 导出几何数据 -- 导出质量报告 - -**验收标准**: -- JSON 格式正确 -- 数据完整 - -**预计工时**:4 小时 - -**依赖任务**:无 - ---- - -### 任务 5.3:PDF 报告导出 - -**任务描述**:实现 PDF 格式报告导出 - -**详细说明**: -- 质量检测报告 -- 包含图表和说明 -- 模板支持 - -**验收标准**: -- PDF 生成成功 -- 内容完整 - -**预计工时**:8 小时 - -**依赖任务**:3.6 - ---- - -### 任务 5.4:IGES 格式支持 - -**任务描述**:添加 IGES 格式支持 - -**详细说明**: -- IGES 导入 -- IGES 导出 -- 格式验证 - -**验收标准**: -- 导出文件可被 CAM 软件使用 - -**预计工时**:6 小时 - -**依赖任务**:5.1 - ---- - -### 任务 5.5:集成测试 - -**任务描述**:完整的系统集成测试 - -**详细说明**: -- 功能测试 -- 性能测试 -- 兼容性测试 - -**验收标准**: -- 所有功能正常运行 -- 达到性能指标 - -**预计工时**:8 小时 - -**依赖任务**:全部 - ---- - -### 任务 5.6:用户验收测试 - -**任务描述**:配合用户进行验收测试 - -**详细说明**: -- 演示功能 -- 收集反馈 -- 修复问题 - -**验收标准**: -- 用户满意 -- 达到预期目标 - -**预计工时**:8 小时 - -**依赖任务**:5.5 - ---- - -## 任务依赖关系图 - -``` -第一阶段: 基础框架 -├── 1.1 创建参数类 -├── 1.2 材料数据库 ──┐ -├── 1.3 扩展生成器 ──┼── 1.4 API ──┬── 1.5 前端 ──┬── 1.6 模板 ──┬── 1.7 验证 ──→ 1.8 测试 -│ │ │ │ │ -└────────────────────┴──────────────┴──────────────┴──────────────┘ - -第二阶段: 分模算法 -│ -├── 2.1 法向量分析 ──→ 2.2 多分型面 ──→ 2.3 倒扣检测 -│ -├── 2.4 拔模角 ──────────────────────────────────────────────────────────┐ -│ │ -├── 2.5 收缩补偿 ◄──────────────────┐ │ -│ │ │ -├── 2.6 型腔分离 ──→ 2.7 模具块 ──→ 2.8 平滑处理 ──→ 2.9 优化 ──→ 2.10 测试 -│ │ -└────────────────────────────────────┴────────────────────────────────────┘ - -第三阶段: 质量检测 -│ -├── 3.1 检测器类 ──→ 3.2 平滑度 ──→ 3.3 连续性 ──→ 3.4 结构 ──→ 3.5 可行性 ──→ 3.6 报告 -│ -└────────────────────────────────────┬────────────────────────────────────┘ - -第四阶段: 可视化 -│ -├── 4.1 分型面 ──→ 4.2 分型线 ──→ 4.3 拖拽 ──→ 4.4 参数调整 ──→ 4.5 剖视 -│ │ │ -├── 4.6 测量 ──→ 4.7 视角 ──→ 4.8 导出 ◄─────────────┘ -│ -└────────────────────────────────────┬────────────────────────────────────┘ - -第五阶段: 接口和测试 -│ -├── 5.1 STEP ──→ 5.2 JSON ◄──┐ -│ │ -├── 5.3 PDF ◄─────────────────┼── 5.4 IGES ──→ 5.5 集成 ──→ 5.6 验收 -│ │ -└──────────────────────────────┘ -``` - ---- - -## 资源分配 - -| 角色 | 任务 | 预计工时 | -|------|------|----------| -| 后端开发 | 1.1-1.4, 2.1-2.10, 3.1-3.6, 5.1-5.4 | 180 小时 | -| 前端开发 | 1.5-1.6, 4.1-4.8 | 60 小时 | -| 测试 | 1.8, 2.10, 5.5-5.6 | 32 小时 | -| **总计** | | **272 小时** | - ---- - -## 风险评估 - -| 风险 | 影响 | 应对措施 | -|------|------|----------| -| 算法复杂度高 | 时间延误 | 预留缓冲时间,分阶段交付 | -| OpenCASCADE 兼容问题 | 功能受限 | 多种实现方案,准备备选 | -| 性能不达标 | 用户体验差 | 持续优化,必要时降级功能 | -| 需求变更 | 计划调整 | 敏捷开发,快速迭代 | - ---- - -**文档结束** diff --git a/docs/TECH_DEBT.md b/docs/TECH_DEBT.md new file mode 100644 index 0000000..1d99c45 --- /dev/null +++ b/docs/TECH_DEBT.md @@ -0,0 +1,158 @@ +# geMoldInsight 技术债与治理计划(TECH_DEBT) + +> 文档定位:**当前活跃技术债与治理计划的权威文档**。 +> 本文回答“现在还有哪些重要债务、优先级如何、下一步怎么处理”;不负责维护当前实现状态,当前状态见 [STATUS.md](STATUS.md)。架构边界见 [ARCHITECTURE.md](ARCHITECTURE.md),未来路线见 [ROADMAP.md](ROADMAP.md)。 +> 本文由归档文档 [archive/MOLDINSIGHT_TECH_DEBT_PLAN.md](archive/MOLDINSIGHT_TECH_DEBT_PLAN.md) 收敛整理而来,保留活跃债务与治理结论,弱化详细实施流水账。 + +--- + +## 1. 当前技术债概览 + +当前最主要的技术债集中在两个区域: + +- **moldinsight API 与处理链路的结构收口** +- **文档 / 部署 / 历史语义与当前代码现状未完全一致** + +已经完成的高优先级治理不再作为持续待办反复展开,当前重点聚焦在“还没完成、且值得继续推进”的部分。 + +--- + +## 2. 已完成的重要治理(摘要) + +以下高价值治理已完成: + +### 2.1 安全与权限 +- debug/history 路由补鉴权 +- 任务访问控制收紧 +- 无主数据不再默认放行 + +### 2.2 静默失败与可用性 +- `detect-undercuts` 改为基于真实 shape 分析 +- OCC 超时后重建 executor,避免全队列永久堵死 +- 后台任务统一分派,补强引用与并发控制 + +### 2.3 状态存储与缓存 +- Redis 任务状态改为 Hash 字段级更新,兼容旧格式 +- 完成态任务视图增加缓存 +- 导出缓存与持久化链路收口,支持重启后再导出 + +### 2.4 架构与代码清理 +- 删除旧单体入口与死代码 +- 设置惰性配置校验,提升可测试性 +- Generator 公共接口提取完成,补充契约测试 + +详细历史过程保留在原始技术债文档中,后续将转入归档。 + +--- + +## 3. 当前活跃技术债 + +### D1. `advanced_router` 过大,职责混杂 + +现状: +- 导出、估算、设计/分析相关接口仍混在同一个 router 中 +- 请求体仍有较多手动解析逻辑 + +影响: +- 路由边界不清晰 +- OpenAPI 可读性差 +- 接口参数校验不统一 +- 后续继续扩展时维护成本高 + +建议: +- 拆分为 export / design / cost 等子路由 +- 高优先级请求体改为 Pydantic 模型 + +优先级:**P1** + +### D2. 铝价模拟数据未显式标注来源 + +现状: +- 铝价服务返回的是模拟/参考数据,但接口层未明确表达 + +影响: +- 容易误导前端与业务使用者,把模拟数据理解为实时行情 + +建议: +- 响应增加 `source: "simulated"` +- 前端界面同步标注“模拟/参考数据” + +优先级:**P2** + +### D3. shared/platform 边界仍需继续收敛 + +现状: +- `shared` 同时承担平台基础能力与部分历史耦合职责 +- 共享 ORM 与 app factory 仍是主要耦合点 + +影响: +- 模块边界认知成本较高 +- 新增逻辑容易继续堆入 shared + +建议: +- 继续从文档、目录语义、职责边界上推进收敛 +- 在后续实际重构中优先避免把业务逻辑继续沉入 shared + +优先级:**P2** + +### D4. 文档现状 / 规划 / 历史混放 + +现状: +- 文档存在部署说明重叠、计划/总结/权威文档混放 +- README 承担过多职责 + +影响: +- 新成员难以判断“哪篇才是当前有效说法” +- 状态、部署、规划容易发生漂移 + +建议: +- 建立 `STATUS / ARCHITECTURE / ROADMAP / DEPLOYMENT` 主骨架 +- 历史材料迁入 `docs/archive/` + +优先级:**P1** + +--- + +## 4. 当前推荐治理顺序 + +### 第一优先级 +1. `advanced_router` 拆分 +2. 高优先级接口补 Pydantic 请求模型 +3. 文档主骨架收口并减少重复说明 + +### 第二优先级 +4. 铝价模拟数据来源显式化 +5. 部署历史文档归档 +6. shared/platform 语义继续收敛 + +--- + +## 5. 治理原则 + +### 5.1 先收口接口与边界,再做更大结构调整 + +当前最值得继续投入的,不是大规模目录重写,而是: +- 先把接口边界、文档边界、部署边界收清楚 +- 再逐步推进 shared/platform 的后续调整 + +### 5.2 优先做“降低长期维护成本”的改动 + +优先处理: +- 重复逻辑 +- 模糊边界 +- 静态契约缺失 +- 文档漂移风险 + +### 5.3 已解决问题不再长期占据主文档中心 + +已经完成且稳定的问题,只在本文保留摘要结论;详细实施流水账后续归档,不继续作为主文档主体。 + +--- + +## 6. 与相关文档的边界 + +- 当前项目状态:看 [STATUS.md](STATUS.md) +- 当前架构与模块边界:看 [ARCHITECTURE.md](ARCHITECTURE.md) +- 后续演进路线:看 [ROADMAP.md](ROADMAP.md) +- 部署主题入口:看 [DEPLOYMENT.md](DEPLOYMENT.md) +- 原始 moldinsight 细粒度债务记录:看 [archive/MOLDINSIGHT_TECH_DEBT_PLAN.md](archive/MOLDINSIGHT_TECH_DEBT_PLAN.md) diff --git a/docs/archive/BACKEND_MODULARIZATION_BLUEPRINT.md b/docs/archive/BACKEND_MODULARIZATION_BLUEPRINT.md new file mode 100644 index 0000000..f577a66 --- /dev/null +++ b/docs/archive/BACKEND_MODULARIZATION_BLUEPRINT.md @@ -0,0 +1,5 @@ +# geMoldInsight 后端模块化重构蓝图(归档) + +> 文档定位:**模块化设计蓝图档案 / 补充设计材料**。 +> 当前架构与边界的默认入口见 [../ARCHITECTURE.md](../ARCHITECTURE.md),当前状态见 [../STATUS.md](../STATUS.md),未来演进路线见 [../ROADMAP.md](../ROADMAP.md)。 +> 本文保留更完整的模块化设计背景、目标与分阶段思考,用于追溯设计决策,不再保留在 `docs/` 顶层作为默认入口。 diff --git a/docs/archive/CHECKLIST_ALUMINUM_FOAM_MOLD.md b/docs/archive/CHECKLIST_ALUMINUM_FOAM_MOLD.md new file mode 100644 index 0000000..706bcb5 --- /dev/null +++ b/docs/archive/CHECKLIST_ALUMINUM_FOAM_MOLD.md @@ -0,0 +1,7 @@ +# 铝制家电包装泡沫模具分模功能开发检查清单(归档) + +> 文档定位:**阶段性检查清单 / 历史材料**,不再作为当前权威文档。 +> 当前项目状态见 [../STATUS.md](../STATUS.md),当前架构边界见 [../ARCHITECTURE.md](../ARCHITECTURE.md),当前活跃技术债见 [../TECH_DEBT.md](../TECH_DEBT.md)。 +> 若需了解当前模具分析方向,请优先参考主骨架文档,而不是本文的阶段 checklist。 + +本文保留的是 2026-03-13 铝泡沫模具分模功能增强时期的检查清单,用于记录当时的开发跟踪方式。 diff --git a/docs/CONFLUENCE_ARCHIVE_STRUCTURE.md b/docs/archive/CONFLUENCE_ARCHIVE_STRUCTURE.md similarity index 68% rename from docs/CONFLUENCE_ARCHIVE_STRUCTURE.md rename to docs/archive/CONFLUENCE_ARCHIVE_STRUCTURE.md index af09d0f..8ab26c7 100644 --- a/docs/CONFLUENCE_ARCHIVE_STRUCTURE.md +++ b/docs/archive/CONFLUENCE_ARCHIVE_STRUCTURE.md @@ -1,5 +1,8 @@ # Confluence 归档目录结构(建议) +> 文档定位:**外部文档归档结构建议稿**。 +> 本文描述的是面向 Confluence/知识库归档时的目录建议,不作为当前仓库内文档体系的权威说明。当前仓库文档入口见 [../../README.md](../../README.md) 与 [README.md](README.md)。 + ## 业务流程 - 01 端到端流程(客户订单→采购→到货→生产→交付) diff --git a/docs/archive/DELIVERABLES.md b/docs/archive/DELIVERABLES.md new file mode 100644 index 0000000..11c8b0e --- /dev/null +++ b/docs/archive/DELIVERABLES.md @@ -0,0 +1,6 @@ +# 交付物清单(归档) + +> 文档定位:**一次性交付产物索引 / 历史材料**。 +> 本文记录某轮分析/整改时的交付物集合,不作为当前项目状态或当前文档导航入口。当前默认入口见 [../../README.md](../../README.md),当前状态见 [../STATUS.md](../STATUS.md)。 + +保留本文的目的主要是追溯当时的分析交付范围,而不是指导当前项目维护。 diff --git a/docs/archive/EVOLUTION_ROADMAP.md b/docs/archive/EVOLUTION_ROADMAP.md new file mode 100644 index 0000000..6a3077e --- /dev/null +++ b/docs/archive/EVOLUTION_ROADMAP.md @@ -0,0 +1,5 @@ +# geMoldInsight 演进路线图(原始执行记录,归档) + +> 文档定位:**历史路线与执行记录原文 / 归档材料**。 +> 当前默认路线文档见 [../ROADMAP.md](../ROADMAP.md),当前状态见 [../STATUS.md](../STATUS.md),当前技术债见 [../TECH_DEBT.md](../TECH_DEBT.md)。 +> 本文保留较细粒度的历史诊断、执行清单与过程记录,仅用于追溯,不再作为顶层默认文档。 diff --git a/docs/archive/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md b/docs/archive/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md new file mode 100644 index 0000000..7e16133 --- /dev/null +++ b/docs/archive/FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md @@ -0,0 +1,19 @@ +# 前端独立部署 + 统一后端入口实施计划(归档) + +> 文档定位:**阶段性实施计划 / 历史材料**,不再作为当前部署权威文档。 +> 当前部署入口见 [../DEPLOYMENT.md](../DEPLOYMENT.md),Linux 详细部署步骤见 [../deployment/LINUX_SETUP.md](../deployment/LINUX_SETUP.md),当前项目状态见 [../STATUS.md](../STATUS.md)。 + +本文保留的是一次针对“前端独立部署 + unified backend”方向的实施计划,用于记录当时的设计思路与迁移目标。 + +当前项目的默认阅读方式已经调整为: +- 部署主题入口: [../DEPLOYMENT.md](../DEPLOYMENT.md) +- 当前推荐方案与当前事实: [../STATUS.md](../STATUS.md) +- 架构边界: [../ARCHITECTURE.md](../ARCHITECTURE.md) + +如果你正在查找**当前有效的部署方式**,请不要以本文作为默认依据,而应优先参考上述主文档。 + +--- + +# 原始内容 + +> 目标:在已经切换到“前端独立部署 + 同域反代”的基础上,进一步取消前端 Nginx 对 `/api` 的路径级分流,改为反代到一个真正的 **unified backend**,一次性解决长期维护成本。 diff --git a/docs/archive/MOLDINSIGHT_TECH_DEBT_PLAN.md b/docs/archive/MOLDINSIGHT_TECH_DEBT_PLAN.md new file mode 100644 index 0000000..c1d5cc1 --- /dev/null +++ b/docs/archive/MOLDINSIGHT_TECH_DEBT_PLAN.md @@ -0,0 +1,5 @@ +# moldinsight 模块技术债务分析与重构计划(原始记录,归档) + +> 文档定位:**moldinsight 技术债原始分析与实施记录 / 归档材料**。 +> 当前默认技术债文档见 [../TECH_DEBT.md](../TECH_DEBT.md),当前状态见 [../STATUS.md](../STATUS.md)。 +> 本文保留更细粒度的问题清单、实施记录与阶段性说明,仅用于追溯,不再作为顶层默认文档。 diff --git a/docs/MOLD_ERP_ANALYSIS_REPORT.md b/docs/archive/MOLD_ERP_ANALYSIS_REPORT.md similarity index 97% rename from docs/MOLD_ERP_ANALYSIS_REPORT.md rename to docs/archive/MOLD_ERP_ANALYSIS_REPORT.md index b91929e..198055d 100644 --- a/docs/MOLD_ERP_ANALYSIS_REPORT.md +++ b/docs/archive/MOLD_ERP_ANALYSIS_REPORT.md @@ -1,5 +1,8 @@ # 模具制造进销存核心模块分析报告(代码基线:geMoldInsight) +> 文档定位:**业务分析/审计型报告文档**。 +> 本文保留一次特定分析基线下的观察结论与流程梳理,不作为当前项目状态或当前架构的权威说明。当前状态见 [../STATUS.md](../STATUS.md),当前架构见 [../ARCHITECTURE.md](../ARCHITECTURE.md),演进路线见 [../ROADMAP.md](../ROADMAP.md)。 + ## 0. 范围与术语映射 - 客户订单(Customer Order):本仓库实现为 SalesOrder(销售订单),其业务语义更贴近“模具订单/按单生产订单”。对应表:`sales_orders`、`sales_order_items`。 diff --git a/docs/archive/PORT_REFACTOR_SUMMARY.md b/docs/archive/PORT_REFACTOR_SUMMARY.md new file mode 100644 index 0000000..6eb87e8 --- /dev/null +++ b/docs/archive/PORT_REFACTOR_SUMMARY.md @@ -0,0 +1,22 @@ +# 端口配置历史说明(归档) + +> 文档定位:**历史迁移说明 / 不再作为当前部署权威文档**。 +> 当前部署入口见 [../DEPLOYMENT.md](../DEPLOYMENT.md),Linux 详细部署步骤见 [../deployment/LINUX_SETUP.md](../deployment/LINUX_SETUP.md)。 + +本文件保留为历史说明。 + +它所描述的“单体应用单一端口配置”思路,已经不再能完整代表当前 geMoldInsight 的模块化架构。 + +当前项目已演进为: + +- gemold 模块可独立部署 +- inventory 模块可独立部署 +- unified 作为组合模式存在 +- gemold 与 inventory 应分别考虑端口与网关暴露方式 + +因此,端口配置的当前权威说明已转移到以下文档: + +- [../DEPLOYMENT.md](../DEPLOYMENT.md) +- [../deployment/LINUX_SETUP.md](../deployment/LINUX_SETUP.md) +- [../deployment/DEPLOY_PORT.md](../deployment/DEPLOY_PORT.md) +- [../deployment/PORT_CONFIG.md](../deployment/PORT_CONFIG.md) diff --git a/docs/archive/README.md b/docs/archive/README.md new file mode 100644 index 0000000..9150d63 --- /dev/null +++ b/docs/archive/README.md @@ -0,0 +1,21 @@ +# 文档归档说明(archive) + +> 文档定位:**历史文档与阶段性材料归档目录**。 +> 当前权威文档请优先查看: +> - [../STATUS.md](../STATUS.md) +> - [../ARCHITECTURE.md](../ARCHITECTURE.md) +> - [../ROADMAP.md](../ROADMAP.md) +> - [../TECH_DEBT.md](../TECH_DEBT.md) +> - [../DEPLOYMENT.md](../DEPLOYMENT.md) + +本目录用于存放: +- 历史迁移说明 +- 阶段性实施计划 +- 已不再作为默认入口的旧文档 + +当前已归档: +- [PORT_REFACTOR_SUMMARY.md](PORT_REFACTOR_SUMMARY.md) +- [FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md](FRONTEND_UNIFIED_DEPLOYMENT_PLAN.md) +- [TASKS_ALUMINUM_FOAM_MOLD.md](TASKS_ALUMINUM_FOAM_MOLD.md) +- [CHECKLIST_ALUMINUM_FOAM_MOLD.md](CHECKLIST_ALUMINUM_FOAM_MOLD.md) +- [DELIVERABLES.md](DELIVERABLES.md) diff --git a/docs/archive/TASKS_ALUMINUM_FOAM_MOLD.md b/docs/archive/TASKS_ALUMINUM_FOAM_MOLD.md new file mode 100644 index 0000000..a3bd8d6 --- /dev/null +++ b/docs/archive/TASKS_ALUMINUM_FOAM_MOLD.md @@ -0,0 +1,7 @@ +# 铝制家电包装泡沫模具分模功能开发任务清单(归档) + +> 文档定位:**阶段性任务清单 / 历史材料**,不再作为当前权威文档。 +> 当前项目状态见 [../STATUS.md](../STATUS.md),当前架构边界见 [../ARCHITECTURE.md](../ARCHITECTURE.md),当前活跃技术债见 [../TECH_DEBT.md](../TECH_DEBT.md)。 +> 若需了解当前模具分析方向,请优先参考主骨架文档,而不是本文的阶段任务分解。 + +本文保留的是 2026-03-13 铝泡沫模具分模功能增强时期的任务拆解,用于记录当时的实施计划与阶段安排。 diff --git a/docs/ZERO_FINISHED_INVENTORY_CERTIFICATE.md b/docs/archive/ZERO_FINISHED_INVENTORY_CERTIFICATE.md similarity index 84% rename from docs/ZERO_FINISHED_INVENTORY_CERTIFICATE.md rename to docs/archive/ZERO_FINISHED_INVENTORY_CERTIFICATE.md index c261de1..d2fc8a2 100644 --- a/docs/ZERO_FINISHED_INVENTORY_CERTIFICATE.md +++ b/docs/archive/ZERO_FINISHED_INVENTORY_CERTIFICATE.md @@ -1,5 +1,8 @@ # “零成品库存”证明报告(geMoldInsight) +> 文档定位:**特定业务口径下的专题证明/分析报告**。 +> 本文解释“零成品库存”这一业务与财务口径,不作为当前项目整体状态的权威说明。当前状态见 [../STATUS.md](../STATUS.md),相关业务分析见 [MOLD_ERP_ANALYSIS_REPORT.md](MOLD_ERP_ANALYSIS_REPORT.md)。 + ## 1. 结论 系统不设置成品入库、成品出库、销售退货等成品库存模块;系统库存口径仅覆盖“物料(material)”,成品(finished/模具)仅作为订单交付对象,不进入库存核算链路。 diff --git a/docs/deployment/DEPLOY_PORT.md b/docs/deployment/DEPLOY_PORT.md index fe0a223..28e81f2 100644 --- a/docs/deployment/DEPLOY_PORT.md +++ b/docs/deployment/DEPLOY_PORT.md @@ -1,5 +1,7 @@ # 模块化部署端口说明 +> 文档定位:**当前部署下的端口规划补充说明**。 +> 部署入口与当前推荐方案见 [../DEPLOYMENT.md](../DEPLOYMENT.md),Linux 部署步骤见 [LINUX_SETUP.md](LINUX_SETUP.md)。 > 本文档描述的是 **当前模块化部署模式** 下的端口规划,不再以历史单体 `src.main:app` 作为默认前提。 当前推荐部署对象: @@ -128,7 +130,7 @@ VITE_INVENTORY_API_BASE_URL=https://inventory.example.com ``` 当前详细策略见: -- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) +- [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](../archive/BACKEND_MODULARIZATION_BLUEPRINT.md) --- diff --git a/docs/deployment/LINUX_SETUP.md b/docs/deployment/LINUX_SETUP.md index 8eec9d0..73ffe2a 100644 --- a/docs/deployment/LINUX_SETUP.md +++ b/docs/deployment/LINUX_SETUP.md @@ -1,6 +1,8 @@ # geMoldInsight Linux 部署指南 -> 本文档描述的是 **当前模块化架构** 下的 Linux 部署方式,而不是历史单体 `src.main:app` 方案。 +> 文档定位:**Linux 环境下的详细部署操作文档**。 +> 当前部署主题入口见 [../DEPLOYMENT.md](../DEPLOYMENT.md),当前项目状态见 [../STATUS.md](../STATUS.md),当前架构边界见 [../ARCHITECTURE.md](../ARCHITECTURE.md)。 +> 本文档描述的是 **当前模块化架构** 下的 Linux 部署方式,而不是历史单体入口方案。 当前项目支持三种部署模式: @@ -17,7 +19,7 @@ - **复用服务器上已存在的 PostgreSQL / Redis / RustFS(或 MinIO 兼容存储)** 详细架构蓝图见: -- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) +- [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](../archive/BACKEND_MODULARIZATION_BLUEPRINT.md) --- @@ -192,12 +194,12 @@ celery -A src.celery_app.celery_app worker --loglevel=info ## 6.3 unified -当前仓库仍保留历史统一入口 [main.py](../../src/main.py),但它更适合作为**过渡参考**,不建议作为长期标准入口。 +当前仓库历史上存在过统一入口,但它更适合作为**过渡参考**,不建议再作为长期标准入口。 在正式完成组合层重构前,如需统一部署,可优先使用反向代理或部署编排层统一暴露 gemold 与 inventory;后续会演进为显式 `unified_app.py`。 蓝图参考: -- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) +- [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](../archive/BACKEND_MODULARIZATION_BLUEPRINT.md) --- @@ -421,6 +423,6 @@ docker compose --profile full up -d ## 12. 推荐阅读 - [README.md](../../README.md) -- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) +- [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](../archive/BACKEND_MODULARIZATION_BLUEPRINT.md) - [DEPLOY_PORT.md](./DEPLOY_PORT.md) - [PORT_CONFIG.md](./PORT_CONFIG.md) diff --git a/docs/deployment/PORT_CONFIG.md b/docs/deployment/PORT_CONFIG.md index b4cf4ab..462cd08 100644 --- a/docs/deployment/PORT_CONFIG.md +++ b/docs/deployment/PORT_CONFIG.md @@ -1,5 +1,7 @@ # 端口配置说明(模块化架构) +> 文档定位:**模块化部署下的端口与环境变量配置补充说明**。 +> 当前部署主题入口见 [../DEPLOYMENT.md](../DEPLOYMENT.md),详细 Linux 部署步骤见 [LINUX_SETUP.md](LINUX_SETUP.md)。 > 本文档说明当前 geMoldInsight 在**模块化部署**下的端口配置方式。 当前架构中应区分: @@ -174,5 +176,5 @@ Compose 通过端口映射暴露服务: - [LINUX_SETUP.md](./LINUX_SETUP.md) - [DEPLOY_PORT.md](./DEPLOY_PORT.md) -- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) +- [archive/BACKEND_MODULARIZATION_BLUEPRINT.md](../archive/BACKEND_MODULARIZATION_BLUEPRINT.md) - [README.md](../../README.md) diff --git a/docs/deployment/PORT_REFACTOR_SUMMARY.md b/docs/deployment/PORT_REFACTOR_SUMMARY.md deleted file mode 100644 index 9c937d2..0000000 --- a/docs/deployment/PORT_REFACTOR_SUMMARY.md +++ /dev/null @@ -1,39 +0,0 @@ -# 端口配置历史说明(已被模块化部署文档取代) - -本文件保留为历史说明。 - -它所描述的“单体应用单一端口配置”思路,已经不再能完整代表当前 geMoldInsight 的模块化架构。 - -当前项目已演进为: - -- gemold 模块可独立部署 -- inventory 模块可独立部署 -- unified 作为组合模式存在 -- gemold 与 inventory 应分别考虑端口与网关暴露方式 - -因此,端口配置的权威说明已转移到以下文档: - -- [LINUX_SETUP.md](./LINUX_SETUP.md) -- [DEPLOY_PORT.md](./DEPLOY_PORT.md) -- [PORT_CONFIG.md](./PORT_CONFIG.md) -- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) - ---- - -## 当前结论 - -1. 不再默认以历史单体 `src.main:app` 作为部署中心。 -2. 不再假设整个系统只有一个后端端口。 -3. gemold 与 inventory 应按模块分别规划端口。 -4. unified 更适合通过组合层或网关统一暴露,而不是继续沿用旧单体部署语义。 - ---- - -## 建议 - -如果你正在查找当前有效的端口/部署方式,请不要继续参考旧的单体端口说明,而应直接查看: - -- [README.md](../../README.md) -- [LINUX_SETUP.md](./LINUX_SETUP.md) -- [DEPLOY_PORT.md](./DEPLOY_PORT.md) -- [PORT_CONFIG.md](./PORT_CONFIG.md) diff --git a/docs/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md b/docs/templates/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md similarity index 76% rename from docs/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md rename to docs/templates/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md index 5c00659..21253fe 100644 --- a/docs/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md +++ b/docs/templates/INTERFACE_INTEGRATION_CATALOG_TEMPLATE.md @@ -1,5 +1,8 @@ # 外部接口与集成盘点模板(ERP/财务/供应商门户/客户门户) +> 文档定位:**接口梳理与集成盘点模板文档**。 +> 本文是用于外部系统对接时的模板,不作为当前项目状态或当前接口实现清单的权威说明。当前状态见 [../STATUS.md](../STATUS.md),当前架构见 [../ARCHITECTURE.md](../ARCHITECTURE.md)。 + ## 1. 接口清单 | 接口名称 | 调用方向 | 协议 | 鉴权 | 频率 | 单次数据量 | 幂等键 | 超时 | 重试策略 | 死信/补偿 | 负责人 | diff --git a/docs/UAT_CHECKLIST.md b/docs/templates/UAT_CHECKLIST.md similarity index 86% rename from docs/UAT_CHECKLIST.md rename to docs/templates/UAT_CHECKLIST.md index 6819642..f841f70 100644 --- a/docs/UAT_CHECKLIST.md +++ b/docs/templates/UAT_CHECKLIST.md @@ -1,5 +1,8 @@ # UAT 验收清单(模具制造进销存主线) +> 文档定位:**UAT 验收模板 / 验收过程文档**。 +> 本文用于业务验收与签字过程,不作为当前项目状态或当前架构的权威说明。当前状态见 [../STATUS.md](../STATUS.md),当前架构见 [../ARCHITECTURE.md](../ARCHITECTURE.md)。 + ## 1. 业务流程签字 | 模块 | 场景 | 验收点 | 结果 | 业务签字 | 日期 | diff --git a/docs/AI_ENGINE_DESIGN.md b/docs/topics/ai/AI_ENGINE_DESIGN.md similarity index 96% rename from docs/AI_ENGINE_DESIGN.md rename to docs/topics/ai/AI_ENGINE_DESIGN.md index eff6bd7..66e2182 100644 --- a/docs/AI_ENGINE_DESIGN.md +++ b/docs/topics/ai/AI_ENGINE_DESIGN.md @@ -1,5 +1,7 @@ # AI 智能引擎设计文档 +> 文档定位:**AI 能力方向的设计性/专题性文档**。 +> 本文描述的是 AI 引擎的设计设想与能力规划,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),当前架构边界见 [../../ARCHITECTURE.md](../../ARCHITECTURE.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。 ## 一、AI 引擎架构 ### 1.1 整体架构 diff --git a/docs/AI_FREECAD_INTEGRATION.md b/docs/topics/ai/AI_FREECAD_INTEGRATION.md similarity index 94% rename from docs/AI_FREECAD_INTEGRATION.md rename to docs/topics/ai/AI_FREECAD_INTEGRATION.md index 213d255..fd73d66 100644 --- a/docs/AI_FREECAD_INTEGRATION.md +++ b/docs/topics/ai/AI_FREECAD_INTEGRATION.md @@ -1,5 +1,7 @@ # AI + FreeCAD 集成方案 +> 文档定位:**AI / FreeCAD 集成方向的专题设计文档**。 +> 本文描述的是集成设想、能力规划与差距分析,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),当前架构边界见 [../../ARCHITECTURE.md](../../ARCHITECTURE.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。 ## 一、项目概述 本文档描述 geMoldInsight 项目集成 AI 智能引擎和 FreeCAD 的完整方案,实现真实的模具型腔生成和 G 代码输出功能。 diff --git a/docs/FREECAD_SETUP.md b/docs/topics/ai/FREECAD_SETUP.md similarity index 100% rename from docs/FREECAD_SETUP.md rename to docs/topics/ai/FREECAD_SETUP.md diff --git a/docs/GCODE_GENERATION.md b/docs/topics/ai/GCODE_GENERATION.md similarity index 100% rename from docs/GCODE_GENERATION.md rename to docs/topics/ai/GCODE_GENERATION.md diff --git a/docs/MOLD_SPLITTING_IMPROVEMENTS.md b/docs/topics/aluminum-foam/MOLD_SPLITTING_IMPROVEMENTS.md similarity index 100% rename from docs/MOLD_SPLITTING_IMPROVEMENTS.md rename to docs/topics/aluminum-foam/MOLD_SPLITTING_IMPROVEMENTS.md diff --git a/docs/SPEC_ALUMINUM_FOAM_MOLD.md b/docs/topics/aluminum-foam/SPEC_ALUMINUM_FOAM_MOLD.md similarity index 98% rename from docs/SPEC_ALUMINUM_FOAM_MOLD.md rename to docs/topics/aluminum-foam/SPEC_ALUMINUM_FOAM_MOLD.md index 2a9c395..fded7b1 100644 --- a/docs/SPEC_ALUMINUM_FOAM_MOLD.md +++ b/docs/topics/aluminum-foam/SPEC_ALUMINUM_FOAM_MOLD.md @@ -1,5 +1,8 @@ # 铝制家电包装泡沫模具分模功能技术规格说明书 +> 文档定位:**铝泡沫模具分模方向的专题规格文档**。 +> 本文保留该方向的需求背景、规格设想与能力边界,不作为当前项目整体状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),总体架构见 [../../ARCHITECTURE.md](../../ARCHITECTURE.md),活跃技术债见 [../../TECH_DEBT.md](../../TECH_DEBT.md)。 + ## 文档信息 | 项目 | 内容 | diff --git a/docs/PERFORMANCE_BENCHMARKS.md b/docs/topics/performance/PERFORMANCE_BENCHMARKS.md similarity index 76% rename from docs/PERFORMANCE_BENCHMARKS.md rename to docs/topics/performance/PERFORMANCE_BENCHMARKS.md index d10f7b4..0cb2918 100644 --- a/docs/PERFORMANCE_BENCHMARKS.md +++ b/docs/topics/performance/PERFORMANCE_BENCHMARKS.md @@ -1,5 +1,7 @@ # 性能基准定义(建议) +> 文档定位:**性能基准与压测口径的专题参考文档**。 +> 本文给出建议性性能指标与测试数据口径,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。 ## 1. 核心接口基准 | 场景 | 接口 | 指标 | diff --git a/docs/PERFORMANCE_SCALABILITY_PLAN.md b/docs/topics/performance/PERFORMANCE_SCALABILITY_PLAN.md similarity index 87% rename from docs/PERFORMANCE_SCALABILITY_PLAN.md rename to docs/topics/performance/PERFORMANCE_SCALABILITY_PLAN.md index 160eb89..866eda8 100644 --- a/docs/PERFORMANCE_SCALABILITY_PLAN.md +++ b/docs/topics/performance/PERFORMANCE_SCALABILITY_PLAN.md @@ -1,5 +1,7 @@ # 性能与扩展性评估补充(模具订单/采购主线) +> 文档定位:**性能与扩展性方向的专题规划文档**。 +> 本文描述的是性能评估、慢 SQL 发现、扩展路线等补充规划,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。 ## 1. 高并发冲突面与加固点 ### 1.1 新增/修改模具订单的锁冲突来源 diff --git a/docs/RUSTFS_STORAGE.md b/docs/topics/storage/RUSTFS_STORAGE.md similarity index 96% rename from docs/RUSTFS_STORAGE.md rename to docs/topics/storage/RUSTFS_STORAGE.md index ce3c1b0..caaf078 100644 --- a/docs/RUSTFS_STORAGE.md +++ b/docs/topics/storage/RUSTFS_STORAGE.md @@ -1,5 +1,7 @@ # RustFS 对象存储集成说明 +> 文档定位:**RustFS / 对象存储集成的专题说明文档**。 +> 本文解释对象存储侧的接口与集成思路,不作为当前部署入口文档。当前部署方式见 [../../DEPLOYMENT.md](../../DEPLOYMENT.md) 与 [../../deployment/LINUX_SETUP.md](../../deployment/LINUX_SETUP.md),当前状态见 [../../STATUS.md](../../STATUS.md)。 ## 架构概述 本项目采用 **RustFS** 作为对象存储和 **PostgreSQL** 作为元数据存储的双层存储架构。 diff --git a/docs/STORAGE_SETUP.md b/docs/topics/storage/STORAGE_SETUP.md similarity index 80% rename from docs/STORAGE_SETUP.md rename to docs/topics/storage/STORAGE_SETUP.md index 18d1535..20c29df 100644 --- a/docs/STORAGE_SETUP.md +++ b/docs/topics/storage/STORAGE_SETUP.md @@ -1,6 +1,8 @@ # 存储架构说明 -> 本文档主要解释 geMoldInsight 的存储分层与数据流。其历史中的“本项目自行拉起 PostgreSQL / MinIO 并通过 `python src/main.py` 启动单体”的部分,**已不再代表当前默认部署方式**。 +> 文档定位:**存储分层与数据流的专题说明文档**。 +> 本文主要解释 geMoldInsight 的存储架构,不作为当前部署入口或当前状态的权威说明。当前部署方式见 [../../DEPLOYMENT.md](../../DEPLOYMENT.md),当前状态见 [../../STATUS.md](../../STATUS.md),总体架构见 [../../ARCHITECTURE.md](../../ARCHITECTURE.md)。 +> 其历史中的“本项目自行拉起 PostgreSQL / MinIO 并通过 `python src/main.py` 启动单体”的部分,**已不再代表当前默认部署方式**。 当前默认部署前提是: @@ -10,10 +12,10 @@ - 项目自身只部署:`moldinsight` / `moldinsight-celery` / `inventory` 如需查看当前部署方式,请优先参考: -- [README.md](../README.md) -- [LINUX_SETUP.md](./deployment/LINUX_SETUP.md) -- [DEPLOY_PORT.md](./deployment/DEPLOY_PORT.md) -- [BACKEND_MODULARIZATION_BLUEPRINT.md](./BACKEND_MODULARIZATION_BLUEPRINT.md) +- [../../../README.md](../../../README.md) +- [../../deployment/LINUX_SETUP.md](../../deployment/LINUX_SETUP.md) +- [../../deployment/DEPLOY_PORT.md](../../deployment/DEPLOY_PORT.md) +- [../../archive/BACKEND_MODULARIZATION_BLUEPRINT.md](../../archive/BACKEND_MODULARIZATION_BLUEPRINT.md) --- @@ -110,13 +112,13 @@ RUSTFS_SECRET_KEY=change-me ### 2. 初始化数据库 当前初始化入口参考: -- [init_db.py](../src/shared/database/init_db.py) +- [init_db.py](../../../src/shared/database/init_db.py) ### 3. 启动项目服务 当前推荐通过: -- [docker-compose.yml](../docker-compose.yml) -- 或 [src/entrypoints/](../src/entrypoints/) +- [docker-compose.yml](../../../docker-compose.yml) +- 或 [src/entrypoints/](../../../src/entrypoints/) 而不是继续使用历史单体 `python src/main.py` 作为默认方式。 diff --git a/scripts/test_mold_splitting.py b/scripts/test_mold_splitting.py index be5d698..27c2cdb 100644 --- a/scripts/test_mold_splitting.py +++ b/scripts/test_mold_splitting.py @@ -170,7 +170,7 @@ def test_parting_line_calculation(): generator = MoldCavityGenerator() # 计算分型线 - parting_line = generator._calculate_parting_line(box, parting_surface) + parting_line = generator.calculate_parting_line(box, parting_surface) print(f"✓ 分型线计算完成") print(f" - 点数:{len(parting_line)}") diff --git a/src/moldinsight/core/aluminum_foam_mold.py b/src/moldinsight/core/aluminum_foam_mold.py index b49f883..18d4474 100644 --- a/src/moldinsight/core/aluminum_foam_mold.py +++ b/src/moldinsight/core/aluminum_foam_mold.py @@ -12,6 +12,7 @@ """ from typing import Dict, List, Any, Tuple, Optional +import warnings import numpy as np from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox @@ -55,13 +56,11 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): self.foam_material = foam_material - self.parting_line_tolerance = 0.1 self.max_draft_angle = 5.0 self.min_draft_angle = 1.0 self.cavity_count = 1 self.parting_precision = 0.1 - self.cavity_match_rate = 95.0 self.side_action_designer = SideActionDesigner() def set_foam_material(self, material: str): @@ -89,7 +88,7 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): def generate_mold_cavities(self, product_shape: TopoDS_Shape) -> Dict[str, Any]: """ - 从产品的3D模型生成型腔和型芯 + [已废弃] 单方案分模入口。生产路径请使用 MultiSchemeMoldPlanner.generate_plan。 完整流程: 1. 分析产品几何 @@ -100,10 +99,15 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): 6. 分离型腔和型芯 7. 生成模具块 """ + warnings.warn( + "generate_mold_cavities 已废弃,请改用 MultiSchemeMoldPlanner.generate_plan 生成多方案分模结果", + DeprecationWarning, + stacklevel=2, + ) logger.info(f"开始生成铝泡沫模具型腔 (材料: {self.foam_material})...") try: - analysis = self._analyze_product_geometry(product_shape) + analysis = self.analyze_product_geometry(product_shape) parting_result = self._detect_parting_surfaces(product_shape, analysis) primary_parting_surface = parting_result["primary_surface"] @@ -113,20 +117,20 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): side_action_result = self.side_action_designer.analyze_and_design( shape=product_shape, parting_direction=primary_parting_direction, - mold_size=self._calculate_mold_size(analysis), + mold_size=self.calculate_mold_size(analysis), parting_surface=primary_parting_surface, ) - undercut_regions = self._build_undercut_regions( + undercut_regions = self.build_undercut_regions( side_action_result.get("undercut_analysis", {}) ) - scaled_shape = self._apply_shrinkage_compensation(product_shape) + scaled_shape = self.apply_shrinkage_compensation(product_shape) - drafted_shape = self._apply_draft_angles(scaled_shape, primary_parting_surface) + drafted_shape = self.apply_draft_angles(scaled_shape, primary_parting_surface) - cavity, core = self._split_cavity_core(drafted_shape, primary_parting_surface) + cavity, core = self.split_cavity_core(drafted_shape, primary_parting_surface) - mold_block = self._generate_mold_block(cavity, analysis) + mold_block = self.generate_mold_block(cavity, analysis) smoothed_parting_line = self._smooth_parting_line(primary_parting_line) @@ -187,7 +191,7 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): }, "parting_surface": parting_geometry, "manufacturing_info": { - "estimated_mold_size": self._calculate_mold_size(analysis), + "estimated_mold_size": self.calculate_mold_size(analysis), "estimated_clamping_force": self._calculate_clamping_force(analysis), "clamping_force_formula": "投影面积(cm²) × 0.3 (泡沫材料系数)", "recommended_material": material_info.get("description", "Aluminum Foam Mold"), @@ -251,9 +255,9 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): # ==================== 核心算法实现 ==================== - def _analyze_product_geometry(self, shape: TopoDS_Shape) -> Dict[str, Any]: + def analyze_product_geometry(self, shape: TopoDS_Shape) -> Dict[str, Any]: """分析产品几何属性(扩展基类版本,增加法向量统计)""" - result = super()._analyze_product_geometry(shape) + result = super().analyze_product_geometry(shape) result["normal_statistics"] = self._analyze_parting_direction(shape) return result @@ -266,7 +270,7 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): face = topods.Face(explorer.Current()) explorer.Next() try: - normal = self._get_face_normal(face) + normal = self.get_face_normal(face) if normal is None: continue props = GProp_GProps() @@ -287,9 +291,9 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): for axis, value in stats.items() } - def _split_cavity_core(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face) -> Tuple[TopoDS_Shape, TopoDS_Shape]: + def split_cavity_core(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face) -> Tuple[TopoDS_Shape, TopoDS_Shape]: """分离型腔和型芯(铝泡沫使用更大余量)""" - return super()._split_cavity_core(shape, parting_surface, margin=25) + return super().split_cavity_core(shape, parting_surface, margin=25) def _detect_parting_surfaces(self, shape: TopoDS_Shape, analysis: Dict) -> Dict[str, Any]: """ @@ -317,7 +321,7 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): logger.info(f"泡沫模具 Z 轴分型面: Z={parting_z:.2f} mm (包围盒中心)") parting_line = self.optimize_parting_line( - self._calculate_parting_line(shape, parting_surface) + self.calculate_parting_line(shape, parting_surface) ) additional_surfaces = [] @@ -352,7 +356,7 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): "parting_position_z": parting_z, } - def _build_undercut_regions(self, undercut_analysis: Dict[str, Any]) -> List[Dict[str, Any]]: + def build_undercut_regions(self, undercut_analysis: Dict[str, Any]) -> List[Dict[str, Any]]: """将侧向机构分析结果转换为兼容旧结构的倒扣区域列表。""" undercut_faces = undercut_analysis.get("undercut_faces", []) regions = [] @@ -429,7 +433,7 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): except Exception: return 50.0 - def _generate_mold_block(self, cavity: TopoDS_Shape, analysis: Dict) -> TopoDS_Shape: + def generate_mold_block(self, cavity: TopoDS_Shape, analysis: Dict) -> TopoDS_Shape: """生成完整的模具块(包含A/B板结构)""" try: bbox = analysis["bounding_box"] @@ -464,7 +468,7 @@ class AluminumFoamMoldGenerator(BaseMoldGenerator): # ==================== 辅助方法 ==================== - def _calculate_mold_size(self, analysis: Dict) -> Dict[str, float]: + def calculate_mold_size(self, analysis: Dict) -> Dict[str, float]: """估算模具尺寸""" dims = analysis["bounding_box"]["dimensions"] margin = 30 diff --git a/src/moldinsight/core/base_mold_generator.py b/src/moldinsight/core/base_mold_generator.py index 7cf53bd..65bd19b 100644 --- a/src/moldinsight/core/base_mold_generator.py +++ b/src/moldinsight/core/base_mold_generator.py @@ -25,15 +25,60 @@ logger = get_logger(__name__) class BaseMoldGenerator: - """模具生成器基类 - 提供共用方法""" + """模具生成器基类 - 提供共用方法 + + 公共接口契约(MultiSchemeMoldPlanner 及上层服务依赖,子类覆写时必须保持签名稳定): + - analyze_product_geometry(shape) -> 几何分析结果 dict + - calculate_parting_line(shape, parting_surface) -> 分型线点列 + - calculate_mold_size(analysis) -> 模具尺寸估算 dict + - build_undercut_regions(undercut_analysis) -> 倒扣区域列表 + - apply_shrinkage_compensation(shape) / apply_draft_angles(shape, parting_surface) -> 形状 + - split_cavity_core(shape, parting_surface) -> (cavity, core) + - create_mold_block(analysis, margin) -> 模具包围盒形状 + - split_mold_block_by_plane(mold_block, parting_plane) -> (a_plate, b_plate) + - get_parting_plane(parting_surface, shape) -> gp_Pln + - get_face_normal(face) -> gp_Dir + - apply_process_params(material, process_params) -> None + - generate_mold_block(cavity, analysis):仅泡沫类生成器实现 + - set_material / generate_detailed_cavity_json / generate_cavity_key_info / side_action_designer + + generate_mold_cavities 为已废弃的单方案入口,生产路径走 MultiSchemeMoldPlanner.generate_plan。 + """ def __init__(self, shrinkage_rate: float = 0.005, draft_angle: float = 2.0, material_density: float = 1.05): self.shrinkage_rate = shrinkage_rate self.draft_angle = draft_angle self.material_density = material_density + self.parting_line_tolerance = 0.1 + self.cavity_match_rate = 95.0 - def _apply_shrinkage_compensation(self, shape: TopoDS_Shape) -> TopoDS_Shape: + def apply_process_params( + self, + material: Dict[str, Any], + process_params: Optional[Dict[str, Any]] = None, + ) -> None: + """按用户工艺参数覆盖生成器参数,未指定的项取材料默认值或当前值。 + + material 为 MaterialService.get_material() 返回的材料属性 dict; + process_params 支持 draft_angle / shrinkage_rate(百分数) / parting_precision / cavity_match。 + """ + params = process_params or {} + draft_angle = float(params.get("draft_angle", getattr(self, "draft_angle", 2.0))) + shrinkage_rate = float(params.get("shrinkage_rate", material.get("shrinkage", 0.005) * 100.0)) / 100.0 + parting_precision = float(params.get("parting_precision", getattr(self, "parting_line_tolerance", 0.1))) + cavity_match = float(params.get("cavity_match", getattr(self, "cavity_match_rate", 95.0))) + + self.draft_angle = draft_angle + self.shrinkage_rate = shrinkage_rate + self.parting_line_tolerance = parting_precision + self.cavity_match_rate = cavity_match + + def generate_mold_block(self, cavity: TopoDS_Shape, analysis: Dict) -> TopoDS_Shape: + """生成完整模具块(A/B板结构)。仅泡沫类生成器实现,基类不提供默认。""" + raise NotImplementedError("generate_mold_block 仅由泡沫模具生成器实现") + + def apply_shrinkage_compensation(self, shape: TopoDS_Shape) -> TopoDS_Shape: scale_factor = 1.0 + self.shrinkage_rate trsf = gp_Trsf() trsf.SetScale(gp_Pnt(0, 0, 0), scale_factor) @@ -45,7 +90,7 @@ class BaseMoldGenerator: logger.warning(f"收缩率补偿失败: {e}") return shape - def _apply_draft_angles(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face) -> TopoDS_Shape: + def apply_draft_angles(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face) -> TopoDS_Shape: try: draft_direction = self._get_draft_direction(parting_surface) if draft_direction is None: @@ -78,7 +123,7 @@ class BaseMoldGenerator: return gp_Dir(0, 0, 1) @staticmethod - def _create_mold_block(analysis: Dict, margin: float = 30.0) -> TopoDS_Shape: + def create_mold_block(analysis: Dict, margin: float = 30.0) -> TopoDS_Shape: """基于产品边界框创建模具包围盒(用于切分 A/B 半模等可视化用途)。""" bbox = analysis.get("bounding_box", {}) dims = bbox.get("dimensions", [100, 100, 100]) @@ -95,7 +140,7 @@ class BaseMoldGenerator: while explorer.More(): face = topods.Face(explorer.Current()) - normal = self._get_face_normal(face) + normal = self.get_face_normal(face) if normal is not None: dot = abs(normal.Dot(draft_direction)) @@ -107,7 +152,7 @@ class BaseMoldGenerator: return draftable - def _get_face_normal(self, face: TopoDS_Face) -> Optional[gp_Dir]: + def get_face_normal(self, face: TopoDS_Face) -> Optional[gp_Dir]: try: surface = BRepAdaptor_Surface(face) u = (surface.FirstUParameter() + surface.LastUParameter()) / 2 @@ -133,7 +178,7 @@ class BaseMoldGenerator: for face in faces: try: - normal = self._get_face_normal(face) + normal = self.get_face_normal(face) if normal is None: continue @@ -168,7 +213,7 @@ class BaseMoldGenerator: for face in faces: try: draft = BRepOffsetAPI_DraftAngle(current_shape) - normal = self._get_face_normal(face) + normal = self.get_face_normal(face) if normal is None: continue @@ -194,7 +239,7 @@ class BaseMoldGenerator: return current_shape - def _analyze_product_geometry(self, shape: TopoDS_Shape) -> Dict[str, Any]: + def analyze_product_geometry(self, shape: TopoDS_Shape) -> Dict[str, Any]: try: props = GProp_GProps() brepgprop.VolumeProperties(shape, props) @@ -228,7 +273,7 @@ class BaseMoldGenerator: logger.error(f"产品几何分析失败: {e}") raise - def _split_cavity_core(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face, margin: int = 20) -> Tuple[TopoDS_Shape, TopoDS_Shape]: + def split_cavity_core(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face, margin: int = 20) -> Tuple[TopoDS_Shape, TopoDS_Shape]: """ 分离型腔和型芯 — 完全嵌入 + 突出贴合方式。 @@ -254,7 +299,7 @@ class BaseMoldGenerator: gp_Pnt(mold_xmax, mold_ymax, mold_zmax) ).Shape() - parting_plane = self._get_parting_plane(parting_surface, shape) + parting_plane = self.get_parting_plane(parting_surface, shape) if parting_plane is None: center_z = (zmin + zmax) / 2 parting_plane = gp_Pln(gp_Pnt(0, 0, center_z), gp_Dir(0, 0, 1)) @@ -371,7 +416,7 @@ class BaseMoldGenerator: logger.info("型芯 Compound 兜底构建 (底座+产品)") return compound - def _get_parting_plane(self, parting_surface: TopoDS_Face, shape: TopoDS_Shape) -> Optional[gp_Pln]: + def get_parting_plane(self, parting_surface: TopoDS_Face, shape: TopoDS_Shape) -> Optional[gp_Pln]: """从分型面提取平面方程""" try: surface = BRepAdaptor_Surface(parting_surface) @@ -388,7 +433,7 @@ class BaseMoldGenerator: logger.warning(f"分型面平面提取失败: {e}") return None - def _split_mold_block_by_plane(self, mold_block: TopoDS_Shape, + def split_mold_block_by_plane(self, mold_block: TopoDS_Shape, parting_plane: gp_Pln) -> Tuple[TopoDS_Shape, TopoDS_Shape]: """ 用分型面将模具块切分为A板(上模)和B板(下模) @@ -751,7 +796,7 @@ class BaseMoldGenerator: return total_length - def _calculate_parting_line(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face) -> List[List[float]]: + def calculate_parting_line(self, shape: TopoDS_Shape, parting_surface: TopoDS_Face) -> List[List[float]]: try: section = BRepAlgoAPI_Section(shape, parting_surface) section.Build() diff --git a/src/moldinsight/core/mold_generator.py b/src/moldinsight/core/mold_generator.py index 6397bec..8e93f45 100644 --- a/src/moldinsight/core/mold_generator.py +++ b/src/moldinsight/core/mold_generator.py @@ -1,4 +1,5 @@ from typing import Dict, List, Any, Tuple, Optional +import warnings import numpy as np from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace from OCC.Core.gp import gp_Pln, gp_Dir, gp_Pnt @@ -25,7 +26,6 @@ class MoldCavityGenerator(BaseMoldGenerator): material_density: float = 1.05): super().__init__(shrinkage_rate, draft_angle, material_density) - self.parting_line_tolerance = 0.1 self.max_draft_angle = 5.0 self.side_action_designer = SideActionDesigner() @@ -39,7 +39,7 @@ class MoldCavityGenerator(BaseMoldGenerator): def generate_mold_cavities(self, product_shape: TopoDS_Shape) -> Dict[str, Any]: """ - 从产品的3D模型生成型腔和型芯 + [已废弃] 单方案分模入口。生产路径请使用 MultiSchemeMoldPlanner.generate_plan。 Returns: { @@ -49,10 +49,15 @@ class MoldCavityGenerator(BaseMoldGenerator): "parting_line": parting_line } """ + warnings.warn( + "generate_mold_cavities 已废弃,请改用 MultiSchemeMoldPlanner.generate_plan 生成多方案分模结果", + DeprecationWarning, + stacklevel=2, + ) logger.info("开始生成模具型腔...") try: - analysis = self._analyze_product_geometry(product_shape) + analysis = self.analyze_product_geometry(product_shape) parting_result = self._detect_primary_parting(product_shape, analysis) parting_surface = parting_result["surface"] @@ -62,18 +67,18 @@ class MoldCavityGenerator(BaseMoldGenerator): side_action_result = self.side_action_designer.analyze_and_design( shape=product_shape, parting_direction=parting_direction, - mold_size=self._calculate_mold_size(analysis), + mold_size=self.calculate_mold_size(analysis), parting_surface=parting_surface, ) - undercut_regions = self._build_undercut_regions( + undercut_regions = self.build_undercut_regions( side_action_result.get("undercut_analysis", {}) ) - scaled_shape = self._apply_shrinkage_compensation(product_shape) + scaled_shape = self.apply_shrinkage_compensation(product_shape) - drafted_shape = self._apply_draft_angles(scaled_shape, parting_surface) + drafted_shape = self.apply_draft_angles(scaled_shape, parting_surface) - cavity, core = self._split_cavity_core(drafted_shape, parting_surface) + cavity, core = self.split_cavity_core(drafted_shape, parting_surface) logger.info("模具型腔生成完成") @@ -137,7 +142,7 @@ class MoldCavityGenerator(BaseMoldGenerator): "side_action_summary": cavity_data.get("side_actions", {}).get("summary", {}), }, "manufacturing_info": { - "estimated_mold_size": self._calculate_mold_size(analysis), + "estimated_mold_size": self.calculate_mold_size(analysis), "estimated_clamping_force": self._calculate_clamping_force(analysis), "recommended_material": self._get_recommended_material() } @@ -223,7 +228,7 @@ class MoldCavityGenerator(BaseMoldGenerator): parting_plane, -span, span, -span, span ).Face() parting_surface = self.extend_parting_surface(parting_surface, shape, extension=30.0) - parting_line = self._calculate_parting_line(shape, parting_surface) + parting_line = self.calculate_parting_line(shape, parting_surface) return { "surface": parting_surface, "line": parting_line, @@ -243,7 +248,7 @@ class MoldCavityGenerator(BaseMoldGenerator): "confidence": 0.6, } - def _build_undercut_regions(self, undercut_analysis: Dict[str, Any]) -> List[Dict[str, Any]]: + def build_undercut_regions(self, undercut_analysis: Dict[str, Any]) -> List[Dict[str, Any]]: """将侧向机构分析结果转换为兼容旧结构的倒扣区域列表。""" undercut_faces = undercut_analysis.get("undercut_faces", []) regions = [] @@ -360,7 +365,7 @@ class MoldCavityGenerator(BaseMoldGenerator): "bounds": metadata["bounds"], } - def _calculate_mold_size(self, analysis: Dict) -> Dict[str, float]: + def calculate_mold_size(self, analysis: Dict) -> Dict[str, float]: """估算模具尺寸""" product_bbox = analysis["bounding_box"]["dimensions"] margin = 30 diff --git a/src/moldinsight/core/multi_scheme_planner.py b/src/moldinsight/core/multi_scheme_planner.py index d229206..da80d7e 100644 --- a/src/moldinsight/core/multi_scheme_planner.py +++ b/src/moldinsight/core/multi_scheme_planner.py @@ -33,9 +33,9 @@ class MultiSchemeMoldPlanner: ) -> Dict[str, Any]: generator = mold_generator_registry.get_by_type("aluminum_foam" if is_foam_material else "injection") generator.set_material(material["name"]) - self._apply_process_params(generator, material, process_params) + generator.apply_process_params(material, process_params) - analysis = generator._analyze_product_geometry(shape) + analysis = generator.analyze_product_geometry(shape) analysis["axis_normal_stats"] = self._collect_axis_normal_stats(generator, shape) candidates = self.candidate_generator.generate_candidates( analysis=analysis, @@ -100,24 +100,24 @@ class MultiSchemeMoldPlanner: candidate.get("opening_span_mm"), ) parting_line = generator.optimize_parting_line( - generator._calculate_parting_line(shape, parting_surface) + generator.calculate_parting_line(shape, parting_surface) ) parting_direction = candidate["direction"] side_action_result = generator.side_action_designer.analyze_and_design( shape=shape, parting_direction=parting_direction, - mold_size=generator._calculate_mold_size(analysis), + mold_size=generator.calculate_mold_size(analysis), parting_surface=parting_surface, ) - undercut_regions = generator._build_undercut_regions( + undercut_regions = generator.build_undercut_regions( side_action_result.get("undercut_analysis", {}) ) mold_structure = self._determine_mold_structure(analysis, undercut_regions) - scaled_shape = generator._apply_shrinkage_compensation(shape) - drafted_shape = generator._apply_draft_angles(scaled_shape, parting_surface) - cavity, core = generator._split_cavity_core(drafted_shape, parting_surface) + scaled_shape = generator.apply_shrinkage_compensation(shape) + drafted_shape = generator.apply_draft_angles(scaled_shape, parting_surface) + cavity, core = generator.split_cavity_core(drafted_shape, parting_surface) cavity_result = { "cavity": cavity, @@ -130,7 +130,7 @@ class MultiSchemeMoldPlanner: } if is_foam_material: - cavity_result["mold_block"] = generator._generate_mold_block(cavity, analysis) + cavity_result["mold_block"] = generator.generate_mold_block(cavity, analysis) cavity_result["parting_surfaces"] = { "primary_surface": parting_surface, "primary_line": parting_line, @@ -158,10 +158,10 @@ class MultiSchemeMoldPlanner: # 生成可视化辅助形状:A/B 半模(分型面切分)、产品本体 a_plate, b_plate, product_for_export = None, None, scaled_shape try: - mold_block_shape = generator._create_mold_block(analysis, margin=30.0) - a_plate, b_plate = generator._split_mold_block_by_plane( + mold_block_shape = generator.create_mold_block(analysis, margin=30.0) + a_plate, b_plate = generator.split_mold_block_by_plane( mold_block_shape, - generator._get_parting_plane(parting_surface, shape), + generator.get_parting_plane(parting_surface, shape), ) except Exception as exc: logger.debug(f"A/B 半模生成失败(不影响主流程): {exc}") @@ -199,19 +199,6 @@ class MultiSchemeMoldPlanner: }, } - @staticmethod - def _apply_process_params(generator: Any, material: Dict[str, Any], process_params: Optional[Dict[str, Any]]): - params = process_params or {} - draft_angle = float(params.get("draft_angle", getattr(generator, "draft_angle", 2.0))) - shrinkage_rate = float(params.get("shrinkage_rate", material.get("shrinkage", 0.005) * 100.0)) / 100.0 - parting_precision = float(params.get("parting_precision", getattr(generator, "parting_line_tolerance", 0.1))) - cavity_match = float(params.get("cavity_match", getattr(generator, "cavity_match_rate", 95.0))) - - generator.draft_angle = draft_angle - generator.shrinkage_rate = shrinkage_rate - generator.parting_line_tolerance = parting_precision - generator.cavity_match_rate = cavity_match - def _build_parting_surface( self, generator: Any, @@ -290,7 +277,7 @@ class MultiSchemeMoldPlanner: explorer.Next() try: - normal = generator._get_face_normal(face) + normal = generator.get_face_normal(face) if normal is None: continue diff --git a/tests/test_mold_generator_contract.py b/tests/test_mold_generator_contract.py new file mode 100644 index 0000000..002953a --- /dev/null +++ b/tests/test_mold_generator_contract.py @@ -0,0 +1,159 @@ +"""Generator 公共接口契约测试(技术债计划 P2-⑩)。 + +BaseMoldGenerator 的公共契约原先以 `_` 私有方法形式暴露给 MultiSchemeMoldPlanner, +本文件锁定提取后的公共接口:方法存在性、参数覆写行为、废弃入口告警, +并用真实几何(OCC box)走一遍 generate_plan 集成路径。 + +OCC(pythonocc)仅 conda 环境提供(本地 gemold / 服务器 py_3.12), +无 OCC 的环境自动跳过本文件,不影响其余测试。 +""" + +import pytest + +pytest.importorskip("OCC.Core.BRepPrimAPI", reason="需要 pythonocc 运行生成器契约测试") + +from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox +from OCC.Core.gp import gp_Pnt + +from moldinsight.core.aluminum_foam_mold import AluminumFoamMoldGenerator +from moldinsight.core.base_mold_generator import BaseMoldGenerator +from moldinsight.core.mold_generator import MoldCavityGenerator +from moldinsight.core.multi_scheme_planner import MultiSchemeMoldPlanner +from moldinsight.services.material_service import MaterialService + +# BaseMoldGenerator 上的公共契约(含子类必须可调用的基类默认实现) +BASE_CONTRACT_METHODS = ( + "analyze_product_geometry", + "apply_shrinkage_compensation", + "apply_draft_angles", + "split_cavity_core", + "create_mold_block", + "split_mold_block_by_plane", + "get_parting_plane", + "get_face_normal", + "calculate_parting_line", + "apply_process_params", +) + +# 两个子类共同实现的完整契约 +SUBCLASS_CONTRACT_METHODS = BASE_CONTRACT_METHODS + ( + "calculate_mold_size", + "build_undercut_regions", + "set_material", + "side_action_designer", + "generate_detailed_cavity_json", + "generate_cavity_key_info", + "generate_mold_cavities", # 已废弃但保留兼容 +) + + +def _box(dx=50.0, dy=40.0, dz=30.0): + return BRepPrimAPI_MakeBox( + gp_Pnt(-dx / 2, -dy / 2, -dz / 2), gp_Pnt(dx / 2, dy / 2, dz / 2) + ).Shape() + + +@pytest.mark.parametrize("method", SUBCLASS_CONTRACT_METHODS) +@pytest.mark.parametrize( + "generator_cls", [MoldCavityGenerator, AluminumFoamMoldGenerator] +) +def test_generator_exposes_public_contract(generator_cls, method): + generator = generator_cls() + attr = getattr(generator, method, None) + assert attr is not None, f"{generator_cls.__name__} 缺少公共接口 {method}" + assert callable(attr) or isinstance(attr, object) + + +def test_foam_generator_implements_generate_mold_block(): + assert callable(AluminumFoamMoldGenerator().generate_mold_block) + + +def test_base_generate_mold_block_is_not_implemented(): + with pytest.raises(NotImplementedError): + BaseMoldGenerator().generate_mold_block(None, {}) + + +def test_apply_process_params_overrides_generator_state(): + generator = MoldCavityGenerator(shrinkage_rate=0.005, draft_angle=2.0) + material = MaterialService.get_material("ABS") + + generator.apply_process_params( + material, + { + "draft_angle": 1.5, + "shrinkage_rate": 1.2, # 百分数 + "parting_precision": 0.05, + "cavity_match": 97.0, + }, + ) + + assert generator.draft_angle == pytest.approx(1.5) + assert generator.shrinkage_rate == pytest.approx(0.012) + assert generator.parting_line_tolerance == pytest.approx(0.05) + assert generator.cavity_match_rate == pytest.approx(97.0) + + +def test_apply_process_params_defaults_to_material_shrinkage(): + generator = MoldCavityGenerator(shrinkage_rate=0.005, draft_angle=2.0) + material = MaterialService.get_material("PP") # shrinkage 0.016 + + generator.apply_process_params(material, None) + + assert generator.shrinkage_rate == pytest.approx(0.016) + assert generator.draft_angle == pytest.approx(2.0) + + +def test_generate_mold_cavities_is_deprecated(): + generator = MoldCavityGenerator() + + with pytest.warns(DeprecationWarning): + result = generator.generate_mold_cavities(_box()) + + assert result["cavity"] is not None + assert result["core"] is not None + + +def test_planner_generate_plan_injection_box(): + planner = MultiSchemeMoldPlanner() + + plan = planner.generate_plan( + _box(), + MaterialService.get_material("ABS"), + is_foam_material=False, + max_schemes=2, + ) + + schemes = plan["candidate_schemes"] + assert 1 <= len(schemes) <= 2 + assert plan["best_scheme_id"] == schemes[0]["scheme_id"] + + best = schemes[0] + assert best["cavity_data"]["mold_cavities"]["cavity"]["vertex_count"] > 0 + assert best["cavity_data"]["mold_cavities"]["core"]["vertex_count"] > 0 + assert best["cavity_data"]["metadata"]["scheme_id"] == best["scheme_id"] + assert best["parting"]["line"] + + export_shapes = plan["_export_shapes"][best["scheme_id"]] + assert export_shapes["cavity"] is not None + assert export_shapes["product"] is not None + + +def test_planner_generate_plan_foam_box(): + planner = MultiSchemeMoldPlanner() + + plan = planner.generate_plan( + _box(120, 100, 60), + MaterialService.get_material("AlSi10Mg"), + is_foam_material=True, + max_schemes=1, + ) + + best = plan["candidate_schemes"][0] + assert plan["best_scheme_id"] == best["scheme_id"] + # 泡沫材料优先 Z 轴上下开模 + assert best["axis"] == "Z" + assert best["cavity_data"]["metadata"]["foam_material"] == "AlSi10Mg" + assert best["cavity_data"]["mold_cavities"]["cavity"]["vertex_count"] > 0 + + export_shapes = plan["_export_shapes"][best["scheme_id"]] + assert export_shapes["cavity"] is not None