# Shop Style Table > 来源:`3DTank/src/module_82347.js`(与 `3dtank.com/play/static/js/unpacked/module_82347.js` 同构)。 > 提取方法:`3DTank/tools/headless_probe.js` 加载 `module_37036` + `module_82347`,实例化样式类,执行 `dk(...)` 的 style 函数。 > Kotlin 侧:`TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/LobbyScreens.kt` 的 `ShopScreen` 及其上方 `Shop*` 样式。 ## 1. 样式类 | 类 | 语义名 | 定义 | 访问器 | |---|---|---|---| | `$Fi` | `NewShopCommonComponentStyle` | `93477` | `e1hz` container / `b1sk` commonBlockMenuShop / `b1k7` commonContainer / `c1sj` gradient / `l1sk` containerAnnouncement | | `zHi` | `ShopSelectedSectionComponentStyle` | `94195` | `y1qq` commonCard / `a1sp` gradientCategory / `y1so` limitedOffersCommon / `x1so` mobileCardContainer / `c1sp` scrollContainerShop / `u1ju` commonBlock / `u1sj` activeCategory / `v1sj` notifier / `k1nd` timer;参数化 `t1sj(icon, active)` | | `MVi` | `ShopCategoryComponentStyle` | `95731` | `e1hz` container / `ri5` header / `gax` description / `t1su` bonusContainer / `v1su` bonus / `w1su` marginItemsContainer;参数化 `u1su(rec, bonus)` | | `YVi` | `ShopCategoryOfferSectionStyle` | `95908` | `x1su` promoCodesItemsContainer / `p1st` widthSearchInput / `b1m1` containerItem / `y1su` containerCoin / `z1su` containerLimitOffers / `a1sv` containerKitOffers | | `RKi` | `ShopFooterComponentStyle` | `96243` | `u1hz` mainContainer / `n1sw` buttonAndTextContainer / `o1sw` exclamation / `k1sw` reportButton | | `uXi` | `ShopItemComponentStyle` | `96891` | `k1sy` 基础卡片 / `h1sy` footerContent / `h1pt` headerContainer / `j1sy` headerScroll / `y1sx` headerContent / `i1sy` containerName / `n1sy` previewContainer / `e1mb` discount / `s1ma` discountContainer 等 | | `PZt` | `ShopBuyButtonComponentStyle` | `31920` | `u11p` root / `vck` price | ## 2. 关键 CSS ### 2.1 左侧分类菜单 `commonBlockMenuShop`(`b1sk`): ```css display:flex; flex-direction:column; align-items:center; justify-content:flex-start; cursor:default; background-color:rgba(3,8,13,.25); backdrop-filter:blur(.781em); border-radius:1rem; border-right:1.25em solid transparent; height:max-content; margin-left:2em; margin-top:2em; max-height:calc(100% - 9.8em); z-index:2; padding:1.25em; padding-right:0; width:25em; ``` 分类项 `t1sj(icon, active)`: ```css display:flex; align-items:center; justify-content:flex-start; width:23.75em; height:3.5em; min-height:3.5em; max-height:3.5em; margin:0; position:relative; overflow:hidden; cursor:pointer; /* active */ background-color:rgba(255,204,0,.25); border-radius:.5rem; color:rgb(255,204,0); ``` 图标(`div`): ```css width:1.5em; height:1.5em; margin-right:1.25em; background-color:white; /* active: rgb(255,204,0) + margin-left:1.25em */ mask-image:url(icon); mask-position:center; mask-repeat:no-repeat; mask-size:contain; ``` 标签(`h4`): ```css font:500 1em/1 BaseFontMedium; text-transform:uppercase; color:white; /* active: rgb(255,204,0) */ margin:.2em 0 0; ``` ### 2.2 主容器 `commonContainer`(`b1k7`): ```css background:radial-gradient(50% 100% at 50% 100%, #203040 0%, #03080D 100%); display:flex; align-items:stretch; justify-content:space-between; height:100%; width:100%; max-height:calc(100% - 6em); ``` 原版 `pFi.tap` 的三个子节点:左菜单、分类内容、右侧选中区。 ### 2.3 分类内容 `ShopCategoryComponentStyle-container`(`e1hz`)是 `display:contents`;标题/描述/物品网格直接进入 `commonContainer`。 标题(`ri5`): ```css font:500 1.875em/1.4em BaseFontBold; margin:1em 0 0; text-transform:uppercase; ``` 描述(`gax`): ```css opacity:.6; line-height:1.25em; font-size:.938em; ``` 物品容器 `u1su(rec, bonus)`: ```css display:flex; flex-wrap:wrap; align-items:flex-start; justify-content:flex-start; width:37em; height:100%; gap:1em; margin-left:.25em; margin-top:.25em; /* bonus: .6em */ ``` `containerItem`(`b1m1`): ```css display:grid; grid-template-columns:50% 50%; grid-template-rows:31.35%; gap:1em; width:37.25em; margin:2em .9em 1em .25em; padding:0 0 0 .25em; justify-content:flex-start; align-content:flex-start; z-index:3; ``` ### 2.4 物品卡片 `k1sy`: ```css display:flex; flex-direction:column; align-items:center; justify-content:center; position:relative; user-select:none; box-sizing:border-box; cursor:pointer; border-radius:1rem; background-color:rgba(255,255,255,.15); width:17.5em; height:inherit; box-shadow:0 0 0 1px rgba(255,255,255,.3); ``` 标题容器 `h1pt`: ```css width:calc(100% - 1.5em); position:absolute; left:.75em; top:.75em; display:flex; align-items:center; justify-content:flex-start; z-index:1; ``` 标题文字 `y1sx`: ```css font:500 1em/1 BaseFontMedium; text-transform:uppercase; color:white; margin-top:.2em; ``` 价格文字 `h1sy`: ```css font:500 1.125em/1.125 BaseFontMedium; text-transform:uppercase; margin-top:.125em; ``` 预览 `n1sy`: ```css display:flex; align-items:center; justify-content:center; height:auto; width:auto; max-width:80%; z-index:3; ``` 折扣 `e1mb`: ```css position:absolute; right:.625em; bottom:1em; line-height:1.333em; font-size:.938em; font-weight:bold; ``` ### 2.5 底部栏 `ShopFooterComponentStyle-mainContainer`(`u1hz`): ```css display:flex; align-items:center; justify-content:flex-start; width:100%; height:3.125em; position:absolute; bottom:0; border-top:.063em solid rgba(255,255,255,.1); backdrop-filter:blur(2.688em); z-index:3; ``` `buttonAndTextContainer`(`n1sw`): ```css width:auto; height:2.2em; margin-left:1.8em; display:flex; align-items:center; justify-content:flex-start; ``` `exclamation`(`o1sw`): ```css margin-left:.7em; opacity:.5; font:400 .875em/1 BaseFontRegular; ``` ### 2.6 分类卡(`ShopSelectedSectionComponentStyle-commonBlock`) 原版 `$Gi` 的 DOM: ```text div (commonCard / limitedOffersCommon) ├─ div.cardImg (z1so) 背景图 100%×100%,background-size:cover,圆角 .625em └─ span (b1sp) 标题,absolute,top:1em(limited: bottom:1em) ``` `commonCard`: ```css display:flex; align-items:center; justify-content:center; width:22.5em; height:calc(100% / 2 - 1.2em); padding:.4em; border-radius:.625em; overflow:hidden; position:relative; cursor:pointer; ``` `z1so`: ```css background-color:rgba(191,213,255,.15); background-size:cover; background-position:center; background-repeat:no-repeat; border-radius:.625em; width:100%; height:100%; z-index:1; ``` `b1sp`: ```css font:500 1.125em/1 BaseFontMedium; text-transform:uppercase; position:absolute; top:1em; z-index:3; ``` 离线实现:没有 `dsw_1` 分类美术 URL,保留官方 `z1so` 的背景色/尺寸/圆角,图像区域用 `stub.shop.card.art` 虚线占位;标题仍按 `b1sp` 定位。 #### 两种列布局 原版 `MGi.tap` 先渲染 `specialCategories`,再渲染 `generalCategories`: | 类型 | 列样式 | 卡片样式 | 高度 | |---|---|---|---| | 普通分类(一排两行) | `w1hz`:`flex column; justify-content:space-between` | `commonCard` | `calc(100% / 2 - 1.2em)` | | 特殊/限时(一排一行) | `f1if`:`flex column; justify-content:flex-start` | `limitedOffersCommon` | `calc(100% - .5em)` | 两种列都是 `width:22.5em; flex:0 0 22.5em; height:calc(100% - .5em); margin-right:1em`。 离线数据没有原版 `esw_1` 特殊分类标记;当前用 `KIT(套件)` 作为特殊分类演示全高卡(代码内有 `STUB` 注释)。 #### Hover 细节 | 目标 | 原版 | CSS | |---|---|---| | 分类卡图像 | `VGi` / `KGi` | `transform:scale(1.05,1.05); transition:all .2s ease-in-out` | | 分类菜单项(未激活) | `pHi` / `wHi` | `box-shadow:0 0 0 2px rgb(255,255,255); border-radius:.5em; margin-left:1.25em; transition:all .1s ease-in-out` | | 分类菜单项(激活) | `aHi` / `cHi` | `box-shadow:none` | | 物品卡 | `TYi` | `box-shadow:0 0 0 2px rgb(255,255,255)` | 这些都已用无头探针确认生成的 CSS,例如: ```css .css-1vz2w25:hover { transform: scale(1.05, 1.05); transition: 0.2s ease-in-out; } .css-1owq6vw:hover { box-shadow: rgb(255, 255, 255) 0em 0em 0em 2px; } .css-1vberae:hover { box-shadow: none; } ``` ## 3. 资源 | 用途 | 资源 | |---|---| | 红宝石 | `ruby.ce62efbc.svg` | | 水晶 | `crystalSmall.242e6c15.svg` | | 金币 | `coin.3a16e831.svg` | | 红宝石加号 | `addRuby.ff47c8be.svg` | | 水晶加号 | `addCrystal.af9a397c.svg` | | 金币加号 | `addCoin.cc7a25d3.svg` | ## 4. 当前实现状态 已还原: - 先进入 `ShopSelectedSectionComponentStyle-commonBlock`:横向滚动的 22.5em 分类卡(每列 2 张,`commonCard` / `scrollContainerShop`) - 点击分类卡后进入 `NewShopCommonComponentStyle-commonContainer` - 左侧竖向分类菜单(25em 面板 + 23.75em × 3.5em 分类项 + 图标/激活态) - 主容器径向渐变 - 右侧 37.25em 物品区:分类标题/描述 + 2 列物品网格 - 物品卡片(17.5em 宽,1rem 圆角,15% 白底,1px 内描边) - 物品名称/价格/货币图标 - 底部 3.125em 栏 + `报告问题` 按钮 + 提示 未展开 / 近似: - 分类卡背景:原版 `z1so` 使用 `dsw_1` 分类美术(服务器下发 URL),离线资源里没有;当前保留官方 `z1so` 背景色/尺寸/圆角,图像区域用 `stub.shop.card.art` 虚线占位(`STUB` 标记) - `containerItem` 的 `grid-template-rows:31.35%` 动态行高(当前固定 `11.5em`) - `ShopFooterComponentStyle-reportButton` 的共享 Button 完整外观(当前金色按钮近似) - 金币 / 限时 / 礼包特殊分类(`containerCoin` / `containerLimitOffers` / `containerKitOffers`) - 折扣/加成/促销码/能源条(当前数据模型没有这些字段) - 分类菜单的 `(any-hover:hover)` 悬停样式(当前未加) - 物品目录按 `Name` 去重显示(离线目录同一炮塔有多个等级条目;原版按服务器商品条目显示) ## 5. 验收 ```powershell node 3DTank/tools/headless_probe.js ` --url "http://localhost:8080/?autoconnect=1" ` --out "build/probe/shop" ` --width 1296 --height 1006 --wait 14000 ` --eval-file "C:\Users\TermiNexus\AppData\Local\Temp\opencode\goto_shop.js" ``` 实测: ```text 分类卡页:22.5em 宽,每列 2 张,横向滚动 shop.menu x=36 y=104 w=328 h=452 shop.category x=805 y=104 w=483 h=... shop.item 226.8 × 149.0(17.5em × 11.5em) shop.footer y=966 h=40 ```