from typing import Any from pydantic import BaseModel, ConfigDict, Field, field_validator PROFILE_LIMITS = { "nickname": 50, "real_name": 20, "city": 30, "job_industry": 50, "job_company": 100, "wechat_id": 64, "phone": 20, "prefer_city": 30, "self_intro": 500, "tag_item": 20, "tag_items": 20, } class UserProfileResponse(BaseModel): model_config = ConfigDict(extra="ignore", from_attributes=True) id: int nickname: str | None = None real_name: str | None = None gender: int | None = None birth_year: int | None = None city: str | None = None height: int | None = None education: int | None = None job_industry: str | None = None job_company: str | None = None income_range: int | None = None marriage_status: int | None = None personality_tags: list[str] | None = None hobbies: list[str] | None = None value_answers: dict[str, Any] | None = None prefer_age_min: int | None = None prefer_age_max: int | None = None prefer_city: str | None = None prefer_education: int | None = None self_intro: str | None = None wechat_id: str | None = None phone: str | None = None avatar_url: str | None = None avatar_blur_url: str | None = None audit_status: int audit_remark: str | None = None profile_completeness: int class UserUpdateRequest(BaseModel): nickname: str | None = Field(default=None, max_length=PROFILE_LIMITS["nickname"]) real_name: str | None = Field(default=None, max_length=PROFILE_LIMITS["real_name"]) gender: int | None = None birth_year: int | None = None city: str | None = Field(default=None, max_length=PROFILE_LIMITS["city"]) height: int | None = None education: int | None = None job_industry: str | None = Field(default=None, max_length=PROFILE_LIMITS["job_industry"]) job_company: str | None = Field(default=None, max_length=PROFILE_LIMITS["job_company"]) income_range: int | None = None marriage_status: int | None = None personality_tags: list[str] | None = None hobbies: list[str] | None = None wechat_id: str | None = Field(default=None, max_length=PROFILE_LIMITS["wechat_id"]) phone: str | None = Field(default=None, max_length=PROFILE_LIMITS["phone"]) avatar_url: str | None = Field(default=None, max_length=500) avatar_blur_url: str | None = Field(default=None, max_length=500) value_answers: dict[str, Any] | None = None prefer_age_min: int | None = None prefer_age_max: int | None = None prefer_city: str | None = Field(default=None, max_length=PROFILE_LIMITS["prefer_city"]) prefer_education: int | None = None self_intro: str | None = Field(default=None, max_length=PROFILE_LIMITS["self_intro"]) @field_validator("personality_tags", "hobbies") @classmethod def validate_tag_lists(cls, value): if value is None: return value if not isinstance(value, list): raise ValueError("必须是数组") if len(value) > PROFILE_LIMITS["tag_items"]: raise ValueError(f"最多允许{PROFILE_LIMITS['tag_items']}项") cleaned = [] for item in value: if not isinstance(item, str): raise ValueError("数组项必须是字符串") text = item.strip() if not text: continue if len(text) > PROFILE_LIMITS["tag_item"]: raise ValueError(f"单项不能超过{PROFILE_LIMITS['tag_item']}个字符") cleaned.append(text) return cleaned class SubmitAuditResponse(BaseModel): audit_status: int message: str