"""运营端管理接口(租户、角色下拉等)""" from typing import Any, List, Optional from fastapi import APIRouter, Depends, Query from pydantic import BaseModel, ConfigDict, Field from sqlalchemy.orm import Session from app.core.database import get_db from app.core.menu_guard import require_admin_or_super_admin from app.core.response import success_response, error_response from app.crud import tenant as tenant_svc from app.models.models import SysRole from app.services.web_auth_roles import _map_role_name_to_web router = APIRouter(prefix="/web/admin", tags=["运营端管理"]) # --------------------------------------------------------------------------- # 角色下拉(用户弹窗等) # --------------------------------------------------------------------------- @router.get("/roles") async def list_roles_for_select( _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): """返回运营端角色下拉选项(label=库中角色名,value=Web 角色码)。""" rows: List[SysRole] = ( db.query(SysRole) .filter(SysRole.del_flag == 0, SysRole.status == "1") .order_by(SysRole.order_num.asc()) .all() ) seen: set[str] = set() out: List[dict] = [] for r in rows: name = (r.role_name or "").strip() if not name: continue code = _map_role_name_to_web(name) key = f"{code}:{name}" if key in seen: continue seen.add(key) out.append({"label": name, "value": code}) if not out: out = [ {"label": "超级管理员", "value": "super_admin"}, {"label": "运营管理员", "value": "admin"}, ] return success_response(out) # --------------------------------------------------------------------------- # 租户管理 # --------------------------------------------------------------------------- class TenantCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) tenant_no: str = Field(..., alias="tenantNo") tenant_name: str = Field(..., alias="tenantName") contact_name: Optional[str] = Field(None, alias="contactName") contact_phone: Optional[str] = Field(None, alias="contactPhone") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class TenantUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) tenant_no: Optional[str] = Field(None, alias="tenantNo") tenant_name: Optional[str] = Field(None, alias="tenantName") contact_name: Optional[str] = Field(None, alias="contactName") contact_phone: Optional[str] = Field(None, alias="contactPhone") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/tenants") async def list_tenants( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), keyword: Optional[str] = None, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): items, total = tenant_svc.list_tenants(db, page=page, page_size=pageSize, keyword=keyword) total_pages = tenant_svc.total_pages(total, pageSize) return success_response( { "list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": total_pages, } ) @router.post("/tenants") async def create_tenant( body: TenantCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: obj = tenant_svc.create_tenant( db, tenant_no=body.tenant_no, tenant_name=body.tenant_name, contact_name=body.contact_name, contact_phone=body.contact_phone, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(tenant_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/tenants/{tenant_id}") async def update_tenant( tenant_id: str, body: TenantUpdateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: payload: dict[str, Any] = body.model_dump(exclude_unset=True, by_alias=False) obj = tenant_svc.update_tenant( db, tenant_id, tenant_no=payload.get("tenant_no"), tenant_name=payload.get("tenant_name"), contact_name=payload.get("contact_name"), contact_phone=payload.get("contact_phone"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(tenant_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/tenants/{tenant_id}") async def delete_tenant( tenant_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_svc.soft_delete_tenant(db, tenant_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e))