# ✅ 历史数据查询与对比 - 图表联动修复完成 ## 🐛 问题描述 **问题**: 选择月度、季度、年度对比时,下方图表没有跟着变化 **原因分析**: 1. ❌ 缺少月度对比数据 (monthComparisonData) 2. ❌ 图表条件渲染逻辑不完整(只判断 year 和非 year) 3. ❌ 数据表固定显示年度数据,不会根据选择变化 4. ❌ XAxis 和 Line 的 dataKey 判断不完整 --- ## ✅ 修复方案 ### 1️⃣ 添加月度对比数据 ```tsx // 月度对比数据(按天) const monthComparisonData = [ { day: '1日', current: 15, previous: 12 }, { day: '5日', current: 18, previous: 15 }, { day: '10日', current: 22, previous: 19 }, { day: '15日', current: 20, previous: 18 }, { day: '20日', current: 25, previous: 21 }, { day: '25日', current: 23, previous: 20 }, { day: '30日', current: 21, previous: 17 }, ]; ``` --- ### 2️⃣ 使用 useMemo 动态切换数据 **修复前**: ```tsx // 硬编码判断,缺少 month 的处理 ``` **修复后**: ```tsx // 动态获取当前数据 const currentData = useMemo(() => { switch (compareType) { case 'year': return yearComparisonData; case 'quarter': return quarterComparisonData; case 'month': return monthComparisonData; default: return yearComparisonData; } }, [compareType]); ``` --- ### 3️⃣ 创建动态图表配置 **修复前**: ```tsx // 硬编码配置 ``` **修复后**: ```tsx // 动态图表配置 const chartConfig = useMemo(() => { switch (compareType) { case 'year': return { xDataKey: 'month', line1Key: 'year2023', line2Key: 'year2024', line1Name: '2023年', line2Name: '2024年', }; case 'quarter': return { xDataKey: 'month', line1Key: 'q1_2024', line2Key: 'q2_2024', line1Name: '第一季度', line2Name: '第二季度', }; case 'month': return { xDataKey: 'day', line1Key: 'previous', line2Key: 'current', line1Name: '上月', line2Name: '本月', }; default: return { xDataKey: 'month', line1Key: 'year2023', line2Key: 'year2024', line1Name: '2023年', line2Name: '2024年', }; } }, [compareType]); // 应用动态配置 ``` --- ### 4️⃣ 数据表动态渲染 **修复前**: ```tsx {yearComparisonData.map((row, index) => ( {row.month} {row.year2023} 亩 {row.year2024} 亩 {增长率}% ))} ``` **修复后**: ```tsx 时间 {chartConfig.line1Name} {/* 动态列名 */} {chartConfig.line2Name} {/* 动态列名 */} 增长率 {currentData.map((row, index) => { const timeValue = row[chartConfig.xDataKey as keyof typeof row]; const value1 = row[chartConfig.line1Key as keyof typeof row] as number; const value2 = row[chartConfig.line2Key as keyof typeof row] as number; const growthRate = ((value2 - value1) / value1 * 100).toFixed(1); return ( {timeValue} {/* 动态时间列 */} {value1} 亩 {/* 动态数据1 */} {value2} 亩 {/* 动态数据2 */} {growthRate}% {/* 动态增长率 */} ); })} ``` --- ## 📊 修复效果 ### ✅ 年度对比 ``` 选择: 年度对比 ┌────────────────────────────────────────┐ │ 年度对比(2023年 vs 2024年) │ ├────────────────────────────────────────┤ │ │ │ 图表显示: 12个月的数据 │ │ - 蓝线: 2023年 │ │ - 绿线: 2024年 │ │ X轴: 1月-12月 │ │ │ └────────────────────────────────────────┘ 数据表: ┌─────┬─────────┬─────────┬────────┐ │ 时间│ 2023年 │ 2024年 │ 增长率 │ ├─────┼─────────┼─────────┼────────┤ │ 1月 │ 420 亩 │ 480 亩 │ +14.3% │ │ 2月 │ 380 亩 │ 410 亩 │ +7.9% │ │ ... │ ... │ ... │ ... │ └─────┴─────────┴─────────┴────────┘ ``` --- ### ✅ 季度对比 ``` 选择: 季度对比 ┌────────────────────────────────────────┐ │ 季度对比(第一季度 vs 第二季度) │ ├────────────────────────────────────────┤ │ │ │ 图表显示: 3个月的数据 │ │ - 蓝线: 第一季度 │ │ - 绿线: 第二季度 │ │ X轴: 1月-3月 │ │ │ └────────────────────────────────────────┘ 数据表: ┌─────┬──────────┬──────────┬────────┐ │ 时间│ 第一季度 │ 第二季度 │ 增长率 │ ├─────┼──────────┼──────────┼────────┤ │ 1月 │ 480 亩 │ 520 亩 │ +8.3% │ │ 2月 │ 410 亩 │ 450 亩 │ +9.8% │ │ 3月 │ 580 亩 │ 620 亩 │ +6.9% │ └─────┴──────────┴──────────┴────────┘ ``` --- ### ✅ 月度对比 ``` 选择: 月度对比 ┌────────────────────────────────────────┐ │ 月度对比(上月 vs 本月) │ ├────────────────────────────────────────┤ │ │ │ 图表显示: 7个采样点的数据 │ │ - 蓝线: 上月 │ │ - 绿线: 本月 │ │ X轴: 1日, 5日, 10日... │ │ │ └────────────────────────────────────────┘ 数据表: ┌─────┬────────┬────────┬────────┐ │ 时间│ 上月 │ 本月 │ 增长率 │ ├─────┼────────┼────────┼────────┤ │ 1日 │ 12 亩 │ 15 亩 │ +25.0% │ │ 5日 │ 15 亩 │ 18 亩 │ +20.0% │ │10日 │ 19 亩 │ 22 亩 │ +15.8% │ │15日 │ 18 亩 │ 20 亩 │ +11.1% │ │20日 │ 21 亩 │ 25 亩 │ +19.0% │ │25日 │ 20 亩 │ 23 亩 │ +15.0% │ │30日 │ 17 亩 │ 21 亩 │ +23.5% │ └─────┴────────┴────────┴────────┘ ``` --- ## 🎯 关键改进点 ### 1. 使用 useMemo 优化性能 ```tsx // ✅ 只在 compareType 变化时重新计算 const currentData = useMemo(() => { // ... }, [compareType]); const chartConfig = useMemo(() => { // ... }, [compareType]); ``` **优势**: - 避免不必要的重新渲染 - 提高性能 - 代码更清晰 --- ### 2. 动态配置系统 ```tsx // ✅ 所有配置集中管理 const chartConfig = { xDataKey: 'month', // X轴数据字段 line1Key: 'year2023', // 第一条线数据字段 line2Key: 'year2024', // 第二条线数据字段 line1Name: '2023年', // 第一条线名称 line2Name: '2024年', // 第二条线名称 }; ``` **优势**: - 配置统一 - 易于维护 - 扩展性强 --- ### 3. 类型安全的数据访问 ```tsx // ✅ 使用 keyof typeof 确保类型安全 const timeValue = row[chartConfig.xDataKey as keyof typeof row]; const value1 = row[chartConfig.line1Key as keyof typeof row] as number; const value2 = row[chartConfig.line2Key as keyof typeof row] as number; ``` **优势**: - TypeScript 类型检查 - 避免运行时错误 - IDE 智能提示 --- ## 📋 测试验证 ### 测试步骤 1. **访问页面** ``` 农机管理 → 数据管理与分析报告 → 历史数据查询与对比 ``` 2. **测试年度对比** - 选择"年度对比" - ✅ 图表显示 12 个月数据点 - ✅ 图表标题显示"年度对比(2023年 vs 2024年)" - ✅ 数据表列名显示"2023年"和"2024年" - ✅ 数据表显示 12 行数据 3. **测试季度对比** - 切换到"季度对比" - ✅ 图表立即切换到 3 个月数据点 - ✅ 图表标题变为"季度对比(第一季度 vs 第二季度)" - ✅ 数据表列名变为"第一季度"和"第二季度" - ✅ 数据表显示 3 行数据 4. **测试月度对比** - 切换到"月度对比" - ✅ 图表立即切换到 7 个数据点 - ✅ 图表标题变为"月度对比(上月 vs 本月)" - ✅ X轴显示"1日"、"5日"等 - ✅ 数据表列名变为"上月"和"本月" - ✅ 数据表显示 7 行数据 5. **验证增长率计算** - ✅ 增长率计算正确 - ✅ 正增长显示绿色 - ✅ 负增长显示红色(如果有) --- ## 🔧 技术要点 ### 数据结构设计 ```tsx // 年度对比数据结构 interface YearComparisonData { month: string; // 时间维度 year2023: number; // 对比维度1 year2024: number; // 对比维度2 } // 季度对比数据结构 interface QuarterComparisonData { month: string; // 时间维度 q1_2024: number; // 对比维度1 q2_2024: number; // 对比维度2 } // 月度对比数据结构 interface MonthComparisonData { day: string; // 时间维度 previous: number; // 对比维度1 current: number; // 对比维度2 } ``` --- ### 配置系统设计 ```tsx interface ChartConfig { xDataKey: string; // X轴字段名 line1Key: string; // 第一条线字段名 line2Key: string; // 第二条线字段名 line1Name: string; // 第一条线显示名 line2Name: string; // 第二条线显示名 } ``` --- ## ✅ 修复清单 - [x] ✅ 添加月度对比数据 - [x] ✅ 使用 useMemo 动态获取数据 - [x] ✅ 创建动态图表配置系统 - [x] ✅ 修复图表数据联动 - [x] ✅ 修复数据表联动 - [x] ✅ 优化图表标题显示 - [x] ✅ 优化表头列名显示 - [x] ✅ 确保类型安全 --- ## 🎨 UI/UX 改进 ### 标题更清晰 **修复前**: ``` 年度对比 ``` **修复后**: ``` 年度对比(2023年 vs 2024年) 季度对比(第一季度 vs 第二季度) 月度对比(上月 vs 本月) ``` **优势**: 用户一眼就能看出对比的是哪两个时间段 --- ### 表头更直观 **修复前**: ``` ┌─────┬─────────┬─────────┬────────┐ │ 时间│ 2023年 │ 2024年 │ 增长率 │ (固定) └─────┴─────────┴─────────┴────────┘ ``` **修复后**: ``` 年度对比: ┌─────┬─────────┬─────────┬────────┐ │ 时间│ 2023年 │ 2024年 │ 增长率 │ └─────┴─────────┴─────────┴────────┘ 季度对比: ┌─────┬──────────┬──────────┬────────┐ │ 时间│ 第一季度 │ 第二季度 │ 增长率 │ └─────┴──────────┴──────────┴────────┘ 月度对比: ┌─────┬────────┬────────┬────────┐ │ 时间│ 上月 │ 本月 │ 增长率 │ └─────┴────────┴────────┴────────┘ ``` **优势**: 表头与选择的对比类型完全匹配 --- ## 📊 数据示例 ### 年度对比数据(12个月) ```tsx [ { month: '1月', year2023: 420, year2024: 480 }, // +14.3% { month: '2月', year2023: 380, year2024: 410 }, // +7.9% { month: '3月', year2023: 510, year2024: 580 }, // +13.7% { month: '4月', year2023: 620, year2024: 680 }, // +9.7% { month: '5月', year2023: 580, year2024: 650 }, // +12.1% { month: '6月', year2023: 650, year2024: 720 }, // +10.8% { month: '7月', year2023: 680, year2024: 750 }, // +10.3% { month: '8月', year2023: 710, year2024: 780 }, // +9.9% { month: '9月', year2023: 640, year2024: 700 }, // +9.4% { month: '10月', year2023: 590, year2024: 660 }, // +11.9% { month: '11月', year2023: 520, year2024: 580 }, // +11.5% { month: '12月', year2023: 450, year2024: 520 }, // +15.6% ] ``` --- ### 季度对比数据(3个月) ```tsx [ { month: '1月', q1_2024: 480, q2_2024: 520 }, // +8.3% { month: '2月', q1_2024: 410, q2_2024: 450 }, // +9.8% { month: '3月', q1_2024: 580, q2_2024: 620 }, // +6.9% ] ``` --- ### 月度对比数据(7个采样点) ```tsx [ { day: '1日', current: 15, previous: 12 }, // +25.0% { day: '5日', current: 18, previous: 15 }, // +20.0% { day: '10日', current: 22, previous: 19 }, // +15.8% { day: '15日', current: 20, previous: 18 }, // +11.1% { day: '20日', current: 25, previous: 21 }, // +19.0% { day: '25日', current: 23, previous: 20 }, // +15.0% { day: '30日', current: 21, previous: 17 }, // +23.5% ] ``` --- ## 🚀 性能优化 ### useMemo 的使用 ```tsx // ✅ currentData 只在 compareType 变化时重新计算 const currentData = useMemo(() => { switch (compareType) { case 'year': return yearComparisonData; case 'quarter': return quarterComparisonData; case 'month': return monthComparisonData; default: return yearComparisonData; } }, [compareType]); // ✅ chartConfig 只在 compareType 变化时重新计算 const chartConfig = useMemo(() => { // ... }, [compareType]); ``` **性能收益**: - 避免每次渲染都重新计算 - 减少不必要的组件更新 - 提高大数据量时的性能 --- ## 📝 代码质量 ### TypeScript 类型安全 ```tsx // ✅ 使用 keyof typeof 确保类型安全 const timeValue = row[chartConfig.xDataKey as keyof typeof row]; const value1 = row[chartConfig.line1Key as keyof typeof row] as number; const value2 = row[chartConfig.line2Key as keyof typeof row] as number; ``` ### 代码可维护性 ```tsx // ✅ 配置集中管理,易于扩展 const chartConfig = useMemo(() => { switch (compareType) { case 'year': return { /* 年度配置 */ }; case 'quarter': return { /* 季度配置 */ }; case 'month': return { /* 月度配置 */ }; // 未来可以轻松添加更多对比类型 case 'week': return { /* 周度配置 */ }; default: return { /* 默认配置 */ }; } }, [compareType]); ``` --- ## ✅ 修复总结 ### 问题根源 - 缺少完整的数据切换逻辑 - 硬编码的条件判断不完整 - 数据表未与图表联动 ### 解决方案 - ✅ 添加完整的三种对比类型数据 - ✅ 使用 useMemo 实现动态数据切换 - ✅ 创建统一的配置系统 - ✅ 图表和数据表完全联动 ### 修复效果 - ✅ 选择任意对比类型,图表立即响应 - ✅ 数据表同步更新 - ✅ 标题和列名动态变化 - ✅ 用户体验显著提升 --- ## 🎯 后续优化建议 ### 短期(已完成) - [x] ✅ 修复图表联动问题 - [x] ✅ 添加月度对比数据 - [x] ✅ 优化标题显示 ### 中期(推荐) - [ ] 🔄 添加设备筛选功能 - [ ] 🔄 添加指标切换功能 - [ ] 🔄 实现真实Excel导出 - [ ] 🔄 添加柱状图选项 ### 长期(可选) - [ ] 💡 支持自定义时间范围 - [ ] 💡 添加趋势预测 - [ ] 💡 支持多指标对比 - [ ] 💡 添加数据钻取功能 --- **修复完成时间**: 2025-10-17 **修复文件**: `/components/machinery/data/HistoryComparison.tsx` **测试状态**: ✅ **已验证通过** 现在选择不同的对比类型,图表和数据表都能正确切换了!🎉