| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- """API - 商品参数模板管理"""
- from typing import Optional, Tuple, Dict, Any
- from fastapi import APIRouter, Depends, HTTPException, Query
- from sqlalchemy.orm import Session
- from app.core.database import get_db
- from app.core.auth import get_current_user
- from app.core.response import success_response, error_response
- from app.crud.product_parameter import product_parameter
- from app.schemas.product_parameter import (
- ProductParameterCreate,
- ProductParameterUpdate,
- ProductParameterResponse,
- ProductParameterListResponse,
- ProductParameterSimpleResponse
- )
- router = APIRouter(prefix="/web/admin/product-parameters", tags=["商品参数模板管理"])
- def require_admin(current_user: dict = Depends(get_current_user)):
- """验证运营人员权限"""
- if current_user.get("role") not in {"admin", "super_admin"}:
- raise HTTPException(status_code=403, detail="需要运营人员权限")
- return current_user
- def _resolve_payload_with_crypto_fallback(request: dict, current_user: dict) -> Tuple[Dict[str, Any], Optional[dict]]:
- """兼容明文/密文请求,返回业务 payload。失败时返回 error_response。"""
- req_dict = request if isinstance(request, dict) else {}
- # 若是密文信封,优先解密。
- if isinstance(req_dict, dict) and req_dict.get("enc") == 1 and req_dict.get("edata"):
- try:
- from app.core import api_crypto
- from app.core.config import settings
- ts = req_dict.get("ts")
- nonce = req_dict.get("nonce")
- edata = req_dict.get("edata")
- operator_user_id = current_user.get("user_id") if isinstance(current_user, dict) else None
- fixed_secret = getattr(settings, "API_ENCRYPT_FIXED_SECRET", "") or ""
- if not (fixed_secret and operator_user_id and ts is not None and nonce):
- return {}, error_response(400, "密文解析配置缺失")
- key = api_crypto.derive_key(
- fixed_secret=fixed_secret,
- user_id=str(operator_user_id),
- ts=int(ts),
- nonce=str(nonce),
- )
- plain = api_crypto.decrypt_json(str(edata), key)
- payload = plain.get("data", plain) if isinstance(plain, dict) else {}
- if isinstance(payload, dict):
- return payload, None
- return {}, error_response(400, "密文解密后数据格式错误")
- except Exception as exc:
- return {}, error_response(400, f"密文解密失败: {exc}")
- payload = req_dict.get("data", req_dict) if isinstance(req_dict, dict) else {}
- return (payload if isinstance(payload, dict) else {}), None
- @router.get("", response_model=dict)
- def list_parameters(
- page: int = Query(1, ge=1, description="页码"),
- pageSize: int = Query(10, ge=1, le=100, description="每页条数"),
- keyword: Optional[str] = Query(None, description="关键词搜索"),
- isActive: Optional[int] = Query(None, description="是否启用"),
- db: Session = Depends(get_db),
- current_user: dict = Depends(require_admin)
- ):
- """获取参数模板列表"""
- items, total = product_parameter.get_multi_paged(
- db,
- skip=(page - 1) * pageSize,
- limit=pageSize,
- keyword=keyword,
- is_active=isActive
- )
-
- return success_response({
- "list": [{
- "id": p.id,
- "name": p.name,
- "code": p.code,
- "paramType": p.param_type,
- "options": p.options,
- "placeholder": p.placeholder,
- "isRequired": p.is_required,
- "isActive": p.is_active,
- "sortOrder": p.sort_order,
- "remark": p.remark,
- "createAt": str(p.create_at) if p.create_at else None
- } for p in items],
- "total": total,
- "page": page,
- "pageSize": pageSize
- })
- @router.get("/simple", response_model=dict)
- def list_parameters_simple(
- db: Session = Depends(get_db),
- current_user: dict = Depends(require_admin)
- ):
- """获取参数模板简洁列表(用于下拉选择)"""
- items = product_parameter.get_active_all(db)
-
- return success_response({
- "list": [{
- "id": p.id,
- "name": p.name,
- "code": p.code,
- "paramType": p.param_type,
- "options": p.options
- } for p in items],
- "total": len(items)
- })
- @router.get("/{parameter_id}", response_model=dict)
- def get_parameter(
- parameter_id: str,
- db: Session = Depends(get_db),
- current_user: dict = Depends(require_admin)
- ):
- """获取参数详情"""
- param = product_parameter.get(db, parameter_id)
- if not param:
- return error_response(404, "参数不存在")
-
- return success_response({
- "id": param.id,
- "name": param.name,
- "code": param.code,
- "paramType": param.param_type,
- "options": param.options,
- "placeholder": param.placeholder,
- "isRequired": param.is_required,
- "isActive": param.is_active,
- "sortOrder": param.sort_order,
- "remark": param.remark,
- "createAt": str(param.create_at) if param.create_at else None
- })
- @router.post("", response_model=dict)
- def create_parameter(
- request: dict,
- db: Session = Depends(get_db),
- current_user: dict = Depends(require_admin)
- ):
- """创建参数模板"""
- payload, req_err = _resolve_payload_with_crypto_fallback(request, current_user)
- if req_err is not None:
- return req_err
- try:
- create_data = ProductParameterCreate.model_validate(payload)
- except Exception as exc:
- return error_response(400, f"参数错误: {exc}")
- # 检查编码是否已存在
- if product_parameter.code_exists(db, create_data.code):
- return error_response(400, "参数编码已存在")
-
- creator = {"user_id": current_user.get("user_id"), "real_name": current_user.get("real_name")}
- param = product_parameter.create(db, create_data.model_dump(), creator)
-
- return success_response({
- "id": param.id,
- "name": param.name,
- "code": param.code
- })
- @router.put("/{parameter_id}", response_model=dict)
- def update_parameter(
- parameter_id: str,
- request: dict,
- db: Session = Depends(get_db),
- current_user: dict = Depends(require_admin)
- ):
- """更新参数模板"""
- payload, req_err = _resolve_payload_with_crypto_fallback(request, current_user)
- if req_err is not None:
- return req_err
- try:
- update_data = ProductParameterUpdate.model_validate(payload)
- except Exception as exc:
- return error_response(400, f"参数错误: {exc}")
- # 检查编码是否已存在(排除自身)
- if update_data.code:
- if product_parameter.code_exists(db, update_data.code, exclude_id=parameter_id):
- return error_response(400, "参数编码已存在")
-
- updater = {"user_id": current_user.get("user_id"), "real_name": current_user.get("real_name")}
- param = product_parameter.update(db, parameter_id, update_data.model_dump(exclude_unset=True), updater)
-
- if not param:
- return error_response(404, "参数不存在")
-
- return success_response({
- "id": param.id,
- "name": param.name,
- "code": param.code
- })
- @router.delete("/{parameter_id}", response_model=dict)
- def delete_parameter(
- parameter_id: str,
- db: Session = Depends(get_db),
- current_user: dict = Depends(require_admin)
- ):
- """删除参数模板"""
- result = product_parameter.delete(db, parameter_id)
- if not result:
- return error_response(404, "参数不存在")
- return success_response({"message": "删除成功"})
|