This commit is contained in:
13684185576
2025-11-05 09:33:38 +08:00
parent aed0ed60ba
commit 5c7efdd1e8
6 changed files with 362 additions and 231 deletions

View File

@ -1,28 +1,41 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang=""> <html lang="">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<!-- <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" /> --> <!-- <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" /> -->
<title><%= htmlWebpackPlugin.options.title %></title> <title><%= htmlWebpackPlugin.options.title %></title>
<!-- 线上地图 --> <!-- 线上地图 -->
<script type="text/javascript" src="./EzMapFile/EzMapAPI.js"></script> <script type="text/javascript" src="./EzMapFile/EzMapAPI.js"></script>
<script type="text/javascript" src="./EzMapFile/EzServerClient.min.js"></script> <script
type="text/javascript"
src="./EzMapFile/EzServerClient.min.js"
></script>
<script type="text/javascript" src="./android.js"></script> <script type="text/javascript" src="./android.js"></script>
<script type="text/javascript" src="./js/recorder.js"></script> <script type="text/javascript" src="./js/recorder.js"></script>
<link rel="stylesheet" href="./EzMapFile/EzServerClient.min.css"> <link rel="stylesheet" href="./EzMapFile/EzServerClient.min.css" />
<!-- EzMap地图引入 --> <!-- EzMap地图引入 -->
<script type="text/javascript" src="./pgis/eliMapboxgl.min.js"></script> <script type="text/javascript" src="./pgis/eliMapboxgl.min.js"></script>
<!-- <script src="https://webapi.amap.com/maps?v=2.0&key=28161d95613f4bbf837d280529855a9d"></script> --> <!-- <script src="https://webapi.amap.com/maps?v=2.0&key=28161d95613f4bbf837d280529855a9d"></script> -->
</head> </head>
<body> <body>
<noscript> <noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> <strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript> </noscript>
<div id="app"></div> <div id="app"></div>
<!-- built files will be auto injected --> <!-- built files will be auto injected -->

View File

@ -1,22 +1,31 @@
<template> <template>
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<Component :is="Component"></Component> <Component :is="Component"></Component>
<van-popup v-model:show="showAlert" closeable :close-on-click-overlay="false" close-icon-position="top-right" <van-popup
position="bottom" @close="closePopup"> v-model:show="showAlert"
closeable
:close-on-click-overlay="false"
close-icon-position="top-right"
position="bottom"
@close="closePopup"
>
<div class="alert-content"> <div class="alert-content">
<div class="alert-cnt"> <div class="alert-cnt">
<van-icon name="warning-o" color="orange"></van-icon> {{ message }} <van-icon name="warning-o" color="orange"></van-icon> {{ message }}
</div> </div>
<div class="foot-btn"> <div class="foot-btn">
<van-button round block type="primary" @click="okUpdate"> 确定更新 </van-button> <van-button round block type="primary" @click="okUpdate">
确定更新
</van-button>
</div> </div>
</div> </div>
</van-popup> </van-popup>
</router-view> </router-view>
<GdMap />
</template> </template>
<script setup> <script setup>
import GdMap from "./components/GdMap/index.vue";
import watermark from "./utils/watermark.js"; import watermark from "./utils/watermark.js";
import emitter from "./utils/eventBus.js"; import emitter from "./utils/eventBus.js";
import { onMounted, onUnmounted, ref, watch, reactive } from "vue"; import { onMounted, onUnmounted, ref, watch, reactive } from "vue";
@ -24,6 +33,7 @@ import { getMyTaskList, getMyTaskTotal } from "./api/rwzx.js";
import { updateDate } from "./api/checkponit.js"; import { updateDate } from "./api/checkponit.js";
import { getDistance, hintToast, timeValidate } from "./utils/tools"; import { getDistance, hintToast, timeValidate } from "./utils/tools";
import { getAPPLocation } from "./api/spsApi"; import { getAPPLocation } from "./api/spsApi";
import { qcckPost, qcckGet } from "@/api/qcckApi";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import router from "./router/index.js"; import router from "./router/index.js";
import store from "./store"; import store from "./store";
@ -76,6 +86,10 @@ watch(
); );
onMounted(() => { onMounted(() => {
getLocation(); //获取经纬度
setInterval(() => {
getLocation(); //获取经纬度
}, 10000);
//默认设置用户主题色 //默认设置用户主题色
if (!getStorage("themeSetting")) { if (!getStorage("themeSetting")) {
setStorage("themeSetting", "light"); setStorage("themeSetting", "light");
@ -88,9 +102,31 @@ onMounted(() => {
setAttribute(res); // 应用主题 setAttribute(res); // 应用主题
}); });
}); });
const getLocation = () => {
if ("geolocation" in navigator) {
console.log(navigator.geolocation, "navigator.geolocation");
navigator.geolocation.getCurrentPosition(
(pos) => {
console.log(pos.coords, "pos");
if (pos.coords) {
var latitude = pos.coords.latitude;
var longitude = pos.coords.longitude;
qcckPost(
{ jd: longitude, wd: latitude, bbid: "" },
"/mosty-qwzx/tbQwXfbb/updateBbJzwz"
).then((res) => {
console.log(res, "res");
});
}
},
(err) => {
console.log(err, "err");
}
);
} else {
console.log("Geolocation is not supported by this browser.");
}
};
// 关闭提示 // 关闭提示
function closePopup() { function closePopup() {

View File

@ -1,13 +1,21 @@
<script setup> <script setup>
import TopNav from "@/components/topNav.vue"; import TopNav from "@/components/topNav.vue";
import {onMounted, reactive, ref, computed, nextTick, onUnmounted, watch} from "vue"; import {
onMounted,
reactive,
ref,
computed,
nextTick,
onUnmounted,
watch,
} from "vue";
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, fetchPatrolList,
fetchSelectByBddxlrwId, fetchSelectByBddxlrwId,
fetchSelectListByBddxlrwId, fetchSelectListByBddxlrwId,
fetchTbZdxlFgdwBddxlrwJlClockIn fetchTbZdxlFgdwBddxlrwJlClockIn,
} from "@/api/patrolList"; } from "@/api/patrolList";
import { getBase64, hintToast } from "@/utils/tools"; import { getBase64, hintToast } from "@/utils/tools";
import { ImagePreview } from "vant"; import { ImagePreview } from "vant";
@ -16,14 +24,11 @@ import MapWrapper from "@/pages/clockInPage/components/mapWrapper.vue";
import emitter from "@/utils/eventBus"; import emitter from "@/utils/eventBus";
const route = useRoute(); const route = useRoute();
const active = ref(0) const active = ref(0);
const nextStep = ref(0) 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 = (minutes = 10) => {
const timeLeft = ref(0); // 剩余毫秒数 const timeLeft = ref(0); // 剩余毫秒数
const timer = ref(null); const timer = ref(null);
@ -95,23 +100,25 @@ const useCountdownFromTime = (minutes = 10) => {
// 格式化时间显示 // 格式化时间显示
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,
}); });
}); });
@ -125,55 +132,53 @@ const useCountdownFromTime = (minutes = 10) => {
isRunning, isRunning,
isExpired, isExpired,
start, start,
stop stop,
}; };
}; };
const data = reactive({ const data = reactive({
patroObj: {}, patroObj: {},
info: [], info: [],
query: {} query: {},
}) });
const infoData = computed(() => { const infoData = computed(() => {
return data.info?.[nextStep.value] return data.info?.[nextStep.value];
}) });
const activeInfoData = computed(() => data.patroObj?.bddList?.[active.value]);
const activeInfoData = computed(() => data.patroObj?.bddList?.[active.value]) const { formattedTime, isExpired, expirationTime, start, stop } =
useCountdownFromTime(10);
const { formattedTime, isExpired, expirationTime, start, stop } = useCountdownFromTime(10);
// 删除打卡图片 // 删除打卡图片
const clearImage = () => { const clearImage = () => {
baseUrl.value = "" baseUrl.value = "";
} };
// 浏览图片 // 浏览图片
const onClickImg = (url) => { const onClickImg = (url) => {
ImagePreview([url]) ImagePreview([url]);
} };
// 点击上传 // 点击上传
const photoFn = () => { const photoFn = () => {
try { try {
bridge.pZ("photo"); bridge.pZ("photo");
} catch (err) { } catch (err) {
console.log(err, 'err'); console.log(err, "err");
}
} }
};
// 支持更大数字的转换 // 支持更大数字的转换
const getChineseNumber = (num) => { const getChineseNumber = (num) => {
const numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']; const numbers = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"];
if (num <= 10) { if (num <= 10) {
return numbers[num - 1]; return numbers[num - 1];
} else if (num <= 19) { } else if (num <= 19) {
return `${numbers[num - 11] || ''}`; return `${numbers[num - 11] || ""}`;
} else if (num <= 99) { } else if (num <= 99) {
const tens = Math.floor(num / 10); const tens = Math.floor(num / 10);
const units = num % 10; const units = num % 10;
return `${numbers[tens - 1]}${units > 0 ? numbers[units - 1] : ''}`; return `${numbers[tens - 1]}${units > 0 ? numbers[units - 1] : ""}`;
} else { } else {
return num.toString(); // 超过99返回阿拉伯数字 return num.toString(); // 超过99返回阿拉伯数字
} }
@ -181,34 +186,34 @@ const getChineseNumber = (num) => {
const onChange = (value) => { const onChange = (value) => {
active.value = value; active.value = value;
nextStep.value = 0 nextStep.value = 0;
getPatrolList(data?.query) getPatrolList(data?.query);
} };
const handleNext = (index) => { const handleNext = (index) => {
stop() stop();
nextStep.value = index; nextStep.value = index;
start(infoData?.value?.dkKsSj); start(infoData?.value?.dkKsSj);
} };
function setimage_base64(pzid, base64) { function setimage_base64(pzid, base64) {
console.log(base64, '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(res => { qcckPost({ base64: base64 }, "/mosty-base/minio/image/upload/base64").then(
(res) => {
fileId.value = res; fileId.value = res;
}) }
);
} }
const imageCache = new Map(); const imageCache = new Map();
const getImageUrl = async (fileId) => { const getImageUrl = async (fileId) => {
if (!fileId) return null; if (!fileId) return null;
// 检查缓存 // 检查缓存
if (imageCache.has(fileId)) { if (imageCache.has(fileId)) {
return imageCache.get(fileId); return imageCache.get(fileId);
} }
try { try {
const res = await qcckGet({}, `/mosty-base/minio/file/download/${fileId}`); const res = await qcckGet({}, `/mosty-base/minio/file/download/${fileId}`);
if (res?.url) { if (res?.url) {
@ -219,23 +224,23 @@ const getImageUrl = async (fileId) => {
} }
return null; return null;
} catch (error) { } catch (error) {
console.warn('获取图片失败:', error); console.warn("获取图片失败:", error);
return null; return null;
} }
}; };
const getData = async () => { const getData = async () => {
try { try {
const res = await fetchSelectListByBddxlrwId({ bddxlrwId: activeInfoData?.value?.id || '' }); const res = await fetchSelectListByBddxlrwId({
bddxlrwId: activeInfoData?.value?.id || "",
});
if (res && res?.length > 0) { if (res && res?.length > 0) {
// 获取所有唯一的图片ID // 获取所有唯一的图片ID
const uniqueImageIds = new Set(); const uniqueImageIds = new Set();
res?.forEach(item => { res?.forEach((item) => {
if (item?.dkJsFj) uniqueImageIds.add(item.dkJsFj); if (item?.dkJsFj) uniqueImageIds.add(item.dkJsFj);
if (item?.dkKsFj) uniqueImageIds.add(item.dkKsFj); if (item?.dkKsFj) uniqueImageIds.add(item.dkKsFj);
}); });
// 批量获取图片URL // 批量获取图片URL
const imageEntries = await Promise.allSettled( const imageEntries = await Promise.allSettled(
Array.from(uniqueImageIds).map(async (id) => { Array.from(uniqueImageIds).map(async (id) => {
@ -250,8 +255,8 @@ const getData = async () => {
// 创建图片映射表 // 创建图片映射表
const imageMap = new Map(); const imageMap = new Map();
imageEntries.forEach(entry => { imageEntries.forEach((entry) => {
if (entry.status === 'fulfilled') { if (entry.status === "fulfilled") {
imageMap.set(entry.value.id, entry.value.url); imageMap.set(entry.value.id, entry.value.url);
} }
}); });
@ -265,9 +270,9 @@ const getData = async () => {
})); }));
// 打卡结束经纬度 // 打卡结束经纬度
const dkJs = res?.map(i => ({ jd: i?.dkJsJd, wd: i?.dkJsWd })) const dkJs = res?.map((i) => ({ jd: i?.dkJsJd, wd: i?.dkJsWd }));
// 打卡开始经纬度 // 打卡开始经纬度
const dkKs = res?.map(i => ({ jd: i?.dkKsJd, wd: i?.dkKsWd })) const dkKs = res?.map((i) => ({ jd: i?.dkKsJd, wd: i?.dkKsWd }));
// 删除标注 // 删除标注
emitter.emit("deletePointArea", "annotationDkKs"); emitter.emit("deletePointArea", "annotationDkKs");
@ -284,14 +289,16 @@ const getData = async () => {
startTime.value = infoData?.value?.dkKsSj; startTime.value = infoData?.value?.dkKsSj;
start(startTime.value); start(startTime.value);
} else { } else {
start(''); start("");
} }
}); });
} }
if (activeInfoData.value) {
const result = await fetchSelectByBddxlrwId(activeInfoData?.value?.id || "") const result = await fetchSelectByBddxlrwId(
activeInfoData?.value?.id || ""
);
if (result) { if (result) {
const { jd, wd } = result const { jd, wd } = result;
// 删除标注 // 删除标注
emitter.emit("deletePointArea", "checkPoint"); emitter.emit("deletePointArea", "checkPoint");
//地图撒点然后移动 //地图撒点然后移动
@ -301,7 +308,7 @@ const getData = async () => {
flag: "checkPoint", flag: "checkPoint",
}); });
} }
}
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
@ -319,7 +326,7 @@ function getUserLocation(sfdw) {
flag: "dw", flag: "dw",
sfdw: sfdw, sfdw: sfdw,
sizeX: 30, sizeX: 30,
sizeY: 35 sizeY: 35,
}); });
} else { } else {
hintToast("暂无坐标信息"); hintToast("暂无坐标信息");
@ -327,47 +334,56 @@ function getUserLocation(sfdw) {
} }
const getPatrolList = async ({ current, id }) => { const getPatrolList = async ({ current, id }) => {
const res = await fetchPatrolList({ pageCurrent: current, pageSize: 10 }) const res = await fetchPatrolList({ pageCurrent: current, pageSize: 10 });
if (res?.records.length > 0) { if (res?.records.length > 0) {
getUserLocation() getUserLocation();
data.patroObj = res?.records?.find((item) => item.id === id) || {}; data.patroObj = res?.records?.find((item) => item.id === id) || {};
// 删除方格 // 删除方格
emitter.emit("deletePointArea", "zdxl_fzyc") emitter.emit("deletePointArea", "zdxl_fzyc");
// 生成方格 // 生成方格
const { x1, y1, x2, y2, fgId, zxX, zxY, fgMc } = data.patroObj const { x1, y1, x2, y2, fgId, zxX, zxY, fgMc } = data.patroObj;
const centerPoint = [zxX, zxY] const centerPoint = [zxX, zxY];
const position = [[Number(x1),Number(y1)],[Number(x2),Number(y2)]] const position = [
const text = fgMc [Number(x1), Number(y1)],
const obj = [{ position: position, text, id: fgId, userData: activeInfoData?.value }] [Number(x2), Number(y2)],
];
emitter.emit("echoPlane", { fontColor:'#12fdb8',coords: obj, type:'rectangle', flag:'zdxl_fzyc', color:'rgba(2,20,51,0.5)', linecolor:'#1C97FF'}) const text = fgMc;
const obj = [
{ position: position, text, id: fgId, userData: activeInfoData?.value },
];
emitter.emit("echoPlane", {
fontColor: "#12fdb8",
coords: obj,
type: "rectangle",
flag: "zdxl_fzyc",
color: "rgba(2,20,51,0.5)",
linecolor: "#1C97FF",
});
emitter.emit("setMapCenter", { location: centerPoint, zoomLevel: 12 }); emitter.emit("setMapCenter", { location: centerPoint, zoomLevel: 12 });
await getData();
await getData()
}
} }
};
// 简单的时间加法函数 // 简单的时间加法函数
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.toLocaleString('zh-CN', { return date
year: 'numeric', .toLocaleString("zh-CN", {
month: '2-digit', year: "numeric",
day: '2-digit', month: "2-digit",
hour: '2-digit', day: "2-digit",
minute: '2-digit', hour: "2-digit",
second: '2-digit', minute: "2-digit",
hour12: false second: "2-digit",
}).replace(/\//g, '-'); hour12: false,
})
.replace(/\//g, "-");
}; };
// 判断是否超过10分钟 // 判断是否超过10分钟
@ -385,55 +401,59 @@ const isTenMinutesPassed = (startTime) => {
// 判断当前时间是否超过10分钟后 // 判断当前时间是否超过10分钟后
return now > tenMinutesLater; return now > tenMinutesLater;
} catch (error) { } catch (error) {
console.error('时间判断错误:', error); console.error("时间判断错误:", error);
return false; return false;
} }
}; };
// 打卡 // 打卡
const handleClick = async () => { const handleClick = async () => {
const { id } = data.info?.[nextStep.value] if (data.info.length == 0) {
hintToast("此方格没有必打卡点位!");
return;
}
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({
id, id,
dkWd: lat, dkWd: lat,
dkJd: lng, dkJd: lng,
dkFj: fileId.value, dkFj: fileId.value,
}) });
if (res) { if (res) {
hintToast(`打卡成功`) hintToast(`打卡成功`);
await getData() await getData();
start(); start();
} }
} catch (error) { } catch (error) {
hintToast(`打卡异常`) hintToast(`打卡异常`);
stop() stop();
console.log(error); console.log(error);
} }
} };
onMounted(() => { onMounted(() => {
if (route?.query) { if (route?.query) {
data.query = route?.query; data.query = route?.query;
getPatrolList(route?.query) getPatrolList(route?.query);
} }
window.setimagebase64 = setimage_base64; window.setimagebase64 = setimage_base64;
}) });
</script> </script>
<template> <template>
@ -449,17 +469,24 @@ 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 :class="['clockInList_item', { 'active': nextStep === index }]" @click="handleNext(index)"> <div
: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" />
<div>开始</div> <div>开始</div>
<div v-if="item?.dkKsSj" class="time">{{ item?.dkKsSj?.split(' ')[1] }}已打卡</div> <div v-if="item?.dkKsSj" class="time">
{{ item?.dkKsSj?.split(" ")[1] }}已打卡
</div>
</div> </div>
<div class="dec"> <div class="dec">
<van-icon v-if="item?.dkJsSj" name="checked" color="#007DE9" /> <van-icon v-if="item?.dkJsSj" name="checked" color="#007DE9" />
<div>离开</div> <div>离开</div>
<div v-if="item?.dkJsSj" class="time">{{ item?.dkJsSj?.split(' ')[1] }}已打卡</div> <div v-if="item?.dkJsSj" class="time">
{{ item?.dkJsSj?.split(" ")[1] }}已打卡
</div>
</div> </div>
</div> </div>
</template> </template>
@ -467,8 +494,18 @@ 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 name="close" class="close_icon" @click="clearImage" color="#000" size="24px" /> <van-icon
<van-image :src="baseUrl" @click="onClickImg(baseUrl)" style="flex: 1"> name="close"
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>
@ -480,16 +517,33 @@ onMounted(() => {
</div> </div>
<!-- <van-uploader v-model="clockList" :max-count="1" :after-read="afterRead" capture="camera" <!-- <van-uploader v-model="clockList" :max-count="1" :after-read="afterRead" capture="camera"
:before-read="beforeRead" accept="image/*" /> --> :before-read="beforeRead" accept="image/*" /> -->
<div class="upload_tip"><span style="color: red;">*</span>须拍摄实景图才可进行打卡</div> <div class="upload_tip">
<span style="color: red">*</span>须拍摄实景图才可进行打卡
</div>
</div> </div>
<div class="clockWrapper"> <div class="clockWrapper">
<div v-if="!infoData?.dkJsSj || !infoData?.dkKsSj" class="circleWrapper" :class="{ 'disabled': !isExpired && expirationTime || infoData?.dkJsSj }" @click="handleClick"> <div
<div v-if="!isExpired && expirationTime" class="time">{{ formattedTime }}</div> v-if="!infoData?.dkJsSj || !infoData?.dkKsSj"
<div class="title">{{ !infoData?.dkKsSj ? `开始` : `离开` }}</div> class="circleWrapper"
<div class="info">{{ `${infoData?.count || ''}次打卡` }}</div> :class="{
disabled: (!isExpired && expirationTime) || infoData?.dkJsSj,
}"
@click="handleClick"
>
<div v-if="!isExpired && expirationTime" class="time">
{{ formattedTime }}
</div> </div>
<div v-else class="circleWrapper" :class="{ 'disabled': !isExpired && expirationTime || infoData?.dkJsSj }"> <div class="title">{{ !infoData?.dkKsSj ? `开始` : `离开` }}</div>
<div class="info">{{ `${infoData?.count || ""}次打卡` }}</div>
</div>
<div
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 class="info">{{ `${infoData?.count || ''}次打卡` }}</div>-->
</div> </div>
@ -535,7 +589,7 @@ onMounted(() => {
justify-content: center; justify-content: center;
width: 3.73vw; width: 3.73vw;
height: 3.73vw; height: 3.73vw;
background: #11AA66; background: #11aa66;
border-radius: 13.33vw; border-radius: 13.33vw;
} }
} }
@ -548,7 +602,7 @@ onMounted(() => {
justify-content: center; justify-content: center;
width: 42.67vw; width: 42.67vw;
height: 42.67vw; height: 42.67vw;
background: linear-gradient( 180deg, #1DB1FF 0%, #007DE9 100%); background: linear-gradient(180deg, #1db1ff 0%, #007de9 100%);
border-radius: 26.67vw; border-radius: 26.67vw;
color: #fff; color: #fff;
font-family: PingFang HK, PingFang HK; font-family: PingFang HK, PingFang HK;
@ -572,8 +626,8 @@ onMounted(() => {
} }
.disabled { .disabled {
background: #EDEDED !important; background: #ededed !important;
color: #75787F !important; color: #75787f !important;
} }
} }
@ -581,7 +635,7 @@ onMounted(() => {
margin-top: 4vw; margin-top: 4vw;
display: flex; display: flex;
padding-bottom: 4vw; padding-bottom: 4vw;
border-bottom: 0.27vw solid #D9D9D9; border-bottom: 0.27vw solid #d9d9d9;
.upload_tip { .upload_tip {
color: #999999; color: #999999;
@ -612,8 +666,8 @@ onMounted(() => {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: #1DB1FF; color: #1db1ff;
border: 0.27vw dashed #1DB1FF; border: 0.27vw dashed #1db1ff;
text-align: center; text-align: center;
width: 29.33vw; width: 29.33vw;
height: 16.53vw; height: 16.53vw;
@ -631,7 +685,7 @@ onMounted(() => {
padding: 4vw 2vw; padding: 4vw 2vw;
width: 43vw; width: 43vw;
height: 18vw; height: 18vw;
background: #EDEDED; background: #ededed;
border-radius: 2.67vw; border-radius: 2.67vw;
flex-shrink: 0; flex-shrink: 0;
margin-right: 2.67vw; margin-right: 2.67vw;
@ -648,7 +702,7 @@ onMounted(() => {
.dec { .dec {
display: flex; display: flex;
align-items: center; align-items: center;
color: #75787F; color: #75787f;
font-size: 3.73vw; font-size: 3.73vw;
margin-top: 1.33vw; margin-top: 1.33vw;
@ -685,8 +739,8 @@ onMounted(() => {
width: auto !important; width: auto !important;
height: 9.33vw; height: 9.33vw;
padding: 0 2.67vw; padding: 0 2.67vw;
border: 0.27vw solid #EDEDED; border: 0.27vw solid #ededed;
color: #75787F; color: #75787f;
flex-shrink: 0; flex-shrink: 0;
border-radius: 2vw; border-radius: 2vw;
margin-right: 2vw; margin-right: 2vw;
@ -698,8 +752,8 @@ onMounted(() => {
.van-tab--active { .van-tab--active {
background: rgba(62, 110, 232, 0.2); background: rgba(62, 110, 232, 0.2);
border: 0.27vw solid #3E6EE8; border: 0.27vw solid #3e6ee8;
color: #3E6EE8 !important; color: #3e6ee8 !important;
} }
} }
} }

View File

@ -9,67 +9,69 @@ import {getSelectPage} from "@/api/collectPage";
const finished = ref(false); const finished = ref(false);
const loading = ref(false); const loading = ref(false);
const loadingRefresh = ref(false); const loadingRefresh = ref(false);
const searchValue = ref("") const searchValue = ref("");
const pageData = reactive({ const pageData = reactive({
pageSize: 10, pageSize: 10,
pageCurrent: 1, pageCurrent: 1,
total: 0, total: 0,
}) });
const data = reactive({ const data = reactive({
list: [] list: [],
}) });
const onSearch = (value) => { const onSearch = (value) => {
loading.value = true; loading.value = true;
pageData.pageCurrent = 1; pageData.pageCurrent = 1;
data.list = [] data.list = [];
getData() getData();
} };
const onRefresh = () => { const onRefresh = () => {
loading.value = false; loading.value = false;
loadingRefresh.value = true; loadingRefresh.value = true;
finished.value = false; finished.value = false;
pageData.pageCurrent = 1; pageData.pageCurrent = 1;
data.list = [] data.list = [];
getData() getData();
} };
const getData = async () => { const getData = async () => {
loading.value = true; loading.value = true;
try { try {
const { total, ...ret } = pageData const { total, ...ret } = pageData;
const res = await getSelectPage({ ...ret, bddMc: searchValue.value }) const res = await getSelectPage({ ...ret, bddMc: searchValue.value });
if (res?.records.length > 0) { if (res?.records.length > 0) {
data.list = data.list.concat(res?.records) || [] data.list = data.list.concat(res?.records) || [];
pageData.total = res?.total pageData.total = res?.total;
loading.value = false; loading.value = false;
} else {
finished.value = true;
} }
loadingRefresh.value = false; loadingRefresh.value = false;
} catch (error) { } catch (error) {
loading.value = false; loading.value = false;
loadingRefresh.value = false; loadingRefresh.value = false;
} }
} };
const onLoad = () => { const onLoad = () => {
if (data.list.length >= pageData?.total) { if (data.list.length >= pageData?.total) {
finished.value = true; finished.value = true;
return return;
} }
pageData.pageCurrent++ pageData.pageCurrent++;
getData() getData();
} };
onMounted(() => { onMounted(() => {
data.list = [] data.list = [];
getData() getData();
}) });
const handleTo = () => { const handleTo = () => {
router.push("/collectAndAdd") router.push("/collectAndAdd");
} };
</script> </script>
<template> <template>
@ -78,7 +80,8 @@ const handleTo = () => {
<van-sticky> <van-sticky>
<div class="header"> <div class="header">
<search placeholder="请输入部门、所属方格或必到点名称进行查询" <search
placeholder="请输入部门、所属方格或必到点名称进行查询"
v-model="searchValue" v-model="searchValue"
@update:modelValue="onSearch" @update:modelValue="onSearch"
/> />
@ -87,21 +90,27 @@ const handleTo = () => {
<div class="content"> <div class="content">
<van-pull-refresh v-model="loadingRefresh" @refresh="onRefresh"> <van-pull-refresh v-model="loadingRefresh" @refresh="onRefresh">
<van-list v-model:loading="loading" :finished="finished" finished-text="" @load="onLoad" offset="1" :immediate-check="false"> <van-list
v-model:loading="loading"
:finished="finished"
finished-text=""
@load="onLoad"
offset="1"
:immediate-check="false"
>
<list-item-wrapper :list="data.list" /> <list-item-wrapper :list="data.list" />
<van-empty description="暂无采集数据" image="default" v-if="data.list.length <= 0 && loadingRefresh === false" /> <van-empty
description="暂无采集数据"
image="default"
v-if="data.list.length <= 0 && loadingRefresh === false"
/>
</van-list> </van-list>
</van-pull-refresh> </van-pull-refresh>
</div> </div>
<div class="footer" @click="handleTo"> <div class="footer" @click="handleTo">
<van-button <van-button round native-type="submit" block type="primary">
round
native-type="submit"
block
type="primary"
>
新增必到点采集 新增必到点采集
</van-button> </van-button>
</div> </div>

View File

@ -553,3 +553,22 @@ export function hintToast(msg, hintType = 'top') {
position: hintType position: hintType
}) })
} }
export function getLocationJs() {
let jwd = {}
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
(pos) => {
if (pos.coords) {
jwd.lat = pos.coords.latitude;
jwd.lng = pos.coords.longitude;
}
},
(err) => {
console.log(err, "err");
}
);
} else {
console.log("Geolocation is not supported by this browser.");
}
return jwd;
};

View File

@ -12,8 +12,8 @@ module.exports = {
port: 9528, port: 9528,
proxy: { proxy: {
'/mosty-api': { '/mosty-api': {
// target: "http://118.122.165.45:35623", target: "http://118.122.165.45:35623",
target: "http://192.168.1.8:8006", // target: "http://192.168.19.212:8006",
changeOrigin: true, changeOrigin: true,
}, },
} }