# TankiOffline UI 重建计划书(全站 UI) > 目标:把原客户端(`module_82347` 大厅/车库/商店/军团/结算 UI + `module_21300` 战斗 HUD) > 还原到 Kotlin/JS 新工程,最终覆盖**全站所有界面**,并与真实状态 / 协议数据打通。 > 本文件用于对齐范围、技术栈、里程碑与验收口径。 ## 0. 已确认决策(2026-10-25) | 议题 | 决策 | |---|---| | 技术栈 | **Kotlin/JS + kotlin-react + Emotion**(与现工程同栈) | | 还原精度 | **组件级还原**;背景/摄像机是动态的,不做像素 diff,由人工验收,尽可能贴近 | | 数据源 | **本地 mock 服务器**(协议级 mock,稳定产出用户/物品/大厅数据) | | 原版账号 | 有(`WYT2WYT`),仅用于线上获取必要信息(DOM/CSS/资源/文案),**不做逐屏截图对拍** | | 3D | **现在接 WebGL**:先做 3D 资源加载器与车库预览,再逐步接 `92980` 渲染管线 | | 首批屏幕 | **大厅骨架 + 车库** | | 资源部署 | 开发用本地镜像;生产走 CDN / 反向代理 | | 混跑策略 | 允许长期保留部分原 JS UI,按屏幕逐步替换为 Kotlin | --- ## 1. 调研结论(先纠正三个认知) ### 1.1 原前端不是手写 React,而是 **Kotlin/JS + React + Emotion** 证据: | 证据 | 说明 | |---|---| | `module_glossary`:`78931` = React 18.3.1、`45555` = React-DOM 18.3.1 | 运行时确实是 React | | `94090` = “React 封装的内部 UI 构建工具 RBuilder” | Kotlin 侧的 React DSL | | `82347` 的代码形态:`Sq(d7n, "MainScreenComponentStyle", $q, h$)`、`this.aux([], K2n)`、`Eq("containerPanel", 1, …)` | 这是 Kotlin/JS 编译后的 styled-component 构造,不是手写 JS | | 类名如 `MainScreenComponentStyle-containerPanel`、`RoundBigButtonComponentStyle-outerCircle` | Emotion 生成的组件样式名 | | `82347` 依赖 `10032 / 18334 / 61860 / 87072 / 92980 / 61378 / 85196 …` | UI 直接吃状态、服务、渲染、战斗系统 | **结论**:另起一个 React/TS 工程不是“更原版”,反而会丢掉 Kotlin 数据模型。 推荐在现有 Kotlin/JS 工程里加 **kotlin-react + Emotion**,逐屏移植;纯 React/TS 只作为备选。 ### 1.2 原 UI 的体量与耦合 - `82347`:5.50 MB,约 21.3 万行,覆盖大厅 / 车库 / 商店 / 军团 / 好友 / 新闻 / 设置 / 结算 / 弹窗。 - `21300`:战斗内 HUD(血条、准星、道具、计分板、聊天…)。 - 大量组件直接依赖: - 状态:`RootState` 的 89 个切片(已迁移 89/89); - 服务:`18334` 的 509 处动作派发、物品目录(已迁移 `ItemCatalog`); - 渲染:`92980` WebGL(车库 3D 预览、战斗场景); - 战斗:`87072`(HUD 数据)。 - 因此 UI 必须分层:**布局/样式可先独立还原,数据和 3D 后接**。 ### 1.3 资源已经齐了 - 镜像:`3DTank/web/play/static`(1239 文件 / 71.4 MB,含 images / fonts / translations / sound / videos / textdata)。 - 已复制到:`TankiOffline/app/src/jsMain/resources/play/static`,开发服务器直接以 `/play/static/...` 提供。 - 官方翻译:`/play/static/translations/zh-CN.61d6ab60.json`(运行时加载,已接)。 - 可直接引用的资源 id → 路径:`3DTank/src/resources.json` 的 `resourceMap`。 - 可选:`3DTank/Start-LocalAndRelay.ps1` 启动镜像 + 中继(抓包/真实服务器)。 --- ## 2. 技术方案 ### 2.1 推荐方案 A:Kotlin/JS + kotlin-react + Emotion(与现工程同栈) ``` TankiOffline/ ui/ # 新:React 组件(Kotlin) src/jsMain/kotlin/Ui/ Theme.kt # 颜色/字体/间距 token(从原 Emotion 样式抽出) Components/ # Button / Panel / Tabs / Dialog / ItemCard ... Screens/ # Lobby / Garage / Shop / Battles / Quests ... Layout/ # MainScreen / Header / Menu / Chat / Footer app/ # 入口:Entrance → 连接 → Lobby state/ # 已有 RootState net/ # 已有协议 ``` 依赖: ```kotlin implementation(npm("react", "18.3.1")) implementation(npm("react-dom", "18.3.1")) implementation(npm("@emotion/react", "11.x")) // Kotlin 侧可用 kotlin-react / kotlin-emotion 包装,或直接 external 声明 ``` 数据流: ``` SessionRouter (Store) ──订阅──> UiStore (Adapter) ──props──> React 组件 ItemCatalog ───────────────────┘ Session 状态(连接/帧/日志)─────┘ ``` 优点:复用现有状态类;一套 Gradle 构建;后续可直接接 3D/战斗。 缺点:Kotlin React 组件写法与原始编译产物不完全一致,需要逐屏翻译。 ### 2.2 备选方案 B:独立 React/TS 工程 ``` webui/ (Vite + React + TS + Emotion) ↕ WebSocket / postMessage TankiOffline (Kotlin/JS 客户端) ``` 优点:前端生态成熟、UI 开发快、便于像素级还原。 缺点:状态模型要跨语言复制/序列化;构建两套;长期维护成本高。 ### 2.3 备选方案 C:混跑原 JS 模块 直接把 `module_82347` 作为 external 挂到 `window.__modules__`,用现有 Kotlin 状态通过 bridge 驱动。 优点:**保真度最高**、最快看到完整原版 UI。 缺点:不是“重建”,依赖原 bundle;长期难以维护。 可作为 **过渡验收**(视觉基准)而不是最终形态。 ### 2.4 保真度分层 | 级别 | 内容 | 验收 | |---|---|---| | L0 | 结构骨架(当前) | 能导航、无报错 | | L1 | 官方资源 / 字体 / 布局比例 | 截图肉眼接近 | | L2 | 像素级静态还原 | 与原版截图逐屏 diff | | L3 | 真实数据 + 交互 | 状态变化驱动 UI | | L4 | 3D 车库 / 战斗场景 | WebGL 管线接入 | --- ## 3. 里程碑 ### M0 基础设施(进行中) - [x] 资源镜像接入(`/play/static`)。 - [x] 登录页 1:1(EntranceView + entrance.css)。 - [ ] `ui` 模块启用 kotlin-react + Emotion,建立 `Theme.kt`。 - [ ] 协议级 mock 服务器(用户属性 / 物品目录 / 大厅列表)。 - [ ] `ScreenRegistry`:屏幕 ID ↔ 组件(对齐原 `ScreenId`)。 - [ ] `UiStore`:订阅 `SessionRouter.Store`,节流重绘。 - [ ] 3D 资源加载器(`.3ds` / 贴图 / 场景描述)+ 车库预览最小场景。 - [ ] 截图 / DOM 基准工具(人工验收辅助,不做像素门禁)。 ### M1 大厅骨架(2 个迭代) - 顶栏:等级/昵称/GS/水晶/金币/VIP/设置/声音。 - 左侧菜单:9 个官方图标 + 文案 + 选中态。 - 底部:大号“开始战斗”按钮、聊天面板、新闻条。 - 公告/活动/每日任务浮层。 - 验收:与官方大厅截图逐项对齐(无 3D 场景时用静态背景占位)。 ### M2 车库(3 个迭代) - 分类页签(12 类,来自 `ItemCategory` 枚举)。 - 物品网格:名称/稀有度/数量/VIP/价格;数据源 `ItemCatalog`。 - 物品详情:属性、升级、装备、皮肤。 - 3D 预览:接 M0 的 3D 加载器,先渲染底盘/炮塔/贴图与旋转,再补光照/摄像机。 ### M2.5 3D / 渲染(并行) - 3DS / 贴图 / 资源清单加载。 - 车库场景:平台、背景、坦克组装、光照、摄像机环绕。 - 与 `92980` 渲染管线的接口对齐;最终替换为原引擎实现。 ### M3 商店 / 幸运礼盒(2 个迭代) - 商店分类、卡片、折扣、支付方式、礼盒开启动画占位。 - 数据:`Shop` 切片 + `ItemCatalog`。 ### M4 战斗选择 / 任务 / 军团 / 好友 / 新闻(3 个迭代) - 战斗模式卡片、战斗列表、创建战场表单。 - 任务:主线/每日/每周/星级挑战/合约。 - 军团/好友:列表、搜索、请求、成员管理。 - 新闻:列表 + 详情。 ### M5 设置 / 弹窗体系(2 个迭代) - 设置 8 个页签(游戏/画面/声音/操控/账户/战斗/安全/支持)。 - 通用 Dialog / Toast / 确认框 / 购买弹窗 / 升级弹窗 / 排名弹窗。 ### M6 结算与 HUD(依赖 S5) - 战斗结算、奖励、排名变化。 - 战斗 HUD(`21300`):血条、道具、准星、计分板、聊天。 --- ## 4. 每屏的数据契约(先定,避免返工) | 屏幕 | 主要数据 | 现有来源 | 缺口 | |---|---|---|---| | Entrance | 语言/资源/连接状态 | `Translations` / `LobbyClient` | 真实登录 | | Lobby Home | User / News / Notifications / Quests 摘要 | RootState 已迁移 | 公告、活动配置 | | Garage | ItemCatalog / Garage 切片 / GaragePreview | 已有 | 3D 预览、装备操作 | | Shop | Shop 切片 / ItemCatalog | 已有 | 支付流程 | | Battles | BattlesSelect / Maps / Matchmaking | 已有 | 创建/匹配 | | Quests | Quests / Challenges / ContractState | 已有 | 领奖链路 | | Clans | Clan / ClanStorage / ClanChat | 已有 | 社交操作 | | Friends | Friends 切片 | 已有 | 搜索/请求 | | News | News 切片 | 已有 | 详情页 | | Settings | 8 个设置切片 | 已有 | 持久化 port | | HUD | BattleStatistics / BattleUsers / Supplies | 部分 | S5 战斗系统 | --- ## 5. 验收方式 1. **视觉基准**:原版客户端逐屏截图(需要可登录环境);新 UI 同分辨率截图,人工/像素 diff。 2. **DOM 基准**:同一数据下对比关键元素的尺寸、间距、颜色 token。 3. **交互基准**:点击路径一致(菜单、返回、弹窗层级)。 4. **数据基准**:同一抓包回放后,界面显示与状态断言一致(可自动化)。 --- ## 6. 风险与待决事项 | 风险 | 影响 | 对策 | |---|---|---| | 没有可登录账号,拿不到原版大厅截图/DOM | 无法做像素级对比 | 用测试账号 / 本地 mock 服务器 / 仅按源码还原 | | 3D 车库与战斗场景 | 大厅“灵魂”缺失 | 先用静态背景 + 官方素材,S4 后替换 | | `82347` 21 万行,逐屏翻译量大 | 周期长 | 按 M1–M5 切片,先布局后逻辑 | | 原样式是 Emotion 动态类名 | 难以直接复用 CSS | 抽 token + 按截图复写;或运行时抓取 CSS | | 资源 71 MB 进包 | 首屏体积 | 开发用镜像;生产走 CDN/代理 | --- ## 7. 当前进度(本文件创建时) - 登录页:1:1 完成(官方背景、logo、圆形登录按钮、健康忠告、年龄提示、ClientInfo)。 - 大厅:L0/L1 骨架(官方图标、真实翻译、物品目录、连接状态)。 - 资源:本地镜像已接入。 - 已确认:技术栈 Kotlin/React、组件级还原、本地 mock、3D 现在做、首批大厅+车库、允许混跑。 ## 9. 原版 DOM 实测映射(2026-10-25,登录 WYT2WYT 后) 视口 1296×1006,根字号 12.96px(`.ksc-37` 的 `max(min(1.48148vh,1vw),3px)`)。 所有尺寸换算:1em ≈ 12.96px。 ### 9.1 大厅首页 | 原 DOM 类 | 位置 / 尺寸 | 含义 | |---|---|---| | `MainScreenComponentStyle-containerPanel` | 0,0 1296×78 | 顶栏(6em,底边 1px 白 25%) | | `UserInfoContainerStyle-blockLeftPanel` | 0,0 408×78 | 等级图标 / 组队图标 / 昵称 / XP | | `UserInfoContainerStyle-rankIconContainerClickable` | 155,0 78×78 | 等级图标(`static/images/..webp`) | | `UserInfoContainerStyle-containerProgressMainScreen` | 246,15 162×49 | 昵称 + XP 条 + 数值 | | `UserScoreComponentStyle-blockRightPanel` | 1017,0 279×78 | 两行货币(红宝石 / 水晶)+ 全屏 + 退出 | | `MainScreenComponentStyle-containerForMenuGradient` | 0,0 648×1006 | 左侧 50%,黑→透明 0.5 | | `MainScreenComponentStyle-playButtonContainer` | 57,130 284×139 | “开始战斗”,背景 `videoplay.79570900.gif` | | `MainScreenComponentStyle-blockMainMenu` | 57,283 324×645 | 菜单容器 | | `PrimaryMenuItemComponentStyle-menuItemContainer` | 65,283 350×58 | 菜单项:礼盒 / 任务 / 车库 / 商店 / 设置 | | `PrimaryMenuItemComponentStyle-itemCommonLi` | 73,290 45×45 | 图标(mask + `#bfd5ff`) | | `PrimaryMenuItemComponentStyle-itemName` | 133,293 | 2em 大写文字 | | `FooterComponentStyle-footer` | 0,928 648×78 | 新闻 / 聊天 / 好友 / 军团(65×65) | | `MainScreenComponentStyle-gradientBlockRight` | 936,0 360×1006 | 右侧渐变(27.75em,0.75,旋转 180°) | | `BattlePassLobbyComponentStyle-menuBattlePass` | 972,110 292×130 | 星级挑战面板(22.5em×10em,right 2.5em) | | `AnnouncementHomeScreenComponentStyle-mainContainer` | 971,778 293×196 | 公告卡(22.5em 宽,right/bottom 2.5em) | | `ClientInfoComponentStyle-main` | 0,989 1296×17 | UID / 版本 / 电池 | ### 9.2 车库 | 原 DOM 类 | 位置 / 尺寸 | 含义 | |---|---|---| | `BreadcrumbsComponentStyle-headerContainer` | 0,0 1296×78 | 车库顶栏(返回 / 标题 / 货币 / 退出) | | `BreadcrumbsComponentStyle-backButton` | 0,0 78×78 | 返回 | | `BreadcrumbsComponentStyle-rootTitle` | 585,2 126×73 | 当前屏幕标题 | | `GarageCommonStyle-garageContainer` | 0,78 1296×928 | 车库主体 | | `GarageCommonStyle-positionContent` | 0,130 1296×876 | 内容区 | | `GarageMainScreenStyle-blockParameters` | 78,130 1140×685 | 中央 3D 预览 + 左右参数 | | `TankParametersStyle-leftParamsContainer` | 78,130 293×209 | 左上:GS + 参数 | | `MountedItemsStyle-container` | 920,130 298×492 | 右上:无人机 / 手榴弹 / 炮塔 / 底盘 | | `MountedItemsStyle-resistanceContainer` | 78,740 52×65 ×4 | 左下:防御模块 | | `SuppliesComponentStyle-commonBlockSupplies` | 78,862 1140×125 | 底部道具栏 | | `TankPreviewComponentStyle-visible GarageComponentStyle-tankPreview` | 0,0 1296×1006 | 3D 坦克画布 | ### 9.3 对应关系(JS → DOM) - `82347` 里 `Sq(Class, "XxxComponentStyle", ...)` 注册的样式类,就是 DOM 上的 `XxxComponentStyle-*`。 - `Eq("containerPanel", 1, ...)` 返回的类名拼接为 `MainScreenComponentStyle-containerPanel`。 - 样式值直接写在 `jq(Class).xxx = function(){ return this..dk(this, Eq("...")) }` 的样式对象里; 运行时可从 `document.styleSheets` 按类名前缀抓取(已用于本表)。 - 组件层级:`MainScreen` → `Header` / `PrimaryMenu` / `Footer` / `BattlePass` / `Announcement`; 车库:`GarageCommon` → `TankParameters` / `MountedItems` / `Supplies` / `TankPreview`。 ### 9.4 当前实现状态 - 大厅首页已按上表重建(6em 顶栏、21.875em Play、27em 菜单、5em 底栏、22.5em 右栏)。 - 车库正在按 9.2 重建:左侧参数 / 中央 3D / 右侧已装配件 / 底部道具栏; 物品选择列表作为抽屉保留,后续替换为原版的分类轮盘。 - [x] Kotlin/React 工具链接通(kotlin-react / kotlin-react-dom / kotlin-emotion,React 19.1)。 - [x] 物品目录 fixture:`SessionCheck` 从抓包导出 `resources/fixtures/catalog.json`(1399 物品)。 - [x] 车库第一版 React 界面:分类页签(12 类)、搜索、物品网格(120 张卡片)、右侧详情位。 - [ ] 车库按 9.2 的原版布局重建 + 3D 预览加载器。 - [ ] 协议级 mock 服务器(用户 / 大厅列表 / 任务)。 - [ ] 大厅其余屏幕迁移到 React。 --- ## 10. 原版 UI 还原方法(已验证,2026-10-26 设置页) > 这一节记录的是实际跑通的方法。后续所有页面都按这个流程做,不再先写通用样式再“看起来像”。 ### 10.1 原则 1. **不自己设计 UI**:布局、尺寸、颜色、类名、DOM 层级都以混淆版源码/原版 DOM 为唯一来源。 2. **先找定义,再做映射**:找不到原版定义就标注“未展开”,不靠截图猜。 3. **能用原版资源就不画近似**:图标、勾、knob、箭头、背景图优先用 `play/static/images` 里的原版资源。 4. **文案走 i18n**:使用 `Translations.T("lobby....")`,不硬编码中文。 5. **颜色走配色表**:使用 `Palette.kt`(来源 `C9i`),不手写近似色。 6. **每页完成后删除旧近似样式和死代码**,避免两套样式并存。 ### 10.2 定位组件定义 1. 在 `module_82347.js` 搜索: ```js Sq(Class, "XxxComponentStyle", ...) ``` 找到样式类。 2. 看类构造器: ```js this.xxx_1 = this.aux([], styleFn) ``` 找到字段与对应 `styleFn`。 3. 看访问器: ```js jq(Class).accessor = function () { ... Eq("fieldName", ...) ... } ``` 确认字段名和生成的语义类名。 4. 找渲染函数/组件:`jq(Component).tap` / `render`,确认 DOM 层级和子组件。 5. 把类名、字段、行号记录到对应的 `*StyleTable.md`。 示例(设置页): | 组件 | 类 / 函数 | 位置 | |---|---|---| | `SettingsComponentStyle` | `kNi` | `module_82347.js:89525` | | `SettingsMenuComponentStyle` | `EMi` | `90329` | | `SettingsButtonsComponentStyle` | `UPi` | `89326` | | `DropDownStyle` | `J7t` | `34073` | | `ContextMenuStyle` | `u7t` | `33638` | | `CheckBoxComponentStyle` | `QBi` | `92742` | | `CheckBoxStyle` | `Z0t` | `33272` | | `InputRangeComponentStyle` | `EUi` | `92980` | ### 10.3 提取真实 CSS 1. 在无头页面加载 `module_37036`(Kotlin 运行时)+ `module_82347`。 2. 实现最小 webpack require:`i(id)`、`i.p`、`i.d`、`i.r`、`i.n`、`i.o`、`i.hmd`。 3. patch `module_37036` 的 `ld`,捕获 `Sq(Class, Name)` 注册表。 4. 实例化目标样式类,遍历 `kuv_1.a1_1`,执行每个 `entry.duv_1[0](recorder)`。 5. recorder 记录 `rpf` / `gp8` / `jp8` / `lp7` / `qp7`,输出 base/nested CSS。 6. 动态方法直接调用,例如: - `d1mg(recorder, important)`:下拉选项 - `m1md` / `n1md`:复选框 / Toggle Switch - `hUi.tap`:滑杆进度渐变 7. 提取结果写入 `*StyleTable.md`,作为实现依据。 ### 10.4 还原真实 DOM 和类名 1. 按原版 DOM 写结构,不替换成自创的 `button` / `div`。 2. 保留语义类名: - `InputRangeComponentStyle-blockSoundVolume` - `InputRangeComponentStyle-soundVolume` - `InputRangeComponentStyle-range` - `SettingsComponentStyle-slider` - `CheckBoxComponentStyle-oneSetting` - `CheckBoxStyle-checkbox` - `DropDownStyle` / `ContextMenuStyle` 相关类 3. 保留原版 `ksc-*` 标记用于核对,例如 `ksc-56`(百分比)、`ksc-57`(滑杆)、`ksc-62`(Switch)、`ksc-63`(标签容器)。 4. 原版 DOM 示例: 滑杆: ```html

主音量(80%)

``` Switch: ```html
``` ### 10.5 提取原版资源 1. 资源模块通常长这样: ```js 67116:(t,n,i)=>{ t.exports = i.p + "static/images/correct.afad1b22.svg" } ``` 2. 通过 IIFE 参数表与调用参数对齐,找到变量对应的 module id: - `Vn` → module `67116` → `correct.afad1b22.svg`(Switch 开) - `Kn` → module `13357` → `incorrectCheck.1918884a.svg`(Switch 关) - `$n` → module `74120` → `checkMark.fb44274a.svg`(方形复选框勾) 3. 资源放到 `/play/static/images/`,直接引用,不再用 CSS 画近似图形。 ### 10.6 配色 / i18n / 尺寸 - 颜色:`C9i` / `E9i()` 主题对象 → `Palette.kt` → `ColorPalette.md`。 - 文案:`Translations.T("lobby....")`,语言切换走 `Translations.LoadLocale`。 - 尺寸:直接使用 style 函数里的 em 值;`1em ≈ 12.96px`(1296×1006)。 - 细节:百分比位置、颜色、间距、圆角都按原 DOM / style 函数,不凭感觉调。 ### 10.7 验收 1. 无头探针打开页面,记录 DOM、rect、computed style、截图。 2. 对比项: - 语义类名 / `ksc-*` 标记是否存在 - 尺寸、间距、圆角、边框 - 颜色(背景、文字、强调色、进度、Switch) - 交互(下拉展开/滚动、滑杆拖动、Switch 切换) 3. 与 `*StyleTable.md` 对齐;不一致就回到 10.2 重新提取。 4. 完成后删除旧近似样式、未使用函数、死代码。 ### 10.8 设置页验证记录 设置页已按本方法完成: - HEAD 复用主页顶栏,只替换 VIP 为退出键。 - 菜单顺序:游戏显示 / 战斗 / 画面 / 音效 / 操控 / 账户 / 安全。 - 颜色全部走 `Palette`。 - 文案全部走 i18n。 - 滑杆:原版 DOM + `InputRangeComponentStyle` + 进度渐变。 - Switch:原版 `CheckBoxComponentStyle-oneSetting` + `ksc-62` + 原版圆形 knob。 - 下拉:`DropDownStyle` + `ContextMenuStyle` + 固定选项高度 + 按需滚动。 详细映射见: - `3DTank/docs/SettingsStyleTable.md` 第 6/7/8 节 - `3DTank/docs/ColorPalette.md` --- ## 11. 桩代码标记规范 > 目的:不允许“看起来像原版”的自创组件混进最终 UI。找不到原版定义时,只能留明确标记的桩。 ### 11.1 强制标记 任何非原版实现、占位、模拟数据、临时组件必须同时具备: 1. 源码注释: ```kotlin // STUB: 原版 <组件名/样式类> 尚未展开 ``` 2. DOM 标记: ```kotlin Ui("stub..") ``` 3. 文档记录:在 `UiTranslationStatus.md` 的“待翻译/未展开”中列出。 ### 11.2 禁止事项 - 禁止用自创的 `button` / `div` / 卡片替代原版组件而不标记。 - 禁止用近似色、近似尺寸冒充原版值。 - 禁止把 mock 数据写成真实数据;mock 必须标 `STUB` 或 `offline demo`。 - 禁止在未找到原版定义时直接写“完成”。 ### 11.3 删除规则 - 原版定义补齐后,删除对应 `STUB` 注释、`data-ui="stub.*"` 和文档条目。 - 删除旧近似样式时,同步删除未使用的 style 函数/常量,避免两套实现并存。 ### 11.4 HEAD 验证记录 HEAD 已按第 10 节方法重写: - 样式类:`MainScreenComponentStyle-containerPanel` / `UserInfoContainerStyle-blockLeftPanel` / `UserScoreComponentStyle-blockRightPanel` - Logo:`iconTankiOnline.2a9c236f.svg`(192×60px) - 等级块:`5.9375em × 6em`,仅右边框 - XP 容器:`.875em` 高,`margin-top:.55em`,`opacity:.8` - XP 条:`12.5em × .25em`,绿色 50% 背景 - 货币列:`9.2em` 宽,`margin-right:2em` - VIP 块(`x6n.tap`):`6em × 6em`,`box-shadow:1px 0 0 0 rgba(255,255,255,.25)`,未开通 VIP 时金红径向渐变,`:hover` 5% 白;图标 `iconButtonPremium.bc17a592.svg`,`2em × 2em` - 组队块(`L4.tap`):`5.9375em × 6em`,右边框,`:hover` 5% 白;2 人组 `commonUserIconsBlockGroup` `3.25em × 1.9em` + 两个 `q4` 图标 `1.5em`(`groupUser.67c9ec61.svg`,空位色 `rgba(191,212,255,.5)`) - 全屏块(`uKt`):`6em × 6em`,左右各 1px 白 25% 边框,`:hover` 5% 白 + 图标变白;图标 `fullscreen.0b4547f5.svg`,`1.5em` - 退出块(`BreadcrumbsComponentStyle-logout`):`6em × 6em`,无边框,`:hover` 5% 白 + 图标变白;图标 `iconBack.62869951.svg`,`1.5em` - 货币列(`nti`):`display:flex; flex-direction:column; position:relative`;红宝石/水晶行按 `l1qd`/`n1qd`,`min-width:7.9375em`、`height:3em`、`padding-right:.75em`、红宝石行 `border-bottom`;不再套用 `coinsContainer` 的 `9.2em` / `margin-right:2em` / 右边框 - 实测 rect:左块 `408.58×77.75`、VIP `77.75×77.75`、组队/等级 `77.94×77.75`、用户 `162×48.59`、货币列 `102.86×77.75`(x=1035.64)、右块从 `1035.64` 开始。