Просмотр исходного кода

✨ feat(home): 新增供应链大屏动态路由和统一数据管理

- 在首页添加四个供应链组合入口卡片【粮食油脂、种业果蔬、畜牧水产、鲜食泛盐】
- 创建动态路由组件 SupplyChainDashboard 支持参数化访问不同组合
- 重构 ThemeContext 为 SupplyChainContext,统一管理组合类型和产业数据
- 实现静态数据加载机制,支持四个组合的完整供应链数据展示
- 更新所有相关组件导入路径,从 ThemeContext 切换到 SupplyChainContext
- 保持向后兼容性,原有 GrainOilDashboard 组件仍可独立使用
yourname 2 месяцев назад
Родитель
Сommit
4024eced85

+ 59 - 12
src/client/home/pages/HomePage.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import { useAuth } from '@/client/home/hooks/AuthProvider';
-import { useNavigate } from 'react-router-dom';
+import { useNavigate, Link } from 'react-router-dom';
 
 const HomePage: React.FC = () => {
   const { user } = useAuth();
@@ -125,24 +125,71 @@ const HomePage: React.FC = () => {
             <p className="text-gray-600 text-sm">支持Web、移动端等多平台访问,随时随地管理您的文件</p>
           </div>
 
-          {/* 供应链可视化大屏 */}
-          <div
-            className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer"
-            onClick={() => navigate('/supply-chain/grain-oil')}
+          {/* 供应链可视化大屏 - 粮食油脂组合 */}
+          <Link
+            to="/supply-chain/grain-oil"
+            target="_blank"
+            className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer block"
           >
             <div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
               <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                 <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
               </svg>
             </div>
-            <h3 className="font-semibold text-lg mb-2">供应链可视化</h3>
-            <p className="text-gray-600 text-sm">粮食油脂供应链大屏展示,实时监控产业链运行状态</p>
-          </div>
+            <h3 className="font-semibold text-lg mb-2">粮食油脂供应链</h3>
+            <p className="text-gray-600 text-sm">粮食油脂产业链大屏展示,实时监控加工能力和基地规模</p>
+          </Link>
+
+          {/* 供应链可视化大屏 - 种业果蔬组合 */}
+          <Link
+            to="/supply-chain/seed-fruit"
+            target="_blank"
+            className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer block"
+          >
+            <div className="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center mb-4">
+              <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
+              </svg>
+            </div>
+            <h3 className="font-semibold text-lg mb-2">种业果蔬供应链</h3>
+            <p className="text-gray-600 text-sm">种业果蔬产业链大屏展示,监控良种繁育和加工能力</p>
+          </Link>
+
+          {/* 供应链可视化大屏 - 畜牧水产组合 */}
+          <Link
+            to="/supply-chain/livestock-aquaculture"
+            target="_blank"
+            className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer block"
+          >
+            <div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mb-4">
+              <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
+              </svg>
+            </div>
+            <h3 className="font-semibold text-lg mb-2">畜牧水产供应链</h3>
+            <p className="text-gray-600 text-sm">畜牧水产产业链大屏展示,监控养殖规模和基地建设</p>
+          </Link>
+
+          {/* 供应链可视化大屏 - 鲜食泛盐组合 */}
+          <Link
+            to="/supply-chain/fresh-food-salt"
+            target="_blank"
+            className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer block"
+          >
+            <div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mb-4">
+              <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-purple-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
+              </svg>
+            </div>
+            <h3 className="font-semibold text-lg mb-2">鲜食泛盐供应链</h3>
+            <p className="text-gray-600 text-sm">鲜食泛盐产业链大屏展示,监控加工能力和基地规模</p>
+          </Link>
 
           {/* 财务数据可视化大屏 */}
-          <div
-            className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer"
-            onClick={() => navigate('/financial-dashboard')}
+          <Link
+            to="/financial-dashboard"
+            target="_blank"
+            className="bg-white rounded-xl p-6 shadow-sm border border-gray-100 hover:shadow-md transition-shadow cursor-pointer block"
           >
             <div className="w-12 h-12 bg-emerald-100 rounded-lg flex items-center justify-center mb-4">
               <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-emerald-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -151,7 +198,7 @@ const HomePage: React.FC = () => {
             </div>
             <h3 className="font-semibold text-lg mb-2">财务数据可视化</h3>
             <p className="text-gray-600 text-sm">财务指标大屏展示,直观查看资产、利润、收入等关键数据</p>
-          </div>
+          </Link>
         </div>
 
         {/* 技术架构 */}

+ 5 - 5
src/client/home/pages/SupplyChainDashboards/GrainOilDashboard.tsx

@@ -11,8 +11,8 @@ import BackgroundGrid from './components/layout/BackgroundGrid';
 import HeaderBar from './components/layout/HeaderBar';
 import { IndustryType } from './components/icons/IndustryIcon';
 
-// 导入主题上下文
-import { ThemeProvider, useTheme } from './context/ThemeContext';
+// 导入供应链上下文
+import { SupplyChainProvider, useSupplyChain } from './context/SupplyChainContext';
 
 // 定义组件接口
 interface GrainOilDashboardProps {
@@ -41,7 +41,7 @@ const DashboardContent: React.FC = () => {
     isVisible: false,
     position: { x: 650, y: 250 }
   });
-  const { setIndustry } = useTheme();
+  const { setIndustry } = useSupplyChain();
 
   // 处理tab切换
   const handleTabChange = (tab: IndustryType) => {
@@ -132,9 +132,9 @@ const DashboardContent: React.FC = () => {
 // 主组件
 const GrainOilDashboard: React.FC<GrainOilDashboardProps> = () => {
   return (
-    <ThemeProvider defaultIndustry="粮食">
+    <SupplyChainProvider defaultIndustry="粮食">
       <DashboardContent />
-    </ThemeProvider>
+    </SupplyChainProvider>
   );
 };
 

+ 167 - 0
src/client/home/pages/SupplyChainDashboards/SupplyChainDashboard.tsx

@@ -0,0 +1,167 @@
+import React from 'react';
+import { useParams } from 'react-router';
+import { SupplyChainProvider, DashboardType, useSupplyChain } from './context/SupplyChainContext';
+import SupplyChainMap from './components/SupplyChainMap';
+import SupplyChainModel from './components/SupplyChainModel';
+import KeyMetrics from './components/KeyMetrics';
+import PopupInfoBox from './components/PopupInfoBox';
+import Navigation from './components/layout/Navigation';
+import SupplyChainBackground from './components/layout/SupplyChainBackground';
+import BackgroundGrid from './components/layout/BackgroundGrid';
+import HeaderBar from './components/layout/HeaderBar';
+import { IndustryType } from './components/icons/IndustryIcon';
+
+// 定义弹出框状态
+interface PopupState {
+  isVisible: boolean;
+  position: { x: number; y: number };
+  data?: {
+    title: string;
+    subtitle: string;
+    metrics: {
+      label: string;
+      value: string;
+      unit: string;
+    }[];
+  };
+}
+
+// 内部组件,使用SupplyChainContext
+const DashboardContent: React.FC = () => {
+  const [popupState, setPopupState] = React.useState<PopupState>({
+    isVisible: false,
+    position: { x: 650, y: 250 }
+  });
+  const { currentIndustry, setIndustry, currentDashboard } = useSupplyChain();
+
+  // 处理定位点点击
+  const handlePointClick = (point: any) => {
+    console.log('点击定位点:', point);
+
+    // 根据定位点类型设置不同的数据
+    let popupData;
+    if (point.type === 'base') {
+      popupData = {
+        title: "源头",
+        subtitle: "江汉大米核心示范基地荆门/荆州/黄冈/孝感",
+        metrics: [
+          { label: "辐射带动:", value: ">20", unit: "万亩" },
+          { label: "自建基地规模:", value: "6~15", unit: "万亩" }
+        ]
+      };
+    } else {
+      popupData = {
+        title: "源头",
+        subtitle: "江汉大米核心示范基地荆门/荆州/黄冈/孝感",
+        metrics: [
+          { label: "辐射带动:", value: ">20", unit: "万亩" },
+          { label: "自建基地规模:", value: "6~15", unit: "万亩" }
+        ]
+      };
+    }
+
+    setPopupState({
+      isVisible: true,
+      position: { x: 650, y: 250 },
+      data: popupData
+    });
+  };
+
+  // 关闭弹出框
+  const handleClosePopup = () => {
+    setPopupState(prev => ({ ...prev, isVisible: false }));
+  };
+
+  return (
+    <div className="h-[1080px] w-[1920px] bg-[#0a1a3a] relative overflow-hidden">
+      {/* 背景 */}
+      <div className="absolute contents left-0 top-0">
+        <SupplyChainBackground />
+        <BackgroundGrid />
+        <HeaderBar title={getDashboardTitle(currentDashboard)} />
+      </div>
+
+      {/* 左侧导航 */}
+      <Navigation
+        activeTab={currentIndustry}
+        onTabChange={setIndustry}
+        availableIndustries={getDashboardIndustries(currentDashboard)}
+      />
+
+      {/* 中间地图区域 */}
+      <SupplyChainMap
+        onPointClick={handlePointClick}
+      />
+
+      {/* 右侧供应链合作模式 */}
+      <SupplyChainModel />
+
+      {/* 左侧数据展示 */}
+      <KeyMetrics
+        title={getMetricsTitle(currentDashboard)}
+        subtitle="产业链联合体"
+      />
+
+      {/* 弹出框 */}
+      {popupState.isVisible && (
+        <PopupInfoBox
+          data={popupState.data}
+          position={popupState.position}
+          onClose={handleClosePopup}
+        />
+      )}
+    </div>
+  );
+};
+
+// 辅助函数:根据组合类型获取标题
+const getDashboardTitle = (dashboardType: DashboardType): string => {
+  const titles: Record<DashboardType, string> = {
+    'grain-oil': '粮食•油脂',
+    'seed-fruit': '种业•果蔬',
+    'livestock-aquaculture': '畜牧•水产',
+    'fresh-food-salt': '鲜食•泛盐'
+  };
+  return titles[dashboardType] || '供应链大屏';
+};
+
+// 辅助函数:根据组合类型获取支持的产业
+const getDashboardIndustries = (dashboardType: DashboardType): IndustryType[] => {
+  const industries: Record<DashboardType, IndustryType[]> = {
+    'grain-oil': ['粮食', '油脂'],
+    'seed-fruit': ['种业', '果蔬'],
+    'livestock-aquaculture': ['畜牧', '水产'],
+    'fresh-food-salt': ['鲜食', '泛盐']
+  };
+  return industries[dashboardType] || ['粮食', '油脂'];
+};
+
+// 辅助函数:根据组合类型获取指标标题
+const getMetricsTitle = (dashboardType: DashboardType): string => {
+  const titles: Record<DashboardType, string> = {
+    'grain-oil': '优质稻米',
+    'seed-fruit': '良种繁育',
+    'livestock-aquaculture': '养殖规模',
+    'fresh-food-salt': '加工能力'
+  };
+  return titles[dashboardType] || '关键指标';
+};
+
+// 主组件
+const SupplyChainDashboard: React.FC = () => {
+  const { dashboardType } = useParams<{ dashboardType: DashboardType }>();
+
+  // 验证路由参数
+  const validDashboardTypes: DashboardType[] = ['grain-oil', 'seed-fruit', 'livestock-aquaculture', 'fresh-food-salt'];
+  const currentDashboard = dashboardType && validDashboardTypes.includes(dashboardType as DashboardType)
+    ? dashboardType as DashboardType
+    : 'grain-oil';
+
+  return (
+    <SupplyChainProvider defaultDashboard={currentDashboard}>
+      <DashboardContent />
+    </SupplyChainProvider>
+  );
+};
+
+export default SupplyChainDashboard;

+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/KeyMetrics.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { useTheme } from './../context/ThemeContext';
+import { useSupplyChain } from './../context/SupplyChainContext';
 
 // 定义指标数据类型
 interface MetricData {
@@ -21,7 +21,7 @@ const DataCard: React.FC<{
   unit: string;
   digits: string[];
 }> = ({ title, unit, digits }) => {
-  const { themeColor } = useTheme();
+  const { themeColor } = useSupplyChain();
 
   return (
     <div className="box-border content-stretch flex flex-col gap-[20px] items-start px-0 py-[20px] relative shrink-0 w-[278px]">

+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/PopupInfoBox.tsx

@@ -1,7 +1,7 @@
 import React from 'react';
 import { IndustryType } from './icons/IndustryIcon';
 import PopupInfoBoxIcon from './icons/PopupInfoBox';
-import { useTheme } from './../context/ThemeContext';
+import { useSupplyChain } from './../context/SupplyChainContext';
 
 // 定义弹出框数据类型
 interface PopupData {
@@ -26,7 +26,7 @@ const PopupInfoBox: React.FC<PopupInfoBoxProps> = ({
   position = { x: 717.28, y: 273.13 },
   onClose
 }) => {
-  const { themeColor } = useTheme();
+  const { themeColor } = useSupplyChain();
   // 默认数据
   const defaultData: PopupData = {
     title: "源头",

+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/icons/BasePointIcon.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { useTheme } from '../../context/ThemeContext';
+import { useSupplyChain } from '../../context/SupplyChainContext';
 
 interface BasePointIconProps {
   className?: string;
@@ -12,7 +12,7 @@ const BasePointIcon: React.FC<BasePointIconProps> = ({
   width,
   height
 }) => {
-  const { currentIndustry } = useTheme();
+  const { currentIndustry } = useSupplyChain();
 
   // 根据产业类型加载对应的SVG文件
   const getIconPath = (industry: string) => {

+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/icons/Img5.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { useTheme } from '../../context/ThemeContext';
+import { useSupplyChain } from '../../context/SupplyChainContext';
 
 interface Img5Props {
   className?: string;
@@ -16,7 +16,7 @@ const Img5: React.FC<Img5Props> = ({
   width,
   height
 }) => {
-  const { themeColor } = useTheme();
+  const { themeColor } = useSupplyChain();
   return (
     <svg height="50" width="50" fill="none" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
 	<path d="M28.1795 7.10254C28.1795 7.10254 27.0088 6.45224 25 6.5028C22.9911 6.45224 21.8222 7.10254 21.8222 7.10254V9.54132H28.1795V7.10254L28.1795 7.10254ZM36.8945 40.2447C36.8945 40.2447 36.8945 19.4698 36.8945 18.3318C36.8945 17.1937 36.1755 16.8143 36.1755 16.8143L28.2103 10.4699H21.7915L13.8263 16.8143C13.8263 16.8143 13.1055 17.1937 13.1055 18.3318C13.1055 19.4698 13.1055 40.2447 13.1055 40.2447C13.1055 40.2447 12.8273 43.5 16.3753 43.5H21.8222C25.0542 43.5 28.1795 43.5 28.1795 43.5H33.6263C37.1727 43.5 36.8945 40.2447 36.8945 40.2447ZM33.6245 32.372C33.6245 32.7296 33.3247 33.0223 32.9561 33.0223H28.0874C27.7189 33.0223 27.4208 32.7296 27.4208 32.372V21.6268C27.4208 21.2656 27.7189 20.9747 28.0874 20.9747H32.9562C33.3247 20.9747 33.6246 21.2656 33.6246 21.6268V32.372L33.6245 32.372Z" fill="white" fillOpacity="0.5" opacity="0.78"/>

+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/icons/IndustryIcon.tsx

@@ -1,7 +1,7 @@
 import React from 'react';
 import GrainIcon from './GrainIcon';
 import OilIcon from './OilIcon';
-import { useTheme } from '../../context/ThemeContext';
+import { useSupplyChain } from '../../context/SupplyChainContext';
 
 // 定义产业类型
 export type IndustryType = "粮食" | "油脂" | "种业" | "果蔬" | "畜牧" | "水产" | "鲜食" | "泛盐";
@@ -20,7 +20,7 @@ const IndustryIcon: React.FC<IndustryIconProps> = ({
   industry,
   isActive = true
 }) => {
-  const { themeColor } = useTheme();
+  const { themeColor } = useSupplyChain();
   const themeColorClass = `text-[${themeColor}]`;
   const iconColor = isActive ? themeColorClass : "text-white opacity-50";
 

+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/icons/PopupInfoBox.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { useTheme } from '../../context/ThemeContext';
+import { useSupplyChain } from '../../context/SupplyChainContext';
 
 interface PopupInfoBoxProps {
   className?: string;
@@ -16,7 +16,7 @@ const PopupInfoBox: React.FC<PopupInfoBoxProps> = ({
   width,
   height
 }) => {
-  const { themeColor } = useTheme();
+  const { themeColor } = useSupplyChain();
   return (
     <svg height="320" width="573" fill="none" viewBox="0 0 573 320" xmlns="http://www.w3.org/2000/svg">
 	<g clipPath="url(#clip0_2019_16940)">

+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/icons/SupplyChainIcons.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { useTheme } from '../../context/ThemeContext';
+import { useSupplyChain } from '../../context/SupplyChainContext';
 
 interface SupplyChainIconsProps {
   className?: string;
@@ -12,7 +12,7 @@ const SupplyChainIcons: React.FC<SupplyChainIconsProps> = ({
   width,
   height
 }) => {
-  const { currentIndustry } = useTheme();
+  const { currentIndustry } = useSupplyChain();
 
   // 根据产业类型加载对应的SVG文件
   const getIconPath = (industry: string) => {

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
src/client/home/pages/SupplyChainDashboards/components/icons/Union.tsx


+ 638 - 0
src/client/home/pages/SupplyChainDashboards/context/SupplyChainContext.tsx

@@ -0,0 +1,638 @@
+import React, { createContext, useContext, useState, ReactNode, useEffect } from 'react';
+import { useQuery, useQueryClient } from '@tanstack/react-query';
+
+// 继承自现有ThemeContext的产业类型
+export type IndustryType = "粮食" | "油脂" | "种业" | "果蔬" | "畜牧" | "水产" | "鲜食" | "泛盐";
+
+// 组合类型定义
+export type DashboardType = 'grain-oil' | 'seed-fruit' | 'livestock-aquaculture' | 'fresh-food-salt';
+
+// 产业主题色映射
+const industryColors: Record<IndustryType, string> = {
+  "粮食": "#C5FF92",
+  "油脂": "#f6b02e",
+  "种业": "#5def8b",
+  "果蔬": "#fff586",
+  "畜牧": "#f593a5",
+  "水产": "#6be9ff",
+  "鲜食": "#de7e66",
+  "泛盐": "#92a5fe"
+};
+
+// 定位点坐标接口
+interface LocationPoint {
+  id: string;
+  type: 'base' | 'chain';
+  x: number;
+  y: number;
+  industry: IndustryType;
+  name?: string;
+  data?: Record<string, any>;
+}
+
+// 关键指标数据接口
+interface MetricData {
+  id: string;
+  label: string;
+  value: string | number;
+  unit?: string;
+  industry: IndustryType;
+}
+
+// 供应链网络数据接口
+interface SupplyChainNetwork {
+  connections: Array<{
+    from: string;
+    to: string;
+    type: string;
+  }>;
+  nodes: Record<string, LocationPoint>;
+}
+
+// 弹出框数据接口
+interface PopupData {
+  id: string;
+  title: string;
+  content: string;
+  position: { x: number; y: number };
+  industry: IndustryType;
+  metrics?: Array<{
+    label: string;
+    value: string;
+    unit: string;
+  }>;
+}
+
+// 供应链数据接口
+interface SupplyChainData {
+  // 组合名称
+  name: string;
+  // 支持的产业
+  industries: IndustryType[];
+  // 定位点数据
+  mapPoints: Partial<Record<IndustryType, LocationPoint[]>>;
+  // 关键指标数据
+  keyMetrics: Partial<Record<IndustryType, MetricData[]>>;
+  // 供应链网络数据
+  supplyChainNetwork: Partial<Record<IndustryType, SupplyChainNetwork>>;
+  // 弹出框数据
+  popupData: Partial<Record<IndustryType, PopupData[]>>;
+}
+
+// 扩展的Context接口
+interface SupplyChainContextType {
+  // 当前组合类型
+  currentDashboard: DashboardType;
+  // 当前产业
+  currentIndustry: IndustryType;
+  // 主题色
+  themeColor: string;
+  // 当前组合数据
+  currentData: SupplyChainData | null;
+  // 加载状态
+  isLoading: boolean;
+  // 错误信息
+  error: string | null;
+  // 设置方法
+  setDashboard: (dashboard: DashboardType) => void;
+  setIndustry: (industry: IndustryType) => void;
+  // 数据加载方法
+  loadDashboardData: (dashboard: DashboardType) => Promise<void>;
+  // 刷新数据
+  refreshData: () => Promise<void>;
+}
+
+// 创建Context
+const SupplyChainContext = createContext<SupplyChainContextType | undefined>(undefined);
+
+// Provider Props接口
+interface SupplyChainProviderProps {
+  children: ReactNode;
+  defaultDashboard?: DashboardType;
+  defaultIndustry?: IndustryType;
+}
+
+// 静态数据定义 - 粮食-油脂组合
+const grainOilData: SupplyChainData = {
+  name: '粮食-油脂组合',
+  industries: ['粮食', '油脂'],
+  mapPoints: {
+    '粮食': [
+      { id: 'grain-base1', type: 'base', x: 1142.89, y: 717.84, industry: '粮食' },
+      { id: 'grain-base2', type: 'base', x: 1664.25, y: 530.82, industry: '粮食' },
+      { id: 'grain-base3', type: 'base', x: 1435, y: 527.14, industry: '粮食' },
+      { id: 'grain-base4', type: 'base', x: 1203.07, y: 514.31, industry: '粮食' },
+      { id: 'grain-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '粮食' },
+      { id: 'grain-chain2', type: 'chain', x: 1403, y: 597.5, industry: '粮食' },
+      { id: 'grain-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '粮食' },
+      { id: 'grain-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '粮食' }
+    ],
+    '油脂': [
+      { id: 'oil-base1', type: 'base', x: 985, y: 610.22, industry: '油脂' },
+      { id: 'oil-base2', type: 'base', x: 1125.81, y: 409.52, industry: '油脂' },
+      { id: 'oil-base3', type: 'base', x: 1229.57, y: 570, industry: '油脂' },
+      { id: 'oil-base4', type: 'base', x: 1445, y: 560.35, industry: '油脂' },
+      { id: 'oil-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '油脂' },
+      { id: 'oil-chain2', type: 'chain', x: 1178.36, y: 418.4, industry: '油脂' },
+      { id: 'oil-chain3', type: 'chain', x: 1307.42, y: 551.47, industry: '油脂' },
+      { id: 'oil-chain4', type: 'chain', x: 1403.37, y: 603.77, industry: '油脂' }
+    ]
+  },
+  keyMetrics: {
+    '粮食': [
+      { id: 'grain-metric1', label: '加工能力达', value: '200', unit: '万吨/年', industry: '粮食' },
+      { id: 'grain-metric2', label: '自建优质水稻基地', value: '15', unit: '万亩', industry: '粮食' },
+      { id: 'grain-metric3', label: '辐射带动面积', value: '20', unit: '万亩', industry: '粮食' }
+    ],
+    '油脂': [
+      { id: 'oil-metric1', label: '加工能力达', value: '150', unit: '万吨/年', industry: '油脂' },
+      { id: 'oil-metric2', label: '自建油料基地', value: '10', unit: '万亩', industry: '油脂' },
+      { id: 'oil-metric3', label: '辐射带动面积', value: '18', unit: '万亩', industry: '油脂' }
+    ]
+  },
+  supplyChainNetwork: {
+    '粮食': {
+      connections: [
+        { from: 'grain-base1', to: 'grain-chain1', type: 'supply' },
+        { from: 'grain-base2', to: 'grain-chain2', type: 'supply' },
+        { from: 'grain-base3', to: 'grain-chain3', type: 'supply' },
+        { from: 'grain-base4', to: 'grain-chain4', type: 'supply' }
+      ],
+      nodes: {
+        'grain-base1': { id: 'grain-base1', type: 'base', x: 1142.89, y: 717.84, industry: '粮食' },
+        'grain-base2': { id: 'grain-base2', type: 'base', x: 1664.25, y: 530.82, industry: '粮食' },
+        'grain-base3': { id: 'grain-base3', type: 'base', x: 1435, y: 527.14, industry: '粮食' },
+        'grain-base4': { id: 'grain-base4', type: 'base', x: 1203.07, y: 514.31, industry: '粮食' },
+        'grain-chain1': { id: 'grain-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '粮食' },
+        'grain-chain2': { id: 'grain-chain2', type: 'chain', x: 1403, y: 597.5, industry: '粮食' },
+        'grain-chain3': { id: 'grain-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '粮食' },
+        'grain-chain4': { id: 'grain-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '粮食' }
+      }
+    },
+    '油脂': {
+      connections: [
+        { from: 'oil-base1', to: 'oil-chain1', type: 'supply' },
+        { from: 'oil-base2', to: 'oil-chain2', type: 'supply' },
+        { from: 'oil-base3', to: 'oil-chain3', type: 'supply' },
+        { from: 'oil-base4', to: 'oil-chain4', type: 'supply' }
+      ],
+      nodes: {
+        'oil-base1': { id: 'oil-base1', type: 'base', x: 985, y: 610.22, industry: '油脂' },
+        'oil-base2': { id: 'oil-base2', type: 'base', x: 1125.81, y: 409.52, industry: '油脂' },
+        'oil-base3': { id: 'oil-base3', type: 'base', x: 1229.57, y: 570, industry: '油脂' },
+        'oil-base4': { id: 'oil-base4', type: 'base', x: 1445, y: 560.35, industry: '油脂' },
+        'oil-chain1': { id: 'oil-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '油脂' },
+        'oil-chain2': { id: 'oil-chain2', type: 'chain', x: 1178.36, y: 418.4, industry: '油脂' },
+        'oil-chain3': { id: 'oil-chain3', type: 'chain', x: 1307.42, y: 551.47, industry: '油脂' },
+        'oil-chain4': { id: 'oil-chain4', type: 'chain', x: 1403.37, y: 603.77, industry: '油脂' }
+      }
+    }
+  },
+  popupData: {
+    '粮食': [
+      {
+        id: 'grain-popup1',
+        title: '源头',
+        content: '江汉大米核心示范基地荆门/荆州/黄冈/孝感',
+        position: { x: 717.28, y: 273.13 },
+        industry: '粮食',
+        metrics: [
+          { label: '辐射带动:', value: '>20', unit: '万亩' },
+          { label: '自建基地规模:', value: '6~15', unit: '万亩' }
+        ]
+      }
+    ],
+    '油脂': [
+      {
+        id: 'oil-popup1',
+        title: '源头',
+        content: '油脂核心示范基地',
+        position: { x: 814.45, y: 464.02 },
+        industry: '油脂',
+        metrics: [
+          { label: '辐射带动:', value: '>18', unit: '万亩' },
+          { label: '自建基地规模:', value: '5~10', unit: '万亩' }
+        ]
+      }
+    ]
+  }
+};
+
+// 其他组合的静态数据定义(简化版,实际使用时需要完整定义)
+const seedFruitData: SupplyChainData = {
+  name: '种业-果蔬组合',
+  industries: ['种业', '果蔬'],
+  mapPoints: {
+    '种业': [
+      { id: 'seed-base1', type: 'base', x: 1142.89, y: 717.84, industry: '种业' },
+      { id: 'seed-base2', type: 'base', x: 1664.25, y: 530.82, industry: '种业' },
+      { id: 'seed-base3', type: 'base', x: 1435, y: 527.14, industry: '种业' },
+      { id: 'seed-base4', type: 'base', x: 1203.07, y: 514.31, industry: '种业' },
+      { id: 'seed-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '种业' },
+      { id: 'seed-chain2', type: 'chain', x: 1403, y: 597.5, industry: '种业' },
+      { id: 'seed-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '种业' },
+      { id: 'seed-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '种业' }
+    ],
+    '果蔬': [
+      { id: 'fruit-base1', type: 'base', x: 985, y: 610.22, industry: '果蔬' },
+      { id: 'fruit-base2', type: 'base', x: 1125.81, y: 409.52, industry: '果蔬' },
+      { id: 'fruit-base3', type: 'base', x: 1229.57, y: 570, industry: '果蔬' },
+      { id: 'fruit-base4', type: 'base', x: 1445, y: 560.35, industry: '果蔬' },
+      { id: 'fruit-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '果蔬' }
+    ]
+  },
+  keyMetrics: {
+    '种业': [
+      { id: 'seed-metric1', label: '良种繁育能力', value: '50', unit: '万公斤/年', industry: '种业' },
+      { id: 'seed-metric2', label: '自建育种基地', value: '8', unit: '万亩', industry: '种业' },
+      { id: 'seed-metric3', label: '辐射带动面积', value: '15', unit: '万亩', industry: '种业' }
+    ],
+    '果蔬': [
+      { id: 'fruit-metric1', label: '加工能力达', value: '80', unit: '万吨/年', industry: '果蔬' },
+      { id: 'fruit-metric2', label: '自建果蔬基地', value: '12', unit: '万亩', industry: '果蔬' },
+      { id: 'fruit-metric3', label: '辐射带动面积', value: '25', unit: '万亩', industry: '果蔬' }
+    ]
+  },
+  supplyChainNetwork: {
+    '种业': {
+      connections: [
+        { from: 'seed-base1', to: 'seed-chain1', type: 'supply' },
+        { from: 'seed-base2', to: 'seed-chain2', type: 'supply' },
+        { from: 'seed-base3', to: 'seed-chain3', type: 'supply' },
+        { from: 'seed-base4', to: 'seed-chain4', type: 'supply' }
+      ],
+      nodes: {
+        'seed-base1': { id: 'seed-base1', type: 'base', x: 1142.89, y: 717.84, industry: '种业' },
+        'seed-base2': { id: 'seed-base2', type: 'base', x: 1664.25, y: 530.82, industry: '种业' },
+        'seed-base3': { id: 'seed-base3', type: 'base', x: 1435, y: 527.14, industry: '种业' },
+        'seed-base4': { id: 'seed-base4', type: 'base', x: 1203.07, y: 514.31, industry: '种业' },
+        'seed-chain1': { id: 'seed-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '种业' },
+        'seed-chain2': { id: 'seed-chain2', type: 'chain', x: 1403, y: 597.5, industry: '种业' },
+        'seed-chain3': { id: 'seed-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '种业' },
+        'seed-chain4': { id: 'seed-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '种业' }
+      }
+    },
+    '果蔬': {
+      connections: [
+        { from: 'fruit-base1', to: 'fruit-chain1', type: 'supply' },
+        { from: 'fruit-base2', to: 'fruit-chain1', type: 'supply' },
+        { from: 'fruit-base3', to: 'fruit-chain1', type: 'supply' },
+        { from: 'fruit-base4', to: 'fruit-chain1', type: 'supply' }
+      ],
+      nodes: {
+        'fruit-base1': { id: 'fruit-base1', type: 'base', x: 985, y: 610.22, industry: '果蔬' },
+        'fruit-base2': { id: 'fruit-base2', type: 'base', x: 1125.81, y: 409.52, industry: '果蔬' },
+        'fruit-base3': { id: 'fruit-base3', type: 'base', x: 1229.57, y: 570, industry: '果蔬' },
+        'fruit-base4': { id: 'fruit-base4', type: 'base', x: 1445, y: 560.35, industry: '果蔬' },
+        'fruit-chain1': { id: 'fruit-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '果蔬' }
+      }
+    }
+  },
+  popupData: {
+    '种业': [
+      {
+        id: 'seed-popup1',
+        title: '源头',
+        content: '种业核心示范基地',
+        position: { x: 717.28, y: 273.13 },
+        industry: '种业',
+        metrics: [
+          { label: '辐射带动:', value: '>15', unit: '万亩' },
+          { label: '自建基地规模:', value: '4~8', unit: '万亩' }
+        ]
+      }
+    ],
+    '果蔬': [
+      {
+        id: 'fruit-popup1',
+        title: '源头',
+        content: '果蔬核心示范基地',
+        position: { x: 814.45, y: 464.02 },
+        industry: '果蔬',
+        metrics: [
+          { label: '辐射带动:', value: '>25', unit: '万亩' },
+          { label: '自建基地规模:', value: '8~12', unit: '万亩' }
+        ]
+      }
+    ]
+  }
+};
+
+const livestockAquacultureData: SupplyChainData = {
+  name: '畜牧-水产组合',
+  industries: ['畜牧', '水产'],
+  mapPoints: {
+    '畜牧': [
+      { id: 'livestock-base1', type: 'base', x: 1203.07, y: 514.31, industry: '畜牧' },
+      { id: 'livestock-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '畜牧' },
+      { id: 'livestock-chain2', type: 'chain', x: 1403, y: 597.5, industry: '畜牧' },
+      { id: 'livestock-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '畜牧' },
+      { id: 'livestock-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '畜牧' }
+    ],
+    '水产': [
+      { id: 'aquaculture-base1', type: 'base', x: 1445, y: 560.35, industry: '水产' },
+      { id: 'aquaculture-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '水产' },
+      { id: 'aquaculture-chain2', type: 'chain', x: 1178.36, y: 418.4, industry: '水产' },
+      { id: 'aquaculture-chain3', type: 'chain', x: 1307.42, y: 551.47, industry: '水产' },
+      { id: 'aquaculture-chain4', type: 'chain', x: 1403.37, y: 603.77, industry: '水产' }
+    ]
+  },
+  keyMetrics: {
+    '畜牧': [
+      { id: 'livestock-metric1', label: '养殖规模', value: '100', unit: '万头/年', industry: '畜牧' },
+      { id: 'livestock-metric2', label: '自建养殖基地', value: '20', unit: '万亩', industry: '畜牧' },
+      { id: 'livestock-metric3', label: '辐射带动面积', value: '30', unit: '万亩', industry: '畜牧' }
+    ],
+    '水产': [
+      { id: 'aquaculture-metric1', label: '养殖规模', value: '50', unit: '万吨/年', industry: '水产' },
+      { id: 'aquaculture-metric2', label: '自建养殖基地', value: '15', unit: '万亩', industry: '水产' },
+      { id: 'aquaculture-metric3', label: '辐射带动面积', value: '22', unit: '万亩', industry: '水产' }
+    ]
+  },
+  supplyChainNetwork: {
+    '畜牧': {
+      connections: [
+        { from: 'livestock-base1', to: 'livestock-chain1', type: 'supply' },
+        { from: 'livestock-base1', to: 'livestock-chain2', type: 'supply' },
+        { from: 'livestock-base1', to: 'livestock-chain3', type: 'supply' },
+        { from: 'livestock-base1', to: 'livestock-chain4', type: 'supply' }
+      ],
+      nodes: {
+        'livestock-base1': { id: 'livestock-base1', type: 'base', x: 1203.07, y: 514.31, industry: '畜牧' },
+        'livestock-chain1': { id: 'livestock-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '畜牧' },
+        'livestock-chain2': { id: 'livestock-chain2', type: 'chain', x: 1403, y: 597.5, industry: '畜牧' },
+        'livestock-chain3': { id: 'livestock-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '畜牧' },
+        'livestock-chain4': { id: 'livestock-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '畜牧' }
+      }
+    },
+    '水产': {
+      connections: [
+        { from: 'aquaculture-base1', to: 'aquaculture-chain1', type: 'supply' },
+        { from: 'aquaculture-base1', to: 'aquaculture-chain2', type: 'supply' },
+        { from: 'aquaculture-base1', to: 'aquaculture-chain3', type: 'supply' },
+        { from: 'aquaculture-base1', to: 'aquaculture-chain4', type: 'supply' }
+      ],
+      nodes: {
+        'aquaculture-base1': { id: 'aquaculture-base1', type: 'base', x: 1445, y: 560.35, industry: '水产' },
+        'aquaculture-chain1': { id: 'aquaculture-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '水产' },
+        'aquaculture-chain2': { id: 'aquaculture-chain2', type: 'chain', x: 1178.36, y: 418.4, industry: '水产' },
+        'aquaculture-chain3': { id: 'aquaculture-chain3', type: 'chain', x: 1307.42, y: 551.47, industry: '水产' },
+        'aquaculture-chain4': { id: 'aquaculture-chain4', type: 'chain', x: 1403.37, y: 603.77, industry: '水产' }
+      }
+    }
+  },
+  popupData: {
+    '畜牧': [
+      {
+        id: 'livestock-popup1',
+        title: '源头',
+        content: '畜牧核心示范基地',
+        position: { x: 717.28, y: 273.13 },
+        industry: '畜牧',
+        metrics: [
+          { label: '辐射带动:', value: '>30', unit: '万亩' },
+          { label: '自建基地规模:', value: '15~20', unit: '万亩' }
+        ]
+      }
+    ],
+    '水产': [
+      {
+        id: 'aquaculture-popup1',
+        title: '源头',
+        content: '水产核心示范基地',
+        position: { x: 814.45, y: 464.02 },
+        industry: '水产',
+        metrics: [
+          { label: '辐射带动:', value: '>22', unit: '万亩' },
+          { label: '自建基地规模:', value: '10~15', unit: '万亩' }
+        ]
+      }
+    ]
+  }
+};
+
+const freshFoodSaltData: SupplyChainData = {
+  name: '鲜食-泛盐组合',
+  industries: ['鲜食', '泛盐'],
+  mapPoints: {
+    '鲜食': [
+      { id: 'fresh-base1', type: 'base', x: 1203.07, y: 514.31, industry: '鲜食' },
+      { id: 'fresh-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '鲜食' },
+      { id: 'fresh-chain2', type: 'chain', x: 1403, y: 597.5, industry: '鲜食' },
+      { id: 'fresh-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '鲜食' },
+      { id: 'fresh-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '鲜食' }
+    ],
+    '泛盐': [
+      { id: 'salt-base1', type: 'base', x: 1445, y: 560.35, industry: '泛盐' },
+      { id: 'salt-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '泛盐' },
+      { id: 'salt-chain2', type: 'chain', x: 1178.36, y: 418.4, industry: '泛盐' },
+      { id: 'salt-chain3', type: 'chain', x: 1319.74, y: 441.51, industry: '泛盐' },
+      { id: 'salt-chain4', type: 'chain', x: 1403.37, y: 603.77, industry: '泛盐' }
+    ]
+  },
+  keyMetrics: {
+    '鲜食': [
+      { id: 'fresh-metric1', label: '加工能力达', value: '60', unit: '万吨/年', industry: '鲜食' },
+      { id: 'fresh-metric2', label: '自建鲜食基地', value: '8', unit: '万亩', industry: '鲜食' },
+      { id: 'fresh-metric3', label: '辐射带动面积', value: '18', unit: '万亩', industry: '鲜食' }
+    ],
+    '泛盐': [
+      { id: 'salt-metric1', label: '加工能力达', value: '40', unit: '万吨/年', industry: '泛盐' },
+      { id: 'salt-metric2', label: '自建盐业基地', value: '6', unit: '万亩', industry: '泛盐' },
+      { id: 'salt-metric3', label: '辐射带动面积', value: '12', unit: '万亩', industry: '泛盐' }
+    ]
+  },
+  supplyChainNetwork: {
+    '鲜食': {
+      connections: [
+        { from: 'fresh-base1', to: 'fresh-chain1', type: 'supply' },
+        { from: 'fresh-base1', to: 'fresh-chain2', type: 'supply' },
+        { from: 'fresh-base1', to: 'fresh-chain3', type: 'supply' },
+        { from: 'fresh-base1', to: 'fresh-chain4', type: 'supply' }
+      ],
+      nodes: {
+        'fresh-base1': { id: 'fresh-base1', type: 'base', x: 1203.07, y: 514.31, industry: '鲜食' },
+        'fresh-chain1': { id: 'fresh-chain1', type: 'chain', x: 1273.12, y: 551.14, industry: '鲜食' },
+        'fresh-chain2': { id: 'fresh-chain2', type: 'chain', x: 1403, y: 597.5, industry: '鲜食' },
+        'fresh-chain3': { id: 'fresh-chain3', type: 'chain', x: 1694.25, y: 645.5, industry: '鲜食' },
+        'fresh-chain4': { id: 'fresh-chain4', type: 'chain', x: 1237.87, y: 761.84, industry: '鲜食' }
+      }
+    },
+    '泛盐': {
+      connections: [
+        { from: 'salt-base1', to: 'salt-chain1', type: 'supply' },
+        { from: 'salt-base1', to: 'salt-chain2', type: 'supply' },
+        { from: 'salt-base1', to: 'salt-chain3', type: 'supply' },
+        { from: 'salt-base1', to: 'salt-chain4', type: 'supply' }
+      ],
+      nodes: {
+        'salt-base1': { id: 'salt-base1', type: 'base', x: 1445, y: 560.35, industry: '泛盐' },
+        'salt-chain1': { id: 'salt-chain1', type: 'chain', x: 949.08, y: 680.31, industry: '泛盐' },
+        'salt-chain2': { id: 'salt-chain2', type: 'chain', x: 1178.36, y: 418.4, industry: '泛盐' },
+        'salt-chain3': { id: 'salt-chain3', type: 'chain', x: 1319.74, y: 441.51, industry: '泛盐' },
+        'salt-chain4': { id: 'salt-chain4', type: 'chain', x: 1403.37, y: 603.77, industry: '泛盐' }
+      }
+    }
+  },
+  popupData: {
+    '鲜食': [
+      {
+        id: 'fresh-popup1',
+        title: '源头',
+        content: '鲜食核心示范基地',
+        position: { x: 717.28, y: 273.13 },
+        industry: '鲜食',
+        metrics: [
+          { label: '辐射带动:', value: '>18', unit: '万亩' },
+          { label: '自建基地规模:', value: '5~8', unit: '万亩' }
+        ]
+      }
+    ],
+    '泛盐': [
+      {
+        id: 'salt-popup1',
+        title: '源头',
+        content: '泛盐核心示范基地',
+        position: { x: 814.45, y: 464.02 },
+        industry: '泛盐',
+        metrics: [
+          { label: '辐射带动:', value: '>12', unit: '万亩' },
+          { label: '自建基地规模:', value: '3~6', unit: '万亩' }
+        ]
+      }
+    ]
+  }
+};
+
+// 静态数据加载函数
+const loadStaticData = async (dashboardType: DashboardType): Promise<SupplyChainData> => {
+  // 模拟API延迟
+  await new Promise(resolve => setTimeout(resolve, 500));
+
+  // 返回对应组合的静态数据
+  switch (dashboardType) {
+    case 'grain-oil':
+      return grainOilData;
+    case 'seed-fruit':
+      return seedFruitData;
+    case 'livestock-aquaculture':
+      return livestockAquacultureData;
+    case 'fresh-food-salt':
+      return freshFoodSaltData;
+    default:
+      throw new Error(`Unknown dashboard type: ${dashboardType}`);
+  }
+};
+
+// SupplyChainProvider组件
+export const SupplyChainProvider: React.FC<SupplyChainProviderProps> = ({
+  children,
+  defaultDashboard = 'grain-oil',
+  defaultIndustry = '粮食'
+}) => {
+  const [currentDashboard, setCurrentDashboard] = useState<DashboardType>(defaultDashboard);
+  const [currentIndustry, setCurrentIndustry] = useState<IndustryType>(defaultIndustry);
+  const [currentData, setCurrentData] = useState<SupplyChainData | null>(null);
+  const [isLoading, setIsLoading] = useState(false);
+  const [error, setError] = useState<string | null>(null);
+
+  const themeColor = industryColors[currentIndustry];
+
+  // 使用React Query加载数据
+  const queryClient = useQueryClient();
+
+  const { data, isLoading: queryLoading, error: queryError } = useQuery({
+    queryKey: ['supply-chain', currentDashboard],
+    queryFn: () => loadStaticData(currentDashboard),
+    enabled: !!currentDashboard,
+  });
+
+  // 同步数据到状态
+  useEffect(() => {
+    if (data) {
+      setCurrentData(data);
+    }
+  }, [data]);
+
+  // 合并加载状态
+  useEffect(() => {
+    setIsLoading(queryLoading);
+  }, [queryLoading]);
+
+  // 合并错误状态
+  useEffect(() => {
+    if (queryError) {
+      setError(queryError instanceof Error ? queryError.message : '数据加载失败');
+    } else {
+      setError(null);
+    }
+  }, [queryError]);
+
+  // 设置组合
+  const handleSetDashboard = (dashboard: DashboardType) => {
+    setCurrentDashboard(dashboard);
+    // 重置当前产业为组合的第一个产业
+    if (currentData && currentData.industries.length > 0) {
+      setCurrentIndustry(currentData.industries[0]);
+    }
+  };
+
+  // 设置产业
+  const handleSetIndustry = (industry: IndustryType) => {
+    setCurrentIndustry(industry);
+  };
+
+  // 加载数据
+  const handleLoadDashboardData = async (dashboard: DashboardType) => {
+    try {
+      setIsLoading(true);
+      setError(null);
+      const data = await loadStaticData(dashboard);
+      setCurrentData(data);
+      setCurrentDashboard(dashboard);
+      // 设置默认产业
+      if (data.industries.length > 0) {
+        setCurrentIndustry(data.industries[0]);
+      }
+    } catch (err) {
+      setError(err instanceof Error ? err.message : '数据加载失败');
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  // 刷新数据
+  const handleRefreshData = async () => {
+    await queryClient.invalidateQueries({ queryKey: ['supply-chain', currentDashboard] });
+  };
+
+  const contextValue: SupplyChainContextType = {
+    currentDashboard,
+    currentIndustry,
+    themeColor,
+    currentData,
+    isLoading,
+    error,
+    setDashboard: handleSetDashboard,
+    setIndustry: handleSetIndustry,
+    loadDashboardData: handleLoadDashboardData,
+    refreshData: handleRefreshData,
+  };
+
+  return (
+    <SupplyChainContext.Provider value={contextValue}>
+      {children}
+    </SupplyChainContext.Provider>
+  );
+};
+
+// 使用SupplyChainContext的Hook
+export const useSupplyChain = (): SupplyChainContextType => {
+  const context = useContext(SupplyChainContext);
+  if (!context) {
+    throw new Error('useSupplyChain must be used within a SupplyChainProvider');
+  }
+  return context;
+};
+
+export default SupplyChainContext;

+ 8 - 2
src/client/home/routes.tsx

@@ -8,6 +8,7 @@ import LoginPage from './pages/LoginPage';
 import RegisterPage from './pages/RegisterPage';
 import MemberPage from './pages/MemberPage';
 import GrainOilDashboard from './pages/SupplyChainDashboards/GrainOilDashboard';
+import SupplyChainDashboard from './pages/SupplyChainDashboards/SupplyChainDashboard';
 import FinancialDashboard from './pages/FinancialDashboard/FinancialDashboard';
 
 export const router = createBrowserRouter([
@@ -24,9 +25,14 @@ export const router = createBrowserRouter([
     element: <RegisterPage />
   },
   {
-    path: '/supply-chain/grain-oil',
-    element: <GrainOilDashboard />
+    path: '/supply-chain/:dashboardType',
+    element: <SupplyChainDashboard />
   },
+  // 保持向后兼容的静态路由
+  // {
+  //   path: '/supply-chain/grain-oil',
+  //   element: <GrainOilDashboard />
+  // },
   {
     path: '/financial-dashboard',
     element: <FinancialDashboard />

Некоторые файлы не были показаны из-за большого количества измененных файлов