文档目录结构简洁化

This commit is contained in:
2026-09-01 18:05:18 +08:00
parent bee439cf34
commit 5e531ffe1e
47 changed files with 1334 additions and 3380 deletions
+126 -391
View File
@@ -11,11 +11,19 @@
</div>
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)
---
+221
View File
@@ -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)
-908
View File
@@ -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 与部署文档
这条路径风险最低、收益最大,也最符合当前代码现状与团队演进成本。
-390
View File
@@ -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 规范
- [ ] 包含类型注解
- [ ] 包含文档字符串
- [ ] 单元测试覆盖
- [ ] 无安全漏洞
- [ ] 无硬编码密码
---
**文档结束**
-37
View File
@@ -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 产物归档。
+117
View File
@@ -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 只保留最短启动说明,不再承担部署手册职责
-258
View File
@@ -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 天
-315
View File
@@ -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 路径级业务分流”的长期维护问题。
-127
View File
@@ -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` 停写后,历史行中的旧数据仍可读(列保留),仅新行不再写入
+142
View File
@@ -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)
+149
View File
@@ -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)
-827
View File
@@ -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 兼容问题 | 功能受限 | 多种实现方案,准备备选 |
| 性能不达标 | 用户体验差 | 持续优化,必要时降级功能 |
| 需求变更 | 计划调整 | 敏捷开发,快速迭代 |
---
**文档结束**
+158
View File
@@ -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)
@@ -0,0 +1,5 @@
# geMoldInsight 后端模块化重构蓝图(归档)
> 文档定位:**模块化设计蓝图档案 / 补充设计材料**。
> 当前架构与边界的默认入口见 [../ARCHITECTURE.md](../ARCHITECTURE.md),当前状态见 [../STATUS.md](../STATUS.md),未来演进路线见 [../ROADMAP.md](../ROADMAP.md)。
> 本文保留更完整的模块化设计背景、目标与分阶段思考,用于追溯设计决策,不再保留在 `docs/` 顶层作为默认入口。
@@ -0,0 +1,7 @@
# 铝制家电包装泡沫模具分模功能开发检查清单(归档)
> 文档定位:**阶段性检查清单 / 历史材料**,不再作为当前权威文档。
> 当前项目状态见 [../STATUS.md](../STATUS.md),当前架构边界见 [../ARCHITECTURE.md](../ARCHITECTURE.md),当前活跃技术债见 [../TECH_DEBT.md](../TECH_DEBT.md)。
> 若需了解当前模具分析方向,请优先参考主骨架文档,而不是本文的阶段 checklist。
本文保留的是 2026-03-13 铝泡沫模具分模功能增强时期的检查清单,用于记录当时的开发跟踪方式。
@@ -1,5 +1,8 @@
# Confluence 归档目录结构(建议)
> 文档定位:**外部文档归档结构建议稿**。
> 本文描述的是面向 Confluence/知识库归档时的目录建议,不作为当前仓库内文档体系的权威说明。当前仓库文档入口见 [../../README.md](../../README.md) 与 [README.md](README.md)。
## 业务流程
- 01 端到端流程(客户订单→采购→到货→生产→交付)
+6
View File
@@ -0,0 +1,6 @@
# 交付物清单(归档)
> 文档定位:**一次性交付产物索引 / 历史材料**。
> 本文记录某轮分析/整改时的交付物集合,不作为当前项目状态或当前文档导航入口。当前默认入口见 [../../README.md](../../README.md),当前状态见 [../STATUS.md](../STATUS.md)。
保留本文的目的主要是追溯当时的分析交付范围,而不是指导当前项目维护。
+5
View File
@@ -0,0 +1,5 @@
# geMoldInsight 演进路线图(原始执行记录,归档)
> 文档定位:**历史路线与执行记录原文 / 归档材料**。
> 当前默认路线文档见 [../ROADMAP.md](../ROADMAP.md),当前状态见 [../STATUS.md](../STATUS.md),当前技术债见 [../TECH_DEBT.md](../TECH_DEBT.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**,一次性解决长期维护成本。
@@ -0,0 +1,5 @@
# moldinsight 模块技术债务分析与重构计划(原始记录,归档)
> 文档定位:**moldinsight 技术债原始分析与实施记录 / 归档材料**。
> 当前默认技术债文档见 [../TECH_DEBT.md](../TECH_DEBT.md),当前状态见 [../STATUS.md](../STATUS.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`。
+22
View File
@@ -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)
+21
View File
@@ -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)
+7
View File
@@ -0,0 +1,7 @@
# 铝制家电包装泡沫模具分模功能开发任务清单(归档)
> 文档定位:**阶段性任务清单 / 历史材料**,不再作为当前权威文档。
> 当前项目状态见 [../STATUS.md](../STATUS.md),当前架构边界见 [../ARCHITECTURE.md](../ARCHITECTURE.md),当前活跃技术债见 [../TECH_DEBT.md](../TECH_DEBT.md)。
> 若需了解当前模具分析方向,请优先参考主骨架文档,而不是本文的阶段任务分解。
本文保留的是 2026-03-13 铝泡沫模具分模功能增强时期的任务拆解,用于记录当时的实施计划与阶段安排。
@@ -1,5 +1,8 @@
# “零成品库存”证明报告(geMoldInsight)
> 文档定位:**特定业务口径下的专题证明/分析报告**。
> 本文解释“零成品库存”这一业务与财务口径,不作为当前项目整体状态的权威说明。当前状态见 [../STATUS.md](../STATUS.md),相关业务分析见 [MOLD_ERP_ANALYSIS_REPORT.md](MOLD_ERP_ANALYSIS_REPORT.md)。
## 1. 结论
系统不设置成品入库、成品出库、销售退货等成品库存模块;系统库存口径仅覆盖“物料(material)”,成品(finished/模具)仅作为订单交付对象,不进入库存核算链路。
+3 -1
View File
@@ -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)
---
+7 -5
View File
@@ -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)
+3 -1
View File
@@ -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)
-39
View File
@@ -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)
@@ -1,5 +1,8 @@
# 外部接口与集成盘点模板(ERP/财务/供应商门户/客户门户)
> 文档定位:**接口梳理与集成盘点模板文档**。
> 本文是用于外部系统对接时的模板,不作为当前项目状态或当前接口实现清单的权威说明。当前状态见 [../STATUS.md](../STATUS.md),当前架构见 [../ARCHITECTURE.md](../ARCHITECTURE.md)。
## 1. 接口清单
| 接口名称 | 调用方向 | 协议 | 鉴权 | 频率 | 单次数据量 | 幂等键 | 超时 | 重试策略 | 死信/补偿 | 负责人 |
@@ -1,5 +1,8 @@
# UAT 验收清单(模具制造进销存主线)
> 文档定位:**UAT 验收模板 / 验收过程文档**。
> 本文用于业务验收与签字过程,不作为当前项目状态或当前架构的权威说明。当前状态见 [../STATUS.md](../STATUS.md),当前架构见 [../ARCHITECTURE.md](../ARCHITECTURE.md)。
## 1. 业务流程签字
| 模块 | 场景 | 验收点 | 结果 | 业务签字 | 日期 |
@@ -1,5 +1,7 @@
# AI 智能引擎设计文档
> 文档定位:**AI 能力方向的设计性/专题性文档**。
> 本文描述的是 AI 引擎的设计设想与能力规划,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),当前架构边界见 [../../ARCHITECTURE.md](../../ARCHITECTURE.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。
## 一、AI 引擎架构
### 1.1 整体架构
@@ -1,5 +1,7 @@
# AI + FreeCAD 集成方案
> 文档定位:**AI / FreeCAD 集成方向的专题设计文档**。
> 本文描述的是集成设想、能力规划与差距分析,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),当前架构边界见 [../../ARCHITECTURE.md](../../ARCHITECTURE.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。
## 一、项目概述
本文档描述 geMoldInsight 项目集成 AI 智能引擎和 FreeCAD 的完整方案,实现真实的模具型腔生成和 G 代码输出功能。
@@ -1,5 +1,8 @@
# 铝制家电包装泡沫模具分模功能技术规格说明书
> 文档定位:**铝泡沫模具分模方向的专题规格文档**。
> 本文保留该方向的需求背景、规格设想与能力边界,不作为当前项目整体状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),总体架构见 [../../ARCHITECTURE.md](../../ARCHITECTURE.md),活跃技术债见 [../../TECH_DEBT.md](../../TECH_DEBT.md)。
## 文档信息
| 项目 | 内容 |
@@ -1,5 +1,7 @@
# 性能基准定义(建议)
> 文档定位:**性能基准与压测口径的专题参考文档**。
> 本文给出建议性性能指标与测试数据口径,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。
## 1. 核心接口基准
| 场景 | 接口 | 指标 |
@@ -1,5 +1,7 @@
# 性能与扩展性评估补充(模具订单/采购主线)
> 文档定位:**性能与扩展性方向的专题规划文档**。
> 本文描述的是性能评估、慢 SQL 发现、扩展路线等补充规划,不作为当前实现状态的权威说明。当前状态见 [../../STATUS.md](../../STATUS.md),后续路线见 [../../ROADMAP.md](../../ROADMAP.md)。
## 1. 高并发冲突面与加固点
### 1.1 新增/修改模具订单的锁冲突来源
@@ -1,5 +1,7 @@
# RustFS 对象存储集成说明
> 文档定位:**RustFS / 对象存储集成的专题说明文档**。
> 本文解释对象存储侧的接口与集成思路,不作为当前部署入口文档。当前部署方式见 [../../DEPLOYMENT.md](../../DEPLOYMENT.md) 与 [../../deployment/LINUX_SETUP.md](../../deployment/LINUX_SETUP.md),当前状态见 [../../STATUS.md](../../STATUS.md)。
## 架构概述
本项目采用 **RustFS** 作为对象存储和 **PostgreSQL** 作为元数据存储的双层存储架构。
@@ -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` 作为默认方式。
+1 -1
View File
@@ -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)}")
+24 -20
View File
@@ -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
+59 -14
View File
@@ -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()
+17 -12
View File
@@ -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
+13 -26
View File
@@ -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
+159
View File
@@ -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