Browse Source

refactor(clockIn): 打卡根据后端考勤规则判断打卡状态
feat(store/config): 考勤规则状态管理

HMY 1 year ago
parent
commit
2eabbaa396
5 changed files with 629 additions and 496 deletions
  1. 25 18
      App.vue
  2. 27 3
      api/mine.js
  3. 25 18
      pages/login.vue
  4. 471 457
      pages/mine/clockIn/clockIn.vue
  5. 81 0
      store/config.js

+ 25 - 18
App.vue

@@ -3,6 +3,9 @@ import { getUserInfo } from '@/utils/auth'
 import { checkAttendance } from '@/api/mine.js'
 import config from '@/config.js'
 import $tab from '@/plugins/tab.js'
+import { useConfigStore } from '@/store/config.js'
+
+
 export default {
 	onLaunch: function () {
 		// console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
@@ -24,30 +27,34 @@ export default {
 			this.checkLogin()
 		},
 		checkLogin() {
+			const configStore=useConfigStore()
 			const user = getUserInfo()
 			if (!getUserInfo()) {
 				$tab.reLaunch('/pages/login')
 			} else {
 				// 是否在上班打卡时间段
-				if (this.isInTimeRange(...config.signInTimeRange)) {
-					const now = new Date()
-					const params = {
-						universalid: user.useId,
-						rizi: (now.getFullYear()) + '-' + (now.getMonth() + 1) + '-' + (now.getDate())
-					}
-					// 获取当天考勤信息
-					checkAttendance(params).then(({ returnParams }) => { 
-						if (returnParams.list.length) {
-							// 已签到 跳转消息页
-							$tab.reLaunch('/pages/message/index')
-						} else {
-							// 未签到 跳转考勤页面
-							$tab.reLaunch('/pages/message/index?to=clockIn')
+				configStore.GetAttRule(user).then(()=>{
+					if (this.isInTimeRange(...configStore.signInTimeRange)) {
+						const now = new Date()
+						const params = {
+							universalid: user.useId,
+							rizi: (now.getFullYear()) + '-' + (now.getMonth() + 1) + '-' + (now.getDate())
 						}
-					})
-				} else {
-					$tab.reLaunch('/pages/message/index')
-				}
+						// 获取当天考勤信息
+						checkAttendance(params).then(({ returnParams }) => { 
+							if (returnParams.list.length) {
+								// 已签到 跳转消息页
+								$tab.reLaunch('/pages/message/index')
+							} else {
+								// 未签到 跳转考勤页面
+								$tab.reLaunch('/pages/message/index?to=clockIn')
+							}
+						})
+					} else {
+						$tab.reLaunch('/pages/message/index')
+					}
+				})
+				
 			}
 		},
 		//判断时间是否在区间内

+ 27 - 3
api/mine.js

@@ -1,9 +1,7 @@
 import request from '@/utils/request.js'
 import config from '@/config'
 import upload from '@/utils/upload'
-import {
-	getSession
-} from '@/utils/auth.js'
+import {getSession} from '@/utils/auth.js'
 const preUrl = '/clientServices.do?iscrypt=1'
 
 export function getUserInfo(useId) {
@@ -19,6 +17,7 @@ export function getUserInfo(useId) {
 	})
 }
 
+
 //检查今日考勤状况
 export function checkAttendance({ universalid, rizi }) {
 	return request({
@@ -155,3 +154,28 @@ export function updateUserInfoHeaderFileId(params) {
 	})
 }
 
+//考勤班次获取
+export function getAttendanceSegment(unitId) {
+	return request({
+		url: preUrl,
+		method: 'post',
+		data: {
+			serviceId: "miniapp_getAttendanceSegment",
+			params: { unitId }
+		}
+	})
+}
+
+
+//考勤规则获取
+export function getAttendanceRule(unitId) {
+	return request({
+		url: preUrl,
+		method: 'post',
+		data: {
+			serviceId: "miniapp_getAttendanceRule",
+			params: { unitId }
+		}
+	})
+}
+

+ 25 - 18
pages/login.vue

@@ -29,7 +29,9 @@ import $modal from '@/plugins/modal.js'
 import $tab from '@/plugins/tab.js'
 import { useUserStore } from '@/store/user.js'
 import { getLoginInfo } from '@/utils/auth'
+import { useConfigStore } from '@/store/config.js'
 const userStore = useUserStore()
+const configStore=useConfigStore();
 
 const loginForm = ref({
 	username: getLoginInfo().username || '',
@@ -54,25 +56,30 @@ function handleLogin() {
 function loginSuccess() {
 	userStore.GetInfo()
 	// 是否在上班打卡时间段
-	if (isInTimeRange(...config.signInTimeRange)) {
-		const now = new Date()
-		const params = {
-			universalid: userStore.useId,
-			rizi: (now.getFullYear()) + '-' + (now.getMonth() + 1) + '-' + (now.getDate())
-		}
-		// 获取当天考勤信息
-		checkAttendance(params).then(({ returnParams }) => {
-			if (returnParams.list.length) {
-				// 已签到 跳转消息页
-				$tab.reLaunch('/pages/message/index')
-			} else {
-				// 未签到 跳转考勤页面
-				$tab.reLaunch('/pages/message/index?to=clockIn')
+	configStore.GetAttRule(userStore.user).then(()=>{
+		console.log('======',configStore.signInTimeRange);
+		if (isInTimeRange(...configStore.signInTimeRange)) {
+			const now = new Date()
+			const params = {
+				universalid: userStore.useId,
+				rizi: (now.getFullYear()) + '-' + (now.getMonth() + 1) + '-' + (now.getDate())
 			}
-		})
-	} else {
-		$tab.reLaunch('/pages/message/index')
-	}
+			// 获取当天考勤信息
+			checkAttendance(params).then(({ returnParams }) => {
+				if (returnParams.list.length) {
+					// 已签到 跳转消息页
+					$tab.reLaunch('/pages/message/index')
+				} else {
+					// 未签到 跳转考勤页面
+					$tab.reLaunch('/pages/message/index?to=clockIn')
+				}
+			})
+		} else {
+			$tab.reLaunch('/pages/message/index')
+		}
+	})
+	
+	
 }
 //判断时间是否在区间内
 function isInTimeRange(start, end) {

+ 471 - 457
pages/mine/clockIn/clockIn.vue

@@ -29,8 +29,8 @@
 			</view>
 		</view>
 		<!-- 地图 -->
-		<atl-map :mapKey="config.mapKey" :mapType="mapType" :longitude="longitude" :latitude="latitude"
-			:marker="marker" :polygons="polygons" :isPolygons="true">
+		<atl-map :mapKey="config.mapKey" :mapType="mapType" :longitude="longitude" :latitude="latitude" :marker="marker"
+			:polygons="polygons" :isPolygons="true">
 			<template v-slot:content>
 			</template>
 		</atl-map>
@@ -46,504 +46,518 @@
 
 
 <script setup lang="ts">
-import {onBeforeUnmount,onMounted,reactive,ref} from 'vue';
-// 导入地理位置相关函数
-import booleanPointInPolygon from "@turf/boolean-point-in-polygon";
-import {point,polygon} from "@turf/helpers";
-import {useUserStore} from '@/store/user';
-import $modal from '@/plugins/modal.js'
-import $tab from '@/plugins/tab.js';
-import config from '@/config.js';
-import {createAttendance,tranAddress,checkAttendance} from '@/api/mine.js'
-const userStore = useUserStore();
-const thisUser = userStore.user;
-const intervalId = ref(null); // 定时器ID
-onBeforeUnmount(() => {
-	clearInterval(intervalId.value);
-})
-// 组件挂载后初始化当前日期与位置
-onMounted(() => {
-	dateInit();
-	getAddress();
-});
-
-
-
-function showNowTime() {
-	// let nowMilliseconds=Date.now();
-	// intervalId.value = setInterval(() => {
-	// 	nowMilliseconds+=1000;
-	// 	 nowTime.value = new Date(nowMilliseconds).toLocaleString('zh-CN', {
-	// 	        year: 'numeric',
-	// 	        month: '2-digit',
-	// 	        day: '2-digit',
-	// 	        hour: '2-digit',
-	// 	        minute: '2-digit',
-	// 	        second: '2-digit',
-	// 	        hour12: false // 24小时制
-	// 	    });
-	// 	}, 1000); // 每1秒更新一次
-
-	intervalId.value = setInterval(() => {
-		nowTime.value = getNowTime()
-	}, 1000); // 每1秒更新一次
-}
-// 当前日期和时间相关信息
-const currentDate = ref('2023-04-01');
-const currentDay = ref('星期三');
-const nowTime = ref(''); // 当前时间
-const weekArr = reactive(['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']); // 星期数组
-
-
-// 初始化日期
-function dateInit() {
-	showNowTime();
-	const nowDate = new Date();
-	const year = nowDate.getFullYear(); // 获取年份
-	const month = nowDate.getMonth() + 1; // 获取月份
-	const day = nowDate.getDate(); // 获取日期
-	// 格式化月份和日期为两位数
-	const formattedMonth = month < 10 ? '0' + month : month;
-	const formattedDay = day < 10 ? '0' + day : day;
-	currentDate.value = `${year}-${formattedMonth}-${formattedDay}`; // 设置当前日期
-	const dayOfWeek = nowDate.getDay(); // 获取当前星期
-	currentDay.value = weekArr[dayOfWeek]; // 设置当前星期
-	getTodayAtt();
-}
-
-
-const signInTime = ref(''); // 上班签到时间
-const signOutTime = ref(''); // 下班签到时间
-//打卡按钮文字显示
-const signName = ref('')
-
-//迟到早退状态,默认隐藏
-const signInStatusName = ref('迟到')
-const signOutStatusName = ref('早退')
-const isSignInStatusDisabled = ref(true)
-const isSignOutStatusDisabled = ref(true)
-//获取今天考勤状态
-function getTodayAtt() {
-	const params = {
-		universalid: thisUser.useId,
-		rizi: currentDate.value
+	import { onBeforeUnmount, onMounted, reactive, ref } from 'vue';
+	// 导入地理位置相关函数
+	import booleanPointInPolygon from "@turf/boolean-point-in-polygon";
+	import { point, polygon } from "@turf/helpers";
+	import { useUserStore } from '@/store/user';
+	import { useConfigStore } from '@/store/config'
+	import $modal from '@/plugins/modal.js';
+	import $tab from '@/plugins/tab.js';
+	import config from '@/config.js';
+	import { createAttendance, tranAddress, checkAttendance, getAttendanceRule, getAttendanceSegment } from '@/api/mine.js'
+	const userStore = useUserStore();
+	const configStore=useConfigStore();
+	const thisUser = userStore.user;
+	const intervalId = ref(null); // 定时器ID
+	onBeforeUnmount(() => {
+		clearInterval(intervalId.value);
+	})
+	// 组件挂载后初始化当前日期与位置
+	onMounted(() => {
+		// getAttRule();
+		dateInit();
+		getAddress();
+	});
+
+	function showNowTime() {
+		intervalId.value = setInterval(() => {
+			nowTime.value = getNowTime()
+		}, 1000); // 每1秒更新一次
 	}
-	checkAttendance(params).then(res => {
-
-		if ("success" == res.returnMsg) {
-			// console.log("kaoqin",res);
-			const attList = res.returnParams.list;
-			const time1 = attList.find(item => item.att_type_id === '1');
-			//拿到所有签退数据后,用pop取最后一个
-			const time2 = attList.filter(item => item.att_type_id === '2').pop();
-			console.log('time2', time2);
-			if (time1 !== undefined) {
-				// console.log('getTime1',time1);
-				signInTime.value = time1.att_time.split(' ')[1];
-				signName.value = '下班签退';
-				if (Array.isArray(config.lateTimeRange) && isTimeInRange(signInTime.value, config
-					.lateTimeRange[0], '23:59:59')) {
-					isSignInStatusDisabled.value = false; //迟到
-				}
-			} else {
-				signName.value = '上班签到';
-			}
-			if (time2 !== undefined) {
-				signOutTime.value = time2.att_time.split(' ')[1];
-				if (Array.isArray(config.signOutTimeRange) && isTimeInRange(signOutTime.value, "00:00:00",
-					config.signOutTimeRange[0])) {
-					isSignOutStatusDisabled.value = false; //早退
+	// 当前日期和时间相关信息
+	const currentDate = ref('2023-04-01');
+	const currentDay = ref('星期三');
+	const nowTime = ref(''); // 当前时间
+	const weekArr = reactive(['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']); // 星期数组
+
+
+	// 初始化日期
+	function dateInit() {
+		showNowTime();
+		const nowDate = new Date();
+		const year = nowDate.getFullYear(); // 获取年份
+		const month = nowDate.getMonth() + 1; // 获取月份
+		const day = nowDate.getDate(); // 获取日期
+		// 格式化月份和日期为两位数
+		const formattedMonth = month < 10 ? '0' + month : month;
+		const formattedDay = day < 10 ? '0' + day : day;
+		currentDate.value = `${year}-${formattedMonth}-${formattedDay}`; // 设置当前日期
+		const dayOfWeek = nowDate.getDay(); // 获取当前星期
+		currentDay.value = weekArr[dayOfWeek]; // 设置当前星期
+		getTodayAtt();
+	}
+
+
+	const signInTime = ref(''); // 上班签到时间
+	const signOutTime = ref(''); // 下班签到时间
+	//打卡按钮文字显示
+	const signName = ref('')
+
+	//迟到早退状态,默认隐藏
+	const signInStatusName = ref('迟到')
+	const signOutStatusName = ref('早退')
+	const isSignInStatusDisabled = ref(true)
+	const isSignOutStatusDisabled = ref(true)
+	//获取今天考勤状态
+	function getTodayAtt() {
+		const params = {
+			universalid: thisUser.useId,
+			rizi: currentDate.value
+		}
+		checkAttendance(params).then(res => {
+			if ("success" == res.returnMsg) {
+				// console.log("kaoqin",res);
+				const attList = res.returnParams.list;
+				const time1 = attList.find(item => item.att_type_id === '1');
+				//拿到所有签退数据后,用pop取最后一个
+				const time2 = attList.filter(item => item.att_type_id === '2').pop();
+				console.log('time2', time2);
+				if (time1 !== undefined) {
+					// console.log('getTime1',time1);
+					signInTime.value = time1.att_time.split(' ')[1];
+					signName.value = '下班签退';
+					if (isTimeInRange(signInTime.value, ...configStore.lateTimeRange)) {//迟到
+						signInStatusName.value = '迟到';
+						isSignInStatusDisabled.value = false;
+					} else if (isTimeInRange(signInTime.value, configStore.lateTimeRange[1], '23:59:59')) {
+						signInStatusName.value = '旷工';
+						isSignInStatusDisabled.value = false;
+					}
 				} else {
-					isSignOutStatusDisabled.value = true; //隐藏早退状态
+					signName.value = '上班签到';
+				}
+				if (time2 !== undefined) {
+					signOutTime.value = time2.att_time.split(' ')[1];
+					if (isTimeInRange(signOutTime.value, "00:00:00", configStore.earlyTimeRange[0])) {//旷工
+						signOutStatusName.value = '旷工';
+						isSignOutStatusDisabled.value = false;
+					}
+					else if (isTimeInRange(signOutTime.value, ...configStore.earlyTimeRange)) {
+						signOutStatusName.value = '早退';
+						isSignOutStatusDisabled.value = false;
+					}
+					else {
+						isSignOutStatusDisabled.value = true; //隐藏早退状态
+					}
 				}
 			}
-		}
-	})
-}
+		})
+	}
 
 
 
-//上班卡或下班卡
-function signInOrOut() {
-	if ('上班签到' == signName.value) {
-		signIn();
-	} else {
-		signOut();
+	//上班卡或下班卡
+	function signInOrOut() {
+		if ('上班签到' == signName.value) {
+			signIn();
+		} else {
+			signOut();
+		}
 	}
-}
-
-//上班签到
-function signIn() {
-	const now = getNowTime();
-	const signIn = 1;
-	getAddress().then(() => {
-		clockIn(signIn);
-	});
-};
-
-// 下班签退
-function signOut() {
-	const now = getNowTime();
-	const signOut = 2;
-	//判断打卡时间是否符合
-	if (!isTimeInRange(now, ...config.signOutTimeRange)) {
-		$modal.confirm('当前非正常签退时间,是否继续?').then(res => {
-			if (res) {
-				getAddress().then(() => {
-					clockIn(signOut); // 执行打卡并获取结果
-				});
-			}
-		}).catch(() => { })
-	} else {
+
+	//上班签到
+	function signIn() {
+		const now = getNowTime();
+		const signIn = 1;
 		getAddress().then(() => {
-			clockIn(signOut);
+			clockIn(signIn);
 		});
+	};
+
+	// 下班签退
+	function signOut() {
+		const now = getNowTime();
+		const signOut = 2;
+		//判断打卡时间是否符合
+		if (!isTimeInRange(now, ...configStore.signOutTimeRange)) {
+			$modal.confirm('当前非正常签退时间,是否继续?').then(res => {
+				if (res) {
+					getAddress().then(() => {
+						clockIn(signOut); // 执行打卡并获取结果
+					});
+				}
+			}).catch(() => { })
+		} else {
+			getAddress().then(() => {
+				clockIn(signOut);
+			});
+		}
+	};
+
+	//获取当前时间
+	function getNowTime() {
+		return new Date().toLocaleTimeString('en-US', {
+			hour12: false
+		}).substring(0, 8)
 	}
-};
-
-//获取当前时间
-function getNowTime() {
-	return new Date().toLocaleTimeString('en-US', {
-		hour12: false
-	}).substring(0, 8)
-}
-
-//判断时间是否在区间内
-function isTimeInRange(time, startTime, endTime) {
-	// 将时间字符串转换为Date对象
-	const timeObj = new Date('1970-01-01T' + time + 'Z');
-	const startObj = new Date('1970-01-01T' + startTime + 'Z');
-	const endObj = new Date('1970-01-01T' + endTime + 'Z');
-	// 比较时间
-	return timeObj >= startObj && timeObj <= endObj;
-}
-
-
-// 地图配置信息
-// const mapKey = config.mapKey; // 地图API密钥
-const mapType = ref('tmap'); // 地图类型
-const address = ref(''); // 初始化地址
-
-// 打卡定位信息
-const longitude = ref(); // 经度
-const latitude = ref(); // 纬度
-
-// 标记信息
-const marker = reactive({
-	id: 1,
-	latitude: 25.958812,
-	longitude: 119.213036,
-	width: 50, // 标记宽度
-	height: 50, // 标记高度
-	title: '宇光同行' // 标记标题
-});
-
-// 获取当前定位经纬度
-function getlocation() {
-	return new Promise((resolve, reject) => {
-		//判断用户是否打开位置权限
-		uni.getSetting({
-			success(res) {
-				// 如果用户未授权
-				if (!res.authSetting['scope.userLocation']) {
-					$modal.confirm('需要您授权获取地理位置信息').then(res => {
-						if (res) {
-							// 打开权限设置页面
-							uni.openSetting({
-								success: (settingData) => {
-									if (settingData.authSetting[
-										'scope.userLocation']) {
-										$modal.msg('授权后请重新打开此页面')
-										// reject("用户未授权");
-									}
-								}
-							});
-						}
-					})
-						.catch(err => {
-							//用户点击取消
-							if (!err) {
-								uni.showToast({
-									title: '获取地理位置授权失败',
-									icon: 'none',
-									success: () => {
-										// 返回上一页
-										setTimeout(() => {
-											$tab.navigateBack()
-										}, 1000);
+
+	//判断时间是否在区间内
+	function isTimeInRange(time, startTime, endTime) {
+		// 将时间字符串转换为Date对象
+		const timeObj = new Date('1970-01-01T' + time + 'Z');
+		const startObj = new Date('1970-01-01T' + startTime + 'Z');
+		const endObj = new Date('1970-01-01T' + endTime + 'Z');
+		// 比较时间
+		return timeObj >= startObj && timeObj <= endObj;
+	}
+
+
+	// 地图配置信息
+	// const mapKey = config.mapKey; // 地图API密钥
+	const mapType = ref('tmap'); // 地图类型
+	const address = ref(''); // 初始化地址
+
+	// 打卡定位信息
+	const longitude = ref(); // 经度
+	const latitude = ref(); // 纬度
+
+	// 标记信息
+	const marker = reactive({
+		id: 1,
+		latitude: 25.958812,
+		longitude: 119.213036,
+		width: 50, // 标记宽度
+		height: 50, // 标记高度
+		title: '宇光同行' // 标记标题
+	});
+
+	// 获取当前定位经纬度
+	function getlocation() {
+		return new Promise((resolve, reject) => {
+			//判断用户是否打开位置权限
+			uni.getSetting({
+				success(res) {
+					// 如果用户未授权
+					if (!res.authSetting['scope.userLocation']) {
+						$modal.confirm('需要您授权获取地理位置信息').then(res => {
+							if (res) {
+								// 打开权限设置页面
+								uni.openSetting({
+									success: (settingData) => {
+										if (settingData.authSetting[
+											'scope.userLocation']) {
+											$modal.msg('授权后请重新打开此页面')
+											// reject("用户未授权");
+										}
 									}
 								});
-								// reject("用户未授权");
 							}
 						})
-				} else {
-					// 已授权,获取位置
-					fetchLocation(resolve, reject);
+							.catch(err => {
+								//用户点击取消
+								if (!err) {
+									uni.showToast({
+										title: '获取地理位置授权失败',
+										icon: 'none',
+										success: () => {
+											// 返回上一页
+											setTimeout(() => {
+												$tab.navigateBack()
+											}, 1000);
+										}
+									});
+									// reject("用户未授权");
+								}
+							})
+					} else {
+						// 已授权,获取位置
+						fetchLocation(resolve, reject);
+					}
+				},
+				fail(err) {
+					reject(err); // 拒绝 Promise
 				}
+			});
+		});
+	}
+
+	// 封装获取位置的函数
+	function fetchLocation(resolve, reject) {
+		wx.getLocation({
+			success: (res) => {
+				longitude.value = res.longitude; // 保存经度
+				latitude.value = res.latitude; // 保存纬度	
+				resolve(); // 解析 Promise
 			},
-			fail(err) {
+			fail: (err) => {
+				if (err.errMsg.includes("频繁调用")) {
+					$modal.msg('请勿频繁调用');
+					// reject("频繁调用错误");
+					return;
+				}
+				console.log('getLocationErr', err);
 				reject(err); // 拒绝 Promise
-			}
+			},
 		});
-	});
-}
-
-// 封装获取位置的函数
-function fetchLocation(resolve, reject) {
-	wx.getLocation({
-		success: (res) => {
-			longitude.value = res.longitude; // 保存经度
-			latitude.value = res.latitude; // 保存纬度	
-			resolve(); // 解析 Promise
-		},	
-		fail: (err) => {
-			if (err.errMsg.includes("频繁调用")) {
-				$modal.msg('请勿频繁调用');
-				// reject("频繁调用错误");
-				return;
-			}
-			console.log('getLocationErr', err);
-			reject(err); // 拒绝 Promise
-		},
-	});
-}
+	}
 
 
-// 获取当前位置地址
-function getAddress() {
-	return new Promise((resolve, reject) => {
-		getlocation()
-			.then(res => {
-				tranLocationToAddress(); // 执行地址转换
-				resolve(res); // 地址获取成功
-			})
-			.catch(err => {
-				// console.error('获取地址失败', err);
-				reject(err); // 地址获取失败
-			});
-	});
-}
+	// 获取当前位置地址
+	function getAddress() {
+		return new Promise((resolve, reject) => {
+			getlocation()
+				.then(res => {
+					tranLocationToAddress(); // 执行地址转换
+					resolve(res); // 地址获取成功
+				})
+				.catch(err => {
+					// console.error('获取地址失败', err);
+					reject(err); // 地址获取失败
+				});
+		});
+	}
 
-// 经纬度转地址
-function tranLocationToAddress() {
-	let locationStr = latitude.value + ',' + longitude.value; // 组合经纬度
-	tranAddress(locationStr).then(res => {
-		address.value = res.result.address; // 保存地址
-	})
-		.catch(err => {
-			console.log('地址转换请求失败', err); // 请求错误处理
+	// 经纬度转地址
+	function tranLocationToAddress() {
+		let locationStr = latitude.value + ',' + longitude.value; // 组合经纬度
+		tranAddress(locationStr).then(res => {
+			address.value = res.result.address; // 保存地址
 		})
-}
-
-
-// 多边形区域设置
-const polygons = reactive([{
-	points: [{
-		latitude: 25.9591401,
-		longitude: 119.21292356
-	},
-	{
-		latitude: 25.95828592,
-		longitude: 119.21261955
-	},
-	{
-		latitude: 25.9576709,
-		longitude: 119.21458294
-	},
-	{
-		latitude: 25.95845106,
-		longitude: 119.21486162
-	},
-	{
-		latitude: 25.9591401,
-		longitude: 119.21292356
-	}
-	],
-	strokeWidth: 1, // 边框宽度
-	strokeColor: "#ff000066", // 边框颜色
-	fillColor: "#ff000016", // 填充颜色
-}]);
-
-// 打卡
-function clockIn(attType) {
-	// 发起打卡请求相关业务逻辑
-	//判断是否已经打过卡
-	if (isClockIn(attType)) {
-		return;
+			.catch(err => {
+				console.log('地址转换请求失败', err); // 请求错误处理
+			})
 	}
-	var now = new Date();
-	// 使用toISOString()获取一个ISO格式的字符串,然后替换T为空格,并去除最后的Z(表示UTC时间)
-	var formatted = now.toISOString().replace('T', ' ').replace('Z', '');
-	var localString = new Date(formatted + '-08:00').toISOString().replace('T', ' ').replace('Z', '');
-	// console.log('nowtime',formatted,localString);
-	const params = {
-		user_name: thisUser.name,
-		user_id: thisUser.useId,
-		kaoqin_type: attType,
-		now_date: localString,
-		longitude: longitude.value,
-		latitude: latitude.value,
-		address: address.value,
-		unitId: thisUser.unitId
-	};
-	createAttendance(params).then(res => {
-		if ("success" == res.returnMsg) {
-			getTodayAtt(); //更新今日考勤数据
-			isToFillClock(attType, localString.substring(12,19));
-			// return true;
-		} else {
-			uni.showToast({
-				title: "未在指定范围,打卡失败",
-				icon: 'none'
-			});
-			// return false;
+
+	// 多边形区域设置
+	const polygons = reactive([{
+		points: [{
+			latitude: 25.9591401,
+			longitude: 119.21292356
+		},
+		{
+			latitude: 25.95828592,
+			longitude: 119.21261955
+		},
+		{
+			latitude: 25.9576709,
+			longitude: 119.21458294
+		},
+		{
+			latitude: 25.95845106,
+			longitude: 119.21486162
+		},
+		{
+			latitude: 25.9591401,
+			longitude: 119.21292356
 		}
-	})
-	// const _polygons = polygons.map((polygon) => {
-	// 	return polygon.points.map((i) => [
-	// 		Number(i.longitude),
-	// 		Number(i.latitude),
-	// 	]);
-	// });
-	// const _point = point([longitude.value, latitude.value]); // 用当前坐标创建点
-	// const _polygon = polygon(_polygons); // 创建多边形
-	// const f = booleanPointInPolygon(_point, _polygon); // 判断点是否在多边形内	
-}
-
-//是否补卡、请假判断
-function isToFillClock(attType,time){
-	//早上迟到跳补卡
-	if(attType==1&&!isTimeInRange(time,...config.signInTimeRange)){
-		$modal.confirm('当前已迟到!\n是否跳转补卡页面').then(()=>{
-			$tab.reLaunch('/pages/work/index')
-		})
-		.catch(()=>{
-			$tab.navigateTo('/pages/mine/checkIn/checkIn')
-		})
-	}else if(attType==2&&!isTimeInRange(time,"00:00:00",config.signOutTimeRange[0])){
-		//早退请假提示
-		$modal.confirm('当前已早退!\n是否跳转请假页面').then(()=>{
-			$tab.reLaunch('/pages/work/index')
-		})
-		.catch(()=>{
-			$tab.navigateTo('/pages/mine/checkIn/checkIn')
+		],
+		strokeWidth: 1, // 边框宽度
+		strokeColor: "#ff000066", // 边框颜色
+		fillColor: "#ff000016", // 填充颜色
+	}]);
+
+	// 打卡
+	function clockIn(attType) {
+		// 发起打卡请求相关业务逻辑
+		//判断是否已经打过卡
+		if (isClockIn(attType)) {
+			return;
+		}
+		var now = new Date();
+		// 使用toISOString()获取一个ISO格式的字符串,然后替换T为空格,并去除最后的Z(表示UTC时间)
+		var formatted = now.toISOString().replace('T', ' ').replace('Z', '');
+		var localString = new Date(formatted + '-08:00').toISOString().replace('T', ' ').replace('Z', '');
+		const params = {
+			user_name: thisUser.name,
+			user_id: thisUser.useId,
+			kaoqin_type: attType,
+			now_date: localString,
+			longitude: longitude.value,
+			latitude: latitude.value,
+			address: address.value,
+			unitId: thisUser.unitId
+		};
+		createAttendance(params).then(res => {
+			if ("success" == res.returnMsg) {
+				getTodayAtt(); //更新今日考勤数据
+				isToFillClock(attType, localString.substring(11, 19));
+				// return true;
+			} else {
+				uni.showToast({
+					title: "未在指定范围,打卡失败",
+					icon: 'none'
+				});
+				// return false;
+			}
 		})
+		// const _polygons = polygons.map((polygon) => {
+		// 	return polygon.points.map((i) => [
+		// 		Number(i.longitude),
+		// 		Number(i.latitude),
+		// 	]);
+		// });
+		// const _point = point([longitude.value, latitude.value]); // 用当前坐标创建点
+		// const _polygon = polygon(_polygons); // 创建多边形
+		// const f = booleanPointInPolygon(_point, _polygon); // 判断点是否在多边形内	
 	}
-	else{
-		$modal.msgSuccess('打卡成功')
-		setTimeout(()=>{
-			$tab.navigateTo('/pages/mine/checkIn/checkIn')
-		},1000)
-	}
-}
-
-//判断是否已经打卡
-function isClockIn(attType) {
-	var attTypeData = '';
-	switch (attType) {
-		case 1:
-			attTypeData = signInTime.value;
-			break;
-		case 2:
-			break;
+
+	//是否补卡、请假判断
+	function isToFillClock(attType, time) {
+		//早上迟到跳补卡
+		let status = '';
+		if (attType == 1) {
+			if (isTimeInRange(time, ...configStore.lateTimeRange)){
+				status = '迟到'
+			} else if (isTimeInRange(time, configStore.lateTimeRange[1], '23:59:59')) {
+				status = '旷工'
+			} else{
+				return
+			}
+			$modal.confirm('当前状态为' + status + '!\n是否跳转补卡页面').then(() => {
+				$tab.reLaunch('/pages/work/index')
+			})
+			.catch(() => {
+					$tab.navigateTo('/pages/mine/checkIn/checkIn')
+				})
+		} else if (attType == 2) {
+			//早退请假提示
+			if(isTimeInRange(time, '00:00:00',configStore.earlyTimeRange[0])){
+				status = '旷工'
+			}else if (isTimeInRange(time, ...configStore.earlyTimeRange)) {
+				status = '早退'
+			} else{
+				return
+			}
+			$modal.confirm('当前状态为' + status + '!\n是否跳转请假页面').then(() => {
+				$tab.reLaunch('/pages/work/index')
+			})
+			.catch(() => {
+					$tab.navigateTo('/pages/mine/checkIn/checkIn')
+				})
+		}
+		else {
+			$modal.msgSuccess('打卡成功')
+			setTimeout(() => {
+				$tab.navigateTo('/pages/mine/checkIn/checkIn')
+			}, 1000)
+		}
 	}
-	if ('' !== attTypeData) {
-		$modal.showToast('请勿重复打卡')
-		return true;
+
+	//判断是否已经打卡
+	function isClockIn(attType) {
+		var attTypeData = '';
+		switch (attType) {
+			case 1:
+				attTypeData = signInTime.value;
+				break;
+			case 2:
+				break;
+		}
+		if ('' !== attTypeData) {
+			$modal.showToast('请勿重复打卡')
+			return true;
+		}
+		return false;
 	}
-	return false;
-}
 </script>
 
 <style lang="scss" scoped>
-// @import "@/static/font/ygoa/iconfont.css";
-
-.ygoa-icon {
-	margin-right: 20rpx;
-	/* font-size: calc(26px + .5(1rem - 16px)); */
-	font-size: calc(1.625rem + 0px) !important;
-}
-
-.container {
-	display: flex;
-	flex-direction: column;
-	align-items: center;
-	padding: 20rpx;
-	.header {
-		width: 100%;
-		height: 200rpx;
-		background-color: #f8f8f8;
+	// @import "@/static/font/ygoa/iconfont.css";
+
+	.ygoa-icon {
+		margin-right: 20rpx;
+		/* font-size: calc(26px + .5(1rem - 16px)); */
+		font-size: calc(1.625rem + 0px) !important;
+	}
+
+	.container {
 		display: flex;
 		flex-direction: column;
 		align-items: center;
-		justify-content: center;
-		.day {
-			font-size: calc(1.5rem + 0px);
-			color: #333;
-			/* font-weight: bold; */
-		}
+		padding: 20rpx;
+
+		.header {
+			width: 100%;
+			height: 200rpx;
+			background-color: #f8f8f8;
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			justify-content: center;
+
+			.day {
+				font-size: calc(1.5rem + 0px);
+				color: #333;
+				/* font-weight: bold; */
+			}
 
-		.date, .nowTime {
-			font-size: calc(1rem + 0px);
-			color: #666;
-		}
+			.date,
+			.nowTime {
+				font-size: calc(1rem + 0px);
+				color: #666;
+			}
 
-		// .nowTime {
-		// 	font-size: 16px;
-		// 	color: #666;
-		// }
-	}
-}
-
-.record {
-	width: 100%;
-	margin-top: 20rpx;
-	border-top: 1px solid #ddd;
-	border-bottom: 1px solid #ddd;
-	padding: 0 15rpx;
-	.record-item {
-		display: flex;
-		align-items: center;
-		height: 100rpx;
-		border-bottom: 1px solid #eee;
-		.icon {
-			width: 50rpx;
-			height: 50rpx;
-			margin-right: 10rpx;
-		}
-		.title {
-			font-size: calc(0.9rem + 0px);
+			// .nowTime {
+			// 	font-size: 16px;
+			// 	color: #666;
+			// }
 		}
+	}
 
-		.time {
-			font-size: calc(0.8rem + 0px);
-			color: #999;
-			margin-left: auto;
-		}
-		.signStatus {
-			font-size: calc(0.9rem + 0px);
-			color: orange;
-			/* margin-left: auto; */
+	.record {
+		width: 100%;
+		margin-top: 20rpx;
+		border-top: 1px solid #ddd;
+		border-bottom: 1px solid #ddd;
+		padding: 0 15rpx;
+
+		.record-item {
+			display: flex;
+			align-items: center;
+			height: 100rpx;
+			border-bottom: 1px solid #eee;
+
+			.icon {
+				width: 50rpx;
+				height: 50rpx;
+				margin-right: 10rpx;
+			}
+
+			.title {
+				font-size: calc(0.9rem + 0px);
+			}
+
+			.time {
+				font-size: calc(0.8rem + 0px);
+				color: #999;
+				margin-left: auto;
+			}
+
+			.signStatus {
+				font-size: calc(0.9rem + 0px);
+				color: orange;
+				/* margin-left: auto; */
+			}
 		}
 	}
-}
 
-::v-deep.map-content {
-	.map {
-		margin-top: 20rpx;
-		height: 56vh !important;
+	::v-deep.map-content {
+		.map {
+			margin-top: 20rpx;
+			height: 56vh !important;
+		}
 	}
-}
-
-.footer {
-	width: 100%;
-	margin-top: 20rpx;
-	display: flex;
-	justify-content: space-around;
-	button {
-		font-size: calc(18px + .5*(1rem - 16px));
+
+	.footer {
 		width: 100%;
-	}
-}
+		margin-top: 20rpx;
+		display: flex;
+		justify-content: space-around;
 
+		button {
+			font-size: calc(18px + .5*(1rem - 16px));
+			width: 100%;
+		}
+	}
 </style>

+ 81 - 0
store/config.js

@@ -0,0 +1,81 @@
+import { defineStore } from 'pinia'
+import { getAttendanceRule, getAttendanceSegment } from '@/api/mine.js'
+import { ref } from 'vue'
+
+export const useConfigStore = defineStore('config', () => {
+	const signInTimeRange = ref([]);//正常签到时间
+	const signOutTimeRange = ref([]);//正常签退时间
+	const lateTimeRange = ref([]);//迟到时间
+	const earlyTimeRange = ref([]);//早退时间
+	
+	function GetAttRule(user) {
+		const fillZero = (timeStr) => timeStr + ':00'
+		return new Promise((resolve) => {
+		    getAttendanceSegment(user.unitId).then(res => {
+		    	const result = res.returnParams.find(item => item.segment_status == "1");
+		    	const { startTime, endTime } = getStartAndEndTime(result.work_time);
+		    	getAttendanceRule(user.unitId).then(res => {
+		    		//找到正在用的考勤规则
+		    		const attRule = res.returnParams.Rows.find(item => item.rule_status == "1");
+		    		signInTimeRange.value = [addMinutesToTime(startTime, -attRule.on_advance_num), fillZero(startTime)];
+		    		signOutTimeRange.value = [fillZero(endTime), addMinutesToTime(endTime, attRule.off_delay_num)];
+		    		lateTimeRange.value = [fillZero(startTime), addMinutesToTime(startTime, attRule.late_num)];
+		    		earlyTimeRange.value = [addMinutesToTime(endTime, -attRule.eary_num), fillZero(endTime)];
+					resolve(); // 确保执行完成后调用 resolve
+				})
+		    })
+		    
+		  });
+		
+	}
+	
+	//获取当天的上班时间和下班时间
+	function getStartAndEndTime(timeString) {
+		//去除最后一个分号
+		timeString = timeString.trim().replace(/;$/, '');
+		const periods = timeString.split(';');
+		let startTime = null;
+		let endTime = null;
+		// 遍历每个时间段
+		for (let period of periods) {
+			if (period) { // 确保不是空字符串
+				const [start, end] = period.split(',').map(time => time.trim());
+				if (!startTime || start < startTime) {
+					startTime = start;
+				}
+				if (!endTime || end > endTime) {
+					endTime = end;
+				}
+			}
+		}
+		return { startTime, endTime };
+	}
+	
+	//处理时间运算
+	function addMinutesToTime(timeStr, minutesToAdd) {
+		const [hours, minutes] = timeStr.split(':').map(Number);
+		let date = new Date();
+		date.setHours(hours);
+		date.setMinutes(minutes);
+		// 添加分钟数
+		date.setMinutes(date.getMinutes() + minutesToAdd);
+		// 获取新的小时和分钟值,确保它们是两位数格式
+		const newHours = String(date.getHours()).padStart(2, '0');
+		const newMinutes = String(date.getMinutes()).padStart(2, '0');
+		// 返回格式化后的新时间字符串
+		return `${newHours}:${newMinutes}:00`;
+	}
+	
+	//补零方法(09:00=>09:00:00)
+	
+	
+
+
+	return {
+		signInTimeRange,
+		signOutTimeRange,
+		lateTimeRange,
+		earlyTimeRange,
+		GetAttRule
+	}
+})