统一游戏平台 · 02

🗄️ 数据模型:一套库管所有游戏

Postgres 16 单库,按「账号 → 游戏库 → 存档 → 经济 → 社交 → 运营」六域共 18 张表。设计原则:游戏差异全部收进 jsonb(存档结构、任务目标、商品内容物),表结构对所有游戏(含未来新款)通用,新游戏零建表。

1. ER 总览

          ┌──────────┐ 1:N ┌────────────┐
          │  users   │────▶│ identities │  (platform+openid → 统一账号)
          └────┬─────┘     └────────────┘
    ┌──────────┼─────────────┬──────────────┬─────────────┐
    ▼          ▼             ▼              ▼             ▼
┌────────┐ ┌─────────┐ ┌───────────────┐ ┌──────────┐ ┌───────────────┐
│ saves  │ │ wallets │ │ currency_txns │ │  orders  │ │ share_records │
│ N per  │ │ 1:1     │ │ 流水 N        │ │ N        │ │ N ──▶ share_visits
│ (game) │ └─────────┘ └───────────────┘ └────┬─────┘ └───────────────┘
└───┬────┘                                    │ product_id
    │ game_id                                 ▼
    │      ┌─────────┐              ┌──────────────┐
    └─────▶│  games  │◀─────────────│   products   │
           └────┬────┘              └──────────────┘
                │ game_id
    ┌───────────┼────────────────┬────────────────┐
    ▼           ▼                ▼                ▼
┌──────────────────┐ ┌─────────┐ ┌───────────┐ ┌───────────┐
│leaderboard_scores│ │ seasons │ │ ad_events │ │  events   │(埋点,短保留)
└──────────────────┘ └─────────┘ └───────────┘ └───────────┘
 用户日常域: signins · streaks · tasks · task_progress
 管理域:     admin_users · audit_logs · app_configs

2. 账号域

2.1 users — 统一用户

字段类型说明
idbigserial PK全平台唯一 user_id,所有业务表外键
nickname / avatartext用户授权后写入;昵称入库前过内容安全检查
provincetext地域攀比(省榜)用;来源 IP 归属或用户授权
statussmallint0 正常 / 1 禁言(榜单匿名)/ 2 封禁
risk_levelsmallint风控分层:0 正常 / 1 观察 / 2 高危(作弊嫌疑,奖励降权)
created_at / last_login_attimestamptz注册与活跃;last_login_at 支撑回归奖励判定(≥3/7 天未登录)

2.2 identities — 平台身份(双平台打通的关键)

字段类型说明
idbigserial PK
user_idbigint FK→users一个用户可挂多个平台身份
platformtextwx / tt(预留海外平台)
appidtext合集与独立爆款是不同 appid,都映射到同一 user(靠 unionid)
openidtextUNIQUE(platform, appid, openid)
unionidtext,可空,索引微信同主体多小游戏合并账号的依据;留意 拆独立爆款前必须在开放平台绑定主体拿到 unionid,否则合集与独立款账号无法打通
session_key_enctext加密存储,用于解密平台数据(如需要);短期有效

3. 游戏库域

3.1 games — 游戏库(registry.html 的数据库化)

字段类型说明
game_idtext PKg01_dieta(全民叠塔)…g15_juecha;见 04 映射表
title / emoji / engine_tagtext名称、图标、心理引擎标签(沿用 registry 分类)
statustextdev / test / online / offline——大厅只下发 online;灰度用 test+白名单
entrytext合集内分包名/入口路径;独立版记录其 appid
sort / is_newint / bool大厅排序与 NEW 角标(运营可调)
configjsonb逐款游戏参数:{ energyMax, energyRegenSec, scoreMax, sessionMinSec, adScenes:[...], metaVersion }scoreMax/sessionMinSec 是服务端防作弊校验的依据(见 03)
updated_attimestamptz客户端以此做配置缓存失效

4. 存档域(M1 的落点)

4.1 saves — 统一云存档

字段类型说明
user_id / game_id / slot复合 PKslot 默认 0;预留多存档位。特殊 game_id:_hub 存合集大厅级数据(用户设置、新手引导标记)
datajsonb游戏自定义结构,SDK 透传;单档上限 64KB(服务端硬校验,防滥用)
versionint乐观锁:客户端提交 version=n,服务端仅当 db.version==n 时写入并 +1,否则返回 409 与云端档,由 SDK 走冲突策略(见 04)
updated_attimestamptz冲突提示与运营排查用
存档内容约定:货币(金币/钻石/体力)不放 saves.data,一律走 wallets(服务端记账,客户端只读);saves 只放玩法进度(关卡、天赋等级、图鉴、局内统计)。这样"改存档刷钱"在结构上不可能。

5. 经济域(M2 的落点)

5.1 wallets — 钱包(服务端权威)

字段类型说明
user_idbigint PK1:1 users
coinbigint软货币(全游戏通用——合集的统一金币,是"一个总系统"的核心体验)
gembigint硬货币(主要靠付费;签到/成就少量赠送)
energy / energy_updated_atint / timestamptz体力惰性结算:读取时按 games.config.energyRegenSec 补算,不跑定时器

5.2 currency_txns — 货币流水(审计与对账)

字段类型说明
idbigserial PK
user_id / game_idbigint / text索引 (user_id, created_at)
currency / delta / balance_aftertext / bigint / bigint每笔变动记余额快照,客服排查零成本
reasontextsignin / task / ad_reward / share_reward / pay_grant / consume_revive / consume_gacha / admin_adjust…——直接支撑 v2 的 sink/source 报表
ref_type / ref_idtext关联单据(order_id / share_id / task_id),保证每笔发放可溯源、可幂等

5.3 orders — 支付订单(M8 的落点)

字段类型说明
order_idtext PK自有单号(雪花/ULID),下单时生成并传给平台
user_id / platform / product_id
amount_fenint以分计价,对账基准
statustext状态机:created → paid → delivered;分支 refunded / failed回调幂等靠状态机:paid 重复回调直接 200
platform_txn_id / raw_callbacktext / jsonb平台流水号与回调原文(争议仲裁用)
paid_at / delivered_attimestamptz发货延迟监控(正常应 <1s,同事务)

5.4 products — 商品配置(管理后台维护)

字段类型说明
product_idtext PKfirst_charge_6 / monthly_card / gem_30 / gift_newbie
typetextfirst_charge / monthly / gift / gem / skin —— 对应 v2 3.3 定价梯度
price_fen / grantsint / jsonbgrants 示例:{gem:60, skin:"s01", monthlyDays:30};发货逻辑读 grants 通用执行
limit_per_user / platform / status首充限 1 次;平台定向(iOS 政策差异);上下架

6. 社交域(分享 / 排行榜)

6.1 share_records + share_visits — 分享与回流(M4/P 分享通道的落点)

字段说明
share_recordsshare_id(PK, 短随机码) · user_id · game_id · scene · created_at用户点「喊好友帮忙」即创建;share_id 编进分享卡 query
share_visitsid · share_id · visitor_user_id · is_new_user · rewarded · created_atUNIQUE(share_id, visitor_user_id) 同一好友只计一次;visitor==分享者本人不计;rewarded 标记是否已给分享者发奖。回流判定与限额策略见 05

6.2 leaderboard_scores + seasons — 排行榜(R8 的服务端化)

字段说明
leaderboard_scoresgame_id · season · user_id · score · extra(jsonb) · updated_at,UNIQUE(game_id, season, user_id)Postgres 为持久层;Redis ZSET lb:{game}:{season} 为读缓存(topN/我的排名 O(logN))。写入必过服务端校验(score ≤ games.config.scoreMax 等)
seasonsseason_id · game_id(可空=全局) · start_at · end_at · status · rewards(jsonb)赛季化支撑 M7 长线;结算由 VPS cron 执行:榜单快照→发奖入 currency_txns→开新季

7. 日常域(签到 / 任务)

字段说明
streaksuser_id PK · current_streak · longest_streak · last_date · freeze_countR6 落点;freeze_count = 断签保护卡余量(广告/付费获得)
signins(user_id, date) PK · streak_after · reward(jsonb)7 日/30 日阶梯奖励在服务端按 streak_after 计算发放
taskstask_id PK · type(daily/weekly/achievement) · title · target(jsonb) · reward(jsonb) · statustarget 示例:{event:"game_finish", gameId:"any", count:3}——由埋点事件驱动进度,新任务零代码
task_progress(user_id, task_id, period_key) PK · progress · claimed_atperiod_key = 日期/周号(achievement 为 'all');claimed_at 空 = 可领未领(蔡格尼克 R12 的红点数据源)

8. 埋点与广告事件

字段说明
ad_eventsid · user_id · game_id · scene · platform · status(show/complete/abort) · created_at激励视频漏斗:人均次数、完播率——07 看板直接消费
eventsid · user_id · game_id · name · props(jsonb) · created_at通用埋点(session_start/game_finish/unlock_choice/…,事件字典见 05)。留意 按月分区、只保留 90 天明细;日级聚合结果另存 stats_daily 供看板长期查询

9. 管理域

字段说明
admin_usersid · email · role(superadmin/ops/readonly) · status · last_login_atRBAC 见 07;CF Access 白名单 + 本表双重校验
audit_logsid · admin_id · action · target · detail(jsonb) · created_at所有写操作(改配置/调余额/封号)强制落审计
app_configskey PK · value(jsonb) · updated_at · updated_by全局开关与活动配置:首充弹窗开关、分享每日限额、公告、卡点参数(M6 日程的运营侧调参入口)

10. 一致性与幂等要点(跨表规则)