This commit is contained in:
张成
2025-12-30 15:46:18 +08:00
parent d14f89e008
commit 65833dd32d
29 changed files with 2416 additions and 1048 deletions

View File

@@ -0,0 +1,158 @@
/**
* 时间范围验证器
* 检查当前时间是否在指定的时间范围内(支持工作日限制)
*/
class TimeRangeValidator {
/**
* 检查当前时间是否在指定的时间范围内
* @param {object} timeRange - 时间范围配置 {start_time: '09:00', end_time: '18:00', workdays_only: 1}
* @returns {{allowed: boolean, reason: string}} 检查结果
*/
static checkTimeRange(timeRange) {
if (!timeRange || !timeRange.start_time || !timeRange.end_time) {
return { allowed: true, reason: '未配置时间范围' };
}
const now = new Date();
const currentHour = now.getHours();
const currentMinute = now.getMinutes();
const currentTime = currentHour * 60 + currentMinute; // 转换为分钟数
// 解析开始时间和结束时间
const [startHour, startMinute] = timeRange.start_time.split(':').map(Number);
const [endHour, endMinute] = timeRange.end_time.split(':').map(Number);
const startTime = startHour * 60 + startMinute;
const endTime = endHour * 60 + endMinute;
// 检查是否仅工作日(使用宽松比较,兼容字符串和数字)
if (timeRange.workdays_only == 1) {
const dayOfWeek = now.getDay(); // 0=周日, 1=周一, ..., 6=周六
if (dayOfWeek === 0 || dayOfWeek === 6) {
return { allowed: false, reason: '当前是周末,不在允许的时间范围内' };
}
}
// 检查当前时间是否在时间范围内
if (startTime <= endTime) {
// 正常情况09:00 - 18:00
if (currentTime < startTime || currentTime >= endTime) {
const currentTimeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
return {
allowed: false,
reason: `当前时间 ${currentTimeStr} 不在允许的时间范围内 (${timeRange.start_time} - ${timeRange.end_time})`
};
}
} else {
// 跨天情况22:00 - 06:00
if (currentTime < startTime && currentTime >= endTime) {
const currentTimeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
return {
allowed: false,
reason: `当前时间 ${currentTimeStr} 不在允许的时间范围内 (${timeRange.start_time} - ${timeRange.end_time})`
};
}
}
return { allowed: true, reason: '在允许的时间范围内' };
}
/**
* 检查是否在工作时间内
* @param {string} startTime - 开始时间 '09:00'
* @param {string} endTime - 结束时间 '18:00'
* @returns {boolean}
*/
static isWithinWorkingHours(startTime = '09:00', endTime = '18:00') {
const result = this.checkTimeRange({
start_time: startTime,
end_time: endTime,
workdays_only: 0
});
return result.allowed;
}
/**
* 检查是否是工作日
* @returns {boolean}
*/
static isWorkingDay() {
const dayOfWeek = new Date().getDay();
return dayOfWeek !== 0 && dayOfWeek !== 6; // 非周六周日
}
/**
* 获取下一个可操作时间
* @param {object} timeRange - 时间范围配置
* @returns {Date|null} 下一个可操作时间,如果当前可操作则返回 null
*/
static getNextAvailableTime(timeRange) {
const check = this.checkTimeRange(timeRange);
if (check.allowed) {
return null; // 当前可操作
}
if (!timeRange || !timeRange.start_time) {
return null;
}
const now = new Date();
const [startHour, startMinute] = timeRange.start_time.split(':').map(Number);
// 如果是工作日限制且当前是周末
if (timeRange.workdays_only == 1) {
const dayOfWeek = now.getDay();
if (dayOfWeek === 0) {
// 周日,下一个可操作时间是周一
const nextTime = new Date(now);
nextTime.setDate(now.getDate() + 1);
nextTime.setHours(startHour, startMinute, 0, 0);
return nextTime;
} else if (dayOfWeek === 6) {
// 周六,下一个可操作时间是下周一
const nextTime = new Date(now);
nextTime.setDate(now.getDate() + 2);
nextTime.setHours(startHour, startMinute, 0, 0);
return nextTime;
}
}
// 计算下一个开始时间
const nextTime = new Date(now);
nextTime.setHours(startHour, startMinute, 0, 0);
// 如果已经过了今天的开始时间,则设置为明天
if (nextTime <= now) {
nextTime.setDate(now.getDate() + 1);
}
return nextTime;
}
/**
* 格式化剩余时间
* @param {object} timeRange - 时间范围配置
* @returns {string} 剩余时间描述
*/
static formatRemainingTime(timeRange) {
const nextTime = this.getNextAvailableTime(timeRange);
if (!nextTime) {
return '当前可操作';
}
const now = Date.now();
const diff = nextTime.getTime() - now;
const hours = Math.floor(diff / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
if (hours > 24) {
const days = Math.floor(hours / 24);
return `需要等待 ${days}${hours % 24} 小时`;
} else if (hours > 0) {
return `需要等待 ${hours} 小时 ${minutes} 分钟`;
} else {
return `需要等待 ${minutes} 分钟`;
}
}
}
module.exports = TimeRangeValidator;