提交
This commit is contained in:
@ -124,6 +124,10 @@ export function MapUtil(map) {
|
|||||||
let textTitle = item.jzMc ? item.jzMc : item.fzrXm + '警组';
|
let textTitle = item.jzMc ? item.jzMc : item.fzrXm + '警组';
|
||||||
if(flag == 'sbwz_car' || flag == 'sbwz_sb' ) textTitle = item.sbmc;
|
if(flag == 'sbwz_car' || flag == 'sbwz_sb' ) textTitle = item.sbmc;
|
||||||
if(flag == 'gapText') textTitle = text
|
if(flag == 'gapText') textTitle = text
|
||||||
|
// 支持打卡点名称
|
||||||
|
if(item.bxdMc) textTitle = item.bxdMc;
|
||||||
|
// 支持通用标题字段
|
||||||
|
if(item.title) textTitle = item.title;
|
||||||
// 设置样式
|
// 设置样式
|
||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
el.className = 'makerTitle';
|
el.className = 'makerTitle';
|
||||||
|
|||||||
@ -8,12 +8,25 @@
|
|||||||
<PrpcPopup ref="prpc" :key="pcKey + 'pc'" />
|
<PrpcPopup ref="prpc" :key="pcKey + 'pc'" />
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted,nextTick } from "vue";
|
import { ref, onMounted, nextTick } from "vue";
|
||||||
import { useRouter, useRoute } from "vue-router";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
import PrpcPopup from "../spsHome/components/prpcPopup.vue";
|
import PrpcPopup from "../spsHome/components/prpcPopup.vue";
|
||||||
|
import { getMybbTodayNew } from "@/api/common";
|
||||||
|
import { getItem, setItem } from "@/utils/storage";
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pcKey = ref(0);
|
const pcKey = ref(0);
|
||||||
const prpc = ref(null);
|
const prpc = ref(null);
|
||||||
|
const userInfo = getItem("userInfo") || {};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getMybbTodayNew().then((res) => {
|
||||||
|
if (!res) return;
|
||||||
|
userInfo.bbId = res.id;
|
||||||
|
userInfo.jzId = res.jzId;
|
||||||
|
userInfo.jzMc = res.jzMc;
|
||||||
|
setItem("userInfo", userInfo);
|
||||||
|
});
|
||||||
|
});
|
||||||
const listData = ref([
|
const listData = ref([
|
||||||
{
|
{
|
||||||
text: '勤务报备',
|
text: '勤务报备',
|
||||||
@ -27,12 +40,6 @@ const listData = ref([
|
|||||||
type: 'rcpc',
|
type: 'rcpc',
|
||||||
path: '/yyzx/xfbb/addXfbb'
|
path: '/yyzx/xfbb/addXfbb'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: '巡逻打卡',
|
|
||||||
imgUrl: require("@/assets/home/xldk.png"),
|
|
||||||
type: 'xldk',
|
|
||||||
path: '/patrolList'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: '任务中心',
|
text: '任务中心',
|
||||||
imgUrl: require("@/assets/home/xldk.png"),
|
imgUrl: require("@/assets/home/xldk.png"),
|
||||||
@ -45,12 +52,6 @@ const listData = ref([
|
|||||||
type: 'zllz',
|
type: 'zllz',
|
||||||
path: '/yyzx/zlzx/zlzxIndex'
|
path: '/yyzx/zlzx/zlzxIndex'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: '必到点采集',
|
|
||||||
imgUrl: require("@/assets/home/bddcj.png"),
|
|
||||||
type: 'bddcj',
|
|
||||||
path: '/collectPage'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: '处警报送',
|
text: '处警报送',
|
||||||
imgUrl: require("@/assets/home/dqwz.png"),
|
imgUrl: require("@/assets/home/dqwz.png"),
|
||||||
@ -67,11 +68,9 @@ const listData = ref([
|
|||||||
const changeOpen = (val) => {
|
const changeOpen = (val) => {
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case 'qwbb':
|
case 'qwbb':
|
||||||
case 'xldk':
|
|
||||||
case 'zllz':
|
case 'zllz':
|
||||||
case 'grxx':
|
case 'grxx':
|
||||||
case 'cjbs':
|
case 'cjbs':
|
||||||
case 'bddcj':
|
|
||||||
case 'rwzx':
|
case 'rwzx':
|
||||||
case 'clockIn':
|
case 'clockIn':
|
||||||
router.push(val.path)
|
router.push(val.path)
|
||||||
|
|||||||
@ -17,6 +17,12 @@ const listQuery = ref({
|
|||||||
jd: "",
|
jd: "",
|
||||||
wd: "",
|
wd: "",
|
||||||
});
|
});
|
||||||
|
const leaveQuery = ref({
|
||||||
|
id: "",
|
||||||
|
lkjd: "",
|
||||||
|
lkwd: "",
|
||||||
|
lktp: "",
|
||||||
|
});
|
||||||
const zxdksj = ref("");
|
const zxdksj = ref("");
|
||||||
const dwIndex = ref();
|
const dwIndex = ref();
|
||||||
const imageMap = new Map();
|
const imageMap = new Map();
|
||||||
@ -66,10 +72,11 @@ const loadData = async () => {
|
|||||||
linecolor: "#1C97FF",
|
linecolor: "#1C97FF",
|
||||||
});
|
});
|
||||||
emitter.emit("setMapCenter", { location: centerPoint, zoomLevel: 12 });
|
emitter.emit("setMapCenter", { location: centerPoint, zoomLevel: 12 });
|
||||||
// 获取所有唯一的图片ID
|
// 获取所有唯一的图片ID(打卡图片和离开图片)
|
||||||
const uniqueImageIds = new Set();
|
const uniqueImageIds = new Set();
|
||||||
detail.bxds?.forEach((item) => {
|
detail.bxds?.forEach((item) => {
|
||||||
if (item?.dktp) uniqueImageIds.add(item.dktp);
|
if (item?.dktp) uniqueImageIds.add(item.dktp);
|
||||||
|
if (item?.lktp) uniqueImageIds.add(item.lktp);
|
||||||
});
|
});
|
||||||
// 批量获取图片URL
|
// 批量获取图片URL
|
||||||
const imageEntries = await Promise.allSettled(
|
const imageEntries = await Promise.allSettled(
|
||||||
@ -93,11 +100,31 @@ const loadData = async () => {
|
|||||||
pointsList.value = detail.bxds.map((item, index) => ({
|
pointsList.value = detail.bxds.map((item, index) => ({
|
||||||
...item,
|
...item,
|
||||||
imgUrlDkFj: item?.dktp ? imageMap.get(item.dktp) : null,
|
imgUrlDkFj: item?.dktp ? imageMap.get(item.dktp) : null,
|
||||||
|
lkImgUrl: item?.lktp ? imageMap.get(item.lktp) : null,
|
||||||
}));
|
}));
|
||||||
// 为每个必到点添加图片URL
|
// 为每个必到点添加图片URL
|
||||||
zxdksj.value = detail.zxdksj;
|
zxdksj.value = detail.zxdksj;
|
||||||
info.value = detail.fgrw;
|
info.value = detail.fgrw;
|
||||||
listQuery.value.fgrwid = info.value.id;
|
listQuery.value.fgrwid = info.value.id;
|
||||||
|
|
||||||
|
// 在地图上显示打卡点
|
||||||
|
const dkPoints = detail.bxds
|
||||||
|
?.filter((item) => item.jd && item.wd)
|
||||||
|
.map((item) => ({
|
||||||
|
jd: item.jd,
|
||||||
|
wd: item.wd,
|
||||||
|
bxdMc: item.bxdMc,
|
||||||
|
dkzt: item.dkzt,
|
||||||
|
}));
|
||||||
|
if (dkPoints && dkPoints.length > 0) {
|
||||||
|
emitter.emit("deletePointArea", "historyPoints");
|
||||||
|
emitter.emit("addPointArea", {
|
||||||
|
coords: dkPoints,
|
||||||
|
icon: require("../../assets/images/11.png"),
|
||||||
|
flag: "historyPoints",
|
||||||
|
showTitle: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//获取当前位置信息
|
//获取当前位置信息
|
||||||
@ -134,8 +161,20 @@ function isInThirtyMinutes(targetTime, jgsj) {
|
|||||||
}
|
}
|
||||||
return flag
|
return flag
|
||||||
}
|
}
|
||||||
|
// 检查是否存在已打卡但未离开的点
|
||||||
|
const hasUnfinishedCheckIn = () => {
|
||||||
|
// dksj: 打卡时间,lksj: 离开时间
|
||||||
|
// 已打卡且有打卡时间,但没有离开时间,说明未完成
|
||||||
|
return pointsList.value.some((item) => item.dksj && !item.lksj);
|
||||||
|
};
|
||||||
// 点击上传
|
// 点击上传
|
||||||
const photoFn = (val, index) => {
|
const photoFn = (val, index) => {
|
||||||
|
// 检查是否存在已打卡但未离开的点
|
||||||
|
const unfinishedPoint = pointsList.value.find((item) => item.dksj && !item.lksj);
|
||||||
|
if (unfinishedPoint) {
|
||||||
|
hintToast(`请先完成【${unfinishedPoint.bxdMc || '上一个点'}】的离开打卡`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
dwIndex.value = index;
|
dwIndex.value = index;
|
||||||
listQuery.value.bxdid = val.bxdid;
|
listQuery.value.bxdid = val.bxdid;
|
||||||
// 判断此任务最新打卡时间如果在打卡间隔时间之后才能继续打卡
|
// 判断此任务最新打卡时间如果在打卡间隔时间之后才能继续打卡
|
||||||
@ -181,7 +220,68 @@ const handleClick = () => {
|
|||||||
loadData()
|
loadData()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
// 检查是否可以离开打卡(当前时间要大于打卡时间+打卡间隔时间)
|
||||||
|
const canLeave = (dksj, dkjgsj) => {
|
||||||
|
if (!dksj) return false;
|
||||||
|
const now = new Date();
|
||||||
|
const dkTime = new Date(dksj);
|
||||||
|
const minLeaveTime = new Date(dkTime.getTime() + Number(dkjgsj || 0) * 60 * 1000);
|
||||||
|
return now.getTime() >= minLeaveTime.getTime();
|
||||||
|
};
|
||||||
|
// 获取剩余等待时间(分钟)
|
||||||
|
const getLeaveWaitTime = (dksj, dkjgsj) => {
|
||||||
|
if (!dksj) return 0;
|
||||||
|
const now = new Date();
|
||||||
|
const dkTime = new Date(dksj);
|
||||||
|
const minLeaveTime = new Date(dkTime.getTime() + Number(dkjgsj || 0) * 60 * 1000);
|
||||||
|
const diff = minLeaveTime.getTime() - now.getTime();
|
||||||
|
return Math.ceil(diff / 1000 / 60);
|
||||||
|
};
|
||||||
|
// 离开打卡拍照
|
||||||
|
const leavePhotoFn = (item, index) => {
|
||||||
|
// 判断时间间隔
|
||||||
|
if (!canLeave(item.dksj, info.value.dkjgsj)) {
|
||||||
|
const waitMin = getLeaveWaitTime(item.dksj, info.value.dkjgsj);
|
||||||
|
hintToast(`请于${waitMin}分钟后离开打卡`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dwIndex.value = index;
|
||||||
|
leaveQuery.value.id = item.id;
|
||||||
|
const { lng, lat } = getLocation();
|
||||||
|
leaveQuery.value.lkjd = lng;
|
||||||
|
leaveQuery.value.lkwd = lat;
|
||||||
|
try {
|
||||||
|
bridge.pZ("leavePhoto");
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err, "err");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 离开打卡提交
|
||||||
|
const handleLeaveSubmit = () => {
|
||||||
|
qcckPost(leaveQuery.value, "/mosty-yjzl/tbZdyrw/zdyLkdk")
|
||||||
|
.then((res) => {
|
||||||
|
if (res) {
|
||||||
|
hintToast(`离开打卡成功`);
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err, "err");
|
||||||
|
hintToast("离开打卡失败");
|
||||||
|
});
|
||||||
|
};
|
||||||
function setimage_base64(pzid, base64) {
|
function setimage_base64(pzid, base64) {
|
||||||
|
if (pzid === "leavePhoto") {
|
||||||
|
// 离开打卡
|
||||||
|
pointsList.value[dwIndex.value].lkImgUrl = `data:image/jpeg;base64,${base64}`;
|
||||||
|
qcckPost({ base64: base64 }, "/mosty-base/minio/image/upload/base64").then(
|
||||||
|
(res) => {
|
||||||
|
leaveQuery.value.lktp = res;
|
||||||
|
handleLeaveSubmit();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 打卡
|
||||||
pointsList.value[dwIndex.value].imgUrlDkFj = `data:image/jpeg;base64,${base64}`;
|
pointsList.value[dwIndex.value].imgUrlDkFj = `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) => {
|
||||||
@ -189,6 +289,7 @@ function setimage_base64(pzid, base64) {
|
|||||||
handleClick();
|
handleClick();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadData();
|
await loadData();
|
||||||
@ -228,12 +329,23 @@ onUnmounted(() => {
|
|||||||
<!-- Checked In: Show Image -->
|
<!-- Checked In: Show Image -->
|
||||||
<div v-if="item.imgUrlDkFj" class="img-container" @click="preview(item.imgUrlDkFj)">
|
<div v-if="item.imgUrlDkFj" class="img-container" @click="preview(item.imgUrlDkFj)">
|
||||||
<img :src="item.imgUrlDkFj" alt="打卡图片" />
|
<img :src="item.imgUrlDkFj" alt="打卡图片" />
|
||||||
<div class="time-overlay">{{ item.dksj }}</div>
|
<div class="time-overlay">打卡:{{ item.dksj }}</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Not Checked In: Show Button (Visual only) -->
|
<!-- Not Checked In: Show Button (Visual only) -->
|
||||||
<div v-else class="btn-container">
|
<div v-else class="btn-container">
|
||||||
<div class="btn" @click="photoFn(item, index)">打卡拍照</div>
|
<div class="btn" @click="photoFn(item, index)">打卡拍照</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Leave Check-in Button: Show after checked in and not left yet -->
|
||||||
|
<div v-if="item.imgUrlDkFj && !item.lkjd" class="btn-container leave-btn-container">
|
||||||
|
<div class="btn leave-btn" @click="leavePhotoFn(item, index)">离开打卡</div>
|
||||||
|
</div>
|
||||||
|
<!-- Leave Image: Show if already left -->
|
||||||
|
<div v-if="item.lkjd && item.lkImgUrl" class="img-container leave-img" @click="preview(item.lkImgUrl)">
|
||||||
|
<img :src="item.lkImgUrl" alt="离开图片" />
|
||||||
|
<div class="time-overlay leave-time-overlay">离开:{{ item.lksj }}</div>
|
||||||
|
</div>
|
||||||
|
<!-- Leave time without image -->
|
||||||
|
<div v-else-if="item.lkjd && !item.lkImgUrl" class="leave-time">离开时间:{{ item.lksj }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Map Section -->
|
<!-- Map Section -->
|
||||||
@ -332,6 +444,16 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.leave-img {
|
||||||
|
margin-top: 2vw;
|
||||||
|
|
||||||
|
.leave-time-overlay {
|
||||||
|
background: rgba(255, 107, 53, 0.8);
|
||||||
|
padding: 0.5vw 1.5vw;
|
||||||
|
border-radius: 1vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn-container {
|
.btn-container {
|
||||||
margin-top: 2vw;
|
margin-top: 2vw;
|
||||||
|
|
||||||
@ -346,6 +468,21 @@ onUnmounted(() => {
|
|||||||
box-shadow: 0 2vw 4vw rgba(62, 110, 232, 0.3);
|
box-shadow: 0 2vw 4vw rgba(62, 110, 232, 0.3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.leave-btn-container {
|
||||||
|
margin-top: 2vw;
|
||||||
|
|
||||||
|
.leave-btn {
|
||||||
|
background: linear-gradient(90deg, #ff8c28 0%, #ff6b35 100%);
|
||||||
|
box-shadow: 0 2vw 4vw rgba(255, 107, 53, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.leave-time {
|
||||||
|
margin-top: 2vw;
|
||||||
|
font-size: 3.4vw;
|
||||||
|
color: #ff6b35;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-card {
|
.map-card {
|
||||||
|
|||||||
Reference in New Issue
Block a user