- ink-400 #9C9587(2.90:1)→ #756F61(paper-50 4.87:1 / paper-100 4.55:1),正文级小字全部达标 - serif 栈插入 Noto Serif SC(fontsource 子集加载),Windows 不再跌进 SimSun - 首页加 feTurbulence 纸张噪点层(.grain);报头/赛程行/预测版 rise-in 错峰入场(60ms 步进) - reduce 动效用户:隐藏态与动画同在 no-preference 块,不会白屏 - Switch 提到模块顶层(修 render 重建丢焦点);a→Link(SPA 内链);h3→h2/h4→h3 修标题层级 - 按钮/输入热区抬高(btn 40px / btn-sm 32px / field py-2);index.css 硬编码色值改 :root 令牌
92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
/**
|
|
* 主应用入口
|
|
*
|
|
* 整合前台(报纸风格)和后台(暗色管理)的路由。
|
|
* - / → 先知(Profeto)主站
|
|
* - /admin/* → 管理后台
|
|
*/
|
|
|
|
import { BrowserRouter, Routes, Route, Navigate, Link } from 'react-router-dom'
|
|
import { ErrorBoundary } from './components/ErrorBoundary'
|
|
import Matches from './pages/Matches'
|
|
import { adminRoutes } from './admin/routes'
|
|
|
|
/** 报眉日期行 */
|
|
function dateLine(): string {
|
|
return new Date().toLocaleDateString('zh-CN', {
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric',
|
|
weekday: 'long',
|
|
})
|
|
}
|
|
|
|
function HomePage() {
|
|
return (
|
|
// grain: 纸张噪点氛围层;报头、赛程行、预测版各自带 rise-in 入场
|
|
<div className="grain min-h-screen bg-paper-50">
|
|
{/* ── 报头:粗线 + 居中刊名 + 报眉 ── */}
|
|
<header className="masthead-rule rise-in">
|
|
<div className="mx-auto max-w-5xl px-5 sm:px-8">
|
|
<div className="border-b border-ink-900 py-5 text-center sm:py-6">
|
|
<h1 className="font-serif text-4xl font-bold tracking-widest text-ink-900">
|
|
先知
|
|
<span className="ml-3 align-baseline font-serif text-base font-normal italic tracking-normal text-ink-500">
|
|
Profeto
|
|
</span>
|
|
</h1>
|
|
<p className="mt-2 text-2xs tracking-[0.4em] text-ink-500">
|
|
足球比分预测 · 五路专家 · 终裁汇总
|
|
</p>
|
|
</div>
|
|
<div className="flex items-center justify-between border-b border-ink-200 py-2 text-2xs text-ink-500">
|
|
<span>{dateLine()}</span>
|
|
<Link
|
|
to="/admin"
|
|
className="flex min-h-[32px] items-center gap-1.5 text-press transition-colors hover:text-press-dark"
|
|
>
|
|
<span aria-hidden="true">⚙</span>
|
|
管理后台
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<main className="mx-auto max-w-5xl px-5 py-6 sm:px-8 sm:py-8">
|
|
<Matches />
|
|
</main>
|
|
|
|
<footer className="mx-auto max-w-5xl px-5 pb-10 sm:px-8">
|
|
<div className="border-t border-ink-200 pt-3 text-center text-2xs leading-relaxed text-ink-400">
|
|
预测结果由大语言模型生成 · 仅供研究参考 · 不构成任何投注建议
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default function App() {
|
|
return (
|
|
<ErrorBoundary>
|
|
<BrowserRouter>
|
|
<Routes>
|
|
<Route path="/" element={<HomePage />} />
|
|
{adminRoutes.map(route => (
|
|
<Route key={route.path} path={route.path} element={route.element}>
|
|
{route.children.map(child => (
|
|
<Route
|
|
key={child.path ?? 'index'}
|
|
index={child.index}
|
|
path={child.path}
|
|
element={child.element}
|
|
/>
|
|
))}
|
|
</Route>
|
|
))}
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
|
</Routes>
|
|
</BrowserRouter>
|
|
</ErrorBoundary>
|
|
)
|
|
}
|