zhangwencui
7 天以前 6739faebc8bac0aa168a6f61573466b1c80bbecd
src/pages/humanResources/attendance/checkin.vue
@@ -132,10 +132,12 @@
        } else {
          noNeedCheckIn.value = false;
        }
        updateInCheckRange();
      } else {
        // 页面显示“无需打卡”
        todayRecord.value = {};
        noNeedCheckIn.value = true;
        updateInCheckRange();
      }
    });
  };
@@ -158,21 +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 (noNeedCheckIn.value) {
      return "无需打卡";
    }
    if (!todayRecord.value || !todayRecord.value.workStartAt) {
      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 "已打卡";
  });
@@ -799,4 +884,4 @@
  .attendance-records {
    animation-delay: 0.2s;
  }
</style>
</style>