feat: 支持新版的首页 UI

This commit is contained in:
richarjiang
2026-10-25 21:15:15 +08:00
parent 4ca32c22f9
commit d93cc921db
30 changed files with 827 additions and 223 deletions

View File

@@ -0,0 +1,55 @@
"""Render the homepage's simple native tab symbols from editable vector geometry.
Run with Python + Pillow. No external images or fonts are used.
"""
from pathlib import Path
from PIL import Image, ImageDraw
DEST = Path(__file__).resolve().parents[1] / 'src/static/tab'
SIZE, SCALE = 81, 24
FACTOR = SIZE * 4 / SCALE
def render(name, active):
image = Image.new('RGBA', (SIZE * 4, SIZE * 4))
draw = ImageDraw.Draw(image)
color = '#6b8276' if active else '#99948e'
weight = round(1.35 * FACTOR)
def box(coords): return tuple(round(value * FACTOR) for value in coords)
def line(points, width=weight):
points = [box(point) for point in points]
draw.line(points, fill=color, width=width, joint='curve')
r = width / 2
for x, y in (points[0], points[-1]):
draw.ellipse((x-r, y-r, x+r, y+r), fill=color)
if name == 'home':
roof = [(3.8,10), (12,3.2), (20.2,10)]
if active:
draw.polygon([box(p) for p in roof + [(20.2,20.4),(14.6,20.4),(14.6,13.2),(9.4,13.2),(9.4,20.4),(3.8,20.4)]], fill=color)
else:
line(roof)
line([(5.2,9.5),(5.2,20.4),(9.4,20.4),(9.4,13.2),(14.6,13.2),(14.6,20.4),(18.8,20.4),(18.8,9.5)])
elif name == 'booking':
draw.rounded_rectangle(box((4.2,5.7,19.8,21)), radius=round(3*FACTOR), outline=color, width=weight)
line([(4.5,10.5),(19.5,10.5)])
line([(8,3.2),(8,7.8)])
line([(16,3.2),(16,7.8)])
if active:
line([(8.5,15.8),(11,18),(15.8,13.8)])
elif name == 'learn':
draw.ellipse(box((3,3,21,21)), outline=color, width=weight)
points = [(15.8,8.2),(13.7,13.7),(8.2,15.8),(10.3,10.3),(15.8,8.2)]
if active:
draw.polygon([box(p) for p in points], fill=color)
else:
line(points, round(1.1*FACTOR))
elif name == 'profile':
draw.ellipse(box((8,2.8,16,10.8)), outline=color, width=weight)
draw.rounded_rectangle(box((4.2,14,19.8,21.5)), radius=round(3.6*FACTOR), outline=color, width=weight)
if active:
draw.ellipse(box((9.2,4,14.8,9.6)), fill=color)
image = image.resize((SIZE,SIZE), Image.Resampling.LANCZOS)
image.save(DEST / f"{name}{'-active' if active else ''}.png", optimize=True)
for name in ['home','booking','learn','profile']:
for active in [False,True]:
render(name,active)
print('Rendered 8 tab icons, 81×81px, sage active / warm-gray inactive.')