概述:废话不多说,直接上代码
DOM
<wxs src="../../../utils/common.wxs" module="model" />
<view class="main-container">
<van-tabs
swipeable
color="#02BA4B"
bind:change="tabChange"
active="{{currentTab}}"
>
<van-tab title="待支付" name="1" />
<van-tab title="已支付" name="3" />
<van-tab title="已取消" name="5" />
<van-tab title="全部" name="66" />
</van-tabs>
<scroll-view
scroll-y
refresher-enabled="{{true}}"
refresher-triggered="{{loading}}"
bindrefresherrefresh="onRefresh"
bindscrolltolower="onLoadMore"
style="height: calc(100vh - 100rpx)">
<view class="m24-card-box pr25 pl25 pt25 pb25" wx:for="{{orderMyList}}" wx:key="index">
<view class="box content-between align-items-center mb25">
<view class="order-no">{{item.no}}</view>
<view class="box">
<!-- 待支付 -->
<view wx:if="{{item.payStatus == 1 && item.remainPayTime > 0}}" class="remaining-time">
<text class="mr20">剩余时间</text><text>{{item.countdownStr}}</text>
</view>
<!-- 支付完成 -->
<view wx:if="{{item.payStatus == 3}}" class="pay-status">{{item.payNameStatus}}({{item.ticketNameStatus}})</view>
<!-- 5 已取消 -->
<view wx:else class="{{ item.payStatus == 5 ? 'cancel-status' : 'pay-status' }}">{{item.payNameStatus}}</view>
</view>
</view>
<view class="content-box">
<view class="number-name">{{item.gradeName}}</view>
<view class="detail-item">有效期:{{item.validTime}}个月</view>
<view class="box content-between align-items-center">
<view class="detail-item">下单时间:{{model.formatTimeCommon(item.payTime, "YYYY-MM-DD HH:MM")}}</view>
<view>
<text class="total-unit">¥</text><text class="total-money">{{model.toFixed(item.amount)}}</text>
</view>
</view>
</view>
<view wx:if="{{item.payStatus == 1}}" class="box content-end" bind:tap="clickSubmit" data-item="{{item}}">
<view class="pay-btn btn">立即支付</view>
</view>
</view>
<van-empty wx:if="{{orderMyList.length == 0 && !loading}}" description="暂无数据" />
<block wx:else>
<view wx:if="{{!loading && !hasMore}}" class="no-more">没有更多数据了</view>
<view wx:else class="loading">加载中...</view>
</block>
</scroll-view>
</view>
js
// pages/test/index.js
// import { getPermit } from "@utils/permit.js"; // 引入权限模块
import { formatTime, throttle } from "@utils/util";
import { orderList, payOrder, bindWxUser } from "@service-api/mine/index";
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
openId: null,
currentData: {},
loading: false,
orderMyList: [],
currentTab: '1',
queryParams: {
page: 1,
rows: 10,
payStatus: '1',
payPlatform: 2
},
hasMore: true, // 是否还有更多数据
timer: null // 新增定时器
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.setData({
openId: options.openId,
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
// getPermit(this); // 获取并设置页面权限
this.getInit()
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
if (this.data.timer) {
clearInterval(this.data.timer);
}
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {},
// 切换tab
tabChange(event) {
this.setData({
loading: true,
orderMyList: [],
'queryParams.page': 1,
'queryParams.payStatus': event.detail.name == 66 ? '' : event.detail.name
});
this.getInit();
},
// 下拉刷新方法
async onRefresh() {
this.data.queryParams.page = 1; // 重置页码
this.setData({ loading: true, orderMyList: [] });
this.getInit();
},
// 上拉加载更多方法
async onLoadMore() {
if (!this.data.hasMore) return;
this.data.queryParams.page += 1; // 增加页码
this.getInit();
},
async getInit() {
const { code, data } = await orderList(this.data.queryParams);
if (code == 0) {
if (data.rows) {
let processedRows = data.rows.map((item) => {
// payStatus 支付状态:1待支付, 3已支付,4支付失败,5支付关闭(取消),6已退款
// ticketStatus 开票状态0:未开票1:已开票
return {
payNameStatus:
item.payStatus == 1 ? '待支付' :
item.payStatus == 3 ? '已支付' :
item.payStatus == 4 ? '支付失败' :
item.payStatus == 5 ? '支付关闭(取消)' :
item.payStatus == 6 ? '已退款' : '',
ticketNameStatus: item.ticketStatus == 0 ? '未开票' : '已开票',
...item,
countdown: item.remainPayTime,
isCountdownEnd: false // 倒计时结束标记
};
});
this.setData({
loading: false,
hasMore: data.rows.length < 10 ? false : true,
orderMyList: this.data.queryParams.page == 1 ? processedRows : this.data.orderMyList.concat(processedRows)
}, () => {
this.startCountdown();
});
} else {
this.setData({
loading: false,
hasMore: false,
});
}
}
},
// 新增倒计时方法
startCountdown() {
if (this.data.timer) {
clearInterval(this.data.timer);
}
const timer = setInterval(() => {
const updatedList = this.data.orderMyList.map(item => {
if (item.countdown > 0 && !item.isCountdownEnd) {
const newCountdown = item.countdown - 1;
// 修改:使用剩余秒数直接转换
const hours = Math.floor(newCountdown / 3600);
const minutes = Math.floor((newCountdown % 3600) / 60);
const seconds = newCountdown % 60;
const countdownStr = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
return {
...item,
countdown: newCountdown,
countdownStr,
isCountdownEnd: newCountdown <= 0
};
}
return item;
});
this.setData({
orderMyList: updatedList
});
// 检查是否所有倒计时都结束
const allEnded = updatedList.every(item => item.countdown <= 0 || item.isCountdownEnd);
if (allEnded) {
clearInterval(timer);
}
}, 1000);
this.setData({
timer
});
},
// 立即支付
clickSubmit: throttle(function (e) {
wx.showLoading({
title: "支付中...",
});
this.setData({ currentData: e.currentTarget.dataset.item })
this.getCreateOrder()
}, 3000), // 设置节流间隔为 3000ms
// 创建订单
async getCreateOrder() {
const params = {
wxCode: '',
payPlatform: 2,
id: this.data.currentData.id
}
const { code, data } = await payOrder(params);
if (code == 0) {
this.getPayment(data)
} else {
wx.hideLoading()
}
},
// 去支付
async getPayment(data) {
wx.requestPayment({
timeStamp: data.jsapiResult.timeStamp,
nonceStr: data.jsapiResult.nonceStr,
package: data.jsapiResult.packageValue,
signType: data.jsapiResult.signType,
paySign: data.jsapiResult.paySign,
success: () => {
wx.showToast({
title: '支付成功',
icon: 'none',
duration: 2000
})
this.data.queryParams.page = 1
this.getInit()
setTimeout(() => {
this.getInit();
}, 1000);
},
fail(err) {
console.log(err)
if (err.errMsg != "requestPayment:fail cancel") {
wx.showToast({
title: '支付失败:' + err.errMsg,
icon: 'none',
duration: 2000
})
} else {
wx.showToast({
title: '取消支付',
icon: 'none',
duration: 2000
})
}
},
complete: () => {}
})
wx.hideLoading()
}
})
css
.loading, .no-more {
text-align: center;
padding: 20rpx 0;
color: #999;
font-size: 24rpx;
}
.main-container {
overflow: hidden;
height: 100vh;
}
.m24-card-box {
.order-no {
font-size: 28rpx;
color: #83878EFF;
}
.remaining-time {
font-size: 24rpx;
color: #ed3b3bff;
padding: 4rpx 8rpx;
border-radius: 4px;
background: #fdebebff;
border: 1px solid #ed3b3bff;
}
.pay-status {
font-size: 28rpx;
color: #ed3b3bff;
margin-left: 16rpx;
}
.cancel-status {
font-size: 28rpx;
margin-left: 16rpx;
color: #83878EFF;
}
.content-box {
padding: 24rpx;
border-radius: 8px;
background-color: #F7F8FCFF;
.number-name {
font-size: 32rpx;
color: #303133ff;
font-weight: 600;
margin-bottom: 16rpx;
}
.detail-item {
color: #83878eff;
font-size: 28rpx;
}
.total-unit {
font-size: 28rpx;
color: #303133FF;
}
.total-money {
font-size: 40rpx;
color: #303133FF;
font-weight: 600;
}
}
.btn {
font-size: 28rpx;
padding: 8rpx 16rpx;
border-radius: 8px;
margin-top: 24rpx;
}
.cancel-btn {
color: #83878eff;
border: 2px solid #e5e6ebff;
}
.pay-btn {
color: #165dffff;
border: 2px solid #165dffff;
margin-left: 24rpx;
}
}
json
{
"navigationBarTitleText": "我的订单",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"usingComponents": {
"van-icon": "@vant/weapp/icon/index",
"van-action-sheet": "@vant/weapp/action-sheet/index",
"van-popup": "@vant/weapp/popup/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-picker": "@vant/weapp/picker/index",
"van-tab": "@vant/weapp/tab/index",
"van-tabs": "@vant/weapp/tabs/index",
"van-empty": "@vant/weapp/empty/index"
}
}