From 3ea59551dbe6a7b1682fd97d7de079e6727f3944 Mon Sep 17 00:00:00 2001 From: chenjw28 <792430652@qq.com> Date: Thu, 27 Aug 2026 14:53:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9D=97=E6=8B=86=E5=88=86=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 17 +- .env.example | 25 +- Dockerfile | 23 +- README.md | 598 +++++++++------ deploy/.env.example | 69 +- deploy/docker-compose.yml | 165 ---- docker-compose.yml | 226 +++--- docs/BACKEND_MODULARIZATION_BLUEPRINT.md | 908 +++++++++++++++++++++++ docs/EVOLUTION_ROADMAP.md | 4 +- docs/STORAGE_SETUP.md | 299 +++----- docs/deployment/DEPLOY_PORT.md | 284 +++---- docs/deployment/LINUX_SETUP.md | 478 +++++++----- docs/deployment/PORT_CONFIG.md | 223 ++++-- docs/deployment/PORT_REFACTOR_SUMMARY.md | 205 +---- start.sh | 66 -- 15 files changed, 2191 insertions(+), 1399 deletions(-) delete mode 100644 deploy/docker-compose.yml create mode 100644 docs/BACKEND_MODULARIZATION_BLUEPRINT.md delete mode 100644 start.sh diff --git a/.env b/.env index 24472c2..593d892 100644 --- a/.env +++ b/.env @@ -3,11 +3,12 @@ HOST=0.0.0.0 # ================================ # 端口配置 - 唯一修改端口的地方 # ================================ -# 应用端口(容器内端口) - +# gemold(moldinsight)API 对外端口 +MOLDINSIGHT_PORT=10003 +# inventory API 对外端口 +INVENTORY_PORT=10004 +# 应用内部监听端口(通常无需修改) PORT=10003 -# Docker映射到宿主机的端口(docker-compose使用) -HOST_PORT=10001 # ================================ @@ -29,7 +30,7 @@ DB_HOST=szcjw DB_PORT=5432 DB_NAME=moldinsight DB_USER=moldinsight -DB_PASSWORD=Qqs1996* +DB_PASSWORD=Qqs1996 # RustFS 对象存储配置 (S3v4 API) RUSTFS_ENDPOINT=http://szcjw:8010 @@ -46,12 +47,12 @@ ACCESS_TOKEN_EXPIRE_MINUTES=1440 # Redis配置 REDIS_HOST=szcjw REDIS_PORT=6379 -REDIS_PASSWORD=Qqs1996* +REDIS_PASSWORD=Qqs1996 REDIS_DB=0 # 管理员配置 ADMIN_USERNAME=cjw -ADMIN_PASSWORD=Qqs1996* +ADMIN_PASSWORD=Qqs1996 ADMIN_EMAIL=792430652@qq.com ADMIN_FULL_NAME=管理员 @@ -60,7 +61,7 @@ ADMIN_FULL_NAME=管理员 # LLM 增强分析配置(可选) # 启用后自动生成模具设计评审报告和分模方向推荐 # 支持 OpenAI 兼容 API(OpenAI / DeepSeek / vLLM / Ollama 等) -LLM_ENABLED=true +LLM_ENABLED=false LLM_API_URL=https://api.deepseek.com/v1 LLM_API_KEY=sk-509f968af3e2466bbef8b5949180782c LLM_MODEL=deepseek-v4-flash diff --git a/.env.example b/.env.example index 86bd386..f5b1f2f 100644 --- a/.env.example +++ b/.env.example @@ -2,13 +2,16 @@ HOST=0.0.0.0 # ================================ -# 端口配置 - 唯一修改端口的地方 +# 模块 API 对外端口 # ================================ -# 应用端口(容器内端口) +# gemold(moldinsight)API 对外端口 +MOLDINSIGHT_PORT=8000 +# inventory API 对外端口 +INVENTORY_PORT=8001 +# ================================ + +# 应用内部监听端口(通常无需修改;compose 内已固定为 8000/8001) PORT=8000 -# Docker映射到宿主机的端口(docker-compose使用) -HOST_PORT=10001 -# ================================ DEBUG=false @@ -28,27 +31,33 @@ POINTCLOUD_SAMPLE_COUNT=10000 MESH_QUALITY=high PARALLEL_PROCESSING=true -# 数据库配置 +# 数据库配置(服务器已部署,请填写真实地址) DB_HOST=localhost DB_PORT=5432 DB_NAME=moldinsight DB_USER=moldinsight_user DB_PASSWORD=moldinsight_password -# RustFS 对象存储配置 (S3v4 API) +# RustFS / MinIO 兼容对象存储配置(服务器已部署,请填写真实地址) RUSTFS_ENDPOINT=http://localhost:9000 RUSTFS_ACCESS_KEY=your-access-key RUSTFS_SECRET_KEY=your-secret-key RUSTFS_TIMEOUT=30 RUSTFS_PRESIGNED_URL_EXPIRES=3600 +# Redis 配置(服务器已部署,请填写真实地址) +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_PASSWORD= +REDIS_DB=0 + # JWT认证配置 SECRET_KEY=your-secret-key-change-in-production-min-32-chars ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=1440 # CORS 白名单(逗号分隔,不设置则默认为 [*],生产环境务必设置) -# CORS_ORIGINS=http://localhost:5173,http://localhost:10001,https://your-domain.com +# CORS_ORIGINS=http://localhost:5173,http://localhost:8000,http://localhost:8001,https://your-domain.com # 管理员账户配置 ADMIN_USERNAME=admin diff --git a/Dockerfile b/Dockerfile index 5e77384..6350274 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,29 +1,28 @@ -# Dockerfile for MoldInsight +# Legacy Dockerfile for geMoldInsight +# +# 说明: +# 该文件保留为历史/兼容用途,仍按旧的单体入口 `src/main.py` 组织。 +# 当前模块化部署的主入口应优先使用: +# - deploy/Dockerfile.moldinsight +# - deploy/Dockerfile.inventory +# - deploy/Dockerfile.celery +# 以及 deploy/docker-compose.yml + FROM continuumio/miniconda3:latest -# 设置工作目录 WORKDIR /app - -# 复制项目文件 COPY . . -# 更新conda并创建环境 RUN conda update -n base -c defaults conda -y && \ conda create -n moldinsight python=3.11 pythonocc-core=7.9.0 -c conda-forge -y -# 激活环境并安装Python依赖 RUN . /opt/conda/etc/profile.d/conda.sh && \ conda activate moldinsight && \ pip install -r requirements.txt -# 创建必要的目录 RUN mkdir -p uploads html_output logs - -# 设置启动脚本 RUN chmod +x start.sh -# 暴露端口 EXPOSE 8000 -# 启动命令(使用shell形式确保环境激活) -CMD ["/bin/bash", "-c", "source /opt/conda/etc/profile.d/conda.sh && conda activate moldinsight && python src/main.py"] \ No newline at end of file +CMD ["/bin/bash", "-c", "source /opt/conda/etc/profile.d/conda.sh && conda activate moldinsight && python src/main.py"] diff --git a/README.md b/README.md index d8ec96b..2520c5e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Gemold - 模具制造管理系统 +# geMoldInsight
@@ -7,319 +7,441 @@ ![FastAPI](https://img.shields.io/badge/fastapi-0.100.0-green) ![Vue.js](https://img.shields.io/badge/vue.js-3-green) ![PostgreSQL](https://img.shields.io/badge/postgresql-15-blue) -![License](https://img.shields.io/badge/license-Mit-green) +![License](https://img.shields.io/badge/license-MIT-green)
-## 项目简介 +geMoldInsight 是一个面向模具制造场景的综合系统,围绕 **STP/STEP 模型分析、模具方案生成、分析结果沉淀、成品创建、BOM/库存/采购/销售闭环** 展开。 -**Gemold** 是一个面向模具制造行业的综合性管理系统,集成了STP文件分析、模具设计建议、用户权限管理和进销存功能。 系统采用现代化的技术栈,提供高效、稳定、易扩展的解决方案。 +当前项目已经从早期单体演进为: -### 核心功能 +- **gemold(moldinsight)模块**:模具分析、几何处理、批量分析、成本估算、结果导出 +- **inventory 模块**:产品、BOM、库存、采购、销售、财务 +- **frontend 模块**:Vue 3 前端工程 +- **shared 平台层**:配置、数据库、认证、日志、应用工厂 -| 功能模块 | 描述 | -|---------|------| -| 🔷 STP文件分析 | 使用PythonOCC解析STP文件,提取几何特征 | -| 📊 模具设计建议 | 自动生成型腔、型芯、工艺参数等设计方案 | -| 🎨 3D可视化 | 实时预览产品模型和模具结构 | -| 👥 用户权限管理 | 完整的角色权限控制系统 | -| 📦 进销存管理 | 库存、供应商、客户管理 | -| 💾 数据持久化 | PostgreSQL + RustFS存储 | +项目当前采用: + +> **单仓库 + 单数据库 + 多模块 + 可独立部署** + +详细重构方向见:[BACKEND_MODULARIZATION_BLUEPRINT.md](docs/BACKEND_MODULARIZATION_BLUEPRINT.md) + +--- + +## 核心能力 + +| 模块 | 能力 | +|---|---| +| gemold | STP/STEP 上传、几何分析、特征识别、模具方案、批量分析、成本估算、结果导出 | +| inventory | 成品/物料、BOM、库存、库存流水、采购订单、销售订单、财务、采购建议 | +| integration | 分析结果一键创建成品,打通“模具分析 → 成品 → BOM → 销售/采购/库存” | +| platform | 用户、角色、权限、JWT 鉴权、数据库连接、日志、健康检查 | --- ## 技术栈 ### 后端 -- **FastAPI** - 笷性能异步Web框架 -- **PythonOCC** - 专业CAD几何处理 -- **SQLAlchemy** - ORM框架 -- **PostgreSQL** - 关系型数据库 -- **RustFS** - 高性能文件存储 +- **FastAPI** +- **SQLAlchemy 2.0** +- **PostgreSQL** +- **Alembic** +- **Redis** +- **Celery** +- **PythonOCC / trimesh / pyvista** +- **RustFS / MinIO 兼容对象存储** ### 前端 -- **Vue.js 3** - 渐进式JavaScript框架 -- **Three.js** - 3D可视化库 -- **原生CSS** - 白色简约现代风格 +- **Vue 3** +- **Vite** +- **TypeScript** +- **Pinia** +- **Vue Router** +- **TDesign Vue Next** ### 基础设施 -- **Docker** - 容器化部署 -- **Systemd** - 服务管理 -- **Conda** - 环境管理 +- **Docker / Docker Compose** +- **结构化日志 / request_id** +- **OpenAPI → TypeScript 类型生成** --- -## 项目结构 +## 当前项目结构 -``` +> 下述结构反映的是**当前代码现状**,不是历史单体结构。 + +```text geMoldInsight/ -├── src/ # 源代码目录 -│ ├── main.py # 主程序入口 -│ ├── api/ # API路由层 -│ │ ├── routes.py # 模具分析API路由聚合 -│ │ ├── auth_routes.py # 认证API -│ │ ├── v1/ # MoldInsight API (v1) -│ │ │ ├── upload_router.py # 文件上传 -│ │ │ ├── task_router.py # 任务状态查询 -│ │ │ └── history_router.py # 分析历史 -│ │ └── inventory/ # 进销存API -│ │ ├── product_routes.py # 产品管理 -│ │ ├── sales_order_routes.py # 销售订单 -│ │ ├── purchase_order_routes.py # 采购订单 -│ │ ├── finance_routes.py # 财务管理 -│ │ ├── material_routes.py # 物料管理 -│ │ └── schemas/ # 请求/响应模型 -│ ├── core/ # 核心业务逻辑 -│ │ ├── stp_parser.py # STP文件解析 -│ │ ├── geometry_analyzer.py # 几何分析 -│ │ ├── mesh_generator.py # 网格生成 -│ │ ├── mold_generator.py # 普通塑料模具生成 -│ │ ├── aluminum_foam_mold.py # 铝泡沫模具生成 -│ │ ├── mold_quality_inspector.py # 模具质量检测 -│ │ └── ai_mold_assistant.py # AI模具助手 -│ ├── models/ # 数据模型 -│ │ ├── database.py # SQLAlchemy ORM模型 -│ │ └── schemas.py # Pydantic模式 -│ ├── services/ # 服务层 -│ │ ├── auth_service.py # 认证服务 -│ │ ├── processing_service.py # STP处理流程编排 -│ │ ├── calculation_service.py # 工程参数计算 -│ │ ├── material_service.py # 材料属性管理 -│ │ ├── task_query_service.py # 任务状态查询 -│ │ ├── storage_integration_rustfs.py # RustFS存储集成 -│ │ ├── redis_task_manager.py # Redis任务管理 -│ │ └── verification_service.py # FreeCAD几何验证 -│ ├── database/ # 数据库管理 -│ │ ├── database.py # 数据库连接池 -│ │ ├── init_db.py # 数据库初始化 -│ │ └── migrate_db.py # 数据库迁移 -│ ├── storage/ # 对象存储 -│ │ ├── rustfs_storage.py # RustFS S3客户端 -│ │ └── object_storage.py # 通用对象存储 -│ └── utils/ # 工具类 -│ ├── logger.py # 日志工具 -│ ├── file_handler.py # 文件处理 -│ └── html_generator.py # 3D可视化HTML生成 -├── static/ # 前端静态资源 -│ ├── vue-app.js # Vue3 SPA应用 -│ ├── style.css # 全局样式 -│ └── index.html # 入口页面 -├── templates/ # Jinja2模板 -├── config/ # 配置模块 -│ └── settings.py # 环境变量配置 -├── scripts/ # 脚本工具 -│ ├── db/ # SQL脚本 -│ ├── migrations/ # 数据迁移脚本 -│ ├── tools/ # 临时检查/清理工具 -│ └── verify_stp.py # STP验证脚本 -├── docs/ # 项目文档 -│ └── deployment/ # 部署相关文档 -├── tests/ # 测试用例 -├── uploads/ # 上传文件目录 (gitignore) -├── html_output/ # 3D可视化输出 (gitignore) -├── requirements.txt # Python依赖 -├── docker-compose.yml # Docker编排配置 -├── Dockerfile # Docker构建文件 -├── start.sh # Linux启动脚本 -├── .env.example # 环境变量模板 -└── .env # 环境变量 (gitignore) +├── 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/ # 镜像构建与部署辅助文件 +│ ├── Dockerfile.base +│ ├── Dockerfile.moldinsight +│ ├── Dockerfile.inventory +│ └── Dockerfile.celery +│ +├── 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。 + +适合: +- 本地开发 +- 集成环境 +- 小团队统一部署 + +### 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.10+ -- PostgreSQL 13+ -- Conda (推荐) +## 1. 环境要求 -### 2. 安装依赖 +- Python 3.12 +- PostgreSQL 15+(服务器已部署或自行提供) +- Redis(服务器已部署或自行提供) +- 对象存储(MinIO / RustFS 兼容;gemold 模块需要,服务器已部署或自行提供) +- Node.js 20+(前端开发需要) +- 推荐使用 `docker-compose.yml` 仅启动项目自身服务,复用服务器已有 PostgreSQL / Redis / 对象存储 + +--- + +## 2. 安装后端依赖 ```bash -# 创建Conda环境 -conda create -n py_3.12 python=3.12 - -# 激活环境 -conda activate py_3.12 - -# 安装依赖 pip install -r requirements.txt ``` -### 3. 配置环境变量 +如果需要几何分析能力,还需确保 PythonOCC 运行环境可用。项目中已说明其通常通过 conda 提供,而不是直接由 pip 安装。 -创建 `.env` 文件: +--- + +## 3. 配置环境变量 + +复制并编辑: + +- [`.env.example`](.env.example) +- 部署场景也可参考 [deploy/.env.example](deploy/.env.example) + +最少需要关注: ```env -# 数据库配置 -DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/gemold - -# 服务配置 -SECRET_KEY=your-secret-key-here +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=admin123 +ADMIN_PASSWORD=change-me + +RUSTFS_ENDPOINT=http://localhost:9000 +RUSTFS_ACCESS_KEY=your-access-key +RUSTFS_SECRET_KEY=your-secret-key ``` -### 4. 初始化数据库 - -```bash -python src/database/init_db.py -``` - -### 5. 启动服务 - -**Linux:** -```bash -chmod +x start.sh -./start.sh -``` - -**Windows:** -```cmd -start.bat -``` - -**Docker:** -```bash -docker-compose up -d -``` - -### 6. 访问服务 - -- 服务地址: http://localhost:8000 -- 默认管理员: admin / admin123 +更多配置项见: +- [settings.py](src/shared/config/settings.py) +- [.env.example](.env.example) --- -## 核心功能详解 +## 4. 初始化数据库 -### STP文件分析 +项目当前使用 Alembic 管理迁移。应用启动时也会执行初始化逻辑,但首次部署建议显式执行迁移流程。 -系统使用PythonOCC解析STP文件,提取以下几何特征: - -| 特征类型 | 描述 | -|---------|------| -| 边界框 | 产品整体尺寸 | -| 体积 | 产品体积计算 | -| 表面积 | 产品表面积计算 | -| 壁厚 | 壁厚分布分析 | -| 加强筋 | 加强筋位置和密度 | -| 孔洞 | 孔洞和凹槽位置 | -| 倒扣 | 倒扣区域检测 | -| 对称性 | 对称性分析 | -| 重心 | 重心位置计算 | - -### 模具设计建议 - -系统自动生成以下设计建议。 - -| 建议类型 | 描述 | -|---------|------| -| 型腔数量 | 单腔或多腔建议 | -| 模架尺寸 | 基于产品尺寸推荐 | -| 顶出系统 | 顶针顶出布局 | -| 冷却水路 | 冷却需求分析 | -| 材料选择 | 基于产量推荐材料 | - -### 3D可视化 - -- **点云模型** - 从STP提取的真实几何形状 -- **模具型腔** - 型腔和型芯可视化 -- **分型面** - 分型面位置显示 -- **交互控制** - 旋转、缩放、平移 - - - **视图切换** - 显示/隐藏各组件 +如需查看初始化实现,可参考: +- [init_db.py](src/shared/database/init_db.py) --- -## API文档 +## 5. 启动方式 -### 认证API +### 方式 A:使用根目录 Compose(推荐) -``` -POST /api/auth/login # 用户登录 -POST /api/auth/logout # 用户登出 -GET /api/auth/me # 获取当前用户信息 +当前唯一 Compose 入口: +- [docker-compose.yml](docker-compose.yml) + +该 compose 文件**只启动项目自身容器**: +- `moldinsight` +- `moldinsight-celery` +- `inventory` + +并通过 `.env` 连接服务器上**已经存在**的: +- PostgreSQL +- Redis +- RustFS / MinIO 兼容对象存储 + +示例: + +```bash +docker compose --profile full up -d ``` -### 文件分析API +可选 profile: +- `full` +- `moldinsight` +- `inventory` -``` -POST /api/upload # 上传STP文件 -POST /api/status/{task_id} # 获取分析状态 -GET /api/history # 获取分析历史 +> 说明:`docker-compose.yml` 不再重复部署 postgres / redis / minio,而是复用服务器现有基础设施。 + +### 方式 B:直接启动后端入口 + +gemold-only: + +```bash +uvicorn src.entrypoints.moldinsight:app --reload --host 0.0.0.0 --port 8000 ``` -### 进销存API +inventory-only: +```bash +uvicorn src.entrypoints.inventory:app --reload --host 0.0.0.0 --port 8001 ``` -GET /api/inventory/dashboard # 仪表盘数据 -GET /api/inventory/products # 产品列表 -POST /api/inventory/products # 创建产品 + +### 方式 C:启动前端 + +```bash +cd frontend +npm install +npm run dev +``` + +生产构建: + +```bash +cd frontend +npm run build ``` --- -## 部署指南 +## 健康检查与接口 -### Systemd服务 (Linux) +### 健康检查 -```bash -# 复制服务文件 -sudo cp gemoldinsight.service /etc/systemd/system/ +两类后端都通过共享 app factory 暴露健康检查: -# 启用服务 -sudo systemctl enable gemoldinsight +- `GET /health` +- `POST /health` -# 启动服务 -sudo systemctl start gemoldinsight -``` +参考实现: +- [app_factory.py](src/shared/app_factory.py) -### Docker部署 +### 认证接口 -```bash -# 构建镜像 -docker build -t gemold:latest . +- `POST /api/auth/login` +- `POST /api/auth/logout` +- `GET /api/auth/me` -# 启动容器 -docker-compose up -d -``` +### 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) --- -## 开发指南 +## 当前架构重点说明 -### 代码风格 -- 遵循PEP 8规范 -- 使用类型注解 -- 保持函数简洁 +### 1. gemold 与 inventory 已基本模块化 -### 提交规范 -- feat: 新功能 -- fix: 修复bug -- docs: 文档更新 -- refactor: 代码重构 -- test: 测试相关 +当前代码层面,`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/) — 现有部署文档(部分仍在对齐中) + +--- + +## 开发建议 + +- 新增业务逻辑优先放入对应业务模块,不要继续堆进 `shared` +- 新增 API 时优先考虑模块归属,而不是“能放就放” +- 前端优先通过域 API client 调用接口,而不是散落裸 `/api/...` 路径 +- 数据模型改动要同时考虑表归属与 Alembic 迁移影响 --- ## 许可证 -本项目采用 MIT 许可证 - 详见 [LICENSE](LICENSE) 文件 - ---- - -## 贡献者 - -感谢所有为这个项目做出贡献的开发者。 - ---- - -## 联系方式 - -- 项目地址: [GitHub](https://github.com/your-org/gemold) -- 问题反馈: [Issues](https://github.com/your-org/gemold/issues) +本项目采用 MIT 许可证,详见 [LICENSE](LICENSE)。 diff --git a/deploy/.env.example b/deploy/.env.example index 424698a..621c668 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -1,23 +1,41 @@ # ============================================ -# 环境变量模板 — 独立部署版 +# 环境变量模板 — 复用服务器已有基础设施 # ============================================ -# 复制为 .env 并修改配置 +# 复制为 .env 并按服务器实际服务地址修改 -# 数据库 -DB_HOST=postgres +# API 对外端口 +MOLDINSIGHT_PORT=8000 +INVENTORY_PORT=8001 + +# 数据库(服务器已部署) +DB_HOST=127.0.0.1 DB_PORT=5432 DB_NAME=moldinsight -DB_USER=moldinsight_user -DB_PASSWORD=moldinsight_password +DB_USER=moldinsight +DB_PASSWORD=change-me -# Redis -REDIS_HOST=redis +# Redis(服务器已部署) +REDIS_HOST=127.0.0.1 REDIS_PORT=6379 REDIS_PASSWORD= +REDIS_DB=0 -# MinIO (RustFS 兼容存储) -MINIO_ACCESS_KEY=minioadmin -MINIO_SECRET_KEY=minioadmin +# RustFS / MinIO 兼容对象存储(服务器已部署) +RUSTFS_ENDPOINT=http://127.0.0.1:9000 +RUSTFS_ACCESS_KEY=change-me +RUSTFS_SECRET_KEY=change-me +RUSTFS_TIMEOUT=30 +RUSTFS_PRESIGNED_URL_EXPIRES=3600 + +# 服务配置 +HOST=0.0.0.0 +DEBUG=false +UPLOAD_DIR=./uploads +MAX_FILE_SIZE=104857600 +ALLOWED_EXTENSIONS=.stp,.step,.stp.gz +POINTCLOUD_SAMPLE_COUNT=10000 +MESH_QUALITY=high +PARALLEL_PROCESSING=true # 认证 SECRET_KEY=your-secret-key-change-in-production-min-32-chars @@ -30,35 +48,14 @@ ADMIN_PASSWORD=change-this-to-a-secure-password ADMIN_EMAIL=admin@gemold.com ADMIN_FULL_NAME=系统管理员 -# 端口 -MOLDINSIGHT_PORT=8000 -INVENTORY_PORT=8001 +# FreeCAD 验证(可选) +ENABLE_FREECAD_VERIFICATION=false +FREECAD_VERIFICATION_TIMEOUT=120 -# 文件上传 -UPLOAD_DIR=./uploads -MAX_FILE_SIZE=104857600 -ALLOWED_EXTENSIONS=.stp,.step,.stp.gz - -# 几何处理 -POINTCLOUD_SAMPLE_COUNT=10000 -MESH_QUALITY=high -PARALLEL_PROCESSING=true - -# RustFS 对象存储 -RUSTFS_ENDPOINT=http://minio:9000 -RUSTFS_ACCESS_KEY=minioadmin -RUSTFS_SECRET_KEY=minioadmin -RUSTFS_TIMEOUT=30 -RUSTFS_PRESIGNED_URL_EXPIRES=3600 - -# LLM (可选) +# LLM(可选) LLM_ENABLED=false LLM_API_URL=https://api.openai.com/v1 LLM_API_KEY=sk-your-api-key LLM_MODEL=gpt-4o-mini LLM_TIMEOUT=60 LLM_MAX_TOKENS=2000 - -# FreeCAD 验证 (可选) -ENABLE_FREECAD_VERIFICATION=false -FREECAD_VERIFICATION_TIMEOUT=120 diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml deleted file mode 100644 index 53de53c..0000000 --- a/deploy/docker-compose.yml +++ /dev/null @@ -1,165 +0,0 @@ -services: - postgres: - image: postgres:15 - container_name: gemold_postgres - environment: - POSTGRES_DB: ${DB_NAME:-moldinsight} - POSTGRES_USER: ${DB_USER:-moldinsight_user} - POSTGRES_PASSWORD: ${DB_PASSWORD:-moldinsight_password} - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-moldinsight_user} -d ${DB_NAME:-moldinsight}"] - interval: 10s - timeout: 5s - retries: 5 - restart: unless-stopped - networks: - - gemold_network - - redis: - image: redis:7-alpine - container_name: gemold_redis - ports: - - "6379:6379" - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - restart: unless-stopped - networks: - - gemold_network - - minio: - image: minio/minio:latest - container_name: gemold_minio - command: server /data --console-address ":9001" - environment: - MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin} - MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin} - ports: - - "9000:9000" - - "9001:9001" - volumes: - - minio_data:/data - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] - interval: 30s - timeout: 20s - retries: 3 - restart: unless-stopped - networks: - - gemold_network - - moldinsight: - build: - context: .. - dockerfile: deploy/Dockerfile.moldinsight - image: gemold-moldinsight:latest - container_name: gemold_moldinsight - ports: - - "${MOLDINSIGHT_PORT:-8000}:8000" - environment: - HOST: 0.0.0.0 - PORT: "8000" - DB_HOST: postgres - DB_PORT: "5432" - DB_NAME: ${DB_NAME:-moldinsight} - DB_USER: ${DB_USER:-moldinsight_user} - DB_PASSWORD: ${DB_PASSWORD:-moldinsight_password} - REDIS_HOST: redis - REDIS_PORT: "6379" - REDIS_PASSWORD: ${REDIS_PASSWORD:-} - RUSTFS_ENDPOINT: http://minio:9000 - RUSTFS_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} - RUSTFS_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} - SECRET_KEY: ${SECRET_KEY:-change-me-in-production} - ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} - ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123} - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - minio: - condition: service_healthy - restart: unless-stopped - profiles: - - full - - moldinsight - networks: - - gemold_network - - moldinsight-celery: - build: - context: .. - dockerfile: deploy/Dockerfile.celery - container_name: gemold_celery - environment: - DB_HOST: postgres - DB_PORT: "5432" - DB_NAME: ${DB_NAME:-moldinsight} - DB_USER: ${DB_USER:-moldinsight_user} - DB_PASSWORD: ${DB_PASSWORD:-moldinsight_password} - REDIS_HOST: redis - REDIS_PORT: "6379" - REDIS_PASSWORD: ${REDIS_PASSWORD:-} - RUSTFS_ENDPOINT: http://minio:9000 - RUSTFS_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} - RUSTFS_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} - RUSTFS_TIMEOUT: ${RUSTFS_TIMEOUT:-30} - depends_on: - - moldinsight - restart: unless-stopped - profiles: - - full - - moldinsight - networks: - - gemold_network - - inventory: - build: - context: .. - dockerfile: deploy/Dockerfile.inventory - image: gemold-inventory:latest - container_name: gemold_inventory - ports: - - "${INVENTORY_PORT:-8001}:8001" - environment: - HOST: 0.0.0.0 - PORT: "8001" - DB_HOST: postgres - DB_PORT: "5432" - DB_NAME: ${DB_NAME:-moldinsight} - DB_USER: ${DB_USER:-moldinsight_user} - DB_PASSWORD: ${DB_PASSWORD:-moldinsight_password} - REDIS_HOST: redis - REDIS_PORT: "6379" - REDIS_PASSWORD: ${REDIS_PASSWORD:-} - SECRET_KEY: ${SECRET_KEY:-change-me-in-production} - ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} - ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123} - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - restart: unless-stopped - profiles: - - full - - inventory - networks: - - gemold_network - -volumes: - postgres_data: - driver: local - minio_data: - driver: local - -networks: - gemold_network: - driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml index a53c38a..a2187d8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,119 +1,137 @@ -# docker-compose.yml - 完整版(包含PostgreSQL和MinIO) services: - postgres: - image: postgres:15 - container_name: moldinsight_postgres - environment: - POSTGRES_DB: ${DB_NAME:-moldinsight} - POSTGRES_USER: ${DB_USER:-moldinsight_user} - POSTGRES_PASSWORD: ${DB_PASSWORD:-moldinsight_password} - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-moldinsight_user} -d ${DB_NAME:-moldinsight}"] - interval: 10s - timeout: 5s - retries: 5 - restart: unless-stopped - networks: - - moldinsight_network - - minio: - image: minio/minio:latest - container_name: moldinsight_minio - command: server /data --console-address ":9001" - environment: - MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin} - MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin} - ports: - - "9000:9000" # API端口 - - "9001:9001" # 控制台端口 - volumes: - - minio_data:/data - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] - interval: 30s - timeout: 20s - retries: 3 - restart: unless-stopped - networks: - - moldinsight_network - moldinsight: - build: . - container_name: moldinsight_app + build: + context: . + dockerfile: deploy/Dockerfile.moldinsight + image: gemold-moldinsight:latest + container_name: gemold_moldinsight ports: - - "${HOST_PORT:-10001}:${CONTAINER_PORT:-8000}" # 宿主机端口:容器端口 - volumes: - - ./uploads:/app/uploads - - ./html_output:/app/html_output - - ./logs:/app/logs - - ./.env:/app/.env:ro + - "${MOLDINSIGHT_PORT:-8000}:8000" environment: - # 应用端口配置(从settings.py读取) - - HOST=${HOST:-0.0.0.0} - - PORT=${CONTAINER_PORT:-8000} - # 数据库配置 - - DB_HOST=postgres - - DB_PORT=5432 - - DB_NAME=${DB_NAME:-moldinsight} - - DB_USER=${DB_USER:-moldinsight_user} - - DB_PASSWORD=${DB_PASSWORD:-moldinsight_password} - # RustFS配置 - - RUSTFS_ENDPOINT=http://minio:9000 - - RUSTFS_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - - RUSTFS_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} - depends_on: - postgres: - condition: service_healthy - minio: - condition: service_healthy + HOST: 0.0.0.0 + PORT: "8000" + DB_HOST: ${DB_HOST} + DB_PORT: ${DB_PORT:-5432} + DB_NAME: ${DB_NAME:-moldinsight} + DB_USER: ${DB_USER} + DB_PASSWORD: ${DB_PASSWORD} + REDIS_HOST: ${REDIS_HOST} + REDIS_PORT: ${REDIS_PORT:-6379} + REDIS_PASSWORD: ${REDIS_PASSWORD:-} + RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT} + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + RUSTFS_TIMEOUT: ${RUSTFS_TIMEOUT:-30} + SECRET_KEY: ${SECRET_KEY:-change-me-in-production} + ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} + ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123} + ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@gemold.com} + ADMIN_FULL_NAME: ${ADMIN_FULL_NAME:-系统管理员} + ALGORITHM: ${ALGORITHM:-HS256} + ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-1440} + DEBUG: ${DEBUG:-false} + UPLOAD_DIR: ${UPLOAD_DIR:-./uploads} + MAX_FILE_SIZE: ${MAX_FILE_SIZE:-104857600} + ALLOWED_EXTENSIONS: ${ALLOWED_EXTENSIONS:-.stp,.step,.stp.gz} + POINTCLOUD_SAMPLE_COUNT: ${POINTCLOUD_SAMPLE_COUNT:-10000} + MESH_QUALITY: ${MESH_QUALITY:-high} + PARALLEL_PROCESSING: ${PARALLEL_PROCESSING:-true} + RUSTFS_PRESIGNED_URL_EXPIRES: ${RUSTFS_PRESIGNED_URL_EXPIRES:-3600} + ENABLE_FREECAD_VERIFICATION: ${ENABLE_FREECAD_VERIFICATION:-false} + FREECAD_VERIFICATION_TIMEOUT: ${FREECAD_VERIFICATION_TIMEOUT:-120} + LLM_ENABLED: ${LLM_ENABLED:-false} + LLM_API_URL: ${LLM_API_URL:-https://api.openai.com/v1} + LLM_API_KEY: ${LLM_API_KEY:-} + LLM_MODEL: ${LLM_MODEL:-gpt-4o-mini} + LLM_TIMEOUT: ${LLM_TIMEOUT:-60} + LLM_MAX_TOKENS: ${LLM_MAX_TOKENS:-2000} restart: unless-stopped - healthcheck: - test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 60s + profiles: + - full + - moldinsight networks: - - moldinsight_network + - gemold_network - celery-worker: - build: . - container_name: moldinsight_celery - command: > - /bin/bash -c "source /opt/conda/etc/profile.d/conda.sh && conda activate moldinsight && cd /app/src && celery -A celery_app worker --concurrency=2 --loglevel=info" - volumes: - - ./uploads:/app/uploads - - ./html_output:/app/html_output - - ./logs:/app/logs - - ./.env:/app/.env:ro + moldinsight-celery: + build: + context: . + dockerfile: deploy/Dockerfile.celery + container_name: gemold_celery environment: - - DB_HOST=postgres - - DB_PORT=5432 - - DB_NAME=${DB_NAME:-moldinsight} - - DB_USER=${DB_USER:-moldinsight_user} - - DB_PASSWORD=${DB_PASSWORD:-moldinsight_password} - - RUSTFS_ENDPOINT=http://minio:9000 - - RUSTFS_ACCESS_KEY=${MINIO_ACCESS_KEY:-minioadmin} - - RUSTFS_SECRET_KEY=${MINIO_SECRET_KEY:-minioadmin} + DB_HOST: ${DB_HOST} + DB_PORT: ${DB_PORT:-5432} + DB_NAME: ${DB_NAME:-moldinsight} + DB_USER: ${DB_USER} + DB_PASSWORD: ${DB_PASSWORD} + REDIS_HOST: ${REDIS_HOST} + REDIS_PORT: ${REDIS_PORT:-6379} + REDIS_PASSWORD: ${REDIS_PASSWORD:-} + RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT} + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + RUSTFS_TIMEOUT: ${RUSTFS_TIMEOUT:-30} + SECRET_KEY: ${SECRET_KEY:-change-me-in-production} + ALGORITHM: ${ALGORITHM:-HS256} + ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-1440} + DEBUG: ${DEBUG:-false} + UPLOAD_DIR: ${UPLOAD_DIR:-./uploads} + MAX_FILE_SIZE: ${MAX_FILE_SIZE:-104857600} + ALLOWED_EXTENSIONS: ${ALLOWED_EXTENSIONS:-.stp,.step,.stp.gz} + POINTCLOUD_SAMPLE_COUNT: ${POINTCLOUD_SAMPLE_COUNT:-10000} + MESH_QUALITY: ${MESH_QUALITY:-high} + PARALLEL_PROCESSING: ${PARALLEL_PROCESSING:-true} + RUSTFS_PRESIGNED_URL_EXPIRES: ${RUSTFS_PRESIGNED_URL_EXPIRES:-3600} + ENABLE_FREECAD_VERIFICATION: ${ENABLE_FREECAD_VERIFICATION:-false} + FREECAD_VERIFICATION_TIMEOUT: ${FREECAD_VERIFICATION_TIMEOUT:-120} + LLM_ENABLED: ${LLM_ENABLED:-false} + LLM_API_URL: ${LLM_API_URL:-https://api.openai.com/v1} + LLM_API_KEY: ${LLM_API_KEY:-} + LLM_MODEL: ${LLM_MODEL:-gpt-4o-mini} + LLM_TIMEOUT: ${LLM_TIMEOUT:-60} + LLM_MAX_TOKENS: ${LLM_MAX_TOKENS:-2000} depends_on: - postgres: - condition: service_healthy - minio: - condition: service_healthy + - moldinsight restart: unless-stopped + profiles: + - full + - moldinsight networks: - - moldinsight_network + - gemold_network -volumes: - postgres_data: - driver: local - minio_data: - driver: local + inventory: + build: + context: . + dockerfile: deploy/Dockerfile.inventory + image: gemold-inventory:latest + container_name: gemold_inventory + ports: + - "${INVENTORY_PORT:-8001}:8001" + environment: + HOST: 0.0.0.0 + PORT: "8001" + DB_HOST: ${DB_HOST} + DB_PORT: ${DB_PORT:-5432} + DB_NAME: ${DB_NAME:-moldinsight} + DB_USER: ${DB_USER} + DB_PASSWORD: ${DB_PASSWORD} + REDIS_HOST: ${REDIS_HOST} + REDIS_PORT: ${REDIS_PORT:-6379} + REDIS_PASSWORD: ${REDIS_PASSWORD:-} + SECRET_KEY: ${SECRET_KEY:-change-me-in-production} + ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} + ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123} + ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@gemold.com} + ADMIN_FULL_NAME: ${ADMIN_FULL_NAME:-系统管理员} + ALGORITHM: ${ALGORITHM:-HS256} + ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-1440} + DEBUG: ${DEBUG:-false} + restart: unless-stopped + profiles: + - full + - inventory + networks: + - gemold_network networks: - moldinsight_network: + gemold_network: driver: bridge diff --git a/docs/BACKEND_MODULARIZATION_BLUEPRINT.md b/docs/BACKEND_MODULARIZATION_BLUEPRINT.md new file mode 100644 index 0000000..d44f59a --- /dev/null +++ b/docs/BACKEND_MODULARIZATION_BLUEPRINT.md @@ -0,0 +1,908 @@ +# geMoldInsight 后端模块化重构蓝图 + +> 目标:在**同一 Git 仓库**、**同一数据库**前提下,将当前代码结构整理为**可独立部署的多模块架构**,明确 gemold、inventory、frontend 的边界与演进路径。本文档是后续实施的权威蓝图,不是历史记录。 + +--- + +## 1. 背景与目标 + +当前项目已经从早期单体演进为“双应用 + 共享层”的形态: + +- 业务模块:`src/moldinsight/`、`src/inventory/` +- 共享层:`src/shared/` +- 部署入口:`src/entrypoints/moldinsight.py`、`src/entrypoints/inventory.py` +- 前端工程:`frontend/` + +从代码现状看,`moldinsight` 与 `inventory` 已基本无直接互引,说明模块边界已经初步形成;但同时,数据库模型、认证、配置、应用工厂等仍集中在 `shared/`,导致当前更接近“**模块化中的单体**”,而不是“**可独立部署的模块化单体**”。 + +本次蓝图的目标不是拆库、拆仓、微服务化,而是: + +1. 保持**单仓库(monorepo)** +2. 保持**单数据库** +3. 将后端正式整理为多个模块: + - **gemold**(模具分析 / moldinsight) + - **inventory**(进销存) + - **identity / platform**(共享基础设施与认证) +4. 保持前端为**独立模块工程**,并增强其对多部署模式的兼容 +5. 支持三种部署模式: + - **unified**:gemold + inventory 同时部署 + - **gemold-only**:仅部署 gemold + - **inventory-only**:仅部署 inventory + +--- + +## 2. 范围与非目标 + +### 2.1 本次蓝图覆盖范围 + +- 后端模块边界 +- 共享层职责重新定义 +- 单数据库下的模型归属与表所有权 +- 独立部署模式设计 +- 前端 API 边界强化策略 +- 分阶段迁移路径 +- 风险与验证方法 + +### 2.2 非目标 + +本蓝图**不包含**以下方向: + +- 多 Git 仓库拆分 +- 多数据库拆分 +- 分布式微服务重构 +- 全量 DDD 重写 +- 全量前端重构 +- 事件驱动或消息总线主导的跨服务通信改造 + +换句话说,目标架构是: + +> **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith** + +而不是微服务系统。 + +--- + +## 3. 当前架构快照 + +### 3.1 后端现状 + +当前核心目录结构如下: + +```text +src/ + entrypoints/ + moldinsight.py + inventory.py + shared/ + app_factory.py + config/ + database/ + models/ + services/ + utils/ + moldinsight/ + api/ + core/ + services/ + storage/ + inventory/ + api/ + schemas/ + services/ +``` + +其中: + +- [app_factory.py](../src/shared/app_factory.py) 已统一 CORS、日志中间件、startup/shutdown、认证路由、健康检查与 SPA fallback。 +- [moldinsight.py](../src/entrypoints/moldinsight.py) 与 [inventory.py](../src/entrypoints/inventory.py) 已提供独立入口。 +- [database.py](../src/shared/models/database.py) 同时包含 identity、moldinsight、inventory 三类模型,是当前最强耦合点。 + +### 3.2 前端现状 + +前端已是独立 Vite/Vue 工程: + +```text +frontend/ + src/ + modules/ + moldinsight/ + inventory/ + login/ + users/ + home/ + router/ + shared/ + stores/ + types/ +``` + +特点: + +- 已按页面/业务模块组织 +- 已有共享 API 层雏形:[api-client.ts](../frontend/src/shared/api-client.ts) +- 已接入 OpenAPI 生成类型:[api.ts](../frontend/src/types/api.ts) +- 当前仍有大量相对路径 `/api/...` 与 raw `fetch()` 的同源假设 + +### 3.3 现状判断 + +当前架构可概括为: + +> **HTTP 入口已分离,业务代码已分组,但平台层与数据层仍共享。** + +因此,它适合继续朝“可独立部署的模块化单体”演进,而不适合直接跳到微服务。 + +--- + +## 4. 目标架构:可独立部署的模块化单体 + +### 4.1 架构原则 + +目标态采用以下原则: + +1. **组合优先于复制**:不同部署模式通过组合不同模块得到,而不是复制多套代码。 +2. **平台与业务分离**:`platform` 只承载技术性共享能力,不继续承载业务逻辑。 +3. **模块所有权清晰**:每张表、每条 API、每个服务类都应有明确归属。 +4. **单数据库但显式边界**:允许共享 DB,但不允许“共享数据库 = 没有边界”。 +5. **统一前端,兼容多后端部署形态**:前端继续是一套工程,通过 API client 适配 unified / split deployment。 + +### 4.2 架构定位 + +目标架构不是“多个服务各自拥有数据库”的微服务,而是: + +- 同一个仓库 +- 同一个数据库 +- 多个模块 +- 多个部署入口 +- 同一套迁移历史 +- 同一套共享基础设施能力 + +这是一种适合当前项目阶段的**治理性重构**,而不是组织级拆分。 + +--- + +## 5. 目标目录结构 + +以下结构是**目标态**,不要求一次性到位: + +```text +src/ + platform/ + app/ + app_factory.py + lifecycle.py + middleware/ + config/ + auth/ + database/ + engine.py + session.py + migrations/ + observability/ + contracts/ + api/ + events/ + shared_kernel/ + types/ + exceptions/ + utils/ + + modules/ + moldinsight/ + application/ + services/ + use_cases/ + domain/ + models/ + policies/ + repositories/ + infrastructure/ + persistence/ + storage/ + adapters/ + interfaces/ + api/ + schemas/ + module.py + + inventory/ + application/ + services/ + use_cases/ + domain/ + models/ + policies/ + repositories/ + infrastructure/ + persistence/ + adapters/ + interfaces/ + api/ + schemas/ + module.py + + identity/ + application/ + domain/ + infrastructure/ + interfaces/ + module.py + + compositions/ + unified_app.py + gemold_app.py + inventory_app.py + + legacy/ + main.py +``` + +### 5.1 当前目录到目标目录的映射 + +| 当前路径 | 目标路径 | 说明 | +|---|---|---| +| `src/shared/*` | `src/platform/*` | 共享基础设施重新命名与归位 | +| `src/moldinsight/*` | `src/modules/moldinsight/*` | gemold 业务模块 | +| `src/inventory/*` | `src/modules/inventory/*` | inventory 业务模块 | +| `src/entrypoints/*` | `src/compositions/*` | 部署组合层 | +| `src/main.py` | `src/legacy/main.py` | 过渡期兼容入口 | + +### 5.2 为什么要引入 `compositions/` + +当前 [entrypoints/](../src/entrypoints/) 已经承担“部署入口”角色,但语义更偏“启动文件”。 + +引入 `compositions/` 的意义是明确: + +- 它不是业务模块 +- 它不是平台能力 +- 它是“**按部署模式装配模块**”的组合层 + +例如: + +- `gemold_app.py`:平台 + identity + moldinsight +- `inventory_app.py`:平台 + identity + inventory +- `unified_app.py`:平台 + identity + moldinsight + inventory + +--- + +## 6. 模块职责边界 + +### 6.1 platform + +`platform` 是技术共享层,只承载**跨模块公共基础设施能力**。 + +#### 归属范围 +- app factory / middleware / 生命周期 +- config +- 数据库 engine / session / Alembic 接线 +- auth / JWT / 权限 +- 日志 / request_id / observability +- 通用 contracts / utilities + +#### 可复用现有实现 +- [app_factory.py](../src/shared/app_factory.py) +- [settings.py](../src/shared/config/settings.py) +- [database.py](../src/shared/database/database.py) +- [auth_service.py](../src/shared/services/auth_service.py) +- [auth_routes.py](../src/shared/services/auth_routes.py) + +#### 规则 +`platform` 不得继续吸收业务规则代码,否则新的 `platform` 会变成旧的 `shared`。 + +--- + +### 6.2 moldinsight(gemold) + +`moldinsight` 模块负责模具分析、几何处理和分析结果生命周期。 + +#### 归属范围 +- 上传、任务、历史、批量分析、成本估算、CAM、分析结果 +- 几何分析、特征检测、模具方案、报告 +- RustFS / 对象存储接入 +- Celery 异步处理链路 + +#### 可复用现有实现 +- [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py) +- [processing_service.py](../src/moldinsight/services/processing_service.py) +- [task_query_service.py](../src/moldinsight/services/task_query_service.py) +- [moldinsight/core/](../src/moldinsight/core/) +- [celery_app.py](../src/celery_app.py) +- [celery_tasks.py](../src/celery_tasks.py) + +--- + +### 6.3 inventory + +`inventory` 模块负责 ERP / 进销存类业务流程。 + +#### 归属范围 +- 产品、物料、供应商、客户、仓库 +- 库存、库存流水 +- 销售订单、采购订单、财务、采购建议 +- BOM / 采购需求推导 + +#### 可复用现有实现 +- [inventory/api/__init__.py](../src/inventory/api/__init__.py) +- [inventory_service.py](../src/inventory/services/inventory_service.py) +- [sales_order_service.py](../src/inventory/services/sales_order_service.py) +- [purchase_order_service.py](../src/inventory/services/purchase_order_service.py) +- [finance_service.py](../src/inventory/services/finance_service.py) + +--- + +### 6.4 identity + +`identity` 负责用户、角色、权限与认证授权。 + +#### 归属范围 +- User / Role / Permission +- 登录、鉴权、管理员接口 +- 统一授权能力 + +在物理目录上,identity 可以先靠近 platform;但逻辑上应从一开始就被视为独立边界,而不是“moldinsight 的一部分”或“inventory 的一部分”。 + +--- + +## 7. 允许的依赖方向 + +这是本蓝图最重要的治理规则之一。 + +### 7.1 依赖规则 + +```text +compositions -> platform +compositions -> modules/* + +platform -> 不依赖业务模块 + +modules/*/interfaces -> modules/*/application +modules/*/application -> modules/*/domain +modules/*/infrastructure -> modules/*/domain + +modules/*/interfaces -> platform +modules/*/infrastructure -> platform +``` + +### 7.2 跨模块约束 + +- `inventory` 不能直接 import `moldinsight.api` / `moldinsight.services` +- `moldinsight` 不能直接 import `inventory.api` / `inventory.services` +- `platform` 不得依赖任一业务模块 +- 跨模块协作只能通过: + - 显式 contract / query service + - composition wiring + - 受控的共享数据库引用 + +### 7.3 当前代码与规则的差距 + +从代码检查看,当前 `moldinsight` 与 `inventory` 基本没有直接互引,这说明上述规则在业务代码层**已经接近成立**。 + +当前主要问题集中在: + +- [database.py](../src/shared/models/database.py) 集中承载所有 ORM 模型 +- [app_factory.py](../src/shared/app_factory.py) 同时知道通用平台逻辑与 moldinsight 专属 startup 行为 + +因此,后续实施的重点不是“切断业务模块互引”,而是“**把共享层与数据层的边界拉直**”。 + +--- + +## 8. 单数据库下的模型与表归属策略 + +### 8.1 核心原则 + +数据库继续保持为**一个 PostgreSQL 数据库**,但代码中的模型归属必须显式化。 + +也就是说: + +> **数据库不拆,模型归属要拆。** + +### 8.2 当前最强耦合点 + +当前 [database.py](../src/shared/models/database.py) 同时包含: + +- identity / 平台相关模型 +- moldinsight 业务模型 +- inventory 业务模型 + +这会带来两个问题: + +1. 代码层看不出模型所有权 +2. 开发者更容易跨模块直接访问整套 ORM 图谱 + +因此,后续实施应优先将这个文件按归属拆分。 + +### 8.3 推荐表归属矩阵 + +#### platform / identity-owned +- users +- roles +- permissions +- user_roles +- role_permissions +- (可选)system_logs + +#### moldinsight-owned +- stp_files +- geometry_data +- mesh_data +- html_files +- processing_tasks +- mold_cavity_data +- feature_detections +- design_recommendations +- analysis_metrics + +#### inventory-owned +- products +- product_materials +- material_price_history +- material_suppliers +- suppliers +- customers +- warehouses +- inventory +- stock_movements +- purchase_orders +- purchase_order_items +- sales_orders +- sales_order_items +- finance_transactions +- finance_allocations + +### 8.4 目标代码形态 + +推荐逐步演进到: + +```text +platform/database/base.py +modules/identity/infrastructure/persistence/models.py +modules/moldinsight/infrastructure/persistence/models.py +modules/inventory/infrastructure/persistence/models.py +``` + +同时保持: + +- 同一个 SQLAlchemy `Base` +- 同一个 metadata +- 同一条 Alembic 历史链 +- 同一个数据库连接 + +### 8.5 跨模块 FK 的处理策略 + +当前存在真实跨模块业务桥: + +- `STPFile.product_id -> Product.id` + +这是合理的,因为它反映了真实业务关系:模具分析结果可以创建成品,并与 inventory 中的产品建立连接。 + +原则上允许保留这类稳定 FK,但应遵守: + +1. 跨模块 FK 是**业务桥**,不是“任意跨模块查询”的许可 +2. 模块之间应逐步通过 query service / repository contract 暴露需要的读取能力 +3. 避免一个模块直接依赖另一个模块的整套 ORM 图谱 + +--- + +## 9. 部署模式设计 + +本项目必须支持三种部署模式。 + +### 9.1 unified + +#### 组成 +- platform + identity + moldinsight + inventory + +#### 适用场景 +- 本地开发 +- 小团队部署 +- 集成环境 +- 一体化业务场景 + +#### 说明 +新的 unified 组合层应接替旧 [main.py](../src/main.py) 的语义,但应通过 `compositions/unified_app.py` 的方式实现,而不是继续维持旧单体式入口。 + +--- + +### 9.2 gemold-only + +#### 组成 +- platform + identity + moldinsight + +#### 适用场景 +- 仅开放模具分析能力 +- 分析服务独立扩容 +- 单独部署算法/文件处理能力 + +#### 说明 +- 只暴露 gemold 路由 +- 可保留对共享数据库中 `products` 的受控引用 +- RustFS / Celery 等专属基础设施只在该模式启用 + +当前入口基线: +- [moldinsight.py](../src/entrypoints/moldinsight.py) + +--- + +### 9.3 inventory-only + +#### 组成 +- platform + identity + inventory + +#### 适用场景 +- 仅提供 ERP / 进销存能力 +- 不需要模具分析链路的后台场景 + +#### 说明 +- 只暴露 inventory 路由 +- 不要求启动 RustFS 等 moldinsight 专属基础设施 + +当前入口基线: +- [inventory.py](../src/entrypoints/inventory.py) + +--- + +### 9.4 当前共享工厂的边界问题 + +需要特别指出:当前 [app_factory.py](../src/shared/app_factory.py) 通过 `mount_html=True` 分支初始化 RustFS,这说明共享工厂仍然知道 moldinsight 模块专属基础设施。 + +这意味着: + +- `shared` / `platform` 还不够纯 +- 模块专属 startup hook 还没有完全从平台层剥离 + +后续实施时,这应是**优先解决的问题之一**: + +> app factory 只负责通用平台装配;模块专属生命周期应由 module hook 或 composition layer 决定。 + +--- + +## 10. 前端 API 边界策略 + +### 10.1 设计原则 + +前端已经是独立工程,不需要再拆目录或拆仓。后续重点应放在: + +- 强化域 API 边界 +- 消除对单一同源 `/api/...` 的强依赖 +- 兼容 unified / split deployment + +### 10.2 当前可复用基础 + +当前前端已经具备良好基础: + +- 域客户端入口:[api-client.ts](../frontend/src/shared/api-client.ts) +- 生成类型:[api.ts](../frontend/src/types/api.ts) +- 模块目录:[frontend/src/modules/moldinsight/](../frontend/src/modules/moldinsight/) 与 [frontend/src/modules/inventory/](../frontend/src/modules/inventory/) + +因此,后续策略应是“**边界强化**”,不是“前端重写”。 + +### 10.3 建议的客户端边界 + +应继续收敛为: + +- `authApi` +- `moldinsightApi` +- `inventoryApi` + +并要求: + +- 页面/组件尽量不直接写裸 `/api/...` 字符串 +- multipart upload / download / export 也尽量通过域客户端封装 +- 统一利用 OpenAPI 生成类型,而不是额外维护平行手写类型 + +### 10.4 支持两类部署配置 + +#### unified 模式 +- `VITE_API_BASE_URL` + +#### split 模式 +- `VITE_AUTH_API_BASE_URL` +- `VITE_MOLDINSIGHT_API_BASE_URL` +- `VITE_INVENTORY_API_BASE_URL` + +客户端实现上应支持: + +- unified 下三个 client 指向同一个 base URL +- split 下各 client 指向不同服务 + +### 10.5 capability-aware UI + +在 gemold-only 或 inventory-only 部署模式下,前端不应假设所有模块总是存在。 + +因此建议: + +- 后端通过 `/health` 或单独 capability endpoint 暴露已启用模块信息 +- 前端根据 capability 隐藏未部署模块入口或禁用对应页面 + +这样可避免“前端路由还在,但后端根本没部署”的硬失败场景。 + +--- + +## 11. 分阶段迁移计划 + +### Phase 0:蓝图冻结 + +目标:冻结目标结构与边界规则,防止迁移过程中继续长出新的耦合。 + +动作: +- 确认模块边界 +- 确认依赖规则 +- 确认三种部署模式 +- 确认 shared/platform 的使用边界 + +--- + +### Phase 1:组合层标准化 + +目标:将部署模式从“若干入口脚本”升级为“正式的 composition layer”。 + +动作: +- 将 `entrypoints/*` 升级为 `compositions/*` +- 定义 `unified_app.py` / `gemold_app.py` / `inventory_app.py` +- 将 module-specific startup hooks 从通用 app factory 中迁出 + +重点问题: +- 当前 `mount_html -> RustFS connect` 属于模块专属逻辑,必须从 shared factory 中剥离 + +--- + +### Phase 2:platform 与业务代码分治 + +目标:把“共享基础设施”从“共享杂项”中真正分离出来。 + +动作: +- 从 `shared` 语义切换到更清晰的 `platform` +- 归位 config / auth / db / observability / utils +- 禁止新业务逻辑继续沉积到 `shared` + +--- + +### Phase 3:ORM 按归属拆分 + +目标:解决当前最大的代码耦合源。 + +动作: +- 拆分 [database.py](../src/shared/models/database.py) +- 保持单 Base / 单 Alembic / 单 DB +- 先完成代码层归属拆分,再处理更深层的业务隔离 + +这是整个重构中最关键的一步。 + +--- + +### Phase 4:模块内部继续分层 + +目标:让每个模块内部的“路由 / 服务 / 领域 / 基础设施”边界更清晰。 + +动作: +- inventory:从现有 service 层继续向 `application / domain / infrastructure / interfaces` 拉开 +- moldinsight:逐步理顺 `api / services / core / storage` 的边界 + +原则: +- 不要求一步完成 DDD 化 +- 先把层次职责清楚,再考虑更纯粹的领域对象抽象 + +--- + +### Phase 5:建立跨模块集成规则 + +目标:把当前 ad hoc 跨表访问逐步收敛成显式桥接能力。 + +动作: +- 定义跨模块 query services / repository contracts +- 明确“从分析创建成品”等桥接能力的正式入口 +- 收敛直接穿透跨模块 ORM 图谱的做法 + +重点桥接场景: +- `STPFile.product_id` +- [product_routes.py](../src/inventory/api/product_routes.py) 中的“按 task 创建产品”逻辑 + +--- + +### Phase 6:前端边界加固 + +目标:让前端真正适配 unified / split deployment。 + +动作: +- 强制域 API client 收口 +- 支持 per-module base URL +- 支持 capability-aware UI +- 减少页面中裸 `fetch('/api/...')` + +--- + +### Phase 7:部署与文档收尾 + +目标:使架构蓝图与部署事实一致。 + +动作: +- 固化 unified / gemold-only / inventory-only 部署说明 +- 更新 README / deployment docs / frontend docs +- 明确旧入口、旧 Dockerfile、旧部署说明的地位(兼容 / 历史 / 废弃) + +--- + +## 12. 风险与缓解措施 + +### 风险 1:共享模型文件继续隐藏领域归属 + +**现象**:所有模型集中在 [database.py](../src/shared/models/database.py) + +**风险**:边界无法落实,任何模块都能自然跨领域访问 + +**缓解**: +- 先产出表归属矩阵 +- 再拆 ORM 文件 +- 拆归属优先于改业务逻辑 + +--- + +### 风险 2:`shared` 继续变成杂物间 + +**风险**:shared/platform 成为“不知道放哪就放这里”的位置 + +**缓解**: +- 以 `platform` 重新定义共享层 +- 明确只有技术性共享能力可进入 platform +- 代码 review 中禁止新增业务逻辑进入 platform + +--- + +### 风险 3:模块专属启动逻辑继续留在 app factory + +**现象**:当前 `mount_html` 分支控制 RustFS 连接 + +**风险**:平台层继续了解业务模块内部基础设施 + +**缓解**: +- module lifecycle hook +- composition 层控制模块 startup/shutdown +- 通用 app factory 保持纯平台化 + +--- + +### 风险 4:独立部署后,前端仍假设所有模块存在 + +**风险**:前端路由可见,但后端未部署,造成运行时错误 + +**缓解**: +- capability metadata +- feature gating +- 前端按模块部署形态动态隐藏入口 + +--- + +### 风险 5:单数据库导致开发者随意跨模块查表 + +**风险**:虽然数据库未拆,但代码边界被绕开 + +**缓解**: +- 表归属规则文档化 +- code review 要求说明跨模块访问理由 +- 逐步通过 query services 收口 + +--- + +### 风险 6:大爆炸式目录迁移导致 import churn + +**风险**:一次性移动所有目录,修改面过大,回归成本高 + +**缓解**: +- 分阶段迁移 +- 保留兼容 import 过渡层 +- 先稳定组合层与模型层,再做深层目录调整 + +--- + +## 13. 验证清单 + +### 13.1 结构验证 + +- `platform` 不 import 业务模块 +- `moldinsight` / `inventory` 无直接 api/services 互引 +- ORM 文件已按归属拆分,或至少表归属矩阵已文档化并被遵守 + +### 13.2 运行验证 + +#### unified +- 两类路由都能正常挂载 +- 统一 health / auth / request-id 机制生效 + +#### gemold-only +- inventory 路由未挂载 +- gemold 路由可用 +- RustFS / Celery 等专属依赖正常初始化 + +#### inventory-only +- moldinsight 路由未挂载 +- inventory 路由可用 +- 不依赖 moldinsight 专属基础设施即可启动 + +### 13.3 数据验证 + +- 三种部署模式使用同一 migration head +- 单数据库中的跨模块 FK 保持有效 +- Alembic 无分叉历史 + +### 13.4 前端验证 + +- unified 模式下,一个 base URL 即可跑通 +- split 模式下,各模块 base URL 可独立配置 +- 未部署模块能被隐藏或优雅失败 + +--- + +## 14. 文档联动更新计划 + +本蓝图批准后,以下文档应逐步对齐: + +- [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md) +- [LINUX_SETUP.md](./deployment/LINUX_SETUP.md) +- [DEPLOY_PORT.md](./deployment/DEPLOY_PORT.md) +- [PORT_CONFIG.md](./deployment/PORT_CONFIG.md) +- [PORT_REFACTOR_SUMMARY.md](./deployment/PORT_REFACTOR_SUMMARY.md) +- `README.md` +- `frontend/README.md` + +其中需要特别注意: + +- `README.md` 当前仍主要描述旧单体结构,与当前实际代码已有明显漂移。 +- 本文档应作为“当前目标架构”的权威蓝图,路线图与部署文档随后对齐。 + +--- + +## 15. 附录:实施热点文件 + +以下文件是后续实际重构时最关键的热点: + +### 平台与组合层 +- [app_factory.py](../src/shared/app_factory.py) +- [settings.py](../src/shared/config/settings.py) +- [database.py](../src/shared/database/database.py) +- [init_db.py](../src/shared/database/init_db.py) +- [moldinsight.py](../src/entrypoints/moldinsight.py) +- [inventory.py](../src/entrypoints/inventory.py) +- [main.py](../src/main.py) + +### 模型与边界 +- [database.py](../src/shared/models/database.py) +- [product_routes.py](../src/inventory/api/product_routes.py) + +### gemold 模块 +- [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py) +- [processing_service.py](../src/moldinsight/services/processing_service.py) +- [task_query_service.py](../src/moldinsight/services/task_query_service.py) + +### inventory 模块 +- [inventory/api/__init__.py](../src/inventory/api/__init__.py) +- [inventory_service.py](../src/inventory/services/inventory_service.py) +- [sales_order_service.py](../src/inventory/services/sales_order_service.py) +- [purchase_order_service.py](../src/inventory/services/purchase_order_service.py) +- [finance_service.py](../src/inventory/services/finance_service.py) + +### 前端边界 +- [api-client.ts](../frontend/src/shared/api-client.ts) +- [api.ts](../frontend/src/types/api.ts) + +### 演进与部署参考 +- [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md) +- [docker-compose.yml](../docker-compose.yml) + +--- + +## 16. 最终结论 + +本项目当前最适合的演进路径不是微服务,而是: + +> **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith** + +它既能保留当前业务闭环(模具分析 → 成品 → BOM → 销售/采购/库存),又能逐步降低共享层和模型层的结构耦合。 + +后续实施时,应优先按以下顺序推进: + +1. 固化组合层(deployment composition) +2. 纯化 platform/shared 边界 +3. 拆分共享 ORM 文件 +4. 再继续模块内部细分层次 +5. 最后收口前端 API 与部署文档 + +这条路径风险最低、收益最大,也最符合当前代码现状与团队演进成本。 \ No newline at end of file diff --git a/docs/EVOLUTION_ROADMAP.md b/docs/EVOLUTION_ROADMAP.md index 1bbfbaa..a7cf3ca 100644 --- a/docs/EVOLUTION_ROADMAP.md +++ b/docs/EVOLUTION_ROADMAP.md @@ -18,7 +18,7 @@ ### P0-1 Celery worker 不连 Redis/RustFS,异步任务全坏 - **现象**:任务进度写进 Celery 私有内存,web 端永远读不到;首次上传 RustFS 直接抛 `RuntimeError("RustFS 未连接")`。 -- **证据**:`redis_task_manager.connect()` / `rustfs_manager.connect()` 只在 FastAPI startup 调用(`entrypoints/moldinsight.py:42,48`),Celery 进程不跑 startup;`processing_service.py` 在 celery 内调 `update_task` 时 `is_connected=False` 走 `_fallback_set`;`rustfs_storage.py:125-126` 未连接直接抛错。`deploy/docker-compose.yml` 的 `moldinsight-celery` 服务块缺 `REDIS_PASSWORD`。 +- **证据**:`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 中能看到对象。 - **状态**:- [ ] @@ -70,7 +70,7 @@ ### P0 执行结果(2026-07-13) -- ✅ **P0-1 Celery 连接**:`celery_tasks.py` 在任务内显式 `redis_task_manager.reconnect()` + `rustfs_manager.connect()`(Redis 客户端绑定事件循环,每任务 reconnect;RustFS 同步客户端连一次复用);`deploy/docker-compose.yml` celery 服务补 `REDIS_PASSWORD`/`RUSTFS_TIMEOUT` +- ✅ **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 diff --git a/docs/STORAGE_SETUP.md b/docs/STORAGE_SETUP.md index c45a87f..18d1535 100644 --- a/docs/STORAGE_SETUP.md +++ b/docs/STORAGE_SETUP.md @@ -1,255 +1,154 @@ # 存储架构说明 +> 本文档主要解释 geMoldInsight 的存储分层与数据流。其历史中的“本项目自行拉起 PostgreSQL / MinIO 并通过 `python src/main.py` 启动单体”的部分,**已不再代表当前默认部署方式**。 + +当前默认部署前提是: + +- PostgreSQL 由服务器已有服务提供 +- Redis 由服务器已有服务提供 +- RustFS / MinIO 兼容对象存储由服务器已有服务提供 +- 项目自身只部署:`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) + +--- + ## 架构概述 -本项目采用 **RustFS (S3兼容)** 作为对象存储和 **PostgreSQL** 作为元数据存储的双层存储架构。 +本项目采用 **RustFS(S3兼容)对象存储** + **PostgreSQL 元数据存储** 的双层存储架构。 -``` +```text ┌─────────────────────────────────────────────────────────────┐ -│ 应用层 (FastAPI) │ +│ 应用层 (gemold / inventory) │ └──────────────────────┬──────────────────────────────────────┘ │ ┌──────────────┴──────────────┐ │ │ ┌───────▼────────┐ ┌─────────▼─────────┐ -│ PostgreSQL │ │ RustFS/S3 │ +│ PostgreSQL │ │ RustFS / S3 │ │ (元数据) │ │ (对象存储) │ │ │ │ │ │ - users │ │ - stp-files │ │ - stp_files │ │ - geometry │ │ - geometry_data│ │ - mold-cavities │ -│ - mold_cavity │ │ - html-files │ -│ - features │ │ - user-files │ -│ - logs │ │ │ +│ - processing │ │ - html-files │ +│ - logs │ │ - user-files │ └────────────────┘ └──────────────────┘ ``` -## PostgreSQL 数据表 +--- + +## PostgreSQL 数据表(摘要) ### 用户管理 -- `users` - 用户信息(用户名、邮箱、密码等) +- `users` - 用户信息 +- `roles` / `permissions` - 权限体系 -### 文件管理 -- `stp_files` - STP文件元数据(文件名、哈希、大小、状态等) -- `html_files` - HTML报告文件元数据 - -### 几何数据 -- `geometry_data` - 几何分析数据(体积、表面积、边界框等) -- `mold_cavity_data` - 模具型腔数据(工艺参数、质量评估等) -- `feature_detections` - 特征检测结果(壁厚、拔模角等) -- `design_recommendations` - 设计建议(优先级、参数等) - -### 任务和日志 +### gemold 相关 +- `stp_files` - STP 文件元数据 +- `html_files` - HTML 报告元数据 +- `geometry_data` - 几何分析数据 +- `mold_cavity_data` - 模具型腔数据 +- `feature_detections` - 特征检测结果 +- `design_recommendations` - 设计建议 - `processing_tasks` - 处理任务记录 -- `user_activities` - 用户活动日志 -- `system_logs` - 系统日志 +- `analysis_metrics` - 分析指标 -## RustFS 存储桶 +### inventory 相关 +- `products` - 产品/物料 +- `product_materials` - BOM +- `inventory` - 库存 +- `stock_movements` - 库存流水 +- `purchase_orders` / `sales_orders` - 订单 +- `finance_transactions` - 财务流水 + +--- + +## RustFS / S3 存储桶 | 存储桶名称 | 用途 | 存储内容 | -|-------------|------|---------| -| `moldinsight-stp-files` | STP/STEP文件 | 用户上传的原始3D模型文件 | -| `moldinsight-geometry` | 几何数据 | 几何分析结果的JSON数据 | -| `moldinsight-mold-cavities` | 模具型腔数据 | 模具设计的详细JSON数据 | -| `moldinsight-html` | HTML文件 | 生成的HTML报告文件 | -| `moldinsight-user-files` | 用户文件 | 其他用户上传的文件 | +|---|---|---| +| `moldinsight-stp-files` | STP/STEP 文件 | 用户上传的原始 3D 模型 | +| `moldinsight-geometry` | 几何结果 | 几何分析 JSON | +| `moldinsight-mold-cavities` | 模具结果 | 模具设计 JSON | +| `moldinsight-html` | HTML 报告 | 生成的 HTML 报告文件 | +| `moldinsight-user-files` | 用户文件 | 其他附件/用户文件 | -## 快速开始 +--- -### 1. 安装依赖 +## 当前推荐初始化方式 + +### 1. 准备环境变量 ```bash -pip install -r requirements.txt -``` - -### 2. 启动 PostgreSQL - -使用 Docker Compose(推荐): -```bash -docker-compose up -d postgres -``` - -或手动启动: -```bash -# 创建数据库 -createdb moldinsight - -# 运行数据库容器 -docker run -d \ - --name postgres \ - -e POSTGRES_DB=moldinsight \ - -e POSTGRES_USER=moldinsight_user \ - -e POSTGRES_PASSWORD=your_password \ - -p 5432:5432 \ - postgres:15 -``` - -### 3. 启动 MinIO - -使用 Docker Compose(推荐): -```bash -docker-compose up -d minio -``` - -或手动启动: -```bash -docker run -d \ - --name minio \ - -p 9000:9000 \ - -p 9001:9001 \ - -e MINIO_ROOT_USER=minioadmin \ - -e MINIO_ROOT_PASSWORD=minioadmin \ - minio/minio server /data --console-address ":9001" -``` - -### 4. 配置环境变量 - -```bash -# 复制示例配置 cp .env.example .env - -# 编辑 .env 文件,修改数据库和MinIO配置 nano .env ``` -### 5. 初始化数据库和存储 +确保以下变量指向**服务器上已存在的真实服务**: -```bash -# 初始化数据库 -python src/database/init_db.py +```env +DB_HOST=your-db-host +DB_PORT=5432 +DB_NAME=moldinsight +DB_USER=moldinsight +DB_PASSWORD=change-me -# 初始化MinIO存储 -python src/storage/init_storage.py +REDIS_HOST=your-redis-host +REDIS_PORT=6379 +REDIS_PASSWORD= + +RUSTFS_ENDPOINT=http://your-storage-host:9000 +RUSTFS_ACCESS_KEY=change-me +RUSTFS_SECRET_KEY=change-me ``` -### 6. 启动服务 +### 2. 初始化数据库 -```bash -python src/main.py -``` +当前初始化入口参考: +- [init_db.py](../src/shared/database/init_db.py) -## 使用示例 +### 3. 启动项目服务 -### 保存STP文件 +当前推荐通过: +- [docker-compose.yml](../docker-compose.yml) +- 或 [src/entrypoints/](../src/entrypoints/) -```python -from services.storage_integration import storage_integration -from database.database import db_manager +而不是继续使用历史单体 `python src/main.py` 作为默认方式。 -async def upload_file(file_path: str): - async with db_manager.get_session() as session: - stp_file = await storage_integration.save_stp_file( - session=session, - file_path=Path(file_path), - original_filename="model.stp", - user_id=1 - ) - print(f"文件已保存,ID: {stp_file.id}") -``` +--- -### 保存几何数据 +## 监控与维护 -```python -async def save_geometry(stp_file_id: int, geometry_data: dict): - async with db_manager.get_session() as session: - geo_data = await storage_integration.save_geometry_data( - session=session, - stp_file_id=stp_file_id, - geometry_json=geometry_data, - analysis_method="pythonocc" - ) - print(f"几何数据已保存,ID: {geo_data.id}") -``` - -### 获取文件数据 - -```python -async def get_file_data(stp_file_id: int): - async with db_manager.get_session() as session: - data = await storage_integration.get_stp_file_with_data( - session=session, - stp_file_id=stp_file_id - ) - - # 访问几何数据 - geometry = data['geometry_data'] - print(f"体积: {geometry['volume']}") - print(f"表面积: {geometry['surface_area']}") - - # 访问模具型腔数据 - cavity = data['mold_cavity_data'] - print(f"模具材料: {cavity['mold_material']}") - - # 访问特征和建议 - for feature in data['features']: - print(f"特征: {feature['feature_type']}") -``` - -## 数据清理策略 - -### MinIO 对象存储 -- 设置生命周期策略自动删除旧文件 -- 示例:删除30天前的临时文件 +### 对象存储 +- 检查对象存储服务可达性 +- 定期清理历史产物 +- 配置生命周期策略 ### PostgreSQL -- 定期清理已删除用户的记录 -- 归档超过6个月的日志数据 +- 定期备份 +- 监控连接池与慢查询 +- 保持 Alembic 迁移链一致 -## 监控和维护 - -### 检查存储使用情况 -```bash -# MinIO控制台 -# http://localhost:9001 -# 用户名: minioadmin -# 密码: minioadmin -``` - -### 数据库备份 -```bash -# 备份数据库 -pg_dump -h localhost -U moldinsight_user moldinsight > backup.sql - -# 恢复数据库 -psql -h localhost -U moldinsight_user moldinsight < backup.sql -``` - -## 性能优化 - -### PostgreSQL -- 创建适当的索引(已在模型中定义) -- 定期运行 VACUUM 和 ANALYZE -- 考虑使用连接池(已配置) - -### MinIO -- 启用缓存层 -- 配置CDN分发静态文件 -- 使用多区域复制 - -## 安全建议 - -1. **更改默认密码**:生产环境必须更改所有默认密码 -2. **启用TLS**:生产环境启用 HTTPS -3. **访问控制**:配置适当的用户权限 -4. **数据加密**:敏感数据加密存储 -5. **定期备份**:设置自动备份策略 +--- ## 故障排除 -### 连接MinIO失败 -``` -错误: 对象存储连接失败 -解决: 检查 MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY 配置 -``` +### 对象存储连接失败 +- 检查 `RUSTFS_ENDPOINT` +- 检查 access key / secret key +- 检查服务端口与网络策略 ### 数据库连接失败 -``` -错误: 数据库连接失败 -解决: 检查 DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD 配置 -``` +- 检查 `DB_HOST` / `DB_PORT` +- 检查数据库账号密码 +- 检查防火墙与白名单 ### 文件上传失败 -``` -错误: STP文件上传失败 -解决: 检查磁盘空间、网络连接、MinIO权限 -``` +- 检查对象存储可用性 +- 检查 Celery worker 是否运行 +- 检查 Redis 是否可达 diff --git a/docs/deployment/DEPLOY_PORT.md b/docs/deployment/DEPLOY_PORT.md index 7555407..37dea57 100644 --- a/docs/deployment/DEPLOY_PORT.md +++ b/docs/deployment/DEPLOY_PORT.md @@ -1,170 +1,204 @@ -# 部署时端口配置说明 +# 模块化部署端口说明 -## 生产环境部署端口配置 +> 本文档描述的是 **当前模块化部署模式** 下的端口规划,不再以历史单体 `src.main:app` 作为默认前提。 -本项目现在使用统一的端口配置文件 `.env`,部署时需要相应调整配置。 +当前推荐部署对象: -### Gunicorn 启动配置 +- gemold API +- gemold Celery worker(无 HTTP 端口) +- inventory API -**推荐方式(使用 .env 配置):** +以下基础设施默认由服务器现有服务提供,不在本项目 compose 中重复部署: + +- PostgreSQL +- Redis +- MinIO / RustFS(gemold 需要) + +--- + +## 1. 推荐端口规划 + +| 组件 | 默认端口 | 说明 | +|---|---:|---| +| gemold API | 8000 | 模具分析后端 | +| inventory API | 8001 | 进销存后端 | +| PostgreSQL | 5432 | 共享数据库 | +| Redis | 6379 | 共享队列/缓存 | +| MinIO API | 9000 | 对象存储接口 | +| MinIO Console | 9001 | 对象存储控制台 | + +> Celery worker 不直接暴露 HTTP 端口。 + +--- + +## 2. 三种部署模式下的端口 + +### 2.1 gemold-only + +- 对外开放:`8000` +- 依赖:PostgreSQL、Redis、MinIO/RustFS +- 可选:前置 Nginx 暴露 80/443 + +### 2.2 inventory-only + +- 对外开放:`8001` +- 依赖:PostgreSQL、Redis +- 不要求对象存储 + +### 2.3 unified + +两种常见实现: + +1. **统一网关模式** + - 外部只开放 80/443 + - 网关转发到 gemold / inventory +2. **统一应用组合模式** + - 统一后端监听单一端口 + - 后续组合层重构完成后更适合采用 + +当前阶段,如果需要统一对外,更推荐**网关统一**而不是继续依赖历史单体入口。 + +--- + +## 3. Docker Compose 端口来源 + +当前主部署文件: +- [docker-compose.yml](../../docker-compose.yml) + +关键端口映射: + +- `MOLDINSIGHT_PORT` → gemold API 外部端口 +- `INVENTORY_PORT` → inventory API 外部端口 + +示例: + +```env +MOLDINSIGHT_PORT=8000 +INVENTORY_PORT=8001 +``` + +对应 compose 行为: + +- gemold:`${MOLDINSIGHT_PORT:-8000}:8000` +- inventory:`${INVENTORY_PORT:-8001}:8001` + +--- + +## 4. 直接运行时的端口约定 + +### gemold-only ```bash -# 创建启动脚本 -cat > start_production.sh << 'EOF' -#!/bin/bash -cd /opt/moldinsight/moldinsight_project -source venv/bin/activate - -# 从 .env 读取端口配置 -if [ -f .env ]; then - PORT=$(grep '^PORT=' .env | cut -d'=' -f2) -else - PORT=8000 -fi - -# 启动服务 -gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:${PORT} -EOF - -chmod +x start_production.sh -./start_production.sh +uvicorn src.entrypoints.moldinsight:app --host 0.0.0.0 --port 8000 ``` -### systemd 服务配置 +### inventory-only -创建 `/etc/systemd/system/moldinsight.service`: - -```ini -[Unit] -Description=MoldInsight Geometry Analysis Service -After=network.target postgresql.service - -[Service] -Type=simple -User=www-data -Group=www-data -WorkingDirectory=/opt/moldinsight/moldinsight_project -Environment=PATH=/opt/moldinsight/moldinsight_project/venv/bin -Environment="PORT=8000" -ExecStart=/opt/moldinsight/moldinsight_project/venv/bin/gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:${PORT} -Restart=always - -[Install] -WantedBy=multi-user.target +```bash +uvicorn src.entrypoints.inventory:app --host 0.0.0.0 --port 8001 ``` -**重要:** 在 `[Service]` 部分添加 `Environment="PORT=8000"`,或在 `.env` 文件中配置 `PORT=8000`。 +如果改端口: +- gemold 改 `--port` +- inventory 改 `--port` +- 同步更新 Nginx / 防火墙 / 前端 base URL -### Nginx 反向代理配置 +--- + +## 5. 前端联动 + +如果前端与后端分开部署,需要与前端环境变量保持一致。 + +建议前端支持: + +### unified 模式 +```env +VITE_API_BASE_URL=https://api.example.com +``` + +### split 模式 +```env +VITE_AUTH_API_BASE_URL=https://auth.example.com +VITE_MOLDINSIGHT_API_BASE_URL=https://gemold.example.com +VITE_INVENTORY_API_BASE_URL=https://inventory.example.com +``` + +当前详细策略见: +- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) + +--- + +## 6. Nginx 示例 + +### gemold-only ```nginx -upstream moldinsight_backend { - server 127.0.0.1:8000; # 对应 .env 中的 PORT -} - server { listen 80; - server_name your-domain.com; + server_name gemold.example.com; location / { - proxy_pass http://moldinsight_backend; + proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } +} +``` - location /static { - alias /opt/moldinsight/moldinsight_project/static; - } +### inventory-only - location /html_output { - alias /opt/moldinsight/moldinsight_project/html_output; +```nginx +server { + listen 80; + server_name inventory.example.com; + + location / { + proxy_pass http://127.0.0.1:8001; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; } } ``` -### Docker 部署 +--- -Docker 部署自动从 `.env` 读取配置,无需额外设置: +## 7. 防火墙建议 + +如果不通过 Nginx 统一入口而是直接暴露服务端口,则应显式开放: ```bash -# .env 文件配置 -PORT=8000 # 容器内端口 -HOST_PORT=8080 # 宿主机端口 +# gemold +sudo ufw allow 8000/tcp -# 启动 -docker-compose up -d +# inventory +sudo ufw allow 8001/tcp ``` -### 修改生产环境端口 +生产环境更推荐: +- 外部只开放 80/443 +- 内部仅开放 8000/8001 给 Nginx 或内网访问 -1. **编辑 .env 文件** - ```bash - PORT=9000 # 修改应用端口 - ``` +--- -2. **重启服务** - ```bash - # systemd - sudo systemctl restart moldinsight - - # Docker - docker-compose down && docker-compose up -d - - # 手动启动 - ./start_production.sh - ``` - -3. **更新 Nginx 配置(如果使用)** - ```nginx - upstream moldinsight_backend { - server 127.0.0.1:9000; # 更新为新端口 - } - ``` - ```bash - sudo nginx -t && sudo nginx -s reload - ``` - -### 防火墙配置 - -如果修改了端口,需要更新防火墙规则: +## 8. 快速检查 ```bash -# UFW (Ubuntu/Debian) -sudo ufw allow 9000/tcp -sudo ufw delete allow 8000/tcp # 删除旧端口 - -# firewall-cmd (CentOS/RHEL) -sudo firewall-cmd --permanent --add-port=9000/tcp -sudo firewall-cmd --permanent --remove-port=8000/tcp -sudo firewall-cmd --reload +curl http://127.0.0.1:8000/health +curl http://127.0.0.1:8001/health ``` -### 健康检查 +如果只部署单模块,只检查对应服务即可。 -修改端口后,更新健康检查命令: +--- -```bash -# 检查服务状态 -curl http://localhost:9000/health -curl http://your-domain.com/health -``` +## 9. 结论 -## 快速参考 +在当前模块化架构下: -| 部署方式 | 端口配置位置 | 重启命令 | -|---------|------------|---------| -| 直接运行 | `.env` 中的 `PORT` | Ctrl+C 后重新运行 | -| Gunicorn | `.env` 中的 `PORT` | `systemctl restart moldinsight` | -| Docker | `.env` 中的 `PORT` 和 `HOST_PORT` | `docker-compose restart` | -| Nginx代理 | Nginx配置中的 `proxy_pass` | `nginx -s reload` | - -## 注意事项 - -⚠️ **重要:** -1. 所有端口配置统一在 `.env` 文件中管理 -2. 修改端口后需要同步更新相关配置(Nginx、防火墙等) -3. 确保新端口没有被其他服务占用 -4. 生产环境建议使用 Nginx 反向代理,对外提供 80/443 端口 -5. .env 文件不应提交到版本控制系统,使用 `.env.example` 作为模板 +- gemold 与 inventory 应视为**两个独立后端模块** +- 端口应按模块分配,而不是继续沿用单体“一个后端一个端口”的思路 +- unified 更适合通过**组合层或网关**实现,而不是继续让历史单体入口承载全部语义 diff --git a/docs/deployment/LINUX_SETUP.md b/docs/deployment/LINUX_SETUP.md index e788769..e69b953 100644 --- a/docs/deployment/LINUX_SETUP.md +++ b/docs/deployment/LINUX_SETUP.md @@ -1,177 +1,315 @@ -# MoldInsight Linux 部署指南 +# geMoldInsight Linux 部署指南 -## 系统要求 -- Linux 系统 (Ubuntu 20.04+ / CentOS 8+) -- Python 3.8+ -- PostgreSQL 12+ +> 本文档描述的是 **当前模块化架构** 下的 Linux 部署方式,而不是历史单体 `src.main:app` 方案。 + +当前项目支持三种部署模式: + +- **unified**:gemold + inventory 统一部署 +- **gemold-only**:仅部署模具分析后端 +- **inventory-only**:仅部署进销存后端 + +项目保持: + +- **同一 Git 仓库** +- **同一 PostgreSQL 数据库** +- **共享认证体系** +- **按模块独立部署** +- **复用服务器上已存在的 PostgreSQL / Redis / RustFS(或 MinIO 兼容存储)** + +详细架构蓝图见: +- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) + +--- + +## 1. 系统要求 + +### 基础要求 +- Linux(Ubuntu 22.04+ / Debian 12+ / CentOS Stream 9+) +- Python 3.12 - Git +- 服务器上已可访问的 PostgreSQL 15+ +- 服务器上已可访问的 Redis 7+ -## 1. 环境准备 +### 按模块附加要求 + +#### gemold / unified 需要 +- 服务器上已可访问的 MinIO 或 RustFS 兼容对象存储 +- PythonOCC 运行环境 +- Celery worker(推荐与 gemold 一起部署) + +#### inventory-only 需要 +- PostgreSQL +- Redis +- 不依赖 MinIO / RustFS +- 不依赖 Celery worker + +--- + +## 2. 代码获取与目录约定 -### 安装系统依赖 ```bash -# Ubuntu/Debian -sudo apt update -sudo apt install python3 python3-pip python3-venv postgresql postgresql-contrib git - -# CentOS/RHEL -sudo yum update -sudo yum install python3 python3-pip postgresql postgresql-server git -``` - -### 配置PostgreSQL -```bash -# 启动PostgreSQL服务 -sudo systemctl start postgresql -sudo systemctl enable postgresql - -# 创建数据库和用户 -sudo -u postgres psql -``` - -在PostgreSQL中执行: -```sql -CREATE DATABASE moldinsight; -CREATE USER molduser WITH PASSWORD 'moldpassword'; -GRANT ALL PRIVILEGES ON DATABASE moldinsight TO molduser; -\q -``` - -## 2. 项目部署 - -### 克隆或复制项目 -```bash -# 如果使用Git cd /opt -sudo git clone moldinsight -sudo chown -R $USER:$USER moldinsight -cd moldinsight - -# 或者直接复制项目文件到Linux服务器 +sudo git clone geMoldInsight +sudo chown -R $USER:$USER geMoldInsight +cd geMoldInsight ``` -### 创建Python虚拟环境 +后续示例默认项目位于: + ```bash -cd moldinsight_project -python3 -m venv venv -source venv/bin/activate +/opt/geMoldInsight ``` -### 安装依赖 +--- + +## 3. Python 环境准备 + ```bash +python3.12 -m venv .venv +source .venv/bin/activate pip install --upgrade pip pip install -r requirements.txt ``` -## 3. 环境配置 +> 如果需要 gemold 分析能力,请额外准备 PythonOCC 运行环境。该依赖通常通过 conda 或预构建运行镜像提供,而不是直接由 pip 安装。 + +--- + +## 4. 环境变量配置 + +复制模板: -### 修改环境配置文件 -编辑 `.env` 文件: ```bash -nano .env +cp .env.example .env ``` -修改为Linux环境的配置: -```env -# 数据库配置(Linux环境) -DATABASE_URL=postgresql+asyncpg://molduser:moldpassword@localhost:5432/moldinsight +或部署场景参考: -# 服务配置 -DEBUG=false +```bash +cp deploy/.env.example .env +``` + +至少需要配置(并指向服务器上已存在的基础设施): + +```env HOST=0.0.0.0 PORT=8000 -# Redis配置(可选) -REDIS_HOST=localhost +DB_HOST=127.0.0.1 +DB_PORT=5432 +DB_NAME=moldinsight +DB_USER=moldinsight_user +DB_PASSWORD=change-me + +REDIS_HOST=127.0.0.1 REDIS_PORT=6379 REDIS_PASSWORD= -# Kafka配置(可选) -KAFKA_BOOTSTRAP_SERVERS=localhost:9092 -KAFKA_SECURITY_PROTOCOL=PLAINTEXT +SECRET_KEY=change-me-in-production +ADMIN_USERNAME=admin +ADMIN_PASSWORD=change-me + +RUSTFS_ENDPOINT=http://127.0.0.1:9000 +RUSTFS_ACCESS_KEY=minioadmin +RUSTFS_SECRET_KEY=minioadmin ``` -### 创建必要的目录 +说明: +- `RUSTFS_*` 仅 **gemold / unified** 模式需要 +- `inventory-only` 可不使用对象存储 +- 当前配置读取实现见 [settings.py](../../src/shared/config/settings.py) + +--- + +## 5. 数据库初始化 + +项目当前使用 Alembic 管理迁移,应用启动时也会执行初始化流程。 + +首次部署建议: + +1. 确保服务器上的 PostgreSQL / Redis / 对象存储服务已可访问 +2. 启动应用前确认 `.env` 中的 `DB_HOST` / `REDIS_HOST` / `RUSTFS_ENDPOINT` 指向真实服务地址 +3. 让应用执行初始化/升级逻辑 + +相关实现参考: +- [init_db.py](../../src/shared/database/init_db.py) + +> 当前项目是 **单数据库** 设计,因此 unified / gemold-only / inventory-only 都连接到同一个数据库与同一 migration head。 + +--- + +## 6. 启动方式 + +## 6.1 inventory-only + ```bash -mkdir -p uploads html_output logs -chmod 755 uploads html_output logs +source .venv/bin/activate +uvicorn src.entrypoints.inventory:app --host 0.0.0.0 --port 8001 ``` -## 4. 启动服务 +适合: +- 只提供进销存能力 +- 不需要模具分析与异步任务 + +--- + +## 6.2 gemold-only -### 开发模式启动 ```bash -cd moldinsight_project -source venv/bin/activate -python src/main.py +source .venv/bin/activate +uvicorn src.entrypoints.moldinsight:app --host 0.0.0.0 --port 8000 ``` -### 生产环境启动(使用Gunicorn) +适合: +- 单独部署模具分析能力 +- 文件上传 / 分析 / 导出 / 批量分析 + +### gemold Celery worker + +建议同时启动 worker: + ```bash -# 安装Gunicorn -pip install gunicorn uvloop httptools - -# 启动服务 -cd moldinsight_project -source venv/bin/activate -gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 +source .venv/bin/activate +celery -A src.celery_app.celery_app worker --loglevel=info ``` -## 5. 系统服务配置(可选) +> gemold 的异步处理链路依赖 Celery + Redis;若只启动 HTTP 服务而不启动 worker,上传分析任务可能无法完整处理。 + +--- + +## 6.3 unified + +当前仓库仍保留历史统一入口 [main.py](../../src/main.py),但它更适合作为**过渡参考**,不建议作为长期标准入口。 + +在正式完成组合层重构前,如需统一部署,可优先使用反向代理或部署编排层统一暴露 gemold 与 inventory;后续会演进为显式 `unified_app.py`。 + +蓝图参考: +- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) + +--- + +## 7. systemd 部署示例 + +## 7.1 inventory-only 服务 + +创建: -### 创建systemd服务文件 ```bash -sudo nano /etc/systemd/system/moldinsight.service +sudo nano /etc/systemd/system/gemold-inventory.service ``` -添加以下内容: ```ini [Unit] -Description=MoldInsight Geometry Analysis Service -After=network.target postgresql.service +Description=geMoldInsight Inventory API +After=network.target postgresql.service redis.service [Service] Type=simple User=www-data Group=www-data -WorkingDirectory=/opt/moldinsight/moldinsight_project -Environment=PATH=/opt/moldinsight/moldinsight_project/venv/bin -ExecStart=/opt/moldinsight/moldinsight_project/venv/bin/gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 +WorkingDirectory=/opt/geMoldInsight +Environment=PATH=/opt/geMoldInsight/.venv/bin +ExecStart=/opt/geMoldInsight/.venv/bin/uvicorn src.entrypoints.inventory:app --host 0.0.0.0 --port 8001 Restart=always +RestartSec=5 [Install] WantedBy=multi-user.target ``` -### 启用并启动服务 +启用: + ```bash sudo systemctl daemon-reload -sudo systemctl enable moldinsight -sudo systemctl start moldinsight -sudo systemctl status moldinsight +sudo systemctl enable gemold-inventory +sudo systemctl start gemold-inventory ``` -## 6. Nginx反向代理配置(可选) +--- + +## 7.2 gemold-only API 服务 + +创建: -### 安装Nginx ```bash -# Ubuntu/Debian -sudo apt install nginx - -# CentOS/RHEL -sudo yum install nginx +sudo nano /etc/systemd/system/gemold-moldinsight.service ``` -### 创建Nginx配置文件 +```ini +[Unit] +Description=geMoldInsight MoldInsight API +After=network.target postgresql.service redis.service + +[Service] +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/opt/geMoldInsight +Environment=PATH=/opt/geMoldInsight/.venv/bin +ExecStart=/opt/geMoldInsight/.venv/bin/uvicorn src.entrypoints.moldinsight:app --host 0.0.0.0 --port 8000 +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +--- + +## 7.3 gemold Celery worker 服务 + +创建: + ```bash -sudo nano /etc/nginx/sites-available/moldinsight +sudo nano /etc/systemd/system/gemold-celery.service ``` -添加以下内容: +```ini +[Unit] +Description=geMoldInsight MoldInsight Celery Worker +After=network.target postgresql.service redis.service + +[Service] +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/opt/geMoldInsight +Environment=PATH=/opt/geMoldInsight/.venv/bin +ExecStart=/opt/geMoldInsight/.venv/bin/celery -A src.celery_app.celery_app worker --loglevel=info +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +--- + +## 8. Nginx 反向代理示例 + +### 8.1 inventory-only + ```nginx server { listen 80; - server_name your-domain.com; + server_name inventory.example.com; + + location / { + proxy_pass http://127.0.0.1:8001; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +### 8.2 gemold-only + +```nginx +server { + listen 80; + server_name gemold.example.com; location / { proxy_pass http://127.0.0.1:8000; @@ -180,102 +318,86 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } - - location /static { - alias /opt/moldinsight/moldinsight_project/static; - expires 30d; - } } ``` -### 启用站点并重启Nginx -```bash -sudo ln -s /etc/nginx/sites-available/moldinsight /etc/nginx/sites-enabled/ -sudo nginx -t -sudo systemctl restart nginx -``` +### 8.3 unified(示意) -## 7. 防火墙配置 +统一对外时,可由网关做模块路由,也可直接暴露统一组合后的应用入口。组合层标准化完成前,更推荐通过部署编排或网关来实现统一对外访问。 + +--- + +## 9. 验证部署 + +### 9.1 健康检查 + +inventory-only: ```bash -# Ubuntu/Debian (ufw) -sudo ufw allow 80 -sudo ufw allow 8000 -sudo ufw allow ssh -sudo ufw enable - -# CentOS/RHEL (firewalld) -sudo firewall-cmd --permanent --add-port=80/tcp -sudo firewall-cmd --permanent --add-port=8000/tcp -sudo firewall-cmd --permanent --add-service=ssh -sudo firewall-cmd --reload +curl http://127.0.0.1:8001/health ``` -## 8. 验证部署 +gemold-only: -### 检查服务状态 ```bash -# 检查应用服务 -curl http://localhost:8000/health - -# 检查数据库连接 -sudo -u postgres psql -d moldinsight -c "SELECT version();" +curl http://127.0.0.1:8000/health ``` -### 测试文件上传 -访问 `http://your-server-ip:8000` 上传STP文件测试功能。 +### 9.2 基础能力验证 -## 9. 故障排除 +#### inventory-only +- 登录接口可用 +- `/api/products` 返回数据 +- `/api/inventory` 返回数据 -### 常见问题 +#### gemold-only +- 登录接口可用 +- `/api/upload` 可访问 +- 上传后 worker 能正常消费任务 +- `/api/status/{task_id}` 能看到进度 -1. **数据库连接失败** - - 检查PostgreSQL服务状态:`sudo systemctl status postgresql` - - 验证数据库连接:`psql -h localhost -U molduser -d moldinsight` +--- -2. **端口被占用** - - 检查端口使用:`netstat -tulpn | grep 8000` - - 修改端口或停止占用进程 +## 10. 常见问题 -3. **权限问题** - - 确保目录权限正确:`chmod 755 uploads html_output logs` - - 检查文件所有者:`ls -la` +### 1. 为什么不再推荐 `src.main:app`? +因为当前项目已演进为模块化结构,`src.main:app` 更适合作为过渡兼容入口,而不是长期部署标准。应优先围绕 [entrypoints/](../../src/entrypoints/) 部署。 -4. **依赖安装失败** - - 更新pip:`pip install --upgrade pip` - - 使用国内镜像:`pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple` +### 2. inventory-only 为什么不需要对象存储? +因为对象存储主要服务于 gemold 分析产物(HTML、导出文件等)。纯 inventory 部署不需要这部分基础设施。 -## 10. 备份和恢复 +### 3. gemold-only 为什么建议同时部署 Celery? +因为模具分析任务通常走异步处理链路,仅启动 API 而不启动 worker,会影响上传后的任务处理。 + +--- + +## 11. Docker Compose 说明 + +当前 [docker-compose.yml](../../docker-compose.yml) 仅启动: + +- `moldinsight` +- `moldinsight-celery` +- `inventory` + +它**不会**再拉起: + +- PostgreSQL +- Redis +- MinIO + +这些基础设施应由服务器现有服务提供,并通过 `.env` 传入连接信息。 + +示例: -### 数据库备份 ```bash -# 备份数据库 -sudo -u postgres pg_dump moldinsight > moldinsight_backup.sql - -# 恢复数据库 -sudo -u postgres psql -d moldinsight < moldinsight_backup.sql +docker compose --profile full up -d ``` -### 文件备份 -```bash -# 备份上传的文件和配置 -tar -czf moldinsight_backup.tar.gz uploads/ html_output/ .env requirements.txt -``` +--- -## 快速启动脚本 +## 12. 推荐阅读 -创建启动脚本 `start.sh`: -```bash -#!/bin/bash -cd /opt/moldinsight/moldinsight_project -source venv/bin/activate -python src/main.py -``` - -赋予执行权限: -```bash -chmod +x start.sh -./start.sh -``` - -现在您的MoldInsight项目已经可以在Linux环境下正常运行! \ No newline at end of file +- [README.md](../../README.md) +- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) +- [DEPLOY_PORT.md](./DEPLOY_PORT.md) +- [PORT_CONFIG.md](./PORT_CONFIG.md) diff --git a/docs/deployment/PORT_CONFIG.md b/docs/deployment/PORT_CONFIG.md index 51aef3c..b6bef78 100644 --- a/docs/deployment/PORT_CONFIG.md +++ b/docs/deployment/PORT_CONFIG.md @@ -1,107 +1,174 @@ -# 端口配置说明 +# 端口配置说明(模块化架构) -## ⚠️ 重要提示 +> 本文档说明当前 geMoldInsight 在**模块化部署**下的端口配置方式。 -本项目现在采用**统一端口配置管理**,所有端口配置集中在一个地方: +当前架构中应区分: -**唯一修改端口的地方:** `.env` 文件中的端口配置部分 +- **gemold API 端口** +- **inventory API 端口** +- **数据库/Redis/对象存储端口** +- **前端访问地址** -## 配置说明 +不再推荐把所有部署场景都抽象成“单应用单端口”。 -编辑项目根目录下的 `.env` 文件: +--- -```bash -# ================================ -# 端口配置 - 唯一修改端口的地方 -# ================================ -# 应用端口(容器内端口) -PORT=8000 -# Docker映射到宿主机的端口(docker-compose使用) -HOST_PORT=10001 -# ================================ +## 1. 当前主配置位置 + +对于 Docker Compose 部署,当前主要端口配置来源于: + +- [docker-compose.yml](../../docker-compose.yml) +- `.env` / `deploy/.env.example` + +注意:该 compose 文件仅负责项目应用容器,不负责 PostgreSQL / Redis / 对象存储容器。 + +核心环境变量: + +```env +MOLDINSIGHT_PORT=8000 +INVENTORY_PORT=8001 ``` -### 端口含义 +其余基础设施通常为: -| 变量 | 用途 | 默认值 | 说明 | -|------|------|--------|------| -| `PORT` | 应用监听端口 | 8000 | FastAPI/Uvicorn 服务监听的端口 | -| `HOST_PORT` | 宿主机映射端口 | 10001 | Docker Compose 映射到宿主机的端口 | - -### 使用场景 - -#### 1. 本地直接运行(Python) -```bash -python src/main.py +```env +DB_PORT=5432 +REDIS_PORT=6379 ``` -服务将在 `http://localhost:8000` 启动(使用 `PORT` 配置) -#### 2. Docker Compose 运行 -```bash -docker-compose up +对象存储常见端口(由服务器既有服务提供): + +```env +RUSTFS_ENDPOINT=http://localhost:9000 ``` -服务将在 `http://localhost:10001` 访问(使用 `HOST_PORT` 配置) -容器内部使用 `PORT` 配置的端口(8000) -#### 3. 修改端口 +--- -**场景A:只想修改外部访问端口(Docker)** -```bash -# .env 文件 -PORT=8000 # 容器内不变 -HOST_PORT=8080 # 宿主机改为8080 +## 2. 各端口的含义 + +| 变量 / 端口 | 用途 | +|---|---| +| `MOLDINSIGHT_PORT` | gemold API 宿主机暴露端口 | +| `INVENTORY_PORT` | inventory API 宿主机暴露端口 | +| `DB_PORT` | PostgreSQL 端口 | +| `REDIS_PORT` | Redis 端口 | +| `9000` | MinIO/RustFS S3 兼容 API | +| `9001` | MinIO 控制台 | + +--- + +## 3. 推荐配置方式 + +### 3.1 gemold-only + +```env +MOLDINSIGHT_PORT=8000 +DB_PORT=5432 +REDIS_PORT=6379 ``` -访问地址:`http://localhost:8080` -**场景B:修改应用端口(容器内/本地运行)** -```bash -# .env 文件 -PORT=9000 # 应用改为9000 -HOST_PORT=10001 # 宿主机映射到10001 +### 3.2 inventory-only + +```env +INVENTORY_PORT=8001 +DB_PORT=5432 +REDIS_PORT=6379 ``` -- 本地运行:`http://localhost:9000` -- Docker运行:`http://localhost:10001` (映射到容器内9000) -**场景C:同时修改两个端口** -```bash -# .env 文件 -PORT=9000 -HOST_PORT=9000 +### 3.3 full / 模块同时部署 + +```env +MOLDINSIGHT_PORT=8000 +INVENTORY_PORT=8001 +DB_PORT=5432 +REDIS_PORT=6379 ``` -- 本地运行:`http://localhost:9000` -- Docker运行:`http://localhost:9000` -## 配置文件说明 +--- -### 配置读取优先级 +## 4. 为什么不再强调单一 `PORT` 变量 -1. **`config/settings.py`** - 从 `.env` 读取 `PORT` 和 `HOST` -2. **`src/main.py`** - 从 `settings` 获取端口配置 -3. **`docker-compose.yml`** - 从 `.env` 读取 `HOST_PORT` 和 `PORT` +历史单体部署通常只有一个后端入口,因此 `PORT=8000` 足够。 -### 相关文件 +当前项目已经是: +- gemold 独立入口 +- inventory 独立入口 +- unified 作为组合模式而非默认单体入口 -- **`.env`** - ⭐ 唯一需要修改的配置文件 -- **`config/settings.py`** - 配置读取逻辑(无需修改) -- **`src/main.py`** - 使用配置启动服务(无需修改) -- **`docker-compose.yml`** - Docker端口映射(自动读取 `.env`) -- **`start.sh` / `start_fixed.sh`** - 启动脚本(自动读取 `.env`) +因此端口配置必须模块化: -## 常见问题 +- gemold 一个端口 +- inventory 一个端口 +- 如果 unified 对外存在,可以由网关统一暴露 80/443 -### Q: 为什么 Docker 宿主机端口和应用端口分开配置? -A: 这样可以灵活调整容器端口而不影响外部访问,也避免端口冲突。 +这比继续强行把所有模式压成一个 `PORT` 更清晰,也更符合真实部署方式。 -### Q: 修改后需要重启吗? -A: 是的,修改 `.env` 后需要重启服务才能生效: -- 本地运行:Ctrl+C 停止后重新 `python src/main.py` -- Docker: `docker-compose down && docker-compose up` +--- -### Q: 如何避免端口冲突? -A: 确保 `HOST_PORT` 不与其他服务冲突,可以使用 `netstat -an | grep <端口>` 检查端口占用情况。 +## 5. 直接运行与 Compose 的区别 -### Q: 可以使用 80 端口吗? -A: 可以,但需要管理员权限: -- Linux/Mac: 使用 sudo -- Docker: 需要容器有足够权限 -- 生产环境建议使用反向代理(如 Nginx) +### 直接运行 + +gemold: + +```bash +uvicorn src.entrypoints.moldinsight:app --port 8000 +``` + +inventory: + +```bash +uvicorn src.entrypoints.inventory:app --port 8001 +``` + +### Docker Compose + +Compose 通过端口映射暴露服务: + +- gemold → `${MOLDINSIGHT_PORT}:8000` +- inventory → `${INVENTORY_PORT}:8001` + +当前实际定义见: +- [docker-compose.yml](../../docker-compose.yml) + +--- + +## 6. 与前端配置的关系 + +前端是否使用 unified / split deployment,会影响前端 API 地址配置。 + +### unified +- 一个 API 基地址 + +### split +- gemold 与 inventory 各自基地址 + +因此,修改后端端口后,可能还需要同步: + +- 前端 `.env` +- Nginx 反向代理 +- 浏览器访问地址 + +--- + +## 7. 推荐实践 + +1. **本地开发** + - gemold:8000 + - inventory:8001 + +2. **服务器部署** + - 外网只暴露 80/443 + - Nginx 反代到 8000 / 8001 + +3. **不要继续把所有部署模式都写成 `src.main:app + PORT=8000`** + - 这已不符合当前架构 + +--- + +## 8. 关联文档 + +- [LINUX_SETUP.md](./LINUX_SETUP.md) +- [DEPLOY_PORT.md](./DEPLOY_PORT.md) +- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md) +- [README.md](../../README.md) diff --git a/docs/deployment/PORT_REFACTOR_SUMMARY.md b/docs/deployment/PORT_REFACTOR_SUMMARY.md index da85a5d..9c937d2 100644 --- a/docs/deployment/PORT_REFACTOR_SUMMARY.md +++ b/docs/deployment/PORT_REFACTOR_SUMMARY.md @@ -1,192 +1,39 @@ -# 端口配置重构总结 +# 端口配置历史说明(已被模块化部署文档取代) -## 修改内容 +本文件保留为历史说明。 -本次重构将项目的端口配置统一到 `.env` 文件中,确保整个项目只有一个地方需要修改端口。 +它所描述的“单体应用单一端口配置”思路,已经不再能完整代表当前 geMoldInsight 的模块化架构。 -## 修改的文件 +当前项目已演进为: -### 1. ⭐ `.env` - 唯一配置入口 -**变更:** 添加了统一的端口配置区域 -```bash -# ================================ -# 端口配置 - 唯一修改端口的地方 -# ================================ -# 应用端口(容器内端口) -PORT=8000 -# Docker映射到宿主机的端口(docker-compose使用) -HOST_PORT=10001 -# ================================ -``` +- gemold 模块可独立部署 +- inventory 模块可独立部署 +- unified 作为组合模式存在 +- gemold 与 inventory 应分别考虑端口与网关暴露方式 -### 2. `src/main.py` -**变更:** 从硬编码的环境变量读取改为从 `config.settings` 读取 -```python -# 修改前 -host = os.getenv('HOST', '0.0.0.0') -port = int(os.getenv('PORT', '8000')) +因此,端口配置的权威说明已转移到以下文档: -# 修改后 -from config.settings import settings -# ... -host=settings.HOST, -port=settings.PORT -``` +- [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) -### 3. `docker-compose.yml` -**变更:** 端口映射从硬编码改为从环境变量读取 -```yaml -# 修改前 -ports: - - "10001:8000" -environment: - - PORT=8000 +--- -# 修改后 -ports: - - "${HOST_PORT:-10001}:${CONTAINER_PORT:-8000}" -environment: - - HOST=${HOST:-0.0.0.0} - - PORT=${CONTAINER_PORT:-8000} -``` +## 当前结论 -### 4. `start.sh` 和 `start_fixed.sh` -**变更:** 自动从 `.env` 读取端口并显示正确的访问地址 -```bash -# 添加 -PORT=$(grep '^PORT=' .env 2>/dev/null | cut -d'=' -f2 || echo '8000') -echo "🌐 服务将在 http://localhost:${PORT} 启动" -``` +1. 不再默认以历史单体 `src.main:app` 作为部署中心。 +2. 不再假设整个系统只有一个后端端口。 +3. gemold 与 inventory 应按模块分别规划端口。 +4. unified 更适合通过组合层或网关统一暴露,而不是继续沿用旧单体部署语义。 -### 5. `README.md` -**变更:** 更新访问说明,提示端口配置位置 +--- -### 6. 新增文件 -- `.env.example` - 配置文件模板 -- `PORT_CONFIG.md` - 端口配置详细说明 -- `DEPLOY_PORT.md` - 部署时端口配置指南 +## 建议 -## 配置读取流程 +如果你正在查找当前有效的端口/部署方式,请不要继续参考旧的单体端口说明,而应直接查看: -``` -.env 文件 - ↓ -config/settings.py (读取 PORT 和 HOST) - ↓ -src/main.py (使用 settings.PORT) - ↓ -uvicorn 启动服务 -``` - -Docker 部署流程: -``` -.env 文件 - ↓ -docker-compose.yml (读取 HOST_PORT 和 PORT) - ↓ -容器映射和内部启动 -``` - -## 如何修改端口 - -### 方法 1:修改应用端口 -```bash -# 编辑 .env -PORT=9000 # 修改此行 -``` -- 本地运行:`http://localhost:9000` -- Docker运行:需同时修改 `HOST_PORT=9000` - -### 方法 2:修改 Docker 外部访问端口 -```bash -# 编辑 .env -HOST_PORT=8080 # 修改此行(PORT 保持不变) -``` -- Docker运行:`http://localhost:8080` -- 容器内仍使用 PORT 配置的端口 - -## 测试验证 - -### 测试 1:本地运行 -```bash -# 修改 .env 中的 PORT -PORT=9999 - -# 启动服务 -python src/main.py - -# 验证 -curl http://localhost:9999/health -``` - -### 测试 2:Docker 运行 -```bash -# 修改 .env -PORT=8000 -HOST_PORT=9999 - -# 启动容器 -docker-compose up -d - -# 验证 -curl http://localhost:9999/health -``` - -### 测试 3:启动脚本 -```bash -# 修改 .env -PORT=8888 - -# 运行启动脚本 -./start.sh - -# 检查输出是否显示正确的端口 -``` - -## 注意事项 - -1. ✅ 所有端口配置集中在 `.env` 文件 -2. ✅ 无需修改代码文件即可更改端口 -3. ✅ 支持本地运行和 Docker 部署两种场景 -4. ✅ 提供了详细的配置文档 -5. ⚠️ 修改端口后需要重启服务 -6. ⚠️ Docker 部署时需要同时考虑容器内外端口 -7. ⚠️ 确保新端口没有被占用 - -## 文件清单 - -### 修改的文件 -- `.env` - 添加端口配置区域 -- `src/main.py` - 统一使用 settings 配置 -- `docker-compose.yml` - 支持环境变量配置端口 -- `start.sh` - 自动读取和显示端口 -- `start_fixed.sh` - 自动读取和显示端口 -- `README.md` - 更新访问说明 - -### 新增的文件 -- `.env.example` - 配置模板 -- `PORT_CONFIG.md` - 端口配置详细说明 -- `DEPLOY_PORT.md` - 部署配置指南 -- `PORT_REFACTOR_SUMMARY.md` - 本文档 - -## 回滚方案 - -如果需要回滚,按以下步骤操作: - -```bash -git checkout -- src/main.py -git checkout -- docker-compose.yml -git checkout -- start.sh start_fixed.sh -git checkout -- .env -git checkout -- README.md - -# 删除新增文件 -rm .env.example PORT_CONFIG.md DEPLOY_PORT.md PORT_REFACTOR_SUMMARY.md -``` - -## 联系支持 - -如有问题,请查看: -- `PORT_CONFIG.md` - 端口配置详细说明 -- `DEPLOY_PORT.md` - 部署配置指南 -- `.env.example` - 配置示例 +- [README.md](../../README.md) +- [LINUX_SETUP.md](./LINUX_SETUP.md) +- [DEPLOY_PORT.md](./DEPLOY_PORT.md) +- [PORT_CONFIG.md](./PORT_CONFIG.md) diff --git a/start.sh b/start.sh deleted file mode 100644 index a1e3c60..0000000 --- a/start.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# MoldInsight 启动脚本 - 修复版 -# 适用于Linux miniforge环境 - -echo "🚀 启动 MoldInsight 模具几何分析系统..." - -# 检查Python版本 -python_version=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))') -echo "📋 Python版本: $python_version" - -# 初始化miniforge环境 -echo "🔧 初始化miniforge环境..." -source /opt/miniforge3/etc/profile.d/conda.sh - -# 激活conda环境 -echo "🔧 激活py_3.12环境..." -conda activate py_3.12 - -# 验证PythonOCC是否可用 -echo "🔍 验证PythonOCC..." -python3 -c "import OCC; print('✅ PythonOCC可用')" || { - echo "❌ PythonOCC不可用,请先安装PythonOCC" - exit 1 -} - -# 检查是否已经安装依赖 -echo "📦 检查依赖包..." -pip install --upgrade -r requirements.txt - -# 创建必要目录 -echo "📁 创建必要目录..." -mkdir -p uploads html_output logs - -# 检查环境配置文件 -if [ ! -f ".env" ]; then - echo "❌ 错误: 未找到.env配置文件" - echo "📋 请创建.env文件并配置数据库连接信息:" - echo " 1. 创建.env文件: touch .env" - echo " 2. 编辑配置文件: nano .env" - echo " 3. 添加数据库配置:" - echo " DATABASE_URL=postgresql+asyncpg://username:password@localhost:5432/database_name" - echo "" - echo "💡 提示: 请根据实际的PostgreSQL连接信息修改上述配置" - exit 1 -fi - -echo "🔧 检查数据库连接..." - -# 启动服务 -echo "🚀 启动 MoldInsight 服务..." -PORT=$(grep '^PORT=' .env 2>/dev/null | cut -d'=' -f2 || echo '8000') -echo "🌐 服务将在 http://localhost:${PORT} 启动" -echo "📊 功能特性:" -echo " - STP文件解析和几何分析" -echo " - JSON数据导出" -echo " - PostgreSQL数据库存储" -echo " - 3D可视化HTML生成" -echo " - Web界面文件上传" -echo " - 任务状态跟踪" -echo "" -echo "按 Ctrl+C 停止服务" -echo "" - -# 启动应用 -python3 src/main.py \ No newline at end of file