|
@@ -0,0 +1,332 @@
|
|
|
|
|
+# Story 005.004: 种业-果蔬组合数据集成
|
|
|
|
|
+
|
|
|
|
|
+**父史诗**: 史诗005 - 史诗005 - 供应链可视化大屏实现
|
|
|
|
|
+docs/prd/epic-005-supply-chain-visualization.md
|
|
|
|
|
+
|
|
|
|
|
+## Status
|
|
|
|
|
+In Progress
|
|
|
|
|
+
|
|
|
|
|
+## Story
|
|
|
|
|
+**As a** 前端开发者
|
|
|
|
|
+**I want** 组件能够动态加载SupplyChainContext中的种业-果蔬组合数据
|
|
|
|
|
+**so that** 用户可以通过路由参数`/supply-chain/seed-fruit`访问种业-果蔬组合大屏,并看到基于动态数据的完整供应链地图可视化、关键指标和数据卡片
|
|
|
|
|
+
|
|
|
|
|
+**Scope**: 修改现有组件以动态加载SupplyChainContext中的种业-果蔬组合数据,包括定位点坐标、关键指标、供应链网络和弹出框数据
|
|
|
|
|
+
|
|
|
|
|
+## Acceptance Criteria
|
|
|
|
|
+1. **SupplyChainMap组件动态加载定位点数据** - 组件应从SupplyChainContext中动态加载种业和果蔬的定位点坐标数据,而不是使用硬编码的默认数据
|
|
|
|
|
+2. **KeyMetrics组件动态加载关键指标数据** - 组件应从SupplyChainContext中动态加载种业和果蔬的关键指标数据,而不是使用硬编码的默认数据
|
|
|
|
|
+3. **组件支持产业切换** - 当用户在种业和果蔬之间切换时,组件应自动更新显示对应产业的数据
|
|
|
|
|
+4. **验证数据完整性** - 确保种业和果蔬的所有定位点、关键指标、供应链网络和弹出框数据都能正确显示
|
|
|
|
|
+
|
|
|
|
|
+## Tasks / Subtasks
|
|
|
|
|
+- [ ] 修改SupplyChainMap组件使用动态数据 (AC: #1, #3, #4)
|
|
|
|
|
+ - [ ] 移除组件中的硬编码defaultPoints
|
|
|
|
|
+ - [ ] 从SupplyChainContext中获取当前产业的定位点数据
|
|
|
|
|
+ - [ ] 实现定位点数据的动态渲染
|
|
|
|
|
+ - [ ] 验证种业定位点正确显示(8个点:4个基地+4个产业链)
|
|
|
|
|
+ - [ ] 验证果蔬定位点正确显示(5个点:4个基地+1个产业链)
|
|
|
|
|
+- [ ] 修改KeyMetrics组件使用动态数据 (AC: #2, #3, #4)
|
|
|
|
|
+ - [ ] 移除组件中的硬编码defaultMetrics
|
|
|
|
|
+ - [ ] 从SupplyChainContext中获取当前产业的关键指标数据
|
|
|
|
|
+ - [ ] 实现关键指标数据的动态渲染
|
|
|
|
|
+ - [ ] 验证种业关键指标正确显示(良种繁育能力、自建育种基地、辐射带动面积)
|
|
|
|
|
+ - [ ] 验证果蔬关键指标正确显示(加工能力、自建果蔬基地、辐射带动面积)
|
|
|
|
|
+- [ ] 验证种业-果蔬组合路由功能 (AC: #3, #4)
|
|
|
|
|
+ - [ ] 测试路由`/supply-chain/seed-fruit`正确加载种业-果蔬数据
|
|
|
|
|
+ - [ ] 验证组合内产业切换功能(种业↔果蔬)
|
|
|
|
|
+ - [ ] 验证主题色正确应用(种业:#5DEF8B,果蔬:#FFF586)
|
|
|
|
|
+- [ ] 测试数据集成完整性 (AC: #4)
|
|
|
|
|
+ - [ ] 验证地图定位点正确显示
|
|
|
|
|
+ - [ ] 验证关键指标数据正确展示
|
|
|
|
|
+ - [ ] 验证数据卡片内容准确
|
|
|
|
|
+ - [ ] 验证供应链网络连接线正确绘制
|
|
|
|
|
+
|
|
|
|
|
+## 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/pages/SupplyChainDashboards/components/`
|
|
|
|
|
+- **类型定义**: `src/share/types.ts` (共享类型)
|
|
|
|
|
+- **测试位置**: `tests/unit/client/home/pages/SupplyChainDashboards/context/`
|
|
|
|
|
+
|
|
|
|
|
+### 组件架构模式 [Source: architecture/component-architecture.md#前端组件架构]
|
|
|
|
|
+- **Context设计**: 遵循现有React Context模式,提供类型安全的接口
|
|
|
|
|
+- **状态管理**: 使用useState和useReducer管理本地状态
|
|
|
|
|
+- **数据流**: 单向数据流,通过Context Provider传递数据
|
|
|
|
|
+- **错误处理**: 统一的错误边界和加载状态管理
|
|
|
|
|
+
|
|
|
|
|
+### 现有SupplyChainContext分析 [Source: src/client/home/pages/SupplyChainDashboards/context/SupplyChainContext.tsx]
|
|
|
|
|
+- **当前状态**: 已实现所有4套组合的完整数据,包括seed-fruit组合的种业和果蔬数据
|
|
|
|
|
+- **数据结构**: SupplyChainContext包含完整的定位点、关键指标、网络连接和弹出框数据
|
|
|
|
|
+- **问题**: 组件没有使用context数据,而是使用硬编码的默认数据
|
|
|
|
|
+- **解决方案**: 修改组件从useSupplyChain() hook获取currentData
|
|
|
|
|
+
|
|
|
|
|
+### 统一数据结构设计 [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[]>;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 组件数据流问题分析
|
|
|
|
|
+
|
|
|
|
|
+#### SupplyChainMap组件问题
|
|
|
|
|
+- **位置**: `src/client/home/pages/SupplyChainDashboards/components/SupplyChainMap.tsx`
|
|
|
|
|
+- **问题**: 使用硬编码的defaultPoints(第150-159行)
|
|
|
|
|
+- **解决方案**: 从useSupplyChain()获取currentData.mapPoints[currentIndustry]
|
|
|
|
|
+
|
|
|
|
|
+#### KeyMetrics组件问题
|
|
|
|
|
+- **位置**: `src/client/home/pages/SupplyChainDashboards/components/KeyMetrics.tsx`
|
|
|
|
|
+- **问题**: 使用硬编码的defaultMetrics(第60-79行)
|
|
|
|
|
+- **解决方案**: 从useSupplyChain()获取currentData.keyMetrics[currentIndustry]
|
|
|
|
|
+
|
|
|
|
|
+#### 数据获取模式
|
|
|
|
|
+```typescript
|
|
|
|
|
+// 正确的数据获取方式
|
|
|
|
|
+const { currentData, currentIndustry } = useSupplyChain();
|
|
|
|
|
+
|
|
|
|
|
+// 获取当前产业的定位点数据
|
|
|
|
|
+const mapPoints = currentData?.mapPoints[currentIndustry] || [];
|
|
|
|
|
+
|
|
|
|
|
+// 获取当前产业的关键指标数据
|
|
|
|
|
+const keyMetrics = currentData?.keyMetrics[currentIndustry] || [];
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 颜色系统规范 [Source: docs/prd/epic-005-supply-chain-visualization.md#样式系统]
|
|
|
|
|
+- **种业产业**: 主色 #5DEF8B
|
|
|
|
|
+- **果蔬产业**: 主色 #FFF586
|
|
|
|
|
+
|
|
|
|
|
+### 数据集成策略 [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. 组件修改策略
|
|
|
|
|
+基于现有SupplyChainContext数据,修改组件使用动态数据:
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// SupplyChainMap组件修改示例
|
|
|
|
|
+const SupplyChainMap: React.FC<SupplyChainMapProps> = ({ onPointClick }) => {
|
|
|
|
|
+ const { currentData, currentIndustry } = useSupplyChain();
|
|
|
|
|
+
|
|
|
|
|
+ // 从context获取当前产业的定位点数据
|
|
|
|
|
+ const mapPoints = currentData?.mapPoints[currentIndustry] || [];
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div className="supply-chain-map">
|
|
|
|
|
+ {mapPoints.map(point => (
|
|
|
|
|
+ <MapPoint
|
|
|
|
|
+ key={point.id}
|
|
|
|
|
+ point={point}
|
|
|
|
|
+ onClick={() => onPointClick(point)}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// KeyMetrics组件修改示例
|
|
|
|
|
+const KeyMetrics: React.FC<KeyMetricsProps> = ({ title, subtitle }) => {
|
|
|
|
|
+ const { currentData, currentIndustry } = useSupplyChain();
|
|
|
|
|
+
|
|
|
|
|
+ // 从context获取当前产业的关键指标数据
|
|
|
|
|
+ const keyMetrics = currentData?.keyMetrics[currentIndustry] || [];
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div className="key-metrics">
|
|
|
|
|
+ {keyMetrics.map(metric => (
|
|
|
|
|
+ <DataCard
|
|
|
|
|
+ key={metric.id}
|
|
|
|
|
+ title={metric.label}
|
|
|
|
|
+ value={metric.value}
|
|
|
|
|
+ unit={metric.unit}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 3. 组件修改实施步骤
|
|
|
|
|
+
|
|
|
|
|
+**SupplyChainMap组件修改步骤:**
|
|
|
|
|
+1. 移除第150-159行的硬编码defaultPoints
|
|
|
|
|
+2. 添加useSupplyChain() hook获取currentData和currentIndustry
|
|
|
|
|
+3. 从currentData.mapPoints[currentIndustry]获取定位点数据
|
|
|
|
|
+4. 修改渲染逻辑使用动态数据
|
|
|
|
|
+
|
|
|
|
|
+**KeyMetrics组件修改步骤:**
|
|
|
|
|
+1. 移除第60-79行的硬编码defaultMetrics
|
|
|
|
|
+2. 添加useSupplyChain() hook获取currentData和currentIndustry
|
|
|
|
|
+3. 从currentData.keyMetrics[currentIndustry]获取关键指标数据
|
|
|
|
|
+4. 修改DataCard组件适配新的数据结构
|
|
|
|
|
+5. 更新渲染逻辑使用动态数据
|
|
|
|
|
+
|
|
|
|
|
+### 兼容性要求
|
|
|
|
|
+- [ ] 现有grain-oil组合功能保持不变
|
|
|
|
|
+- [ ] 现有路由配置向后兼容
|
|
|
|
|
+- [ ] 组件修改后保持原有API接口
|
|
|
|
|
+- [ ] 性能指标满足要求(加载时间<3秒)
|
|
|
|
|
+
|
|
|
|
|
+### 性能要求 [Source: docs/prd/epic-005-supply-chain-visualization.md#性能验收]
|
|
|
|
|
+- **Context初始化时间**: < 100ms
|
|
|
|
|
+- **数据加载时间**: < 2秒
|
|
|
|
|
+- **路由切换响应时间**: < 1秒
|
|
|
|
|
+- **内存使用**: 合理,支持数据缓存
|
|
|
|
|
+
|
|
|
|
|
+## Testing
|
|
|
|
|
+### 测试策略 [Source: architecture/testing-strategy.md#单元测试]
|
|
|
|
|
+- **测试框架**: Vitest + Testing Library
|
|
|
|
|
+- **测试位置**: `tests/unit/client/home/pages/SupplyChainDashboards/context/`
|
|
|
|
|
+- **覆盖率目标**: ≥ 85%
|
|
|
|
|
+- **测试类型**: Context功能测试、数据加载测试、路由集成测试
|
|
|
|
|
+
|
|
|
|
|
+### 测试验证点
|
|
|
|
|
+- SupplyChainContext正确加载种业-果蔬组合数据
|
|
|
|
|
+- 路由参数`/supply-chain/seed-fruit`正确解析
|
|
|
|
|
+- 种业和果蔬产业切换功能正常
|
|
|
|
|
+- 地图定位点正确显示
|
|
|
|
|
+- 关键指标数据正确展示
|
|
|
|
|
+- 供应链网络连接线正确绘制
|
|
|
|
|
+- 主题色正确应用
|
|
|
|
|
+
|
|
|
|
|
+### 测试用例
|
|
|
|
|
+- 验证seed-fruit组合数据正确加载
|
|
|
|
|
+- 测试种业产业切换功能
|
|
|
|
|
+- 测试果蔬产业切换功能
|
|
|
|
|
+- 验证定位点坐标正确性
|
|
|
|
|
+- 验证关键指标数据准确性
|
|
|
|
|
+- 测试路由参数解析
|
|
|
|
|
+- 验证React Query缓存机制
|
|
|
|
|
+
|
|
|
|
|
+## Change Log
|
|
|
|
|
+| Date | Version | Description | Author |
|
|
|
|
|
+|------|---------|-------------|--------|
|
|
|
|
|
+| 2025-11-16 | 1.0 | 初始故事创建,基于Epic 005需求 | Bob (SM) |
|
|
|
|
|
+
|
|
|
|
|
+## Dev Agent Record
|
|
|
|
|
+
|
|
|
|
|
+### Agent Model Used
|
|
|
|
|
+- Claude Sonnet 4.5 (model ID: 'claude-sonnet-4-5-20250929')
|
|
|
|
|
+
|
|
|
|
|
+### Debug Log References
|
|
|
|
|
+- 代码检查和分析完成于 2025-11-16
|
|
|
|
|
+- 发现种业-果蔬组合数据已在SupplyChainContext中完整实现
|
|
|
|
|
+
|
|
|
|
|
+### Completion Notes List
|
|
|
|
|
+1. **种业-果蔬组合数据已完整实现** - 在SupplyChainContext.tsx中已包含完整的seedFruitData定义
|
|
|
|
|
+2. **所有定位点坐标已实现** - 包含种业8个定位点和果蔬5个定位点的完整坐标数据
|
|
|
|
|
+3. **关键指标数据已实现** - 包含种业和果蔬的完整关键指标数据
|
|
|
|
|
+4. **供应链网络已实现** - 包含种业和果蔬的供应链连接关系
|
|
|
|
|
+5. **弹出框数据已实现** - 包含种业和果蔬的弹出框数据
|
|
|
|
|
+6. **路由配置已完成** - 动态路由`/supply-chain/:dashboardType`已支持seed-fruit组合
|
|
|
|
|
+7. **React Query集成已完成** - 数据加载和缓存机制已实现
|
|
|
|
|
+8. **组件数据流问题已识别** - SupplyChainMap和KeyMetrics组件使用硬编码数据,需要修改为动态数据
|
|
|
|
|
+
|
|
|
|
|
+### File List
|
|
|
|
|
+#### 需要修改的文件
|
|
|
|
|
+- `src/client/home/pages/SupplyChainDashboards/components/SupplyChainMap.tsx` - 需要修改为使用动态定位点数据
|
|
|
|
|
+- `src/client/home/pages/SupplyChainDashboards/components/KeyMetrics.tsx` - 需要修改为使用动态关键指标数据
|
|
|
|
|
+
|
|
|
|
|
+#### 已完成的文件
|
|
|
|
|
+- `src/client/home/pages/SupplyChainDashboards/context/SupplyChainContext.tsx` - 包含完整的种业-果蔬组合数据
|
|
|
|
|
+- `src/client/home/routes.tsx` - 动态路由配置
|
|
|
|
|
+
|
|
|
|
|
+#### 无需修改的文件
|
|
|
|
|
+- `src/client/home/pages/SupplyChainDashboards/SupplyChainDashboard.tsx` - 统一组件已支持所有组合
|
|
|
|
|
+
|
|
|
|
|
+## QA Results
|
|
|
|
|
+- **功能完整性**: ⚠️ 数据已实现但组件未使用动态数据
|
|
|
|
|
+- **代码质量**: ✅ TypeScript类型安全,数据结构完整
|
|
|
|
|
+- **性能**: ✅ React Query缓存机制已实现
|
|
|
|
|
+- **兼容性**: ✅ 与现有架构完全兼容
|
|
|
|
|
+- **测试覆盖**: ⚠️ 需要添加单元测试验证数据正确性
|
|
|
|
|
+- **文档**: ✅ 代码注释完整,接口定义清晰
|
|
|
|
|
+- **组件数据流**: ❌ SupplyChainMap和KeyMetrics组件使用硬编码数据,需要修改
|