<template> <view class="flex-row relative page"> <view class="flex-row justify-center items-center section_2 pos"> <image class="image" src="https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FVrgKnxCu-sousuo.png" /> <text class="font text ml-4">搜索订单</text> </view> <view class="flex-col section_44"> <view class="flex-row justify-between self-stretch groupp"> <view class="font_22" :class="{ active: orderStatus === '全部', selected: isSelected('全部') }" @click="changeTab('全部')"> 全部 </view> <view class="font_22" :class="{ active: orderStatus === '待支付', selected: isSelected('待支付') }" @click="changeTab('待支付')"> 待支付 </view> <view class="font_22" :class="{ active: orderStatus === '待发货', selected: isSelected('待发货') }" @click="changeTab('待发货')"> 待发货 </view> <view class="font_22" :class="{ active: orderStatus === '待收货', selected: isSelected('待收货') }" @click="changeTab('待收货')"> 已发货 </view> <view class="font_22" :class="{ active: orderStatus === '已退款', selected: isSelected('已退款') }" @click="changeTab('已退款')"> 售后/退款 </view> </view> <view class="flex-col pos_8"> <view class="flex-col section_4 list-item_1 mt-14" v-for="(order, index) in Status.displayedOrders" :key="order.id" @click="goToText(order)"> <view class="flex-col"> <view class="flex-row items-center self-stretch mt-2" style="display: flex; justify-content: space-between;"> <view> <text class="font_4">订单编号:</text> <text class="font_5 ml-5">{{order.orderNumber}}</text> </view> <view style="width: 150rpx; display: flex; justify-content: space-between;"> <view><text v-if="order.orderStatus === '待支付'" class="font_status text_5">{{ order.countdown }}</text></view> <view><text class="font_status text_5">{{ order.orderStatus }}</text></view> </view> </view> </view> <view class="flex-col group"> <view class="flex-row justify-between list-item group_3" v-for="(item,goodIndex) in order.orderItemList" :key="goodIndex"> <view class="flex-row"> <image class="image_2" :src="item.goodSnapshot.goodImg.split(';')[0]" /> <view class="flex-col self-start group_1 ml-18"> <view class="flex-row self-stretch"> <text class="font">{{ item.goodSnapshot.name }}</text> <text class="font text_10">【{{ item.goodSnapshot.type }}】</text> </view> <text class="self-start font_7 text_12 mt-36">x{{ item.quantity }}</text> </view> </view> <view class="flex-row items-center self-start group_2"> ¥ {{ item.goodSnapshot.price }} </view> </view> </view> <view class="divider view_1"></view> <!-- <view class="flex-row justify-end group_5"> <view v-if="order.orderStatus==='待支付'" class="font text_18">去支付</view> <view v-if="order.orderStatus==='待发货'" class="font text_18">取消订单</view> <view v-if="order.orderStatus==='已发货'" class="font text_18">确认收货</view> <view v-if="order.orderStatus==='已退款'" class="font text_18">售后详情</view> </view> --> <view class="flex-row justify-end items-center view"> <text class="font_9 text_16">总金额:</text> <image class="image_4 image_5" src="https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FJmxvlQvD-rmbpink.png" /> <text class="font_8 text_17">{{order.totalAmount}}</text> </view> <!-- <view class="flex-row justify-end group_7"> --> <!-- <view class="flex-col justify-start items-center text-wrapper"><text class="font text_18">删除记录</text></view> <view class="flex-col justify-start items-center text-wrapper_2 ml-14" v-if="order.orderStatus==='待支付'"> <text class="font_3">去支付</text> </view> <view class="flex-col justify-start items-center text-wrapper_2 ml-14" v-if="order.orderStatus==='待发货'"> <text class="font_3">取消订单</text> </view> <view class="flex-col justify-start items-center text-wrapper_2 ml-14" v-if="order.orderStatus==='已发货'"> <text class="font_3">确认收货</text> </view> <view class="flex-col justify-start items-center text-wrapper_2 ml-14" v-if="order.orderStatus==='已退款'"> <text class="font_3">已退款</text> </view> --> <!-- </view> --> <view @click.stop> <view class="flex-row justify-end group_7" v-if="order.orderStatus==='待支付'"> <view class="flex-col justify-start items-center text-wrapper" @click="cancelOrder(order)"><text class="font text_18">取消订单</text></view> <view class="flex-col justify-start items-center text-wrapper_2 ml-14" @click="wxPayFd(order)"> <text class="font_3">去支付</text> </view> </view> <view class="flex-row justify-end group_7" v-if="order.orderStatus==='待发货'"> <view class="flex-col justify-start items-center text-wrapper_2 ml-14"> <text class="font_3">联系客服</text> </view> </view> <view class="flex-row justify-end group_7" v-if="order.orderStatus==='待收货'"> <view class="flex-col justify-start items-center text-wrapper_2 ml-14" @click="viewLogistics(order.id)"> <text class="font_3">查看物流</text> </view> <view class="flex-col justify-start items-center text-wrapper ml-14" @click="confirm()"> <text class="font">确认收货</text> </view> </view> <view class="flex-row justify-end group_7" v-if="order.orderStatus==='已退款' || order.orderStatus === '交易关闭'"> <view class="flex-col justify-start items-center text-wrapper" @click="deleteOrder()"><text class="font text_18">删除订单</text></view> </view> </view> </view> </view> </view> </view> <!-- 遮罩层 --> <view v-if="isShow" class="overlay"></view> </template> <script setup> import { ref,onMounted,toRaw, onBeforeUnmount } from 'vue'; import { baseUrl } from '@/api/request'; import { onLoad } from "@dcloudio/uni-app"; const Status = ref({ orderStatus: '全部', orders: [], displayedOrders: [], }) const orderStatus = '' //订单状态 const currentColor = ref(0); var plugin = requirePlugin('logisticsPlugin') //微信插件 let waybillToken = '' //物流信息唯一标识符 const isSelected = (tab) => Status.value.orderStatus === tab onMounted(async () => { await Getorder() if (Status.value.orderStatus === '全部') { Status.value.displayedOrders = Status.value.orders; console.log('Status.value.displayedOrders--->',Status.value.displayedOrders); } else { Status.value.displayedOrders = Status.value.orders.filter((order) => { switch (Status.value.orderStatus) { case '待支付': return order.orderStatus === '待支付' case '待发货': return order.orderStatus === '待发货' case '已发货': return order.orderStatus === '待收货' case '待收货': return order.orderStatus === '已退款' default: return false; } }) } getFonts() }) const userInfo = wx.getStorageSync('userInfo') const Getorder = async () => { const res = await uni.request({ url: baseUrl + '/order/list', method: 'POST', header: { cookie: wx.getStorageSync('cookie') } }) if (res.data.code === 1) { Status.value.orders = res.data.data Status.value.orders.forEach((order) => { //会导致前端爆很多警告 startCountdown(order) }) // console.log('Status.value.orders--->',Status.value.orders); } else { console.log('没拿到用户数据') } } const zt = ref({ tab:'' }) onLoad((options)=>{ zt.value.tab = JSON.parse(options.zt) changeTab(zt.value.tab) }) const changeTab = (tab) => { if (tab === '全部') { Status.value.displayedOrders = Status.value.orders; Status.value.orderStatus = '全部'; } else { Status.value.displayedOrders = Status.value.orders.filter((order) => { switch (tab) { case '待支付': return order.orderStatus === '待支付'; case '待发货': return order.orderStatus === '待发货'; case '待收货': return order.orderStatus === '待收货'; case '已退款': return order.orderStatus === '已退款'; default: return false; } }) Status.value.orderStatus = tab } } const goToText = (orderInfo) => { console.log('订单信息--->',orderInfo); if(orderInfo.orderType === 'product') { uni.navigateTo({ url: '../../../pages/order/product-paysuccess/product-paysuccess?oid=' + JSON.stringify(orderInfo.id) }) } else { uni.navigateTo({ url: '../../../pages/order/service-paystatus/service-paystatus?oid=' + JSON.stringify(orderInfo.id) }) } } const cancelOrder = async (order) => { //取消订单 console.log(order); uni.showModal({ title: '提示', content: '确定要取消订单吗?', success:(e) => { if(e.confirm) { postCancelOrder(order) } else if(e.cancel) { return; } } }) } const wxPay = async( oid )=> { //传入订单id try { const res = await uni.request({ url: baseUrl + '/wechat/payment/create', method: 'POST', header: { 'cookie': wx.getStorageSync("cookie") }, data: { id: oid } }) const paymentData = res.data.data wx.requestPayment({ appid: paymentData.appId, nonceStr: paymentData.nonceStr, package: paymentData.packageVal, paySign: paymentData.paySign, timeStamp: paymentData.timeStamp, signType: paymentData.signType, success(res) { uni.showModal({ content: '支付成功', showCancel: false }) uni.redirectTo({ url: '/pages/order/product-paysuccess/product-paysuccess?oid=' + JSON.stringify(oid) }) console.log('支付成功res--->',res); }, fail(e) { // uni.showModal({ // content: '支付失败,原因为:' + e.errMsg, // showCancel: false // }) // console.log('e.errMsg--->',e.errMsg); } }) }catch(error) { console.error('支付请求失败',error); uni.showModal({ content: '支付请求失败,请重试。', showCancel: false }) } } const postCancelOrder = async(order)=>{ //向后端发送取消订单请求 if(order.addressSnapshot != null) { const res = await uni.request({ url: baseUrl + '/order/cancel/id', method: 'POST', header: { cookie: wx.getStorageSync('cookie') }, data: { id: order.id } }) console.log('取消订单的信息--->',res.data); if(res.data.code === 1) { Getorder() //成功请求后获取订单信息 uni.redirectTo({ url: '/pages/mine/mineorders/mineorders?zt=' + JSON.stringify(Status.value.orderStatus) }) } } else { const res = await uni.request({ url: baseUrl + '/order/cancel/service/id', method: 'POST', header: { cookie: wx.getStorageSync('cookie') }, data: { id: order.id } }) console.log('取消订单的信息--->',res.data); if(res.data.code === 1) { Getorder() //成功请求后获取订单信息 uni.redirectTo({ url: '/pages/mine/mineorders/mineorders?zt=' + JSON.stringify(Status.value.orderStatus) }) } } } //查看物流方法 const viewLogistics = ( oid )=>{ // console.log('订单编号--->',oid); uni.request({ url: baseUrl + '/logistics/get/info', method: 'POST', data: { id: oid }, header: { 'cookie': wx.getStorageSync("cookie") }, success: (res) => { console.log(res.data.data) waybillToken = res.data.data.waybill_token plugin.openWaybillTracking({ waybillToken: waybillToken }) } }) } const deleteOrder = async () => { //删除订单方法 console.log('删除订单方法'); } //获取字体 const getFonts =()=>{ uni.loadFontFace({ family: 'FangZhengFonts', source: `url("https://carbon2.obs.cn-north-4.myhuaweicloud.com/fonts/FangZhengFonts.TTF")`, success:(res) =>{ console.log('success',res); }, fail:(err) => { console.log('err',err); } }) } const confirm =()=> { //确认收货方法 console.log('确认收货方法'); } //防抖相关变量 let debounceTimer = null; let wxPayTimer = null; let loading = false; let isLoading = ref(false) let isShow = ref(false) const wxPayFd = (order) => { //微信支付按钮防抖 clearTimeout(wxPayTimer) showLoading() isShow.value = true //打开遮罩 wxPayTimer = setTimeout(async () => { await wxPay(order.id) }, 1000) setTimeout(()=>{ hideLoading() isShow.value = false //关闭遮罩 },2000) } function showLoading() { //加载弹窗 if (!loading) { wx.showLoading({ title: '加载中...', }); loading = true; isLoading.value = true } } function hideLoading() { //关闭弹窗 if (loading) { wx.hideLoading(); loading = false; isLoading.value = false } } // 时间格式化函数,处理后端返回的时间 const parseDate = (dateString) => { const [date, time] = dateString.split(' '); const [year, month, day] = date.split('-').map(Number); const [hour, minute, second] = time.split(':').map(Number); return new Date(year, month - 1, day, hour, minute, second); // JavaScript Date的月份是从0开始的 }; // 给订单创建时间加上30分钟 const add30Minutes = (createdTime) => { const date = parseDate(createdTime); date.setMinutes(date.getMinutes() + 31); // 加上30分钟 return Math.floor(date.getTime() / 1000); // 返回时间戳(秒) }; // 启动每个订单的倒计时(仅对待支付订单有效) const startCountdown = (order) => { if (order.orderStatus === '待支付') { order.endTime = add30Minutes(order.createTime); // 设置最终取消时间 order.countdownInterval = setInterval(() => { const now = Math.floor(Date.now() / 1000); // 获取当前时间的时间戳(秒) const remainingTime = order.endTime - now; if (remainingTime <= 0) { order.countdown = '00:00'; clearInterval(order.countdownInterval); // 清除定时器 Getorder() // uni.showModal({ // title: '提示', // content: '订单超时未支付,交易关闭', // showCancel: false // }) } else { const minutes = Math.floor(remainingTime / 60); // 计算剩余分钟 const seconds = remainingTime % 60; // 计算剩余秒数 order.countdown = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`; } }, 1000); } }; // 在组件挂载时启动待支付订单的倒计时 // 在组件卸载时清除所有定时器,避免内存泄漏 onBeforeUnmount(() => { Status.value.orders.forEach(order => { if (order.countdownInterval) { clearInterval(order.countdownInterval); } }); }); </script> <style lang="scss" scoped> .overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.4); /* 半透明黑色背景 */ z-index: 999; } .groupp { padding: 22.5rpx 0 18.75rpx; } .section_44 { padding-left: 33.75rpx; padding-right: 30rpx; width: 100%; height: 120rpx; margin-top: 80rpx; } .ml-5 { margin-left: 9.38rpx; } .font_22.selected { position: relative; } .font_22.selected::after { content: ''; position: absolute; bottom: -5px; // 调整线条距离底部的距离 left: 0; right: 0; height: 2px; // 调整线条的粗细 background-color: #f6aaa4; // 调整线条颜色 transition: all 0.3s ease; // 添加过渡效果 } .page { padding: 46.88rpx 22.5rpx 401.25rpx; background-color: #ffffff; background-image: url('https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FQfLHXSAU-feiyigongfangbeijin.png'); background-size: 100% 100%; background-repeat: no-repeat; height: 100vh; width: 100%; overflow-y: auto; overflow-x: hidden; } .section_2 { padding: 9.38rpx 0; background-color: #ffffff; border-radius: 75rpx; } .pos { position: absolute; left: 35.63rpx; right: 35.63rpx; top: 46.88rpx; } .image { width: 37.5rpx; height: 37.5rpx; } .font { font-size: 26.25rpx; font-family: FangZhengFonts; line-height: 25.54rpx; color: #323232; } .text { color: #c0c0c0; line-height: 25.84rpx; } .font_2 { font-size: 30rpx; font-family: FangZhengFonts; line-height: 28.84rpx; color: #323232; } .font_22 { font-size: 30rpx; font-family: FangZhengFonts; line-height: 27.81rpx; color: #323232; } .text_2 { line-height: 28.48rpx; } .pos_2 { position: absolute; left: 33.99rpx; top: 146.36rpx; } .text_3 { line-height: 28.24rpx; } .pos_3 { position: absolute; left: 147.66rpx; top: 146.14rpx; } .pos_4 { position: absolute; left: 295.78rpx; top: 145.78rpx; } .pos_5 { position: absolute; right: 214.22rpx; top: 145.78rpx; } .text_4 { line-height: 29.53rpx; } .pos_6 { position: absolute; right: 34.22rpx; top: 147.07rpx; } .section_3 { background-color: #ffaaa5; width: 73.13rpx; height: 5.63rpx; } .pos_7 { position: absolute; left: 30rpx; top: 182.81rpx; } .pos_8 { position: absolute; left: 22.5rpx; right: 30rpx; top: 217.5rpx; } .section_4 { padding: 34.61rpx 31rpx 31.88rpx; background-color: #ffffff; border-radius: 31.88rpx; } .list-item_1:first-child { margin-top: 0; } .list-item_1:last-child { margin-bottom: 30rpx; } .font_status { // font-size: 26.25rpx; font-family: FangZhengFonts; line-height: 25.54rpx; color: #ffaaa5; } .font_3 { font-size: 26.25rpx; font-family: FangZhengFonts; line-height: 25.54rpx; color: #ffaaa5; } .text_5 { line-height: 24.62rpx; } .font_4 { font-size: 22.5rpx; font-family: FangZhengFonts; line-height: 22.14rpx; color: #818181; } .font_5 { font-size: 22.5rpx; font-family: FangZhengFonts; line-height: 15.04rpx; color: #818181; } .group { margin-top: 29.21rpx; } .list-item:first-child { margin-top: 0; } .image_2 { border-radius: 9.38rpx; width: 146.25rpx; height: 144.38rpx; } .group_1 { margin-top: 2.33rpx; } .text_10 { line-height: 25.01rpx; } .font_7 { font-size: 26.25rpx; font-family: Open Sans; line-height: 19.29rpx; color: #323232; } .text_12 { margin-left: 5.34rpx; line-height: 18.73rpx; } .group_2 { margin-right: 8.23rpx; margin-top: 89.19rpx; } .font_6 { font-size: 33.75rpx; font-family: Open Sans; line-height: 25.54rpx; font-weight: 600; color: #323232; } .text_11 { margin-left: 25.03rpx; line-height: 24.88rpx; } .image_3 { margin-left: -90.66rpx; width: 30rpx; height: 26.25rpx; } .font_8 { font-size: 26.25rpx; font-family: Open Sans; line-height: 19.29rpx; font-weight: 600; color: #323232; } .text_13 { margin-left: 61.14rpx; } .divider { background-color: #dad2d2; height: 0.81rpx; } .view_1 { margin: 30.43rpx 28.13rpx 0 39.38rpx; } .group_5 { margin-top: 49.41rpx; padding: 0 21.21rpx; color: #ffaaa5; } .font_9 { font-size: 26.25rpx; font-family: FangZhengFonts; line-height: 25.54rpx; color: #000000; } .text_14 { line-height: 24.62rpx; } .text_15 { margin-top: 2.17rpx; line-height: 24rpx; } .view { margin-top: 19.93rpx; padding: 0 19.54rpx; } .text_16 { margin-right: 6.99rpx; line-height: 24.3rpx; } .image_4 { width: 31.88rpx; height: 30rpx; } .image_5 { margin-right: -8.29rpx; } .text_17 { color: #ffaaa5; line-height: 19.39rpx; } .group_7 { margin-top: 52.5rpx; padding: 0 9.38rpx; } .text-wrapper { padding: 13.86rpx 0 13.52rpx; background-color: #fffef8; border-radius: 75rpx; width: 155.63rpx; height: 56.25rpx; border: solid 1.88rpx #cbcbcb; } .text_18 { line-height: 25.13rpx; } .text-wrapper_2 { padding: 13.46rpx 0 13.5rpx; background-color: #fffef8; border-radius: 75rpx; width: 155.63rpx; height: 56.25rpx; border: solid 1.88rpx #ffaaa5; } .group_3 { margin-top: 15rpx; } @import url("../../../common/css/global.css"); </style>