前言 📝

本文主要是记录一下上下班打开的逻辑,该业务场景是通过管理端配置上下班打卡次数,例如:2次(上午上班、下午下班)、4次(上午上班、上午下班、下午上班、下午下班)、6次(上午上班、上午下班、下午上班、下午下班、加班上班、加班下班)。通过配置实现对应的打卡逻辑,当打过这个时间段的卡之后,并且目前还没有进入下一个时间段,这区间是不能再次进行打卡的。

具体的逻辑我也记不清楚了,虽然是自己写的。但是也忘的差不多了。本文主要是用于记录一下,下次如果遇到的情况,可以返回来回顾一下当时的逻辑,没准会有不一样的体验想法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

/**
* AttendanceTypeEnum枚举:{上午上班 = 1,上午下班 = 2,下午上班 = 4,下午下班 = 8,加班上班 = 16,加班下班 = 32},前端枚举,value和后端字段相呼应
* clockConfig: 后端返回的上下班打开配置 数据格式 { 1: '9:00', 8: '18:00' }、{ 1: '9:00', 2: '12:00', 4: '13:00', 8: '18:00' }...
* todayClockRecord:该人员近日打卡记录,格式和clockConfig一样
*/

// 上下班状态
const status = computed(() => {
const arr = Object.keys(clockConfig.value).sort();
const now = +new Date();

// 判断是否在指定时间段内,并检查对应的打卡记录
const isInTimeRange = (start: string, end: string, recordKey: string) =>
now > +timeCompare(start) &&
now < +timeCompare(end) &&
!todayClockRecord.value[+recordKey];

// 双时间段:上午上班和下午下班
if (arr.length === 2) {
const morningPunchIn = AttendanceTypeEnum.上午上班;
const afternoonPunchOut = AttendanceTypeEnum.下午下班;

if (!todayClockRecord.value[+morningPunchIn]) return '上午上班';
if (isInTimeRange(clockConfig.value[+afternoonPunchOut], '23:59:59', afternoonPunchOut))
return '下午下班';
return '无需打卡';
}

// 四时间段:上午上班、上午下班、下午上班、下午下班
if (arr.length === 4) {
const morningPunchIn = AttendanceTypeEnum.上午上班;
const morningPunchOut = AttendanceTypeEnum.上午下班;
const afternoonPunchIn = AttendanceTypeEnum.下午上班;
const afternoonPunchOut = AttendanceTypeEnum.下午下班;

if (isInTimeRange('00:00:00', clockConfig.value[+morningPunchOut], morningPunchIn))
return '上午上班';
if (isInTimeRange(clockConfig.value[+morningPunchOut], clockConfig.value[+afternoonPunchIn], morningPunchOut))
return '上午下班';
if (isInTimeRange(clockConfig.value[+morningPunchOut], clockConfig.value[+afternoonPunchOut], afternoonPunchIn))
return '下午上班';
if (isInTimeRange(clockConfig.value[+afternoonPunchOut], '23:59:59', afternoonPunchOut))
return '下午下班';
return '无需打卡';
}

// 六时间段:上午上班、上午下班、下午上班、下午下班、加班上班、加班下班
if (arr.length === 6) {
const morningPunchIn = AttendanceTypeEnum.上午上班;
const morningPunchOut = AttendanceTypeEnum.上午下班;
const afternoonPunchIn = AttendanceTypeEnum.下午上班;
const afternoonPunchOut = AttendanceTypeEnum.下午下班;
const overtimePunchIn = AttendanceTypeEnum.加班上班;
const overtimePunchOut = AttendanceTypeEnum.加班下班;

if (isInTimeRange('00:00:00', clockConfig.value[+morningPunchOut], morningPunchIn))
return '上午上班';
if (isInTimeRange(clockConfig.value[+morningPunchOut], clockConfig.value[+afternoonPunchIn], morningPunchOut))
return '上午下班';
if (isInTimeRange(clockConfig.value[+morningPunchOut], clockConfig.value[+afternoonPunchOut], afternoonPunchIn))
return '下午上班';
if (isInTimeRange(clockConfig.value[+afternoonPunchOut], clockConfig.value[+overtimePunchIn], afternoonPunchOut))
return '下午下班';
if (isInTimeRange(clockConfig.value[+afternoonPunchOut], '23:59:59', overtimePunchIn))
return '加班上班';
if (isInTimeRange(clockConfig.value[+overtimePunchOut], '23:59:59', overtimePunchOut))
return '加班下班';
return '无需打卡';
}

return '无需打卡';
});

// 时间比较函数:用于将字符串时间转换为当日的 Date 对象
function timeCompare(str: string) {
const currentDate = new Date();
const targetDateStr = currentDate.toDateString() + ' ' + str;
return new Date(targetDateStr);
}