2026-10-12 16:44:49 +08:00
|
|
|
"""租户与站点配置模型。
|
|
|
|
|
|
|
|
|
|
- TenantConfig.data = deep_merge(DEFAULT_CONFIG, snapshot):租户快照 ⊕ 出厂默认
|
|
|
|
|
- Site.brand 的合并基线是**租户级** data["brand"](而非出厂默认),
|
|
|
|
|
这样租户级 brand 自定义也能被各站点继承。
|
|
|
|
|
"""
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
|
|
|
|
from app.platform.defaults import DEFAULT_CONFIG, deep_merge
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
class Site:
|
|
|
|
|
slug: str
|
|
|
|
|
name: str
|
|
|
|
|
domains: tuple[str, ...]
|
2026-10-12 16:59:31 +08:00
|
|
|
brand: dict # 站点门面覆盖层 ⊕ 租户默认 brand(已深合并)。
|
|
|
|
|
# 只读约定:构造后不得修改
|
2026-10-12 16:44:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
class TenantConfig:
|
|
|
|
|
slug: str
|
|
|
|
|
name: str
|
|
|
|
|
status: str # active | disabled
|
2026-10-12 16:59:31 +08:00
|
|
|
data: dict # deep_merge(DEFAULT_CONFIG, snapshot)。
|
|
|
|
|
# 只读约定:构造后不得修改
|
2026-10-12 16:44:49 +08:00
|
|
|
sites: tuple[Site, ...] = ()
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def from_snapshot(cls, slug, name, snapshot, sites=(), status="active"):
|
|
|
|
|
merged = deep_merge(DEFAULT_CONFIG, snapshot)
|
|
|
|
|
resolved = tuple(
|
|
|
|
|
Site(s["slug"], s.get("name", s["slug"]), tuple(s.get("domains", ())),
|
|
|
|
|
deep_merge(merged["brand"], s.get("brand", {})))
|
|
|
|
|
for s in sites)
|
|
|
|
|
return cls(slug=slug, name=name, status=status, data=merged, sites=resolved)
|