feat(douyu): 新增和平小店查询模块(绑定角色/商品列表/点券余额)

- activity_client: getIframeUrl 签发 code/sig,道聚城 getrole.out/recommend/balance 接口
  (2026-08 起需 isCode=1 + authType=delegate + sAnchorId 才能通过 Livelink 校验)
- 迁移 0016: accounts xpd_* 字段、douyu_config 小店配置(actAlias/actId/rid)、
  douyu_xpd_goods_snapshot 商品快照表
- runner/service/router/schema 注册 query_xpd_role/refresh_xpd_goods/query_xpd_balance
  三个任务,任务结果剥离 role.raw 防 openid 泄露
- 前端: 和平小店路由/菜单/DouyuTasksPage 三态/商品下拉/配置弹窗
This commit is contained in:
yml2213
2026-08-06 17:23:59 +08:00
parent f8de495029
commit fdc74eba8c
12 changed files with 702 additions and 25 deletions
+44
View File
@@ -554,6 +554,9 @@ class DouyuConfigOut(BaseModel):
esports_chicken_skin_id: str = "0"
esports_firework_gift_id: str = "24767"
esports_firework_skin_id: str = "3850"
xpd_act_alias: str = "20260623KDQFH"
xpd_act_id: str = "46195"
xpd_rid: str = "9263298"
gold_pay_type: int = 1
gift_id: str = "23643"
skin_id: str = "2942"
@@ -576,6 +579,9 @@ class DouyuConfigOut(BaseModel):
"esports_chicken_skin_id": self.esports_chicken_skin_id,
"esports_firework_gift_id": self.esports_firework_gift_id,
"esports_firework_skin_id": self.esports_firework_skin_id,
"xpd_act_alias": self.xpd_act_alias,
"xpd_act_id": self.xpd_act_id,
"xpd_rid": self.xpd_rid,
"gold_pay_type": self.gold_pay_type,
"gift_id": self.gift_id,
"skin_id": self.skin_id,
@@ -598,6 +604,9 @@ class DouyuConfigUpdate(BaseModel):
esports_chicken_skin_id: Optional[str] = None
esports_firework_gift_id: Optional[str] = None
esports_firework_skin_id: Optional[str] = None
xpd_act_alias: Optional[str] = None
xpd_act_id: Optional[str] = None
xpd_rid: Optional[str] = None
gold_pay_type: Optional[int] = Field(None, ge=1, le=9)
gift_id: Optional[str] = None
skin_id: Optional[str] = None
@@ -689,10 +698,45 @@ class DouyuTaskAccountOut(BaseModel):
esports_bind_status: str = ""
esports_change_role_wait_time: Optional[int] = None
esports_can_change_time: Optional[int] = None
xpd_game_name: str = ""
xpd_openid: str = ""
xpd_role_id: str = ""
xpd_plat_id: Optional[int] = None
xpd_area_id: Optional[int] = None
xpd_balance: Optional[int] = None
xpd_bind_status: str = ""
assigned_to: Optional[int] = None
assigned_username: Optional[str] = None
class DouyuXpdGoodsOut(BaseModel):
id: int
commodity_id: str
name: str = ""
price: Optional[int] = None
org_price: Optional[int] = None
category: str = ""
goods_left: Optional[int] = None
raw: Optional[dict[str, Any]] = None
updated_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
@model_serializer
def _serialize(self) -> dict[str, Any]:
return {
"id": self.id,
"commodity_id": self.commodity_id,
"name": self.name,
"price": self.price,
"org_price": self.org_price,
"category": self.category,
"goods_left": self.goods_left,
"raw": self.raw,
"updated_at": _ensure_tz(self.updated_at).isoformat() if self.updated_at else None,
}
# ---- 代理配置 ----
class ProxyConfigOut(BaseModel):
enabled: bool = False