From c66fac5992d5edac1eecdc7a1085e4c9d089e0b5 Mon Sep 17 00:00:00 2001 From: linxi <957440651@qq.com> Date: Wed, 18 Mar 2026 12:22:28 +0800 Subject: [PATCH] =?UTF-8?q?Feat:=E4=BD=93=E9=AA=8C=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/product.js | 4 + pkg_product/views/experienceCoupon.vue | 202 ++++++++++++------ .../views/experienceCouponOrderDetail.vue | 11 +- pkg_product/views/sojoumOrderDetails.vue | 123 ++++++++++- 4 files changed, 267 insertions(+), 73 deletions(-) diff --git a/api/product.js b/api/product.js index a04c643..83cc6f9 100644 --- a/api/product.js +++ b/api/product.js @@ -180,3 +180,7 @@ export function createExperienceCouponOrder(data) { export function getExperienceCouponOrderDetail(orderId) { return request.get(`/experienceCoupon/order/detail/${orderId}`, {}, {login: true}) } + +export function checkExperienceCoupon(params) { + return request.get('/experienceCoupon/check', params, {login: true}) +} diff --git a/pkg_product/views/experienceCoupon.vue b/pkg_product/views/experienceCoupon.vue index 10e5776..a600da8 100644 --- a/pkg_product/views/experienceCoupon.vue +++ b/pkg_product/views/experienceCoupon.vue @@ -22,7 +22,9 @@ export default { { id: 'all', name: '全部体验' } ], activeCategoryId: 'all', - experienceList: [] + experienceList: [], + userLatitude: null, + userLongitude: null } }, computed: { @@ -56,10 +58,51 @@ export default { return value }, initPage() { + this.getUserLocation() this.fetchExperienceCoupon() this.fetchCouponList() this.fetchCategoryList() }, + getUserLocation() { + uni.getLocation({ + type: 'gcj02', + success: (res) => { + this.userLatitude = res.latitude + this.userLongitude = res.longitude + this.updateDistances() + }, + fail: (err) => { + console.error('获取位置失败', err) + } + }) + }, + updateDistances() { + if (!this.experienceList.length || !this.userLatitude || !this.userLongitude) { + return + } + this.experienceList = this.experienceList.map(item => { + if (item.latitude && item.longitude) { + return { + ...item, + distance: this.calculateDistance(this.userLatitude, this.userLongitude, item.latitude, item.longitude) + } + } + return item + }) + }, + calculateDistance(lat1, lon1, lat2, lon2) { + if (!lat1 || !lon1 || !lat2 || !lon2) return '' + const R = 6371 // 地球半径 km + const dLat = (lat2 - lat1) * Math.PI / 180 + const dLon = (lon2 - lon1) * Math.PI / 180 + const a = + Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * + Math.sin(dLon / 2) * Math.sin(dLon / 2) + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)) + const d = R * c + return d.toFixed(1) + 'km' + }, setActiveCoupon(coupon) { if (!coupon) { return @@ -130,17 +173,28 @@ export default { } getExperienceCouponItems(params).then(({ data }) => { const list = data || [] - this.experienceList = list.map(item => ({ - id: item.id != null ? item.id : (item.projectId != null ? item.projectId : item.merId), - title: item.name || '', - subTitle: item.projectName || item.intro || '', - distance: item.cityName && item.areaName ? `${item.cityName}${item.areaName}` : '', - businessTime: item.serviceTime && item.serviceEndTime ? `${item.serviceTime}-${item.serviceEndTime}` : (item.serviceTime || ''), - tags: item.intro || '', - categoryId: this.activeCategoryId === 'all' ? 'all' : this.activeCategoryId, - image: item.image || item.cover || '', - selected: false - })) + this.experienceList = list.map(item => { + const lat = Number(item.latitude || 0) + const lon = Number(item.longitude || 0) + let distance = '' + if (this.userLatitude && this.userLongitude && lat && lon) { + distance = this.calculateDistance(this.userLatitude, this.userLongitude, lat, lon) + } + + return { + id: item.id != null ? item.id : (item.projectId != null ? item.projectId : item.merId), + title: item.name || '', + subTitle: item.projectName || item.intro || '', + distance, + latitude: lat, + longitude: lon, + businessTime: item.serviceTime && item.serviceEndTime ? `${item.serviceTime}-${item.serviceEndTime}` : (item.serviceTime || ''), + tags: item.intro || '', + categoryId: this.activeCategoryId === 'all' ? 'all' : this.activeCategoryId, + image: item.image || item.cover || '', + selected: false + } + }) }).catch(() => { this.experienceList = [] }) @@ -236,21 +290,26 @@ export default { mode="aspectFill" /> + - - - 体验券{{ index + 1}} + + + 体验券{{ index + 1}} + - + @@ -258,7 +317,7 @@ export default { - + 已选清单 {{ selectedCount }}/{{ totalCount }} @@ -320,14 +379,16 @@ export default { {{ item.title }} - - {{ item.subTitle }} - - - - + + + {{ item.subTitle }} + + + 距该地{{ item.distance }} + + 营业时间:{{ item.businessTime }} @@ -336,15 +397,17 @@ export default { :class="{ selected: item.selected }" @click.stop="toggleSelect(item)" > - {{ item.selected ? '取消选择' : '立即选择' }} - + {{ item.selected ? '取消选择' : '选择' }} + + + - + - 已完成 - 期待再次光临 + 已完成 + 期待再次光临 已过期 @@ -39,10 +39,10 @@ {{ orderInfo.experienceItemInfo && orderInfo.experienceItemInfo.themeName ? orderInfo.experienceItemInfo.themeName : '' }} 营业时间:{{ formattedBusinessTime }} - + 距该地{{ distanceText }}km - {{ orderInfo.address }} + {{ orderInfo.address }} @@ -92,7 +92,7 @@ - + 返回主页 @@ -419,7 +419,6 @@ export default { align-items: center; font-size: 24rpx; color: #999; - padding-right: 160rpx; } .location-icon { diff --git a/pkg_product/views/sojoumOrderDetails.vue b/pkg_product/views/sojoumOrderDetails.vue index 1f3a391..3786db9 100644 --- a/pkg_product/views/sojoumOrderDetails.vue +++ b/pkg_product/views/sojoumOrderDetails.vue @@ -75,7 +75,6 @@ - {{ title }} @@ -98,6 +97,21 @@ + + + + + + + 暂不领取 + 去领取体验券 + + + 联系人信息 @@ -204,6 +218,7 @@