update:css样式拆分
This commit is contained in:
@@ -1,8 +1,19 @@
|
||||
import Icon from "../../components/common/Icon";
|
||||
import { useAuth } from "../../context/AuthContext";
|
||||
|
||||
import "../../styles/admin.css";
|
||||
import "../../styles/dashboard.css";
|
||||
const TREND_VALUES = [38, 55, 44, 73, 61, 86, 78] as const;
|
||||
const TREND_LABELS = ["周一", "周二", "周三", "周四", "周五", "周六", "今天"] as const;
|
||||
|
||||
const ACTIVITY_ROWS = [
|
||||
["数据探索.ipynb 发布稳定版本 v3.0", "张三", "成功", "16:42"],
|
||||
["每日模型训练流程完成调度运行", "Scheduler", "成功", "15:25"],
|
||||
["批量预测.py 更新工作副本", "王五", "已同步", "14:18"],
|
||||
["风险验证流程完成 DAG 校验", "李四", "成功", "11:06"],
|
||||
] as const;
|
||||
|
||||
function LegendDot({ className }: { className: string }) {
|
||||
return <i className={`inline-block size-[7px] rounded-full ${className}`} />;
|
||||
}
|
||||
|
||||
export function DashboardPage({
|
||||
scriptCount,
|
||||
@@ -15,71 +26,217 @@ export function DashboardPage({
|
||||
}) {
|
||||
const { user, currentWorkspace } = useAuth();
|
||||
const isSystemAdmin = user?.is_system_admin ?? false;
|
||||
const notebookCount = Math.max(1, Math.round(scriptCount * 0.67));
|
||||
const pythonCount = Math.max(0, scriptCount - Math.round(scriptCount * 0.67));
|
||||
|
||||
return (
|
||||
<section className="dashboard-page">
|
||||
<div className="dashboard-hero">
|
||||
<section className="h-full overflow-auto bg-bg p-6">
|
||||
<div className="dashboard-hero-shell flex items-center justify-between rounded-xl px-[34px] py-[34px] text-white shadow-[0_12px_30px_rgb(19_80_137/18%)]">
|
||||
<div>
|
||||
<span>MODEL DEVELOPMENT PLATFORM</span>
|
||||
<h2>下午好,{user?.display_name ?? "用户"}</h2>
|
||||
<p>
|
||||
<span className="text-[10px] tracking-[0.12em] opacity-80">
|
||||
MODEL DEVELOPMENT PLATFORM
|
||||
</span>
|
||||
<h2 className="my-2 mb-[5px] text-[25px]">
|
||||
下午好,{user?.display_name ?? "用户"}
|
||||
</h2>
|
||||
<p className="m-0 text-xs opacity-90">
|
||||
当前位于 {currentWorkspace?.workspace_name ?? "(未选择 Workspace)"}
|
||||
,可以继续构建脚本或配置调度。
|
||||
</p>
|
||||
</div>
|
||||
<span className="dashboard-hero__badge">{online ? "服务正常" : "服务连接中"}</span>
|
||||
<span className="rounded-[20px] bg-white/16 px-3 py-2 text-sm">
|
||||
{online ? "服务正常" : "服务连接中"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="dashboard-metrics">
|
||||
<article><Icon name="script" /><span><b>{scriptCount}</b><small>工作副本</small></span></article>
|
||||
<article><Icon name="workspace" /><span><b>2</b><small>Workspace</small></span></article>
|
||||
<article><Icon name="settings" /><span><b>4</b><small>平台用户</small></span></article>
|
||||
<article><Icon name="check" /><span><b>{online ? "正常" : "检查中"}</b><small>平台状态</small></span></article>
|
||||
|
||||
<div className="mt-[18px] grid grid-cols-4 gap-3.5">
|
||||
{[
|
||||
{ icon: "script" as const, value: scriptCount, label: "工作副本" },
|
||||
{ icon: "workspace" as const, value: 2, label: "Workspace" },
|
||||
{ icon: "settings" as const, value: 4, label: "平台用户" },
|
||||
{
|
||||
icon: "check" as const,
|
||||
value: online ? "正常" : "检查中",
|
||||
label: "平台状态",
|
||||
},
|
||||
].map((item) => (
|
||||
<article
|
||||
key={item.label}
|
||||
className="flex items-center gap-3.5 rounded-[9px] border border-[#e0e8ef] bg-white p-5"
|
||||
>
|
||||
<span className="text-brand">
|
||||
<Icon name={item.icon} />
|
||||
</span>
|
||||
<span className="flex flex-col">
|
||||
<b className="text-[21px] text-[#20364c]">{item.value}</b>
|
||||
<small className="text-[#8796a6]">{item.label}</small>
|
||||
</span>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
<div className="dashboard-actions">
|
||||
<button type="button" onClick={() => onNavigate("scripts")}><Icon name="script" />构建脚本</button>
|
||||
<button type="button" onClick={() => onNavigate("schedules")}><Icon name="schedule" />调度配置</button>
|
||||
|
||||
<div className="mt-[18px] flex gap-3">
|
||||
<button
|
||||
type="button"
|
||||
className="flex cursor-pointer items-center gap-2 rounded-[7px] border border-[#d8e4ef] bg-white px-[18px] py-[13px] text-[#346587]"
|
||||
onClick={() => onNavigate("scripts")}
|
||||
>
|
||||
<Icon name="script" />
|
||||
构建脚本
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="flex cursor-pointer items-center gap-2 rounded-[7px] border border-[#d8e4ef] bg-white px-[18px] py-[13px] text-[#346587]"
|
||||
onClick={() => onNavigate("schedules")}
|
||||
>
|
||||
<Icon name="schedule" />
|
||||
调度配置
|
||||
</button>
|
||||
{isSystemAdmin && (
|
||||
<button type="button" onClick={() => onNavigate("system")}><Icon name="settings" />系统管理</button>
|
||||
<button
|
||||
type="button"
|
||||
className="flex cursor-pointer items-center gap-2 rounded-[7px] border border-[#d8e4ef] bg-white px-[18px] py-[13px] text-[#346587]"
|
||||
onClick={() => onNavigate("system")}
|
||||
>
|
||||
<Icon name="settings" />
|
||||
系统管理
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="dashboard-grid">
|
||||
<section className="dashboard-panel dashboard-panel--trend">
|
||||
<header><div><span>运行趋势</span><h3>近 7 天调度执行</h3></div><b>成功率 92.6%</b></header>
|
||||
<div className="trend-chart">
|
||||
{[38, 55, 44, 73, 61, 86, 78].map((value, index) => (
|
||||
<div className="trend-column" key={index}>
|
||||
<span className="trend-column__value">{Math.round(value / 7)}</span>
|
||||
<i style={{ height: `${value}%` }} />
|
||||
<small>{["周一", "周二", "周三", "周四", "周五", "周六", "今天"][index]}</small>
|
||||
|
||||
<div className="mt-[18px] grid gap-3.5 pb-[25px] max-[1200px]:grid-cols-1 min-[1201px]:grid-cols-[minmax(0,1.6fr)_minmax(310px,0.9fr)]">
|
||||
<section className="rounded-[10px] border border-[#dfe7ee] bg-white shadow-[0_5px_16px_rgb(33_65_97/5%)]">
|
||||
<header className="flex items-center justify-between border-b border-line-soft px-5 py-[17px]">
|
||||
<div>
|
||||
<span className="text-[9px] font-extrabold tracking-[0.09em] text-[#7890a6]">
|
||||
运行趋势
|
||||
</span>
|
||||
<h3 className="mt-1 text-sm text-[#263b50]">近 7 天调度执行</h3>
|
||||
</div>
|
||||
<b className="rounded-[13px] bg-[#e8f8f1] px-[9px] py-[5px] text-[10px] text-[#16855a]">
|
||||
成功率 92.6%
|
||||
</b>
|
||||
</header>
|
||||
<div className="trend-chart-bg flex h-[190px] items-end gap-[18px] px-7 pb-[17px] pt-[26px]">
|
||||
{TREND_VALUES.map((value, index) => (
|
||||
<div
|
||||
className="flex h-full flex-1 flex-col items-center justify-end gap-[5px]"
|
||||
key={TREND_LABELS[index]}
|
||||
>
|
||||
<span className="text-[9px] text-[#7890a3]">
|
||||
{Math.round(value / 7)}
|
||||
</span>
|
||||
<i
|
||||
className="block min-h-3 w-[min(36px,72%)] rounded-t-[5px] rounded-b-[2px] bg-gradient-to-b from-[#49a0eb] to-[#207bd1] shadow-[0_4px_9px_rgb(32_123_209/18%)]"
|
||||
style={{ height: `${value}%` }}
|
||||
/>
|
||||
<small className="text-[9px] text-[#7890a3]">
|
||||
{TREND_LABELS[index]}
|
||||
</small>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<footer><span><i className="legend-dot is-success" />成功 75</span><span><i className="legend-dot is-failed" />失败 6</span></footer>
|
||||
<footer className="flex justify-center gap-[22px] p-2.5 text-[9px] text-[#708397]">
|
||||
<span className="flex items-center gap-[5px]">
|
||||
<LegendDot className="bg-[#27b87c]" />
|
||||
成功 75
|
||||
</span>
|
||||
<span className="flex items-center gap-[5px]">
|
||||
<LegendDot className="bg-[#ed7777]" />
|
||||
失败 6
|
||||
</span>
|
||||
</footer>
|
||||
</section>
|
||||
<section className="dashboard-panel dashboard-panel--donut">
|
||||
<header><div><span>脚本资产</span><h3>类型分布</h3></div></header>
|
||||
<div className="donut-layout">
|
||||
<div className="donut-chart"><span><b>{scriptCount}</b><small>全部脚本</small></span></div>
|
||||
<div className="donut-legend">
|
||||
<span><i className="legend-dot is-notebook" /><b>Notebook</b><small>{Math.max(1, Math.round(scriptCount * .67))} 个 · 67%</small></span>
|
||||
<span><i className="legend-dot is-python" /><b>Python</b><small>{Math.max(0, scriptCount - Math.round(scriptCount * .67))} 个 · 33%</small></span>
|
||||
<span><i className="legend-dot is-version" /><b>稳定版本</b><small>3 个已发布</small></span>
|
||||
|
||||
<section className="rounded-[10px] border border-[#dfe7ee] bg-white shadow-[0_5px_16px_rgb(33_65_97/5%)]">
|
||||
<header className="flex items-center justify-between border-b border-line-soft px-5 py-[17px]">
|
||||
<div>
|
||||
<span className="text-[9px] font-extrabold tracking-[0.09em] text-[#7890a6]">
|
||||
脚本资产
|
||||
</span>
|
||||
<h3 className="mt-1 text-sm text-[#263b50]">类型分布</h3>
|
||||
</div>
|
||||
</header>
|
||||
<div className="flex min-h-[226px] items-center justify-center gap-7 p-5">
|
||||
<div className="dashboard-donut relative grid size-32 shrink-0 place-items-center rounded-full">
|
||||
<span className="z-[1] flex flex-col items-center">
|
||||
<b className="text-xl text-[#273d53]">{scriptCount}</b>
|
||||
<small className="text-[8px] text-[#8a9aaa]">全部脚本</small>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-[15px]">
|
||||
{[
|
||||
{
|
||||
color: "bg-[#318de0]",
|
||||
title: "Notebook",
|
||||
detail: `${notebookCount} 个 · 67%`,
|
||||
},
|
||||
{
|
||||
color: "bg-[#72c9b0]",
|
||||
title: "Python",
|
||||
detail: `${pythonCount} 个 · 33%`,
|
||||
},
|
||||
{
|
||||
color: "bg-[#f3b75c]",
|
||||
title: "稳定版本",
|
||||
detail: "3 个已发布",
|
||||
},
|
||||
].map((item) => (
|
||||
<span
|
||||
key={item.title}
|
||||
className="grid grid-cols-[8px_1fr] items-center gap-x-[7px]"
|
||||
>
|
||||
<LegendDot className={item.color} />
|
||||
<b className="text-[10px] text-[#40566c]">{item.title}</b>
|
||||
<small className="col-start-2 text-[8px] text-[#8a9baa]">
|
||||
{item.detail}
|
||||
</small>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="dashboard-panel dashboard-panel--activity">
|
||||
<header><div><span>ACTIVITY</span><h3>最近平台活动</h3></div><button type="button">查看全部</button></header>
|
||||
<div className="activity-table">
|
||||
<div className="activity-table__head"><span>操作内容</span><span>执行人</span><span>状态</span><span>时间</span></div>
|
||||
{[
|
||||
["数据探索.ipynb 发布稳定版本 v3.0", "张三", "成功", "16:42"],
|
||||
["每日模型训练流程完成调度运行", "Scheduler", "成功", "15:25"],
|
||||
["批量预测.py 更新工作副本", "王五", "已同步", "14:18"],
|
||||
["风险验证流程完成 DAG 校验", "李四", "成功", "11:06"],
|
||||
].map((row) => (
|
||||
<div className="activity-row" key={row[0]}>
|
||||
<span><i className="activity-icon"><Icon name="check" size={13} /></i>{row[0]}</span>
|
||||
<span>{row[1]}</span><span><b>{row[2]}</b></span><span>{row[3]}</span>
|
||||
|
||||
<section className="col-span-full rounded-[10px] border border-[#dfe7ee] bg-white shadow-[0_5px_16px_rgb(33_65_97/5%)] max-[1200px]:col-auto">
|
||||
<header className="flex items-center justify-between border-b border-line-soft px-5 py-[17px]">
|
||||
<div>
|
||||
<span className="text-[9px] font-extrabold tracking-[0.09em] text-[#7890a6]">
|
||||
ACTIVITY
|
||||
</span>
|
||||
<h3 className="mt-1 text-sm text-[#263b50]">最近平台活动</h3>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="border-0 bg-transparent text-[10px] text-[#257bcb]"
|
||||
>
|
||||
查看全部
|
||||
</button>
|
||||
</header>
|
||||
<div>
|
||||
<div className="grid grid-cols-[2fr_0.7fr_0.55fr_0.5fr] items-center gap-[15px] bg-[#f7f9fb] px-5 py-[11px] text-[9px] font-bold text-[#8595a5]">
|
||||
<span>操作内容</span>
|
||||
<span>执行人</span>
|
||||
<span>状态</span>
|
||||
<span>时间</span>
|
||||
</div>
|
||||
{ACTIVITY_ROWS.map((row) => (
|
||||
<div
|
||||
className="grid grid-cols-[2fr_0.7fr_0.55fr_0.5fr] items-center gap-[15px] border-t border-line-soft px-5 py-[11px] text-[10px] text-[#607488]"
|
||||
key={row[0]}
|
||||
>
|
||||
<span className="flex items-center gap-[9px] text-[#344c63]">
|
||||
<i className="grid size-[25px] place-items-center rounded-md bg-[#eaf4ff] text-[#277fcc]">
|
||||
<Icon name="check" size={13} />
|
||||
</i>
|
||||
{row[0]}
|
||||
</span>
|
||||
<span>{row[1]}</span>
|
||||
<span>
|
||||
<b className="rounded-[10px] bg-[#e9f8f2] px-[7px] py-[3px] text-[9px] text-[#16855a]">
|
||||
{row[2]}
|
||||
</b>
|
||||
</span>
|
||||
<span>{row[3]}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user