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.

330 lines
9.7 KiB

  1. <template>
  2. <view class="order-detail-page">
  3. <!-- 订单内容区域 -->
  4. <view class="order-detail-content">
  5. <!-- 服务地址组件 -->
  6. <service-address :address="orderDetail.address"></service-address>
  7. <!-- 服务宠物组件 -->
  8. <service-pets :pets="orderDetail.pets"></service-pets>
  9. <!-- 服务项目及费用组件 -->
  10. <service-items :items="orderDetail.items" :totalAmount="orderDetail.totalAmount"
  11. :discount="orderDetail.discount" :finalAmount="orderDetail.finalAmount"></service-items>
  12. <!-- 服务备注组件 -->
  13. <service-remarks :remarks="orderDetail.remarks"></service-remarks>
  14. <!-- 其他信息组件 -->
  15. <order-info :orderInfo="orderDetail.orderInfo"></order-info>
  16. </view>
  17. <!-- 底部按钮区域 -->
  18. <view class="order-detail-footer">
  19. <view class="footer-btn cancel-btn" v-if="orderDetail.status === '1'" @click="$refs.cancelOrderPopup.open()">
  20. <text>取消订单</text>
  21. </view>
  22. <view class="footer-btn pay-btn" v-if="orderDetail.status === '1'" @click="goToPay">
  23. <text>去付款</text>
  24. </view>
  25. <!-- <view class="footer-btn modify-btn" v-if="orderDetail.status != 0 && orderDetail.status != 3" @click="modifyOrder">
  26. <text>修改订单</text>
  27. </view> -->
  28. <view class="footer-btn review-btn" v-if="orderDetail.status === 4" @click="goToReview">
  29. <text>评价订单</text>
  30. </view>
  31. <view class="footer-btn contact-btn">
  32. <text>联系客服</text>
  33. </view>
  34. </view>
  35. <!-- 取消订单弹窗 -->
  36. <cancel-order-popup
  37. ref="cancelOrderPopup"
  38. @cancel="handleCancelOrder"
  39. ></cancel-order-popup>
  40. <!-- 客服组件 -->
  41. <Kefu></Kefu>
  42. </view>
  43. </template>
  44. <script>
  45. import Kefu from '@/pages/common/kefu.vue'
  46. import ServiceAddress from '@/pages_order/components/order/ServiceAddress.vue'
  47. import ServicePets from '@/pages_order/components/order/ServicePets.vue'
  48. import ServiceItems from '@/pages_order/components/order/ServiceItems.vue'
  49. import ServiceRemarks from '@/pages_order/components/order/ServiceRemarks.vue'
  50. import OrderInfo from '@/pages_order/components/order/OrderInfo.vue'
  51. import CancelOrderPopup from '@/pages_order/components/order/CancelOrderPopup.vue'
  52. import { getOrderList } from "@/api/system/user.js"
  53. import { getOpenIdKey } from '@/utils/auth'
  54. import { getOrderDetail } from '@/api/order/order.js'
  55. import { getOrderServiceText, getProductNameText } from '@/utils/serviceTime.js'
  56. import dayjs from '@/utils/lib/dayjs.min.js'
  57. // 服务时间段映射
  58. const timeSlotMap = {
  59. 'MORNING': '上午',
  60. 'AFTERNOON': '下午',
  61. 'EVENING': '晚上'
  62. }
  63. export default {
  64. components: {
  65. Kefu,
  66. ServiceAddress,
  67. ServicePets,
  68. ServiceItems,
  69. ServiceRemarks,
  70. OrderInfo,
  71. CancelOrderPopup
  72. },
  73. data() {
  74. return {
  75. orderId: null,
  76. orderDetail: {},//格式化后的数据
  77. detail : {},//未格式化的数据
  78. };
  79. },
  80. onLoad(options) {
  81. if (options.id) {
  82. this.orderId = options.id;
  83. this.getOrderDetail();
  84. }
  85. },
  86. methods: {
  87. // 获取订单详情
  88. getOrderDetail() {
  89. const params = {
  90. openId: getOpenIdKey(),
  91. orderId: this.orderId
  92. };
  93. getOrderDetail(params).then(res => {
  94. if (res) {
  95. // 处理接口返回的数据
  96. const data = res;
  97. data.petVOList.forEach(pet => {
  98. pet.orderServiceText = getOrderServiceText(pet.id, data.orderServiceList) // 日期
  99. pet.productNameText = getProductNameText(pet.id, data.orderItemList, data.orderServiceList) // 服务
  100. })
  101. //=====================服务项目以及费用的计算开始=====================
  102. let items = []
  103. //1、找出有哪些日期
  104. let days = [...new Set(data.orderServiceList.map(item => item.serviceDate))]
  105. days.forEach(day => {
  106. let price = 0;
  107. let itemsText = []
  108. //2、找出每个日期对应的服务对象
  109. let dayItems = data.orderServiceList.filter(item => item.serviceDate === day)
  110. //3、找出每个服务对象对应的宠物
  111. let pets = data.petVOList.filter(item => dayItems.some(dayItem => dayItem.petId === item.id))
  112. //深度拷贝pets
  113. pets = JSON.parse(JSON.stringify(pets))
  114. //4、将每个服务对象添加进对应的宠物
  115. pets.forEach(pet => {
  116. pet.serviceList = dayItems.filter(item => item.petId === pet.id)
  117. let itemList = []
  118. //5、将每个服务对象中添加对应的项目
  119. pet.serviceList.forEach(item => {
  120. itemList.push(...(data.orderItemList.filter(n => n.orderServiceId == item.id)))
  121. })
  122. itemList.forEach(p => {
  123. price += p.salePrice
  124. itemsText = [...new Set([...itemsText, p.productName])]
  125. })
  126. pet.itemList = itemList
  127. })
  128. //6、将每个宠物添加进items
  129. items.push({
  130. price,
  131. pets,
  132. day,
  133. itemsText,
  134. })
  135. })
  136. //根据日期排序
  137. items = items.sort((a, b) => dayjs(a.day).valueOf() - dayjs(b.day).valueOf())
  138. console.log(items);
  139. //=====================服务项目以及费用的计算结束=====================
  140. // 构建符合组件渲染需要的数据结构
  141. this.orderDetail = {
  142. // 地址信息
  143. address: {
  144. address: data.receiverProvince + data.receiverCity + data.receiverDistrict + data.receiverDetailAddress,
  145. contact: data.receiverName + ' ' + data.receiverPhone
  146. },
  147. // 宠物信息
  148. pets: data.petVOList ? data.petVOList.map(pet => {
  149. return {
  150. id: pet.id,
  151. name: pet.name,
  152. avatar: pet.photo,
  153. gender: pet.gender,
  154. serviceDays: pet.orderServiceText ? pet.orderServiceText.length : 0,
  155. serviceDates: pet.orderServiceText || [],
  156. services: pet.productNameText || []
  157. };
  158. }) : [],
  159. // 服务项目列表
  160. items,
  161. // 费用信息
  162. totalAmount: data.totalAmount,
  163. discount: data.totalAmount - data.payAmount,
  164. finalAmount: data.payAmount,
  165. // 订单状态
  166. status: data.status.toString(),
  167. // 备注信息
  168. remarks: {
  169. keyHandoverMethod: '存于快递柜',
  170. isAdvanceFamiliar: true,
  171. priceInfo: `价格${data.payAmount}`,
  172. serviceContent: '服务内容: 伴宠师将按照约定时间上门照顾宠物',
  173. serviceCondition: '服务保障: 购买此服务后,平台将安排伴宠师与您确认服务细节',
  174. notes: data.note || ''
  175. },
  176. // 其他信息
  177. orderInfo: {
  178. orderNumber: data.orderSn,
  179. orderTime: data.createTime,
  180. paymentTime: data.paymentTime
  181. }
  182. };
  183. // 如果有服务信息,处理服务日期和时间段
  184. if (data.orderServiceList && data.orderServiceList.length > 0) {
  185. // 处理服务日期和时间段
  186. const serviceDate = data.orderServiceList[0].serviceDate;
  187. const serviceTime = data.orderServiceList[0].expectServiceTime;
  188. // 更新服务项目描述
  189. if (this.orderDetail.items.length > 0) {
  190. this.orderDetail.items[0].serviceDate = serviceDate;
  191. this.orderDetail.items[0].serviceTime = timeSlotMap[serviceTime] || serviceTime;
  192. }
  193. }
  194. }
  195. }).catch(err => {
  196. console.error('获取订单详情失败', err);
  197. });
  198. },
  199. // 去付款
  200. goToPay() {
  201. uni.navigateTo({
  202. url: `/pages/details/order?id=${this.orderId}`
  203. });
  204. },
  205. // 去评价
  206. goToReview() {
  207. uni.navigateTo({
  208. url: `/pages_order/order/orderReview?id=${this.orderId}`
  209. });
  210. },
  211. // 处理取消订单
  212. handleCancelOrder() {
  213. // 待实现取消订单逻辑
  214. },
  215. // 修改订单
  216. modifyOrder() {
  217. // 跳转到服务选择页面,并传递订单ID参数
  218. uni.navigateTo({
  219. url: `/pages_order/order/orderModify?orderId=${this.orderId}`
  220. });
  221. }
  222. }
  223. }
  224. </script>
  225. <style lang="scss" scoped>
  226. .order-detail-page {
  227. background-color: #f5f5f5;
  228. min-height: 100vh;
  229. display: flex;
  230. flex-direction: column;
  231. }
  232. .order-detail-content {
  233. flex: 1;
  234. padding: 20rpx;
  235. }
  236. .order-detail-footer {
  237. display: flex;
  238. justify-content: flex-end;
  239. align-items: center;
  240. padding: 20rpx 30rpx;
  241. background-color: #FFFFFF;
  242. border-top: 1px solid #EEEEEE;
  243. .footer-btn {
  244. padding: 16rpx 30rpx;
  245. border-radius: 30rpx;
  246. font-size: 26rpx;
  247. margin-left: 20rpx;
  248. }
  249. .cancel-btn {
  250. background-color: #FFFFFF;
  251. color: #666;
  252. border: 1px solid #DDDDDD;
  253. }
  254. .pay-btn {
  255. background-color: #FFAA48;
  256. color: #FFFFFF;
  257. }
  258. .modify-btn {
  259. background-color: #FFAA48;
  260. color: #FFFFFF;
  261. }
  262. .review-btn {
  263. background-color: #FFAA48;
  264. color: #FFFFFF;
  265. }
  266. .contact-btn {
  267. background-color: #FFFFFF;
  268. color: #666;
  269. border: 1px solid #DDDDDD;
  270. }
  271. }
  272. </style>