You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1418 lines
43 KiB

<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="buyInfo.teacher">指定喂养员 - {{buyInfo.teacher.userName}}</text>
<text v-else>系统派单</text>
</text>
</view>
<view style="margin-top: 10rpx;">
<text v-if="buyInfo.teacher" style="color: #A94F20; font-size: 24rpx; font-weight: 400;">
(若伴宠师1小时内无响应或拒绝接单则系统派单)
</text>
</view>
</view>
<view>
<uni-card padding=0 :is-shadow="false">
<view class="service-new-title" slot="title">
<view class="service-new-title-left">
<view class="service-new-flag"></view>
<view>爱宠选择</view>
</view>
</view>
<view class="split-line"></view>
<view class="service-new-pet-content">
<scroll-view scroll-x class="scroll-view">
<view class="scroll-content">
<view v-for="item in currentPets" :key="item.id" class="service-new-pet-item ellipsis"
:class="{'pet-selected': item.id === currentPetId, 'pet-unselect': item.id !== currentPetId}"
@click="selectPet(item)">
{{ item.name }}
</view>
</view>
</scroll-view>
</view>
</uni-card>
</view>
<view>
<uni-card padding=0 :is-shadow="false">
<view class="service-new-title" slot="title">
<view class="service-new-title-left">
<view class="service-new-flag"></view>
<view>服务日期</view>
</view>
</view>
<view class="split-line"></view>
<view class="service-new-pet-content">
<scroll-view scroll-y class="scroll-view-vertical">
<view v-for="(month, monthIndex) in sortedGroupedDates" :key="monthIndex" class="month-group">
<view class="month-title">{{ month.monthLabel }}</view>
<scroll-view scroll-x class="scroll-view-horizontal">
<view class="dates-wrapper">
<view v-for="(day, dayIndex) in month.dates" :key="dayIndex" class="calendar-day"
:class="{'day-selected': isDateSelected(day)}" @click="selectDate(day)">
<image :src="isDateSelected(day) ?
'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/updated.png' :
'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/update_un.png'"
class="calendar-bg"/>
<text class="day-text" :class="{'day-highlighted': isCurrentSelected(day) ,'day-normal': !isCurrentSelected(day)} ">
{{ day.date < 10 ? '0' + day.date : day.date }}</text>
</view>
</view>
</scroll-view>
</view>
</scroll-view>
</view>
</uni-card>
</view>
<view>
<uni-card padding=0 :is-shadow="false">
<view class="service-new-title" slot="title">
<view class="service-new-title-left">
<view class="service-new-flag"></view>
<view>期望时间 <span class="time-slot-time-tip">*请勾选您可以接受的上门时间段</span></view>
</view>
</view>
<view class="split-line"></view>
<view class="service-new-pet-content">
<view class="time-slots">
<view v-for="slot in timeSlots" :key="slot.id" class="time-slot-item"
@click="selectTimeSlot(slot.id)">
<image :src="slot.selected ? slot.activeIcon : slot.inactiveIcon" class="time-slot-icon" />
<view class="time-slot-info">
<text class="time-slot-time">{{ slot.time }}</text>
</view>
</view>
</view>
</view>
</uni-card>
</view>
<view>
<uni-card padding=0 :is-shadow="false">
<view class="service-new-title" slot="title">
<view class="service-new-title-left">
<view class="service-new-flag"></view>
<view>服务选择</view>
</view>
<view style="display: flex; justify-content: flex-end; align-items: center; ">
<view style="margin-right: 10rpx;color: #AAAAAA;">爱宠:{{currentPetId && getCurrentPetName()}} 全日期保持一致</view>
<u-switch
space="2" :value="isAllSame" activeColor="#f9ae3d" size="18"
@change="isAllSameChange"
inactiveColor="rgb(230, 230, 230)">
</u-switch>
</view>
</view>
<view class="split-line"></view>
<view class="service-new-pet-content">
<view class="service-item">
<view class="service-item-header">
<image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/service.png"
class="service-icon"></image>
<text class="service-title">基础服务</text>
</view>
<view class="service-list">
<!-- <view style="border-radius: 8rpx" :style="{'background-color': needFeed.length > 0 ? '#FFFCF2' : '#F9F9F9', 'border': needFeed.length > 0 ? '1px solid #FFBF60' : 'none'}" >
<view style="padding: 30rpx 0; margin: 0 20rpx; ">
<u-checkbox-group
v-model="needFeed"
iconPlacement="right"
placement="column">
<u-checkbox activeColor="#FFBF60" label="专业喂养" shape="circle"></u-checkbox>
</u-checkbox-group>
</view>
</view> -->
<view class="service-list" style="border-radius: 8rpx;margin-top: 28rpx;">
<view class="service-row" style="background-color: #FFECCD">
<view class="service-row-content"
:style="{'border-bottom': feedCount > 1 ? '1rpx solid #ECBFA8' : 'none'}">
<text class="service-name" style="color: #A94F20;">一天多次</text>
<view class="service-price">
<u-number-box
slot="right-icon"
:value="feedCount"
@change="feedCountChange"
step="1"
:min="1"
:max="3"
>
<view slot="minus" class="minus">
<u-icon name="minus-circle-fill" size="20" color="#FFBF60"></u-icon>
</view>
<text slot="input" style="width: 40rpx;text-align: center;"
class="input">{{feedCount}}</text>
<view slot="plus" class="plus">
<u-icon name="plus-circle-fill" color="#FFBF60" size="20"></u-icon>
</view>
</u-number-box>
</view>
</view>
</view>
<view v-if="feedCount > 1" class="service-row" style="background-color: #FFECCD">
<view class="service-row-content">
<text class="service-name" style="color: #A94F20;">额外服务费</text>
<view class="service-price" style="color:#A94F20">
¥{{ feedCount >2? 130 : 45}}
</view>
</view>
</view>
</view>
</view>
</view>
<view class="service-item">
<view class="service-item-header">
<image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/love.png"
class="service-icon"></image>
<text class="service-title">定制服务</text>
</view>
<view class="service-list" style="border-radius: 8rpx;">
<view class="service-row" v-for="(item, index) in customServices" :key="item.skuId">
<view class="service-row-content" :style="{'border-bottom': index !== customServices.length-1 ? '1rpx solid #EFEFEF' : 'none'}">
<text class="service-name" style="">{{item.name}}</text>
<view class="service-price">
<text style="font-size: 32rpx; color: #FFBF60; margin-right: 20rpx;">¥{{item.price}}元/次</text>
<u-number-box
slot="right-icon"
:value="item.quantity"
:name="item.name"
@change="customServiceCountChange"
step="1"
:min="0"
:max="10"
>
<view slot="minus" class="minus">
<u-icon name="minus-circle-fill" size="20" color="#FFBF60"></u-icon>
</view>
<text
slot="input"
style="width: 40rpx;text-align: center;"
class="input"
>{{item.quantity}}</text>
<view slot="plus" class="plus">
<u-icon name="plus-circle-fill" color="#FFBF60" size="20"></u-icon>
</view>
</u-number-box>
</view>
</view>
</view>
</view>
</view>
</view>
</uni-card>
</view>
<view v-if="!showPriceDetails" class="details-subscribe">
<view style="display: flex;justify-content: space-between;">
<view style="height: 80rpx;">
<view>
<text style="color: #333333;">订单总价: </text>
<text style="color: #FF530A; font-size: 40rpx;">¥{{ totalPrice }} <text style="font-size: 32rpx;">.00</text></text>
</view>
<view style="display: flex; justify-content: flex-end;" @click="togglePriceDetails">
<text v-if="currentDayPrice" style="color:#FF530A; font-size: 22rpx;"> 当日价格:¥{{ currentDayPrice }}.00 |</text>
<text style="color:#FF530A; font-size: 22rpx;margin-left: 10rpx;">明细</text>
<u-icon name="arrow-up" color="#FF530A" size="10"></u-icon>
</view>
</view>
<view style="display: flex;">
<u-button color="#FFF4E4" customStyle="width: 200rpx; color: #FFAA48; margin-right: 20rpx;" text="上一步" @click="goBack"></u-button>
<u-button color="#FFBF60" customStyle="width: 200rpx; color: #FFF;" text="确认下单" @click="goNext"></u-button>
</view>
</view>
</view>
<!-- 遮罩层 -->
<view v-if="showPriceDetails" class="price-details-overlay">
<view class="price-details">
<view class="price-details-header">
<text
style="text-align: center; width: 100%; font-size: 32rpx; font-weight: 500; color: #333333;">价格明细</text>
<u-icon name="close" @click="togglePriceDetails"></u-icon>
</view>
<view style="text-align: center; width: 100%; font-size: 28rpx; color: #AAAAAA; margin: 20rpx 0;">
实际支付金额以确认下单页为准</view>
<view class="split-line"></view>
<scroll-view class="price-details-body" scroll-y>
<view v-for="(item, index) in priceDetails" :key="index">
<view class="price-details-item">
<view v-if="showName(item)" style="font-size: 28rpx; color: #333333;">{{ item.name }}</view>
<view class="price-details-item-price-total">
<view style="display: flex;" v-for="(item2, index) in item.item" :key="index">
<view style="display: flex; align-items: center;">
<view v-if="item2.date && item2.quantity"
class="price-details-item-price-total-item">{{ item2.date }}</view>
<view v-if="item2.itemName != item.name && item2.quantity"
class="price-details-item-price-total-item">{{ item2.itemName }}</view>
<view v-if="item2.quantity" class="price-details-item-price-total-item">
¥{{ item2.price }} × {{ item2.quantity }} {{ item2.unit }}</view>
</view>
<view v-if="item2.quantity"
style="color: #333333; margin-left: 20rpx; margin: auto 0; width: 100rpx; text-align: right; font-size: 28rpx;">
¥{{ item2.price * item2.quantity }}</view>
</view>
</view>
</view>
</view>
</scroll-view>
<view style="position: absolute; bottom: 0; left: 0; right: 0; padding: 20rpx;">
<view class="split-line"></view>
<view class="price-details-item" style="margin: 20rpx 0;">
<view style="font-size: 32rpx; color: #333333; font-weight: 500;">合计</view>
<view style="font-size: 32rpx; color: #333333; font-weight: 500;">¥{{ totalPrice }}</view>
</view>
<view class="split-line"></view>
</view>
</view>
<view class="details-subscribe">
<view style="display: flex;justify-content: space-between;">
<view style="height: 80rpx;">
<view>
<text style="color: #333333;">订单总价: </text>
<text style="color: #FF530A; font-size: 40rpx;">¥{{ totalPrice }} <text style="font-size: 32rpx;">.00</text></text>
</view>
<view style="display: flex; justify-content: flex-end;" @click="togglePriceDetails">
<text v-if="currentDayPrice" style="color:#FF530A; font-size: 22rpx;"> 当日价格:¥{{ currentDayPrice }}.00 |</text>
<text style="color:#FF530A; font-size: 22rpx;margin-left: 10rpx;">明细</text>
<u-icon name="arrow-up" color="#FF530A" size="10"></u-icon>
</view>
</view>
<view style="display: flex;">
<u-button color="#FFF4E4" customStyle="width: 200rpx; color: #FFAA48; margin-right: 20rpx;" text="上一步" @click="goBack"></u-button>
<u-button color="#FFBF60" customStyle="width: 200rpx; color: #FFF;" text="确认下单" @click="goNext"></u-button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
getProductList,
getOpenId
} from "@/api/system/user"
import { setToken,setOpenIdKey } from '@/utils/auth'
export default {
data() {
return {
basePrice:75,
baseProduct:'专业喂养',
currentPets: [],
currentPetId: '',
currentMonthDay: {},
selectedDates: [],
groupedDates: [],
timeSlots: [
{
id: 'MORNING',
name: '早上',
time: '08:00-12:00',
selected: false,
activeIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/morning.png',
inactiveIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/morning_un.png'
},
{
id: 'AFTERNOON',
name: '午后',
time: '12:00-18:00',
selected: false,
activeIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/noon.png',
inactiveIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/noon_un.png'
},
{
id: 'EVENING',
name: '晚间',
time: '18:00-22:00',
selected: false,
activeIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/night.png',
inactiveIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/night_un.png'
}
],
feedCount:1,
// customServices原始值
customServicesStr:'',
customServices: [
{ name: '陪玩(20分钟)', price: 20, quantity: 0 },
{ name: '活动区吸毛', price: 20, quantity: 0 },
{ name: '毛发梳理', price: 15, quantity: 0 },
{ name: '身体清洁(如眼、耳、鼻等)', price: 5, quantity: 0 },
{ name: '指甲修剪', price: 10, quantity: 0 },
{ name: '会员深度清洁', price: 20, quantity: 0 },
{ name: '喂药', price: 15, quantity: 0 },
{ name: '上药', price: 25, quantity: 0 }
],
showPriceDetails: false, // 控制价格明细的显示
priceDetails: [],
totalPrice: 0,
isAllSame: false,
newOrderData: [],
// 提前熟悉费用
needPreFamiliarizeCost: 0,
// 基础服务总费用
baseServiceTotalCost: 0,
// 额外宠物总费用
additionalTotalCost: 0,
// 多次服务总费用
multServicesTotalCost: 0,
// 定制服务总费用
customServicesTotalCost: 0,
// 一天两次日期
oneDayTwoTimesDates: [],
// 一天三次日期
oneDayThreeTimesDates: [],
// 宠物类型次数统计
petTypeCounts: [],
// 定制服务单项总次数统计
customServiceItemCount:[],
// 当日价格
currentDayPrice : 0,
}
},
onLoad: function(option) {
},
mounted() {
this.currentPets = this.$globalData.newOrderData.currentPets;
if(this.currentPets.length<1){
uni.reLaunch({
url: '/pages/index'
});
return
}
if(this.$globalData.mainSku&&this.$globalData.mainSku[0]){
this.basePrice = this.$globalData.mainSku[0].price
this.baseProduct = this.$globalData.mainSku[0].name
}
this.getProductList()
},
watch: {
currentPetId: {
immediate: true,
handler(newId) {
if (newId) {
this.updateGroupedDates()
}
}
}
},
methods: {
initNewOrderData(){
const needPreFamiliarize=this.$globalData.newOrderData.needPreFamiliarize.length>0
const pets=[]
// 初始化当前宠物全日期保持一致
this.currentPets = this.currentPets.map(pet=>{
pet.isAllSame = false
return pet
})
this.currentPets.map(pet=>{
// 单个宠物服务日期列表
const serviceDateList = pet.selectedDate.map(item => item.date)
serviceDateList.forEach(date => {
pets.push({
petId: pet.id,
serviceDate: date,
name: pet.name,
gender: pet.gender,
petType: pet.petType,
bodyType:pet.bodyType,
photo: pet.photo,
feedCount: 1,
selectedTimeSlots: [],
customServices: [],
//额外费用
additionalCost: 0
})
})
})
this.newOrderData = {
needPreFamiliarize: needPreFamiliarize, // 是否需要提前熟悉 40元/次 参与计算
pets: pets
}
// 默认选择第一个宠物
this.selectPet(this.currentPets[0] || {})
this.calculateTotalPrice()
},
// 选择宠物
selectPet(pet) {
this.currentPetId = pet.id
// 默认选择当前宠物的最小日期
if (pet.selectedDate?.length > 1) {
const minDate = pet.selectedDate.reduce((min, date) => {
const currentDate = new Date(date.date);
const minDate = new Date(min.date);
return currentDate < minDate ? date : min;
}, pet.selectedDate[0]);
// 当前选择日期
this.currentMonthDay = {
petId: this.currentPetId,
date: new Date(minDate.date).getDate(),
fullDate: minDate.date
}
} else {
this.currentMonthDay = {
petId: this.currentPetId,
date: new Date(pet.selectedDate[0].date).getDate(),
fullDate: pet.selectedDate[0].date
}
}
this.getCurrentPetIsAllSame()
this.selectDate(this.currentMonthDay)
},
selectDate(day) {
// 当前选择日期
this.currentMonthDay = day
const selectedDay = this.selectedDates?.find(item => item.fullDate === day.fullDate && item
.currentPetId === day.petId)
if (!selectedDay) {
this.selectedDates.push(day)
}
// 还原当前选择日期是否已选择期望时间
const pets = this.newOrderData?.pets
const selectedPet = pets.find(pet => pet.petId === this.currentPetId && pet.serviceDate === this
.currentMonthDay.fullDate);
const selectedTimeSlots = selectedPet ? selectedPet.selectedTimeSlots : [];
if(selectedTimeSlots.length > 0){
this.timeSlots.forEach(slot=>{
if(selectedTimeSlots.includes(slot.id)){
slot.selected = true
} else {
slot.selected = false
}
})
} else {
this.timeSlots.forEach(slot => {
slot.selected = false
})
}
// 还原当前选择日期喂食次数
this.feedCount = selectedPet ? selectedPet.feedCount : 1
// 还原当前选择日期是否已选择定制服务
this.customServices = selectedPet.customServices.length > 0 ? selectedPet.customServices : JSON.parse(this.customServicesStr)
this.getCurrentDayPrice(this.currentMonthDay.fullDate)
},
isDateSelected(day) {
const selectedDay = this.selectedDates.find(item => item.fullDate === day.fullDate && this.currentPetId ===
item.petId)
if (selectedDay) {
return true
}
return false
},
isCurrentSelected(day){
return this.currentMonthDay.fullDate === day.fullDate && this.currentPetId === day.petId
},
updateGroupedDates() {
const currentPet = this.currentPets.find(pet => pet.id === this.currentPetId)
if (!currentPet) return
// 按月份分组日期
const grouped = currentPet.selectedDate.reduce((acc, dateObj) => {
const date = new Date(dateObj.date)
const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`
const monthLabel = `${date.getFullYear()}年${date.getMonth() + 1}月`
if (!acc[monthKey]) {
acc[monthKey] = {
monthLabel,
dates: []
}
}
acc[monthKey].dates.push({
petId: currentPet.id,
date: date.getDate(),
fullDate: dateObj.date
})
return acc
}, {})
// 转换为数组并排序
this.groupedDates = Object.values(grouped).sort((a, b) => {
return a.monthLabel.localeCompare(b.monthLabel)
})
},
selectTimeSlot(slotId) {
const slot = this.timeSlots.find(slot => slot.id === slotId)
if (slot) {
slot.selected = !slot.selected
}
// 将期望时间添加到当前宠物
const selectedTimeSlots = this.timeSlots.filter(slot => slot.selected)
if(this.isAllSame){
// 如果保持一致,则更新该宠物所有期望时间
this.newOrderData.pets.forEach(pet=>{
pet.selectedTimeSlots=selectedTimeSlots.map(item => item.id)
})
} else{
const currentPetIndex = this.newOrderData.pets.findIndex(pet => pet.petId === this.currentPetId
&& pet.serviceDate === this.currentMonthDay.fullDate)
if (currentPetIndex !== -1) {
this.newOrderData.pets[currentPetIndex].selectedTimeSlots = selectedTimeSlots.map(item => item.id)
}
}
},
feedCountChange(e){
this.feedCount = e.value
if(this.isAllSame){
// 如果保持一致,则更新该宠物的喂食次数
this.newOrderData.pets.forEach(pet=>{
if(pet.petId === this.currentPetId){
pet.feedCount=this.feedCount
}
})
} else {
const pets = this.newOrderData.pets
const currentPetIndex = pets.findIndex(pet => pet.petId === this.currentPetId && pet.serviceDate ===
this.currentMonthDay.fullDate)
if (currentPetIndex !== -1) {
this.newOrderData.pets[currentPetIndex].feedCount = this.feedCount
}
}
this.calculateTotalPrice()
},
customServiceCountChange(val) {
console.log(val)
this.customServices.forEach(item=>{
if(item.name === val.name){
item.quantity = val.value
}
})
if(this.isAllSame){
// 如果保持一致,则更新当前宠物的定制服务次数
this.newOrderData.pets.forEach(pet=>{
if(pet.petId === this.currentPetId){
pet.customServices= JSON.parse(JSON.stringify(this.customServices))
}
})
} else {
const pets = this.newOrderData.pets
const currentPetIndex = pets.findIndex(pet => pet.petId === this.currentPetId && pet.serviceDate ===
this.currentMonthDay.fullDate)
if (currentPetIndex !== -1) {
this.newOrderData.pets[currentPetIndex].customServices = JSON.parse(JSON.stringify(this
.customServices))
}
}
this.calculateTotalPrice()
},
togglePriceDetails() {
this.showPriceDetails = !this.showPriceDetails; // 切换价格明细的显示状态
if (this.showPriceDetails) {
this.priceDetailDate()
}
},
calculateTotalPrice() {
// 1. 订单维度:是否需要提前熟悉
if(this.$globalData.newOrderData.needPreFamiliarize && this.$globalData.newOrderData.needPreFamiliarize.length>0){
this.needPreFamiliarizeCost = 40
}else{
this.needPreFamiliarizeCost = 0
}
// 2. 日期维度
// 2.1 基础服务费用
const uniqueDates = new Set(this.newOrderData.pets.map(item => item.serviceDate)); // 去重日期
this.baseServiceTotalCost = uniqueDates.size * this.basePrice; // 每个唯一日期75元
// 2.2 额外宠物费用
// petType为dog 且bodyType包含 '大型' 则为大型犬,40元/次
// petType为dog 且bodyType包含 '中型' 则为中型犬,30元/次
// petType为dog 且bodyType包含 '小型' 则为小型犬,15元/次
// petType为cat 则为猫,10元/次
this.newOrderData.pets.forEach(pet => {
if (pet.petType === 'dog' && pet.bodyType.includes('大型')) {
pet.additionalCost = 40
} else if (pet.petType === 'dog' && pet.bodyType.includes('中型')) {
pet.additionalCost = 30
} else if (pet.petType === 'dog' && pet.bodyType.includes('小型')) {
pet.additionalCost = 15
} else if (pet.petType === 'cat') {
pet.additionalCost = 10
}
})
// const largeDogArray = this.newOrderData.pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('大型'));
// this.additionalTotalCost = this.additionalTotalCost + (largeDogArray.length * 40)
// // 非大型犬
// const otherPets = this.newOrderData.pets.filter(pet => pet.petType !== 'dog' && !pet.bodyType.includes('大型'));
// 宠物日期分组
const dailyPets = [];
// 按日期分组宠物
this.newOrderData.pets.forEach(pet => {
const serviceDate = pet.serviceDate;
if (!dailyPets[serviceDate]) {
dailyPets[serviceDate] = [];
}
dailyPets[serviceDate].push(pet);
});
const petTypeCounts = []
let additionalTotalCost = 0
// 计算每日额外宠物费用
for (const date in dailyPets) {
const pets = dailyPets[date];
const largeDogCount = pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('大型')).length;
let mediumDogCount = pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('中型')).length;
let smallDogCount = pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('小型')).length;
let catCount = pets.filter(pet => pet.petType === 'cat').length;
let additionalCost = 0
// 总宠物费用
let totalPetCost = pets.reduce((acc, pet) => {
return acc + this.calculatePetCost(pet);
}, 0);
// 如果总宠物费用>30
if (totalPetCost > 30) {
// 如果猫数量>=3
if (catCount >= 3) {
additionalCost = totalPetCost - 30
catCount = catCount - 3
} else if (smallDogCount >= 2) {
additionalCost = totalPetCost - 30
smallDogCount = smallDogCount - 2
} else if (mediumDogCount >= 1) {
additionalCost = totalPetCost - 30
mediumDogCount = mediumDogCount - 1
} else {
additionalCost = totalPetCost - 25
catCount = catCount - 1
smallDogCount = smallDogCount - 1
}
petTypeCounts.push({
date,
largeDogCount,
mediumDogCount,
smallDogCount,
catCount
})
}
// 如果有大型犬,额外费用为40元/只
if (largeDogCount > 0) {
additionalCost += (40 * largeDogCount)
}
// 如果有额外费用,添加到总额外费用
if (additionalCost > 0) {
additionalTotalCost += additionalCost;
}
}
this.additionalTotalCost = additionalTotalCost
this.petTypeCounts = petTypeCounts
// 2.3 当日多次服务总价
// 计算每日多次服务次数费用
let multServicesTotalCost = 0
let oneDayTwoTimesDates = []
let oneDayThreeTimesDates = []
for (const date in dailyPets) {
const maxFeedCount = Math.max(...dailyPets[date].map(pet => pet.feedCount));
if (maxFeedCount === 2) {
multServicesTotalCost += 45; // 1天2次
oneDayTwoTimesDates.push(date)
} else if (maxFeedCount === 3) {
multServicesTotalCost += 130; // 1天3次
oneDayThreeTimesDates.push(date)
}
}
this.oneDayTwoTimesDates = oneDayTwoTimesDates
this.oneDayThreeTimesDates = oneDayThreeTimesDates
this.multServicesTotalCost = multServicesTotalCost
// 3. 定制服务
//定制服务单项总次数统计
const customServiceItemCount = JSON.parse(this.customServicesStr)
let customServicesTotalCost = 0
this.newOrderData.pets.forEach(pet => {
const customServices = pet.customServices
// 定制服务费用
customServices.forEach(service=>{
const itemIndex = customServiceItemCount.findIndex(item=>item.name === service.name)
if(itemIndex !== -1){
customServiceItemCount[itemIndex].quantity += service.quantity
}
customServicesTotalCost += service.price * service.quantity;
})
});
this.customServiceItemCount = customServiceItemCount
this.customServicesTotalCost = customServicesTotalCost
this.totalPrice = this.needPreFamiliarizeCost
+ this.baseServiceTotalCost
+ this.additionalTotalCost
+ this.multServicesTotalCost
+ this.customServicesTotalCost; // 更新总价
this.getCurrentDayPrice(this.currentMonthDay.fullDate)
},
calculatePetCost(pet) {
// 宠物额外费用 不计算大型犬
let petCost = 0;
if (pet.petType === 'cat') {
petCost += 10; // 猫额外费用
} else if (pet.petType === 'dog' && pet.bodyType.includes('小型')) {
petCost += 15; // 小型犬额外费用
} else if (pet.petType === 'dog' && pet.bodyType.includes('中型')) {
petCost += 30; // 中型犬额外费用
}
return petCost;
},
goNext() {
this.calculateTotalPrice(); // 计算总价
this.showPriceDetails = false;
this.$globalData.newOrderData.currentPetsByDay = this.newOrderData.pets
this.$globalData.newOrderData.totalPrice = this.totalPrice
uni.navigateTo({
url: '/pages/newOrder/confirmOrder'
});
},
goBack() {
this.showPriceDetails = false
let len = getCurrentPages().length;
this.loading = false
if (len >= 2) {
uni.navigateBack();
} else {
uni.redirectTo({
url: '/pages/newOrder/serviceNew'
});
}
},
// 价格明细数据
priceDetailDate() {
const priceDetails = []
if (this.newOrderData.needPreFamiliarize) {
priceDetails.push({
name: '提前熟悉',
item: [{
itemName: '提前熟悉',
price: 40,
quantity: this.newOrderData.needPreFamiliarize ? 1 : 0,
unit: '次'
}, ]
})
}
const uniqueDateCount = new Set(this.newOrderData.pets.map(item => item.serviceDate)).size; // 去重日期
if(uniqueDateCount>1){
priceDetails.push({ name: this.baseProduct, item: [
{ itemName: this.baseProduct, price:this.basePrice, quantity: uniqueDateCount, unit: '天' },
]})
}
if (this.oneDayTwoTimesDates.length > 0 || this.oneDayThreeTimesDates.length > 0) {
priceDetails.push({
name: '上门次数',
item: [{
itemName: '1天2次',
price: 45,
quantity: this.oneDayTwoTimesDates.length,
unit: '天'
},
{
itemName: '1天3次',
price: 130,
quantity: this.oneDayThreeTimesDates.length,
unit: '天'
},
]
})
}
// 过滤宠物类型数量>0的数组
const additionalCostItem = []
const petTypeArr = this.petTypeCounts.filter(item => item.largeDogCount > 0 || item.mediumDogCount > 0 ||
item.smallDogCount > 0 || item.catCount > 0)
// 假设largeDogCount=1 mediumDogCount=2 smallDogCount=3 catCount=4 则生成4条数据
petTypeArr.forEach(item => {
if (item.largeDogCount > 0) {
additionalCostItem.push({
itemName: '大型犬',
price: 40,
quantity: item.largeDogCount,
unit: '只',
date: item.date
})
}
if (item.mediumDogCount > 0) {
additionalCostItem.push({
itemName: '中型犬',
price: 30,
quantity: item.mediumDogCount,
unit: '只',
date: item.date
})
}
if (item.smallDogCount > 0) {
additionalCostItem.push({
itemName: '小型犬',
price: 15,
quantity: item.smallDogCount,
unit: '只',
date: item.date
})
}
if (item.catCount > 0) {
additionalCostItem.push({
itemName: '猫猫',
price: 10,
quantity: item.catCount,
unit: '只',
date: item.date
})
}
})
// 按日期先后顺序排序
additionalCostItem.sort((a, b) => new Date(a.date) - new Date(b.date))
if (additionalCostItem.length > 0) {
priceDetails.push({
name: '额外宠物费用',
item: additionalCostItem
})
}
const customServiceItem = this.customServiceItemCount.filter(item=>item.quantity>0).map(service=>{
return { itemName: service.name, price: service.price, quantity: service.quantity, unit: '次' }
})
if (customServiceItem.length > 0) {
priceDetails.push({
name: '定制服务',
item: customServiceItem
})
}
this.priceDetails = priceDetails
this.calculateTotalPrice()
},
showName(item) {
return item.item.some(item2 => item2.quantity > 0)
},
isAllSameChange(e) {
if (e) {
this.isAllSame = true
this.setCurrentPetIsAllSame()
// 当前宠物全日期保持一致
this.newOrderData.pets.forEach(pet=>{
if(pet.petId === this.currentPetId){
pet.selectedTimeSlots = this.timeSlots.filter(slot => slot.selected).map(item => item.id)
pet.feedCount = this.feedCount
pet.customServices = this.customServices
}
})
this.calculateTotalPrice()
} else {
this.isAllSame = false
this.setCurrentPetIsAllSame()
}
},
getProductList() {
getProductList({
"publishStatus": 1,
"categoryId": 78,
"needSku": true
}).then(response => {
if (response && response.content && response.content.length > 0) {
this.customServices = response.content.map(item=>{
const skus = item.skus
if(skus && skus.length>0){
let productSku = {
"skuId": skus[0].id,
"price":skus[0].price,
"name":item.name,
"quantity": 0,
"isMainProduct":false
}
return productSku
}
})
this.customServicesStr = JSON.stringify(this.customServices)
// 初始化新订单数据
this.initNewOrderData()
}else {
uni.showToast('获取主产品失败,请联系管理员')
}
console.log(response);
})
},
login() {
uni.login({
provider: 'weixin',
success: (loginRes) => {
this.getOpenId(loginRes.code)
},
fail: function(error) {
// 授权失败处理
uni.showToast('授权失败,请授权后再试')
}
});
},
getOpenId(code) {
getOpenId(code).then(res => {
if (res.code == 200 && res.data) {
let resData = JSON.parse(res.data)
let token = resData.token;
let openId = resData.openId;
setOpenIdKey(openId)
if(token){
setToken(token)
}
}
})
},
getCurrentDayPrice(currentDay){
const currentDayPets = this.newOrderData.pets.filter(pet => pet.serviceDate === currentDay)
// 基础服务
const baseServiceCost = this.basePrice
const largeDogCount = currentDayPets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('大型')).length;
let mediumDogCount = currentDayPets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('中型')).length;
let smallDogCount = currentDayPets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('小型')).length;
let catCount = currentDayPets.filter(pet => pet.petType === 'cat').length;
const additionalCostItem = []
let additionalCost = 0
// 单天总宠物费用
let totalPetCost = currentDayPets.reduce((acc, pet) => {
return acc + this.calculatePetCost(pet);
}, 0);
// 如果总宠物费用>30
if(totalPetCost>30){
// 如果猫数量>=3,则免3只猫
if (catCount >= 3) {
additionalCost = totalPetCost - 30
catCount = catCount-3
}else if (smallDogCount >= 2) { // 如果小型犬数量>=2,则免2只小型犬
additionalCost = totalPetCost - 30
smallDogCount = smallDogCount-2
}else if(mediumDogCount >= 1) { // 如果中型犬数量>=1,则免1只中型犬
additionalCost = totalPetCost - 30
mediumDogCount = mediumDogCount-1
}else{
additionalCost = totalPetCost - 25
catCount = catCount - 1
smallDogCount = smallDogCount - 1
}
if(largeDogCount>0){
additionalCostItem.push({ itemName: '大型犬', price: 40, quantity: largeDogCount, unit: '只'})
}
if(mediumDogCount>0){
additionalCostItem.push({ itemName: '中型犬', price: 30, quantity: mediumDogCount, unit: '只'})
}
if(smallDogCount>0){
additionalCostItem.push({ itemName: '小型犬', price: 15, quantity: smallDogCount, unit: '只'})
}
if(catCount>0){
additionalCostItem.push({ itemName: '猫猫', price: 10, quantity: catCount, unit: '只'})
}
}
// 如果有大型犬,额外费用为40元/只
if (largeDogCount > 0) {
additionalCost +=(40 * largeDogCount)
}
// 当日多次服务次数
let multServicesTotalCost = 0
const maxFeedCount = Math.max(...currentDayPets.map(pet => pet.feedCount));
if (maxFeedCount === 2) {
multServicesTotalCost += 45; // 1天2次
} else if (maxFeedCount === 3) {
multServicesTotalCost += 130; // 1天3次
}
// 所有宠物定制服务费用
const customServiceCost = currentDayPets.reduce((acc, pet) => acc + this.calculatePetCustomServiceCost(pet), 0)
const totalCost = baseServiceCost + additionalCost + multServicesTotalCost + customServiceCost
this.currentDayPrice = totalCost
},
calculatePetCustomServiceCost(pet) {
const customServiceCost = pet.customServices.reduce((acc, item) => acc + item.price * item.quantity, 0)
return customServiceCost
},
getCurrentPetName(){
const currentPet = this.currentPets.find(pet=>pet.id === this.currentPetId)
return currentPet.name
},
setCurrentPetIsAllSame(){
const currentPet = this.currentPets.find(pet=>pet.id === this.currentPetId)
currentPet.isAllSame=this.isAllSame
},
getCurrentPetIsAllSame(){
const currentPet = this.currentPets.find(pet=>pet.id === this.currentPetId)
this.isAllSame = currentPet.isAllSame
},
},
computed: {
sortedGroupedDates() {
return this.groupedDates.sort((a, b) => {
const dateA = new Date(a.monthLabel.replace('年', '-').replace('月', '-01'))
const dateB = new Date(b.monthLabel.replace('年', '-').replace('月', '-01'))
return dateA - dateB
})
}
}
}
</script>
<style scoped lang="less">
.container {
position: relative;
height: 100%;
padding-bottom: 160rpx;
.details-subscribe {
background-color: #FFFFFF;
padding: 10px;
width: 100%;
height: 160rpx;
position: fixed;
bottom: 0;
z-index: 100;
.details-btn {
width: 100%;
border-radius: 6px;
background: #FFB13F;
font-size: 16px;
color: #FFFFFF;
}
}
}
.service-new {
.service-new-flag {
width: 8rpx;
height: 32rpx;
background: #FFBF60;
border-radius: 30rpx 30rpx 30rpx 30rpx;
margin-right: 10rpx;
}
.split-line {
width: 100%;
height: 1rpx;
background: #EFEFEF;
}
.service-new-title {
display: flex;
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 33rpx;
margin: 42rpx 0 30rpx;
justify-content: space-between;
.service-new-title-left {
display: flex;
align-items: center;
}
}
.service-new-pet-content{
padding: 20rpx 0;
}
.service-new-pet-item {
height: 96rpx;
width: 184rpx;
border-radius: 8rpx;
padding: 0 20rpx;
margin-right: 40rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
flex-shrink: 0;
}
.scroll-content {
display: inline-flex;
}
.scroll-view {
width: 100%;
white-space: nowrap;
}
.pet-selected {
background: #FFBF60;
color: #FFFFFF;
}
.pet-unselect {
background: #F5F5F7;
color: #7D8196;
}
}
.calendar-wrapper {
display: flex;
gap: 20rpx;
padding: 20rpx;
}
.scroll-view {
width: 100%;
white-space: nowrap;
}
.calendar-day {
position: relative;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-right: 20rpx;
flex-shrink: 0;
}
.calendar-bg {
position: absolute;
width: 88rpx;
height: 78rpx;
z-index: 1;
}
.day-text {
position: relative;
z-index: 2;
top: 5rpx;
}
.day-highlighted {
font-size: 38rpx;
font-weight: bold;
color: #FFBF60;
}
.day-normal {
color: #3E3A39;
font-size: 32rpx;
}
.month-group {
margin-bottom: 30rpx;
.month-title {
font-size: 32rpx;
color: #666;
margin-bottom: 20rpx;
}
.dates-wrapper {
display: inline-flex;
}
}
.scroll-view-vertical {
height: 100%;
}
.scroll-view-horizontal {
width: 100%;
white-space: nowrap;
}
.time-slots {
display: flex;
justify-content: space-around;
}
.time-slot-item {
display: flex;
flex-direction: column;
align-items: center;
width: 200rpx;
cursor: pointer;
}
.time-slot-icon {
width: 160rpx;
height: 160rpx;
margin-bottom: 10rpx;
}
.time-slot-info {
display: flex;
flex-direction: column;
align-items: center;
}
.time-slot-name {
font-size: 28rpx;
color: #333;
margin-bottom: 8rpx;
}
.time-slot-time {
font-size: 24rpx;
color: #666;
}
.time-slot-time-tip {
background-color: #FFECCD;
color: #A94F20;
margin-left: 10rpx;
padding: 5rpx 10rpx;
font-size: 20rpx;
}
.service-item {
margin-bottom: 20rpx;
/* 每个服务项之间的间距 */
}
.service-item-header {
display: flex;
align-items: center;
margin-bottom: 10rpx;
/* 标题与服务列表之间的间距 */
}
.service-icon {
width: 40rpx;
/* 图标大小 */
height: 40rpx;
/* 图标大小 */
margin-right: 10rpx;
/* 图标与标题之间的间距 */
}
.service-title {
font-size: 28rpx; /* 服务标题字体大小 */
font-weight: bold; /* 服务标题加粗 */
}
.service-row {
display: flex;
align-items: center;
/* 垂直居中对齐 */
flex-wrap: wrap;
background-color: #F9F9F9;
}
.service-row-content {
display: flex;
justify-content: space-between;
/* 每行的上下内边距 */
width: 100%;
padding: 32rpx 0rpx;
margin: 0 20rpx;
}
.service-name {
width: 50%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 28rpx;
color: #333;
/* 服务名称颜色 */
}
.service-price {
display: flex;
align-items: center;
/* 垂直居中对齐 */
}
.service-count {
display: flex;
align-items: center;
/* 垂直居中对齐 */
margin-left: 10rpx;
/* 价格数量之间的间距 */
}
.price-details {
position: fixed;
/* 固定位置 */
bottom: 160rpx;
/* 根据需要调整位置 */
left: 0;
right: 0;
background: #FFF;
/* 背景颜色 */
padding: 10px 10px 0 10px;
/* 内边距 */
border-radius: 8rpx 8rpx 0 0;
/* 圆角 */
z-index: 1000;
/* 确保在其他元素之上 */
min-height: 600rpx;
/* 固定高度 */
overflow: hidden;
/* 隐藏超出部分 */
}
.price-details-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.price-details-body {
margin-top: 10px;
max-height: 300rpx;
/* 留出头部空间 */
overflow-y: auto;
/* 允许上下滚动 */
}
.price-details-overlay {
position: fixed;
/* 固定位置 */
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
/* 半透明背景 */
z-index: 999;
/* 确保在其他元素之上 */
display: flex;
justify-content: center;
align-items: center;
}
.price-details-item {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
.price-details-item-price-total {
display: flex;
width: 70%;
justify-content: flex-end;
flex-wrap: wrap;
}
.price-details-item-price-total-item {
color: #999999;
text-align: right;
font-size: 28rpx;
margin-right: 20rpx;
}
}
</style>