6 changed files with 3422 additions and 9 deletions
			
			
		| @ -0,0 +1,878 @@ | |||||
|  | <template> | ||||
|  |   <view class="aftersale-container"> | ||||
|  |     <!-- 订单信息 --> | ||||
|  |     <view class="order-section"> | ||||
|  |       <view class="section-title">订单信息</view> | ||||
|  |       <view class="order-card"> | ||||
|  |         <view class="order-header"> | ||||
|  |           <text class="order-no">订单号:{{ orderInfo.orderNo }}</text> | ||||
|  |           <text class="order-status">{{ getOrderStatusText(orderInfo.status) }}</text> | ||||
|  |         </view> | ||||
|  |         <view class="supplier-info"> | ||||
|  |           <text class="supplier-name">供应商:{{ orderInfo.supplierName }}</text> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 商品信息 --> | ||||
|  |     <view class="goods-section"> | ||||
|  |       <view class="section-title">选择售后商品</view> | ||||
|  |       <view class="goods-list"> | ||||
|  |         <view | ||||
|  |           class="goods-item" | ||||
|  |           v-for="goods in orderInfo.orderGoods" | ||||
|  |           :key="goods.id" | ||||
|  |           :class="{ 'selected': selectedGoods.includes(goods.id) }" | ||||
|  |           @click="toggleGoodsSelect(goods)" | ||||
|  |         > | ||||
|  |           <view class="goods-checkbox"> | ||||
|  |             <view class="checkbox" :class="{ 'checked': selectedGoods.includes(goods.id) }"> | ||||
|  |               <text class="checkbox-icon" v-if="selectedGoods.includes(goods.id)">✓</text> | ||||
|  |             </view> | ||||
|  |           </view> | ||||
|  |           <view class="goods-image"> | ||||
|  |             <image :src="showImgJdsz(goods.goodsImg)" mode="aspectFill" /> | ||||
|  |           </view> | ||||
|  |           <view class="goods-info"> | ||||
|  |             <view class="goods-name">{{ goods.goodsTitle }}</view> | ||||
|  |             <view class="goods-sku" v-if="goods.skuName">{{ goods.skuName }}</view> | ||||
|  |             <view class="goods-meta"> | ||||
|  |               <text class="goods-price">¥{{ goods.price }}</text> | ||||
|  |               <text class="goods-quantity">×{{ goods.num }}</text> | ||||
|  |             </view> | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 售后类型 --> | ||||
|  |     <view class="type-section"> | ||||
|  |       <view class="section-title">售后类型</view> | ||||
|  |       <view class="type-list"> | ||||
|  |         <view | ||||
|  |           class="type-item" | ||||
|  |           v-for="type in aftersaleTypes" | ||||
|  |           :key="type.value" | ||||
|  |           :class="{ 'selected': aftersaleForm.type === type.value }" | ||||
|  |           @click="selectType(type.value)" | ||||
|  |         > | ||||
|  |           <view class="type-radio"> | ||||
|  |             <view class="radio" :class="{ 'checked': aftersaleForm.type === type.value }"> | ||||
|  |               <view class="radio-dot" v-if="aftersaleForm.type === type.value"></view> | ||||
|  |             </view> | ||||
|  |           </view> | ||||
|  |           <view class="type-info"> | ||||
|  |             <text class="type-name">{{ type.name }}</text> | ||||
|  |             <text class="type-desc">{{ type.desc }}</text> | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 售后原因 --> | ||||
|  |     <view class="reason-section"> | ||||
|  |       <view class="section-title">售后原因</view> | ||||
|  |       <view class="reason-list"> | ||||
|  |         <view | ||||
|  |           class="reason-item" | ||||
|  |           v-for="reason in reasonList" | ||||
|  |           :key="reason.value" | ||||
|  |           :class="{ 'selected': aftersaleForm.reason === reason.value }" | ||||
|  |           @click="selectReason(reason.value)" | ||||
|  |         > | ||||
|  |           <text class="reason-text">{{ reason.name }}</text> | ||||
|  |           <view class="reason-check" v-if="aftersaleForm.reason === reason.value">✓</view> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 问题描述 --> | ||||
|  |     <view class="description-section"> | ||||
|  |       <view class="section-title">问题描述</view> | ||||
|  |       <textarea | ||||
|  |         class="description-input" | ||||
|  |         v-model="aftersaleForm.description" | ||||
|  |         placeholder="请详细描述遇到的问题,以便我们更好地为您处理" | ||||
|  |         maxlength="500" | ||||
|  |       /> | ||||
|  |       <view class="char-count">{{ aftersaleForm.description.length }}/500</view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 上传凭证 --> | ||||
|  |     <view class="upload-section"> | ||||
|  |       <view class="section-title">上传凭证(选填)</view> | ||||
|  |       <view class="upload-area"> | ||||
|  |         <view class="image-list"> | ||||
|  |           <view | ||||
|  |             class="image-item" | ||||
|  |             v-for="(image, index) in aftersaleForm.images" | ||||
|  |             :key="index" | ||||
|  |           > | ||||
|  |             <image class="uploaded-image" :src="image" mode="aspectFill" /> | ||||
|  |             <view class="delete-btn" @click="deleteImage(index)">×</view> | ||||
|  |           </view> | ||||
|  |           <view class="upload-btn" @click="chooseImage" v-if="aftersaleForm.images.length < 6"> | ||||
|  |             <text class="upload-icon">+</text> | ||||
|  |             <text class="upload-text">添加图片</text> | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  |         <view class="upload-tip">最多可上传6张图片,支持jpg、png格式</view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 联系方式 --> | ||||
|  |     <view class="contact-section"> | ||||
|  |       <view class="section-title">联系方式</view> | ||||
|  |       <view class="contact-form"> | ||||
|  |         <view class="form-item"> | ||||
|  |           <text class="form-label">联系人</text> | ||||
|  |           <input | ||||
|  |             class="form-input" | ||||
|  |             v-model="aftersaleForm.contactName" | ||||
|  |             placeholder="请输入联系人姓名" | ||||
|  |           /> | ||||
|  |         </view> | ||||
|  |         <view class="form-item"> | ||||
|  |           <text class="form-label">联系电话</text> | ||||
|  |           <input | ||||
|  |             class="form-input" | ||||
|  |             v-model="aftersaleForm.contactPhone" | ||||
|  |             placeholder="请输入联系电话" | ||||
|  |             type="number" | ||||
|  |           /> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 底部提交按钮 --> | ||||
|  |     <view class="submit-section"> | ||||
|  |       <button class="submit-btn" @click="submitAftersale" :disabled="!canSubmit"> | ||||
|  |         提交售后申请 | ||||
|  |       </button> | ||||
|  |     </view> | ||||
|  |   </view> | ||||
|  | </template> | ||||
|  | 
 | ||||
|  | <script> | ||||
|  | export default { | ||||
|  |   data() { | ||||
|  |     return { | ||||
|  |       orderId: '', | ||||
|  |       orderInfo: { | ||||
|  |         orderNo: '', | ||||
|  |         status: 0, | ||||
|  |         supplierName: '', | ||||
|  |         orderGoods: [] | ||||
|  |       }, | ||||
|  |       selectedGoods: [], // 选中的商品ID列表 | ||||
|  |       aftersaleForm: { | ||||
|  |         type: 1, // 售后类型:1-退货退款,2-换货,3-仅退款 | ||||
|  |         reason: '', // 售后原因 | ||||
|  |         description: '', // 问题描述 | ||||
|  |         images: [], // 上传的图片 | ||||
|  |         contactName: '', // 联系人 | ||||
|  |         contactPhone: '' // 联系电话 | ||||
|  |       }, | ||||
|  |       aftersaleTypes: [ | ||||
|  |         { | ||||
|  |           value: 1, | ||||
|  |           name: '退货退款', | ||||
|  |           desc: '商品有质量问题,需要退货并退款' | ||||
|  |         }, | ||||
|  |         { | ||||
|  |           value: 2, | ||||
|  |           name: '换货', | ||||
|  |           desc: '商品有问题,需要更换同款商品' | ||||
|  |         }, | ||||
|  |         { | ||||
|  |           value: 3, | ||||
|  |           name: '仅退款', | ||||
|  |           desc: '未收到商品或商品严重损坏' | ||||
|  |         } | ||||
|  |       ], | ||||
|  |       reasonList: [ | ||||
|  |         { value: 'quality', name: '商品质量问题' }, | ||||
|  |         { value: 'damage', name: '商品破损' }, | ||||
|  |         { value: 'wrong', name: '发错商品' }, | ||||
|  |         { value: 'description', name: '与描述不符' }, | ||||
|  |         { value: 'logistics', name: '物流问题' }, | ||||
|  |         { value: 'other', name: '其他原因' } | ||||
|  |       ] | ||||
|  |     }; | ||||
|  |   }, | ||||
|  |   computed: { | ||||
|  |     // 是否可以提交 | ||||
|  |     canSubmit() { | ||||
|  |       return ( | ||||
|  |         this.selectedGoods.length > 0 && | ||||
|  |         this.aftersaleForm.type && | ||||
|  |         this.aftersaleForm.reason && | ||||
|  |         this.aftersaleForm.description.trim() && | ||||
|  |         this.aftersaleForm.contactName.trim() && | ||||
|  |         this.aftersaleForm.contactPhone.trim() | ||||
|  |       ); | ||||
|  |     } | ||||
|  |   }, | ||||
|  |   onLoad(options) { | ||||
|  |     if (options.orderId) { | ||||
|  |       this.orderId = options.orderId; | ||||
|  |       this.loadOrderInfo(); | ||||
|  |       this.loadUserInfo(); | ||||
|  |     } | ||||
|  |   }, | ||||
|  |   methods: { | ||||
|  |     showImgJdsz(img) { | ||||
|  |       if (!img) return '/static/images/default-goods.png'; | ||||
|  |       if (img.indexOf("https://") != -1 || img.indexOf("http://") != -1) { | ||||
|  |         return img; | ||||
|  |       } else { | ||||
|  |         return this.JDSU_IMG_URL + img; | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 加载订单信息 | ||||
|  |     async loadOrderInfo() { | ||||
|  |       try { | ||||
|  |         this.Post( | ||||
|  |           { orderId: this.orderId }, | ||||
|  |           '/framework/haveFeeling/order/detail', | ||||
|  |           'DES' | ||||
|  |         ).then((res) => { | ||||
|  |           if (res.code == 200) { | ||||
|  |             this.orderInfo = res.data; | ||||
|  |           } else { | ||||
|  |             uni.showToast({ | ||||
|  |               title: res.msg, | ||||
|  |               icon: 'none' | ||||
|  |             }); | ||||
|  |           } | ||||
|  |         }); | ||||
|  |       } catch (error) { | ||||
|  |         console.error('加载订单信息失败:', error); | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 加载用户信息 | ||||
|  |     loadUserInfo() { | ||||
|  |       const userInfo = uni.getStorageSync('userInfo'); | ||||
|  |       if (userInfo) { | ||||
|  |         const user = JSON.parse(userInfo); | ||||
|  |         this.aftersaleForm.contactName = user.nickName || ''; | ||||
|  |         this.aftersaleForm.contactPhone = user.phone || ''; | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 获取订单状态文本 | ||||
|  |     getOrderStatusText(status) { | ||||
|  |       const statusMap = { | ||||
|  |         "-1": "已取消", | ||||
|  |         0: "待支付", | ||||
|  |         1: "已支付", | ||||
|  |         2: "已发货", | ||||
|  |         3: "已完成" | ||||
|  |       }; | ||||
|  |       return statusMap[status] || "未知"; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 切换商品选择 | ||||
|  |     toggleGoodsSelect(goods) { | ||||
|  |       const index = this.selectedGoods.indexOf(goods.id); | ||||
|  |       if (index > -1) { | ||||
|  |         this.selectedGoods.splice(index, 1); | ||||
|  |       } else { | ||||
|  |         this.selectedGoods.push(goods.id); | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 选择售后类型 | ||||
|  |     selectType(type) { | ||||
|  |       this.aftersaleForm.type = type; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 选择售后原因 | ||||
|  |     selectReason(reason) { | ||||
|  |       this.aftersaleForm.reason = reason; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 选择图片 | ||||
|  |     chooseImage() { | ||||
|  |       const remainCount = 6 - this.aftersaleForm.images.length; | ||||
|  |       uni.chooseImage({ | ||||
|  |         count: remainCount, | ||||
|  |         sizeType: ['compressed'], | ||||
|  |         sourceType: ['album', 'camera'], | ||||
|  |         success: (res) => { | ||||
|  |           this.uploadImages(res.tempFilePaths); | ||||
|  |         } | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 上传图片 | ||||
|  |     async uploadImages(filePaths) { | ||||
|  |       uni.showLoading({ | ||||
|  |         title: '上传中...' | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       try { | ||||
|  |         for (let filePath of filePaths) { | ||||
|  |           const uploadResult = await this.uploadSingleImage(filePath); | ||||
|  |           if (uploadResult) { | ||||
|  |             this.aftersaleForm.images.push(uploadResult); | ||||
|  |           } | ||||
|  |         } | ||||
|  |       } catch (error) { | ||||
|  |         console.error('图片上传失败:', error); | ||||
|  |         uni.showToast({ | ||||
|  |           title: '图片上传失败', | ||||
|  |           icon: 'none' | ||||
|  |         }); | ||||
|  |       } finally { | ||||
|  |         uni.hideLoading(); | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 上传单张图片 | ||||
|  |     uploadSingleImage(filePath) { | ||||
|  |       return new Promise((resolve, reject) => { | ||||
|  |         uni.uploadFile({ | ||||
|  |           url: this.BASE_URL + '/framework/upload/image', | ||||
|  |           filePath: filePath, | ||||
|  |           name: 'file', | ||||
|  |           success: (res) => { | ||||
|  |             try { | ||||
|  |               const data = JSON.parse(res.data); | ||||
|  |               if (data.code === 200) { | ||||
|  |                 resolve(data.data.url); | ||||
|  |               } else { | ||||
|  |                 reject(new Error(data.msg)); | ||||
|  |               } | ||||
|  |             } catch (error) { | ||||
|  |               reject(error); | ||||
|  |             } | ||||
|  |           }, | ||||
|  |           fail: (error) => { | ||||
|  |             reject(error); | ||||
|  |           } | ||||
|  |         }); | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 删除图片 | ||||
|  |     deleteImage(index) { | ||||
|  |       this.aftersaleForm.images.splice(index, 1); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 提交售后申请 | ||||
|  |     async submitAftersale() { | ||||
|  |       if (!this.canSubmit) { | ||||
|  |         uni.showToast({ | ||||
|  |           title: '请完善售后信息', | ||||
|  |           icon: 'none' | ||||
|  |         }); | ||||
|  |         return; | ||||
|  |       } | ||||
|  | 
 | ||||
|  |       // 验证联系电话格式 | ||||
|  |       const phoneReg = /^1[3-9]\d{9}$/; | ||||
|  |       if (!phoneReg.test(this.aftersaleForm.contactPhone)) { | ||||
|  |         uni.showToast({ | ||||
|  |           title: '请输入正确的手机号', | ||||
|  |           icon: 'none' | ||||
|  |         }); | ||||
|  |         return; | ||||
|  |       } | ||||
|  | 
 | ||||
|  |       uni.showLoading({ | ||||
|  |         title: '提交中...' | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       try { | ||||
|  |         const params = { | ||||
|  |           orderId: this.orderId, | ||||
|  |           goodsIds: this.selectedGoods, | ||||
|  |           type: this.aftersaleForm.type, | ||||
|  |           reason: this.aftersaleForm.reason, | ||||
|  |           description: this.aftersaleForm.description, | ||||
|  |           images: this.aftersaleForm.images.join(','), | ||||
|  |           contactName: this.aftersaleForm.contactName, | ||||
|  |           contactPhone: this.aftersaleForm.contactPhone | ||||
|  |         }; | ||||
|  | 
 | ||||
|  |         this.Post( | ||||
|  |           params, | ||||
|  |           '/framework/haveFeeling/aftersale/submit', | ||||
|  |           'DES' | ||||
|  |         ).then((res) => { | ||||
|  |           uni.hideLoading(); | ||||
|  |           if (res.code == 200) { | ||||
|  |             uni.showToast({ | ||||
|  |               title: '售后申请提交成功', | ||||
|  |               icon: 'success' | ||||
|  |             }); | ||||
|  |             setTimeout(() => { | ||||
|  |               uni.navigateBack(); | ||||
|  |             }, 1500); | ||||
|  |           } else { | ||||
|  |             uni.showToast({ | ||||
|  |               title: res.msg || '提交失败', | ||||
|  |               icon: 'none' | ||||
|  |             }); | ||||
|  |           } | ||||
|  |         }); | ||||
|  |       } catch (error) { | ||||
|  |         uni.hideLoading(); | ||||
|  |         console.error('提交售后申请失败:', error); | ||||
|  |         uni.showToast({ | ||||
|  |           title: '提交失败', | ||||
|  |           icon: 'none' | ||||
|  |         }); | ||||
|  |       } | ||||
|  |     } | ||||
|  |   } | ||||
|  | }; | ||||
|  | </script> | ||||
|  | 
 | ||||
|  | <style lang="scss" scoped> | ||||
|  | .aftersale-container { | ||||
|  |   min-height: 100vh; | ||||
|  |   background-color: #f5f5f5; | ||||
|  |   padding-bottom: 100rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 通用样式 | ||||
|  | .section-title { | ||||
|  |   font-size: 28rpx; | ||||
|  |   font-weight: 600; | ||||
|  |   color: #333; | ||||
|  |   margin-bottom: 24rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 订单信息 | ||||
|  | .order-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-card { | ||||
|  |   background-color: #f8f9fa; | ||||
|  |   border-radius: 12rpx; | ||||
|  |   padding: 24rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-header { | ||||
|  |   display: flex; | ||||
|  |   justify-content: space-between; | ||||
|  |   align-items: center; | ||||
|  |   margin-bottom: 12rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-no { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #333; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-status { | ||||
|  |   font-size: 24rpx; | ||||
|  |   color: #007aff; | ||||
|  |   background-color: #e6f3ff; | ||||
|  |   padding: 4rpx 12rpx; | ||||
|  |   border-radius: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .supplier-info { | ||||
|  |   .supplier-name { | ||||
|  |     font-size: 24rpx; | ||||
|  |     color: #666; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 商品选择 | ||||
|  | .goods-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-list { | ||||
|  |   .goods-item { | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     padding: 20rpx 0; | ||||
|  |     border-bottom: 1rpx solid #f0f0f0; | ||||
|  |     transition: all 0.3s ease; | ||||
|  | 
 | ||||
|  |     &:last-child { | ||||
|  |       border-bottom: none; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     &.selected { | ||||
|  |       background-color: #f0f8ff; | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-checkbox { | ||||
|  |   margin-right: 20rpx; | ||||
|  | 
 | ||||
|  |   .checkbox { | ||||
|  |     width: 40rpx; | ||||
|  |     height: 40rpx; | ||||
|  |     border: 2rpx solid #ddd; | ||||
|  |     border-radius: 50%; | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     justify-content: center; | ||||
|  |     transition: all 0.3s ease; | ||||
|  | 
 | ||||
|  |     &.checked { | ||||
|  |       background-color: #007aff; | ||||
|  |       border-color: #007aff; | ||||
|  | 
 | ||||
|  |       .checkbox-icon { | ||||
|  |         color: #fff; | ||||
|  |         font-size: 24rpx; | ||||
|  |         font-weight: bold; | ||||
|  |       } | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-image { | ||||
|  |   width: 80rpx; | ||||
|  |   height: 80rpx; | ||||
|  |   border-radius: 8rpx; | ||||
|  |   overflow: hidden; | ||||
|  |   margin-right: 20rpx; | ||||
|  | 
 | ||||
|  |   image { | ||||
|  |     width: 100%; | ||||
|  |     height: 100%; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-info { | ||||
|  |   flex: 1; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-name { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #333; | ||||
|  |   font-weight: 600; | ||||
|  |   margin-bottom: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-sku { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #666; | ||||
|  |   margin-bottom: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-meta { | ||||
|  |   display: flex; | ||||
|  |   justify-content: space-between; | ||||
|  |   align-items: center; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-price { | ||||
|  |   font-size: 24rpx; | ||||
|  |   color: #f56565; | ||||
|  |   font-weight: 600; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-quantity { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #999; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 售后类型 | ||||
|  | .type-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .type-list { | ||||
|  |   .type-item { | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     padding: 24rpx 0; | ||||
|  |     border-bottom: 1rpx solid #f0f0f0; | ||||
|  | 
 | ||||
|  |     &:last-child { | ||||
|  |       border-bottom: none; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     &.selected { | ||||
|  |       background-color: #f0f8ff; | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .type-radio { | ||||
|  |   margin-right: 20rpx; | ||||
|  | 
 | ||||
|  |   .radio { | ||||
|  |     width: 40rpx; | ||||
|  |     height: 40rpx; | ||||
|  |     border: 2rpx solid #ddd; | ||||
|  |     border-radius: 50%; | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     justify-content: center; | ||||
|  |     transition: all 0.3s ease; | ||||
|  | 
 | ||||
|  |     &.checked { | ||||
|  |       border-color: #007aff; | ||||
|  | 
 | ||||
|  |       .radio-dot { | ||||
|  |         width: 20rpx; | ||||
|  |         height: 20rpx; | ||||
|  |         background-color: #007aff; | ||||
|  |         border-radius: 50%; | ||||
|  |       } | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .type-info { | ||||
|  |   flex: 1; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .type-name { | ||||
|  |   display: block; | ||||
|  |   font-size: 28rpx; | ||||
|  |   color: #333; | ||||
|  |   font-weight: 600; | ||||
|  |   margin-bottom: 6rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .type-desc { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #666; | ||||
|  |   line-height: 1.4; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 售后原因 | ||||
|  | .reason-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .reason-list { | ||||
|  |   display: flex; | ||||
|  |   flex-wrap: wrap; | ||||
|  |   gap: 16rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .reason-item { | ||||
|  |   position: relative; | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  |   justify-content: center; | ||||
|  |   padding: 16rpx 24rpx; | ||||
|  |   background-color: #f5f5f5; | ||||
|  |   border-radius: 24rpx; | ||||
|  |   border: 1rpx solid transparent; | ||||
|  |   transition: all 0.3s ease; | ||||
|  |   min-width: 140rpx; | ||||
|  | 
 | ||||
|  |   &.selected { | ||||
|  |     background-color: #e6f3ff; | ||||
|  |     border-color: #007aff; | ||||
|  |     color: #007aff; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .reason-text { | ||||
|  |   font-size: 24rpx; | ||||
|  |   color: #333; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .reason-check { | ||||
|  |   position: absolute; | ||||
|  |   top: -8rpx; | ||||
|  |   right: -8rpx; | ||||
|  |   width: 24rpx; | ||||
|  |   height: 24rpx; | ||||
|  |   background-color: #007aff; | ||||
|  |   color: #fff; | ||||
|  |   border-radius: 50%; | ||||
|  |   font-size: 16rpx; | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  |   justify-content: center; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 问题描述 | ||||
|  | .description-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .description-input { | ||||
|  |   width: 100%; | ||||
|  |   min-height: 200rpx; | ||||
|  |   background-color: #f8f9fa; | ||||
|  |   border-radius: 12rpx; | ||||
|  |   padding: 20rpx; | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #333; | ||||
|  |   line-height: 1.6; | ||||
|  |   border: none; | ||||
|  |   resize: none; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .char-count { | ||||
|  |   text-align: right; | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #999; | ||||
|  |   margin-top: 12rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 上传凭证 | ||||
|  | .upload-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .upload-area { | ||||
|  |   .image-list { | ||||
|  |     display: flex; | ||||
|  |     flex-wrap: wrap; | ||||
|  |     gap: 16rpx; | ||||
|  |     margin-bottom: 16rpx; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   .image-item { | ||||
|  |     position: relative; | ||||
|  |     width: 160rpx; | ||||
|  |     height: 160rpx; | ||||
|  |     border-radius: 12rpx; | ||||
|  |     overflow: hidden; | ||||
|  | 
 | ||||
|  |     .uploaded-image { | ||||
|  |       width: 100%; | ||||
|  |       height: 100%; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     .delete-btn { | ||||
|  |       position: absolute; | ||||
|  |       top: -8rpx; | ||||
|  |       right: -8rpx; | ||||
|  |       width: 32rpx; | ||||
|  |       height: 32rpx; | ||||
|  |       background-color: #ff4757; | ||||
|  |       color: #fff; | ||||
|  |       border-radius: 50%; | ||||
|  |       display: flex; | ||||
|  |       align-items: center; | ||||
|  |       justify-content: center; | ||||
|  |       font-size: 20rpx; | ||||
|  |       font-weight: bold; | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   .upload-btn { | ||||
|  |     width: 160rpx; | ||||
|  |     height: 160rpx; | ||||
|  |     background-color: #f8f9fa; | ||||
|  |     border: 2rpx dashed #ddd; | ||||
|  |     border-radius: 12rpx; | ||||
|  |     display: flex; | ||||
|  |     flex-direction: column; | ||||
|  |     align-items: center; | ||||
|  |     justify-content: center; | ||||
|  |     color: #666; | ||||
|  | 
 | ||||
|  |     .upload-icon { | ||||
|  |       font-size: 48rpx; | ||||
|  |       margin-bottom: 8rpx; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     .upload-text { | ||||
|  |       font-size: 22rpx; | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   .upload-tip { | ||||
|  |     font-size: 22rpx; | ||||
|  |     color: #999; | ||||
|  |     text-align: center; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 联系方式 | ||||
|  | .contact-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .contact-form { | ||||
|  |   .form-item { | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     margin-bottom: 24rpx; | ||||
|  | 
 | ||||
|  |     &:last-child { | ||||
|  |       margin-bottom: 0; | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   .form-label { | ||||
|  |     width: 160rpx; | ||||
|  |     font-size: 26rpx; | ||||
|  |     color: #333; | ||||
|  |     font-weight: 500; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   .form-input { | ||||
|  |     flex: 1; | ||||
|  |     height: 80rpx; | ||||
|  |     background-color: #f8f9fa; | ||||
|  |     border-radius: 8rpx; | ||||
|  |     padding: 0 20rpx; | ||||
|  |     font-size: 26rpx; | ||||
|  |     color: #333; | ||||
|  |     border: none; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 提交按钮 | ||||
|  | .submit-section { | ||||
|  |   position: fixed; | ||||
|  |   bottom: 0; | ||||
|  |   left: 0; | ||||
|  |   right: 0; | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 20rpx 30rpx; | ||||
|  |   padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); | ||||
|  |   border-top: 1rpx solid #eee; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .submit-btn { | ||||
|  |   width: 100%; | ||||
|  |   height: 88rpx; | ||||
|  |   background-color: #007aff; | ||||
|  |   color: #fff; | ||||
|  |   border-radius: 12rpx; | ||||
|  |   font-size: 28rpx; | ||||
|  |   font-weight: 600; | ||||
|  |   border: none; | ||||
|  |   transition: all 0.3s ease; | ||||
|  | 
 | ||||
|  |   &:disabled { | ||||
|  |     background-color: #ccc; | ||||
|  |     color: #999; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   &:not(:disabled):active { | ||||
|  |     transform: scale(0.98); | ||||
|  |   } | ||||
|  | } | ||||
|  | </style> | ||||
								
									
										File diff suppressed because it is too large
									
								
							
						
					| @ -0,0 +1,810 @@ | |||||
|  | <template> | ||||
|  |   <view class="order-list-container"> | ||||
|  |     <!-- Tab切换 --> | ||||
|  |     <view class="tab-container"> | ||||
|  |       <view | ||||
|  |         class="tab-item" | ||||
|  |         :class="[{ active: currentTab == index }]" | ||||
|  |         v-for="(tab, index) in tabs" | ||||
|  |         :key="index" | ||||
|  |         @click="switchTab(index)" | ||||
|  |       > | ||||
|  |         <text class="tab-text">{{ tab.name }}</text> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 订单列表 --> | ||||
|  |     <scroll-view | ||||
|  |       class="order-scroll" | ||||
|  |       scroll-y | ||||
|  |       @scrolltolower="loadMore" | ||||
|  |       :show-scrollbar="false" | ||||
|  |       enhanced | ||||
|  |     > | ||||
|  |       <!-- 订单项 --> | ||||
|  |       <view | ||||
|  |         class="order-item" | ||||
|  |         v-for="order in orderList" | ||||
|  |         :key="order.id" | ||||
|  |         @click="goToOrderDetail(order)" | ||||
|  |       > | ||||
|  |         <!-- 订单头部 - 供应商信息 --> | ||||
|  |         <view class="order-header"> | ||||
|  |           <view class="supplier-info"> | ||||
|  |             <view class="supplier-name">{{ | ||||
|  |               order.supplierName || "默认供应商" | ||||
|  |             }}</view> | ||||
|  |             <view class="order-number">订单号:{{ order.orderNo }}</view> | ||||
|  |           </view> | ||||
|  |           <view class="order-status-wrapper"> | ||||
|  |             <text class="status-name" :class="[getStatusClass(order.status)]">{{ | ||||
|  |               getStatusText(order.status) | ||||
|  |             }}</text> | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  | 
 | ||||
|  |         <!-- 商品列表 --> | ||||
|  |         <view class="goods-section"> | ||||
|  |           <view class="goods-list"> | ||||
|  |             <view | ||||
|  |               class="goods-item" | ||||
|  |               v-for="goods in order.orderItems" | ||||
|  |               :key="goods.id" | ||||
|  |             > | ||||
|  |               <view class="goods-image-container"> | ||||
|  |                 <image | ||||
|  |                   v-if="goods.specImage" | ||||
|  |                   class="goods-image" | ||||
|  |                   :src="goods.specImage" | ||||
|  |                   mode="aspectFill" | ||||
|  |                 /> | ||||
|  |               </view> | ||||
|  |               <view class="goods-info"> | ||||
|  |                 <text class="goods-name">{{ goods.goodsName }}</text> | ||||
|  |                 <view class="goods-specs"> | ||||
|  |                   <view class="spec-tag"> | ||||
|  |                     {{ goods.specValueOne }}-{{ goods.specValueTwo }} | ||||
|  |                   </view> | ||||
|  |                 </view> | ||||
|  |                 <view class="goods-meta"> | ||||
|  |                   <text class="goods-price">¥{{ goods.price }}</text> | ||||
|  |                   <text class="goods-quantity">×{{ goods.quantity || 1 }}</text> | ||||
|  |                 </view> | ||||
|  |                 <!-- 规格信息 --> | ||||
|  |               </view> | ||||
|  |             </view> | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  | 
 | ||||
|  |         <!-- 订单底部 --> | ||||
|  |         <view class="order-footer"> | ||||
|  |           <view class="order-info"> | ||||
|  |             <view class="order-total-section"> | ||||
|  |               <text class="total-label">实付</text> | ||||
|  |               <text class="order-total">¥{{ order.payAmount || 0 }}</text> | ||||
|  |             </view> | ||||
|  |             <view class="order-time">{{ order.createTime }}</view> | ||||
|  |           </view> | ||||
|  |           <view class="order-actions"> | ||||
|  |             <!-- 基于订单状态的操作按钮 --> | ||||
|  |             <button | ||||
|  |               class="action-btn" | ||||
|  |               @click.stop="handleOrderAction(order, 'pay')" | ||||
|  |               v-if="order.status === 0" | ||||
|  |             > | ||||
|  |               去支付 | ||||
|  |             </button> | ||||
|  |             <button | ||||
|  |               class="action-btn" | ||||
|  |               @click.stop="handleOrderAction(order, 'logistics')" | ||||
|  |               v-if="[2, 3].includes(order.status)" | ||||
|  |             > | ||||
|  |               查看物流 | ||||
|  |             </button> | ||||
|  |             <button | ||||
|  |               class="action-btn confirm-btn" | ||||
|  |               @click.stop="handleOrderAction(order, 'confirm')" | ||||
|  |               v-if="order.status === 2" | ||||
|  |             > | ||||
|  |               确认收货 | ||||
|  |             </button> | ||||
|  |             <button | ||||
|  |               class="action-btn" | ||||
|  |               @click.stop="handleOrderAction(order, 'contact')" | ||||
|  |               v-if="[1, 2].includes(order.status)" | ||||
|  |             > | ||||
|  |               联系供应商 | ||||
|  |             </button> | ||||
|  |             <button | ||||
|  |               class="action-btn secondary-btn" | ||||
|  |               @click.stop="handleOrderAction(order, 'aftersale')" | ||||
|  |               v-if="order.status === 3" | ||||
|  |             > | ||||
|  |               申请售后 | ||||
|  |             </button> | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  | 
 | ||||
|  |       <!-- 空状态 --> | ||||
|  |       <view | ||||
|  |         class="empty-state" | ||||
|  |         v-if="(orderList && orderList.length == 0) || loading" | ||||
|  |       > | ||||
|  |         <image | ||||
|  |           class="empty-image" | ||||
|  |           :src=" | ||||
|  |             showImg('/uploads/20250808/c16267f9cc2b7a68bf23713b5847987e.png') | ||||
|  |           " | ||||
|  |           mode="aspectFit" | ||||
|  |         /> | ||||
|  |         <text class="empty-text">暂无订单</text> | ||||
|  |       </view> | ||||
|  | 
 | ||||
|  |       <!-- 加载更多 --> | ||||
|  |       <view class="load-more" v-if="hasMore && orderList.length > 0"> | ||||
|  |         <text class="load-text">{{ | ||||
|  |           loading ? "加载中..." : "上拉加载更多" | ||||
|  |         }}</text> | ||||
|  |       </view> | ||||
|  | 
 | ||||
|  |       <!-- 没有更多数据 --> | ||||
|  |       <view class="no-more" v-if="!hasMore && orderList.length > 0"> | ||||
|  |         <text class="no-more-text">没有更多数据了</text> | ||||
|  |       </view> | ||||
|  |     </scroll-view> | ||||
|  |   </view> | ||||
|  | </template> | ||||
|  | 
 | ||||
|  | <script> | ||||
|  | export default { | ||||
|  |   data() { | ||||
|  |     return { | ||||
|  |       currentTab: 0, | ||||
|  |       tabs: [ | ||||
|  |         { | ||||
|  |           name: "全部", | ||||
|  |           status: "", | ||||
|  |         }, | ||||
|  |         { | ||||
|  |           name: "待支付", | ||||
|  |           status: 0, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |           name: "已支付", | ||||
|  |           status: 1, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |           name: "已发货", | ||||
|  |           status: 2, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |           name: "已完成", | ||||
|  |           status: 3, | ||||
|  |         }, | ||||
|  |       ], | ||||
|  |       orderList: [], | ||||
|  |       loading: false, | ||||
|  |       refresherTriggered: false, | ||||
|  |       hasMore: true, | ||||
|  |       currentPage: 1, | ||||
|  |       pageSize: 10, | ||||
|  |     }; | ||||
|  |   }, | ||||
|  |   onLoad(e) { | ||||
|  |     if (e.status) { | ||||
|  |       this.currentTab = e.status; | ||||
|  |     } | ||||
|  |   }, | ||||
|  |   onShow() { | ||||
|  |     this.resetList(); | ||||
|  |     this.loadOrderList(); | ||||
|  |   }, | ||||
|  |   methods: { | ||||
|  |     showImgJdsz(img) { | ||||
|  |       if (!img) return; | ||||
|  |       if (img.indexOf("https://") != -1 || img.indexOf("http://") != -1) { | ||||
|  |         return img; | ||||
|  |       } else { | ||||
|  |         return this.JDSU_IMG_URL + img; | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 切换Tab | ||||
|  |     switchTab(index) { | ||||
|  |       this.currentTab = index; | ||||
|  |       this.resetList(); | ||||
|  |       this.loadOrderList(); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 重置列表 | ||||
|  |     resetList() { | ||||
|  |       this.orderList = []; | ||||
|  |       this.currentPage = 1; | ||||
|  |       this.hasMore = true; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 加载订单列表 | ||||
|  |     async loadOrderList() { | ||||
|  |       if (this.loading || !this.hasMore) return; | ||||
|  | 
 | ||||
|  |       this.loading = true; | ||||
|  |       try { | ||||
|  |         const params = { | ||||
|  |           pageNum: this.currentPage, | ||||
|  |           pageSize: this.pageSize, | ||||
|  |           status: this.tabs[this.currentTab].status, | ||||
|  |         }; | ||||
|  | 
 | ||||
|  |         this.Post( | ||||
|  |           { | ||||
|  |             ...params, | ||||
|  |           }, | ||||
|  |           "/framework/ygOrder/pageList", | ||||
|  |           "DES" | ||||
|  |         ).then((res) => { | ||||
|  |           if (res.code == 200) { | ||||
|  |             this.orderList.push(...res.rows); | ||||
|  |             console.log(this.orderList); | ||||
|  |             this.hasMore = res.rows.length === this.pageSize; | ||||
|  |             this.currentPage++; | ||||
|  |           } else { | ||||
|  |             uni.showToast({ | ||||
|  |               title: res.msg, | ||||
|  |               icon: "none", | ||||
|  |             }); | ||||
|  |           } | ||||
|  |         }); | ||||
|  |       } catch (error) { | ||||
|  |         console.error("加载订单列表失败:", error); | ||||
|  |         uni.showToast({ | ||||
|  |           title: "加载失败", | ||||
|  |           icon: "none", | ||||
|  |         }); | ||||
|  |       } finally { | ||||
|  |         this.loading = false; | ||||
|  |         this.refresherTriggered = false; | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 上拉加载更多 | ||||
|  |     loadMore() { | ||||
|  |       this.loadOrderList(); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 下拉刷新 | ||||
|  |     onRefresh() { | ||||
|  |       this.refresherTriggered = true; | ||||
|  |       this.resetList(); | ||||
|  |       this.loadOrderList(); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 获取订单状态文本 | ||||
|  |     getStatusText(status) { | ||||
|  |       const statusMap = { | ||||
|  |         "-1": "已取消", | ||||
|  |         0: "待支付", | ||||
|  |         1: "已支付", | ||||
|  |         2: "已发货", | ||||
|  |         3: "已完成", | ||||
|  |       }; | ||||
|  |       return statusMap[status] || "未知"; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 获取订单状态样式类 | ||||
|  |     getStatusClass(status) { | ||||
|  |       const classMap = { | ||||
|  |         "-1": "status-cancelled", | ||||
|  |         0: "status-pending", | ||||
|  |         1: "status-paid", | ||||
|  |         2: "status-shipping", | ||||
|  |         3: "status-completed", | ||||
|  |       }; | ||||
|  |       return classMap[status] || ""; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 处理订单操作 | ||||
|  |     handleOrderAction(order, action) { | ||||
|  |       switch (action) { | ||||
|  |         case "pay": | ||||
|  |           this.goToPay(order); | ||||
|  |           break; | ||||
|  |         case "logistics": | ||||
|  |           this.viewLogistics(order); | ||||
|  |           break; | ||||
|  |         case "confirm": | ||||
|  |           this.confirmReceipt(order); | ||||
|  |           break; | ||||
|  |         case "contact": | ||||
|  |           this.contactSupplier(order); | ||||
|  |           break; | ||||
|  |         case "aftersale": | ||||
|  |           this.applyAfterSale(order); | ||||
|  |           break; | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 去支付 | ||||
|  |     goToPay(order) { | ||||
|  |       this.Post( | ||||
|  |         { | ||||
|  |           method: "POST", | ||||
|  |           orderNo: order.orderNo, | ||||
|  |           fromType: 2, | ||||
|  |           payAmount: order.payAmount, | ||||
|  |         }, | ||||
|  |         "/framework/wxPay/submitShopPurOrder", | ||||
|  |         "DES" | ||||
|  |       ).then((res) => { | ||||
|  |         uni.requestPayment({ | ||||
|  |           nonceStr: res.data.wxInfo.nonceStr, | ||||
|  |           package: res.data.wxInfo.package, | ||||
|  |           paySign: res.data.wxInfo.paySign, | ||||
|  |           signType: res.data.wxInfo.signType, | ||||
|  |           timeStamp: res.data.wxInfo.timeStamp, | ||||
|  |           success: () => { | ||||
|  |             this.resetList(); | ||||
|  |             this.loadOrderList(); | ||||
|  |           }, | ||||
|  |           fail() { | ||||
|  |             // uni.navigateTo({ | ||||
|  |             // 	url: '/subPackages/order/trades' | ||||
|  |             // }) | ||||
|  |           }, | ||||
|  |         }); | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 查看物流 | ||||
|  |     viewLogistics(order) { | ||||
|  |       uni.navigateTo({ | ||||
|  |         url: `/subPackages/haveFeeling/logistics?orderId=${order.id}`, | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 确认收货 | ||||
|  |     confirmReceipt(order) { | ||||
|  |       uni.showModal({ | ||||
|  |         title: "确认收货", | ||||
|  |         content: "确认已收到所有商品吗?", | ||||
|  |         success: (res) => { | ||||
|  |           if (res.confirm) { | ||||
|  |             this.confirmReceiptApi(order.id); | ||||
|  |           } | ||||
|  |         }, | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 确认收货API | ||||
|  |     confirmReceiptApi(orderId) { | ||||
|  |       uni.showLoading({ | ||||
|  |         title: "确认中...", | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       this.Post( | ||||
|  |         { | ||||
|  |           orderId: orderId, | ||||
|  |         }, | ||||
|  |         "/framework/haveFeeling/order/confirm", | ||||
|  |         "DES" | ||||
|  |       ).then((res) => { | ||||
|  |         uni.hideLoading(); | ||||
|  |         if (res.code == 200) { | ||||
|  |           uni.showToast({ | ||||
|  |             title: "确认收货成功", | ||||
|  |             icon: "success", | ||||
|  |           }); | ||||
|  |           setTimeout(() => { | ||||
|  |             this.resetList(); | ||||
|  |             this.loadOrderList(); | ||||
|  |           }, 800); | ||||
|  |         } else { | ||||
|  |           uni.showToast({ | ||||
|  |             title: res.msg || "确认收货失败", | ||||
|  |             icon: "none", | ||||
|  |           }); | ||||
|  |         } | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 联系供应商 | ||||
|  |     contactSupplier(order) { | ||||
|  |       uni.showToast({ | ||||
|  |         title: "正在联系供应商", | ||||
|  |         icon: "none", | ||||
|  |       }); | ||||
|  |       // 这里可以跳转到聊天页面或者拨打电话 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 申请售后 | ||||
|  |     applyAfterSale(order) { | ||||
|  |       uni.navigateTo({ | ||||
|  |         url: `/subPackages/haveFeeling/aftersale?orderId=${order.id}`, | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 跳转到订单详情页面 | ||||
|  |     goToOrderDetail(order) { | ||||
|  |       uni.navigateTo({ | ||||
|  |         url: `/subPackages/haveFeeling/detail?id=${order.id}`, | ||||
|  |       }); | ||||
|  |     }, | ||||
|  |   }, | ||||
|  | }; | ||||
|  | </script> | ||||
|  | 
 | ||||
|  | <style lang="scss" scoped> | ||||
|  | // 主题色彩变量 | ||||
|  | $primary-color: #667eea; | ||||
|  | $secondary-color: #f8f9fa; | ||||
|  | $text-primary: #2d3748; | ||||
|  | $text-secondary: #718096; | ||||
|  | $text-muted: #a0aec0; | ||||
|  | $border-color: #e2e8f0; | ||||
|  | $success-color: #48bb78; | ||||
|  | $warning-color: #ed8936; | ||||
|  | $danger-color: #f56565; | ||||
|  | $bg-light: #f7fafc; | ||||
|  | 
 | ||||
|  | .order-list-container { | ||||
|  |   min-height: 100vh; | ||||
|  |   background-color: $bg-light; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // Tab样式 | ||||
|  | .tab-container { | ||||
|  |   display: flex; | ||||
|  |   background-color: #ffffff; | ||||
|  |   border-bottom: 1px solid rgba(255, 255, 255, 0.1); | ||||
|  |   color: black; | ||||
|  |   position: sticky; | ||||
|  |   top: 0; | ||||
|  |   z-index: 10; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .tab-item { | ||||
|  |   flex: 1; | ||||
|  |   padding: 32rpx 0; | ||||
|  |   text-align: center; | ||||
|  |   position: relative; | ||||
|  |   transition: all 0.3s ease; | ||||
|  |   color: #333333; | ||||
|  | 
 | ||||
|  |   &.active { | ||||
|  |     .tab-text { | ||||
|  |       color: #77f3f9; | ||||
|  |       font-weight: 600; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     &::after { | ||||
|  |       content: ""; | ||||
|  |       position: absolute; | ||||
|  |       bottom: 0; | ||||
|  |       left: 50%; | ||||
|  |       transform: translateX(-50%); | ||||
|  |       width: 60rpx; | ||||
|  |       height: 4rpx; | ||||
|  |       background-color: #77f3f9; | ||||
|  |       border-radius: 2rpx; | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   &:not(.active) { | ||||
|  |     .tab-text { | ||||
|  |       opacity: 1; | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .tab-text { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #333333; | ||||
|  |   font-weight: 600; | ||||
|  |   transition: all 0.3s ease; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 订单列表样式 | ||||
|  | .order-scroll { | ||||
|  |   height: calc(100vh - 120rpx); | ||||
|  |   padding: 0 24rpx; | ||||
|  |   width: 702rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-item { | ||||
|  |   background-color: #ffffff; | ||||
|  |   border-radius: 20rpx; | ||||
|  |   overflow: hidden; | ||||
|  |   box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08); | ||||
|  |   border: none; | ||||
|  |   transition: all 0.3s ease; | ||||
|  |   margin-top: 40rpx; | ||||
|  | 
 | ||||
|  |   &:active { | ||||
|  |     transform: scale(0.98); | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 订单头部 - 供应商信息 | ||||
|  | .order-header { | ||||
|  |   display: flex; | ||||
|  |   justify-content: space-between; | ||||
|  |   align-items: center; | ||||
|  |   padding: 24rpx 28rpx 20rpx; | ||||
|  |   background: white; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .supplier-info { | ||||
|  |   flex: 1; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .supplier-name { | ||||
|  |   font-size: 30rpx; | ||||
|  |   color: $text-primary; | ||||
|  |   font-weight: 600; | ||||
|  |   margin-bottom: 8rpx; | ||||
|  |   overflow: hidden; | ||||
|  |   text-overflow: ellipsis; | ||||
|  |   white-space: nowrap; | ||||
|  |   max-width: 490rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-number { | ||||
|  |   font-size: 24rpx; | ||||
|  |   color: $text-secondary; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-status-wrapper { | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .status-name { | ||||
|  |   font-size: 26rpx; | ||||
|  |   padding: 12rpx 20rpx; | ||||
|  |   border-radius: 24rpx; | ||||
|  |   font-weight: 600; | ||||
|  |   letter-spacing: 0.5rpx; | ||||
|  | 
 | ||||
|  |   &.status-pending { | ||||
|  |     background: #fff3cd; | ||||
|  |     color: #856404; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   &.status-paid { | ||||
|  |     background: #e6f3ff; | ||||
|  |     color: #0c5460; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   &.status-cancelled { | ||||
|  |     background: #f8d7da; | ||||
|  |     color: #721c24; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   &.status-shipping { | ||||
|  |     background: #d4edda; | ||||
|  |     color: #155724; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   &.status-completed { | ||||
|  |     background: #d1ecf1; | ||||
|  |     color: #0c5460; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 商品部分 | ||||
|  | .goods-section { | ||||
|  |   margin: 20rpx 0; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-list { | ||||
|  |   padding: 0 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-item { | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  |   padding: 20rpx; | ||||
|  |   margin-bottom: 12rpx; | ||||
|  |   background: #ffffff; | ||||
|  |   border-radius: 16rpx; | ||||
|  |   border: 1px solid rgba(0, 0, 0, 0.05); | ||||
|  |   transition: all 0.3s ease; | ||||
|  |   box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04); | ||||
|  | 
 | ||||
|  |   &:last-child { | ||||
|  |     margin-bottom: 0; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-image-container { | ||||
|  |   position: relative; | ||||
|  |   margin-right: 20rpx; | ||||
|  |   flex-shrink: 0; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-image { | ||||
|  |   width: 100rpx; | ||||
|  |   height: 100rpx; | ||||
|  |   border-radius: 12rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-info { | ||||
|  |   flex: 1; | ||||
|  |   margin-right: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-name { | ||||
|  |   display: block; | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: $text-primary; | ||||
|  |   font-weight: 600; | ||||
|  |   margin-bottom: 12rpx; | ||||
|  |   line-height: 1.4; | ||||
|  |   overflow: hidden; | ||||
|  |   text-overflow: ellipsis; | ||||
|  |   white-space: nowrap; | ||||
|  |   max-width: 490rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-meta { | ||||
|  |   display: flex; | ||||
|  |   justify-content: space-between; | ||||
|  |   align-items: center; | ||||
|  |   margin-bottom: 10rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-price { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: $danger-color; | ||||
|  |   font-weight: 600; | ||||
|  |   font-family: "SF Mono", "Monaco", "Cascadia Code", monospace; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .goods-quantity { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: $text-muted; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 商品规格样式 | ||||
|  | .goods-specs { | ||||
|  |   margin-top: 10rpx; | ||||
|  |   display: flex; | ||||
|  |   flex-wrap: wrap; | ||||
|  |   gap: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .spec-tag { | ||||
|  |   background: #f0f8ff; | ||||
|  |   border: 1rpx solid #e6f3ff; | ||||
|  |   border-radius: 12rpx; | ||||
|  |   padding: 4rpx 12rpx; | ||||
|  |   display: inline-block; | ||||
|  |   margin-bottom: 6rpx; | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #4a90e2; | ||||
|  |   font-weight: 500; | ||||
|  |   overflow: hidden; | ||||
|  |   text-overflow: ellipsis; | ||||
|  |   white-space: nowrap; | ||||
|  |   max-width: 490rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 订单底部 | ||||
|  | .order-footer { | ||||
|  |   display: flex; | ||||
|  |   justify-content: space-between; | ||||
|  |   align-items: center; | ||||
|  |   padding: 24rpx 28rpx; | ||||
|  |   background: white; | ||||
|  |   margin-top: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-info { | ||||
|  |   flex: 1; | ||||
|  |   display: flex; | ||||
|  |   flex-direction: column; | ||||
|  |   gap: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-total-section { | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  |   gap: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .total-label { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: $text-muted; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-total { | ||||
|  |   font-size: 32rpx; | ||||
|  |   color: $danger-color; | ||||
|  |   font-weight: 600; | ||||
|  |   font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", | ||||
|  |     "Helvetica Neue", STHeiti, "Microsoft Yahei", Tahoma, Simsun, sans-serif; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-time { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: $text-muted; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .order-actions { | ||||
|  |   display: flex; | ||||
|  |   gap: 12rpx; | ||||
|  |   flex-direction: column; | ||||
|  | 
 | ||||
|  |   .action-btn { | ||||
|  |     padding: 8rpx 20rpx; | ||||
|  |     border-radius: 10rpx; | ||||
|  |     font-size: 24rpx; | ||||
|  |     font-weight: 600; | ||||
|  |     border: none; | ||||
|  |     color: #333333; | ||||
|  |     transition: all 0.3s ease; | ||||
|  |     min-width: 100rpx; | ||||
|  |     text-align: center; | ||||
|  |     background-color: #77f3f9; | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     justify-content: center; | ||||
|  |     height: 58rpx; | ||||
|  |     &:active { | ||||
|  |       transform: scale(0.95); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     &.confirm-btn { | ||||
|  |       background-color: $success-color; | ||||
|  |       color: #ffffff; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     &.secondary-btn { | ||||
|  |       background-color: #f5f5f5; | ||||
|  |       color: #666666; | ||||
|  |       border: 1rpx solid #ddd; | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 空状态 | ||||
|  | .empty-state { | ||||
|  |   text-align: center; | ||||
|  |   padding: 240rpx 40rpx; | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  |   justify-content: center; | ||||
|  |   flex-direction: column; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .empty-image { | ||||
|  |   width: 240rpx; | ||||
|  |   height: 240rpx; | ||||
|  |   margin-bottom: 40rpx; | ||||
|  |   opacity: 0.8; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .empty-text { | ||||
|  |   font-size: 32rpx; | ||||
|  |   color: $text-muted; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 加载更多 | ||||
|  | .load-more, | ||||
|  | .no-more { | ||||
|  |   text-align: center; | ||||
|  |   padding: 40rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .load-text, | ||||
|  | .no-more-text { | ||||
|  |   font-size: 28rpx; | ||||
|  |   color: $text-muted; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | </style> | ||||
| @ -0,0 +1,592 @@ | |||||
|  | <template> | ||||
|  |   <view class="logistics-container"> | ||||
|  |     <!-- 物流状态头部 --> | ||||
|  |     <view class="status-header"> | ||||
|  |       <view class="status-info"> | ||||
|  |         <view class="status-icon"> | ||||
|  |           <image :src="getStatusIcon(logisticsInfo.status)" mode="aspectFit" /> | ||||
|  |         </view> | ||||
|  |         <view class="status-content"> | ||||
|  |           <view class="status-title">{{ getStatusText(logisticsInfo.status) }}</view> | ||||
|  |           <view class="status-desc" v-if="logisticsInfo.lastUpdate"> | ||||
|  |             最新状态:{{ logisticsInfo.lastUpdate }} | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 快递信息 --> | ||||
|  |     <view class="express-section"> | ||||
|  |       <view class="section-title">快递信息</view> | ||||
|  |       <view class="express-card"> | ||||
|  |         <view class="express-item"> | ||||
|  |           <text class="express-label">快递公司</text> | ||||
|  |           <text class="express-value">{{ logisticsInfo.expressCompany || '--' }}</text> | ||||
|  |         </view> | ||||
|  |         <view class="express-item"> | ||||
|  |           <text class="express-label">快递单号</text> | ||||
|  |           <text class="express-value" @longpress="copyExpressNo">{{ logisticsInfo.expressNo || '--' }}</text> | ||||
|  |         </view> | ||||
|  |         <view class="express-item"> | ||||
|  |           <text class="express-label">发货时间</text> | ||||
|  |           <text class="express-value">{{ logisticsInfo.shippingTime || '--' }}</text> | ||||
|  |         </view> | ||||
|  |         <view class="express-item"> | ||||
|  |           <text class="express-label">预计送达</text> | ||||
|  |           <text class="express-value">{{ logisticsInfo.estimatedTime || '--' }}</text> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 收货地址 --> | ||||
|  |     <view class="address-section"> | ||||
|  |       <view class="section-title">收货地址</view> | ||||
|  |       <view class="address-card"> | ||||
|  |         <view class="address-info"> | ||||
|  |           <view class="recipient-info"> | ||||
|  |             <text class="recipient-name">{{ addressInfo.linkName }}</text> | ||||
|  |             <text class="recipient-phone">{{ addressInfo.phone }}</text> | ||||
|  |           </view> | ||||
|  |           <view class="address-detail"> | ||||
|  |             {{ addressInfo.province }}{{ addressInfo.city }}{{ addressInfo.area }}{{ addressInfo.address }} | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 物流轨迹 --> | ||||
|  |     <view class="trace-section"> | ||||
|  |       <view class="section-title">物流轨迹</view> | ||||
|  |       <view class="trace-list"> | ||||
|  |         <view | ||||
|  |           class="trace-item" | ||||
|  |           v-for="(trace, index) in logisticsTrace" | ||||
|  |           :key="index" | ||||
|  |           :class="{ 'is-current': index === 0 }" | ||||
|  |         > | ||||
|  |           <view class="trace-time">{{ trace.time }}</view> | ||||
|  |           <view class="trace-content"> | ||||
|  |             <view class="trace-status">{{ trace.status }}</view> | ||||
|  |             <view class="trace-location" v-if="trace.location">{{ trace.location }}</view> | ||||
|  |             <view class="trace-remark" v-if="trace.remark">{{ trace.remark }}</view> | ||||
|  |           </view> | ||||
|  |         </view> | ||||
|  |       </view> | ||||
|  | 
 | ||||
|  |       <!-- 空状态 --> | ||||
|  |       <view class="empty-trace" v-if="!logisticsTrace || logisticsTrace.length === 0"> | ||||
|  |         <image class="empty-image" src="/static/images/empty-logistics.png" mode="aspectFit" /> | ||||
|  |         <text class="empty-text">暂无物流轨迹信息</text> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 联系供应商 --> | ||||
|  |     <view class="contact-section"> | ||||
|  |       <view class="section-title">联系供应商</view> | ||||
|  |       <view class="contact-card"> | ||||
|  |         <view class="supplier-info"> | ||||
|  |           <view class="supplier-name">{{ supplierInfo.name || '默认供应商' }}</view> | ||||
|  |           <view class="supplier-phone">联系电话:{{ supplierInfo.phone || '暂无' }}</view> | ||||
|  |         </view> | ||||
|  |         <button class="contact-btn" @click="contactSupplier"> | ||||
|  |           <text>联系供应商</text> | ||||
|  |         </button> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 订单操作 --> | ||||
|  |     <view class="order-actions"> | ||||
|  |       <button | ||||
|  |         class="action-btn confirm-btn" | ||||
|  |         @click="confirmReceipt" | ||||
|  |         v-if="logisticsInfo.status === 3" | ||||
|  |       > | ||||
|  |         确认收货 | ||||
|  |       </button> | ||||
|  |       <button | ||||
|  |         class="action-btn secondary-btn" | ||||
|  |         @click="applyAfterSale" | ||||
|  |         v-if="[2, 3, 4].includes(logisticsInfo.status)" | ||||
|  |       > | ||||
|  |         申请售后 | ||||
|  |       </button> | ||||
|  |     </view> | ||||
|  |   </view> | ||||
|  | </template> | ||||
|  | 
 | ||||
|  | <script> | ||||
|  | export default { | ||||
|  |   data() { | ||||
|  |     return { | ||||
|  |       orderId: '', | ||||
|  |       logisticsInfo: { | ||||
|  |         status: 0, | ||||
|  |         expressCompany: '', | ||||
|  |         expressNo: '', | ||||
|  |         shippingTime: '', | ||||
|  |         estimatedTime: '', | ||||
|  |         lastUpdate: '' | ||||
|  |       }, | ||||
|  |       addressInfo: { | ||||
|  |         linkName: '', | ||||
|  |         phone: '', | ||||
|  |         province: '', | ||||
|  |         city: '', | ||||
|  |         area: '', | ||||
|  |         address: '' | ||||
|  |       }, | ||||
|  |       supplierInfo: { | ||||
|  |         name: '', | ||||
|  |         phone: '' | ||||
|  |       }, | ||||
|  |       logisticsTrace: [] | ||||
|  |     }; | ||||
|  |   }, | ||||
|  |   onLoad(options) { | ||||
|  |     if (options.orderId) { | ||||
|  |       this.orderId = options.orderId; | ||||
|  |       this.loadLogisticsInfo(); | ||||
|  |     } | ||||
|  |   }, | ||||
|  |   methods: { | ||||
|  |     // 加载物流信息 | ||||
|  |     async loadLogisticsInfo() { | ||||
|  |       try { | ||||
|  |         uni.showLoading({ | ||||
|  |           title: '加载中...' | ||||
|  |         }); | ||||
|  | 
 | ||||
|  |         this.Post( | ||||
|  |           { orderId: this.orderId }, | ||||
|  |           '/framework/haveFeeling/order/logistics', | ||||
|  |           'DES' | ||||
|  |         ).then((res) => { | ||||
|  |           if (res.code == 200) { | ||||
|  |             this.logisticsInfo = res.data.logistics || {}; | ||||
|  |             this.addressInfo = res.data.address || {}; | ||||
|  |             this.supplierInfo = res.data.supplier || {}; | ||||
|  |             this.logisticsTrace = res.data.trace || []; | ||||
|  |           } else { | ||||
|  |             uni.showToast({ | ||||
|  |               title: res.msg, | ||||
|  |               icon: 'none' | ||||
|  |             }); | ||||
|  |           } | ||||
|  |         }); | ||||
|  |       } catch (error) { | ||||
|  |         console.error('加载物流信息失败:', error); | ||||
|  |         uni.showToast({ | ||||
|  |           title: '加载失败', | ||||
|  |           icon: 'none' | ||||
|  |         }); | ||||
|  |       } finally { | ||||
|  |         uni.hideLoading(); | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 获取状态文本 | ||||
|  |     getStatusText(status) { | ||||
|  |       const statusMap = { | ||||
|  |         0: '待发货', | ||||
|  |         1: '已发货', | ||||
|  |         2: '运输中', | ||||
|  |         3: '派送中', | ||||
|  |         4: '已签收', | ||||
|  |         5: '异常' | ||||
|  |       }; | ||||
|  |       return statusMap[status] || '待发货'; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 获取状态图标 | ||||
|  |     getStatusIcon(status) { | ||||
|  |       const iconMap = { | ||||
|  |         0: '/static/images/logistics-waiting.png', | ||||
|  |         1: '/static/images/logistics-shipped.png', | ||||
|  |         2: '/static/images/logistics-transit.png', | ||||
|  |         3: '/static/images/logistics-delivering.png', | ||||
|  |         4: '/static/images/logistics-completed.png', | ||||
|  |         5: '/static/images/logistics-exception.png' | ||||
|  |       }; | ||||
|  |       return iconMap[status] || '/static/images/logistics-waiting.png'; | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 复制快递单号 | ||||
|  |     copyExpressNo() { | ||||
|  |       if (this.logisticsInfo.expressNo) { | ||||
|  |         uni.setClipboardData({ | ||||
|  |           data: this.logisticsInfo.expressNo, | ||||
|  |           success: () => { | ||||
|  |             uni.showToast({ | ||||
|  |               title: '快递单号已复制', | ||||
|  |               icon: 'success' | ||||
|  |             }); | ||||
|  |           } | ||||
|  |         }); | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 联系供应商 | ||||
|  |     contactSupplier() { | ||||
|  |       if (this.supplierInfo.phone) { | ||||
|  |         uni.makePhoneCall({ | ||||
|  |           phoneNumber: this.supplierInfo.phone | ||||
|  |         }); | ||||
|  |       } else { | ||||
|  |         uni.showToast({ | ||||
|  |           title: '暂无供应商联系方式', | ||||
|  |           icon: 'none' | ||||
|  |         }); | ||||
|  |       } | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 确认收货 | ||||
|  |     confirmReceipt() { | ||||
|  |       uni.showModal({ | ||||
|  |         title: '确认收货', | ||||
|  |         content: '确认已收到所有商品吗?', | ||||
|  |         success: (res) => { | ||||
|  |           if (res.confirm) { | ||||
|  |             this.confirmReceiptApi(); | ||||
|  |           } | ||||
|  |         } | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 确认收货API | ||||
|  |     confirmReceiptApi() { | ||||
|  |       uni.showLoading({ | ||||
|  |         title: '确认中...' | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       this.Post( | ||||
|  |         { orderId: this.orderId }, | ||||
|  |         '/framework/haveFeeling/order/confirm', | ||||
|  |         'DES' | ||||
|  |       ).then((res) => { | ||||
|  |         uni.hideLoading(); | ||||
|  |         if (res.code == 200) { | ||||
|  |           uni.showToast({ | ||||
|  |             title: '确认收货成功', | ||||
|  |             icon: 'success' | ||||
|  |           }); | ||||
|  |           setTimeout(() => { | ||||
|  |             uni.navigateBack(); | ||||
|  |           }, 800); | ||||
|  |         } else { | ||||
|  |           uni.showToast({ | ||||
|  |             title: res.msg || '确认收货失败', | ||||
|  |             icon: 'none' | ||||
|  |           }); | ||||
|  |         } | ||||
|  |       }); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     // 申请售后 | ||||
|  |     applyAfterSale() { | ||||
|  |       uni.navigateTo({ | ||||
|  |         url: `/subPackages/haveFeeling/aftersale?orderId=${this.orderId}` | ||||
|  |       }); | ||||
|  |     } | ||||
|  |   } | ||||
|  | }; | ||||
|  | </script> | ||||
|  | 
 | ||||
|  | <style lang="scss" scoped> | ||||
|  | .logistics-container { | ||||
|  |   min-height: 100vh; | ||||
|  |   background-color: #f5f5f5; | ||||
|  |   padding-bottom: 100rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 状态头部 | ||||
|  | .status-header { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 40rpx 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .status-info { | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .status-icon { | ||||
|  |   width: 80rpx; | ||||
|  |   height: 80rpx; | ||||
|  |   margin-right: 24rpx; | ||||
|  | 
 | ||||
|  |   image { | ||||
|  |     width: 100%; | ||||
|  |     height: 100%; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .status-content { | ||||
|  |   flex: 1; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .status-title { | ||||
|  |   font-size: 32rpx; | ||||
|  |   color: #333; | ||||
|  |   font-weight: 600; | ||||
|  |   margin-bottom: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .status-desc { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #666; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 通用样式 | ||||
|  | .section-title { | ||||
|  |   font-size: 28rpx; | ||||
|  |   font-weight: 600; | ||||
|  |   color: #333; | ||||
|  |   margin-bottom: 24rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 快递信息 | ||||
|  | .express-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .express-card { | ||||
|  |   background-color: #f8f9fa; | ||||
|  |   border-radius: 12rpx; | ||||
|  |   padding: 24rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .express-item { | ||||
|  |   display: flex; | ||||
|  |   justify-content: space-between; | ||||
|  |   align-items: center; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | 
 | ||||
|  |   &:last-child { | ||||
|  |     margin-bottom: 0; | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .express-label { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #666; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .express-value { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #333; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 收货地址 | ||||
|  | .address-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .address-card { | ||||
|  |   background-color: #f8f9fa; | ||||
|  |   border-radius: 12rpx; | ||||
|  |   padding: 24rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .recipient-info { | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  |   gap: 20rpx; | ||||
|  |   margin-bottom: 16rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .recipient-name { | ||||
|  |   font-size: 28rpx; | ||||
|  |   color: #333; | ||||
|  |   font-weight: 600; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .recipient-phone { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #666; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .address-detail { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #333; | ||||
|  |   line-height: 1.5; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 物流轨迹 | ||||
|  | .trace-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .trace-list { | ||||
|  |   .trace-item { | ||||
|  |     display: flex; | ||||
|  |     padding: 24rpx 0; | ||||
|  |     border-left: 2rpx solid #e2e8f0; | ||||
|  |     padding-left: 40rpx; | ||||
|  |     position: relative; | ||||
|  |     margin-bottom: 16rpx; | ||||
|  | 
 | ||||
|  |     &:before { | ||||
|  |       content: ''; | ||||
|  |       position: absolute; | ||||
|  |       left: -8rpx; | ||||
|  |       top: 30rpx; | ||||
|  |       width: 14rpx; | ||||
|  |       height: 14rpx; | ||||
|  |       border-radius: 50%; | ||||
|  |       background-color: #e2e8f0; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     &.is-current { | ||||
|  |       border-left-color: #007aff; | ||||
|  | 
 | ||||
|  |       &:before { | ||||
|  |         background-color: #007aff; | ||||
|  |         box-shadow: 0 0 0 4rpx rgba(0, 122, 255, 0.2); | ||||
|  |       } | ||||
|  | 
 | ||||
|  |       .trace-time, | ||||
|  |       .trace-status { | ||||
|  |         color: #007aff; | ||||
|  |         font-weight: 600; | ||||
|  |       } | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     &:last-child { | ||||
|  |       border-left-color: transparent; | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | .trace-time { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #999; | ||||
|  |   margin-bottom: 8rpx; | ||||
|  |   min-width: 120rpx; | ||||
|  |   flex-shrink: 0; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .trace-content { | ||||
|  |   flex: 1; | ||||
|  |   margin-left: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .trace-status { | ||||
|  |   font-size: 26rpx; | ||||
|  |   color: #333; | ||||
|  |   margin-bottom: 6rpx; | ||||
|  |   font-weight: 500; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .trace-location { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #666; | ||||
|  |   margin-bottom: 4rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .trace-remark { | ||||
|  |   font-size: 22rpx; | ||||
|  |   color: #999; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 空状态 | ||||
|  | .empty-trace { | ||||
|  |   text-align: center; | ||||
|  |   padding: 80rpx 40rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .empty-image { | ||||
|  |   width: 200rpx; | ||||
|  |   height: 200rpx; | ||||
|  |   margin-bottom: 30rpx; | ||||
|  |   opacity: 0.6; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .empty-text { | ||||
|  |   font-size: 28rpx; | ||||
|  |   color: #999; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 联系供应商 | ||||
|  | .contact-section { | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 30rpx; | ||||
|  |   margin-bottom: 20rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .contact-card { | ||||
|  |   display: flex; | ||||
|  |   align-items: center; | ||||
|  |   justify-content: space-between; | ||||
|  |   background-color: #f8f9fa; | ||||
|  |   border-radius: 12rpx; | ||||
|  |   padding: 24rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .supplier-info { | ||||
|  |   flex: 1; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .supplier-name { | ||||
|  |   font-size: 28rpx; | ||||
|  |   color: #333; | ||||
|  |   font-weight: 600; | ||||
|  |   margin-bottom: 8rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .supplier-phone { | ||||
|  |   font-size: 24rpx; | ||||
|  |   color: #666; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .contact-btn { | ||||
|  |   padding: 12rpx 24rpx; | ||||
|  |   border-radius: 20rpx; | ||||
|  |   font-size: 24rpx; | ||||
|  |   background-color: #007aff; | ||||
|  |   color: #fff; | ||||
|  |   border: none; | ||||
|  | } | ||||
|  | 
 | ||||
|  | // 订单操作 | ||||
|  | .order-actions { | ||||
|  |   position: fixed; | ||||
|  |   bottom: 0; | ||||
|  |   left: 0; | ||||
|  |   right: 0; | ||||
|  |   background-color: #fff; | ||||
|  |   padding: 20rpx 30rpx; | ||||
|  |   padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); | ||||
|  |   border-top: 1rpx solid #eee; | ||||
|  |   display: flex; | ||||
|  |   gap: 16rpx; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .action-btn { | ||||
|  |   flex: 1; | ||||
|  |   padding: 20rpx 0; | ||||
|  |   border-radius: 10rpx; | ||||
|  |   font-size: 28rpx; | ||||
|  |   font-weight: 600; | ||||
|  |   border: none; | ||||
|  |   text-align: center; | ||||
|  | 
 | ||||
|  |   &.confirm-btn { | ||||
|  |     background-color: #48bb78; | ||||
|  |     color: #fff; | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   &.secondary-btn { | ||||
|  |     background-color: #f5f5f5; | ||||
|  |     color: #666; | ||||
|  |     border: 1rpx solid #ddd; | ||||
|  |   } | ||||
|  | } | ||||
|  | </style> | ||||
					Loading…
					
					
				
		Reference in new issue