refactor(dashboard): remove Pyramid and align activity charts
This commit is contained in:
+18
-147
@@ -3,9 +3,7 @@ import {
|
||||
Banner,
|
||||
Button,
|
||||
Card,
|
||||
Input,
|
||||
Spin,
|
||||
Table,
|
||||
Tag,
|
||||
Toast,
|
||||
Tooltip,
|
||||
@@ -14,9 +12,7 @@ import {
|
||||
BarChart3,
|
||||
CalendarDays,
|
||||
Clock3,
|
||||
Layers3,
|
||||
RefreshCw,
|
||||
Search,
|
||||
Send,
|
||||
ShieldCheck,
|
||||
} from "lucide-react";
|
||||
@@ -24,14 +20,6 @@ import { api, post } from "../api";
|
||||
import type { Account, Job } from "../types";
|
||||
import "./home.css";
|
||||
|
||||
type PyramidRow = {
|
||||
region: string;
|
||||
delay: number;
|
||||
category_id: string;
|
||||
category_name: string;
|
||||
value: number | null;
|
||||
};
|
||||
type PyramidSnapshot = { items: PyramidRow[]; fetched_at: string };
|
||||
type ActivityDay = { date: string; count: number | null };
|
||||
type ActivitySnapshot = {
|
||||
items: ActivityDay[];
|
||||
@@ -108,7 +96,6 @@ export function HomePage({
|
||||
const [sending, setSending] = useState(false);
|
||||
const [verificationId, setVerificationId] = useState<string | null>(null);
|
||||
const [verificationError, setVerificationError] = useState("");
|
||||
const [search, setSearch] = useState("");
|
||||
useEffect(() => {
|
||||
const timer = window.setInterval(() => setNow(new Date()), 1000);
|
||||
return () => clearInterval(timer);
|
||||
@@ -128,11 +115,6 @@ export function HomePage({
|
||||
connected,
|
||||
revision,
|
||||
);
|
||||
const multipliers = useResource<PyramidSnapshot>(
|
||||
"/dashboard/pyramid-multipliers",
|
||||
connected,
|
||||
revision,
|
||||
);
|
||||
const verification = jobs.find((job) => job.id === verificationId);
|
||||
const authRunning = jobs.some(
|
||||
(job) =>
|
||||
@@ -166,21 +148,6 @@ export function HomePage({
|
||||
setSending(false);
|
||||
}
|
||||
}
|
||||
const eligible = (multipliers.data?.items ?? [])
|
||||
.filter((row) => row.value !== null && row.value > 1)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
b.value! - a.value! ||
|
||||
a.region.localeCompare(b.region) ||
|
||||
a.delay - b.delay ||
|
||||
a.category_id.localeCompare(b.category_id),
|
||||
);
|
||||
const query = search.trim().toLowerCase();
|
||||
const rows = eligible.filter((row) =>
|
||||
`${row.region} D${row.delay} ${row.category_id} ${row.category_name}`
|
||||
.toLowerCase()
|
||||
.includes(query),
|
||||
);
|
||||
const submittedToday =
|
||||
submissions.data?.today === today
|
||||
? submissions.data.items.find((day) => day.date === today)?.count
|
||||
@@ -191,8 +158,6 @@ export function HomePage({
|
||||
(sum, day) => sum + day.count!,
|
||||
0,
|
||||
);
|
||||
const unknownMultipliers =
|
||||
multipliers.data?.items.filter((row) => row.value === null).length ?? 0;
|
||||
|
||||
return (
|
||||
<section className="home-page" aria-label="首页看板">
|
||||
@@ -286,34 +251,26 @@ export function HomePage({
|
||||
}
|
||||
loading={simulations.loading}
|
||||
/>
|
||||
<Metric
|
||||
label="Pyramid 加成类别"
|
||||
icon={<Layers3 size={18} aria-hidden="true" />}
|
||||
value={multipliers.data ? eligible.length : null}
|
||||
unit="类"
|
||||
hint="当前乘数 > 1 的地区 / 延迟 / 类别"
|
||||
loading={multipliers.loading}
|
||||
/>
|
||||
</div>
|
||||
<Card
|
||||
className="home-card home-calendar-card"
|
||||
title={
|
||||
<PanelTitle
|
||||
icon={<CalendarDays size={18} aria-hidden="true" />}
|
||||
title="Alpha 提交日历"
|
||||
/>
|
||||
}
|
||||
headerExtraContent={<Tag>近 26 周</Tag>}
|
||||
>
|
||||
<ResourceContent
|
||||
state={submissions}
|
||||
connected={connected}
|
||||
name="提交日历"
|
||||
>
|
||||
{submissions.data && <SubmissionCalendar data={submissions.data} />}
|
||||
</ResourceContent>
|
||||
</Card>
|
||||
<div className="home-panels">
|
||||
<Card
|
||||
className="home-card home-calendar-card"
|
||||
title={
|
||||
<PanelTitle
|
||||
icon={<CalendarDays size={18} aria-hidden="true" />}
|
||||
title="Alpha 提交日历"
|
||||
/>
|
||||
}
|
||||
headerExtraContent={<Tag>近 26 周</Tag>}
|
||||
>
|
||||
<ResourceContent
|
||||
state={submissions}
|
||||
connected={connected}
|
||||
name="提交日历"
|
||||
>
|
||||
{submissions.data && <SubmissionCalendar data={submissions.data} />}
|
||||
</ResourceContent>
|
||||
</Card>
|
||||
<Card
|
||||
className="home-card"
|
||||
title={
|
||||
@@ -332,92 +289,6 @@ export function HomePage({
|
||||
{simulations.data && <SimulationChart data={simulations.data} />}
|
||||
</ResourceContent>
|
||||
</Card>
|
||||
<Card
|
||||
className="home-card home-pyramid-card"
|
||||
title={
|
||||
<PanelTitle
|
||||
icon={<Layers3 size={18} aria-hidden="true" />}
|
||||
title="Pyramid 乘数"
|
||||
/>
|
||||
}
|
||||
headerExtraContent={<Tag color="blue">乘数 > 1</Tag>}
|
||||
>
|
||||
<ResourceContent
|
||||
state={multipliers}
|
||||
connected={connected}
|
||||
name="Pyramid 乘数"
|
||||
>
|
||||
{multipliers.data && (
|
||||
<>
|
||||
<div className="home-table-tools">
|
||||
<Input
|
||||
aria-label="搜索 Pyramid 类别"
|
||||
prefix={<Search size={16} aria-hidden="true" />}
|
||||
value={search}
|
||||
onChange={setSearch}
|
||||
showClear
|
||||
placeholder="搜索地区、延迟或类别"
|
||||
/>
|
||||
<span>{rows.length} 类</span>
|
||||
</div>
|
||||
<div className="home-table-wrap">
|
||||
<Table<PyramidRow>
|
||||
dataSource={rows}
|
||||
rowKey={(row) =>
|
||||
row ? `${row.region}:${row.delay}:${row.category_id}` : ""
|
||||
}
|
||||
pagination={false}
|
||||
size="small"
|
||||
sticky
|
||||
empty={
|
||||
eligible.length
|
||||
? "没有匹配的 Pyramid 类别"
|
||||
: "当前没有乘数大于 1 的类别"
|
||||
}
|
||||
columns={[
|
||||
{
|
||||
title: "数据类别",
|
||||
dataIndex: "category_name",
|
||||
render: (_, row) => (
|
||||
<div className="home-category">
|
||||
<strong>{row.category_name}</strong>
|
||||
<small>{row.category_id}</small>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{ title: "地区", dataIndex: "region", width: 68 },
|
||||
{
|
||||
title: "延迟",
|
||||
key: "delay",
|
||||
width: 58,
|
||||
render: (_, row) => `D${row.delay}`,
|
||||
},
|
||||
{
|
||||
title: "乘数",
|
||||
key: "value",
|
||||
width: 80,
|
||||
align: "right",
|
||||
render: (_, row) => (
|
||||
<Tag color="blue">
|
||||
{row.value?.toLocaleString("zh-CN")}×
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<p className="home-footnote">
|
||||
按乘数从高到低排列
|
||||
{unknownMultipliers
|
||||
? ` · ${unknownMultipliers} 类乘数未知,未列入`
|
||||
: ""}{" "}
|
||||
· 更新于 {easternTime(new Date(multipliers.data.fetched_at))}{" "}
|
||||
美东
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</ResourceContent>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
}
|
||||
.home-metrics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
@@ -107,14 +107,11 @@
|
||||
color: var(--muted);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.home-calendar-card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.home-panels {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
align-items: stretch;
|
||||
}
|
||||
.home-connect {
|
||||
display: flex;
|
||||
@@ -170,15 +167,15 @@
|
||||
.home-calendar {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
min-width: 550px;
|
||||
min-width: 510px;
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.home-weekdays {
|
||||
display: grid;
|
||||
grid-template-rows: repeat(7, 1fr);
|
||||
gap: 5px;
|
||||
padding-top: 25px;
|
||||
gap: 4px;
|
||||
padding-top: 24px;
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
@@ -188,15 +185,17 @@
|
||||
}
|
||||
.home-calendar-weeks {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: minmax(14px, 1fr);
|
||||
gap: 5px;
|
||||
gap: 4px;
|
||||
flex: 1;
|
||||
}
|
||||
.home-calendar-week {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
grid-template-rows: 20px repeat(7, 1fr);
|
||||
gap: 5px;
|
||||
gap: 4px;
|
||||
}
|
||||
.home-month {
|
||||
color: var(--muted);
|
||||
@@ -282,32 +281,6 @@ body[theme-mode="dark"] .heat-4 {
|
||||
.home-legend > span {
|
||||
margin: 0 4px;
|
||||
}
|
||||
.home-table-tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.home-table-tools > span {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.home-table-wrap {
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
.home-category {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.home-category strong {
|
||||
font-weight: 400;
|
||||
}
|
||||
.home-category small {
|
||||
display: block;
|
||||
margin-top: 3px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.home-footnote {
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
|
||||
Reference in New Issue
Block a user