Ver Fonte

✨ feat(supply-chain): 创建粮食油脂供应链仪表盘页面

- 实现粮食油脂供应链可视化仪表盘,包含粮食和油脂两个标签页
- 设计左侧导航系统,支持粮食/油脂数据切换功能
- 开发数据卡片组件,展示加工能力、基地面积和储备仓容等关键指标
- 构建供应链网络可视化地图,包含基地和产业链定位点
- 实现"1+1+N"供应链合作模式展示区域
- 添加背景网格、装饰元素和交互效果,提升视觉体验
yourname há 2 meses atrás
pai
commit
06db2f4d15

+ 373 - 0
src/client/home/pages/SupplyChainDashboards/GrainOilDashboard.tsx

@@ -0,0 +1,373 @@
+import React, { useState } from 'react';
+
+// 定义组件接口
+interface GrainOilDashboardProps {
+  // 可以添加props如果需要
+}
+
+// 图标组件 - 粮食图标
+const GrainIcon: React.FC<{ className?: string }> = ({ className }) => {
+  return (
+    <div className={className}>
+      <div className="absolute inset-[13%_21.7%]">
+        <img
+          alt="粮食图标"
+          className="block max-w-none size-full"
+          src="https://www.figma.com/api/mcp/asset/74aa7038-2d6c-44fa-8671-4472845f5469"
+        />
+      </div>
+    </div>
+  );
+};
+
+// 图标组件 - 油脂图标
+const OilIcon: React.FC<{ className?: string }> = ({ className }) => {
+  return (
+    <div className={className}>
+      <div className="absolute inset-[13%_26.2%]">
+        <img
+          alt="油脂图标"
+          className="block max-w-none size-full"
+          src="https://www.figma.com/api/mcp/asset/0df5dc87-b48b-4b8d-a3ee-7721d3185ddc"
+        />
+      </div>
+    </div>
+  );
+};
+
+// 产业链图标组件
+const IndustryChainIcon: React.FC<{ className?: string }> = ({ className }) => {
+  return (
+    <div className={className}>
+      <div className="absolute inset-[5.36%_10.72%]">
+        <img
+          alt="产业链图标"
+          className="block max-w-none size-full"
+          src="https://www.figma.com/api/mcp/asset/2388ddbc-149e-4662-89ae-e9df0ed9c546"
+        />
+      </div>
+    </div>
+  );
+};
+
+// 导航组件
+const Navigation: React.FC<{
+  activeTab: 'grain' | 'oil';
+  onTabChange: (tab: 'grain' | 'oil') => void
+}> = ({ activeTab, onTabChange }) => {
+  return (
+    <div className="absolute h-[1078.893px] left-[40px] top-0 w-[150.879px]">
+      <div className="absolute content-stretch flex flex-col gap-[40px] h-[944px] items-center justify-center left-0 right-[37.7%] top-1/2 translate-y-[-50%]">
+        {/* 粮食导航项 */}
+        <div
+          className={`box-border content-stretch flex flex-col gap-[20px] h-[220px] items-center justify-center px-[20px] py-0 relative rounded-[10px] shrink-0 w-[60px] cursor-pointer transition-all ${
+            activeTab === 'grain'
+              ? 'bg-[rgba(255,255,255,0.05)]'
+              : 'hover:bg-[rgba(255,255,255,0.02)]'
+          }`}
+          onClick={() => onTabChange('grain')}
+        >
+          <GrainIcon className="overflow-clip relative shrink-0 size-[50px]" />
+          <div className="box-border content-stretch flex gap-[10px] items-center px-0 py-[4px] relative shrink-0">
+            <div className="flex flex-col font-bold justify-center leading-[32px] not-italic relative shrink-0 text-[26px] whitespace-nowrap">
+              <p className="mb-0 text-white">粮</p>
+              <p className="mb-0">&nbsp;</p>
+              <p className="text-white">食</p>
+            </div>
+          </div>
+        </div>
+
+        {/* 油脂导航项 */}
+        <div
+          className={`box-border content-stretch flex flex-col gap-[20px] h-[220px] items-center justify-center px-[20px] py-0 relative rounded-[10px] shrink-0 w-[60px] cursor-pointer transition-all ${
+            activeTab === 'oil'
+              ? 'bg-[rgba(255,255,255,0.05)]'
+              : 'hover:bg-[rgba(255,255,255,0.02)]'
+          }`}
+          onClick={() => onTabChange('oil')}
+        >
+          <OilIcon className="overflow-clip relative shrink-0 size-[50px]" />
+          <div className="box-border content-stretch flex gap-[10px] items-center px-0 py-[4px] relative shrink-0">
+            <div className="flex flex-col font-bold justify-center leading-[32px] not-italic relative shrink-0 text-[26px] whitespace-nowrap">
+              <p className="mb-0 text-[rgba(255,255,255,0.5)]">油</p>
+              <p className="mb-0">&nbsp;</p>
+              <p className="text-[rgba(255,255,255,0.5)]">脂</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      {/* 导航光标 */}
+      <div className="absolute bottom-0 flex items-center justify-center left-[25.05%] right-0 top-0">
+        <div className="flex-none h-[1078.893px] rotate-[180deg] scale-y-[-100%] w-[113.088px]">
+          <div className="relative size-full">
+            <div className="absolute bottom-[-0.04%] left-0 right-0 top-[-0.04%]">
+              <img
+                alt="导航光标"
+                className="block max-w-none size-full"
+                src="https://www.figma.com/api/mcp/asset/800cef2d-f019-4e81-aea2-643efa15258e"
+              />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+// 数据卡片组件
+const DataCard: React.FC<{
+  title: string;
+  value: string;
+  unit: string;
+  digits: string[];
+}> = ({ title, value, unit, digits }) => {
+  return (
+    <div className="box-border content-stretch flex flex-col gap-[20px] items-start px-0 py-[20px] relative shrink-0 w-[278px]">
+      <div className="box-border content-stretch flex gap-[10px] items-center px-0 py-[4px] relative shrink-0 w-full">
+        <div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[40px] text-white whitespace-nowrap">
+          <p className="leading-[50px]">{title}</p>
+        </div>
+      </div>
+      <div className="content-stretch flex gap-[10px] h-[80px] items-end relative shrink-0 w-full">
+        <div className="content-stretch flex gap-[6px] items-center relative shrink-0">
+          {digits.map((digit, index) => (
+            <div key={index} className="h-[80px] relative shrink-0 w-[53.333px]">
+              <div className="absolute bg-gradient-to-b border-2 border-[#5e697e] border-solid from-[#474e60] inset-0 rounded-[6px] to-[#2b2f39]" />
+              <div className="absolute flex flex-col font-bold inset-[16.16%_13.74%] justify-center leading-[0] not-italic text-[#c5ff92] text-[60px] text-center tracking-[6px]">
+                <p className="leading-[normal] whitespace-pre-wrap">{digit}</p>
+              </div>
+            </div>
+          ))}
+        </div>
+        <div className="box-border content-stretch flex gap-[10px] items-center px-0 py-[4px] relative shrink-0">
+          <div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[24px] text-white whitespace-nowrap">
+            <p className="leading-[32px]">{unit}</p>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+// 主组件
+const GrainOilDashboard: React.FC<GrainOilDashboardProps> = () => {
+  const [activeTab, setActiveTab] = useState<'grain' | 'oil'>('grain');
+
+  // 模拟数据
+  const grainData = {
+    processingCapacity: { value: '200', unit: '万吨/年', digits: ['2', '0', '0'] },
+    baseArea: { value: '15', unit: '万亩', digits: ['1', '5'] },
+    storageCapacity: { value: '?000', unit: '万吨', digits: ['?', '0', '0', '0'] }
+  };
+
+  return (
+    <div className="h-[1080px] w-[1920px] bg-[#0a1a3a] relative overflow-hidden">
+      {/* 背景 */}
+      <div className="absolute contents left-0 top-0">
+        <div className="absolute h-[1080px] left-0 overflow-clip top-0 w-[1920px]">
+          <div aria-hidden="true" className="absolute inset-0 pointer-events-none">
+            <img
+              alt="背景"
+              className="absolute max-w-none object-50%-50% object-cover size-full"
+              src="https://www.figma.com/api/mcp/asset/d046358a-9a3b-42e0-89cb-4a2b2a843ced"
+            />
+            <div className="absolute bg-[rgba(0,79,154,0.1)] inset-0" />
+          </div>
+        </div>
+
+        {/* 底部网格 */}
+        <div className="absolute h-[1080px] left-0 top-0 w-[1920px]">
+          <div className="absolute bottom-[-71.42%] content-stretch flex flex-col items-start left-0 mask-alpha mask-intersect mask-no-clip mask-no-repeat mask-position-[0px_175.624px] mask-size-[1920px_1080px] right-0 top-[-16.26%]">
+            <div className="h-[1013.464px] relative shrink-0 w-[1920px]">
+              <img
+                alt="网格"
+                className="block max-w-none size-full"
+                src="https://www.figma.com/api/mcp/asset/597ea7a4-6131-4e5c-b0c3-955a775a85b0"
+              />
+            </div>
+          </div>
+        </div>
+
+        {/* 顶部标题栏 */}
+        <div className="absolute h-[71.119px] left-[526.95px] top-[40px] w-[866.265px]">
+          <div className="absolute bottom-[18.95%] left-0 right-0 top-0">
+            <div className="absolute inset-[-181.3%_-19.68%_-413.77%_-19.68%]">
+              <img
+                alt="标题栏背景"
+                className="block max-w-none size-full"
+                src="https://www.figma.com/api/mcp/asset/e595857a-5eff-4590-b426-0a8ae38539f6"
+              />
+            </div>
+          </div>
+          <div className="absolute bottom-0 left-[27.44%] right-[27.44%] top-[62.9%]">
+            <div className="absolute inset-[-257.75%_-17.4%]">
+              <img
+                alt="标题栏装饰"
+                className="block max-w-none size-full"
+                src="https://www.figma.com/api/mcp/asset/5ad5a4ea-c56a-4b77-9b93-7aa1afb09e71"
+              />
+            </div>
+          </div>
+        </div>
+
+        {/* 主标题 */}
+        <div className="absolute box-border content-stretch flex gap-[10px] items-center justify-center left-1/2 px-0 py-[4px] top-[40px] translate-x-[-50%]">
+          <div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[34px] text-center text-white tracking-[10.2px] whitespace-nowrap">
+            <p className="leading-[32px]">粮食•油脂</p>
+          </div>
+        </div>
+      </div>
+
+      {/* 左侧导航 */}
+      <Navigation activeTab={activeTab} onTabChange={setActiveTab} />
+
+      {/* 中间地图区域 */}
+      <div className="absolute contents left-[529.88px] top-[calc(50%+64.03px)] translate-y-[-50%]">
+        <div className="absolute contents left-[27.6%] right-[4.17%] top-[calc(50%+33.79px)] translate-y-[-50%]">
+          {/* 地图边框 */}
+          <div className="absolute h-[731.454px] left-[27.6%] right-[4.17%] top-[calc(50%+33.79px)] translate-y-[-50%]">
+            <div className="absolute inset-0">
+              <img
+                alt="地图边框"
+                className="block max-w-none size-full"
+                src="https://www.figma.com/api/mcp/asset/fca4f7a9-10d7-41df-8b54-87e52233ff24"
+              />
+            </div>
+          </div>
+
+          {/* 供应链网络连接线 */}
+          <div className="absolute inset-[19.27%_4.17%_13.01%_27.6%]">
+            {/* 这里可以添加供应链网络连接线的SVG或图片 */}
+            <img
+              alt="供应链网络"
+              className="block max-w-none size-full"
+              src="https://www.figma.com/api/mcp/asset/480a665e-4639-4757-b0f5-ae8c1d4e7f17"
+            />
+          </div>
+
+          {/* 定位点 - 基地 */}
+          <div className="absolute h-[48px] left-[1142.89px] top-[717.84px] w-[40px]">
+            <div className="absolute inset-[12.5%_8.66%]">
+              <img
+                alt="基地定位点"
+                className="block max-w-none size-full"
+                src="https://www.figma.com/api/mcp/asset/05a7ea4e-ca3d-42b4-a448-9693541b81c1"
+              />
+            </div>
+            <GrainIcon className="absolute inset-[27.5%_23%] overflow-clip" />
+          </div>
+
+          {/* 定位点 - 产业链 */}
+          <div className="absolute h-[48px] left-[1273.12px] top-[551.14px] w-[40px]">
+            <div className="absolute inset-[10%_13.79%]">
+              <img
+                alt="产业链定位点"
+                className="block max-w-none size-full"
+                src="https://www.figma.com/api/mcp/asset/b3a56933-87f3-4183-812c-82694fe92db1"
+              />
+            </div>
+            <IndustryChainIcon className="absolute bottom-[40.42%] left-1/4 overflow-clip right-1/4 shadow-[0px_0px_6px_0px_#4593ff] top-[17.92%]" />
+          </div>
+
+          {/* 图例 */}
+          <div className="absolute bottom-[80px] content-stretch flex items-center left-[calc(50%+224.94px)] translate-x-[-50%]">
+            <div className="box-border content-stretch flex gap-[20px] h-[54px] items-center justify-center px-[20px] py-0 relative rounded-[10px] shrink-0 w-[202px]">
+              <div className="h-[50px] relative shrink-0 w-[41.667px]">
+                <div className="absolute inset-[12.5%_8.66%]">
+                  <img
+                    alt="基地图例"
+                    className="block max-w-none size-full"
+                    src="https://www.figma.com/api/mcp/asset/70b2be21-698f-43c3-8ca1-e70d375e55c3"
+                  />
+                </div>
+                <GrainIcon className="absolute inset-[27.5%_23%] overflow-clip" />
+              </div>
+              <div className="box-border content-stretch flex gap-[10px] items-center px-0 py-[4px] relative shrink-0">
+                <div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[26px] text-white whitespace-nowrap">
+                  <p className="leading-[32px]">基地</p>
+                </div>
+              </div>
+            </div>
+
+            <div className="box-border content-stretch flex gap-[20px] h-[54px] items-center justify-center px-[20px] py-0 relative rounded-[10px] shrink-0 w-[202px]">
+              <div className="h-[50px] relative shrink-0 w-[41.667px]">
+                <div className="absolute inset-[10%_13.79%]">
+                  <img
+                    alt="产业链图例"
+                    className="block max-w-none size-full"
+                    src="https://www.figma.com/api/mcp/asset/4b244cde-2253-4616-8046-a642a889b316"
+                  />
+                </div>
+                <IndustryChainIcon className="absolute bottom-[40.42%] left-1/4 overflow-clip right-1/4 shadow-[0px_0px_6px_0px_#4593ff] top-[17.92%]" />
+              </div>
+              <div className="box-border content-stretch flex gap-[10px] items-center px-0 py-[4px] relative shrink-0">
+                <div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[26px] text-white whitespace-nowrap">
+                  <p className="leading-[32px]">产业链</p>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      {/* 右侧供应链合作模式 */}
+      <div className="absolute content-stretch flex flex-col gap-[10px] items-end right-[80px] top-[150px]">
+        <div className="box-border content-stretch flex gap-[10px] items-center px-0 py-[4px] relative shrink-0">
+          <div className="flex flex-col font-normal justify-center leading-[0] not-italic relative shrink-0 text-[24px] text-[rgba(255,255,255,0.5)] whitespace-nowrap">
+            <p className="leading-[32px]">省粮油集团+区域公司+新型农业经营主体</p>
+          </div>
+        </div>
+        <div className="box-border content-stretch flex gap-[10px] h-[77px] items-center justify-end px-0 py-[4px] relative shrink-0 w-full">
+          <div className="bg-clip-text bg-gradient-to-b flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[80px] text-right whitespace-nowrap" style={{
+            backgroundImage: 'linear-gradient(to bottom, #ffffff, #40deff)',
+            WebkitTextFillColor: 'transparent'
+          }}>
+            <p className="leading-[50px]">1+1+N</p>
+          </div>
+        </div>
+        <div className="box-border content-stretch flex gap-[10px] items-center justify-end px-0 py-[4px] relative shrink-0">
+          <div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[50px] text-[cyan] text-right whitespace-nowrap">
+            <p className="leading-[50px]">供应链合作模式</p>
+          </div>
+        </div>
+      </div>
+
+      {/* 左侧数据展示 */}
+      <div className="absolute content-stretch flex flex-col gap-[11px] items-start left-[199.88px] top-[calc(50%+4.02px)] translate-y-[-50%] w-[330px]">
+        <div className="box-border content-stretch flex gap-[10px] h-[80px] items-center px-[26px] py-[4px] relative shrink-0 w-full">
+          <div className="flex flex-col font-bold justify-center leading-[0] not-italic relative shrink-0 text-[0px] text-white whitespace-nowrap">
+            <p>
+              <span className="leading-[50px] text-[40px]">优质稻米</span>
+              <span className="leading-[32px] text-[28px]">产业链联合体</span>
+            </p>
+          </div>
+        </div>
+        <div className="grid-cols-[max-content] grid-rows-[max-content] inline-grid justify-items-start leading-[0] relative shrink-0">
+          <div className="box-border col-[1] content-stretch flex flex-col h-[700px] items-center justify-between ml-0 mt-0 px-0 py-[20px] relative row-[1] w-[330px]">
+            <DataCard
+              title="加工能力达"
+              value={grainData.processingCapacity.value}
+              unit={grainData.processingCapacity.unit}
+              digits={grainData.processingCapacity.digits}
+            />
+            <DataCard
+              title="自建优质水稻基地"
+              value={grainData.baseArea.value}
+              unit={grainData.baseArea.unit}
+              digits={grainData.baseArea.digits}
+            />
+            <DataCard
+              title="储备仓容"
+              value={grainData.storageCapacity.value}
+              unit={grainData.storageCapacity.unit}
+              digits={grainData.storageCapacity.digits}
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default GrainOilDashboard;