180 lines
3.9 KiB
Vue
180 lines
3.9 KiB
Vue
<template>
|
||
<view class="map-location-component">
|
||
<!-- 地址显示框 -->
|
||
<view class="form-item address-form-item">
|
||
<text class="field-label">{{ label || '地址' }}</text>
|
||
<view class="address-display-wrapper">
|
||
<view class="address-display" @click="authVerification">
|
||
<text class="address-text">{{ addressValue || placeholder || '请选择收货地址' }}</text>
|
||
</view>
|
||
<view class="map-icon-wrapper" title="点击获取定位并打开地图" @click="authVerification">
|
||
<text class="map-icon">🗺️</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'MapLocation',
|
||
props: {
|
||
label: {
|
||
type: String,
|
||
default: '地址',
|
||
},
|
||
placeholder: {
|
||
type: String,
|
||
default: '请选择收货地址',
|
||
},
|
||
value: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
addressValue: this.value,
|
||
locationData: null, // 存储完整的定位信息
|
||
}
|
||
},
|
||
watch: {
|
||
value(newVal) {
|
||
this.addressValue = newVal
|
||
},
|
||
addressValue(newVal) {
|
||
this.$emit('input', newVal)
|
||
},
|
||
},
|
||
methods: {
|
||
authVerification() {
|
||
uni.getSetting({
|
||
success: res => {
|
||
if (res.authSetting['scope.userLocation']) {
|
||
this.handerChooseLocation()
|
||
} else if (res.authSetting['scope.userLocation'] === undefined) {
|
||
this.handleOpenSetting()
|
||
} else {
|
||
this.handleOpenSetting()
|
||
}
|
||
},
|
||
})
|
||
},
|
||
handerChooseLocation(latitude, longitude) {
|
||
uni.chooseLocation({
|
||
latitude: latitude || '',
|
||
longitude: longitude || '',
|
||
success: res => {
|
||
this.addressValue = res.address || res.name
|
||
this.locationData = res // 保存完整的定位信息
|
||
|
||
// 触发事件传递给父组件
|
||
this.$emit('location-selected', res)
|
||
this.$emit('location-success', res)
|
||
this.$emit('update:location', res) // 新增:传递完整定位数据
|
||
|
||
uni.setStorageSync('currentLocation', res)
|
||
},
|
||
fail: err => {
|
||
console.log('取消选择位置', err)
|
||
this.$emit('location-cancel', err)
|
||
this.$emit('location-error', err)
|
||
},
|
||
})
|
||
},
|
||
handleOpenSetting() {
|
||
wx.openSetting({
|
||
success: res => {
|
||
if (res.authSetting['scope.userLocation']) {
|
||
this.handerChooseLocation()
|
||
}
|
||
},
|
||
})
|
||
},
|
||
|
||
// 新增方法:获取经纬度数据供父组件调用
|
||
getLocationData() {
|
||
return this.locationData
|
||
},
|
||
|
||
// 新增方法:清空定位数据
|
||
clearLocation() {
|
||
this.locationData = null
|
||
this.addressValue = ''
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.map-location-component {
|
||
border-bottom: 1rpx solid #d8d8d8;
|
||
width: 100%;
|
||
}
|
||
|
||
.address-form-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx 0;
|
||
|
||
.field-label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 400;
|
||
flex: 1;
|
||
line-height: 1.5;
|
||
}
|
||
}
|
||
|
||
.address-display-wrapper {
|
||
flex: 3;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
padding: 0 20rpx;
|
||
border-radius: 12rpx;
|
||
background: #fff;
|
||
|
||
.address-display {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.address-text {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
line-height: 1.5;
|
||
word-break: break-all;
|
||
white-space: pre-wrap;
|
||
display: -webkit-box;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.map-icon-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 42rpx;
|
||
height: 42rpx;
|
||
background: #f15a04;
|
||
border-radius: 50%;
|
||
margin-left: 16rpx;
|
||
flex-shrink: 0;
|
||
|
||
&:active {
|
||
transform: scale(0.9);
|
||
box-shadow: 0 2rpx 8rpx rgba(241, 90, 4, 0.4);
|
||
}
|
||
|
||
.map-icon {
|
||
font-size: 28rpx;
|
||
color: white;
|
||
}
|
||
}
|
||
}
|
||
</style>
|