用户指南
本指南面向平台管理员与运营人员。
角色说明
- 管理员:维护项目、版本、公告、反馈与日志
- API 调用方:使用 API Key 调用对外接口
后台页面说明
后台入口为 /admin,左侧菜单包含以下页面。各页面的新建入口统一是页面右上角的“新增”按钮,点击后在弹窗中填写并提交;列表里的“复制配置”会带着原记录的内容直接打开新建弹窗。
新增与编辑弹窗内容改过之后,点弹窗外的遮罩、按 ESC、点右上角关闭或底部“取消”都会先弹一次确认,选“放弃修改”才真的关闭,避免长篇的发布说明、公告正文误触丢失;没改过则照常直接关闭,点“保存”成功后也不会再问。
列表通用操作
所有列表页共用同一套数据表格,一个字段一列:
- 列显隐:表格右上角的「列」按钮里勾选要显示的列。ID、User-Agent、创建时间这类排查时才用得上的字段默认隐藏,需要时开出来即可。选择按页面记在浏览器本地,下次进来还在;「恢复默认」回到初始那几列。
- 搜索:左上角搜索框,停止输入后自动查询,命中范围是整个项目而不只是当前页。各页可搜的字段见下面各节。
- 筛选:搜索框右侧的下拉,按平台、级别、状态等维度收窄。改任何一个条件都会回到第一页。「重置」清空搜索与全部筛选。
- 行详情:表格里的长内容一律截成一行,点行首的展开图标(或直接点这一行)会从右侧滑出详情抽屉,里面是这条记录的全部字段——包括你在「列」里关掉的那些——反馈正文、日志正文、发布说明、项目描述都在这里完整展开,Markdown 会正常渲染,
device_info/custom_data展开成可折叠的 JSON 树。抽屉顶部可以「上一条 / 下一条」连着看,也能用左右方向键;翻到本页首尾时会自动加载相邻一页并接着显示,列表也同步翻到那一页,所以能一路看完当前筛选下的全部数据;「复制」按钮把整条详情拷进剪贴板,Esc 关闭。 - 列宽:把鼠标移到表头两列之间的分隔线上可以左右拖动调整列宽,双击还原。调过的列宽会记在浏览器本地。
- 固定列:横向滚动时,最右侧的「操作」列固定不动,宽表也不用滚回去才能点按钮。
- 概览
- 查看项目数、Token 数、版本/公告/反馈/日志统计
- 用于发布前后快速巡检
- 项目管理
- 新建、编辑、删除项目
- 维护
project_key、名称、仓库地址、官网、文档链接、作者、发布时间等 - 搜索命中
project_key、名称、描述、作者、仓库地址与历史 Key —— 项目改名后按旧 Key 也能找到 - 项目描述支持 Markdown(GFM)语法,表单可在“编写/预览”间切换
- 在项目列表中可直接打开“项目展示页”链接(
/projects/{project_key}) - 编辑项目时可指定「文件存储」(留空用实例默认存储),并开启「镜像 GitHub Release 附件」
- 删除项目会一并删除它在文件存储中的全部文件
- 版本管理
- 选择项目后发布版本、编辑版本、删除版本
- 搜索命中版本号、可比较版本号、标题与更新内容;可按平台、预览版、废弃、里程碑筛选
- 维护语义化版本号、可比较版本号、里程碑、更新内容、下载地址、平台、发布时间
- 更新内容支持 Markdown(GFM)语法,可直接粘贴 GitHub Release 正文
- 支持 latest/preview、废弃标记等发布策略
- 项目注册了语言后,弹窗顶部出现语言页签,可为标题与更新内容录入译文,也可一键 AI 翻译
- 下载链接列表右上角的「从文件库添加」可把文件分发里的文件以直链追加进来
- 下载链接含 GitHub Release 附件的版本,操作列会出现「镜像 GitHub 附件到文件存储」按钮
- 文件分发
- 选择项目后上传安装包等文件(可多选,大文件自动分片上传,失败的分片会自动重试),每个文件得到一条固定直链
{分发域名}/f/{项目}/{文件 ID}/{文件名} - 直链直接返回文件内容、不经过跳转,可用于版本下载链接、Microsoft Store 等要求直链的应用商店提交
- 直链写入后永不改变内容;要替换安装包请上传新文件,再把版本的下载链接换成新直链
- 状态:「可分发」可以下载;「写入中」表示正在转存到 WebDAV 或正在下载 GitHub 附件,列表会自动刷新;「失败」可在「错误」列查看原因并点「重试」(上传的文件失败后 7 天内可重试,GitHub 附件会重新下载)
- 「引用版本」列出下载链接指向该文件的版本,删除前会提示;搜索命中文件名、文件 ID 与 SHA-256
- 「上传文件」打开上传弹窗:把文件拖进虚线框或点击选择,可一次添加多个;也可以直接把文件拖到页面上,弹窗会自动打开。空文件与超过大小上限的文件会标出并跳过;弹窗里可选择本次写入的存储。点「开始上传」后弹窗关闭,进度显示在文件列表上方,可随时取消
- 删除后源站立即 404。启用了 CDN 缓存刷新(阿里云)时,删除会自动提交直链的刷新任务,操作列也有「刷新 CDN 缓存」按钮;未启用时 CDN 已缓存的副本在过期前仍可下载,需要到 CDN 控制台刷新
- 公告管理
- 选择项目后发布公告
- 搜索命中标题、正文与作者;可按平台、是否置顶、是否隐藏筛选
- 支持置顶、发布时间与正文内容维护
- 正文支持 Markdown(GFM)语法;展示页仅显示摘要,点击“查看全文”弹窗查看完整内容
- 行为分析
事件不需要预先在后台登记。 客户端调一次 client.public.track("事件名"),服务端第一次 收到就自动建立定义,随后出现在下面的「事件清单」里。这是与旧版「行为管理」最关键的差别—— 旧版要求先在后台建定义、把生成的 ID 硬编码进客户端,那道门槛让该功能从未被真正用起来。
本模块分七个子页:
- 概览:事件总量、独立用户数、活跃会话、事件种类四个 KPI,加上事件量趋势(可按事件 / 平台 / 地区拆分)、事件排行、平台与地区分布、活跃节律热力图
- 事件清单:自动发现的全部事件。能做的只有补充显示名与描述、把停用的事件归档—— 事件名是客户端上报时使用的键,不可修改
- 漏斗:按顺序串联 2 到 8 个事件,看每一步掉了多少人。转化窗口从第一步算起
- 留存:按首次触发起始事件的日期把用户分组,看其后各周期的回访比例。 尚未走完的周期显示为空格而不是 0%——把还没发生的时间画成 0% 留存会让人误判
- 路径:看用户做完一个动作后接着做了什么。默认按会话串联,跨会话会连出用户从没 连续做过的动作序列
- 查询构建器:自由组合事件、属性条件与度量,可写
A / B * 100这样的跨事件公式, 满意的结果直接存成看板卡片 - 看板:保存下来的卡片。卡片存的是查询定义不是结果,因此换个时间区间看到的就是 那个区间的数字
单条行为记录本身没有分析价值,上面这几项都是「把多条事件组合起来才能回答的问题」—— 这也是为什么事件上报里带了一个匿名标识,见下文的隐私说明。
采集开关与保留期在「项目管理 → 编辑项目」里:可整项目关停事件采集(关停后采集接口 空转,既有数据保留),也可单独设置事件明细的保留期(默认 90 天,比统计的 365 天短, 因为明细带匿名标识)。
代用户删除数据:用户通过客服提出删除请求时,用其匿名标识调用 DELETE /admin/projects/{k}/events/subjects/{distinct_id}。事件量的小时汇总不在删除 范围内——它只保存计数、不含任何标识符,属于匿名信息。
- 反馈管理
- 查看用户反馈、评分、联系方式、平台信息
- 每条反馈附带来源 IP 与解析出的地区
- 搜索命中反馈内容、用户 ID、联系方式与来源信息(IP、地区、系统版本);可按平台、评分筛选
- 支持管理员手动新增反馈,用于补录渠道外(邮件、社群)收到的意见
- 可隐藏单条反馈:列表默认不显示隐藏项,勾选「显示已隐藏」才列出。隐藏只影响展示,记录仍在,评分照常计入统计与评分分布
- 跟进处理状态并沉淀处理结果
- 日志管理
- 搜索命中日志内容与来源信息(IP、城市、地区、系统版本);可按级别、平台、时间范围筛选
- 行首箭头展开后可见以树形展开的
device_info/custom_data;来源 IP、地区、平台、User-Agent 各自成列(后两者默认隐藏) - 可隐藏单条日志:列表默认不显示隐藏项,勾选「显示已隐藏」才列出。隐藏只影响展示,记录仍在,等级统计照常计入。日志正文、级别与来源写入后不可修改——它是排障凭证,能改的只有「要不要在列表里看到它」
- 支持管理员手动新增日志,用于补录人工处理的运维事件,补录时可直接建成隐藏状态
- 用于故障排查和审计复盘
手动补录的反馈与日志不会写入来源 IP、User-Agent 和地理位置——这些只在真实客户端上报时才有意义,填成后台自己的会污染排障判断。平台与平台版本可以在弹窗里显式指定。
- Token 管理
- 创建、轮换、撤销 API Key
- 设置权限范围、项目范围、过期时间
- Token 列表一次全量返回,所以这一页的搜索(名称、权限)与状态筛选在浏览器本地完成,不受分页影响
- 撤销是软删除:token 立即失效,但记录会留在列表里并标记「已撤销」,作为审计痕迹;已撤销的 token 不能再编辑或轮转
- 网站设置
「网站设置」下分以下子页:
管理员设置
- 修改管理员账号与密码
- 保存后需要重新登录
GitHub APP 设置
- 接入 GitHub App(非必需,不配置不影响其他功能):填写 App ID、私钥(PEM)与 App 级 webhook secret。私钥加密存储、永不回显,页面只展示指纹用于确认
- webhook secret 可点“重新生成”随机生成后复制去填 GitHub;已配置时输入框占位符是与真实长度等宽的星号加末六位,输入框内的 × 一键清除,都在页面底部的「保存配置」时才落库
- 在这里启用想用的功能后,才能到「项目管理 → GitHub 集成」里为具体项目打开对应开关。目前支持:
- 反馈转发 GitHub Issue:允许把客户端反馈转成 Issue。所需权限:Issues (Read and write);项目模板来源选「仓库文件」时还需要 Contents (Read-only)。并把 App 安装到目标仓库
- 评论命令触发工作流:在 Issue / PR 评论首行写
/verhub-<命令> <参数>触发项目配置的 workflow_dispatch。所需权限:Actions (Read and write)、订阅 Issue comment 事件、配置页面展示的 Webhook URL 与 secret
- 功能未勾选时只显示标题与开关,勾选后才展开该功能所需的权限清单
- 反馈转发 Issue 的实例级模板默认就是内置模板;需要改时打开「自定义模板」开关,编辑器里预填的就是内置模板内容,可直接在上面改。正文按 Markdown 渲染,编辑器带预览,可用变量列在正文下方、点击即插入到光标处
- 内置正文包含反馈内容与联系方式、平台等元信息,不含评分;需要评分请自定义模板并插入
存储设置
- 顶部显示分发域名(环境变量
VERHUB_DIST_BASE_URL,部署时配置,见部署指南)。未配置时直链暂按当前站点地址访问,GitHub 附件镜像不可用 - 内置「本机存储」,文件存放在服务器磁盘上;可「添加 WebDAV」接入坚果云、Nextcloud、群晖、rclone 等 WebDAV 服务,文件写入
{WebDAV 地址}/f/... - 「测试」会写入、按 Range 读回并删除一个探测文件,再试写一个 2MB 的文件;提示不支持 Range 的服务不适合分发大文件
- 「分片大小」:WebDAV 服务限制了单次上传大小(如宝塔 WAF 拦截大请求、测试提示「单次写入失败」)时填写,如 512 KB。大文件会拆成多个分片存放、下载时自动拼接,直链不变;设置后该存储不能使用零带宽模式。只影响之后写入的文件
- 「设为默认」决定未单独指定存储的项目把新文件写到哪里;项目也可以在「项目管理 → 编辑」里单独指定存储。切换存储只影响之后的文件,已有文件的直链不变
- 仍存有文件的存储、当前默认存储不能删除;修改 WebDAV 地址不会迁移已有文件
- 「CDN 缓存刷新(阿里云)」:填入 AccessKey ID / Secret 并启用后,删除文件会自动刷新其直链在阿里云 CDN 上的缓存;「测试凭据」会查询当日 URL 刷新余量。需要先配置分发域名,且分发域名已接入阿里云 CDN
- WebDAV 存储下方的「零带宽模式」给出了让 CDN 直接回源该 WebDAV 所需的回源地址、路径改写与请求头,填入密码可在浏览器本地生成
Authorization头(不会发送到服务器)
条款设置
维护两份对外公示的条款文档,页内用选项卡切换,各自独立保存:
- 隐私政策(
/terms/privacy-policy):面向最终用户。提示条款 + 十二章,说明收集哪些信息、如何去标识化与聚合统计、向谁共享与是否跨境、留存多久,以及如何行使权利 - SDK 合规性文档(
/terms/sdk-compliance):面向接入方开发者,同时向最终用户公开。逐项公示 SDK 收集的字段与上限、是否属于个人信息、系统权限使用情况、各语言版本差异、第三方依赖,以及接入方自身的合规义务与配置指引 —— 接入方据此在自己的隐私政策里披露
两份文档的入口都在首页页脚与项目展示页页脚,正文顶部标题居中,最后更新日期在正文末尾。
- 两份内置正文按 Verhub 各采集点的实际实现逐条撰写:请求头、各端点 DTO 的字段与上限、限流值、去重窗口、各语言 SDK 的探测逻辑与依赖。改动了采集行为就要同步修订正文,否则公示即失实
- 内置正文是模板不是终稿。 运营主体、注册地址、联系邮箱、存储地域、留存期限等只有你知道的内容留成了
,页面顶部的「填写模板待补项」逐项列出并给了填写要求与示例 - 填完点「生成正文」,替换后的成品写入下方编辑器并自动打开自定义开关;可继续手改,保存时入库的就是这份成品,前台不做任何替换
- 表单里填的值不入库,重新生成需要再填一次;保存时正文里若仍有
,会二次确认后才允许保存 - 前台生效的正文里还有占位符时,设置页顶部会有醒目提示:未填写就等于对外公示了一份不可用的条款
- 开关关掉时前台立即回到内置正文,自定义正文仍作为草稿留在库里,重新打开即可继续编辑;「恢复内置正文」按钮则会连草稿一并删除
- 《隐私政策》以「我们」指代运营者、以「您」指代最终用户,口径按中华人民共和国法域撰写。其中明确声明 Verhub 的开发者不参与实例运营、不接触数据、不对数据安全作保证,安全与合规责任在部署与运营方
- 日志与行为事件两项能力,两份文档都写明应由接入方在取得用户明确同意后调用,且日志正文与事件属性的最小化与匿名化由接入方负责 —— 服务端按原样存储、不解析、不代为匿名化
- 行为事件采集是 SDK 里唯一会在设备上写入数据的能力(匿名标识 + 待发送队列 + 退出标记)。两份文档都单列一节说明它写什么、写在哪、怎么退出,并明确写出面向欧盟用户的接入方必须开启事前同意模式(ePrivacy Directive Art.5(3) 要求写入设备前取得同意,分析用途不适用「严格必要」例外)
- 项目 GitHub 集成(项目管理 → 行内「GitHub 集成」按钮)
弹窗分「GitHub App」与「Release Webhook」两个选项卡,互不干扰。原「编辑项目」弹窗里的 Release Webhook 配置迁移到后者。
GitHub App 选项卡里配置目标仓库(owner/repo,未配置时按项目自己的仓库地址预填)与要启用的功能。功能未打开时只显示标题与开关,打开后才展开详细配置:
- 允许把反馈转发为 GitHub Issue:打开后客户端会多出「同时提交到 GitHub Issue」的选项,是否转发由提交者逐条选择。只有选了转发的那条反馈才必须留联系方式(缺失时服务端拒收并把原因返回给 SDK),也只有这类请求受单 IP 转发限流约束(默认每小时 3 次,
VERHUB_GITHUB_FORWARD_RATE_LIMIT/VERHUB_GITHUB_FORWARD_RATE_TTL可调,超额返回 429)。没选转发的反馈照常收下,不受任何额外限制 - 选了转发的反馈建 Issue 成功才会被记录:GitHub 侧失败时提交直接报错(503),后台不会留下这条反馈,避免用户以为问题已经报到仓库里。转发成功的反馈在反馈列表里带
Issue #编号徽章,点击直达该 Issue - Issue 模板来源三选一:
- 跟随实例:用「GitHub APP 设置」里的实例级模板
- 本项目自定义:只对本项目生效,编辑器同样带 Markdown 预览与变量插入
- 从仓库文件读取:把模板放进目标仓库并在这里填相对路径(可选分支/标签),改完仓库里的文件即自动生效,服务端缓存约 5 分钟;配置界面可随时「从仓库拉取并预览」确认能读到。文件可用
---front matter 声明title与labels,其余内容作为正文;没有 front matter 时整个文件即正文。此来源需要 GitHub App 的 Contents (Read-only) 权限
- 评论命令:定义命令名 → workflow 文件 → 目标 ref → 参数名的映射(如
/verhub-release 3.2.0以version=3.2.0触发release.yml);并通过评论者身份(author_association)与用户白名单限制可触发的来源
项目开关只有在实例级已启用对应功能且凭据齐全时才实际生效,未生效时界面会给出提示。
常见操作流程
1. 新建项目
手动创建
- 登录后台
- 进入项目管理,点击右上角“新增项目”
- 在弹窗中填写项目 key、名称、仓库地址等信息后提交
从 GitHub 获取项目信息
- 登录后台
- 进入项目管理,点击右上角“新增项目”
- 在“仓库地址”字段中输入 GitHub 仓库地址(如
https://github.com/IvanHanloth/Verhub) - 点击弹窗内的“从 GitHub 获取项目信息”按钮,系统会自动拉取仓库信息并填充项目名称、作者、官网等字段,用户可根据需要进行编辑后保存。
重命名项目(修改 Project Key 并保留旧 Key)
project_key 是项目的访问标识(公开页 /projects/{project_key}、版本/公告/上报等接口都以它定位项目)。项目更名时可以直接在“编辑”弹窗里修改 Project Key:
- 在项目管理页点击目标项目的“编辑”
- 修改“项目 key”字段为新值后保存
保存后:
- 项目内容(版本、公告、反馈、日志、行为事件、统计)整体迁移到新 Key 之下;
- 旧 Key 会被自动登记为“别名”并继续指向本项目——用旧 Key 访问任意公开或管理接口都会透明命中当前项目,已经上线的客户端和 SDK 无需改动;
- 新 Key 不能与任何已有项目或别名冲突。
在编辑弹窗底部的「项目别名(旧 Key)」区域可以查看该项目累积的全部别名。若确认某个旧 Key 不再需要,可点击“删除”将其移除——删除后以该旧 Key 访问会返回 404,且这个 Key 重新变为可用。
2. 发布版本
手动发布
- 选择指定项目,点击右上角“新增版本”
- 在弹窗中填写版本号、发布说明、下载链接
- 根据需求设置
latest或preview
按版本号获取 Release 信息
- 选择指定项目,点击右上角“新增版本”;如果项目已绑定 GitHub 仓库,弹窗内会显示“按版本号获取 Release 信息”按钮
- 如直接点击该按钮,会拉取最新的 Release 作为版本草稿
- 如先填写版本号再点击,会尝试拉取指定版本号的 Release 作为版本草稿,若该版本不存在则会提示错误
- 获取到的版本草稿会自动填充版本信息与发布说明、设置 latest/preview 状态,用户可根据需要进行编辑后发布
同步最新 Release
- 选择指定项目,如果项目已绑定 GitHub 仓库,页面右上角会显示“同步最新 Release”按钮
- 点击后直接把 GitHub 上最新的 Release 落库,不经过表单。同一个 Release 反复同步会覆盖已有记录而不是报错,改完发布说明再点一次即可
同步历史版本
- 选择指定项目,如果项目已绑定 GitHub 仓库,页面右上角会显示“同步历史版本”按钮
- 点击按钮后,将会自动拉取并入库该项目在 GitHub 上的所有 Release 版本,用户可在版本列表中查看并编辑这些版本信息。注意,如果获取到的版本号已存在则会被跳过以避免覆盖现有版本。
通过 GitHub Webhook 自动同步
配置一次之后,GitHub 上发布或编辑 Release 会自动写回 Verhub,不需要再手动点“获取版本”。
配置步骤:
- 在项目管理页点击目标项目的「GitHub 集成」,切到「Release Webhook」选项卡
- 点击 secret 输入框右侧的“重新生成”,随机 secret 会直接填进输入框。先复制它——保存后接口只回读末六位,看不到完整值
- 复制上方的 Payload URL
- 到 GitHub 仓库 Settings → Webhooks → Add webhook,填入 Payload URL 与 secret,Content type 选
application/json,事件选择 “Let me select individual events” 并只勾选 Releases - 回到弹窗点底部的「保存集成配置」,GitHub 侧保存后会发一次 ping,在 Recent Deliveries 里看到 200 即接通
若仓库上已经配置过 webhook,直接把原有 secret 粘进输入框保存即可,不必改动 GitHub 侧配置。
secret 输入框的行为与「网站设置 → GitHub APP 设置」里的那个完全一致:已配置时占位符是与真实长度等宽的星号加末六位;输入框内右侧的 × 一键清除(含已保存的那份),保存后生效,误点可撤销。两个选项卡的改动由底部同一个「保存集成配置」按钮一起提交。
同步规则:
- 只处理
release事件的published/released/prereleased/created/edited动作 - 版本号已存在时按 GitHub 的内容覆盖:这意味着在后台手工改过的标题、说明会被下一次 Release 编辑覆盖回去。需要长期保留的自定义内容,请改用手动发布而不是 webhook 同步
deleted/unpublished不会删除 Verhub 里的版本,避免客户端拿到的下载地址突然消失;需要下架请到后台手动删除- 草稿(draft)Release 会被跳过;
nightly、2024-06-01这类无法解析为可比较版本号的 tag 也会被跳过,返回ignored并注明原因 prerelease会写成预览版本,不会抢占 latest;正式版本只有在版本号不低于当前 latest 时才会接管 latest,因此编辑旧 Release 不会把 latest 拉回旧版本- 附件(assets)会写入下载链接;没有附件时回落到源码包地址。若 CI 是「先建 Release 再传附件」,首次推送可能拿不到附件,等附件上传后编辑一次 Release 即可补齐
- 项目开启了「镜像 GitHub Release 附件」时,附件会在后台下载到文件存储,完成后下载链接自动替换为分发直链;之后再推送同一个 Release,已镜像的附件直接写直链,不会被覆盖回 GitHub 地址
安全说明:
- 该接口不接受管理员 JWT 或 API Key,唯一凭据是 secret 对应的
X-Hub-Signature-256签名 - 未配置 secret 的项目会拒绝所有推送
- 反向代理不得改写请求体,否则签名校验必然失败
用文件分发托管安装包
适用于需要稳定直链(如 Microsoft Store 提交的安装包 URL)、或希望下载走自己的 CDN 的场景:
- 进入「文件分发」,选择项目,点击右上角「上传文件」
- 上传完成后在列表里复制直链
- 发布或编辑版本时,在下载链接列表右上角点「从文件库添加」,选择刚上传的文件
提交到应用商店的 URL 就是这条直链。换包时上传新文件得到新直链,而不是覆盖旧文件——商店要求同一 URL 的二进制内容不变。
镜像 GitHub Release 附件
不想让用户直连 GitHub 下载时,可以把 Release 附件搬到自己的存储:
- 自动:在「项目管理 → 编辑」中勾选「镜像 GitHub Release 附件」,之后经 Release Webhook 同步的版本会自动镜像
- 手动:在版本列表点击该版本操作列的「镜像 GitHub 附件到文件存储」,对批量导入的历史版本同样适用
镜像在后台进行,完成后项目内所有指向该附件的下载链接都会替换为直链;同一个附件只下载一次。私有仓库的附件无法匿名下载,会显示为失败。需要先配置分发域名。
更新策略与判定逻辑
公开更新接口:
GET /api/v1/public/{projectKey}/versions/by-version/{version}(支持语义化版本号与可比较版本号)GET /api/v1/public/{projectKey}/versions/latest-previewPOST /api/v1/public/{projectKey}/versions/check-update
判定核心:
- 比较当前版本与目标版本(按
comparable_version) - 检查是否超出项目级可选更新范围
- 检查当前版本是否被废弃(废弃版本有更新时必更)
- 检查是否触发里程碑拦截(存在里程碑时先升到最早里程碑版本)
参数优先级:
current_version与current_comparable_version同时提交时,服务端优先使用current_comparable_version
判定结果通过以下字段返回:
should_updaterequiredreason_codestarget_version
后台配置方法(重点)
1. 项目管理页配置“可选更新范围”
在项目表单中配置:
- 可选更新范围下限(
optional_update_min_comparable_version) - 可选更新范围上限(
optional_update_max_comparable_version)
说明:
- 当前版本在范围内:可以提示更新但不强制
- 当前版本不在范围内:遇到新版本将触发必更
- 支持将范围下限/上限清空并保存
2. 版本管理页配置“版本策略”
在版本表单中配置:
version:展示版本号comparable_version:用于比较的版本号is_milestone:里程碑标记is_deprecated:是否废弃(勾选后该版本必更)
建议:
- 版本发布时同时维护
version与comparable_version - 仅在关键升级节点版本上勾选
is_milestone,勾选后用户必须先升级到该里程碑版本才能继续后续更新 - 废弃版本需配合公告说明升级理由与目标版本
3. 发布公告
- 进入公告管理
- 绑定项目并编辑正文
- 发布后前台与 API 可见
公告正文与版本的更新说明都不限字数,长篇的发布说明可以整段贴进来。
只给特定版本的用户看
公告弹窗里有「可见版本范围」,填最低 / 最高版本(闭区间,留空即该端不限)。发「2.x 用户请尽快升级」这类内容时填上范围,已经升到 3.x 的用户就不会再看到。
判定依据是客户端调用公告接口时提交的版本号。没提交版本号的客户端看不到任何设了范围的公告——服务端判断不了它属不属于目标人群,与其推错不如不推。不设范围的公告不受影响,照常对所有人可见。
一条公告,多种语言
先在「项目管理 → 编辑 → 公告语言」里注册这个项目要支持的语言(如 en-US,可以另填展示名)。注册后,公告的新建与编辑弹窗顶部会出现语言页签:
- 默认内容页填标题与正文,另外平台、置顶、发布时间、可见版本范围也都在这一页设置,对所有语言生效。
- 每个语言页有三项设置,彼此独立:译文标题、译文内容,以及在该语言下隐藏这条公告。标题与正文各自留空就沿用默认内容;三项都不动,就等于没为这个语言配过任何东西。
想让某条公告对某个语言的用户不可见,只勾隐藏开关即可——不必为它编一份译文。这与公告自身的「隐藏公告」是两层:那个对所有人生效,这个只挡住那一个语言。
客户端调用公告接口时带上语言偏好即可拿到对应译文。以下三种情况都会返回默认内容:没提交语言偏好、提交了项目没注册的语言、该公告没有这个语言的译文。所以默认内容是兜底,任何情况下都有东西可显示。
客户端提交的语言写法不设限,也不会因为格式被拒:en-US、en_US、en(US) 都认作同一个标签(大小写也不区分);不含 - 或 _ 的写法按整串比对。提交了却没命中任何注册的语言时,接口照常返回默认内容,并在返回对象上附一个 locale_message 字段说明提交的语言没有命中,方便客户端排查。
已注册的语言可以直接点「编辑」修改标签、同义标签与展示名,不必注销后重新注册。修改主标签时,这个语言下已录入的公告、版本与项目译文会一并迁到新标签;如果旧版客户端还会提交旧标签,记得把它填进同义标签。
注销一个语言不会删掉已经录入的译文——译文留在库里,只是客户端暂时取不到,重新注册该语言即恢复。
一个语言,多个标签
注册语言时可以填「同义标签」(逗号分隔)。主标签填 en、同义标签填 en-US, en-GB,那么客户端报这三种写法中的任何一个都会取到同一份译文,接口返回的 locale 统一是主标签 en。
同义标签只需填一种写法,en_GB、en(GB) 这类分隔符变体自动等价。但不会自动匹配 en- 开头的其它标签——这样你才能在需要时单独给某个地区变体配一份不同的内容。同一个项目里,一个标签不能同时属于两个语言。
版本标题与更新内容的多语言
注册语言后,版本的新建与编辑弹窗顶部同样出现语言页签。默认内容页是版本的全部字段,语言页只有译文标题与译文更新内容两项,各自留空即沿用版本自身的值。
版本译文没有「按语言隐藏」开关,这一点与公告不同:版本是拿来分发的,把某个版本对某个语言的用户藏起来,只会让他们收不到更新提示却仍然能下到安装包。要停发某个版本请用「标记为废弃版本」,它对所有人生效。
客户端带上语言偏好后,版本列表、最新版、按版本号查询、以及更新检查都会返回对应译文。更新检查里的三个版本对象(最新版、最新预发布版、目标版本)按同一个语言回落——它们通常并排显示在同一个更新弹窗里。
复制某个版本的配置到新建表单时不带译文:译文写的是那个版本的变更,跟着复制过来只会得到一份描述旧版本的说明,而且很容易忘了改。
项目名称与描述的多语言
注册语言后,「编辑项目」弹窗顶部也会出现同样的语言页签。默认内容页是项目的全部字段,语言页只有项目名称与项目描述两项,各自留空即沿用默认值。
客户端调用项目详情接口时带上语言偏好,就能拿到对应语言的名称与描述;命中规则与公告完全一致。
用 AI 翻译打底
不必每种语言都找人写。在「网站设置 → AI 翻译设置」里配好上游模型后,公告、版本与项目的每个语言页上都会出现一个**「AI 翻译」**按钮:点一下,把默认内容整条译进当前语言页的输入框——公告与版本是标题加正文、项目是名称加描述,一次译完。
译文只填进输入框,不会自动保存。改完再点保存,与手写译文的流程完全一样——机器翻译只是省掉从零起草的那一步,最终发出去什么仍由你决定。当前语言页已经填了内容时,会先问一句是否覆盖。
配置在「网站设置 → AI 翻译设置」,需要管理员账号:
- 接口协议:选「OpenAI 兼容」还是「Anthropic Messages」。OpenAI、DeepSeek、通义千问、各类中转站,以及自建的 Ollama、vLLM、one-api 都属于前者。
- API 地址:只填到路径前缀,后缀由系统按协议拼接,页面上会实时显示最终请求的完整地址供核对。OpenAI 兼容填
https://api.openai.com/v1(拼成.../v1/chat/completions),Anthropic 填https://api.anthropic.com(拼成.../v1/messages)。 - API Key:加密存储,保存后不再回显,只显示指纹供你判断有没有换过。自建的 Ollama、vLLM 通常不需要鉴权,这一项可以留空。
- 模型:如
gpt-4o-mini、claude-sonnet-4-5、qwen2.5。 - 提示词:默认用内置的,已经要求模型保留 Markdown 结构与
、只输出 JSON。有特殊术语或语气要求时才打开「使用自定义提示词」;改坏了把开关关掉即可回到内置文案,不必逐字删回去。
填完点「保存配置」,再点「测试连接」——它会用当前配置译一句样例并把结果显示在页面上,地址填错或 Key 无效都能立刻看出来,不必先去建一条公告试。
顶部的「启用 AI 翻译」是总开关:关掉后翻译按钮不再出现,已填的地址与 Key 保留不动。
Verhub 不内置任何厂商的凭据,也不代付费用——用的是你自己填的 API Key,翻译产生的调用计在你的账上。
4. 处理反馈
- 进入反馈管理
- 按状态筛选待处理项
- 更新状态并记录处理结论
- 无需再露出的反馈(骚扰、重复、含隐私联系方式)点行内「隐藏」;要复查时勾选「显示已隐藏」
5. 看统计大屏
统计大屏按项目展示公开接口的调用情况。顶部六张指标卡带环比(与紧邻的上一个等长区间相比)与迷你趋势线;上一区间没有数据时显示「新增」而不是编一个百分比。
- 请求趋势 / 活跃度日历:时间按你浏览器所在时区呈现,是给你看的绝对时间轴。趋势图右上角可在「总量 / 按接口 / 按平台」之间切换:后两者是堆叠面积图,能看出流量构成怎么随时间变化,包络线就是总量。
- 访问热力图:「星期 × 小时」按每条请求的来源当地时区折叠,回答的是「用户在他们当地几点活跃」。官方 SDK 默认随请求上报设备的本地时间与 UTC 偏移,这部分流量精确按用户自己的时区折叠(包括美国西海岸这类跨时区国家里的具体时区);没上报的(旧版 SDK、直接调 HTTP、接入方关闭了该项)退回按来源国家近似——中国精确按 UTC+8,跨时区国家(美/俄等)取代表时区,无法定位来源的按你的浏览器时区兜底。升级前积累的数据没有时区信息,一律按后一种方式近似。
同一个上报值还用来校正设备时钟:行为事件带着设备自己记的发生时间,如果设备时钟慢了几个小时,服务端会按这次请求测得的偏差把同一批事件的时间一并校正过来(偏差不足 1 分钟视为网络延迟,不校正)。它与请求趋势口径不同是有意为之:一个看用户作息节律,一个看你这边的绝对走势。
- 客户端版本分布、系统版本分布、接口构成、来源地区:右上角可在柱状图与环形图之间切换。柱状图看排名,环形图看占比。环形图最多画 8 块,其余(含接口已截断的长尾)归入「其他」——再多就看不出差别了。
- 版本采纳曲线:头部若干个客户端版本的上报量随时间变化,用来判断新版推广得多快、旧版退得多干净。
- 日志等级分布:四个等级恒定显示,某个等级为 0 也占位——「这个范围内一条 ERROR 都没有」本身就是信息。
- 反馈评分分布:1..5 星直方图,缺档也占位。未打分的反馈计入卡片副标题的「未评分」条数,不并入任何星级,以免拉歪平均分。
- 系统版本分布:调用方跑在什么操作系统上,如 Windows 11、ubuntu 24.04、macOS 26。平台固定为 Windows / Linux / macOS / iOS / Android / Web / 其他七类,具体版本是客户端另外提交的自由文本(
platform_version字段或x-verhub-platform-version请求头),没提交的由 User-Agent 尽力解析。条目标注「未报版本」的,是报了平台但没报版本的那部分流量——它照样计入总数,否则占比会失真。它与「客户端版本分布」问的不是一回事:那张图看装的是你产品的哪个版本,这张看跑在什么系统上。 - 来源地区:由调用方 IP 解析得到。「未知」是无法定位的地址(也包括后端未开启出网解析时的全部请求),「内网/本机」是私有网段调用,两者都不会被送去外部解析服务。右侧为热力地图,右上角在「国内 / 全球」之间切换:国内是省级着色,精确到省(依据行政区划码聚合,不受各解析服务省市命名差异影响);全球是国家/地区级着色,境外只到国家这一级,且不含「未知」「内网/本机」这类无法落到地图上的来源。鼠标悬停看名称、请求数与占比。
统计只做小时级聚合,不保存单条请求,保留时长在项目管理里按项目配置。
API Key 使用建议
API API Key 可用于全部管理接口,与管理员登录后拿到的 JWT 等价。调用时放在 Authorization: Bearer 里即可:
curl -X PUT "https://api.example.com/api/v1/admin/projects/demo/versions/by-version/1.2.3" \
-H "Authorization: Bearer vh_xxx" \
-H "Content-Type: application/json" \
-d '{"title":"Release 1.2.3","is_latest":true}'能访问哪些接口由 Key 的权限(scope)和项目范围决定:读接口需要 <资源>:read,写接口需要 <资源>:write,写权限不包含读权限。两个例外要知道:
- 创建、轮换、撤销 API Key 这类凭据管理操作只能由管理员登录后进行,不能用 API Key 调用——否则一个 Key 就能换出权限更大的 Key。
X-API-Key请求头仍然可用(老集成不受影响),但新接入建议统一用Authorization: Bearer。
详见开发指南的「管理接口认证方式」。
- 为不同系统生成独立 Key,便于追踪与撤销
- 设置合理过期时间,避免长期暴露风险
- 仅授予必要权限与项目范围
- 定期轮换 Key 并监控使用情况
安全与审计建议
- 定期轮换敏感凭据
- 监控异常请求频率
- 对关键管理操作保留审计记录
