"""用户列表 — 对接 MOM sys_user""" from fastapi import APIRouter, Query, HTTPException, status from pydantic import BaseModel from app.core.config import settings from app.core.mom_database import MomSessionLocal from sqlalchemy import text router = APIRouter(prefix="/users", tags=["用户"]) class UserOption(BaseModel): id: str username: str full_name: str department: str = "" model_config = {"from_attributes": True} @router.get("/", response_model=list[UserOption]) def list_users( keyword: str = Query("", description="按用户名/姓名模糊搜索"), limit: int = Query(100, ge=1, le=500), dept: str = Query("", description="已废弃:部门由服务端按 ORG_DEPARTMENT 钉死,此参数不参与过滤"), ): """获取 MOM 系统用户列表,只返回本部门(ORG_DEPARTMENT)人员""" # 部门隔离由服务端钉死:无论客户端传什么(含旧版 App 里写死的 dept=IRIS), # 一律只按 ORG_DEPARTMENT 过滤。这样同一份 App 源码不必按部门分叉。 # # 这里刻意【不做】「查询异常就退回全表」的降级:那等于把另一个部门的人员 # 名单也列出来供本部门挑选,是跨部门数据泄漏。查不出来就报错 —— # 宁可查不出,不可查过头。 db = MomSessionLocal() try: base_sql = """ SELECT id, username, SPLIT_PART(username, '/', 1) AS full_name, COALESCE(department, '') AS department FROM sys_user WHERE department = :dept """ params = {"dept": settings.ORG_DEPARTMENT, "lim": limit} if keyword.strip(): sql = text(base_sql + " AND username ILIKE :kw ORDER BY username LIMIT :lim") params["kw"] = f"%{keyword.strip()}%" else: sql = text(base_sql + " ORDER BY username LIMIT :lim") rows = db.execute(sql, params).fetchall() return [ UserOption( id=str(row.id), username=row.username.split("/")[-1] if "/" in row.username else row.username, full_name=row.full_name, department=row.department or "", ) for row in rows ] except HTTPException: raise except Exception as e: raise HTTPException( status_code=status.HTTP_502_BAD_GATEWAY, detail=f"MOM 用户查询失败: {str(e)}", ) finally: db.close()