2026-05-06 17:43:47 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from typing import Annotated
|
|
|
|
|
|
2026-05-07 11:50:10 +08:00
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
2026-05-06 17:43:47 +08:00
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
|
|
|
|
from app.api.deps import get_db
|
2026-05-11 05:18:16 +00:00
|
|
|
from app.schemas.common import ErrorResponse
|
2026-05-07 13:48:00 +08:00
|
|
|
from app.schemas.employee import EmployeeCreate, EmployeeMetaRead, EmployeeRead, EmployeeUpdate
|
2026-05-06 17:43:47 +08:00
|
|
|
from app.services.employee import EmployeeService
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
DbSession = Annotated[Session, Depends(get_db)]
|
|
|
|
|
|
|
|
|
|
|
2026-05-11 05:18:16 +00:00
|
|
|
@router.get(
|
|
|
|
|
"/meta",
|
|
|
|
|
response_model=EmployeeMetaRead,
|
|
|
|
|
summary="读取员工目录元数据",
|
|
|
|
|
description="返回员工总数、状态汇总和可选角色列表,供员工管理页面初始化使用。",
|
|
|
|
|
)
|
2026-05-07 11:50:10 +08:00
|
|
|
def get_employee_meta(db: DbSession) -> EmployeeMetaRead:
|
|
|
|
|
return EmployeeService(db).get_employee_meta()
|
|
|
|
|
|
|
|
|
|
|
2026-05-11 05:18:16 +00:00
|
|
|
@router.get(
|
|
|
|
|
"",
|
|
|
|
|
response_model=list[EmployeeRead],
|
|
|
|
|
summary="查询员工列表",
|
|
|
|
|
description="按状态和关键字筛选员工目录。",
|
|
|
|
|
)
|
2026-05-07 11:50:10 +08:00
|
|
|
def list_employees(
|
|
|
|
|
db: DbSession,
|
2026-05-11 05:18:16 +00:00
|
|
|
status_filter: Annotated[
|
|
|
|
|
str | None,
|
|
|
|
|
Query(alias="status", description="员工状态筛选值。"),
|
|
|
|
|
] = None,
|
|
|
|
|
keyword: Annotated[
|
|
|
|
|
str | None,
|
|
|
|
|
Query(description="姓名、工号、邮箱等关键字模糊查询。"),
|
|
|
|
|
] = None,
|
2026-05-07 11:50:10 +08:00
|
|
|
) -> list[EmployeeRead]:
|
|
|
|
|
return EmployeeService(db).list_employees(status=status_filter, keyword=keyword)
|
2026-05-06 17:43:47 +08:00
|
|
|
|
|
|
|
|
|
2026-05-11 05:18:16 +00:00
|
|
|
@router.post(
|
|
|
|
|
"",
|
|
|
|
|
response_model=EmployeeRead,
|
|
|
|
|
status_code=status.HTTP_201_CREATED,
|
|
|
|
|
summary="创建员工",
|
|
|
|
|
description="创建新的员工目录记录,并初始化基础角色与组织归属。",
|
|
|
|
|
responses={
|
|
|
|
|
status.HTTP_400_BAD_REQUEST: {
|
|
|
|
|
"model": ErrorResponse,
|
|
|
|
|
"description": "员工数据校验失败。",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
2026-05-06 17:43:47 +08:00
|
|
|
def create_employee(payload: EmployeeCreate, db: DbSession) -> EmployeeRead:
|
2026-05-07 11:50:10 +08:00
|
|
|
try:
|
|
|
|
|
return EmployeeService(db).create_employee(payload)
|
|
|
|
|
except ValueError as exc:
|
|
|
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
|
2026-05-06 17:43:47 +08:00
|
|
|
|
|
|
|
|
|
2026-05-11 05:18:16 +00:00
|
|
|
@router.get(
|
|
|
|
|
"/{employee_id}",
|
|
|
|
|
response_model=EmployeeRead,
|
|
|
|
|
summary="读取员工详情",
|
|
|
|
|
description="根据员工主键读取员工完整档案信息。",
|
|
|
|
|
responses={
|
|
|
|
|
status.HTTP_404_NOT_FOUND: {
|
|
|
|
|
"model": ErrorResponse,
|
|
|
|
|
"description": "员工不存在。",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
2026-05-06 17:43:47 +08:00
|
|
|
def get_employee(employee_id: str, db: DbSession) -> EmployeeRead:
|
|
|
|
|
employee = EmployeeService(db).get_employee(employee_id)
|
|
|
|
|
if employee is None:
|
|
|
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Employee not found")
|
|
|
|
|
return employee
|
2026-05-07 13:48:00 +08:00
|
|
|
|
|
|
|
|
|
2026-05-11 05:18:16 +00:00
|
|
|
@router.patch(
|
|
|
|
|
"/{employee_id}",
|
|
|
|
|
response_model=EmployeeRead,
|
|
|
|
|
summary="更新员工",
|
|
|
|
|
description="更新员工基础信息、角色、密码等可维护字段。",
|
|
|
|
|
responses={
|
|
|
|
|
status.HTTP_400_BAD_REQUEST: {
|
|
|
|
|
"model": ErrorResponse,
|
|
|
|
|
"description": "请求字段不合法。",
|
|
|
|
|
},
|
|
|
|
|
status.HTTP_404_NOT_FOUND: {
|
|
|
|
|
"model": ErrorResponse,
|
|
|
|
|
"description": "员工不存在。",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
2026-05-07 13:48:00 +08:00
|
|
|
def update_employee(employee_id: str, payload: EmployeeUpdate, db: DbSession) -> EmployeeRead:
|
|
|
|
|
try:
|
|
|
|
|
return EmployeeService(db).update_employee(employee_id, payload)
|
|
|
|
|
except LookupError as exc:
|
|
|
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
|
|
|
|
except ValueError as exc:
|
|
|
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
|
|
|
|
|
|
|
|
|
|
|
2026-05-11 05:18:16 +00:00
|
|
|
@router.post(
|
|
|
|
|
"/{employee_id}/disable",
|
|
|
|
|
response_model=EmployeeRead,
|
|
|
|
|
summary="停用员工",
|
|
|
|
|
description="将员工状态切换为停用,阻止其继续登录系统。",
|
|
|
|
|
responses={
|
|
|
|
|
status.HTTP_404_NOT_FOUND: {
|
|
|
|
|
"model": ErrorResponse,
|
|
|
|
|
"description": "员工不存在。",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
2026-05-07 13:48:00 +08:00
|
|
|
def disable_employee(employee_id: str, db: DbSession) -> EmployeeRead:
|
|
|
|
|
try:
|
|
|
|
|
return EmployeeService(db).disable_employee(employee_id)
|
|
|
|
|
except LookupError as exc:
|
|
|
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|