# 会员权益与算力 · 设计与开发文档 > 状态:**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](../apps/services/modules/user/api_translate.go) 入口 | | 同传 / 面对面(三段式) | ASR 直连,**机器翻译走自家网关** | ✅ | 同上,拦住翻译那一跳即整体不可用 | | 会议纪要 | 录音传 OSS,**服务端起任务** | ✅ | `echomeet` starttask 入口 | | **通话翻译(端到端)** | **客户端直连服务商 WS** | ⚠️ **拦不住** | 只能靠「不下发凭据」+ 客户端自觉 | > ⚠️ 通话翻译走阿里端到端,客户端拿着服务端下发的凭据直连服务商 WebSocket, > **整个过程一个请求都不经过我们的服务器**。唯一的服务端手段是在 > [svcresolve.go](../apps/services/modules/user/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 共用) 1. 收到原始用量(App 上报的秒数 / 字数,或服务端自算的会议秒数) 2. 写原始统计(现有字段照写,不动) 3. 按 `COMPUTE_RATE_*` 换算成算力 `c`,向上取整,最低 1 4. **扣减**:先扣当前绑定设备的剩余(`compute_grant - compute_used`),不够再扣 `user.compute_balance`,扣到 0 为止;仍不够的部分记为**超额** 5. 闸门**开**且超额 > 0 → 拒绝,返回算力不足;闸门**关** → 放行 6. 写流水:`user_use_log` 记本次算力 `c` 与来源拆分(设备 / 用户 / 超额) 7. 累计:`user_statistics.compute_total += c` 8. 返回当前算力余额(设备剩余 + 用户余额) 绑定多台设备时,先扣**剩余最少**的那台(用完一台再动下一台,避免多台都剩一点)。 ### 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 解绑流程(顺序不能反) 1. 点解绑 → 2. 判 `need_erase`,为 0 跳到 6 → 3. 弹确权:清空并解绑 / 保留并解绑 → 4. 选清空且在线:下发**带回执**的清空指令 → 5. 失败/超时让用户选重试或仍然解绑,**不能卡死** → 6. 调解绑接口写标签 → 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 节。 ### 存量迁移 1. **VIP 天数不动**:存量 `vipexptime` 视同自购 2. **旧三桶余额折算成算力**写入 `compute_balance`:翻译秒 ÷ 60 × 系数 + 会议秒 ÷ 60 × 系数 + AI 次 × 1,向上取整。旧字段保留不清 3. **存量设备补快照**:`vipdays` 按批次 `rewardvip` 回填;`compute_grant` 按批次新值回填(批次没配就是 0);`compute_used = 0` 4. **存量用户已领过的一次性绑定礼不追溯** --- ## 11. 待决策 已拍板不再讨论:**VIP 是功能准入闸门**、**VIP 过期后翻译与会议纪要受限**、**用量统一折算算力**、**设备带赠送算力上限**、**算力闸门默认关**。 | # | 问题 | 建议 | |---|---|---| | Q1 | 「禁止接管」挂 `has_storage` 还是 `need_erase`? | **挂 `need_erase`** | | Q2 | 设备赠送算力要不要设有效期(如与 VIP 期同步)? | **不设**,用完为止。「上限」语义就是总量,加有效期多一套结算 | | Q3 | 旧三桶余额:折算进 `compute_balance` 还是直接放弃? | **折算**,用户已购买的额度不能凭空消失 | | ~~Q4~~ | ~~三个换算系数的初始值~~ | ✅ 已落地:后台可配,默认全 1 | | ~~Q5~~ | ~~算力包商品的定价与档位~~ | ✅ 已落地:`UsageType.Compute=5`,后台可建算力包商品,客户端会员页展示并可购买。**具体档位与定价由运营在后台建商品** | | ~~Q6~~ | ~~开户礼送多少~~ | ✅ 已落地:后台可配(VIP 天数 + 算力),默认 30 天 / 100 算力,**都可配 0 = 不送** | | ~~Q7~~ | ~~提前提示阈值~~ | ✅ 已落地:后台可配(到期前 N 天、算力低于 N),默认 7 天 / 100,**配 0 = 不提示**;随 `user_getcompute` 下发,客户端据此显示提示条 | | Q8 | 设备端物理重置要不要做? | 二期与固件一起评估 | | Q9 | 后台强制解绑的权限与审计? | 限超管,留日志 | --- ## 附:口径演进 | 轮次 | 变更 | |---|---| | v1 | 权益归属设备、按期发放、期末清零、灵活可配 | | v2 | 确认「优先扣设备额度」「激活日起算」;新增共享绑定、解绑隐私确权 | | v3 | 统一 token 计量;带存储禁止接管;清空标签;连续计时 | | v4 | VIP 成为唯一闸门;生产配置只留 VIP 天数;token 退回纯统计;绑定规则拆两期 | | v4 补充 | 取消额度闸门;VIP 过期受限范围 = 翻译与会议纪要;功能权限清单与拦截点 | | **v5(本版)** | **用量统一折算「算力」**,系数后台可配;**设备带赠送算力上限**;用户可充值算力;**算力闸门做成开关默认关**;补齐后台功能与接口清单到字段级 |