Files
huakai-project/huakai-app/pages/paymentIndex/paymentIndex.vue
2026-10-14 09:28:49 +08:00

443 lines
9.1 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="生活缴费" backgroundColor="transparent" :border="false"></uni-nav-bar>
<view class="topbox">
<image class="titleImg" :src="`${imgBaseUrl}/images/propertyImgs/payTitle.png`"></image>
<image class="payImg" :src="`${imgBaseUrl}/images/propertyImgs/payImg.png`"></image>
</view>
<scroll-view class="page" scroll-y="true">
<view class="container">
<!-- 未登录提示条 -->
<view class="login-tip" v-if="!isLogin" @click="handleLoginPrompt">
<image class="login-tip-icon" :src="`${imgBaseUrl}/images/login/phone.png`"></image>
<text class="login-tip-text">登录后可查看缴费账单</text>
<text class="login-tip-link">去登录</text>
</view>
<!-- 账单列表(仅登录后显示) -->
<view class="bill-list" v-if="isLogin && paymentList.length > 0">
<view class="bill-item" @click="goToBill(item)" v-for="(item, index) in paymentList" :key="index">
<image class="billIcon" :src="waterImg" v-if="item.type == '水费'"></image>
<image class="billIcon" :src="electricImg" 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>
<text :class="item.balance < 0 ? 'balance-debt' : 'balance-normal'">(余额:{{ item.balance || 0.0 }}元)</text>
</view>
<view class="bill-desc">{{ item.villageName + '-' + item.buildingName + '-' + formatAddress(item.fullAddress) }}</view>
</view>
<view class="arrow"></view>
</view>
</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>
</view>
</view>
</view>
<view style="width: 100%; height: 30rpx"></view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onShow, onLoad } from '@dcloudio/uni-app';
import { getTopUpSelectByResident, getopenIdByCode, postInsertOpenId } from '/pageSubPack/api/apiSub.js';
import { isLoggedIn, requireAuth } from '/pageSubPack/api/auth.js';
import { imgBaseUrl } from '/pageSubPack/api/request.js';
const isLogin = ref(false);
const paymentList = ref([]);
const waterImg = imgBaseUrl + '/images/propertyImgs/water.png';
const electricImg = imgBaseUrl + '/images/propertyImgs/electric.png';
const addList = ref([
{
name: '水表',
type: 'water',
icon: waterImg,
iconClass: 'water'
},
{
name: '电表',
type: 'electric',
icon: electricImg,
iconClass: 'electric'
}
]);
// ===== 刷新登录状态 =====
const refreshLoginState = () => {
isLogin.value = isLoggedIn();
if (!isLogin.value) {
// 未登录时清空账单数据
paymentList.value = [];
}
};
// ===== openid 相关(仅登录后) =====
const postOpenId = async () => {
if (!isLogin.value) return;
const openid = uni.getStorageSync('openid');
if (openid && typeof openid === 'string' && openid.trim() !== '') {
return openid;
}
try {
const loginRes = await wx.login();
// uni.login;
if (!loginRes.code) {
console.error('wx.login 失败');
return;
}
const openIdRes = await getopenIdByCode({ code: loginRes.code });
if (openIdRes.code !== 200 || !openIdRes.data) {
console.error('获取openid失败');
return;
}
uni.setStorageSync('openid', openIdRes.data);
await postInsertOpenId({
openid: openIdRes.data,
residentUserId: uni.getStorageSync('userId')
});
} catch (err) {
console.error('postOpenId 报错:', err);
}
};
// ===== 获取缴费列表 =====
const getPayList = async () => {
if (!isLogin.value) return;
try {
const res = await getTopUpSelectByResident({
residentUserId: uni.getStorageSync('userId')
});
paymentList.value = res.rows || [];
} catch (err) {
console.error('列表接口报错:', err);
}
};
// ===== 生命周期 =====
onLoad(() => {
refreshLoginState();
uni.hideTabBar({ animation: false });
if (isLogin.value) {
getPayList();
}
});
onShow(() => {
refreshLoginState();
if (isLogin.value) {
postOpenId();
getPayList();
}
});
// ===== 点击事件(统一用 isLogin 判断) =====
// 点击"去登录"提示条
const handleLoginPrompt = () => {
if (isLogin.value) return;
requireAuth({
title: '查看缴费账单',
onLoggedIn: () => {
refreshLoginState();
getPayList();
}
});
};
// 点击账单明细
const goToBill = (item) => {
if (!isLogin.value) {
requireAuth({
title: '查看缴费详情',
onLoggedIn: () => {
refreshLoginState();
goToBill(item);
}
});
return;
}
uni.setStorageSync('arrearsPayment', item);
uni.navigateTo({ url: '/pageSubPack/payment-list/arrearsPayment' });
};
// 点击缴费记录
const goToRecord = () => {
if (!isLogin.value) {
requireAuth({
title: '查看缴费记录',
onLoggedIn: () => {
refreshLoginState();
goToRecord();
}
});
return;
}
uni.navigateTo({ url: '/pageSubPack/payment-list/paymentRecord' });
};
// 点击新增缴费(水表/电表等)
const goToAdd = (type) => {
if (!isLogin.value) {
requireAuth({
title: '新增缴费',
onLoggedIn: () => {
refreshLoginState();
goToAdd(type);
}
});
return;
}
if (type.name == '燃气' || type.name == '暖气') {
uni.navigateTo({ url: '/pageSubPack/payment-list/selectPaymentEntity' });
} else if (type.name == '水表' || type.name == '电表') {
uni.navigateTo({ url: '/pageSubPack/payment-list/addHydropower' });
}
uni.setStorageSync('addPaymentType', type.name);
};
const formatAddress = (addr) => {
if (!addr) return '';
return addr
.replace(/\d+[层楼]\s*/g, '')
.replace(/单元\s*/g, '-')
.replace(/\s+/g, '');
};
</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;
}
/* ===== 未登录提示条 ===== */
.login-tip {
display: flex;
align-items: center;
background-color: #fff;
padding: 24rpx 30rpx;
border-radius: 10rpx;
margin-bottom: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.login-tip-icon {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
.login-tip-text {
flex: 1;
font-size: 28rpx;
color: #666;
}
.login-tip-link {
font-size: 28rpx;
color: #1677ff;
font-weight: 500;
}
.bill-list {
margin-bottom: 40rpx;
background-color: #fff;
padding: 30rpx;
border-radius: 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;
align-items: center;
gap: 10rpx;
}
.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;
}
.balance-normal {
font-size: 28rpx;
color: #333;
}
.balance-debt {
font-size: 28rpx;
color: #e34d59;
}
.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% - 50rpx);
background-color: #f6f9fe;
border-radius: 12rpx;
padding: 20rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
flex-direction: column;
}
.icon-box {
width: 88rpx;
height: 88rpx;
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;
}
.status-bar {
width: 100vw;
height: 46px;
}
</style>