修改打卡

This commit is contained in:
13684185576
2025-11-07 17:38:16 +08:00
parent b6dc821182
commit b08b634fe3
2 changed files with 38 additions and 84 deletions

View File

@ -8,7 +8,13 @@ export function fetchPatrolList(params) {
params params
}) })
} }
// 获取巡逻详情
export function selectByBBdId(params) {
return service({
url: `${api}/tbZdxlFgxlrw/selectByBBdId`,
params
})
}
export function fetchSelectListByBddxlrwId(params) { export function fetchSelectListByBddxlrwId(params) {
return service({ return service({

View File

@ -12,7 +12,7 @@ import {
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import Timeline from "@/pages/clockInPage/components/Timeline.vue"; import Timeline from "@/pages/clockInPage/components/Timeline.vue";
import { import {
fetchPatrolList, selectByBBdId,
fetchSelectByBddxlrwId, fetchSelectByBddxlrwId,
fetchSelectListByBddxlrwId, fetchSelectListByBddxlrwId,
fetchTbZdxlFgdwBddxlrwJlClockIn, fetchTbZdxlFgdwBddxlrwJlClockIn,
@ -29,27 +29,23 @@ const nextStep = ref(0);
const baseUrl = ref(""); const baseUrl = ref("");
const fileId = ref(""); const fileId = ref("");
const startTime = ref("2025-09-18 18:15:00"); const startTime = ref("2025-09-18 18:15:00");
const useCountdownFromTime = (minutes = 10) => { const useCountdownFromTime = () => {
const timeLeft = ref(0); // 剩余毫秒数 const timeLeft = ref(0); // 剩余毫秒数
const timer = ref(null); const timer = ref(null);
const isRunning = ref(false); // 是否运行中 const isRunning = ref(false); // 是否运行中
const isExpired = ref(false); // 是否过期 const isExpired = ref(false); // 是否过期
const expirationTime = ref(null); // 过期时间 const expirationTime = ref(null); // 过期时间
// 计算过期时间 // 计算过期时间
const calculateExpirationTime = (time) => { const calculateExpirationTime = (time, minutes = 10) => {
if (!time) return null; if (!time) return null;
try { try {
const startDate = new Date(time); const startDate = new Date(time);
if (isNaN(startDate.getTime())) return null; if (isNaN(startDate.getTime())) return null;
return new Date(startDate.getTime() + minutes * 60000); return new Date(startDate.getTime() + minutes * 60000);
} catch { } catch {
return null; return null;
} }
}; };
// 更新倒计时 // 更新倒计时
const update = () => { const update = () => {
if (!expirationTime.value) { if (!expirationTime.value) {
@ -57,10 +53,8 @@ const useCountdownFromTime = (minutes = 10) => {
isRunning.value = false; isRunning.value = false;
return; return;
} }
const now = new Date(); const now = new Date();
timeLeft.value = expirationTime.value - now; timeLeft.value = expirationTime.value - now;
if (timeLeft.value <= 0) { if (timeLeft.value <= 0) {
timeLeft.value = 0; timeLeft.value = 0;
isExpired.value = true; isExpired.value = true;
@ -68,27 +62,23 @@ const useCountdownFromTime = (minutes = 10) => {
stop(); stop();
return; return;
} }
if (timeLeft.value > 0) { if (timeLeft.value > 0) {
timer.value = setTimeout(update, 1000); timer.value = setTimeout(update, 1000);
} }
}; };
// 开始倒计时 // 开始倒计时
const start = (startTime) => { const start = (startTime, minutes) => {
stop(); stop();
expirationTime.value = calculateExpirationTime(startTime); expirationTime.value = calculateExpirationTime(startTime, minutes);
if (!expirationTime.value) { if (!expirationTime.value) {
isExpired.value = true; isExpired.value = true;
return; return;
} }
isRunning.value = true; isRunning.value = true;
isExpired.value = false; isExpired.value = false;
update(); update();
}; };
// 停止倒计时 // 停止倒计时
const stop = () => { const stop = () => {
if (timer.value) { if (timer.value) {
@ -97,34 +87,27 @@ const useCountdownFromTime = (minutes = 10) => {
} }
isRunning.value = false; isRunning.value = false;
}; };
// 格式化时间显示 // 格式化时间显示
const formattedTime = computed(() => { const formattedTime = computed(() => {
if (timeLeft.value <= 0) return "00:00"; if (timeLeft.value <= 0) return '00:00';
const totalSeconds = Math.floor(timeLeft.value / 1000); const totalSeconds = Math.floor(timeLeft.value / 1000);
const mins = Math.floor(totalSeconds / 60); const mins = Math.floor(totalSeconds / 60);
const secs = totalSeconds % 60; const secs = totalSeconds % 60;
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
return `${mins.toString().padStart(2, "0")}:${secs
.toString()
.padStart(2, "0")}`;
}); });
// 过期时间显示 // 过期时间显示
const expirationTimeFormatted = computed(() => { const expirationTimeFormatted = computed(() => {
if (!expirationTime.value) return ""; if (!expirationTime.value) return '';
return expirationTime.value.toLocaleTimeString("zh-CN", { return expirationTime.value.toLocaleTimeString('zh-CN', {
hour: "2-digit", hour: '2-digit',
minute: "2-digit", minute: '2-digit',
second: "2-digit", second: '2-digit',
hour12: false, hour12: false
}); });
}); });
// 自动清理 // 自动清理
onUnmounted(stop); onUnmounted(stop);
return { return {
timeLeft, timeLeft,
formattedTime, formattedTime,
@ -132,7 +115,7 @@ const useCountdownFromTime = (minutes = 10) => {
isRunning, isRunning,
isExpired, isExpired,
start, start,
stop, stop
}; };
}; };
@ -190,17 +173,16 @@ const onChange = (value) => {
nextStep.value = 0; nextStep.value = 0;
baseUrl.value = ""; baseUrl.value = "";
fileId.value = ""; fileId.value = "";
getPatrolList(data?.query); getData();
}; };
const handleNext = (index) => { const handleNext = (index) => {
stop(); stop();
nextStep.value = index; nextStep.value = index;
start(infoData?.value?.dkKsSj); start(infoData?.value?.dkKsSj,activeInfoData.value.dkjgsj);
}; };
function setimage_base64(pzid, base64) { function setimage_base64(pzid, base64) {
console.log(base64, "base64");
baseUrl.value = `data:image/jpeg;base64,${base64}`; baseUrl.value = `data:image/jpeg;base64,${base64}`;
qcckPost({ base64: base64 }, "/mosty-base/minio/image/upload/base64").then( qcckPost({ base64: base64 }, "/mosty-base/minio/image/upload/base64").then(
(res) => { (res) => {
@ -210,7 +192,6 @@ function setimage_base64(pzid, base64) {
} }
const imageCache = new Map(); const imageCache = new Map();
const getImageUrl = async (fileId) => { const getImageUrl = async (fileId) => {
if (!fileId) return null; if (!fileId) return null;
// 检查缓存 // 检查缓存
@ -235,7 +216,7 @@ const getImageUrl = async (fileId) => {
const getData = async () => { const getData = async () => {
try { try {
const res = await fetchSelectListByBddxlrwId({ const res = await fetchSelectListByBddxlrwId({
bddxlrwId: activeInfoData?.value?.id || "", bddxlrwId: activeInfoData.value.id || "",
}); });
if (res && res?.length > 0) { if (res && res?.length > 0) {
// 获取所有唯一的图片ID // 获取所有唯一的图片ID
@ -290,7 +271,7 @@ const getData = async () => {
const firstItem = data.info[nextStep.value || 0]; const firstItem = data.info[nextStep.value || 0];
if (firstItem?.dkKsSj) { if (firstItem?.dkKsSj) {
startTime.value = infoData?.value?.dkKsSj; startTime.value = infoData?.value?.dkKsSj;
start(startTime.value); start(startTime.value,activeInfoData.value.dkjgsj);
} else { } else {
start(""); start("");
} }
@ -336,11 +317,11 @@ function getUserLocation(sfdw) {
} }
} }
const getPatrolList = async ({ current, id }) => { const getPatrolList = async ({ id }) => {
const res = await fetchPatrolList({ pageCurrent: current, pageSize: 10 }); const res = await selectByBBdId({ bbdId: id });
if (res?.records.length > 0) { if (res) {
getUserLocation(); getUserLocation();
data.patroObj = res?.records?.find((item) => item.id === id) || {}; data.patroObj = res;
// 删除方格 // 删除方格
emitter.emit("deletePointArea", "zdxl_fzyc"); emitter.emit("deletePointArea", "zdxl_fzyc");
// 生成方格 // 生成方格
@ -370,12 +351,9 @@ const getPatrolList = async ({ current, id }) => {
// 简单的时间加法函数 // 简单的时间加法函数
const addTenMinutes = (timeString) => { const addTenMinutes = (timeString) => {
if (!timeString) return ""; if (!timeString) return "";
const date = new Date(timeString); const date = new Date(timeString);
if (isNaN(date.getTime())) return ""; if (isNaN(date.getTime())) return "";
date.setMinutes(date.getMinutes() + 10); date.setMinutes(date.getMinutes() + 10);
return date return date
.toLocaleString("zh-CN", { .toLocaleString("zh-CN", {
year: "numeric", year: "numeric",
@ -392,15 +370,12 @@ const addTenMinutes = (timeString) => {
// 判断是否超过10分钟 // 判断是否超过10分钟
const isTenMinutesPassed = (startTime) => { const isTenMinutesPassed = (startTime) => {
if (!startTime) return false; if (!startTime) return false;
try { try {
const startDate = new Date(startTime); const startDate = new Date(startTime);
if (isNaN(startDate.getTime())) return false; if (isNaN(startDate.getTime())) return false;
// 计算10分钟后的时间 // 计算10分钟后的时间
const tenMinutesLater = new Date(startDate.getTime() + 10 * 60 * 1000); const tenMinutesLater = new Date(startDate.getTime() + 10 * 60 * 1000);
const now = new Date(); const now = new Date();
// 判断当前时间是否超过10分钟后 // 判断当前时间是否超过10分钟后
return now > tenMinutesLater; return now > tenMinutesLater;
} catch (error) { } catch (error) {
@ -416,18 +391,15 @@ const handleClick = async () => {
return; return;
} }
const { id } = data.info?.[nextStep.value]; const { id } = data.info?.[nextStep.value];
if (!isTenMinutesPassed(infoData?.value.dkKsSj) && infoData?.value.dkKsSj) { if (!isTenMinutesPassed(infoData?.value.dkKsSj) && infoData?.value.dkKsSj) {
const newTime = addTenMinutes(infoData?.value.dkKsSj); const newTime = addTenMinutes(infoData?.value.dkKsSj);
hintToast(`请于${newTime.split(" ")[1]}后打卡`); hintToast(`请于${newTime.split(" ")[1]}后打卡`);
return; return;
} }
if (fileId.value === "") { if (fileId.value === "") {
hintToast("请拍照再打卡"); hintToast("请拍照再打卡");
return; return;
} }
const { lng, lat } = getLocation(); const { lng, lat } = getLocation();
try { try {
const res = await fetchTbZdxlFgdwBddxlrwJlClockIn({ const res = await fetchTbZdxlFgdwBddxlrwJlClockIn({
@ -456,7 +428,6 @@ onMounted(() => {
data.query = route?.query; data.query = route?.query;
getPatrolList(route?.query); getPatrolList(route?.query);
} }
window.setimagebase64 = setimage_base64; window.setimagebase64 = setimage_base64;
}); });
</script> </script>
@ -473,10 +444,7 @@ onMounted(() => {
<div class="clockInList"> <div class="clockInList">
<template v-for="(item, index) in data.info" :key="index"> <template v-for="(item, index) in data.info" :key="index">
<div <div :class="['clockInList_item', { active: nextStep === index }]" @click="handleNext(index)">
:class="['clockInList_item', { active: nextStep === index }]"
@click="handleNext(index)"
>
<div class="label">{{ `${item?.count}次打卡` }}</div> <div class="label">{{ `${item?.count}次打卡` }}</div>
<div class="dec"> <div class="dec">
<van-icon v-if="item?.dkKsSj" name="checked" color="#007DE9" /> <van-icon v-if="item?.dkKsSj" name="checked" color="#007DE9" />
@ -498,18 +466,8 @@ onMounted(() => {
<div class="upload_box"> <div class="upload_box">
<div class="image_box" v-if="baseUrl"> <div class="image_box" v-if="baseUrl">
<van-icon <van-icon name="close" class="close_icon" @click="clearImage" color="#000" size="24px" />
name="close" <van-image :src="baseUrl" @click="onClickImg(baseUrl)" style="flex: 1">
class="close_icon"
@click="clearImage"
color="#000"
size="24px"
/>
<van-image
:src="baseUrl"
@click="onClickImg(baseUrl)"
style="flex: 1"
>
<template v-slot:loading> <template v-slot:loading>
<van-loading type="spinner" size="20" /> <van-loading type="spinner" size="20" />
</template> </template>
@ -527,29 +485,17 @@ onMounted(() => {
</div> </div>
<div class="clockWrapper"> <div class="clockWrapper">
<div <div v-if="!infoData?.dkJsSj || !infoData?.dkKsSj" class="circleWrapper" :class="{
v-if="!infoData?.dkJsSj || !infoData?.dkKsSj" disabled: (!isExpired && expirationTime) || infoData?.dkJsSj,
class="circleWrapper" }" @click="handleClick">
:class="{
disabled: (!isExpired && expirationTime) || infoData?.dkJsSj,
}"
@click="handleClick"
>
<div v-if="!isExpired && expirationTime" class="time"> <div v-if="!isExpired && expirationTime" class="time">
{{ formattedTime }} {{ formattedTime }}
</div> </div>
<div class="title">{{ !infoData?.dkKsSj ? `开始` : `离开` }}</div> <div class="title">{{ !infoData?.dkKsSj ? `开始` : `离开` }}</div>
<div class="info">{{ `${infoData?.count || ""}次打卡` }}</div> <div class="info">{{ `${infoData?.count || ""}次打卡` }}</div>
</div> </div>
<div <div v-else class="circleWrapper" :class="{ disabled: (!isExpired && expirationTime) || infoData?.dkJsSj,}">
v-else
class="circleWrapper"
:class="{
disabled: (!isExpired && expirationTime) || infoData?.dkJsSj,
}"
>
<div class="title">已结束</div> <div class="title">已结束</div>
<!-- <div class="info">{{ `${infoData?.count || ''}次打卡` }}</div>-->
</div> </div>
<div class="circleWrapperTip"> <div class="circleWrapperTip">
<van-icon name="success" color="#FFFFFF" /> <van-icon name="success" color="#FFFFFF" />
@ -713,6 +659,7 @@ onMounted(() => {
.van-icon-checked { .van-icon-checked {
margin-right: 1.33vw; margin-right: 1.33vw;
} }
.time { .time {
margin-left: 1.33vw; margin-left: 1.33vw;
} }
@ -728,6 +675,7 @@ onMounted(() => {
.van-tabs__nav { .van-tabs__nav {
flex-wrap: wrap; flex-wrap: wrap;
} }
.van-tabs__nav--line { .van-tabs__nav--line {
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }