From 8f9a96754b67ecd9a16ef38a49c2d018affdd024 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 26 Oct 2026 21:44:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=E6=8C=89=E5=8E=9F=E7=89=88=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20HEAD=20=E8=B4=A7=E5=B8=81=E5=88=97=E5=AF=B9?= =?UTF-8?q?=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3DTank/docs/HeadStyleTable.md | 18 ++- 3DTank/docs/UI_Rebuild_Plan.md | 3 +- .../kotlin/App/Browser/Ui/HeadScreen.kt | 105 ++++++++++++------ 3 files changed, 86 insertions(+), 40 deletions(-) diff --git a/3DTank/docs/HeadStyleTable.md b/3DTank/docs/HeadStyleTable.md index ce5b987..fabf8ba 100644 --- a/3DTank/docs/HeadStyleTable.md +++ b/3DTank/docs/HeadStyleTable.md @@ -74,10 +74,14 @@ Lq = To.$_$.gd, // module_37036: gd = te = ne("class", ...) | `head.user.xp.fill` | XP 进度 | `display:block; height:100%; width:%; background:rgb(118,255,51); border-radius:inherit` | `XpFillStyle(Ratio)` | | `head.user.xp.text` | XP 数字 | `display:flex; align-items:center; margin-top:.35em; margin-left:.25em; font:500 1em/1 BaseFontMedium; text-shadow:0 0 .25em rgba(0,0,0,.5); color:rgb(118,255,51)` | `XpTextStyle` | | `head.logo` | `blockForIconTankiOnline` | `position:absolute; inset:0; margin:auto; display:flex; align-items:center; justify-content:center; z-index:1; pointer-events:none`;图片 `iconTankiOnline.2a9c236f.svg`,`192×60px → 14.81em×4.63em` | `LogoStyle` | -| `head.right` | `blockRightPanel` | `display:flex; align-items:center; height:100%; z-index:5` | `RightStyle` | -| `head.currencies` | `coinsContainer` | `display:flex; flex-direction:column; justify-content:center; height:100%; width:9.2em; box-sizing:border-box; border-right:1px solid rgba(255,255,255,.25); margin-right:2em` | `CurrenciesStyle` | -| `head.currency.ruby` | 红宝石 | `position:relative; display:flex; align-items:center; gap:.4em; width:100%; height:3em; padding:0 .75em 0 .6em; box-sizing:border-box; cursor:pointer; border-bottom:1px solid rgba(255,255,255,.25)` | `CurrencyStyle(true)` | -| `head.currency.crystal` | 水晶 | 同上,无 `border-bottom` | `CurrencyStyle(false)` | +| `head.right` | `blockRightPanel`(`Dni`) | `display:flex; justify-content:flex-end; align-items:center; align-self:center; margin-right:0; height:6em; margin-top:0; z-index:5` | `RightStyle` | +| `head.currencies` | `nti`(红宝石/水晶列) | `display:flex; flex-direction:column; position:relative`。没有 `coinsContainer` 的 `9.2em` / `margin-right:2em` / 右边框 | `CurrenciesStyle` | +| `head.currency.ruby` | `HeaderCommonStyle-icons` + `l1qd` | `display:flex; align-items:center; justify-content:flex-start; height:3em; order:1; flex-grow:1; flex-shrink:0; cursor:pointer; min-width:7.9375em; box-sizing:border-box; padding-right:.75em; border-bottom:1px solid rgba(255,255,255,.25)` | `CurrencyStyle(true, false)` | +| `head.currency.crystal` | `HeaderCommonStyle-icons` + `n1qd` | 同上,`padding-left:.75em; padding-right:.75em`,无 `border-bottom` | `CurrencyStyle(false, true)` | +| `head.currency.value` | `l1qd`/`n1qd` 的 `span` | `font:500 1.125em/1.313em BaseFontMedium; font-style:normal; text-transform:uppercase; word-spacing:.1em; margin-left:.6em; margin-right:1em`;红宝石 `color:rgb(255,102,102); margin-top:.1em`,水晶 `color:rgb(0,215,255)` | `CurrencyValueStyle(Color, MarginTop)` | +| `head.currency.ruby.icon` | `iconCoinSizeMedium` + `margin-right:0` | `width:1em; height:1em; margin-right:0` | `RubyIconStyle` | +| `head.currency.crystal.icon` | `iconCrystal` | `width:1em; height:1em; margin-left:-.78em` | `CrystalIconStyle` | +| `head.currency.plus` | `addRubyCrystal` | `width:1em; height:1em; position:absolute; right:1em` | `PlusStyle` | | `head.fullscreen` | `uKt`(`eKt` 全屏按钮) | `display:flex; align-items:center; justify-content:center; width:6em; height:6em; padding:0; position:relative; border-left:1px solid rgba(255,255,255,.25); border-right:1px solid rgba(255,255,255,.25); background:transparent; cursor:pointer; :hover{background-color:rgba(255,255,255,.05)}` | `FullscreenStyle` | | `head.fullscreen.icon` | `hKt().c1m0(n)` | `width:1.5em; height:1.5em; background-color:rgb(191,213,255); mask:url(fullscreen.0b4547f5.svg) center/contain no-repeat`;全屏时换 `fullscreenOff.5691cd5d.svg`;hover 变白 | `FullscreenIconStyle` | | `head.logout` | `BreadcrumbsComponentStyle-logout`(`i1pt`) | `display:flex; align-items:center; justify-content:center; width:6em; height:6em; margin-left:0; border:0; background:transparent; cursor:pointer; :hover{background-color:rgba(255,255,255,.05)}` | `LogoutStyle` | @@ -119,8 +123,10 @@ node 3DTank/tools/headless_probe.js ` - `head.group`:`77.94×77.75` - `head.rank`:`77.94×77.75` - `head.user`:`162×48.59` -- `head.currencies`:`119.22×77.75` -- `head.fullscreen` / `head.logout`:`77.75×77.75` +- `head.currencies`:`102.86×77.75`(x=1035.64) +- `head.right`:`260.36×77.75`(x=1035.64) +- `head.fullscreen`:`79.75×77.75` +- `head.logout`:`77.75×77.75` ## 6. 已确认 / 待核对常量 diff --git a/3DTank/docs/UI_Rebuild_Plan.md b/3DTank/docs/UI_Rebuild_Plan.md index c18b845..6dbe507 100644 --- a/3DTank/docs/UI_Rebuild_Plan.md +++ b/3DTank/docs/UI_Rebuild_Plan.md @@ -473,4 +473,5 @@ HEAD 已按第 10 节方法重写: - 组队块(`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` -- 实测 rect:左块 `408.58×77.75`、VIP `77.75×77.75`、组队/等级 `77.94×77.75`、用户 `162×48.59`、右块从 `994` 开始,与计划 9.1 基本一致。 +- 货币列(`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` 开始。 diff --git a/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/HeadScreen.kt b/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/HeadScreen.kt index 0938037..e57e29d 100644 --- a/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/HeadScreen.kt +++ b/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/HeadScreen.kt @@ -78,13 +78,6 @@ private val LeftStyle: PropertiesBuilder.() -> Unit = { Css("z-index", "2") } -private val RightStyle: PropertiesBuilder.() -> Unit = { - Css("display", "flex") - Css("align-items", "center") - Css("height", "100%") - Css("z-index", "5") -} - private val Divider = "1px solid rgba(255, 255, 255, 0.25)" /** Emotion 嵌套选择器:原版 `qp7(m6n)` / `qp7(x4)` 的 hover 背景。 */ @@ -178,7 +171,7 @@ private val GroupIconsStyle: PropertiesBuilder.() -> Unit = { Css("height", "1.9em") } -/** 原版 `q4`:1.5em 组员图标,绝对定位贴左/右下角。 */ +/** 原版 `q4`:1.5em 组员图标,绝对定位贴左/右下角;`air` 是 mask-image。 */ private fun GroupIconStyle(Side: String, Color: String): PropertiesBuilder.() -> Unit = { Css("width", "1.5em") Css("height", "1.5em") @@ -187,10 +180,14 @@ private fun GroupIconStyle(Side: String, Color: String): PropertiesBuilder.() -> Css(Side, "0") Css("bottom", "0") Css("background-color", Color) - Css("background-image", "url(\"${Asset("static/images/groupUser.67c9ec61.svg")}\")") - Css("background-position", "center") - Css("background-repeat", "no-repeat") - Css("background-size", "contain") + Css("mask-image", "url(\"${Asset("static/images/groupUser.67c9ec61.svg")}\")") + Css("mask-position", "center") + Css("mask-repeat", "no-repeat") + Css("mask-size", "contain") + Css("-webkit-mask-image", "url(\"${Asset("static/images/groupUser.67c9ec61.svg")}\")") + Css("-webkit-mask-position", "center") + Css("-webkit-mask-repeat", "no-repeat") + Css("-webkit-mask-size", "contain") } // ---------------------------------------------------------------- 等级 / 用户 @@ -296,47 +293,77 @@ private val LogoImgStyle: PropertiesBuilder.() -> Unit = { // ---------------------------------------------------------------- 右侧货币 / F11 / 退出 +/** 原版 `Dni`(blockRightPanel)。 */ +private val RightStyle: PropertiesBuilder.() -> Unit = { + Css("display", "flex") + Css("justify-content", "flex-end") + Css("align-items", "center") + Css("align-self", "center") + Css("margin-right", "0") + Css("height", "6em") + Css("margin-top", "0") + Css("z-index", "5") +} + +/** 原版 `nti`:红宝石/水晶列。没有 coinsContainer 的 9.2em / 边框 / margin-right。 */ private val CurrenciesStyle: PropertiesBuilder.() -> Unit = { Css("display", "flex") Css("flex-direction", "column") - Css("justify-content", "center") - Css("height", "100%") - Css("width", "9.2em") - Css("box-sizing", "border-box") - Css("border-right", Divider) - Css("margin-right", "2em") + Css("position", "relative") } -private fun CurrencyStyle(BorderBottom: Boolean): PropertiesBuilder.() -> Unit = { - Css("position", "relative") +/** 原版 `HeaderCommonStyle-icons` + `l1qd`(红宝石行)/ `n1qd`(水晶行)。 */ +private fun CurrencyStyle(BorderBottom: Boolean, PaddingLeft: Boolean): PropertiesBuilder.() -> Unit = { Css("display", "flex") Css("align-items", "center") - Css("gap", "0.4em") - Css("width", "100%") + Css("justify-content", "flex-start") Css("height", "3em") - Css("padding", "0 0.75em 0 0.6em") - Css("box-sizing", "border-box") + Css("order", "1") + Css("flex-grow", "1") + Css("flex-shrink", "0") Css("cursor", "pointer") + Css("min-width", "7.9375em") + Css("box-sizing", "border-box") + if (PaddingLeft) Css("padding-left", "0.75em") + Css("padding-right", "0.75em") if (BorderBottom) Css("border-bottom", Divider) } -private val CoinStyle: PropertiesBuilder.() -> Unit = { +/** 原版 `iconCoinSizeMedium` + `o$(a, 0)`(红宝石图标)。 */ +private val RubyIconStyle: PropertiesBuilder.() -> Unit = { Css("width", "1em") Css("height", "1em") - Css("margin-right", "0.25em") - Css("margin-top", "0.2em") + Css("margin-right", "0") } -private val CurrencyValueStyle: PropertiesBuilder.() -> Unit = { - Css("font", "500 1.05em/1 BaseFontMedium, sans-serif") +/** 原版 `iconCrystal`(水晶图标)。 */ +private val CrystalIconStyle: PropertiesBuilder.() -> Unit = { + Css("width", "1em") + Css("height", "1em") + Css("margin-left", "-0.78em") } +/** 原版 `l1qd` / `n1qd` 的 `span` 子样式。 */ +private fun CurrencyValueStyle(Color: String, MarginTop: Boolean): PropertiesBuilder.() -> Unit = { + Css("font-family", "BaseFontMedium, FallbackFontMedium") + Css("font-style", "normal") + Css("font-weight", "500") + Css("font-size", "1.125em") + Css("line-height", "1.313em") + Css("text-transform", "uppercase") + Css("word-spacing", "0.1em") + Css("color", Color) + Css("margin-left", "0.6em") + Css("margin-right", "1em") + if (MarginTop) Css("margin-top", "0.1em") +} + +/** 原版 `addRubyCrystal`。 */ private val PlusStyle: PropertiesBuilder.() -> Unit = { Css("width", "1em") Css("height", "1em") Css("position", "absolute") Css("right", "1em") - Css("opacity", "0.85") } private val FullscreenStyle: PropertiesBuilder.() -> Unit = { @@ -391,12 +418,16 @@ private fun react.ChildrenBuilder.CurrencyRow( Value: Int, UiName: String, BorderBottom: Boolean, + PaddingLeft: Boolean, + ValueColor: String, + MarginTop: Boolean, + IconStyle: PropertiesBuilder.() -> Unit, ) { div { - css(CurrencyStyle(BorderBottom)) + css(CurrencyStyle(BorderBottom, PaddingLeft)) Ui(UiName) - img { src = Asset(Icon); css(CoinStyle) } - span { css(CurrencyValueStyle); +"$Value" } + img { src = Asset(Icon); css(IconStyle) } + span { css(CurrencyValueStyle(ValueColor, MarginTop)); +"$Value" } img { src = Asset(Plus); css(PlusStyle) } } } @@ -496,6 +527,10 @@ val HeadScreen = FC { HeadContext.Rubies, "head.currency.ruby", true, + false, + Palette.RedSoft, + true, + RubyIconStyle, ) CurrencyRow( "static/images/crystalSmall.242e6c15.svg", @@ -503,6 +538,10 @@ val HeadScreen = FC { HeadContext.Crystals, "head.currency.crystal", false, + true, + Palette.CyanBright, + false, + CrystalIconStyle, ) } div {