"""运营端管理接口(租户、角色下拉等)""" 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.crud import dict_type as dict_type_svc from app.crud import dict_data as dict_data_svc from app.crud import dept as dept_svc from app.crud import site as site_svc from app.crud import post as post_svc from app.crud import item_unit as item_unit_svc from app.crud import express_company as express_company_svc from app.crud import menu as menu_svc from app.crud import role as role_svc from app.crud import user as user_svc from app.models.models import SysRole, SysUser 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)) # --------------------------------------------------------------------------- # Helper: resolve tenant_no from user context # --------------------------------------------------------------------------- def _get_tenant_no(db: Session, user: dict) -> str: user_id = user.get("user_id") if not user_id: return "zkxw" sys_user = db.query(SysUser).filter(SysUser.id == user_id).first() return (sys_user.tenant_no if sys_user else None) or "zkxw" # --------------------------------------------------------------------------- # 用户管理 # --------------------------------------------------------------------------- class UserCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) user_no: str = Field(..., alias="userNo") nick_name: str = Field(..., alias="nickName") password: str = Field(..., alias="password") dept_id: Optional[str] = Field(None, alias="deptId") email: Optional[str] = Field("", alias="email") phone_no: Optional[str] = Field("", alias="phoneNo") sex: Optional[str] = Field("0", alias="sex") avatar: Optional[str] = Field(None, alias="avatar") status: Optional[str] = Field("1", alias="status") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None role_ids: Optional[List[str]] = Field(None, alias="roleIds") post_ids: Optional[List[str]] = Field(None, alias="postIds") class UserUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) nick_name: Optional[str] = Field(None, alias="nickName") dept_id: Optional[str] = Field(None, alias="deptId") email: Optional[str] = Field(None, alias="email") phone_no: Optional[str] = Field(None, alias="phoneNo") sex: Optional[str] = Field(None, alias="sex") avatar: Optional[str] = Field(None, alias="avatar") status: Optional[str] = Field(None, alias="status") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None role_ids: Optional[List[str]] = Field(None, alias="roleIds") post_ids: Optional[List[str]] = Field(None, alias="postIds") @router.get("/users") async def list_users( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), keyword: Optional[str] = None, deptId: Optional[str] = Query(None, alias="deptId"), status: Optional[str] = None, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) items, total = user_svc.list_users( db, page=page, page_size=pageSize, keyword=keyword, dept_id=deptId, tenant_no=tenant_no, status=status, ) tp = user_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/users") async def create_user( body: UserCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) if user_svc.user_no_exists(db, body.user_no, tenant_no): return error_response(400, "用户账号已存在") obj = user_svc.create_user( db, user_no=body.user_no, nick_name=body.nick_name, password=body.password, dept_id=body.dept_id, email=body.email, phone_no=body.phone_no, sex=body.sex, avatar=body.avatar, status=body.status, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), role_ids=body.role_ids, post_ids=body.post_ids, ) return success_response(user_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/users/{user_id}") async def update_user( user_id: str, body: UserUpdateBody, 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 = user_svc.update_user( db, user_id, nick_name=payload.get("nick_name"), dept_id=payload.get("dept_id"), email=payload.get("email"), phone_no=payload.get("phone_no"), sex=payload.get("sex"), avatar=payload.get("avatar"), status=payload.get("status"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id_updater=user.get("user_id"), role_ids=payload.get("role_ids"), post_ids=payload.get("post_ids"), ) return success_response(user_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/users/{user_id}") async def delete_user( user_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: user_svc.soft_delete_user(db, user_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) @router.post("/users/{user_id}/reset-password") async def reset_user_password( user_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: user_svc.reset_password(db, user_id, "111111") return success_response(None, message="密码已重置为 111111") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 字典类型管理 # --------------------------------------------------------------------------- class DictTypeCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) dict_name: str = Field(..., alias="dictName") dict_type: str = Field(..., alias="dictType") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class DictTypeUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) dict_name: Optional[str] = Field(None, alias="dictName") dict_type: Optional[str] = Field(None, alias="dictType") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/dict-types") async def list_dict_types( 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), ): tenant_no = _get_tenant_no(db, user) items, total = dict_type_svc.list_dict_types( db, page=page, page_size=pageSize, keyword=keyword, tenant_no=tenant_no ) tp = dict_type_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/dict-types") async def create_dict_type( body: DictTypeCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = dict_type_svc.create_dict_type( db, dict_name=body.dict_name, dict_type=body.dict_type, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(dict_type_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/dict-types/{dict_type_id}") async def update_dict_type( dict_type_id: str, body: DictTypeUpdateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) payload: dict[str, Any] = body.model_dump(exclude_unset=True, by_alias=False) obj = dict_type_svc.update_dict_type( db, dict_type_id, dict_name=payload.get("dict_name"), dict_type=payload.get("dict_type"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), tenant_no=tenant_no, ) return success_response(dict_type_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/dict-types/{dict_type_id}") async def delete_dict_type( dict_type_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: dict_type_svc.soft_delete_dict_type(db, dict_type_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 字典数据管理 # --------------------------------------------------------------------------- class DictDataCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) dict_label: str = Field(..., alias="dictLabel") dict_value: str = Field(..., alias="dictValue") dict_type: str = Field(..., alias="dictType") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class DictDataUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) dict_label: Optional[str] = Field(None, alias="dictLabel") dict_value: Optional[str] = Field(None, alias="dictValue") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/dict-data") async def list_dict_data( page: int = Query(1, ge=1), pageSize: int = Query(10, ge=1, le=100, alias="pageSize"), dictType: Optional[str] = None, keyword: Optional[str] = None, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) items, total = dict_data_svc.list_dict_data( db, page=page, page_size=pageSize, dict_type_code=dictType, keyword=keyword, tenant_no=tenant_no ) tp = dict_data_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/dict-data") async def create_dict_data( body: DictDataCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = dict_data_svc.create_dict_data( db, dict_label=body.dict_label, dict_value=body.dict_value, dict_type=body.dict_type, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(dict_data_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/dict-data/{data_id}") async def update_dict_data( data_id: str, body: DictDataUpdateBody, 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 = dict_data_svc.update_dict_data( db, data_id, dict_label=payload.get("dict_label"), dict_value=payload.get("dict_value"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(dict_data_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/dict-data/{data_id}") async def delete_dict_data( data_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: dict_data_svc.soft_delete_dict_data(db, data_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) @router.get("/dict-data/options") async def dict_data_options( dictType: str = Query(..., alias="dictType"), user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) items = dict_data_svc.list_dict_data_options(db, dict_type_code=dictType, tenant_no=tenant_no) return success_response(items) # --------------------------------------------------------------------------- # 组织管理 # --------------------------------------------------------------------------- class DeptCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) parent_id: str = Field("0", alias="parentId") dept_name: str = Field(..., alias="deptName") dept_category_code: Optional[str] = Field(None, alias="deptCategoryCode") status: Optional[str] = Field("1") leader: Optional[str] = None leader_phone: Optional[str] = Field(None, alias="leaderPhone") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class DeptUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) dept_name: Optional[str] = Field(None, alias="deptName") dept_category_code: Optional[str] = Field(None, alias="deptCategoryCode") status: Optional[str] = None leader: Optional[str] = None leader_phone: Optional[str] = Field(None, alias="leaderPhone") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/depts") async def list_depts( keyword: Optional[str] = None, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) tree = dept_svc.list_depts_tree(db, keyword=keyword, tenant_no=tenant_no) return success_response(tree) @router.post("/depts") async def create_dept( body: DeptCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = dept_svc.create_dept( db, parent_id=body.parent_id, dept_name=body.dept_name, dept_category_code=body.dept_category_code, status=body.status, leader=body.leader, leader_phone=body.leader_phone, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(dept_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/depts/{dept_id}") async def update_dept( dept_id: str, body: DeptUpdateBody, 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 = dept_svc.update_dept( db, dept_id, dept_name=payload.get("dept_name"), dept_category_code=payload.get("dept_category_code"), status=payload.get("status"), leader=payload.get("leader"), leader_phone=payload.get("leader_phone"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(dept_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/depts/{dept_id}") async def delete_dept( dept_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: dept_svc.soft_delete_dept(db, dept_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 站点管理 # --------------------------------------------------------------------------- class SiteCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) site_name: str = Field(..., alias="siteName") site_code: str = Field(..., alias="siteCode") site_type: Optional[str] = Field(None, alias="siteType") status: Optional[str] = Field("1") address: Optional[str] = None contact_name: Optional[str] = Field(None, alias="contactName") contact_phone: Optional[str] = Field(None, alias="contactPhone") business_scope: Optional[str] = Field(None, alias="businessScope") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class SiteUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) site_name: Optional[str] = Field(None, alias="siteName") site_code: Optional[str] = Field(None, alias="siteCode") site_type: Optional[str] = Field(None, alias="siteType") status: Optional[str] = None address: Optional[str] = None contact_name: Optional[str] = Field(None, alias="contactName") contact_phone: Optional[str] = Field(None, alias="contactPhone") business_scope: Optional[str] = Field(None, alias="businessScope") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/sites") async def list_sites( 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), ): tenant_no = _get_tenant_no(db, user) items, total = site_svc.list_sites(db, page=page, page_size=pageSize, keyword=keyword, tenant_no=tenant_no) tp = site_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/sites") async def create_site( body: SiteCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = site_svc.create_site( db, site_name=body.site_name, site_code=body.site_code, site_type=body.site_type, status=body.status, address=body.address, contact_name=body.contact_name, contact_phone=body.contact_phone, business_scope=body.business_scope, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(site_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/sites/{site_id}") async def update_site( site_id: str, body: SiteUpdateBody, 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 = site_svc.update_site( db, site_id, site_name=payload.get("site_name"), site_code=payload.get("site_code"), site_type=payload.get("site_type"), status=payload.get("status"), address=payload.get("address"), contact_name=payload.get("contact_name"), contact_phone=payload.get("contact_phone"), business_scope=payload.get("business_scope"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(site_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/sites/{site_id}") async def delete_site( site_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: site_svc.soft_delete_site(db, site_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 职位管理 # --------------------------------------------------------------------------- class PostCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) post_name: str = Field(..., alias="postName") post_code: str = Field(..., alias="postCode") status: Optional[str] = Field("1") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class PostUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) post_name: Optional[str] = Field(None, alias="postName") post_code: Optional[str] = Field(None, alias="postCode") status: Optional[str] = None order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/posts") async def list_posts( 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), ): tenant_no = _get_tenant_no(db, user) items, total = post_svc.list_posts(db, page=page, page_size=pageSize, keyword=keyword, tenant_no=tenant_no) tp = post_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/posts") async def create_post( body: PostCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = post_svc.create_post( db, post_name=body.post_name, post_code=body.post_code, status=body.status, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(post_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/posts/{post_id}") async def update_post( post_id: str, body: PostUpdateBody, 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 = post_svc.update_post( db, post_id, post_name=payload.get("post_name"), post_code=payload.get("post_code"), status=payload.get("status"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(post_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/posts/{post_id}") async def delete_post( post_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: post_svc.soft_delete_post(db, post_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 物品单位管理 # --------------------------------------------------------------------------- class ItemUnitCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) unit_code: str = Field(..., alias="unitCode") unit_name: str = Field(..., alias="unitName") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class ItemUnitUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) unit_code: Optional[str] = Field(None, alias="unitCode") unit_name: Optional[str] = Field(None, alias="unitName") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/item-units") async def list_item_units( 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), ): tenant_no = _get_tenant_no(db, user) items, total = item_unit_svc.list_item_units(db, page=page, page_size=pageSize, keyword=keyword, tenant_no=tenant_no) tp = item_unit_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/item-units") async def create_item_unit( body: ItemUnitCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = item_unit_svc.create_item_unit( db, unit_code=body.unit_code, unit_name=body.unit_name, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(item_unit_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/item-units/{unit_id}") async def update_item_unit( unit_id: str, body: ItemUnitUpdateBody, 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 = item_unit_svc.update_item_unit( db, unit_id, unit_code=payload.get("unit_code"), unit_name=payload.get("unit_name"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(item_unit_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/item-units/{unit_id}") async def delete_item_unit( unit_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: item_unit_svc.soft_delete_item_unit(db, unit_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 快递公司管理 # --------------------------------------------------------------------------- class ExpressCompanyCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) express_code: str = Field(..., alias="expressCode") express_name: str = Field(..., alias="expressName") order_num: Optional[int] = Field(0, alias="orderNum") remark: Optional[str] = None class ExpressCompanyUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) express_code: Optional[str] = Field(None, alias="expressCode") express_name: Optional[str] = Field(None, alias="expressName") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/express-companies") async def list_express_companies( 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), ): tenant_no = _get_tenant_no(db, user) items, total = express_company_svc.list_express_companies(db, page=page, page_size=pageSize, keyword=keyword, tenant_no=tenant_no) tp = express_company_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/express-companies") async def create_express_company( body: ExpressCompanyCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = express_company_svc.create_express_company( db, express_code=body.express_code, express_name=body.express_name, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(express_company_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/express-companies/{company_id}") async def update_express_company( company_id: str, body: ExpressCompanyUpdateBody, 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 = express_company_svc.update_express_company( db, company_id, express_code=payload.get("express_code"), express_name=payload.get("express_name"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(express_company_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/express-companies/{company_id}") async def delete_express_company( company_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: express_company_svc.soft_delete_express_company(db, company_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 菜单管理 # --------------------------------------------------------------------------- class MenuCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) menu_name: str = Field(..., alias="menuName") parent_id: str = Field("0", alias="parentId") menu_type: str = Field("M", alias="menuType") path: Optional[str] = Field("", alias="path") component: Optional[str] = Field(None, alias="component") perms: Optional[str] = Field(None, alias="perms") is_frame: Optional[int] = Field(1, alias="isFrame") visible: Optional[str] = Field("1", alias="visible") status: Optional[str] = Field("1", alias="status") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None class MenuUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) menu_name: Optional[str] = Field(None, alias="menuName") parent_id: Optional[str] = Field(None, alias="parentId") menu_type: Optional[str] = Field(None, alias="menuType") path: Optional[str] = Field(None, alias="path") component: Optional[str] = Field(None, alias="component") perms: Optional[str] = Field(None, alias="perms") is_frame: Optional[int] = Field(None, alias="isFrame") visible: Optional[str] = Field(None, alias="visible") status: Optional[str] = Field(None, alias="status") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None @router.get("/menus") async def list_menus( keyword: Optional[str] = None, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): tenant_no = _get_tenant_no(db, user) tree = menu_svc.list_menus_tree(db, keyword=keyword, tenant_no=tenant_no) return success_response(tree) @router.post("/menus") async def create_menu( body: MenuCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = menu_svc.create_menu( db, menu_name=body.menu_name, parent_id=body.parent_id, menu_type=body.menu_type, path=body.path, component=body.component, perms=body.perms, is_frame=body.is_frame, visible=body.visible, status=body.status, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(menu_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/menus/{menu_id}") async def update_menu( menu_id: str, body: MenuUpdateBody, 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 = menu_svc.update_menu( db, menu_id, menu_name=payload.get("menu_name"), parent_id=payload.get("parent_id"), menu_type=payload.get("menu_type"), path=payload.get("path"), component=payload.get("component"), perms=payload.get("perms"), is_frame=payload.get("is_frame"), visible=payload.get("visible"), status=payload.get("status"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(menu_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/menus/{menu_id}") async def delete_menu( menu_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: menu_svc.soft_delete_menu(db, menu_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) # --------------------------------------------------------------------------- # 角色管理 # --------------------------------------------------------------------------- class RoleCreateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) role_name: str = Field(..., alias="roleName") data_scope: Optional[str] = Field("1", alias="dataScope") status: Optional[str] = Field("1", alias="status") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None class RoleUpdateBody(BaseModel): model_config = ConfigDict(populate_by_name=True) role_name: Optional[str] = Field(None, alias="roleName") data_scope: Optional[str] = Field(None, alias="dataScope") status: Optional[str] = Field(None, alias="status") order_num: Optional[int] = Field(None, alias="orderNum") remark: Optional[str] = None class RoleMenuBody(BaseModel): menu_ids: List[str] = Field(..., alias="menuIds") class RoleDataScopeBody(BaseModel): model_config = ConfigDict(populate_by_name=True) data_scope: str = Field(..., alias="dataScope") scope_details: Optional[List[dict]] = Field(None, alias="scopeDetails") @router.get("/role-management") async def list_role_management( 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), ): tenant_no = _get_tenant_no(db, user) items, total = role_svc.list_roles(db, page=page, page_size=pageSize, keyword=keyword, tenant_no=tenant_no) tp = role_svc.total_pages(total, pageSize) return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}) @router.post("/role-management") async def create_role_management( body: RoleCreateBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) obj = role_svc.create_role( db, role_name=body.role_name, data_scope=body.data_scope, status=body.status, tenant_no=tenant_no, order_num=body.order_num, remark=body.remark, user_id=user.get("user_id"), ) return success_response(role_svc._row_to_dict(obj), message="创建成功") except ValueError as e: return error_response(400, str(e)) @router.put("/role-management/{role_id}") async def update_role_management( role_id: str, body: RoleUpdateBody, 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 = role_svc.update_role( db, role_id, role_name=payload.get("role_name"), data_scope=payload.get("data_scope"), status=payload.get("status"), order_num=payload.get("order_num"), remark=payload.get("remark"), user_id=user.get("user_id"), ) return success_response(role_svc._row_to_dict(obj), message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.delete("/role-management/{role_id}") async def delete_role_management( role_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: role_svc.soft_delete_role(db, role_id) return success_response(None, message="删除成功") except ValueError as e: return error_response(400, str(e)) @router.get("/role-management/{role_id}/menus") async def get_role_menus( role_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): menu_ids = role_svc.get_role_menu_ids(db, role_id) return success_response({"menuIds": menu_ids}) @router.put("/role-management/{role_id}/menus") async def update_role_menus( role_id: str, body: RoleMenuBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) role_svc.update_role_menus(db, role_id, body.menu_ids, tenant_no, user_id=user.get("user_id")) return success_response(None, message="更新成功") except ValueError as e: return error_response(400, str(e)) @router.get("/role-management/{role_id}/data-scope") async def get_role_data_scope( role_id: str, _user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): role = role_svc.get_role(db, role_id) if not role: return error_response(404, "角色不存在") details = role_svc.get_role_data_scope(db, role_id) return success_response({"dataScope": role.data_scope or "1", "scopeDetails": details}) @router.put("/role-management/{role_id}/data-scope") async def update_role_data_scope( role_id: str, body: RoleDataScopeBody, user: dict = Depends(require_admin_or_super_admin), db: Session = Depends(get_db), ): try: tenant_no = _get_tenant_no(db, user) role_svc.update_role_data_scope( db, role_id, body.data_scope, body.scope_details, tenant_no=tenant_no, user_id=user.get("user_id"), ) return success_response(None, message="更新成功") except ValueError as e: return error_response(400, str(e))