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.

308 lines
8.3 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. // 服务时间段映射
  57. const timeSlotMap = {
  58. 'MORNING': '上午',
  59. 'AFTERNOON': '下午',
  60. 'EVENING': '晚上'
  61. }
  62. export default {
  63. components: {
  64. Kefu,
  65. ServiceAddress,
  66. ServicePets,
  67. ServiceItems,
  68. ServiceRemarks,
  69. OrderInfo,
  70. CancelOrderPopup
  71. },
  72. data() {
  73. return {
  74. orderId: null,
  75. orderDetail: {},
  76. };
  77. },
  78. onLoad(options) {
  79. if (options.id) {
  80. this.orderId = options.id;
  81. this.getOrderDetail();
  82. }
  83. },
  84. methods: {
  85. // 获取订单详情
  86. getOrderDetail() {
  87. const params = {
  88. openId: getOpenIdKey(),
  89. orderId: this.orderId
  90. };
  91. getOrderDetail(params).then(res => {
  92. if (res) {
  93. // 处理接口返回的数据
  94. const data = res;
  95. data.petVOList.forEach(pet => {
  96. pet.orderServiceText = getOrderServiceText(pet.id, data.orderServiceList) // 日期
  97. pet.productNameText = getProductNameText(pet.id, data.orderItemList, data.orderServiceList) // 服务
  98. })
  99. // 构建符合组件渲染需要的数据结构
  100. this.orderDetail = {
  101. // 地址信息
  102. address: {
  103. address: data.receiverProvince + data.receiverCity + data.receiverDistrict + data.receiverDetailAddress,
  104. contact: data.receiverName + ' ' + data.receiverPhone
  105. },
  106. // 宠物信息
  107. pets: data.petVOList ? data.petVOList.map(pet => {
  108. return {
  109. id: pet.id,
  110. name: pet.name,
  111. avatar: pet.photo,
  112. gender: pet.gender,
  113. serviceDays: pet.orderServiceText ? pet.orderServiceText.length : 0,
  114. serviceDates: pet.orderServiceText || [],
  115. services: pet.productNameText || []
  116. };
  117. }) : [],
  118. // 服务项目列表
  119. items: data.orderItemList.map((item, index) => {
  120. // 解析商品附加数据
  121. let spData = {};
  122. try {
  123. spData = JSON.parse(item.spData || '{}');
  124. } catch (e) {
  125. console.error('解析商品附加数据失败', e);
  126. }
  127. // 获取对应的宠物信息
  128. const pet = data.petVOList && data.petVOList[index] ? {
  129. name: data.petVOList[index].name,
  130. avatar: data.petVOList[index].photo
  131. } : null;
  132. // 生成模拟的定制服务数据
  133. const customServices = [
  134. // {
  135. // name: '基础护理',
  136. // price: 50,
  137. // quantity: 2
  138. // },
  139. // {
  140. // name: '美容服务',
  141. // price: 100,
  142. // quantity: 1
  143. // },
  144. // {
  145. // name: '特殊护理',
  146. // price: 80,
  147. // quantity: 1
  148. // }
  149. ];
  150. return {
  151. id: index + 1,
  152. name: item.productName,
  153. price: item.salePrice,
  154. quantity: item.quantity,
  155. pet: pet ? pet.name : null,
  156. petAvatar: pet ? pet.avatar : null,
  157. customServices: customServices
  158. };
  159. }),
  160. // 费用信息
  161. totalAmount: data.totalAmount,
  162. discount: data.totalAmount - data.payAmount,
  163. finalAmount: data.payAmount,
  164. // 订单状态
  165. status: data.status.toString(),
  166. // 备注信息
  167. remarks: {
  168. keyHandoverMethod: '存于快递柜',
  169. isAdvanceFamiliar: true,
  170. priceInfo: `价格${data.payAmount}`,
  171. serviceContent: '服务内容: 伴宠师将按照约定时间上门照顾宠物',
  172. serviceCondition: '服务保障: 购买此服务后,平台将安排伴宠师与您确认服务细节',
  173. notes: data.note || ''
  174. },
  175. // 其他信息
  176. orderInfo: {
  177. orderNumber: data.orderSn,
  178. orderTime: data.createTime,
  179. paymentTime: data.paymentTime
  180. }
  181. };
  182. // 如果有服务信息,处理服务日期和时间段
  183. if (data.orderServiceList && data.orderServiceList.length > 0) {
  184. // 处理服务日期和时间段
  185. const serviceDate = data.orderServiceList[0].serviceDate;
  186. const serviceTime = data.orderServiceList[0].expectServiceTime;
  187. // 更新服务项目描述
  188. if (this.orderDetail.items.length > 0) {
  189. this.orderDetail.items[0].serviceDate = serviceDate;
  190. this.orderDetail.items[0].serviceTime = timeSlotMap[serviceTime] || serviceTime;
  191. }
  192. }
  193. }
  194. }).catch(err => {
  195. console.error('获取订单详情失败', err);
  196. });
  197. },
  198. // 去付款
  199. goToPay() {
  200. uni.navigateTo({
  201. url: `/pages/details/order?id=${this.orderId}`
  202. });
  203. },
  204. // 去评价
  205. goToReview() {
  206. uni.navigateTo({
  207. url: `/pages_order/order/orderReview?id=${this.orderId}`
  208. });
  209. },
  210. // 处理取消订单
  211. handleCancelOrder() {
  212. // 待实现取消订单逻辑
  213. },
  214. // 修改订单
  215. modifyOrder() {
  216. // 跳转到服务选择页面,并传递订单ID参数
  217. uni.navigateTo({
  218. url: `/pages_order/order/orderModify?orderId=${this.orderId}`
  219. });
  220. }
  221. }
  222. }
  223. </script>
  224. <style lang="scss" scoped>
  225. .order-detail-page {
  226. background-color: #f5f5f5;
  227. min-height: 100vh;
  228. display: flex;
  229. flex-direction: column;
  230. }
  231. .order-detail-content {
  232. flex: 1;
  233. padding: 20rpx;
  234. }
  235. .order-detail-footer {
  236. display: flex;
  237. justify-content: flex-end;
  238. align-items: center;
  239. padding: 20rpx 30rpx;
  240. background-color: #FFFFFF;
  241. border-top: 1px solid #EEEEEE;
  242. .footer-btn {
  243. padding: 16rpx 30rpx;
  244. border-radius: 30rpx;
  245. font-size: 26rpx;
  246. margin-left: 20rpx;
  247. }
  248. .cancel-btn {
  249. background-color: #FFFFFF;
  250. color: #666;
  251. border: 1px solid #DDDDDD;
  252. }
  253. .pay-btn {
  254. background-color: #FFAA48;
  255. color: #FFFFFF;
  256. }
  257. .modify-btn {
  258. background-color: #FFAA48;
  259. color: #FFFFFF;
  260. }
  261. .review-btn {
  262. background-color: #FFAA48;
  263. color: #FFFFFF;
  264. }
  265. .contact-btn {
  266. background-color: #FFFFFF;
  267. color: #666;
  268. border: 1px solid #DDDDDD;
  269. }
  270. }
  271. </style>