开放多项目大屏免登录访问
需求描述:/admin/display 需要无需管理员登录即可直接查看多项目公开运行状态。 实现思路:新增公开字段白名单接口与独立大屏页面,移除该路由的管理员会话依赖,同时保留 /api/admin/overview 的鉴权并补充隐私、路由和页面回归测试。 验证:Go 全量测试通过;前端 18 个测试文件共 59 项通过,TypeScript 检查通过。
This commit is contained in:
40
web/src/pages/PublicDisplayCenterPage.tsx
Normal file
40
web/src/pages/PublicDisplayCenterPage.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { api } from "../api";
|
||||
import { FeedbackBanner, FreshnessBanner, LoadingState } from "../components/Feedback";
|
||||
import { usePollingResource } from "../hooks/usePollingResource";
|
||||
import { isTimestampStale } from "../lib/format";
|
||||
import { DisplayCenter } from "./AdminPage";
|
||||
|
||||
export function PublicDisplayCenterPage() {
|
||||
const resource = usePollingResource((signal) => api.displayOverview(signal), { intervalMs: 5_000 });
|
||||
const data = resource.data;
|
||||
const stale = Boolean(data) && isTimestampStale(resource.lastClientSuccessAt, 30_000);
|
||||
|
||||
return (
|
||||
<div className="app-shell app-shell--admin app-shell--no-primary-action">
|
||||
<a className="skip-link" href="#main-content">跳到主要内容</a>
|
||||
<header className="app-header">
|
||||
<div className="brand-lockup" aria-label="景区排队叫号系统">
|
||||
<span className="brand-logo-frame" aria-hidden="true"><img className="brand-logo" src="/xiaoqikong-logo.jpg" alt="" /></span>
|
||||
<span className="brand-lockup__text"><strong>景区排队叫号系统</strong></span>
|
||||
</div>
|
||||
<div className="account-menu"><span><strong>大屏中心</strong></span></div>
|
||||
</header>
|
||||
<main id="main-content" className="app-main">
|
||||
<section className="admin-content" aria-label="公开大屏内容">
|
||||
{resource.loading && !data ? <LoadingState label="正在汇总项目状态" /> : null}
|
||||
{resource.error && !data ? (
|
||||
<FeedbackBanner tone="danger" title="大屏数据暂时不可用" action={<button className="button button--secondary button--small" onClick={resource.refresh}>重试</button>}>
|
||||
{resource.error.message}
|
||||
</FeedbackBanner>
|
||||
) : null}
|
||||
{data ? (
|
||||
<>
|
||||
<FreshnessBanner offline={resource.offline} stale={stale} timestamp={resource.lastClientSuccessAt} refreshing={resource.refreshing} errorMessage={resource.error?.message} onRetry={resource.refresh} />
|
||||
<DisplayCenter projects={data.projects} />
|
||||
</>
|
||||
) : null}
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user