"""登录页与应用外壳(顶栏 + 标签页导航)。
外壳把各分区(我的数据 / 管理)组装起来,按钮均在静态区,id 稳定。
"""
from __future__ import annotations
from typing import Any
from shiny import ui
from . import config, theme
from .view_admin import _admin_panel
from .view_me import _my_panel
def login_view() -> ui.Tag:
return ui.div(
ui.div(
theme.crest(96),
ui.div(config.TEAM_NAME, class_="zh"),
ui.div(config.TEAM_NAME_EN, class_="en"),
ui.div(f"{config.TEAM_CITY} · EST. {config.EST_YEAR}", class_="city"),
theme.card(
"球员登录",
ui.input_text("in_user", "用户名", placeholder="如 leo / hakimi / admin"),
ui.input_password("in_pw", "密码", placeholder="请输入密码"),
ui.input_action_button("btn_login", "登 录", class_="btn-primary"),
icon="🔐",
),
ui.div(
ui.HTML(
"球员用球队分配的用户名登录,初始密码请向领队索取;"
"首次登录后请到『我的数据』页修改密码。"
),
class_="sde-login-hint",
),
class_="sde-login",
),
class_="sde-login-wrap",
)
def app_shell(
user: dict[str, Any],
user_choices: dict[str, str],
seasons: list[int],
) -> ui.Tag:
top = ui.div(
ui.div(
theme.crest(52),
ui.div(
ui.div(config.TEAM_NAME, class_="zh"),
ui.div(config.TEAM_NAME_EN, class_="en"),
),
class_="sde-brand",
),
ui.div(class_="sde-spacer"),
ui.span(ui.HTML(f'欢迎,{user["display_name"]}'), class_="sde-welcome"),
ui.input_action_button("btn_logout", "退出", class_="btn-outline-light btn-sm"),
class_="sde-topbar",
)
season_choices = {"all": "全部赛季", **{str(y): f"{y} 赛季" for y in seasons}}
panels = [
ui.nav_panel(
"🏆 主页",
ui.div(
ui.download_button("dl_leaderboard", "📷 导出榜单图", class_="btn-outline-light btn-sm"),
ui.input_select("home_season", "赛季", season_choices, selected="all", width="150px"),
class_="sde-season-bar",
),
ui.output_ui("home_content"),
value="home",
),
ui.nav_panel("📝 我的数据", _my_panel(), value="me"),
]
if user["is_admin"]:
panels.append(ui.nav_panel("⚙️ 管理", _admin_panel(user_choices), value="admin"))
return ui.div(
top,
ui.navset_tab(*panels, id="main_tabs"),
ui.div(
ui.HTML(f"肆带贰足球俱乐部 · {config.TEAM_NAME_EN}"),
class_="sde-foot",
),
class_="sde-shell",
)