From c9f5296b73abcc5145db519f082ffcd84e428ad8 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Thu, 2 Jul 2026 07:45:16 +0000 Subject: [PATCH] =?UTF-8?q?feat(license):=20=E5=9C=A8=E7=BA=BF=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=B5=AE=E5=91=8A=E8=AD=A6=E5=8D=A1+=E7=A6=BB?= =?UTF-8?q?=E7=BA=BFSN/MAC=E6=A0=87=E7=AD=BE=E5=8C=96=EF=BC=8C=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E4=B8=A4Tab=E6=8E=92=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在线:正常态只显示核心信息,提醒/过期/设备不匹配时浮出告警卡,SN/MAC 收进折叠诊断;frozen 状态文案统一为「已过期」 - 离线:SN/MAC 改行尾标签+失配整行标红,IP/域名/创建时间折叠进「更多」 - 统一在线/离线信息行的字号/行高/间距/label - 清理死样式 .information 与死变量 onlineIng - 同步 ai-kb online.md 状态措辞并登记新增文案 --- language/original-web.txt | 23 + resources/ai-kb/zh/howto/license/online.md | 26 +- .../js/pages/manage/setting/license.vue | 539 ++++++++++++------ 3 files changed, 402 insertions(+), 186 deletions(-) diff --git a/language/original-web.txt b/language/original-web.txt index b219eda0c..65d86b261 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -2499,3 +2499,26 @@ AI任务分析 (*)秒后重发 请输入邮箱和验证码 刷新中 +诊断详情 +授权 SN +当前 SN +授权 MAC +当前 MAC +授权与当前设备不匹配 +检测到设备标识(SN)已变更,在线授权可能已失效。请重新登录授权,或先在原设备退出以释放座位。 +在线授权已过期 +新增用户已受限,请尽快联网以自动续期恢复。 +检测到网卡(MAC)变化 +系统会在下次续期时自动恢复授权,通常无需处理。 +续期失败,请检查网络 +授权仍然有效,联网后会自动续期恢复。 +授权即将到期 +请保持联网,系统会自动为你续期。 +重新登录授权 +匹配 +与本机不一致 +收起 +更多信息 +提示 +将释放当前设备占用的授权座位并回到登录,确定继续? +已过期 diff --git a/resources/ai-kb/zh/howto/license/online.md b/resources/ai-kb/zh/howto/license/online.md index 81410369a..a1a6b7346 100644 --- a/resources/ai-kb/zh/howto/license/online.md +++ b/resources/ai-kb/zh/howto/license/online.md @@ -19,6 +19,11 @@ aliases: - 在线授权冻结 - 在线授权被吊销 - 换机 deactivate + - SN 与 License 不匹配 + - MAC 与 License 不匹配 + - 终端SN与License不匹配 + - 终端MAC与License不匹配 + - 换机后在线授权失效 related_tools: [] related_pages: [] prerequisites: @@ -30,7 +35,7 @@ negative: - 离线授权(粘贴 License 原文)完全不受影响,没有自动续期 - 一个账号同一时刻只占用一个实例座位,换机需先在原实例「退出在线授权」释放 - 试用每个账号仅一次,时长由 App Store 管理员配置且硬上限 60 天 -last_verified: v1.7.91 +last_verified: v1.8.45 --- # 在线授权(邮箱验证码登录 / 申请试用 / 自动续期) @@ -53,15 +58,14 @@ DooTask 的 License 页提供两种授权方式,可在页面顶部 Tab 切换 ### 已有授权 → 登录授权 - 填好邮箱与验证码后点击「登录授权」 - 终端把自身指纹(doo_sn、网卡 MAC、版本)上报授权中心,签发一张租约 License 并落地 -- 成功后页面显示套餐、使用人数、租约到期、当前状态 +- 成功后页面显示账号、套餐、使用人数、授权有效期、SN/MAC(与本机是否匹配)、当前状态 ### 没有正式授权 → 申请试用 - 填好邮箱与验证码后点击「申请试用」即开通试用授权并签发 - 试用默认 14 天 / 不限人数(具体以 App Store 管理员配置为准,时长硬上限 60 天),每个账号仅能申请一次 ### 日常维护 -- **自动续期**:终端每小时检查,租约将尽时自动向授权中心续期,无需人工干预(需保持联网) -- **立即续期**:状态页「立即续期」按钮可手动触发一次 +- **自动续期**:终端每小时检查,租约将尽时自动向授权中心续期,无需人工干预(需保持联网);进入授权页时也会静默刷新一次 - **换机 / 退出**:「退出在线授权」会释放该账号在授权中心占用的座位,并把终端回落到基础版;换机时先在原实例退出,再到新实例登录 ## 状态与提醒(断网/欠费时的分级降级) @@ -71,11 +75,21 @@ DooTask 的 License 页提供两种授权方式,可在页面顶部 Tab 切换 | --- | --- | --- | | 生效中 | 续期正常 | 无 | | 即将到期 | 续期失败或租约临近 | 仅提醒 | -| 已冻结 | 租约已过期 | 限制新增用户(沿用离线过期的既有行为) | -| 已吊销 | 冻结超过宽限期或授权被收回 | 回落基础版(最多 3 人,超出的账号按既有规则禁用) | +| 已过期 | 租约已到期 | 限制新增用户(沿用离线过期的既有行为) | +| 已吊销 | 过期超过宽限期或授权被收回 | 回落基础版(最多 3 人,超出的账号按既有规则禁用) | 只要在租约窗口内恢复联网并成功续期一次,即可回到「生效中」。 +## SN / MAC 与本机匹配 +在线授权签发的 License 内嵌了签发时的终端 SN 与网卡 MAC。正常情况下二者与本机一致,「在线授权」Tab 保持极简,只显示账号、套餐、使用人数、有效期与状态(带颜色圆点),不常驻展示 SN/MAC 这类技术细节。 + +一旦 SN 或 MAC 与本机不一致,页面顶部会浮出告警卡,并展开「诊断详情」逐项列出「授权 SN / 当前 SN / 授权 MAC / 当前 MAC」及匹配标记(✓/✕);同一批告警也会出现在仪表盘顶部横幅。「离线授权」Tab(手动粘贴场景)则始终以列表展示 SN/MAC,用行尾标签直陈匹配与否、不一致时整行标红,IP/域名/创建时间等低频字段收纳在「更多信息」里。 + +授权成功后若终端的 SN 或 MAC 发生变化,行为不同: + +- **MAC 变化(SN 不变)**:属于同一实例,下一次自动续期会用新的 MAC 重新签发 License 自动恢复,通常无感;重签前的短暂窗口可能出现 MAC 不匹配告警。 +- **SN 变化**:视为换机。续期会被授权中心判为座位被占用而拒绝重签,原 License 因 SN 对不上而失效,终端将按状态机走向「已过期 → 已吊销」并回落基础版。需在原实例(或让管理员在 App Store 授权中心)释放座位后,在新实例重新登录授权。 + ## 怎么自检 - 接口 `POST api/license/status` 返回当前在线授权状态(mode/plan/people/lease_expired_at/status) - 提醒文案同样并入 `POST api/system/license` 的 `error` 数组,便于脚本巡检 diff --git a/resources/assets/js/pages/manage/setting/license.vue b/resources/assets/js/pages/manage/setting/license.vue index 7aa1c05cb..f2c4b5056 100644 --- a/resources/assets/js/pages/manage/setting/license.vue +++ b/resources/assets/js/pages/manage/setting/license.vue @@ -1,173 +1,166 @@ @@ -177,6 +170,11 @@ flex: 1; overflow-y: auto; } +.license-form { + .ivu-form-item { + margin-bottom: 12px; + } +} .license-box { position: relative; padding-top: 6px; @@ -194,8 +192,8 @@ > li { list-style: none; font-size: 14px; - line-height: 22px; - padding-bottom: 6px; + line-height: 24px; + padding-bottom: 4px; display: flex; align-items: center; gap: 6px; @@ -208,15 +206,6 @@ font-style: normal; opacity: 0.8; } - .information { - display: flex; - align-items: center; - justify-content: center; - margin-left: 6px; - &.error { - color: #ed4014; - } - } } } } @@ -264,6 +253,105 @@ margin-top: 4px; opacity: 0.6; } +/* 在线授权:异常告警卡(正常态不渲染) */ +.online-alert { + display: flex; + gap: 10px; + max-width: calc(100vw - 20px); + margin: 0 auto 14px; + padding: 11px 13px; + border-radius: 6px; + &.warning { background: #fdf6ec; border: 1px solid #faecd8; } + &.error { background: #fef0ef; border: 1px solid #fcd7d3; } + .online-alert-ico { + flex-shrink: 0; + width: 18px; + height: 18px; + border-radius: 50%; + color: #fff; + font-size: 12px; + font-style: normal; + display: flex; + align-items: center; + justify-content: center; + } + &.warning .online-alert-ico { background: #ff9900; } + &.error .online-alert-ico { background: #ed4014; } + .online-alert-title { font-size: 13px; font-weight: 600; margin-bottom: 2px; } + &.warning .online-alert-title { color: #b8791b; } + &.error .online-alert-title { color: #c0341a; } + .online-alert-desc { font-size: 12px; line-height: 18px; } + &.warning .online-alert-desc { color: #8a7455; } + &.error .online-alert-desc { color: #97544a; } +} +/* 在线授权:状态圆点 */ +.online-status { + display: inline-flex; + align-items: center; + .online-status-dot { + width: 7px; + height: 7px; + border-radius: 50%; + margin-right: 6px; + background: #c5c8ce; + } + &.is-ok { color: #19be6b; .online-status-dot { background: #19be6b; } } + &.is-warning { color: #ff9900; .online-status-dot { background: #ff9900; } } + &.is-error { color: #ed4014; font-weight: 500; .online-status-dot { background: #ed4014; } } +} +/* 在线授权:诊断详情(仅 SN/MAC 不匹配时出现) */ +.online-diag { + max-width: calc(100vw - 20px); + margin: 10px auto 0; + margin-top: 10px; + padding: 10px 12px; + background: #f8f9fb; + border-radius: 6px; + .online-diag-title { font-size: 12px; color: #808695; margin-bottom: 6px; } + .online-diag-row { + font-size: 12.5px; + line-height: 20px; + display: flex; + > em { font-style: normal; opacity: 0.55; width: 72px; flex-shrink: 0; } + b { font-weight: 500; } + &.bad { color: #ed4014; > em { opacity: 0.7; } } + } +} +/* 离线授权:详情行 + 匹配标签 */ +.offline-detail { + .offline-row { + /* 文字排版(字号/行高/label/gap)沿用默认信息行,只保留标红块所需的内边距与圆角 */ + padding: 2px 0; + border-radius: 5px; + > .v { flex: 1; word-break: break-all; } + .offline-flag { + flex-shrink: 0; + font-size: 12px; + padding: 1px 8px; + border-radius: 9px; + background: #e8f7f0; + color: #19be6b; + } + &.bad { + color: #ed4014; + .offline-flag { background: #fdecea; color: #ed4014; } + } + } + .offline-more { + padding: 4px 0; + a { + font-size: 13px; + color: #2d8cf0; + cursor: pointer; + &:hover { text-decoration: underline; } + } + } +} +body.window-portrait { + .license-box { + padding-top: 16px; + } +}