Enhance backend functionality and frontend UI
- Updated main.py to include authentication for brand, model, and OTA routers. - Added new OTA schemas in schemas.py for version management. - Enhanced model retrieval with sorting options in models.py. - Improved model update functionality to support multipart/form-data uploads. - Updated frontend layout and styles for a more modern look, including new font integration. - Implemented login route and authentication checks in router/index.js. - Added sorting capabilities in model table and improved file handling in model view. - Updated requirements.txt to include PyJWT for token management.
This commit is contained in:
+80
-36
@@ -1,10 +1,10 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Body, UploadFile, File, Form
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import asc, desc
|
||||
from typing import List, Optional
|
||||
import logging
|
||||
from database import get_db
|
||||
from models.model import Model
|
||||
from schemas import ModelCreate, ModelUpdate, ModelResponse
|
||||
from response import ApiResponse, PageData
|
||||
import requests
|
||||
import os
|
||||
@@ -36,18 +36,34 @@ def get_models(
|
||||
limit: int = Query(100, ge=1, le=1000, description="返回记录数"),
|
||||
brand_name: Optional[str] = Query(None, description="按品牌名称模糊查询"),
|
||||
name: Optional[str] = Query(None, description="按型号名称模糊查询"),
|
||||
sort_by: str = Query("id", description="排序字段:id 或 create_at"),
|
||||
sort_order: str = Query("desc", description="排序方向:asc 或 desc"),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取所有型号列表(支持按品牌名称和型号名称模糊查询)"""
|
||||
"""获取所有型号列表(支持按品牌名称和型号名称模糊查询;支持按 id、create_at 排序)"""
|
||||
try:
|
||||
logger.info(f"Getting models: skip={skip}, limit={limit}, brand_name={brand_name}, name={name}")
|
||||
logger.info(
|
||||
f"Getting models: skip={skip}, limit={limit}, brand_name={brand_name}, name={name}, "
|
||||
f"sort_by={sort_by}, sort_order={sort_order}"
|
||||
)
|
||||
query = db.query(Model)
|
||||
if brand_name:
|
||||
query = query.filter(Model.brand_name.like(f"%{brand_name}%"))
|
||||
if name:
|
||||
query = query.filter(Model.name.like(f"%{name}%"))
|
||||
|
||||
|
||||
total = query.count()
|
||||
|
||||
sort_columns = {"id": Model.id, "create_at": Model.create_at}
|
||||
order_col = sort_columns.get(sort_by, Model.id)
|
||||
order_dir = (sort_order or "desc").lower()
|
||||
if order_dir not in ("asc", "desc"):
|
||||
order_dir = "desc"
|
||||
if order_dir == "desc":
|
||||
query = query.order_by(desc(order_col))
|
||||
else:
|
||||
query = query.order_by(asc(order_col))
|
||||
|
||||
models = query.offset(skip).limit(limit).all()
|
||||
|
||||
logger.info(f"Found {len(models)} models, total={total}")
|
||||
@@ -149,43 +165,71 @@ def create_model(
|
||||
|
||||
|
||||
@router.put("/{model_id}", response_model=ApiResponse)
|
||||
def update_model(model_id: int, model: ModelUpdate, db: Session = Depends(get_db)):
|
||||
"""更新型号"""
|
||||
def update_model(
|
||||
model_id: int,
|
||||
brand_name: Optional[str] = Form(None),
|
||||
name: Optional[str] = Form(None),
|
||||
form: Optional[str] = Form(None),
|
||||
rig: Optional[str] = Form(None),
|
||||
source: Optional[str] = Form(None),
|
||||
eq_key: Optional[str] = Form(None),
|
||||
measurement_file: UploadFile = File(None),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""更新型号(与 POST 一致,支持 multipart/form-data,可选上传频响文件)"""
|
||||
try:
|
||||
logger.info(f"Updating model: id={model_id}, data={model.dict()}")
|
||||
logger.info(
|
||||
f"Updating model: id={model_id}, brand_name={brand_name}, name={name}, form={form}"
|
||||
)
|
||||
db_model = db.query(Model).filter(Model.id == model_id).first()
|
||||
if not db_model:
|
||||
logger.warning(f"Model not found: id={model_id}")
|
||||
return ApiResponse(code=2, msg="empty", data=None)
|
||||
|
||||
# 如果更新品牌或型号名称,检查是否冲突
|
||||
if model.brand_name or model.name:
|
||||
new_brand_name = model.brand_name or db_model.brand_name
|
||||
new_name = model.name or db_model.name
|
||||
|
||||
if new_brand_name != db_model.brand_name or new_name != db_model.name:
|
||||
existing = db.query(Model).filter(
|
||||
Model.brand_name == new_brand_name,
|
||||
Model.name == new_name
|
||||
).first()
|
||||
if existing:
|
||||
logger.warning(f"Model already exists: brand_name={new_brand_name}, name={new_name}")
|
||||
return ApiResponse(code=0, msg="该品牌下型号名称已存在", data=None)
|
||||
|
||||
# 更新字段
|
||||
if model.brand_name:
|
||||
db_model.brand_name = model.brand_name
|
||||
if model.name:
|
||||
db_model.name = model.name
|
||||
if model.form is not None:
|
||||
db_model.form = model.form
|
||||
if model.rig is not None:
|
||||
db_model.rig = model.rig
|
||||
if model.source is not None:
|
||||
db_model.source = model.source
|
||||
if model.eq_key is not None:
|
||||
db_model.eq_key = model.eq_key
|
||||
|
||||
|
||||
new_brand_name = db_model.brand_name if brand_name is None else brand_name
|
||||
new_name = db_model.name if name is None else name
|
||||
if new_brand_name != db_model.brand_name or new_name != db_model.name:
|
||||
existing = (
|
||||
db.query(Model)
|
||||
.filter(Model.brand_name == new_brand_name, Model.name == new_name)
|
||||
.first()
|
||||
)
|
||||
if existing:
|
||||
logger.warning(
|
||||
f"Model already exists: brand_name={new_brand_name}, name={new_name}"
|
||||
)
|
||||
return ApiResponse(code=0, msg="该品牌下型号名称已存在", data=None)
|
||||
|
||||
eff_source = db_model.source if source is None else source
|
||||
eff_form = db_model.form if form is None else form
|
||||
if measurement_file and measurement_file.filename:
|
||||
logger.info(f"Uploading measurement file: {measurement_file.filename}")
|
||||
file_ext = os.path.splitext(measurement_file.filename)[1].lower()
|
||||
if file_ext not in ALLOWED_EXTENSIONS:
|
||||
logger.error(f"Unsupported file format: {file_ext}")
|
||||
return ApiResponse(code=0, msg=f"不支持的文件格式:{file_ext}", data=None)
|
||||
if not eff_source or not eff_form:
|
||||
return ApiResponse(code=0, msg="上传频响文件需要来源与形式字段", data=None)
|
||||
save_dir = UPLOAD_FOLDER / eff_source / "data" / eff_form
|
||||
save_dir.mkdir(parents=True, exist_ok=True)
|
||||
file_path = save_dir / measurement_file.filename
|
||||
with open(file_path, "wb") as buffer:
|
||||
shutil.copyfileobj(measurement_file.file, buffer)
|
||||
logger.info(f"File saved: {file_path}")
|
||||
|
||||
if brand_name is not None:
|
||||
db_model.brand_name = brand_name
|
||||
if name is not None:
|
||||
db_model.name = name
|
||||
if form is not None:
|
||||
db_model.form = form
|
||||
if rig is not None:
|
||||
db_model.rig = rig
|
||||
if source is not None:
|
||||
db_model.source = source
|
||||
if eq_key is not None:
|
||||
db_model.eq_key = eq_key
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_model)
|
||||
logger.info(f"Model updated successfully: id={db_model.id}")
|
||||
|
||||
Reference in New Issue
Block a user