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

740 lines
15 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="arrearsPayment.value" left-icon="left" @clickLeft="goBack" backgroundColor="transparent"
:border="false">
</uni-nav-bar>
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<view class="container">
<!-- 1. 缴费详情 -->
<view v-if="currentStep === 1" class="pay-page">
<!-- 物业费缴费 -->
<!-- 金额展示 -->
<view class="amount-section">
<text class="amount-text"
:class="{ 'outstandingPaymentClass':outstandingPayment }">{{outstandingPayment?'-¥'+payAmount:'¥'+payAmount}}</text>
</view>
<view style="border-bottom: 2rpx solid #ededed;margin:10rpx 0rpx;"></view>
<!-- 缴费信息 -->
<view class="info-section" style="">
<view>
<view class="info-item">
<text class="info-label">户号</text>
<text class="info-value">101123456</text>
</view>
<view class="info-item">
<text class="info-label">户主</text>
<text class="info-value">周大声</text>
</view>
<view class="info-item">
<text class="info-label">缴费单位</text>
<text class="info-value">HN热力有限公司</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>
</view>
<view style="border-bottom: 2rpx solid #ededed;margin:10rpx 0rpx;"></view>
<view class="arrears-row" v-if="outstandingPayment==true">
<text class="arrears-text">当前欠费金额¥{{ arrearsAmount }}</text>
<text class="auto-fill-btn" @click="handleAutoFill">点击自动填入</text>
</view>
<view class="arrears-row" v-if="outstandingPayment==false">
<text class="arrears-text">暂未查询到欠费</text>
</view>
</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">
<!-- 成功图标 -->
<view class="success-icon">
<text class="icon-check"></text>
</view>
<!-- 主标题 -->
<view class="title">缴费成功</view>
<!-- 提示文案 -->
<view class="desc">
成功缴纳物业费
</view>
</view>
</view>
</scroll-view>
<!-- 立即缴费按钮 -->
<view class="btn-section" v-if="currentStep === 1">
<button class="pay-btn" @click="handlePay">立即缴费</button>
</view>
<!-- 返回按钮 -->
<view class="btn-section" v-if="currentStep === 3">
<button class="pay-btn" @click="handleBackToList">返回生活缴费</button>
</view>
</view>
</template>
<script setup>
import {
ref
} from 'vue'
// 响应式数据
const statusBarHeight = ref(20)
const outstandingPayment = ref(true)
const arrearsPayment = ref(uni.getStorageSync('arrearsPayment'))
const currentStep = ref(1)
const payAmount = ref('1680.00')
const password = ref('')
const showBankList = ref(false)
const arrearsAmount = ref('21.21')
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'
})
// 自动填充欠费金额
const handleAutoFill = () => {
payNum.value = arrearsAmount.value
uni.vibrateShort({
type: 'light'
})
}
// 返回
const goBack = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
}
// 立即缴费
const handlePay = () => {
if (!payAmount.value || Number(payAmount.value) <= 0) {
uni.showToast({
title: '请输入正确的缴费金额',
icon: 'none'
})
return
}
requestPayOrder()
// 原支付注释
// currentStep.value = 2
}
// 统一下单后后端返回的支付参数
const payInfo = ref({
appId: '', // 公众号/小程序ID
timeStamp: '', // 时间戳
nonceStr: '', // 随机串
package: '', // 数据包 如 prepay_id=xxx
signType: 'MD5', // 签名方式
paySign: '' // 签名
})
// 1. 先请求后端接口生成预支付订单
const requestPayOrder = async () => {
try {
uni.showLoading({
title: '发起支付中'
})
const res = await getMyHouseList({
deviceNo: '设备号',
money: 0.01, // 金额
openid: '用户openid'
})
uni.hideLoading()
// 后端返回支付所需参数
const data = res.data
if (data.code !== 0) {
uni.showToast({
title: data.msg || '下单失败',
icon: 'none'
})
return
}
// 赋值支付参数
payInfo.value = {
appId: data.appId,
timeStamp: data.timeStamp,
nonceStr: data.nonceStr,
package: data.package,
signType: data.signType,
paySign: data.paySign
}
// 2. 调起微信支付
wx.requestPayment({
...payInfo.value,
success(res) {
console.log('支付成功', res)
uni.showToast({
title: '支付成功'
})
currentStep.value == 3
},
fail(err) {
console.log('支付失败', err)
uni.showToast({
title: '支付取消或失败',
icon: 'none'
})
}
})
} catch (err) {
uni.hideLoading()
console.log('请求异常', err)
uni.showToast({
title: '支付请求异常',
icon: 'none'
})
}
}
// 关闭密码弹窗
const closePasswordModal = () => {
currentStep.value = 1
password.value = ''
showBankList.value = false
}
// 选择银行卡
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
})
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">
page {
background-color: #f9f9f9;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
background-color: #f9f9f9;
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 40rpx;
box-sizing: border-box;
background-color: #
/* fff */
;
}
/* 1. 物业费详情页 */
.pay-page {
width: 100%;
/* min-height: 100vh; */
/* background-color: #fff; */
}
.amount-section {
padding: 60rpx 0;
text-align: center;
}
.amount-text {
font-size: 56rpx;
font-weight: 600;
}
.outstandingPaymentClass {
color: #E34D59;
}
.info-section {
padding-top: 20rpx;
/* margin-bottom: 40rpx; */
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 80rpx;
}
.info-label {
font-size: 30rpx;
color: #666;
}
.info-value {
font-size: 30rpx;
color: #333;
font-weight: 600;
}
.info-payAmountItem {
height: 100rpx;
line-height: 100rpx;
margin-bottom: 60rpx;
}
.info-payAmount {
font-size: 50rpx;
color: #333;
font-weight: 600;
}
.input-section {
/* padding: 030rpx; */
}
.amount-input {
width: 100%;
height: 100rpx;
font-size: 32rpx;
line-height: 100rpx;
border: none;
outline: none;
margin-right: 10rpx;
}
.btn-section {
padding: 20rpx 30rpx 40rpx;
display: flex;
gap: 20rpx;
}
.pay-btn {
width: 100%;
height: 100rpx;
line-height: 100rpx;
background-color: #007aff;
color: #fff;
border-radius: 16rpx;
font-size: 32rpx;
border: none;
outline: none;
}
/* 2. 支付密码弹窗 */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
display: flex;
align-items: flex-end;
}
.password-modal {
width: 100%;
background-color: #fff;
border-radius: 24rpx 24rpx 0 0;
padding-bottom: 40rpx;
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 100rpx;
padding: 0 30rpx;
border-bottom: 2rpx solid #f0f0f0;
}
.close-icon {
font-size: 44rpx;
width: 80rpx;
height: 100rpx;
display: flex;
align-items: center;
}
.modal-title {
font-size: 32rpx;
font-weight: 500;
color: #000;
}
.header-right {
width: 80rpx;
}
.pay-info {
padding: 40rpx 30rpx;
text-align: center;
}
.merchant-name {
display: block;
font-size: 32rpx;
color: #333;
margin-bottom: 20rpx;
}
.pay-amount {
font-size: 64rpx;
font-weight: 500;
color: #000;
}
.pay-way {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx;
border-bottom: 2rpx solid #f0f0f0;
}
.way-label {
font-size: 30rpx;
color: #666;
}
.way-content {
display: flex;
align-items: center;
}
.bank-icon {
width: 32rpx;
height: 32rpx;
margin-right: 6rpx;
}
.bank-name {
font-size: 30rpx;
color: #333;
margin-right: 16rpx;
}
.arrow-icon {
font-size: 28rpx;
color: #999;
}
/* 银行卡列表 */
.bank-list {
padding: 030rpx;
border-bottom: 2rpx solid #f0f0f0;
}
.bank-item {
display: flex;
align-items: center;
height: 100rpx;
border-bottom: 2rpx solid #f5f5f5;
}
.bank-item:last-child {
border-bottom: none;
}
.bank-item-icon {
width: 48rpx;
height: 48rpx;
margin-right: 20rpx;
}
.bank-item-name {
flex: 1;
font-size: 30rpx;
color: #333;
}
.check-icon {
font-size: 36rpx;
color: #007aff;
}
/* 密码输入框 */
.password-input {
display: flex;
justify-content: space-between;
padding: 40rpx 30rpx;
}
.password-item {
width: 100rpx;
height: 100rpx;
/* border: 2rpx solid #dcdcdc; */
background-color: #efefef;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
}
.password-dot {
width: 24rpx;
height: 24rpx;
background-color: #000;
border-radius: 50%;
}
/* 数字键盘 */
.keyboard {
width: 100%;
}
.keyboard-row {
display: flex;
}
.keyboard-item {
flex: 1;
height: 54px;
line-height: 54px;
text-align: center;
font-size: 48rpx;
color: #000;
border: 2rpx solid #f0f0f0;
background-color: #fff;
}
.keyboard-item:active {
background-color: #e5e5e5;
}
.keyboard-item.empty {
background-color: #f5f5f5;
border: none;
}
.keyboard-item.delete {
background-color: #f5f5f5;
border: none;
}
/* 3. 缴费成功页 */
/* 全局容器 */
.container {
display: flex;
flex-direction: column;
align-items: center;
}
/* 成功图标 */
.success-icon {
width: 220rpx;
height: 220rpx;
border-radius: 50%;
background-color: #1677ff;
display: flex;
align-items: center;
justify-content: center;
margin-top: 200rpx;
margin-bottom: 60rpx;
}
.icon-check {
color: #fff;
font-size: 130rpx;
font-weight: bold;
line-height: 1;
}
/* 主标题 */
.title {
font-size: 40rpx;
font-weight: bold;
color: #000;
margin-bottom: 20rpx;
}
/* 提示文案 */
.desc {
font-size: 32rpx;
color: #666;
line-height: 1.6;
text-align: center;
margin-bottom: 150rpx;
}
/* 核心:欠费金额行样式 */
.arrears-row {
display: flex;
align-items: center;
justify-content: space-between;
/* padding:30rpx; */
margin-bottom: 60rpx;
}
.arrears-text {
font-size: 28rpx;
color: #999;
}
.auto-fill-btn {
font-size: 28rpx;
color: #007aff;
/* 蓝色,匹配设计图 */
font-weight: 500;
padding: 10rpx 0;
}
.status-bar {
width: 100vw;
height: 46px;
}
</style>