This commit is contained in:
2026-03-07 03:04:15 +08:00
parent bfe6da3376
commit 557fcd578a
10 changed files with 1469 additions and 201 deletions
+149 -17
View File
@@ -6,6 +6,7 @@ from pathlib import Path
from typing import Optional, Dict, Any
import json
from datetime import datetime
import uuid
from models.database import (
STPFile, GeometryData, MeshData, MoldCavityData,
@@ -25,8 +26,12 @@ class StorageIntegrationService:
async def save_stp_file(self, session: AsyncSession,
file_path: Path,
original_filename: str,
user_id: Optional[int] = None) -> STPFile:
"""保存STP文件到PostgreSQL元数据 + RustFS对象存储"""
user_id: Optional[int] = None,
upload_batch: Optional[str] = None) -> STPFile:
"""保存STP文件到PostgreSQL元数据 + RustFS对象存储
支持同一文件多次上传,每次上传都会创建新记录
"""
# 1. 上传到RustFS
upload_result = await rustfs_manager.upload_file(
@@ -35,23 +40,15 @@ class StorageIntegrationService:
original_filename=original_filename,
metadata={
'original_filename': original_filename,
'user_id': str(user_id) if user_id else 'anonymous'
'user_id': str(user_id) if user_id else 'anonymous',
'upload_batch': upload_batch or str(uuid.uuid4())
}
)
file_hash = upload_result['file_hash']
# 2. 检查是否已存在相同文件
existing_file = await session.execute(
select(STPFile).where(STPFile.file_hash == file_hash)
)
existing_file = existing_file.scalar_one_or_none()
if existing_file:
logger.info(f"文件已存在,返回现有记录: {existing_file.id}")
return existing_file
batch_id = upload_batch or str(uuid.uuid4())
# 3. 创建新PostgreSQL记录
# 2. 创建新PostgreSQL记录(每次上传都创建新记录)
stp_file = STPFile(
user_id=user_id,
object_key=upload_result['object_key'],
@@ -59,15 +56,16 @@ class StorageIntegrationService:
original_filename=original_filename,
file_size=upload_result['file_size'],
file_hash=file_hash,
upload_batch=batch_id,
status="uploaded",
file_path=str(file_path) # 保留本地路径以兼容
file_path=str(file_path)
)
session.add(stp_file)
await session.commit()
await session.refresh(stp_file)
logger.info(f"STP文件保存成功 RustFS: {stp_file.id}")
logger.info(f"STP文件保存成功 RustFS: {stp_file.id}, 批次: {batch_id}")
return stp_file
async def create_processing_task(self, session: AsyncSession,
@@ -415,7 +413,7 @@ class StorageIntegrationService:
resource_type=resource_type,
resource_id=resource_id,
description=description,
metadata=metadata,
meta_data=metadata,
ip_address=ip_address,
user_agent=user_agent
)
@@ -529,6 +527,140 @@ class StorageIntegrationService:
return result
async def get_file_history_by_filename(
self,
session: AsyncSession,
filename: str,
user_id: Optional[int] = None,
limit: int = 50
) -> list:
"""获取同一文件名的所有上传历史记录"""
query = select(STPFile).where(
STPFile.original_filename == filename
).order_by(STPFile.upload_time.desc())
if user_id:
query = query.where(STPFile.user_id == user_id)
query = query.limit(limit)
result = await session.execute(query)
files = result.scalars().all()
return [
{
'id': f.id,
'upload_batch': f.upload_batch,
'upload_time': f.upload_time.isoformat() if f.upload_time else None,
'file_size': f.file_size,
'status': f.status,
'volume': f.volume,
'surface_area': f.surface_area,
'product_weight': f.product_weight,
'has_analysis': f.status == 'completed'
}
for f in files
]
async def get_all_file_groups(
self,
session: AsyncSession,
user_id: Optional[int] = None,
limit: int = 100
) -> list:
"""获取所有文件分组(按文件名分组),包含每个文件的最新分析结果"""
from sqlalchemy import func, desc
# 子查询:获取每个文件名的最新上传
subquery = (
select(
STPFile.original_filename,
func.max(STPFile.upload_time).label('latest_upload')
)
.group_by(STPFile.original_filename)
.order_by(desc('latest_upload'))
.limit(limit)
)
if user_id:
subquery = subquery.where(STPFile.user_id == user_id)
subquery = subquery.subquery()
# 主查询:获取最新记录和统计信息
query = (
select(STPFile)
.join(
subquery,
(STPFile.original_filename == subquery.c.original_filename) &
(STPFile.upload_time == subquery.c.latest_upload)
)
.order_by(STPFile.upload_time.desc())
)
result = await session.execute(query)
latest_files = result.scalars().all()
# 获取每个文件名的上传次数
file_groups = []
for f in latest_files:
count_query = select(func.count()).where(
STPFile.original_filename == f.original_filename
)
if user_id:
count_query = count_query.where(STPFile.user_id == user_id)
count_result = await session.execute(count_query)
upload_count = count_result.scalar()
file_groups.append({
'filename': f.original_filename,
'latest_id': f.id,
'latest_upload_time': f.upload_time.isoformat() if f.upload_time else None,
'latest_status': f.status,
'upload_count': upload_count,
'file_size': f.file_size,
'volume': f.volume,
'surface_area': f.surface_area,
'product_weight': f.product_weight
})
return file_groups
async def update_stp_file_analysis_summary(
self,
session: AsyncSession,
stp_file_id: int,
volume: Optional[float] = None,
surface_area: Optional[float] = None,
product_weight: Optional[float] = None
):
"""更新STP文件的分析摘要字段(用于快速查询)"""
try:
update_data = {}
if volume is not None:
update_data['volume'] = volume
if surface_area is not None:
update_data['surface_area'] = surface_area
if product_weight is not None:
update_data['product_weight'] = product_weight
if update_data:
await session.execute(
update(STPFile)
.where(STPFile.id == stp_file_id)
.values(**update_data)
)
await session.commit()
logger.info(f"STP文件分析摘要更新: ID {stp_file_id}")
except Exception as e:
await session.rollback()
logger.error(f"更新STP文件分析摘要失败: {e}")
raise
async def delete_stp_file_cascade(self, session: AsyncSession,
stp_file_id: int):
"""级联删除STP文件及其所有关联数据"""