优化地址选择,使用chooseLocation

This commit is contained in:
WindowBird 2025-09-03 17:57:17 +08:00
parent f4fac402d9
commit 6c738fb09c
2 changed files with 128 additions and 388 deletions

View File

@ -1,78 +1,40 @@
<template> <template>
<view class="map-location-component"> <view class="map-location-component">
<!-- 地址输入--> <!-- 地址显示-->
<view class="form-item address-form-item"> <view class="form-item address-form-item">
<text class="field-label">{{ label || '地址' }}</text> <text class="field-label">{{ label || '地址' }}</text>
<view class="address-input-wrapper"> <view class="address-display-wrapper">
<input <view class="address-display" @click="authVerification">
v-model="addressValue" <text class="address-text">{{ addressValue || placeholder || '请选择收货地址' }}</text>
:placeholder="placeholder || '请输入或选择收货地址'" </view>
class="address-input" <view class="map-icon-wrapper" title="点击获取定位并打开地图" @click="authVerification">
@focus="onAddressFocus"
@input="onAddressInput"
/>
<view class="map-icon-wrapper" title="点击获取定位并打开地图" @click="openMapWithLocation">
<text class="map-icon">🗺</text> <text class="map-icon">🗺</text>
</view> </view>
</view> </view>
</view> </view>
<!-- 当前定位 -->
<!-- <view class="location-suggestion">-->
<!-- <view v-if="currentLocation" class="location-card">-->
<!-- <view class="location-content">-->
<!-- <view class="location-header">-->
<!-- <text class="location-title">当前定位</text>-->
<!-- </view>-->
<!-- <text class="location-address">{{ currentLocation.address }}</text>-->
<!-- </view>-->
<!-- <button class="use-location-btn" @click="useCurrentLocation">使用</button>-->
<!-- </view>-->
<!-- <view v-else class="location-card">-->
<!-- <view class="location-content">-->
<!-- <view class="location-header">-->
<!-- <text class="location-title">获取位置</text>-->
<!-- <text class="location-company">点击获取当前位置</text>-->
<!-- </view>-->
<!-- <text class="location-address">需要定位权限</text>-->
<!-- </view>-->
<!-- <button class="get-location-btn" @click="getCurrentLocation">获取</button>-->
<!-- </view>-->
<!-- </view>-->
</view> </view>
</template> </template>
<script> <script>
import { getLocationWithPermission, handleLocationError } from '@/utils/permission.js'
export default { export default {
name: 'MapLocation', name: 'MapLocation',
props: { props: {
//
label: { label: {
type: String, type: String,
default: '地址', default: '地址',
}, },
//
placeholder: { placeholder: {
type: String, type: String,
default: '请输入或选择收货地址', default: '请选择收货地址',
}, },
//
value: { value: {
type: String, type: String,
default: '', default: '',
}, },
//
showLocationCard: {
type: Boolean,
default: true,
},
}, },
data() { data() {
return { return {
currentLocation: null,
isMapTriggered: false,
addressValue: this.value, addressValue: this.value,
} }
}, },
@ -85,179 +47,44 @@ export default {
}, },
}, },
methods: { methods: {
// authVerification() {
async getCurrentLocation() { uni.getSetting({
try { success: res => {
uni.showLoading({ if (res.authSetting['scope.userLocation']) {
title: '获取位置中...', this.handerChooseLocation()
}) } else if (res.authSetting['scope.userLocation'] === undefined) {
this.handleOpenSetting()
const location = await getLocationWithPermission() } else {
console.log('位置信息:', location) this.handleOpenSetting()
}
// 使 },
this.currentLocation = {
address: `纬度: ${location.latitude.toFixed(6)}, 经度: ${location.longitude.toFixed(6)}`,
latitude: location.latitude,
longitude: location.longitude,
}
uni.hideLoading()
//
if (!this.isMapTriggered) {
uni.showToast({
title: '位置获取成功,点击地图图标查看',
icon: 'success',
duration: 3000,
})
}
//
this.$emit('location-success', this.currentLocation)
return this.currentLocation
} catch (err) {
uni.hideLoading()
handleLocationError(err)
this.$emit('location-error', err)
throw err
}
},
//
onAddressFocus() {
this.$emit('address-focus')
},
//
onAddressInput(e) {
const value = e.detail.value
this.addressValue = value
this.$emit('input', value)
this.$emit('address-input', value)
},
//
async openMapWithLocation() {
try {
this.isMapTriggered = true
//
await this.getCurrentLocation()
//
this.openMap()
} catch (err) {
console.error('获取位置失败:', err)
uni.showToast({
title: '获取位置失败',
icon: 'error',
})
} finally {
this.isMapTriggered = false
}
},
//
openMap() {
if (!this.currentLocation) {
uni.showToast({
title: '请先获取位置信息',
icon: 'none',
})
return
}
const { latitude, longitude } = this.currentLocation
//
uni.showLoading({
title: '打开地图中...',
}) })
},
// handerChooseLocation(latitude, longitude) {
// #ifdef APP-PLUS uni.chooseLocation({
uni.openLocation({ latitude: latitude || '',
latitude: latitude, longitude: longitude || '',
longitude: longitude, success: res => {
name: '当前位置', this.addressValue = res.address || res.name
address: this.currentLocation.address || '未知地址', this.$emit('location-selected', res)
scale: 18, this.$emit('location-success', res)
success: () => { uni.setStorageSync('currentLocation', res)
uni.hideLoading()
console.log('地图打开成功')
this.$emit('map-opened')
}, },
fail: err => { fail: err => {
uni.hideLoading() console.log('取消选择位置', err)
console.error('打开地图失败:', err) this.$emit('location-cancel', err)
this.showMapInApp() this.$emit('location-error', err)
}, },
}) })
// #endif },
handleOpenSetting() {
// #ifdef MP-WEIXIN wx.openSetting({
uni.openLocation({ success: res => {
latitude: latitude, if (res.authSetting['scope.userLocation']) {
longitude: longitude, this.handerChooseLocation()
name: '当前位置', }
address: this.currentLocation.address || '未知地址',
scale: 18,
success: () => {
uni.hideLoading()
this.$emit('map-opened')
},
fail: err => {
uni.hideLoading()
console.error('打开地图失败:', err)
this.showMapInApp()
}, },
}) })
// #endif
// #ifdef H5
// H5使线
uni.hideLoading()
const mapUrl = `https://uri.amap.com/marker?position=${longitude},${latitude}&name=${encodeURIComponent('当前位置')}&address=${encodeURIComponent(this.currentLocation.address || '未知地址')}`
window.open(mapUrl, '_blank')
this.$emit('map-opened')
// #endif
},
//
showMapInApp() {
uni.showModal({
title: '地图功能',
content: `${this.currentLocation.address}\n\n经纬度${this.currentLocation.latitude.toFixed(6)}, ${this.currentLocation.longitude.toFixed(6)}`,
showCancel: false,
confirmText: '确定',
})
},
// 使
useCurrentLocation() {
if (!this.currentLocation) {
this.getCurrentLocation()
return
}
this.addressValue = this.currentLocation.address
this.$emit('input', this.currentLocation.address)
this.$emit('use-location', this.currentLocation)
uni.showToast({
title: '已使用当前定位',
icon: 'success',
})
},
//
setLocation(location) {
this.currentLocation = location
},
//
clearLocation() {
this.currentLocation = null
}, },
}, },
} }
@ -269,44 +96,46 @@ export default {
width: 100%; width: 100%;
} }
//
.address-form-item { .address-form-item {
//margin-bottom: 20rpx;
display: flex; display: flex;
align-items: center; align-items: center; /* 改为 center 让标签和内容垂直居中 */
padding: 20rpx 0;
.field-label { .field-label {
display: block;
font-size: 28rpx; font-size: 28rpx;
color: #333; color: #333;
font-weight: 400; font-weight: 400;
flex: 1; flex: 1;
line-height: 1.5; /* 确保文本垂直居中 */
} }
} }
// .address-display-wrapper {
.address-input-wrapper {
flex: 3; flex: 3;
display: flex; display: flex;
align-items: center; align-items: center;
height: 80rpx; min-height: 80rpx;
padding: 0 20rpx; padding: 0 20rpx;
border-radius: 12rpx; border-radius: 12rpx;
background: #fff; background: #fff;
transition: all 0.3s ease;
.address-input { .address-display {
flex: 1; flex: 1;
height: 100%; display: flex;
font-size: 28rpx; align-items: center;
color: #333; min-height: 56rpx;
border: none; }
outline: none;
background: transparent;
&::placeholder { .address-text {
color: #999; 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 { .map-icon-wrapper {
@ -315,10 +144,10 @@ export default {
justify-content: center; justify-content: center;
width: 48rpx; width: 48rpx;
height: 48rpx; height: 48rpx;
background: #f15a04; background: #f15a04; /* 橙色背景 */
border-radius: 50%; border-radius: 50%;
transition: all 0.3s ease;
margin-left: 16rpx; margin-left: 16rpx;
flex-shrink: 0;
&:active { &:active {
transform: scale(0.9); transform: scale(0.9);
@ -331,96 +160,4 @@ export default {
} }
} }
} }
//
.location-suggestion {
margin-bottom: 40rpx;
.location-card {
display: flex;
align-items: center;
justify-content: space-between;
background: white;
border: 2rpx solid #e8f4fd;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
position: relative;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 6rpx;
background: #f3f5f6;
border-radius: 6rpx 0 0 6rpx;
}
.location-content {
flex: 1;
margin-right: 20rpx;
.location-header {
display: flex;
align-items: center;
margin-bottom: 8rpx;
.location-title {
font-size: 24rpx;
color: #f15a04;
font-weight: 500;
margin-right: 12rpx;
}
.location-company {
font-size: 26rpx;
color: #333;
font-weight: 500;
}
}
.location-address {
font-size: 24rpx;
color: #666;
line-height: 1.4;
}
}
.use-location-btn {
background: #f15a04;
color: #000000;
border: none;
border-radius: 24rpx;
padding: 12rpx 24rpx;
font-size: 24rpx;
font-weight: 500;
box-shadow: 0 4rpx 12rpx rgba(255, 107, 107, 0.3);
transition: all 0.3s ease;
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(255, 107, 107, 0.4);
}
}
.get-location-btn {
background: #f15a04;
color: #ffffff;
border: none;
border-radius: 24rpx;
padding: 12rpx 24rpx;
font-size: 24rpx;
font-weight: 500;
box-shadow: 0 4rpx 12rpx rgba(255, 107, 107, 0.3);
transition: all 0.3s ease;
&:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(255, 107, 107, 0.4);
}
}
}
}
</style> </style>

View File

@ -1,69 +1,72 @@
<template> <template>
<view class="content"> <view class="content">
<button @tap="authVerification">请选择位置</button> <button @tap="authVerification">请选择位置</button>
<template v-if="currentLocation.address"> <template v-if="currentLocation.address">
<div>name{{currentLocation.name}}</div> <div>name{{ currentLocation.name }}</div>
<div>address{{currentLocation.address}}</div> <div>address{{ currentLocation.address }}</div>
<div>latitude{{currentLocation.latitude}}</div> <div>latitude{{ currentLocation.latitude }}</div>
<div>longitude{{currentLocation.longitude}}</div> <div>longitude{{ currentLocation.longitude }}</div>
</template> </template>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
currentLocation:{}, currentLocation: {},
} }
}, },
onShow () { onShow() {
uni.getStorage({ uni.getStorage({
key: 'currentLocation', key: 'currentLocation',
success: (res) => { success: res => {
this.currentLocation = res.data this.currentLocation = res.data
} },
}) })
}, },
methods: { methods: {
authVerification () { authVerification() {
uni.getSetting({ uni.getSetting({
success: (res) => { success: res => {
if (res.authSetting['scope.userLocation']) { /* 用户授权成功时走这里 */ if (res.authSetting['scope.userLocation']) {
this.handerChooseLocation() /* 用户授权成功时走这里 */
} else if (res.authSetting['scope.userLocation'] === undefined) { /* 用户未授权时走这里 */ this.handerChooseLocation()
console.log('没有授权') } else if (res.authSetting['scope.userLocation'] === undefined) {
this.handleOpenSetting() /* 用户未授权时走这里 */
} else { /* 用户拒绝了授权后走这里 */ console.log('没有授权')
console.log('拒绝了授权 false') this.handleOpenSetting()
this.handleOpenSetting() } else {
} /* 用户拒绝了授权后走这里 */
}, console.log('拒绝了授权 false')
}) this.handleOpenSetting()
}, }
handerChooseLocation (latitude, longitude) { },
uni.chooseLocation({ })
latitude: latitude || '', },
longitude: longitude || '', handerChooseLocation(latitude, longitude) {
success: (res) => { uni.chooseLocation({
console.log('wx.chooseLocation res=', res) latitude: latitude || '',
uni.setStorageSync('currentLocation', res) longitude: longitude || '',
}, success: res => {
fail: function (err) { console.log('wx.chooseLocation res=', res)
console.log('取消按钮', err) uni.setStorageSync('currentLocation', res)
} },
}) fail: function (err) {
}, console.log('取消按钮', err)
handleOpenSetting () { },
wx.openSetting({ })
success: (res) => { },
console.log('定位 openSetting', res) handleOpenSetting() {
if (res.authSetting["scope.userLocation"]) { wx.openSetting({
this.handerChooseLocation() success: res => {
} console.log('定位 openSetting', res)
} if (res.authSetting['scope.userLocation']) {
}) this.handerChooseLocation()
} }
} },
} })
},
},
}
</script> </script>