feat(models): add external promotion tables (6 models)

Add ExternalProduct, PromotionCampaign, CampaignKeyword, SEOAudit, KeywordRanking, OptimizationTask models and 18 Pydantic schemas for the external promotion module.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
yuzhiran
2026-06-21 16:04:52 +08:00
parent 81f89f6f00
commit 12e49f2811
2 changed files with 365 additions and 0 deletions
+160
View File
@@ -636,3 +636,163 @@ class MenuResponse(MenuBase):
model_config = ConfigDict(from_attributes=True)
# ========== 外部推广模块 ==========
class ExternalProductBase(BaseModel):
name: str
type: str = "website"
url: Optional[str] = None
domain: Optional[str] = None
app_id: Optional[str] = None
account_id: Optional[str] = None
description: Optional[str] = None
class ExternalProductCreate(ExternalProductBase):
pass
class ExternalProductUpdate(BaseModel):
name: Optional[str] = None
type: Optional[str] = None
url: Optional[str] = None
domain: Optional[str] = None
app_id: Optional[str] = None
account_id: Optional[str] = None
description: Optional[str] = None
class ExternalProductResponse(ExternalProductBase):
id: int
org_id: Optional[str] = None
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
class PromotionCampaignBase(BaseModel):
name: str
product_id: int
status: str = "active"
keywords: List[str] = []
target_engines: List[str] = []
notes: Optional[str] = None
class PromotionCampaignCreate(PromotionCampaignBase):
pass
class PromotionCampaignUpdate(BaseModel):
name: Optional[str] = None
status: Optional[str] = None
keywords: Optional[List[str]] = None
target_engines: Optional[List[str]] = None
notes: Optional[str] = None
class PromotionCampaignResponse(PromotionCampaignBase):
id: int
org_id: Optional[str] = None
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
class CampaignKeywordBase(BaseModel):
campaign_id: int
keyword: str
search_volume: Optional[int] = None
difficulty: Optional[float] = None
current_rank: Optional[int] = None
target_rank: Optional[int] = None
class CampaignKeywordCreate(CampaignKeywordBase):
pass
class CampaignKeywordUpdate(BaseModel):
search_volume: Optional[int] = None
difficulty: Optional[float] = None
current_rank: Optional[int] = None
target_rank: Optional[int] = None
class CampaignKeywordResponse(CampaignKeywordBase):
id: int
best_rank: Optional[int] = None
last_checked: Optional[datetime] = None
org_id: Optional[str] = None
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
class SEOAuditResponse(BaseModel):
id: int
product_id: int
audit_type: str
overall_score: Optional[float] = None
meta_score: Optional[float] = None
heading_score: Optional[float] = None
content_score: Optional[float] = None
perf_score: Optional[float] = None
links_score: Optional[float] = None
mobile_score: Optional[float] = None
page_count: Optional[int] = None
issues_found: Optional[int] = None
org_id: Optional[str] = None
checked_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
class KeywordRankingResponse(BaseModel):
id: int
campaign_id: Optional[int] = None
keyword_id: Optional[int] = None
product_id: Optional[int] = None
keyword: str
search_engine: str
rank: Optional[int] = None
url_found: Optional[str] = None
org_id: Optional[str] = None
checked_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
class OptimizationTaskBase(BaseModel):
category: str
severity: str = "medium"
issue: str
recommendation: Optional[str] = None
class OptimizationTaskCreate(OptimizationTaskBase):
audit_id: int
product_id: int
class OptimizationTaskUpdate(BaseModel):
status: Optional[str] = None
severity: Optional[str] = None
recommendation: Optional[str] = None
class OptimizationTaskResponse(OptimizationTaskBase):
id: int
audit_id: int
product_id: int
status: str
org_id: Optional[str] = None
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)