浏览代码

地图选点

xiaohaizhao 1 年之前
父节点
当前提交
87853f36b8
共有 4 个文件被更改,包括 286 次插入54 次删除
  1. 6 1
      components/My_search.vue
  2. 243 33
      select/place/index.vue
  3. 32 0
      utils/tianditu.js
  4. 5 20
      utils/tool.js

+ 6 - 1
components/My_search.vue

@@ -3,7 +3,8 @@
         <view class="search" :style="{ background: background || '#F2F2F2' }">
             <icon class="icon" type="search" size="3.733vw" />
             <input v-model="value" class="input" :disabled="disabled" confirm-type="search"
-                placeholder-style="font-size:3.733vw;" :placeholder="placeholder" type="text" @confirm="onConfirm">
+                placeholder-style="font-size:3.733vw;" :placeholder="placeholder" type="text"
+                @input="isInput ? onConfirm($event) : ''" @confirm="isInput ? '' : onConfirm($event)">
             <icon v-if="value" class="icon" type="clear" size="3.733vw" @click="onClear" />
         </view>
         <slot />
@@ -26,6 +27,10 @@ export default {
         },
         background: {
             type: String
+        },
+        isInput: {
+            type: Boolean,
+            default: false
         }
     },
     data() {

+ 243 - 33
select/place/index.vue

@@ -1,71 +1,281 @@
 <template>
     <view>
-        <map id="Mymap" class="Mymap" :longitude="my.longitude" :latitude="my.latitude" scale="16" :markers="markers"
-            bindregionchange="" bindtap="" bindupdated="" />
+        <map id="Mymap" class="Mymap" :longitude="choose.longitude" :latitude="choose.latitude" show-location scale="16"
+            :markers="markers" />
         <view class="search-box">
-            <My_search />
+            <picker v-if="area.show" :value="area.name" mode="region" level="city" @change="regionChange">
+                <view class="picker">
+                    <view class="name">
+                        {{ area.name[1] }}
+                    </view>
+                    <view class="iconfont icon-a-wodetiaozhuan" />
+                </view>
+            </picker>
+            <view style="flex: 1;margin-left: 10px;">
+                <My_search @onSearch="onSearch" isInput />
+            </view>
         </view>
-        <My_listbox boxBackground="#fff">
-
-
+        <My_listbox boxBackground="#fff" bottomHeight="70" pullDown="false">
+            <view v-if="list.length == 0" style="padding-top: 6vw;">
+                <u-empty mode="search" />
+            </view>
+            <view class="item" @click="changeChoose(item)"
+                :style="{ background: choose.lonlat == item.lonlat ? '#F8FBFF' : '#fff' }" v-for="item in list"
+                :key="item.lonlat" hover-class="navigator-hover">
+                <view class="name">
+                    {{ item.name }}
+                </view>
+                <view class="address">
+                    {{ getCity(item) }}
+                </view>
+            </view>
         </My_listbox>
+        <view class="footer">
+            <view class="confirm" :class="choose.name ? '' : 'forbidden'" @click="choose.name ? submit() : ''"
+                hover-class="navigator-hover">
+                确定
+            </view>
+        </view>
     </view>
 </template>
 
 <script>
+import { tianditu } from "../../utils/tianditu.js"
+const api = new tianditu();
+
 export default {
     data() {
         return {
-            my: {
+            keyWord: "",
+            choose: {
                 longitude: "",
                 latitude: ""
             },
-            markers: []
+            area: {
+                show: false,
+            },
+            markers: [],
+            list: [],
+            circumjacents: []
         }
     },
-    onLoad() {
-        this.getLocation(true).then(my => {
-            this.my = my;
-            console.log(my)
+    onLoad(options) {
+        this.getLocation(true).then(location => {
+            this.choose = location;
+            api.getPlace(location.longitude, location.latitude).then(place => {
+                console.log("逆解析", place)
+                if (place.msg == 'ok') {
+                    this.list = [{
+                        ...place.result.addressComponent,
+                        name: place.result.addressComponent.poi,
+                        lonlat: `${location.longitude},${location.latitude}`,
+                        ...location
+                    }]
+
+                    this.choose = this.list[0];
+
+                    this.markers = [{
+                        longitude: this.choose.longitude,
+                        latitude: this.choose.latitude
+                    }];
+
+                    this.area = {
+                        show: true,
+                        name: [place.result.addressComponent.province, place.result.addressComponent.city, place.result.addressComponent.county],
+                        specify: [place.result.addressComponent.province_code, place.result.addressComponent.city_code, place.result.addressComponent.county_code]
+                    }
+
+                    this.getCircumjacent(place.result);
+                } else {
+                    uni.showModal({
+                        title: '提示',
+                        content: '获取位置失败',
+                        showCancel: false,
+                    })
+                }
+            })
         })
         uni.setNavigationBarTitle({
-            title: '地图选点'
+            title: options.title || '选择地点'
         });
-        setTimeout(() => {
-            this.$Http.basic({
-                id: "10030901",
-                content: {
-                    postStr: {
-                        "yingjiType": 1,
-                        "sourceType": 0,
-                        "keyWord": "楚楚吊顶",
-                        "level": 6,
-                        "mapBound": "113.75989136166874,29.393072654041134,128.27534863832096,32.031873462231246",
-                        "queryType": "4",
-                        "start": 0,
-                        "count": 10,
-                        "queryTerminal": 10000
+    },
+    methods: {
+        getCircumjacent(place) {
+            api.placeNameSearch({
+                keyWord: place.addressComponent.road,
+                queryRadius: "1000",
+                pointLonlat: `${place.location.lon},${place.location.lat}`,
+                queryType: 3,
+                start: 0,
+                count: 5,
+                dataTypes: "公司,标志性建筑物,家装建材零售,家居用品,五金,电器零售,工业园",
+                show: 2
+            }).then(res => {
+                console.log("地址", res)
+                for (const key in res) {
+                    if (key != 'keyWord' && res[key].pois) {
+                        this.list = this.unique(this.list.concat(res[key].pois.map(v => {
+                            let lonlat = v.lonlat.split(",")
+                            v.longitude = lonlat[0]
+                            v.latitude = lonlat[1]
+                            return v
+                        })), 'lonlat')
+                        this.circumjacents = JSON.parse(JSON.stringify(this.list))
                     }
                 }
-            }).then(res => {
-                console.log("搜索地点", res)
             })
-        }, 500)
-
-    }
+        },
+        regionChange({ detail }) {
+            this.area = {
+                show: true,
+                name: detail.value,
+                specify: detail.code.map(v => "156" + v),
+            }
+            console.log(this.area)
+            if (this.keyWord) this.onSearch(this.keyWord)
+        },
+        unique(arr, key) {
+            for (let i = 0; i < arr.length; i++) {
+                for (let j = i + 1; j < arr.length; j++) {
+                    if (arr[i][key] == arr[j][key]) {
+                        arr.splice(j, 1);
+                        j--;
+                    };
+                };
+            };
+            return arr;
+        },
+        changeChoose(item) {
+            this.choose = item;
+            this.markers = [{
+                longitude: item.longitude,
+                latitude: item.latitude
+            }];
+        },
+        onSearch(keyWord) {
+            this.keyWord = keyWord;
+            if (!keyWord) {
+                this.list = this.circumjacents;
+            } else {
+                api.placeNameSearch({
+                    keyWord: keyWord,
+                    specify: this.area.specify[1],
+                    queryType: 12,
+                    start: 0,
+                    count: 30,
+                    show: 2
+                }).then(res => {
+                    console.log("搜索地址", res)
+                    if (res.pois) {
+                        this.list = this.unique(res.pois.map(v => {
+                            let lonlat = v.lonlat.split(",")
+                            v.longitude = lonlat[0]
+                            v.latitude = lonlat[1]
+                            return v
+                        }), 'lonlat')
+                    } else {
+                        this.list = [];
+                        this.markers = [];
+                        this.choose = {
+                            longitude: "",
+                            latitude: ""
+                        };
+                    }
+                })
+            }
+            if (this.list.length) {
+                this.choose = this.list[0];
+                this.markers = [{
+                    longitude: this.choose.longitude,
+                    latitude: this.choose.latitude
+                }];
+            }
+        },
+        submit() {
+            console.log('提交', this.choose)
+        }
+    },
 }
 </script>
 
 <style lang="scss" scoped>
 .Mymap {
     width: 100vw;
-    height: 300px;
+    height: 37vh;
 }
 
 .search-box {
+    display: flex;
+    align-items: center;
     width: 100vw;
     padding: 10px;
     box-sizing: border-box;
     background: #fff;
+
+    .picker {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+
+        .icon-a-wodetiaozhuan {
+            transform: rotate(90deg);
+            margin-left: 4px;
+        }
+    }
+
+
+}
+
+.item {
+    width: 100vw;
+    margin: 0 auto;
+    // border-bottom: .5px solid #ddd;
+    padding: 10px;
+    box-sizing: border-box;
+
+    .name {
+        line-height: 20px;
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-weight: bold;
+        font-size: 14px;
+        color: #333333;
+        margin-bottom: 5px;
+    }
+
+    .address {
+        line-height: 17px;
+        font-family: Source Han Sans SC, Source Han Sans SC;
+        font-size: 12px;
+        color: #999999;
+    }
+}
+
+.footer {
+    position: fixed;
+    bottom: 0;
+    width: 100vw;
+    height: 65px;
+    background: #FFFFFF;
+    box-shadow: 0px -2px 6px 1px rgba(0, 0, 0, 0.16);
+    box-sizing: border-box;
+    padding: 5px 10px;
+    z-index: 2;
+
+    .confirm {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 100%;
+        height: 45px;
+        background: #C30D23;
+        border-radius: 5px;
+        font-family: PingFang SC, PingFang SC;
+        font-size: 14px;
+        color: #FFFFFF;
+    }
+
+    .forbidden {
+        opacity: .6;
+    }
 }
 </style>

+ 32 - 0
utils/tianditu.js

@@ -0,0 +1,32 @@
+/* 文档 http://lbs.tianditu.gov.cn/server/search2.html */
+
+class tianditu {
+    /* 逆解析 */
+    getPlace(lon, lat) {
+        return this.request(`/geocoder?postStr={'lon':${lon},'lat':${lat},'ver':1}&type=geocode`)
+    }
+    /* 地名搜索 */
+    placeNameSearch(data = {}) {
+        return this.request(`/v2/search?postStr=${JSON.stringify(data)}&type=query`)
+    }
+    request(query, method = 'GET') {
+        const tks = ['524ebc3954aaa26259f80ea937a3f569', '8aad97b24c38ed6643207de9da174b98', '47bb2ca36a43839fd7c45e2d762561f8'],
+            url = 'https://api.tianditu.gov.cn' + query + `&tk=${tks[ Math.floor(Math.random() * tks.length)]}`
+        return new Promise((resolve, reject) => {
+            this._request(url, method, resolve)
+        })
+    }
+    _request(url, method, resolve) {
+        uni.request({
+            url,
+            method,
+            success: (res) => {
+                resolve(res.data)
+            }
+        });
+    }
+}
+
+export {
+    tianditu
+}

+ 5 - 20
utils/tool.js

@@ -29,33 +29,18 @@ function setBar() {
 
 function mount() {
     Vue.prototype.qrCodePrefix = "https://www.jiushengboard.cc/";
-    Vue.prototype.getLocation = (isReverseGeocoder = false) => {
+
+    Vue.prototype.getLocation = (isHighAccuracy = false) => {
         return new Promise((resolve, reject) => {
             let that = this;
             handle()
-
             function handle() {
-                /*     altitude: true,
-                    highAccuracyExpireTime: 8000,
-                    isHighAccuracy: true, */
                 uni.getLocation({
+                    isHighAccuracy,
+                    highAccuracyExpireTime: isHighAccuracy ? 8000 : '',
                     success: res => {
                         console.log("获取定位", res)
-                        if (isReverseGeocoder) {
-                            Vue.prototype.$Http.basic({
-                                "id": "10027201",
-                                "content": {
-                                    "lon": res.longitude,
-                                    "lat": res.latitude
-                                }
-                            }).then(s => {
-                                console.log("定位", s)
-                                res.result = s.data.result;
-                                resolve(res)
-                            })
-                        } else {
-                            resolve(res)
-                        }
+                        resolve(res)
                     },
                     fail: err => {
                         console.log("获取位置失败", err)