deving
This commit is contained in:
+58
-8
@@ -15,6 +15,7 @@ from database.database import get_db_session
|
||||
from utils.logger import get_logger
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from core.mold_generator import MoldCavityGenerator
|
||||
from core.mesh_generator import MeshGenerator
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -27,6 +28,7 @@ file_handler = FileHandler()
|
||||
html_generator = HTMLGenerator()
|
||||
# 初始化模具生成器(可配置不同材料的收缩率)
|
||||
mold_generator = MoldCavityGenerator(shrinkage_rate=0.005) # ABS材料
|
||||
mesh_generator = MeshGenerator(quality="medium")
|
||||
|
||||
# 内存中的任务存储
|
||||
tasks = {}
|
||||
@@ -359,7 +361,55 @@ async def process_file_core(
|
||||
shape = stp_parser.load_step_file(Path(file_path))
|
||||
geometry_data = stp_parser.analyze_geometry(shape)
|
||||
|
||||
# 2. 生成模具型腔(模拟数据)
|
||||
# 2. 生成网格数据并持久化(详细 JSON 存 RustFS,摘要写 PostgreSQL)
|
||||
await storage_service.update_task_status(
|
||||
db_session, task_id, "processing", 30, "生成网格数据"
|
||||
)
|
||||
|
||||
mesh_result = None
|
||||
mesh_json = None
|
||||
try:
|
||||
mesh_result = mesh_generator.generate_mesh_from_shape(shape)
|
||||
|
||||
tri_mesh = mesh_result.get("trimesh_mesh")
|
||||
pointcloud = mesh_result.get("pointcloud") or {}
|
||||
|
||||
if tri_mesh is not None:
|
||||
# 顶点和面转为 JSON 可序列化
|
||||
vertices = tri_mesh.vertices.tolist()
|
||||
faces = tri_mesh.faces.tolist()
|
||||
|
||||
# 使用已计算的几何边界框,避免重复计算
|
||||
bbox = geometry_data.get("bounding_box", {})
|
||||
|
||||
mesh_json = {
|
||||
"metadata": {
|
||||
"file_name": Path(file_path).name,
|
||||
"generated_at": datetime.now().isoformat(),
|
||||
"quality": "medium",
|
||||
"vertex_count": len(vertices),
|
||||
"face_count": len(faces),
|
||||
"point_count": pointcloud.get("count"),
|
||||
},
|
||||
"mesh": {
|
||||
"vertices": vertices,
|
||||
"faces": faces,
|
||||
},
|
||||
"pointcloud": pointcloud,
|
||||
"bounding_box": bbox,
|
||||
}
|
||||
|
||||
await storage_service.save_mesh_data(
|
||||
db_session,
|
||||
stp_file_id=stp_file_id,
|
||||
mesh_json=mesh_json,
|
||||
quality="medium",
|
||||
)
|
||||
except Exception as mesh_err:
|
||||
# 网格失败不影响整体流程,只记录日志
|
||||
logger.warning(f"网格生成或保存失败,不影响主流程: {mesh_err}")
|
||||
|
||||
# 3. 生成模具型腔(模拟数据)
|
||||
await storage_service.update_task_status(
|
||||
db_session, task_id, "processing", 40, "生成模具型腔(模拟)"
|
||||
)
|
||||
@@ -371,7 +421,7 @@ async def process_file_core(
|
||||
"gating_type": "edge_gate"
|
||||
}
|
||||
|
||||
# 3. 生成详细JSON数据(使用计算值)
|
||||
# 4. 生成详细JSON数据(使用计算值)
|
||||
await storage_service.update_task_status(
|
||||
db_session, task_id, "processing", 60, "生成型腔详细数据"
|
||||
)
|
||||
@@ -472,10 +522,10 @@ async def process_file_core(
|
||||
}
|
||||
}
|
||||
|
||||
# 4. 生成关键信息(模拟)
|
||||
# 5. 生成关键信息(模拟)
|
||||
cavity_key_info = detailed_cavity_json["mold_cavities"]["cavity_key_info"]
|
||||
|
||||
# 5. 保存几何数据到数据库
|
||||
# 6. 保存几何数据到数据库
|
||||
await storage_service.update_task_status(
|
||||
db_session, task_id, "processing", 70, "保存几何数据"
|
||||
)
|
||||
@@ -487,14 +537,14 @@ async def process_file_core(
|
||||
geometry_data.get("analysis_method", "mold_cavity")
|
||||
)
|
||||
|
||||
# 6. 保存模具型腔数据
|
||||
# 7. 保存模具型腔数据
|
||||
await storage_service.save_mold_cavity_data(
|
||||
db_session,
|
||||
stp_file_id,
|
||||
detailed_cavity_json
|
||||
)
|
||||
|
||||
# 7. 生成HTML可视化(包含型腔信息)
|
||||
# 8. 生成HTML可视化(包含型腔信息)
|
||||
await storage_service.update_task_status(
|
||||
db_session, task_id, "processing", 85, "生成可视化报告"
|
||||
)
|
||||
@@ -513,10 +563,10 @@ async def process_file_core(
|
||||
html_file_path
|
||||
)
|
||||
|
||||
# 8. 分析模具设计
|
||||
# 9. 分析模具设计
|
||||
analysis_result = geometry_analyzer.analyze_mold_design(geometry_data)
|
||||
|
||||
# 9. 完成处理
|
||||
# 10. 完成处理
|
||||
await storage_service.update_stp_file_status(db_session, stp_file_id, "completed")
|
||||
await storage_service.update_task_status(
|
||||
db_session, task_id, "completed", 100, "模具型腔生成完成"
|
||||
|
||||
@@ -61,6 +61,8 @@ class STPFile(Base):
|
||||
# 关联关系
|
||||
user = relationship("User", back_populates="stp_files")
|
||||
geometry_data = relationship("GeometryData", back_populates="stp_file", uselist=False)
|
||||
# 网格数据:一条 STP 记录对应一条网格摘要记录(详细 JSON 在 RustFS)
|
||||
mesh_data = relationship("MeshData", back_populates="stp_file", uselist=False)
|
||||
mold_cavity_data = relationship("MoldCavityData", back_populates="stp_file", uselist=False)
|
||||
html_file = relationship("HTMLFile", back_populates="stp_file", uselist=False)
|
||||
|
||||
@@ -103,6 +105,40 @@ class GeometryData(Base):
|
||||
def __repr__(self):
|
||||
return f"<GeometryData(id={self.id}, stp_file_id={self.stp_file_id})>"
|
||||
|
||||
|
||||
class MeshData(Base):
|
||||
"""网格数据JSON元数据表(详细网格存 RustFS,PostgreSQL 存摘要)"""
|
||||
__tablename__ = "mesh_data"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
stp_file_id = Column(Integer, ForeignKey("stp_files.id"), nullable=False, index=True)
|
||||
|
||||
# 对象存储信息
|
||||
object_key = Column(String(500), nullable=False)
|
||||
storage_bucket = Column(String(100), nullable=False)
|
||||
object_url = Column(String(1000), nullable=True)
|
||||
|
||||
# 生成设置
|
||||
quality = Column(String(20), default="medium") # low / medium / high
|
||||
|
||||
# 网格规模信息
|
||||
vertex_count = Column(Integer, nullable=True)
|
||||
face_count = Column(Integer, nullable=True)
|
||||
point_count = Column(Integer, nullable=True) # 采样点云数量
|
||||
|
||||
# 网格边界框(便于快速查询)
|
||||
bounding_box_min = Column(JSON, nullable=True)
|
||||
bounding_box_max = Column(JSON, nullable=True)
|
||||
|
||||
# 时间戳
|
||||
created_time = Column(DateTime, default=func.now())
|
||||
|
||||
# 关联关系
|
||||
stp_file = relationship("STPFile", back_populates="mesh_data")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<MeshData(id={self.id}, stp_file_id={self.stp_file_id}, quality='{self.quality}')>"
|
||||
|
||||
class HTMLFile(Base):
|
||||
"""网页文件元数据表"""
|
||||
__tablename__ = "html_files"
|
||||
|
||||
@@ -8,7 +8,7 @@ import json
|
||||
from datetime import datetime
|
||||
|
||||
from models.database import (
|
||||
STPFile, GeometryData, MoldCavityData,
|
||||
STPFile, GeometryData, MeshData, MoldCavityData,
|
||||
HTMLFile, ProcessingTask, User,
|
||||
FeatureDetection, DesignRecommendation,
|
||||
UserActivity, SystemLog
|
||||
@@ -200,6 +200,62 @@ class StorageIntegrationService:
|
||||
logger.info(f"几何数据保存成功 RustFS: {geometry_data.id}")
|
||||
return geometry_data
|
||||
|
||||
async def save_mesh_data(
|
||||
self,
|
||||
session: AsyncSession,
|
||||
stp_file_id: int,
|
||||
mesh_json: Dict[str, Any],
|
||||
quality: str = "medium"
|
||||
) -> MeshData:
|
||||
"""保存网格数据到 PostgreSQL 元数据 + RustFS 对象存储
|
||||
|
||||
mesh_json 为完整网格 JSON(顶点、面、点云等),
|
||||
PostgreSQL 只存 object_key 和一些摘要字段,详细数据放在 RustFS。
|
||||
"""
|
||||
|
||||
# 1. 获取文件哈希
|
||||
stp_file = await session.get(STPFile, stp_file_id)
|
||||
file_hash = stp_file.file_hash
|
||||
|
||||
# 2. 上传网格 JSON 到 RustFS
|
||||
upload_result = await rustfs_manager.upload_json_data(
|
||||
file_type='mesh_data',
|
||||
json_data=mesh_json,
|
||||
file_hash=file_hash
|
||||
)
|
||||
|
||||
# 3. 提取摘要信息
|
||||
mesh_section = mesh_json.get('mesh', {})
|
||||
pointcloud_section = mesh_json.get('pointcloud', {})
|
||||
bbox = mesh_json.get('bounding_box', {})
|
||||
|
||||
vertices = mesh_section.get('vertices') or []
|
||||
faces = mesh_section.get('faces') or []
|
||||
|
||||
vertex_count = len(vertices)
|
||||
face_count = len(faces)
|
||||
point_count = pointcloud_section.get('count')
|
||||
|
||||
# 4. 创建 PostgreSQL 记录
|
||||
mesh_data = MeshData(
|
||||
stp_file_id=stp_file_id,
|
||||
object_key=upload_result['object_key'],
|
||||
storage_bucket=upload_result['bucket'],
|
||||
quality=quality,
|
||||
vertex_count=vertex_count,
|
||||
face_count=face_count,
|
||||
point_count=point_count,
|
||||
bounding_box_min=bbox.get('min'),
|
||||
bounding_box_max=bbox.get('max')
|
||||
)
|
||||
|
||||
session.add(mesh_data)
|
||||
await session.commit()
|
||||
await session.refresh(mesh_data)
|
||||
|
||||
logger.info(f"网格数据保存成功 RustFS: {mesh_data.id}")
|
||||
return mesh_data
|
||||
|
||||
async def save_mold_cavity_data(self, session: AsyncSession,
|
||||
stp_file_id: int,
|
||||
cavity_json: Dict[str, Any]) -> MoldCavityData:
|
||||
@@ -388,6 +444,7 @@ class StorageIntegrationService:
|
||||
'user_id': stp_file.user_id
|
||||
},
|
||||
'geometry_data': None,
|
||||
'mesh_data': None,
|
||||
'mold_cavity_data': None,
|
||||
'html_content': None,
|
||||
'features': [],
|
||||
@@ -412,6 +469,14 @@ class StorageIntegrationService:
|
||||
)
|
||||
result['mold_cavity_data'] = json.loads(cavity_data_bytes.decode('utf-8'))
|
||||
|
||||
# 网格数据
|
||||
if stp_file.mesh_data:
|
||||
mesh_bytes = await rustfs_manager.download_file(
|
||||
file_type='mesh_data',
|
||||
object_key=stp_file.mesh_data.object_key
|
||||
)
|
||||
result['mesh_data'] = json.loads(mesh_bytes.decode('utf-8'))
|
||||
|
||||
# HTML文件
|
||||
if stp_file.html_file:
|
||||
html_bytes = await rustfs_manager.download_file(
|
||||
@@ -481,6 +546,12 @@ class StorageIntegrationService:
|
||||
except Exception as e:
|
||||
logger.error(f"删除型腔数据失败: {e}")
|
||||
|
||||
try:
|
||||
if stp_file.mesh_data:
|
||||
await rustfs_manager.delete_file('mesh_data', stp_file.mesh_data.object_key)
|
||||
except Exception as e:
|
||||
logger.error(f"删除网格数据失败: {e}")
|
||||
|
||||
try:
|
||||
if stp_file.html_file:
|
||||
await rustfs_manager.delete_file('html_files', stp_file.html_file.object_key)
|
||||
|
||||
@@ -27,7 +27,8 @@ class RustFSManager:
|
||||
# 文件类型前缀(子目录结构)
|
||||
self.file_types = {
|
||||
'stp_files': 'stp-files',
|
||||
'geometry_data': 'geometry',
|
||||
'geometry_data': 'geometry',
|
||||
'mesh_data': 'mesh',
|
||||
'mold_cavities': 'mold-cavities',
|
||||
'html_files': 'html',
|
||||
'user_files': 'user-files'
|
||||
|
||||
Reference in New Issue
Block a user