feat: redesign market-facing ui surfaces
This commit is contained in:
@@ -47,7 +47,7 @@ export default function DashboardPage() {
|
||||
<span className="header-kicker">Control overview</span>
|
||||
<h3>统一观察用户经济、模型路由和任务健康度</h3>
|
||||
<p className="muted">
|
||||
当前后台适合快速联调 MVP:前台创作流、积分系统、邀请奖励、模型供应商和任务轮询都能在这里找到对应控制面。
|
||||
后台围绕用户经济系统、模型供应商、任务状态和公共配置四条主线组织,适合持续运营而不是只做演示。
|
||||
</p>
|
||||
</div>
|
||||
<div className="dashboard-stage-grid">
|
||||
@@ -63,8 +63,8 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
<div className="dashboard-mini-card">
|
||||
<span>运行主线</span>
|
||||
<strong>本地 mock / 源码模式</strong>
|
||||
<small>适合先打磨前后台交互和管理体验。</small>
|
||||
<strong>任务执行 / 回调审计</strong>
|
||||
<small>更适合持续观察稳定性、成功率与异常链路。</small>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { startTransition, useState } from "react";
|
||||
import { ArrowRight, Blocks, Coins, Settings2, ShieldCheck } from "lucide-react";
|
||||
import { ArrowRight, Blocks, Coins, ShieldCheck } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -31,65 +31,51 @@ export default function AdminLoginPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="login-grid auth-grid-admin">
|
||||
<section className="auth-hero auth-hero-admin">
|
||||
<div className="auth-copy">
|
||||
<div className="brand-kicker">Ops Console</div>
|
||||
<h1 className="headline">把模型、价格、奖励、订单和任务链路收进一块控制台。</h1>
|
||||
<p className="subcopy">
|
||||
这轮后台视觉沿用 `MiniMax-DESIGN.md` 的轻白产品感,用更轻的卡片矩阵承载更重的运营信息,让配置、审计和异常排查更易读。
|
||||
<div className="admin-auth-page">
|
||||
<section className="admin-auth-copy">
|
||||
<span className="admin-page-kicker">OPERATIONS CONSOLE</span>
|
||||
<h1>AIVIDEO CONTROL SURFACE</h1>
|
||||
<p>
|
||||
用更克制的 dark console 管理模型、价格、订单、奖励和任务治理链路,让后台像控制面,而不是营销页。
|
||||
</p>
|
||||
<div className="auth-chip-row">
|
||||
<span className="auth-chip">Provider routing</span>
|
||||
<span className="auth-chip">Pricing control</span>
|
||||
<span className="auth-chip">Audit trail</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="showcase-stack">
|
||||
<div className="showcase-card showcase-card-hero">
|
||||
<div className="toolbar">
|
||||
<span className="status-badge tone-success">Admin access</span>
|
||||
<span className="mini-note">Operational overview</span>
|
||||
</div>
|
||||
<h3>后台只做关键决策,不做噪音堆叠</h3>
|
||||
<p className="muted">
|
||||
当前后台围绕四个维度组织:用户经济系统、模型与供应商、任务状态以及公共配置。适合直接联调 MVP。
|
||||
</p>
|
||||
</div>
|
||||
<div className="showcase-card-grid">
|
||||
<article className="showcase-card">
|
||||
|
||||
<div className="admin-auth-grid">
|
||||
<article className="admin-auth-info">
|
||||
<Blocks size={18} />
|
||||
<strong>模型控制面</strong>
|
||||
<span>平台模型、供应商模型和路由关系都在一个壳层里完成。</span>
|
||||
<strong>模型与路由</strong>
|
||||
<span>平台模型、供应商模型和绑定关系统一管理。</span>
|
||||
</article>
|
||||
<article className="showcase-card">
|
||||
<article className="admin-auth-info">
|
||||
<Coins size={18} />
|
||||
<strong>积分与价格系统</strong>
|
||||
<span>订单、兑换码、价格规则和奖励规则统一维护。</span>
|
||||
<strong>价格与资金</strong>
|
||||
<span>订单、兑换码、价格规则和奖励系统保持同一视图。</span>
|
||||
</article>
|
||||
<article className="showcase-card">
|
||||
<Settings2 size={18} />
|
||||
<strong>配置与审计</strong>
|
||||
<span>系统配置、任务回调和异常日志便于排查问题。</span>
|
||||
<article className="admin-auth-info">
|
||||
<ShieldCheck size={18} />
|
||||
<strong>审计与处置</strong>
|
||||
<span>回调日志、异常任务和系统配置更容易定位问题。</span>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="fullscreen-shell">
|
||||
<form className="auth-card auth-card-strong" onSubmit={handleSubmit}>
|
||||
<div className="auth-card-head">
|
||||
<div className="brand-kicker">AIVideo Admin</div>
|
||||
<h3>管理员登录</h3>
|
||||
<p className="muted">进入运营控制台,处理规则配置和异常链路。</p>
|
||||
<section className="admin-auth-panel">
|
||||
<form className="admin-auth-card" onSubmit={handleSubmit}>
|
||||
<div className="admin-auth-head">
|
||||
<span className="admin-page-kicker">ADMIN ACCESS</span>
|
||||
<h2>登录控制台</h2>
|
||||
<p>进入管理员界面,处理配置、审计和异常任务。</p>
|
||||
</div>
|
||||
|
||||
<div className="form-stack">
|
||||
<label className="field-label">
|
||||
用户名
|
||||
<input
|
||||
value={form.username}
|
||||
onChange={(event) =>
|
||||
setForm((previous) => ({ ...previous, username: event.target.value }))
|
||||
setForm((previous) => ({
|
||||
...previous,
|
||||
username: event.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
@@ -99,23 +85,28 @@ export default function AdminLoginPage() {
|
||||
type="password"
|
||||
value={form.password}
|
||||
onChange={(event) =>
|
||||
setForm((previous) => ({ ...previous, password: event.target.value }))
|
||||
setForm((previous) => ({
|
||||
...previous,
|
||||
password: event.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
|
||||
{error ? <div className="inline-feedback is-error">{error}</div> : null}
|
||||
|
||||
<button className="primary-button" type="submit">
|
||||
{loading ? "登录中..." : "进入后台"}
|
||||
{loading ? "SIGNING IN..." : "ENTER CONSOLE"}
|
||||
{loading ? null : <ArrowRight size={16} />}
|
||||
</button>
|
||||
<div className="auth-action-row">
|
||||
|
||||
<div className="auth-form-actions">
|
||||
<Link href="/login" className="ghost-button">
|
||||
返回用户端
|
||||
</Link>
|
||||
<div className="field-note">
|
||||
<ShieldCheck size={14} />
|
||||
默认管理员账号已由后端初始化脚本自动创建。
|
||||
</div>
|
||||
<Link href="/" className="auth-inline-link">
|
||||
返回首页
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import { DM_Sans, Outfit, Roboto_Mono } from "next/font/google";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
|
||||
export const displayFont = Outfit({
|
||||
export const displayFont = Geist({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-display",
|
||||
weight: ["500", "600", "700"],
|
||||
});
|
||||
|
||||
export const bodyFont = DM_Sans({
|
||||
export const bodyFont = Geist({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-body",
|
||||
weight: ["400", "500", "700"],
|
||||
});
|
||||
|
||||
export const monoFont = Roboto_Mono({
|
||||
export const monoFont = Geist_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-mono",
|
||||
weight: ["400", "500", "600"],
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { startTransition, useState } from "react";
|
||||
import { ArrowRight, Clapperboard, Coins, FolderKanban, Sparkles } from "lucide-react";
|
||||
import { ArrowRight, Coins, FolderKanban, ImagePlus } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -9,7 +9,10 @@ import { api, ApiError } from "@/lib/api";
|
||||
|
||||
export default function LoginPage() {
|
||||
const router = useRouter();
|
||||
const [form, setForm] = useState({ account: "demo@example.com", password: "12345678" });
|
||||
const [form, setForm] = useState({
|
||||
account: "demo@example.com",
|
||||
password: "12345678",
|
||||
});
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
@@ -28,65 +31,54 @@ export default function LoginPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="auth-grid">
|
||||
<section className="auth-hero auth-hero-studio">
|
||||
<div className="auth-copy">
|
||||
<div className="eyebrow">Creative Workbench</div>
|
||||
<h1 className="headline">从一句提示词到成片交付,把 AI 视频生产线收进一块工作台。</h1>
|
||||
<p className="subcopy">
|
||||
参考 `MiniMax-DESIGN.md` 的产品画布思路,把模型切换、素材引用、积分消耗和任务轮询组织成一组清爽的能力卡片。
|
||||
</p>
|
||||
<div className="auth-chip-row">
|
||||
<span className="auth-chip">Prompt to video</span>
|
||||
<span className="auth-chip">Capability cards</span>
|
||||
<span className="auth-chip">Realtime task polling</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="showcase-stack">
|
||||
<div className="showcase-card showcase-card-hero">
|
||||
<div className="toolbar">
|
||||
<span className="status-badge tone-success">Studio ready</span>
|
||||
<span className="mini-note">Source mode</span>
|
||||
</div>
|
||||
<h3>一次登录,接管创作链路</h3>
|
||||
<p className="muted">
|
||||
默认即可走本地 mock 供应商、SQLite 和本地存储,适合先把完整交互、任务状态和后台规则跑通。
|
||||
<div className="auth-page auth-page-user">
|
||||
<section className="auth-showcase auth-showcase-user">
|
||||
<div className="auth-showcase-copy">
|
||||
<span className="auth-showcase-kicker">AIVIDEO FOR CREATORS</span>
|
||||
<h1>把创作体验打磨成真正能面对市场的产品,而不只是一个生成入口。</h1>
|
||||
<p>
|
||||
从提示词、素材引用到任务交付与积分体系,AIVideo
|
||||
把用户真正会触达的关键环节收进同一套产品体验里。
|
||||
</p>
|
||||
</div>
|
||||
<div className="showcase-card-grid">
|
||||
<article className="showcase-card">
|
||||
<Clapperboard size={18} />
|
||||
<strong>工作台直达成片</strong>
|
||||
<span>模型、时长、比例与素材引用在同一视图完成。</span>
|
||||
|
||||
<div className="auth-showcase-grid">
|
||||
<article className="auth-showcase-card">
|
||||
<ImagePlus size={18} />
|
||||
<strong>素材先行</strong>
|
||||
<span>图片、视频、音频素材统一管理,创作时随时调用。</span>
|
||||
</article>
|
||||
<article className="showcase-card">
|
||||
<article className="auth-showcase-card">
|
||||
<FolderKanban size={18} />
|
||||
<strong>任务状态持续刷新</strong>
|
||||
<span>提交后自动轮询,成功后直接打开结果视频。</span>
|
||||
<strong>任务可追踪</strong>
|
||||
<span>生成状态、结果视频和扣费记录都能持续回看。</span>
|
||||
</article>
|
||||
<article className="showcase-card">
|
||||
<article className="auth-showcase-card">
|
||||
<Coins size={18} />
|
||||
<strong>积分链路完整</strong>
|
||||
<span>注册奖励、充值、兑换码和冻结扣费全部可见。</span>
|
||||
<strong>商业闭环</strong>
|
||||
<span>积分、充值、兑换和邀请奖励自然衔接到产品流中。</span>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="fullscreen-shell">
|
||||
<form className="auth-card auth-card-strong" onSubmit={handleSubmit}>
|
||||
<div className="auth-card-head">
|
||||
<div className="eyebrow">Welcome Back</div>
|
||||
<section className="auth-form-column">
|
||||
<form className="auth-form-card" onSubmit={handleSubmit}>
|
||||
<div className="auth-form-head">
|
||||
<span className="auth-form-kicker">Welcome Back</span>
|
||||
<h2>登录 AIVideo</h2>
|
||||
<p className="muted">继续你的创作队列、素材库和积分操作。</p>
|
||||
<p>继续你的创作项目、素材库和任务队列。</p>
|
||||
</div>
|
||||
|
||||
<div className="form-stack">
|
||||
<label className="field-label">
|
||||
账号
|
||||
<input
|
||||
value={form.account}
|
||||
onChange={(event) =>
|
||||
setForm((previous) => ({ ...previous, account: event.target.value }))
|
||||
setForm((previous) => ({
|
||||
...previous,
|
||||
account: event.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
@@ -96,23 +88,28 @@ export default function LoginPage() {
|
||||
type="password"
|
||||
value={form.password}
|
||||
onChange={(event) =>
|
||||
setForm((previous) => ({ ...previous, password: event.target.value }))
|
||||
setForm((previous) => ({
|
||||
...previous,
|
||||
password: event.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
|
||||
{error ? <div className="inline-feedback is-error">{error}</div> : null}
|
||||
|
||||
<button className="primary-button" disabled={loading} type="submit">
|
||||
{loading ? "登录中..." : "登录并进入工作台"}
|
||||
{loading ? "登录中..." : "进入创作工作台"}
|
||||
{loading ? null : <ArrowRight size={16} />}
|
||||
</button>
|
||||
<div className="auth-action-row">
|
||||
|
||||
<div className="auth-form-actions">
|
||||
<Link href="/register" className="ghost-button">
|
||||
创建账号
|
||||
</Link>
|
||||
<div className="field-note">
|
||||
<Sparkles size={14} />
|
||||
新用户注册后可按后台规则领取初始积分。
|
||||
</div>
|
||||
<Link href="/" className="auth-inline-link">
|
||||
返回首页
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,6 +1,189 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import {
|
||||
ArrowRight,
|
||||
CirclePlay,
|
||||
Coins,
|
||||
FolderKanban,
|
||||
ImagePlus,
|
||||
ShieldCheck,
|
||||
Sparkles,
|
||||
} from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
const productHighlights = [
|
||||
{
|
||||
title: "生成工作台",
|
||||
copy: "把模型、提示词、时长、比例和素材引用收进一个创作面板。",
|
||||
icon: Sparkles,
|
||||
},
|
||||
{
|
||||
title: "素材系统",
|
||||
copy: "图片、视频、音频参考素材统一入库,创作时直接调用。",
|
||||
icon: ImagePlus,
|
||||
},
|
||||
{
|
||||
title: "任务追踪",
|
||||
copy: "生成状态实时刷新,结果视频、积分消耗和任务详情一屏可见。",
|
||||
icon: FolderKanban,
|
||||
},
|
||||
{
|
||||
title: "积分与增长",
|
||||
copy: "充值、兑换码、注册奖励和邀请关系形成完整的商业闭环。",
|
||||
icon: Coins,
|
||||
},
|
||||
];
|
||||
|
||||
export default function HomePage() {
|
||||
redirect("/workspace/create");
|
||||
}
|
||||
return (
|
||||
<main className="marketing-home">
|
||||
<header className="marketing-nav">
|
||||
<div className="marketing-logo">AIVideo</div>
|
||||
<nav className="marketing-nav-links">
|
||||
<a href="#product">产品能力</a>
|
||||
<a href="#workflow">创作流程</a>
|
||||
<a href="#ops">运营控制</a>
|
||||
</nav>
|
||||
<div className="marketing-nav-actions">
|
||||
<Link href="/login" className="marketing-link-button">
|
||||
登录
|
||||
</Link>
|
||||
<Link href="/register" className="marketing-primary-button">
|
||||
立即体验
|
||||
</Link>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section className="marketing-hero">
|
||||
<div className="marketing-hero-copy">
|
||||
<span className="marketing-kicker">AI VIDEO PLATFORM</span>
|
||||
<h1>把视频生成、素材管理与运营链路,做成可交付的产品级体验。</h1>
|
||||
<p>
|
||||
AIVideo 把用户创作端与后台控制台收进同一套系统里,既能让普通用户顺滑出片,也能让运营团队管理模型、价格、订单与任务健康度。
|
||||
</p>
|
||||
<div className="marketing-hero-actions">
|
||||
<Link href="/register" className="marketing-primary-button">
|
||||
免费开始
|
||||
<ArrowRight size={16} />
|
||||
</Link>
|
||||
<Link href="/login" className="marketing-secondary-button">
|
||||
进入工作台
|
||||
</Link>
|
||||
</div>
|
||||
<div className="marketing-stat-row">
|
||||
<div>
|
||||
<strong>一体化</strong>
|
||||
<span>创作、素材、任务、钱包和后台控制台</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>更少跳转</strong>
|
||||
<span>用户从提示词到成片提交只需要一条主流程</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>可商业化</strong>
|
||||
<span>支持积分、充值、兑换和邀请奖励体系</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="marketing-stage">
|
||||
<div className="marketing-stage-card marketing-stage-card-dark">
|
||||
<div className="marketing-stage-label">Creator Workspace</div>
|
||||
<h2>一块真正能交付创作结果的 AI 工作台</h2>
|
||||
<p>
|
||||
把模型选择、提示词、素材引用和任务提交放在同一屏里,让用户不需要理解底层供应商和协议,也能稳定完成视频生产。
|
||||
</p>
|
||||
<div className="marketing-chip-row">
|
||||
<span>Text to video</span>
|
||||
<span>Asset references</span>
|
||||
<span>Task polling</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="marketing-stage-grid">
|
||||
<div className="marketing-stage-card">
|
||||
<CirclePlay size={18} />
|
||||
<strong>从提交到成片</strong>
|
||||
<span>任务页持续刷新进度,成功后直接打开结果视频。</span>
|
||||
</div>
|
||||
<div className="marketing-stage-card">
|
||||
<Coins size={18} />
|
||||
<strong>从增长到付费</strong>
|
||||
<span>积分冻结、充值订单、兑换码和奖励规则统一串联。</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="marketing-section marketing-section-light" id="product">
|
||||
<div className="marketing-section-copy">
|
||||
<span className="marketing-kicker">Product Capabilities</span>
|
||||
<h2>对用户足够简单,对业务足够完整。</h2>
|
||||
<p>
|
||||
不是一个只有生成接口的 DEMO,而是一套从创作体验到运营规则都能继续打磨和落地的产品基础设施。
|
||||
</p>
|
||||
</div>
|
||||
<div className="marketing-tile-grid">
|
||||
{productHighlights.map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
<article className="marketing-tile" key={item.title}>
|
||||
<div className="marketing-tile-icon">
|
||||
<Icon size={20} />
|
||||
</div>
|
||||
<h3>{item.title}</h3>
|
||||
<p>{item.copy}</p>
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="marketing-section marketing-section-dark" id="workflow">
|
||||
<div className="marketing-section-copy">
|
||||
<span className="marketing-kicker">Workflow</span>
|
||||
<h2>把复杂的视频生成流程,压缩成用户能理解的三步。</h2>
|
||||
</div>
|
||||
<div className="marketing-flow-grid">
|
||||
<div className="marketing-flow-card">
|
||||
<span>01</span>
|
||||
<strong>选择模型与输出规格</strong>
|
||||
<p>平台只暴露对创作真正重要的参数,不把底层技术复杂度扔给用户。</p>
|
||||
</div>
|
||||
<div className="marketing-flow-card">
|
||||
<span>02</span>
|
||||
<strong>组织提示词和参考素材</strong>
|
||||
<p>提示词、图片、视频和音频素材在同一工作台里互相配合。</p>
|
||||
</div>
|
||||
<div className="marketing-flow-card">
|
||||
<span>03</span>
|
||||
<strong>提交任务并持续跟踪</strong>
|
||||
<p>任务记录页承接状态轮询、扣费结果和最终视频交付。</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="marketing-section marketing-section-light" id="ops">
|
||||
<div className="marketing-ops-shell">
|
||||
<div className="marketing-section-copy">
|
||||
<span className="marketing-kicker">Operations Console</span>
|
||||
<h2>面向运营和业务团队的控制台,也在同一套设计语言里。</h2>
|
||||
<p>
|
||||
用户端强调体验,后台强调秩序。两者共享同一业务模型,但在视觉气质上各自准确,不互相污染。
|
||||
</p>
|
||||
</div>
|
||||
<div className="marketing-ops-card">
|
||||
<ShieldCheck size={20} />
|
||||
<strong>用户、模型、价格、任务、回调与系统配置</strong>
|
||||
<p>
|
||||
运营后台不是附属页面,而是产品交付的一部分。AIVideo
|
||||
从一开始就把增长、付费和模型治理一起纳入设计。
|
||||
</p>
|
||||
<Link href="/admin/login" className="marketing-link-inline">
|
||||
进入管理员登录
|
||||
<ArrowRight size={14} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,20 +21,20 @@ import { useEffect, useMemo } from "react";
|
||||
import { api } from "@/lib/api";
|
||||
|
||||
const navigation = [
|
||||
{ href: "/admin/dashboard", label: "仪表盘", description: "查看系统总览、支付与任务健康度", icon: ChartColumnBig },
|
||||
{ href: "/admin/users", label: "用户管理", description: "维护用户状态、余额与基本资料", icon: Users },
|
||||
{ href: "/admin/recharge-orders", label: "充值订单", description: "跟踪充值流转与支付状态", icon: Coins },
|
||||
{ href: "/admin/redeem-codes", label: "兑换密钥", description: "批量生成、停用与审计兑换码", icon: KeySquare },
|
||||
{ href: "/admin/growth-rules", label: "增长奖励", description: "配置注册奖励与邀请返利规则", icon: Link2 },
|
||||
{ href: "/admin/invite-relations", label: "邀请关系", description: "查看邀请码链路与归因结果", icon: Link2 },
|
||||
{ href: "/admin/provider-accounts", label: "供应商账号", description: "管理各供应商 baseUrl 与鉴权信息", icon: Workflow },
|
||||
{ href: "/admin/provider-models", label: "供应商模型", description: "维护供应商模型能力与协议", icon: Blocks },
|
||||
{ href: "/admin/video-models", label: "平台模型", description: "定义前台可见的统一模型层", icon: Package2 },
|
||||
{ href: "/admin/video-model-bindings", label: "模型绑定", description: "决定平台模型到供应商模型的路由", icon: Workflow },
|
||||
{ href: "/admin/pricing-rules", label: "价格规则", description: "按模型与版本维护积分定价", icon: Coins },
|
||||
{ href: "/admin/video-tasks", label: "视频任务", description: "处理异常任务与追踪回调结果", icon: Workflow },
|
||||
{ href: "/admin/callback-logs", label: "回调日志", description: "查看供应商回调负载与重放线索", icon: ChartColumnBig },
|
||||
{ href: "/admin/system-config", label: "系统配置", description: "维护站点公告、策略与公开配置", icon: Settings2 },
|
||||
{ href: "/admin/dashboard", label: "OVERVIEW", title: "系统总览", description: "查看平台总览、支付与任务健康度。", icon: ChartColumnBig },
|
||||
{ href: "/admin/users", label: "USERS", title: "用户管理", description: "维护用户状态、余额与资料。", icon: Users },
|
||||
{ href: "/admin/recharge-orders", label: "ORDERS", title: "充值订单", description: "跟踪充值流转与支付状态。", icon: Coins },
|
||||
{ href: "/admin/redeem-codes", label: "REDEEM", title: "兑换密钥", description: "管理兑换码的创建、停用和审计。", icon: KeySquare },
|
||||
{ href: "/admin/growth-rules", label: "GROWTH", title: "增长奖励", description: "配置注册奖励与邀请返利规则。", icon: Link2 },
|
||||
{ href: "/admin/invite-relations", label: "INVITES", title: "邀请关系", description: "查看邀请码链路与归因结果。", icon: Link2 },
|
||||
{ href: "/admin/provider-accounts", label: "ACCOUNTS", title: "供应商账号", description: "管理供应商账号和鉴权信息。", icon: Workflow },
|
||||
{ href: "/admin/provider-models", label: "MODELS", title: "供应商模型", description: "维护供应商模型能力与协议。", icon: Blocks },
|
||||
{ href: "/admin/video-models", label: "CATALOG", title: "平台模型", description: "定义前台可见的统一模型层。", icon: Package2 },
|
||||
{ href: "/admin/video-model-bindings", label: "ROUTING", title: "模型绑定", description: "决定平台模型到供应商模型的路由。", icon: Workflow },
|
||||
{ href: "/admin/pricing-rules", label: "PRICING", title: "价格规则", description: "按模型与版本维护积分定价。", icon: Coins },
|
||||
{ href: "/admin/video-tasks", label: "TASKS", title: "视频任务", description: "处理异常任务与追踪执行结果。", icon: Workflow },
|
||||
{ href: "/admin/callback-logs", label: "CALLBACKS", title: "回调日志", description: "查看供应商回调负载与异常线索。", icon: ChartColumnBig },
|
||||
{ href: "/admin/system-config", label: "CONFIG", title: "系统配置", description: "维护站点和策略配置。", icon: Settings2 },
|
||||
];
|
||||
|
||||
export function AdminShell({ children }: { children: React.ReactNode }) {
|
||||
@@ -61,119 +61,71 @@ export function AdminShell({ children }: { children: React.ReactNode }) {
|
||||
|
||||
if (meQuery.isLoading || !meQuery.data) {
|
||||
return (
|
||||
<div className="fullscreen-shell">
|
||||
<div className="fullscreen-shell admin-loading-shell">
|
||||
<div className="pulse-card">正在校验管理员身份...</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="shell-grid shell-grid-admin">
|
||||
<aside className="shell-sidebar">
|
||||
<div className="brand-block brand-block-admin">
|
||||
<div className="brand-visual" aria-hidden="true">
|
||||
<span className="brand-orb brand-orb-primary" />
|
||||
<span className="brand-orb brand-orb-secondary" />
|
||||
</div>
|
||||
<span className="brand-kicker">AIVIDEO ADMIN</span>
|
||||
<h1>控制后台</h1>
|
||||
<p>围绕模型、价格、奖励、订单和任务链路做统一配置、审计和异常处置,用更产品化的矩阵视角管理能力层。</p>
|
||||
<div className="brand-pill-row">
|
||||
<span className="brand-pill">Ops control</span>
|
||||
<span className="brand-pill">Pricing</span>
|
||||
<span className="brand-pill">Capability routing</span>
|
||||
</div>
|
||||
<div className="admin-app-shell">
|
||||
<aside className="admin-rail">
|
||||
<div className="admin-rail-brand">
|
||||
<span className="admin-rail-kicker">AIVIDEO CONTROL</span>
|
||||
<h1>AIVideo</h1>
|
||||
<p>统一管理模型、价格、订单、奖励和任务治理链路。</p>
|
||||
</div>
|
||||
|
||||
<div className="sidebar-note">
|
||||
<div className="sidebar-note-label">Operations Matrix</div>
|
||||
<div className="sidebar-metrics">
|
||||
<div className="sidebar-metric">
|
||||
<strong>Models</strong>
|
||||
<span>平台模型与供应商协议</span>
|
||||
</div>
|
||||
<div className="sidebar-metric">
|
||||
<strong>Economy</strong>
|
||||
<span>充值、价格、奖励规则</span>
|
||||
</div>
|
||||
<div className="sidebar-metric">
|
||||
<strong>Audit</strong>
|
||||
<span>任务回调、关系链和配置变更</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav className="sidebar-nav">
|
||||
{navigation.map((item, index) => {
|
||||
<nav className="admin-rail-nav">
|
||||
{navigation.map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className={clsx("nav-item", {
|
||||
className={clsx("admin-rail-link", {
|
||||
active: pathname.startsWith(item.href),
|
||||
})}
|
||||
>
|
||||
<Icon size={18} />
|
||||
<div>
|
||||
<Icon size={15} />
|
||||
<span>{item.label}</span>
|
||||
<small>{item.description}</small>
|
||||
</div>
|
||||
<div className="nav-index">{String(index + 1).padStart(2, "0")}</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
|
||||
<div className="profile-card">
|
||||
<div className="profile-card-main">
|
||||
<div className="profile-avatar">
|
||||
{String((meQuery.data as { nickname: string }).nickname ?? "AD")
|
||||
.slice(0, 2)
|
||||
.toUpperCase()}
|
||||
</div>
|
||||
<div className="profile-name">
|
||||
{(meQuery.data as { nickname: string }).nickname}
|
||||
</div>
|
||||
<div className="profile-meta">
|
||||
{(meQuery.data as { username: string }).username}
|
||||
</div>
|
||||
</div>
|
||||
<div className="profile-card-stats">
|
||||
<div className="profile-stat">
|
||||
<span>权限</span>
|
||||
<strong>Admin</strong>
|
||||
</div>
|
||||
<div className="profile-stat">
|
||||
<span>模式</span>
|
||||
<strong>Control</strong>
|
||||
</div>
|
||||
<div className="admin-rail-footer">
|
||||
<div className="admin-rail-user">
|
||||
<strong>{(meQuery.data as { nickname: string }).nickname}</strong>
|
||||
<span>{(meQuery.data as { username: string }).username}</span>
|
||||
</div>
|
||||
<button
|
||||
className="ghost-button"
|
||||
className="ghost-button compact-button"
|
||||
onClick={async () => {
|
||||
await api.post("/api/v1/admin/auth/logout");
|
||||
router.replace("/admin/login");
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<LogOut size={16} />
|
||||
退出
|
||||
<LogOut size={14} />
|
||||
SIGN OUT
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main className="shell-main">
|
||||
<header className="shell-header">
|
||||
<div className="shell-header-content">
|
||||
<div className="header-kicker">Operations Console</div>
|
||||
<h2>{current.label}</h2>
|
||||
<p className="shell-header-copy">{current.description}</p>
|
||||
<main className="admin-main-shell">
|
||||
<header className="admin-page-hero">
|
||||
<div>
|
||||
<span className="admin-page-kicker">OPERATIONS CONSOLE</span>
|
||||
<h2>{current.title}</h2>
|
||||
<p>{current.description}</p>
|
||||
</div>
|
||||
<div className="shell-header-meta">
|
||||
<div className="header-chip header-chip-success">管理员会话已建立</div>
|
||||
<div className="header-chip">统一配置 / 审计 / 处置</div>
|
||||
<div className="admin-page-tags">
|
||||
<span>LIVE SESSION</span>
|
||||
<span>RULES / TASKS / PRICING</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section className="shell-content">{children}</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { startTransition, useState } from "react";
|
||||
import { ArrowRight, Coins, Gift, Link2, Sparkles } from "lucide-react";
|
||||
import { ArrowRight, Coins, Gift, Link2 } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -36,58 +36,43 @@ export function RegisterForm({ inviteCode = "" }: { inviteCode?: string }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="auth-grid">
|
||||
<section className="auth-hero auth-hero-studio">
|
||||
<div className="auth-copy">
|
||||
<div className="eyebrow">New Account</div>
|
||||
<h1 className="headline">用一个账号,串起创作、积分、邀请奖励和素材管理。</h1>
|
||||
<p className="subcopy">
|
||||
注册后会读取后台增长规则发放奖励;如果带邀请码进入,则会同步建立邀请关系,让增长链路也保持和创作体验一样清爽直接。
|
||||
</p>
|
||||
<div className="auth-chip-row">
|
||||
<span className="auth-chip">Signup rewards</span>
|
||||
<span className="auth-chip">Invite tracking</span>
|
||||
<span className="auth-chip">Wallet ready</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="showcase-stack">
|
||||
<div className="showcase-card showcase-card-hero">
|
||||
<div className="toolbar">
|
||||
<span className="status-badge tone-soft">Growth loop</span>
|
||||
<span className="mini-note">Reward rules active</span>
|
||||
</div>
|
||||
<h3>把增长规则自然接到用户首登体验里</h3>
|
||||
<p className="muted">
|
||||
注册成功后直接进入工作台,不需要在多个页面之间跳转,就能继续上传素材、创建任务和消费积分。
|
||||
<div className="auth-page auth-page-user">
|
||||
<section className="auth-showcase auth-showcase-user">
|
||||
<div className="auth-showcase-copy">
|
||||
<span className="auth-showcase-kicker">CREATE ACCOUNT</span>
|
||||
<h1>把用户注册、增长奖励和首次创作,接成一个更完整的首日体验。</h1>
|
||||
<p>
|
||||
新用户不该在一堆跳转里迷失。注册后直接进入创作端,同时让奖励、邀请和钱包体系自然接入首登流程。
|
||||
</p>
|
||||
</div>
|
||||
<div className="showcase-card-grid">
|
||||
<article className="showcase-card">
|
||||
|
||||
<div className="auth-showcase-grid">
|
||||
<article className="auth-showcase-card">
|
||||
<Gift size={18} />
|
||||
<strong>注册奖励自动发放</strong>
|
||||
<span>遵循后台增长配置,不在前台写死业务规则。</span>
|
||||
<strong>注册奖励</strong>
|
||||
<span>按后台规则自动发放,不在前台写死业务策略。</span>
|
||||
</article>
|
||||
<article className="showcase-card">
|
||||
<article className="auth-showcase-card">
|
||||
<Link2 size={18} />
|
||||
<strong>邀请码自动建链</strong>
|
||||
<span>注册时携带邀请码即可完成邀请归因。</span>
|
||||
<strong>邀请归因</strong>
|
||||
<span>带邀请码注册即可建立邀请关系和后续奖励链路。</span>
|
||||
</article>
|
||||
<article className="showcase-card">
|
||||
<article className="auth-showcase-card">
|
||||
<Coins size={18} />
|
||||
<strong>积分钱包即刻可用</strong>
|
||||
<span>注册完成后可直接进入充值、兑换和视频生成流程。</span>
|
||||
<strong>钱包可用</strong>
|
||||
<span>注册完成后立即进入创作、充值和兑换流程。</span>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="fullscreen-shell">
|
||||
<form className="auth-card auth-card-strong" onSubmit={handleSubmit}>
|
||||
<div className="auth-card-head">
|
||||
<div className="eyebrow">Create Account</div>
|
||||
<h2>注册用户</h2>
|
||||
<p className="muted">创建账号后会直接进入创作端工作台。</p>
|
||||
<section className="auth-form-column">
|
||||
<form className="auth-form-card" onSubmit={handleSubmit}>
|
||||
<div className="auth-form-head">
|
||||
<span className="auth-form-kicker">Get Started</span>
|
||||
<h2>创建用户账号</h2>
|
||||
<p>注册成功后将直接进入创作工作台。</p>
|
||||
</div>
|
||||
|
||||
<div className="form-stack">
|
||||
<label className="field-label">
|
||||
邮箱账号
|
||||
@@ -95,7 +80,10 @@ export function RegisterForm({ inviteCode = "" }: { inviteCode?: string }) {
|
||||
placeholder="user@example.com"
|
||||
value={form.account}
|
||||
onChange={(event) =>
|
||||
setForm((previous) => ({ ...previous, account: event.target.value }))
|
||||
setForm((previous) => ({
|
||||
...previous,
|
||||
account: event.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
@@ -105,7 +93,10 @@ export function RegisterForm({ inviteCode = "" }: { inviteCode?: string }) {
|
||||
type="password"
|
||||
value={form.password}
|
||||
onChange={(event) =>
|
||||
setForm((previous) => ({ ...previous, password: event.target.value }))
|
||||
setForm((previous) => ({
|
||||
...previous,
|
||||
password: event.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
@@ -114,23 +105,28 @@ export function RegisterForm({ inviteCode = "" }: { inviteCode?: string }) {
|
||||
<input
|
||||
value={form.inviteCode}
|
||||
onChange={(event) =>
|
||||
setForm((previous) => ({ ...previous, inviteCode: event.target.value }))
|
||||
setForm((previous) => ({
|
||||
...previous,
|
||||
inviteCode: event.target.value,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
|
||||
{error ? <div className="inline-feedback is-error">{error}</div> : null}
|
||||
|
||||
<button className="primary-button" disabled={loading} type="submit">
|
||||
{loading ? "注册中..." : "注册并领取初始积分"}
|
||||
{loading ? "注册中..." : "注册并进入工作台"}
|
||||
{loading ? null : <ArrowRight size={16} />}
|
||||
</button>
|
||||
<div className="auth-action-row">
|
||||
|
||||
<div className="auth-form-actions">
|
||||
<Link href="/login" className="ghost-button">
|
||||
返回登录
|
||||
</Link>
|
||||
<div className="field-note">
|
||||
<Sparkles size={14} />
|
||||
若通过邀请链接进入,邀请码会自动带入当前表单。
|
||||
</div>
|
||||
<Link href="/" className="auth-inline-link">
|
||||
返回首页
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -2,17 +2,7 @@
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import clsx from "clsx";
|
||||
import {
|
||||
Activity,
|
||||
Coins,
|
||||
FolderKanban,
|
||||
ImagePlus,
|
||||
LogOut,
|
||||
Sparkles,
|
||||
Ticket,
|
||||
UserRound,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
import { Activity, LogOut } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { useEffect, useMemo } from "react";
|
||||
@@ -23,51 +13,39 @@ import type { UserProfile } from "@/lib/types";
|
||||
const navigation = [
|
||||
{
|
||||
href: "/workspace/create",
|
||||
label: "工作台",
|
||||
description: "生成参数、提示词与素材联动",
|
||||
icon: Sparkles,
|
||||
label: "创作",
|
||||
title: "生成工作台",
|
||||
description: "组织模型、提示词、素材和任务提交。",
|
||||
},
|
||||
{
|
||||
href: "/workspace/tasks",
|
||||
label: "任务记录",
|
||||
description: "查看队列、状态轮询与结果视频",
|
||||
icon: FolderKanban,
|
||||
label: "任务",
|
||||
title: "任务记录",
|
||||
description: "追踪生成状态、扣费结果和最终视频。",
|
||||
},
|
||||
{
|
||||
href: "/workspace/assets",
|
||||
label: "素材管理",
|
||||
description: "上传图片、视频和音频素材",
|
||||
icon: ImagePlus,
|
||||
label: "素材",
|
||||
title: "素材管理",
|
||||
description: "统一管理图片、视频和音频参考素材。",
|
||||
},
|
||||
{
|
||||
href: "/wallet",
|
||||
label: "钱包概览",
|
||||
description: "查看可用积分和冻结明细",
|
||||
icon: Coins,
|
||||
},
|
||||
{
|
||||
href: "/wallet/recharge",
|
||||
label: "充值中心",
|
||||
description: "采购积分,补足生产额度",
|
||||
icon: Coins,
|
||||
},
|
||||
{
|
||||
href: "/wallet/redeem",
|
||||
label: "兑换密钥",
|
||||
description: "使用兑换码快速充值",
|
||||
icon: Ticket,
|
||||
label: "钱包",
|
||||
title: "钱包概览",
|
||||
description: "查看积分、充值和兑换的资金流转。",
|
||||
},
|
||||
{
|
||||
href: "/invite",
|
||||
label: "邀请中心",
|
||||
description: "管理关系链与推广奖励",
|
||||
icon: Users,
|
||||
label: "邀请",
|
||||
title: "邀请中心",
|
||||
description: "处理邀请关系和增长奖励链路。",
|
||||
},
|
||||
{
|
||||
href: "/profile",
|
||||
label: "个人资料",
|
||||
description: "维护账户信息与展示名",
|
||||
icon: UserRound,
|
||||
label: "账户",
|
||||
title: "个人资料",
|
||||
description: "维护基础资料和账户身份信息。",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -89,11 +67,12 @@ export function SiteShell({ children }: { children: React.ReactNode }) {
|
||||
}
|
||||
}, [error, router]);
|
||||
|
||||
const title = useMemo(() => {
|
||||
const current = [...navigation]
|
||||
const current = useMemo(() => {
|
||||
return (
|
||||
[...navigation]
|
||||
.sort((left, right) => right.href.length - left.href.length)
|
||||
.find((item) => matchesPath(pathname, item.href));
|
||||
return current ?? navigation[0];
|
||||
.find((item) => matchesPath(pathname, item.href)) ?? navigation[0]
|
||||
);
|
||||
}, [pathname]);
|
||||
|
||||
if (isLoading || !data) {
|
||||
@@ -105,116 +84,79 @@ export function SiteShell({ children }: { children: React.ReactNode }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="shell-grid shell-grid-studio">
|
||||
<aside className="shell-sidebar">
|
||||
<div className="brand-block brand-block-studio">
|
||||
<div className="brand-visual" aria-hidden="true">
|
||||
<span className="brand-orb brand-orb-primary" />
|
||||
<span className="brand-orb brand-orb-secondary" />
|
||||
</div>
|
||||
<span className="brand-kicker">AI VIDEO STUDIO</span>
|
||||
<h1>AIVideo</h1>
|
||||
<p>把模型路由、素材管理和任务轮询收进一块轻白画布,让每个创作动作都像切换一个 AI 能力卡片。</p>
|
||||
<div className="brand-pill-row">
|
||||
<span className="brand-pill">Creative matrix</span>
|
||||
<span className="brand-pill">Mock providers</span>
|
||||
<span className="brand-pill">Local assets</span>
|
||||
</div>
|
||||
<div className="brand-status">
|
||||
<span className="status-dot" />
|
||||
创作链路在线
|
||||
</div>
|
||||
<div className="site-app-shell">
|
||||
<header className="site-topbar">
|
||||
<div className="site-brand-block">
|
||||
<Link className="site-brand" href="/">
|
||||
AIVideo
|
||||
</Link>
|
||||
<span className="site-brand-subtitle">AI Video Platform</span>
|
||||
</div>
|
||||
|
||||
<div className="sidebar-note">
|
||||
<div className="sidebar-note-label">Capability Grid</div>
|
||||
<div className="sidebar-metrics">
|
||||
<div className="sidebar-metric">
|
||||
<strong>Prompt</strong>
|
||||
<span>主体、动作、镜头和情绪描述</span>
|
||||
</div>
|
||||
<div className="sidebar-metric">
|
||||
<strong>Assets</strong>
|
||||
<span>图片、视频、音频参考素材</span>
|
||||
</div>
|
||||
<div className="sidebar-metric">
|
||||
<strong>Tasks</strong>
|
||||
<span>轮询进度、冻结扣费和结果回收</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav className="sidebar-nav">
|
||||
{navigation.map((item, index) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
<nav className="site-topnav">
|
||||
{navigation.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className={clsx("nav-item", {
|
||||
active: title.href === item.href,
|
||||
className={clsx("site-topnav-link", {
|
||||
active: current.href === item.href,
|
||||
})}
|
||||
>
|
||||
<Icon size={18} />
|
||||
<div>
|
||||
<span>{item.label}</span>
|
||||
<small>{item.description}</small>
|
||||
</div>
|
||||
<div className="nav-index">{String(index + 1).padStart(2, "0")}</div>
|
||||
{item.label}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div className="profile-card">
|
||||
<div className="profile-card-main">
|
||||
<div className="profile-avatar">
|
||||
{(data.nickname || data.username || "AI")
|
||||
.slice(0, 2)
|
||||
.toUpperCase()}
|
||||
</div>
|
||||
<div className="profile-name">{data.nickname || data.username}</div>
|
||||
<div className="profile-meta">{data.email}</div>
|
||||
</div>
|
||||
<div className="profile-card-stats">
|
||||
<div className="profile-stat">
|
||||
<span>身份</span>
|
||||
<strong>Creator</strong>
|
||||
</div>
|
||||
<div className="profile-stat">
|
||||
<span>ID</span>
|
||||
<strong>{(data.publicId || "AIVIDEO").slice(-8)}</strong>
|
||||
</div>
|
||||
<div className="site-userbar">
|
||||
<div className="site-userbar-meta">
|
||||
<strong>{data.nickname || data.username}</strong>
|
||||
<span>{data.email}</span>
|
||||
</div>
|
||||
<button
|
||||
className="ghost-button"
|
||||
className="ghost-button compact-button"
|
||||
onClick={async () => {
|
||||
await api.post("/api/v1/auth/logout");
|
||||
router.replace("/login");
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<LogOut size={16} />
|
||||
<LogOut size={14} />
|
||||
退出
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
</header>
|
||||
|
||||
<main className="shell-main">
|
||||
<header className="shell-header">
|
||||
<div className="shell-header-content">
|
||||
<div className="header-kicker">Creative Ops Console</div>
|
||||
<h2>{title.label}</h2>
|
||||
<p className="shell-header-copy">{title.description}</p>
|
||||
<main className="site-main-shell">
|
||||
<section className="site-page-hero">
|
||||
<div className="site-page-copy">
|
||||
<span className="header-kicker">Creative Workspace</span>
|
||||
<h1>{current.title}</h1>
|
||||
<p>{current.description}</p>
|
||||
</div>
|
||||
<div className="shell-header-meta">
|
||||
<div className="site-page-meta">
|
||||
<div className="header-chip header-chip-success">
|
||||
<Activity size={14} />
|
||||
会话正常
|
||||
服务可用
|
||||
</div>
|
||||
<div className="header-chip">{data.publicId || "UNAVAILABLE"}</div>
|
||||
<div className="header-chip">本地素材 / 本地存储 / mock 供应商</div>
|
||||
<div className="header-chip">{data.publicId || "USER"}</div>
|
||||
</div>
|
||||
</header>
|
||||
</section>
|
||||
|
||||
<section className="site-highlight-strip">
|
||||
<div className="site-highlight-card">
|
||||
<span>创作体验</span>
|
||||
<strong>提示词、素材与模型同屏协作</strong>
|
||||
</div>
|
||||
<div className="site-highlight-card">
|
||||
<span>交付链路</span>
|
||||
<strong>任务追踪、结果视频和积分消耗可回看</strong>
|
||||
</div>
|
||||
<div className="site-highlight-card">
|
||||
<span>产品增长</span>
|
||||
<strong>充值、兑换和邀请奖励形成闭环</strong>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="shell-content">{children}</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user