29 KiB
会员权益与算力 · 设计与开发文档
状态:v5 一期已落地(服务端 + 后台 + 客户端,2026-09-11),二期(带存储设备)仅设计|最后更新:2026-09-11 一期改动的落点见 CLAUDE.md「会员与算力」一节;第 10 节的「现在(线上)」列描述的是改造前的旧行为。
0. 一句话概括
两层权益,各管一件事:
| 层 | 管什么 | 来源 |
|---|---|---|
| VIP | 功能准入:没有 VIP,翻译与会议纪要不可用 | 设备赠送(按天)+ 用户自购 |
| 算力 | 用量计量:翻译、会议、AI 对话的消耗统一折算成算力 | 设备赠送(有上限)+ 用户充值 |
- 归属规则两层一致:设备赠送的归设备(解绑即失去、随设备流转),用户自购的归账号
- 算力的换算系数后台可配,客户端只上报原始用量、只展示算力
- 算力是否作为闸门(用完就拦)由后台开关控制,默认关——只记账不拦
相对 v4 的变化
v4 把权益简化成「只有 VIP」,用量只记原始数据。本版把算力加回来,作为统一的用量计量与设备赠送的载体:
| v4 | v5 |
|---|---|
| 生产批次只配 VIP 天数 | VIP 天数 + 赠送算力上限 |
| 用量按翻译秒 / 会议秒 / AI 字数分别记 | 原始数据照记,另外统一折算成算力 |
| 无换算 | 换算系数后台可配,改价不发版 |
| 无消耗品 | 用户可充值算力,商品加算力发放项 |
| 无闸门 | 算力闸门做成开关,默认关 |
1. 权益模型
1.1 VIP:功能准入
翻译 / 会议纪要是否可用 = 自购 VIP 未过期
或(当前绑定着某台设备 且 该设备的 VIP 期未结束)
任一成立即可用。不相减、不收回、不结转。受限范围见 1.5。
1.2 算力:用量计量
算力(compute)是平台自定义的计量单位,所有产生服务商成本的功能都折算成它:
| 功能 | 原始计量 | 换算 | 后台配置键 |
|---|---|---|---|
| 翻译(同传 / 面对面 / 通话 / 影音 / 文本 / 图片) | 秒 | 每分钟 = N 算力 |
COMPUTE_RATE_TRANSLATE |
| 会议纪要 | 秒 | 每分钟 = N 算力 |
COMPUTE_RATE_MEETING |
| AI 对话 | 输入 + 输出字符数 | 每 100 字 = N 算力 |
COMPUTE_RATE_AICHAT |
- 系数在服务端换算,客户端不参与。改系数只影响改动之后的消耗,不追溯
- 三个系数默认都是
1,即 1 分钟翻译 = 1 分钟会议 = 100 字对话 = 1 算力 - 单次会话内按原始量累计,结束时换算并向上取整,单次最低 1 算力
- 字符按 Unicode 码点计:中文 1 字 = 1,英文 1 字母 = 1
⚠️ 算力不是大模型的 token,与模型侧的 tokenizer 无关。代码里统一用
compute, 不要再出现 token 这个词,避免与服务商用量混淆。
1.3 算力的两个来源与归属
| 设备赠送算力 | 用户充值算力 | |
|---|---|---|
| 来源 | 生产批次配置,激活时快照 | 充值、后台调整 |
| 归属 | 设备硬件 | 账号 |
| 存储 | 设备行 compute_grant(总量)/ compute_used(已用) |
用户行 compute_balance |
| 有效期 | 不过期,用完为止 | 不过期,用完为止 |
| 解绑 | 立即失去剩余部分 | 不受影响 |
| 流转 | 剩余部分随设备给下一个绑定者 | 跟着账号走 |
| 扣减 | 先扣这一份 | 设备剩余为 0 时才动用 |
⚠️ 设备算力是共用一份,不是每人一份。 前一个人用掉 300,下一个人接手只剩 700。
compute_used在解绑时不重置,否则一台设备在几个账号间轮流绑定就能无限刷。
设备算力与设备 VIP 期相互独立:VIP 期到了算力还在,算力用完了 VIP 期还在,都是正常状态。
1.4 算力闸门:后台开关,默认关
| 开关状态 | 消耗时的行为 |
|---|---|
| 关(默认) | 换算 → 扣减(先设备后用户,扣到 0 为止)→ 超出部分记为「超额」→ 照常放行 |
| 开 | 换算 → 设备剩余 + 用户余额 < 本次消耗 → 拒绝,返回算力不足 |
默认关的理由:上一轮已定「取消额度闸门」——用户在 VIP 期内不限量。 算力先作为记账与展示跑起来,数据积累到位、商业策略明确后再决定要不要开。
⚠️ 开闸门需要配合预扣。 现在
user_usages是客户端用完之后上报、服务端才扣, 余额校验发生在扣减那一刻——余额只剩 1 的用户仍可先用满 100 分钟再上报。 开关关着时这不是问题(反正放行);开关打开前必须先把预扣 + 心跳续扣做了, 否则闸门形同虚设。预扣逻辑本期不做,列为开关的前置条件。
1.5 功能权限边界(VIP 过期后)
| 功能 | VIP 期内 | VIP 过期 | 算力 | 说明 |
|---|---|---|---|---|
| 同传 / 面对面 / 通话 / 影音翻译 | ✅ | ❌ 受限 | 扣 | |
| 文本翻译 / 图片翻译 | ✅ | ❌ 受限 | 扣 | 同属翻译,同样按量计费 |
| 会议纪要(新建转写 / 总结) | ✅ | ❌ 受限 | 扣 | |
| 历史翻译记录、历史会议纪要 | ✅ | ✅ 可查看 | 不扣 | 数据是用户的 |
| EMAI AI 对话 | ✅ | ✅ 不受限 | 扣 | 唯一「不受 VIP 限但扣算力」的功能 |
| 通话录音 / 现场录音 | ✅ | ✅ | 不扣 | 本地能力 |
| 设备连接、电量、设备管理、OTA | ✅ | ✅ | 不扣 | 不产生服务商成本 |
| EQ / 音色 / 音乐 | ✅ | ✅ | 不扣 | 同上 |
| 商城、支付、实名认证 | ✅ | ✅ | 不扣 | 必须可用,否则用户无法续费 |
- 历史数据永远可查看。 受限的是「新建」,不是「回看」
- VIP 与算力的组合:VIP 过期但算力还有 → 翻译/会议不可用(准入没过),AI 对话可用并扣算力; VIP 在但算力为 0 → 闸门关时照常可用(记超额),闸门开时拒绝
1.6 受限怎么落地:两类拦截点
不是所有功能都能在服务端拦住,关键区别是这条链路走不走我们自己的服务器:
| 功能 | 数据流向 | 服务端能否强拦 | 拦截点 |
|---|---|---|---|
| 文本 / 图片翻译 | 客户端 → 自家网关 → 服务商 | ✅ | api_translate.go 入口 |
| 同传 / 面对面(三段式) | ASR 直连,机器翻译走自家网关 | ✅ | 同上,拦住翻译那一跳即整体不可用 |
| 会议纪要 | 录音传 OSS,服务端起任务 | ✅ | echomeet starttask 入口 |
| 通话翻译(端到端) | 客户端直连服务商 WS | ⚠️ 拦不住 | 只能靠「不下发凭据」+ 客户端自觉 |
⚠️ 通话翻译走阿里端到端,客户端拿着服务端下发的凭据直连服务商 WebSocket, 整个过程一个请求都不经过我们的服务器。唯一的服务端手段是在 svcresolve.go 的
resolveThirdSvcs里按 VIP 状态决定要不要下发翻译类凭据。凭据是启动时拉一次的, VIP 在使用期间过期时客户端手里的凭据仍有效,直到下次重新拉配置—— 这个窗口(最长一个启动周期)已接受,不值得为它引入短 TTL。
双端都要做,职责不同:客户端进入功能前判断,负责体验;服务端接口入口判断,负责兜底。
1.7 受限时的交互口径
| 项目 | 口径 | 理由 |
|---|---|---|
| 入口表现 | 可点击,点击后弹开通引导;不置灰 | 置灰不说明原因,用户只会以为功能坏了 |
| 提示内容 | 说明「续费会员」与「绑定带会员的设备」两条路 | 设备也能带来 VIP |
| 进行中的会话 | 允许跑完,不中途掐断 | 翻译到一半断掉是事故级体验 |
| 算力展示 | 「设备剩余 + 账户余额」合并展示,明细可拆 | 数字无声变少用户一律当 bug |
2. 设备权益:VIP 天数 + 赠送算力
2.1 生产批次配置
在后台「MAC 生成管理 → 生成 MAC」为每个批次配置:
| 配置项 | 单位 | 示例 | 0 的含义 |
|---|---|---|---|
vipdays |
天 | 180 | 不送 VIP |
viplevel |
等级 | 1 | 1 = VIP,2 = VIP-Pro(预留) |
compute_grant |
算力 | 1000 | 不送算力 |
原先的 rewardtranslate / rewardmeeting(翻译分钟、会议分钟)不再使用,存量列保留不动。
- 生产批次优先,未配置回退产品档案——判据是批次三项全 0
- 激活时快照:首次绑定时把三项固化到设备行,此后改批次配置只影响尚未激活的库存设备
2.2 激活日与连续计时
激活日 = 设备第一次被任意账号成功绑定的服务端时间,已有字段 device_mac.usedtime,直接复用。
设备 VIP 期 = [激活日, 激活日 + vipdays),按日历天连续走,解绑不暂停。
不需要定时任务,任何时刻的状态都能直接算出。
2.3 设备 VIP 与自购 VIP 必须分开存
现有做法是把赠送天数累加到 user.vipexptime,一旦累加就与自购混成同一个数字,解绑时无法拆分。
正确做法:设备侧不写用户表。
| 来源 | 存在哪 | 怎么算 |
|---|---|---|
| 自购 VIP | user.vipexptime(只记自购) |
直接读 |
| 设备 VIP | 设备行 usedtime + vipdays |
激活日 + vipdays |
解绑时什么都不用做——不绑了自然就不享有了。
2.4 VIP 等级
user.viplv 已存在(支付成功时置 1)。实际等级 = max(自购等级, 当前绑定设备的等级)。vip-pro 用等级 2,无需新字段。
3. 绑定规则 · 一期:无存储设备
| 场景 | 行为 |
|---|---|
| 别人直接绑定 | 允许顶掉(接管),原绑定自动失效。与现有实现一致 |
| 同账号换手机 | 允许(uid 相同,不算接管) |
| VIP 期 / 设备算力 | 接着走、接着用,不重新开始,不重置激活日 |
| 原持有者 | 立即失去设备 VIP 与设备剩余算力,需给提示 |
数据不跟着走:新用户看不到前一个人的录音、纪要、对话——那些按 uid 存在服务端。
4. 用量与算力记账
4.1 谁上报什么
| 数据 | 来源 | 现状 |
|---|---|---|
| 翻译时长(按模式) | App 上报原始秒数 | ✅ 已有:Trademodel1~5Time |
| AI 对话输入 / 输出字数 | App 上报原始字符数 | ⚠️ 字段有但从未写入:Aichatuptoken / Aichatdowntoken |
| 会议纪要时长 | 服务端自己统计 | ✅ 已有:echomeet 里 Meettime += model.Seconds |
⚠️ 客户端只上报原始量,不上报算力。 换算系数在后台可改,客户端如果自己算, 改一次系数就要发一次版,且新老版本算出的数不一致。客户端拿到的算力是服务端返回的。
4.2 消耗流程(user_usages 与 echomeet starttask 共用)
- 收到原始用量(App 上报的秒数 / 字数,或服务端自算的会议秒数)
- 写原始统计(现有字段照写,不动)
- 按
COMPUTE_RATE_*换算成算力c,向上取整,最低 1 - 扣减:先扣当前绑定设备的剩余(
compute_grant - compute_used),不够再扣user.compute_balance,扣到 0 为止;仍不够的部分记为超额 - 闸门开且超额 > 0 → 拒绝,返回算力不足;闸门关 → 放行
- 写流水:
user_use_log记本次算力c与来源拆分(设备 / 用户 / 超额) - 累计:
user_statistics.compute_total += c - 返回当前算力余额(设备剩余 + 用户余额)
绑定多台设备时,先扣剩余最少的那台(用完一台再动下一台,避免多台都剩一点)。
4.3 展示
客户端「用量」页展示:
- VIP 状态、来源(自购 / 设备)、到期日
- 算力:设备剩余 + 账户余额合并数,明细可拆
- 累计消耗、本月消耗
数据从服务端 user_getcompute 一次拿齐,客户端不做任何换算。
4.4 已定取舍:算力闸门默认关
VIP 期内不限量意味着单用户成本上不封顶。这是产品上明确接受的取舍。 算力记账跑起来之后,后台看板与异常告警自然就有了数据基础;要不要开闸门,看数据再定。
5. 带存储设备 · 二期
本阶段暂不实现,先把设计定下来。现役设备均不带存储。
5.1 两个产品开关
| 字段 | 含义 | 影响 |
|---|---|---|
has_storage |
带不带本地存储 | 为 0 时下面一项无意义 |
need_erase |
解绑时需不需要清空 | 驱动解绑确权弹窗 + 禁止接管 |
has_storage |
need_erase |
可否被顶掉 | 解绑弹确权 |
|---|---|---|---|
| 0 | — | ✅ | 否 |
| 1 | 0 | ✅ | 否 |
| 1 | 1 | ❌ 禁止 | 是 |
建议「禁止接管」挂在
need_erase上(见 Q1)。devicetype已废弃,不要依赖它。
5.2 清空标签
设备行新增 erasestate(0 = 无残留,1 = 待清空)与 lastuid(最后绑定者,解绑时写入不清空)。
解绑时写标签,绑定时随「校验 MAC」返回给客户端。
| 解绑时 | erasestate |
|---|---|
| 设备在线,清空成功 | 0 |
| 设备在线,用户选保留 / 清空失败 | 1 |
| 设备未连接 | 1,照常允许解绑 |
need_erase = 0 |
0 |
| 绑定时读到 | 客户端动作 |
|---|---|
| 0 | 直接握手 |
1 且 lastuid ≠ 当前 uid |
握手后第一时间下发清空指令,成功后上报置 0 |
1 且 lastuid = 当前 uid |
跳过清空,直接置 0 |
⚠️
lastuid不能省:A 离线解绑后又自己绑回来,无脑清空删的是 A 自己的数据。
清空失败不阻断使用:标签保持 1,每次连接重试,App 顶部提示。
5.3 解绑流程(顺序不能反)
- 点解绑 → 2. 判
need_erase,为 0 跳到 6 → 3. 弹确权:清空并解绑 / 保留并解绑 → - 选清空且在线:下发带回执的清空指令 → 5. 失败/超时让用户选重试或仍然解绑,不能卡死 →
- 调解绑接口写标签 → 7. 清本地痕迹并断连
⚠️ 现有实现是「先调解绑接口 → 清白名单 → 断连」。一旦解绑链路已断,清空指令没通道。 清空必须排在解绑接口之前。
5.4 必须一并解决的两件事
- 解绑时
uid清理现在是尽力而为的(失败只记日志)。禁止接管的规则下,uid没清掉 = 设备永久锁死。带存储设备的解绑必须强一致 - 设备锁死的兜底:原用户手机丢了 / 卸载 / 注销 / 忘记解绑就转卖 —— 后台强制解绑必须做;设备端物理重置推荐做;超时自动释放不推荐
5.5 三个前提,目前都不成立
产品档案无存储能力位;固件无清空指令(且命令号随固件版本变,新指令必须带回执);现役耳机不带存储(录音流式推给手机)。
6. 管理后台功能清单
按页面列,每项标明字段与接口。
6.1 系统配置 → 算力设置(新页面)
| 项 | 键(config 表,KV) |
类型 | 默认 |
|---|---|---|---|
| 翻译换算系数(算力 / 分钟) | COMPUTE_RATE_TRANSLATE |
int | 1 |
| 会议换算系数(算力 / 分钟) | COMPUTE_RATE_MEETING |
int | 1 |
| AI 对话换算系数(算力 / 100 字) | COMPUTE_RATE_AICHAT |
int | 1 |
| 算力闸门 | COMPUTE_GATE |
0 / 1 | 0 |
| 开户礼 · VIP 天数 | NEWUSER_GIFT_VIPDAYS |
int | 30 |
| 开户礼 · 算力 | NEWUSER_GIFT_COMPUTE |
int | 100 |
| 提示 · VIP 到期前(天) | VIP_WARN_DAYS |
int | 7 |
| 提示 · 算力低于 | COMPUTE_WARN |
int | 100 |
⚠️ 后四项与换算系数的校验规则不同:允许配 0(0 = 不送 / 不提示,是合法表达)。 所以解析时只有「键不存在」或「解析不出数字」才回落默认值,解析出 0 就用 0; 前端读取也必须用
??而不是||,否则后台配的 0 会被当成「没配」显示成默认值。
- 存
config表(comm.TableAppConfig),按应用作用域,随user_getappconfig的 env 下发——客户端可读到系数,仅用于本地预估展示,不用于上报 - 改系数后触发现有的
Rpc_ModifyAppConifg事件刷新缓存 - 闸门开关旁必须有提示:「开启前需确认预扣逻辑已上线」(见 1.4)
6.2 MAC 生成管理 → 生成 MAC(改表单)
| 字段 | 变更 |
|---|---|
| VIP 天数 | 保留(列 rewardvip) |
| VIP 等级 | 新增,下拉:1 = VIP / 2 = VIP-Pro,默认 1 |
| 赠送算力 | 新增(列 compute_grant),0 = 不送 |
| 翻译分钟 / 会议分钟 | 去掉 |
批次列表页同步展示这三项。
6.3 产品管理(改表单)
- 产品档案上的旧奖励字段(
bindrewardvpitime/bindrewardtranslate/bindrewardmeeting)改为:VIP 天数、VIP 等级、赠送算力,作为批次未配置时的回退 - 二期:加
has_storage/need_erase两个开关
6.4 用户管理(改详情页)
| 项 | 变更 |
|---|---|
| VIP 到期时间 | 保留,标注「自购部分」 |
| 设备赋予的 VIP | 新增只读展示:来自哪台设备、到期日 |
| 算力余额 | 新增可调:compute_balance,支持加减,必填备注 |
| 设备算力 | 新增只读展示:各绑定设备的 已用 / 总量 |
| 旧三个额度 | 保留只读,标注「已停用」 |
| 消耗流水 | 新增:按时间倒序,列 时间 / 功能 / 原始量 / 算力 / 来源拆分 |
后台调整算力走 api_adjustusercompute,写一条 logtype = AdminAdjust 的流水。
6.5 设备管理(改列表 / 详情)
| 列 | 说明 |
|---|---|
| 激活日 | usedtime |
| VIP 到期 | usedtime + vipdays,未激活显示「未激活」 |
| 算力 已用 / 总量 | compute_used / compute_grant |
| 当前绑定者 | uid |
| 二期:清空状态 | erasestate |
| 二期:强制解绑 | 按钮,限超管,写审计日志 |
6.6 商品管理(改表单)
| 字段 | 变更 |
|---|---|
| VIP 天数 | 保留(viptime) |
| 算力 | 新增(compute) |
| AI 次数 / 会议分钟 / 翻译分钟 | 去掉(ainum / meetnum / tradenum 列保留不读) |
6.7 统计看板(新页面)
| 维度 | 指标 |
|---|---|
| 按日 | 算力消耗总量、活跃消耗用户数 |
| 按功能 | 翻译 / 会议 / AI 各自的原始量与算力 |
| 按渠道 / 产品 | 算力消耗(沿用现有 StatEvent 的渠道归属) |
| 按用户 Top N | 单日 / 单月消耗排行——异常用量的发现入口 |
| 设备算力 | 已发放总量、已消耗、剩余 |
7. 服务端接口清单
7.1 App 侧(modules/user/,反射注册,路由 user_<方法小写>)
| 接口 | 变更 | 请求 | 响应 |
|---|---|---|---|
user_usages |
改 | 原样:usagetype + usages 原始量;AI 分支补 upchars / downchars |
增加 compute(本次扣减)、compute_device_left、compute_user_left、over(超额,闸门关时才可能 > 0) |
user_getcompute |
新增 | 无 | vip{ level, exptime, source[] }、compute{ device_left, user_balance, total_used, month_used }、rates{} |
user_binddevice |
改 | 原样 | 不再往 vipexptime 累加;改为在设备行写 vipdays / viplevel / compute_grant 快照;响应带设备算力剩余 |
user_translate |
改 | 原样 | 入口加 VIP 校验;成功后走 4.2 扣减流程 |
user_getinfo 等返回 VIP 的接口 |
改 | — | VIP 状态改为「自购 或 设备赋予」合并判定 |
user_getappconfig |
改 | — | env 里带出 COMPUTE_RATE_* / COMPUTE_GATE |
resolveThirdSvcs |
改 | — | 按 VIP 状态决定是否下发翻译类凭据 |
echomeet starttask |
改 | — | 入口加 VIP 校验;任务开始时按会议秒数走 4.2 扣减流程 |
二期 user_binddevice |
改 | — | 响应加 erasestate;带存储被占用时返回明确错误码 |
二期 user_unbinddevice |
改 | 加 erased |
— |
二期 user_reportdeviceerased |
新增 | devicemac |
— |
VIP 判定统一封装一个函数(如 comm.UserHasVip(user, devices) (level, exptime, source)),
所有需要判 VIP 的入口都调它,别各写一份。
7.2 Console 侧(modules/console/ 或 modules/api/)
| 接口 | 变更 |
|---|---|
api_getcomputeconfig / api_savecomputeconfig |
新增,读写 6.1 四个键 |
| 批次新增 / 编辑 | 加 viplevel / compute_grant |
| 产品保存 | 奖励字段改为三项 |
api_adjustusercompute |
新增:uid、delta(可负)、remark,写 AdminAdjust 流水 |
api_getusercomputelogs |
新增:分页返回消耗流水 |
| 用户详情 | 加设备 VIP / 设备算力只读展示 |
| 设备列表 / 详情 | 加激活日、VIP 到期、算力字段 |
| 商品保存 | 加 compute |
api_getcomputestats |
新增:按日 / 功能 / 渠道 / 用户 Top N |
二期 api_forceunbind |
新增,限超管,写审计 |
7.3 支付发货(modules/pay/)
deliverGrant 里按商品的 compute 累加 user.compute_balance,写 logtype = Pay 流水;
原来发 Ainum / Meetnum / Tradenum 的三段删除。
8. 数据结构变更
8.1 设备表 device_mac(pb.DBAuthCode)
| 列 | 类型 | 阶段 | 说明 |
|---|---|---|---|
vipdays |
int32 | 一期 | 激活时从批次快照,0 = 不送 |
viplevel |
int32 | 一期 | 1 = VIP,2 = VIP-Pro |
compute_grant |
int64 | 一期 | 赠送算力总量(快照) |
compute_used |
int64 | 一期 | 已消耗,解绑不重置 |
erasestate |
int32 | 二期 | 0 / 1 |
lastuid |
string(50) | 二期 | 最后绑定者 |
复用:usedtime(激活日)、uid、status、disabled。
8.2 生产批次表 production_batch
| 列 | 变更 |
|---|---|
rewardvip |
复用为 VIP 天数 |
viplevel |
新增,默认 1 |
compute_grant |
新增,默认 0 |
rewardtranslate / rewardmeeting |
不再读写 |
8.3 用户表 user
| 列 | 变更 |
|---|---|
vipexptime |
语义收窄为只记自购 |
viplv |
保持 |
compute_balance |
新增 int64,默认 0 |
tradeintegral / meetintegral / aichatintegral |
停用,保留不清(见 Q3) |
8.4 用量流水 user_use_log
| 列 | 变更 |
|---|---|
compute |
新增 int64,本次算力(消耗为负,发放为正) |
compute_device |
新增 int64,从设备扣的部分 |
compute_user |
新增 int64,从用户余额扣的部分 |
compute_over |
新增 int64,超额部分(闸门关时) |
devicemac |
新增 string,扣了哪台设备 |
logtype |
枚举加 AdminAdjust |
现有 addvipday / addtradesecond / addmeetsecond / addagentintegral |
保留:原始量照记 |
8.5 统计表 user_statistics
| 列 | 变更 |
|---|---|
compute_total |
新增 int64,累计消耗算力 |
aichatuptoken / aichatdowntoken |
补写入(存字符数,注释写死口径) |
| 其余 | 不变 |
8.6 商品表 goods
compute 新增 int64。ainum / meetnum / tradenum 保留不读。
8.7 产品表 product
一期:奖励三字段语义改为 VIP 天数 / 等级 / 算力(可复用 bindrewardvpitime,新增 bindviplevel / bindcompute)。
二期:has_storage / need_erase。
8.8 配置表 config(KV)
四个键见 6.1。
⚠️
pb/*.pb.go由 protoc 生成,不能手改。改apps/proto/下.proto后cd apps/proto && python3 pb.py,生成器须是protoc-gen-go v1.36.6, 之后git diff --stat -- apps/services/pb/确认只动了该动的文件。 客户端appconfig_model.dart是手写镜像,新增下发字段后要同步并重跑build_runner。
9. 边界场景
| 场景 | 系统行为 |
|---|---|
| 出厂后长期未激活 | 不计时。激活后仍是完整 vipdays 与 compute_grant |
| A 解绑后 B 绑定 | B 继承剩余 VIP 天数与剩余算力,不重新开始 |
| A 未解绑,B 直接绑定 | 一期允许接管;A 立即失去设备 VIP 与设备算力,需提示 |
| 同账号换手机 | 允许,不算接管 |
| 同一用户绑多台设备 | VIP 取期最晚、等级取最高;算力求和,扣减时先扣剩余最少的那台 |
| 设备算力用完,VIP 还在 | 闸门关:照常用,记超额;闸门开:扣用户余额,也没了则拒绝 |
| VIP 过期,算力还有 | 翻译 / 会议不可用;AI 对话可用并扣算力 |
| VIP 在使用过程中过期 | 当前会话允许跑完,下次开启才拦 |
| VIP 过期后查看历史 | 照常可看 |
| 改换算系数 | 只影响之后的消耗,历史流水里的算力值不重算 |
| 闸门从关切到开 | 已有超额记录不追溯;开启前必须先上线预扣 |
| 后台调整用户算力为负 | 拒绝,余额不能低于 0 |
| 账号注销 | 视同解绑;自购 VIP 与用户算力随账号消失 |
| 设备被后台禁用 / 退货 | 立即不再赋予 VIP 与算力 |
| 时区 | 全部按服务端秒级时间戳 |
10. 与线上现状的差异
一期
| 维度 | 现在(线上) | 目标 |
|---|---|---|
| 功能准入 | 三个额度桶各自拦 | 只看 VIP |
| 用量计量 | 翻译秒 / 会议秒 / AI 次数三桶 | 原始量照记,统一折算算力 |
| 换算系数 | 无 | 后台可配 |
| 生产批次配置 | VIP 天 + 翻译分钟 + 会议分钟 | VIP 天 + 等级 + 算力 |
| VIP 发放 | 绑定时累加天数到用户表 | 设备行存激活日 + 天数,不碰用户表 |
| 发放判据 | 只有第一个绑定者能拿 | 随绑定流转,剩余部分给下一个人 |
| 设备算力记账 | 无 | 设备行 compute_grant / compute_used |
| 用户算力 | 无 | compute_balance,可充值可后台调 |
| 消耗时行为 | 扣桶,不足则拒绝 | 换算 → 先设备后用户扣减 → 闸门关时放行 |
| 商品发放 | AI 次 / 会议分 / 翻译分 / VIP 天 | 算力 + VIP 天 |
| AI 用量 | 只记次数 | 补记输入 / 输出字数 |
| 用量看板 | 无 | 新增 |
二期
接管禁止、清空标签、产品存储开关、固件清空指令、后台强制解绑——见第 5 节。
存量迁移
- VIP 天数不动:存量
vipexptime视同自购 - 旧三桶余额折算成算力写入
compute_balance:翻译秒 ÷ 60 × 系数 + 会议秒 ÷ 60 × 系数 + AI 次 × 1,向上取整。旧字段保留不清 - 存量设备补快照:
vipdays按批次rewardvip回填;compute_grant按批次新值回填(批次没配就是 0);compute_used = 0 - 存量用户已领过的一次性绑定礼不追溯
11. 待决策
已拍板不再讨论:VIP 是功能准入闸门、VIP 过期后翻译与会议纪要受限、用量统一折算算力、设备带赠送算力上限、算力闸门默认关。
| # | 问题 | 建议 |
|---|---|---|
| Q1 | 「禁止接管」挂 has_storage 还是 need_erase? |
挂 need_erase |
| Q2 | 设备赠送算力要不要设有效期(如与 VIP 期同步)? | 不设,用完为止。「上限」语义就是总量,加有效期多一套结算 |
| Q3 | 旧三桶余额:折算进 compute_balance 还是直接放弃? |
折算,用户已购买的额度不能凭空消失 |
| ✅ 已落地:后台可配,默认全 1 | ||
✅ 已落地:UsageType.Compute=5,后台可建算力包商品,客户端会员页展示并可购买。具体档位与定价由运营在后台建商品 |
||
| ✅ 已落地:后台可配(VIP 天数 + 算力),默认 30 天 / 100 算力,都可配 0 = 不送 | ||
✅ 已落地:后台可配(到期前 N 天、算力低于 N),默认 7 天 / 100,配 0 = 不提示;随 user_getcompute 下发,客户端据此显示提示条 |
||
| Q8 | 设备端物理重置要不要做? | 二期与固件一起评估 |
| Q9 | 后台强制解绑的权限与审计? | 限超管,留日志 |
附:口径演进
| 轮次 | 变更 |
|---|---|
| v1 | 权益归属设备、按期发放、期末清零、灵活可配 |
| v2 | 确认「优先扣设备额度」「激活日起算」;新增共享绑定、解绑隐私确权 |
| v3 | 统一 token 计量;带存储禁止接管;清空标签;连续计时 |
| v4 | VIP 成为唯一闸门;生产配置只留 VIP 天数;token 退回纯统计;绑定规则拆两期 |
| v4 补充 | 取消额度闸门;VIP 过期受限范围 = 翻译与会议纪要;功能权限清单与拦截点 |
| v5(本版) | 用量统一折算「算力」,系数后台可配;设备带赠送算力上限;用户可充值算力;算力闸门做成开关默认关;补齐后台功能与接口清单到字段级 |