Skip to content

缴费列表

UI

组件

vue
<template>
	<div class="page">
		<template v-if="isop === '1'">
			<van-list
				v-model="loading"
				finished-text="列表只能显示最近200条记录"
				offset="200"
				:finished="finished"
				:immediate-check="false"
				@load="onLoad"
			>
				<div v-for="(hist, index) in formattedHistory" :key="index">
					<div v-if="hist.sign" class="pay-tab">{{ hist.sign }}</div>
					<div v-else style="background-color: #fff;">
						<div class="ite" @click="toDetail(hist)">
								<div class="Icon ite-icon" :class="fnImg(hist.bizType)" />
								<div class="ite-center">
									<div class="ite-name">{{ hist.payFeeDesc }}</div>
									<div class="ite-no">
											<span>{{ hist.billNo }}</span>
											<span>&nbsp;&nbsp;</span>
											<span class="date">{{hist.createDate.substr(5,11)}}</span>
									</div>
								</div>
								<div class="ite-money">
										<div class="money"><span class="money-icon">¥</span>{{ hist.orderAmount | fen2yuan }}</div>
										<div v-show="hist.orderStatusCH != '缴费成功'" class="orderStatus" :class="{ active: hist.orderStatusCH === '交易处理中' }">{{ hist.orderStatusCH }}</div>
								</div>
						</div>
					</div>
				</div>
			</van-list>
		</template>
		<!-- 没有数据 0 或是 2 -->
		<template v-else>
			<div class="nullbox">
				<img src="~@/assets/img/failToLoad.svg" alt="" />
				<p>{{ isop === '0' ? '暂无缴费记录' : isop === '2' ? '网络异常' : '' }}</p>
			</div>
		</template>
	</div>
</template>
<script>
import { mapState, mapGetters, mapActions  } from 'vuex';
import { List  } from 'vant';
import {ORDER_STATUS} from '@/utils/common/order-status';
import filter from '@/utils/filter';

export default {
	components: {
		VanList: List
	},
	filters: filter,
	data() {
		return {
			currentPage: 1,
			// 正在加载数据中
			loading: false,
			// 数据已加载完
			finished: false,
			// 区分状态 0 - 没有数据    1 - 有数据    2 - 接口失败
			isop: '1',
			// 缴费记录
			history: [],
		}
	},
	activated () {
		if (!this.fromPaymentDetail) {
			this.resetData()
		 	this.init();
		}
	},
	methods: {
		...mapActions('payment', ['queryHistory']),
		fnImg (type) {
				switch (type) {
						case '2':
								return 'electric';
						case '4': // 应该是电视费,但在缴费列表显示燃气 icon(只在这里特殊处理,因为后端接口是两个写的出了点问题)
						case '3': // 燃气
								return 'gas';
						case 'C':
								return 'tv';
						case '1':
								return 'water';
						case '6':
								return 'heat';
				}
		},
		resetData () {
			this.currentPage = 1
			// 正在加载数据中
			this.loading = false
			// 数据已加载完
			this.finished = false,
			// 区分状态 0 - 没有数据    1 - 有数据    2 - 接口失败
			this.isop = '1'
			// 缴费记录
			this.history = []
		},
		toDetail (detail) {
			this.$store.commit('payment/setHistoryDetailObj', detail)
			this.$router.push({
				name: 'paymentDetail'
			});
		},
		onLoad () {
			this.loading = true;
			this.currentPage += 1;
			this.init();
		},
		async init () {
			const params = {
				currentPage: `${this.currentPage}`,
				pageSize: '20'
			};

			try {
				const result = await this.queryHistory(params)
				if (!result.success) {
					return this.$Toast(result.errorMsg)
				}
				if (result?.result.length > 0) {
					// 请求到列表数据
					this.isop = '1';
					this.loading = false;
					// this.recordList = [...this.recordList, ...result.result];
					// this.handleResult(this.recordList);
					this.history = [...this.history, ...result.result]
					if (result.result.length < 20) {
						// 结束加载
						this.finished = true;
					}
				} else if (result?.result.length == 0) {
					this.isop = '0'; // 第一页就没有数据 显示骨架图
					this.finished = true;
				} else {
					this.finished = true; // 列表数据为整数 结束加载
					this.loading = false;
				}
			} catch (err) {
				this.$Toast(err.errorMsg || '网络异常');
				this.loading = false;
			}
		}
	},
	computed: {
		...mapState('common', ['productNo']),
		...mapGetters('businessType', ['getBusTypeByKey']),
		formattedHistory () {
			// 当前时间对象
			const date = new Date();
			// 当前月份
			let mon = (date.getMonth() + 1);
			mon = mon < 10 ? ('0' + mon) : mon;
			// date = date.getFullYear() + "-" + mon;
			// 当前时间的年月份
			const yearMon = date.getFullYear() + "-" + mon;
			// 经过处理后的 history 数组是一个包含对象的数组
			// sign 属性表示该对象所代表的时间段,比如 "本月" 或者 "2023年3月"。
			// 没有 sign 属性的对象里面存放了在该时间段内的所有交易记录,每个交易记录包括订单号、交易时间、订单状态、交易金额等信息。
			// 下面是一个简单的示例,以展示这个数组的结构:
			// [
			// 	{ sign: '本月' },
			// 	{
			// 		orderNo: '1234567890',
			// 		createTime: '2023-03-01 14:23:56',
			// 		orderStatus: 'S0C',
			// 		amount: '100.00'
			// 	},
			//  {
			// 		orderNo: '0987654321',
			// 		createTime: '2023-03-08 09:15:27',
			// 		orderStatus: 'S0F',
			// 		amount: '50.00'
			// 	}
			// ]
			const history = [];
			// 用来判断是否往 history 数组推入表示年月份时间的数组
			let lastSign = "";
			for (const value of this.history) {
				// if (value.orderStatus === "S0A") {
				// 	continue
				// }
				const createDate = value.createDate;
				const valueDate = new Date(createDate.substr(0, 4), createDate.substr(5, 2) - 1, createDate.substr(8, 2));
				// 往 value 上添加一个 weekDate 属性
				value.weekDate = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"][valueDate.getDay()]
				// 往 value 上添加一个 orderStatusCH 属性
				value.orderStatusCH = ORDER_STATUS?.[value.orderStatus]?.desc;

				// 循环项年月份
				const valueYearMon = createDate.substr(0, 7);
				if (lastSign !== valueYearMon) {
					if (yearMon === valueYearMon) {
						history.push({
							sign: "本月"
						});
					} else {
						// 循环项的月份
						let valueMon = (valueDate.getMonth() + 1);
						valueMon = valueMon < 10 ? ('0' + valueMon) : valueMon;
						// 循环项的年月
						let signYearMon = valueDate.getFullYear() + "年" + valueMon + "月";
						// 如果当前时间的年份和循环项的年份相同,只显示月即可
						if (date.getFullYear() == valueDate.getFullYear()) {
							signYearMon = valueMon + "月";
						}
						history.push({
							sign: signYearMon
						});
					}
					lastSign = valueYearMon;
				}
				history.push(value);
			}
			return history
		}
	},
	beforeRouteEnter (to , from, next) {
		if (from.name === 'paymentDetail') {
			next(vm => {
				vm.fromPaymentDetail = true
			})
		} else {
			next(vm => {
				vm.fromPaymentDetail = false
			})
		}
	}
}
</script>
<style lang="scss" scoped>
.page {
	background-color: #fff;
	height: 100%;
	.pay-tab {
		width: 100%;
		box-sizing: border-box;
		height: 46px;
		background-color: #f5f5f5;
		font-size: 16px;
		font-weight: 600;
		padding-left: 15px;
		line-height: 46px;
		color: #242424;
	}
	.ite {
			width: 345px;
			padding: 15px 0;
			overflow: hidden;
			margin: 0 15px;
			display: flex;
			align-items: center;
			.ite-icon {
					width: 28px;
					height: 28px;
					align-self: self-start;
			}
			.ite-center {
					margin-left: 12px;
					width: 240px;
					.ite-name {
							font-size: 16px;
							color: #242424;
							overflow: hidden;
							white-space: nowrap;
							text-overflow: ellipsis;
							margin-bottom: 5px;
					}
					.ite-no {
							color: #808080;
							overflow: hidden;
							white-space: nowrap;
							text-overflow: ellipsis;
							font-size: 13px;
					}
			}
			.ite-money {
					margin-left: auto;
					text-align: right;
					.money {
							font-size: 18px;
							color: #242424;
							font-weight: 700;
						.money-icon {
								font-size: 15px;
								color: $color-46;
						}
					}
					.orderStatus {
							font-size: 13px;
							color: $color-c7;
							margin-top: 5px;
					}
					.active{
							color: #4A7BFF;
					}
			}
	}
	.no-data-tip {
		text-align: center;
		font-size: 30px;
	}
	.nullbox {
		font-size: 14px;
		text-align: center;
		color: #808080;
		margin: 0 auto;
		padding: 240px 0;
		img {
			width: 130px;
			height: 130px;
			margin-bottom: 16px;
		}
	}
}
</style>

ORDER_STATUS

js
// 注意:"S0C" 中间的字符是数字 0,不是字母 O

export const ORDER_STATUS = {
	S0C: {
		desc: "交易成功",
		key: "S0C"
	},
	S0F: {
		desc: "交易失败,正在退款",
		key: "S0F"
	},
	S0R: {
		desc: "已退款",
		key: "S0R"
	},
	S0D: {
		desc: "交易进行中",
		key: "S0D"
	},
	S0B: {
		desc: "交易进行中",
		key: "S0B"
	},
	S0A: {
		desc: "待付款",
		key: "S0A"
	}
}

Released under the MIT License.