File size: 2,117 Bytes
6e876c1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | """视图层共享小构件:名次、球员单元格、排行表、比赛头部行、带球衣号的名字。
被 view_home / view_me 复用,避免重复实现。
"""
from __future__ import annotations
from typing import Any, Callable, Optional
from shiny import ui
from . import theme
def _medal(rank: int) -> str:
return {1: "🥇", 2: "🥈", 3: "🥉"}.get(rank, str(rank))
def _player_cell(r: dict[str, Any], me_id: Optional[int]) -> ui.Tag:
parts: list[Any] = []
if r.get("jersey"):
parts.append(ui.span(f'#{r["jersey"]}', class_="sde-jersey"))
parts.append(r["name"])
if r["user_id"] == me_id:
parts.append(ui.span("我", class_="sde-me-tag"))
return ui.span(*parts)
def _rank_table(
rows: list[dict[str, Any]],
columns: list[tuple[str, Callable[[dict, int], Any], str]],
me_id: Optional[int],
) -> ui.Tag:
if not rows:
return ui.div("暂无数据", class_="sde-empty")
head = ui.tags.tr(*[ui.tags.th(h) for h, _, _ in columns])
body = []
for i, r in enumerate(rows, 1):
tds = [ui.tags.td(fn(r, i), class_=(cls or None)) for _, fn, cls in columns]
body.append(ui.tags.tr(*tds, class_=("is-me" if r["user_id"] == me_id else None)))
table = ui.tags.table(
ui.tags.thead(head), ui.tags.tbody(*body), class_="sde-table sde-rank-table"
)
return ui.div(table, class_="sde-table-wrap")
def _match_top(m: dict[str, Any]) -> ui.Tag:
"""一场比赛的头部行:日期 · 主客 · 对手 · 比分 · 结果(flex 自动换行)。"""
return ui.div(
ui.span(m["date"], class_="sde-mc-date"),
theme.ha_pill(m["home_away"]),
ui.span(m["opponent"], class_="sde-mc-opp"),
(ui.span(m["note"], class_="sde-mc-note") if m["note"] else None),
ui.span(class_="sde-spacer"),
ui.span(m["score_str"], class_="sde-mc-score"),
theme.result_badge(m["result"]),
class_="sde-mc-top",
)
def _name_with_jersey(p: dict[str, Any]) -> str:
return f'#{p["jersey"]} {p["display_name"]}' if p.get("jersey") else p["display_name"]
|