2026-09-21 15:56:52 +08:00
|
|
|
|
"""用户列表 — 对接 MOM sys_user"""
|
|
|
|
|
|
from fastapi import APIRouter, Query, HTTPException, status
|
|
|
|
|
|
from pydantic import BaseModel
|
2026-09-21 16:10:52 +08:00
|
|
|
|
from app.core.config import settings
|
2026-09-21 15:56:52 +08:00
|
|
|
|
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),
|
2026-09-21 16:10:52 +08:00
|
|
|
|
dept: str = Query("", description="已废弃:部门由服务端按 ORG_DEPARTMENT 钉死,此参数不参与过滤"),
|
2026-09-21 15:56:52 +08:00
|
|
|
|
):
|
2026-09-21 16:10:52 +08:00
|
|
|
|
"""获取 MOM 系统用户列表,只返回本部门(ORG_DEPARTMENT)人员"""
|
|
|
|
|
|
# 部门隔离由服务端钉死:无论客户端传什么(含旧版 App 里写死的 dept=IRIS),
|
|
|
|
|
|
# 一律只按 ORG_DEPARTMENT 过滤。这样同一份 App 源码不必按部门分叉。
|
|
|
|
|
|
#
|
|
|
|
|
|
# 这里刻意【不做】「查询异常就退回全表」的降级:那等于把另一个部门的人员
|
|
|
|
|
|
# 名单也列出来供本部门挑选,是跨部门数据泄漏。查不出来就报错 ——
|
|
|
|
|
|
# 宁可查不出,不可查过头。
|
2026-09-21 15:56:52 +08:00
|
|
|
|
db = MomSessionLocal()
|
|
|
|
|
|
try:
|
2026-09-21 16:10:52 +08:00
|
|
|
|
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()
|
2026-09-21 15:56:52 +08:00
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
]
|
2026-09-21 16:10:52 +08:00
|
|
|
|
except HTTPException:
|
|
|
|
|
|
raise
|
2026-09-21 15:56:52 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
|
status_code=status.HTTP_502_BAD_GATEWAY,
|
|
|
|
|
|
detail=f"MOM 用户查询失败: {str(e)}",
|
|
|
|
|
|
)
|
|
|
|
|
|
finally:
|
|
|
|
|
|
db.close()
|