Browse Source

feat(订单流程): 新增用户选择老师功能并优化距离计算

- 在 Vuex 中新增 `buyInfo` 和 `position` 状态,用于存储用户选择的老师和位置信息
- 新增 `position.js` 工具类,用于计算两点之间的距离
- 在 `companionPetList.vue` 和 `companionPetInfo.vue` 中集成距离计算功能,显示老师与用户的距离
- 优化订单流程,支持用户选择指定老师下单,并在页面中显示相关信息
master
前端-胡立永 1 day ago
parent
commit
00fa7d3b67
9 changed files with 130 additions and 41 deletions
  1. +1
    -1
      mixins/configList.js
  2. +38
    -0
      mixins/position.js
  3. +15
    -5
      pages/companionPetList/companionPetInfo.vue
  4. +19
    -5
      pages/companionPetList/companionPetList.vue
  5. +14
    -3
      pages/index.vue
  6. +2
    -14
      pages/newOrder/serviceNew.vue
  7. +4
    -13
      pages/newOrder/serviceNew2.vue
  8. +7
    -0
      store/index.js
  9. +30
    -0
      utils/position.js

+ 1
- 1
mixins/configList.js View File

@ -13,7 +13,7 @@ export default {
}
},
computed: {
...mapState(['configList', 'userInfo']),
...mapState(['configList', 'userInfo', 'buyInfo']),
// currentPagePath() {
// const pages = getCurrentPages();
// const currentPage = pages[pages.length - 1];


+ 38
- 0
mixins/position.js View File

@ -0,0 +1,38 @@
import { mapState } from 'vuex'
import { calculateDistance } from '@/utils/position'
export default {
data() {
return {
}
},
computed: {
...mapState(['position']),
},
methods: {
calculateDistanceAddress(teacherAddress) {
if (!teacherAddress ||
teacherAddress.length == 0 ||
!this.position ||
!this.position.latitude ||
!this.position.longitude) {
return 0
}
let minDistance = 0
teacherAddress.forEach(item => {
let distance = calculateDistance(
this.position.latitude,
this.position.longitude,
item.latitude,
item.longitude,
)
minDistance = Math.min(minDistance, distance)
})
return minDistance
}
}
}

+ 15
- 5
pages/companionPetList/companionPetInfo.vue View File

@ -10,7 +10,7 @@
<view class="companion-info-detail">
<view class="" style="width: 360rpx;">
<view class="companion-info-left">
<text class="companion-info-left-title">{{companionInfo.name}}</text>
<text class="companion-info-left-title">{{companionInfo.userName}}</text>
<view>
<img :src="companionInfo.appletUsersTeacher.sex==1?'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/personal/pet/sex_m.png':
'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/personal/pet/sex_f.png'" alt="sex"
@ -18,8 +18,8 @@
</view>
</view>
<view class="">
<image src="/static/images/pages/cwfw.png" mode="heightFix"
style="height: 40rpx;"></image>
<!-- <image src="/static/images/pages/cwfw.png" mode="heightFix"
style="height: 40rpx;"></image> -->
</view>
</view>
<view class="companion-info-right" @click="onClickFav">
@ -272,7 +272,7 @@
<view class="service-record-info-2">
<view class="service-record-info-title">
<view class="service-record-name">
{{companionInfo.name}}
{{companionInfo.userName}}
</view>
</view>
<view class="service-record-location">
@ -312,7 +312,8 @@
</view>
</uni-card>
</view>
<view class="bottom-btn-sticky" style="padding: 10rpx 40rpx 0 40rpx;">
<view class="bottom-btn-sticky" style="padding: 10rpx 40rpx 0 40rpx;"
@click="toBuy">
<!-- <button class="bottom-btn" @click="getOrder">立即预约</button> -->
<image style="width: 670rpx; height: 80rpx;" slot='cover'
src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/petServiceOrder/orderNow.png" />
@ -356,7 +357,9 @@
getTeacherServiceLogList,
} from "@/api/order/order"
import uniRate from '@/uni_modules/uni-rate/components/uni-rate/uni-rate.vue';
import positionMixin from '../../mixins/position';
export default {
mixins: [positionMixin],
data() {
return {
currentCompanionPetId: '',
@ -475,6 +478,12 @@
this.getCurrentCompanionPetInfo(this.currentCompanionPetId)
},
methods: {
toBuy(){
this.buyInfo.teacher = this.companionInfo
uni.navigateTo({
url: '/pages/newOrder/serviceNew?type=teacher'
})
},
onClickFav() {
this.collect = !this.collect
this.$forceUpdate()
@ -483,6 +492,7 @@
getTeacherDetail({userId}).then(response => {
if (response) {
this.companionInfo = response
this.companionInfo.distanceText = this.calculateDistanceAddress(response.appletAddresseList)
}
console.log('getCurrentCompanionPetInfo', response);
})


+ 19
- 5
pages/companionPetList/companionPetList.vue View File

@ -18,7 +18,7 @@
<view style="width: 50%;">
<view class="top-select-right" @click="toggleCalendar('bottom')">
<image style="width: 32rpx; height: 32rpx; margin-right: 10rpx;" slot='cover'
src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/petServiceOrder/Calendar.png">
src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/petServiceOrder/Calendar.png"/>
<text v-if="isCheckTime" style="color: #FFB13F;font-size: 28rpx;font-weight: 400;">
{{selectedDateShowText}}{{selectedDate.length}}</text>
<text v-else style="color: #AAAAAA;font-size: 28rpx;font-weight: 400;">选择时间</text>
@ -128,8 +128,8 @@
</view>
</view>
<view class="personal-info-3" style="width: 100%;">
<view class="ellipsis" v-if="item.id">
距离{{ item.id }}km
<view class="ellipsis" v-if="item.distanceText">
距离{{ item.distanceText }}km
</view>
<view class="ellipsis" v-else>
暂无距离估测
@ -152,7 +152,9 @@
</uni-row>
</view>
<view v-else
style="display: flex; justify-content: center; align-items: center; height: 100px; font-size: 16px; font-weight: bold;">
style="
color: #AAAAAA;
display: flex; justify-content: center; align-items: center; height: 100px; font-size: 16px; font-weight: bold;">
暂无数据
</view>
</view>
@ -164,6 +166,7 @@
import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue';
import uniFab from '@/uni_modules/uni-fab/components/uni-fab/uni-fab.vue'
import FilterPopup from '@/components/FilterPopup/FilterPopup.vue'
import positionMixin from '../../mixins/position';
// import {
// getCompanionList,
// getCompanionInfo
@ -172,6 +175,7 @@
getTeacherList,
} from "@/api/order/order"
export default {
mixins: [positionMixin],
data() {
return {
allInfo: {
@ -300,11 +304,16 @@
getTeacherList(data).then(response => {
if (response.code == 200) {
this.companionList = response.rows
console.log(response);
this.calculateTeacherListDistance()
}
console.log(response);
})
},
calculateTeacherListDistance(){
this.companionList.forEach(item => {
item.distanceText = this.calculateDistanceAddress(item.appletAddresseList)
})
},
iconClick() {},
changeSelectedPet(type) {
console.log('changeSelectedPet type', type);
@ -407,6 +416,11 @@
this.locationLatitude = res.latitude
this.locationAddress = res.address
console.log('选择的位置:', res);
this.position.address = this.locationAddress
this.position.longitude = this.locationLongitude
this.position.latitude = this.locationLatitude
},
fail: (err) => {
//


+ 14
- 3
pages/index.vue View File

@ -616,16 +616,27 @@
icon: "none"
})
} else {
this.$store.commit('setPosition', {
address: this.locationAddress,
longitude: this.locationLongitude,
latitude: this.locationLatitude,
date: this.selectedDateShowText
})
uni.navigateTo({
// url: '/pages/companionPetList/companionPetList',
url: `/pages/companionPetList/companionPetList?info=` + encodeURIComponent(JSON
url: `/pages/companionPetList/companionPetList?info=`
+ encodeURIComponent(JSON
.stringify(this.allInfo))
});
}
} else {
this.$store.commit('setPosition', {})
this.buyInfo.teacher = null
uni.navigateTo({
url: '/pages_order/order/payOrderSuccessful',
// url: '/pages/newOrder/serviceNew',
// url: '/pages_order/order/payOrderSuccessful',
url: '/pages/newOrder/serviceNew',
// url: '/pages/newOrder/serviceNew2',
});
}


+ 2
- 14
pages/newOrder/serviceNew.vue View File

@ -1,8 +1,7 @@
<template>
<view class="service-new container">
<view class="order-type-select">
<view class="order-type-select" v-if="!buyInfo.teacher">
<view class="order-type-title">
<image style="width: 40rpx; height: 40rpx;margin-right: 10rpx;" slot='cover' src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/petServiceOrder/OrderIcon.png">
@ -58,7 +57,7 @@
<view class="service-new-address">
<uni-card padding=0 :is-shadow="false">
<view class="service-new-title" slot="title">
<view class="service-new-title-left">
<view class="service-new-title-left">
<view class="service-new-flag"></view>
<view>服务地址</view>
</view>
@ -220,20 +219,9 @@
companionLevel: 'junior', //
popupTitle: '',
popupLevel: '',
//
orderMethod : false,
//
orderName : '',
// id
servicerId : 0,
}
},
onLoad: function(option) {
if (option.userName) {
this.orderMethod = true
this.orderName = option.userName;
this.servicerId = option.servicerId;
}
},
onShow() {
if (!getToken() || !getOpenIdKey()) {


+ 4
- 13
pages/newOrder/serviceNew2.vue View File

@ -1,17 +1,19 @@
<template>
<view class="service-new container">
<view style="background-color: #FFF4E5; margin: 10px; padding: 10px; border-radius: 8rpx;">
<view style="display: flex;">
<image style="width: 40rpx; height: 40rpx;" slot='cover' src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/petServiceOrder/OrderIcon.png">
</image>
<text style="color: #A94F20; font-size: 28rpx; font-weight: 500;">
下单方式
<text v-if="orderMethod">指定喂养员 - {{orderName}}</text>
<text v-if="buyInfo.teacher">指定喂养员 - {{buyInfo.teacher.userName}}</text>
<text v-else>系统派单</text>
</text>
</view>
<view style="margin-top: 10rpx;">
<text v-if="orderMethod" style="color: #A94F20; font-size: 24rpx; font-weight: 400;">
<text v-if="buyInfo.teacher" style="color: #A94F20; font-size: 24rpx; font-weight: 400;">
(若伴宠师1小时内无响应或拒绝接单则系统派单)
</text>
</view>
@ -373,21 +375,10 @@
customServiceItemCount:[],
//
currentDayPrice : 0,
//
orderMethod : false,
//
orderName : '',
// id
servicerId : 0,
}
},
onLoad: function(option) {
if (option.userName) {
this.orderMethod = true
this.orderName = option.userName;
this.servicerId = option.servicerId;
}
},
mounted() {
this.currentPets = this.$globalData.newOrderData.currentPets;


+ 7
- 0
store/index.js View File

@ -10,6 +10,10 @@ Vue.use(Vuex)
const store = new Vuex.Store({
state : {
configList : {},
position : {},//用户选择的定位信息
buyInfo : {
teacher : null,//用户选择的购买老师
},//用户选择的购买信息
},
mutations : {
// 初始化配置
@ -28,6 +32,9 @@ const store = new Vuex.Store({
uni.$emit('initConfig', state.configList)
})
},
setPosition(state, position){
state.position = position;
},
},
modules: {
user


+ 30
- 0
utils/position.js View File

@ -0,0 +1,30 @@
/**
* 计算两点之间的距离
* @param {number} lat1 地点1精度
* @param {number} lon1 地点1维度
* @param {number} lat2 地点2精度
* @param {number} lon2 地点2维度
* @param {number} fixed 保留几位小数,默认0,单位km
*/
export function calculateDistance(lat1, lon1, lat2, lon2, fixed = 0) { //计算两点距离
let distance = 0
if (!lat2 || !lon2) return distance
//先强制转换一下(后端给的字符串)
lat1 = parseFloat(lat1)
lon1 = parseFloat(lon1)
lat2 = parseFloat(lat2)
lon2 = parseFloat(lon2)
// 将角度转换为弧度
const R = 6371; // 地球半径,单位公里
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
lat1 = lat1 * Math.PI / 180;
lat2 = lat2 * Math.PI / 180;
// Haversine公式
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
// 计算距离
distance = R * c;
return distance.toFixed(fixed)
}

Loading…
Cancel
Save