后端模块拆分

This commit is contained in:
2026-05-29 18:10:08 +08:00
parent 5bb9bc84ea
commit 823a387118
93 changed files with 198 additions and 833 deletions
-1
View File
@@ -1 +0,0 @@
# API 模块
-601
View File
@@ -1,601 +0,0 @@
# api/routes.py
from fastapi import APIRouter, UploadFile, File, HTTPException, Request, Depends
from typing import Optional, Dict, Any, List
import uuid
from datetime import datetime
import os
from pathlib import Path
from models.schemas import ProcessingStatus, create_task_info
from utils.file_handler import FileHandler
from services.storage_integration_rustfs import StorageIntegrationService
from services.redis_task_manager import redis_task_manager
from services.task_query_service import TaskQueryService
from database.database import get_db_session
try:
from celery_tasks import process_stp_task
_use_celery = True
except ImportError:
process_stp_task = None
_use_celery = False
from utils.logger import get_logger
from sqlalchemy.ext.asyncio import AsyncSession
from core.cavity_layout_optimizer import CavityLayoutOptimizer
from core.mold_system_designer import MoldSystemDesigner
from core.side_action_designer import SideActionDesigner
from core.mold_cam import MoldCAMDesigner
from core.mold_machining import CollisionDetector, ToolpathOptimizer, EDMElectrodeDesigner, MachiningSimulator
from core.cad_exporter import CADExporter
from services.auth_service import get_current_active_user
from models.database import User
logger = get_logger(__name__)
router = APIRouter()
file_handler = FileHandler()
cavity_layout_optimizer = CavityLayoutOptimizer()
mold_system_designer = MoldSystemDesigner()
side_action_designer = SideActionDesigner()
mold_cam_designer = MoldCAMDesigner()
collision_detector = CollisionDetector()
toolpath_optimizer = ToolpathOptimizer()
edm_designer = EDMElectrodeDesigner()
machining_simulator = MachiningSimulator()
cad_exporter = CADExporter()
@router.get("/health")
@router.post("/health")
async def health():
task_count = await redis_task_manager.get_task_count()
return {
"status": "healthy",
"pythonocc": True,
"total_tasks": task_count,
"redis_connected": redis_task_manager.is_connected,
}
@router.post("/upload")
async def upload_stp(
file: UploadFile = File(...),
material: Optional[str] = "ABS",
db_session: AsyncSession = Depends(get_db_session),
current_user: User = Depends(get_current_active_user)
):
"""上传STP文件并存储到数据库"""
logger.info(
f"[UPLOAD] 用户={current_user.username}(id={current_user.id}) "
f"文件={file.filename} 材料={material}"
)
if not file.filename.lower().endswith(('.stp', '.step')):
logger.warning(f"[UPLOAD] 拒绝: 不支持的文件类型 - {file.filename}")
raise HTTPException(400, "只支持STP/STEP文件")
task_id = str(uuid.uuid4())
# 保存文件
file_path, file_size = await file_handler.save_uploaded_file(file)
logger.info(f"[UPLOAD] 文件已保存: {file_path} ({file_size} bytes), task_id={task_id}")
# 创建存储集成服务实例
storage_service = StorageIntegrationService()
# 保存STP文件到RustFS + PostgreSQL
stp_file = await storage_service.save_stp_file(
session=db_session,
file_path=file_path,
original_filename=file.filename,
user_id=current_user.id
)
logger.info(f"[UPLOAD] STP文件已存入RustFS+PG: stp_file.id={stp_file.id}")
# 创建处理任务记录
await storage_service.create_processing_task(db_session, task_id, stp_file.id)
# 创建任务记录(Redis 为主,内存作为兼容回退)
task_info = create_task_info(
task_id=task_id,
status=ProcessingStatus.PROCESSING,
filename=file.filename,
file_path=str(file_path),
file_size=file_size,
upload_time=str(datetime.now())
)
await redis_task_manager.set_task(task_id, task_info)
# 后台处理走统一编排服务,避免请求会话在后台失效
process_params = {"material": material}
if _use_celery:
process_stp_task.delay(task_id, str(file_path), stp_file.id, process_params)
logger.info(f"[UPLOAD] Celery 任务已调度: task_id={task_id}")
else:
import asyncio
from services.processing_service import processing_service
asyncio.create_task(processing_service.process_file_with_storage(
task_id, str(file_path), stp_file.id, process_params
))
logger.info(f"[UPLOAD] 直接后台处理: task_id={task_id} (celery 未安装)")
return {
"task_id": task_id,
"status": "processing",
"message": "文件上传成功,开始处理并存储到数据库",
"file_info": {
"filename": file.filename,
"size": file_size,
"pythonocc_available": True,
"database_file_id": stp_file.id
}
}
@router.get("/status/{task_id}")
@router.post("/status/{task_id}")
async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_session)):
"""
获取任务状态
优先返回内存中的任务信息;
如果内存中不存在,则从 PostgreSQL + RustFS 组装一个持久化的任务视图,
结构与内存任务保持尽量一致,便于前端集中展示总结性信息。
"""
try:
task_view = await TaskQueryService.get_task_view(db_session, task_id)
if task_view is None:
raise HTTPException(404, "任务不存在")
return task_view
except HTTPException:
raise
except Exception as e:
logger.error(f"获取任务状态失败: {e}")
raise HTTPException(500, f"获取任务状态失败: {str(e)}")
@router.get("/debug/tasks")
@router.post("/debug/tasks")
async def debug_tasks():
"""调试接口:查看所有任务"""
all_tasks = await redis_task_manager.get_all_tasks()
return {
"total_tasks": len(all_tasks),
"tasks": all_tasks,
"redis_connected": redis_task_manager.is_connected,
}
@router.get("/history")
@router.post("/history")
async def get_file_history(db_session: AsyncSession = Depends(get_db_session)):
"""获取按文件名分组的文件历史记录(支持多上传)"""
storage_service = StorageIntegrationService()
file_groups = await storage_service.get_all_file_groups(db_session)
return {
"total_files": len(file_groups),
"files": file_groups
}
@router.get("/history/{filename}")
@router.post("/history/{filename}")
async def get_file_records(filename: str, db_session: AsyncSession = Depends(get_db_session)):
"""获取指定文件名的所有上传记录(支持多上传历史)"""
import urllib.parse
decoded_filename = urllib.parse.unquote(filename)
storage_service = StorageIntegrationService()
file_records = await storage_service.get_file_history_by_filename(
db_session,
decoded_filename
)
return file_records
@router.get("/result/{task_id}")
@router.post("/result/{task_id}")
async def result_page(request: Request, task_id: str, db_session: AsyncSession = Depends(get_db_session)):
"""结果详情页面"""
from sqlalchemy import select
from models.database import ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile
# 从数据库查询任务详情
result = await db_session.execute(
select(ProcessingTask, STPFile)
.join(STPFile, ProcessingTask.stp_file_id == STPFile.id)
.where(ProcessingTask.task_id == task_id)
)
task_record = result.first()
if not task_record:
raise HTTPException(404, "任务不存在")
task, stp_file = task_record
# 构建任务详情数据(先只包含基本数据)
task_data = {
"task_id": task.task_id,
"filename": stp_file.original_filename if stp_file else "",
"file_size": stp_file.file_size if stp_file else 0,
"status": task.status,
"progress": task.progress,
"current_step": task.current_step,
"created_at": task.created_time.isoformat() if task.created_time else "",
"completed_at": task.completed_time.isoformat() if task.completed_time else "",
"error": task.error_message if task.error_message else ""
}
from fastapi.templating import Jinja2Templates
import os
# 简化路径配置,直接使用当前工作目录下的templates文件夹
templates_dir = os.path.join(os.getcwd(), "templates")
templates = Jinja2Templates(directory=templates_dir)
return templates.TemplateResponse("result.html", {
"request": request,
"task": task_data,
"pythonocc_available": True,
"version": "3.0.0"
})
# ==================== P3 新增 API ====================
@router.post("/optimize-layout")
async def optimize_cavity_layout(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""多型腔布局优化"""
body = await request.json()
product_bbox = body.get("product_bbox", {"dimensions": [100, 100, 50]})
cavity_count = body.get("cavity_count", 1)
mold_base_size = body.get("mold_base_size")
layout_type = body.get("layout_type", "auto")
if cavity_count < 1 or cavity_count > 64:
raise HTTPException(400, "型腔数量必须在 1-64 之间")
result = cavity_layout_optimizer.optimize_layout(
product_bbox=product_bbox,
cavity_count=cavity_count,
mold_base_size=mold_base_size,
layout_type=layout_type,
)
return {"status": "success", "data": result}
@router.post("/design-cooling")
async def design_cooling_system(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""冷却系统设计"""
body = await request.json()
mold_size = body.get("mold_size", {"length": 300, "width": 300, "height": 200})
product_bbox = body.get("product_bbox", {"dimensions": [100, 100, 50]})
material = body.get("material", "ABS")
cavity_count = body.get("cavity_count", 1)
cycle_time_target = body.get("cycle_time_target")
from core.mold_system_designer import CoolingSystemDesigner
designer = CoolingSystemDesigner()
result = designer.design_cooling_system(
mold_size=mold_size,
product_bbox=product_bbox,
material=material,
cavity_count=cavity_count,
cycle_time_target=cycle_time_target,
)
return {"status": "success", "data": result}
@router.post("/design-gating")
async def design_gating_system(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""浇注系统设计"""
body = await request.json()
product_bbox = body.get("product_bbox", {"dimensions": [100, 100, 50]})
material = body.get("material", "ABS")
cavity_count = body.get("cavity_count", 1)
gate_type = body.get("gate_type", "auto")
layout_positions = body.get("layout_positions")
from core.mold_system_designer import GatingSystemDesigner
designer = GatingSystemDesigner()
result = designer.design_gating_system(
product_bbox=product_bbox,
material=material,
cavity_count=cavity_count,
gate_type=gate_type,
layout_positions=layout_positions,
)
return {"status": "success", "data": result}
@router.post("/design-mold-system")
async def design_complete_mold_system(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""综合模具系统设计(冷却+浇注)"""
body = await request.json()
mold_size = body.get("mold_size", {"length": 300, "width": 300, "height": 200})
product_bbox = body.get("product_bbox", {"dimensions": [100, 100, 50]})
material = body.get("material", "ABS")
cavity_count = body.get("cavity_count", 1)
gate_type = body.get("gate_type", "auto")
cycle_time_target = body.get("cycle_time_target")
layout_positions = body.get("layout_positions")
result = mold_system_designer.design_complete_system(
mold_size=mold_size,
product_bbox=product_bbox,
material=material,
cavity_count=cavity_count,
gate_type=gate_type,
cycle_time_target=cycle_time_target,
layout_positions=layout_positions,
)
return {"status": "success", "data": result}
@router.post("/ai-parting-detect")
async def ai_parting_surface_detect(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""AI 分型面检测"""
body = await request.json()
task_id = body.get("task_id")
if not task_id:
raise HTTPException(404, "缺少 task_id")
task_data = await redis_task_manager.get_task(task_id)
if not task_data:
raise HTTPException(404, "任务不存在")
geometry_data = task_data.get("geometry_data")
if not geometry_data:
raise HTTPException(400, "该任务尚未完成几何分析")
from core.ai_parting_detector import AIPartingSurfaceDetectorV2
detector = AIPartingSurfaceDetectorV2(use_gnn=True)
result = detector._detect_with_geometry(None, geometry_data)
return {"status": "success", "data": result}
@router.post("/detect-undercuts")
async def detect_undercuts(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""倒扣区域检测与滑块/斜顶机构设计"""
body = await request.json()
task_id = body.get("task_id")
parting_direction = body.get("parting_direction", [0, 0, 1])
mold_size = body.get("mold_size", {"length": 300, "width": 300, "height": 200})
if not task_id:
raise HTTPException(404, "缺少 task_id")
task_data = await redis_task_manager.get_task(task_id)
if not task_data:
raise HTTPException(404, "任务不存在")
geometry_data = task_data.get("geometry_data")
if not geometry_data:
raise HTTPException(400, "该任务尚未完成几何分析")
result = side_action_designer.analyze_and_design(
shape=None, parting_direction=parting_direction, mold_size=mold_size
)
return {"status": "success", "data": result}
@router.post("/design-cam")
async def design_mold_cam(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""模具CAM刀路设计"""
body = await request.json()
cavity_bbox = body.get("cavity_bbox", {"dimensions": [100, 100, 50], "min": [-50, -50, -25], "max": [50, 50, 25]})
stock_bbox = body.get("stock_bbox", {"dimensions": [150, 150, 100], "min": [-75, -75, -50], "max": [75, 75, 50]})
mold_steel = body.get("mold_steel", "P20")
surface_quality = body.get("surface_quality", "standard")
controller = body.get("controller", "fanuc")
result = mold_cam_designer.design_mold_cam(
cavity_bbox=cavity_bbox,
stock_bbox=stock_bbox,
mold_steel=mold_steel,
surface_quality=surface_quality,
controller=controller,
)
return {"status": "success", "data": result}
@router.post("/check-collision")
async def check_toolpath_collision(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""刀路碰撞检测"""
body = await request.json()
toolpath_points = body.get("toolpath_points", [[0, 0, 50], [10, 10, -5], [20, 20, -10]])
tool = body.get("tool", {"diameter": 10, "flute_length": 30, "shank_diameter": 10})
stock_bbox = body.get("stock_bbox", {"min": [-50, -50, -25], "max": [50, 50, 25]})
clamp_positions = body.get("clamp_positions")
result = collision_detector.check_toolpath_safety(
toolpath_points, tool, stock_bbox, clamp_positions
)
return {"status": "success", "data": result}
@router.post("/optimize-toolpath")
async def optimize_toolpath(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""刀路优化"""
body = await request.json()
toolpath_points = body.get("toolpath_points", [[0, 0, 50], [10, 10, -5], [20, 20, -10]])
cutting_params = body.get("cutting_params", {"feed_rate_mm_min": 500})
stock_bbox = body.get("stock_bbox")
result = toolpath_optimizer.optimize_toolpath(
toolpath_points, cutting_params, stock_bbox
)
return {"status": "success", "data": result}
@router.post("/design-electrodes")
async def design_edm_electrodes(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""EDM电极设计"""
body = await request.json()
undercut_regions = body.get("undercut_regions", [{"center": [0, 0, 0], "area": 100, "type": "undercut"}])
cavity_bbox = body.get("cavity_bbox", {"dimensions": [100, 100, 50]})
material = body.get("material", "copper")
spark_gap = body.get("spark_gap", 0.05)
overburn = body.get("overburn", 0.1)
result = edm_designer.design_electrodes(
undercut_regions, cavity_bbox, material, spark_gap, overburn
)
return {"status": "success", "data": result}
@router.post("/simulate-machining")
async def simulate_machining(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""加工仿真"""
body = await request.json()
operations = body.get("operations", [{"strategy": "z_level_roughing", "levels": [{"z": -5}]}])
stock_bbox = body.get("stock_bbox", {"dimensions": [100, 100, 50], "min": [-50, -50, -25], "max": [50, 50, 25]})
resolution = body.get("resolution", 2.0)
result = machining_simulator.simulate_machining(
operations, stock_bbox, resolution
)
return {"status": "success", "data": result}
# ==================== CAD 导出 API ====================
@router.post("/export-mold")
async def export_mold_results(
request: Request,
current_user: User = Depends(get_current_active_user),
):
"""导出模具设计结果(STEP/IGES/STL/BRep)"""
body = await request.json()
task_id = body.get("task_id")
formats = body.get("formats", ["step", "stl"])
components = body.get("components", ["cavity", "core"])
scheme_id = body.get("scheme_id")
if not task_id:
raise HTTPException(404, "缺少 task_id")
cavity_shapes = processing_service.get_export_shapes(task_id, scheme_id=scheme_id)
if not cavity_shapes:
task_data = await redis_task_manager.get_task(task_id)
if not task_data:
raise HTTPException(404, "任务不存在")
filename = task_data.get("filename", f"mold_{task_id}")
raise HTTPException(
400,
f"该任务的 OCC 形状数据已过期(仅保留 STEP 导出文件),"
f"请通过历史页面的下载链接获取已导出的 STEP 文件",
)
task_data = await redis_task_manager.get_task(task_id)
base_filename = (
Path(task_data.get("filename", f"mold_{task_id}")).stem
if task_data
else f"mold_{task_id}"
)
result = cad_exporter.export_mold_results(
cavity_data=cavity_shapes,
base_filename=base_filename,
formats=formats,
components=components,
)
return {"status": "success", "data": result}
@router.get("/export-download/{filepath:path}")
async def download_export_file(
filepath: str,
current_user: User = Depends(get_current_active_user),
):
"""下载导出的CAD文件"""
from fastapi.responses import FileResponse
full_path = os.path.join(cad_exporter.output_dir, filepath)
if not os.path.exists(full_path):
raise HTTPException(404, "文件不存在")
if not os.path.abspath(full_path).startswith(os.path.abspath(cad_exporter.output_dir)):
raise HTTPException(403, "禁止访问")
media_types = {
".step": "application/step",
".stp": "application/step",
".iges": "application/iges",
".igs": "application/iges",
".stl": "model/stl",
".brep": "application/octet-stream",
}
ext = Path(full_path).suffix.lower()
media_type = media_types.get(ext, "application/octet-stream")
return FileResponse(
full_path,
media_type=media_type,
filename=os.path.basename(full_path),
)
@router.get("/export-recommendations")
async def get_export_recommendations(
target: str = "ug",
current_user: User = Depends(get_current_active_user),
):
"""获取导出格式建议(UG/FreeCAD/SolidWorks)"""
result = cad_exporter.get_export_recommendations(target)
return {"status": "success", "data": result}
+2 -2
View File
@@ -1,6 +1,6 @@
from celery_app import app
from services.processing_service import processing_service
from utils.logger import get_logger
from moldinsight.services.processing_service import processing_service
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -15,9 +15,9 @@ from sqlalchemy import select
from typing import Optional, List
from datetime import datetime
from database.database import get_db_session
from services.auth_service import get_current_active_user, get_current_admin_user
from models.database import User, Customer
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user, get_current_admin_user
from shared.models.database import User, Customer
from .schemas import CustomerCreate, CustomerResponse
router = APIRouter(prefix="/customers", tags=["客户管理"])
@@ -13,9 +13,9 @@ from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import (
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import (
User, Product, Supplier, Customer, Warehouse,
Inventory, PurchaseOrder, SalesOrder
)
@@ -6,9 +6,9 @@ from typing import Optional, List, Dict, Tuple
from datetime import datetime
from decimal import Decimal
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import (
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import (
User,
Customer,
Supplier,
@@ -34,7 +34,7 @@ from .schemas import (
PaginatedResponse,
)
from .utils import generate_order_no
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -12,9 +12,9 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, func
from typing import Optional, List
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import User, Product, Warehouse, Inventory
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import User, Product, Warehouse, Inventory
from .schemas import InventoryResponse, InventoryCreate, InventoryUpdate, PaginatedResponse
router = APIRouter(prefix="/inventory", tags=["库存管理"])
@@ -13,9 +13,9 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, desc
from typing import Optional, List
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import User, Product, MaterialPriceHistory, MaterialSupplier, Supplier
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import User, Product, MaterialPriceHistory, MaterialSupplier, Supplier
from .schemas import (
MaterialPriceHistoryCreate,
MaterialPriceHistoryResponse,
@@ -15,9 +15,9 @@ from sqlalchemy import select, or_, func, delete
from typing import Optional, List, Dict
from decimal import Decimal
from database.database import get_db_session
from services.auth_service import get_current_active_user, get_current_admin_user
from models.database import User, Product, ProductMaterial
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user, get_current_admin_user
from shared.models.database import User, Product, ProductMaterial
from .schemas import (
ProductCreate,
ProductResponse,
@@ -14,9 +14,9 @@ from sqlalchemy import select, func, update
from typing import Optional, List
from decimal import Decimal
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import (
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import (
User,
Supplier,
Product,
@@ -16,9 +16,9 @@ from math import ceil
from pydantic import BaseModel, Field
from decimal import Decimal
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import (
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import (
User,
Customer,
Product,
@@ -14,9 +14,9 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, func
from typing import Optional, List
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import User, Product, Warehouse, Inventory, StockMovement
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import User, Product, Warehouse, Inventory, StockMovement
from .schemas import StockMovementCreate, StockMovementResponse, PaginatedResponse
from .utils import generate_order_no
@@ -15,9 +15,9 @@ from sqlalchemy import select
from typing import Optional, List
from datetime import datetime
from database.database import get_db_session
from services.auth_service import get_current_active_user, get_current_admin_user
from models.database import User, Supplier
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user, get_current_admin_user
from shared.models.database import User, Supplier
from .schemas import SupplierCreate, SupplierResponse
router = APIRouter(prefix="/suppliers", tags=["供应商管理"])
@@ -13,9 +13,9 @@ from sqlalchemy import select
from typing import List
from datetime import datetime
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import User, Warehouse
from shared.database.database import get_db_session
from shared.services.auth_service import get_current_active_user
from shared.models.database import User, Warehouse
from .schemas import WarehouseCreate, WarehouseResponse
router = APIRouter(prefix="/warehouses", tags=["仓库管理"])
+15 -26
View File
@@ -19,7 +19,7 @@ print(f"当前工作目录: {os.getcwd()}")
# 测试导入配置模块
try:
from config.settings import settings
from shared.config.settings import settings
print("[OK] 配置模块导入成功")
except ImportError as e:
print(f"[FAIL] 配置模块导入失败: {e}")
@@ -42,11 +42,11 @@ from fastapi.responses import JSONResponse
import asyncio
import time
from api.auth_routes import router as auth_router
from api.inventory import inventory_router
from api.aluminum_price_routes import router as aluminum_price_router
from utils.logger import setup_logging, get_logger
from database.init_db import init_database
from shared.services.auth_routes import router as auth_router
from inventory.api import inventory_router
from moldinsight.api.aluminum_price_routes import router as aluminum_price_router
from shared.utils.logger import setup_logging, get_logger
from shared.database.init_db import init_database
setup_logging()
logger = get_logger(__name__)
@@ -94,8 +94,8 @@ async def startup_event():
# 初始化RustFS连接
try:
from storage.rustfs_storage import rustfs_manager
from config.settings import settings
from moldinsight.storage.rustfs_storage import rustfs_manager
from shared.config.settings import settings
await rustfs_manager.connect(
endpoint=settings.RUSTFS_ENDPOINT,
@@ -110,7 +110,7 @@ async def startup_event():
# 初始化Redis连接
try:
from services.redis_task_manager import redis_task_manager
from shared.services.redis_task_manager import redis_task_manager
await redis_task_manager.connect()
if redis_task_manager.is_connected:
print("[OK] Redis连接成功")
@@ -124,7 +124,7 @@ async def startup_event():
async def shutdown_event():
"""应用关闭时清理资源"""
try:
from services.redis_task_manager import redis_task_manager
from shared.services.redis_task_manager import redis_task_manager
await redis_task_manager.disconnect()
print("[OK] Redis连接已断开")
except Exception as e:
@@ -154,27 +154,16 @@ app.include_router(auth_router)
app.include_router(inventory_router)
app.include_router(aluminum_price_router, prefix="/api")
try:
from api.v1 import router as moldinsight_router
except Exception as e:
moldinsight_router = None
print(f"[WARN] MoldInsight v1路由未加载: {e}")
if moldinsight_router is None:
try:
from api.routes import router as moldinsight_router
print("[WARN] 已回退到旧版 MoldInsight 路由")
except Exception as fallback_error:
moldinsight_router = None
print(f"[WARN] MoldInsight旧版路由也未加载: {fallback_error}")
if moldinsight_router is not None:
from moldinsight.api import router as moldinsight_router
app.include_router(moldinsight_router, prefix="/api")
except Exception as e:
print(f"[WARN] MoldInsight 路由未加载: {e}")
@app.get("/health")
@app.post("/health")
async def health():
from database.database import db_manager
from shared.database.database import db_manager
from sqlalchemy import text
db_ok = False
db_error = None
@@ -246,7 +235,7 @@ async def release():
if __name__ == "__main__":
import uvicorn
from config.settings import settings
from shared.config.settings import settings
reload_enabled = os.getenv("UVICORN_RELOAD", "0").lower() in {"1", "true", "yes", "on"}
print("启动 Gemold 模具制造管理系统 v4.0...")
View File
@@ -1,7 +1,7 @@
from fastapi import APIRouter
import importlib
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -19,10 +19,10 @@ def _safe_include(module_path: str, label: str):
logger.warning(f"{label} 路由加载失败,已跳过: {exc}")
_safe_include("api.v1.health_router", "健康检查")
_safe_include("api.v1.upload_router", "上传")
_safe_include("api.v1.task_router", "任务")
_safe_include("api.v1.history_router", "历史")
_safe_include("api.v1.debug_router", "调试")
_safe_include("api.v1.cam_router", "CAM")
_safe_include("api.v1.advanced_router", "高级")
_safe_include("moldinsight.api.health_router", "健康检查")
_safe_include("moldinsight.api.upload_router", "上传")
_safe_include("moldinsight.api.task_router", "任务")
_safe_include("moldinsight.api.history_router", "历史")
_safe_include("moldinsight.api.debug_router", "调试")
_safe_include("moldinsight.api.cam_router", "CAM")
_safe_include("moldinsight.api.advanced_router", "高级")
@@ -7,16 +7,16 @@ from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from services.auth_service import get_current_active_user
from services.redis_task_manager import redis_task_manager
from services.processing_service import processing_service
from services.storage_integration_rustfs import StorageIntegrationService
from services.task_query_service import TaskQueryService
from database.database import get_db_session
from models.database import User
from models.database import ProcessingTask, STPFile
from core.cad_exporter import CADExporter
from utils.logger import get_logger
from shared.services.auth_service import get_current_active_user
from shared.services.redis_task_manager import redis_task_manager
from moldinsight.services.processing_service import processing_service
from moldinsight.services.storage_integration_rustfs import StorageIntegrationService
from moldinsight.services.task_query_service import TaskQueryService
from shared.database.database import get_db_session
from shared.models.database import User
from shared.models.database import ProcessingTask, STPFile
from moldinsight.core.cad_exporter import CADExporter
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -216,7 +216,7 @@ async def design_cooling_system(
material = body.get("material", "ABS")
cavity_count = body.get("cavity_count", 1)
cycle_time_target = body.get("cycle_time_target")
from core.mold_system_designer import CoolingSystemDesigner
from moldinsight.core.mold_system_designer import CoolingSystemDesigner
designer = CoolingSystemDesigner()
result = designer.design_cooling_system(
mold_size=mold_size, product_bbox=product_bbox,
@@ -237,7 +237,7 @@ async def design_gating_system(
cavity_count = body.get("cavity_count", 1)
gate_type = body.get("gate_type", "auto")
layout_positions = body.get("layout_positions")
from core.mold_system_designer import GatingSystemDesigner
from moldinsight.core.mold_system_designer import GatingSystemDesigner
designer = GatingSystemDesigner()
result = designer.design_gating_system(
product_bbox=product_bbox, material=material,
@@ -287,7 +287,7 @@ async def ai_parting_surface_detect(
geometry_data = task_data.get("geometry_data")
if not geometry_data:
raise HTTPException(400, "该任务尚未完成几何分析")
from core.ai_parting_detector import AIPartingSurfaceDetectorV2
from moldinsight.core.ai_parting_detector import AIPartingSurfaceDetectorV2
detector = AIPartingSurfaceDetectorV2(use_gnn=True)
result = detector._detect_with_geometry(None, geometry_data)
return {"status": "success", "data": result}
@@ -6,7 +6,7 @@
不需要认证,公开访问。
"""
from fastapi import APIRouter, Query
from services.aluminum_price_service import get_aluminum_current_price, get_aluminum_price_history
from moldinsight.services.aluminum_price_service import get_aluminum_current_price, get_aluminum_price_history
router = APIRouter(prefix="/aluminum-price", tags=["铝金属价格"])
@@ -3,12 +3,12 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from datetime import datetime
from database.database import get_db_session
from models.database import User, ProcessingTask
from services.auth_service import get_current_active_user
from services.cam_bundle_service import cam_bundle_service
from services.task_query_service import TaskQueryService
from utils.logger import get_logger
from shared.database.database import get_db_session
from shared.models.database import User, ProcessingTask
from shared.services.auth_service import get_current_active_user
from moldinsight.services.cam_bundle_service import cam_bundle_service
from moldinsight.services.task_query_service import TaskQueryService
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -1,7 +1,7 @@
# api/v1/debug_router.py
from fastapi import APIRouter
from services.redis_task_manager import redis_task_manager
from shared.services.redis_task_manager import redis_task_manager
router = APIRouter()
@@ -1,7 +1,7 @@
# api/v1/health_router.py
from fastapi import APIRouter
from services.redis_task_manager import redis_task_manager
from shared.services.redis_task_manager import redis_task_manager
router = APIRouter()
@@ -2,8 +2,8 @@
from fastapi import APIRouter, Depends
import urllib.parse
from services.storage_integration_rustfs import StorageIntegrationService
from database.database import get_db_session
from moldinsight.services.storage_integration_rustfs import StorageIntegrationService
from shared.database.database import get_db_session
from sqlalchemy.ext.asyncio import AsyncSession
router = APIRouter()
@@ -4,10 +4,10 @@ from fastapi import APIRouter, HTTPException, Request, Depends
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from services.task_query_service import TaskQueryService
from database.database import get_db_session
from utils.logger import get_logger
from models.database import ProcessingTask, STPFile
from moldinsight.services.task_query_service import TaskQueryService
from shared.database.database import get_db_session
from shared.utils.logger import get_logger
from shared.models.database import ProcessingTask, STPFile
logger = get_logger(__name__)
@@ -4,15 +4,15 @@ import uuid
from datetime import datetime
from pathlib import Path
from models.schemas import ProcessingStatus, create_task_info
from utils.file_handler import FileHandler
from services.storage_integration_rustfs import StorageIntegrationService
from services.redis_task_manager import redis_task_manager
from database.database import get_db_session
from utils.logger import get_logger
from shared.models.schemas import ProcessingStatus, create_task_info
from shared.utils.file_handler import FileHandler
from moldinsight.services.storage_integration_rustfs import StorageIntegrationService
from shared.services.redis_task_manager import redis_task_manager
from shared.database.database import get_db_session
from shared.utils.logger import get_logger
from sqlalchemy.ext.asyncio import AsyncSession
from services.auth_service import get_current_active_user
from models.database import User
from shared.services.auth_service import get_current_active_user
from shared.models.database import User
try:
from celery_tasks import process_stp_task
@@ -101,7 +101,7 @@ async def upload_stp(
logger.info(f"[UPLOAD] Celery 任务已调度: task_id={task_id}")
else:
import asyncio
from services.processing_service import processing_service
from moldinsight.services.processing_service import processing_service
asyncio.create_task(processing_service.process_file_with_storage(
task_id, str(file_path), stp_file.id, process_params
))
@@ -195,7 +195,7 @@ if __name__ == "__main__":
draft_analyzer = AIDraftAnalyzer(model_path="models/draft_analysis.pth")
# 2. 设置到 MoldCavityGenerator
from core.mold_generator import MoldCavityGenerator
from moldinsight.core.mold_generator import MoldCavityGenerator
generator = MoldCavityGenerator()
generator.set_ai_model(
@@ -23,7 +23,7 @@ GNN 模型:
from typing import Dict, List, Any, Optional, Tuple
import numpy as np
from OCC.Core.TopoDS import TopoDS_Shape
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -25,10 +25,10 @@ from OCC.Core.BRepBndLib import brepbndlib
from OCC.Core.GProp import GProp_GProps
from OCC.Core.BRepGProp import brepgprop
from models.schemas import create_mold_cavity_data, create_mold_key_info
from utils.logger import get_logger
from core.base_mold_generator import BaseMoldGenerator
from core.side_action_designer import SideActionDesigner
from shared.models.schemas import create_mold_cavity_data, create_mold_key_info
from shared.utils.logger import get_logger
from moldinsight.core.base_mold_generator import BaseMoldGenerator
from moldinsight.core.side_action_designer import SideActionDesigner
logger = get_logger(__name__)
@@ -18,8 +18,8 @@ from OCC.Core.Bnd import Bnd_Box
from OCC.Core.BRepBndLib import brepbndlib
from OCC.Core.TopLoc import TopLoc_Location
from models.schemas import create_mold_cavity_data, create_mold_key_info
from utils.logger import get_logger
from shared.models.schemas import create_mold_cavity_data, create_mold_key_info
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -30,7 +30,7 @@ import re
from typing import Dict, List, Any, Optional, Tuple
from pathlib import Path
from OCC.Core.TopoDS import TopoDS_Shape
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -20,7 +20,7 @@
from typing import Dict, List, Any, Optional, Tuple
import math
import numpy as np
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -3,12 +3,12 @@ import math
from concurrent.futures import ThreadPoolExecutor, as_completed
import numpy as np
from OCC.Core.TopoDS import TopoDS_Shape
from models.schemas import (
from shared.models.schemas import (
create_mold_feature,
create_design_recommendation,
create_analysis_result
)
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -19,7 +19,7 @@
from typing import Dict, List, Any, Optional, Tuple
import math
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -9,10 +9,10 @@ from OCC.Core.TopAbs import TopAbs_FACE
from OCC.Core.Bnd import Bnd_Box
from OCC.Core.BRepBndLib import brepbndlib
from models.schemas import create_mold_cavity_data, create_mold_key_info
from utils.logger import get_logger
from core.base_mold_generator import BaseMoldGenerator
from core.side_action_designer import SideActionDesigner
from shared.models.schemas import create_mold_cavity_data, create_mold_key_info
from shared.utils.logger import get_logger
from moldinsight.core.base_mold_generator import BaseMoldGenerator
from moldinsight.core.side_action_designer import SideActionDesigner
logger = get_logger(__name__)
@@ -29,7 +29,7 @@
from typing import Dict, List, Any, Optional, Tuple
import math
import numpy as np
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -7,7 +7,7 @@
from typing import Dict, List, Any
import numpy as np
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -16,7 +16,7 @@
from typing import Dict, List, Any, Optional
import math
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -8,11 +8,11 @@ from OCC.Core.TopAbs import TopAbs_FACE
from OCC.Core.TopExp import TopExp_Explorer
from OCC.Core.TopoDS import TopoDS_Face, TopoDS_Shape, topods
from core.mold_generator import MoldCavityGenerator
from core.aluminum_foam_mold import AluminumFoamMoldGenerator
from core.parting_candidate_generator import PartingCandidateGenerator
from core.parting_scheme_scorer import PartingSchemeScorer
from utils.logger import get_logger
from moldinsight.core.mold_generator import MoldCavityGenerator
from moldinsight.core.aluminum_foam_mold import AluminumFoamMoldGenerator
from moldinsight.core.parting_candidate_generator import PartingCandidateGenerator
from moldinsight.core.parting_scheme_scorer import PartingSchemeScorer
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -22,7 +22,7 @@ from typing import Dict, List, Any, Optional, Tuple
import math
import numpy as np
from OCC.Core.TopoDS import TopoDS_Shape, TopoDS_Face
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -3,7 +3,7 @@ from pathlib import Path
from typing import Dict, Any, Optional, List
import numpy as np
import json
from utils.logger import get_logger
from shared.utils.logger import get_logger
from OCC.Core.GProp import GProp_GProps
from OCC.Core.BRepGProp import brepgprop
from OCC.Core.TopoDS import TopoDS_Shape
@@ -371,7 +371,7 @@ class CalculationService:
material_name: str,
) -> Dict[str, Any]:
"""为每个候选方案补充注塑模冷却/浇注摘要。"""
from core.mold_system_designer import MoldSystemDesigner
from moldinsight.core.mold_system_designer import MoldSystemDesigner
designer = MoldSystemDesigner()
for scheme in plan_result.get("candidate_schemes", []):
@@ -1,6 +1,6 @@
from typing import Dict, Any, List, Optional
from core.mold_cam import MoldCAMDesigner
from moldinsight.core.mold_cam import MoldCAMDesigner
class CAMBundleService:
@@ -15,8 +15,8 @@ from typing import Optional, Dict, Any, List
import httpx
from config.settings import settings
from utils.logger import get_logger
from shared.config.settings import settings
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -11,23 +11,23 @@ from typing import Optional, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from core.stp_parser import STPParser
from core.geometry_analyzer import GeometryAnalyzer
from core.mold_generator import MoldCavityGenerator
from core.aluminum_foam_mold import AluminumFoamMoldGenerator
from core.mold_quality_inspector import AluminumFoamMoldQualityInspector
from core.mesh_generator import MeshGenerator
from core.multi_scheme_planner import MultiSchemeMoldPlanner
from core.cad_exporter import CADExporter
from services.storage_integration_rustfs import StorageIntegrationService
from services.redis_task_manager import redis_task_manager
from services.material_service import MaterialService
from services.calculation_service import CalculationService
from services.llm_service import llm_service
from models.schemas import ProcessingStatus
from database.database import db_manager
from utils.html_generator import HTMLGenerator
from utils.logger import get_logger
from moldinsight.core.stp_parser import STPParser
from moldinsight.core.geometry_analyzer import GeometryAnalyzer
from moldinsight.core.mold_generator import MoldCavityGenerator
from moldinsight.core.aluminum_foam_mold import AluminumFoamMoldGenerator
from moldinsight.core.mold_quality_inspector import AluminumFoamMoldQualityInspector
from moldinsight.core.mesh_generator import MeshGenerator
from moldinsight.core.multi_scheme_planner import MultiSchemeMoldPlanner
from moldinsight.core.cad_exporter import CADExporter
from moldinsight.services.storage_integration_rustfs import StorageIntegrationService
from shared.services.redis_task_manager import redis_task_manager
from moldinsight.services.material_service import MaterialService
from moldinsight.services.calculation_service import CalculationService
from moldinsight.services.llm_service import llm_service
from shared.models.schemas import ProcessingStatus
from shared.database.database import db_manager
from shared.utils.html_generator import HTMLGenerator
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -65,7 +65,7 @@ class ProcessingService:
try:
logger.info(f"开始处理文件并生成模具型腔: {file_path}")
from config.settings import settings
from shared.config.settings import settings
file_size_bytes = Path(file_path).stat().st_size if Path(file_path).exists() else 0
file_size_mb = max(file_size_bytes / (1024 * 1024), 1)
@@ -550,7 +550,7 @@ class ProcessingService:
task_id: str, stp_file_id: int, analysis_result: Optional[dict],
) -> Optional[Dict[str, Any]]:
"""FreeCAD 几何验证(可通过配置禁用)"""
from config.settings import settings
from shared.config.settings import settings
if not settings.ENABLE_FREECAD_VERIFICATION:
logger.info("FreeCAD验证已禁用(设置 ENABLE_FREECAD_VERIFICATION=true 启用)")
@@ -561,7 +561,7 @@ class ProcessingService:
)
try:
from services.verification_service import GeometryVerificationService
from moldinsight.services.verification_service import GeometryVerificationService
verification_svc = GeometryVerificationService(timeout=settings.FREECAD_VERIFICATION_TIMEOUT)
verification_result = await verification_svc.verify_stp_file(file_path)
@@ -611,7 +611,7 @@ class ProcessingService:
async def _save_analysis_metrics(self, session: AsyncSession, stp_file_id: int, analysis_result: dict):
"""保存分析指标到数据库"""
from models.database import AnalysisMetrics
from shared.models.database import AnalysisMetrics
quality_metrics = analysis_result.get("quality_metrics", {})
analysis_summary = analysis_result.get("analysis_summary", "")
@@ -630,7 +630,7 @@ class ProcessingService:
async def _save_verification_metrics(self, session: AsyncSession, stp_file_id: int, verification_result: dict):
"""保存验证指标到数据库"""
from models.database import AnalysisMetrics
from shared.models.database import AnalysisMetrics
from sqlalchemy import select
result = await session.execute(
@@ -6,14 +6,14 @@ from pathlib import Path
from typing import Optional, Dict, Any
import json
from models.database import (
from shared.models.database import (
STPFile, GeometryData, MoldCavityData,
HTMLFile, ProcessingTask, User,
FeatureDetection, DesignRecommendation,
UserActivity, SystemLog
)
from storage.object_storage import storage_manager
from utils.logger import get_logger
from moldinsight.storage.object_storage import storage_manager
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -8,14 +8,14 @@ import json
from datetime import datetime
import uuid
from models.database import (
from shared.models.database import (
STPFile, GeometryData, MeshData, MoldCavityData,
HTMLFile, ProcessingTask, User,
FeatureDetection, DesignRecommendation,
UserActivity, SystemLog
)
from storage.rustfs_storage import rustfs_manager
from utils.logger import get_logger
from moldinsight.storage.rustfs_storage import rustfs_manager
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -662,7 +662,7 @@ class StorageIntegrationService:
limit: int = 50
) -> list:
"""获取同一文件名的所有上传历史记录"""
from models.database import ProcessingTask
from shared.models.database import ProcessingTask
from sqlalchemy.orm import joinedload
query = select(STPFile).options(
@@ -705,7 +705,7 @@ class StorageIntegrationService:
from sqlalchemy import func, desc
from sqlalchemy.orm import joinedload
from models.database import ProcessingTask
from shared.models.database import ProcessingTask
# 子查询:获取每个文件名的最新上传
subquery = (
@@ -7,10 +7,10 @@ import json
from pathlib import Path
from typing import Optional, Dict, Any
from models.database import STPFile, GeometryData, HTMLFile, ProcessingTask
from utils.logger import get_logger
from shared.models.database import STPFile, GeometryData, HTMLFile, ProcessingTask
from shared.utils.logger import get_logger
from models.database import MoldCavityData
from shared.models.database import MoldCavityData
logger = get_logger(__name__)
@@ -7,10 +7,10 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload
from services.storage_integration_rustfs import StorageIntegrationService
from services.redis_task_manager import redis_task_manager
from models.database import ProcessingTask, STPFile, MeshData, HTMLFile
from utils.logger import get_logger
from moldinsight.services.storage_integration_rustfs import StorageIntegrationService
from shared.services.redis_task_manager import redis_task_manager
from shared.models.database import ProcessingTask, STPFile, MeshData, HTMLFile
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -11,7 +11,7 @@ from pathlib import Path
from typing import Dict, Any, Optional
from datetime import datetime
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -10,9 +10,9 @@ src_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
sys.path.insert(0, str(src_root))
from storage.rustfs_storage import rustfs_manager
from config.settings import settings
from utils.logger import get_logger
from moldinsight.storage.rustfs_storage import rustfs_manager
from shared.config.settings import settings
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -5,7 +5,7 @@ from minio.error import S3Error
from pathlib import Path
from typing import Optional, BinaryIO
from io import BytesIO
from utils.logger import get_logger
from shared.utils.logger import get_logger
import hashlib
import uuid
@@ -5,7 +5,7 @@ from minio.error import S3Error
from pathlib import Path
from typing import Optional, Dict, Any
from io import BytesIO
from utils.logger import get_logger
from shared.utils.logger import get_logger
from datetime import timedelta
import hashlib
import uuid
+5 -5
View File
@@ -8,11 +8,11 @@ sys.path.insert(0, str(project_root))
sys.path.insert(0, str(src_root))
from sqlalchemy import select
from database.database import db_manager
from models.database import User, Role, UserRole
from services.auth_service import get_password_hash
from config.settings import settings
from utils.logger import get_logger
from shared.database.database import db_manager
from shared.models.database import User, Role, UserRole
from shared.services.auth_service import get_password_hash
from shared.config.settings import settings
from shared.utils.logger import get_logger
logger = get_logger(__name__)
View File
View File
@@ -1,18 +1,15 @@
# database/database.py
# shared/database/database.py
import sys
import os
from pathlib import Path
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy import text
from sqlalchemy.orm import sessionmaker
from config.settings import settings
from shared.config.settings import settings
import asyncio
from contextlib import asynccontextmanager
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -1,19 +1,12 @@
import asyncio
import sys
from pathlib import Path
from sqlalchemy import text
project_root = Path(__file__).parent.parent.parent
src_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
sys.path.insert(0, str(src_root))
from sqlalchemy import select
from database.database import db_manager
from models.database import User, Role, Permission, UserRole, RolePermission
from services.auth_service import get_password_hash
from config.settings import settings
from utils.logger import get_logger
from sqlalchemy import text, select
from shared.database.database import db_manager
from shared.models.database import User, Role, Permission, UserRole, RolePermission
from shared.services.auth_service import get_password_hash
from shared.config.settings import settings
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -1,20 +1,8 @@
"""数据库迁移脚本 - 删除旧表并重新创建"""
import asyncio
import sys
import os
from pathlib import Path
# 添加项目根目录到路径
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))
sys.path.insert(0, str(Path(__file__).parent.parent))
# 设置环境变量确保正确导入
os.environ['PYTHONPATH'] = str(project_root) + os.pathsep + str(Path(__file__).parent.parent)
from src.database.database import db_manager
from src.models.database import Base
from src.utils.logger import get_logger
from shared.database.database import db_manager
from shared.models.database import Base
from shared.utils.logger import get_logger
logger = get_logger(__name__)
View File
@@ -7,16 +7,16 @@ from datetime import timedelta
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from database.database import get_db_session
from services.auth_service import (
from shared.database.database import get_db_session
from shared.services.auth_service import (
authenticate_user,
create_access_token,
get_current_active_user,
get_password_hash
)
from models.database import User, Role, Permission, UserRole, RolePermission
from config.settings import settings
from utils.logger import get_logger
from shared.models.database import User, Role, Permission, UserRole, RolePermission
from shared.config.settings import settings
from shared.utils.logger import get_logger
logger = get_logger(__name__)
router = APIRouter(prefix="/api/auth", tags=["认证"])
@@ -8,10 +8,10 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from config.settings import settings
from database.database import get_db_session
from models.database import User, UserRole
from utils.logger import get_logger
from shared.config.settings import settings
from shared.database.database import get_db_session
from shared.models.database import User, UserRole
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -8,7 +8,7 @@ from datetime import datetime
import redis.asyncio as aioredis
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)
@@ -2,7 +2,7 @@
from pathlib import Path
from typing import Dict, Any, Optional
from datetime import datetime
from utils.logger import get_logger
from shared.utils.logger import get_logger
logger = get_logger(__name__)