3dba6db9d2
统一清理前端万华相关文案与公司展示口径为滨化集团,移除登录与门户页角色选框,并同步更新全量页面截图及Word汇总文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
593 lines
28 KiB
TypeScript
593 lines
28 KiB
TypeScript
import { useMemo, useState } from "react";
|
||
import { useNavigate, Link } from "react-router";
|
||
import {
|
||
Hexagon,
|
||
ArrowLeft,
|
||
ArrowRight,
|
||
UploadCloud,
|
||
CheckCircle2,
|
||
Loader2,
|
||
XCircle,
|
||
Building2,
|
||
UserRound,
|
||
ShieldCheck,
|
||
X,
|
||
Eye,
|
||
EyeOff,
|
||
Info,
|
||
} from "lucide-react";
|
||
import { toast } from "sonner";
|
||
import { Button } from "../components/ui/button";
|
||
import { cn } from "../components/ui/utils";
|
||
|
||
type Registrant = "supplier" | "expert";
|
||
type AuditState = "idle" | "auditing" | "success" | "rejected";
|
||
|
||
const SUPPLIER_STEPS = ["企业信息", "联系人", "提交 / 自动审核"];
|
||
const EXPERT_STEPS = ["基本信息", "专业资质 / 收款", "提交审核"];
|
||
|
||
interface PwdRule {
|
||
label: string;
|
||
test: (v: string) => boolean;
|
||
}
|
||
|
||
const PWD_RULES: PwdRule[] = [
|
||
{ label: "长度 8~20 位", test: (v) => v.length >= 8 && v.length <= 20 },
|
||
{ label: "包含大写字母(A-Z)与小写字母(a-z)", test: (v) => /[A-Z]/.test(v) && /[a-z]/.test(v) },
|
||
{ label: "包含数字(0-9)与特殊字符(!@#$%^&*)", test: (v) => /\d/.test(v) && /[!@#$%^&*()_+\-=]/.test(v) },
|
||
{ label: "禁止连续/重复字符(如 12345678、aaaa)", test: (v) => !/(.)\1{3,}/.test(v) && !/0123|1234|2345|3456|4567|5678|6789/.test(v) },
|
||
{ label: "非常见弱口令(password、admin123 等)", test: (v) => !["password", "admin123", "12345678", "qwerty"].includes(v.toLowerCase()) },
|
||
];
|
||
|
||
function Field({
|
||
label,
|
||
placeholder,
|
||
required,
|
||
hint,
|
||
className,
|
||
type = "text",
|
||
readOnly,
|
||
}: {
|
||
label: string;
|
||
placeholder?: string;
|
||
required?: boolean;
|
||
hint?: string;
|
||
className?: string;
|
||
type?: string;
|
||
readOnly?: boolean;
|
||
}) {
|
||
return (
|
||
<div className={className}>
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">
|
||
{label} {required && <span className="text-[#e91e63]">*</span>}
|
||
</label>
|
||
<input
|
||
type={type}
|
||
readOnly={readOnly}
|
||
placeholder={placeholder}
|
||
className={cn(
|
||
"h-11 w-full rounded-lg border bg-input-background px-3 text-sm outline-none transition-colors focus:border-primary",
|
||
readOnly && "bg-muted text-muted-foreground",
|
||
)}
|
||
/>
|
||
{hint && <p className="mt-1 text-xs text-muted-foreground">{hint}</p>}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
function StepBar({ steps, current }: { steps: string[]; current: number }) {
|
||
return (
|
||
<div className="flex items-center justify-center rounded-full border bg-white px-6 py-4 shadow-sm">
|
||
{steps.map((s, i) => (
|
||
<div key={s} className="flex items-center">
|
||
<div className="flex flex-col items-center">
|
||
<div
|
||
className={cn(
|
||
"flex size-9 items-center justify-center rounded-full text-sm font-bold transition-colors",
|
||
i <= current ? "bg-brand-gradient text-white" : "bg-muted text-muted-foreground",
|
||
)}
|
||
>
|
||
{i < current ? <CheckCircle2 className="size-5" /> : i + 1}
|
||
</div>
|
||
<span className={cn("mt-2 text-xs", i <= current ? "font-medium text-primary" : "text-muted-foreground")}>{s}</span>
|
||
</div>
|
||
{i < steps.length - 1 && (
|
||
<div className={cn("mx-3 mb-6 h-0.5 w-16 rounded-full sm:w-24", i < current ? "bg-brand-gradient" : "bg-border")} />
|
||
)}
|
||
</div>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
function Notice({ items }: { items: string[] }) {
|
||
return (
|
||
<div className="rounded-xl border border-[#ffcc80] bg-[#fff3e0] p-4">
|
||
<div className="flex items-center gap-1.5 text-sm font-semibold text-[#e65100]">
|
||
<Info className="size-4" /> 注册须知
|
||
</div>
|
||
<ol className="mt-2 space-y-1.5 text-xs leading-relaxed text-[#bf360c]">
|
||
{items.map((t, i) => (
|
||
<li key={i}>
|
||
{i + 1}. {t}
|
||
</li>
|
||
))}
|
||
</ol>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export function RegisterPage() {
|
||
const navigate = useNavigate();
|
||
const [registrant, setRegistrant] = useState<Registrant>("supplier");
|
||
const [step, setStep] = useState(0);
|
||
const [ocr, setOcr] = useState<"none" | "scanning" | "done">("none");
|
||
const [audit, setAudit] = useState<AuditState>("idle");
|
||
const [products, setProducts] = useState<string[]>(["工业阀门", "管道配件"]);
|
||
const [productInput, setProductInput] = useState("");
|
||
const [pwd, setPwd] = useState("");
|
||
const [confirmPwd, setConfirmPwd] = useState("");
|
||
const [showPwd, setShowPwd] = useState(false);
|
||
const [smsCountdown, setSmsCountdown] = useState(0);
|
||
|
||
const steps = registrant === "supplier" ? SUPPLIER_STEPS : EXPERT_STEPS;
|
||
|
||
const passedRules = useMemo(() => PWD_RULES.map((r) => r.test(pwd)), [pwd]);
|
||
const passedCount = passedRules.filter(Boolean).length;
|
||
const strength: 0 | 1 | 2 = passedCount >= 5 && pwd.length >= 12 ? 2 : passedCount >= 4 ? 1 : 0;
|
||
|
||
function switchRegistrant(r: Registrant) {
|
||
setRegistrant(r);
|
||
setStep(0);
|
||
setAudit("idle");
|
||
setOcr("none");
|
||
}
|
||
|
||
function triggerOcr() {
|
||
setOcr("scanning");
|
||
setTimeout(() => {
|
||
setOcr("done");
|
||
toast.success("营业执照识别完成,已自动回填企业信息");
|
||
}, 1500);
|
||
}
|
||
|
||
function addProduct() {
|
||
const v = productInput.trim();
|
||
if (v && products.length < 20 && !products.includes(v)) {
|
||
setProducts((p) => [...p, v]);
|
||
}
|
||
setProductInput("");
|
||
}
|
||
|
||
function sendSms() {
|
||
toast.success("验证码已发送");
|
||
setSmsCountdown(60);
|
||
const t = setInterval(() => {
|
||
setSmsCountdown((c) => {
|
||
if (c <= 1) {
|
||
clearInterval(t);
|
||
return 0;
|
||
}
|
||
return c - 1;
|
||
});
|
||
}, 1000);
|
||
}
|
||
|
||
function submitAudit() {
|
||
setStep(steps.length - 1);
|
||
setAudit("auditing");
|
||
setTimeout(() => {
|
||
setAudit("success");
|
||
}, 3800);
|
||
}
|
||
|
||
const isLastFormStep = step === steps.length - 2;
|
||
|
||
return (
|
||
<div className="min-h-screen bg-[#f5f7fa]">
|
||
<header className="flex h-16 items-center justify-between border-b bg-card px-8">
|
||
<div className="flex items-center gap-2.5">
|
||
<div className="flex size-8 items-center justify-center rounded-lg bg-brand-gradient">
|
||
<Hexagon className="size-5 text-white" />
|
||
</div>
|
||
<span className="font-semibold">滨化集团智慧招标平台 · 新用户注册</span>
|
||
</div>
|
||
<Link to="/" className="flex items-center gap-1 text-sm text-muted-foreground hover:text-primary">
|
||
<ArrowLeft className="size-4" /> 返回登录
|
||
</Link>
|
||
</header>
|
||
|
||
<div className="mx-auto max-w-5xl px-6 py-8">
|
||
{/* 注册对象选择 */}
|
||
<div className="mb-6 flex justify-center gap-3">
|
||
{(
|
||
[
|
||
{ id: "supplier" as Registrant, label: "供应商注册", icon: Building2 },
|
||
{ id: "expert" as Registrant, label: "外部专家注册", icon: UserRound },
|
||
]
|
||
).map((r) => {
|
||
const Icon = r.icon;
|
||
return (
|
||
<button
|
||
key={r.id}
|
||
onClick={() => switchRegistrant(r.id)}
|
||
className={cn(
|
||
"flex items-center gap-2 rounded-full border px-5 py-2.5 text-sm font-medium transition-all",
|
||
registrant === r.id
|
||
? "border-transparent bg-brand-gradient text-white shadow-sm"
|
||
: "border-border bg-white text-muted-foreground hover:border-primary hover:text-primary",
|
||
)}
|
||
>
|
||
<Icon className="size-4" /> {r.label}
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
<div className="mb-6 flex items-center justify-between gap-4">
|
||
<StepBar steps={steps} current={step} />
|
||
<div className="hidden shrink-0 items-center gap-1.5 rounded-full border border-[#4caf50] bg-[#e8f5e9] px-3 py-1.5 text-xs text-[#2e7d32] lg:flex">
|
||
<ShieldCheck className="size-3.5" /> AI 即时审核 · 秒级通过
|
||
</div>
|
||
</div>
|
||
|
||
{/* ============ 供应商注册 ============ */}
|
||
{registrant === "supplier" && (
|
||
<>
|
||
{step === 0 && (
|
||
<div className="grid gap-6 lg:grid-cols-[1fr_300px]">
|
||
<div className="rounded-2xl bg-card p-8 shadow-sm">
|
||
<h3 className="text-foreground">供应商注册</h3>
|
||
<p className="mt-1 text-sm text-muted-foreground">请填写企业真实信息,上传营业执照,系统将自动识别并回填</p>
|
||
<div className="my-5 h-px bg-border" />
|
||
|
||
{/* 营业执照上传 */}
|
||
<div
|
||
onClick={triggerOcr}
|
||
className="flex cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed border-primary bg-[#fafbfc] py-6 transition-colors hover:bg-secondary/40"
|
||
>
|
||
<UploadCloud className="mb-2 size-7 text-primary" />
|
||
<div className="text-sm font-medium text-primary">上传营业执照(JPG/PNG/PDF,≤10MB)</div>
|
||
<div className="mt-1 text-xs text-muted-foreground">支持拖拽或点击上传,AI 将自动识别企业信息并填充表单</div>
|
||
</div>
|
||
|
||
{ocr === "scanning" && (
|
||
<div className="mt-3 flex items-center gap-2 rounded-lg bg-[#fff8e1] px-3 py-2 text-sm text-[#e65100]">
|
||
<Loader2 className="size-4 animate-spin" /> 正在识别营业执照...
|
||
</div>
|
||
)}
|
||
{ocr === "done" && (
|
||
<div className="mt-3 flex items-center gap-2 rounded-lg border border-[#a5d6a7] bg-[#e8f5e9] px-3 py-2 text-sm text-[#2e7d32]">
|
||
<CheckCircle2 className="size-4" /> 已识别:营业执照信息提取成功(统一信用代码:91370100XXXXXXXXXX)
|
||
</div>
|
||
)}
|
||
|
||
<div className="mt-6 grid grid-cols-2 gap-x-5 gap-y-4">
|
||
<Field label="企业全称" required placeholder="系统自动识别或手动输入" className="col-span-2" />
|
||
<Field label="统一社会信用代码" required placeholder="18 位代码" />
|
||
<Field label="注册资本(万元)" required placeholder="请输入数字" />
|
||
<Field label="法定代表人" required placeholder="请输入法定代表人姓名" />
|
||
<Field label="行业分类" required placeholder="请选择或搜索行业(GB/T 4754)" />
|
||
<Field label="注册地址" required placeholder="请填写详细地址" className="col-span-2" />
|
||
<div className="col-span-2">
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">
|
||
经营范围 <span className="text-[#e91e63]">*</span>
|
||
</label>
|
||
<textarea
|
||
rows={2}
|
||
placeholder="系统自动识别或手动输入,不超过 500 字"
|
||
className="w-full resize-none rounded-lg border bg-input-background px-3 py-2 text-sm outline-none transition-colors focus:border-primary"
|
||
/>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">
|
||
主要产品 <span className="text-[#e91e63]">*</span>
|
||
</label>
|
||
<div className="flex gap-2">
|
||
<input
|
||
value={productInput}
|
||
onChange={(e) => setProductInput(e.target.value)}
|
||
onKeyDown={(e) => e.key === "Enter" && (e.preventDefault(), addProduct())}
|
||
placeholder="输入产品名称,回车添加"
|
||
className="h-11 flex-1 rounded-lg border bg-input-background px-3 text-sm outline-none transition-colors focus:border-primary"
|
||
/>
|
||
<Button type="button" variant="outline" className="h-11" onClick={addProduct}>
|
||
+ 添加
|
||
</Button>
|
||
</div>
|
||
<div className="mt-2 flex flex-wrap gap-2">
|
||
{products.map((p) => (
|
||
<span
|
||
key={p}
|
||
className="flex items-center gap-1 rounded-full border border-primary bg-secondary px-3 py-1 text-xs text-primary"
|
||
>
|
||
{p}
|
||
<button onClick={() => setProducts((ps) => ps.filter((x) => x !== p))}>
|
||
<X className="size-3" />
|
||
</button>
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<Notice
|
||
items={[
|
||
"请确保信息与营业执照一致",
|
||
"统一社会信用代码将作为唯一标识",
|
||
"提交后由 AI 即时自动审核",
|
||
"审核通过后可参与投标报名",
|
||
"已有 SRM 账号请直接登录",
|
||
]}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{step === 1 && (
|
||
<div className="mx-auto max-w-2xl rounded-2xl bg-card p-8 shadow-sm">
|
||
<h3 className="text-foreground">联系人信息</h3>
|
||
<div className="my-5 h-px bg-border" />
|
||
<div className="space-y-4">
|
||
<Field label="联系人姓名" required placeholder="请输入联系人姓名" hint="必填,最大 64 字符" />
|
||
<Field label="联系电话(手机号)" required placeholder="请输入 11 位手机号" hint="必填,格式校验,全局唯一" />
|
||
<Field label="电子邮箱" required placeholder="请输入常用邮箱" hint="必填,格式校验,全局唯一" />
|
||
<div>
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">
|
||
短信验证码 <span className="text-[#e91e63]">*</span>
|
||
</label>
|
||
<div className="flex gap-3">
|
||
<input
|
||
placeholder="点击发送验证码"
|
||
className="h-11 flex-1 rounded-lg border bg-input-background px-3 text-sm outline-none transition-colors focus:border-primary"
|
||
/>
|
||
<button
|
||
type="button"
|
||
onClick={sendSms}
|
||
disabled={smsCountdown > 0}
|
||
className="h-11 w-32 shrink-0 rounded-lg bg-brand-gradient text-sm font-medium text-white transition-opacity hover:opacity-90 disabled:opacity-50"
|
||
>
|
||
{smsCountdown > 0 ? `${smsCountdown}s 后重发` : "发送验证码"}
|
||
</button>
|
||
</div>
|
||
<p className="mt-1 text-xs text-muted-foreground">用于验证手机号真实性(注册必验)</p>
|
||
</div>
|
||
|
||
{/* 密码 */}
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">
|
||
输入密码 <span className="text-[#e91e63]">*</span>
|
||
</label>
|
||
<div className="relative">
|
||
<input
|
||
type={showPwd ? "text" : "password"}
|
||
value={pwd}
|
||
onChange={(e) => setPwd(e.target.value)}
|
||
placeholder="请设置登录密码"
|
||
className="h-11 w-full rounded-lg border bg-input-background px-3 pr-10 text-sm outline-none transition-colors focus:border-primary"
|
||
/>
|
||
<button
|
||
type="button"
|
||
onClick={() => setShowPwd((s) => !s)}
|
||
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground"
|
||
>
|
||
{showPwd ? <EyeOff className="size-4" /> : <Eye className="size-4" />}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">
|
||
确认密码 <span className="text-[#e91e63]">*</span>
|
||
</label>
|
||
<input
|
||
type={showPwd ? "text" : "password"}
|
||
value={confirmPwd}
|
||
onChange={(e) => setConfirmPwd(e.target.value)}
|
||
placeholder="请再次输入密码"
|
||
className={cn(
|
||
"h-11 w-full rounded-lg border bg-input-background px-3 text-sm outline-none transition-colors focus:border-primary",
|
||
confirmPwd && confirmPwd !== pwd && "border-destructive",
|
||
)}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 密码复杂度要求 */}
|
||
<div className="rounded-xl border bg-[#f8fafc] p-4">
|
||
<div className="text-sm font-medium text-[#374151]">密码复杂度要求</div>
|
||
<ul className="mt-2 space-y-1.5">
|
||
{PWD_RULES.map((r, i) => (
|
||
<li key={r.label} className="flex items-center gap-2 text-[13px]">
|
||
<span className={passedRules[i] ? "text-[#10b981]" : "text-[#ef4444]"}>{passedRules[i] ? "✔" : "✘"}</span>
|
||
<span className="text-[#374151]">{r.label}</span>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
{/* 强度条 */}
|
||
<div className="mt-3 flex items-center gap-3">
|
||
<span className="text-xs text-muted-foreground">密码强度</span>
|
||
<div className="h-2 w-40 overflow-hidden rounded-full bg-[#e5e7eb]">
|
||
<div
|
||
className={cn(
|
||
"h-full rounded-full transition-all",
|
||
strength === 0 ? "w-1/3 bg-[#ef4444]" : strength === 1 ? "w-2/3 bg-[#f59e0b]" : "w-full bg-[#10b981]",
|
||
)}
|
||
/>
|
||
</div>
|
||
<span
|
||
className={cn(
|
||
"text-xs font-medium",
|
||
strength === 0 ? "text-[#ef4444]" : strength === 1 ? "text-[#f59e0b]" : "text-[#10b981]",
|
||
)}
|
||
>
|
||
{strength === 0 ? "弱" : strength === 1 ? "中" : "强"}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</>
|
||
)}
|
||
|
||
{/* ============ 外部专家注册 ============ */}
|
||
{registrant === "expert" && (
|
||
<>
|
||
{step === 0 && (
|
||
<div className="grid gap-6 lg:grid-cols-[1fr_300px]">
|
||
<div className="rounded-2xl bg-card p-8 shadow-sm">
|
||
<h3 className="text-foreground">外部专家注册</h3>
|
||
<p className="mt-1 text-sm text-muted-foreground">请完整填写以下信息,所有数据将受到严格加密保护</p>
|
||
<div className="my-5 h-px bg-border" />
|
||
<div className="grid grid-cols-2 gap-x-5 gap-y-4">
|
||
<Field label="真实姓名" required placeholder="请输入中文姓名" />
|
||
<Field label="性别" required placeholder="请选择" />
|
||
<Field label="身份证号码" required placeholder="请输入 18 位身份证号" hint="🔒 将使用 AES-256 加密存储" className="col-span-2" />
|
||
<Field label="出生日期" placeholder="由身份证自动识别" readOnly />
|
||
<Field label="年龄" placeholder="自动计算" readOnly />
|
||
<Field label="手机号码" required placeholder="请输入手机号" />
|
||
<Field label="电子邮箱" required placeholder="请输入常用邮箱" />
|
||
<Field label="工作单位" placeholder="请输入单位全称" />
|
||
<Field label="现从事专业" required placeholder="如:化工工艺、设备管理" />
|
||
<Field label="技术职称" required placeholder="高级 / 副高级 / 中级" />
|
||
<Field label="职称专业" placeholder="如:化学工程" />
|
||
<div className="col-span-2">
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">
|
||
职称 / 资质证书扫描件 <span className="text-[#e91e63]">*</span>
|
||
</label>
|
||
<div className="flex cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed border-primary bg-[#fafbfc] py-5 hover:bg-secondary/40">
|
||
<UploadCloud className="mb-1.5 size-6 text-primary" />
|
||
<div className="text-sm text-primary">点击上传或拖拽文件(支持 PDF/JPG/PNG,≤20MB)</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<Notice
|
||
items={[
|
||
"所有信息须与身份证及职称证书一致",
|
||
"滨化集团将对信息进行真实性核验",
|
||
"入库专家须遵守《评委管理规定》",
|
||
"至少具备中级及以上职称方可入库",
|
||
"个人信息变更需及时在线更新",
|
||
]}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{step === 1 && (
|
||
<div className="mx-auto max-w-2xl rounded-2xl bg-card p-8 shadow-sm">
|
||
<h3 className="text-foreground">专业资质与收款账户</h3>
|
||
<div className="my-5 h-px bg-border" />
|
||
<div className="grid grid-cols-2 gap-x-5 gap-y-4">
|
||
<div className="col-span-2">
|
||
<label className="mb-1.5 block text-sm text-[#4a5568]">擅长领域标签(用于智能匹配)</label>
|
||
<input
|
||
placeholder="如:石油化工、反应工程、分离技术,逗号分隔"
|
||
className="h-11 w-full rounded-lg border bg-input-background px-3 text-sm outline-none focus:border-primary"
|
||
/>
|
||
</div>
|
||
<Field label="开户银行" placeholder="如:中国银行北京分行" />
|
||
<Field label="银行账号" placeholder="请输入收款账号" hint="🔒 将使用 AES-256 加密存储" />
|
||
<label className="col-span-2 mt-2 flex items-start gap-2 rounded-lg border border-[#ffcc80] bg-[#fff3e0] p-3 text-xs text-[#bf360c]">
|
||
<input type="checkbox" className="mt-0.5 size-4 accent-[var(--primary)]" />
|
||
我已阅读并同意签署《评标纪律承诺书》,承诺客观公正评审,遵守评委管理规定。
|
||
</label>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</>
|
||
)}
|
||
|
||
{/* ============ 提交 / 自动审核态(两种注册对象共用最后一步) ============ */}
|
||
{step === steps.length - 1 && (
|
||
<div className="mx-auto max-w-lg">
|
||
{audit === "auditing" && (
|
||
<div className="rounded-2xl bg-card p-10 text-center shadow-sm">
|
||
<Loader2 className="mx-auto size-14 animate-spin text-primary" />
|
||
<div className="mt-5 text-lg font-bold text-foreground">
|
||
{registrant === "supplier" ? "AI 正在审核企业信息..." : "已提交,AI 正在初审..."}
|
||
</div>
|
||
<div className="mt-2 text-sm text-muted-foreground">预计 3~8 秒,请勿关闭页面</div>
|
||
<div className="mt-3 text-[13px] text-muted-foreground/80">✓ 工商信息核验 ✓ 风险扫描 ✓ 唯一性检查</div>
|
||
</div>
|
||
)}
|
||
|
||
{audit === "success" && (
|
||
<div className="rounded-2xl bg-card p-10 text-center shadow-sm">
|
||
<div className="mx-auto flex size-24 items-center justify-center rounded-full bg-[#e8f5e9]">
|
||
<CheckCircle2 className="size-14 text-[#4caf50]" />
|
||
</div>
|
||
<div className="mt-5 text-2xl font-bold text-foreground">🎉 注册成功!</div>
|
||
<p className="mt-2 text-sm text-muted-foreground">
|
||
{registrant === "supplier" ? "您的供应商账号已激活,正在自动登录..." : "您的专家账号已创建,请留意激活通知短信/邮件。"}
|
||
</p>
|
||
<div className="my-5 h-px bg-border" />
|
||
<div className="space-y-1.5 text-sm text-muted-foreground">
|
||
<div>
|
||
{registrant === "supplier" ? "供应商编号" : "专家编号"}:
|
||
<span className="font-semibold text-foreground">
|
||
{registrant === "supplier" ? "SUP_20260709_0158" : "EXP_20260709_002"}
|
||
</span>
|
||
</div>
|
||
<div>
|
||
登录账号:<span className="font-semibold text-foreground">138****8001</span>
|
||
</div>
|
||
</div>
|
||
<div className="mt-5 rounded-lg border border-[#ffcc80] bg-[#fff3e0] px-4 py-2.5 text-xs text-[#e65100]">
|
||
📌 温馨提示:参与具体项目投标时,需按招标公告要求提交资质审核材料
|
||
</div>
|
||
<Button className="mt-6 h-11 w-full bg-brand-gradient hover:opacity-90" onClick={() => navigate("/app")}>
|
||
进入工作台 <ArrowRight className="size-4" />
|
||
</Button>
|
||
</div>
|
||
)}
|
||
|
||
{audit === "rejected" && (
|
||
<div className="rounded-2xl bg-card p-10 text-center shadow-sm">
|
||
<div className="mx-auto flex size-24 items-center justify-center rounded-full bg-[#ffcdd2]">
|
||
<XCircle className="size-14 text-[#c62828]" />
|
||
</div>
|
||
<div className="mt-5 text-2xl font-bold text-[#c62828]">审核未通过</div>
|
||
<div className="mt-5 rounded-lg border bg-[#fafafa] p-4 text-left text-[13px] text-[#c62828]">
|
||
<div>• 统一社会信用代码与工商登记信息不匹配</div>
|
||
<div>• 企业状态为“注销”,不符合注册条件</div>
|
||
<div className="mt-2 text-[#666]">💡 请核对信息后重新提交,如有疑问请联系客服</div>
|
||
</div>
|
||
<Button
|
||
className="mt-6 h-11 w-full bg-brand-gradient hover:opacity-90"
|
||
onClick={() => {
|
||
setAudit("idle");
|
||
setStep(0);
|
||
}}
|
||
>
|
||
修改后重新提交
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
{/* 底部导航按钮 */}
|
||
{audit === "idle" && (
|
||
<div className="mx-auto mt-6 flex max-w-5xl items-center justify-end gap-3">
|
||
{step > 0 && (
|
||
<Button variant="outline" className="h-11 px-6" onClick={() => setStep((s) => s - 1)}>
|
||
上一步
|
||
</Button>
|
||
)}
|
||
{isLastFormStep ? (
|
||
<Button className="h-11 bg-brand-gradient px-8 hover:opacity-90" onClick={submitAudit}>
|
||
提交注册
|
||
</Button>
|
||
) : (
|
||
<Button className="h-11 bg-brand-gradient px-8 hover:opacity-90" onClick={() => setStep((s) => s + 1)}>
|
||
下一步 <ArrowRight className="size-4" />
|
||
</Button>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|