order.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. <template>
  2. <view class="pages">
  3. <u-navbar
  4. title="我的订单"
  5. :placeholder="true"
  6. :autoBack="false"
  7. @leftClick="leftClick"
  8. :safeAreaInsetTop="true"
  9. >
  10. </u-navbar>
  11. <view class="tabs-wrap">
  12. <u-tabs
  13. :list="tabsList"
  14. lineColor="#EE0D0D"
  15. :current="tabsCurrent"
  16. :activeStyle="{color:'#EE0D0D','font-weight': '600','font-size':'30rpx'}"
  17. :inactiveStyle="{color:'#7F7F7F'}"
  18. itemStyle="width:20%;box-sizing:border-box;padding:24rpx"
  19. @click="tabsClick"></u-tabs>
  20. </view>
  21. <view class="page-wrap">
  22. <mescroll-body class="" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
  23. <view class="order">
  24. <view v-for="(item,index) in orderListWithClass" class="order-item"
  25. :class="item.class"
  26. @click="goOrderDetails(item)" :key="item.id">
  27. <view class="top u-flex u-row-between">
  28. <text>{{item.theatreName}}</text>
  29. <text>{{item.status|filterOrderState}}</text>
  30. </view>
  31. <view class="info u-flex u-col-top">
  32. <image class="img" :src="item.performImg"></image>
  33. <view class="text">
  34. <view class="name">{{item.performName}} - {{item.goodsName}}</view>
  35. <view class="time">{{item.performDate}} {{item.performTimeStart}}</view>
  36. <!-- <view class="position">{{item.performDate}}</view> -->
  37. <view class="statistics">
  38. <text>共{{item.viewerNum}}张</text>
  39. <text class="label">合计:</text>
  40. <text class="price">¥{{item.realPrice}}</text>
  41. </view>
  42. </view>
  43. </view>
  44. <view class="btn-wrap u-flex u-row-right">
  45. <view
  46. class="btn"
  47. :class="btn.class"
  48. @click.stop="clickEven(btn.fun,item)"
  49. v-for="(btn,index) in statusBtn[item.status]" :key="index">
  50. {{btn.name}}
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </mescroll-body>
  56. </view>
  57. <u-toast ref="uToast"></u-toast>
  58. <tabbar :tabbarIndexProps="1" />
  59. </view>
  60. </template>
  61. <script>
  62. import tabbar from "../components/tabbar.vue";
  63. // 引入mescroll-mixins.js
  64. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  65. export default {
  66. mixins: [MescrollMixin], // 使用mixin
  67. components:{
  68. tabbar
  69. },
  70. data() {
  71. return {
  72. staticUrl:this.$commonConfig.staticUrl,
  73. goodsKey:1,
  74. hasfetch:false,
  75. tabsCurrent:1,
  76. tabsList:[
  77. {name:'全部',status:null,},
  78. {name:'待支付',status:'0',badge:{isDot:false,value:null}},
  79. {name:'待使用',status:'3',badge:{isDot:false,value:null}},
  80. {name:'已完成',status:'7',badge:{isDot:false,value:null}},
  81. {name:'售后',status:'4,5,6',badge:{isDot:false,value:null}}
  82. ],
  83. status:'',
  84. dataList:[],
  85. statusBtn:{// 状态(0待支付,2超时取消,3支付完成,待使用,4退款中,5己退款,6退款失败,7己使用,8己超期 9关闭)
  86. 0:[{name:'取消订单',fun:'cancelOrder',class:''},{name:'去支付',fun:'pay',class:'red'}],
  87. 1:[],
  88. 2:[],
  89. 3:[{name:'出示二维码',fun:'goOrderDetails',class:'red'}],
  90. //,{name:'评价',fun:'evaluate',class:'green'}
  91. 4:[],
  92. 5:[],
  93. 6:[],
  94. // ,{name:'查看评价',fun:'viewEvaluate',class:'green'}
  95. 7:[],
  96. 8:[],
  97. 9:[]
  98. },
  99. orderBadge:{
  100. noPayNum:0,
  101. deliverNum:0,
  102. collectNum:0,
  103. commentNum:0,
  104. refundNum:0,
  105. },
  106. }
  107. },
  108. computed: {
  109. orderListWithClass() {
  110. return this.dataList.map(order => {
  111. // let spliceData = order.detailList.splice(0,2);
  112. // let moreData = order.detailList.splice(2,order.detailList.length);
  113. // let moreData = order.detailList.slice(2);
  114. // if(order.detailList.length>2){
  115. // moreData = order.detailList;
  116. // }
  117. return {
  118. ...order,
  119. // spliceData:spliceData,
  120. // moreData:moreData,
  121. // showMore:false,
  122. class: {
  123. 0: 'status-0',
  124. 1: 'status-1',
  125. 2: 'status-2',
  126. 3: 'status-3',
  127. 4: 'status-4',
  128. 5: 'status-5',
  129. 6: 'status-6',
  130. 7: 'status-7',
  131. 8: 'status-8'
  132. }[order.status] || ''
  133. }
  134. })
  135. }
  136. },
  137. onLoad(page) {
  138. // console.log('page',page);
  139. const status = page.status;
  140. const index = this.tabsList.findIndex(item => item.status === status);
  141. this.tabsCurrent = index>=0?index:0;
  142. },
  143. onShow() {
  144. setTimeout(()=>{
  145. this.hasfetch&&this.reloadList()
  146. },500);
  147. // this.statisticsOrder();
  148. },
  149. methods: {
  150. leftClick(){
  151. uni.reLaunch({url: '/center/center'});
  152. },
  153. /*下拉刷新的回调, 重置列表为第一页 (此处可删,mixins已默认)
  154. downCallback(){
  155. this.mescroll.resetUpScroll();
  156. },
  157. /*上拉加载的回调*/
  158. upCallback(page) {
  159. // this.statisticsOrder();
  160. // 此处可以继续请求其他接口
  161. // if(page.num == 1){
  162. // // 请求其他接口...
  163. // }
  164. // 如果希望先请求其他接口,再触发upCallback,可参考以下写法
  165. // if(!this.hasTypeId){
  166. // this.shopNewsType();
  167. // return // 此处return,先获取xx
  168. // }
  169. let pageNum = page.num; // 页码, 默认从1开始
  170. let pageSize = page.size; // 页长, 默认每页10条
  171. let params = {
  172. pageNum : page.num,
  173. pageSize : page.size,
  174. statusIn : this.tabsList[this.tabsCurrent]?.status||'',
  175. userid:this.vuex_member_info.id
  176. // status : this.tabsList[this.tabsCurrent].status,
  177. }
  178. // console.log('this.params',params);
  179. this.$u.api.orderList(params).then(data => {
  180. this.hasfetch = true;
  181. console.log('data',JSON.parse(JSON.stringify(data)));
  182. // 接口返回的当前页数据列表 (数组)
  183. let curPageData = data.data.rows;
  184. // console.log('curPageData',JSON.parse(JSON.stringify(curPageData)));
  185. // 接口返回的当前页数据长度 (如列表有26个数据,当前页返回8个,则curPageLen=8)
  186. let curPageLen = curPageData.length;
  187. // 接口返回的总页数 (如列表有26个数据,每页10条,共3页; 则totalPage=3)
  188. // let totalPage = data.data.data.totalPage;
  189. // 接口返回的总数据量(如列表有26个数据,每页10条,共3页; 则totalSize=26)
  190. let totalSize = data.data.total;
  191. // 接口返回的是否有下一页 (true/false)
  192. // let hasNext = data.xxx;
  193. // console.log('totalPage',totalPage,'curPageLen',curPageLen);
  194. //设置列表数据
  195. if(page.num == 1) this.dataList = []; //如果是第一页需手动置空列表
  196. this.dataList = this.dataList.concat(curPageData); //追加新数据
  197. // 请求成功,隐藏加载状态
  198. //方法一(推荐): 后台接口有返回列表的总页数 totalPage
  199. // this.mescroll.endByPage(curPageLen, totalPage);
  200. //方法二(推荐): 后台接口有返回列表的总数据量 totalSize
  201. this.mescroll.endBySize(curPageLen, totalSize);
  202. }).catch(err => {
  203. this.mescroll.endErr()
  204. console.log(err)
  205. });
  206. },
  207. /*若希望重新加载列表,只需调用此方法即可(内部会自动page.num=1,再主动触发up.callback)*/
  208. reloadList() {
  209. this.mescroll.resetUpScroll();
  210. },
  211. tabsClick(item){
  212. // this.status = item.status;
  213. this.tabsCurrent = item.index;
  214. this.reloadList()
  215. // console.log('item',item);
  216. },
  217. goOrderDetails(item){
  218. uni.$u.route('/center/orderdetails', {
  219. id: item.id
  220. });
  221. },
  222. toggleMore(item,index){
  223. // console.log('toggleMore',item);
  224. this.orderListWithClass[index].showMore = !this.orderListWithClass[index].showMore
  225. this.goodsKey++;
  226. },
  227. clickEven(fun,item){
  228. // console.log('fun',fun);
  229. let funObj = {
  230. pay: this.pay,
  231. goOrderDetails:this.goOrderDetails,
  232. evaluate:this.evaluate,
  233. refund:this.refund,
  234. cancelOrder:this.cancelOrder,
  235. viewRefund:this.viewRefund,
  236. confirmReceipt:this.confirmReceipt,
  237. viewEvaluate:this.viewEvaluate
  238. };
  239. // console.log('funObj[fun]',funObj[fun]);
  240. if (fun in funObj) {
  241. funObj[fun](item);
  242. }
  243. },
  244. pay(item){
  245. console.log('pay',item);
  246. this.gotoPay(item.id);
  247. // uni.$u.route('/shopping/pay', {
  248. // orderId: item.id,
  249. // // openid: that.vuex_wechatOpenid,
  250. // payAmount:item.orderPrice
  251. // });
  252. },
  253. evaluate(item){
  254. // console.log('logistics',item);
  255. uni.$u.route('/shopping/evaluate', {
  256. id: item.id
  257. });
  258. },
  259. comment(orderId,orderDetailId,goodsId){
  260. uni.$u.route('/shopping/addcomment', {
  261. orderId,
  262. orderDetailId,
  263. goodsId
  264. });
  265. },
  266. viewComment(orderDetailId,goodsId,goods){
  267. uni.$u.route('/shopping/viewcomment', {
  268. orderDetailId,
  269. goodsId,
  270. goods:JSON.stringify(goods)
  271. });
  272. },
  273. refund(item){
  274. // console.log('logistics',item);
  275. uni.$u.route('/shopping/refund', {
  276. id: item.id
  277. });
  278. },
  279. cancelOrder(item){
  280. let that = this;
  281. uni.showModal({
  282. title: '提示',
  283. content: '确认取消吗!',
  284. success: res => {
  285. if (res.confirm) {
  286. this.$u.api.cancelOrder({orderId:item.id}).then(res=>{
  287. this.$refs.uToast.show({
  288. message:res.msg,
  289. complete() {
  290. that.reloadList();
  291. }
  292. });
  293. // uni.$u.toast(res.msg);
  294. console.log('res',res.data);
  295. }).catch(err=>{
  296. console.log('cancelOrder',err);
  297. })
  298. }
  299. }
  300. });
  301. // console.log('logistics',item);
  302. },
  303. viewRefund(item){
  304. uni.$u.route('/center/viewRefund', {
  305. orderId: item.id
  306. });
  307. },
  308. confirmReceipt(item){
  309. let that = this;
  310. uni.showModal({
  311. title: '提示',
  312. content: '确认收货吗!',
  313. success: res => {
  314. if (res.confirm) {
  315. this.$u.api.confirmReceipt({orderId:item.id}).then(res=>{
  316. uni.showToast({
  317. title:res.msg,
  318. duration:2000,
  319. complete() {
  320. that.reloadList();
  321. }
  322. });
  323. console.log('res',res.data);
  324. }).catch(err=>{
  325. console.log('confirmReceipt',err);
  326. })
  327. }
  328. }
  329. })
  330. },
  331. viewEvaluate(item){
  332. uni.$u.route('/shopping/orderdetails', {
  333. id: item.id
  334. });
  335. },
  336. gotoPay(orderId){
  337. this.$u.api.gotoPay({orderId:orderId,openid:''}).then(res=>{
  338. this.payResult = res.data.payInfo;
  339. this.payResult.package = res.data.payInfo.packageValue;
  340. this.wxPay()
  341. // if(this.params.paymentMode==1||this.params.paymentMode==4){
  342. // this.wxPay()
  343. // }else{
  344. // uni.$u.route('/shopping/paysuccess');
  345. // }
  346. console.log('gotoPayres',res.data);
  347. }).catch(err=>{
  348. this.paypass = '';
  349. this.checkPassShow = false;
  350. console.log('gotoPay',err);
  351. })
  352. },
  353. wxPay(){
  354. let that = this;
  355. uni.requestPayment({
  356. ... this.payResult,
  357. "provider": "wxpay",
  358. "orderInfo": {
  359. // "appid": "wx499********7c70e", // 微信开放平台 - 应用 - AppId,注意和微信小程序、公众号 AppId 可能不一致
  360. // "noncestr": "c5sEwbaNPiXAF3iv", // 随机字符串
  361. // "package": "Sign=WXPay", // 固定值
  362. // "partnerid": "148*****52", // 微信支付商户号
  363. // "prepayid": "wx202254********************fbe90000", // 统一下单订单号
  364. // "timestamp": 1597935292, // 时间戳(单位:秒)
  365. // "sign": "A842B45937F6EFF60DEC7A2EAA52D5A0" // 签名,这里用的 MD5/RSA 签名
  366. },
  367. success(res) {
  368. that.payQuery();
  369. },
  370. fail(e) {
  371. console.log('wxPayfail',e);
  372. }
  373. })
  374. },
  375. payQuery(){
  376. let that = this;
  377. let retryCount = 0;
  378. let maxRetryCount = 5; // 设置最大重试次数
  379. let interval = 2000; // 设置间隔时间为2秒
  380. let timeout = 10000; // 设置超时时间为10秒
  381. let timer;
  382. uni.showLoading({
  383. title:'支付结果查询中'
  384. })
  385. timer = setInterval(() => {
  386. retryCount++;
  387. if (retryCount > maxRetryCount || retryCount * interval > timeout) {
  388. clearInterval(timer);
  389. uni.hideLoading();
  390. console.log("支付查询超时或达到最大重试次数");
  391. // 在这里添加超时或达到最大重试次数的处理逻辑
  392. this.reloadList()
  393. } else {
  394. console.log("第" + retryCount + "次查询");
  395. // 调用查询支付状态的方法
  396. // 如果支付状态为成功,则清除定时器并处理成功的逻辑
  397. // 如果支付状态为失败,则清除定时器并处理失败的逻辑
  398. this.$u.api.payQuery({orderId:this.orderId}).then(res=>{
  399. // 0-未支付 1-已支付 2-支付中 3-支付失败 4-支付退款
  400. let payStatus = res.data.payStatus;
  401. if(payStatus===1){
  402. uni.$u.route('/center/paysuccess');
  403. }else if(payStatus===0||payStatus===2){
  404. this.payQuery()
  405. }else if(payStatus===3){
  406. uni.toast('支付失败')
  407. }
  408. clearInterval(timer);
  409. }).catch(err=>{
  410. console.log('payQuery',err);
  411. }).finally(()=>{
  412. uni.hideLoading()
  413. })
  414. }
  415. }, interval);
  416. },
  417. statisticsOrder(){
  418. this.$u.api.statisticsOrder().then(res=>{
  419. let data = res.data || {};
  420. this.orderBadge = Object.assign(this.orderBadge,data);
  421. let {noPayNum,deliverNum,collectNum,commentNum,refundNum} = res.data;
  422. let noPayNumindex = this.tabsList.findIndex(item => item.status == 0);
  423. this.tabsList[1].badge.isDot = false;
  424. this.tabsList[1].badge.value = noPayNum;
  425. this.tabsList[2].badge.isDot = false;
  426. this.tabsList[2].badge.value = deliverNum;
  427. this.tabsList[3].badge.isDot = false;
  428. this.tabsList[3].badge.value = collectNum;
  429. this.tabsList[4].badge.isDot = false;
  430. this.tabsList[4].badge.value = commentNum;
  431. this.tabsList[5].badge.isDot = false;
  432. this.tabsList[5].badge.value = refundNum;
  433. // console.log('statisticsOrder',res.data);
  434. // console.log('this.orderBadge',this.orderBadge);
  435. }).catch(err=>{
  436. console.log('memberInfo',err.data);
  437. })
  438. }
  439. }
  440. }
  441. </script>
  442. <style>
  443. page{
  444. background-color: #F5F5F5;
  445. }
  446. </style>
  447. <style lang="scss" scoped>
  448. .tabs-wrap{
  449. background-color: #fff;
  450. margin-bottom: 10rpx;
  451. }
  452. .list-item{
  453. overflow: hidden;
  454. width: 48%;
  455. margin-bottom: 30rpx;
  456. background-color: #fff;
  457. .image-wrap{
  458. margin-bottom: 20rpx;
  459. }
  460. }
  461. .order-item{
  462. margin-bottom: 20rpx;
  463. background: #FFFFFF;
  464. box-shadow: 0rpx 2rpx 12rpx 0rpx rgba(221,221,221,0.5);
  465. border-radius: 20rpx;
  466. padding: 32rpx;
  467. .top{
  468. font-size: 24rpx;
  469. font-weight: 400;
  470. color: #7F7F7F;
  471. line-height: 36rpx;
  472. margin-bottom: 36rpx;
  473. }
  474. .info{
  475. margin-bottom: 30rpx;
  476. .img{
  477. width: 180rpx;
  478. height: 160rpx;
  479. }
  480. .text{
  481. font-size: 24rpx;
  482. font-weight: 400;
  483. color: #7F7F7F;
  484. padding-left: 26rpx;
  485. flex: 1;
  486. .name{
  487. font-size: 28rpx;
  488. font-weight: bold;
  489. color: #363636;
  490. margin-bottom: 20rpx;
  491. }
  492. .time{
  493. margin-bottom: 20rpx;
  494. }
  495. .position{
  496. margin-bottom: 20rpx;
  497. }
  498. .statistics{
  499. text-align: right;
  500. }
  501. .label{
  502. font-size: 24rpx;
  503. font-weight: 400;
  504. color: #363636;
  505. margin-left: 10rpx;
  506. }
  507. .price{
  508. font-size: 32rpx;
  509. font-weight: bold;
  510. color: #ED0000;
  511. }
  512. }
  513. }
  514. .btn-wrap{
  515. }
  516. .btn{
  517. padding: 12rpx 40rpx;
  518. border: 1px solid #E5E5E5;
  519. color: #7F7F7F;
  520. text-align: center;
  521. border-radius: 8rpx;
  522. font-size: 24rpx;
  523. &.red{border-color: #ED0000;color: #ED0000;}
  524. &.red.solid{border-color: #ED0000;background-color:#ED0000;color: #fff;}
  525. &.green{color: #00A447;border-color: #00A447;}
  526. &:not(:first-child){
  527. margin-left: 20rpx;
  528. }
  529. }
  530. &.status-0{.status{color:#FF3C3F;}}
  531. &.status-1{.status{color:#FF3C3F;}}
  532. &.status-2{.status{color:#0099EB;}}
  533. &.status-3{.status{color:#00A447;}}
  534. &.status-4{.status{color:#FF3C3F;}}
  535. &.status-5{.status{color:#FF3C3F;}}
  536. &.status-6{.status{color:#FF3C3F;}}
  537. &.status-7{.status{color:#FFB100;}}
  538. }
  539. </style>