Commit 16da3a9f authored by yaoke.yk's avatar yaoke.yk

Revert "企业级工业风格"

This reverts commit 75992d7b.
parent 75992d7b
import type { ReactNode } from "react";
import { Link } from "react-router";
import { ArrowLeft, ShieldCheck, Sparkles } from "lucide-react";
import { brand, brandHighlights, brandMetrics } from "../../lib/brand";
import { BrandLogo } from "./BrandLogo";
type AuthShellProps = {
title: string;
description: string;
children: ReactNode;
footer: ReactNode;
};
export function AuthShell({ title, description, children, footer }: AuthShellProps) {
return (
<div className="relative min-h-screen overflow-hidden bg-background">
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(34,146,255,0.22),transparent_34%),radial-gradient(circle_at_bottom_right,_rgba(6,43,92,0.16),transparent_28%)]" />
<div className="absolute inset-0 opacity-60 [background-image:linear-gradient(rgba(15,87,157,0.06)_1px,transparent_1px),linear-gradient(90deg,rgba(15,87,157,0.06)_1px,transparent_1px)] [background-size:32px_32px]" />
<div className="relative mx-auto flex min-h-screen max-w-7xl flex-col px-4 py-6 lg:px-8">
<div className="mb-6 flex items-center justify-between">
<BrandLogo subtitle={brand.tagline} />
<Link
to="/"
className="inline-flex items-center gap-2 rounded-full border border-border/80 bg-white/75 px-4 py-2 text-sm text-muted-foreground shadow-sm backdrop-blur hover:text-foreground"
>
<ArrowLeft className="h-4 w-4" />
返回工作台
</Link>
</div>
<div className="grid flex-1 items-stretch gap-6 lg:grid-cols-[1.15fr_0.85fr]">
<section className="relative overflow-hidden rounded-[32px] border border-white/70 bg-[linear-gradient(145deg,#0d294b_0%,#11477f_46%,#1f9ce8_100%)] p-8 text-white shadow-[0_32px_90px_rgba(9,42,82,0.24)] lg:p-10">
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_right,_rgba(255,255,255,0.18),transparent_24%),radial-gradient(circle_at_bottom_left,_rgba(255,255,255,0.1),transparent_28%)]" />
<div className="absolute -right-20 top-10 h-72 w-72 rounded-full border border-white/15" />
<div className="absolute right-10 top-28 h-44 w-44 rounded-full border border-white/10" />
<div className="absolute bottom-10 left-8 h-28 w-28 rounded-full border border-white/10" />
<div className="relative flex h-full flex-col">
<div className="mb-8 inline-flex w-fit items-center gap-2 rounded-full border border-white/20 bg-white/10 px-4 py-2 text-sm text-white/86 backdrop-blur">
<ShieldCheck className="h-4 w-4" />
企业级短剧生产平台
</div>
<div className="max-w-2xl">
<div className="mb-3 text-sm uppercase tracking-[0.32em] text-white/64">
{brand.companyName}
</div>
<h1 className="max-w-xl text-4xl font-semibold leading-tight lg:text-5xl">
{brand.heroTitle}
</h1>
<p className="mt-5 max-w-xl text-base leading-7 text-white/76 lg:text-lg">
{brand.heroDescription}
</p>
</div>
<div className="mt-10 grid gap-4 sm:grid-cols-3">
{brandMetrics.map((metric) => (
<div
key={metric.label}
className="rounded-3xl border border-white/14 bg-white/10 px-5 py-4 backdrop-blur-sm"
>
<div className="text-2xl font-semibold">{metric.value}</div>
<div className="mt-2 text-sm text-white/66">{metric.label}</div>
</div>
))}
</div>
<div className="mt-auto pt-10">
<div className="mb-4 inline-flex items-center gap-2 rounded-full bg-white/10 px-3 py-1.5 text-xs uppercase tracking-[0.28em] text-white/72">
<Sparkles className="h-3.5 w-3.5" />
Platform Value
</div>
<div className="grid gap-3">
{brandHighlights.map((item) => (
<div
key={item}
className="rounded-2xl border border-white/14 bg-white/8 px-4 py-3 text-sm leading-6 text-white/82"
>
{item}
</div>
))}
</div>
</div>
</div>
</section>
<section className="flex items-center">
<div className="w-full rounded-[32px] border border-white/80 bg-white/82 p-6 shadow-[0_30px_80px_rgba(15,57,99,0.12)] backdrop-blur-xl lg:p-8">
<div className="mb-6">
<div className="mb-2 text-xs uppercase tracking-[0.28em] text-primary/70">
Secure Access
</div>
<h2 className="text-3xl font-semibold text-foreground">{title}</h2>
<p className="mt-3 text-sm leading-6 text-muted-foreground">{description}</p>
</div>
{children}
<div className="mt-6 border-t border-border/80 pt-5 text-sm text-muted-foreground">
{footer}
</div>
</div>
</section>
</div>
</div>
</div>
);
}
import { Link } from "react-router";
import { brand } from "../../lib/brand";
import { cn } from "./ui/utils";
type BrandLogoProps = {
compact?: boolean;
className?: string;
href?: string;
subtitle?: string;
};
export function BrandLogo({
compact = false,
className,
href = "/",
subtitle,
}: BrandLogoProps) {
const content = (
<div className={cn("flex items-center gap-3", className)}>
<div
className={cn(
"overflow-hidden rounded-2xl ring-1 ring-white/70 shadow-[0_12px_28px_rgba(15,77,143,0.16)]",
compact ? "h-10 w-10 rounded-xl" : "h-12 w-12",
)}
>
<img
src={brand.logo}
alt={brand.companyName}
className="h-full w-full object-cover"
/>
</div>
<div className="min-w-0">
<div className="text-[11px] font-semibold uppercase tracking-[0.24em] text-primary/70">
{brand.companyName}
</div>
<div
className={cn(
"truncate font-semibold text-foreground",
compact ? "text-sm" : "text-base",
)}
>
{brand.productName}
</div>
{subtitle ? (
<div className="truncate text-xs text-muted-foreground">{subtitle}</div>
) : null}
</div>
</div>
);
return href ? (
<Link to={href} className="inline-flex">
{content}
</Link>
) : (
content
);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import { useState } from "react";
import { Link } from "react-router";
import { LockKeyhole, Mail, ShieldCheck } from "lucide-react";
import { Button } from "../components/ui/button";
import { Input } from "../components/ui/input";
import { Label } from "../components/ui/label";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card";
import { useAuth } from "../../hooks/useAuth";
import { AuthShell } from "../components/AuthShell";
export function LoginPage() {
const { login, loginPending, loginError } = useAuth();
......@@ -17,78 +16,56 @@ export function LoginPage() {
};
return (
<AuthShell
title="登录企业工作台"
description="使用企业账号进入中科集团 AI 短剧工业化平台,继续推进剧本、设定、分镜与视频任务。"
footer={
<div className="flex items-center justify-between gap-3">
<div className="inline-flex items-center gap-2 text-xs text-muted-foreground">
<ShieldCheck className="h-4 w-4 text-primary" />
统一身份认证与团队空间隔离
</div>
<div>
没有账号?
<Link to="/register" className="ml-1 font-medium text-primary hover:underline">
立即注册
</Link>
</div>
</div>
}
>
<form onSubmit={handleSubmit} className="space-y-5">
<div className="space-y-2">
<Label htmlFor="email" className="text-sm text-foreground">
邮箱账号
</Label>
<div className="relative">
<Mail className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="email"
type="email"
placeholder="you@example.com"
required
value={form.email}
onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
className="h-11 rounded-xl border-border/90 bg-white pl-10 shadow-sm"
/>
</div>
</div>
<div className="min-h-screen flex items-center justify-center bg-background px-4">
<Card className="w-full max-w-sm">
<CardHeader className="text-center">
<CardTitle className="text-2xl">YaoAI Comic Studio</CardTitle>
<CardDescription>登录您的账号</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">邮箱</Label>
<Input
id="email"
type="email"
placeholder="you@example.com"
required
value={form.email}
onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="password">密码</Label>
<Input
id="password"
type="password"
placeholder="••••••••"
required
value={form.password}
onChange={(e) => setForm((f) => ({ ...f, password: e.target.value }))}
/>
</div>
<div className="space-y-2">
<div className="flex items-center justify-between">
<Label htmlFor="password" className="text-sm text-foreground">
登录密码
</Label>
<span className="text-xs text-muted-foreground">建议使用企业统一密码</span>
</div>
<div className="relative">
<LockKeyhole className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="password"
type="password"
placeholder="••••••••"
required
value={form.password}
onChange={(e) => setForm((f) => ({ ...f, password: e.target.value }))}
className="h-11 rounded-xl border-border/90 bg-white pl-10 shadow-sm"
/>
</div>
</div>
{loginError && (
<p className="text-sm text-destructive">
{loginError instanceof Error ? loginError.message : "登录失败"}
</p>
)}
{loginError ? (
<div className="rounded-2xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
{loginError instanceof Error ? loginError.message : "登录失败,请检查账号和密码。"}
</div>
) : null}
<Button type="submit" className="w-full" disabled={loginPending}>
{loginPending ? "登录中..." : "登录"}
</Button>
<Button
type="submit"
className="h-12 w-full rounded-xl bg-[linear-gradient(135deg,#0f74d8_0%,#1ea5ff_100%)] text-base font-medium shadow-[0_16px_30px_rgba(15,116,216,0.22)] transition hover:translate-y-[-1px] hover:shadow-[0_20px_38px_rgba(15,116,216,0.26)]"
disabled={loginPending}
>
{loginPending ? "正在登录..." : "进入工作台"}
</Button>
</form>
</AuthShell>
<p className="text-center text-sm text-muted-foreground">
没有账号?{" "}
<Link to="/register" className="text-primary underline-offset-4 hover:underline">
立即注册
</Link>
</p>
</form>
</CardContent>
</Card>
</div>
);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import { useState } from "react";
import { Link } from "react-router";
import { Building2, LockKeyhole, Mail, UserRound } from "lucide-react";
import { Button } from "../components/ui/button";
import { Input } from "../components/ui/input";
import { Label } from "../components/ui/label";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card";
import { useAuth } from "../../hooks/useAuth";
import { AuthShell } from "../components/AuthShell";
export function RegisterPage() {
const { register, registerPending, registerError } = useAuth();
......@@ -27,109 +26,78 @@ export function RegisterPage() {
};
return (
<AuthShell
title="创建企业账号"
description="注册后即可创建团队空间,统一管理短剧项目、成员权限、资产沉淀与 AI 生成流程。"
footer={
<div className="flex items-center justify-between gap-3">
<span className="text-xs text-muted-foreground">支持个人试用,也支持企业团队空间接入</span>
<div>
已有账号?
<Link to="/login" className="ml-1 font-medium text-primary hover:underline">
立即登录
</Link>
</div>
</div>
}
>
<form onSubmit={handleSubmit} className="space-y-5">
<div className="space-y-2">
<Label htmlFor="username" className="text-sm text-foreground">
用户名
</Label>
<div className="relative">
<UserRound className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="username"
placeholder="your-name"
required
value={form.username}
onChange={(e) => setForm((f) => ({ ...f, username: e.target.value }))}
className="h-11 rounded-xl border-border/90 bg-white pl-10 shadow-sm"
/>
</div>
</div>
<div className="min-h-screen flex items-center justify-center bg-background px-4">
<Card className="w-full max-w-sm">
<CardHeader className="text-center">
<CardTitle className="text-2xl">创建账号</CardTitle>
<CardDescription>免费开始使用 YaoAI Comic Studio</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="username">用户名</Label>
<Input
id="username"
placeholder="your-name"
required
value={form.username}
onChange={(e) => setForm((f) => ({ ...f, username: e.target.value }))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="email">邮箱</Label>
<Input
id="email"
type="email"
placeholder="you@example.com"
required
value={form.email}
onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="password">密码</Label>
<Input
id="password"
type="password"
placeholder="至少 8 位"
required
minLength={8}
value={form.password}
onChange={(e) => setForm((f) => ({ ...f, password: e.target.value }))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="tenantName">
工作空间名称 <span className="text-muted-foreground text-xs">(可选)</span>
</Label>
<Input
id="tenantName"
placeholder="我的工作室"
value={form.tenantName}
onChange={(e) => setForm((f) => ({ ...f, tenantName: e.target.value }))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="email" className="text-sm text-foreground">
邮箱
</Label>
<div className="relative">
<Mail className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="email"
type="email"
placeholder="you@example.com"
required
value={form.email}
onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
className="h-11 rounded-xl border-border/90 bg-white pl-10 shadow-sm"
/>
</div>
</div>
{registerError && (
<p className="text-sm text-destructive">
{registerError instanceof Error ? registerError.message : "注册失败"}
</p>
)}
<div className="space-y-2">
<Label htmlFor="password" className="text-sm text-foreground">
密码
</Label>
<div className="relative">
<LockKeyhole className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="password"
type="password"
placeholder="至少 8 位"
required
minLength={8}
value={form.password}
onChange={(e) => setForm((f) => ({ ...f, password: e.target.value }))}
className="h-11 rounded-xl border-border/90 bg-white pl-10 shadow-sm"
/>
</div>
</div>
<Button type="submit" className="w-full" disabled={registerPending}>
{registerPending ? "注册中..." : "注册"}
</Button>
<div className="space-y-2">
<div className="flex items-center justify-between">
<Label htmlFor="tenantName" className="text-sm text-foreground">
工作空间名称
</Label>
<span className="text-xs text-muted-foreground">可选</span>
</div>
<div className="relative">
<Building2 className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
id="tenantName"
placeholder="我的工作室"
value={form.tenantName}
onChange={(e) => setForm((f) => ({ ...f, tenantName: e.target.value }))}
className="h-11 rounded-xl border-border/90 bg-white pl-10 shadow-sm"
/>
</div>
</div>
{registerError ? (
<div className="rounded-2xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
{registerError instanceof Error ? registerError.message : "注册失败,请稍后重试。"}
</div>
) : null}
<Button
type="submit"
className="h-12 w-full rounded-xl bg-[linear-gradient(135deg,#0f74d8_0%,#1ea5ff_100%)] text-base font-medium shadow-[0_16px_30px_rgba(15,116,216,0.22)] transition hover:translate-y-[-1px] hover:shadow-[0_20px_38px_rgba(15,116,216,0.26)]"
disabled={registerPending}
>
{registerPending ? "正在注册..." : "创建账号"}
</Button>
</form>
</AuthShell>
<p className="text-center text-sm text-muted-foreground">
已有账号?{" "}
<Link to="/login" className="text-primary underline-offset-4 hover:underline">
立即登录
</Link>
</p>
</form>
</CardContent>
</Card>
</div>
);
}
This diff is collapsed.
import { useState } from "react";
import { useState } from "react";
import { useNavigate, useParams } from "react-router";
import { ArrowRight, Check, Loader2 } from "lucide-react";
import { useUpdateProject } from "../../hooks/useProjects";
......@@ -20,9 +20,10 @@ export function StyleSelection() {
<div className="h-full overflow-auto bg-background p-6">
<div className="mx-auto max-w-6xl">
<div className="mb-8 text-center">
<h1 className="mb-2 text-3xl font-semibold text-foreground">閫夋嫨椤圭洰瑙嗚椋庢牸</h1>
<h1 className="mb-2 text-3xl font-semibold text-foreground">选择项目视觉风格</h1>
<p className="text-sm text-muted-foreground">
杩欓噷閫夋嫨鐨勬槸瑙嗚鍛堢幇鏂瑰紡锛屼笉鏄鏉愮被鍨嬨€侫I 浼氭牴鎹墍閫夐鏍煎奖鍝嶄汉鐗┿€佸満鏅笌鍚庣画鍥惧儚鐢熸垚銆? </p>
这里选择的是视觉呈现方式,不是题材类型。AI 会根据所选风格影响人物、场景与后续图像生成。
</p>
</div>
<div className="mb-8 grid grid-cols-3 gap-4">
......@@ -60,13 +61,13 @@ export function StyleSelection() {
<button
onClick={handleContinue}
disabled={!selectedStyle || updateProject.isPending}
className="flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-[#0f74d8] to-[#1ea5ff] py-3 text-white transition-all hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:shadow-none"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] py-3 text-white transition-all hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:shadow-none"
>
{updateProject.isPending ? (
<Loader2 className="h-5 w-5 animate-spin" />
) : (
<>
<span>缁х画</span>
<span>继续</span>
<ArrowRight className="h-5 w-5" />
</>
)}
......@@ -75,4 +76,3 @@ export function StyleSelection() {
</div>
);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import logoImage from "../imports/ab7d1ce5faf061d2af2b02d93e11935.png";
export const brand = {
companyName: "中科集团",
productName: "AI 短剧工业化平台",
shortProductName: "短剧工业化平台",
tagline: "从剧本拆解到视频成片的企业级创作中台",
heroTitle: "面向企业协同的 AI 短剧生产工作台",
heroDescription:
"统一管理剧本、大纲、角色、场景、分镜与视频任务,让团队在同一条生产链路中协作推进。",
logo: logoImage,
};
export const brandMetrics = [
{ label: "流程阶段", value: "6+" },
{ label: "团队协作", value: "多角色" },
{ label: "内容资产", value: "统一管理" },
];
export const brandHighlights = [
"品牌化工作台与中科集团统一视觉体系",
"覆盖剧本、设定、分镜、视频的完整生产链路",
"支持团队协作、资产沉淀与项目进度追踪",
];
:root {
--font-sans-brand:
"Avenir Next",
"Segoe UI",
"PingFang SC",
"Hiragino Sans GB",
"Microsoft YaHei",
"Noto Sans SC",
sans-serif;
}
......@@ -2,43 +2,43 @@
:root {
--font-size: 14px;
--background: #eef4f9;
--foreground: #12263f;
--card: rgba(255, 255, 255, 0.92);
--card-foreground: #12263f;
--background: #f8f9fa;
--foreground: #1a1a1a;
--card: #ffffff;
--card-foreground: #1a1a1a;
--popover: #ffffff;
--popover-foreground: #12263f;
--primary: #0f74d8;
--popover-foreground: #1a1a1a;
--primary: #5b5ff9;
--primary-foreground: #ffffff;
--secondary: #d9e7f4;
--secondary-foreground: #163b62;
--muted: #f4f8fc;
--muted-foreground: #5d6f84;
--accent: #e5f1fb;
--accent-foreground: #0f4d8f;
--destructive: #d95050;
--secondary: #f1f3f5;
--secondary-foreground: #1a1a1a;
--muted: #f8f9fa;
--muted-foreground: #6c757d;
--accent: #e7f5ff;
--accent-foreground: #1971c2;
--destructive: #f03e3e;
--destructive-foreground: #ffffff;
--border: rgba(16, 74, 132, 0.12);
--input: rgba(16, 74, 132, 0.12);
--input-background: rgba(255, 255, 255, 0.92);
--switch-background: #c3d4e5;
--border: rgba(0, 0, 0, 0.06);
--input: rgba(0, 0, 0, 0.06);
--input-background: #ffffff;
--switch-background: #dee2e6;
--font-weight-medium: 500;
--font-weight-normal: 400;
--ring: #0f74d8;
--chart-1: #0f74d8;
--chart-2: #28a5ea;
--chart-3: #2fbe93;
--chart-4: #ff8b52;
--chart-5: #f2c84b;
--radius: 1rem;
--sidebar: rgba(255, 255, 255, 0.86);
--sidebar-foreground: #12263f;
--sidebar-primary: #0f74d8;
--ring: #5b5ff9;
--chart-1: #5b5ff9;
--chart-2: #22b8cf;
--chart-3: #51cf66;
--chart-4: #ff6b6b;
--chart-5: #fcc419;
--radius: 0.75rem;
--sidebar: #ffffff;
--sidebar-foreground: #1a1a1a;
--sidebar-primary: #5b5ff9;
--sidebar-primary-foreground: #ffffff;
--sidebar-accent: #eff5fb;
--sidebar-accent-foreground: #123c67;
--sidebar-border: rgba(16, 74, 132, 0.12);
--sidebar-ring: #0f74d8;
--sidebar-accent: #f8f9fa;
--sidebar-accent-foreground: #1a1a1a;
--sidebar-border: rgba(0, 0, 0, 0.06);
--sidebar-ring: #5b5ff9;
}
.dark {
......@@ -126,26 +126,6 @@
body {
@apply bg-background text-foreground;
font-family: var(--font-sans-brand);
min-height: 100vh;
background-image:
radial-gradient(circle at top left, rgba(30, 165, 255, 0.18), transparent 26%),
radial-gradient(circle at bottom right, rgba(12, 59, 106, 0.12), transparent 24%),
linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(255, 255, 255, 0.72));
background-attachment: fixed;
}
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
background-image:
linear-gradient(rgba(15, 87, 157, 0.035) 1px, transparent 1px),
linear-gradient(90deg, rgba(15, 87, 157, 0.035) 1px, transparent 1px);
background-size: 28px 28px;
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.7), transparent 92%);
z-index: -1;
}
/**
......@@ -198,9 +178,4 @@
font-weight: var(--font-weight-normal);
line-height: 1.5;
}
::selection {
background: rgba(15, 116, 216, 0.18);
color: var(--foreground);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment