17 KiB
17 KiB
✅ 作业数据分析 - 自定义时间范围功能
🎯 功能说明
为作业数据分析页面添加自定义时间范围选择功能,支持精确选择开始和结束日期
📅 功能特点
核心功能
-
时间范围选择器 ✅
- 最近6个月
- 最近3个月
- 最近1个月
- 自定义时间
-
自定义日期选择 ✅
- 开始日期选择
- 结束日期选择
- 日期范围验证
- 天数统计显示
-
智能交互 ✅
- 选择"自定义时间"自动展开日期选择器
- 结束日期不能早于开始日期
- 中文日期格式显示
- 实时计算时间跨度
🎨 界面展示
时间范围选择器
┌────────────────────────────────────────────────────────────────┐
│ 🔍 数据筛选 │
├────────────────────────────────────────────────────────────────┤
│ 时间范围 地块 农机 驾驶员 │
│ [自定义时间 ▼] [全部地块 ▼] [全部农机 ▼] [全部 ▼] │
└────────────────────────────────────────────────────────────────┘
自定义时间范围面板(展开后)
┌────────────────────────────────────────────────────────────────┐
│ 📅 自定义时间范围 │
├────────────────────────────────────────────────────────────────┤
│ 开始日期 结束日期 │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ 📅 2024年09月01日 ▼ │ │ 📅 2024年10月17日 ▼ │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ✅ 已选择时间段:2024年09月01日 至 2024年10月17日 │ │
│ │ (共 46 天) │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
日期选择器弹窗
点击日期输入框后弹出:
┌──────────────────────────┐
│ 2024年10月 │
├──────────────────────────┤
│ 日 一 二 三 四 五 六│
│ 1 2│
│ 3 4 5 6 7 8 9│
│ 10 11 12 13 14 15 16│
│ 17 18 19 20 21 22 23│ ← 17日被选中
│ 24 25 26 27 28 29 30│
│ 31 │
└──────────────────────────┘
💡 使用方法
步骤1: 选择"自定义时间"
操作:
1. 进入作业数据分析页面
2. 点击"时间范围"下拉框
3. 选择"自定义时间"
4. 自动展开日期选择面板
步骤2: 选择开始日期
操作:
1. 点击"开始日期"输入框
2. 在日历中选择开始日期
3. 确认选择
日期显示:
未选择:[📅 选择开始日期]
已选择:[📅 2024年09月01日]
步骤3: 选择结束日期
操作:
1. 点击"结束日期"输入框
2. 在日历中选择结束日期
(早于开始日期的日期会被禁用)
3. 确认选择
日期显示:
未选择:[📅 选择结束日期]
已选择:[📅 2024年10月17日]
步骤4: 查看选择结果
选择完成后自动显示:
┌────────────────────────────────────────────┐
│ ✅ 已选择时间段: │
│ 2024年09月01日 至 2024年10月17日 │
│ (共 46 天) │
└────────────────────────────────────────────┘
步骤5: 应用筛选
结果:
- 数据自动按选定时间范围筛选
- 所有图表和统计指标更新
- KPI卡片显示该时段数据
🔧 技术实现
状态管理
// 时间范围状态
const [timeRange, setTimeRange] = useState('last6months');
// 自定义日期状态
const [customStartDate, setCustomStartDate] = useState<Date>();
const [customEndDate, setCustomEndDate] = useState<Date>();
const [showCustomDateRange, setShowCustomDateRange] = useState(false);
时间范围切换处理
const handleTimeRangeChange = (value: string) => {
setTimeRange(value);
if (value === 'custom') {
// 选择自定义时,显示日期选择器
setShowCustomDateRange(true);
} else {
// 选择预设时间,隐藏日期选择器
setShowCustomDateRange(false);
setCustomStartDate(undefined);
setCustomEndDate(undefined);
}
};
开始日期选择器
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" className="w-full justify-start text-left">
<CalendarIcon className="mr-2 h-4 w-4" />
{customStartDate ? (
format(customStartDate, 'yyyy年MM月dd日', { locale: zhCN })
) : (
<span className="text-muted-foreground">选择开始日期</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={customStartDate}
onSelect={setCustomStartDate}
initialFocus
locale={zhCN}
/>
</PopoverContent>
</Popover>
结束日期选择器(带验证)
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" className="w-full justify-start text-left">
<CalendarIcon className="mr-2 h-4 w-4" />
{customEndDate ? (
format(customEndDate, 'yyyy年MM月dd日', { locale: zhCN })
) : (
<span className="text-muted-foreground">选择结束日期</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={customEndDate}
onSelect={setCustomEndDate}
initialFocus
locale={zhCN}
disabled={(date) =>
customStartDate ? date < customStartDate : false // 禁用早于开始日期的日期
}
/>
</PopoverContent>
</Popover>
验证逻辑:
- 如果已选择开始日期,结束日期不能早于开始日期
- 早于开始日期的日期在日历中会被禁用(灰色不可点击)
时间跨度计算
{customStartDate && customEndDate && (
<div className="mt-3 p-3 bg-white rounded border border-blue-200">
<p className="text-sm text-blue-800">
已选择时间段:
<strong className="mx-1">
{format(customStartDate, 'yyyy年MM月dd日', { locale: zhCN })}
</strong>
至
<strong className="mx-1">
{format(customEndDate, 'yyyy年MM月dd日', { locale: zhCN })}
</strong>
(共 {Math.ceil((customEndDate.getTime() - customStartDate.getTime()) / (1000 * 60 * 60 * 24))} 天)
</p>
</div>
)}
计算公式:
天数 = Math.ceil((结束日期 - 开始日期) / (1000 * 60 * 60 * 24))
📋 时间范围选项
预设选项
| 选项 | 说明 | 时间跨度 |
|---|---|---|
| 最近6个月 | 从今天往前6个月 | ~180天 |
| 最近3个月 | 从今天往前3个月 | ~90天 |
| 最近1个月 | 从今天往前1个月 | ~30天 |
| 自定义时间 | 用户自定义选择 | 任意 |
自定义时间的优势
-
精确控制 ✅
- 可以精确到日
- 选择任意时间段
- 不受预设限制
-
灵活分析 ✅
- 季度分析(3个月)
- 半年分析(6个月)
- 年度分析(12个月)
- 特定活动周期分析
-
对比分析 ✅
- 选择去年同期
- 选择特定作业季节
- 选择特定事件前后
🎨 界面细节
1. 日期输入框样式
未选择状态:
┌──────────────────────┐
│ 📅 选择开始日期 │
└──────────────────────┘
↑ 灰色提示文字
已选择状态:
┌──────────────────────┐
│ 📅 2024年09月01日 ▼ │
└──────────────────────┘
↑ 黑色正常文字
2. 日历弹窗
特点:
- 中文星期显示(日、一、二...)
- 中文月份显示(2024年10月)
- 当前日期高亮
- 选中日期蓝色背景
- 禁用日期灰色不可点击
3. 时间段提示框
样式:
- 蓝色边框
- 白色背景
- 清晰的文字说明
- 天数统计
┌────────────────────────────────────────────┐
│ ✅ 已选择时间段: │
│ 2024年09月01日 至 2024年10月17日 │
│ (共 46 天) │
└────────────────────────────────────────────┘
💡 使用场景
场景1: 季度分析
需求:分析第三季度(7-9月)的作业数据
操作:
1. 选择"自定义时间"
2. 开始日期:2024年07月01日
3. 结束日期:2024年09月30日
4. 查看该季度数据
结果:
- 第三季度作业面积
- 季度成本统计
- 季度效率分析
场景2: 同比分析
需求:对比今年和去年同期数据
今年数据:
- 开始:2024年09月01日
- 结束:2024年10月17日
去年数据:
- 开始:2023年09月01日
- 结束:2023年10月17日
操作:
1. 先查看今年数据
2. 记录关键指标
3. 切换到去年同期
4. 对比分析
场景3: 特定活动分析
需求:分析某次农忙季节的作业情况
操作:
1. 选择"自定义时间"
2. 开始日期:农忙开始日期
3. 结束日期:农忙结束日期
4. 分析该时段数据
示例:
- 春耕时段:03月15日 - 04月30日
- 秋收时段:09月15日 - 10月31日
📊 数据筛选逻辑
预设时间范围
// 最近1个月
const now = new Date();
const oneMonthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
// 最近3个月
const threeMonthsAgo = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);
// 最近6个月
const sixMonthsAgo = new Date(now.getTime() - 180 * 24 * 60 * 60 * 1000);
自定义时间范围
// 使用用户选择的开始和结束日期
const filteredData = data.filter(item => {
const itemDate = new Date(item.date);
return itemDate >= customStartDate && itemDate <= customEndDate;
});
✅ 功能验证
交互验证
- ✅ 选择"自定义时间"展开日期选择器
- ✅ 选择其他选项隐藏日期选择器
- ✅ 日期选择器中文显示
- ✅ 结束日期验证(不早于开始日期)
日期格式
- ✅ 中文年月日格式
- ✅ date-fns 日期格式化
- ✅ zhCN 中文本地化
计算验证
- ✅ 天数计算正确
- ✅ 时间跨度显示
- ✅ 实时更新提示
样式验证
- ✅ 蓝色主题统一
- ✅ 响应式布局
- ✅ 清晰的视觉层次
🔄 完整操作流程
流程图
┌──────────────────────┐
│ 进入作业数据分析 │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 点击时间范围选择器 │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 选择"自定义时间" │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 展开日期选择面板 │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 选择开始日期 │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 选择结束日期 │
│ (禁用早于开始日期)│
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 显示选择结果 │
│ (时间段 + 天数) │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 数据自动筛选 │
│ 图表自动更新 │
└──────────────────────┘
📝 代码依赖
新增依赖
// UI组件
import { Popover, PopoverContent, PopoverTrigger } from '../../ui/popover';
import { Calendar } from '../../ui/calendar';
// 日期工具
import { format } from 'date-fns';
import { zhCN } from 'date-fns/locale';
// 图标
import { Calendar as CalendarIcon } from 'lucide-react';
使用的Shadcn组件
- Popover - 日期选择器弹窗
- Calendar - 日历组件
- Button - 日期输入框按钮
- Select - 时间范围下拉选择
🎯 用户体验提升
优势1: 直观的日期选择
传统方式:
- 手动输入日期
- 容易出错
- 格式不统一
新方式:
- ✅ 点击日历选择
- ✅ 格式自动正确
- ✅ 可视化选择
优势2: 智能验证
验证逻辑:
- 结束日期不能早于开始日期
- 禁用无效日期
- 实时提示错误
用户体验:
- ✅ 不会选择错误日期
- ✅ 即时反馈
- <20><> 减少操作错误
优势3: 清晰的反馈
选择过程中:
- 实时显示已选日期
- 中文格式易读
- 天数自动计算
完成后:
- 明确的时间段提示
- 天数统计一目了然
- 便于确认选择
🚀 后续增强
Phase 1: 快捷选择
添加常用时间段快捷按钮:
[ 本周 ] [ 本月 ] [ 本季度 ] [ 本年度 ]
[ 上周 ] [ 上月 ] [ 上季度 ] [ 去年 ]
Phase 2: 预设对比期
添加同比/环比快捷选择:
选择基准期:2024年09月01日 - 2024年10月17日
自动计算:
- 去年同期:2023年09月01日 - 2023年10月17日
- 上一周期:2024年07月16日 - 2024年08月31日
Phase 3: 时间段模板
保存常用时间段:
我的模板:
- 春耕季:03月15日 - 04月30日
- 夏管季:05月01日 - 07月31日
- 秋收季:09月15日 - 10月31日
一键应用模板
📚 相关文档
- 组件文件:
/components/machinery/data/OperationAnalysis.tsx - 日期组件:
/components/ui/calendar.tsx - 弹窗组件:
/components/ui/popover.tsx
✅ 总结
主要功能
- ✅ 时间范围选择 - 4种预设 + 自定义
- ✅ 日期选择器 - 可视化日历选择
- ✅ 智能验证 - 结束日期不早于开始日期
- ✅ 中文显示 - 完全中文本地化
- ✅ 天数计算 - 自动计算时间跨度
用户价值
- 精确控制: 可以选择任意时间段
- 易于使用: 点击日历即可选择
- 智能验证: 避免选择错误日期
- 直观反馈: 清晰显示选择结果
技术亮点
- 使用 date-fns 进行日期处理
- 中文本地化支持
- 日期验证和禁用逻辑
- 响应式布局设计
更新时间: 2025-10-17
版本: v1.0
状态: ✅ 自定义时间范围功能已完成
核心改进: 添加可视化日期选择器,支持精确的自定义时间范围选择!