41fc6e86dd
- 新增门户导航子页面(交易信息、政策法规、操作指南、常见问题、采购平台)并统一门户壳层样式 - 按万华站点风格重构首页与登录页(导航、轮播、公告、登录区) - 优化小滨助手:首页/登录页接入、可拖拽吸边、圆形图标、圆形外框与切换动画优化 - 重新生成全量页面截图并更新《滨化智慧招标平台-前端界面截图汇总.docx》 Co-authored-by: Cursor <cursoragent@cursor.com>
222 lines
9.6 KiB
TypeScript
222 lines
9.6 KiB
TypeScript
import { useState } from "react";
|
||
import { useNavigate } from "react-router";
|
||
import { UserRound, Building2, Briefcase, Users } from "lucide-react";
|
||
import { cn } from "../components/ui/utils";
|
||
import { PortalShell } from "./portal/PortalShell";
|
||
import { XiaobinAssistant } from "../components/XiaobinAssistant";
|
||
|
||
type Notice = { title: string; date: string };
|
||
|
||
const ROLES = [
|
||
{ key: "purchaser", label: "采购人", en: "Purchaser", icon: Building2 },
|
||
{ key: "supplier", label: "供应商", en: "Supplier", icon: Briefcase },
|
||
{ key: "expert", label: "专家", en: "Expert", icon: UserRound },
|
||
{ key: "other", label: "其他", en: "Other", icon: Users },
|
||
];
|
||
const NOTICE_TABS = ["招标公告", "资格预审公告", "中标候选人公示", "结果公告", "终止公告"];
|
||
const BANNERS = [
|
||
{
|
||
title: "廉洁过节",
|
||
subtitle: "阳光招采 · 公开透明 · 全流程可追溯",
|
||
style: "from-[#1f4d8f] via-[#2e6dc2] to-[#5c8fe0]",
|
||
},
|
||
{
|
||
title: "上线试运行",
|
||
subtitle: "智慧招标平台已上线,欢迎采购人、供应商、专家使用",
|
||
style: "from-[#0d5f89] via-[#0f7da8] to-[#4ba6c9]",
|
||
},
|
||
{
|
||
title: "轮播图片2",
|
||
subtitle: "统一门户、统一身份、统一公告发布",
|
||
style: "from-[#2f5f3f] via-[#3b8460] to-[#66a37f]",
|
||
},
|
||
];
|
||
|
||
const NOTICE_DATA: Record<string, Notice[]> = {
|
||
招标公告: [
|
||
{ title: "[公开招标] 2026年地脚螺栓、不锈钢及五金紧固件框架招标", date: "2026-07-13" },
|
||
{ title: "[公开招标] 万华莱州100MW分散式风电项目EPC工程总承包[变更公告]", date: "2026-07-13" },
|
||
{ title: "[公开招标] 2026年橡胶密封件框架招标O型圈", date: "2026-07-13" },
|
||
{ title: "[公开招标] 万华旋塞阀框架包一 金属旋塞阀、包二 衬氟旋塞阀", date: "2026-07-10" },
|
||
{ title: "[公开招标] 改性TPU熟化料仓", date: "2026-07-09" },
|
||
],
|
||
资格预审公告: [
|
||
{ title: "滨州园区危化品运输服务资格预审公告", date: "2026-07-11" },
|
||
{ title: "公辅系统维保服务资格预审公告", date: "2026-07-10" },
|
||
{ title: "智慧园区网络安全服务资格预审公告", date: "2026-07-08" },
|
||
],
|
||
中标候选人公示: [
|
||
{ title: "[公开招标] 牵引车租赁服务框架中标候选人公示", date: "2026-07-07" },
|
||
{ title: "[公开招标] 电池材料项目地质勘察工程中标候选人公示", date: "2026-07-06" },
|
||
{ title: "[公开招标] 四轮防爆巡检机器人系统中标候选人公示", date: "2026-06-26" },
|
||
],
|
||
结果公告: [
|
||
{ title: "[公开招标] HDPE管道管件框架招标中标结果公告", date: "2026-07-07" },
|
||
{ title: "[公开招标] 万华起重框架招标包一 单梁起重机中标结果公告", date: "2026-07-02" },
|
||
{ title: "[公开招标] 万华海阳绿电直连光伏组件项目中标结果公告", date: "2026-06-30" },
|
||
],
|
||
终止公告: [
|
||
{ title: "国标切断双偏心蝶阀框架招标废标公告", date: "2026-07-06" },
|
||
{ title: "TPU四期熟化料仓招标废标公告", date: "2026-07-01" },
|
||
{ title: "万华滨州碳酸锂项目冷却窑废标公告", date: "2026-06-24" },
|
||
],
|
||
};
|
||
|
||
function NoticeList({ items }: { items: Notice[] }) {
|
||
return (
|
||
<ul className="space-y-1.5">
|
||
{items.map((item) => (
|
||
<li
|
||
key={item.title}
|
||
className="flex items-center gap-3 border-b border-dashed border-[#e5e7eb] py-1.5 text-sm"
|
||
>
|
||
<span className="line-clamp-1 flex-1 text-[#1f2937] hover:text-primary">{item.title}</span>
|
||
<span className="shrink-0 text-xs text-[#6b7280]">{item.date}</span>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
);
|
||
}
|
||
|
||
export function PortalHome() {
|
||
const navigate = useNavigate();
|
||
const [activeTab, setActiveTab] = useState(NOTICE_TABS[0]);
|
||
const [activeBanner, setActiveBanner] = useState(0);
|
||
const banner = BANNERS[activeBanner];
|
||
|
||
return (
|
||
<PortalShell active="home">
|
||
<section className="grid grid-cols-12 gap-4">
|
||
<div className="col-span-12 border bg-white lg:col-span-3">
|
||
<div className="border-b bg-[#f8fafc] px-4 py-3">
|
||
<h2 className="text-base font-semibold">用户登录</h2>
|
||
<p className="mt-1 text-xs text-[#6b7280]">
|
||
还没有账号,<button onClick={() => navigate("/register")} className="text-primary hover:underline">去注册</button>
|
||
</p>
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-2 p-4">
|
||
{ROLES.map((r) => {
|
||
const Icon = r.icon;
|
||
return (
|
||
<button
|
||
key={r.key}
|
||
onClick={() => navigate("/")}
|
||
className="flex flex-col items-center justify-center border border-[#d9dee7] px-3 py-3.5 text-center hover:border-primary hover:bg-[#f8fbff]"
|
||
>
|
||
<Icon className="size-5 text-primary" />
|
||
<span className="mt-2 text-sm">{r.label}</span>
|
||
<span className="text-[11px] text-[#6b7280]">{r.en}</span>
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
<div className="space-y-3 px-4 pb-4">
|
||
<input
|
||
placeholder="账号 / 手机号"
|
||
className="h-9 w-full border border-[#d9dee7] bg-white px-3 text-sm outline-none focus:border-primary"
|
||
/>
|
||
<input
|
||
type="password"
|
||
placeholder="密码"
|
||
className="h-9 w-full border border-[#d9dee7] bg-white px-3 text-sm outline-none focus:border-primary"
|
||
/>
|
||
<button
|
||
onClick={() => navigate("/")}
|
||
className="h-9 w-full bg-primary text-sm font-medium text-white hover:bg-[#0f4ea6]"
|
||
>
|
||
登录
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="col-span-12 border bg-white lg:col-span-9">
|
||
<div className="relative h-[310px] overflow-hidden">
|
||
<div className={cn("absolute inset-0 bg-gradient-to-br", banner.style)} />
|
||
<div className="absolute inset-0 bg-black/20" />
|
||
<div className="relative flex h-full flex-col justify-end p-7 text-white">
|
||
<div className="text-3xl font-bold tracking-wide">{banner.title}</div>
|
||
<div className="mt-2 text-sm text-white/90">{banner.subtitle}</div>
|
||
</div>
|
||
<div className="absolute left-5 top-5 rounded bg-black/35 px-2 py-1 text-xs text-white/90">
|
||
首页轮播
|
||
</div>
|
||
<div className="absolute bottom-4 right-5 flex gap-2">
|
||
{BANNERS.map((b, idx) => (
|
||
<button
|
||
key={b.title}
|
||
onClick={() => setActiveBanner(idx)}
|
||
className={cn(
|
||
"rounded px-2.5 py-1 text-xs",
|
||
idx === activeBanner ? "bg-white text-[#1f2937]" : "bg-black/35 text-white",
|
||
)}
|
||
>
|
||
{b.title}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="border bg-white">
|
||
<div className="border-b bg-[#f8fafc] px-4 py-3">
|
||
<h2 className="text-base font-semibold">交易信息</h2>
|
||
</div>
|
||
<div className="border-b px-3">
|
||
<div className="flex flex-wrap items-center">
|
||
{NOTICE_TABS.map((tab) => (
|
||
<button
|
||
key={tab}
|
||
onClick={() => setActiveTab(tab)}
|
||
className={cn(
|
||
"relative px-4 py-3 text-sm",
|
||
activeTab === tab ? "font-semibold text-primary" : "text-[#4b5563] hover:text-primary",
|
||
)}
|
||
>
|
||
{tab}
|
||
{activeTab === tab && <span className="absolute inset-x-2 bottom-0 h-0.5 bg-primary" />}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="p-4">
|
||
<NoticeList items={NOTICE_DATA[activeTab]} />
|
||
</div>
|
||
</section>
|
||
|
||
<section className="grid grid-cols-12 gap-4">
|
||
<div className="col-span-12 border bg-white lg:col-span-6">
|
||
<div className="border-b bg-[#f8fafc] px-4 py-3 text-sm font-semibold">通知公告</div>
|
||
<div className="p-4">
|
||
<NoticeList
|
||
items={[
|
||
{ title: "万华蓬莱园区高温管道耐火衬里类物资供应商招募", date: "2026-07-10" },
|
||
{ title: "万华化学桨叶冷却机类供应商招募", date: "2026-07-10" },
|
||
{ title: "万华化学洗车平台服务类供应商招募", date: "2026-06-25" },
|
||
]}
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div className="col-span-12 border bg-white lg:col-span-6">
|
||
<div className="border-b bg-[#f8fafc] px-4 py-3 text-sm font-semibold">常见问题 / 操作指南</div>
|
||
<div className="grid grid-cols-2 gap-2 p-4 text-sm">
|
||
{[
|
||
"系统使用常见问题处理",
|
||
"常见问题帮助",
|
||
"供应商注册操作指南",
|
||
"投标文件制作软件操作手册",
|
||
"标证通申请-投标单位操作指南",
|
||
"浏览器切换IE模式",
|
||
].map((x) => (
|
||
<button key={x} className="border px-3 py-2 text-left hover:border-primary hover:bg-[#f8fbff]">
|
||
{x}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<XiaobinAssistant pageType="portal" />
|
||
</PortalShell>
|
||
);
|
||
}
|