本文详解如何让 easepick 的 presetplugin 预设范围在用户点击时动态计算(如“过去 5 分钟”始终基于当前点击时刻),而非初始化时静态固化,避免时间漂移问题。
本文详解如何让 easepick 的 presetplugin 预设范围在用户点击时动态计算(如“过去 5 分钟”始终基于当前点击时刻),而非初始化时静态固化,避免时间漂移问题。
Easepick 默认的 PresetPlugin 中预设的时间范围(如 past 5 minutes)是在实例化时一次性计算并固化为 Date 对象的——这意味着若页面长时间未刷新,点击该预设将返回「加载页面时」的 5 分钟前,而非「点击瞬间」的 5 分钟前,造成显著的时间偏差。
解决这一问题的核心思路是:不依赖初始化时静态定义预设区间,而是在用户触发预设选择(select 事件)后,动态重置起止时间。关键在于利用 setup() 生命周期钩子监听 select 事件,并通过判断事件来源区分「预设点击」与「手动日历/时间选择」,从而仅对预设操作执行动态重计算。
以下是完整、可直接运行的解决方案:
const minute = 60 * 1000;
const hour = 60 * minute;
const day = 24 * hour;
const picker = new easepick.create({
element: "#select_start",
css: ["https://cdn.jsdelivr.net/npm/@easepick/bundle@1/dist/index.css"],
format: "D MMM, HH:mm:ss",
grid: 2,
calendars: 2,
plugins: ["RangePlugin", "LockPlugin", "TimePlugin", "PresetPlugin"],
RangePlugin: {
elementEnd: "#select_end",
strict: false
},
LockPlugin: {
maxDate: new Date(),
minDate: new Date(Date.now() - 30 * day)
},
TimePlugin: {
seconds: true
},
PresetPlugin: {
position: 'left',
customPreset: {
"past 5 mins": [new Date(), new Date()], // 占位符:起止时间暂设为当前时间(实际由 select 事件覆盖)
"past 15 mins": [new Date(), new Date()],
"past 30 mins": [new Date(), new Date()],
"past 1 hour": [new Date(), new Date()],
"past 3 hours": [new Date(), new Date()],
"past 6 hours": [new Date(), new Date()],
"past 12 hours": [new Date(), new Date()]
}
},
setup(picker) {
picker.on("select", (e) => {
// 判断是否为预设点击:检查事件目标是否为 preset 按钮(非日历单元格或时间控件)
// Easepick 预设按钮的 innerHTML 通常不含 "selected" 类(而手动选择的日历日期会带选中状态标记)
if (!e.target?.innerHTML?.includes("selected") && e.detail?.start && e.detail?.end) {
const spanMs = e.detail.end - e.detail.start; // 获取原始预设跨度(毫秒)
const now = new Date();
picker.setStartDate(new Date(now.getTime() - spanMs));
picker.setEndDate(now);
}
});
}
});
✅ 关键要点说明:
- 预设定义简化为占位符:所有 customPreset 均设为 [new Date(), new Date()],避免初始化时固化时间;真实逻辑交由 select 事件处理。
- 精准识别预设触发:通过 e.target.innerHTML.includes("selected") 区分——手动点选日期/时间时,目标元素通常含选中态标记;而预设按钮无此标记,可安全判定为预设操作。
- 动态重设时间:获取原始跨度 spanMs,结合 new Date() 实时计算起点,确保“过去 N 分钟”永远相对于点击时刻。
- 兼容性保障:setStartDate() / setEndDate() 是 Easepick 官方 API,稳定可靠;无需修改源码或 hack DOM。
⚠️ 注意事项:
- 确保 PresetPlugin 已正确启用(插件名大小写敏感,应为 "PresetPlugin");
- 若项目使用模块化引入(如 ES Module),请确认 easepick 全局变量已正确定义或改用 import 方式;
- LockPlugin 的 minDate 和 maxDate 仍需在初始化时设定(它们控制可选范围,不影响预设动态逻辑);
- 如需支持“未来时间段”预设(如“接下来 1 小时”),只需将 picker.setStartDate() 改为 now,picker.setEndDate() 改为 new Date(now.getTime() + spanMs)。
该方案以最小侵入性实现最大灵活性,既保持 Easepick 原生 API 的简洁性,又彻底解决了预设时间静态化的痛点,适用于监控面板、日志查询等对时间精度要求严格的场景。











