diff --git a/tauri-app/src-tauri/dmg-background.png b/tauri-app/src-tauri/dmg-background.png index e53ca9d..76fa7a9 100644 Binary files a/tauri-app/src-tauri/dmg-background.png and b/tauri-app/src-tauri/dmg-background.png differ diff --git a/tauri-app/src-tauri/generate-dmg-bg.py b/tauri-app/src-tauri/generate-dmg-bg.py index c7718ae..a90e497 100644 --- a/tauri-app/src-tauri/generate-dmg-bg.py +++ b/tauri-app/src-tauri/generate-dmg-bg.py @@ -1,10 +1,7 @@ #!/usr/bin/env python3 """ 生成 DMG 背景图 — 美家卡智影设计规范 -==================================== - -画布: 660 x 400 px -风格: 与应用 UI 一致(绿色品牌色、卡片阴影、圆角) +画布: 660 x 400 px(直接渲染,无缩放) """ import subprocess @@ -14,74 +11,75 @@ 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), - ) +# 颜色 +BG = (249, 250, 251) +CARD_BG = (255, 255, 255) +PRIMARY = (54, 178, 106) +SECONDARY = (24, 160, 138) +TEXT_PRIMARY = (17, 24, 39) +TEXT_SECONDARY = (107, 114, 128) +TEXT_TERTIARY = (156, 163, 175) +BORDER = (229, 231, 235) # ──────────────────────────── 字体 ──────────────────────────── 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 # 常规/粗体索引 + 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) +font_title = get_font(20, bold=True) +font_subtitle = get_font(16, bold=True) +font_body = get_font(13) +font_caption = get_font(11) # ──────────────────────────── 画布 ──────────────────────────── bg = Image.new("RGBA", (W, H), (*BG, 255)) draw = ImageDraw.Draw(bg) # ──────────────────────────── 顶部品牌区 ──────────────────────────── -# 加载 Logo(绿色 M) -logo = Image.open("icons/icon.png").convert("RGBA") +logo = Image.open("../public/assets/logo.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 +logo_x = (W - logo_size) // 2 - 65 +logo_y = 20 bg.paste(logo, (logo_x, logo_y), logo) -# 品牌名称(品牌绿色) -draw.text((logo_x + logo_size + 10, logo_y + 6), "美家卡智影", - fill=PRIMARY, font=font_title) +# 品牌名称 — 渐变文字效果(加宽 20px 防止截断) +title_text = "美家卡智影" +title_x = logo_x + logo_size + 8 +title_y = logo_y + 2 + +tw = int(draw.textlength(title_text, font=font_title)) + 30 +th = font_title.size + 8 + +gradient = Image.new("RGBA", (tw, th), (0, 0, 0, 0)) +for y in range(th): + ratio = y / th + r = int(PRIMARY[0] * (1 - ratio) + SECONDARY[0] * ratio) + g = int(PRIMARY[1] * (1 - ratio) + SECONDARY[1] * ratio) + b = int(PRIMARY[2] * (1 - ratio) + SECONDARY[2] * ratio) + for x in range(tw): + gradient.putpixel((x, y), (r, g, b, 255)) + +mask = Image.new("L", (tw, th), 0) +mask_draw = ImageDraw.Draw(mask) +mask_draw.text((0, 0), title_text, fill=255, font=font_title) + +gradient.putalpha(mask) +bg.paste(gradient, (title_x, title_y), gradient) # ──────────────────────────── 中部拖拽引导 ──────────────────────────── -# 拖拽箭头(从左侧指向右侧) -arrow_y = 195 +arrow_y = 200 arrow_start = 220 arrow_end = 440 -arrow_mid = (arrow_start + arrow_end) // 2 -# 虚线箭头身 dash_len = 6 gap_len = 4 current = arrow_start @@ -91,22 +89,20 @@ while current < arrow_end - 10: 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 文件夹", +draw.text((W // 2, arrow_y + 14), "将左侧图标拖拽到右侧 Applications 文件夹", fill=TEXT_SECONDARY, font=font_body, anchor="mm") # ──────────────────────────── 底部提示卡片 ──────────────────────────── -card_w = 420 -card_h = 110 +card_w = 600 +card_h = 105 card_x = (W - card_w) // 2 -card_y = 245 +card_y = 242 radius = 12 -# 卡片阴影(多层模拟) +# 阴影 shadow = Image.new("RGBA", (W, H), (0, 0, 0, 0)) shadow_draw = ImageDraw.Draw(shadow) for i in range(6, 0, -1): @@ -126,15 +122,14 @@ draw.rounded_rectangle( 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 + [card_x, card_y + 14, card_x + 3, card_y + card_h - 14], + radius=1, fill=PRIMARY ) -# 提示标题(绿色) -draw.text((card_x + 20, card_y + 14), "首次安装提示", +# 提示标题 +draw.text((card_x + 16, card_y + 12), "首次安装提示", fill=PRIMARY, font=font_subtitle) # 提示正文 @@ -143,14 +138,14 @@ tip_lines = [ "请右键点击应用图标,选择「打开」,或在系统设置中允许", ] for i, line in enumerate(tip_lines): - draw.text((card_x + 20, card_y + 38 + i * 18), line, + draw.text((card_x + 16, card_y + 36 + i * 20), line, fill=TEXT_SECONDARY, font=font_body) # ──────────────────────────── 底部版本号 ──────────────────────────── -draw.text((W // 2, H - 16), "v1.5.18", +draw.text((W // 2, H - 14), "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)") +print("✅ Generated: dmg-background.png (660x400)")