Explorar o código

Merge remote-tracking branch 'origin/master'

yangyuxuan hai 6 meses
pai
achega
e0adbbcb16

+ 363 - 0
src/components/PositionSelect/index.vue

@@ -0,0 +1,363 @@
+<template>
+  <van-dialog v-model:show="showPositionSelect" title="请选择地点" show-cancel-button @close="handleClose" @confirm="submit">
+    <div class="position-container">
+      <div style="position: relative">
+        <div class="box">
+          <van-search
+              v-model="form.address"
+              show-action
+              label="详细地址"
+              left-icon="none"
+              placeholder="请输入"
+              @search="handleInput"
+          >
+            <template #action>
+              <div @click="handleInput">搜索</div>
+            </template>
+          </van-search>
+        </div>
+        <div v-if="searchPop" class="scroll_box">
+          <div class="scroll-header">
+            <span>搜索结果列表</span>
+            <i class="close-icon" @click="closeSearchList()" />
+          </div>
+
+          <div class="scroll">
+            <div v-for="(item, index) in searchList" v-show="searchList.length" :key="index" class="item" @click="handlePanTo(index)">
+              <van-image width="50" height="50" fit="fill" :src="item.img" style="flex-shrink: 0; margin-right: 8px;" />
+              <div>
+                <div class="text">{{ item.name }}</div>
+                <div>{{ item.address }}</div>
+              </div>
+            </div>
+            <div v-show="!searchList.length" class="empty" style="text-align: center">没有搜索到内容</div>
+          </div>
+        </div>
+      </div>
+      <van-field v-model="form.longitude" label="经度" placeholder="请输入" />
+      <van-field v-model="form.latitude" label="纬度" placeholder="请输入" />
+      <div id="map" class="map" />
+    </div>
+  </van-dialog>
+
+</template>
+
+<script  lang="ts" setup name="PositionSelect">
+import AMapLoader from '@amap/amap-jsapi-loader';
+import { useRouter } from 'vue-router';
+import { addEvent } from '@/api/emergencyCommandMap/JointDuty';
+import {nextTick, onUnmounted, reactive, ref, watch} from "vue";
+import {showFailToast} from "vant";
+
+const props = defineProps({
+  address: {//公司地址
+    type: String,
+    default: () => {
+      return '';
+    },
+  },
+  lnglat: {//经纬度
+    type: Array,
+    default: () => {
+      return [];
+    },
+  },
+  visible: {
+    type: Boolean,
+    default: () => {
+      return false;
+    }
+  }
+});
+const emits = defineEmits(['update:visible', 'confirm']);
+let showPositionSelect = ref(false);
+// 地图对象
+let map = null;
+let amap = {};
+let marker = null; //地图上的点标记
+let contextMenu = null;
+let lnglatPosition = ref([]); //选中的新坐标
+let pageNum = ref(1);
+let pageSize = ref(10);
+let total = ref(0);
+
+let searchList = ref([]);
+let searchPop = ref(false);
+let placeSearch;
+let form = reactive({
+  address: '',
+  longitude: '',
+  latitude: ''
+});
+let geocoder = {};
+watch(
+    () => props.visible,
+    (n) => {
+      if (n) {
+        showPositionSelect.value = n;
+        nextTick(() => {
+          initMap();
+          form.address = props.address;
+          handleInput(0)
+        });
+      }
+    },
+    {
+      immediate: true
+    }
+);
+onUnmounted(() => {
+  if (!!map) {
+    map.off('rightclick');
+    map.destroy();
+    map = null;
+  }
+});
+function handleInput(flag?: any) {
+  if (!form.address) return;
+
+  if (!flag) {
+    //搜索
+    total.value = 0;
+    pageNum.value = 1;
+  }
+
+  if (!placeSearch) {
+    placeSearch = new amap.PlaceSearch({
+      pageSize: pageSize.value, // 每页条数,默认10,范围1-50
+      pageIndex: pageNum.value, // 页码
+      extensions: 'all' // 默认base,返回基本地址信息;all:返回详细信息
+    });
+  }
+
+  searchPop.value = true;
+  placeSearch.setPageIndex(pageNum.value);
+  placeSearch.search(form.address, (status, result) => {
+    // console.log(result.poiList.pois, 'result')
+    if (!!result.poiList && result.poiList.pois && result.poiList.pois.length > 0) {
+      let arr = [];
+      const pois = result.poiList.pois;
+      total.value = result.poiList ? result.poiList.count : 0;
+      arr = pois.map((item) => {
+        return {
+          name: item.name,
+          address: item.address,
+          img: item.photos[0]?.url,
+          lnglat: [item.location.lng, item.location.lat]
+        };
+      });
+      searchList.value = arr;
+    } else {
+      total.value = 0;
+      searchList.value = [];
+    }
+  });
+}
+function handleChangePage(newNum) {
+  if (!searchPop.value) return;
+  pageNum.value = newNum;
+  handleInput(1);
+}
+function closeSearchList() {
+  searchPop.value = false;
+  searchList.value = [];
+  total.value = 0;
+  pageNum.value = 1;
+}
+// 地图中心的平移至指定点位置
+function handlePanTo(index) {
+  let lnglat = searchList.value[index].lnglat;
+  form.address = searchList.value[index].name + '(' + searchList.value[index].address + ')';
+  form.longitude = lnglat[0];
+  form.latitude = lnglat[1];
+
+  map.panTo(lnglat);
+  setMarks(lnglat);
+  closeSearchList();
+}
+const updateForm = (position) => {
+  form.longitude = position[0];
+  form.latitude = position[1];
+  geocoder.getAddress(position, (status, result) => {
+    if (status === 'complete' && result.info === 'OK') {
+      form.address = result.regeocode.formattedAddress;
+    }
+  });
+};
+const initMap = async () => {
+  window._AMapSecurityConfig = {
+    securityJsCode: '4868bc1b8fac7d9e54e7279ed556879a'
+  };
+  const AMap = await AMapLoader.load({
+    key: '9c5041381e5e824f9ee324d8f7a40150', // 申请好的Web端开发者Key,首次调用 load 时必填
+    version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+    plugins: ['AMap.PlaceSearch', 'AMap.ContextMenu', 'AMap.PolygonEditor', 'AMap.Geocoder'] // 插件列表
+  });
+  let position = [110.925175, 21.678955];
+  if (props.lnglat && props.lnglat.length > 0) {
+    position = props.lnglat
+  } else {
+    AMap.plugin('AMap.Geolocation', function() {
+      var geolocation = new AMap.Geolocation({
+        enableHighAccuracy: true, // 是否使用高精度定位,默认:true
+        timeout: 10000, // 设置定位超时时间,默认:无穷大
+        offset: [10, 20],  // 定位按钮的停靠位置的偏移量
+        zoomToAccuracy: true,  //  定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
+        position: 'RB' //  定位按钮的排放位置,  RB表示右下
+      })
+
+      geolocation.getCurrentPosition(function(status,result){
+        if(status=='complete'){
+          updateForm(position);
+          setMarks(position);
+        } else{
+          showFailToast('获取定位失败,请手动拖拽选点');
+        }
+      });
+    })
+  }
+  map = new AMap.Map('map', {
+    viewMode: '3D', //是否为3D地图模式
+    center: position,
+    zoom: 15
+  });
+  amap = AMap;
+  geocoder = new AMap.Geocoder({
+    // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
+    city: '010'
+  });
+  // 创建右键菜单
+  ContextMenu();
+  map.on('rightclick', handleRightclick);
+  map.on('complete', () => {
+    if (!props.address) {
+      updateForm(position);
+    } else {
+      form.longitude = position[0];
+      form.latitude = position[1];
+    }
+    setMarks(position);
+  });
+};
+function ContextMenu() {
+  contextMenu = new AMap.ContextMenu();
+  contextMenu.addItem(
+      '选择标点',
+      () => {
+        form.longitude = lnglatPosition.value[0];
+        form.latitude = lnglatPosition.value[1];
+        contextMenu.close();
+        let lnglat = [form.longitude, form.latitude];
+        geocoder.getAddress(lnglat, (status, result) => {
+          if (status === 'complete' && result.info === 'OK') {
+            form.address = result.regeocode.formattedAddress;
+          }
+        });
+        updateForm(lnglat);
+        setMarks(lnglat);
+      },
+      1
+  );
+}
+// 右键事件
+function handleRightclick(e) {
+  let lnglat = [e.lnglat.getLng(), e.lnglat.getLat()];
+  contextMenu.open(map, e.lnglat);
+  lnglatPosition.value = lnglat;
+}
+function setMarks(lnglat) {
+  //添加标记
+  if (marker) map.remove(marker);
+  marker = new AMap.Marker({
+    position: lnglat,
+    icon: new AMap.Icon({
+      size: new AMap.Size(22, 28), //图标所处区域大小
+      imageSize: new AMap.Size(22, 28), //图标大小
+      image: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png'
+    }),
+    draggable: true,
+    anchor: 'bottom-center',
+    offset: new AMap.Pixel(0, 0)
+  });
+  marker.on('dragend', (e) => {
+    updateForm([e.lnglat.lng, e.lnglat.lat]);
+  });
+  marker.setMap(map);
+}
+function handleClose() {
+  emits('update:visible', false);
+}
+let queryFormRef = ref();
+
+function submit() {
+  emits('confirm', { lnglat: [form.longitude, form.latitude], address: form.address });
+  handleClose();
+}
+</script>
+
+<style  lang="scss"scoped>
+.position-container {
+  height: calc(100vh - 250px);
+  min-height: 60%;
+  display: flex;
+  flex-direction: column;
+  .position-header {
+    font-size: 16px;
+    font-weight: bold;
+    height: 45px;
+    line-height: 45px;
+    border-bottom: 1px solid #eeeeee;
+    padding: 0 10px;
+    color: #445267;
+  }
+  #map {
+    width: 100%;
+    flex: 1;
+  }
+}
+.scroll_box {
+  width: 100%;
+  background-color: #fff;
+  position: absolute;
+  left: 0;
+  top: 45px;
+  z-index: 9;
+  padding: 10px;
+  border-radius: 3px;
+  .scroll-header {
+    height: 45px;
+    line-height: 45px;
+    font-size: 16px;
+  }
+  .close-icon {
+    position: absolute;
+    right: 10px;
+    top: 10px;
+    cursor: pointer;
+    font-size: 20px;
+    width: 30px;
+    height: 30px;
+    background: url('@/assets/images/close.png') no-repeat;
+    background-size: 100% 100%;
+  }
+}
+.scroll {
+  width: 100%;
+  height: 380px;
+  overflow-y: auto;
+
+  .item {
+    display: flex;
+    font-size: 14px;
+    cursor: pointer;
+    padding: 8px;
+    .text {
+      color: #3385ff;
+      margin-bottom: 6px;
+    }
+  }
+}
+.box {
+  border-bottom: 1px solid #eeeeee;
+}
+</style>

+ 3 - 0
src/views/event/PositionSelect.vue

@@ -201,6 +201,9 @@ const updateForm = (position) => {
 };
 const initMap = async () => {
   let position = [110.925175, 21.678955];
+  window._AMapSecurityConfig = {
+    securityJsCode: '4868bc1b8fac7d9e54e7279ed556879a'
+  };
   const AMap = await AMapLoader.load({
     key: '9c5041381e5e824f9ee324d8f7a40150', // 申请好的Web端开发者Key,首次调用 load 时必填
     version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15

+ 7 - 2
src/views/mobileControl/PositionSelect.vue

@@ -55,9 +55,11 @@ const props = defineProps({
     default: () => {
       return false;
     }
+  },
+  lnglat: {
+    type: Number
   }
 });
-const router = useRouter();
 const emits = defineEmits(['update:visible', 'confirm']);
 let showPositionSelect = ref(false);
 // 地图对象
@@ -202,10 +204,13 @@ const updateForm = (position) => {
 };
 const initMap = async () => {
   let position = [110.925175, 21.678955];
+  window._AMapSecurityConfig = {
+    securityJsCode: '4868bc1b8fac7d9e54e7279ed556879a'
+  };
   const AMap = await AMapLoader.load({
     key: '9c5041381e5e824f9ee324d8f7a40150', // 申请好的Web端开发者Key,首次调用 load 时必填
     version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
-    plugins: ['AMap.PlaceSearch', 'AMap.ContextMenu', 'AMap.PolygonEditor', 'AMap.Geocoder'] // 插件列表
+    plugins: ['AMap.PlaceSearch', 'AMap.ContextMenu', 'AMap.PolygonEditor', 'AMap.Geocoder', 'AMap.Geolocation'] // 插件列表
   });
   map = new AMap.Map('map', {
     viewMode: '3D', //是否为3D地图模式

+ 19 - 0
src/views/mobileControl/TaskProgressUpdate.vue

@@ -43,6 +43,16 @@
                 </FileUpload>
               </template>
             </van-field>
+            <van-field
+                v-model="form.address"
+                class="common-field"
+                right-icon="location"
+                readonly
+                label="位置信息"
+                placeholder="点击获取当前位置信息"
+                :rules="rules.processing_status"
+                @click="isGetAddress = true"
+            />
           </div>
         </div>
       </div>
@@ -59,6 +69,7 @@
           @confirm="onConfirm"
       />
     </van-popup>
+    <PositionSelect v-if="isGetAddress" v-model:visible="isGetAddress" :address="form.address" :lnglat="form.lnglat" @confirm="handlePositionSelect" />
   </div>
 </template>
 
@@ -74,11 +85,14 @@ import {validateFile} from "@/utils/validate";
 const route = useRoute();
 const router = useRouter();
 let id = ref('');
+let isGetAddress = ref(false);
 // 表单数据
 const form = ref({
   processing_status: '',
   processing_status_text: '',
   feedback_content: '',
+  address: '',
+  lnglat: [],
   fileList: []
 });
 const pickerValue = ref<Numeric[]>([]);
@@ -114,6 +128,11 @@ const handleFileListChange = () => {
   uploaderErrors.value = '';
   return flag;
 };
+// 地点选择回调
+const handlePositionSelect = (data) => {
+  form.value.lnglat = data.lnglat;
+  form.value.address = data.address;
+}
 // 返回
 const onCancel = () => {
   router.go(-1);