feat(frontend): 对齐万华门户风格并更新全量截图文档
- 新增门户导航子页面(交易信息、政策法规、操作指南、常见问题、采购平台)并统一门户壳层样式 - 按万华站点风格重构首页与登录页(导航、轮播、公告、登录区) - 优化小滨助手:首页/登录页接入、可拖拽吸边、圆形图标、圆形外框与切换动画优化 - 重新生成全量页面截图并更新《滨化智慧招标平台-前端界面截图汇总.docx》 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,17 +1,27 @@
|
||||
import { useState } from "react";
|
||||
import { useNavigate, Link } from "react-router";
|
||||
import { Hexagon, User, Lock, Smartphone, ShieldCheck, ArrowRight, Eye, EyeOff, Info } from "lucide-react";
|
||||
import { Hexagon, User, Lock, Smartphone, ShieldCheck, Eye, EyeOff } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { cn } from "../components/ui/utils";
|
||||
import { XiaobinAssistant } from "../components/XiaobinAssistant";
|
||||
|
||||
type Mode = "employee" | "vendor";
|
||||
type Tab = "account" | "mobile";
|
||||
type LoginRole = "purchaser" | "supplier" | "expert" | "other";
|
||||
|
||||
const ROLE_BUTTONS: { id: LoginRole; label: string; en: string }[] = [
|
||||
{ id: "purchaser", label: "采购人", en: "Purchaser" },
|
||||
{ id: "supplier", label: "供应商", en: "Supplier" },
|
||||
{ id: "expert", label: "专家", en: "Expert" },
|
||||
{ id: "other", label: "其他", en: "Other" },
|
||||
];
|
||||
|
||||
export function LoginPage() {
|
||||
const navigate = useNavigate();
|
||||
const [mode, setMode] = useState<Mode>("vendor");
|
||||
const [tab, setTab] = useState<Tab>("account");
|
||||
const [loginRole, setLoginRole] = useState<LoginRole>("supplier");
|
||||
const [account, setAccount] = useState("zhangwei");
|
||||
const [pwd, setPwd] = useState("123456");
|
||||
const [showPwd, setShowPwd] = useState(false);
|
||||
@@ -48,70 +58,59 @@ export function LoginPage() {
|
||||
navigate("/app");
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-screen w-full overflow-hidden bg-[#f5f7fa]">
|
||||
{/* 左侧品牌区 */}
|
||||
<div className="relative hidden w-1/2 flex-col justify-between overflow-hidden bg-brand-gradient p-12 text-white lg:flex">
|
||||
<Link to="/portal" className="flex items-center gap-3">
|
||||
<div className="flex size-11 items-center justify-center rounded-xl bg-white/15 backdrop-blur">
|
||||
<Hexagon className="size-6" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-lg font-semibold">滨化集团智慧招标平台</div>
|
||||
<div className="text-sm text-white/70">Smart Tendering Platform</div>
|
||||
</div>
|
||||
</Link>
|
||||
function selectRole(role: LoginRole) {
|
||||
setLoginRole(role);
|
||||
// 与现有登录逻辑联动:供应商走外部账号,其他角色默认走内部员工
|
||||
if (role === "supplier") {
|
||||
setMode("vendor");
|
||||
setTab("account");
|
||||
} else {
|
||||
setMode("employee");
|
||||
setTab("account");
|
||||
}
|
||||
}
|
||||
|
||||
<div className="relative z-10">
|
||||
<h1 className="text-white" style={{ fontSize: 44, lineHeight: 1.2, fontWeight: 700, letterSpacing: 2 }}>
|
||||
智慧招标平台
|
||||
</h1>
|
||||
<p className="mt-5 max-w-md text-white/80">
|
||||
AI 原生 · 全流程线上闭环 · 主动式智能
|
||||
return (
|
||||
<div className="min-h-screen bg-[#f3f5f8]">
|
||||
<header className="border-b bg-[#0f4ea6] text-white">
|
||||
<div className="mx-auto flex h-14 max-w-[1200px] items-center justify-between px-6">
|
||||
<Link to="/portal" className="flex items-center gap-2">
|
||||
<Hexagon className="size-5" />
|
||||
<span className="text-base font-semibold">滨化电子招标投标交易网</span>
|
||||
</Link>
|
||||
<div className="text-xs text-white/80">欢迎登录 STP 系统</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="mx-auto grid max-w-[1200px] grid-cols-12 gap-4 px-6 py-8">
|
||||
<section className="col-span-12 border bg-white p-5 lg:col-span-4">
|
||||
<h2 className="text-lg font-semibold">用户登录</h2>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
还没有账号?
|
||||
<Link to="/register" className="ml-1 text-primary hover:underline">去注册</Link>
|
||||
</p>
|
||||
<p className="mt-2 max-w-md text-sm text-white/60">
|
||||
覆盖公开招标 · 邀请招标 · 竞争性谈判 · 单一来源
|
||||
</p>
|
||||
<div className="mt-8 grid grid-cols-3 gap-4">
|
||||
{[
|
||||
{ k: "全流程", v: "9 大阶段闭环" },
|
||||
{ k: "AI 寻源", v: "委托效率 +60%" },
|
||||
{ k: "链上存证", v: "投标哈希上链" },
|
||||
].map((s) => (
|
||||
<div key={s.k} className="rounded-xl bg-white/10 p-4 backdrop-blur">
|
||||
<div className="text-lg font-semibold">{s.k}</div>
|
||||
<div className="mt-1 text-xs text-white/70">{s.v}</div>
|
||||
</div>
|
||||
|
||||
{/* 角色登录按钮:对齐万华站点风格 */}
|
||||
<div className="mt-4 grid grid-cols-2 gap-2">
|
||||
{ROLE_BUTTONS.map((r) => (
|
||||
<button
|
||||
key={r.id}
|
||||
type="button"
|
||||
onClick={() => selectRole(r.id)}
|
||||
className={cn(
|
||||
"border px-3 py-3 text-center transition-colors",
|
||||
loginRole === r.id
|
||||
? "border-primary bg-[#eef5ff] text-primary"
|
||||
: "border-[#d9dee7] bg-white text-[#374151] hover:border-primary/60 hover:bg-[#f8fbff]",
|
||||
)}
|
||||
>
|
||||
<div className="text-sm font-medium leading-none">{r.label}</div>
|
||||
<div className="mt-1 text-[11px] text-[#6b7280]">{r.en}</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-white/50">© 2026 滨化集团 | 智慧招标平台 V1.0</div>
|
||||
|
||||
{/* 装饰 */}
|
||||
<div className="pointer-events-none absolute -right-24 top-1/4 size-80 rounded-full bg-white/10 blur-3xl" />
|
||||
<div className="pointer-events-none absolute -bottom-16 right-1/3 size-60 rounded-full bg-white/10 blur-3xl" />
|
||||
<div className="pointer-events-none absolute left-1/2 top-1/2 size-72 -translate-x-1/2 -translate-y-1/2 rounded-full border border-white/10" />
|
||||
<div className="pointer-events-none absolute left-1/2 top-1/2 size-52 -translate-x-1/2 -translate-y-1/2 rounded-full border border-white/10" />
|
||||
</div>
|
||||
|
||||
{/* 右侧表单区 */}
|
||||
<div className="flex flex-1 items-center justify-center p-8">
|
||||
<div className="w-full max-w-[400px]">
|
||||
<div className="mb-6 lg:hidden">
|
||||
<div className="flex items-center gap-2">
|
||||
<Hexagon className="size-7 text-primary" />
|
||||
<span className="font-semibold">滨化智慧招标平台</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
<h2 className="text-foreground" style={{ fontSize: 24 }}>欢迎登录</h2>
|
||||
<p className="mt-1 text-sm text-muted-foreground">登录您的账户,开始智能招采之旅</p>
|
||||
</div>
|
||||
|
||||
{/* 角色切换开关: 内部员工 / 外部账号 */}
|
||||
<div className="mt-6 flex rounded-full bg-muted p-1">
|
||||
<div className="mt-4 flex border bg-[#f8fafc] p-1">
|
||||
{(
|
||||
[
|
||||
{ id: "employee" as Mode, label: "内部员工" },
|
||||
@@ -123,20 +122,19 @@ export function LoginPage() {
|
||||
type="button"
|
||||
onClick={() => setMode(m.id)}
|
||||
className={cn(
|
||||
"flex-1 rounded-full py-2 text-sm font-medium transition-all",
|
||||
mode === m.id ? "bg-brand-gradient text-white shadow-sm" : "text-muted-foreground hover:text-foreground",
|
||||
"flex-1 py-2 text-sm",
|
||||
mode === m.id ? "bg-primary font-medium text-white" : "text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
{m.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-2 text-center text-xs text-primary">
|
||||
{mode === "employee" ? "当前:内部员工模式(走 IAM 集团统一认证)" : "当前:外部账号模式(走平台账号 / SRM 认证)"}
|
||||
<p className="mt-1 text-[11px] text-muted-foreground">
|
||||
当前角色:{ROLE_BUTTONS.find((x) => x.id === loginRole)?.label}
|
||||
</p>
|
||||
|
||||
{/* Tab: 账号登录 / 手机验证码 */}
|
||||
<div className="mt-5 flex border-b border-border">
|
||||
<div className="mt-3 flex border-b border-border">
|
||||
{(
|
||||
[
|
||||
{ id: "account" as Tab, label: "账号登录" },
|
||||
@@ -148,17 +146,17 @@ export function LoginPage() {
|
||||
type="button"
|
||||
onClick={() => setTab(t.id)}
|
||||
className={cn(
|
||||
"relative -mb-px px-4 pb-2.5 text-sm transition-colors",
|
||||
tab === t.id ? "font-medium text-foreground" : "text-muted-foreground hover:text-foreground",
|
||||
"relative px-4 py-2 text-sm",
|
||||
tab === t.id ? "font-medium text-primary" : "text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
{t.label}
|
||||
{tab === t.id && <span className="absolute inset-x-2 -bottom-px h-0.5 rounded-full bg-brand-gradient" />}
|
||||
{tab === t.id && <span className="absolute inset-x-1 bottom-0 h-0.5 bg-primary" />}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<form className="mt-5 space-y-4" onSubmit={submit}>
|
||||
<form className="mt-4 space-y-3" onSubmit={submit}>
|
||||
{tab === "account" ? (
|
||||
<>
|
||||
<div>
|
||||
@@ -248,12 +246,12 @@ export function LoginPage() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Button type="submit" className="h-11 w-full bg-brand-gradient text-base hover:opacity-90">
|
||||
登 录 <ArrowRight className="size-4" />
|
||||
<Button type="submit" className="h-10 w-full text-base">
|
||||
登 录
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<div className="mt-5 text-center text-sm text-muted-foreground">
|
||||
<div className="mt-4 text-center text-sm text-muted-foreground">
|
||||
还没有账号?
|
||||
{mode === "employee" ? (
|
||||
<span className="ml-1 text-muted-foreground/70">员工账号由 HR 系统统一同步</span>
|
||||
@@ -263,22 +261,57 @@ export function LoginPage() {
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-4 border bg-[#fffbea] px-3 py-2 text-xs text-[#92400e]">
|
||||
原 SRM 注册用户,可直接使用 SRM 账号登录,无需重复注册。
|
||||
</div>
|
||||
|
||||
{/* SRM 温馨提示 */}
|
||||
{mode === "vendor" && (
|
||||
<div className="mt-5 flex items-start gap-2 rounded-lg border border-[#ffcc80] bg-[#fff3e0] px-3 py-2.5 text-xs text-[#e65100]">
|
||||
<Info className="mt-0.5 size-4 shrink-0" />
|
||||
<span>原 SRM 注册用户,可直接使用 SRM 账号密码登录,无需重复注册。</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-6 text-center">
|
||||
<div className="mt-4 text-center">
|
||||
<Link to="/portal" className="text-xs text-muted-foreground hover:text-primary">
|
||||
浏览平台首页与公开招标公告 →
|
||||
返回门户首页
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="col-span-12 space-y-4 lg:col-span-8">
|
||||
<div className="border bg-white">
|
||||
<div className="border-b bg-[#f8fafc] px-4 py-3 text-sm font-semibold">交易信息</div>
|
||||
<ul className="space-y-1 p-4 text-sm">
|
||||
{[
|
||||
["[公开招标] 扣电测试柜框架", "2026-07-13"],
|
||||
["[公开招标] 2026年橡胶密封件框架招标O型圈", "2026-07-13"],
|
||||
["[公开招标] 万华莱州100MW分散式风电项目EPC工程总承包[变更公告]", "2026-07-13"],
|
||||
["[公开招标] 万华旋塞阀框架包一 金属旋塞阀、包二 衬氟旋塞阀", "2026-07-10"],
|
||||
["[公开招标] 改性TPU熟化料仓", "2026-07-09"],
|
||||
].map(([title, date]) => (
|
||||
<li key={title} className="flex items-center gap-3 border-b border-dashed py-1.5">
|
||||
<span className="line-clamp-1 flex-1 hover:text-primary">{title}</span>
|
||||
<span className="text-xs text-muted-foreground">{date}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="border bg-white">
|
||||
<div className="border-b bg-[#f8fafc] px-4 py-3 text-sm font-semibold">通知公告</div>
|
||||
<div className="space-y-1 p-4 text-sm text-muted-foreground">
|
||||
<p>万华蓬莱园区高温管道耐火衬里类物资供应商招募</p>
|
||||
<p>万华化学桨叶冷却机类供应商招募</p>
|
||||
<p>万华化学洗车平台服务类供应商招募</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border bg-white">
|
||||
<div className="border-b bg-[#f8fafc] px-4 py-3 text-sm font-semibold">操作指南</div>
|
||||
<div className="space-y-1 p-4 text-sm text-muted-foreground">
|
||||
<p>供应商注册操作指南</p>
|
||||
<p>投标文件制作软件操作手册</p>
|
||||
<p>系统使用常见问题处理</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<XiaobinAssistant pageType="login" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user