feat(marquee): 真实条不按用户去重(打乱+去连簇)+ 后台按模式分页浏览可展示记录
- get_feed 真实条不再按 user 去重:改「洗牌 + 去连簇」(相邻尽量不同用户、减少单人连刷), 同一用户可多条露出但被打散、尽量不连续。_shuffle_declustered 支持传入固定种子 rng。 - 新增 GET /admin/api/marquee-seeds/real-records:按**当前模式**分页浏览全部可展示记录(不去重), 供运营逐页审核——只真实=真实记录;只种子=各启用种子按生成逻辑各出一行;混播=真实+种子。 固定种子洗牌+去连簇 → 排列恒定、翻页稳定、能翻遍全部;含 OpsRealRecord* schema。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,8 @@ from app.admin.schemas.ops_marquee_seed import (
|
||||
OpsMarqueeSeedCreate,
|
||||
OpsMarqueeSeedOut,
|
||||
OpsMarqueeSeedUpdate,
|
||||
OpsRealRecordItem,
|
||||
OpsRealRecordsOut,
|
||||
OpsSavingsFeedPreviewOut,
|
||||
)
|
||||
from app.models.admin import AdminUser
|
||||
@@ -68,6 +70,22 @@ def preview_feed(
|
||||
return OpsSavingsFeedPreviewOut(items=ops_marquee.get_feed(db, limit=limit, mode=mode))
|
||||
|
||||
|
||||
@router.get("/real-records", response_model=OpsRealRecordsOut, summary="分页浏览当前模式下可展示的记录(审核用)")
|
||||
def list_real_records(
|
||||
db: AdminDb,
|
||||
mode: Annotated[str | None, Query(description="mixed/real/seed;不传=当前持久化模式")] = None,
|
||||
offset: Annotated[int, Query(ge=0)] = 0,
|
||||
limit: Annotated[int, Query(ge=1, le=50)] = 8,
|
||||
) -> OpsRealRecordsOut:
|
||||
"""分页列出**当前模式**下可在 app 轮播展示的全部记录(**不去重**):只真实=真实记录;只种子=各启用
|
||||
种子按生成逻辑各出一行;混播=真实+种子。与 app 同口径洗牌+去连簇,固定种子→翻页稳定、能翻遍全部。
|
||||
item.user_id=0 表示种子行。"""
|
||||
if mode is not None and mode not in ops_marquee.FEED_MODES:
|
||||
raise HTTPException(status_code=400, detail="mode 需为 mixed / real / seed")
|
||||
items, total = ops_marquee.list_real_records(db, mode=mode, offset=offset, limit=limit)
|
||||
return OpsRealRecordsOut(items=[OpsRealRecordItem(**it) for it in items], total=total)
|
||||
|
||||
|
||||
# 注:/mode 两个端点须在 /{seed_id} 之前注册,否则 PATCH /mode 会被 /{seed_id} 抢先按 id 解析。
|
||||
@router.get("/mode", summary="首页轮播数据源模式(mixed/real/seed)")
|
||||
def get_feed_mode(db: AdminDb) -> dict:
|
||||
|
||||
@@ -62,3 +62,16 @@ class OpsSavingsFeedPreviewItem(BaseModel):
|
||||
class OpsSavingsFeedPreviewOut(BaseModel):
|
||||
"""运营预览:实际混播出来的 feed(真实记录会插队,与客户端一致)。"""
|
||||
items: list[OpsSavingsFeedPreviewItem]
|
||||
|
||||
|
||||
class OpsRealRecordItem(BaseModel):
|
||||
masked_user: str # 脱敏后展示名(与 app 一致)
|
||||
saved_amount_cents: int # 节省金额(分)
|
||||
created_at: str # 比价记录时间(YYYY-MM-DD HH:MM)
|
||||
user_id: int # 真实 user_id(供运营核对,不下发客户端)
|
||||
|
||||
|
||||
class OpsRealRecordsOut(BaseModel):
|
||||
"""分页浏览「全部可展示的真实记录」(success+省>0,不去重、稳定顺序)。"""
|
||||
items: list[OpsRealRecordItem]
|
||||
total: int # 满足条件的真实记录总数(算页数用)
|
||||
|
||||
Reference in New Issue
Block a user