✨ feat(vscode): 代码阅读函数、导入、常量、变量块预览改成属性表

This commit is contained in:
cruldra committed 2026-09-25 04:56:22 +08:00
1 parent 0c4c9b0fba
commit dd9b39ac5d
19 files changed
+1458 -213

No files matched your search

+126
View File
@@ -0,0 +1,126 @@
"""用户管理路由。
提供用户自助查看 / 更新资料与上传头像接口。
"""
from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends, File, UploadFile
from sqlalchemy.ext.asyncio import AsyncSession
from luffy_agent.core.db import get_db
from luffy_agent.core.exceptions import Forbidden
from luffy_agent.core.params import Int4Path
from luffy_agent.user.auth.deps import get_current_user
from .models import User, UserRole
from .schemas import (
UserAvatarUploadResponse,
UserDetailResponse,
UserUpdateRequest,
)
from .services import user_service
router = APIRouter(tags=["用户管理"], prefix="/users")
@router.get("/{user_id}", response_model=UserDetailResponse)
async def get_user(
user_id: Int4Path,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
) -> UserDetailResponse:
"""获取用户详情。
管理员可查看任意用户,普通用户只能查看自己。
"""
# 非管理员只能查看自己
if current_user.role != UserRole.ADMIN and current_user.id != user_id:
raise Forbidden("无权查看此用户信息")
user = await user_service.get_user(db, user_id=user_id)
return UserDetailResponse(
id=user.id,
username=user.username,
display_name=user.display_name,
role=user.role.value,
email=user.email,
phone=user.phone,
bio=user.bio,
avatar_url=user.avatar_url,
is_active=user.is_active,
created_at=user.created_at,
updated_at=user.updated_at,
)
@router.put("/{user_id}", response_model=UserDetailResponse)
async def update_user(
user_id: Int4Path,
body: UserUpdateRequest,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
) -> UserDetailResponse:
"""更新用户信息。
管理员可更新任意用户,普通用户只能更新自己的基础资料。
"""
# 非管理员只能更新自己
if current_user.role != UserRole.ADMIN and current_user.id != user_id:
raise Forbidden("无权更新此用户信息")
if current_user.role != UserRole.ADMIN:
if body.role is not None:
raise Forbidden("无权修改角色")
if body.is_active is not None:
raise Forbidden("无权修改启用状态")
if body.password is not None:
raise Forbidden("无权修改密码")
user = await user_service.update_user(
db,
user_id=user_id,
display_name=body.display_name,
email=body.email,
phone=body.phone,
bio=body.bio,
avatar_url=body.avatar_url,
role=body.role,
is_active=body.is_active,
password=body.password,
)
return UserDetailResponse(
id=user.id,
username=user.username,
display_name=user.display_name,
role=user.role.value,
email=user.email,
phone=user.phone,
bio=user.bio,
avatar_url=user.avatar_url,
is_active=user.is_active,
created_at=user.created_at,
updated_at=user.updated_at,
)
@router.post("/me/avatar", response_model=UserAvatarUploadResponse)
async def upload_current_user_avatar(
file: Annotated[UploadFile, File(..., description="头像文件")],
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
) -> UserAvatarUploadResponse:
"""上传当前登录用户头像。"""
payload = await file.read()
avatar_url = await user_service.upload_avatar(
db,
user_id=current_user.id,
file_name=file.filename or "avatar.bin",
content_type=file.content_type,
payload=payload,
)
return UserAvatarUploadResponse(avatar_url=avatar_url)