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.

265 lines
7.1 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 review-btn" v-if="orderDetail.status === 4" @click="goToReview">
  26. <text>评价订单</text>
  27. </view>
  28. <view class="footer-btn contact-btn">
  29. <text>联系客服</text>
  30. </view>
  31. </view>
  32. <!-- 取消订单弹窗 -->
  33. <cancel-order-popup
  34. ref="cancelOrderPopup"
  35. @cancel="handleCancelOrder"
  36. ></cancel-order-popup>
  37. <!-- 客服组件 -->
  38. <Kefu></Kefu>
  39. </view>
  40. </template>
  41. <script>
  42. import Kefu from '@/pages/common/kefu.vue'
  43. import ServiceAddress from '@/pages_order/components/order/ServiceAddress.vue'
  44. import ServicePets from '@/pages_order/components/order/ServicePets.vue'
  45. import ServiceItems from '@/pages_order/components/order/ServiceItems.vue'
  46. import ServiceRemarks from '@/pages_order/components/order/ServiceRemarks.vue'
  47. import OrderInfo from '@/pages_order/components/order/OrderInfo.vue'
  48. import CancelOrderPopup from '@/pages_order/components/order/CancelOrderPopup.vue'
  49. import { getOrderList } from "@/api/system/user.js"
  50. import { getOpenIdKey } from '@/utils/auth'
  51. import { getOrderDetail } from '@/api/order/order.js'
  52. import { getOrderServiceText, getProductNameText } from '@/utils/serviceTime.js'
  53. // 服务时间段映射
  54. const timeSlotMap = {
  55. 'MORNING': '上午',
  56. 'AFTERNOON': '下午',
  57. 'EVENING': '晚上'
  58. }
  59. export default {
  60. components: {
  61. Kefu,
  62. ServiceAddress,
  63. ServicePets,
  64. ServiceItems,
  65. ServiceRemarks,
  66. OrderInfo,
  67. CancelOrderPopup
  68. },
  69. data() {
  70. return {
  71. orderId: null,
  72. orderDetail: {},
  73. };
  74. },
  75. onLoad(options) {
  76. if (options.id) {
  77. this.orderId = options.id;
  78. this.getOrderDetail();
  79. }
  80. },
  81. methods: {
  82. // 获取订单详情
  83. getOrderDetail() {
  84. const params = {
  85. openId: getOpenIdKey(),
  86. orderId: this.orderId
  87. };
  88. getOrderDetail(params).then(res => {
  89. if (res) {
  90. // 处理接口返回的数据
  91. const data = res;
  92. data.petVOList.forEach(pet => {
  93. pet.orderServiceText = getOrderServiceText(pet.id, data.orderServiceList) // 日期
  94. pet.productNameText = getProductNameText(pet.id, data.orderItemList, data.orderServiceList) // 服务
  95. })
  96. // 构建符合组件渲染需要的数据结构
  97. this.orderDetail = {
  98. // 地址信息
  99. address: {
  100. address: data.receiverProvince + data.receiverCity + data.receiverDistrict + data.receiverDetailAddress,
  101. contact: data.receiverName + ' ' + data.receiverPhone
  102. },
  103. // 宠物信息
  104. pets: data.petVOList ? data.petVOList.map(pet => {
  105. return {
  106. id: pet.id,
  107. name: pet.name,
  108. avatar: pet.photo,
  109. gender: pet.gender,
  110. serviceDays: pet.orderServiceText ? pet.orderServiceText.length : 0,
  111. serviceDates: pet.orderServiceText || [],
  112. services: pet.productNameText || []
  113. };
  114. }) : [],
  115. // 服务项目列表
  116. items: data.orderItemList.map((item, index) => {
  117. // 解析商品附加数据
  118. let spData = {};
  119. try {
  120. spData = JSON.parse(item.spData || '{}');
  121. } catch (e) {
  122. console.error('解析商品附加数据失败', e);
  123. }
  124. return {
  125. id: index + 1,
  126. name: item.productName,
  127. price: item.salePrice,
  128. quantity: item.quantity,
  129. customServices: []
  130. };
  131. }),
  132. // 费用信息
  133. totalAmount: data.totalAmount,
  134. discount: data.totalAmount - data.payAmount,
  135. finalAmount: data.payAmount,
  136. // 订单状态
  137. status: data.status.toString(),
  138. // 备注信息
  139. remarks: {
  140. keyHandoverMethod: '存于快递柜',
  141. isAdvanceFamiliar: true,
  142. priceInfo: `价格${data.payAmount}`,
  143. serviceContent: '服务内容: 伴宠师将按照约定时间上门照顾宠物',
  144. serviceCondition: '服务保障: 购买此服务后,平台将安排伴宠师与您确认服务细节',
  145. notes: data.note || ''
  146. },
  147. // 其他信息
  148. orderInfo: {
  149. orderNumber: data.orderSn,
  150. orderTime: data.createTime,
  151. paymentTime: data.paymentTime
  152. }
  153. };
  154. // 如果有服务信息,处理服务日期和时间段
  155. if (data.orderServiceList && data.orderServiceList.length > 0) {
  156. // 处理服务日期和时间段
  157. const serviceDate = data.orderServiceList[0].serviceDate;
  158. const serviceTime = data.orderServiceList[0].expectServiceTime;
  159. // 更新服务项目描述
  160. if (this.orderDetail.items.length > 0) {
  161. this.orderDetail.items[0].serviceDate = serviceDate;
  162. this.orderDetail.items[0].serviceTime = timeSlotMap[serviceTime] || serviceTime;
  163. }
  164. }
  165. }
  166. }).catch(err => {
  167. console.error('获取订单详情失败', err);
  168. });
  169. },
  170. // 去付款
  171. goToPay() {
  172. uni.navigateTo({
  173. url: `/pages/details/order?id=${this.orderId}`
  174. });
  175. },
  176. // 去评价
  177. goToReview() {
  178. uni.navigateTo({
  179. url: `/pages_order/order/orderReview?id=${this.orderId}`
  180. });
  181. },
  182. // 处理取消订单
  183. handleCancelOrder() {
  184. // 待实现取消订单逻辑
  185. }
  186. }
  187. }
  188. </script>
  189. <style lang="scss" scoped>
  190. .order-detail-page {
  191. background-color: #f5f5f5;
  192. min-height: 100vh;
  193. display: flex;
  194. flex-direction: column;
  195. }
  196. .order-detail-content {
  197. flex: 1;
  198. padding: 20rpx;
  199. }
  200. .order-detail-footer {
  201. display: flex;
  202. justify-content: flex-end;
  203. align-items: center;
  204. padding: 20rpx 30rpx;
  205. background-color: #FFFFFF;
  206. border-top: 1px solid #EEEEEE;
  207. .footer-btn {
  208. padding: 16rpx 30rpx;
  209. border-radius: 30rpx;
  210. font-size: 26rpx;
  211. margin-left: 20rpx;
  212. }
  213. .cancel-btn {
  214. background-color: #FFFFFF;
  215. color: #666;
  216. border: 1px solid #DDDDDD;
  217. }
  218. .pay-btn {
  219. background-color: #FFAA48;
  220. color: #FFFFFF;
  221. }
  222. .review-btn {
  223. background-color: #FFAA48;
  224. color: #FFFFFF;
  225. }
  226. .contact-btn {
  227. background-color: #FFFFFF;
  228. color: #666;
  229. border: 1px solid #DDDDDD;
  230. }
  231. }
  232. </style>