From 66ba163ef63838d1cc3b0256a0b4d93d73cff715 Mon Sep 17 00:00:00 2001 From: Zichao Lin Date: Mon, 6 Jul 2026 00:24:03 +0800 Subject: [PATCH] feat(showcase): lightbox, checkbox per-card toggle, lazyload, fix toggle Y-align, remove navbar on public page --- app/routers/web.py | 4 +- app/static/style.css | 16 ++++++- app/templates/base.html | 4 +- app/templates/dashboard.html | 2 +- app/templates/postcards.html | 4 +- app/templates/settings.html | 10 +---- app/templates/showcase.html | 86 +++++++++++++++++++++++++++++++----- 7 files changed, 98 insertions(+), 28 deletions(-) diff --git a/app/routers/web.py b/app/routers/web.py index f07063f..2aff537 100644 --- a/app/routers/web.py +++ b/app/routers/web.py @@ -514,12 +514,12 @@ def profile_showcase_save( @router.post("/postcards/{postcard_id}/showcase-toggle") -def postcard_showcase_toggle(postcard_id: int, showcase_hidden: str = Form(""), user: User = Depends(get_current_user_web), db: Session = Depends(get_db)): +def postcard_showcase_toggle(postcard_id: int, showcase_visible: str = Form(""), user: User = Depends(get_current_user_web), db: Session = Depends(get_db)): pc = db.query(Postcard).filter(Postcard.id == postcard_id).first() if pc: profile = db.query(Profile).filter(Profile.id == pc.profile_id, Profile.user_id == user.id).first() if profile and profile.showcase_enabled: - pc.showcase_hidden = showcase_hidden == "1" + pc.showcase_hidden = showcase_visible != "1" db.commit() return _redirect("/settings?tab=showcase") diff --git a/app/static/style.css b/app/static/style.css index 9b7f155..9da9ecc 100644 --- a/app/static/style.css +++ b/app/static/style.css @@ -227,13 +227,13 @@ code { background: var(--bg); padding: .15rem .4rem; border-radius: 4px; font-si .empty { color: var(--text-muted); padding: 2rem; text-align: center; } /* Toggle switch */ -.toggle-switch { position: relative; display: inline-block; width: 36px; height: 20px; } +.toggle-switch { position: relative; display: inline-block; width: 36px; height: 20px; margin: 0; vertical-align: middle; } .toggle-switch input { opacity: 0; width: 0; height: 0; } .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background: var(--border); border-radius: 20px; transition: .2s; } .toggle-slider::before { content: ""; position: absolute; height: 16px; width: 16px; left: 2px; bottom: 2px; background: #fff; border-radius: 50%; transition: .2s; } .toggle-switch input:checked + .toggle-slider { background: var(--primary); } .toggle-switch input:checked + .toggle-slider::before { transform: translateX(16px); } -.toggle-sm { width: 30px; height: 18px; } +.toggle-sm { width: 30px; height: 18px; margin: 0; } .toggle-sm .toggle-slider::before { height: 14px; width: 14px; } .toggle-sm input:checked + .toggle-slider::before { transform: translateX(12px); } @@ -247,6 +247,18 @@ code { background: var(--bg); padding: .15rem .4rem; border-radius: 4px; font-si .showcase-card-meta { display: flex; gap: .5rem; font-size: .8rem; color: var(--text-muted); margin-top: .25rem; } .showcase-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: .75rem; margin-bottom: 1rem; } +/* Lightbox */ +.lightbox { display: none; position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,.85); justify-content: center; align-items: center; } +.lightbox.active { display: flex; } +.lightbox-content { position: relative; max-width: 90vw; max-height: 85vh; text-align: center; } +.lightbox-content img { max-width: 90vw; max-height: 80vh; object-fit: contain; border-radius: 6px; } +.lightbox-caption { color: #fff; font-size: .85rem; margin-top: .5rem; text-align: center; } +.lightbox-close { position: absolute; top: .75rem; right: 1rem; background: none; border: none; color: #fff; font-size: 2rem; cursor: pointer; z-index: 101; line-height: 1; } +.lightbox-prev, .lightbox-next { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(255,255,255,.15); border: none; color: #fff; font-size: 1.8rem; cursor: pointer; padding: .5rem .75rem; border-radius: 4px; z-index: 101; transition: background .2s; } +.lightbox-prev:hover, .lightbox-next:hover { background: rgba(255,255,255,.3); } +.lightbox-prev { left: 1rem; } +.lightbox-next { right: 1rem; } + /* Responsive */ @media (max-width: 640px) { .detail-grid { grid-template-columns: 1fr; } diff --git a/app/templates/base.html b/app/templates/base.html index 3090625..a2b91ad 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -7,8 +7,8 @@ + {% block nav %} + {% endblock %}
{% block content %}{% endblock %}
diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 497a558..6f77d82 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -68,7 +68,7 @@
{% if pc.image_front %} - + {% else %} 📷 {% endif %} diff --git a/app/templates/postcards.html b/app/templates/postcards.html index fd2cec5..3f49613 100644 --- a/app/templates/postcards.html +++ b/app/templates/postcards.html @@ -28,7 +28,7 @@ diff --git a/app/templates/showcase.html b/app/templates/showcase.html index 89dab3f..20f8e8f 100644 --- a/app/templates/showcase.html +++ b/app/templates/showcase.html @@ -1,6 +1,6 @@ {% extends "base.html" %} -{% block title %}{{ profile_user.username }} 的展示页{% endblock %} -{% block navbar %}{% endblock %} +{% block title %}{{ profile_user.username }} 的明信片{% endblock %} +{% block nav %}{% endblock %} {% block content %}

📮 {{ profile_user.username }} 的明信片

@@ -22,9 +22,9 @@ {% if mode == 'flat' %}
{% for pc in sent_all %} -
+
{% if pc.image_front %} - + {% else %}
📷
{% endif %} @@ -44,9 +44,9 @@

{{ g.profile.nickname }}

{% for pc in g.sent %} -
+
{% if pc.image_front %} - + {% else %}
📷
{% endif %} @@ -69,9 +69,9 @@ {% if mode == 'flat' %}
{% for pc in received_all %} -
+
{% if pc.image_front %} - + {% else %}
📷
{% endif %} @@ -91,9 +91,9 @@

{{ g.profile.nickname }}

{% for pc in g.received %} -
+
{% if pc.image_front %} - + {% else %}
📷
{% endif %} @@ -111,6 +111,17 @@ {% endfor %} {% endif %}
+{% endif %} + + -{% endif %} {% endblock %}