Files
property-resident-side/property-uniapp-project/pageSubPack/payment-list/paymentIndex.vue

576 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="contentStyle" style="">
<view class="status-bar"></view>
<uni-nav-bar title="生活缴费" left-icon="left" @clickLeft="goBack" backgroundColor="transparent" :border="false">
</uni-nav-bar>
<view class="topbox">
<image class="titleImg" src="https://wuyeadmin.bugtc.com/images/propertyImgs/payTitle.png"></image>
<image class="payImg" src="https://wuyeadmin.bugtc.com/images/propertyImgs/payImg.png"></image>
</view>
<scroll-view class="page" scroll-y="true">
<view class="container">
<!-- 已缴费/欠费列表 -->
<view class="bill-list" v-if="paymentList.length != 0">
<view class="bill-item" @click="goToBill(item)" v-for="item,index in paymentList" :key="index">
<image class="billIcon" src="https://wuyeadmin.bugtc.com/images/propertyImgs/water.png"
v-if="item.type=='水费'"></image>
<image class="billIcon" src="https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png"
v-if="item.type=='电费'"></image>
<view class="bill-info">
<view class="bill-title">{{item.type}}
<view class="bill-status debt" v-if="item.balance<0">已欠费</view>
</view>
<view class="bill-desc">{{item.villageName+item.buildingName+item.fullAddress}}</view>
</view>
<view class="arrow"></view>
</view>
</view>
<!-- 物业费/车位费/垃圾处理费列表 -->
<scroll-view class="details-scroll" scroll-y="true" @scrolltolower="onLoadMore" v-if="detailslist.length != 0">
<view class="bill-list">
<view class="bill-item" @click="goToBill(item)" v-for="item,index in detailslist" :key="index">
<image class="billIcon" src="https://wuyeadmin.bugtc.com/images/propertyImgs/property.png"
v-if="item.type=='0'"></image>
<image class="billIcon" src="https://wuyeadmin.bugtc.com/images/propertyImgs/parkingIcon.png"
v-if="item.type=='1'"></image>
<image class="billIcon" src="https://wuyeadmin.bugtc.com/images/propertyImgs/垃圾处理2x.png"
v-if="item.type=='2'"></image>
<view class="bill-info">
<view class="bill-title">{{switchStatus(item.type)}}
<view class="bill-status debt" v-if="item.payStatus === '0'">未缴纳</view>
</view>
<view class="bill-desc">{{item.name}}</view>
</view>
<view class="arrow"></view>
</view>
<!-- 滚动加载状态 -->
<view class="load-more-status" v-if="loadingMore">
<text class="loading-text">加载中...</text>
</view>
<view class="load-more-status" v-else-if="!hasMore && detailslist.length >= pageSize">
<text class="no-more-text"> 没有更多了 </text>
</view>
</view>
</scroll-view>
<!-- 新增缴费区域 -->
<view class="add-section">
<view class="section-header">
<text class="section-title">新增缴费</text>
<text class="record-link" @click="goToRecord">缴费记录</text>
</view>
<view class="grid-list">
<view class="grid-item" v-for="(item, index) in addList" :key="index" @click="goToAdd(item)">
<view class="icon-box" :class="item.iconClass">
<image class="iconStyle" :src="item.icon"></image>
</view>
<!-- <text class="item-name">{{ item.name +'费'}}</text> -->
<text class="item-name">{{ item.name}}</text>
</view>
</view>
</view>
<!-- 开启通知按钮 -->
<!-- v-if="subscribeAuth !== 'accepted'" -->
<!-- <view class="subscribe-btn" @click="requestSubscribeMessageClick">
<text class="subscribe-btn-text">开启缴费通知</text>
</view> -->
<!-- <button class="subscribe-btn" @tap="handleWaterElecSubscribe" open-type="subscribeMessage">
开启订单状态通知
</button> -->
<view style="width: 100%;height: 30rpx;"></view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import {
ref,
onMounted,
computed
} from 'vue'
import {
onShow,
onReady,
onReachBottom,
onLoad,
onUnload,
onPullDownRefresh
} from '@dcloudio/uni-app'
import {
getTopUpSelectByResident,
postInsertOpenId,
postSubscribeAuth,
getTopUpDetails,
} from '/pageSubPack/api/apiSub.js'
// 响应式数据
const statusBarHeight = ref(20)
const detailslist = ref([])
const pageNum = ref(1)
const pageSize = ref(3)
const total = ref(0)
const hasMore = ref(true)
const loadingMore = ref(false)
const paymentList = ref([
// {
// id: 1,
// name: '物业费',
// status: '已欠费',
// address: '桂花园别墅2号楼2层',
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/property.png",
// },
// {
// id: 2,
// name: '暖气费',
// status: '',
// address: '山东省日照市东港区桂花园别墅2号楼2层',
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/heating.png",
// },
{
id: 3,
name: '电费',
status: '已欠费',
address: '山东省日照市东港区桂花园别墅2号楼2层',
icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png",
}
])
const addList = ref([
// {
// name: "燃气",
// type: "gas",
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/gas.png",
// iconClass: "gas"
// },
{
name: "水费",
type: "water",
icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/water.png",
iconClass: "water"
},
{
name: "电费",
type: "electric",
icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png",
iconClass: "electric"
},
// {
// name: "物业费",
// type: "property",
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/property.png",
// iconClass: "property"
// },
// {
// name: "车位费",
// type: "parking",
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/parkingIcon.png",
// iconClass: "parking"
// }
])
const postOpenId = async () => {
// App 端直接从本地存储获取 openid
try {
const openid = uni.getStorageSync('openid')
if (!openid) {
uni.showToast({
title: '请先登录',
icon: 'none'
})
return
}
await postInsertOpenId({
openid: openid,
residentUserId: uni.getStorageSync('userId')
})
} catch (err) {
uni.showToast({
title: err.msg || '网络异常',
icon: 'none'
})
// console.error('列表接口报错:', err)
}
}
onShow(() => {
// Zy --------------
getBillDetails()
// Zy --------------
// 不再自动请求订阅消息,改为用户点击触发
})
// 生命周期
onReady(() => {})
onLoad(() => {
postOpenId()
uni.hideTabBar({
animation: false // 关闭动画,更稳定
});
getPayList()
})
const getPayList = async () => {
// 防重复请求
try {
const res = await getTopUpSelectByResident({
residentUserId: uni.getStorageSync('userId')
})
const data = res.data
paymentList.value = data
} catch (err) {
uni.showToast({
title: err.msg || '网络异常',
icon: 'none'
})
// console.error('列表接口报错:', err)
} finally {
}
}
// 方法
const goToBill = (item) => {
uni.setStorageSync('arrearsPayment', item)
const type = String(item.type || '')
// 物业费、车位费、垃圾处理费走物业费缴纳页;水费、电费走欠费缴纳页
const isProperty = ['物业费', '车位费', '垃圾处理费', '垃圾费', '0', '1', '2'].includes(type)
if (isProperty) {
uni.redirectTo({
url: `/pageSubPack/payment-list/propertyFeePayment?amount=${item.amount || ''}`
})
} else {
uni.redirectTo({
url: '/pageSubPack/payment-list/arrearsPayment'
})
}
}
const goToRecord = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentRecord'
})
}
const goToAdd = (type) => {
if (type.name == '燃气' || type.name == '暖气') {
uni.redirectTo({
url: '/pageSubPack/payment-list/selectPaymentEntity'
})
} else if (type.name == '水费' || type.name == '电费') {
uni.redirectTo({
url: '/pageSubPack/payment-list/addHydropower'
})
}
uni.setStorageSync('addPaymentType', type.name)
}
const goBack = () => {
console.log('返回',uni.getStorageSync('sourcePage'))
if (uni.getStorageSync('sourcePage') == 'serviceIndex') {
uni.switchTab({
url: '/pages/serviceIndex/serviceIndex'
})
} else if (uni.getStorageSync('sourcePage') == 'index') {
uni.switchTab({
url: '/pages/index/index'
})
}
uni.removeStorageSync('sourcePage')
}
// 获取缴费列表
const getBillDetails = (isLoadMore = false) => {
if (isLoadMore) {
if (!hasMore.value || loadingMore.value) return
pageNum.value++
loadingMore.value = true
} else {
pageNum.value = 1
hasMore.value = true
}
getTopUpDetails({
userId: uni.getStorageSync('userId'),
villageId: uni.getStorageSync('currentVillageId'),
pageNum: pageNum.value,
pageSize: pageSize.value,
}).then(res => {
if (isLoadMore) {
detailslist.value = [...detailslist.value, ...(res.rows || [])]
loadingMore.value = false
} else {
detailslist.value = res.rows || []
}
total.value = res.total || 0
hasMore.value = detailslist.value.length < total.value
}).catch(() => {
if (isLoadMore) {
pageNum.value--
loadingMore.value = false
}
})
}
const onLoadMore = () => {
getBillDetails(true)
}
const switchStatus = (type) => {
const typeMap = {
'0': '物业费',
'1': '车位费',
'2': '垃圾处理费'
}
return typeMap[type] || type
}
</script>
<style lang="scss">
page {
background: linear-gradient(180deg, #dfedfd, #F6FAFF);
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
background: linear-gradient(180deg, #dfedfd, #F6FAFF);
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 40rpx;
box-sizing: border-box;
}
.topbox {
height: 150rpx;
width: 100%;
position: relative;
}
.titleImg {
width: 262rpx;
height: 74rpx;
position: absolute;
left: 40rpx;
bottom: 20rpx;
}
.payImg {
width: 349.97rpx;
height: 313.57rpx;
position: absolute;
right: -80rpx;
bottom: -140rpx;
}
.container {}
.bill-list {
margin-bottom: 40rpx;
background-color: #fff;
padding: 30rpx;
border-radius: 10rpx;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
color: #ccc;
}
.empty-text {
font-size: 32rpx;
color: #999;
margin-top: 20rpx;
margin-bottom: 10rpx;
}
.bill-item {
display: flex;
align-items: center;
background-color: #F6F9FE;
border-radius: 12rpx;
padding: 20rpx 20rpx 20rpx 0px;
margin-bottom: 20rpx;
}
.bill-item:last-child {
margin-bottom: 0rpx;
}
.bill-info {
width: calc(90% - 100rpx);
flex: 1;
}
.billIcon {
width: 64rpx;
height: 64rpx;
margin: 20rpx;
}
.bill-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 10rpx;
display: flex;
}
.bill-desc {
font-size: 28rpx;
font-weight: 600;
color: #999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.bill-status {
padding: 2rpx 16rpx;
border-radius: 30rpx;
font-size: 24rpx;
font-weight: 500;
color: #fff;
background-color: #E34D59;
margin-left: 10rpx;
line-height: 1.5;
}
.arrow {
width: 12rpx;
height: 12rpx;
border-right: 4rpx solid #ccc;
border-bottom: 4rpx solid #ccc;
transform: rotate(-45deg);
}
.add-section {
background-color: #fff;
padding: 30rpx;
border-radius: 10rpx;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.record-link {
font-size: 28rpx;
color: #1677ff;
}
.grid-list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
/* gap: 26rpx; */
}
.grid-item {
width: calc(25% - 60rpx);
background-color: #F6F9FE;
border-radius: 12rpx;
padding: 20rpx;
margin-bottom: 20rpx;
margin-left: 20rpx;
display: flex;
align-items: center;
flex-direction: column;
}
/* 每行第 1 个 item 清除左边距,保证对齐 */
.grid-item:nth-child(4n+1) {
margin-left: 0;
}
.icon-box {
width: 52rpx;
height: 52rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
}
.iconStyle {
width: 100%;
height: 100%;
}
.item-name {
font-size: 28rpx;
font-weight: 600;
color: #333;
}
.subscribe-btn {
margin-top: 20rpx;
background-color: #1677ff;
padding: 24rpx;
border-radius: 10rpx;
text-align: center;
}
.subscribe-btn-text {
color: #fff;
font-size: 32rpx;
font-weight: 600;
}
.status-bar {
width: 100vw;
height: 46px;
}
.details-scroll {
max-height: 500rpx;
margin-bottom: 40rpx;
}
.load-more-status {
display: flex;
justify-content: center;
align-items: center;
padding: 20rpx 0;
}
.loading-text {
font-size: 26rpx;
color: #999;
}
.no-more-text {
font-size: 26rpx;
color: #ccc;
}
</style>