打卡页面修改 增加地图功能处理
This commit is contained in:
@ -1,15 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="info-container">
|
<div class="info-container">
|
||||||
|
<div class="title">时间轴</div>
|
||||||
<template v-for="(item, index) in data" :key="index">
|
<template v-for="(item, index) in data" :key="index">
|
||||||
<div v-if="item?.dkKsSj" class="item">
|
<div :class="['item', { 'disabled': !item?.dkKsSj }]">
|
||||||
<div class="point"></div>
|
<div class="point"></div>
|
||||||
<div class="line" v-if="index + 1 != data.length"></div>
|
|
||||||
<div class="info-right">
|
<div class="info-right">
|
||||||
<div class="name">{{ `第${item?.count}次打卡` }}</div>
|
<div class="name">{{ `第${item?.count}次打卡 开始` }}</div>
|
||||||
<div class="time">打卡时间:<text>{{ item?.dkKsSj }}</text></div>
|
<div v-if="item?.dkKsSj" class="time">打卡时间:<text>{{ handleTime(item?.dkKsSj) }}</text></div>
|
||||||
|
|
||||||
<div v-if="item?.imgUrl" class="image">
|
<div v-if="item?.imgUrlDkKsFj" class="image">
|
||||||
<van-image width="80px" :src="item?.imgUrl" @click="onClickImg(item?.imgUrl)" style="flex: 1">
|
<van-image width="80px" :src="item?.imgUrlDkKsFj" @click="onClickImg(item?.imgUrlDkKsFj)" style="flex: 1">
|
||||||
|
<template v-slot:loading>
|
||||||
|
<van-loading type="spinner" size="20" />
|
||||||
|
</template>
|
||||||
|
</van-image>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="address">-->
|
||||||
|
<!-- <van-icon name="location-o" color="#1DB1FF" />-->
|
||||||
|
<!-- <div class="name">四川省成都市</div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :class="['item', { 'disabled': !item?.dkJsSj }]">
|
||||||
|
<div class="point"></div>
|
||||||
|
<div class="info-right">
|
||||||
|
<div class="name">{{ `第${item?.count}次打卡 离开` }}</div>
|
||||||
|
<div v-if="item?.dkJsSj" class="time">打卡时间:<text>{{ handleTime(item?.dkJsSj) }}</text></div>
|
||||||
|
|
||||||
|
<div v-if="item?.imgUrlDkJsFj" class="image">
|
||||||
|
<van-image width="80px" :src="item?.imgUrlDkJsFj" @click="onClickImg(item?.imgUrlDkJsFj)" 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>
|
||||||
@ -40,6 +61,10 @@ const props = defineProps({
|
|||||||
function onClickImg(url) {
|
function onClickImg(url) {
|
||||||
ImagePreview([url]);
|
ImagePreview([url]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleTime = (time) => {
|
||||||
|
if (time) return time?.split(' ')[1]
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -47,6 +72,12 @@ function onClickImg(url) {
|
|||||||
padding: 0 2.67vw;
|
padding: 0 2.67vw;
|
||||||
margin-top: 4vw;
|
margin-top: 4vw;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #707070;
|
||||||
|
font-size: 3.73vw;
|
||||||
|
margin-bottom: 4vw;
|
||||||
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
color: #666;
|
color: #666;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -55,7 +86,7 @@ function onClickImg(url) {
|
|||||||
height: auto;
|
height: auto;
|
||||||
border-left: 0.53vw dashed #1DB1FF;
|
border-left: 0.53vw dashed #1DB1FF;
|
||||||
max-height: 46.93vw;
|
max-height: 46.93vw;
|
||||||
padding-bottom: 2.67vw;
|
padding-bottom: 8vw;
|
||||||
|
|
||||||
.point {
|
.point {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -70,6 +101,7 @@ function onClickImg(url) {
|
|||||||
.info-right {
|
.info-right {
|
||||||
margin-left: 5.33vw;
|
margin-left: 5.33vw;
|
||||||
font-family: PingFang HK, PingFang HK;
|
font-family: PingFang HK, PingFang HK;
|
||||||
|
margin-top: -1.33vw;
|
||||||
.name {
|
.name {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 3.73vw;
|
font-size: 3.73vw;
|
||||||
@ -84,6 +116,7 @@ function onClickImg(url) {
|
|||||||
|
|
||||||
.time {
|
.time {
|
||||||
margin-top: 2.13vw;
|
margin-top: 2.13vw;
|
||||||
|
font-size: 3.73vw;
|
||||||
|
|
||||||
text {
|
text {
|
||||||
color: #0386FB;
|
color: #0386FB;
|
||||||
@ -106,5 +139,13 @@ function onClickImg(url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
border-left: 0.53vw dashed #EDEDED !important;
|
||||||
|
|
||||||
|
.point {
|
||||||
|
background: #EDEDED !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
17
src/pages/clockInPage/components/mapWrapper.vue
Normal file
17
src/pages/clockInPage/components/mapWrapper.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script setup>
|
||||||
|
import GdMap from "@/components/GdMap/index.vue"
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="mapWrapper">
|
||||||
|
<gd-map />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.mapWrapper {
|
||||||
|
margin-top: 4vw;
|
||||||
|
height: 40vh;
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,10 +3,12 @@ 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 {fetchSelectListByBddxlrwId, fetchTbZdxlFgdwBddxlrwJlClockIn} from "@/api/patrolList";
|
import {fetchPatrolList, fetchSelectListByBddxlrwId, fetchTbZdxlFgdwBddxlrwJlClockIn} from "@/api/patrolList";
|
||||||
import {getBase64, hintToast} from "@/utils/tools";
|
import {getBase64, hintToast} from "@/utils/tools";
|
||||||
import {ImagePreview} from "vant";
|
import {ImagePreview} from "vant";
|
||||||
import {qcckPost, qcckGet} from "@/api/qcckApi";
|
import {qcckPost, qcckGet} from "@/api/qcckApi";
|
||||||
|
import MapWrapper from "@/pages/clockInPage/components/mapWrapper.vue";
|
||||||
|
import emitter from "@/utils/eventBus";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const active = ref(0)
|
const active = ref(0)
|
||||||
@ -123,15 +125,16 @@ const useCountdownFromTime = (minutes = 10) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
tabsList: [],
|
patroObj: {},
|
||||||
info: [],
|
info: [],
|
||||||
|
query: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
const infoData = computed(() => {
|
const infoData = computed(() => {
|
||||||
return data.info?.[nextStep.value]
|
return data.info?.[nextStep.value]
|
||||||
})
|
})
|
||||||
|
|
||||||
const activeInfoData = computed(() => data.tabsList?.[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);
|
||||||
|
|
||||||
@ -165,7 +168,7 @@ const count = (item) => {
|
|||||||
|
|
||||||
const onChange = (value) => {
|
const onChange = (value) => {
|
||||||
active.value = value;
|
active.value = value;
|
||||||
getData(data.tabsList[value]?.id)
|
getPatrolList(data?.query)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleNext = (index) => {
|
const handleNext = (index) => {
|
||||||
@ -207,34 +210,73 @@ const getImageUrl = async (fileId) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getData = async (bddxlrwId = '') => {
|
const getData = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetchSelectListByBddxlrwId({ bddxlrwId });
|
const res = await fetchSelectListByBddxlrwId({ bddxlrwId: activeInfoData?.value?.id || '' });
|
||||||
if (res) {
|
if (res && res?.length > 0) {
|
||||||
// 收集所有需要加载的图片ID
|
|
||||||
const imageIds = res.map(i => i?.dkJsFj).filter(Boolean);
|
// 获取所有唯一的图片ID
|
||||||
|
const uniqueImageIds = new Set();
|
||||||
|
res?.forEach(item => {
|
||||||
|
if (item?.dkJsFj) uniqueImageIds.add(item.dkJsFj);
|
||||||
|
if (item?.dkKsFj) uniqueImageIds.add(item.dkKsFj);
|
||||||
|
});
|
||||||
|
|
||||||
// 批量获取图片URL
|
// 批量获取图片URL
|
||||||
const imagePromises = imageIds.map(id => getImageUrl(id));
|
const imageEntries = await Promise.allSettled(
|
||||||
const imageResults = await Promise.allSettled(imagePromises);
|
Array.from(uniqueImageIds).map(async (id) => {
|
||||||
|
try {
|
||||||
|
const url = await getImageUrl(id);
|
||||||
|
return { id, url };
|
||||||
|
} catch (error) {
|
||||||
|
return { id, url: null };
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// 创建图片映射表
|
// 创建图片映射表
|
||||||
const imageMap = new Map();
|
const imageMap = new Map();
|
||||||
imageIds.forEach((id, index) => {
|
imageEntries.forEach(entry => {
|
||||||
const result = imageResults[index];
|
if (entry.status === 'fulfilled') {
|
||||||
imageMap.set(id, result.status === 'fulfilled' ? result.value : null);
|
imageMap.set(entry.value.id, entry.value.url);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置数据
|
// 设置数据
|
||||||
data.info = res.map(i => ({
|
data.info = res.map(item => ({
|
||||||
...i,
|
...item,
|
||||||
count: count(i),
|
count: count(item),
|
||||||
imgUrl: imageMap.get(i?.dkJsFj) || null
|
imgUrlDkJsFj: item?.dkJsFj ? imageMap.get(item.dkJsFj) : null,
|
||||||
|
imgUrlDkKsFj: item?.dkKsFj ? imageMap.get(item.dkKsFj) : null,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
active.value = 1;
|
data.info?.forEach(i => {
|
||||||
|
if (i?.dkKsJd && i?.dkKsWd) {
|
||||||
|
// 删除标注
|
||||||
|
emitter.emit("deletePointArea", "dkKs");
|
||||||
|
//地图撒点然后移动
|
||||||
|
emitter.emit("addPointArea", {
|
||||||
|
coords: [{ jd: i?.dkKsJd, wd: i?.dkKsWd }],
|
||||||
|
icon: require("../../assets/images/11.png"),
|
||||||
|
flag: "dkKs",
|
||||||
|
sizeX: 30,
|
||||||
|
sizeY: 35
|
||||||
|
});
|
||||||
|
} else if (i?.dkJsJd && i?.dkJsWd) {
|
||||||
|
// 删除标注
|
||||||
|
emitter.emit("deletePointArea", "dkJs");
|
||||||
|
//地图撒点然后移动
|
||||||
|
emitter.emit("addPointArea", {
|
||||||
|
coords: [{ jd: i?.dkJsJd, wd: i?.dkJsWd }],
|
||||||
|
icon: require("../../assets/images/11.png"),
|
||||||
|
flag: "dkKs",
|
||||||
|
sizeX: 30,
|
||||||
|
sizeY: 35
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
console.log('完整数据:', data.info);
|
active.value = 1;
|
||||||
|
|
||||||
await nextTick(() => {
|
await nextTick(() => {
|
||||||
const firstItem = data.info[nextStep.value || 0];
|
const firstItem = data.info[nextStep.value || 0];
|
||||||
@ -251,6 +293,49 @@ const getData = async (bddxlrwId = '') => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//获取当前位置信息
|
||||||
|
function getUserLocation(sfdw) {
|
||||||
|
let { lng, lat } = getLocation();
|
||||||
|
if (lng && lat) {
|
||||||
|
emitter.emit("deletePointArea", "dw");
|
||||||
|
//地图撒点然后移动
|
||||||
|
emitter.emit("addPointArea", {
|
||||||
|
coords: [{ jd: lng, wd: lat }],
|
||||||
|
icon: require("../../assets/lz/dw.png"),
|
||||||
|
flag: "dw",
|
||||||
|
sfdw: sfdw,
|
||||||
|
sizeX: 30,
|
||||||
|
sizeY: 35
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
hintToast("暂无坐标信息");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPatrolList = async ({ current, id }) => {
|
||||||
|
const res = await fetchPatrolList({ pageCurrent: current, pageSize: 10 })
|
||||||
|
if (res?.records.length > 0) {
|
||||||
|
getUserLocation()
|
||||||
|
|
||||||
|
data.patroObj = res?.records?.find((item) => item.id === id) || {};
|
||||||
|
// 删除方格
|
||||||
|
emitter.emit("deletePointArea", "zdxl_fzyc")
|
||||||
|
|
||||||
|
// 生成方格
|
||||||
|
const { x1, y1, x2, y2, fgId, zxX, zxY, fgMc } = data.patroObj
|
||||||
|
const centerPoint = [zxX, zxY]
|
||||||
|
const position = [[Number(x1),Number(y1)],[Number(x2),Number(y2)]]
|
||||||
|
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 });
|
||||||
|
|
||||||
|
|
||||||
|
await getData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 简单的时间加法函数
|
// 简单的时间加法函数
|
||||||
const addTenMinutes = (timeString) => {
|
const addTenMinutes = (timeString) => {
|
||||||
if (!timeString) return '';
|
if (!timeString) return '';
|
||||||
@ -317,7 +402,7 @@ const handleClick = async () => {
|
|||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
hintToast(`打卡成功`)
|
hintToast(`打卡成功`)
|
||||||
await getData(data.tabsList?.[0]?.id)
|
await getData()
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -328,12 +413,11 @@ const handleClick = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (route.query.item) {
|
if (route?.query) {
|
||||||
data.tabsList = JSON.parse(route.query.item)
|
data.query = route?.query;
|
||||||
|
getPatrolList(route?.query)
|
||||||
}
|
}
|
||||||
|
|
||||||
getData(data.tabsList?.[0]?.id)
|
|
||||||
|
|
||||||
window.setimagebase64 = setimage_base64;
|
window.setimagebase64 = setimage_base64;
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -344,7 +428,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<div class="clockInWrapper">
|
<div class="clockInWrapper">
|
||||||
<van-tabs v-model:active="active" :active="active" @click="onChange">
|
<van-tabs v-model:active="active" :active="active" @click="onChange">
|
||||||
<template v-for="(item, index) in data.tabsList" :key="index">
|
<template v-for="(item, index) in data.patroObj?.bddList" :key="index">
|
||||||
<van-tab :title="item.bddMc" />
|
<van-tab :title="item.bddMc" />
|
||||||
</template>
|
</template>
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
@ -389,7 +473,7 @@ onMounted(() => {
|
|||||||
<div class="circleWrapper" :class="{ 'disabled': !isExpired && expirationTime }" @click="handleClick">
|
<div class="circleWrapper" :class="{ 'disabled': !isExpired && expirationTime }" @click="handleClick">
|
||||||
<div v-if="!isExpired && expirationTime" class="time">{{ formattedTime }}后</div>
|
<div v-if="!isExpired && expirationTime" class="time">{{ formattedTime }}后</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 class="circleWrapperTip">
|
<div class="circleWrapperTip">
|
||||||
<van-icon name="success" color="#FFFFFF" />
|
<van-icon name="success" color="#FFFFFF" />
|
||||||
@ -397,7 +481,8 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<timeline :data="data.info" />
|
<timeline v-if="data.info.length > 0" :data="data.info" />
|
||||||
|
<map-wrapper />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import router from "@/router";
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
list: {
|
list: {
|
||||||
type: Array,
|
type: Array,
|
||||||
@ -9,10 +7,10 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emits = defineEmits(["onConfirm"]);
|
const emits = defineEmits(["click"]);
|
||||||
|
|
||||||
const handleClockInPage = (item) => {
|
const handleClockInPage = (item) => {
|
||||||
router.push({ path: '/clockInPage', query: { item: JSON.stringify(item?.bddList), id: item.id } });
|
emits("click", item);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import Search from "@/components/search.vue";
|
|||||||
import PatrolWrapper from "@/pages/patrolList/copmonents/patrolWrapper.vue";
|
import PatrolWrapper from "@/pages/patrolList/copmonents/patrolWrapper.vue";
|
||||||
import {fetchPatrolList} from "@/api/patrolList";
|
import {fetchPatrolList} from "@/api/patrolList";
|
||||||
import {getDictListByCode} from "@/api/common";
|
import {getDictListByCode} from "@/api/common";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
const finished = ref(false);
|
const finished = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -47,6 +48,10 @@ const onLoad = () => {
|
|||||||
getData()
|
getData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleClockInPage = (item) => {
|
||||||
|
router.push({ path: '/clockInPage', query: { id: item.id, current: pageData.pageCurrent } });
|
||||||
|
}
|
||||||
|
|
||||||
const parseAndJoinLx = (jsonString, type = 'lx') => {
|
const parseAndJoinLx = (jsonString, type = 'lx') => {
|
||||||
if (!jsonString) return '';
|
if (!jsonString) return '';
|
||||||
|
|
||||||
@ -127,7 +132,7 @@ onMounted(() => {
|
|||||||
<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">
|
||||||
<patrol-wrapper :list="data?.list" />
|
<patrol-wrapper :list="data?.list" @click="handleClockInPage" />
|
||||||
|
|
||||||
<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>
|
||||||
|
Reference in New Issue
Block a user