db399a40fa
- ops_stat: 真实值 offset→保底(max);初始基数过只增不减护栏 - ops_marquee: 脱敏名手机尾号+中文昵称混合;金额长尾;时间随机抖动;真实+种子不足兜底补满;真实记录查询 ~30s 缓存 - comparison_record: 复合索引 (status, created_at) + 迁移(PG CONCURRENTLY);修复 alembic 多 head(merge 改挂 onboarding_completion) - 轮播种子批量删除/启用接口 + ids 上限;docs 同步 - 附带并行会话 WIP:admin users / wallet Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: OuYingJun1024 <1034284404@qq.com> Reviewed-on: #42 Co-authored-by: ouzhou <ouzhou@wonderable.ai> Co-committed-by: ouzhou <ouzhou@wonderable.ai>
72 lines
3.9 KiB
Python
72 lines
3.9 KiB
Python
"""首页三统计展示配置表(帮助用户 / 完成比价 / 累计节省)。
|
|
|
|
客户端首页顶部三个门面数字,每个指标可独立选 3 种展示模式(运营后台配):
|
|
- real : 实时查真实数据(help_users=去重成功比价用户数 / total_compares=成功比价数 /
|
|
total_saved=成功比价省额求和)。
|
|
- manual : 直接用运营手填的固定值。
|
|
- random : 「只增不减」的伪增长——读取时惰性 tick:距上次 tick 超过 random_tick_seconds
|
|
就把 random_current 乘以一个 [min,max] 内的随机倍率(倍率恒 ≥1.0 → 只增不减)。
|
|
|
|
数值单位约定(三指标都用各自「基础单位」的整数存,避免浮点):
|
|
- help_users / total_compares : 个数(人 / 次)
|
|
- total_saved : 分(cents);客户端 ÷100 显示「元」
|
|
|
|
倍率用千分比整数存:1.000→1000、1.100→1100,读时 factor = randint(min,max)/1000。
|
|
|
|
一行一指标,主键 = metric。初始由 migration 播种 3 行(默认 manual + 当前写死门面值,
|
|
保证上线无视觉变化),运营再按需切模式。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import Boolean, DateTime, Integer, String, func
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.db.base import Base
|
|
|
|
|
|
class OpsStatConfig(Base):
|
|
__tablename__ = "ops_stat_config"
|
|
|
|
# help_users / total_compares / total_saved
|
|
metric: Mapped[str] = mapped_column(String(32), primary_key=True)
|
|
# real / manual / random(每指标独立)
|
|
mode: Mapped[str] = mapped_column(String(16), nullable=False, default="real")
|
|
|
|
# manual 模式固定值(基础单位整数;total_saved 为分)
|
|
manual_value: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
|
|
# random 模式:倍率区间(千分比,≥1000 保证只增不减)+ tick 周期 + 当前值 + 上次 tick 时刻
|
|
random_mult_min: Mapped[int] = mapped_column(Integer, nullable=False, default=1000)
|
|
random_mult_max: Mapped[int] = mapped_column(Integer, nullable=False, default=1100)
|
|
random_tick_seconds: Mapped[int] = mapped_column(Integer, nullable=False, default=86400)
|
|
# 触发时刻对齐偏移:距北京时间 0 点的分钟数。按单位:天=每日时刻(h*60+m)、小时=每小时第几分、
|
|
# 分钟=0。刷新在北京时间 (anchor + k*interval) 的钟点边界触发(见 repo _refresh)。
|
|
random_anchor_minutes: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
random_current: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
random_last_tick_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
|
|
# random 增长方式:mult=×倍率(用 random_mult_*) / add=+绝对增量(用 random_step_*,基础单位整数)
|
|
random_kind: Mapped[str] = mapped_column(String(8), nullable=False, default="mult")
|
|
random_step_min: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
random_step_max: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
# real 模式保底值(基础单位;total_saved 为分):展示值 = max(真实值, 保底值)。冷启动显示保底撑
|
|
# 场面,真实值涨过保底后显示纯真实、零差距。列名沿用 real_offset(语义已从"偏移"改为"保底")
|
|
real_offset: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
# 门面数字默认「只增不减」;运营明确要下调时才开此开关(real/manual 刷新都受护栏约束)
|
|
allow_decrease: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
|
|
updated_by_admin_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
nullable=False,
|
|
)
|
|
|
|
def __repr__(self) -> str: # pragma: no cover
|
|
return f"<OpsStatConfig metric={self.metric} mode={self.mode}>"
|