You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

433 lines
12 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="tm-mapSelectedPoint" :class="[black_tmeme?'grey-darken-5':'']">
<map :scale="mapscale" id="MapTm" ref="MapTm" @regionchange="moveMapChange" :markers="markers" :latitude="mapCenter.lat" :longitude="mapCenter.lng" :style="{width:`${width}rpx`,height:`400rpx`}"></map>
<view class=" pa-32 ">
<view class="tm-mapSelectedPoint-contr">
<view class="pb-32"><text class=" text-size-n fulled text-overflow-1">当前:{{adress.adress||"获取失败,请移动地图选择"}}</text></view>
<view class="flex-between pb-10">
<tm-button @click="confirm" block height="80" style="width:60%">确认位置</tm-button>
<view style="width:35%" class="flex-shrink">
<tm-button :black="black_tmeme" :fllowTheme="fllowTheme" :theme="color_tmeme" @click="getLocation" text block height="80" icon="icon-position-fill">定位当前</tm-button>
</view>
</view>
</view>
<view v-if="adressList.length>0" class="grey-lighten-5 px-24 round-6 mt-32" :class="[black_tmeme?'bk grey-darken-4':'']">
<scroll-view scroll-y :style="{height: scrollHeight+'px'}">
<view @click="selecListitem(item)" v-for="(item,index) in adressList" :key="index" :class="[black_tmeme?'bk':'']" class="py-24 border-b-1 flex-between">
<view class="mr-32">
<view class="pb-12"> {{item.name}}</view>
<view class="text-size-s text-grey">{{item.address}}</view>
</view>
<view class="flex-shrink">
<tm-icons :black="black_tmeme" :fllowTheme="fllowTheme" :color="color_tmeme" size="40" v-if="activeId == item.id" name="icon-check-circle"></tm-icons>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
/**
* 地图选点
* @property {Boolean|String} black = [true|false] 默认null,是否开启暗黑模式
* @property {String} color = [] 主题默认:primary提供是请写主题色名称
* @property {String} map-key = [] 地图key:默认为作者测试的用户不要使用我的否则会被限制key作废。
* @property {String} map-type = [] 地图类型:qqqq,baidu,amp高德。
* @property {Number} scale = [] 默认:14地图绽放级别5-18
* @property {Number} width = [] 默认:700组件的宽度。
* @property {Number} height = [] 默认:1200组件的高度。
* @property {Object} location = [] 默认:{latitude:39.908823,longitude:116.39747},默认的定位点,北京。
* @property {Function} confirm 点击确认位置按钮时返回当前定位资料信息。
* @property {Function} change 当移动地图时的位置信息返回的结构同confirm
*/
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
export default {
name:"tm-mapSelectedPoint",
components:{tmButton,tmIcons},
props:{
width:{
type:Number|String,
default:700
},
height:{
type:Number|String,
default:1200
},
location:{
type:Object,
default:()=>{
return {
latitude:0,
longitude:0
}
}
},
scale:{
type:Number,
default:14
},
// 是否开启暗黑模式
black: {
type: String | Boolean,
default: null
},
color: {
type: String | Array,
default: 'primary'
},
// 跟随主题色的改变而改变。
fllowTheme: {
type: Boolean | String,
default: true
},
mapKey:{
type:String,
default:'U3QBZ-3YIKI-YBEGX-5WURG-5ZQE6-ZGFME'
},
mapType:{
type:String,
default:'qq' //qq,baidu,amp
}
},
watch: {
location:{
deep:true,
async handler(newValue, oldValue) {
this.moveMap(newValue.latitude,newValue.longitude)
await this.moveMarkes(newValue.latitude,newValue.longitude)
}
}
},
data() {
return {
now_latitude:0,
now_longitude:0,
mapCenter:{
lat:0,
lng:0
},
markers:[],
timeid:9566555566,
adressList:[],
adress:{
adress:'',
city:[]
},
scrollHeight:0,
activeId:'',
map:null,
};
},
computed:{
black_tmeme: function() {
if (this.black !== null) return this.black;
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme: function() {
if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
.fllowTheme) {
return this.$tm.vx.state().tmVuetify.color;
}
return this.color;
},
mapscale:function(){
return this.scale;
}
},
created() {
this.now_latitude = this.location.latitude;
this.now_longitude = this.location.longitude;
this.mapCenter = {
lat:this.location.latitude,
lng:this.location.longitude
}
},
async mounted() {
let t = this;
this.map = uni.createMapContext("MapTm", this)
let q = await this.$Querey('.tm-mapSelectedPoint-contr',this).catch(e=>{});
let h = q[0].height||80;
this.scrollHeight = uni.upx2px(this.height) - uni.upx2px(400) - h;
// #ifdef MP
uni.authorize({
scope: 'scope.userLocation',
success() {
t.mapready();
}
})
// #endif
// #ifndef MP
this.$nextTick(async function(){
await uni.$tm.sleep(200)
await this.mapready();
})
// #endif
},
methods: {
moveMap(latitude,longitude){
this.map.moveToLocation({
latitude:latitude,
longitude:longitude
})
},
async mapready(){
let t = this;
// #ifndef H5
uni.getSetting({
success: async (res) => {
if(!res.authSetting['scope.userLocation']){
uni.showModal({
title:"权限受限",
content:"你禁止了位置受限,请打开设置,允许访问地址!否则功能无法使用。",
cancelText:"我已允许",
confirmText:"前往设置",
success: async (rks) => {
if(rks.cancel==true){
await t.getLocation();
return
}
uni.openSetting({})
}
})
return;
}
if(t.mapCenter.lat !==0 && t.mapCenter.lng!==0){
t.markers = [t.createMarker( t.mapCenter.lat ,t.mapCenter.lng)]
await t.poiSidel_byTencentMap(t.mapCenter.lat ,t.mapCenter.lng)
return;
}
await t.getLocation();
},
fail: (res) => {
uni.$tm.toast("系统错误")
}
})
// #endif
// #ifdef H5
if(t.mapCenter.lat !==0 && t.mapCenter.lng!==0){
t.markers = [t.createMarker( t.mapCenter.lat ,t.mapCenter.lng)]
await t.poiSidel_byTencentMap(t.mapCenter.lat ,t.mapCenter.lng)
return;
}
await this.getLocation();
// #endif
},
confirm(){
this.$emit('confirm',{...this.adress,latitude:this.now_latitude,longitude:this.now_longitude})
},
async getLocation() {
let t = this;
//非h5通过GPS定位 。
// #ifndef H5
uni.getSetting({
success: async (res) => {
if(!res.authSetting['scope.userLocation']){
uni.showModal({
title:"权限受限",
content:"你禁止了位置受限,请打开设置,允许访问地址!否则功能无法使用。",
cancelText:"我已允许",
confirmText:"前往设置",
success: async (rks) => {
if(rks.cancel==true){
await t.getLocation();
return
}
uni.openSetting({})
}
})
return;
}
uni.getLocation({
type: 'gcj02', //返回可以用于uni.openLocation的经纬度
success:async function (res) {
const latitude = res.latitude;
const longitude = res.longitude;
t.now_latitude = latitude;
t.now_longitude = longitude;
t.mapCenter = {
lat:latitude,
lng:longitude
}
t.moveMap(t.mapCenter.lat,t.mapCenter.lng)
await t.moveMarkes(latitude,longitude)
//缓存定位点。否则失败间隔15s小于15秒。不允许调用。
uni.setStorageSync('tmvue_map_selectePoint',{latitude:latitude,longitude:longitude})
},
fail: async (err) => {
let p = uni.getStorageSync('tmvue_map_selectePoint');
try{
if(typeof p == 'object'){
const latitude = p .latitude;
const longitude = p .longitude;
t.now_latitude = latitude;
t.now_longitude = longitude;
t.mapCenter = {
lat:latitude,
lng:longitude
}
t.moveMap(t.mapCenter.lat,t.mapCenter.lng)
await t.moveMarkes(latitude,longitude)
}
}catch(e){
uni.$tm.toast('请间隙至少15s调用不可频繁定位。')
}
}
});
},
fail: (res) => {
uni.$tm.toast("系统错误")
}
})
// #endif
//h5通过ip定位
// #ifdef H5
uni.showLoading({
mask:true,title:'...'
})
//没有获取到地址资料。通过Ip尝试定位 。
let adressPoiObj = await uni.$tm.request.get("https://apis.map.qq.com/ws/location/v1/ip?key="+this.mapKey).catch(e=>{
uni.hideLoading();
uni.$tm.toast("地址解析错误")
})
if(adressPoiObj['status']==0){
t.now_latitude = adressPoiObj.result.location.lat;
t.now_longitude = adressPoiObj.result.location.lng;
t.map.moveToLocation({
latitude:t.now_latitude,
longitude:t.now_longitude
})
t.moveMap(t.mapCenter.lat,t.mapCenter.lng)
t.markers = [t.createMarker( adressPoiObj.result.location.lat,adressPoiObj.result.location.lng)]
await t.poiSidel_byTencentMap(adressPoiObj.result.location.lat,adressPoiObj.result.location.lng)
}
// #endif
},
createMarker(latitude,longitude){
let id = 636598;
let label = {
content:'',
color:'#000000',
fontSize:12,
bgColor:'red',
padding:5,
textAlign:'center',
}
return {
id:id,
iconPath:'/static/posiimg.png',
width:45,
height:45,
latitude:latitude,
longitude:longitude,
label:label,
}
},
moveMapChange(e){
var etype = ''
// #ifdef APP-PLUS
etype = 'end'
// #endif
// #ifdef MP-WEIXIN
etype = e.type
// #endif
clearTimeout(this.timeid);
if(etype ==='end'){
let t = this;
this.timeid = setTimeout(function() {
t.map.getCenterLocation({
success:async (res)=>{
await t.moveMarkes(res.latitude,res.longitude)
}
})
}, 350);
}
},
async selecListitem(item){
let t = this;
this.$set(this.adress,'adress',item.address)
await this.moveMarkes(item.location.latitude,item.location.longitude)
this.activeId = item.id;
},
async moveMarkes(latitude,longitude,callback){
let t = this;
t.markers = []
await uni.$tm.sleep(50)
if(t.markers.length==0){
t.markers = [t.createMarker( latitude,longitude)]
}
t.now_latitude = latitude;
t.now_longitude = longitude;
t.poiSidel_byTencentMap(latitude,longitude)
},
//mp腾讯地址获取当前地址资料。
async poiSidel_byTencentMap(latitude,longitude){
let t = this;
uni.showLoading({
mask:true,title:'...'
})
let lot=`location=${latitude},${longitude}&get_poi=1&key=${this.mapKey}`
let adressPoiObj = await uni.$tm.request.get("https://apis.map.qq.com/ws/geocoder/v1/?"+lot).catch(e=>{
uni.hideLoading();
uni.$tm.toast("地址解析错误")
})
uni.hideLoading();
if(adressPoiObj.status!==0){
uni.$tm.toast(adressPoiObj.message)
return;
}
let adress = adressPoiObj.result;
this.$set(this.adress,'adress',adress.address)
this.$set(this.adress,'city',[adress.address_component.province,adress.address_component.city,adress.address_component.district]);
this.$emit('change',{...this.adress,latitude:this.now_latitude,longitude:this.now_longitude})
let pos = adress.pois;
if(pos.length==0) return;
let list = [];
for(let i=0;i<pos.length;i++){
list.push({
address:pos[i].address,
name:pos[i].title,
id:pos[i].id,
location:{
latitude:pos[i].location.lat,
longitude:pos[i].location.lng
}
})
}
this.adressList = list;
}
},
}
</script>
<style lang="scss">
</style>