小程序 uni地图上显示弹窗,包含textarea,点击标记点弹出自定义弹窗,实时记录位置展示线路

最近在小程序做巡逻打卡功能,现在记录一下用到的api和实现的方式。
包括:可随时添加标记点,并且在地图上显示弹窗,包含textarea,在上面记录信息。然后实时显示出添加的标记,点击标记会弹出自定义弹窗,展示记录的内容。并且实时记录位置巡逻结束后会展示线路。

<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解决真机上 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设置圆角的限制-->
                <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>
            <!--点击标记点弹出自定义弹窗 -->
          <cover-view
            @click="controlModal"
            class="marker-modal"
            v-show="showMarkModal"
          >
     <!-- marker-modal-title 的样式解决 cover-view不能对某一边r设置border的限制 主要是给目标元素加上4个边的border,然后使其超出父元素 然后父元素overflow:hidden,这样看起来就只有一个边-->
            <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设置圆角的限制 主要是在元素的外层套一个 <cover-view>然后把形状设置为长方形,然后对这个外层设置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>结束</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> 恭喜您,今日巡逻已结束 </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>外勤报备</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状态
      inputModel: "", // input 框的输入内容
      inputInfo: "请输入搜索地址", // cover-view 显示的 input 的输入内容,初始值充当placeholder作用
      id: "0", // 使用 marker点击事件 需要填写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() {
    //进入首页就定位
    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) => {});
          //判断是否在考勤范围内
          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: "未获取到当前位置!",
              icon: "none",
              duration: 2000,
            });
            reject(res);
          },
        });
      });
    },
    showMark(e) {
      var coverId = e.detail.markerId;
      var tabCover = this.patrolRecords.find((item, index) => {
        //生产标记点
        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: "确定结束吗",
        success: function (res) {
          if (!that.lock1) {
            if (res.confirm) {
              that.lock1 = true;
              // 1,判断是否在考勤范围内 是才能结束
              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 = {
                        //指定一系列坐标点,从数组第一项连线至最后一项
                        points: points,
                        color: "#005CA3", //线的颜色
                        width: 10, //线的宽度
                        dottedLine: true, //是否虚线
                      };
                      that.polyline.push(pointsObj);
                      //添加终点标记点
                      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: "不在考勤范围内",
                      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) => {
              //生产标记点
              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) {
                  //结束
                  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) => {
            // 然后再获取 再产生标记点
            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);

  /* 定位相关 */
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;

  /* 利用flex进行布局 */
  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>


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,113评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,644评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,340评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,449评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,445评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,166评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,442评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,105评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,601评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,066评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,161评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,792评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,351评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,352评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,584评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,618评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,916评论 2 344

推荐阅读更多精彩内容