11
This commit is contained in:
158
api/middleware/schedule/services/timeRangeValidator.js
Normal file
158
api/middleware/schedule/services/timeRangeValidator.js
Normal 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;
|
||||
Reference in New Issue
Block a user