feat(settings): 添加通知偏好设置和后端 API 集成

This commit is contained in:
qzl
2026-04-07 18:43:42 +08:00
parent b18a205bf3
commit b22673ce49
9 changed files with 612 additions and 29 deletions
+9
View File
@@ -8,6 +8,7 @@ from v1.users.schemas import (
AvatarUploadUrlResponse,
ProfileResponse,
UpdateProfileRequest,
UpdateSettingsRequest,
)
from v1.users.service import UserService
@@ -30,6 +31,14 @@ async def update_my_profile(
return await service.update_profile(payload)
@router.patch("/me/settings", response_model=ProfileResponse)
async def update_my_settings(
payload: UpdateSettingsRequest,
service: UserService = Depends(get_user_service),
) -> ProfileResponse:
return await service.update_settings(payload)
@router.post("/me/avatar/upload-url", response_model=AvatarUploadUrlResponse)
async def create_avatar_upload_url(
payload: AvatarUploadUrlRequest,
+9 -2
View File
@@ -1,10 +1,11 @@
from __future__ import annotations
from datetime import datetime
from typing import Any
from pydantic import BaseModel, ConfigDict, Field
from schemas.shared.user import ProfileSettingsV1
class ProfileResponse(BaseModel):
model_config = ConfigDict(extra="forbid")
@@ -14,7 +15,7 @@ class ProfileResponse(BaseModel):
bio: str | None = None
avatar_path: str | None = None
avatar_url: str | None = None
settings: dict[str, Any] = Field(default_factory=dict)
settings: ProfileSettingsV1
updated_at: datetime
@@ -26,6 +27,12 @@ class UpdateProfileRequest(BaseModel):
avatar_path: str | None = None
class UpdateSettingsRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
settings: ProfileSettingsV1
class AvatarUploadUrlRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
+24 -3
View File
@@ -11,12 +11,13 @@ from core.config.settings import config
from core.auth.models import CurrentUser
from core.http.errors import ApiProblemError, problem_payload
from services.base.supabase import SupabaseService
from schemas.shared.user import UserContext
from schemas.shared.user import UserContext, parse_profile_settings
from v1.users.repository import SQLAlchemyUserRepository
from v1.users.schemas import (
AvatarUploadUrlRequest,
ProfileResponse,
UpdateProfileRequest,
UpdateSettingsRequest,
)
@@ -40,7 +41,9 @@ class UserService:
email=self.current_user.email,
avatar_url=profile.avatar_url if profile is not None else None,
bio=profile.bio if profile is not None else None,
settings=profile.settings if profile is not None else None,
settings=parse_profile_settings(profile.settings)
if profile is not None
else None,
)
async def get_profile(self) -> ProfileResponse:
@@ -62,7 +65,7 @@ class UserService:
bio=profile.bio,
avatar_path=profile.avatar_url,
avatar_url=avatar_url,
settings=profile.settings,
settings=parse_profile_settings(profile.settings),
updated_at=profile.updated_at,
)
@@ -122,6 +125,24 @@ class UserService:
await self.repository.save()
return await self.get_profile()
async def update_settings(self, payload: UpdateSettingsRequest) -> ProfileResponse:
profile = await self.repository.get_profile_by_user_id(
user_id=self.current_user.id
)
if profile is None:
raise ApiProblemError(
status_code=404,
detail=problem_payload(
code="PROFILE_NOT_FOUND",
detail="Profile not found",
),
)
profile.settings = payload.settings.model_dump(mode="json")
await self.repository.save()
return await self.get_profile()
async def create_avatar_upload_url(
self, payload: AvatarUploadUrlRequest
) -> dict[str, str | int]: