"""系统设置(公司信息 + 站点信息)请求/响应模型。 `SettingPublicOut` 与 `SettingOut` **刻意不共用**:public 端点无鉴权, 响应字段必须白名单显式列出——将来往 SettingOut 加敏感字段时不会 顺着复用链泄漏到匿名端点。 2026-10-20 精简(用户确认):删除系统副标题与企业档案字段(信用代码/ 地址/电话/邮箱);新增站点标题(浏览器标签页/侧边栏副标题)与站点图标 (浏览器标签页 favicon)。public 端点只需登录页/标签页展示字段,两者 恰好同集合,但仍保留独立 schema 作为白名单防线。 """ from pydantic import BaseModel, ConfigDict, Field class SettingOut(BaseModel): """公司信息与站点信息(管理端)。""" company_name: str logo_url: str | None = None site_title: str | None = None brand_slogan: str | None = None footer_text: str | None = None icp_no: str | None = None favicon_url: str | None = None class SettingPublicOut(BaseModel): """公司信息与站点信息(匿名端点白名单):登录页/浏览器标签页展示所需字段。""" company_name: str logo_url: str | None = None site_title: str | None = None brand_slogan: str | None = None footer_text: str | None = None icp_no: str | None = None favicon_url: str | None = None class SettingUpdateIn(BaseModel): """公司信息与站点信息更新(**部分更新**语义)。 仅提交的字段生效(``exclude_unset``),未提交或显式 null 的字段保持 不变;可选文本传空串等价清空(落库为 null、前端回退内置默认)。 company_name 若提交必须非空(DB 非空约束)。 """ model_config = ConfigDict(str_strip_whitespace=True) company_name: str | None = Field( default=None, min_length=1, max_length=64, description="公司名称(提交则须非空)" ) site_title: str | None = Field(default=None, max_length=64, description="站点标题") brand_slogan: str | None = Field(default=None, max_length=64, description="品牌标语") footer_text: str | None = Field(default=None, max_length=64, description="页脚版权文本") icp_no: str | None = Field(default=None, max_length=32, description="ICP 备案号")