from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.api.crud import crud_router from app.api.deps import get_current_user from app.core.database import get_db from app.core.security import hash_password from app.models import Announcement, Menu, Permission, Role, User from app.schemas.common import Page, ResponseModel from app.schemas.core import ( AnnouncementBase, AnnouncementOut, MenuBase, MenuOut, PermissionBase, PermissionOut, RoleBase, RoleOut, UserCreate, UserOut, UserUpdate, ) router = APIRouter(prefix="/core", tags=["基础管理"], dependencies=[Depends(get_current_user)]) @router.get("/users", response_model=Page[UserOut]) async def list_users( page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), keyword: str | None = None, db: AsyncSession = Depends(get_db), ): conditions = [User.is_deleted == False] if keyword: conditions.append((User.username.ilike(f"%{keyword}%")) | (User.email.ilike(f"%{keyword}%"))) query = select(User).where(*conditions) total = await db.scalar(select(func.count()).select_from(query.subquery())) result = await db.execute(query.order_by(User.created_at.desc()).offset((page - 1) * page_size).limit(page_size)) return Page(items=result.scalars().all(), total=total or 0, page=page, page_size=page_size) @router.post("/users", response_model=UserOut) async def create_user(payload: UserCreate, db: AsyncSession = Depends(get_db)): exists = await db.scalar(select(User.id).where((User.username == payload.username) | (User.email == payload.email))) if exists: raise HTTPException(status_code=400, detail="用户已存在") user = User(**payload.model_dump(exclude={"password"}), password_hash=hash_password(payload.password)) db.add(user) await db.commit() await db.refresh(user) return user @router.put("/users/{user_id}", response_model=UserOut) async def update_user(user_id: str, payload: UserUpdate, db: AsyncSession = Depends(get_db)): user = await db.get(User, user_id) if not user or user.is_deleted: raise HTTPException(status_code=404, detail="用户不存在") data = payload.model_dump(exclude_unset=True) password = data.pop("password", None) for key, value in data.items(): setattr(user, key, value) if password: user.password_hash = hash_password(password) await db.commit() await db.refresh(user) return user @router.delete("/users/{user_id}", response_model=ResponseModel) async def delete_user(user_id: str, db: AsyncSession = Depends(get_db)): user = await db.get(User, user_id) if not user or user.is_deleted: raise HTTPException(status_code=404, detail="用户不存在") user.is_deleted = True await db.commit() return ResponseModel(message="deleted") router.include_router( crud_router(prefix="/roles", tags=["角色"], model=Role, create_schema=RoleBase, update_schema=RoleBase, out_schema=RoleOut) ) router.include_router( crud_router( prefix="/permissions", tags=["权限"], model=Permission, create_schema=PermissionBase, update_schema=PermissionBase, out_schema=PermissionOut, ) ) router.include_router( crud_router(prefix="/menus", tags=["菜单"], model=Menu, create_schema=MenuBase, update_schema=MenuBase, out_schema=MenuOut) ) router.include_router( crud_router( prefix="/announcements", tags=["公告"], model=Announcement, create_schema=AnnouncementBase, update_schema=AnnouncementBase, out_schema=AnnouncementOut, ) )