feat: add DMG background with app design system and Gatekeeper guide

This commit is contained in:
小鱼开发
2026-05-19 10:15:35 +08:00
parent 92359e98f8
commit 6431666e7d
3 changed files with 172 additions and 1 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+156
View File
@@ -0,0 +1,156 @@
#!/usr/bin/env python3
"""
生成 DMG 背景图 — 美家卡智影设计规范
====================================
画布: 660 x 400 px
风格: 与应用 UI 一致(绿色品牌色、卡片阴影、圆角)
"""
import subprocess
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
# ──────────────────────────── 配置 ────────────────────────────
W, H = 660, 400
# 颜色(引用应用 CSS 变量)
BG = (249, 250, 251) # --bg-main: #f9fafb
CARD_BG = (255, 255, 255) # --bg-card: #fff
PRIMARY = (54, 178, 106) # --primary: #36b26a
TEXT_PRIMARY = (17, 24, 39) # --text-primary: #111827
TEXT_SECONDARY = (107, 114, 128) # --text-secondary: #6b7280
TEXT_TERTIARY = (156, 163, 175) # --text-tertiary: #9ca3af
BORDER = (229, 231, 235) # --border-color: #e5e7eb
SUCCESS = (16, 185, 129) # --success: #10b981
# 阴影(模拟 CSS box-shadow
def draw_card_shadow(draw, bbox, color=(0, 0, 0), alpha=0.05, blur=8):
"""绘制卡片阴影"""
x1, y1, x2, y2 = bbox
for i in range(blur, 0, -1):
a = int(alpha * 255 * (i / blur))
offset = blur - i + 2
draw.rounded_rectangle(
[x1 - offset, y1 - offset + 2, x2 + offset, y2 + offset + 4],
radius=12,
fill=(0, 0, 0, a),
)
# ──────────────────────────── 字体 ────────────────────────────
def get_font(size, bold=False):
"""获取中文字体"""
result = subprocess.run(
["fc-match", "-f", "%{file}", "PingFang SC"],
capture_output=True, text=True
)
path = result.stdout.strip()
if path and Path(path).exists():
idx = 2 if bold else 0 # 常规/粗体索引
return ImageFont.truetype(path, size, index=idx)
return ImageFont.load_default()
font_title = get_font(22, bold=True)
font_subtitle = get_font(13, bold=True)
font_body = get_font(12)
font_caption = get_font(10)
# ──────────────────────────── 画布 ────────────────────────────
bg = Image.new("RGBA", (W, H), (*BG, 255))
draw = ImageDraw.Draw(bg)
# ──────────────────────────── 顶部品牌区 ────────────────────────────
# 加载 Logo(绿色 M
logo = Image.open("icons/icon.png").convert("RGBA")
logo_size = 36
logo.thumbnail((logo_size, logo_size), Image.LANCZOS)
# 放置 Logo(顶部居中偏左,与文字搭配)
logo_x = (W - logo_size) // 2 - 70
logo_y = 28
bg.paste(logo, (logo_x, logo_y), logo)
# 品牌名称
draw.text((logo_x + logo_size + 10, logo_y + 6), "美家卡智影",
fill=TEXT_PRIMARY, font=font_title)
# ──────────────────────────── 中部拖拽引导 ────────────────────────────
# 拖拽箭头(从左侧指向右侧)
arrow_y = 195
arrow_start = 220
arrow_end = 440
arrow_mid = (arrow_start + arrow_end) // 2
# 虚线箭头身
dash_len = 6
gap_len = 4
current = arrow_start
while current < arrow_end - 10:
seg = min(dash_len, arrow_end - 10 - current)
draw.line([(current, arrow_y), (current + seg, arrow_y)],
fill=PRIMARY, width=2)
current += dash_len + gap_len
# 箭头头部
draw.polygon([(arrow_end, arrow_y), (arrow_end - 8, arrow_y - 4),
(arrow_end - 8, arrow_y + 4)], fill=PRIMARY)
# 引导文字
draw.text((W // 2, arrow_y + 18), "将左侧图标拖拽到右侧 Applications 文件夹",
fill=TEXT_SECONDARY, font=font_body, anchor="mm")
# ──────────────────────────── 底部提示卡片 ────────────────────────────
card_w = 420
card_h = 110
card_x = (W - card_w) // 2
card_y = 245
radius = 12
# 卡片阴影(多层模拟)
shadow = Image.new("RGBA", (W, H), (0, 0, 0, 0))
shadow_draw = ImageDraw.Draw(shadow)
for i in range(6, 0, -1):
a = int(0.04 * 255 * (i / 6))
offset = 8 - i
shadow_draw.rounded_rectangle(
[card_x - offset, card_y - offset + 2,
card_x + card_w + offset, card_y + card_h + offset + 4],
radius=radius, fill=(0, 0, 0, a)
)
bg = Image.alpha_composite(bg, shadow)
draw = ImageDraw.Draw(bg)
# 卡片本体
draw.rounded_rectangle(
[card_x, card_y, card_x + card_w, card_y + card_h],
radius=radius, fill=CARD_BG, outline=BORDER, width=1
)
# 左侧绿色竖条(强调色)
bar_w = 4
draw.rounded_rectangle(
[card_x, card_y + 16, card_x + bar_w, card_y + card_h - 16],
radius=bar_w // 2, fill=PRIMARY
)
# 提示标题(绿色)
draw.text((card_x + 20, card_y + 14), "首次安装提示",
fill=PRIMARY, font=font_subtitle)
# 提示正文
tip_lines = [
"由于未注册 Apple 开发者,首次打开时可能会被系统拦截",
"请右键点击应用图标,选择「打开」,或在系统设置中允许",
]
for i, line in enumerate(tip_lines):
draw.text((card_x + 20, card_y + 38 + i * 18), line,
fill=TEXT_SECONDARY, font=font_body)
# ──────────────────────────── 底部版本号 ────────────────────────────
draw.text((W // 2, H - 16), "v1.5.18",
fill=TEXT_TERTIARY, font=font_caption, anchor="mm")
# ──────────────────────────── 保存 ────────────────────────────
output = bg.convert("RGB")
output.save("dmg-background.png", "PNG")
print("✅ Generated: tauri-app/src-tauri/dmg-background.png (660x400)")
+16 -1
View File
@@ -70,7 +70,22 @@
],
"macOS": {
"minimumSystemVersion": "13.0",
"infoPlist": "Info.plist"
"infoPlist": "Info.plist",
"dmg": {
"background": "dmg-background.png",
"windowSize": {
"width": 660,
"height": 400
},
"appPosition": {
"x": 180,
"y": 170
},
"applicationFolderPosition": {
"x": 480,
"y": 170
}
}
},
"windows": {
"nsis": {