From c4d25912d11ab9059f8165c25a161634bb9b5e97 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 16 六月 2026 09:45:33 +0800
Subject: [PATCH] proapp 1.工作台分类修改
---
src/pages/humanResources/attendance/checkin.vue | 223 +++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 191 insertions(+), 32 deletions(-)
diff --git a/src/pages/humanResources/attendance/checkin.vue b/src/pages/humanResources/attendance/checkin.vue
index a9856f4..ab93ed9 100644
--- a/src/pages/humanResources/attendance/checkin.vue
+++ b/src/pages/humanResources/attendance/checkin.vue
@@ -14,14 +14,14 @@
<u-icon name="calendar"
color="#348fe2"
size="16"></u-icon>
- <text class="shift-text">鐧界彮: {{ workTimeDict.startAt }}-{{ workTimeDict.endAt }}</text>
+ <text class="shift-text">{{ todayRecord.shift || '-' }}: {{ todayRecord.startAt }}-{{ todayRecord.endAt }}</text>
</view>
</view>
<!-- 鎵撳崱鎸夐挳 -->
<view class="checkin-button-container">
<view class="checkin-button-wrapper">
<view class="checkin-button"
- :class="{ 'disabled': todayRecord.workEndAt }"
+ :class="{ 'disabled': todayRecord.workEndAt || noNeedCheckIn }"
@click="handleCheckInOut">
<text class="checkin-button-text">{{ checkInOutText }}</text>
<text class="checkin-time">{{ nowTime.split(' ')[1] }}</text>
@@ -106,14 +106,17 @@
const todayRecord = ref({});
// 鐝淇℃伅
- const workTimeDict = ref({
- startAt: "09:00",
- endAt: "18:00",
- });
+ const workTimeDict = ref();
// 褰撳墠鏃堕棿灞曠ず
const nowTime = ref("");
let timer = null;
+
+ // 涓婃鎵撳崱鏃堕棿
+ const lastCheckInTime = ref(null);
+
+ // 鎵撳崱鍐峰嵈鏃堕棿锛堟绉掞級
+ const CHECKIN_COOLDOWN = 5000;
// 杩斿洖涓婁竴椤�
const goBack = () => {
uni.navigateBack();
@@ -121,12 +124,29 @@
// 鏌ヨ浠婃棩鎵撳崱淇℃伅
const fetchTodayData = () => {
findTodayPersonalAttendanceRecord({}).then(res => {
- todayRecord.value = res.data;
+ if (res.data) {
+ todayRecord.value = res.data;
+ // 妫�鏌tartAt鍜宔ndAt鏄惁涓虹┖锛屼负绌哄垯鏃犻渶鎵撳崱
+ if (!todayRecord.value.startAt || !todayRecord.value.endAt) {
+ noNeedCheckIn.value = true;
+ } else {
+ noNeedCheckIn.value = false;
+ }
+ updateInCheckRange();
+ } else {
+ // 椤甸潰鏄剧ず鈥滄棤闇�鎵撳崱鈥�
+ todayRecord.value = {};
+ noNeedCheckIn.value = true;
+ updateInCheckRange();
+ }
});
};
// 鎵撳崱鑼冨洿鐘舵��
const inCheckRange = ref(true);
+
+ // 鏄惁鏃犻渶鎵撳崱
+ const noNeedCheckIn = ref(false);
// 褰撳墠浣嶇疆
const currentLocation = ref(null);
@@ -140,18 +160,104 @@
const m = String(now.getMinutes()).padStart(2, "0");
const s = String(now.getSeconds()).padStart(2, "0");
nowTime.value = `${Y}-${M}-${D} ${h}:${m}:${s}`;
+ updateInCheckRange();
};
// 浠婃棩鏃ユ湡
const todayStr = computed(() => nowTime.value.slice(0, 10));
+ const parseHmToMinutes = hm => {
+ if (!hm || typeof hm !== "string") return null;
+ const [hStr, mStr] = hm.split(":");
+ const h = Number(hStr);
+ const m = Number(mStr);
+ if (!Number.isFinite(h) || !Number.isFinite(m)) return null;
+ if (h < 0 || h > 23 || m < 0 || m > 59) return null;
+ return h * 60 + m;
+ };
+
+ const parseYmdToDate = ymd => {
+ if (!ymd || typeof ymd !== "string") return null;
+ const [yStr, mStr, dStr] = ymd.slice(0, 10).split("-");
+ const y = Number(yStr);
+ const m = Number(mStr);
+ const d = Number(dStr);
+ if (!Number.isFinite(y) || !Number.isFinite(m) || !Number.isFinite(d)) {
+ return null;
+ }
+ return new Date(y, m - 1, d, 0, 0, 0, 0);
+ };
+
+ const addMinutes = (date, minutes) => {
+ return new Date(date.getTime() + minutes * 60 * 1000);
+ };
+
+ const buildShiftWindow = () => {
+ const startAtMinutes = parseHmToMinutes(todayRecord.value?.startAt);
+ const endAtMinutes = parseHmToMinutes(todayRecord.value?.endAt);
+ if (startAtMinutes === null || endAtMinutes === null) return null;
+
+ const baseYmd = todayRecord.value?.date
+ ? String(todayRecord.value.date).slice(0, 10)
+ : todayStr.value;
+ const baseDate = parseYmdToDate(baseYmd);
+ if (!baseDate) return null;
+
+ const startDateTime = addMinutes(baseDate, startAtMinutes);
+ const crossDay = startAtMinutes > endAtMinutes;
+ const endBase = crossDay ? addMinutes(baseDate, 24 * 60) : baseDate;
+ const endDateTime = addMinutes(endBase, endAtMinutes);
+
+ return { startDateTime, endDateTime };
+ };
+
+ const updateInCheckRange = () => {
+ if (noNeedCheckIn.value) {
+ inCheckRange.value = true;
+ return;
+ }
+ const window = buildShiftWindow();
+ if (!window) {
+ inCheckRange.value = true;
+ return;
+ }
+ const now = new Date();
+ const checkInEarlyMinutes = 120;
+ const checkOutLateMinutes = 720;
+ const needAction = (() => {
+ if (todayRecord.value?.workEndAt) return "done";
+ if (todayRecord.value?.workStartAt) return "checkOut";
+ const distToStart = Math.abs(
+ now.getTime() - window.startDateTime.getTime()
+ );
+ const distToEnd = Math.abs(now.getTime() - window.endDateTime.getTime());
+ return distToEnd < distToStart ? "checkOut" : "checkIn";
+ })();
+ const start = addMinutes(window.startDateTime, -checkInEarlyMinutes);
+ const end = addMinutes(
+ window.endDateTime,
+ needAction === "checkOut" ? checkOutLateMinutes : 0
+ );
+ inCheckRange.value = now >= start && now <= end;
+ };
+
// 鎵撳崱鎸夐挳鏂囨湰
const checkInOutText = computed(() => {
- if (!todayRecord.value || !todayRecord.value.workStartAt) {
- return "涓婄彮鎵撳崱";
+ if (noNeedCheckIn.value) {
+ return "鏃犻渶鎵撳崱";
}
if (!todayRecord.value.workEndAt) {
- return "涓嬬彮鎵撳崱";
+ if (todayRecord.value.workStartAt) {
+ return "涓嬬彮鎵撳崱";
+ }
+ const window = buildShiftWindow();
+ if (!window) return "涓婄彮鎵撳崱";
+ const now = new Date();
+ const distToStart = Math.abs(
+ now.getTime() - window.startDateTime.getTime()
+ );
+ const distToEnd = Math.abs(now.getTime() - window.endDateTime.getTime());
+ return distToEnd < distToStart ? "涓嬬彮鎵撳崱" : "涓婄彮鎵撳崱";
}
return "宸叉墦鍗�";
});
@@ -217,26 +323,52 @@
// #endif
});
};
+ const form = ref({
+ longitude: "",
+ latitude: "",
+ });
- // 鑾峰彇褰撳墠浣嶇疆
const getCurrentLocation = () => {
- return new Promise((resolve, reject) => {
- uni.getLocation({
- type: "wgs84",
- success: res => {
- currentLocation.value = res;
- // 妯℃嫙妫�鏌ユ槸鍚﹀湪鎵撳崱鑼冨洿鍐咃紙瀹為檯椤圭洰涓簲鏍规嵁鍏徃浣嶇疆鍜屽厑璁哥殑鍗婂緞杩涜璁$畻锛�
- // 杩欓噷绠�鍗曟ā鎷熶负濮嬬粓鍦ㄨ寖鍥村唴
- inCheckRange.value = true;
- resolve(res);
- },
- fail: err => {
- console.error("鑾峰彇浣嶇疆澶辫触:", err);
- // 澶辫触鏃堕粯璁ゅ厑璁告墦鍗★紙瀹為檯椤圭洰涓簲鏍规嵁涓氬姟闇�姹傚鐞嗭級
- inCheckRange.value = true;
- reject(err);
- },
- });
+ uni.showLoading({ title: "鑾峰彇浣嶇疆涓�..." });
+
+ uni.getLocation({
+ type: "gcj02",
+ success: res => {
+ uni.hideLoading();
+ form.value.latitude = res.latitude;
+ form.value.longitude = res.longitude;
+ },
+ fail: err => {
+ uni.hideLoading();
+ console.error("鑾峰彇浣嶇疆澶辫触:", err);
+
+ // 鏄剧ず閿欒鎻愮ず骞跺紩瀵肩敤鎴锋鏌ユ潈闄�
+ showToast("鑾峰彇浣嶇疆澶辫触锛岃妫�鏌ュ畾浣嶆潈闄�");
+
+ // 寮曞鐢ㄦ埛妫�鏌ユ潈闄愯缃�
+ uni.showModal({
+ title: "浣嶇疆鏉冮檺鎻愮ず",
+ content:
+ "鑾峰彇浣嶇疆澶辫触锛屽彲鑳芥槸鍥犱负浣嶇疆鏉冮檺鏈紑鍚紝璇峰湪璁惧璁剧疆涓鏌ュ苟寮�鍚綅缃潈闄愩��",
+ confirmText: "鐭ラ亾浜�",
+ cancelText: "鍙栨秷",
+ success: res => {
+ if (res.confirm) {
+ // 鍙互灏濊瘯鎵撳紑璁剧疆椤甸潰锛堝鏋滄敮鎸侊級
+ if (uni.openSetting) {
+ uni.openSetting({
+ success: settingRes => {
+ console.log("璁剧疆缁撴灉:", settingRes);
+ },
+ });
+ }
+ }
+ },
+ });
+
+ // 澶辫触鏃舵樉绀洪敊璇俊鎭�
+ form.value.visitAddress = "浣嶇疆鑾峰彇澶辫触";
+ },
});
};
@@ -259,6 +391,14 @@
// 鎵撳崱閫昏緫
const handleCheckInOut = async () => {
+ if (noNeedCheckIn.value) {
+ uni.showToast({
+ title: "浠婃棩鏃犻渶鎵撳崱",
+ icon: "none",
+ });
+ return;
+ }
+
if (todayRecord.value.workEndAt) {
uni.showToast({
title: "鎮ㄥ凡缁忔墦杩囧崱浜�,鏃犻渶閲嶅鎵撳崱!!!",
@@ -266,6 +406,21 @@
});
return;
}
+
+ // 妫�鏌ユ槸鍚﹀湪鎵撳崱鍐峰嵈鏃堕棿鍐�
+ if (lastCheckInTime.value) {
+ const currentTime = Date.now();
+ const timeDiff = currentTime - lastCheckInTime.value;
+ if (timeDiff < CHECKIN_COOLDOWN) {
+ const remainingTime = Math.ceil((CHECKIN_COOLDOWN - timeDiff) / 1000);
+ uni.showToast({
+ title: `璇�${remainingTime}绉掑悗鍐嶈瘯`,
+ icon: "none",
+ });
+ return;
+ }
+ }
+
// 妫�鏌ユ槸鍚﹀湪鎵撳崱鑼冨洿鍐�
if (!inCheckRange.value) {
uni.showToast({
@@ -276,8 +431,13 @@
}
// 璋冪敤鎵撳崱API
- createPersonalAttendanceRecord({})
+ createPersonalAttendanceRecord({
+ ...form.value,
+ })
.then(res => {
+ // 璁板綍鎵撳崱鏃堕棿
+ lastCheckInTime.value = Date.now();
+
uni.showToast({
title: "鎵撳崱鎴愬姛锛�",
icon: "success",
@@ -286,7 +446,6 @@
fetchTodayData();
})
.catch(error => {
- console.error("鎵撳崱澶辫触:", error);
uni.showToast({
title: error.msg || "鎵撳崱澶辫触锛岃閲嶈瘯",
icon: "none",
@@ -302,7 +461,7 @@
// 鑾峰彇浣嶇疆鏉冮檺骞舵鏌ヤ綅缃�
try {
- await getLocationPermission();
+ // await getLocationPermission();
await getCurrentLocation();
} catch (error) {
console.error("浣嶇疆鏉冮檺鑾峰彇澶辫触:", error);
@@ -725,4 +884,4 @@
.attendance-records {
animation-delay: 0.2s;
}
-</style>
\ No newline at end of file
+</style>
--
Gitblit v1.9.3