最近在小程序做巡邏打卡功能舌胶,現(xiàn)在記錄一下用到的api和實(shí)現(xiàn)的方式。
包括:可隨時(shí)添加標(biāo)記點(diǎn)疮丛,并且在地圖上顯示彈窗幔嫂,包含textarea辆它,在上面記錄信息。然后實(shí)時(shí)顯示出添加的標(biāo)記婉烟,點(diǎn)擊標(biāo)記會(huì)彈出自定義彈窗娩井,展示記錄的內(nèi)容。并且實(shí)時(shí)記錄位置巡邏結(jié)束后會(huì)展示線路似袁。
<template>
<view class="wrap">
<view class="page-body">
<view class="page-section page-section-gap">
<map
style="width: 100%; height: 100vh"
:latitude="latitude"
:longitude="longitude"
:markers="covers"
:circles="circles"
:polyline="polyline"
@markertap="showMark"
>
<!-- 顯示彈窗洞辣,包含textarea, -->
<cover-view class="cover-modal" v-show="isShowModal">
<cover-view class="modal-title">
記錄信息
<cover-view style="font-size: 24rpx; color: #666666"
>({{ inputLength ? inputLength : 0 }}/50)</cover-view
>
</cover-view>
<!--給modal-body加上background-color和border解決真機(jī)上 map里cover-view里不能改變textarea背景色和加border的限制-->
<cover-view class="modal-body">
<textarea
class="l-textarea lg"
:maxlength="50"
auto-height
:value="inputSerialNum"
@input="inputRecord"
placeholder="請輸入文字...... "
></textarea>
</cover-view>
<cover-view class="textarea-btn-wrap df_hbt_vc">
<cover-view
class="df_hc_vc"
style="height: 107rpx; width: 49.5%"
@click="handleCancel"
>
<cover-view class="btn">取消 </cover-view>
<!--解決 cover-view不能對某一邊的border設(shè)置圓角的限制-->
<cover-view
style="background: #ddd; height: 38px; width: 1%"
></cover-view>
</cover-view>
<cover-view
class="df_hc_vc"
style="height: 107rpx; width: 49.5%"
@click="handleConfirm"
>
<cover-view class="btn">確定 </cover-view>
</cover-view>
</cover-view>
</cover-view>
<!--點(diǎn)擊標(biāo)記點(diǎn)彈出自定義彈窗 -->
<cover-view
@click="controlModal"
class="marker-modal"
v-show="showMarkModal"
>
<!-- marker-modal-title 的樣式解決 cover-view不能對某一邊r設(shè)置border的限制 主要是給目標(biāo)元素加上4個(gè)邊的border,然后使其超出父元素 然后父元素overflow:hidden昙衅,這樣看起來就只有一個(gè)邊-->
<cover-view class="marker-modal-title">
{{ markerCtime | FormatTime }}
</cover-view>
<cover-view class="marker-modal-body">
{{ markerContent }}
</cover-view>
</cover-view>
// out-border-radius解決 cover-view不能對某一邊的border設(shè)置圓角的限制 主要是在元素的外層套一個(gè) <cover-view>然后把形狀設(shè)置為長方形扬霜,然后對這個(gè)外層設(shè)置border-radius
<cover-view
v-if="xunluoing"
class="btn-wrap out-border-radius"
style="width: unset"
>
<cover-view class="df_hc_vc expand">
<cover-view
class="df_hc_vc sure"
@click="record"
style="background-color: #005ca3"
>
<cover-view>記錄</cover-view>
</cover-view>
<cover-view
class="sure df_hc_vc"
:style="{ 'background-color': endColor }"
@click="end"
>
<cover-view>結(jié)束</cover-view>
</cover-view>
</cover-view>
</cover-view>
<cover-view v-else class="end-mes-wrap df_hc_vc">
<cover-image
:src="Icons.common_deal_gou"
class="gou-icon"
></cover-image>
<cover-view> 恭喜您,今日巡邏已結(jié)束 </cover-view>
</cover-view>
<!--地圖上自制tabbar-->
<cover-view class="tab-bar">
<cover-view class="tab-bar-item df_hc_vc">
<cover-view style="width: 38rpx; height: 38rpx">
<cover-image
:src="Icons.common_deal_jrdk_a"
class="icon"
alt=""
/></cover-view>
<cover-view style="color: #005ca3">今日打卡</cover-view>
</cover-view>
<cover-view
class="tab-bar-item df_hc_vc"
@click="navigate('/pages/waiqing-baobei/index')"
>
<cover-view style="width: 38rpx; height: 38rpx">
<cover-image :src="Icons.common_deal_wqbb" class="icon" alt=""
/></cover-view>
<cover-view>外勤報(bào)備</cover-view>
</cover-view>
<cover-view
class="tab-bar-item df_hc_vc"
@click="navigate('/pages/punch-calender-xunluo/index')"
>
<cover-view style="width: 38rpx; height: 38rpx">
<cover-image :src="Icons.common_deal_kqrl" class="icon" alt=""
/></cover-view>
<cover-view>考勤日歷</cover-view>
</cover-view>
<cover-view
class="tab-bar-item df_hc_vc"
@click="navigate('/pages/punch-setting-remind/index')"
>
<cover-view style="width: 38rpx; height: 38rpx">
<cover-image :src="Icons.common_deal_kqtx" class="icon" alt=""
/></cover-view>
<cover-view>考勤提醒</cover-view>
</cover-view>
</cover-view>
</map>
</view>
</view>
</view>
</template>
<script>
import { common } from "@/mixin";
import {
locationLegal,
getToday,
addPatrolRecord,
gePatrolRecord,
addMove,
getMove,
} from "@/services/punch";
import LModal from "@/components/common/Modal";
import dayjs from "dayjs";
export default {
mixins: [common],
components: {
LModal,
MainTabBar,
},
data() {
return {
isShowModal: false,
modalTitle: "記錄信息",
xunluoing: true,
getStartInfo: true,
getEndInfo: true,
inputFocus: false, // input 框的focus狀態(tài)
inputModel: "", // input 框的輸入內(nèi)容
inputInfo: "請輸入搜索地址", // cover-view 顯示的 input 的輸入內(nèi)容,初始值充當(dāng)placeholder作用
id: "0", // 使用 marker點(diǎn)擊事件 需要填寫id
title: "map",
latitude: "",
longitude: "",
covers: [],
controls: [],
circles: [],
patrolRecords: [], //巡邏記錄
myClock: "",
polyline: [],
todayInfo: "",
attendanceId: "",
inputSerialNum: "",
lock: false,
lock1: false,
endColor: "#b6c9d8",
markerCtime: "",
markerContent: "",
showMarkModal: false,
xunluoStatus: "started",
};
},
onShow() {
//進(jìn)入首頁就定位
this.useLocation().then((res) => {
this.circles[0] = {};
this.circles[0].latitude = res.latitude;
this.circles[0].longitude = res.longitude;
getToday().then((res) => {
this.todayInfo = { ...res };
this.circles[0].radius = res.shouldStartLocation.radius;
this.circles[0].color = "#428BCA88";
this.circles[0].fillColor = "#B6E1F248";
this.circles[0].strokeWidth = "#B6E1F248";
});
// 獲取巡邏記錄
this.get();
});
},
filters: {
FormatTime: function (val) {
if (!val) {
return "-";
}
return dayjs(val).format("HH:mm:ss");
},
},
onLoad(options) {
if (options.attendanceId) {
uni.setStorageSync("attendanceId", options.attendanceId);
}
this.activeGetLocation();
},
beforeDestroy() {
console.log("銷毀了");
clearInterval(this.myClock);
},
computed: {
inputLength() {
return this.inputSerialNum.length;
},
},
methods: {
controlModal() {
this.showMarkModal = false;
},
navigate(url) {
uni.navigateTo({
url: url + "?xunluoStatus=" + this.xunluoStatus,
});
},
inputRecord(e) {
this.inputSerialNum = e.detail.value;
},
showModal() {
this.isShowModal = true;
},
handleCancel() {
this.isShowModal = false;
this.inputSerialNum = "";
},
handleConfirm() {
if (!this.lock) {
this.lock = true;
if (this.inputSerialNum.trim() == "") {
uni.showToast({
title: "請輸入記錄信息而涉!",
icon: "none",
duration: 2000,
});
this.lock = false;
return;
}
this.me_addPatrolRecord(this.inputSerialNum);
} else {
}
},
//5秒獲取添加一次定位
activeGetLocation() {
this.myClock = setInterval(() => {
console.log("我在ing");
this.me_addMove();
}, 5000);
},
me_addMove() {
this.getLocation().then(
(res) => {
var config = {};
config.attendanceId = uni.getStorageSync("attendanceId");
config.locations = [];
var location = {
longitude: res.longitude,
latitude: res.latitude,
};
config.locations.push(location);
//添加巡邏軌跡
addMove(config).then((res) => {});
//判斷是否在考勤范圍內(nèi)
var config = {
longitude: res.longitude,
latitude: res.latitude,
type: this.todayInfo.start ? "WORK" : "QUIT",
};
locationLegal(config).then((legal) => {
if (legal) {
this.endColor = "#005CA3";
}
});
},
(err) => {}
);
},
useLocation() {
return new Promise((resolve, reject) => {
this.getLocation().then(
(res) => {
this.longitude = res.longitude;
this.latitude = res.latitude;
resolve(res);
},
(err) => {}
);
});
},
getLocation() {
return new Promise((resolve, reject) => {
uni.getLocation({
type: "wgs84",
success: function (res) {
resolve(res);
},
fail: function (res) {
uni.showToast({
title: "未獲取到當(dāng)前位置著瓶!",
icon: "none",
duration: 2000,
});
reject(res);
},
});
});
},
showMark(e) {
var coverId = e.detail.markerId;
var tabCover = this.patrolRecords.find((item, index) => {
//生產(chǎn)標(biāo)記點(diǎn)
return coverId == item.id;
});
this.markerCtime = tabCover.createDate;
this.markerContent = tabCover.mark;
this.showMarkModal = !this.showMarkModal;
},
record() {
this.isShowModal = true;
this.showMarkModal = false;
},
end() {
if (this.endColor == "#b6c9d8") {
return;
}
var that = this;
uni.showModal({
title: "提示",
content: "確定結(jié)束嗎",
success: function (res) {
if (!that.lock1) {
if (res.confirm) {
that.lock1 = true;
// 1,判斷是否在考勤范圍內(nèi) 是才能結(jié)束
that.useLocation().then((res1) => {
var config = {
longitude: res1.longitude,
latitude: res1.latitude,
type: that.todayInfo.start ? "WORK" : "QUIT",
};
locationLegal(config).then((res) => {
if (res) {
clearInterval(that.myClock);
that.isShowModal = false;
//2,切換頁面樣式
that.xunluoing = false;
that.xunluoStatus = "end";
getMove({
attendanceId: uni.getStorageSync("attendanceId"),
}).then((res) => {
//3,展示巡邏軌跡
var points = res.map((item) => {
var obj = {};
obj.longitude = item.longitude;
obj.latitude = item.latitude;
return obj;
});
var pointsObj = {
//指定一系列坐標(biāo)點(diǎn)啼县,從數(shù)組第一項(xiàng)連線至最后一項(xiàng)
points: points,
color: "#005CA3", //線的顏色
width: 10, //線的寬度
dottedLine: true, //是否虛線
};
that.polyline.push(pointsObj);
//添加終點(diǎn)標(biāo)記點(diǎn)
var cover = {
id: Date.parse(new Date()),
longitude: res1.longitude,
latitude: res1.latitude,
iconPath:
"http://60.255.160.15:31314/government-affair/image/2020/1216/efa9c778130c415d82e5a0ea7d19468f.png",
width: 24,
height: 33,
};
that.covers.push(cover);
that.lock1 = false;
});
} else {
uni.showToast({
title: "不在考勤范圍內(nèi)",
icon: "none",
duration: 2000,
});
that.lock1 = false;
}
});
});
} else if (res.cancel) {
that.lock1 = false;
}
}
},
});
},
//獲取巡邏記錄
get() {
gePatrolRecord({ attendanceId: uni.getStorageSync("attendanceId") }).then(
(res) => {
//獲取巡邏記錄
this.patrolRecords = [...res]; //獲取所有巡邏記錄
if (this.patrolRecords.length > 0) {
this.patrolRecords.map((item, index) => {
//生產(chǎn)標(biāo)記點(diǎn)
var i = item.id;
if (this.patrolRecords.length <= 2) {
if (index == 0) {
//開始
iconPath =
"http://60.255.160.15:31314/government-affair/image/2020/1103/0573518208574b40851dac3a91dd5fe7.png";
}
if (index == 1) {
//結(jié)束
iconPath =
"http://60.255.160.15:31314/government-affair/image/2020/1216/14bdff0ac0594e20a11296d1a69ba89c.png";
}
} else {
var iconPath =
"http://60.255.160.15:31314/government-affair/image/2020/1216/14bdff0ac0594e20a11296d1a69ba89c.png";
if (index == 0) {
//開始
iconPath =
"http://60.255.160.15:31314/government-affair/image/2020/1103/0573518208574b40851dac3a91dd5fe7.png";
}
}
var cover = {
id: i,
latitude: item.locationLatitude,
longitude: item.locationLongitude,
iconPath: iconPath,
width: 24,
height: 33,
// callout: {
// // width: 286,
// // height: 141,
// // content: item.mark,
// // display: "BYCLICK",
// // bgColor: "#ffffff",
// // fontSize: "16",
// },
};
this.covers.push(cover);
});
} else {
this.covers[0] = {
id: 0,
latitude: res.latitude,
longitude: res.longitude,
iconPath:
"http://60.255.160.15:31314/government-affair/image/2020/1103/0573518208574b40851dac3a91dd5fe7.png",
width: 24,
height: 33,
};
}
}
);
},
//確定添加記錄
me_addPatrolRecord(val) {
var config = {};
config.attendanceId = uni.getStorageSync("attendanceId");
config.content = val;
this.getLocation().then(
(res) => {
config.location = {
longitude: res.longitude,
latitude: res.latitude,
};
this.isShowModal = false;
this.lock = true;
//添加巡邏記錄
addPatrolRecord(config).then((res) => {
// 然后再獲取 再產(chǎn)生標(biāo)記點(diǎn)
this.get();
});
},
(err) => {}
);
},
},
};
</script>
<style lang="scss" scoped>
.top-bar {
width: 100%;
height: 87rpx;
background: #ffffff;
box-shadow: 0px 9px 24px 0px rgba(0, 0, 0, 0.28);
.rule-wrap {
font-size: 28rpx;
font-family: PingFang SC;
font-weight: bold;
color: #333333;
margin-right: 30rpx;
.rule-icon {
margin-right: 14rpx;
width: 16rpx;
height: 32rpx;
}
}
}
.btn-wrap {
width: 420rpx;
height: 160rpx;
position: absolute;
right: 50%;
bottom: 12%;
transform: translate(50%, 0);
}
.out-border-radius {
border-radius: 80rpx;
}
.sure {
width: 210rpx;
height: 160rpx;
font-size: 32rpx;
color: #ffffff;
}
.end-mes-wrap {
width: 618rpx;
height: 78rpx;
background: #005ca3;
border-radius: 10rpx;
position: absolute;
right: 50%;
bottom: 12%;
transform: translate(50%, 0);
font-size: 32rpx;
color: #ffffff;
margin-left: 22rpx;
font-weight: bold;
}
.gou-icon {
width: 40rpx;
height: 33rpx;
margin-right: 22rpx;
}
.cover-modal {
position: absolute;
width: 572rpx;
height: 420rpx;
background: #ffffff;
border-radius: 20rpx;
top: 33rpx;
left: 50%;
transform: translate(-50%, 0);
overflow: hidden;
}
.modal-title {
padding-top: 41rpx;
padding-bottom: 40rpx;
padding-left: 40rpx;
font-size: 32rpx;
font-weight: bold;
color: #333333;
width: 574rpx;
border: 1rpx solid #eeeeee;
display: flex;
align-items: flex-end;
}
.modal-body {
border: 1px solid #eeeeee !important;
width: 490rpx;
height: 161rpx;
margin: 39rpx auto 0;
background-color: #fafafa !important;
}
.cancel {
background-color: #fff;
font-size: 28rpx;
font-weight: 500;
color: #999999;
}
.btn {
text-align: center;
width: 100%;
}
.textarea-btn-wrap {
height: 107rpx;
// padding: 35rpx 0;
width: 100%;
}
.l-textarea {
width: 490rpx;
height: 161rpx;
background-color: #fafafa !important;
border-radius: 5px;
position: relative;
font-size: 28rpx;
color: #999999;
padding: 20rpx 0 0 20rpx;
&.lg {
min-height: 161rpx;
}
}
.tab-bar {
/* 本身的樣式 */
background-color: #f6f6f6;
height: 96rpx;
border-top: 1rpx solid #eee;
box-shadow: 0rpx -1rpx 1rpx rgba(150, 150, 150, 0.08);
/* 定位相關(guān) */
position: fixed;
left: 0;
right: 0;
bottom: 0;
/* 利用flex進(jìn)行布局 */
display: flex;
text-align: center;
justify-content: space-around;
}
.tab-bar-item {
display: flex;
flex-direction: column;
text-align: center;
justify-content: center;
}
.icon {
width: 38rpx;
height: 38rpx;
margin-bottom: 5rpx;
}
.marker-modal {
width: 572rpx;
min-height: 282rpx;
background: #ffffff;
border-radius: 20px;
position: absolute;
top: 33rpx;
left: 50%;
transform: translate(-50%, 0);
overflow: hidden;
}
.marker-modal-body {
width: 486rpx;
min-height: 128rpx;
margin: 20rpx auto 0;
font-size: 28rpx;
color: #666666;
}
.marker-modal-title {
padding-top: 44rpx;
padding-bottom: 23rpx;
padding-left: 42rpx;
font-size: 32rpx;
font-weight: bold;
color: #333333;
width: 574rpx;
border: 1rpx solid #eeeeee;
display: flex;
align-items: flex-end;
}
</style>