Files
dsh_shenxian/dsh-server-docs/04-调整方案/137-品牌标识改造-去DeepSeek图形.md
T
admin c2b7c5ef71 平台共享模型改为「管理员逐用户授权」+ 品牌中文名改「能力网络」+ 修掉跨机模型落地/语言偏好静默失效
三条线合并入库(同一次部署批次,源码与生产此前已一致):

一、档案 138 · 平台共享模型:管理员逐用户授权(默认关闭)
  用户口径原文:「admin 设置的共享模型,需要 admin 在用户列表中开启(新增选项,默认关闭),
  用户才能在会话中使用(以及在设置的模型设置页面展示)」。
  · DB 迁移 v11:新增 users.shared_model_granted(DEFAULT 0 = 默认关闭)。
    ⚠️ 刻意**不**复用 v6 的 shared_model_enabled —— 那是用户侧偏好(用户能自己关,默认 1),
    而本需求要的是**管理员门禁**;共用一列则用户点一下就给自己授权,门禁形同不存在。
    生效 = granted ∧ enabled(server.ts#sharedLandingRows)。
  · 新路由 POST /api/admin/users/:id/models/shared(requireAdmin)+ 审计 shared_model_grant
    + **尽力而为**重启该用户实例(租约被占/实例未运行都不算失败)。
  · admin 用户列表新增「共享模型」列;用户侧 /api/me/keys 增 shared.granted / sharedModelGranted;
    插件 0.3.24:未授权时「平台共享模型」整块不渲染。

二、顺带修掉一个既有真缺陷:平台侧写用户 home 必须走 UserFs(用户卷在 worker 上)
  landModels 原先 join(owner.home_dir, …) + 本机 fs ⇒ 对「实例不在控制面本机」的用户
  读到空串(**不报错**)⇒ 模型落地一直是**静默空操作**(托管清单还被清空)
  ——即档案 87 的模型设置页对 guest 这类用户**从未生效**。
  · UserFs 新增 readHomeFile/writeHomeFile + 文件名白名单(settings.yaml / .credentials.yaml)
  · worker agent 新增 /fs/home-read /fs/home-write(只认白名单裸文件名)
  · landModels 改走 userFs(与"文件面"同一份按归属路由 ⇒ 落地与实例必然同机)
  · 同轮把 /api/me/locale(档案 102 语言偏好)也改成同一套(原先同样失效)
  · home-files.ts 抽出 backupHomeFile(备份留平台侧,命名规则逐字不变)

三、档案 139 · 品牌中文名:能力枢纽 → 能力网络(其他语言仍 CapabilityNet)
  落点四处:i18n 中文词条 / admin.html 顶栏 / favicon.svg 的 title+aria-label / design.css 注释;
  test/i18n-brand.test.mjs 期望值同步。档案 137 顶部加"后续"指针,不改历史。

验证(全部真机实测):
  · 红腿:未授权 → 106 上 guest 的 .credentials.yaml refs 变空(共享 key 被撤)
  · 绿腿:授权 → key 回来 + 托管清单恢复 ["DEEPSEEK_API_KEY"]
  · admin 列表带出 sharedModelGranted;用户侧 granted 随授权翻面(true/shared ↔ false/none)
  · 开关两次均 200(不再假失败);插件实装 0.3.24 且含 gating 字符串
  · 语言偏好:106 上 settings.yaml 出现 locale.preference=en(属主=实例属主,既有段逐字保留)
  · 本机 npm test 226 tests / 225 pass / 0 fail / 1 skipped;四个 verify 脚本全绿

部署:47 推 51 个 lib 产物、106 推 12 个(lib/ 是 gitignore ⇒ 回滚点物化在
/opt/dsh/backups/seq138b-20260919-125345/,逐文件对账 0 不一致;先 106 后 47);
插件 business-plugins 0.3.24(两机 artifacts 与本机 pack md5 一致)。
2026-09-19 13:51:01 +08:00

10 KiB
Raw Blame History

137-品牌标识改造(去 DeepSeek 图形 → 平台自有标识)

⚠️ 后续(2026-09-19):中文品牌名已由「能力枢纽」改为 「能力网络」(其他语言仍 CapabilityNet) —— 见档案 139。本档正文保留当时的定名,不改历史。

一句话:把我们自己的页面上所有 DeepSeek 品牌标识(鲸鱼图标 / 「DeepSeek」文字图形 / favicon) 换成平台自有标识 —— 中文「能力枢纽」,英语及其他语言「CapabilityNet」。 触发:用户 2026-09-19 原话三句 —— ① 「登录和注册页面上的 deepseek的图标去掉,改为中文: 能力枢纽 小写 CapabilityNet ,英语和其他语言:CapabilityNet」 ② 「一并替换」(= 其余页面也一并办) ③ 「会话页面左上角的 deepseek 先不替换」(= 实例内官方 dsh 界面那处不动) 执行:会话 登录注册页品牌标识改造 → 品牌标识一并替换-admin portal favicon · 状态 ✅ 已上线


0. 替换范围(先划边界,这是本档案最重要的一节)

位置 处置 依据
login.html / register.html 页头品牌区 ✅ 替换 用户①
admin.html(管理台登录卡片) ✅ 替换 用户②「一并替换」
portal.html(管理门户顶栏) ✅ 换图标 用户②;文字「管理门户」保留(见 §1 注)
四页的 favicon ✅ 换新图标 用户②;logo.svg 就是 DeepSeek 图标
🔴 会话页面左上角(用户实例内的 dsh 会话窗口) ⛔ 不替换 用户③明示「先不替换」。技术上它属官方 dsh 的 client bundle,不在本仓 web/ 目录 ⇒ 也不受红线 R2(不改官方 dsh 主程序)允许
index.html / wake.html — 无品牌标识 前者是纯跳转页、后者是启动过渡页,二者均无 logo/wordmark,且本来就没有 favicon link(未加,见 §4)

⚠️ "会话页面"不在本次能力范围内:本仓 web/*.html 是平台自有的门户/管理页; 用户在实例里看到的会话界面由官方 @deepseek-ai/dsh 渲染 ⇒ 那处的标识要么属于官方、要么需走 profile 层官方插件机制(R2 的合规路径),不是"改个静态文件"能解决的。

1. 改了什么

文件 改动
web/login.html .auth-brand 内:删 <img class="logo" src="/logo.svg">(DeepSeek 鲸鱼,2109 B 的 #4D6BFE 图形)+ 删 内联 <svg><title>DeepSeek</title>…</svg>(131×24 文字图形)→ 换 <span class="wordmark" data-i18n="brand.name">CapabilityNet</span>。10758 → 6799 字节
web/register.html 同上。20002 → 16919 字节
web/admin.html 同构处理(它复用 .auth-brand):删图标 + 删内联 DeepSeek SVG → <span class="wordmark">能力枢纽</span>(该页是纯中文页、未接 i18n ⇒ 直接写中文)。11913 → 7928 字节
web/portal.html 顶栏 .brand 只换图标:src="/logo.svg" → src="/favicon.svg";⭐ 文字「管理门户」保留 —— 它是页面定位名、不是 DeepSeek 痕迹,删掉属越界
web/favicon.svg 新建(1008 B):平台自有图标,取「枢纽 / hub」意象 —— 圆角深底 + 中心节点 + 三条辐条 + 三个外环节点;配色用平台自己的 token(ink #0f1c33 底 / accent-2 #38d6d0 节点),刻意避开原 DeepSeek 的 #4D6BFE。同时兼作 favicon 与 portal 顶栏图标
四页 head <link rel="icon" href="/logo.svg"> → href="/favicon.svg"
web/i18n.js 新增词条 brand.name:en → CapabilityNet、zh → 能力枢纽
web/design.css .auth-brand .wordmark 由「定高 22px(给 SVG 用)」改为文字排版(height:auto + 19px/600/行高 1.2)
test/i18n-brand.test.mjs 新增:node:vm + 最小 DOM 桩跑仓库里那份真实的 i18n.js,断言六条语言路径的实际渲染结果
scripts/verify-static.mjs 新增 SVG 段:见 §3-1(踩坑后的防护)

两个刻意的选择

  1. 登录/注册页走 i18n 词条,⛔ 不写死在 HTML:① verify-static.mjs 的 I18N_PAGES 已把这两页列入「不得出现裸中文文案」,硬写「能力枢纽」会被拦;② 「英语和其他语言」 要的正是回退语义 —— lookup() 缺 key 时回退 en,只写 en 一条即覆盖所有其他语言。 ⚠️ admin.html / portal.html 未接 i18n(既有的纯中文页)⇒ 那两处直接写中文, 不引入 i18n 运行时(引它会连带处理它们大量既有裸中文,属扩大范围)。
  2. 发子域名 favicon.svg 而不是复用 logo.svg:favicon 缓存按 URL 生效 ⇒ 换文件名 天然绕过浏览器里那份旧的 DeepSeek 图标缓存,不需要加 ?v= 版本串。

2. 验证证据

项 实测
i18n 渲染自证(跑真实 i18n.js) 六条全绿:浏览器 en-US → CapabilityNet|zh-CN → 能力枢纽|?lang=zh → 能力枢纽|?lang=en(覆盖中文浏览器)→ CapabilityNet|cookie dsh_lang=zh → 能力枢纽|ja-JP → 回退 CapabilityNet
裸 key / 空文案 四种语言下均非 brand.name、非空
SVG 合法性(真 XML 解析器) favicon.svg 解析通过;children=[title, rect, g, circle×4]、paths 三条齐备;另两个既有 SVG 也一并验过
反向自证(坏样本必须被拦) 故意往注释里注入 --accent ⇒ 真解析器报 not well-formed + 校验脚本报红;清理后复跑全绿
残留检查(本地 + 线上) `web/*.html
静态页不变量 verify-static.mjs 全部合格(6 页 + 7 段内联脚本语法 + 3 个 css/js + 3 个 svg)
全量单测 221 pass / 0 fail / 1 skipped(# tests 222,Node 22.22.2)
线上(https://ai1net.com) favicon.svg = 200 + image/svg+xml;四页均 favicon=1 / logo.svg=0;admin.html 显示 <span class="wordmark">能力枢纽</span>;portal.html 显示新图标 + 「管理门户」
部署 md5 对账 5 个 web 文件两端逐一一致(admin 8736bcc7… / portal 164075c8… / login 2467bd50… / register dfbf996f… / favicon fe37ebbf…)
行尾 逐字节核对:admin.html / portal.html 仍 CRLF、login.html / register.html / favicon.svg 仍 LF —— 与该目录既有风格逐一对应,无偏差
回滚点 ① /opt/dsh/backups/rebrand-20260919-084220/pre.tar(第一批 4 文件)② /opt/dsh/backups/rebrand2-20260919-090205/pre.tar(本批)

部署方式:静态文件 scp 即生效(不需要重启);未动任何服务或 env。

3. 踩坑记录

  1. 🔴 SVG 里的 XML 注释不能含 ASCII 双连字符 --(本次实际踩到)。 我在 favicon.svg 的注释里写了 CSS 变量名 --ink / --accent-2 ⇒ XML 语法不允许 ⇒ 整份 SVG 解析失败 ⇒ 浏览器静默不显示图标,页面与接口都不报任何错。
    • 抓到它的方式:用真解析器验一遍(ET.parse 报 not well-formed (invalid token)), 而不是只看标签配对或肉眼看 —— 肉眼 100% 看不出这处问题。
    • ⚠️ 中文破折号 ——(U+2014×2)是合法的,只有 ASCII --(U+002D×2)非法 —— 所以"注释里有破折号"不是判据,"注释里有两个连续半角减号"才是。
    • 已固化为判据:scripts/verify-static.mjs 新增 SVG 段(开头/结尾/viewBox/去痕迹/注释双连字符), 并做了反向自证(注入坏样本 ⇒ 必须报红)。
  2. logo.svg 同时兼作 favicon 与页面图标 ⇒ 换品牌时"页面上的图标"和"浏览器标签图标" 是同一份资产,改一处必须想到另一处(第一批只改了页面内,favicon 就漏了)。

4. 未做 / 已发现(只报告,未动手)

  1. 🟡 index.html / wake.html 没有 favicon link ⇒ 这两个页面的标签图标是浏览器默认。 本轮未加(用户没要求,且属功能增量)。若要统一,改动 = 各加一行 <link rel="icon" href="/favicon.svg">。
  2. 🟡 三个 DeepSeek 资产现已全部无引用:web/logo.svg、web/deepseek-text.svg、web/deepseek.webp (grep 全仓已无任何 HTML/CSS/JS 引用)。未删 —— 属"额外发现即先报告", 删除是不可逆动作、需你点头(git 里可恢复,风险低)。
  3. ⚪ .topbar .wordmark 那条 CSS 保留未改 —— admin.html 用的是 .auth-brand、 portal.html 用的是 .brand,当前没有任何页面用 .topbar .wordmark; 保留是为防样式回归(改它不影响现状,属无收益改动)。

5. 一条待澄清的表述(未阻塞交付)

用户原话里的「小写 CapabilityNet」有两种读法,本轮按读法一实现:

  • 读法一(已实现):中文界面 = 「能力枢纽」;英语及其他语言 = 「CapabilityNet」。
  • 读法二:中文界面 = 「能力枢纽」+ 其下一行小号 CapabilityNet(双语锁定); 或要求英文写成全小写 capabilitynet。

⇒ 若是读法二,改动量 = i18n.js 一处词条 + design.css 一行(无需碰 HTML)。

6. 回滚

对象 方式
第一批(login/register/design.css/i18n.js) /opt/dsh/backups/rebrand-20260919-084220/pre.tar → /opt/dshs/
本批(admin/portal/login/register/favicon/verify-static) /opt/dsh/backups/rebrand2-20260919-090205/pre.tar → /opt/dshs/
生效方式 tar 覆盖即生效,无需重启(纯静态资源)
⚠️ 注意 回滚后页面会重新引用 /logo.svg(DeepSeek 图标仍在服务器上、文件没删)⇒ 回滚是完整的

7. 关联

  • 同一会话的相邻改动:Cloudflare Turnstile 密钥配置并启用(见档案 134 §实现 E)。
  • 旧域移除见 135;控制面并集立项见 136(并行线产物,本档案不重复)。