水费缴费部分代码同步

This commit is contained in:
wangyuxin
2026-06-01 11:17:04 +08:00
parent fbe07e21a6
commit c740126617
14 changed files with 717 additions and 555 deletions

View File

@@ -1,8 +1,8 @@
<template>
<view class="contentStyle" style="">
<view class="status-bar"></view>
<uni-nav-bar :title="arrearsPayment.value" left-icon="left" @clickLeft="goBack" backgroundColor="transparent"
:border="false">
<uni-nav-bar :title="paymentItem.type || '缴费'" left-icon="left" @clickLeft="goBack"
backgroundColor="transparent" :border="false">
</uni-nav-bar>
@@ -14,10 +14,13 @@
<view v-if="currentStep === 1" class="pay-page">
<!-- 物业费缴费 -->
<!-- 金额展示 -->
<view class="amount-section">
<view class="amount-section" v-if="outstandingPayment">
<text class="amount-text"
:class="{ 'outstandingPaymentClass':outstandingPayment }">{{outstandingPayment?'-¥'+payAmount:'¥'+payAmount}}</text>
</view>
<view class="amount-section" v-else>
<text class="amount-text paymentClass">{{'¥'+payAmount}}</text>
</view>
<view style="border-bottom: 2rpx solid #ededed;margin:10rpx 0rpx;"></view>
<!-- 缴费信息 -->
<view class="info-section" style="">
@@ -26,22 +29,22 @@
<view class="info-item">
<text class="info-label">户号</text>
<text class="info-value">101123456</text>
<text class="info-value">{{ paymentItem.deviceCode || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">户主</text>
<text class="info-value">周大声</text>
<text class="info-value">{{ paymentItem.name || '-' }}</text>
</view>
<view class="info-item">
<text class="info-label">缴费单位</text>
<text class="info-value">HN热力有限公司</text>
<text class="info-label">地址</text>
<text class="info-value">{{ paymentItem.fullAddress || '-' }}</text>
</view>
<!-- <view style="border-bottom: 2rpx solid #c7c7c7;padding-bottom:20rpx;"></view> -->
<!-- 缴费金额输入 -->
<view style="border-bottom: 2rpx solid #ededed;margin:10rpx 0rpx;"></view>
<view class="input-section" style="display: flex;">
<text class="amount-input" style="width: auto;margin: 0rpx 20rpx;">¥</text>
<input type="number" v-model="payNum" class="amount-input" placeholder="点击输入缴费金额">
<input type="digit" v-model="payNum" class="amount-input" placeholder="点击输入缴费金额">
</input>
</view>
<view style="border-bottom: 2rpx solid #ededed;margin:10rpx 0rpx;"></view>
@@ -55,79 +58,10 @@
</view>
</view>
</view>
<!-- 2. 支付密码弹窗 -->
<view v-if="currentStep === 2" class="modal-overlay" @click="closePasswordModal">
<view class="password-modal" @click.stop>
<!-- 弹窗头部 -->
<view class="modal-header">
<view class="close-icon" @click="closePasswordModal">
<text class="close-text">×</text>
</view>
<view class="modal-title">请输入支付密码</view>
<view class="header-right"></view>
</view>
<!-- 商户信息 & 金额 -->
<view class="pay-info">
<text class="merchant-name">充值金额</text>
<text class="pay-amount">¥{{ payAmount }}</text>
</view>
<!-- 支付方式选择 -->
<view class="pay-way">
<text class="way-label">支付方式</text>
<view class="way-content">
<image class="bank-icon"
src="http://47.104.199.163:9090/images/propertyImgs/bank-logo.png" mode="aspectFit">
</image>
<text class="bank-name">建设银行储蓄卡(8888)</text>
<text class="arrow-icon">></text>
</view>
</view>
<!-- 密码输入框 -->
<view class="password-input">
<view v-for="(item, index) in 6" :key="index" class="password-item">
<text v-if="password.length > index" class="password-dot"></text>
</view>
</view>
<!-- 数字键盘 -->
<view class="keyboard">
<view class="keyboard-row">
<view class="keyboard-item" @click="inputPassword(1)">1</view>
<view class="keyboard-item" @click="inputPassword(2)">2</view>
<view class="keyboard-item" @click="inputPassword(3)">3</view>
</view>
<view class="keyboard-row">
<view class="keyboard-item" @click="inputPassword(4)">4</view>
<view class="keyboard-item" @click="inputPassword(5)">5</view>
<view class="keyboard-item" @click="inputPassword(6)">6</view>
</view>
<view class="keyboard-row">
<view class="keyboard-item" @click="inputPassword(7)">7</view>
<view class="keyboard-item" @click="inputPassword(8)">8</view>
<view class="keyboard-item" @click="inputPassword(9)">9</view>
</view>
<view class="keyboard-row">
<view class="keyboard-item empty"></view>
<view class="keyboard-item" @click="inputPassword(0)">0</view>
<view class="keyboard-item delete" @click="deletePassword">
<text class="icon"></text>
</view>
</view>
</view>
</view>
</view>
<!-- 3. 缴费成功页 -->
<view class="container" v-if="currentStep==3">
<!-- 2. 缴费成功页 -->
<view class="container" v-if="currentStep==2">
<!-- 成功图标 -->
<view class="success-icon">
<text class="icon-check"></text>
@@ -138,7 +72,7 @@
<!-- 提示文案 -->
<view class="desc">
成功缴纳物业费
成功缴纳{{ paymentItem.type || '' }}费用 ¥{{ payNum || payAmount }}
</view>
@@ -152,7 +86,7 @@
<button class="pay-btn" @click="handlePay">立即缴费</button>
</view>
<!-- 返回按钮 -->
<view class="btn-section" v-if="currentStep === 3">
<view class="btn-section" v-if="currentStep === 2">
<button class="pay-btn" @click="handleBackToList">返回生活缴费</button>
</view>
</view>
@@ -163,45 +97,53 @@
<script setup>
import {
ref
ref,
reactive,
onMounted,
computed
} from 'vue'
import {
onShow,
onReady,
onReachBottom,
onLoad,
onUnload,
onPullDownRefresh
} from '@dcloudio/uni-app'
import {
getTopUp,
getToWxPay,
getopenIdByCode,
postSubscribeAuth
} from '/pageSubPack/api/apiSub.js'
// 响应式数据
const statusBarHeight = ref(20)
const outstandingPayment = ref(true)
const arrearsPayment = ref(uni.getStorageSync('arrearsPayment'))
const storageValue = uni.getStorageSync('arrearsPayment')
const paymentItem = reactive(typeof storageValue === 'object' && storageValue !== null ? storageValue : {})
const currentStep = ref(1)
const payAmount = ref('1680.00')
const password = ref('')
const showBankList = ref(false)
const arrearsAmount = ref('21.21')
const payAmount = ref('0.00')
const arrearsAmount = ref('0.00')
const payNum = ref('')
// 银行卡列表
const bankList = ref([{
id: 1,
name: '建设银行储蓄卡(8888)',
icon: '/static/bank-logo.png'
},
{
id: 2,
name: '工商银行储蓄卡(6666)',
icon: '/static/icbc-logo.png'
},
{
id: 3,
name: '招商银行储蓄卡(9999)',
icon: '/static/cmb-logo.png'
}
])
// 默认选中的银行卡
const selectedBank = ref({
id: 1,
name: '建设银行储蓄卡(8888)',
icon: '/static/bank-logo.png'
// 页面加载时初始化数据
onLoad(() => {
initPaymentData()
checkAllSubscribeStatus()
})
// 初始化缴费数据
const initPaymentData = () => {
if (paymentItem) {
arrearsAmount.value = Math.abs(paymentItem.balance || 0).toFixed(2)
payAmount.value = Math.abs(paymentItem.balance || 0)
outstandingPayment.value = paymentItem.balance < 0
}
}
// 自动填充欠费金额
const handleAutoFill = () => {
payNum.value = arrearsAmount.value
@@ -214,12 +156,12 @@
const goBack = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
});
}
// 立即缴费
const handlePay = () => {
if (!payAmount.value || Number(payAmount.value) <= 0) {
if (!payNum.value || Number(payNum.value) <= 0) {
uni.showToast({
title: '请输入正确的缴费金额',
icon: 'none'
@@ -227,8 +169,6 @@
return
}
requestPayOrder()
// 原支付注释
// currentStep.value = 2
}
// 统一下单后后端返回的支付参数
const payInfo = ref({
@@ -247,33 +187,79 @@
title: '发起支付中'
})
const res = await getMyHouseList({
deviceNo: '设备号',
money: 0.01, // 金额
openid: '用户openid'
// // 获取 openid
// const loginRes = await wx.login()
// if (!loginRes.code) {
// uni.hideLoading()
// uni.showToast({
// title: '登录失败',
// icon: 'none'
// })
// return
// }
// // 用 code 换 openid
// const openIdRes = await getopenIdByCode({
// code: loginRes.code
// })
// if (openIdRes.code !== 200 || !openIdRes.data) {
// uni.hideLoading()
// uni.showToast({
// title: '获取openid失败',
// icon: 'none'
// })
// return
// }
// const openid = openIdRes.data
const openid = uni.getStorageSync('openid')
// 调用充值接口创建订单
console.log('1111111111', paymentItem);
const topUpRes = await getTopUp({
residentUserId: uni.getStorageSync('userId'),
rechargeAmount: payNum.value,
money: payNum.value || payAmount.value,
deviceCode: paymentItem.deviceCode,
// type: paymentItem.type == '物业费A' ? '2' : paymentItem.type == '物业费B' ? '1' : ''
type:'2'
})
uni.hideLoading()
// 后端返回支付所需参数
const data = res.data
if (data.code !== 0) {
const topUpData = topUpRes
console.log(topUpData);
if (topUpData.code !== 200) {
uni.showToast({
title: data.msg || '下单失败',
title: topUpData.msg || '下单失败',
icon: 'none'
})
return
}
// 调用微信支付接口获取支付参数
const payRes = await getToWxPay({
orderId: topUpData.data.orderId,
openid: openid,
// rechargeAmount: payNum.value || payAmount.value,
// type: paymentItem.type == '物业费A' ? '2' : paymentItem.type == '物业费B' ? '1' : ''
})
if (payRes.code !== 200) {
uni.showToast({
title: payRes.msg || '获取支付参数失败',
icon: 'none'
})
return
}
const payData = payRes.data
console.log('payData', payData);
// 赋值支付参数
payInfo.value = {
appId: data.appId,
timeStamp: data.timeStamp,
nonceStr: data.nonceStr,
package: data.package,
signType: data.signType,
paySign: data.paySign
appId: payData.appId,
timeStamp: payData.timeStamp,
nonceStr: payData.nonceStr,
package: payData.package.startsWith('prepay_id=') ? payData.package : 'prepay_id=' + payData
.package,
signType: payData.signType,
paySign: payData.paySign
}
// 2. 调起微信支付
@@ -281,10 +267,7 @@
...payInfo.value,
success(res) {
console.log('支付成功', res)
uni.showToast({
title: '支付成功'
})
currentStep.value == 3
currentStep.value = 2
},
fail(err) {
console.log('支付失败', err)
@@ -294,6 +277,7 @@
})
}
})
handleWaterElecSubscribe()
} catch (err) {
uni.hideLoading()
@@ -304,55 +288,120 @@
})
}
}
// 关闭密码弹窗
const closePasswordModal = () => {
currentStep.value = 1
password.value = ''
showBankList.value = false
// 【双模板ID】你提供的 物业费A+物业费B 催缴模板
const TEMPLATE_IDS = {
water: 'DowYnoGKNtl_eYycRCq-nt7DAoFjH7aVcGUQciZl1v0',
elec: 'PE7Neemv0z77JnBIPmb-Qg2Q3pJSUDGaILCryFCxmaw'
}
// 转成数组微信API要求
const TEMPLATE_ID_ARRAY = Object.values(TEMPLATE_IDS)
// 选择银行卡
const selectBank = (item) => {
selectedBank.value = item
showBankList.value = false
}
// 输入密码
const inputPassword = (num) => {
if (password.value.length >= 6) return
password.value += num.toString()
// 满6位自动提交
if (password.value.length === 6) {
handleConfirmPay()
}
}
// 删除密码
const deletePassword = () => {
password.value = password.value.slice(0, -1)
}
// 确认支付(模拟)
const handleConfirmPay = () => {
uni.showLoading({
title: '支付中...',
mask: true
// 1. 检测 物业费A+物业费B 订阅状态
const checkAllSubscribeStatus = () => {
uni.getSetting({
withSubscriptions: true,
success: (res) => {
const itemSettings = res.subscriptionsSetting?.itemSettings || {}
console.log('物业费A订阅状态', itemSettings[TEMPLATE_IDS.water])
console.log('物业费B订阅状态', itemSettings[TEMPLATE_IDS.elec])
}
})
}
// 2. 点击开启订阅(主方法)
const handleWaterElecSubscribe = () => {
uni.getSetting({
withSubscriptions: true,
success: (res) => {
const itemSettings = res.subscriptionsSetting?.itemSettings || {}
const waterStatus = itemSettings[TEMPLATE_IDS.water]
const elecStatus = itemSettings[TEMPLATE_IDS.elec]
// 如果任意一个被永久拒绝 → 引导去设置
if ((waterStatus === 'reject' || waterStatus === 'ban') ||
(elecStatus === 'reject' || elecStatus === 'ban')) {
uni.showModal({
title: '开启消息通知',
content: '请前往设置页打开物业费A/物业费B提醒开关',
confirmText: '去设置',
success: (modalRes) => {
if (modalRes.confirm) uni.openSetting()
}
})
return
}
// 正常弹出授权框
requestMultiSubscribe()
}
})
}
// 3. 调用微信授权(根据类型传对应模板)
const requestMultiSubscribe = () => {
const tmplIds = paymentItem.type == '物业费A' ? [TEMPLATE_IDS.water] : paymentItem.type == '物业费B' ? [TEMPLATE_IDS.elec] : TEMPLATE_ID_ARRAY
uni.requestSubscribeMessage({
tmplIds: tmplIds,
success: async (res) => {
console.log('双模板授权结果:', res)
let successCount = 0
// 物业费A授权成功
if (res[TEMPLATE_IDS.water] === 'accept') successCount++
// 物业费B授权成功
if (res[TEMPLATE_IDS.elec] === 'accept') successCount++
if (successCount > 0) {
uni.showToast({
title: `已开启${successCount}项提醒`,
icon: 'success'
})
// 保存用户openid到后端
await saveUserSubscribe()
} else {
uni.showToast({
title: '已取消授权',
icon: 'none'
})
}
},
fail: () => {
uni.showToast({
title: '授权失败',
icon: 'none'
})
}
})
}
// 4. 传给后端:保存订阅信息
const saveUserSubscribe = async () => {
const res = await postSubscribeAuth({
openid: uni.getStorageSync('openid'),
templateIds: paymentItem.type == '物业费A' ? [TEMPLATE_IDS.water] : paymentItem.type == '物业费B' ? [TEMPLATE_IDS.elec] : TEMPLATE_ID_ARRAY,
// deviceCode: paymentItem.deviceCode,
// deviceType: paymentItem.type == '物业费A' ? '2' : paymentItem.type == '物业费B' ? '1' : ''
})
if (res.data == 200) {
console.log('111111111111111', res)
} else {
uni.showToast({
title: `${res.msg}`,
icon: 'none'
})
}
setTimeout(() => {
uni.hideLoading()
currentStep.value = 3
password.value = ''
showBankList.value = false
}, 1500)
}
// 返回缴费列表
const handleBackToList = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
});
}
</script>
<style lang="scss">
@@ -402,6 +451,10 @@
color: #E34D59;
}
.paymentClass {
color: #00aaff;
}
.info-section {
padding-top: 20rpx;
/* margin-bottom: 40rpx; */