猫妈狗爸伴宠师小程序前端代码
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.

276 lines
6.2 KiB

  1. <template>
  2. <up-popup :show="show" mode="bottom" @close="close" :round="10" :closeable="true">
  3. <view class="popup-container">
  4. <view class="popup-title">宠物服务时间列表</view>
  5. <view class="pet-list">
  6. <!-- 宠物列表循环 -->
  7. <view class="pet-item" v-for="(pet, petIndex) in petList" :key="pet.id">
  8. <view class="pet-info">
  9. <up-image class="pet-avatar" width="50px" height="50px" :src="pet.photo" shape="circle"></up-image>
  10. <view class="pet-details">
  11. <view class="pet-name">{{ pet.name }}</view>
  12. <view class="pet-breed">{{ pet.breed }} {{ pet.bodyType }}</view>
  13. </view>
  14. </view>
  15. <!-- 该宠物的服务时间列表 -->
  16. <view class="service-list">
  17. <view class="service-item" v-for="(service, index) in pet.services" :key="index">
  18. <view class="service-header">
  19. <view class="service-date">{{ service.serviceDate }}</view>
  20. <view class="service-time">{{ getServiceTimeText(service.expectServiceTime) }}</view>
  21. </view>
  22. <view class="service-products">
  23. <view class="product-item" v-for="(product, pIndex) in service.products" :key="pIndex">
  24. <view class="product-name">{{ product.productName }}</view>
  25. <!-- <view class="product-price">{{ product.salePrice }}</view> -->
  26. </view>
  27. </view>
  28. <view class="service-footer">
  29. <up-button
  30. type="primary"
  31. text="打卡"
  32. @click="handleClock(service)"
  33. shape="circle"
  34. size="mini"
  35. style="height: 60rpx;"
  36. color="#FFAA48"></up-button>
  37. </view>
  38. </view>
  39. </view>
  40. </view>
  41. </view>
  42. </view>
  43. </up-popup>
  44. </template>
  45. <script setup>
  46. import { ref, defineProps, defineEmits } from 'vue';
  47. const props = defineProps({
  48. show: {
  49. type: Boolean,
  50. default: false
  51. },
  52. orderData: {
  53. type: Object,
  54. default: () => ({})
  55. }
  56. });
  57. const emit = defineEmits(['close']);
  58. const petList = ref([]);
  59. // 关闭弹窗
  60. const close = () => {
  61. emit('close');
  62. };
  63. // 获取服务时间段文本
  64. const getServiceTimeText = (timeCode) => {
  65. const timeMap = {
  66. 'MORNING': '早上',
  67. 'AFTERNOON': '下午',
  68. 'EVENING': '晚上'
  69. };
  70. return timeMap[timeCode] || '未指定';
  71. };
  72. // 处理打卡事件
  73. const handleClock = (service) => {
  74. if (!props.orderData || !service) return;
  75. let url = `/otherPages/myOrdersManage/clock/index?id=${props.orderData.orderId}&itemID=${props.orderData.id}&serviceId=${service.id}`
  76. if(service){
  77. }
  78. uni.navigateTo({
  79. url,
  80. });
  81. };
  82. // 处理数据,将订单数据转换为按宠物分组的服务时间列表格式
  83. const processOrderData = (orderData) => {
  84. if (!orderData || !orderData.h5OrderVO) return [];
  85. const { orderServiceList, orderItemList, petVOList } = orderData.h5OrderVO;
  86. if (!orderServiceList || !orderItemList || !petVOList) return [];
  87. // 按宠物ID分组
  88. const petMap = {};
  89. // 先将宠物信息添加到映射中
  90. petVOList.forEach(pet => {
  91. petMap[pet.id] = {
  92. ...pet,
  93. services: []
  94. };
  95. });
  96. // 按服务日期和宠物ID组织数据
  97. const serviceMap = {};
  98. // 遍历服务列表,创建日期和宠物ID的映射
  99. orderServiceList.forEach(service => {
  100. const serviceId = service.id;
  101. const petId = service.petId;
  102. const serviceDate = service.serviceDate;
  103. const expectServiceTime = service.expectServiceTime;
  104. if (!serviceMap[serviceId]) {
  105. serviceMap[serviceId] = {
  106. id: serviceId,
  107. petId,
  108. serviceDate,
  109. expectServiceTime,
  110. products: []
  111. };
  112. }
  113. });
  114. // 遍历订单项,将产品添加到对应的服务日期中
  115. orderItemList.forEach(item => {
  116. const serviceId = item.orderServiceId;
  117. if (serviceMap[serviceId]) {
  118. serviceMap[serviceId].products.push({
  119. productName: item.productName,
  120. salePrice: item.salePrice,
  121. pic: item.pic,
  122. quantity: item.quantity,
  123. spData: item.spData ? JSON.parse(item.spData) : {}
  124. });
  125. }
  126. });
  127. // 将服务添加到对应的宠物中
  128. Object.values(serviceMap).forEach(service => {
  129. if (petMap[service.petId]) {
  130. petMap[service.petId].services.push(service);
  131. }
  132. });
  133. // 转换为数组格式并按日期排序每个宠物的服务
  134. const result = Object.values(petMap);
  135. result.forEach(pet => {
  136. pet.services.sort((a, b) => new Date(a.serviceDate) - new Date(b.serviceDate));
  137. });
  138. return result;
  139. };
  140. // 更新服务列表数据
  141. const updateServiceList = () => {
  142. if (props.orderData && props.orderData.h5OrderVO) {
  143. petList.value = processOrderData(props.orderData);
  144. }
  145. };
  146. // 暴露方法给父组件
  147. defineExpose({
  148. updateServiceList
  149. });
  150. </script>
  151. <style scoped lang="scss">
  152. .popup-container {
  153. padding: 30rpx;
  154. max-height: 70vh;
  155. overflow-y: auto;
  156. }
  157. .popup-title {
  158. font-size: 32rpx;
  159. font-weight: bold;
  160. text-align: center;
  161. margin-bottom: 30rpx;
  162. }
  163. .pet-list {
  164. .pet-item {
  165. margin-bottom: 40rpx;
  166. .pet-info {
  167. display: flex;
  168. align-items: center;
  169. margin-bottom: 20rpx;
  170. .pet-avatar {
  171. flex-shrink: 0;
  172. margin-right: 20rpx;
  173. }
  174. .pet-details {
  175. .pet-name {
  176. font-size: 28rpx;
  177. font-weight: bold;
  178. color: #333;
  179. }
  180. .pet-breed {
  181. font-size: 24rpx;
  182. color: #666;
  183. margin-top: 6rpx;
  184. }
  185. }
  186. }
  187. }
  188. }
  189. .service-list {
  190. .service-item {
  191. margin-bottom: 20rpx;
  192. background-color: #f8f8f8;
  193. border-radius: 12rpx;
  194. padding: 20rpx;
  195. .service-header {
  196. display: flex;
  197. justify-content: space-between;
  198. align-items: center;
  199. margin-bottom: 20rpx;
  200. padding-bottom: 10rpx;
  201. border-bottom: 1px solid #eee;
  202. .service-date {
  203. font-size: 28rpx;
  204. font-weight: bold;
  205. color: #333;
  206. }
  207. .service-time {
  208. font-size: 24rpx;
  209. color: #666;
  210. background-color: #f0f0f0;
  211. padding: 4rpx 12rpx;
  212. border-radius: 20rpx;
  213. }
  214. }
  215. .service-products {
  216. margin-bottom: 20rpx;
  217. .product-item {
  218. display: flex;
  219. justify-content: space-between;
  220. padding: 10rpx 0;
  221. .product-name {
  222. font-size: 26rpx;
  223. color: #666;
  224. }
  225. .product-price {
  226. font-size: 26rpx;
  227. color: #FF530A;
  228. }
  229. }
  230. }
  231. .service-footer {
  232. display: flex;
  233. justify-content: flex-end;
  234. }
  235. }
  236. }
  237. </style>