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

1 year ago
<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>