Browse Source

游客登录入口改为后台按版本控制

需求:后台一个开关控制游客登录按钮显隐,且只对指定版本号的客户端生效,
其余版本一律隐藏(应用商店送审场景:只给正在过审的那一版开)。

白名单语义(comm.ChannelApp.ShowTourists):
  - tourists=false                    → 全部隐藏
  - tourists=true  且 touristsversion 空 → 全部隐藏(没点名任何版本 = 谁都不放行)
  - tourists=true  且 touristsversion=X → 只有版本号等于 X 的客户端可见

留空按"全隐藏"而非"全放行"是刻意选的失败方向:判宽的后果是不该露游客入口的版本
露了出去(过审风险、白嫖新用户开户礼),判严只是入口少显示。要全部隐藏就取消勾选,
后台 saveChannelApp 会拒绝"勾了开关却没填版本"这种等于没开的配置。

判定放在服务端,与 NeedForceUpdate/IsReviewing 同规矩:客户端在 user_getchannelapps
的请求里带 version,服务端把每条渠道配置的 tourists 换算成结论再下发。版本比较各端
各写一遍必然出现实现不一致,而这个开关直接关系到过审,判错代价高。

touristsversion 是 channel_app 的后加列,console 启动时用 ADD COLUMN IF NOT EXISTS
补上——CreateTable 对已存在的表跳过 AutoMigrate,不补就永远没这列。

注:db.proto / user_msg.proto / CLAUDE.md 里另有先于本次改动就存在的编辑,一并带上。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
main
Rodger-Wang 1 month ago
parent
commit
db47e0f3f0
  1. 267
      CLAUDE.md
  2. 32
      apps/admin/app/pages/channels.vue
  3. 23
      apps/proto/db.proto
  4. 44
      apps/proto/user/user_msg.proto
  5. 38
      apps/services/comm/channelapp.go
  6. 41
      apps/services/comm/channelapp_test.go
  7. 11
      apps/services/modules/console/api_channelapp.go
  8. 5
      apps/services/modules/console/api_config.go
  9. 2
      apps/services/modules/user/api_getchannelapp.go
  10. 5
      apps/services/modules/user/api_getchannelapps.go
  11. 32
      apps/services/modules/user/model_user.go
  12. 411
      apps/services/pb/db.pb.go
  13. 516
      apps/services/pb/user_msg.pb.go

267
CLAUDE.md

@ -23,6 +23,7 @@ yunyan-sas/
│ │ ├── pb/ # protoc 生成的 *.pb.go(DO NOT EDIT)
│ │ ├── swagger/、utils/
│ ├── admin/ # 管理后台前端(Nuxt 4 SSR + Tailwind + DaisyUI 4 + Pinia)
│ ├── client/ # 移动端 App(Flutter 3.41 + GetX,pubspec name: eaimar)
│ └── web/ # 用户侧前端骨架(Nuxt 4)
└── deploy/<service>/ # 每服务一份 deploy.sh + docker-compose.yml + env/
```
@ -52,6 +53,20 @@ pnpm build # 产出 .output/(SSR)
本地开发需同时起 console 后端(默认代理到 `127.0.0.1:8080`,见下文 proxy)。超管账号见各 `console.yaml` 的 `AdminAccount/AdminPassword`。
### Client 移动端(在 `apps/client/` 下执行)
```bash
cp .env.example .env # 首次必做,缺 .env 直接起不来(见下文)
flutter pub get
flutter run # 需先 `flutter devices` 确认真机/模拟器
flutter analyze
flutter build apk --debug
./build_channels.sh # 多渠道打包(Android)
```
Flutter 3.41.5 stable(本机 `~/flutter`)。只支持 Android / iOS 两端(pubspec 的 `platforms:` 已锁死)。
iOS 首次还需 `cd ios && pod install`。
### 构建镜像与部署
```bash
@ -136,7 +151,12 @@ ym 首次部署容器一直叫 `starpivot-app` 正是如此)。service 名变
```
就会被注册成路由 `<module>_<methodname小写>`(如 `api_getfactorys`)。新增接口 = 新建 `modules/<mod>/api_xxx.go` 加一个符合签名的方法即可,**无需手动注册**。后缀 `Check` 的方法不注册。
- **错误处理约定**:成功填 `resp`;失败构造 `&pb.ErrorData{Code: pb.ErrorCode_XXX, Message: ...}` 并 `return`。
- **pb 包**:`pb/*.pb.go` 由 `apps/proto/` 下 `.proto` 经 `protoc` + `protoc-gen-go` v1.36 生成,**手动改 .pb.go 无效**;改协议要改 `.proto` 再重新生成。注意 console 模块有本地 gorm struct(非 pb)的 model 文件,见 `modules/console/model_*.go`。
- **pb 包**:`pb/*.pb.go` 由 `apps/proto/` 下 `.proto` 经 `protoc` + `protoc-gen-go` **v1.36.6** 生成
(`cd apps/proto && python3 pb.py`,需 `~/go/bin` 在 PATH 里)。
⚠️ **别照 go.mod 的 `google.golang.org/protobuf v1.36.2` 去装生成器**——那是运行时库版本,
生成器版本写在每个 `.pb.go` 头部(`protoc-gen-go v1.36.6`)。装错版本会让 `pb.py` 把
**全部 22 个文件**降版重写,产出几千行与本次改动无关的 diff。生成后务必
`git diff --stat -- apps/services/pb/` 确认只动了你改的那几个,**手动改 .pb.go 无效**;改协议要改 `.proto` 再重新生成。注意 console 模块有本地 gorm struct(非 pb)的 model 文件,见 `modules/console/model_*.go`。
## Admin 前端约定(关键,易踩坑)
@ -150,6 +170,251 @@ ym 首次部署容器一直叫 `starpivot-app` 正是如此)。service 名变
- **后端返回常多包一层**:如 `getfactorys → {factorys}`、`getproducts → {products}`、`getproduct → {product}`;保存 payload 也常包一层(厂家 `{Factory:{...}}`、产品 `{product:{...}}`);统计 trend 日期字段是 `stat_day`。列表 ID 多以十六进制展示(`id.toString(16).toUpperCase()`)。
- 样式:`app/assets/css/console.css` 由 nuxt.config 引用;DaisyUI 固定 4.x。
## Client 移动端约定(Flutter,2026-08-28 并入 monorepo)
`apps/client` 从 `/Users/yunyanzhineng/work/eaimar_client-main` 搬入,**未带原 `.git`**,历史留在原仓库。
⚠️ 搬仓时源仓库 .gitignore 忽略的文件**不会跟过来**,已手工补回:`.env`、`.mcp.json`、`.metadata`、
`.vscode/settings.json`。(`.icon_preview`、`.vercel`、空的 `.claude` 判定为本机产物,未搬。)
### 与后端怎么对上(联动开发的关键链路)
- 客户端所有业务请求:`POST {SERVER_URL}/api/home/<模块>_<方法小写>`
—— 路径由 gateway 的 `this.gin.Any("/api/:param1/:param2", this.api)`
([wservice_comp.go:66](apps/services/modules/gateway/wservice_comp.go#L66))接住,转发到对应服务里
**反射注册**出来的同名方法。所以**后端加一个 `api_xxx.go` 方法 = 客户端立刻多一个可调接口**,
两边都不用改路由表,只需在 [lib/data/services/network/api.dart](apps/client/lib/data/services/network/api.dart) 补一个静态方法。
- `SERVER_URL` 在 `apps/client/.env` 里,走 `flutter_dotenv`;
[dio_manager.dart](apps/client/lib/data/services/network/dio_manager.dart) 的 `baseUrl` 再按
地区/渠道在 `SERVER_URL` 与 `HW_SERVER_URL` 间选一个(`HW_SERVER_URL` 留空会**回退**到 `SERVER_URL`,不会变成空 host)。
`lib/data/services/network/nw_api.dart` 里那个 `baseApi` 常量已注释废弃,别照着它改。
- **当前这份 client 对应 `ym` 应用**:真实 `.env` 里 `SERVER_URL=HW_SERVER_URL=https://ym-dev.ymaikj.com`
(阿龙测试环境),`Channel=xiaomi`。别照着 `nw_api.dart` 里注释掉的 `api.voitrans.net` 改。
- **本机联调**:`SERVER_URL=http://<局域网IP>:7100`(gateway HTTP 监听端口,见
[deploy/app/confs/gateway.yaml.example](deploy/app/confs/gateway.yaml.example))。
真机调试别写 `127.0.0.1` —— 那是手机自己。
- **两套 "env" 别混**:
- `dotenv.env['X']` = `apps/client/.env`,本机/渠道级,编译进包;
- `AppConfig.env('X')`([appconfig.dart](apps/client/lib/data/models/appconfig.dart))= 后端
`user_getappconfig` 下发的配置(env / agents / mcps / products),由 **console 后台**维护。
- 客户端 `UserGetAppConfigResp`、`DBAgent`、`DBProduct` 等模型是**手写镜像**服务端
`pb.UserGetAppConfigResp`([user_msg.proto:168](apps/proto/user/user_msg.proto#L168))的,
**没有代码生成把两边绑在一起**。改 proto 字段后要手动同步
[appconfig_model.dart](apps/client/lib/data/models/appconfig_model.dart) 并重跑
`dart run build_runner build`(生成 `*.g.dart`)。服务端已为此留了兼容层,
见 [modules/user/compat.go](apps/services/modules/user/compat.go):**Dart 里 non-nullable 字段一旦后端不下发就是
TypeError,整个 `fromJson` 失败**,表现为设备列表/应用配置整体空白——所以后端删字段前先看这个文件。
- `user` 模块的 v2/v3 api 把 `GetAppConfig`/`GetAgents` 列入 `EncryptMsgs`(加密协议),
抓包看到的是密文不是明文 JSON,别以为接口挂了。
### 游客登录与功能闸门(2026-08-29 改)
游客登录**走服务端** `api_sgin` 的 `Tourists` 分支(`stype=6` + `phonemac=设备id`),拿真实雪花 uid 与 JWT。
早先是 `_guestLoginLocal()` 本地伪造会话(token 形如 `guest-xxx`),网关解不出 uid,
游客一个后端请求都发不出去——实名认证接口自然也调不通。
- 服务端 `findtouristformac`([model_user.go](apps/services/modules/user/model_user.go))按设备找回游客账号。
⚠️ **不能改用现成的 `findformac`**:`phonemac` 是所有登录方式建号时都会写的字段,
同一台设备先用手机号登录过、再点游客登录会串进那个正式账号。该函数额外要求
`phone/mail/account/*openid` 全为空,只有游客账号满足。
- ⚠️ 找回逻辑原先是注释掉的,恒定走新建账号分支,后果是游客每次登录都是新账号:
实名记录留不住,且新账号分支紧接着发**新用户开户礼**,等于可以无限白嫖。
- **功能闸门不再按游客身份拦,一律按实名状态拦**:`GuestGuard` 已删除,所有调用点改用
`IdVerifyGuard.blocked()`([id_verify_guard.dart](apps/client/lib/core/utils/id_verify_guard.dart))。
游客点功能弹实名窗,认证通过就能用。卡片角标从「仅浏览」改成「未认证」(复用 `idVerifyNotDone`)。
- `User.isGuest` 现在读登录时写下的 `login_is_tourist` 标记(游客拿到的是正经 uid/JWT,
光看 uid/token 认不出来)。**它已不是功能闸门**,只用于展示层区分身份;登出时随会话一起清。
- 老装机升级上来时本地还留着伪造的 `guest-` token,过不了网关,
splash 的 `_validateTokenAsync` 会清掉会话把人踢回登录页——这是预期行为。
#### 游客登录入口的显隐:后台开关 + 版本限定(2026-08-29 加)
入口显隐由后台「SaaS 管理 → 渠道分发」按 (应用, 渠道) 配置,**判定在服务端**
([comm.ChannelApp.ShowTourists](apps/services/comm/channelapp.go),同 `NeedForceUpdate`/`IsReviewing` 的规矩):
**白名单语义:只有被点名的那一个版本可见,其余一律隐藏。**
| `tourists` | `touristsversion` | 效果 |
|---|---|---|
| 关 | 任意 | 全部版本隐藏 |
| 开 | 空 | 全部版本隐藏(没点名任何版本 = 谁都不放行;后台已拦住这种等于没开的配置) |
| 开 | `1.0.2` | **只有 1.0.2 可见,其余版本一律隐藏** |
留空按「全隐藏」而非「全放行」是刻意选的失败方向:判宽的后果是不该露游客入口的版本
露了出去(过审风险、白嫖开户礼),判严只是入口少显示。**要全部隐藏就取消勾选,
不要靠留空版本号表达**——后台 `saveChannelApp` 会拒绝「勾了开关却没填版本」。
⚠️ **这不向后兼容**:升级前 `tourists=true` 且没填版本的存量配置,升级后入口会消失。
部署后必须去后台把生效版本填上(或确认就是要关掉)。
第三行是送审场景:只给正在过审的那一版开游客登录。客户端在 `user_getchannelapps`
的请求里带 `version`(净版本号,不含构建号),服务端把每条渠道配置的 `tourists`
**换算成结论**再下发——客户端拿到的 `tourists` 已经是「这一版该不该显示」,
**不要再拿 `touristsversion` 自己比一遍**。没上报版本时按不匹配处理(隐藏),
点名了版本却认不出是哪一版只能从严。
- ⚠️ **已发布的老客户端关不掉**:这次改动之前 `_checkGuestLoginConfig()` 恒定写死
`true`([login_controller.dart](apps/client/lib/modules/login/controllers/login_controller.dart)),
入口根本不读服务端配置。所以「其他版本全部隐藏」只对装了本次改动及以后版本的客户端成立,
存量包无论后台怎么配都仍会显示入口。
- 入口所在的 `_buildSocialLoginSection` 必须是 `Obx` 不能是 `Builder`:配置是异步拿到的,
`Builder` 只渲染 onInit 时的初值 `false`,入口再也不会出现。
- 拿不到配置(无网/接口失败)时按**隐藏**处理。反过来默认显示会在送审期把不该露的入口露给审核员。
代价是断网启动后 10 分钟内(`checkForUpdate` 的缓存窗口)入口不出现。
- `touristsversion` 是 `channel_app` 表的后加列,console 启动时由
[api_config.go](apps/services/modules/console/api_config.go) 的 `ADD COLUMN IF NOT EXISTS` 补上
(`CreateTable` 对已存在的表跳过 AutoMigrate,不补就永远没这列)。
### EMAI 助手的端侧指令(2026-08-29 接入)
百炼多模态会在 `RespondingContent` 这一帧里下发端侧函数调用,客户端原先**整个丢掉**了
(只取了 event/text/finished/state 四个字段),所以助手嘴上说"闹钟已经定好",实际什么都没做。
链路:协议层解析 → [assistant_directive_service.dart](apps/client/lib/data/services/assistant_directive_service.dart)
分发 + 落本地记录 → 「代办」页展示(`CalendarController._rebuildEvents`)。
App 内对话页与耳机唤醒(`BesAiSessionService`)两条链路都往同一个 service 送,按指令 id 去重。
抓包实测(原始帧见 `test/assistant_directive_test.dart` 的用例,全是真实 payload):
- 指令在 `payload.output.extra_info.tool_calls`,`arguments` 是**字符串形式的 JSON**,要二次 parse。
- ⚠️ 参数值是**中文自然语言**,哪怕用户全程说英文:`repeat="周一"`、`content="开会"`。别指望 `MON` 这种枚举。
- ⚠️ `extra_info.tool_infos` 是**另一回事**——服务端插件(如 weather)**已经执行完**的结果,端侧不用做事,两者不能混。
- ⚠️ `finish_reason` 决定这一帧的形状:`stop` = 有文案(可能顺带指令);
`command_calls` = **纯指令帧,text/spoken 都是空,而且这一轮不会有 RespondingStarted/Ended**。
照着 text 建气泡会在聊天记录里留下永远填不上的空泡。
- ⚠️ **`time` 不能无条件相信**:实测说 "3:30pm"、文案写"下午3:30",`time` 却给 `"03:30"`
(同批样本里 5pm→17:00、9pm→21:00 又是对的)。`AssistantReminder.disambiguateAfternoon`
按同帧文案里的"下午/晚上/pm"做保守校正,删了会把闹钟定到凌晨。
已知指令(探测所得,**不完整,完整清单要从百炼控制台导**):`SET_clock`(time/date/content/repeat)、
`ROUTE_map`(endLoc_city/endLoc_poi)、`SEND_message`(contact/content)、
`MAKE_A_PHONE_CALL_phone_call`(contact_name)、`INCREASE_DEFAULT_volume`(无参)。
目前**只有 `SET_clock` 真正落地**,其余记一条 `unsupported` 流水而不是丢掉。
`SEND_message` / `MAKE_A_PHONE_CALL_phone_call` 列在 `_declined` 里——本版已移除电话/联系人能力,
接了也执行不了,**要治本得去百炼后台把这两个工具摘掉**。
另有两处模型侧的坑,不是客户端问题:**"取消闹钟"和"记一下待办"都不下发任何指令**,模型却回"已经帮你取消了";
`SEND_message` 的 content 出现过幻觉(说的是"我会迟到",下发的是"项目进展如何了?")。
**当前边界**:指令只在 EMAI 会话建立时(对话页打开或耳机唤醒)才收得到,
「App 没打开也能定闹钟」需要常驻的会话持有者,光把执行代码挪到原生层不解决。
落地也**只到本地**(GetStorage),服务端同步接口未开发——两个模型的 `synced` 字段和 `toJson()`
已按可直接上传的形状设计,接口就绪后补上传即可,不用改结构。
### Android 渠道:国内五家共用一个包(2026-08-29 起)
华为/荣耀/小米/OPPO/vivo **发同一个 APK**,不再按渠道分别打包(`build_channels.sh` 只剩
google 的 aab 需要单独出)。原来靠打包时写进 `.env` 的 `Channel` 区分的逻辑,现在一律
**运行时按设备品牌推导**:
- `getAndroidStoreInfoByBrand()`([version_update_service.dart](apps/client/lib/data/services/version_update_service.dart))
把 `_channel` 设成品牌推导出的渠道,`.env` 的 `Channel` **只作兜底**(品牌认不出的三星/魅族等才用)。
渠道统计、游客登录/跳过设备绑定开关、版本更新地址都走这一个值。
- ⚠️ `GLOBAL_GOOGLE` 与 `OFFICIAL` **不参与品牌推导**:前者装在华为手机上仍须连 `HW_SERVER_URL`
(`dio_manager` 的 baseUrl 只认这个值),后者是官方/内测包才显示的"工具打断"菜单开关。
国内包的兜底值别填这两个。
- ⚠️ `.env` 的 `Channel` 必须写 `UserChannel.fromName` 认识的全名(`CHINA_XIAOMI`),
写成 `xiaomi` 会被解析成 `UNKNOWN`。
- 华为/荣耀商店要求"每次启动重新确认隐私政策",这条判断在
[login_controller.dart](apps/client/lib/modules/login/controllers/login_controller.dart) 的
`_initDeviceInfo()` 里,用 `DeviceBrand.isHuaweiOrHonor(brand, manufacturer)`
([device_brand.dart](apps/client/lib/core/utils/device_brand.dart),两个字段任一命中即算,
老荣耀机型 brand=HONOR/厂商=HUAWEI)。**别改回读 `versionService.cachedChannel`**——那个值在版本
检查跑完前会回退成 `GLOBAL_GOOGLE`,无网启动时合规逻辑直接失效。
`_hasAcceptedPrivacy` 初值 `false`,品牌读出来之前默认"未同意",失败方向偏向合规。
- 口径偏差是已知的取舍:判断依据从"从哪家商店下载"变成了"用哪家的手机"。审核实测都在对应
品牌真机上做,能过审;反向(小米商店的包装在华为手机上)只是多弹一次。
### 必备本机文件
- **`.env` 是硬性前置**:`main.dart` 启动第一步就 `dotenv.load(fileName: ".env")`,且 `.env` 同时被
`pubspec.yaml` 声明为 asset —— 文件不存在**编译期就报 asset 缺失**。已提供 `.env.example`(key 与真实
`.env` 逐项对齐)。`.env` **在 .gitignore 里,不入库**(源仓库 `eaimar_client-main` 的 .gitignore
同样有 `.env*`,本来就从不进 git —— 所以**换机器/重新拉代码后必须手工补 `.env`**,这是搬仓时最容易漏的一步)。
- 真实 `.env` 里 `VOLCANO_*` / `OPENAI_*` **全是空值**:这些第三方能力已改由后端 `AppConfig.env()` 下发,
本机只在绕过后端直连调试时才填。实际必填的只有 `SERVER_URL` 和 `Channel`。
- `.mcp.json` 同样被 pubspec 声明为 asset(`open_ai_service_adapter.dart` 里的加载代码虽已注释,
删文件仍会构建失败)。里面是两个真实 MCP server(`mcp.ideapsound.com` / `api.deapsound.com`),会入库。
### 仓库卫生(重要)
`apps/client/.gitignore` 挡掉的构建产物占 5.8G 中的 5.6G:`build/`(5.2G)、`ios/Pods/`(311M)、
`android/.gradle/`(120M)。实际入库约 **118MB / 3200 文件**,其中 ~40MB 是构建必需的预编译 SDK
(`local_plugins/azure_speech` 的 MicrosoftCognitiveServicesSpeech.xcframework、`device_jieli` 的 JL_BLEKit 等)。
**`build/` 与 `.dart_tool/` 的规则故意不带前导斜杠**,这样才能一并覆盖 `local_plugins/*/android/build` 等嵌套产物。
⚠️ `android/app/sign/eaimar.keystore`(Android 发版签名库)目前**会入库** —— 与本仓库"私有仓库下接受真实凭据"
的既有取舍一致,且不入库会导致其他人打不出可升级的正式包。仓库若要公开,这个必须先摘出去。
### 服务器域名(2026-08-28 统一)
自有服务器域名**一律 `ymaikj.com`**,上一代的 `voitrans.net` / `voitrans.com` / `ideapsound.com` /
`deapsound.com` 已全部清除(含 41 个语言文件里用户可见的 `web.voitrans.com`)。现役清单:
| 用途 | 域名 | 位置 |
|---|---|---|
| 业务后端 | `ym-dev.ymaikj.com` | `.env` 的 `SERVER_URL`/`HW_SERVER_URL` |
| 支付回调 | `pay.ymaikj.com` | `pay_service.dart`、`goods_base_controller.dart` |
| 会议分享 | `share.ymaikj.com` | `share_bottom_sheet.dart` |
| Web 站点 | `web.ymaikj.com` | `member_bottom_sheet.dart`、`meeting_mine_view.dart`、各语言文案 |
| 微信 Universal Link | `ymaikj.com` | `login_service.dart`、`pay_service.dart`、`ios/Runner/Runner.entitlements` |
| MCP(死配置) | `mcp.ymaikj.com`、`api.ymaikj.com` | `.mcp.json` |
⚠️ **微信 Universal Link 改了代码还不够**,三处必须完全一致,否则微信登录与微信支付**静默失败**:
① `universalLink: 'https://ymaikj.com/app/'`(两个 dart 文件)
② `Runner.entitlements` 的 `applinks:ymaikj.com`
③ **微信开放平台后台登记的 Universal Link** + `https://ymaikj.com/.well-known/apple-app-site-association`
代码侧(①②)已改完,**③ 属于外部系统,发版前务必确认已同步**。
⚠️ 另外两处含 `voitrans` 但**不是域名、不要改**:
- `lib/firebase_options.dart` 的 `projectId: 'voitrans'` / `'voitrans-e0e3d'` —— Firebase 项目标识,
改它要在 Firebase 控制台另建项目并换掉 `google-services.json` / `GoogleService-Info.plist`。
- `lib/core/translations/` 里的 key 名(`copyrightVoitrans`、`voitransPrivateCloud`…)—— 是标识符不是文案,
用户不可见,改了要 41 个语言文件连同引用处一起动。
`share_bottom_sheet.dart` 的分享链接格式是 `share.ymaikj.com/share/{serverHost}/ymaikj.com/{id}/{token}`,
**路径第二段是品牌标识、不是要请求的域名**,由 share 端解析,别当成域名误改。
### 其他
- 状态管理 GetX;目录分层见 `apps/client/README.md`(`core/` `data/` `modules/` `routes/`)。
- `local_plugins/` 下 25 个本地插件用 `path:` 依赖,蓝牙/语音/音乐等 native 能力都在这里。
`asr_tr_tts_manager` 在 pubspec 里**是注释掉的**(缺 deepvoice 的 `audio_recorder` 插件,打开会 Gradle 报错)。
- `doc/` 下 41 个语种目录是国际化文案,`tools/i18n_audit.py` 做占位符校验。
## 第三方服务配置:服务端专用类别(2026-08-28 新增)
`svc_config`(后台「第三方服务配置」)默认是**面向客户端**的:[svcresolve.go](apps/services/modules/user/svcresolve.go)
的 `resolveThirdSvcs` 会把 `encrypted` 字段**解密成明文**塞进 `user_getthirdsvcs_v2` /
`user_getappconfig_v3` 的响应下发。
但有些第三方能力只能由服务端调用,凭据是**云账号主 AK/SK**(拿到就能操作整个云账号)。
这类服务放进 `svc_config` 是为了统一后台管理入口,**必须在下发口拦掉**:
- `comm.SvcCatIdVerify = 11`(身份证实名核验)登记在 [comm/svcpool.go](apps/services/comm/svcpool.go)
的 `serverOnlySvcCats` 里;`resolveThirdSvcs` 用 `comm.IsServerOnlySvc` 整条跳过。
- ⚠️ **`svcresolve.go` 里那三行过滤是唯一拦截点**,删掉等于把主账号密钥明文发给每个 App 用户。
`comm/svcpool_serveronly_test.go` 守着这条底线。
- 新增服务端专用类别:`serverOnlySvcCats` 加一行 + admin `serviceconfig.vue` 的 `SERVER_ONLY_SCATS` 加一项
(前端那份只管界面提示,**不产生拦截效果**)。
### 身份证实名核验
- 服务商:阿里云 `Id2MetaVerify`(`cloudauth.aliyuncs.com`,2019-03-07,`ResultObject.BizCode` 1=一致/2=不一致)
与腾讯云 `IdCardVerification`(`faceid.tencentcloudapi.com`,2018-03-01,`Result` "0"=一致/"-1"=不一致)。
实现在 [sys/idverify/](apps/services/sys/idverify/),**无状态工厂**(不同于其它 sys 子系统的启动单例)——
因为配置在 svc_config 里按应用作用域存,调用时才解析。
- **调用失败 ≠ 不一致**:两个 provider 都只在服务商明确判定时返回 `Matched`,其余(网络/鉴权/额度耗尽/
未知返回码)一律返回 error。把它们当成"不一致"会导致服务商欠费时全体用户看到"您填的信息有误"。
- 客户端接口:`user_idverify`(提交核验)、`user_getidverify`(查状态),见
[api_idverify.go](apps/services/modules/user/api_idverify.go)。
- **合规口径**:身份证号**全文不落库**,只存掩码(`4403**********1234`)与加盐 SHA-256 指纹。
盐来自 `ID_HASH_SALT` 环境变量,**留空则不写指纹**(绝不退化成裸哈希——身份证号空间有限,
裸哈希可被彻底反查)。盐一旦启用不要再改,否则历史指纹全部对不上。
- **一证可绑多号**:不拦截,但按指纹回查,后台用户页显示「同证件账号数」。
- 限流:同账号 10 分钟内失败 5 次即拒(`idVerifyFailWindow`/`idVerifyFailLimit`)——服务商按次计费。
- 本地先校验身份证格式(GB 11643 校验位),把明显无效的输入挡在计费调用之前。
## 配置与密钥约定(重要)
- 各 `conf/*.yaml` 与 `deploy/<svc>/deploy.sh` 中**写死了真实的 DSN / 密钥 / 服务器 IP / 仓库密码,且纳入 git**——这是用户在私有仓库下**明确接受**的取舍。修改这些文件时注意它们会随仓库提交。

32
apps/admin/app/pages/channels.vue

@ -69,7 +69,9 @@
<div class="flex flex-wrap items-center gap-1.5 mt-2">
<span v-if="c.force_update" class="flag flag-warn">强制更新</span>
<span v-if="c.tourists" class="flag">游客登录</span>
<span v-if="c.tourists" class="flag" :class="{ 'flag-warn': !c.touristsversion }">
{{ c.touristsversion ? `游客登录 仅 ${c.touristsversion}` : '游客登录 未填版本(不生效)' }}
</span>
<span v-if="c.allowskipdevicebinding" class="flag">可跳过绑定</span>
<span v-if="!c.enable" class="flag flag-off">已停用</span>
</div>
@ -175,6 +177,16 @@
<input v-model="form.tourists" type="checkbox" class="checkbox checkbox-sm checkbox-primary" />
<span>允许游客登录</span>
</label>
<div v-if="form.tourists" class="pl-7">
<span class="ed-label">生效版本(必填)</span>
<input v-model="form.touristsversion" class="input input-bordered input-sm w-full" placeholder="如 1.0.2,只有这一版的客户端能看到游客登录" />
<p class="text-xs text-slate-400 mt-1">
白名单语义:<b>只有填在这里的版本可见,其余版本一律隐藏</b>。
送审场景就是只给正在过审的那一版开。版本号要与客户端上报的一致(不含构建号,如 <code>1.0.2</code>)。
留空等于所有版本都看不到入口——要全部隐藏请直接取消上面的勾选。
</p>
<p v-if="touristsWarn" class="ed-warn">⚠ {{ touristsWarn }}</p>
</div>
<label class="flex items-center gap-2 text-sm cursor-pointer">
<input v-model="form.allowskipdevicebinding" type="checkbox" class="checkbox checkbox-sm checkbox-primary" />
<span>允许跳过设备绑定</span>
@ -236,6 +248,7 @@ interface ChannelApp {
status: number
description: string
tourists: boolean
touristsversion: string
allowskipdevicebinding: boolean
paychannels: string
enable: boolean
@ -299,7 +312,7 @@ function emptyForm(): ChannelApp {
return {
row_id: 0, app_name: '', channel: 0, version: '', min_version: '', force_update: false,
changelog: '', address: '', review_version: '', status: 1, description: '',
tourists: false, allowskipdevicebinding: false, paychannels: '', enable: true,
tourists: false, touristsversion: '', allowskipdevicebinding: false, paychannels: '', enable: true,
}
}
const form = reactive<ChannelApp>(emptyForm())
@ -335,6 +348,17 @@ const payWarnings = computed(() => {
return Object.keys(map).map((k) => ({ key: k, label: payLabel(k), channels: map[k]! }))
})
// 游客登录版本限定的提示:这里只提示,真正的拦截在后端 saveChannelApp(前端提示挡不住直接调接口)。
const touristsWarn = computed(() => {
if (!form.tourists) return ''
const v = (form.touristsversion || '').trim()
if (!v) return '开启游客登录必须填生效版本,留空等于所有版本都看不到入口'
if (form.version.trim() && cmpVer(v, form.version) > 0) {
return '生效版本高于「当前线上版本」,目前线上没有任何一版客户端能看到游客登录入口'
}
return ''
})
const versionWarn = computed(() => {
if (form.force_update && !form.min_version.trim()) return '开启强制更新时必须填「最低支持版本」,否则挡不住任何人'
if (form.min_version.trim() && form.version.trim() && cmpVer(form.min_version, form.version) > 0) {
@ -415,6 +439,10 @@ function togglePay(key: string) {
async function save() {
if (!form.channel) { error('请选择分发渠道'); return }
if (versionWarn.value) { error(versionWarn.value); return }
// 关掉游客登录时顺手清空生效版本:输入框在关掉后是隐藏的,留着旧值会被后端的
// 「填了版本必须勾选开关」校验挡下,用户看不到是哪一项有问题。
if (!form.tourists) form.touristsversion = ''
if (touristsWarn.value) { error(touristsWarn.value); return }
submitting.value = true
try {
await webApi('savechannelapp', { ...form, app_name: scopeApp.value })

23
apps/proto/db.proto

@ -60,6 +60,28 @@ message DBUser {
bool isactivatecode = 48; //@go_tags(`gorm:"isactivatecode" json:"isactivatecode"`) 是否已使用过激活码(厂家公码)每账号一生限领一次
uint32 lastbindproductid = 49; //@go_tags(`gorm:"lastbindproductid" json:"lastbindproductid"`) 最后绑定的产品ID(充值/消耗按此产品归属统计)
string lastbindchannelid = 50; //@go_tags(`gorm:"lastbindchannelid;size:16;index" json:"lastbindchannelid"`) 最后绑定设备的渠道商ID(充值/消耗按此渠道商归属统计与结算)
bool idverified = 51; //@go_tags(`gorm:"idverified;index" json:"idverified"`) 是否已通过身份证实名校验(明细见 useridverify 表)
int64 idverifiedtime = 52; //@go_tags(`gorm:"idverifiedtime" json:"idverifiedtime"`) 实名校验通过时间(0=未通过)
}
//用户实名认证记录(表 useridverify)。一个用户一行。
//
// 合规口径:身份证号**全文不落库**——只存掩码(展示用)与 SHA-256 指纹(排查同证多号用)。
// 指纹加了盐(ID_HASH_SALT),避免拿全国身份证号做彩虹表反查。
// 姓名按业务需要保留原文(开票/客服核实要用),若后续要求更严可再改为加密字段。
message DBUserIdVerify {
string uid = 1; //@go_tags(`gorm:"uid;size:50;primaryKey" json:"uid"`) 用户ID
string realname = 2; //@go_tags(`gorm:"realname;size:64" json:"realname"`) 姓名
string idcardmask = 3; //@go_tags(`gorm:"idcardmask;size:32" json:"idcardmask"`) 身份证号掩码,如 4403**********1234
string idcardhash = 4; //@go_tags(`gorm:"idcardhash;size:64;index" json:"idcardhash"`) 身份证号加盐 SHA-256(后台排查"同一证件多个账号")
string provider = 5; //@go_tags(`gorm:"provider;size:32" json:"provider"`) 核验服务商 aliyun/tencent
string svcid = 6; //@go_tags(`gorm:"svcid;size:64" json:"svcid"`) 使用的第三方服务配置 id
string bizcode = 7; //@go_tags(`gorm:"bizcode;size:16" json:"bizcode"`) 服务商返回的原始结果码(阿里 BizCode / 腾讯 Result)
int64 verifytime = 8; //@go_tags(`gorm:"verifytime" json:"verifytime"`) 校验通过时间(0=未通过)
int32 failcount = 9; //@go_tags(`gorm:"failcount" json:"failcount"`) 累计失败次数(限频用)
int64 lastfailtime = 10; //@go_tags(`gorm:"lastfailtime" json:"lastfailtime"`) 最后一次失败时间
int64 createtime = 11; //@go_tags(`gorm:"createtime" json:"createtime"`) 首次提交时间
int64 updatetime = 12; //@go_tags(`gorm:"updatetime" json:"updatetime"`) 最后更新时间
}
//用户设备数据
@ -317,6 +339,7 @@ message DBChannelApp{
string changelog = 10; //@go_tags(`gorm:"changelog" json:"changelog"`) 更新日志
string reviewversion = 11; //@go_tags(`gorm:"reviewversion" json:"reviewversion"`) 审核中的版本号,客户端报此版本时可隐藏未过审功能
int32 status = 12; //@go_tags(`gorm:"status" json:"status"`) 上架状态 0草稿 1已上架 2审核中 3已下架
string touristsversion = 13; //@go_tags(`gorm:"touristsversion" json:"touristsversion"`) 游客登录生效版本号;非空时仅该版本客户端可见游客登录,其余版本一律隐藏
}

44
apps/proto/user/user_msg.proto

@ -206,7 +206,7 @@ message UserReportAIContentResp{
//获取设备信息 校验升级
message UserGetChannelAppsReq {
string version = 1; //客户端当前版本号(如 1.4.2)。游客登录是否可见由服务端按此版本判定,留空视为不匹配任何「游客登录生效版本」
}
message UserGetChannelAppsResp {
@ -300,3 +300,45 @@ message UserUpdateDeviceSettingResp{
uint64 id = 1;
string lxsetting = 2;
}
//实名认证:提交姓名+身份证号做二要素核验
//路由 user_idverify
message UserIdVerifyReq{
string realname = 1; //姓名
string idcardno = 2; //身份证号(18位;仅用于向服务商核验,服务端不落库全文)
}
message UserIdVerifyResp{
bool verified = 1; //是否核验通过
string realname = 2; //姓名
string idcardmask = 3; //身份证号掩码,如 4403**********1234
int64 verifytime = 4; //通过时间
int32 gender = 5; //按身份证解析出的真实性别 1-男 2-女(0=解析不出),核验通过后已写入用户资料
}
//查询本账号的实名状态
//路由 user_getidverify
message UserGetIdVerifyReq{
}
message UserGetIdVerifyResp{
bool verified = 1; //是否已实名
string realname = 2; //姓名(未实名为空)
string idcardmask = 3; //身份证号掩码(未实名为空)
int64 verifytime = 4; //通过时间(0=未通过)
}
//实时机器翻译(同声传译 / 面对面翻译用)
//
//由服务端调用后台「第三方服务配置」里启用的 MT 服务(类别3),
//云账号凭据因此不必下发到客户端。
//路由 user_translate
message UserTranslateReq{
string text = 1; //待翻译原文
string from = 2; //源语言(BCP-47,如 zh-CN;服务端会归一成服务商要的短码)。**留空 = 自动检测**
string to = 3; //目标语言(BCP-47)
}
message UserTranslateResp{
string text = 1; //译文
string provider = 2; //实际使用的服务商,便于排查
string svcid = 3; //实际使用的服务配置 id
string detected_from = 4;//from 传空(自动检测)时,服务商检测出的源语种短码;否则为空
}

38
apps/services/comm/channelapp.go

@ -72,9 +72,10 @@ type ChannelApp struct {
Description string `gorm:"column:description" json:"description"`
// 能力开关(沿用旧 DBChannelApp 语义)
Tourists bool `gorm:"column:tourists" json:"tourists"` // 允许游客登录
AllowSkipDeviceBinding bool `gorm:"column:allowskipdevicebinding" json:"allowskipdevicebinding"` // 允许跳过设备绑定
PayChannels string `gorm:"column:paychannels;size:128" json:"paychannels"` // 逗号分隔,见 Pay* 常量
Tourists bool `gorm:"column:tourists" json:"tourists"` // 允许游客登录(总开关)
TouristsVersion string `gorm:"column:touristsversion;size:32" json:"touristsversion"` // 游客登录生效版本;非空时只有该版本客户端可见,其余版本一律隐藏
AllowSkipDeviceBinding bool `gorm:"column:allowskipdevicebinding" json:"allowskipdevicebinding"` // 允许跳过设备绑定
PayChannels string `gorm:"column:paychannels;size:128" json:"paychannels"` // 逗号分隔,见 Pay* 常量
Enable bool `gorm:"column:enable" json:"enable"`
Createtime int64 `gorm:"column:createtime" json:"createtime"`
@ -158,6 +159,37 @@ func (c *ChannelApp) IsReviewing(clientVersion string) bool {
return CompareVersion(clientVersion, c.ReviewVersion) == 0
}
// ShowTourists 判断某客户端版本是否该看到「游客登录」入口。
//
// 判定一律在服务端做(同 NeedForceUpdate/IsReviewing):客户端只拿结论,不拿规则。
// 各端各写一遍版本比较必然出现实现不一致,而这个开关直接关系到应用商店过审,判错代价很高。
//
// 语义是「白名单」:**只有被点名的那一个版本可见,其余一律隐藏**。
// - Tourists=false → 一律隐藏(总开关关掉)
// - Tourists=true 且 TouristsVersion="" → 一律隐藏(没点名任何版本 = 谁都不放行)
// - Tourists=true 且 TouristsVersion=X → 只有版本号等于 X 的客户端可见
//
// 送审场景:只给正在审核的那一版开游客登录,线上其它版本不受影响。
//
// ⚠️ 留空按「全隐藏」而非「全放行」处理,是刻意选的失败方向:这个开关一旦判宽,
// 后果是不该露出游客入口的版本露了出去(过审风险、白嫖开户礼);判严只是入口少显示。
// 后台 saveChannelApp 会拦住「勾了开关却没填版本」这种等于没开的配置,避免运营踩空。
//
// 客户端没上报版本时同样隐藏——点名了版本却认不出来是哪一版,只能从严。
func (c *ChannelApp) ShowTourists(clientVersion string) bool {
if c == nil || !c.Tourists {
return false
}
want := strings.TrimSpace(c.TouristsVersion)
if want == "" {
return false
}
if strings.TrimSpace(clientVersion) == "" {
return false
}
return CompareVersion(clientVersion, want) == 0
}
// PickChannelApp 从「应用行 + 全局行」里挑出该渠道生效的一条:应用行覆盖全局行,都没有返回 nil。
// 与 agent / 第三方服务下发同语义(应用优先、无则回退全局)。
func PickChannelApp(rows []*ChannelApp, channel int32) *ChannelApp {

41
apps/services/comm/channelapp_test.go

@ -8,7 +8,7 @@ func TestCompareVersion(t *testing.T) {
want int
}{
{"1.0.0", "1.0.0", 0},
{"1.2", "1.2.0", 0}, // 段数不同,短的补 0
{"1.2", "1.2.0", 0}, // 段数不同,短的补 0
{"1.10.0", "1.9.0", 1}, // 字符串比较会判反,必须按整数
{"1.9.0", "1.10.0", -1},
{"2.0.0", "1.99.99", 1},
@ -86,3 +86,42 @@ func TestSplitPayChannels(t *testing.T) {
t.Fatalf("SplitPayChannels 结果异常: %#v", got)
}
}
// 游客登录的版本限定:这是应用商店过审期的开关,判错要么违规放行、要么审核员看不到入口被拒,
// 三段语义各钉一条。
func TestShowTourists(t *testing.T) {
// 总开关关掉:无论版本、无论有没有配生效版本,一律隐藏。
off := &ChannelApp{Tourists: false, TouristsVersion: "1.0.2"}
if off.ShowTourists("1.0.2") {
t.Fatal("总开关关掉时不该显示游客登录")
}
// 开关开、但没点名任何版本:一律隐藏。白名单语义,不是「没限定就全放行」——
// 判宽的后果是不该露游客入口的版本露了出去,判严只是入口少显示。
none := &ChannelApp{Tourists: true}
for _, v := range []string{"1.0.2", "9.9.9", ""} {
if none.ShowTourists(v) {
t.Fatalf("未填生效版本时 %q 不该可见", v)
}
}
// 开关开、点名 1.0.2:只有这一版可见,高于/低于/没上报一律隐藏。
only := &ChannelApp{Tourists: true, TouristsVersion: "1.0.2"}
if !only.ShowTourists("1.0.2") {
t.Fatal("被点名的版本应可见")
}
// "1.0.2" == "1.0.2.0":段数不同按 0 补齐,别因为后台填了三段、客户端报四段就判不匹配。
if !only.ShowTourists("1.0.2.0") {
t.Fatal("补零等价的版本应可见")
}
for _, v := range []string{"1.0.1", "1.0.3", "1.0.20", "2.0.0", ""} {
if only.ShowTourists(v) {
t.Fatalf("点名 1.0.2 时 %q 不该可见", v)
}
}
var nilApp *ChannelApp
if nilApp.ShowTourists("1.0.2") {
t.Fatal("未配置渠道不该显示游客登录")
}
}

11
apps/services/modules/console/api_channelapp.go

@ -60,6 +60,17 @@ func (this *serverComp) saveChannelApp(c *gin.Context) {
writeErr(c, pb.ErrorCode_ReqParameterError, "「最低支持版本」不能高于「当前线上版本」")
return
}
// 游客登录是白名单语义:只有被点名的那一版可见。勾了开关却不填版本 = 谁都看不到,
// 等于没开——这是配置期就能发现的错,别让运营以为"已经开了"再去查客户端。
// 要全部隐藏就直接取消勾选,不要靠留空版本号来表达。
if m.Tourists && strings.TrimSpace(m.TouristsVersion) == "" {
writeErr(c, pb.ErrorCode_ReqParameterError, "开启游客登录时必须填「生效版本」——留空等于所有版本都看不到入口;要全部隐藏请直接取消勾选")
return
}
if strings.TrimSpace(m.TouristsVersion) != "" && !m.Tourists {
writeErr(c, pb.ErrorCode_ReqParameterError, "填了「游客登录生效版本」就必须同时勾选「允许游客登录」,否则该版本仍然看不到入口")
return
}
now := time.Now().UnixMilli()
m.Updatetime = now
old := &comm.ChannelApp{}

5
apps/services/modules/console/api_config.go

@ -72,6 +72,11 @@ func ensureConfigTables() error {
if err := pg.CreateTable(comm.TableChannelAppCfg, &comm.ChannelApp{}); err != nil {
return err
}
// touristsversion 是后加字段(游客登录生效版本):CreateTable 对已存在的表跳过 AutoMigrate,
// 故显式补列。历史行为空串 = 不限定版本,游客登录按 tourists 总开关全版本生效,行为不变。
if res := postgres.Exec("ALTER TABLE " + comm.TableChannelAppCfg + " ADD COLUMN IF NOT EXISTS touristsversion varchar(32) DEFAULT ''"); res.Error != nil {
return res.Error
}
// 按应用分离的新表(app_name=''为全局默认,'X'为应用X覆盖):第三方服务配置 / 区域覆盖 / Agent 配置。
// 独立于老的 third_svc_config / third_svc_region_override / agent 表,避免影响现有服务接口。
if err := pg.CreateTable(comm.TableSvcConfig, &ThirdSvcConfig{}); err != nil {

2
apps/services/modules/user/api_getchannelapp.go

@ -27,7 +27,7 @@ func (this *apiComp) GetChannelApp(session comm.IUserSession, req *pb.UserGetCha
}
return
}
resp = &pb.UserGetChannelAppResp{App: toPbChannelApp(cfg)}
resp = &pb.UserGetChannelAppResp{App: toPbChannelApp(cfg, req.Version)}
resp.Needupdate, resp.Forceupdate, resp.Reviewing = evalChannelUpgrade(cfg, req.Version)
return
}

5
apps/services/modules/user/api_getchannelapps.go

@ -6,7 +6,8 @@ import (
)
// @Summary 获取渠道包信息
// @Description 获取渠道包信息
// @Description 获取渠道包信息。req.Version 是客户端当前版本号,服务端据此把每条渠道配置里的
// tourists 换算成「这一版是否显示游客登录入口」再下发(见 comm.ChannelApp.ShowTourists)。
// @Tags User
// @Accept json
// @Produce json
@ -18,7 +19,7 @@ func (this *apiComp) GetChannelApps(session comm.IUserSession, req *pb.UserGetCh
model []*pb.DBChannelApp
err error
)
if model, err = this.module.model.getChannelApps(); err != nil {
if model, err = this.module.model.getChannelApps(req.Version); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Message: err.Error(),

32
apps/services/modules/user/model_user.go

@ -52,6 +52,19 @@ func (this *modelUserComp) findformac(mac string) (user *pb.DBUser, err error) {
err = mysql.FindOne(comm.TableUser, user, "phonemac=?", mac)
return
}
// findtouristformac 按设备硬件 id 找回**游客账号**。
//
// 不能直接用 findformac:phonemac 是所有登录方式建号时都会写的字段,
// 同一台设备上先用手机号登录过,再点游客登录就会串进那个正式账号里去。
// 所以这里额外要求所有身份标识都为空——只有游客账号满足这个条件。
func (this *modelUserComp) findtouristformac(mac string) (user *pb.DBUser, err error) {
user = &pb.DBUser{}
err = mysql.FindOne(comm.TableUser, user,
"phonemac=? AND phone='' AND mail='' AND account='' AND wxopenid='' "+
"AND googleopenid='' AND facebookopenid='' AND appleopenid=''", mac)
return
}
func (this *modelUserComp) findforphone(phone string) (user *pb.DBUser, err error) {
user = &pb.DBUser{}
err = mysql.FindOne(comm.TableUser, user, "phone=?", phone)
@ -244,7 +257,12 @@ func (this *modelUserComp) loadChannelApps() ([]*comm.ChannelApp, error) {
}
// toPbChannelApp 把后台配置映射成下发结构;nil 进 nil 出,让上层照旧返回空。
func toPbChannelApp(c *comm.ChannelApp) *pb.DBChannelApp {
//
// clientVer 是客户端上报的当前版本号,只用于把 Tourists 从「后台的原始配置」换算成
// 「这一版客户端到底该不该显示游客登录入口」——下发的 Tourists 是结论而非配置,
// 客户端直接照着显隐即可,不需要也不应该再拿 Touristsversion 自己比一遍。
// Touristsversion 仍原样下发,仅供排查「为什么这版看不到入口」。
func toPbChannelApp(c *comm.ChannelApp, clientVer string) *pb.DBChannelApp {
if c == nil {
return nil
}
@ -253,7 +271,8 @@ func toPbChannelApp(c *comm.ChannelApp) *pb.DBChannelApp {
Version: c.Version,
Description: c.Description,
Address: c.Address,
Tourists: c.Tourists,
Tourists: c.ShowTourists(clientVer),
Touristsversion: c.TouristsVersion,
Allowskipdevicebinding: c.AllowSkipDeviceBinding,
Paychannels: c.PayChannels,
Minversion: c.MinVersion,
@ -278,16 +297,17 @@ func (this *modelUserComp) getChannelAppCfg(channel int32) (*comm.ChannelApp, er
return picked, nil
}
func (this *modelUserComp) getChannelApp(channel int32) (model *pb.DBChannelApp, err error) {
func (this *modelUserComp) getChannelApp(channel int32, clientVer string) (model *pb.DBChannelApp, err error) {
cfg, err := this.getChannelAppCfg(channel)
if err != nil {
return nil, err
}
return toPbChannelApp(cfg), nil
return toPbChannelApp(cfg, clientVer), nil
}
// getChannelApps 下发全部渠道:同一渠道应用行覆盖全局行;草稿状态不下发。
func (this *modelUserComp) getChannelApps() (models []*pb.DBChannelApp, err error) {
// clientVer 供游客登录的版本限定判定,见 toPbChannelApp。
func (this *modelUserComp) getChannelApps(clientVer string) (models []*pb.DBChannelApp, err error) {
rows, err := this.loadChannelApps()
if err != nil {
return nil, err
@ -303,7 +323,7 @@ func (this *modelUserComp) getChannelApps() (models []*pb.DBChannelApp, err erro
if picked == nil || !picked.Enable || picked.Status == comm.ChannelStatusDraft {
continue
}
models = append(models, toPbChannelApp(picked))
models = append(models, toPbChannelApp(picked, clientVer))
}
return models, nil
}

411
apps/services/pb/db.pb.go

@ -232,6 +232,8 @@ type DBUser struct {
Isactivatecode bool `protobuf:"varint,48,opt,name=isactivatecode,proto3" json:"isactivatecode" gorm:"isactivatecode"` //@go_tags(`gorm:"isactivatecode" json:"isactivatecode"`) 是否已使用过激活码(厂家公码)每账号一生限领一次
Lastbindproductid uint32 `protobuf:"varint,49,opt,name=lastbindproductid,proto3" json:"lastbindproductid" gorm:"lastbindproductid"` //@go_tags(`gorm:"lastbindproductid" json:"lastbindproductid"`) 最后绑定的产品ID(充值/消耗按此产品归属统计)
Lastbindchannelid string `protobuf:"bytes,50,opt,name=lastbindchannelid,proto3" json:"lastbindchannelid" gorm:"lastbindchannelid;size:16;index"` //@go_tags(`gorm:"lastbindchannelid;size:16;index" json:"lastbindchannelid"`) 最后绑定设备的渠道商ID(充值/消耗按此渠道商归属统计与结算)
Idverified bool `protobuf:"varint,51,opt,name=idverified,proto3" json:"idverified" gorm:"idverified;index"` //@go_tags(`gorm:"idverified;index" json:"idverified"`) 是否已通过身份证实名校验(明细见 useridverify 表)
Idverifiedtime int64 `protobuf:"varint,52,opt,name=idverifiedtime,proto3" json:"idverifiedtime" gorm:"idverifiedtime"` //@go_tags(`gorm:"idverifiedtime" json:"idverifiedtime"`) 实名校验通过时间(0=未通过)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -518,6 +520,157 @@ func (x *DBUser) GetLastbindchannelid() string {
return ""
}
func (x *DBUser) GetIdverified() bool {
if x != nil {
return x.Idverified
}
return false
}
func (x *DBUser) GetIdverifiedtime() int64 {
if x != nil {
return x.Idverifiedtime
}
return 0
}
// 用户实名认证记录(表 useridverify)。一个用户一行。
//
// 合规口径:身份证号**全文不落库**——只存掩码(展示用)与 SHA-256 指纹(排查同证多号用)。
// 指纹加了盐(ID_HASH_SALT),避免拿全国身份证号做彩虹表反查。
// 姓名按业务需要保留原文(开票/客服核实要用),若后续要求更严可再改为加密字段。
type DBUserIdVerify struct {
state protoimpl.MessageState `protogen:"open.v1"`
Uid string `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid" gorm:"uid;size:50;primaryKey"` //@go_tags(`gorm:"uid;size:50;primaryKey" json:"uid"`) 用户ID
Realname string `protobuf:"bytes,2,opt,name=realname,proto3" json:"realname" gorm:"realname;size:64"` //@go_tags(`gorm:"realname;size:64" json:"realname"`) 姓名
Idcardmask string `protobuf:"bytes,3,opt,name=idcardmask,proto3" json:"idcardmask" gorm:"idcardmask;size:32"` //@go_tags(`gorm:"idcardmask;size:32" json:"idcardmask"`) 身份证号掩码,如 4403**********1234
Idcardhash string `protobuf:"bytes,4,opt,name=idcardhash,proto3" json:"idcardhash" gorm:"idcardhash;size:64;index"` //@go_tags(`gorm:"idcardhash;size:64;index" json:"idcardhash"`) 身份证号加盐 SHA-256(后台排查"同一证件多个账号")
Provider string `protobuf:"bytes,5,opt,name=provider,proto3" json:"provider" gorm:"provider;size:32"` //@go_tags(`gorm:"provider;size:32" json:"provider"`) 核验服务商 aliyun/tencent
Svcid string `protobuf:"bytes,6,opt,name=svcid,proto3" json:"svcid" gorm:"svcid;size:64"` //@go_tags(`gorm:"svcid;size:64" json:"svcid"`) 使用的第三方服务配置 id
Bizcode string `protobuf:"bytes,7,opt,name=bizcode,proto3" json:"bizcode" gorm:"bizcode;size:16"` //@go_tags(`gorm:"bizcode;size:16" json:"bizcode"`) 服务商返回的原始结果码(阿里 BizCode / 腾讯 Result)
Verifytime int64 `protobuf:"varint,8,opt,name=verifytime,proto3" json:"verifytime" gorm:"verifytime"` //@go_tags(`gorm:"verifytime" json:"verifytime"`) 校验通过时间(0=未通过)
Failcount int32 `protobuf:"varint,9,opt,name=failcount,proto3" json:"failcount" gorm:"failcount"` //@go_tags(`gorm:"failcount" json:"failcount"`) 累计失败次数(限频用)
Lastfailtime int64 `protobuf:"varint,10,opt,name=lastfailtime,proto3" json:"lastfailtime" gorm:"lastfailtime"` //@go_tags(`gorm:"lastfailtime" json:"lastfailtime"`) 最后一次失败时间
Createtime int64 `protobuf:"varint,11,opt,name=createtime,proto3" json:"createtime" gorm:"createtime"` //@go_tags(`gorm:"createtime" json:"createtime"`) 首次提交时间
Updatetime int64 `protobuf:"varint,12,opt,name=updatetime,proto3" json:"updatetime" gorm:"updatetime"` //@go_tags(`gorm:"updatetime" json:"updatetime"`) 最后更新时间
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DBUserIdVerify) Reset() {
*x = DBUserIdVerify{}
mi := &file_db_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DBUserIdVerify) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DBUserIdVerify) ProtoMessage() {}
func (x *DBUserIdVerify) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DBUserIdVerify.ProtoReflect.Descriptor instead.
func (*DBUserIdVerify) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{1}
}
func (x *DBUserIdVerify) GetUid() string {
if x != nil {
return x.Uid
}
return ""
}
func (x *DBUserIdVerify) GetRealname() string {
if x != nil {
return x.Realname
}
return ""
}
func (x *DBUserIdVerify) GetIdcardmask() string {
if x != nil {
return x.Idcardmask
}
return ""
}
func (x *DBUserIdVerify) GetIdcardhash() string {
if x != nil {
return x.Idcardhash
}
return ""
}
func (x *DBUserIdVerify) GetProvider() string {
if x != nil {
return x.Provider
}
return ""
}
func (x *DBUserIdVerify) GetSvcid() string {
if x != nil {
return x.Svcid
}
return ""
}
func (x *DBUserIdVerify) GetBizcode() string {
if x != nil {
return x.Bizcode
}
return ""
}
func (x *DBUserIdVerify) GetVerifytime() int64 {
if x != nil {
return x.Verifytime
}
return 0
}
func (x *DBUserIdVerify) GetFailcount() int32 {
if x != nil {
return x.Failcount
}
return 0
}
func (x *DBUserIdVerify) GetLastfailtime() int64 {
if x != nil {
return x.Lastfailtime
}
return 0
}
func (x *DBUserIdVerify) GetCreatetime() int64 {
if x != nil {
return x.Createtime
}
return 0
}
func (x *DBUserIdVerify) GetUpdatetime() int64 {
if x != nil {
return x.Updatetime
}
return 0
}
// 用户设备数据
type DBUserDivice struct {
state protoimpl.MessageState `protogen:"open.v1"`
@ -538,7 +691,7 @@ type DBUserDivice struct {
func (x *DBUserDivice) Reset() {
*x = DBUserDivice{}
mi := &file_db_proto_msgTypes[1]
mi := &file_db_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -550,7 +703,7 @@ func (x *DBUserDivice) String() string {
func (*DBUserDivice) ProtoMessage() {}
func (x *DBUserDivice) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[1]
mi := &file_db_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -563,7 +716,7 @@ func (x *DBUserDivice) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBUserDivice.ProtoReflect.Descriptor instead.
func (*DBUserDivice) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{1}
return file_db_proto_rawDescGZIP(), []int{2}
}
func (x *DBUserDivice) GetId() uint64 {
@ -658,7 +811,7 @@ type DBUserPortrait struct {
func (x *DBUserPortrait) Reset() {
*x = DBUserPortrait{}
mi := &file_db_proto_msgTypes[2]
mi := &file_db_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -670,7 +823,7 @@ func (x *DBUserPortrait) String() string {
func (*DBUserPortrait) ProtoMessage() {}
func (x *DBUserPortrait) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[2]
mi := &file_db_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -683,7 +836,7 @@ func (x *DBUserPortrait) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBUserPortrait.ProtoReflect.Descriptor instead.
func (*DBUserPortrait) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{2}
return file_db_proto_rawDescGZIP(), []int{3}
}
func (x *DBUserPortrait) GetUid() string {
@ -754,7 +907,7 @@ type DBAgent struct {
func (x *DBAgent) Reset() {
*x = DBAgent{}
mi := &file_db_proto_msgTypes[3]
mi := &file_db_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -766,7 +919,7 @@ func (x *DBAgent) String() string {
func (*DBAgent) ProtoMessage() {}
func (x *DBAgent) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[3]
mi := &file_db_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -779,7 +932,7 @@ func (x *DBAgent) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBAgent.ProtoReflect.Descriptor instead.
func (*DBAgent) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{3}
return file_db_proto_rawDescGZIP(), []int{4}
}
func (x *DBAgent) GetId() string {
@ -918,7 +1071,7 @@ type DBMcpServer struct {
func (x *DBMcpServer) Reset() {
*x = DBMcpServer{}
mi := &file_db_proto_msgTypes[4]
mi := &file_db_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -930,7 +1083,7 @@ func (x *DBMcpServer) String() string {
func (*DBMcpServer) ProtoMessage() {}
func (x *DBMcpServer) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[4]
mi := &file_db_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -943,7 +1096,7 @@ func (x *DBMcpServer) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBMcpServer.ProtoReflect.Descriptor instead.
func (*DBMcpServer) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{4}
return file_db_proto_rawDescGZIP(), []int{5}
}
func (x *DBMcpServer) GetId() string {
@ -1017,7 +1170,7 @@ type DBGlobalConfigItem struct {
func (x *DBGlobalConfigItem) Reset() {
*x = DBGlobalConfigItem{}
mi := &file_db_proto_msgTypes[5]
mi := &file_db_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1029,7 +1182,7 @@ func (x *DBGlobalConfigItem) String() string {
func (*DBGlobalConfigItem) ProtoMessage() {}
func (x *DBGlobalConfigItem) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[5]
mi := &file_db_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1042,7 +1195,7 @@ func (x *DBGlobalConfigItem) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBGlobalConfigItem.ProtoReflect.Descriptor instead.
func (*DBGlobalConfigItem) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{5}
return file_db_proto_rawDescGZIP(), []int{6}
}
func (x *DBGlobalConfigItem) GetId() uint64 {
@ -1101,7 +1254,7 @@ type DBAppConfigItem struct {
func (x *DBAppConfigItem) Reset() {
*x = DBAppConfigItem{}
mi := &file_db_proto_msgTypes[6]
mi := &file_db_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1113,7 +1266,7 @@ func (x *DBAppConfigItem) String() string {
func (*DBAppConfigItem) ProtoMessage() {}
func (x *DBAppConfigItem) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[6]
mi := &file_db_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1126,7 +1279,7 @@ func (x *DBAppConfigItem) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBAppConfigItem.ProtoReflect.Descriptor instead.
func (*DBAppConfigItem) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{6}
return file_db_proto_rawDescGZIP(), []int{7}
}
func (x *DBAppConfigItem) GetId() uint64 {
@ -1181,7 +1334,7 @@ type DBSolutionProvider struct {
func (x *DBSolutionProvider) Reset() {
*x = DBSolutionProvider{}
mi := &file_db_proto_msgTypes[7]
mi := &file_db_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1193,7 +1346,7 @@ func (x *DBSolutionProvider) String() string {
func (*DBSolutionProvider) ProtoMessage() {}
func (x *DBSolutionProvider) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[7]
mi := &file_db_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1206,7 +1359,7 @@ func (x *DBSolutionProvider) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBSolutionProvider.ProtoReflect.Descriptor instead.
func (*DBSolutionProvider) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{7}
return file_db_proto_rawDescGZIP(), []int{8}
}
func (x *DBSolutionProvider) GetId() uint32 {
@ -1270,7 +1423,7 @@ type DBBrand struct {
func (x *DBBrand) Reset() {
*x = DBBrand{}
mi := &file_db_proto_msgTypes[8]
mi := &file_db_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1282,7 +1435,7 @@ func (x *DBBrand) String() string {
func (*DBBrand) ProtoMessage() {}
func (x *DBBrand) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[8]
mi := &file_db_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1295,7 +1448,7 @@ func (x *DBBrand) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBBrand.ProtoReflect.Descriptor instead.
func (*DBBrand) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{8}
return file_db_proto_rawDescGZIP(), []int{9}
}
func (x *DBBrand) GetId() uint32 {
@ -1380,7 +1533,7 @@ type DBChannel struct {
func (x *DBChannel) Reset() {
*x = DBChannel{}
mi := &file_db_proto_msgTypes[9]
mi := &file_db_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1392,7 +1545,7 @@ func (x *DBChannel) String() string {
func (*DBChannel) ProtoMessage() {}
func (x *DBChannel) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[9]
mi := &file_db_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1405,7 +1558,7 @@ func (x *DBChannel) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBChannel.ProtoReflect.Descriptor instead.
func (*DBChannel) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{9}
return file_db_proto_rawDescGZIP(), []int{10}
}
func (x *DBChannel) GetId() string {
@ -1549,7 +1702,7 @@ type DBSettlementMonth struct {
func (x *DBSettlementMonth) Reset() {
*x = DBSettlementMonth{}
mi := &file_db_proto_msgTypes[10]
mi := &file_db_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1561,7 +1714,7 @@ func (x *DBSettlementMonth) String() string {
func (*DBSettlementMonth) ProtoMessage() {}
func (x *DBSettlementMonth) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[10]
mi := &file_db_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1574,7 +1727,7 @@ func (x *DBSettlementMonth) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBSettlementMonth.ProtoReflect.Descriptor instead.
func (*DBSettlementMonth) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{10}
return file_db_proto_rawDescGZIP(), []int{11}
}
func (x *DBSettlementMonth) GetPeriod() uint32 {
@ -1710,7 +1863,7 @@ type DBProductionBatch struct {
func (x *DBProductionBatch) Reset() {
*x = DBProductionBatch{}
mi := &file_db_proto_msgTypes[11]
mi := &file_db_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1722,7 +1875,7 @@ func (x *DBProductionBatch) String() string {
func (*DBProductionBatch) ProtoMessage() {}
func (x *DBProductionBatch) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[11]
mi := &file_db_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1735,7 +1888,7 @@ func (x *DBProductionBatch) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBProductionBatch.ProtoReflect.Descriptor instead.
func (*DBProductionBatch) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{11}
return file_db_proto_rawDescGZIP(), []int{12}
}
func (x *DBProductionBatch) GetId() uint32 {
@ -1877,7 +2030,7 @@ type DBProduct struct {
func (x *DBProduct) Reset() {
*x = DBProduct{}
mi := &file_db_proto_msgTypes[12]
mi := &file_db_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1889,7 +2042,7 @@ func (x *DBProduct) String() string {
func (*DBProduct) ProtoMessage() {}
func (x *DBProduct) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[12]
mi := &file_db_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1902,7 +2055,7 @@ func (x *DBProduct) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBProduct.ProtoReflect.Descriptor instead.
func (*DBProduct) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{12}
return file_db_proto_rawDescGZIP(), []int{13}
}
func (x *DBProduct) GetId() uint32 {
@ -2177,7 +2330,7 @@ type DBProductVersion struct {
func (x *DBProductVersion) Reset() {
*x = DBProductVersion{}
mi := &file_db_proto_msgTypes[13]
mi := &file_db_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2189,7 +2342,7 @@ func (x *DBProductVersion) String() string {
func (*DBProductVersion) ProtoMessage() {}
func (x *DBProductVersion) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[13]
mi := &file_db_proto_msgTypes[14]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2202,7 +2355,7 @@ func (x *DBProductVersion) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBProductVersion.ProtoReflect.Descriptor instead.
func (*DBProductVersion) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{13}
return file_db_proto_rawDescGZIP(), []int{14}
}
func (x *DBProductVersion) GetId() uint32 {
@ -2256,13 +2409,14 @@ type DBChannelApp struct {
Changelog string `protobuf:"bytes,10,opt,name=changelog,proto3" json:"changelog" gorm:"changelog"` //@go_tags(`gorm:"changelog" json:"changelog"`) 更新日志
Reviewversion string `protobuf:"bytes,11,opt,name=reviewversion,proto3" json:"reviewversion" gorm:"reviewversion"` //@go_tags(`gorm:"reviewversion" json:"reviewversion"`) 审核中的版本号,客户端报此版本时可隐藏未过审功能
Status int32 `protobuf:"varint,12,opt,name=status,proto3" json:"status" gorm:"status"` //@go_tags(`gorm:"status" json:"status"`) 上架状态 0草稿 1已上架 2审核中 3已下架
Touristsversion string `protobuf:"bytes,13,opt,name=touristsversion,proto3" json:"touristsversion" gorm:"touristsversion"` //@go_tags(`gorm:"touristsversion" json:"touristsversion"`) 游客登录生效版本号;非空时仅该版本客户端可见游客登录,其余版本一律隐藏
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DBChannelApp) Reset() {
*x = DBChannelApp{}
mi := &file_db_proto_msgTypes[14]
mi := &file_db_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2274,7 +2428,7 @@ func (x *DBChannelApp) String() string {
func (*DBChannelApp) ProtoMessage() {}
func (x *DBChannelApp) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[14]
mi := &file_db_proto_msgTypes[15]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2287,7 +2441,7 @@ func (x *DBChannelApp) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBChannelApp.ProtoReflect.Descriptor instead.
func (*DBChannelApp) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{14}
return file_db_proto_rawDescGZIP(), []int{15}
}
func (x *DBChannelApp) GetChannel() int32 {
@ -2374,6 +2528,13 @@ func (x *DBChannelApp) GetStatus() int32 {
return 0
}
func (x *DBChannelApp) GetTouristsversion() string {
if x != nil {
return x.Touristsversion
}
return ""
}
// 授权码数据(按产品分表 license_<pid十六进制>;核心=productid+number 产品级全局序号)
type DBAuthCode struct {
state protoimpl.MessageState `protogen:"open.v1"`
@ -2396,7 +2557,7 @@ type DBAuthCode struct {
func (x *DBAuthCode) Reset() {
*x = DBAuthCode{}
mi := &file_db_proto_msgTypes[15]
mi := &file_db_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2408,7 +2569,7 @@ func (x *DBAuthCode) String() string {
func (*DBAuthCode) ProtoMessage() {}
func (x *DBAuthCode) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[15]
mi := &file_db_proto_msgTypes[16]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2421,7 +2582,7 @@ func (x *DBAuthCode) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBAuthCode.ProtoReflect.Descriptor instead.
func (*DBAuthCode) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{15}
return file_db_proto_rawDescGZIP(), []int{16}
}
func (x *DBAuthCode) GetCode() string {
@ -2537,7 +2698,7 @@ type DBFactoryPublicCode struct {
func (x *DBFactoryPublicCode) Reset() {
*x = DBFactoryPublicCode{}
mi := &file_db_proto_msgTypes[16]
mi := &file_db_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2549,7 +2710,7 @@ func (x *DBFactoryPublicCode) String() string {
func (*DBFactoryPublicCode) ProtoMessage() {}
func (x *DBFactoryPublicCode) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[16]
mi := &file_db_proto_msgTypes[17]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2562,7 +2723,7 @@ func (x *DBFactoryPublicCode) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBFactoryPublicCode.ProtoReflect.Descriptor instead.
func (*DBFactoryPublicCode) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{16}
return file_db_proto_rawDescGZIP(), []int{17}
}
func (x *DBFactoryPublicCode) GetCode() string {
@ -2669,7 +2830,7 @@ type DBGoodsLocal struct {
func (x *DBGoodsLocal) Reset() {
*x = DBGoodsLocal{}
mi := &file_db_proto_msgTypes[17]
mi := &file_db_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2681,7 +2842,7 @@ func (x *DBGoodsLocal) String() string {
func (*DBGoodsLocal) ProtoMessage() {}
func (x *DBGoodsLocal) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[17]
mi := &file_db_proto_msgTypes[18]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2694,7 +2855,7 @@ func (x *DBGoodsLocal) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBGoodsLocal.ProtoReflect.Descriptor instead.
func (*DBGoodsLocal) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{17}
return file_db_proto_rawDescGZIP(), []int{18}
}
func (x *DBGoodsLocal) GetLang() string {
@ -2744,7 +2905,7 @@ type DBGoods struct {
func (x *DBGoods) Reset() {
*x = DBGoods{}
mi := &file_db_proto_msgTypes[18]
mi := &file_db_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2756,7 +2917,7 @@ func (x *DBGoods) String() string {
func (*DBGoods) ProtoMessage() {}
func (x *DBGoods) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[18]
mi := &file_db_proto_msgTypes[19]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2769,7 +2930,7 @@ func (x *DBGoods) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBGoods.ProtoReflect.Descriptor instead.
func (*DBGoods) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{18}
return file_db_proto_rawDescGZIP(), []int{19}
}
func (x *DBGoods) GetId() string {
@ -2857,7 +3018,7 @@ type DBWakeupVoice struct {
func (x *DBWakeupVoice) Reset() {
*x = DBWakeupVoice{}
mi := &file_db_proto_msgTypes[19]
mi := &file_db_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2869,7 +3030,7 @@ func (x *DBWakeupVoice) String() string {
func (*DBWakeupVoice) ProtoMessage() {}
func (x *DBWakeupVoice) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[19]
mi := &file_db_proto_msgTypes[20]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2882,7 +3043,7 @@ func (x *DBWakeupVoice) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBWakeupVoice.ProtoReflect.Descriptor instead.
func (*DBWakeupVoice) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{19}
return file_db_proto_rawDescGZIP(), []int{20}
}
func (x *DBWakeupVoice) GetId() uint32 {
@ -2945,7 +3106,7 @@ type DBUserUseLog struct {
func (x *DBUserUseLog) Reset() {
*x = DBUserUseLog{}
mi := &file_db_proto_msgTypes[20]
mi := &file_db_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2957,7 +3118,7 @@ func (x *DBUserUseLog) String() string {
func (*DBUserUseLog) ProtoMessage() {}
func (x *DBUserUseLog) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[20]
mi := &file_db_proto_msgTypes[21]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2970,7 +3131,7 @@ func (x *DBUserUseLog) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBUserUseLog.ProtoReflect.Descriptor instead.
func (*DBUserUseLog) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{20}
return file_db_proto_rawDescGZIP(), []int{21}
}
func (x *DBUserUseLog) GetId() uint64 {
@ -3061,7 +3222,7 @@ type DBUserStatistics struct {
func (x *DBUserStatistics) Reset() {
*x = DBUserStatistics{}
mi := &file_db_proto_msgTypes[21]
mi := &file_db_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -3073,7 +3234,7 @@ func (x *DBUserStatistics) String() string {
func (*DBUserStatistics) ProtoMessage() {}
func (x *DBUserStatistics) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[21]
mi := &file_db_proto_msgTypes[22]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -3086,7 +3247,7 @@ func (x *DBUserStatistics) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBUserStatistics.ProtoReflect.Descriptor instead.
func (*DBUserStatistics) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{21}
return file_db_proto_rawDescGZIP(), []int{22}
}
func (x *DBUserStatistics) GetUid() string {
@ -3244,7 +3405,7 @@ type DBAppStat struct {
func (x *DBAppStat) Reset() {
*x = DBAppStat{}
mi := &file_db_proto_msgTypes[22]
mi := &file_db_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -3256,7 +3417,7 @@ func (x *DBAppStat) String() string {
func (*DBAppStat) ProtoMessage() {}
func (x *DBAppStat) ProtoReflect() protoreflect.Message {
mi := &file_db_proto_msgTypes[22]
mi := &file_db_proto_msgTypes[23]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -3269,7 +3430,7 @@ func (x *DBAppStat) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBAppStat.ProtoReflect.Descriptor instead.
func (*DBAppStat) Descriptor() ([]byte, []int) {
return file_db_proto_rawDescGZIP(), []int{22}
return file_db_proto_rawDescGZIP(), []int{23}
}
func (x *DBAppStat) GetId() uint64 {
@ -3466,7 +3627,7 @@ var File_db_proto protoreflect.FileDescriptor
const file_db_proto_rawDesc = "" +
"\n" +
"\bdb.proto\x1a\n" +
"enum.proto\"\xae\t\n" +
"enum.proto\"\xf6\t\n" +
"\x06DBUser\x12\x10\n" +
"\x03uid\x18\x01 \x01(\tR\x03uid\x12\x12\n" +
"\x04mail\x18\x02 \x01(\tR\x04mail\x12\x14\n" +
@ -3517,7 +3678,35 @@ const file_db_proto_rawDesc = "" +
"\x11meettotalintegral\x18/ \x01(\x03R\x11meettotalintegral\x12&\n" +
"\x0eisactivatecode\x180 \x01(\bR\x0eisactivatecode\x12,\n" +
"\x11lastbindproductid\x181 \x01(\rR\x11lastbindproductid\x12,\n" +
"\x11lastbindchannelid\x182 \x01(\tR\x11lastbindchannelid\"\xbd\x02\n" +
"\x11lastbindchannelid\x182 \x01(\tR\x11lastbindchannelid\x12\x1e\n" +
"\n" +
"idverified\x183 \x01(\bR\n" +
"idverified\x12&\n" +
"\x0eidverifiedtime\x184 \x01(\x03R\x0eidverifiedtime\"\xec\x02\n" +
"\x0eDBUserIdVerify\x12\x10\n" +
"\x03uid\x18\x01 \x01(\tR\x03uid\x12\x1a\n" +
"\brealname\x18\x02 \x01(\tR\brealname\x12\x1e\n" +
"\n" +
"idcardmask\x18\x03 \x01(\tR\n" +
"idcardmask\x12\x1e\n" +
"\n" +
"idcardhash\x18\x04 \x01(\tR\n" +
"idcardhash\x12\x1a\n" +
"\bprovider\x18\x05 \x01(\tR\bprovider\x12\x14\n" +
"\x05svcid\x18\x06 \x01(\tR\x05svcid\x12\x18\n" +
"\abizcode\x18\a \x01(\tR\abizcode\x12\x1e\n" +
"\n" +
"verifytime\x18\b \x01(\x03R\n" +
"verifytime\x12\x1c\n" +
"\tfailcount\x18\t \x01(\x05R\tfailcount\x12\"\n" +
"\flastfailtime\x18\n" +
" \x01(\x03R\flastfailtime\x12\x1e\n" +
"\n" +
"createtime\x18\v \x01(\x03R\n" +
"createtime\x12\x1e\n" +
"\n" +
"updatetime\x18\f \x01(\x03R\n" +
"updatetime\"\xbd\x02\n" +
"\fDBUserDivice\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x04R\x02id\x12\x10\n" +
"\x03uid\x18\x02 \x01(\tR\x03uid\x12\x1c\n" +
@ -3717,7 +3906,7 @@ const file_db_proto_rawDesc = "" +
"\tproductid\x18\x02 \x01(\rR\tproductid\x12\x18\n" +
"\aversion\x18\x03 \x01(\tR\aversion\x12 \n" +
"\vdescription\x18\x04 \x01(\tR\vdescription\x122\n" +
"\x14updatepackageaddress\x18\x05 \x01(\tR\x14updatepackageaddress\"\x92\x03\n" +
"\x14updatepackageaddress\x18\x05 \x01(\tR\x14updatepackageaddress\"\xbc\x03\n" +
"\fDBChannelApp\x12\x18\n" +
"\achannel\x18\x01 \x01(\x05R\achannel\x12\x18\n" +
"\aversion\x18\x02 \x01(\tR\aversion\x12 \n" +
@ -3733,7 +3922,8 @@ const file_db_proto_rawDesc = "" +
"\tchangelog\x18\n" +
" \x01(\tR\tchangelog\x12$\n" +
"\rreviewversion\x18\v \x01(\tR\rreviewversion\x12\x16\n" +
"\x06status\x18\f \x01(\x05R\x06status\"\xef\x02\n" +
"\x06status\x18\f \x01(\x05R\x06status\x12(\n" +
"\x0ftouristsversion\x18\r \x01(\tR\x0ftouristsversion\"\xef\x02\n" +
"\n" +
"DBAuthCode\x12\x12\n" +
"\x04code\x18\x01 \x01(\tR\x04code\x12%\n" +
@ -3900,55 +4090,56 @@ func file_db_proto_rawDescGZIP() []byte {
}
var file_db_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
var file_db_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
var file_db_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
var file_db_proto_goTypes = []any{
(UserChannel)(0), // 0: UserChannel
(Codetype)(0), // 1: Codetype
(SolutionVendor)(0), // 2: SolutionVendor
(*DBUser)(nil), // 3: DBUser
(*DBUserDivice)(nil), // 4: DBUserDivice
(*DBUserPortrait)(nil), // 5: DBUserPortrait
(*DBAgent)(nil), // 6: DBAgent
(*DBMcpServer)(nil), // 7: DBMcpServer
(*DBGlobalConfigItem)(nil), // 8: DBGlobalConfigItem
(*DBAppConfigItem)(nil), // 9: DBAppConfigItem
(*DBSolutionProvider)(nil), // 10: DBSolutionProvider
(*DBBrand)(nil), // 11: DBBrand
(*DBChannel)(nil), // 12: DBChannel
(*DBSettlementMonth)(nil), // 13: DBSettlementMonth
(*DBProductionBatch)(nil), // 14: DBProductionBatch
(*DBProduct)(nil), // 15: DBProduct
(*DBProductVersion)(nil), // 16: DBProductVersion
(*DBChannelApp)(nil), // 17: DBChannelApp
(*DBAuthCode)(nil), // 18: DBAuthCode
(*DBFactoryPublicCode)(nil), // 19: DBFactoryPublicCode
(*DBGoodsLocal)(nil), // 20: DBGoodsLocal
(*DBGoods)(nil), // 21: DBGoods
(*DBWakeupVoice)(nil), // 22: DBWakeupVoice
(*DBUserUseLog)(nil), // 23: DBUserUseLog
(*DBUserStatistics)(nil), // 24: DBUserStatistics
(*DBAppStat)(nil), // 25: DBAppStat
(UserState)(0), // 26: UserState
(DeviceType)(0), // 27: DeviceType
(AgentSource)(0), // 28: AgentSource
(Region)(0), // 29: Region
(MCPServerType)(0), // 30: MCPServerType
(UsageType)(0), // 31: UsageType
(UserLogType)(0), // 32: UserLogType
(*DBUserIdVerify)(nil), // 4: DBUserIdVerify
(*DBUserDivice)(nil), // 5: DBUserDivice
(*DBUserPortrait)(nil), // 6: DBUserPortrait
(*DBAgent)(nil), // 7: DBAgent
(*DBMcpServer)(nil), // 8: DBMcpServer
(*DBGlobalConfigItem)(nil), // 9: DBGlobalConfigItem
(*DBAppConfigItem)(nil), // 10: DBAppConfigItem
(*DBSolutionProvider)(nil), // 11: DBSolutionProvider
(*DBBrand)(nil), // 12: DBBrand
(*DBChannel)(nil), // 13: DBChannel
(*DBSettlementMonth)(nil), // 14: DBSettlementMonth
(*DBProductionBatch)(nil), // 15: DBProductionBatch
(*DBProduct)(nil), // 16: DBProduct
(*DBProductVersion)(nil), // 17: DBProductVersion
(*DBChannelApp)(nil), // 18: DBChannelApp
(*DBAuthCode)(nil), // 19: DBAuthCode
(*DBFactoryPublicCode)(nil), // 20: DBFactoryPublicCode
(*DBGoodsLocal)(nil), // 21: DBGoodsLocal
(*DBGoods)(nil), // 22: DBGoods
(*DBWakeupVoice)(nil), // 23: DBWakeupVoice
(*DBUserUseLog)(nil), // 24: DBUserUseLog
(*DBUserStatistics)(nil), // 25: DBUserStatistics
(*DBAppStat)(nil), // 26: DBAppStat
(UserState)(0), // 27: UserState
(DeviceType)(0), // 28: DeviceType
(AgentSource)(0), // 29: AgentSource
(Region)(0), // 30: Region
(MCPServerType)(0), // 31: MCPServerType
(UsageType)(0), // 32: UsageType
(UserLogType)(0), // 33: UserLogType
}
var file_db_proto_depIdxs = []int32{
0, // 0: DBUser.channel:type_name -> UserChannel
26, // 1: DBUser.State:type_name -> UserState
27, // 2: DBUserDivice.devicetype:type_name -> DeviceType
28, // 3: DBAgent.source:type_name -> AgentSource
29, // 4: DBMcpServer.region:type_name -> Region
30, // 5: DBMcpServer.stype:type_name -> MCPServerType
29, // 6: DBGlobalConfigItem.region:type_name -> Region
27, // 1: DBUser.State:type_name -> UserState
28, // 2: DBUserDivice.devicetype:type_name -> DeviceType
29, // 3: DBAgent.source:type_name -> AgentSource
30, // 4: DBMcpServer.region:type_name -> Region
31, // 5: DBMcpServer.stype:type_name -> MCPServerType
30, // 6: DBGlobalConfigItem.region:type_name -> Region
2, // 7: DBSolutionProvider.vendor:type_name -> SolutionVendor
27, // 8: DBProduct.devicetype:type_name -> DeviceType
28, // 8: DBProduct.devicetype:type_name -> DeviceType
1, // 9: DBAuthCode.codetype:type_name -> Codetype
31, // 10: DBGoods.usagetype:type_name -> UsageType
32, // 11: DBUserUseLog.logtype:type_name -> UserLogType
32, // 10: DBGoods.usagetype:type_name -> UsageType
33, // 11: DBUserUseLog.logtype:type_name -> UserLogType
12, // [12:12] is the sub-list for method output_type
12, // [12:12] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
@ -3968,7 +4159,7 @@ func file_db_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_db_proto_rawDesc), len(file_db_proto_rawDesc)),
NumEnums: 3,
NumMessages: 23,
NumMessages: 24,
NumExtensions: 0,
NumServices: 0,
},

516
apps/services/pb/user_msg.pb.go

@ -1656,6 +1656,7 @@ func (*UserReportAIContentResp) Descriptor() ([]byte, []int) {
// 获取设备信息 校验升级
type UserGetChannelAppsReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` //客户端当前版本号(如 1.4.2)。游客登录是否可见由服务端按此版本判定,留空视为不匹配任何「游客登录生效版本」
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -1690,6 +1691,13 @@ func (*UserGetChannelAppsReq) Descriptor() ([]byte, []int) {
return file_user_user_msg_proto_rawDescGZIP(), []int{27}
}
func (x *UserGetChannelAppsReq) GetVersion() string {
if x != nil {
return x.Version
}
return ""
}
type UserGetChannelAppsResp struct {
state protoimpl.MessageState `protogen:"open.v1"`
Apps []*DBChannelApp `protobuf:"bytes,1,rep,name=apps,proto3" json:"apps,omitempty"`
@ -2543,6 +2551,375 @@ func (x *UserUpdateDeviceSettingResp) GetLxsetting() string {
return ""
}
// 实名认证:提交姓名+身份证号做二要素核验
// 路由 user_idverify
type UserIdVerifyReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Realname string `protobuf:"bytes,1,opt,name=realname,proto3" json:"realname,omitempty"` //姓名
Idcardno string `protobuf:"bytes,2,opt,name=idcardno,proto3" json:"idcardno,omitempty"` //身份证号(18位;仅用于向服务商核验,服务端不落库全文)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UserIdVerifyReq) Reset() {
*x = UserIdVerifyReq{}
mi := &file_user_user_msg_proto_msgTypes[47]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserIdVerifyReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserIdVerifyReq) ProtoMessage() {}
func (x *UserIdVerifyReq) ProtoReflect() protoreflect.Message {
mi := &file_user_user_msg_proto_msgTypes[47]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserIdVerifyReq.ProtoReflect.Descriptor instead.
func (*UserIdVerifyReq) Descriptor() ([]byte, []int) {
return file_user_user_msg_proto_rawDescGZIP(), []int{47}
}
func (x *UserIdVerifyReq) GetRealname() string {
if x != nil {
return x.Realname
}
return ""
}
func (x *UserIdVerifyReq) GetIdcardno() string {
if x != nil {
return x.Idcardno
}
return ""
}
type UserIdVerifyResp struct {
state protoimpl.MessageState `protogen:"open.v1"`
Verified bool `protobuf:"varint,1,opt,name=verified,proto3" json:"verified,omitempty"` //是否核验通过
Realname string `protobuf:"bytes,2,opt,name=realname,proto3" json:"realname,omitempty"` //姓名
Idcardmask string `protobuf:"bytes,3,opt,name=idcardmask,proto3" json:"idcardmask,omitempty"` //身份证号掩码,如 4403**********1234
Verifytime int64 `protobuf:"varint,4,opt,name=verifytime,proto3" json:"verifytime,omitempty"` //通过时间
Gender int32 `protobuf:"varint,5,opt,name=gender,proto3" json:"gender,omitempty"` //按身份证解析出的真实性别 1-男 2-女(0=解析不出),核验通过后已写入用户资料
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UserIdVerifyResp) Reset() {
*x = UserIdVerifyResp{}
mi := &file_user_user_msg_proto_msgTypes[48]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserIdVerifyResp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserIdVerifyResp) ProtoMessage() {}
func (x *UserIdVerifyResp) ProtoReflect() protoreflect.Message {
mi := &file_user_user_msg_proto_msgTypes[48]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserIdVerifyResp.ProtoReflect.Descriptor instead.
func (*UserIdVerifyResp) Descriptor() ([]byte, []int) {
return file_user_user_msg_proto_rawDescGZIP(), []int{48}
}
func (x *UserIdVerifyResp) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
func (x *UserIdVerifyResp) GetRealname() string {
if x != nil {
return x.Realname
}
return ""
}
func (x *UserIdVerifyResp) GetIdcardmask() string {
if x != nil {
return x.Idcardmask
}
return ""
}
func (x *UserIdVerifyResp) GetVerifytime() int64 {
if x != nil {
return x.Verifytime
}
return 0
}
func (x *UserIdVerifyResp) GetGender() int32 {
if x != nil {
return x.Gender
}
return 0
}
// 查询本账号的实名状态
// 路由 user_getidverify
type UserGetIdVerifyReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UserGetIdVerifyReq) Reset() {
*x = UserGetIdVerifyReq{}
mi := &file_user_user_msg_proto_msgTypes[49]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserGetIdVerifyReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserGetIdVerifyReq) ProtoMessage() {}
func (x *UserGetIdVerifyReq) ProtoReflect() protoreflect.Message {
mi := &file_user_user_msg_proto_msgTypes[49]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserGetIdVerifyReq.ProtoReflect.Descriptor instead.
func (*UserGetIdVerifyReq) Descriptor() ([]byte, []int) {
return file_user_user_msg_proto_rawDescGZIP(), []int{49}
}
type UserGetIdVerifyResp struct {
state protoimpl.MessageState `protogen:"open.v1"`
Verified bool `protobuf:"varint,1,opt,name=verified,proto3" json:"verified,omitempty"` //是否已实名
Realname string `protobuf:"bytes,2,opt,name=realname,proto3" json:"realname,omitempty"` //姓名(未实名为空)
Idcardmask string `protobuf:"bytes,3,opt,name=idcardmask,proto3" json:"idcardmask,omitempty"` //身份证号掩码(未实名为空)
Verifytime int64 `protobuf:"varint,4,opt,name=verifytime,proto3" json:"verifytime,omitempty"` //通过时间(0=未通过)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UserGetIdVerifyResp) Reset() {
*x = UserGetIdVerifyResp{}
mi := &file_user_user_msg_proto_msgTypes[50]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserGetIdVerifyResp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserGetIdVerifyResp) ProtoMessage() {}
func (x *UserGetIdVerifyResp) ProtoReflect() protoreflect.Message {
mi := &file_user_user_msg_proto_msgTypes[50]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserGetIdVerifyResp.ProtoReflect.Descriptor instead.
func (*UserGetIdVerifyResp) Descriptor() ([]byte, []int) {
return file_user_user_msg_proto_rawDescGZIP(), []int{50}
}
func (x *UserGetIdVerifyResp) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
func (x *UserGetIdVerifyResp) GetRealname() string {
if x != nil {
return x.Realname
}
return ""
}
func (x *UserGetIdVerifyResp) GetIdcardmask() string {
if x != nil {
return x.Idcardmask
}
return ""
}
func (x *UserGetIdVerifyResp) GetVerifytime() int64 {
if x != nil {
return x.Verifytime
}
return 0
}
// 实时机器翻译(同声传译 / 面对面翻译用)
//
// 由服务端调用后台「第三方服务配置」里启用的 MT 服务(类别3),
// 云账号凭据因此不必下发到客户端。
// 路由 user_translate
type UserTranslateReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"` //待翻译原文
From string `protobuf:"bytes,2,opt,name=from,proto3" json:"from,omitempty"` //源语言(BCP-47,如 zh-CN;服务端会归一成服务商要的短码)。**留空 = 自动检测**
To string `protobuf:"bytes,3,opt,name=to,proto3" json:"to,omitempty"` //目标语言(BCP-47)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UserTranslateReq) Reset() {
*x = UserTranslateReq{}
mi := &file_user_user_msg_proto_msgTypes[51]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserTranslateReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserTranslateReq) ProtoMessage() {}
func (x *UserTranslateReq) ProtoReflect() protoreflect.Message {
mi := &file_user_user_msg_proto_msgTypes[51]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserTranslateReq.ProtoReflect.Descriptor instead.
func (*UserTranslateReq) Descriptor() ([]byte, []int) {
return file_user_user_msg_proto_rawDescGZIP(), []int{51}
}
func (x *UserTranslateReq) GetText() string {
if x != nil {
return x.Text
}
return ""
}
func (x *UserTranslateReq) GetFrom() string {
if x != nil {
return x.From
}
return ""
}
func (x *UserTranslateReq) GetTo() string {
if x != nil {
return x.To
}
return ""
}
type UserTranslateResp struct {
state protoimpl.MessageState `protogen:"open.v1"`
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"` //译文
Provider string `protobuf:"bytes,2,opt,name=provider,proto3" json:"provider,omitempty"` //实际使用的服务商,便于排查
Svcid string `protobuf:"bytes,3,opt,name=svcid,proto3" json:"svcid,omitempty"` //实际使用的服务配置 id
DetectedFrom string `protobuf:"bytes,4,opt,name=detected_from,json=detectedFrom,proto3" json:"detected_from,omitempty"` //from 传空(自动检测)时,服务商检测出的源语种短码;否则为空
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UserTranslateResp) Reset() {
*x = UserTranslateResp{}
mi := &file_user_user_msg_proto_msgTypes[52]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserTranslateResp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserTranslateResp) ProtoMessage() {}
func (x *UserTranslateResp) ProtoReflect() protoreflect.Message {
mi := &file_user_user_msg_proto_msgTypes[52]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserTranslateResp.ProtoReflect.Descriptor instead.
func (*UserTranslateResp) Descriptor() ([]byte, []int) {
return file_user_user_msg_proto_rawDescGZIP(), []int{52}
}
func (x *UserTranslateResp) GetText() string {
if x != nil {
return x.Text
}
return ""
}
func (x *UserTranslateResp) GetProvider() string {
if x != nil {
return x.Provider
}
return ""
}
func (x *UserTranslateResp) GetSvcid() string {
if x != nil {
return x.Svcid
}
return ""
}
func (x *UserTranslateResp) GetDetectedFrom() string {
if x != nil {
return x.DetectedFrom
}
return ""
}
var File_user_user_msg_proto protoreflect.FileDescriptor
const file_user_user_msg_proto_rawDesc = "" +
@ -2684,8 +3061,9 @@ const file_user_user_msg_proto_rawDesc = "" +
"\bdescribe\x18\x02 \x01(\tR\bdescribe\x12\x18\n" +
"\amessage\x18\x03 \x03(\tR\amessage\x12$\n" +
"\rreportContent\x18\x04 \x01(\tR\rreportContent\"\x19\n" +
"\x17UserReportAIContentResp\"\x17\n" +
"\x15UserGetChannelAppsReq\";\n" +
"\x17UserReportAIContentResp\"1\n" +
"\x15UserGetChannelAppsReq\x12\x18\n" +
"\aversion\x18\x01 \x01(\tR\aversion\";\n" +
"\x16UserGetChannelAppsResp\x12!\n" +
"\x04apps\x18\x01 \x03(\v2\r.DBChannelAppR\x04apps\"J\n" +
"\x14UserGetChannelAppReq\x12\x18\n" +
@ -2738,7 +3116,39 @@ const file_user_user_msg_proto_rawDesc = "" +
"\tlxsetting\x18\x02 \x01(\tR\tlxsetting\"K\n" +
"\x1bUserUpdateDeviceSettingResp\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x04R\x02id\x12\x1c\n" +
"\tlxsetting\x18\x02 \x01(\tR\tlxsettingB\x06Z\x04.;pbb\x06proto3"
"\tlxsetting\x18\x02 \x01(\tR\tlxsetting\"I\n" +
"\x0fUserIdVerifyReq\x12\x1a\n" +
"\brealname\x18\x01 \x01(\tR\brealname\x12\x1a\n" +
"\bidcardno\x18\x02 \x01(\tR\bidcardno\"\xa2\x01\n" +
"\x10UserIdVerifyResp\x12\x1a\n" +
"\bverified\x18\x01 \x01(\bR\bverified\x12\x1a\n" +
"\brealname\x18\x02 \x01(\tR\brealname\x12\x1e\n" +
"\n" +
"idcardmask\x18\x03 \x01(\tR\n" +
"idcardmask\x12\x1e\n" +
"\n" +
"verifytime\x18\x04 \x01(\x03R\n" +
"verifytime\x12\x16\n" +
"\x06gender\x18\x05 \x01(\x05R\x06gender\"\x14\n" +
"\x12UserGetIdVerifyReq\"\x8d\x01\n" +
"\x13UserGetIdVerifyResp\x12\x1a\n" +
"\bverified\x18\x01 \x01(\bR\bverified\x12\x1a\n" +
"\brealname\x18\x02 \x01(\tR\brealname\x12\x1e\n" +
"\n" +
"idcardmask\x18\x03 \x01(\tR\n" +
"idcardmask\x12\x1e\n" +
"\n" +
"verifytime\x18\x04 \x01(\x03R\n" +
"verifytime\"J\n" +
"\x10UserTranslateReq\x12\x12\n" +
"\x04text\x18\x01 \x01(\tR\x04text\x12\x12\n" +
"\x04from\x18\x02 \x01(\tR\x04from\x12\x0e\n" +
"\x02to\x18\x03 \x01(\tR\x02to\"~\n" +
"\x11UserTranslateResp\x12\x12\n" +
"\x04text\x18\x01 \x01(\tR\x04text\x12\x1a\n" +
"\bprovider\x18\x02 \x01(\tR\bprovider\x12\x14\n" +
"\x05svcid\x18\x03 \x01(\tR\x05svcid\x12#\n" +
"\rdetected_from\x18\x04 \x01(\tR\fdetectedFromB\x06Z\x04.;pbb\x06proto3"
var (
file_user_user_msg_proto_rawDescOnce sync.Once
@ -2752,7 +3162,7 @@ func file_user_user_msg_proto_rawDescGZIP() []byte {
return file_user_user_msg_proto_rawDescData
}
var file_user_user_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 52)
var file_user_user_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 58)
var file_user_user_msg_proto_goTypes = []any{
(*UserSginReq)(nil), // 0: UserSginReq
(*UserSginResp)(nil), // 1: UserSginResp
@ -2801,53 +3211,59 @@ var file_user_user_msg_proto_goTypes = []any{
(*UserUpdateAppSettingResp)(nil), // 44: UserUpdateAppSettingResp
(*UserUpdateDeviceSettingReq)(nil), // 45: UserUpdateDeviceSettingReq
(*UserUpdateDeviceSettingResp)(nil), // 46: UserUpdateDeviceSettingResp
nil, // 47: UserGetAppConfigResp.EnvEntry
nil, // 48: UserGetAppConfigResp.McpsEntry
nil, // 49: UserPushActionReq.ActionsEntry
nil, // 50: UserUsagesReq.UsagesEntry
nil, // 51: UserUsagesResp.UsagesEntry
(SginTyoe)(0), // 52: SginTyoe
(UserChannel)(0), // 53: UserChannel
(*DBUser)(nil), // 54: DBUser
(*DBUserDivice)(nil), // 55: DBUserDivice
(MCPServerType)(0), // 56: MCPServerType
(*DBAgent)(nil), // 57: DBAgent
(*DBProduct)(nil), // 58: DBProduct
(*DBProductVersion)(nil), // 59: DBProductVersion
(*DBChannelApp)(nil), // 60: DBChannelApp
(UsageType)(0), // 61: UsageType
(*DBWakeupVoice)(nil), // 62: DBWakeupVoice
(*DBUserStatistics)(nil), // 63: DBUserStatistics
(*DBUuserAppSetting)(nil), // 64: DBUuserAppSetting
(*UserIdVerifyReq)(nil), // 47: UserIdVerifyReq
(*UserIdVerifyResp)(nil), // 48: UserIdVerifyResp
(*UserGetIdVerifyReq)(nil), // 49: UserGetIdVerifyReq
(*UserGetIdVerifyResp)(nil), // 50: UserGetIdVerifyResp
(*UserTranslateReq)(nil), // 51: UserTranslateReq
(*UserTranslateResp)(nil), // 52: UserTranslateResp
nil, // 53: UserGetAppConfigResp.EnvEntry
nil, // 54: UserGetAppConfigResp.McpsEntry
nil, // 55: UserPushActionReq.ActionsEntry
nil, // 56: UserUsagesReq.UsagesEntry
nil, // 57: UserUsagesResp.UsagesEntry
(SginTyoe)(0), // 58: SginTyoe
(UserChannel)(0), // 59: UserChannel
(*DBUser)(nil), // 60: DBUser
(*DBUserDivice)(nil), // 61: DBUserDivice
(MCPServerType)(0), // 62: MCPServerType
(*DBAgent)(nil), // 63: DBAgent
(*DBProduct)(nil), // 64: DBProduct
(*DBProductVersion)(nil), // 65: DBProductVersion
(*DBChannelApp)(nil), // 66: DBChannelApp
(UsageType)(0), // 67: UsageType
(*DBWakeupVoice)(nil), // 68: DBWakeupVoice
(*DBUserStatistics)(nil), // 69: DBUserStatistics
(*DBUuserAppSetting)(nil), // 70: DBUuserAppSetting
}
var file_user_user_msg_proto_depIdxs = []int32{
52, // 0: UserSginReq.stype:type_name -> SginTyoe
53, // 1: UserSginReq.channel:type_name -> UserChannel
54, // 2: UserSginResp.user:type_name -> DBUser
55, // 3: UserSginResp.devices:type_name -> DBUserDivice
53, // 4: UserGetInfoReq.channel:type_name -> UserChannel
54, // 5: UserGetInfoResp.user:type_name -> DBUser
55, // 6: UserGetInfoResp.devices:type_name -> DBUserDivice
55, // 7: UserBindDeviceResp.device:type_name -> DBUserDivice
55, // 8: UserBindAuthCodeResp.device:type_name -> DBUserDivice
56, // 9: McpServer.type:type_name -> MCPServerType
47, // 10: UserGetAppConfigResp.env:type_name -> UserGetAppConfigResp.EnvEntry
57, // 11: UserGetAppConfigResp.agents:type_name -> DBAgent
48, // 12: UserGetAppConfigResp.mcps:type_name -> UserGetAppConfigResp.McpsEntry
58, // 13: UserGetAppConfigResp.products:type_name -> DBProduct
58, // 14: UserGetProductResp.product:type_name -> DBProduct
59, // 15: UserGetProductVersionsResp.versions:type_name -> DBProductVersion
60, // 16: UserGetChannelAppsResp.apps:type_name -> DBChannelApp
60, // 17: UserGetChannelAppResp.app:type_name -> DBChannelApp
49, // 18: UserPushActionReq.actions:type_name -> UserPushActionReq.ActionsEntry
55, // 19: UserGetDevicesResp.devices:type_name -> DBUserDivice
61, // 20: UserUsagesReq.usagetype:type_name -> UsageType
50, // 21: UserUsagesReq.usages:type_name -> UserUsagesReq.UsagesEntry
51, // 22: UserUsagesResp.usages:type_name -> UserUsagesResp.UsagesEntry
62, // 23: UserGetWakeupVoicesResp.voices:type_name -> DBWakeupVoice
63, // 24: UserGetStatisticsResp.statistics:type_name -> DBUserStatistics
64, // 25: UserGetAppSettingResp.setting:type_name -> DBUuserAppSetting
64, // 26: UserUpdateAppSettingReq.setting:type_name -> DBUuserAppSetting
58, // 0: UserSginReq.stype:type_name -> SginTyoe
59, // 1: UserSginReq.channel:type_name -> UserChannel
60, // 2: UserSginResp.user:type_name -> DBUser
61, // 3: UserSginResp.devices:type_name -> DBUserDivice
59, // 4: UserGetInfoReq.channel:type_name -> UserChannel
60, // 5: UserGetInfoResp.user:type_name -> DBUser
61, // 6: UserGetInfoResp.devices:type_name -> DBUserDivice
61, // 7: UserBindDeviceResp.device:type_name -> DBUserDivice
61, // 8: UserBindAuthCodeResp.device:type_name -> DBUserDivice
62, // 9: McpServer.type:type_name -> MCPServerType
53, // 10: UserGetAppConfigResp.env:type_name -> UserGetAppConfigResp.EnvEntry
63, // 11: UserGetAppConfigResp.agents:type_name -> DBAgent
54, // 12: UserGetAppConfigResp.mcps:type_name -> UserGetAppConfigResp.McpsEntry
64, // 13: UserGetAppConfigResp.products:type_name -> DBProduct
64, // 14: UserGetProductResp.product:type_name -> DBProduct
65, // 15: UserGetProductVersionsResp.versions:type_name -> DBProductVersion
66, // 16: UserGetChannelAppsResp.apps:type_name -> DBChannelApp
66, // 17: UserGetChannelAppResp.app:type_name -> DBChannelApp
55, // 18: UserPushActionReq.actions:type_name -> UserPushActionReq.ActionsEntry
61, // 19: UserGetDevicesResp.devices:type_name -> DBUserDivice
67, // 20: UserUsagesReq.usagetype:type_name -> UsageType
56, // 21: UserUsagesReq.usages:type_name -> UserUsagesReq.UsagesEntry
57, // 22: UserUsagesResp.usages:type_name -> UserUsagesResp.UsagesEntry
68, // 23: UserGetWakeupVoicesResp.voices:type_name -> DBWakeupVoice
69, // 24: UserGetStatisticsResp.statistics:type_name -> DBUserStatistics
70, // 25: UserGetAppSettingResp.setting:type_name -> DBUuserAppSetting
70, // 26: UserUpdateAppSettingReq.setting:type_name -> DBUuserAppSetting
19, // 27: UserGetAppConfigResp.McpsEntry.value:type_name -> McpServer
28, // [28:28] is the sub-list for method output_type
28, // [28:28] is the sub-list for method input_type
@ -2870,7 +3286,7 @@ func file_user_user_msg_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_user_user_msg_proto_rawDesc), len(file_user_user_msg_proto_rawDesc)),
NumEnums: 0,
NumMessages: 52,
NumMessages: 58,
NumExtensions: 0,
NumServices: 0,
},

Loading…
Cancel
Save