钱新宇 преди 1 месец
родител
ревизия
db30ded419

+ 2 - 0
.gitignore

@@ -1,6 +1,7 @@
 /company/node_modules
 /retrieval/node_modules
 /saas/node_modules
+/proprice/node_modules
 /company/.env.local
 /company/.umirc.local.ts
 /company/config/config.local.ts
@@ -11,6 +12,7 @@
 /company/.umi-production
 /company/.umi-test
 /dist
+/proprice/dist
 /saas/saas
 /company/home
 /retrieval/price

+ 15 - 0
proprice/index.html

@@ -0,0 +1,15 @@
+<!doctype html>
+<html lang="zh-CN">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>智价云 药店版 - 药店、诊所等终端多电商平台采购比价追踪软件</title>
+    <meta
+      name="description"
+      content="智价云 药店版面向药店老板和采购人员,聚合药师帮、一药城等 B 端电商平台账号,提供跨平台搜索、横向比价、账号管理与全端采购工作台。" />
+  </head>
+  <body>
+    <div id="root"></div>
+    <script type="module" src="/src/main.tsx"></script>
+  </body>
+</html>

+ 5 - 0
proprice/metadata.json

@@ -0,0 +1,5 @@
+{
+  "name": "智价云 药店版 - 药店、诊所等终端多电商平台采购比价追踪软件",
+  "description": "面向药店老板和采购人员的多平台采购比价工作台。",
+  "requestFramePermissions": []
+}

+ 30 - 0
proprice/package.json

@@ -0,0 +1,30 @@
+{
+  "name": "proprice-official-website",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite --port=3000 --host=127.0.0.1",
+    "build": "vite build",
+    "preview": "vite preview",
+    "clean": "rm -rf dist",
+    "lint": "tsc --noEmit"
+  },
+  "dependencies": {
+    "lucide-react": "^0.546.0",
+    "motion": "^12.23.24",
+    "react": "^19.0.0",
+    "react-dom": "^19.0.0"
+  },
+  "devDependencies": {
+    "@types/node": "^22.14.0",
+    "@types/react": "^19.0.10",
+    "@types/react-dom": "^19.0.4",
+    "@vitejs/plugin-react": "^4.3.4",
+    "autoprefixer": "^10.4.21",
+    "postcss": "^8.5.3",
+    "tailwindcss": "^3.4.17",
+    "typescript": "~5.8.2",
+    "vite": "^5.4.14"
+  }
+}

+ 6 - 0
proprice/postcss.config.cjs

@@ -0,0 +1,6 @@
+module.exports = {
+  plugins: {
+    tailwindcss: {},
+    autoprefixer: {},
+  },
+};

+ 741 - 0
proprice/src/App.tsx

@@ -0,0 +1,741 @@
+import { useMemo, useState } from "react";
+import {
+  BadgeCheck,
+  BarChart3,
+  Building2,
+  CheckCircle2,
+  ChevronRight,
+  ClipboardList,
+  Clock3,
+  FileSpreadsheet,
+  Laptop,
+  Layers3,
+  LineChart,
+  LockKeyhole,
+  Mail,
+  MapPin,
+  MonitorDown,
+  PackageSearch,
+  Search,
+  ShieldCheck,
+  Smartphone,
+  TabletSmartphone,
+  WalletCards,
+  type LucideIcon,
+} from "lucide-react";
+import { motion } from "motion/react";
+import logoImage from "./assets/images/zjy/logo.webp";
+
+type PlatformPrice = {
+  platform: string;
+  price: string;
+  best?: boolean;
+};
+
+type DrugQuote = {
+  name: string;
+  spec: string;
+  advice: string;
+  prices: PlatformPrice[];
+};
+
+type Capability = {
+  title: string;
+  desc: string;
+  icon: typeof PackageSearch;
+};
+
+type Scenario = {
+  title: string;
+  desc: string;
+  metrics: string[];
+};
+
+type DownloadOption = {
+  icon: LucideIcon;
+  title: string;
+  desc: string;
+  isAvailable: boolean;
+  url?: string;
+};
+
+const sectionReveal = {
+  initial: { opacity: 0, y: 34 },
+  whileInView: { opacity: 1, y: 0 },
+  viewport: { once: true, amount: 0.18 },
+  transition: { duration: 0.65, ease: "easeOut" as const },
+};
+
+const itemReveal = {
+  initial: { opacity: 0, y: 22 },
+  whileInView: { opacity: 1, y: 0 },
+  viewport: { once: true, amount: 0.25 },
+  transition: { duration: 0.55, ease: "easeOut" as const },
+};
+
+export default function App() {
+  const [activeQuoteIndex, setActiveQuoteIndex] = useState(0);
+  const [activeScenario, setActiveScenario] = useState(0);
+
+  // 平台连接状态用于渲染首屏左侧账号列表,后续若接入真实平台可替换为接口数据。
+  const connectedPlatforms = useMemo(() => ["药**", "一**", "*易*", "*帮*", "药**"], []);
+
+  // 首屏比价示例用于模拟采购人员切换不同药品后的横向价格结果。
+  const quotes: DrugQuote[] = useMemo(
+    () => [
+      {
+        name: "阿莫西林胶囊",
+        spec: "0.25g*24粒 / 300盒起订",
+        advice: "低价优先",
+        prices: [
+          { platform: "药**", price: "¥5.86", best: true },
+          { platform: "一**", price: "¥6.12" },
+        ],
+      },
+      {
+        name: "布洛芬缓释胶囊",
+        spec: "0.3g*20粒 / 区域仓发货",
+        advice: "可凑单",
+        prices: [
+          { platform: "药**", price: "¥9.48" },
+          { platform: "一**", price: "¥9.06", best: true },
+        ],
+      },
+      {
+        name: "连花清瘟胶囊",
+        spec: "36粒 / 支持同城配送",
+        advice: "优先采购",
+        prices: [
+          { platform: "药**", price: "¥11.20" },
+          { platform: "一**", price: "¥10.98" },
+        ],
+      },
+    ],
+    [],
+  );
+
+  // 能力模块承接上传 HTML 的功能信息,并统一成可复用的卡片结构。
+  const capabilities: Capability[] = useMemo(
+    () => [
+      {
+        title: "同品规归并",
+        desc: "按商品名、规格、厂家、批准文号聚合同类结果,减少名称差异造成的误判。",
+        icon: Layers3,
+      },
+      {
+        title: "采购成本看板",
+        desc: "按单次采购、门店、月份统计节省金额,帮助老板看清每一笔差价。",
+        icon: BarChart3,
+      },
+      {
+        title: "起订量与凑单",
+        desc: "同步平台起订量、满减与配送门槛,优先给出适合当前采购量的选择。",
+        icon: WalletCards,
+      },
+      {
+        title: "采购清单导入",
+        desc: "批量导入常采目录或补货清单,一次生成跨平台价格排序结果。",
+        icon: FileSpreadsheet,
+      },
+      {
+        title: "缺货替代提醒",
+        desc: "当前平台缺货时,自动提示其他平台现货与相近替代规格。",
+        icon: Clock3,
+      },
+      {
+        title: "账号安全管控",
+        desc: "按员工角色分配查看与采购权限,离职人员可快速停用访问。",
+        icon: LockKeyhole,
+      },
+    ],
+    [],
+  );
+
+  // 客户场景用于移动端和桌面端共用同一份内容,避免两套文案维护不一致。
+  const scenarios: Scenario[] = useMemo(
+    () => [
+      {
+        title: "单体药店老板",
+        desc: "每天补货品种不多,但价格波动敏感。智价云 药店版把常采品种的各平台价格摆在同一页,老板能快速确认在哪里买更划算。",
+        metrics: ["少登录", "少抄价", "少漏采"],
+      },
+      {
+        title: "连锁采购人员",
+        desc: "采购清单更长、门店更多,需要兼顾价格、起订量和配送时效。智价云 药店版支持批量比价与门店账号管理,适合标准化采购流程。",
+        metrics: ["批量搜", "按门店", "可复盘"],
+      },
+    ],
+    [],
+  );
+
+  // 下载入口保持为配置化数据,便于拿到真实安装包链接后替换跳转行为。
+  const downloadOptions: DownloadOption[] = useMemo(
+    () => [
+      {
+        icon: MonitorDown,
+        title: "Windows",
+        desc: "门店采购主力端",
+        isAvailable: true,
+        url: "https://priceapi.kailin.com.cn/desktop-updates/%E8%8D%AF%E6%98%93%E9%87%87-x64.exe",
+      },
+      {
+        icon: Laptop,
+        title: "MacOS",
+        desc: "总部与采购办公",
+        isAvailable: true,
+        url: "https://priceapi.kailin.com.cn/desktop-updates/%E8%8D%AF%E6%98%93%E9%87%87-arm64.dmg",
+      },
+      { icon: Smartphone, title: "iOS", desc: "敬请期待", isAvailable: false },
+      { icon: TabletSmartphone, title: "Android", desc: "敬请期待", isAvailable: false },
+    ],
+    [],
+  );
+
+  // 产品中心与页脚复用同一份链接,匹配其他官网顶部下拉和底部栏目结构。
+  const products = useMemo(
+    () => [
+      { name: "智价云 药店版", url: "#top" },
+      { name: "智价云", url: "https://price.kailin.com.cn" },
+      { name: "开邻智数", url: "https://saas.kailin.com.cn" },
+    ],
+    [],
+  );
+
+  // 锚点滚动统一经过这个函数,保证导航、按钮在单页内的跳转行为一致。
+  const scrollTo = (id: string) => {
+    const target = document.getElementById(id);
+    target?.scrollIntoView({ behavior: "smooth", block: "start" });
+  };
+
+  const activeQuote = quotes[activeQuoteIndex];
+
+  const openProduct = (url: string) => {
+    if (url.startsWith("#")) {
+      scrollTo(url.slice(1));
+      return;
+    }
+    window.open(url, "_blank", "noreferrer");
+  };
+
+  return (
+    <div className="min-h-screen bg-deep-ink text-on-surface">
+      <header className="fixed top-0 z-50 w-full border-b border-slate-800 bg-slate-950/70 backdrop-blur-md">
+        <nav className="mx-auto flex h-20 max-w-7xl items-center justify-between px-6">
+          <div className="flex cursor-pointer items-center gap-3 font-headline" onClick={() => scrollTo("top")} aria-label="返回智价云药店版首页">
+            <div
+              style={{
+                width: "7.75rem",
+                height: "2.35rem",
+                borderRadius: "9999px",
+                overflow: "hidden",
+              }}
+              className="flex items-center justify-center gap-2 bg-white px-3 text-primary shadow-lg shadow-black/10">
+              <img style={{ width: "6.75rem", height: "3rem" }} src={logoImage} alt="智价云 Logo" className="w-7 h-7 object-contain" />
+            </div>
+          </div>
+
+          <div className="hidden items-center space-x-10 md:flex">
+            <button className="relative inline-flex items-center font-headline text-sm font-bold leading-none text-secondary" onClick={() => scrollTo("top")}>
+              首页
+              <span className="absolute left-0 -bottom-2 h-0.5 w-full rounded-full bg-secondary" />
+            </button>
+
+            <div className="group relative">
+              <span className="inline-flex cursor-default items-center font-headline text-sm font-medium leading-none text-slate-300 transition-colors hover:text-white">
+                产品中心
+              </span>
+              <div className="invisible absolute left-1/2 top-full mt-3 min-w-36 -translate-x-1/2 rounded-lg border border-slate-800 bg-slate-900/95 p-1.5 opacity-0 shadow-xl transition-all duration-200 group-hover:visible group-hover:opacity-100">
+                {products.map((product) =>
+                  product.url.startsWith("#") ? (
+                    <button
+                      key={product.name}
+                      onClick={() => openProduct(product.url)}
+                      className="block w-full rounded-md px-3 py-2 text-left text-sm text-slate-200 transition-colors hover:bg-slate-800 hover:text-white">
+                      {product.name}
+                    </button>
+                  ) : (
+                    <a
+                      key={product.name}
+                      href={product.url}
+                      target="_blank"
+                      rel="noreferrer"
+                      className="block rounded-md px-3 py-2 text-sm text-slate-200 transition-colors hover:bg-slate-800 hover:text-white">
+                      {product.name}
+                    </a>
+                  ),
+                )}
+              </div>
+            </div>
+
+            <a
+              href="https://home.kailin.com.cn"
+              target="_blank"
+              rel="noreferrer"
+              className="relative inline-flex items-center font-headline text-sm font-medium leading-none text-slate-300 transition-colors hover:text-white">
+              关于我们
+            </a>
+          </div>
+
+          <button
+            onClick={() => scrollTo("download")}
+            className="rounded-lg bg-blue-600 px-6 py-2.5 font-headline text-sm font-bold text-white transition-all hover:bg-blue-500 active:scale-95">
+            下载客户端
+          </button>
+        </nav>
+      </header>
+
+      <main id="top" className="overflow-hidden pt-20">
+        <section className="hero-grid relative border-b border-slate-800 bg-[#070d1a] px-5 py-14 md:px-8 lg:min-h-[720px] lg:py-16">
+          <div className="absolute inset-0 bg-[radial-gradient(circle_at_20%_20%,rgba(37,99,235,0.26),transparent_32%),radial-gradient(circle_at_78%_18%,rgba(56,189,248,0.14),transparent_28%),linear-gradient(135deg,rgba(2,6,23,0.84)_0%,rgba(15,23,42,0.94)_52%,rgba(2,6,23,0.98)_100%)]" />
+          <div className="absolute inset-0 hero-grid-lines" />
+
+          <div className="relative z-10 mx-auto grid max-w-7xl items-center gap-10 lg:grid-cols-[0.86fr_1.14fr]">
+            <motion.div initial={{ opacity: 0, y: 28 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.75, ease: "easeOut" }} className="max-w-2xl">
+              <div className="inline-flex items-center gap-3 font-headline text-sm font-extrabold text-blue-200">
+                <span className="h-1 w-8 rounded-full bg-danger" />
+                药店、诊所等终端多电商平台采购比价追踪软件
+              </div>
+              <h1 className="mt-5 font-headline text-5xl font-extrabold leading-[1.04] tracking-normal text-white sm:text-6xl lg:text-7xl">智价云 药店版</h1>
+              <p className="mt-6 max-w-xl text-lg leading-8 text-slate-300 md:text-xl">
+                绑定 B 端电商账号后,跨平台搜索同一商品,价格、库存、起订量和配送条件一次横向对比与下单。抢购快人一步!关注重点品规价格提醒及时扫货购进!
+              </p>
+
+              <div className="mt-9 flex flex-col gap-3 sm:flex-row">
+                <button
+                  onClick={() => window.open("http://8.135.32.236:8001/desktop-updates/%E8%8D%AF%E6%98%93%E9%87%87-x64.exe")}
+                  className="inline-flex h-13 items-center justify-center gap-2 rounded-md bg-primary px-6 font-bold text-white shadow-[0_16px_36px_rgba(37,99,235,0.35)] transition hover:-translate-y-0.5 hover:bg-blue-500">
+                  <MonitorDown className="h-5 w-5" />
+                  下载客户端(Windows)
+                </button>
+                <button
+                  onClick={() => window.open("https://priceapi.kailin.com.cn/desktop-updates/%E8%8D%AF%E6%98%93%E9%87%87-arm64.dmg")}
+                  className="inline-flex h-13 items-center justify-center gap-2 rounded-md bg-primary px-6 font-bold text-white shadow-[0_16px_36px_rgba(37,99,235,0.35)] transition hover:-translate-y-0.5 hover:bg-blue-500">
+                  <Laptop className="h-5 w-5" />
+                  下载客户端(Mac)
+                </button>
+                <button
+                  onClick={() => scrollTo("compare")}
+                  className="inline-flex h-13 items-center justify-center gap-2 rounded-md border border-slate-700 bg-slate-900 px-6 font-bold text-slate-100 transition hover:-translate-y-0.5 hover:border-blue-400 hover:text-blue-200">
+                  <PackageSearch className="h-5 w-5" />
+                  查看比价流程
+                </button>
+              </div>
+
+              {/* <div className="mt-7 flex flex-wrap gap-2 text-sm text-slate-300">
+                {["Windows", "macOS", "iOS 敬请期待", "Android 敬请期待", "单体药店与连锁采购团队"].map((item) => (
+                  <span key={item} className="rounded-md border border-slate-700 bg-slate-900/80 px-3 py-2 shadow-sm shadow-black/10">
+                    {item}
+                  </span>
+                ))}
+              </div> */}
+            </motion.div>
+
+            <motion.div
+              initial={{ opacity: 0, x: 42, scale: 0.98 }}
+              animate={{ opacity: 1, x: 0, scale: 1 }}
+              transition={{ delay: 0.12, duration: 0.75, ease: "easeOut" }}
+              className="relative">
+              <WorkbenchPreview
+                activeQuote={activeQuote}
+                activeQuoteIndex={activeQuoteIndex}
+                connectedPlatforms={connectedPlatforms}
+                quotes={quotes}
+                setActiveQuoteIndex={setActiveQuoteIndex}
+              />
+            </motion.div>
+          </div>
+        </section>
+
+        <motion.section id="compare" className="scroll-mt-20 bg-deep-ink px-5 py-20 md:px-8 lg:py-24" {...sectionReveal}>
+          <div className="mx-auto max-w-7xl">
+            <SectionIntro
+              kicker="横向比价"
+              title="把分散在不同平台里的药品价格,放到同一个采购视图里。"
+              desc="智价云 药店版面向药店老板和采购人员,将搜索、比价、库存判断、起订量检查与采购建议聚合在同一套工作台中,减少反复登录和人工抄价。"
+            />
+
+            <div className="mt-9 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
+              {[
+                ["一站式", "输入商品名、条码或批准文号后多平台并行查询"],
+                ["多平台", "多垂直电商平台"],
+                ["多账号", "同一门店或连锁门店可绑定不同采购账号"],
+                ["实时查", "价格、库存、配送、起订量同步展示"],
+              ].map(([value, label]) => (
+                <motion.div
+                  key={value}
+                  {...itemReveal}
+                  className="rounded-lg border border-slate-800 bg-slate-900/85 p-6 shadow-sm shadow-black/20 transition hover:-translate-y-1 hover:border-blue-500/50 hover:bg-slate-900">
+                  <strong className="block font-headline text-4xl font-extrabold text-primary">{value}</strong>
+                  <span className="mt-4 block text-sm leading-6 text-slate-400">{label}</span>
+                </motion.div>
+              ))}
+            </div>
+          </div>
+        </motion.section>
+
+        <motion.section id="bind" className="scroll-mt-20 bg-slate-950 px-5 py-20 md:px-8 lg:py-24" {...sectionReveal}>
+          <div className="mx-auto max-w-7xl">
+            <SectionIntro
+              kicker="账号绑定"
+              title="采购账号归集管理,平台权益继续保留。"
+              desc="门店仍使用自己的 B 端电商平台账号,智价云 药店版负责统一检索与结果呈现,方便采购人员在同一界面做判断。"
+            />
+
+            <div className="mt-10 grid gap-8 lg:grid-cols-[0.9fr_1.1fr]">
+              <div className="grid gap-3">
+                {[
+                  ["01", "绑定平台账号", "支持主流医药 B2B 电商账号接入。"],
+                  ["02", "选择门店与采购权限", "老板、采购员、财务按岗位查看对应门店和采购范围。"],
+                  ["03", "搜索后横向决策", "同品规商品按价格、库存、配送时效和起订量排序。"],
+                ].map(([index, title, desc]) => (
+                  <motion.article
+                    key={index}
+                    {...itemReveal}
+                    className="grid grid-cols-[42px_1fr] gap-4 rounded-lg border border-slate-800 bg-slate-900/85 p-4">
+                    <div className="grid h-11 w-11 place-items-center rounded-lg bg-blue-500/15 font-headline font-extrabold text-blue-200">{index}</div>
+                    <div>
+                      <h3 className="font-headline text-lg font-extrabold text-white">{title}</h3>
+                      <p className="mt-1 text-sm leading-6 text-slate-400">{desc}</p>
+                    </div>
+                  </motion.article>
+                ))}
+              </div>
+
+              <motion.div {...itemReveal} className="rounded-lg border border-slate-800 bg-slate-900/85 p-5 shadow-panel">
+                <div className="flex flex-wrap items-center justify-between gap-4">
+                  <div>
+                    <p className="text-xs font-bold uppercase tracking-[0.16em] text-slate-500">Account Hub</p>
+                    <h3 className="mt-1 font-headline text-xl font-extrabold text-white">门店账号连接状态</h3>
+                  </div>
+                  <span className="inline-flex items-center gap-2 rounded-full border border-emerald-400/25 bg-emerald-400/10 px-3 py-1.5 text-sm font-bold text-emerald-300">
+                    <ShieldCheck className="h-4 w-4" />
+                    已加密托管
+                  </span>
+                </div>
+
+                <div className="mt-5 grid gap-3">
+                  {[
+                    ["郑州康宁大药房", "药** / 店长账号", "刚刚同步"],
+                    ["金水区二店", "一** / 采购账号", "2分钟前"],
+                  ].map(([store, account, sync]) => (
+                    <div key={store} className="grid gap-3 rounded-md border border-slate-800 bg-slate-950/80 p-4 sm:grid-cols-[1fr_82px_96px] sm:items-center">
+                      <div>
+                        <strong className="block text-sm text-slate-100">{store}</strong>
+                        <span className="text-xs text-slate-500">{account}</span>
+                      </div>
+                      <span className="inline-flex items-center gap-1 text-sm font-extrabold text-emerald-300">
+                        <CheckCircle2 className="h-4 w-4" />
+                        在线
+                      </span>
+                      <span className="text-sm font-bold text-primary sm:text-right">{sync}</span>
+                    </div>
+                  ))}
+                </div>
+              </motion.div>
+            </div>
+          </div>
+        </motion.section>
+
+        <motion.section id="features" className="scroll-mt-20 bg-[#08111f] px-5 py-20 text-white md:px-8 lg:py-24" {...sectionReveal}>
+          <div className="mx-auto max-w-7xl">
+            <SectionIntro
+              dark
+              kicker="核心能力"
+              title="为药店采购设计的高频功能。"
+              desc="围绕采购前、采购中、采购后的高频动作设计,让价格判断、账号安全和成本复盘形成闭环。"
+            />
+
+            <div className="mt-10 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
+              {capabilities.map((item) => (
+                <motion.article
+                  key={item.title}
+                  {...itemReveal}
+                  className="rounded-lg border border-white/10 bg-white/[0.04] p-6 transition hover:-translate-y-1 hover:border-primary/60 hover:bg-white/[0.07]">
+                  <div className="grid h-12 w-12 place-items-center rounded-lg bg-primary/20 text-blue-200">
+                    <item.icon className="h-6 w-6" />
+                  </div>
+                  <h3 className="mt-5 font-headline text-xl font-extrabold">{item.title}</h3>
+                  <p className="mt-3 text-sm leading-6 text-slate-300">{item.desc}</p>
+                </motion.article>
+              ))}
+            </div>
+          </div>
+        </motion.section>
+
+        <motion.section id="download" className="scroll-mt-20 bg-slate-950 px-5 py-20 md:px-8 lg:py-24" {...sectionReveal}>
+          <div className="mx-auto max-w-7xl">
+            <div className="grid gap-8 rounded-lg border border-slate-800 bg-slate-900/85 p-6 shadow-panel lg:grid-cols-[0.75fr_1.25fr] lg:items-center lg:p-8">
+              <div>
+                <p className="font-headline text-sm font-extrabold text-secondary">全端覆盖</p>
+                <h2 className="mt-3 font-headline text-3xl font-extrabold leading-tight text-white md:text-4xl">
+                  电脑端做批量对比与采购,手机端远程管理与查阅。
+                </h2>
+                <p className="mt-4 leading-7 text-slate-400">采购办公室、收银台、仓库盘点、外出谈单都能接上同一套账号与比价结果。</p>
+              </div>
+
+              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
+                {downloadOptions.map(({ icon: Icon, title, desc, isAvailable, url }) => (
+                  <button
+                    key={title}
+                    className={`min-h-32 rounded-lg border p-4 text-left transition ${
+                      isAvailable
+                        ? "border-slate-800 bg-slate-950/80 hover:-translate-y-1 hover:border-blue-500/60 hover:bg-slate-900"
+                        : "cursor-not-allowed border-slate-800 bg-slate-950/45 opacity-70"
+                    }`}
+                    onClick={() => {
+                      // 未上线的平台只展示状态,不触发咨询跳转,避免给用户造成可下载的误解。
+                      if (!isAvailable) return;
+                      if (url) {
+                        window.open(url);
+                        return;
+                      }
+                      scrollTo("contact");
+                    }}>
+                    <strong className="flex items-center gap-2 font-headline text-base font-extrabold text-white">
+                      <Icon className="h-5 w-5 text-secondary" />
+                      {title}
+                    </strong>
+                    <span className="mt-8 block text-sm text-slate-400">{desc}</span>
+                  </button>
+                ))}
+              </div>
+            </div>
+          </div>
+        </motion.section>
+
+        <motion.section className="bg-deep-ink px-5 py-20 md:px-8 lg:py-24" {...sectionReveal}>
+          <div className="mx-auto max-w-7xl">
+            <SectionIntro
+              kicker="客户场景"
+              title="让采购从“人工跑平台 手动查”,变成“按低价秒对比 做选择”。"
+              desc="从单体药店到中小连锁,智价云 药店版帮采购人员把分散平台、账号和价格条件收束成一个稳定流程。"
+            />
+
+            <div className="mt-9 grid gap-4 lg:grid-cols-2">
+              {scenarios.map((scenario, index) => (
+                <button
+                  key={scenario.title}
+                  onClick={() => setActiveScenario(index)}
+                  className={`rounded-lg border p-6 text-left transition ${
+                    activeScenario === index
+                      ? "border-blue-500/60 bg-blue-500/10 shadow-md shadow-black/20"
+                      : "border-slate-800 bg-slate-900/85 hover:border-slate-700"
+                  }`}>
+                  <div className="flex items-center justify-between gap-4">
+                    <h3 className="font-headline text-2xl font-extrabold text-white">{scenario.title}</h3>
+                    <ChevronRight className={`h-5 w-5 transition ${activeScenario === index ? "text-secondary" : "text-slate-600"}`} />
+                  </div>
+                  <p className="mt-4 leading-7 text-slate-400">{scenario.desc}</p>
+                  <div className="mt-6 grid grid-cols-3 gap-3">
+                    {scenario.metrics.map((metric) => (
+                      <span key={metric} className="border-l-4 border-danger bg-slate-950/80 px-3 py-2 text-sm font-bold text-slate-100">
+                        {metric}
+                      </span>
+                    ))}
+                  </div>
+                </button>
+              ))}
+            </div>
+          </div>
+        </motion.section>
+
+        <footer id="contact" className="scroll-mt-20 border-t border-slate-800 bg-slate-950 px-6 py-16">
+          <div className="mx-auto grid max-w-7xl grid-cols-1 gap-12 md:grid-cols-4">
+            <div className="space-y-6">
+              <div className="font-headline text-xl font-bold text-white">智价云 药店版</div>
+              <p className="text-sm leading-relaxed text-slate-400">
+                药店、诊所等终端多电商平台采购比价追踪软件,帮助单体药店与连锁采购团队统一检索、横向比价和管理平台账号。省时省力又省钱!
+              </p>
+            </div>
+
+            <div>
+              <h5 className="mb-6 text-xs font-bold uppercase tracking-widest text-slate-200">联系我们</h5>
+              <ul className="space-y-4 text-sm text-slate-400">
+                <li className="flex items-center gap-2">
+                  <Mail className="h-4 w-4 text-secondary" />
+                  <a
+                    href="mailto:bd@dotouch.tech?subject=%E6%99%BA%E4%BB%B7%E4%BA%91%E8%8D%AF%E5%BA%97%E7%89%88%E4%BA%A7%E5%93%81%E5%92%A8%E8%AF%A2"
+                    className="transition-colors hover:text-secondary">
+                    bd@dotouch.tech
+                  </a>
+                </li>
+                <li className="flex items-start gap-2">
+                  <MapPin className="mt-0.5 h-4 w-4 text-secondary" />
+                  <span>深圳大方无隅科技有限公司</span>
+                </li>
+              </ul>
+            </div>
+
+            <div>
+              <h5 className="mb-6 text-xs font-bold uppercase tracking-widest text-slate-200">产品中心</h5>
+              <ul className="space-y-4 text-sm text-slate-400">
+                {products.map((product) => (
+                  <li key={product.name}>
+                    {product.url.startsWith("#") ? (
+                      <button onClick={() => openProduct(product.url)} className="transition-colors hover:text-secondary">
+                        {product.name}
+                      </button>
+                    ) : (
+                      <a href={product.url} target="_blank" rel="noreferrer" className="transition-colors hover:text-secondary">
+                        {product.name}
+                      </a>
+                    )}
+                  </li>
+                ))}
+              </ul>
+            </div>
+
+            <div>
+              <h5 className="mb-6 text-xs font-bold uppercase tracking-widest text-slate-200">法律条款</h5>
+              <ul className="space-y-4 text-sm text-slate-400">
+                <li>
+                  <a href="/privacy" target="_blank" rel="noreferrer" className="transition-colors hover:text-secondary">
+                    隐私政策
+                  </a>
+                </li>
+                <li>
+                  <a href="/agreement" target="_blank" rel="noreferrer" className="transition-colors hover:text-secondary">
+                    用户协议
+                  </a>
+                </li>
+              </ul>
+            </div>
+          </div>
+
+          <div className="mx-auto mt-16 max-w-7xl border-t border-slate-800 pt-8 text-center">
+            <p className="text-sm text-slate-500">© 粤ICP备2024220172号-9</p>
+          </div>
+        </footer>
+      </main>
+    </div>
+  );
+}
+
+function SectionIntro({ kicker, title, desc, dark = true }: { kicker: string; title: string; desc: string; dark?: boolean }) {
+  return (
+    <div className="max-w-3xl">
+      <p className="font-headline text-sm font-extrabold text-secondary">{kicker}</p>
+      <h2 className={`mt-3 font-headline text-3xl font-extrabold leading-tight md:text-4xl ${dark ? "text-white" : "text-white"}`}>{title}</h2>
+      <p className={`mt-4 leading-7 ${dark ? "text-slate-400" : "text-slate-400"}`}>{desc}</p>
+    </div>
+  );
+}
+
+function WorkbenchPreview({
+  activeQuote,
+  activeQuoteIndex,
+  connectedPlatforms,
+  quotes,
+  setActiveQuoteIndex,
+}: {
+  activeQuote: DrugQuote;
+  activeQuoteIndex: number;
+  connectedPlatforms: string[];
+  quotes: DrugQuote[];
+  setActiveQuoteIndex: (index: number) => void;
+}) {
+  return (
+    <div className="rounded-lg border border-slate-700/80 bg-slate-900/95 shadow-panel">
+      <div className="flex h-12 items-center justify-between border-b border-slate-800 bg-slate-950/90 px-4">
+        <div className="flex gap-2">
+          <span className="h-2.5 w-2.5 rounded-full bg-danger" />
+          <span className="h-2.5 w-2.5 rounded-full bg-slate-600" />
+          <span className="h-2.5 w-2.5 rounded-full bg-emerald-600" />
+        </div>
+        <div className="inline-flex items-center gap-2 text-sm font-bold text-emerald-300">
+          <BadgeCheck className="h-4 w-4" />4 个采购平台已连接
+        </div>
+      </div>
+
+      <div className="grid min-h-[520px] lg:grid-cols-[210px_1fr]">
+        <aside className="border-b border-slate-800 bg-slate-950/70 p-5 lg:border-b-0 lg:border-r">
+          <p className="text-xs font-semibold text-slate-500">B端电商账号</p>
+          <div className="mt-4 grid gap-3">
+            {connectedPlatforms.map((platform) => (
+              <div
+                key={platform}
+                className="flex min-h-11 items-center justify-between rounded-md border border-slate-800 bg-slate-900 px-3 text-sm font-bold text-slate-100">
+                {platform}
+                <span className="h-2 w-2 rounded-full bg-emerald-600" />
+              </div>
+            ))}
+          </div>
+          <div className="mt-7 rounded-md border border-emerald-400/20 bg-emerald-400/10 p-4">
+            <div className="flex items-center gap-2 text-sm font-extrabold text-emerald-300">
+              <ShieldCheck className="h-4 w-4" />
+              账号安全
+            </div>
+            <p className="mt-2 text-xs leading-5 text-emerald-100/70">角色权限、加密托管、离职停用统一管理。</p>
+          </div>
+        </aside>
+
+        <div className="p-5 md:p-6">
+          <div className="grid gap-3 sm:grid-cols-[1fr_118px]">
+            <div className="flex min-h-12 items-center gap-3 rounded-md border border-slate-700 bg-slate-950 px-4 font-bold text-slate-100">
+              <Search className="h-5 w-5 text-secondary" />
+              {activeQuote.name}
+              <span className="hidden font-normal text-slate-500 sm:inline">{activeQuote.spec}</span>
+            </div>
+            <button className="rounded-md bg-danger px-4 font-bold text-white">横向搜索</button>
+          </div>
+
+          <div className="mt-5 grid grid-cols-3 gap-2">
+            {quotes.map((quote, index) => (
+              <button
+                key={quote.name}
+                onClick={() => setActiveQuoteIndex(index)}
+                className={`rounded-md border px-3 py-2 text-left text-xs font-bold transition ${
+                  activeQuoteIndex === index
+                    ? "border-blue-500 bg-blue-500/15 text-blue-200"
+                    : "border-slate-800 text-slate-500 hover:border-blue-500/40 hover:text-slate-300"
+                }`}>
+                {quote.name}
+              </button>
+            ))}
+          </div>
+
+          <div className="mt-5 overflow-hidden rounded-md border border-slate-800">
+            <div className="grid grid-cols-[1.1fr_0.8fr_0.8fr_88px] border-b border-slate-800 bg-slate-950 px-4 py-3 text-xs font-bold text-slate-500">
+              <span>商品</span>
+              <span>平台</span>
+              <span>价格</span>
+              <span>建议</span>
+            </div>
+            {activeQuote.prices.map((item) => (
+              <div
+                key={item.platform}
+                className="grid min-h-16 grid-cols-[1.1fr_0.8fr_0.8fr_88px] items-center border-b border-slate-800 px-4 py-3 text-sm last:border-b-0">
+                <div>
+                  <strong className="block text-slate-100">{activeQuote.name}</strong>
+                  <span className="text-xs text-slate-500">{item.note}</span>
+                </div>
+                <span className="font-bold text-slate-300">{item.platform}</span>
+                <span className={`font-headline text-lg font-extrabold ${item.best ? "text-danger" : "text-blue-300"}`}>{item.price}</span>
+                <span
+                  className={`w-max rounded-full px-2.5 py-1 text-xs font-bold ${
+                    item.best ? "bg-rose-400/10 text-rose-300" : "bg-emerald-400/10 text-emerald-300"
+                  }`}>
+                  {item.best ? activeQuote.advice : "备选"}
+                </span>
+              </div>
+            ))}
+          </div>
+
+          <div className="mt-5 grid gap-3 sm:grid-cols-3">
+            {[
+              [ClipboardList, "本次预计节省", "¥1,286"],
+              [PackageSearch, "可比价商品", "186"],
+              [Building2, "缺货替代", "24"],
+            ].map(([Icon, label, value]) => (
+              <div key={label as string} className="rounded-lg border border-slate-800 bg-slate-950/80 p-4">
+                <Icon className="h-5 w-5 text-secondary" />
+                <span className="mt-3 block text-xs text-slate-500">{label as string}</span>
+                <strong className="mt-1 block font-headline text-2xl font-extrabold text-white">{value as string}</strong>
+              </div>
+            ))}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}

BIN
proprice/src/assets/images/logo.ico


BIN
proprice/src/assets/images/logo_i.png


BIN
proprice/src/assets/images/zjy/logo.webp


BIN
proprice/src/assets/images/zjy/logo_transparent.png


BIN
proprice/src/assets/images/zjy/m3_t11.png


BIN
proprice/src/assets/images/zjy/m3_t22.png


BIN
proprice/src/assets/images/zjy/m3_t33.png


BIN
proprice/src/assets/images/zjy/m3_t44.png


BIN
proprice/src/assets/images/zjy/m3_t55.png


+ 68 - 0
proprice/src/index.css

@@ -0,0 +1,68 @@
+@import url("https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;700;800&family=Inter:wght@300;400;500;600;700;800&display=swap");
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+  * {
+    box-sizing: border-box;
+  }
+
+  html {
+    scroll-behavior: smooth;
+  }
+
+  body {
+    margin: 0;
+    background: #020617;
+    color: #f8fafc;
+    font-family:
+      Inter,
+      -apple-system,
+      BlinkMacSystemFont,
+      "PingFang SC",
+      "Microsoft YaHei",
+      sans-serif;
+    overflow-x: hidden;
+  }
+
+  button,
+  a {
+    -webkit-tap-highlight-color: transparent;
+  }
+
+  button {
+    font: inherit;
+  }
+}
+
+@layer components {
+  .h-13 {
+    height: 3.25rem;
+  }
+
+  .hero-grid-lines {
+    background:
+      repeating-linear-gradient(
+        0deg,
+        rgba(148, 163, 184, 0.08),
+        rgba(148, 163, 184, 0.08) 1px,
+        transparent 1px,
+        transparent 42px
+      ),
+      repeating-linear-gradient(
+        90deg,
+        rgba(148, 163, 184, 0.08),
+        rgba(148, 163, 184, 0.08) 1px,
+        transparent 1px,
+        transparent 42px
+      );
+  }
+}
+
+@media (max-width: 640px) {
+  .hero-grid {
+    min-height: auto;
+  }
+}

+ 10 - 0
proprice/src/main.tsx

@@ -0,0 +1,10 @@
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+import App from "./App";
+import "./index.css";
+
+createRoot(document.getElementById("root")!).render(
+  <StrictMode>
+    <App />
+  </StrictMode>,
+);

+ 24 - 0
proprice/tailwind.config.cjs

@@ -0,0 +1,24 @@
+module.exports = {
+  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
+  theme: {
+    extend: {
+      colors: {
+        primary: "#2563eb",
+        secondary: "#38bdf8",
+        danger: "#f43f5e",
+        surface: "#0f172a",
+        "deep-ink": "#020617",
+        "on-surface": "#f8fafc",
+        "on-surface-variant": "#94a3b8",
+      },
+      fontFamily: {
+        headline: ["Manrope", "Inter", "sans-serif"],
+        body: ["Inter", "sans-serif"],
+      },
+      boxShadow: {
+        panel: "0 24px 80px rgba(0, 0, 0, 0.35)",
+      },
+    },
+  },
+  plugins: [],
+};

+ 17 - 0
proprice/tsconfig.json

@@ -0,0 +1,17 @@
+{
+  "compilerOptions": {
+    "target": "ES2022",
+    "experimentalDecorators": true,
+    "useDefineForClassFields": false,
+    "module": "ESNext",
+    "lib": ["ES2022", "DOM", "DOM.Iterable"],
+    "skipLibCheck": true,
+    "moduleResolution": "bundler",
+    "isolatedModules": true,
+    "moduleDetection": "force",
+    "allowJs": true,
+    "jsx": "react-jsx",
+    "allowImportingTsExtensions": true,
+    "noEmit": true
+  }
+}

+ 15 - 0
proprice/vite.config.ts

@@ -0,0 +1,15 @@
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+
+export default defineConfig(() => {
+  return {
+    plugins: [react()],
+    server: {
+      // 与现有子项目保持一致:允许通过环境变量关闭 HMR,避免自动化编辑时页面频繁刷新。
+      hmr: process.env.DISABLE_HMR !== "true",
+    },
+    build: {
+      outDir: "dist",
+    },
+  };
+});