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.

1427 lines
43 KiB

2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
  1. <template>
  2. <view class="service-new container">
  3. <view style="background-color: #FFF4E5; margin: 10px; padding: 10px; border-radius: 8rpx;">
  4. <view style="display: flex;">
  5. <image style="width: 40rpx; height: 40rpx;" slot='cover' src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/petServiceOrder/OrderIcon.png">
  6. </image>
  7. <text style="color: #A94F20; font-size: 28rpx; font-weight: 500;">
  8. 下单方式
  9. <text v-if="orderMethod">指定喂养员 - {{orderName}}</text>
  10. <text v-else>系统派单</text>
  11. </text>
  12. </view>
  13. <view style="margin-top: 10rpx;">
  14. <text v-if="orderMethod" style="color: #A94F20; font-size: 24rpx; font-weight: 400;">
  15. (若伴宠师1小时内无响应或拒绝接单则系统派单)
  16. </text>
  17. </view>
  18. </view>
  19. <view>
  20. <uni-card padding=0 :is-shadow="false">
  21. <view class="service-new-title" slot="title">
  22. <view class="service-new-title-left">
  23. <view class="service-new-flag"></view>
  24. <view>爱宠选择</view>
  25. </view>
  26. </view>
  27. <view class="split-line"></view>
  28. <view class="service-new-pet-content">
  29. <scroll-view scroll-x class="scroll-view">
  30. <view class="scroll-content">
  31. <view v-for="item in currentPets" :key="item.id" class="service-new-pet-item ellipsis"
  32. :class="{'pet-selected': item.id === currentPetId, 'pet-unselect': item.id !== currentPetId}"
  33. @click="selectPet(item)">
  34. {{ item.name }}
  35. </view>
  36. </view>
  37. </scroll-view>
  38. </view>
  39. </uni-card>
  40. </view>
  41. <view>
  42. <uni-card padding=0 :is-shadow="false">
  43. <view class="service-new-title" slot="title">
  44. <view class="service-new-title-left">
  45. <view class="service-new-flag"></view>
  46. <view>服务日期</view>
  47. </view>
  48. </view>
  49. <view class="split-line"></view>
  50. <view class="service-new-pet-content">
  51. <scroll-view scroll-y class="scroll-view-vertical">
  52. <view v-for="(month, monthIndex) in sortedGroupedDates" :key="monthIndex" class="month-group">
  53. <view class="month-title">{{ month.monthLabel }}</view>
  54. <scroll-view scroll-x class="scroll-view-horizontal">
  55. <view class="dates-wrapper">
  56. <view v-for="(day, dayIndex) in month.dates" :key="dayIndex" class="calendar-day"
  57. :class="{'day-selected': isDateSelected(day)}" @click="selectDate(day)">
  58. <image :src="isDateSelected(day) ?
  59. 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/updated.png' :
  60. 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/update_un.png'"
  61. class="calendar-bg"/>
  62. <text class="day-text" :class="{'day-highlighted': isCurrentSelected(day) ,'day-normal': !isCurrentSelected(day)} ">
  63. {{ day.date < 10 ? '0' + day.date : day.date }}</text>
  64. </view>
  65. </view>
  66. </scroll-view>
  67. </view>
  68. </scroll-view>
  69. </view>
  70. </uni-card>
  71. </view>
  72. <view>
  73. <uni-card padding=0 :is-shadow="false">
  74. <view class="service-new-title" slot="title">
  75. <view class="service-new-title-left">
  76. <view class="service-new-flag"></view>
  77. <view>期望时间 <span class="time-slot-time-tip">*请勾选您可以接受的上门时间段</span></view>
  78. </view>
  79. </view>
  80. <view class="split-line"></view>
  81. <view class="service-new-pet-content">
  82. <view class="time-slots">
  83. <view v-for="slot in timeSlots" :key="slot.id" class="time-slot-item"
  84. @click="selectTimeSlot(slot.id)">
  85. <image :src="slot.selected ? slot.activeIcon : slot.inactiveIcon" class="time-slot-icon" />
  86. <view class="time-slot-info">
  87. <text class="time-slot-time">{{ slot.time }}</text>
  88. </view>
  89. </view>
  90. </view>
  91. </view>
  92. </uni-card>
  93. </view>
  94. <view>
  95. <uni-card padding=0 :is-shadow="false">
  96. <view class="service-new-title" slot="title">
  97. <view class="service-new-title-left">
  98. <view class="service-new-flag"></view>
  99. <view>服务选择</view>
  100. </view>
  101. <view style="display: flex; justify-content: flex-end; align-items: center; ">
  102. <view style="margin-right: 10rpx;color: #AAAAAA;">爱宠{{currentPetId && getCurrentPetName()}} 全日期保持一致</view>
  103. <u-switch
  104. space="2" :value="isAllSame" activeColor="#f9ae3d" size="18"
  105. @change="isAllSameChange"
  106. inactiveColor="rgb(230, 230, 230)">
  107. </u-switch>
  108. </view>
  109. </view>
  110. <view class="split-line"></view>
  111. <view class="service-new-pet-content">
  112. <view class="service-item">
  113. <view class="service-item-header">
  114. <image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/service.png"
  115. class="service-icon"></image>
  116. <text class="service-title">基础服务</text>
  117. </view>
  118. <view class="service-list">
  119. <!-- <view style="border-radius: 8rpx" :style="{'background-color': needFeed.length > 0 ? '#FFFCF2' : '#F9F9F9', 'border': needFeed.length > 0 ? '1px solid #FFBF60' : 'none'}" >
  120. <view style="padding: 30rpx 0; margin: 0 20rpx; ">
  121. <u-checkbox-group
  122. v-model="needFeed"
  123. iconPlacement="right"
  124. placement="column">
  125. <u-checkbox activeColor="#FFBF60" label="专业喂养" shape="circle"></u-checkbox>
  126. </u-checkbox-group>
  127. </view>
  128. </view> -->
  129. <view class="service-list" style="border-radius: 8rpx;margin-top: 28rpx;">
  130. <view class="service-row" style="background-color: #FFECCD">
  131. <view class="service-row-content"
  132. :style="{'border-bottom': feedCount > 1 ? '1rpx solid #ECBFA8' : 'none'}">
  133. <text class="service-name" style="color: #A94F20;">一天多次</text>
  134. <view class="service-price">
  135. <u-number-box
  136. slot="right-icon"
  137. :value="feedCount"
  138. @change="feedCountChange"
  139. step="1"
  140. :min="1"
  141. :max="3"
  142. >
  143. <view slot="minus" class="minus">
  144. <u-icon name="minus-circle-fill" size="20" color="#FFBF60"></u-icon>
  145. </view>
  146. <text slot="input" style="width: 40rpx;text-align: center;"
  147. class="input">{{feedCount}}</text>
  148. <view slot="plus" class="plus">
  149. <u-icon name="plus-circle-fill" color="#FFBF60" size="20"></u-icon>
  150. </view>
  151. </u-number-box>
  152. </view>
  153. </view>
  154. </view>
  155. <view v-if="feedCount > 1" class="service-row" style="background-color: #FFECCD">
  156. <view class="service-row-content">
  157. <text class="service-name" style="color: #A94F20;">额外服务费</text>
  158. <view class="service-price" style="color:#A94F20">
  159. ¥{{ feedCount >2? 130 : 45}}
  160. </view>
  161. </view>
  162. </view>
  163. </view>
  164. </view>
  165. </view>
  166. <view class="service-item">
  167. <view class="service-item-header">
  168. <image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/love.png"
  169. class="service-icon"></image>
  170. <text class="service-title">定制服务</text>
  171. </view>
  172. <view class="service-list" style="border-radius: 8rpx;">
  173. <view class="service-row" v-for="(item, index) in customServices" :key="item.skuId">
  174. <view class="service-row-content" :style="{'border-bottom': index !== customServices.length-1 ? '1rpx solid #EFEFEF' : 'none'}">
  175. <text class="service-name" style="">{{item.name}}</text>
  176. <view class="service-price">
  177. <text style="font-size: 32rpx; color: #FFBF60; margin-right: 20rpx;">¥{{item.price}}/</text>
  178. <u-number-box
  179. slot="right-icon"
  180. :value="item.quantity"
  181. :name="item.name"
  182. @change="customServiceCountChange"
  183. step="1"
  184. :min="0"
  185. :max="10"
  186. >
  187. <view slot="minus" class="minus">
  188. <u-icon name="minus-circle-fill" size="20" color="#FFBF60"></u-icon>
  189. </view>
  190. <text
  191. slot="input"
  192. style="width: 40rpx;text-align: center;"
  193. class="input"
  194. >{{item.quantity}}</text>
  195. <view slot="plus" class="plus">
  196. <u-icon name="plus-circle-fill" color="#FFBF60" size="20"></u-icon>
  197. </view>
  198. </u-number-box>
  199. </view>
  200. </view>
  201. </view>
  202. </view>
  203. </view>
  204. </view>
  205. </uni-card>
  206. </view>
  207. <view v-if="!showPriceDetails" class="details-subscribe">
  208. <view style="display: flex;justify-content: space-between;">
  209. <view style="height: 80rpx;">
  210. <view>
  211. <text style="color: #333333;">订单总价 </text>
  212. <text style="color: #FF530A; font-size: 40rpx;">¥{{ totalPrice }} <text style="font-size: 32rpx;">.00</text></text>
  213. </view>
  214. <view style="display: flex; justify-content: flex-end;" @click="togglePriceDetails">
  215. <text v-if="currentDayPrice" style="color:#FF530A; font-size: 22rpx;"> 当日价格¥{{ currentDayPrice }}.00 |</text>
  216. <text style="color:#FF530A; font-size: 22rpx;margin-left: 10rpx;">明细</text>
  217. <u-icon name="arrow-up" color="#FF530A" size="10"></u-icon>
  218. </view>
  219. </view>
  220. <view style="display: flex;">
  221. <u-button color="#FFF4E4" customStyle="width: 200rpx; color: #FFAA48; margin-right: 20rpx;" text="上一步" @click="goBack"></u-button>
  222. <u-button color="#FFBF60" customStyle="width: 200rpx; color: #FFF;" text="确认下单" @click="goNext"></u-button>
  223. </view>
  224. </view>
  225. </view>
  226. <!-- 遮罩层 -->
  227. <view v-if="showPriceDetails" class="price-details-overlay">
  228. <view class="price-details">
  229. <view class="price-details-header">
  230. <text
  231. style="text-align: center; width: 100%; font-size: 32rpx; font-weight: 500; color: #333333;">价格明细</text>
  232. <u-icon name="close" @click="togglePriceDetails"></u-icon>
  233. </view>
  234. <view style="text-align: center; width: 100%; font-size: 28rpx; color: #AAAAAA; margin: 20rpx 0;">
  235. 实际支付金额以确认下单页为准</view>
  236. <view class="split-line"></view>
  237. <scroll-view class="price-details-body" scroll-y>
  238. <view v-for="(item, index) in priceDetails" :key="index">
  239. <view class="price-details-item">
  240. <view v-if="showName(item)" style="font-size: 28rpx; color: #333333;">{{ item.name }}</view>
  241. <view class="price-details-item-price-total">
  242. <view style="display: flex;" v-for="(item2, index) in item.item" :key="index">
  243. <view style="display: flex; align-items: center;">
  244. <view v-if="item2.date && item2.quantity"
  245. class="price-details-item-price-total-item">{{ item2.date }}</view>
  246. <view v-if="item2.itemName != item.name && item2.quantity"
  247. class="price-details-item-price-total-item">{{ item2.itemName }}</view>
  248. <view v-if="item2.quantity" class="price-details-item-price-total-item">
  249. ¥{{ item2.price }} × {{ item2.quantity }} {{ item2.unit }}</view>
  250. </view>
  251. <view v-if="item2.quantity"
  252. style="color: #333333; margin-left: 20rpx; margin: auto 0; width: 100rpx; text-align: right; font-size: 28rpx;">
  253. ¥{{ item2.price * item2.quantity }}</view>
  254. </view>
  255. </view>
  256. </view>
  257. </view>
  258. </scroll-view>
  259. <view style="position: absolute; bottom: 0; left: 0; right: 0; padding: 20rpx;">
  260. <view class="split-line"></view>
  261. <view class="price-details-item" style="margin: 20rpx 0;">
  262. <view style="font-size: 32rpx; color: #333333; font-weight: 500;">合计</view>
  263. <view style="font-size: 32rpx; color: #333333; font-weight: 500;">¥{{ totalPrice }}</view>
  264. </view>
  265. <view class="split-line"></view>
  266. </view>
  267. </view>
  268. <view class="details-subscribe">
  269. <view style="display: flex;justify-content: space-between;">
  270. <view style="height: 80rpx;">
  271. <view>
  272. <text style="color: #333333;">订单总价 </text>
  273. <text style="color: #FF530A; font-size: 40rpx;">¥{{ totalPrice }} <text style="font-size: 32rpx;">.00</text></text>
  274. </view>
  275. <view style="display: flex; justify-content: flex-end;" @click="togglePriceDetails">
  276. <text v-if="currentDayPrice" style="color:#FF530A; font-size: 22rpx;"> 当日价格¥{{ currentDayPrice }}.00 |</text>
  277. <text style="color:#FF530A; font-size: 22rpx;margin-left: 10rpx;">明细</text>
  278. <u-icon name="arrow-up" color="#FF530A" size="10"></u-icon>
  279. </view>
  280. </view>
  281. <view style="display: flex;">
  282. <u-button color="#FFF4E4" customStyle="width: 200rpx; color: #FFAA48; margin-right: 20rpx;" text="上一步" @click="goBack"></u-button>
  283. <u-button color="#FFBF60" customStyle="width: 200rpx; color: #FFF;" text="确认下单" @click="goNext"></u-button>
  284. </view>
  285. </view>
  286. </view>
  287. </view>
  288. </view>
  289. </template>
  290. <script>
  291. import {
  292. getProductList,
  293. getOpenId
  294. } from "@/api/system/user"
  295. import { setToken,setOpenIdKey } from '@/utils/auth'
  296. export default {
  297. data() {
  298. return {
  299. basePrice:75,
  300. baseProduct:'专业喂养',
  301. currentPets: [],
  302. currentPetId: '',
  303. currentMonthDay: {},
  304. selectedDates: [],
  305. groupedDates: [],
  306. timeSlots: [
  307. {
  308. id: 'MORNING',
  309. name: '早上',
  310. time: '08:00-12:00',
  311. selected: false,
  312. activeIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/morning.png',
  313. inactiveIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/morning_un.png'
  314. },
  315. {
  316. id: 'AFTERNOON',
  317. name: '午后',
  318. time: '12:00-18:00',
  319. selected: false,
  320. activeIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/noon.png',
  321. inactiveIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/noon_un.png'
  322. },
  323. {
  324. id: 'EVENING',
  325. name: '晚间',
  326. time: '18:00-22:00',
  327. selected: false,
  328. activeIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/night.png',
  329. inactiveIcon: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/newOrder/night_un.png'
  330. }
  331. ],
  332. feedCount:1,
  333. // customServices原始值
  334. customServicesStr:'',
  335. customServices: [
  336. { name: '陪玩(20分钟)', price: 20, quantity: 0 },
  337. { name: '活动区吸毛', price: 20, quantity: 0 },
  338. { name: '毛发梳理', price: 15, quantity: 0 },
  339. { name: '身体清洁(如眼、耳、鼻等)', price: 5, quantity: 0 },
  340. { name: '指甲修剪', price: 10, quantity: 0 },
  341. { name: '会员深度清洁', price: 20, quantity: 0 },
  342. { name: '喂药', price: 15, quantity: 0 },
  343. { name: '上药', price: 25, quantity: 0 }
  344. ],
  345. showPriceDetails: false, // 控制价格明细的显示
  346. priceDetails: [],
  347. totalPrice: 0,
  348. isAllSame: false,
  349. newOrderData: [],
  350. // 提前熟悉费用
  351. needPreFamiliarizeCost: 0,
  352. // 基础服务总费用
  353. baseServiceTotalCost: 0,
  354. // 额外宠物总费用
  355. additionalTotalCost: 0,
  356. // 多次服务总费用
  357. multServicesTotalCost: 0,
  358. // 定制服务总费用
  359. customServicesTotalCost: 0,
  360. // 一天两次日期
  361. oneDayTwoTimesDates: [],
  362. // 一天三次日期
  363. oneDayThreeTimesDates: [],
  364. // 宠物类型次数统计
  365. petTypeCounts: [],
  366. // 定制服务单项总次数统计
  367. customServiceItemCount:[],
  368. // 当日价格
  369. currentDayPrice : 0,
  370. // 是否指定喂养员
  371. orderMethod : false,
  372. // 指定喂养员姓名
  373. orderName : '',
  374. // 指定喂养员id
  375. servicerId : 0,
  376. }
  377. },
  378. onLoad: function(option) {
  379. if (option.userName) {
  380. this.orderMethod = true
  381. this.orderName = option.userName;
  382. this.servicerId = option.servicerId;
  383. }
  384. },
  385. mounted() {
  386. this.currentPets = this.$globalData.newOrderData.currentPets;
  387. if(this.currentPets.length<1){
  388. uni.reLaunch({
  389. url: '/pages/index'
  390. });
  391. return
  392. }
  393. if(this.$globalData.mainSku&&this.$globalData.mainSku[0]){
  394. this.basePrice = this.$globalData.mainSku[0].price
  395. this.baseProduct = this.$globalData.mainSku[0].name
  396. }
  397. this.getProductList()
  398. },
  399. watch: {
  400. currentPetId: {
  401. immediate: true,
  402. handler(newId) {
  403. if (newId) {
  404. this.updateGroupedDates()
  405. }
  406. }
  407. }
  408. },
  409. methods: {
  410. initNewOrderData(){
  411. const needPreFamiliarize=this.$globalData.newOrderData.needPreFamiliarize.length>0
  412. const pets=[]
  413. // 初始化当前宠物全日期保持一致
  414. this.currentPets = this.currentPets.map(pet=>{
  415. pet.isAllSame = false
  416. return pet
  417. })
  418. this.currentPets.map(pet=>{
  419. // 单个宠物服务日期列表
  420. const serviceDateList = pet.selectedDate.map(item => item.date)
  421. serviceDateList.forEach(date => {
  422. pets.push({
  423. petId: pet.id,
  424. serviceDate: date,
  425. name: pet.name,
  426. gender: pet.gender,
  427. petType: pet.petType,
  428. bodyType:pet.bodyType,
  429. photo: pet.photo,
  430. feedCount: 1,
  431. selectedTimeSlots: [],
  432. customServices: [],
  433. //额外费用
  434. additionalCost: 0
  435. })
  436. })
  437. })
  438. this.newOrderData = {
  439. needPreFamiliarize: needPreFamiliarize, // 是否需要提前熟悉 40元/次 参与计算
  440. pets: pets
  441. }
  442. // 默认选择第一个宠物
  443. this.selectPet(this.currentPets[0] || {})
  444. this.calculateTotalPrice()
  445. },
  446. // 选择宠物
  447. selectPet(pet) {
  448. this.currentPetId = pet.id
  449. // 默认选择当前宠物的最小日期
  450. if (pet.selectedDate?.length > 1) {
  451. const minDate = pet.selectedDate.reduce((min, date) => {
  452. const currentDate = new Date(date.date);
  453. const minDate = new Date(min.date);
  454. return currentDate < minDate ? date : min;
  455. }, pet.selectedDate[0]);
  456. // 当前选择日期
  457. this.currentMonthDay = {
  458. petId: this.currentPetId,
  459. date: new Date(minDate.date).getDate(),
  460. fullDate: minDate.date
  461. }
  462. } else {
  463. this.currentMonthDay = {
  464. petId: this.currentPetId,
  465. date: new Date(pet.selectedDate[0].date).getDate(),
  466. fullDate: pet.selectedDate[0].date
  467. }
  468. }
  469. this.getCurrentPetIsAllSame()
  470. this.selectDate(this.currentMonthDay)
  471. },
  472. selectDate(day) {
  473. // 当前选择日期
  474. this.currentMonthDay = day
  475. const selectedDay = this.selectedDates?.find(item => item.fullDate === day.fullDate && item
  476. .currentPetId === day.petId)
  477. if (!selectedDay) {
  478. this.selectedDates.push(day)
  479. }
  480. // 还原当前选择日期是否已选择期望时间
  481. const pets = this.newOrderData?.pets
  482. const selectedPet = pets.find(pet => pet.petId === this.currentPetId && pet.serviceDate === this
  483. .currentMonthDay.fullDate);
  484. const selectedTimeSlots = selectedPet ? selectedPet.selectedTimeSlots : [];
  485. if(selectedTimeSlots.length > 0){
  486. this.timeSlots.forEach(slot=>{
  487. if(selectedTimeSlots.includes(slot.id)){
  488. slot.selected = true
  489. } else {
  490. slot.selected = false
  491. }
  492. })
  493. } else {
  494. this.timeSlots.forEach(slot => {
  495. slot.selected = false
  496. })
  497. }
  498. // 还原当前选择日期喂食次数
  499. this.feedCount = selectedPet ? selectedPet.feedCount : 1
  500. // 还原当前选择日期是否已选择定制服务
  501. this.customServices = selectedPet.customServices.length > 0 ? selectedPet.customServices : JSON.parse(this.customServicesStr)
  502. this.getCurrentDayPrice(this.currentMonthDay.fullDate)
  503. },
  504. isDateSelected(day) {
  505. const selectedDay = this.selectedDates.find(item => item.fullDate === day.fullDate && this.currentPetId ===
  506. item.petId)
  507. if (selectedDay) {
  508. return true
  509. }
  510. return false
  511. },
  512. isCurrentSelected(day){
  513. return this.currentMonthDay.fullDate === day.fullDate && this.currentPetId === day.petId
  514. },
  515. updateGroupedDates() {
  516. const currentPet = this.currentPets.find(pet => pet.id === this.currentPetId)
  517. if (!currentPet) return
  518. // 按月份分组日期
  519. const grouped = currentPet.selectedDate.reduce((acc, dateObj) => {
  520. const date = new Date(dateObj.date)
  521. const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`
  522. const monthLabel = `${date.getFullYear()}${date.getMonth() + 1}`
  523. if (!acc[monthKey]) {
  524. acc[monthKey] = {
  525. monthLabel,
  526. dates: []
  527. }
  528. }
  529. acc[monthKey].dates.push({
  530. petId: currentPet.id,
  531. date: date.getDate(),
  532. fullDate: dateObj.date
  533. })
  534. return acc
  535. }, {})
  536. // 转换为数组并排序
  537. this.groupedDates = Object.values(grouped).sort((a, b) => {
  538. return a.monthLabel.localeCompare(b.monthLabel)
  539. })
  540. },
  541. selectTimeSlot(slotId) {
  542. const slot = this.timeSlots.find(slot => slot.id === slotId)
  543. if (slot) {
  544. slot.selected = !slot.selected
  545. }
  546. // 将期望时间添加到当前宠物
  547. const selectedTimeSlots = this.timeSlots.filter(slot => slot.selected)
  548. if(this.isAllSame){
  549. // 如果保持一致,则更新该宠物所有期望时间
  550. this.newOrderData.pets.forEach(pet=>{
  551. pet.selectedTimeSlots=selectedTimeSlots.map(item => item.id)
  552. })
  553. } else{
  554. const currentPetIndex = this.newOrderData.pets.findIndex(pet => pet.petId === this.currentPetId
  555. && pet.serviceDate === this.currentMonthDay.fullDate)
  556. if (currentPetIndex !== -1) {
  557. this.newOrderData.pets[currentPetIndex].selectedTimeSlots = selectedTimeSlots.map(item => item.id)
  558. }
  559. }
  560. },
  561. feedCountChange(e){
  562. this.feedCount = e.value
  563. if(this.isAllSame){
  564. // 如果保持一致,则更新该宠物的喂食次数
  565. this.newOrderData.pets.forEach(pet=>{
  566. if(pet.petId === this.currentPetId){
  567. pet.feedCount=this.feedCount
  568. }
  569. })
  570. } else {
  571. const pets = this.newOrderData.pets
  572. const currentPetIndex = pets.findIndex(pet => pet.petId === this.currentPetId && pet.serviceDate ===
  573. this.currentMonthDay.fullDate)
  574. if (currentPetIndex !== -1) {
  575. this.newOrderData.pets[currentPetIndex].feedCount = this.feedCount
  576. }
  577. }
  578. this.calculateTotalPrice()
  579. },
  580. customServiceCountChange(val) {
  581. console.log(val)
  582. this.customServices.forEach(item=>{
  583. if(item.name === val.name){
  584. item.quantity = val.value
  585. }
  586. })
  587. if(this.isAllSame){
  588. // 如果保持一致,则更新当前宠物的定制服务次数
  589. this.newOrderData.pets.forEach(pet=>{
  590. if(pet.petId === this.currentPetId){
  591. pet.customServices= JSON.parse(JSON.stringify(this.customServices))
  592. }
  593. })
  594. } else {
  595. const pets = this.newOrderData.pets
  596. const currentPetIndex = pets.findIndex(pet => pet.petId === this.currentPetId && pet.serviceDate ===
  597. this.currentMonthDay.fullDate)
  598. if (currentPetIndex !== -1) {
  599. this.newOrderData.pets[currentPetIndex].customServices = JSON.parse(JSON.stringify(this
  600. .customServices))
  601. }
  602. }
  603. this.calculateTotalPrice()
  604. },
  605. togglePriceDetails() {
  606. this.showPriceDetails = !this.showPriceDetails; // 切换价格明细的显示状态
  607. if (this.showPriceDetails) {
  608. this.priceDetailDate()
  609. }
  610. },
  611. calculateTotalPrice() {
  612. // 1. 订单维度:是否需要提前熟悉
  613. if(this.$globalData.newOrderData.needPreFamiliarize && this.$globalData.newOrderData.needPreFamiliarize.length>0){
  614. this.needPreFamiliarizeCost = 40
  615. }else{
  616. this.needPreFamiliarizeCost = 0
  617. }
  618. // 2. 日期维度
  619. // 2.1 基础服务费用
  620. const uniqueDates = new Set(this.newOrderData.pets.map(item => item.serviceDate)); // 去重日期
  621. this.baseServiceTotalCost = uniqueDates.size * this.basePrice; // 每个唯一日期75元
  622. // 2.2 额外宠物费用
  623. // petType为dog 且bodyType包含 '大型' 则为大型犬,40元/次
  624. // petType为dog 且bodyType包含 '中型' 则为中型犬,30元/次
  625. // petType为dog 且bodyType包含 '小型' 则为小型犬,15元/次
  626. // petType为cat 则为猫,10元/次
  627. this.newOrderData.pets.forEach(pet => {
  628. if (pet.petType === 'dog' && pet.bodyType.includes('大型')) {
  629. pet.additionalCost = 40
  630. } else if (pet.petType === 'dog' && pet.bodyType.includes('中型')) {
  631. pet.additionalCost = 30
  632. } else if (pet.petType === 'dog' && pet.bodyType.includes('小型')) {
  633. pet.additionalCost = 15
  634. } else if (pet.petType === 'cat') {
  635. pet.additionalCost = 10
  636. }
  637. })
  638. // const largeDogArray = this.newOrderData.pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('大型'));
  639. // this.additionalTotalCost = this.additionalTotalCost + (largeDogArray.length * 40)
  640. // // 非大型犬
  641. // const otherPets = this.newOrderData.pets.filter(pet => pet.petType !== 'dog' && !pet.bodyType.includes('大型'));
  642. // 宠物日期分组
  643. const dailyPets = [];
  644. // 按日期分组宠物
  645. this.newOrderData.pets.forEach(pet => {
  646. const serviceDate = pet.serviceDate;
  647. if (!dailyPets[serviceDate]) {
  648. dailyPets[serviceDate] = [];
  649. }
  650. dailyPets[serviceDate].push(pet);
  651. });
  652. const petTypeCounts = []
  653. let additionalTotalCost = 0
  654. // 计算每日额外宠物费用
  655. for (const date in dailyPets) {
  656. const pets = dailyPets[date];
  657. const largeDogCount = pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('大型')).length;
  658. let mediumDogCount = pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('中型')).length;
  659. let smallDogCount = pets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('小型')).length;
  660. let catCount = pets.filter(pet => pet.petType === 'cat').length;
  661. let additionalCost = 0
  662. // 总宠物费用
  663. let totalPetCost = pets.reduce((acc, pet) => {
  664. return acc + this.calculatePetCost(pet);
  665. }, 0);
  666. // 如果总宠物费用>30
  667. if (totalPetCost > 30) {
  668. // 如果猫数量>=3
  669. if (catCount >= 3) {
  670. additionalCost = totalPetCost - 30
  671. catCount = catCount - 3
  672. } else if (smallDogCount >= 2) {
  673. additionalCost = totalPetCost - 30
  674. smallDogCount = smallDogCount - 2
  675. } else if (mediumDogCount >= 1) {
  676. additionalCost = totalPetCost - 30
  677. mediumDogCount = mediumDogCount - 1
  678. } else {
  679. additionalCost = totalPetCost - 25
  680. catCount = catCount - 1
  681. smallDogCount = smallDogCount - 1
  682. }
  683. petTypeCounts.push({
  684. date,
  685. largeDogCount,
  686. mediumDogCount,
  687. smallDogCount,
  688. catCount
  689. })
  690. }
  691. // 如果有大型犬,额外费用为40元/只
  692. if (largeDogCount > 0) {
  693. additionalCost += (40 * largeDogCount)
  694. }
  695. // 如果有额外费用,添加到总额外费用
  696. if (additionalCost > 0) {
  697. additionalTotalCost += additionalCost;
  698. }
  699. }
  700. this.additionalTotalCost = additionalTotalCost
  701. this.petTypeCounts = petTypeCounts
  702. // 2.3 当日多次服务总价
  703. // 计算每日多次服务次数费用
  704. let multServicesTotalCost = 0
  705. let oneDayTwoTimesDates = []
  706. let oneDayThreeTimesDates = []
  707. for (const date in dailyPets) {
  708. const maxFeedCount = Math.max(...dailyPets[date].map(pet => pet.feedCount));
  709. if (maxFeedCount === 2) {
  710. multServicesTotalCost += 45; // 1天2次
  711. oneDayTwoTimesDates.push(date)
  712. } else if (maxFeedCount === 3) {
  713. multServicesTotalCost += 130; // 1天3次
  714. oneDayThreeTimesDates.push(date)
  715. }
  716. }
  717. this.oneDayTwoTimesDates = oneDayTwoTimesDates
  718. this.oneDayThreeTimesDates = oneDayThreeTimesDates
  719. this.multServicesTotalCost = multServicesTotalCost
  720. // 3. 定制服务
  721. //定制服务单项总次数统计
  722. const customServiceItemCount = JSON.parse(this.customServicesStr)
  723. let customServicesTotalCost = 0
  724. this.newOrderData.pets.forEach(pet => {
  725. const customServices = pet.customServices
  726. // 定制服务费用
  727. customServices.forEach(service=>{
  728. const itemIndex = customServiceItemCount.findIndex(item=>item.name === service.name)
  729. if(itemIndex !== -1){
  730. customServiceItemCount[itemIndex].quantity += service.quantity
  731. }
  732. customServicesTotalCost += service.price * service.quantity;
  733. })
  734. });
  735. this.customServiceItemCount = customServiceItemCount
  736. this.customServicesTotalCost = customServicesTotalCost
  737. this.totalPrice = this.needPreFamiliarizeCost
  738. + this.baseServiceTotalCost
  739. + this.additionalTotalCost
  740. + this.multServicesTotalCost
  741. + this.customServicesTotalCost; // 更新总价
  742. this.getCurrentDayPrice(this.currentMonthDay.fullDate)
  743. },
  744. calculatePetCost(pet) {
  745. // 宠物额外费用 不计算大型犬
  746. let petCost = 0;
  747. if (pet.petType === 'cat') {
  748. petCost += 10; // 猫额外费用
  749. } else if (pet.petType === 'dog' && pet.bodyType.includes('小型')) {
  750. petCost += 15; // 小型犬额外费用
  751. } else if (pet.petType === 'dog' && pet.bodyType.includes('中型')) {
  752. petCost += 30; // 中型犬额外费用
  753. }
  754. return petCost;
  755. },
  756. goNext() {
  757. this.calculateTotalPrice(); // 计算总价
  758. this.showPriceDetails = false;
  759. this.$globalData.newOrderData.currentPetsByDay = this.newOrderData.pets
  760. this.$globalData.newOrderData.totalPrice = this.totalPrice
  761. uni.navigateTo({
  762. url: '/pages/newOrder/confirmOrder'
  763. });
  764. },
  765. goBack() {
  766. this.showPriceDetails = false
  767. let len = getCurrentPages().length;
  768. this.loading = false
  769. if (len >= 2) {
  770. uni.navigateBack();
  771. } else {
  772. uni.redirectTo({
  773. url: '/pages/newOrder/serviceNew'
  774. });
  775. }
  776. },
  777. // 价格明细数据
  778. priceDetailDate() {
  779. const priceDetails = []
  780. if (this.newOrderData.needPreFamiliarize) {
  781. priceDetails.push({
  782. name: '提前熟悉',
  783. item: [{
  784. itemName: '提前熟悉',
  785. price: 40,
  786. quantity: this.newOrderData.needPreFamiliarize ? 1 : 0,
  787. unit: '次'
  788. }, ]
  789. })
  790. }
  791. const uniqueDateCount = new Set(this.newOrderData.pets.map(item => item.serviceDate)).size; // 去重日期
  792. if(uniqueDateCount>1){
  793. priceDetails.push({ name: this.baseProduct, item: [
  794. { itemName: this.baseProduct, price:this.basePrice, quantity: uniqueDateCount, unit: '天' },
  795. ]})
  796. }
  797. if (this.oneDayTwoTimesDates.length > 0 || this.oneDayThreeTimesDates.length > 0) {
  798. priceDetails.push({
  799. name: '上门次数',
  800. item: [{
  801. itemName: '1天2次',
  802. price: 45,
  803. quantity: this.oneDayTwoTimesDates.length,
  804. unit: '天'
  805. },
  806. {
  807. itemName: '1天3次',
  808. price: 130,
  809. quantity: this.oneDayThreeTimesDates.length,
  810. unit: '天'
  811. },
  812. ]
  813. })
  814. }
  815. // 过滤宠物类型数量>0的数组
  816. const additionalCostItem = []
  817. const petTypeArr = this.petTypeCounts.filter(item => item.largeDogCount > 0 || item.mediumDogCount > 0 ||
  818. item.smallDogCount > 0 || item.catCount > 0)
  819. // 假设largeDogCount=1 mediumDogCount=2 smallDogCount=3 catCount=4 则生成4条数据
  820. petTypeArr.forEach(item => {
  821. if (item.largeDogCount > 0) {
  822. additionalCostItem.push({
  823. itemName: '大型犬',
  824. price: 40,
  825. quantity: item.largeDogCount,
  826. unit: '只',
  827. date: item.date
  828. })
  829. }
  830. if (item.mediumDogCount > 0) {
  831. additionalCostItem.push({
  832. itemName: '中型犬',
  833. price: 30,
  834. quantity: item.mediumDogCount,
  835. unit: '只',
  836. date: item.date
  837. })
  838. }
  839. if (item.smallDogCount > 0) {
  840. additionalCostItem.push({
  841. itemName: '小型犬',
  842. price: 15,
  843. quantity: item.smallDogCount,
  844. unit: '只',
  845. date: item.date
  846. })
  847. }
  848. if (item.catCount > 0) {
  849. additionalCostItem.push({
  850. itemName: '猫猫',
  851. price: 10,
  852. quantity: item.catCount,
  853. unit: '只',
  854. date: item.date
  855. })
  856. }
  857. })
  858. // 按日期先后顺序排序
  859. additionalCostItem.sort((a, b) => new Date(a.date) - new Date(b.date))
  860. if (additionalCostItem.length > 0) {
  861. priceDetails.push({
  862. name: '额外宠物费用',
  863. item: additionalCostItem
  864. })
  865. }
  866. const customServiceItem = this.customServiceItemCount.filter(item=>item.quantity>0).map(service=>{
  867. return { itemName: service.name, price: service.price, quantity: service.quantity, unit: '次' }
  868. })
  869. if (customServiceItem.length > 0) {
  870. priceDetails.push({
  871. name: '定制服务',
  872. item: customServiceItem
  873. })
  874. }
  875. this.priceDetails = priceDetails
  876. this.calculateTotalPrice()
  877. },
  878. showName(item) {
  879. return item.item.some(item2 => item2.quantity > 0)
  880. },
  881. isAllSameChange(e) {
  882. if (e) {
  883. this.isAllSame = true
  884. this.setCurrentPetIsAllSame()
  885. // 当前宠物全日期保持一致
  886. this.newOrderData.pets.forEach(pet=>{
  887. if(pet.petId === this.currentPetId){
  888. pet.selectedTimeSlots = this.timeSlots.filter(slot => slot.selected).map(item => item.id)
  889. pet.feedCount = this.feedCount
  890. pet.customServices = this.customServices
  891. }
  892. })
  893. this.calculateTotalPrice()
  894. } else {
  895. this.isAllSame = false
  896. this.setCurrentPetIsAllSame()
  897. }
  898. },
  899. getProductList() {
  900. getProductList({
  901. "publishStatus": 1,
  902. "categoryId": 78,
  903. "needSku": true
  904. }).then(response => {
  905. if (response && response.content && response.content.length > 0) {
  906. this.customServices = response.content.map(item=>{
  907. const skus = item.skus
  908. if(skus && skus.length>0){
  909. let productSku = {
  910. "skuId": skus[0].id,
  911. "price":skus[0].price,
  912. "name":item.name,
  913. "quantity": 0,
  914. "isMainProduct":false
  915. }
  916. return productSku
  917. }
  918. })
  919. this.customServicesStr = JSON.stringify(this.customServices)
  920. // 初始化新订单数据
  921. this.initNewOrderData()
  922. }else {
  923. uni.showToast('获取主产品失败,请联系管理员')
  924. }
  925. console.log(response);
  926. })
  927. },
  928. login() {
  929. uni.login({
  930. provider: 'weixin',
  931. success: (loginRes) => {
  932. this.getOpenId(loginRes.code)
  933. },
  934. fail: function(error) {
  935. // 授权失败处理
  936. uni.showToast('授权失败,请授权后再试')
  937. }
  938. });
  939. },
  940. getOpenId(code) {
  941. getOpenId(code).then(res => {
  942. if (res.code == 200 && res.data) {
  943. let resData = JSON.parse(res.data)
  944. let token = resData.token;
  945. let openId = resData.openId;
  946. setOpenIdKey(openId)
  947. if(token){
  948. setToken(token)
  949. }
  950. }
  951. })
  952. },
  953. getCurrentDayPrice(currentDay){
  954. const currentDayPets = this.newOrderData.pets.filter(pet => pet.serviceDate === currentDay)
  955. // 基础服务
  956. const baseServiceCost = this.basePrice
  957. const largeDogCount = currentDayPets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('大型')).length;
  958. let mediumDogCount = currentDayPets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('中型')).length;
  959. let smallDogCount = currentDayPets.filter(pet => pet.petType === 'dog' && pet.bodyType.includes('小型')).length;
  960. let catCount = currentDayPets.filter(pet => pet.petType === 'cat').length;
  961. const additionalCostItem = []
  962. let additionalCost = 0
  963. // 单天总宠物费用
  964. let totalPetCost = currentDayPets.reduce((acc, pet) => {
  965. return acc + this.calculatePetCost(pet);
  966. }, 0);
  967. // 如果总宠物费用>30
  968. if(totalPetCost>30){
  969. // 如果猫数量>=3,则免3只猫
  970. if (catCount >= 3) {
  971. additionalCost = totalPetCost - 30
  972. catCount = catCount-3
  973. }else if (smallDogCount >= 2) { // 如果小型犬数量>=2,则免2只小型犬
  974. additionalCost = totalPetCost - 30
  975. smallDogCount = smallDogCount-2
  976. }else if(mediumDogCount >= 1) { // 如果中型犬数量>=1,则免1只中型犬
  977. additionalCost = totalPetCost - 30
  978. mediumDogCount = mediumDogCount-1
  979. }else{
  980. additionalCost = totalPetCost - 25
  981. catCount = catCount - 1
  982. smallDogCount = smallDogCount - 1
  983. }
  984. if(largeDogCount>0){
  985. additionalCostItem.push({ itemName: '大型犬', price: 40, quantity: largeDogCount, unit: '只'})
  986. }
  987. if(mediumDogCount>0){
  988. additionalCostItem.push({ itemName: '中型犬', price: 30, quantity: mediumDogCount, unit: '只'})
  989. }
  990. if(smallDogCount>0){
  991. additionalCostItem.push({ itemName: '小型犬', price: 15, quantity: smallDogCount, unit: '只'})
  992. }
  993. if(catCount>0){
  994. additionalCostItem.push({ itemName: '猫猫', price: 10, quantity: catCount, unit: '只'})
  995. }
  996. }
  997. // 如果有大型犬,额外费用为40元/只
  998. if (largeDogCount > 0) {
  999. additionalCost +=(40 * largeDogCount)
  1000. }
  1001. // 当日多次服务次数
  1002. let multServicesTotalCost = 0
  1003. const maxFeedCount = Math.max(...currentDayPets.map(pet => pet.feedCount));
  1004. if (maxFeedCount === 2) {
  1005. multServicesTotalCost += 45; // 1天2次
  1006. } else if (maxFeedCount === 3) {
  1007. multServicesTotalCost += 130; // 1天3次
  1008. }
  1009. // 所有宠物定制服务费用
  1010. const customServiceCost = currentDayPets.reduce((acc, pet) => acc + this.calculatePetCustomServiceCost(pet), 0)
  1011. const totalCost = baseServiceCost + additionalCost + multServicesTotalCost + customServiceCost
  1012. this.currentDayPrice = totalCost
  1013. },
  1014. calculatePetCustomServiceCost(pet) {
  1015. const customServiceCost = pet.customServices.reduce((acc, item) => acc + item.price * item.quantity, 0)
  1016. return customServiceCost
  1017. },
  1018. getCurrentPetName(){
  1019. const currentPet = this.currentPets.find(pet=>pet.id === this.currentPetId)
  1020. return currentPet.name
  1021. },
  1022. setCurrentPetIsAllSame(){
  1023. const currentPet = this.currentPets.find(pet=>pet.id === this.currentPetId)
  1024. currentPet.isAllSame=this.isAllSame
  1025. },
  1026. getCurrentPetIsAllSame(){
  1027. const currentPet = this.currentPets.find(pet=>pet.id === this.currentPetId)
  1028. this.isAllSame = currentPet.isAllSame
  1029. },
  1030. },
  1031. computed: {
  1032. sortedGroupedDates() {
  1033. return this.groupedDates.sort((a, b) => {
  1034. const dateA = new Date(a.monthLabel.replace('年', '-').replace('月', '-01'))
  1035. const dateB = new Date(b.monthLabel.replace('年', '-').replace('月', '-01'))
  1036. return dateA - dateB
  1037. })
  1038. }
  1039. }
  1040. }
  1041. </script>
  1042. <style scoped lang="less">
  1043. .container {
  1044. position: relative;
  1045. height: 100%;
  1046. padding-bottom: 160rpx;
  1047. .details-subscribe {
  1048. background-color: #FFFFFF;
  1049. padding: 10px;
  1050. width: 100%;
  1051. height: 160rpx;
  1052. position: fixed;
  1053. bottom: 0;
  1054. z-index: 100;
  1055. .details-btn {
  1056. width: 100%;
  1057. border-radius: 6px;
  1058. background: #FFB13F;
  1059. font-size: 16px;
  1060. color: #FFFFFF;
  1061. }
  1062. }
  1063. }
  1064. .service-new {
  1065. .service-new-flag {
  1066. width: 8rpx;
  1067. height: 32rpx;
  1068. background: #FFBF60;
  1069. border-radius: 30rpx 30rpx 30rpx 30rpx;
  1070. margin-right: 10rpx;
  1071. }
  1072. .split-line {
  1073. width: 100%;
  1074. height: 1rpx;
  1075. background: #EFEFEF;
  1076. }
  1077. .service-new-title {
  1078. display: flex;
  1079. font-weight: 500;
  1080. font-size: 28rpx;
  1081. color: #333333;
  1082. line-height: 33rpx;
  1083. margin: 42rpx 0 30rpx;
  1084. justify-content: space-between;
  1085. .service-new-title-left {
  1086. display: flex;
  1087. align-items: center;
  1088. }
  1089. }
  1090. .service-new-pet-content{
  1091. padding: 20rpx 0;
  1092. }
  1093. .service-new-pet-item {
  1094. height: 96rpx;
  1095. width: 184rpx;
  1096. border-radius: 8rpx;
  1097. padding: 0 20rpx;
  1098. margin-right: 40rpx;
  1099. display: flex;
  1100. align-items: center;
  1101. justify-content: center;
  1102. font-size: 28rpx;
  1103. flex-shrink: 0;
  1104. }
  1105. .scroll-content {
  1106. display: inline-flex;
  1107. }
  1108. .scroll-view {
  1109. width: 100%;
  1110. white-space: nowrap;
  1111. }
  1112. .pet-selected {
  1113. background: #FFBF60;
  1114. color: #FFFFFF;
  1115. }
  1116. .pet-unselect {
  1117. background: #F5F5F7;
  1118. color: #7D8196;
  1119. }
  1120. }
  1121. .calendar-wrapper {
  1122. display: flex;
  1123. gap: 20rpx;
  1124. padding: 20rpx;
  1125. }
  1126. .scroll-view {
  1127. width: 100%;
  1128. white-space: nowrap;
  1129. }
  1130. .calendar-day {
  1131. position: relative;
  1132. width: 80rpx;
  1133. height: 80rpx;
  1134. display: flex;
  1135. align-items: center;
  1136. justify-content: center;
  1137. cursor: pointer;
  1138. margin-right: 20rpx;
  1139. flex-shrink: 0;
  1140. }
  1141. .calendar-bg {
  1142. position: absolute;
  1143. width: 88rpx;
  1144. height: 78rpx;
  1145. z-index: 1;
  1146. }
  1147. .day-text {
  1148. position: relative;
  1149. z-index: 2;
  1150. top: 5rpx;
  1151. }
  1152. .day-highlighted {
  1153. font-size: 38rpx;
  1154. font-weight: bold;
  1155. color: #FFBF60;
  1156. }
  1157. .day-normal {
  1158. color: #3E3A39;
  1159. font-size: 32rpx;
  1160. }
  1161. .month-group {
  1162. margin-bottom: 30rpx;
  1163. .month-title {
  1164. font-size: 32rpx;
  1165. color: #666;
  1166. margin-bottom: 20rpx;
  1167. }
  1168. .dates-wrapper {
  1169. display: inline-flex;
  1170. }
  1171. }
  1172. .scroll-view-vertical {
  1173. height: 100%;
  1174. }
  1175. .scroll-view-horizontal {
  1176. width: 100%;
  1177. white-space: nowrap;
  1178. }
  1179. .time-slots {
  1180. display: flex;
  1181. justify-content: space-around;
  1182. }
  1183. .time-slot-item {
  1184. display: flex;
  1185. flex-direction: column;
  1186. align-items: center;
  1187. width: 200rpx;
  1188. cursor: pointer;
  1189. }
  1190. .time-slot-icon {
  1191. width: 160rpx;
  1192. height: 160rpx;
  1193. margin-bottom: 10rpx;
  1194. }
  1195. .time-slot-info {
  1196. display: flex;
  1197. flex-direction: column;
  1198. align-items: center;
  1199. }
  1200. .time-slot-name {
  1201. font-size: 28rpx;
  1202. color: #333;
  1203. margin-bottom: 8rpx;
  1204. }
  1205. .time-slot-time {
  1206. font-size: 24rpx;
  1207. color: #666;
  1208. }
  1209. .time-slot-time-tip {
  1210. background-color: #FFECCD;
  1211. color: #A94F20;
  1212. margin-left: 10rpx;
  1213. padding: 5rpx 10rpx;
  1214. font-size: 20rpx;
  1215. }
  1216. .service-item {
  1217. margin-bottom: 20rpx;
  1218. /* 每个服务项之间的间距 */
  1219. }
  1220. .service-item-header {
  1221. display: flex;
  1222. align-items: center;
  1223. margin-bottom: 10rpx;
  1224. /* 标题与服务列表之间的间距 */
  1225. }
  1226. .service-icon {
  1227. width: 40rpx;
  1228. /* 图标大小 */
  1229. height: 40rpx;
  1230. /* 图标大小 */
  1231. margin-right: 10rpx;
  1232. /* 图标与标题之间的间距 */
  1233. }
  1234. .service-title {
  1235. font-size: 28rpx; /* 服务标题字体大小 */
  1236. font-weight: bold; /* 服务标题加粗 */
  1237. }
  1238. .service-row {
  1239. display: flex;
  1240. align-items: center;
  1241. /* 垂直居中对齐 */
  1242. flex-wrap: wrap;
  1243. background-color: #F9F9F9;
  1244. }
  1245. .service-row-content {
  1246. display: flex;
  1247. justify-content: space-between;
  1248. /* 每行的上下内边距 */
  1249. width: 100%;
  1250. padding: 32rpx 0rpx;
  1251. margin: 0 20rpx;
  1252. }
  1253. .service-name {
  1254. width: 50%;
  1255. white-space: nowrap;
  1256. overflow: hidden;
  1257. text-overflow: ellipsis;
  1258. font-size: 28rpx;
  1259. color: #333;
  1260. /* 服务名称颜色 */
  1261. }
  1262. .service-price {
  1263. display: flex;
  1264. align-items: center;
  1265. /* 垂直居中对齐 */
  1266. }
  1267. .service-count {
  1268. display: flex;
  1269. align-items: center;
  1270. /* 垂直居中对齐 */
  1271. margin-left: 10rpx;
  1272. /* 价格数量之间的间距 */
  1273. }
  1274. .price-details {
  1275. position: fixed;
  1276. /* 固定位置 */
  1277. bottom: 160rpx;
  1278. /* 根据需要调整位置 */
  1279. left: 0;
  1280. right: 0;
  1281. background: #FFF;
  1282. /* 背景颜色 */
  1283. padding: 10px 10px 0 10px;
  1284. /* 内边距 */
  1285. border-radius: 8rpx 8rpx 0 0;
  1286. /* 圆角 */
  1287. z-index: 1000;
  1288. /* 确保在其他元素之上 */
  1289. min-height: 600rpx;
  1290. /* 固定高度 */
  1291. overflow: hidden;
  1292. /* 隐藏超出部分 */
  1293. }
  1294. .price-details-header {
  1295. display: flex;
  1296. justify-content: space-between;
  1297. align-items: center;
  1298. }
  1299. .price-details-body {
  1300. margin-top: 10px;
  1301. max-height: 300rpx;
  1302. /* 留出头部空间 */
  1303. overflow-y: auto;
  1304. /* 允许上下滚动 */
  1305. }
  1306. .price-details-overlay {
  1307. position: fixed;
  1308. /* 固定位置 */
  1309. top: 0;
  1310. left: 0;
  1311. right: 0;
  1312. bottom: 0;
  1313. background: rgba(0, 0, 0, 0.5);
  1314. /* 半透明背景 */
  1315. z-index: 999;
  1316. /* 确保在其他元素之上 */
  1317. display: flex;
  1318. justify-content: center;
  1319. align-items: center;
  1320. }
  1321. .price-details-item {
  1322. display: flex;
  1323. justify-content: space-between;
  1324. margin-bottom: 20rpx;
  1325. .price-details-item-price-total {
  1326. display: flex;
  1327. width: 70%;
  1328. justify-content: flex-end;
  1329. flex-wrap: wrap;
  1330. }
  1331. .price-details-item-price-total-item {
  1332. color: #999999;
  1333. text-align: right;
  1334. font-size: 28rpx;
  1335. margin-right: 20rpx;
  1336. }
  1337. }
  1338. </style>