|
|
@@ -27,6 +27,36 @@ export const PUNCH_TYPE = { |
|
|
|
* 处理所有考勤相关的业务逻辑 |
|
|
|
*/ |
|
|
|
export class AttendanceService { |
|
|
|
/** |
|
|
|
* 创建安全的 Date 对象(兼容 IOS 系统) |
|
|
|
* @param {string|number|Date} input 输入的日期参数 |
|
|
|
* @returns {Date} 有效的 Date 对象 |
|
|
|
* @throws {Error} 当无法创建有效日期时抛出错误 |
|
|
|
*/ |
|
|
|
static createSafeDate(input) { |
|
|
|
let date |
|
|
|
|
|
|
|
if (!input) { |
|
|
|
date = new Date() |
|
|
|
} else if (input instanceof Date) { |
|
|
|
date = input |
|
|
|
} else if (typeof input === 'string') { |
|
|
|
// 处理 IOS 系统的日期格式兼容性问题 |
|
|
|
// 将 'YYYY-MM-DD HH:mm:ss' 格式转换为 'YYYY/MM/DD HH:mm:ss' |
|
|
|
const normalizedInput = input.replace(/-/g, '/') |
|
|
|
date = new Date(normalizedInput) |
|
|
|
} else { |
|
|
|
date = new Date(input) |
|
|
|
} |
|
|
|
|
|
|
|
// 验证创建的日期是否有效 |
|
|
|
if (!date || isNaN(date.getTime())) { |
|
|
|
throw new Error('无法创建有效的日期对象') |
|
|
|
} |
|
|
|
|
|
|
|
return date |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 计算两个经纬度之间的距离 |
|
|
|
* @param {number} lat1 纬度1 |
|
|
@@ -142,17 +172,33 @@ export class AttendanceService { |
|
|
|
* 计算日期信息 |
|
|
|
* @param {Date} date 日期对象 |
|
|
|
* @returns {Object} 包含月、周、日的对象 |
|
|
|
* @throws {Error} 当传入的日期无效时抛出错误 |
|
|
|
*/ |
|
|
|
static calculateDateInfo(date) { |
|
|
|
// 参数验证:确保传入的是有效的 Date 对象 |
|
|
|
if (!date || !(date instanceof Date) || isNaN(date.getTime())) { |
|
|
|
throw new Error('传入的日期参数无效,请确保是有效的 Date 对象') |
|
|
|
} |
|
|
|
|
|
|
|
// 获取月份(1-12) |
|
|
|
const month = date.getMonth() + 1 |
|
|
|
|
|
|
|
// 获取日期(1-31) |
|
|
|
const day = date.getDate() |
|
|
|
|
|
|
|
// 计算是一年中的第几周 |
|
|
|
// 计算是一年中的第几周(0-6,0为周日) |
|
|
|
const week = date.getDay() |
|
|
|
|
|
|
|
// 二次验证:确保返回值都是有效数字 |
|
|
|
if (isNaN(month) || isNaN(day) || isNaN(week)) { |
|
|
|
throw new Error('日期计算结果异常,请检查传入的日期对象') |
|
|
|
} |
|
|
|
|
|
|
|
// 范围验证:确保返回值在合理范围内 |
|
|
|
if (month < 1 || month > 12 || day < 1 || day > 31 || week < 0 || week > 6) { |
|
|
|
throw new Error('日期计算结果超出有效范围') |
|
|
|
} |
|
|
|
|
|
|
|
return { month, week, day } |
|
|
|
} |
|
|
|
|
|
|
@@ -160,6 +206,7 @@ export class AttendanceService { |
|
|
|
* 构建打卡请求数据 |
|
|
|
* @param {Object} params 参数对象 |
|
|
|
* @returns {Object} 打卡数据 |
|
|
|
* @throws {Error} 当日期计算失败时抛出错误 |
|
|
|
*/ |
|
|
|
static buildPunchData(params) { |
|
|
|
const { |
|
|
@@ -179,11 +226,31 @@ export class AttendanceService { |
|
|
|
} |
|
|
|
|
|
|
|
const isClockIn = type.includes('morning') |
|
|
|
const currentTime = this.formatDateTime(new Date()) |
|
|
|
|
|
|
|
// 使用安全的日期创建方法 |
|
|
|
const currentDate = this.createSafeDate() |
|
|
|
const currentTime = this.formatDateTime(currentDate) |
|
|
|
|
|
|
|
// 获取当前日期的年月日信息 |
|
|
|
const currentDate = new Date(currentTime) |
|
|
|
const { month, week, day } = this.calculateDateInfo(currentDate) |
|
|
|
let month, week, day |
|
|
|
try { |
|
|
|
const dateInfo = this.calculateDateInfo(currentDate) |
|
|
|
month = dateInfo.month |
|
|
|
week = dateInfo.week |
|
|
|
day = dateInfo.day |
|
|
|
} catch (error) { |
|
|
|
// 如果日期计算失败,使用当前时间重新计算 |
|
|
|
try { |
|
|
|
const fallbackDate = this.createSafeDate() |
|
|
|
const fallbackDateInfo = this.calculateDateInfo(fallbackDate) |
|
|
|
month = fallbackDateInfo.month |
|
|
|
week = fallbackDateInfo.week |
|
|
|
day = fallbackDateInfo.day |
|
|
|
} catch (fallbackError) { |
|
|
|
// 如果仍然失败,抛出错误 |
|
|
|
throw new Error(`日期计算失败: ${error.message}`) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
userId: userInfo.userId, |