Browse Source

📝 docs(supply-chain): add story for unified data context and routing architecture

- create story document for supply chain data context and dynamic routing architecture
- define acceptance criteria for context extension, data structure, route parsing and configuration
- outline tasks for implementing context, data types, routing and data loading
- provide technical details including data structure designs and routing configurations
- include static data definitions for 4 dashboard combinations and 8 industries
- specify testing strategy and performance requirements
yourname 2 months ago
parent
commit
2ef9af88ac
1 changed files with 738 additions and 0 deletions
  1. 738 0
      docs/stories/005.002.story.md

+ 738 - 0
docs/stories/005.002.story.md

@@ -0,0 +1,738 @@
+# Story 005.002: 统一数据Context和路由架构
+
+**父史诗**: 史诗005 - 供应链可视化大屏实现
+docs/prd/epic-005-supply-chain-visualization.md
+
+## Status
+Draft
+
+## Story
+**As a** 前端开发者
+**I want** 统一的供应链数据Context和动态路由架构
+**so that** 我可以通过路由参数动态加载4套组合大屏数据,实现组件复用和统一数据管理
+
+**Scope**: 扩展ThemeContext为SupplyChainContext,创建统一数据结构,实现路由参数解析,配置动态路由
+
+## Acceptance Criteria
+1. **扩展ThemeContext为SupplyChainContext** - 创建统一的供应链数据Context,支持4套组合和8个产业的数据管理
+2. **创建统一数据结构** - 定义定位点坐标、关键指标、供应链网络数据的统一接口
+3. **实现路由参数解析** - 通过React Router的useParams获取当前组合类型,动态加载对应数据
+4. **配置动态路由** - 在现有路由配置中添加4套组合的动态路由参数
+5. **优化数据加载机制** - 实现数据缓存和动态加载,支持路由切换时的性能优化
+
+## Tasks / Subtasks
+- [ ] 扩展ThemeContext为SupplyChainContext (AC: #1)
+  - [ ] 在`src/client/home/pages/SupplyChainDashboards/context/`目录下创建SupplyChainContext.tsx
+  - [ ] 扩展现有ThemeContext接口,添加组合类型和统一数据管理
+  - [ ] 实现组合切换和产业切换的状态管理
+  - [ ] 添加数据加载和缓存机制
+- [ ] 创建统一数据结构 (AC: #2)
+  - [ ] 定义组合类型接口:`DashboardType`
+  - [ ] 定义供应链数据接口:`SupplyChainData`
+  - [ ] 定义定位点坐标接口:`LocationPoint`
+  - [ ] 定义关键指标接口:`MetricData`
+  - [ ] 定义供应链网络接口:`SupplyChainNetwork`
+  - [ ] 定义弹出框数据接口:`PopupData`
+- [ ] 实现路由参数解析 (AC: #3)
+  - [ ] 分析现有路由配置结构
+  - [ ] 实现useParams获取组合类型
+  - [ ] 创建路由参数解析工具函数
+  - [ ] 添加参数验证和错误处理
+- [ ] 配置动态路由 (AC: #4)
+  - [ ] 修改`src/client/home/routes.tsx`中的路由配置
+  - [ ] 添加4套组合的动态路由:`/supply-chain/:dashboardType`
+  - [ ] 配置路由参数验证和默认值
+  - [ ] 集成到现有导航系统
+- [ ] 集成React Query和静态数据mock (AC: #5)
+  - [ ] 配置React Query QueryClient
+  - [ ] 创建静态数据mock文件,包含4套组合的完整数据定义
+  - [ ] 从PRD提取所有定位点坐标数据
+  - [ ] 实现useSupplyChainData查询Hook
+  - [ ] 集成React Query到SupplyChainContext
+  - [ ] 实现数据预加载和缓存策略
+  - [ ] 添加加载状态和错误处理
+  - [ ] 优化路由切换性能
+  - [ ] 实现数据懒加载机制
+- [ ] 集成测试和验证 (AC: #1-#5)
+  - [ ] 编写Context单元测试
+  - [ ] 测试路由参数解析功能
+  - [ ] 验证数据加载性能
+  - [ ] 测试组合切换功能
+
+## Dev Notes
+
+### 技术栈和前端架构 [Source: architecture/tech-stack.md#前端框架]
+- **前端框架**: React 19.1.0 + TypeScript
+- **状态管理**: React Context (本地状态) + React Query (服务端状态)
+- **路由管理**: React Router
+- **样式系统**: Tailwind CSS 4.1.11
+- **构建工具**: Vite 7.0.0
+- **数据获取**: @tanstack/react-query 5.83.0 [Source: architecture/tech-stack.md#状态管理]
+
+### 项目结构指导 [Source: architecture/source-tree.md#前端应用]
+- **Context位置**: `src/client/home/pages/SupplyChainDashboards/context/SupplyChainContext.tsx`
+- **路由配置**: `src/client/home/routes.tsx`
+- **类型定义**: `src/share/types.ts` (共享类型)
+- **测试位置**: `tests/unit/client/home/pages/SupplyChainDashboards/context/`
+
+### 组件架构模式 [Source: architecture/component-architecture.md#前端组件架构]
+- **Context设计**: 遵循现有React Context模式,提供类型安全的接口
+- **状态管理**: 使用useState和useReducer管理本地状态
+- **数据流**: 单向数据流,通过Context Provider传递数据
+- **错误处理**: 统一的错误边界和加载状态管理
+
+### 现有ThemeContext分析 [Source: src/client/home/pages/SupplyChainDashboards/context/ThemeContext.tsx]
+- **当前状态**: 已实现产业类型定义和主题色管理
+- **扩展点**: 需要添加组合类型、数据加载、路由集成功能
+- **兼容性**: 保持现有ThemeContext接口不变,向后兼容
+
+### 现有路由配置分析 [Source: src/client/home/routes.tsx]
+- **当前路由**: 已有静态路由`/supply-chain/grain-oil`
+- **扩展策略**: 改为动态路由`/supply-chain/:dashboardType`
+- **参数验证**: 需要添加路由参数验证和默认值处理
+
+### 统一数据结构设计 [Source: docs/prd/epic-005-supply-chain-visualization.md#统一数据Context设计]
+```typescript
+// 组合类型定义
+type DashboardType = 'grain-oil' | 'seed-fruit' | 'livestock-aquaculture' | 'fresh-food-salt';
+
+// 产业类型定义(继承自现有ThemeContext)
+type IndustryType = "粮食" | "油脂" | "种业" | "果蔬" | "畜牧" | "水产" | "鲜食" | "泛盐";
+
+// 定位点坐标接口
+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;
+}
+
+// 供应链数据接口
+interface SupplyChainData {
+  // 组合名称
+  name: string;
+  // 支持的产业
+  industries: IndustryType[];
+  // 定位点数据
+  mapPoints: Record<IndustryType, LocationPoint[]>;
+  // 关键指标数据
+  keyMetrics: Record<IndustryType, MetricData[]>;
+  // 供应链网络数据
+  supplyChainNetwork: Record<IndustryType, SupplyChainNetwork>;
+  // 弹出框数据
+  popupData: 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>;
+}
+```
+
+### 路由配置设计
+```typescript
+// 路由参数配置
+const supplyChainRoutes = [
+  {
+    path: '/supply-chain/:dashboardType',
+    component: SupplyChainDashboard,
+    // 参数验证
+    validate: (params: { dashboardType: string }) => {
+      const validTypes: DashboardType[] = ['grain-oil', 'seed-fruit', 'livestock-aquaculture', 'fresh-food-salt'];
+      return validTypes.includes(params.dashboardType as DashboardType);
+    },
+    // 默认参数
+    defaultParams: { dashboardType: 'grain-oil' }
+  }
+];
+```
+
+### 数据集成策略 [Source: architecture/component-architecture.md#技术栈配置]
+
+#### 1. React Query集成
+使用@tanstack/react-query进行服务端状态管理,实现数据获取、缓存和同步:
+
+```typescript
+// React Query配置
+const queryClient = new QueryClient({
+  defaultOptions: {
+    queries: {
+      staleTime: 5 * 60 * 1000, // 5分钟
+      gcTime: 10 * 60 * 1000, // 10分钟
+    },
+  },
+});
+
+// 数据查询Hook
+const useSupplyChainData = (dashboardType: DashboardType) => {
+  return useQuery({
+    queryKey: ['supply-chain', dashboardType],
+    queryFn: () => loadStaticData(dashboardType),
+    enabled: !!dashboardType,
+  });
+};
+```
+
+#### 2. 静态数据mock定义 [Source: docs/prd/epic-005-supply-chain-visualization.md#Stories]
+基于现有粮食-油脂大屏数据和PRD中的坐标数据,定义4套组合的静态数据:
+
+**粮食-油脂组合**: 使用现有GrainOilDashboard中的数据
+
+**种业-果蔬组合**:
+- **种业定位点坐标**:
+  - base1[1142.89,717.84], base2[1664.25,530.82], base3[1435,527.14], base4[1203.07,514.31]
+  - chain1[1273.12,551.14], chain2[1403,597.5], chain3[1694.25,645.5], chain4[1237.87,761.84]
+- **果蔬定位点坐标**:
+  - base1[985,610.22], base2[1125.81,409.52], base3[1229.57,570], base4[1445,560.35]
+  - chain1[949.08,680.31]
+
+**畜牧-水产组合**:
+- **畜牧定位点坐标**:
+  - base1[1203.07,514.31]
+  - chain1[1273.12,551.14], chain2[1403,597.5], chain3[1694.25,645.5], chain4[1237.87,761.84]
+- **水产定位点坐标**:
+  - base1[1445,560.35]
+  - chain1[949.08,680.31], chain2[1178.36,418.4], chain3[1307.42,551.47], chain4[1403.37,603.77]
+
+**鲜食-泛盐组合**:
+- **鲜食定位点坐标**:
+  - base1[1203.07,514.31]
+  - chain1[1273.12,551.14], chain2[1403,597.5], chain3[1694.25,645.5], chain4[1237.87,761.84]
+- **泛盐定位点坐标**:
+  - base1[1445,560.35]
+  - chain1[949.08,680.31], chain2[1178.36,418.4], chain3[1319.74,441.51], chain4[1403.37,603.77]
+
+#### 3. 静态数据定义和加载策略 [Source: docs/figma-jsx/*.md]
+
+```typescript
+// 静态数据定义
+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}`);
+  }
+};
+```
+
+#### 4. React Query性能优化
+- **数据预加载**: 使用`queryClient.prefetchQuery`在路由切换前预加载目标组合数据
+- **缓存机制**: React Query自动管理缓存,减少重复加载
+- **懒加载**: 复杂组件按需加载
+- **错误重试**: React Query内置错误重试机制
+- **乐观更新**: 支持数据更新时的乐观UI更新
+
+### 兼容性要求
+- [ ] 现有ThemeContext功能保持不变
+- [ ] 现有路由配置向后兼容
+- [ ] 现有组件无需修改即可使用新Context
+- [ ] 性能指标满足要求(加载时间<3秒)
+
+### 性能要求 [Source: docs/prd/epic-005-supply-chain-visualization.md#性能验收]
+- **Context初始化时间**: < 100ms
+- **数据加载时间**: < 2秒
+- **路由切换响应时间**: < 1秒
+- **内存使用**: 合理,支持数据缓存
+
+### 测试标准要求 [Source: architecture/testing-strategy.md#单元测试]
+- **测试框架**: Vitest + Testing Library
+- **测试位置**: `tests/unit/client/home/pages/SupplyChainDashboards/context/`
+- **覆盖率目标**: ≥ 85%
+- **测试类型**: Context功能测试、路由参数测试、数据加载测试
+
+## Testing
+### 测试策略
+- **测试类型**: 单元测试 + 集成测试
+- **测试范围**: Context功能、路由参数解析、数据加载机制
+- **测试工具**: Vitest + Testing Library + React Router Testing Library
+- **测试数据**: 使用工厂模式创建测试数据
+
+### 测试验证点
+- Context正确初始化和状态管理
+- 路由参数正确解析和验证
+- React Query数据加载和缓存机制正常工作
+- 静态数据mock正确返回
+- 组合切换功能正常
+- 错误处理和加载状态正确
+- 性能指标满足要求
+
+### 测试用例
+- 验证SupplyChainContext初始状态
+- 测试组合切换功能
+- 验证路由参数解析
+- 测试React Query数据加载和缓存
+- 验证静态数据mock正确性
+- 验证错误处理机制
+- 测试性能指标
+
+## Change Log
+| Date | Version | Description | Author |
+|------|---------|-------------|--------|
+| 2025-11-15 | 1.0 | 初始故事创建,基于架构重构需求 | Claude |
+| 2025-11-15 | 1.1 | 集成React Query和静态数据mock,更新数据加载策略 | Claude |
+| 2025-11-15 | 1.2 | 从PRD提取4套组合的完整定位点坐标数据,完善静态数据定义 | Claude |
+| 2025-11-15 | 1.3 | 从figma-jsx文档提取所有组合的完整定位点数据,包含完整的TypeScript数据定义 | Claude |
+| 2025-11-15 | 1.4 | **数据提取完成**:从现有组件和figma-jsx文档提取完整的关键指标数据、供应链网络数据和弹出框数据 | Claude |
+
+## Dev Agent Record
+
+### Agent Model Used
+
+### Debug Log References
+
+### Completion Notes List
+
+### File List
+
+## QA Results