<template> <view class="pages"> <u-navbar title="我的订单" :placeholder="true" :autoBack="false" @leftClick="leftClick" :safeAreaInsetTop="true" > </u-navbar> <view class="tabs-wrap"> <u-tabs :list="tabsList" lineColor="#EE0D0D" :current="tabsCurrent" :activeStyle="{color:'#EE0D0D','font-weight': '600','font-size':'30rpx'}" :inactiveStyle="{color:'#7F7F7F'}" itemStyle="width:18%;box-sizing:border-box;padding:20rpx 15rpx" @click="tabsClick"></u-tabs> </view> <view class="page-wrap"> <mescroll-body class="" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption"> <view class="order"> <view v-for="(item) in orderListWithClass" class="order-item" :class="item.class" @click="goOrderDetails(item)" :key="item.id"> <view class="top u-flex u-row-between"> <text>{{item.theatreName}}</text> <text>{{item.status|filterOrderState}}</text> </view> <view class="info u-flex u-col-top"> <image class="img" :src="item.performImg"></image> <view class="text"> <view class="name">{{item.performName}} - {{item.goodsName}}</view> <view class="time">{{item.performDate}} {{item.performTimeStart}}</view> <!-- <view class="position">{{item.performDate}}</view> --> <view class="statistics"> <text>共{{item.viewerNum}}张</text> <text class="label">合计:</text> <text class="price">¥{{item.realPrice}}</text> </view> </view> </view> <view class="btn-wrap u-flex u-row-right"> <view class="btn" :class="btn.class" @click.stop="clickEven(btn.fun, item)" v-for="(btn, index) in statusBtn[item.status].filter(b => !b.condition || b.condition(item))" :key="index" > {{ btn.name }} </view> </view> </view> </view> </mescroll-body> </view> <u-toast ref="uToast"></u-toast> <tabbar :tabbarIndexProps="1" /> </view> </template> <script> import tabbar from "../components/tabbar.vue"; // 引入mescroll-mixins.js import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js"; // #ifdef H5 import wxH5 from "weixin-jsapi"; // #endif export default { mixins: [MescrollMixin], // 使用mixin components:{ tabbar }, data() { return { staticUrl:this.$commonConfig.staticUrl, goodsKey:1, hasfetch:false, tabsCurrent:1, tabsList:[ {name:'全部',status:null,}, {name:'待支付',status:'0',badge:{isDot:false,value:null}}, {name:'待使用',status:'3',badge:{isDot:false,value:null}}, {name:'已完成',status:'7',badge:{isDot:false,value:null}}, {name:'已改签/已升舱',status:'10',badge:{isDot:false,value:null}}, {name:'售后',status:'4,5,6',badge:{isDot:false,value:null}} ], status:'', dataList:[], statusBtn:{// 状态(0待支付,2超时取消,3支付完成,待使用,4退款中,5己退款,6退款失败,7己使用,8己超期 9关闭) 0:[{name:'取消订单',fun:'cancelOrder',class:''},{name:'去支付',fun:'pay',class:'red'}], 1:[], 2:[], 3:[ {name:'改签',fun:'rebook',class:'',condition: (item) => item.allowReSubmit === 1}, {name:'升舱',fun:'upgrade',class:'',condition: (item) => item.allowReSubmit === 1}, {name:'查看原订单',fun:'viewOldOrder',class:'',condition: (item) => !!item.orgOrderId}, {name:'出示二维码',fun:'goOrderDetails',class:'red'}, ], //,{name:'评价',fun:'evaluate',class:'green'} 4:[], 5:[], 6:[], // ,{name:'查看评价',fun:'viewEvaluate',class:'green'} 7:[], 8:[], 9:[], 10:[{name:'查看新订单',fun:'viewNewOrder',class:'red'}] }, orderBadge:{ noPayNum:0, deliverNum:0, collectNum:0, commentNum:0, refundNum:0, }, templateIdList:[],//微信小程序订阅消息 } }, computed: { orderListWithClass() { return this.dataList.map(order => { // let spliceData = order.detailList.splice(0,2); // let moreData = order.detailList.splice(2,order.detailList.length); // let moreData = order.detailList.slice(2); // if(order.detailList.length>2){ // moreData = order.detailList; // } return { ...order, // spliceData:spliceData, // moreData:moreData, // showMore:false, class: { 0: 'status-0', 1: 'status-1', 2: 'status-2', 3: 'status-3', 4: 'status-4', 5: 'status-5', 6: 'status-6', 7: 'status-7', 8: 'status-8' }[order.status] || '' } }) } }, onLoad(page) { // console.log('page',page); const status = page.status; const index = this.tabsList.findIndex(item => item.status === status); this.tabsCurrent = index>=0?index:0; this.getTemplateIdList();//获取模板列表 }, onShow() { setTimeout(()=>{ this.hasfetch&&this.reloadList() },500); // this.statisticsOrder(); }, methods: { leftClick(){ uni.reLaunch({url: '/center/center'}); }, /*下拉刷新的回调, 重置列表为第一页 (此处可删,mixins已默认) downCallback(){ this.mescroll.resetUpScroll(); }, /*上拉加载的回调*/ upCallback(page) { // this.statisticsOrder(); // 此处可以继续请求其他接口 // if(page.num == 1){ // // 请求其他接口... // } // 如果希望先请求其他接口,再触发upCallback,可参考以下写法 // if(!this.hasTypeId){ // this.shopNewsType(); // return // 此处return,先获取xx // } let pageNum = page.num; // 页码, 默认从1开始 let pageSize = page.size; // 页长, 默认每页10条 let params = { source:1, pageNum : page.num, pageSize : page.size, statusIn : this.tabsList[this.tabsCurrent]?.status||'', userid:this.vuex_member_info.id // status : this.tabsList[this.tabsCurrent].status, } // console.log('this.params',params); this.$u.api.orderList(params).then(data => { this.hasfetch = true; console.log('data',JSON.parse(JSON.stringify(data))); // 接口返回的当前页数据列表 (数组) let curPageData = data.data.rows; // console.log('curPageData',JSON.parse(JSON.stringify(curPageData))); // 接口返回的当前页数据长度 (如列表有26个数据,当前页返回8个,则curPageLen=8) let curPageLen = curPageData.length; // 接口返回的总页数 (如列表有26个数据,每页10条,共3页; 则totalPage=3) // let totalPage = data.data.data.totalPage; // 接口返回的总数据量(如列表有26个数据,每页10条,共3页; 则totalSize=26) let totalSize = data.data.total; // 接口返回的是否有下一页 (true/false) // let hasNext = data.xxx; // console.log('totalPage',totalPage,'curPageLen',curPageLen); //设置列表数据 if(page.num == 1) this.dataList = []; //如果是第一页需手动置空列表 this.dataList = this.dataList.concat(curPageData); //追加新数据 // 请求成功,隐藏加载状态 //方法一(推荐): 后台接口有返回列表的总页数 totalPage // this.mescroll.endByPage(curPageLen, totalPage); //方法二(推荐): 后台接口有返回列表的总数据量 totalSize this.mescroll.endBySize(curPageLen, totalSize); }).catch(err => { this.mescroll.endErr() console.log(err) }); }, /*若希望重新加载列表,只需调用此方法即可(内部会自动page.num=1,再主动触发up.callback)*/ reloadList() { this.mescroll.resetUpScroll(); }, tabsClick(item){ // this.status = item.status; this.tabsCurrent = item.index; this.reloadList() // console.log('item',item); }, goOrderDetails(item){ uni.$u.route('/center/orderdetails', { id: item.id }); }, toggleMore(item,index){ // console.log('toggleMore',item); this.orderListWithClass[index].showMore = !this.orderListWithClass[index].showMore this.goodsKey++; }, clickEven(fun,item){ // console.log('fun',fun); let funObj = { pay: this.pay, goOrderDetails:this.goOrderDetails, evaluate:this.evaluate, refund:this.refund, cancelOrder:this.cancelOrder, viewRefund:this.viewRefund, confirmReceipt:this.confirmReceipt, viewEvaluate:this.viewEvaluate, rebook:this.rebook, upgrade:this.upgrade, viewNewOrder:this.viewNewOrder, viewOldOrder:this.viewOldOrder, }; // console.log('funObj[fun]',funObj[fun]); if (fun in funObj) { funObj[fun](item); } }, getTemplateIdList(){ this.$u.api.templateIdList({templateLabel:'order_pay'}).then(res=>{ console.log('getTemplateIdList',res.data); this.templateIdList = res.data.list.map(item=>{ return item.templateId }); // if(this.templateIdList.length>0){ // this.templateEven(); // } }).catch(err=>{ console.log('getTemplateIdList',err); }) }, pay(item){ console.log('pay',item); // #ifdef H5 this.gotoPay(item.id); // #endif // #ifdef MP this.setTemplate(item.id); // #endif // uni.$u.route('/shopping/pay', { // orderId: item.id, // // openid: that.vuex_wechatOpenid, // payAmount:item.orderPrice // }); }, evaluate(item){ // console.log('logistics',item); uni.$u.route('/shopping/evaluate', { id: item.id }); }, comment(orderId,orderDetailId,goodsId){ uni.$u.route('/shopping/addcomment', { orderId, orderDetailId, goodsId }); }, viewComment(orderDetailId,goodsId,goods){ uni.$u.route('/shopping/viewcomment', { orderDetailId, goodsId, goods:JSON.stringify(goods) }); }, refund(item){ // console.log('logistics',item); uni.$u.route('/shopping/refund', { id: item.id }); }, cancelOrder(item){ let that = this; uni.showModal({ title: '提示', content: '确认取消吗!', success: res => { if (res.confirm) { this.$u.api.cancelOrder({orderId:item.id}).then(res=>{ this.$refs.uToast.show({ message:res.msg, complete() { that.reloadList(); } }); // uni.$u.toast(res.msg); console.log('res',res.data); }).catch(err=>{ console.log('cancelOrder',err); }) } } }); // console.log('logistics',item); }, viewRefund(item){ uni.$u.route('/center/viewRefund', { orderId: item.id }); }, confirmReceipt(item){ let that = this; uni.showModal({ title: '提示', content: '确认收货吗!', success: res => { if (res.confirm) { this.$u.api.confirmReceipt({orderId:item.id}).then(res=>{ uni.showToast({ title:res.msg, duration:2000, complete() { that.reloadList(); } }); console.log('res',res.data); }).catch(err=>{ console.log('confirmReceipt',err); }) } } }) }, viewEvaluate(item){ uni.$u.route('/shopping/orderdetails', { id: item.id }); }, rebook(item){ // console.log('rebook',item); uni.$u.route('pages/ticketlist',{performId:item.performId,orderId:item.id,fromPage:'rebook'}) }, upgrade(item){ uni.$u.route('pages/ticketlist',{performId:item.performId,orderId:item.id,fromPage:'rebook',isUpgrade:true}) }, viewOldOrder(item){ console.log('viewOldOrder',item.orgOrderId); uni.$u.route('/center/orderdetails', { id: item.orgOrderId }); }, viewNewOrder(item){ console.log('viewNewOrder',item.newOrderId); uni.$u.route('/center/orderdetails', { id: item.newOrderId }); }, // 设置小程序订阅消息 setTemplate(orderId) { let that = this; console.log('templateIdList',this.templateIdList); uni.requestSubscribeMessage({ tmplIds: that.templateIdList, success (res) { // that.gotoPay(); console.log("success:",res); }, fail (res) { console.log("fail:",res); }, complete (res) { that.gotoPay(orderId); console.log("complete:",res); } }) }, gotoPay(orderId){ this.$u.api.gotoPay({orderId:orderId,openid:''}).then(res=>{ this.payResult = res.data.payInfo; this.payResult.package = res.data.payInfo.packageValue; // #ifdef H5 this.initConfig(this.payResult) // #endif // #ifdef MP this.wxPay() // #endif // if(this.params.paymentMode==1||this.params.paymentMode==4){ // this.wxPay() // }else{ // uni.$u.route('/shopping/paysuccess'); // } console.log('gotoPayres',res.data); }).catch(err=>{ this.paypass = ''; this.checkPassShow = false; console.log('gotoPay',err); }) }, wxPay(){ let that = this; uni.requestPayment({ ... this.payResult, "provider": "wxpay", "orderInfo": { // "appid": "wx499********7c70e", // 微信开放平台 - 应用 - AppId,注意和微信小程序、公众号 AppId 可能不一致 // "noncestr": "c5sEwbaNPiXAF3iv", // 随机字符串 // "package": "Sign=WXPay", // 固定值 // "partnerid": "148*****52", // 微信支付商户号 // "prepayid": "wx202254********************fbe90000", // 统一下单订单号 // "timestamp": 1597935292, // 时间戳(单位:秒) // "sign": "A842B45937F6EFF60DEC7A2EAA52D5A0" // 签名,这里用的 MD5/RSA 签名 }, success(res) { setTimeout(()=>{ this.tabsCurrent = 2; this.reloadList(); },1500) // that.payQuery(); }, fail(e) { console.log('wxPayfail',e); } }) }, payQuery(){ let that = this; let retryCount = 0; let maxRetryCount = 5; // 设置最大重试次数 let interval = 2000; // 设置间隔时间为2秒 let timeout = 10000; // 设置超时时间为10秒 let timer; uni.showLoading({ title:'支付结果查询中' }) timer = setInterval(() => { retryCount++; if (retryCount > maxRetryCount || retryCount * interval > timeout) { clearInterval(timer); uni.hideLoading(); console.log("支付查询超时或达到最大重试次数"); // 在这里添加超时或达到最大重试次数的处理逻辑 this.reloadList() } else { console.log("第" + retryCount + "次查询"); // 调用查询支付状态的方法 // 如果支付状态为成功,则清除定时器并处理成功的逻辑 // 如果支付状态为失败,则清除定时器并处理失败的逻辑 this.$u.api.payQuery({orderId:this.orderId}).then(res=>{ // 0-未支付 1-已支付 2-支付中 3-支付失败 4-支付退款 let payStatus = res.data.payStatus; if(payStatus===1){ uni.$u.route('/center/paysuccess'); }else if(payStatus===0||payStatus===2){ this.payQuery() }else if(payStatus===3){ uni.toast('支付失败') } clearInterval(timer); }).catch(err=>{ console.log('payQuery',err); }).finally(()=>{ uni.hideLoading() }) } }, interval); }, statisticsOrder(){ this.$u.api.statisticsOrder().then(res=>{ let data = res.data || {}; this.orderBadge = Object.assign(this.orderBadge,data); let {noPayNum,deliverNum,collectNum,commentNum,refundNum} = res.data; let noPayNumindex = this.tabsList.findIndex(item => item.status == 0); this.tabsList[1].badge.isDot = false; this.tabsList[1].badge.value = noPayNum; this.tabsList[2].badge.isDot = false; this.tabsList[2].badge.value = deliverNum; this.tabsList[3].badge.isDot = false; this.tabsList[3].badge.value = collectNum; this.tabsList[4].badge.isDot = false; this.tabsList[4].badge.value = commentNum; this.tabsList[5].badge.isDot = false; this.tabsList[5].badge.value = refundNum; // console.log('statisticsOrder',res.data); // console.log('this.orderBadge',this.orderBadge); }).catch(err=>{ console.log('memberInfo',err.data); }) }, /** * 公众号微信支付 */ initConfig() { // #ifdef H5 let that = this wxH5.config({ debug: false, // 这里一般在测试阶段先用ture,等打包给后台的时候就改回false, appId: that.payResult.appId, // 必填,公众号的唯一标识 timestamp: that.payResult.timeStamp, // 必填,生成签名的时间戳 nonceStr: that.payResult.nonceStr, // 必填,生成签名的随机串 signature: that.payResult.paySign, // 必填,签名 jsApiList: ['chooseWXPay', 'checkJsApi'] // 必填,需要使用的JS接口列表 }) wxH5.ready(() => { wxH5.chooseWXPay({ timestamp: that.payResult.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 nonceStr: that.payResult.nonceStr, // 支付签名随机串,不长于 32 位 package: that.payResult.packageValue, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*) signType: 'SHA1', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' paySign: that.payResult.paySign, // 支付签名 success: () => { setTimeout(()=>{ that.tabsCurrent = 2; that.reloadList(); },1500) // that.payQuery(); }, fail: (e) => { uni.$u.route('/center/order', { status: 0 }); console.log('wxPayfail', e); }, cancel: () => { uni.$u.route('/center/order', { status: 0 }); that.cansubmit = true; } }) }) // #endif } } } </script> <style> page{ background-color: #F5F5F5; } </style> <style lang="scss" scoped> .tabs-wrap{ background-color: #fff; margin-bottom: 10rpx; ::v-deep .u-tabs__wrapper__nav__item:nth-child(5){ width: 240rpx!important; } } .list-item{ overflow: hidden; width: 48%; margin-bottom: 30rpx; background-color: #fff; .image-wrap{ margin-bottom: 20rpx; } } .order-item{ margin-bottom: 20rpx; background: #FFFFFF; box-shadow: 0rpx 2rpx 12rpx 0rpx rgba(221,221,221,0.5); border-radius: 20rpx; padding: 32rpx; content-visibility: auto; contain-intrinsic-size: 346rpx; .top{ font-size: 24rpx; font-weight: 400; color: #7F7F7F; line-height: 36rpx; margin-bottom: 36rpx; } .info{ margin-bottom: 30rpx; .img{ width: 180rpx; height: 160rpx; border-radius: 12rpx; } .text{ font-size: 24rpx; font-weight: 400; color: #7F7F7F; padding-left: 26rpx; flex: 1; .name{ font-size: 28rpx; font-weight: bold; color: #363636; margin-bottom: 20rpx; } .time{ margin-bottom: 20rpx; } .position{ margin-bottom: 20rpx; } .statistics{ text-align: right; } .label{ font-size: 24rpx; font-weight: 400; color: #363636; margin-left: 10rpx; } .price{ font-size: 32rpx; font-weight: bold; color: #ED0000; } } } .btn-wrap{ } .btn{ padding: 12rpx 40rpx; border: 1px solid #E5E5E5; color: #7F7F7F; text-align: center; border-radius: 8rpx; font-size: 24rpx; &.red{border-color: #ED0000;color: #ED0000;} &.red.solid{border-color: #ED0000;background-color:#ED0000;color: #fff;} &.green{color: #00A447;border-color: #00A447;} &:not(:first-child){ margin-left: 20rpx; } } &.status-0{.status{color:#FF3C3F;}} &.status-1{.status{color:#FF3C3F;}} &.status-2{.status{color:#0099EB;}} &.status-3{.status{color:#00A447;}} &.status-4{.status{color:#FF3C3F;}} &.status-5{.status{color:#FF3C3F;}} &.status-6{.status{color:#FF3C3F;}} &.status-7{.status{color:#FFB100;}} } </style>