release(ios): 0.2.2 构建 8 中性化批量标签禁用态并去蓝化图标底色

- FleetTagBatchSheet:无勾选时标签胶囊不再走 Button 禁用态(系统会压成灰块,像加载
  失败),改为中性标签原样渲染;覆盖度文案留空,图标改 tag;新建标签输入与按钮置灰
  并补一句「勾选节点后即可新建标签并批量贴上」。
- 应用图标:底色与插槽从偏青绿的石墨(R>G=B,亮壁纸上读作蓝)改为严格等值中性灰
  20/19/10,金色跨度拉大(#FADD98 -> #C78D2F)去掉芥末黄塑料感;AppIcon.svg 同步。
- 版本号:marketing 0.2.2 不带括号,构建号 7 -> 8;文档里 0.2.x (N) 一律改写为
  「0.2.x 构建 N」,README 与现行说明同步。
This commit is contained in:
chick
2026-09-15 05:07:03 +08:00
parent 36ce791215
commit 9ad0c46088
11 changed files with 120 additions and 63 deletions
+8 -8
View File
@@ -2,18 +2,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
<defs>
<linearGradient id="field" x1="0.06" y1="0" x2="0.94" y2="1">
<stop offset="0" stop-color="#1A1F1E"/>
<stop offset="0.55" stop-color="#111514"/>
<stop offset="1" stop-color="#0B0E0D"/>
<stop offset="0" stop-color="#202021"/>
<stop offset="0.55" stop-color="#131314"/>
<stop offset="1" stop-color="#0A0A0B"/>
</linearGradient>
<linearGradient id="brass" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#F8D57C"/>
<stop offset="0.50" stop-color="#ECBD56"/>
<stop offset="1" stop-color="#D49E36"/>
<stop offset="0" stop-color="#FADD98"/>
<stop offset="0.46" stop-color="#EEBF64"/>
<stop offset="1" stop-color="#C78D2F"/>
</linearGradient>
<linearGradient id="slot" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0F1312"/>
<stop offset="1" stop-color="#1D2321"/>
<stop offset="0" stop-color="#101011"/>
<stop offset="1" stop-color="#202021"/>
</linearGradient>
</defs>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

+23 -19
View File
@@ -1,10 +1,14 @@
// Renders the 1024x1024 MultiSimAdmin app icon with CoreGraphics only.
// Usage: swift Design/generate_app_icon.swift <output.png>
//
// The mark is the web favicon grown up: a flat brass SIM plate with three
// ascending slots cut out of it, on a graphite field. Two colours, one light
// source from the upper left, no metal texture, so it still reads at the 29pt
// settings size. The plate keeps the classic single SIM cut, top-left.
// The mark is the web favicon grown up: a flat gold SIM plate with three
// ascending slots cut out of it, on a neutral graphite field. Two colours, one
// light source from the upper left, no metal texture, so it still reads at the
// 29pt settings size. The plate keeps the classic single SIM cut, top-left.
//
// The field is deliberately neutral (R = G = B): the moment it drifts cool the
// whole icon reads as "blue icon" on a lit home screen. The gold is pushed warm
// and deep enough that it stays metal rather than mustard.
//
// Every coordinate is in visual space (origin top-left, y grows down).
import AppKit
@@ -129,16 +133,16 @@ func directionalRim(_ path: CGPath, _ rect: CGRect, _ width: CGFloat, _ stops: [
fillLinear(
rectPath(CGRect(x: 0, y: 0, width: side, height: side)),
[
(0.00, (26, 31, 30, 255)),
(0.55, (17, 21, 20, 255)),
(1.00, (11, 14, 13, 255)),
(0.00, (32, 32, 33, 255)),
(0.55, (19, 19, 20, 255)),
(1.00, (10, 10, 11, 255)),
] as [Stop],
CGPoint(x: side * 0.06, y: 0),
CGPoint(x: side * 0.94, y: side)
)
fillRadial(
CGPoint(x: side * 0.22, y: -side * 0.10), CGFloat(side * 0.86),
[(0.0, (214, 226, 218, 26)), (0.60, (214, 226, 218, 7)), (1.0, (214, 226, 218, 0))] as [Stop]
[(0.0, (232, 226, 214, 24)), (0.60, (232, 226, 214, 6)), (1.0, (232, 226, 214, 0))] as [Stop]
)
// MARK: - Plate
@@ -165,9 +169,9 @@ ctx.restoreGState()
fillLinear(
plate,
[
(0.00, (248, 213, 124, 255)),
(0.50, (236, 189, 86, 255)),
(1.00, (212, 158, 54, 255)),
(0.00, (250, 221, 152, 255)),
(0.46, (238, 191, 100, 255)),
(1.00, (199, 141, 47, 255)),
] as [Stop],
CGPoint(x: plateRect.minX, y: plateRect.minY),
CGPoint(x: plateRect.maxX, y: plateRect.maxY)
@@ -175,9 +179,9 @@ fillLinear(
directionalRim(
plate, plateRect, plateSide * 0.007,
[
(0.00, (255, 244, 214, 132)),
(0.36, (255, 238, 198, 30)),
(0.68, (255, 234, 186, 0)),
(0.00, (255, 246, 224, 140)),
(0.36, (255, 240, 206, 32)),
(0.68, (255, 236, 196, 0)),
] as [Stop]
)
@@ -203,8 +207,8 @@ for (index, height) in slotHeights.enumerated() {
fillLinear(
path,
[
(0.00, (15, 19, 18, 255)),
(1.00, (29, 35, 33, 255)),
(0.00, (16, 16, 17, 255)),
(1.00, (32, 32, 33, 255)),
] as [Stop],
CGPoint(x: rect.minX, y: rect.minY),
CGPoint(x: rect.minX, y: rect.maxY)
@@ -213,9 +217,9 @@ for (index, height) in slotHeights.enumerated() {
directionalRim(
path, rect, radius * 0.30,
[
(0.00, (120, 84, 18, 96)),
(0.52, (120, 84, 18, 18)),
(1.00, (255, 232, 176, 58)),
(0.00, (112, 74, 16, 100)),
(0.52, (112, 74, 16, 18)),
(1.00, (255, 236, 190, 60)),
] as [Stop]
)
}