feat: refine website gateway os hero

This commit is contained in:
boos
2026-06-06 18:59:10 +08:00
parent d5babf5f3f
commit 00b3365f5a
3 changed files with 276 additions and 2 deletions
+43 -1
View File
@@ -39,7 +39,33 @@ export function BossAiMotion({ children }: BossAiMotionProps) {
gsap.set(".boot-screen", { display: "none" }); gsap.set(".boot-screen", { display: "none" });
}); });
matchMedia.add("(prefers-reduced-motion: no-preference)", () => { matchMedia.add("(prefers-reduced-motion: no-preference) and (max-width: 640px)", () => {
gsap.set("[data-motion], [data-motion-dot], [data-motion-orbit], [data-motion-line]", {
autoAlpha: 1,
clearProps: "transform",
});
gsap.set(".boot-screen", { display: "none" });
gsap.to("[data-motion-dot]", {
scale: 1.14,
autoAlpha: 0.76,
duration: 1.4,
ease: "sine.inOut",
repeat: -1,
yoyo: true,
stagger: 0.2,
});
gsap.to("[data-motion-line]", {
strokeDashoffset: -120,
duration: 6,
ease: "none",
repeat: -1,
stagger: 0.24,
});
});
matchMedia.add("(prefers-reduced-motion: no-preference) and (min-width: 641px)", () => {
const heroTitle = root.querySelector<HTMLElement>(".hero-copy h1"); const heroTitle = root.querySelector<HTMLElement>(".hero-copy h1");
const splitTitle = heroTitle const splitTitle = heroTitle
? SplitText.create(heroTitle, { ? SplitText.create(heroTitle, {
@@ -73,9 +99,11 @@ export function BossAiMotion({ children }: BossAiMotionProps) {
"-=0.28", "-=0.28",
) )
.from(".hero-copy p", { y: 18, duration: 0.7 }, "-=0.5") .from(".hero-copy p", { y: 18, duration: 0.7 }, "-=0.5")
.from("[data-motion='signal']", { y: 10, duration: 0.42, stagger: 0.06 }, "-=0.42")
.from(".hero-actions > *", { y: 12, duration: 0.46, stagger: 0.08 }, "-=0.42") .from(".hero-actions > *", { y: 12, duration: 0.46, stagger: 0.08 }, "-=0.42")
.from(".hero-proof > div", { y: 12, duration: 0.5, stagger: 0.07 }, "-=0.28") .from(".hero-proof > div", { y: 12, duration: 0.5, stagger: 0.07 }, "-=0.28")
.from("[data-motion='hero-console']", { y: 26, rotateX: 4, duration: 0.9 }, "-=0.78") .from("[data-motion='hero-console']", { y: 26, rotateX: 4, duration: 0.9 }, "-=0.78")
.from("[data-motion='exchange-step']", { y: 12, duration: 0.48, stagger: 0.06 }, "-=0.58")
.from("[data-motion='route-row']", { x: 14, duration: 0.55, stagger: 0.08 }, "-=0.48") .from("[data-motion='route-row']", { x: 14, duration: 0.55, stagger: 0.08 }, "-=0.48")
.from("[data-motion='node']", { scale: 0.96, duration: 0.45, stagger: 0.08 }, "-=0.3"); .from("[data-motion='node']", { scale: 0.96, duration: 0.45, stagger: 0.08 }, "-=0.3");
@@ -107,6 +135,7 @@ export function BossAiMotion({ children }: BossAiMotionProps) {
const heroSection = root.querySelector<HTMLElement>(".hero-section"); const heroSection = root.querySelector<HTMLElement>(".hero-section");
const heroConsole = root.querySelector<HTMLElement>(".hero-console"); const heroConsole = root.querySelector<HTMLElement>(".hero-console");
const routeRows = gsap.utils.toArray<HTMLElement>(".route-row", root); const routeRows = gsap.utils.toArray<HTMLElement>(".route-row", root);
const exchangeSteps = gsap.utils.toArray<HTMLElement>(".exchange-step", root);
const consoleTiles = gsap.utils.toArray<HTMLElement>(".console-metrics > div, .mini-grid > div", root); const consoleTiles = gsap.utils.toArray<HTMLElement>(".console-metrics > div, .mini-grid > div", root);
if (heroSection && heroConsole) { if (heroSection && heroConsole) {
@@ -155,6 +184,19 @@ export function BossAiMotion({ children }: BossAiMotionProps) {
}, },
}); });
gsap.to(exchangeSteps, {
y: (index) => -5 + index * 1.4,
autoAlpha: (index) => 0.98 - index * 0.02,
ease: "none",
stagger: { each: 0.035, from: "start" },
scrollTrigger: {
trigger: heroConsole,
start: "top 80%",
end: "center 18%",
scrub: true,
},
});
gsap.to(consoleTiles, { gsap.to(consoleTiles, {
y: -12, y: -12,
autoAlpha: 0.9, autoAlpha: 0.9,
+181 -1
View File
@@ -606,6 +606,54 @@ a {
font-size: 12px; font-size: 12px;
} }
.hero-system-strip {
width: min(100%, 640px);
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 8px;
}
.hero-system-strip > div {
min-height: 44px;
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 8px;
border: 1px solid var(--line);
border-radius: 999px;
background: var(--surface);
padding: 0 12px;
box-shadow: inset 0 1px 0 var(--surface-highlight);
}
.hero-system-strip span,
.card-signal span {
width: 7px;
height: 7px;
border-radius: 999px;
background: var(--acid);
box-shadow: 0 0 18px rgba(215, 255, 77, 0.48);
}
.hero-system-strip strong {
min-width: 0;
overflow: hidden;
color: var(--text);
font-family: var(--font-geist-mono), monospace;
font-size: 11px;
font-weight: 780;
text-overflow: ellipsis;
white-space: nowrap;
}
.hero-system-strip em {
color: var(--faint);
font-family: var(--font-geist-mono), monospace;
font-size: 10px;
font-style: normal;
white-space: nowrap;
}
.hero-actions { .hero-actions {
gap: 12px; gap: 12px;
padding-top: 4px; padding-top: 4px;
@@ -734,6 +782,8 @@ a {
} }
.console-bar span, .console-bar span,
.exchange-step small,
.exchange-step span,
.route-row em, .route-row em,
.console-metrics span, .console-metrics span,
.mini-grid span, .mini-grid span,
@@ -746,6 +796,74 @@ a {
font-style: normal; font-style: normal;
} }
.exchange-chain {
position: relative;
z-index: 4;
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px;
margin-top: 12px;
}
.exchange-chain::before {
position: absolute;
left: 7%;
right: 7%;
top: 50%;
z-index: 0;
height: 1px;
content: "";
background: linear-gradient(90deg, transparent, rgba(183, 237, 42, 0.38), rgba(24, 185, 199, 0.28), transparent);
}
.exchange-step {
position: relative;
z-index: 1;
min-height: 74px;
display: grid;
align-content: center;
gap: 6px;
border: 1px solid var(--line);
border-radius: 18px;
background: var(--surface);
padding: 12px;
box-shadow: inset 0 1px 0 var(--surface-highlight);
}
.exchange-step::after {
position: absolute;
top: 50%;
right: -9px;
width: 9px;
height: 9px;
border-top: 1px solid rgba(183, 237, 42, 0.5);
border-right: 1px solid rgba(183, 237, 42, 0.5);
content: "";
transform: translateY(-50%) rotate(45deg);
}
.exchange-step:last-child::after {
display: none;
}
.exchange-step small {
font-family: var(--font-geist-mono), monospace;
}
.exchange-step strong {
min-width: 0;
overflow: hidden;
color: var(--text);
font-size: 12px;
letter-spacing: -0.02em;
text-overflow: ellipsis;
white-space: nowrap;
}
.exchange-step span {
font-family: var(--font-geist-mono), monospace;
}
.route-list { .route-list {
position: relative; position: relative;
z-index: 4; z-index: 4;
@@ -1040,6 +1158,7 @@ a {
} }
.capability-card { .capability-card {
position: relative;
min-height: 260px; min-height: 260px;
display: grid; display: grid;
align-content: space-between; align-content: space-between;
@@ -1048,6 +1167,28 @@ a {
border-radius: var(--radius); border-radius: var(--radius);
background: var(--card-gradient); background: var(--card-gradient);
padding: 20px; padding: 20px;
overflow: hidden;
}
.capability-card::before {
position: absolute;
inset: 0;
pointer-events: none;
content: "";
background:
linear-gradient(120deg, transparent 0 42%, rgba(183, 237, 42, 0.14) 48%, transparent 56%),
radial-gradient(circle at 80% 16%, rgba(24, 185, 199, 0.14), transparent 34%);
opacity: 0;
transition: opacity 180ms ease;
}
.capability-card:hover::before {
opacity: 1;
}
.capability-card > * {
position: relative;
z-index: 1;
} }
.card-top { .card-top {
@@ -1069,12 +1210,37 @@ a {
font-size: 13px; font-size: 13px;
} }
.card-signal {
width: fit-content;
display: inline-flex;
align-items: center;
gap: 8px;
border: 1px solid rgba(183, 237, 42, 0.22);
border-radius: 999px;
background: var(--surface-muted);
color: var(--muted);
padding: 7px 10px;
font-family: var(--font-geist-mono), monospace;
font-size: 11px;
}
.capability-card h3 { .capability-card h3 {
margin: 0 0 12px; margin: 0 0 12px;
font-size: 22px; font-size: 22px;
letter-spacing: -0.04em; letter-spacing: -0.04em;
} }
.card-port {
border-top: 1px solid var(--line);
padding-top: 14px;
}
.card-port code {
color: var(--faint);
font-family: var(--font-geist-mono), monospace;
font-size: 11px;
}
.capability-card p, .capability-card p,
.section-heading.split p, .section-heading.split p,
.endpoint-card p, .endpoint-card p,
@@ -1478,6 +1644,15 @@ a {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
} }
.exchange-chain {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.exchange-chain::before,
.exchange-step::after {
display: none;
}
.section-heading.split, .section-heading.split,
.endpoint-grid { .endpoint-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
@@ -1535,16 +1710,21 @@ a {
} }
.hero-proof, .hero-proof,
.hero-system-strip,
.console-metrics { .console-metrics {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.hero-console { .hero-console {
min-height: 520px; min-height: 680px;
border-radius: 26px; border-radius: 26px;
padding: 14px; padding: 14px;
} }
.exchange-chain {
grid-template-columns: 1fr;
}
.route-row { .route-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
align-items: start; align-items: start;
+52
View File
@@ -8,24 +8,32 @@ const platformItems = [
eyebrow: "Gateway", eyebrow: "Gateway",
body: "OpenAI、Claude Messages、Gemini、方舟、图像、视频和语音接口统一到一套入口。", body: "OpenAI、Claude Messages、Gemini、方舟、图像、视频和语音接口统一到一套入口。",
metric: "/v1", metric: "/v1",
signal: "Ingress",
port: "chat · messages · media",
}, },
{ {
title: "智能模型路由", title: "智能模型路由",
eyebrow: "Routing", eyebrow: "Routing",
body: "按站点、账号、令牌、模型能力和失败冷却自动调度,保留真实日志与计费口径。", body: "按站点、账号、令牌、模型能力和失败冷却自动调度,保留真实日志与计费口径。",
metric: "Auto", metric: "Auto",
signal: "Routing",
port: "site · account · token",
}, },
{ {
title: "Comfy 工作流", title: "Comfy 工作流",
eyebrow: "Workflow", eyebrow: "Workflow",
body: "保留完整版 ComfyUI 前端习惯,接入 Cloud、RunningHub、External 或 BoosAPI 执行器。", body: "保留完整版 ComfyUI 前端习惯,接入 Cloud、RunningHub、External 或 BoosAPI 执行器。",
metric: "Canvas", metric: "Canvas",
signal: "Studio",
port: "cloud · rh · external",
}, },
{ {
title: "创作应用生产", title: "创作应用生产",
eyebrow: "Studio", eyebrow: "Studio",
body: "生图助手、视频助手、数字人、短视频工厂和工作空间复用同一套模型资产。", body: "生图助手、视频助手、数字人、短视频工厂和工作空间复用同一套模型资产。",
metric: "Media", metric: "Media",
signal: "Archive",
port: "image · video · voice",
}, },
]; ];
@@ -43,6 +51,19 @@ const routes = [
{ type: "Video", model: "doubao-seedance-2-0-260128", state: "视频队列", tone: "blue" }, { type: "Video", model: "doubao-seedance-2-0-260128", state: "视频队列", tone: "blue" },
]; ];
const systemSignals = [
{ label: "Gateway", value: "online" },
{ label: "Workflow", value: "synced" },
{ label: "Ledger", value: "recording" },
];
const exchangeSteps = [
{ label: "API Ingress", value: "/v1/*" },
{ label: "Model Router", value: "auto" },
{ label: "Creative Apps", value: "studio" },
{ label: "Workspace", value: "archive" },
];
const consoleMetrics = [ const consoleMetrics = [
{ label: "日志写入", value: "stream" }, { label: "日志写入", value: "stream" },
{ label: "计费口径", value: "token + media" }, { label: "计费口径", value: "token + media" },
@@ -171,6 +192,20 @@ function BootScreen() {
); );
} }
function HeroSystemStrip() {
return (
<div className="hero-system-strip" aria-label="BossAI 系统状态">
{systemSignals.map((signal) => (
<div data-motion="signal" key={signal.label}>
<span />
<strong>{signal.label}</strong>
<em>{signal.value}</em>
</div>
))}
</div>
);
}
function FlowGlyph() { function FlowGlyph() {
return ( return (
<svg className="flow-glyph" viewBox="0 0 520 360" aria-hidden="true"> <svg className="flow-glyph" viewBox="0 0 520 360" aria-hidden="true">
@@ -223,6 +258,15 @@ function HeroConsole() {
<span>Model Router</span> <span>Model Router</span>
<strong>GPT-5.5 + Image 2 Ready</strong> <strong>GPT-5.5 + Image 2 Ready</strong>
</div> </div>
<div className="exchange-chain" aria-label="BossAI 模型交换链路">
{exchangeSteps.map((step, index) => (
<div className="exchange-step" data-motion="exchange-step" key={step.label}>
<small>{String(index + 1).padStart(2, "0")}</small>
<strong>{step.label}</strong>
<span>{step.value}</span>
</div>
))}
</div>
<div className="route-list"> <div className="route-list">
{routes.map((route) => ( {routes.map((route) => (
<div <div
@@ -302,6 +346,7 @@ export default function Home() {
<p> <p>
BossAI 把 API 网关、智能路由、Comfy 工作流、数字人和短视频工厂收进一个清晰的运营后台,让团队用一套系统完成接入、生产、计费和交付。 BossAI 把 API 网关、智能路由、Comfy 工作流、数字人和短视频工厂收进一个清晰的运营后台,让团队用一套系统完成接入、生产、计费和交付。
</p> </p>
<HeroSystemStrip />
<div className="hero-actions"> <div className="hero-actions">
<Link className="primary-cta" href="/user/register"> <Link className="primary-cta" href="/user/register">
开始使用 开始使用
@@ -339,8 +384,15 @@ export default function Home() {
<span>{item.eyebrow}</span> <span>{item.eyebrow}</span>
<strong>{item.metric}</strong> <strong>{item.metric}</strong>
</div> </div>
<div className="card-signal" aria-hidden="true">
<span />
{item.signal}
</div>
<h3>{item.title}</h3> <h3>{item.title}</h3>
<p>{item.body}</p> <p>{item.body}</p>
<div className="card-port">
<code>{item.port}</code>
</div>
</article> </article>
))} ))}
</div> </div>