- Add company module (3-tier org, CEO planning, parallel departments) - Add company orchestrator, knowledge extractor, presets, scheduler - Add company API endpoints, models, and frontend views - Add 今天吃啥 PWA app (69 dishes, real images, offline support) - Add team_projects output directory structure - Add unified manage.ps1 for service lifecycle - Add Windows startup guide v1.0 - Add TTS troubleshooting doc - Update frontend (AgentChat UX overhaul, new views) - Update backend (voice engine fix, multi-tenant, RBAC) - Remove deprecated startup scripts and old docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
89 lines
2.9 KiB
Python
89 lines
2.9 KiB
Python
"""Generate PWA icon PNGs using Pillow."""
|
|
import os
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
DIR = os.path.dirname(os.path.abspath(__file__))
|
|
ICONS_DIR = os.path.join(DIR, 'icons')
|
|
os.makedirs(ICONS_DIR, exist_ok=True)
|
|
|
|
# Icon colors
|
|
BG_COLOR = '#FF9800' # Orange background
|
|
FG_COLOR = '#FFFFFF' # White text/icon
|
|
SAFE_BG = '#FF9800' # Safe zone background for maskable
|
|
|
|
def create_icon(size, fname, maskable=False):
|
|
img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
if maskable:
|
|
# Maskable: fill entire square, but draw content in safe zone (80%)
|
|
margin = 0
|
|
safe_margin = int(size * 0.1)
|
|
else:
|
|
margin = int(size * 0.05)
|
|
|
|
# Rounded rect background
|
|
rr = size // 6
|
|
draw.rounded_rectangle([margin, margin, size - margin, size - margin],
|
|
radius=rr, fill=BG_COLOR)
|
|
|
|
# Draw a simple bowl/plate icon using circles
|
|
# Bowl body (semicircle/bowl shape)
|
|
center_x = size // 2
|
|
bowl_top = int(size * 0.38)
|
|
bowl_bottom = int(size * 0.72)
|
|
bowl_width = int(size * 0.4)
|
|
|
|
# Bowl (semicircle)
|
|
draw.ellipse([center_x - bowl_width//2, bowl_top - bowl_width//4,
|
|
center_x + bowl_width//2, bowl_bottom],
|
|
fill=FG_COLOR + '40', outline=FG_COLOR, width=max(3, size//80))
|
|
|
|
# Bowl rim
|
|
rim_y = bowl_top
|
|
draw.ellipse([center_x - bowl_width//2, rim_y - bowl_width//6,
|
|
center_x + bowl_width//2, rim_y + bowl_width//6],
|
|
outline=FG_COLOR, width=max(3, size//80))
|
|
|
|
# Steam lines (3 curves above bowl)
|
|
steam_start = bowl_top - bowl_width//4
|
|
for i, offset in enumerate([-bowl_width//5, 0, bowl_width//5]):
|
|
sx = center_x + offset
|
|
sy = steam_start - int(size * 0.02)
|
|
if maskable:
|
|
sy -= int(size * 0.02)
|
|
draw.arc([sx - size//20, sy - size//10, sx + size//20, sy],
|
|
start=180, end=0, fill=FG_COLOR, width=max(2, size//100))
|
|
|
|
# App name text (bottom area)
|
|
try:
|
|
font_size = size // 8
|
|
font = ImageFont.truetype('C:\\Windows\\Fonts\\msyh.ttc', font_size)
|
|
except:
|
|
try:
|
|
font = ImageFont.truetype('C:\\Windows\\Fonts\\simhei.ttf', font_size)
|
|
except:
|
|
font = ImageFont.load_default()
|
|
|
|
text = '今天吃啥'
|
|
bbox = draw.textbbox((0, 0), text, font=font)
|
|
tw = bbox[2] - bbox[0]
|
|
th = bbox[3] - bbox[1]
|
|
tx = (size - tw) // 2
|
|
ty = size - th - int(size * 0.12)
|
|
draw.text((tx, ty), text, fill=FG_COLOR, font=font)
|
|
|
|
img.save(os.path.join(ICONS_DIR, fname), 'PNG')
|
|
print(f' {fname} ({size}x{size})')
|
|
|
|
# Generate icons
|
|
print('Generating PWA icons...')
|
|
create_icon(192, 'icon-192.png')
|
|
create_icon(512, 'icon-512.png')
|
|
create_icon(192, 'icon-192-maskable.png', maskable=True)
|
|
create_icon(512, 'icon-512-maskable.png', maskable=True)
|
|
|
|
# Also generate Apple touch icon (180x180)
|
|
create_icon(180, 'apple-touch-icon.png')
|
|
print('Done!')
|