first commit

This commit is contained in:
zhouyanli
2026-04-18 08:31:55 +08:00
commit eeb09abc04
989 changed files with 137562 additions and 0 deletions

View File

@@ -0,0 +1,536 @@
<template>
<view class="contentStyle" style="">
<view class="status-bar"></view>
<uni-nav-bar :title="'新增'+paymentType+'缴费'" left-icon="left" @clickLeft="goBack" backgroundColor="transparent"
:border="false">
</uni-nav-bar>
<Loading mask="true" click="true" ref="loading"></Loading>
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<view class="container">
<!-- 顶部蓝色标题栏 -->
<view class="header-card">
<view class="header-icon">
<text class="icon-fire">🔥</text>
</view>
<text class="header-title">燃气费</text>
</view>
<!-- 缴费信息卡片 -->
<view class="info-card">
<view class="form-item">
<text class="label">缴费单位</text>
<text class="company-name">XXXXXXXX燃气有限公司</text>
</view>
<view class="form-item">
<text class="label">缴费单位</text>
<view class="input-wrapper">
<input type="number" placeholder="请输入户号" class="input-field" v-model="userNo" />
<text class="help-link" @click="showPopup = true">如何获取户号?</text>
</view>
</view>
</view>
<!-- 底部协议和提交按钮 -->
<view class="bottom-area">
<view class="agreement">
<checkbox-group @change="handleAgreeChange">
<checkbox :checked="isAgree" />
</checkbox-group>
<text class="agreement-text">已阅并同意</text>
<text class="agreement-link" @click="handleProtocol">协议链接</text>
</view>
<button class="submit-btn" @click="handleSubmit">
提交
</button>
</view>
</view>
<!-- 快速获取户号 底部弹窗 -->
<view v-if="showPopup" class="popup-mask" @click="showPopup = false">
<view class="popup-content" @click.stop>
<view class="popup-header">
<text class="popup-title">快速获取户号</text>
<text class="popup-close" @click="showPopup = false">×</text>
</view>
<view class="popup-list">
<view class="popup-item">
<view class="item-number">1</view>
<view class="item-content">
<text class="item-title">查看缴费通知单</text>
<text class="item-desc">在纸质缴费/催费通知单上查找户号</text>
</view>
</view>
<view class="popup-item">
<view class="item-number">2</view>
<view class="item-content">
<text class="item-title">查询通知短信</text>
<text class="item-desc">搜索手机由缴费单位发送的催缴短信短信中包含户号</text>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
onReady: function(e) {},
components: {
},
computed: {
style() {
var statusBarHeight = this.statusBarHeight;
return statusBarHeight;
},
},
created() {
let statusBarObj = this.getPhoneInfo()
this.statusBarHeight = statusBarObj.statusBarHeight
},
onShow() {
},
mounted() {},
onReady() {
this.$nextTick(() => {
})
},
data() {
return {
/* 设定状态栏默认高度 */
statusBarHeight: 20,
paymentType: uni.getStorageSync('addPaymentType'),
userNo: '',
isAgree: false,
showPopup: false, // 控制弹窗显示
}
},
methods: {
handleAgreeChange(e) {
// e.detail.value 是数组,有值 = 选中,空 = 未选中
this.isAgree = e.detail.value.length > 0
},
// 处理协议链接点击
handleProtocol() {
uni.navigateTo({
})
},
// 处理提交
handleSubmit() {
if (!this.userNo) {
uni.showToast({
title: '请输入户号',
icon: 'none'
})
return
}
if (!this.isAgree) {
uni.showToast({
title: '请先同意协议',
icon: 'none'
})
return
}
uni.showModal({
title: '确认提交',
content: '确认要提交吗?',
success: (res) => {
if (res.confirm) {
uni.showLoading({
title: '提交中...',
mask: true
});
setTimeout(() => {
uni.showToast({
title: '提交成功',
icon: 'success'
});
}, 1000);
setTimeout(() => {
// 提交成功后跳转列表页
uni.hideLoading();
this.goNext()
}, 3000);
}
}
})
},
goNext() {
uni.redirectTo({
url: '/pages/payment-list/addPaymentSuccess',
success: res => {},
fail: () => {},
complete: () => {}
});
},
goBack() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
},
}
</script>
<style lang="scss">
page {
background: #f2f1f6;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
background-color: #f9f9f9;
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 20px;
box-sizing: border-box;
background-color: #fff;
}
.container {
min-height: 100vh;
background-color: #f5f5f5;
padding: 20rpx;
box-sizing: border-box;
}
/* 顶部标题栏 */
.header-card {
background: linear-gradient(135deg, #66b3ff 0%, #4080ff 100%);
border-radius: 20rpx 20rpx 0 0;
padding: 30rpx 40rpx;
display: flex;
align-items: center;
color: #fff;
}
.header-icon {
width: 60rpx;
height: 60rpx;
background-color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
}
.icon-fire {
font-size: 32rpx;
color: #4080ff;
}
.header-title {
font-size: 16px;
font-weight: bold;
}
/* 信息卡片 */
.info-card {
background-color: #fff;
border-radius: 0 0 20rpx 20rpx;
padding: 40rpx;
margin-bottom: 40rpx;
}
.form-item {
margin-bottom: 40rpx;
}
.form-item:last-child {
margin-bottom: 0;
}
.label {
display: block;
font-size: 14px;
color: #565656;
margin-bottom: 20rpx;
}
.company-name {
display: block;
font-size: 16px;
color: #333;
font-weight: 600;
}
.input-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.input-field {
flex: 1;
font-size: 16px;
color: #333;
padding: 10rpx 0;
border: none;
outline: none;
}
.input-field::placeholder {
color: #ccc;
}
.help-link {
font-size: 14px;
color: #4080ff;
white-space: nowrap;
margin-left: 20rpx;
}
/* 底部区域 */
.bottom-area {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
padding: 15px;
box-sizing: border-box;
}
.agreement {
display: flex;
align-items: center;
margin-bottom: 30rpx;
}
.agreement checkbox {
transform: scale(0.8);
margin-right: 10rpx;
}
.agreement-text {
font-size: 14px;
color: #333;
}
.agreement-link {
font-size: 14px;
color: #4080ff;
margin-left: 10rpx;
}
.submit-btn {
width: 100%;
height: 90rpx;
line-height: 90rpx;
background-color: #4080ff;
color: #fff;
border-radius: 10rpx;
font-size: 36rpx;
font-weight: 500;
border: none;
outline: none;
}
.submit-btn[disabled] {
background-color: #a0c4ff;
color: #fff;
opacity: 0.7;
}
/* 弹窗遮罩层 */
.popup-mask {
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;
}
/* 弹窗内容 */
.popup-content {
width: 100%;
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
padding: 30rpx 40rpx 60rpx;
box-sizing: border-box;
animation: slideUp 0.3s ease-out;
}
/* 弹窗标题栏 */
.popup-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 40rpx;
}
.popup-title {
font-size: 16px;
line-height: 30px;
font-weight: bold;
color: #333;
width: 100%;
display: flex;
/* align-items: center; */
justify-content: space-evenly;
border-bottom: 1px solid #ebebeb;
}
.popup-close {
font-size: 48rpx;
color: #999;
line-height: 1;
}
/* 弹窗列表 */
.popup-list {
padding: 0 10rpx;
}
.popup-item {
display: flex;
align-items: flex-start;
margin-bottom: 40rpx;
}
.popup-item:last-child {
margin-bottom: 0;
}
.item-number {
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
border: 2rpx solid #4080ff;
border-radius: 6rpx;
font-size: 28rpx;
font-weight: bold;
color: #4080ff;
margin-right: 20rpx;
flex-shrink: 0;
}
.item-content {
flex: 1;
display: flex;
flex-direction: column;
}
.item-title {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 16rpx;
}
.item-desc {
font-size: 14px;
color: #666;
line-height: 1.5;
}
/* 弹窗动画 */
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
/* 成功提示弹窗 */
.toast-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
z-index: 9999;
}
.toast-content {
background-color: rgba(0, 0, 0, 0.8);
padding: 40rpx 60rpx;
border-radius: 8rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.toast-icon {
width: 60rpx;
height: 60rpx;
line-height: 60rpx;
border-radius: 50%;
background-color: #fff;
color: #1677ff;
font-size: 40rpx;
font-weight: bold;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: center;
}
.toast-text {
color: #fff;
font-size: 28rpx;
}.status-bar{
width: 100vw;
height: 46px;
}
</style>

View File

@@ -0,0 +1,193 @@
<template>
<view class="contentStyle" style="">
<view class="status-bar"></view>
<uni-nav-bar :title="'新增'+paymentType+'缴费'" left-icon="left" @clickLeft="goBack" backgroundColor="transparent"
:border="false">
</uni-nav-bar>
<Loading mask="true" click="true" ref="loading"></Loading>
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<view class="container">
<!-- 成功图标 -->
<view class="success-icon">
<text class="icon-check"></text>
</view>
<!-- 主标题 -->
<view class="title">绑定成功</view>
<!-- 提示文案 -->
<view class="desc">
恭喜您绑定成功费用将在24小时内更新<br>
请您按时查看避免造成费用欠费
</view>
<!-- 操作按钮 -->
<view class="btn-wrap">
<button class="btn-back" @click="goBack">返回生活缴费</button>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
onReady: function(e) {},
components: {
},
computed: {
},
created() {
},
onShow() {
},
mounted() {},
onReady() {
this.$nextTick(() => {
})
},
data() {
return {
/* 设定状态栏默认高度 */
statusBarHeight: 20,
paymentType: uni.getStorageSync('addPaymentType'),
}
},
methods: {
goBack() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
},
}
</script>
<style lang="scss">
page {
background: #f2f1f6;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
background-color: #f9f9f9;
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 20px;
box-sizing: border-box;
background-color: #fff;
}
</style>
<style scoped>
/* 全局容器 */
.container {
min-height: 100vh;
background-color: #f5f5f7;
display: flex;
flex-direction: column;
align-items: center;
padding: 0 30rpx;
box-sizing: border-box;
}
/* 成功图标 */
.success-icon {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
background-color: #1677ff;
display: flex;
align-items: center;
justify-content: center;
margin-top: 200rpx;
margin-bottom: 30rpx;
}
.icon-check {
color: #fff;
font-size: 100rpx;
font-weight: bold;
line-height: 1;
}
/* 主标题 */
.title {
font-size: 44rpx;
font-weight: bold;
color: #000;
margin-bottom: 40rpx;
}
/* 提示文案 */
.desc {
font-size: 32rpx;
color: #666;
line-height: 1.6;
text-align: center;
margin-bottom: 150rpx;
}
/* 按钮容器 */
.btn-wrap {
width: 100%;
}
/* 返回按钮 */
.btn-back {
width: 100%;
height: 96rpx;
line-height: 96rpx;
background-color: #1677ff;
color: #fff;
font-size: 36rpx;
border-radius: 8rpx;
border: none;
padding: 0;
margin: 0;
}
/* 按钮默认样式重置解决uni-app button默认样式问题 */
.btn-back::after {
border: none;
}.status-bar{
width: 100vw;
height: 46px;
}
</style>

View File

@@ -0,0 +1,720 @@
<template>
<view class="contentStyle" style="">
<view class="status-bar"></view>
<uni-nav-bar :title="arrearsPayment" left-icon="left" @clickLeft="goBack" backgroundColor="transparent"
:border="false">
</uni-nav-bar>
<Loading mask="true" click="true" ref="loading"></Loading>
<!-- 表单区域 -->
<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">- ¥1680.00</text>
</view>
<!-- 缴费信息 -->
<view class="info-section" style="">
<view v-if="arrearsPayment=='物业费'">
<view class="info-item">
<text class="info-label">户名</text>
<text class="info-value">桂花园别墅2号楼2层</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">CT物业</text>
</view>
<view class="info-item">
<text class="info-label">可用余额</text>
<text class="info-value">0.00</text>
</view>
<view style="border-bottom: 1px solid #c7c7c7;padding-bottom: 10px;"></view>
<view class="info-payAmountItem">
<text class="info-payAmount">{{'¥'+payAmount}}</text>
</view>
</view>
<view v-else>
<view class="info-item" v-if="arrearsPayment=='暖气费'">
<text class="info-label">房屋</text>
<text class="info-value">桂花园别墅2号楼2层</text>
</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: 1px solid #c7c7c7;padding-bottom: 10px;"></view>
<!-- 缴费金额输入 -->
<view class="input-section" style="display: flex;">
<text class="amount-input" style="width: auto;">¥</text>
<input type="number" v-model="payAmount" class="amount-input" placeholder="点击输入缴费金额">
</input>
</view>
<view class="arrears-row">
<text class="arrears-text">当前欠费金额¥{{ arrearsAmount }}</text>
<text class="auto-fill-btn" @click="handleAutoFill">点击自动填入</text>
</view>
</view>
</view>
<!-- 立即缴费按钮 -->
<view class="btn-section">
<button class="pay-btn" @click="handlePay">立即缴费</button>
</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="/static/propertyImgs/bank-logo.png" mode="aspectFit">
</image>
<text class="bank-name">建设银行储蓄卡(8888)</text>
<text class="arrow-icon">></text>
</view>
</view>
<!-- 银行卡选择列表 -->
<!-- <view v-if="showBankList" class="bank-list">
<view v-for="(item, index) in bankList" :key="index" class="bank-item"
@click="selectBank(item)">
<image class="bank-item-icon" :src="item.icon" mode="aspectFit"></image>
<text class="bank-item-name">{{ item.name }}</text>
<text v-if="selectedBank.id === item.id" class="check-icon">&#xe60c;</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 v-if="currentStep === 3" class="success-page">
<view class="icon-box">
<!-- 成功图标 -->
<view class="success-icon">
<text class="icon"></text>
</view>
</view>
<!-- 成功文字 -->
<view class="success-text">缴费成功</view>
<view class="success-desc">成功缴纳物业费</view>
<!-- 返回按钮 -->
<view class="btn-section">
<button class="pay-btn" @click="handleBackToList">返回生活缴费</button>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
onReady: function(e) {},
components: {
},
computed: {
},
created() {
},
onShow() {
},
mounted() {},
onReady() {
this.$nextTick(() => {
})
},
data() {
return {
/* 设定状态栏默认高度 */
statusBarHeight: 20,
arrearsPayment: uni.getStorageSync('arrearsPayment'),
currentStep: 1, // 1: 详情页 2: 密码弹窗 3: 成功页
payAmount: "1680.00", // 缴费金额
password: "", // 输入的密码
showBankList: false, // 是否显示银行卡列表
arrearsAmount: "21.21",
// 银行卡列表
bankList: [{
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"
}
],
// 默认选中的银行卡
selectedBank: {
id: 1,
name: "建设银行储蓄卡(8888)",
icon: "/static/bank-logo.png"
}
}
},
methods: {
handleAutoFill() {
this.payAmount = this.arrearsAmount;
uni.vibrateShort({
type: "light"
});
},
goBack() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
// 点击立即缴费
handlePay() {
if (!this.payAmount || Number(this.payAmount) <= 0) {
uni.showToast({
title: "请输入正确的缴费金额",
icon: "none"
});
return;
}
this.currentStep = 2;
},
// 关闭密码弹窗
closePasswordModal() {
this.currentStep = 1;
this.password = "";
this.showBankList = false;
},
// 选择银行卡
selectBank(item) {
this.selectedBank = item;
this.showBankList = false;
},
// 输入密码
inputPassword(num) {
if (this.password.length >= 6) return;
this.password += num.toString();
// 密码满6位自动提交
if (this.password.length === 6) {
this.handleConfirmPay();
}
},
// 删除密码
deletePassword() {
this.password = this.password.slice(0, -1);
},
// 确认支付
handleConfirmPay() {
// 这里模拟支付请求,实际项目中调用后端接口
uni.showLoading({
title: "支付中...",
mask: true
});
setTimeout(() => {
uni.hideLoading();
// 支付成功,跳转到成功页
this.currentStep = 3;
this.password = "";
this.showBankList = false;
}, 1500);
},
// 返回生活缴费列表
handleBackToList() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
}
},
}
</script>
<style lang="scss">
page {
background: #f2f1f6;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
background-color: #f9f9f9;
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 20px;
box-sizing: border-box;
background-color: #fff;
}
/* 1. 物业费详情页 */
.pay-page {
width: 100%;
min-height: 100vh;
background-color: #fff;
}
.amount-section {
padding: 30px 0;
text-align: center;
}
.amount-text {
font-size: 28px;
font-weight: 600;
color: #bd3124;
}
.info-section {
padding: 0 15px 15px 15px;
/* margin-bottom: 20px; */
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;
}
.info-label {
font-size: 15px;
color: #666;
}
.info-value {
font-size: 15px;
color: #333;
font-weight: 600;
}
.info-payAmountItem {
height: 50px;
line-height: 50px;
margin-bottom: 30px;
}
.info-payAmount {
font-size: 25px;
color: #333;
font-weight: 600;
}
.input-section {
/* padding: 0 15px; */
}
.amount-input {
width: 100%;
height: 50px;
font-size: 24px;
line-height: 50px;
border: none;
outline: none;
margin-right: 5px;
}
.btn-section {
padding: 0 15px;
}
.pay-btn {
width: 100%;
height: 50px;
line-height: 50px;
background-color: #007aff;
color: #fff;
border-radius: 8px;
font-size: 16px;
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: 12px 12px 0 0;
padding-bottom: 20px;
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
padding: 0 15px;
border-bottom: 1px solid #f0f0f0;
}
.close-icon {
font-size: 22px;
width: 40px;
height: 50px;
display: flex;
align-items: center;
}
.modal-title {
font-size: 17px;
font-weight: 500;
color: #000;
}
.header-right {
width: 40px;
}
.pay-info {
padding: 20px 15px;
text-align: center;
}
.merchant-name {
display: block;
font-size: 16px;
color: #333;
margin-bottom: 10px;
}
.pay-amount {
font-size: 32px;
font-weight: 500;
color: #000;
}
.pay-way {
display: flex;
align-items: center;
justify-content: space-between;
padding: 15px;
border-bottom: 1px solid #f0f0f0;
}
.way-label {
font-size: 15px;
color: #666;
}
.way-content {
display: flex;
align-items: center;
}
.bank-icon {
width: 16px;
height: 16px;
margin-right: 3px;
}
.bank-name {
font-size: 15px;
color: #333;
margin-right: 8px;
}
.arrow-icon {
font-size: 14px;
color: #999;
}
/* 银行卡列表 */
.bank-list {
padding: 0 15px;
border-bottom: 1px solid #f0f0f0;
}
.bank-item {
display: flex;
align-items: center;
height: 50px;
border-bottom: 1px solid #f5f5f5;
}
.bank-item:last-child {
border-bottom: none;
}
.bank-item-icon {
width: 24px;
height: 24px;
margin-right: 10px;
}
.bank-item-name {
flex: 1;
font-size: 15px;
color: #333;
}
.check-icon {
font-size: 18px;
color: #007aff;
}
/* 密码输入框 */
.password-input {
display: flex;
justify-content: space-between;
padding: 20px 15px;
}
.password-item {
width: 50px;
height: 50px;
/* border: 1px solid #dcdcdc; */
background-color: #efefef;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
}
.password-dot {
width: 12px;
height: 12px;
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: 24px;
color: #000;
border: 1px 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. 缴费成功页 */
.success-page {
width: 100%;
min-height: 100vh;
background-color: #fff;
text-align: center;
}
.icon-box {
display: flex;
justify-content: center;
width: 100vw;
height: 150px;
padding: 30px 0px;
}
.success-icon {
/* margin-top: 60px; */
margin-bottom: 20px;
width: 100px;
height: 100px;
font-size: 80px;
color: #007aff;
background-color: #007aff;
color: #fff;
border-radius: 50%;
}
.success-icon .iconfont {}
.success-text {
font-size: 20px;
font-weight: 600;
color: #000;
margin-bottom: 10px;
}
.success-desc {
font-size: 15px;
color: #999;
margin-bottom: 50px;
}
/* 核心:欠费金额行样式 */
.arrears-row {
display: flex;
align-items: center;
justify-content: space-between;
/* padding: 15px; */
margin-bottom: 30px;
}
.arrears-text {
font-size: 14px;
color: #333;
font-weight: 600;
}
.auto-fill-btn {
font-size: 14px;
color: #007aff;
/* 蓝色,匹配设计图 */
font-weight: 500;
padding: 5px 0;
}
.status-bar {
width: 100vw;
height: 46px;
}
</style>

View File

@@ -0,0 +1,659 @@
<template>
<view class="contentStyle" style="">
<view class="status-bar"></view>
<uni-nav-bar :title="arrearsPayment" left-icon="left" @clickLeft="goBack" backgroundColor="transparent"
:border="false">
</uni-nav-bar>
<Loading mask="true" click="true" ref="loading"></Loading>
<!-- 表单区域 -->
<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">- ¥1680.00</text>
</view>
<!-- 缴费信息 -->
<view class="info-section" style="">
<view class="info-item">
<text class="info-label">户名</text>
<text class="info-value">桂花园别墅2号楼2层</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">CT物业</text>
</view>
<view class="info-item" style="border-bottom: 1px solid #c7c7c7;padding-bottom: 10px;">
<text class="info-label">可用余额</text>
<text class="info-value">0.00</text>
</view>
<view class="info-payAmountItem">
<text class="info-payAmount">{{'¥'+payAmount}}</text>
</view>
</view>
<!-- 缴费金额输入 -->
<!-- <view class="input-section">
<input type="number" v-model="payAmount" class="amount-input" placeholder="请输入缴费金额" />
</view> -->
<!-- 立即缴费按钮 -->
<view class="btn-section">
<button class="pay-btn" @click="handlePay">立即缴费</button>
</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="/static/propertyImgs/bank-logo.png" mode="aspectFit">
</image>
<text class="bank-name">建设银行储蓄卡(8888)</text>
<text class="arrow-icon">></text>
</view>
</view>
<!-- 银行卡选择列表 -->
<!-- <view v-if="showBankList" class="bank-list">
<view v-for="(item, index) in bankList" :key="index" class="bank-item"
@click="selectBank(item)">
<image class="bank-item-icon" :src="item.icon" mode="aspectFit"></image>
<text class="bank-item-name">{{ item.name }}</text>
<text v-if="selectedBank.id === item.id" class="check-icon">&#xe60c;</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 v-if="currentStep === 3" class="success-page">
<view class="icon-box">
<!-- 成功图标 -->
<view class="success-icon">
<text class="icon"></text>
</view>
</view>
<!-- 成功文字 -->
<view class="success-text">缴费成功</view>
<view class="success-desc">成功缴纳物业费</view>
<!-- 返回按钮 -->
<view class="btn-section">
<button class="pay-btn" @click="handleBackToList">返回生活缴费</button>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
onReady: function(e) {},
components: {
},
computed: {
},
created() {
},
onShow() {
},
mounted() {},
onReady() {
this.$nextTick(() => {
})
},
data() {
return {
/* 设定状态栏默认高度 */
statusBarHeight: 20,
arrearsPayment: uni.getStorageSync('arrearsPayment'),
currentStep: 1, // 1: 详情页 2: 密码弹窗 3: 成功页
payAmount: "1680.00", // 缴费金额
password: "", // 输入的密码
showBankList: false, // 是否显示银行卡列表
// 银行卡列表
bankList: [{
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"
}
],
// 默认选中的银行卡
selectedBank: {
id: 1,
name: "建设银行储蓄卡(8888)",
icon: "/static/bank-logo.png"
}
}
},
methods: {
goBack() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
// 点击立即缴费
handlePay() {
if (!this.payAmount || Number(this.payAmount) <= 0) {
uni.showToast({
title: "请输入正确的缴费金额",
icon: "none"
});
return;
}
this.currentStep = 2;
},
// 关闭密码弹窗
closePasswordModal() {
this.currentStep = 1;
this.password = "";
this.showBankList = false;
},
// 选择银行卡
selectBank(item) {
this.selectedBank = item;
this.showBankList = false;
},
// 输入密码
inputPassword(num) {
if (this.password.length >= 6) return;
this.password += num.toString();
// 密码满6位自动提交
if (this.password.length === 6) {
this.handleConfirmPay();
}
},
// 删除密码
deletePassword() {
this.password = this.password.slice(0, -1);
},
// 确认支付
handleConfirmPay() {
// 这里模拟支付请求,实际项目中调用后端接口
uni.showLoading({
title: "支付中...",
mask: true
});
setTimeout(() => {
uni.hideLoading();
// 支付成功,跳转到成功页
this.currentStep = 3;
this.password = "";
this.showBankList = false;
}, 1500);
},
// 返回生活缴费列表
handleBackToList() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
}
},
}
</script>
<style lang="scss">
page {
background: #f2f1f6;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
background-color: #f9f9f9;
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 20px;
box-sizing: border-box;
background-color: #fff;
}
/* 1. 物业费详情页 */
.pay-page {
width: 100%;
min-height: 100vh;
background-color: #fff;
}
.amount-section {
padding: 30px 0;
text-align: center;
}
.amount-text {
font-size: 28px;
font-weight: 600;
color: #bd3124;
}
.info-section {
padding: 0 15px 15px 15px;
/* margin-bottom: 20px; */
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;
}
.info-label {
font-size: 15px;
color: #666;
}
.info-value {
font-size: 15px;
color: #333;
font-weight: 600;
}
.info-payAmountItem {
height: 50px;
line-height: 50px;
margin-bottom: 30px;
}
.info-payAmount {
font-size: 25px;
color: #333;
font-weight: 600;
}
.input-section {
padding: 0 15px;
margin-bottom: 30px;
}
.amount-input {
width: 100%;
height: 50px;
font-size: 24px;
border: none;
outline: none;
}
.btn-section {
padding: 0 15px;
}
.pay-btn {
width: 100%;
height: 50px;
line-height: 50px;
background-color: #007aff;
color: #fff;
border-radius: 8px;
font-size: 16px;
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: 12px 12px 0 0;
padding-bottom: 20px;
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
padding: 0 15px;
border-bottom: 1px solid #f0f0f0;
}
.close-icon {
font-size: 22px;
width: 40px;
height: 50px;
display: flex;
align-items: center;
}
.modal-title {
font-size: 17px;
font-weight: 500;
color: #000;
}
.header-right {
width: 40px;
}
.pay-info {
padding: 20px 15px;
text-align: center;
}
.merchant-name {
display: block;
font-size: 16px;
color: #333;
margin-bottom: 10px;
}
.pay-amount {
font-size: 32px;
font-weight: 500;
color: #000;
}
.pay-way {
display: flex;
align-items: center;
justify-content: space-between;
padding: 15px;
border-bottom: 1px solid #f0f0f0;
}
.way-label {
font-size: 15px;
color: #666;
}
.way-content {
display: flex;
align-items: center;
}
.bank-icon {
width: 16px;
height: 16px;
margin-right: 3px;
}
.bank-name {
font-size: 15px;
color: #333;
margin-right: 8px;
}
.arrow-icon {
font-size: 14px;
color: #999;
}
/* 银行卡列表 */
.bank-list {
padding: 0 15px;
border-bottom: 1px solid #f0f0f0;
}
.bank-item {
display: flex;
align-items: center;
height: 50px;
border-bottom: 1px solid #f5f5f5;
}
.bank-item:last-child {
border-bottom: none;
}
.bank-item-icon {
width: 24px;
height: 24px;
margin-right: 10px;
}
.bank-item-name {
flex: 1;
font-size: 15px;
color: #333;
}
.check-icon {
font-size: 18px;
color: #007aff;
}
/* 密码输入框 */
.password-input {
display: flex;
justify-content: space-between;
padding: 20px 15px;
}
.password-item {
width: 50px;
height: 50px;
/* border: 1px solid #dcdcdc; */
background-color: #efefef;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
}
.password-dot {
width: 12px;
height: 12px;
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: 24px;
color: #000;
border: 1px 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. 缴费成功页 */
.success-page {
width: 100%;
min-height: 100vh;
background-color: #fff;
text-align: center;
}
.icon-box {
display: flex;
justify-content: center;
width: 100vw;
height: 150px;
padding: 30px 0px;
}
.success-icon {
/* margin-top: 60px; */
margin-bottom: 20px;
width: 100px;
height: 100px;
font-size: 80px;
color: #007aff;
background-color: #007aff;
color: #fff;
border-radius: 50%;
}
.success-icon .iconfont {}
.success-text {
font-size: 20px;
font-weight: 600;
color: #000;
margin-bottom: 10px;
}
.success-desc {
font-size: 15px;
color: #999;
margin-bottom: 50px;
}.status-bar{
width: 100vw;
height: 46px;
}
</style>

View File

@@ -0,0 +1,387 @@
<template>
<view class="contentStyle" style="">
<view :style="{height:statusBarHeight+'px'}"></view>
<uni-nav-bar title="生活缴费" left-icon="left" @clickLeft="goBack" backgroundColor="transparent" :border="false">
</uni-nav-bar>
<view class="topbox">
<image class="titleImg" src="/static/propertyImgs/payTitle.png"></image>
<image class="payImg" src="/static/propertyImgs/payImg.png"></image>
</view>
<scroll-view class="page" scroll-y="true">
<view class="container">
<!-- 已缴费/欠费列表 -->
<view class="bill-list">
<view class="bill-item" @click="goToBill(item)" v-for="item,index in paymentList" :key="index">
<image class="billIcon" :src="item.icon"></image>
<view class="bill-info">
<view class="bill-title">{{item.name}}
<view class="bill-status debt" v-if="item.status=='已欠费'">已欠费</view>
</view>
<view class="bill-desc">{{item.address}}</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>
</scroll-view>
</view>
</template>
<script>
export default {
onReady: function(e) {
// console.log('onReady')
},
components: {
},
computed: {
},
created() {
},
onShow() {
},
onLoad() {
},
mounted() {},
data() {
return {
/* 设定状态栏默认高度 */
statusBarHeight: 20,
paymentList: [{
id: 1,
name: '物业费',
status: '已欠费',
address: '桂花园别墅2号楼2层',
icon: "/static/propertyImgs/property.png",
},
{
id: 2,
name: '暖气费',
status: '',
address: '山东省日照市东港区桂花园别墅2号楼2层',
icon: "/static/propertyImgs/heating.png",
},
{
id: 3,
name: '电费',
status: '已欠费',
address: '山东省日照市东港区桂花园别墅2号楼2层',
icon: "/static/propertyImgs/electric.png",
}
],
// 新增缴费列表数据
addList: [{
name: "燃气",
type: "gas",
icon: "/static/propertyImgs/gas.png",
iconClass: "gas"
},
{
name: "水",
type: "water",
icon: "/static/propertyImgs/water.png",
iconClass: "water"
},
{
name: "物业",
type: "property",
icon: "/static/propertyImgs/property.png",
iconClass: "property"
},
{
name: "电",
type: "electric",
icon: "/static/propertyImgs/electric.png",
iconClass: "electric"
},
{
name: "暖气",
type: "heating",
icon: "/static/propertyImgs/heating.png",
iconClass: "heating"
},
{
name: "车位",
type: "parking",
icon: "/static/propertyImgs/parkingIcon.png",
iconClass: "parking"
}
]
}
},
methods: {
// 跳转到缴费
goToBill(item) {
uni.setStorageSync('arrearsPayment', item.name)
if (item.status == '已欠费') {
uni.redirectTo({
url: '/pages/payment-list/arrearsPayment',
success: res => {},
fail: () => {},
complete: () => {}
});
} else {
uni.redirectTo({
url: '/pages/payment-list/noArrearsPayment',
success: res => {},
fail: () => {},
complete: () => {}
});
}
},
// 跳转到缴费记录
goToRecord() {
uni.redirectTo({
url: '/pages/payment-list/paymentRecord',
success: res => {},
fail: () => {},
complete: () => {}
});
},
// 跳转到新增缴费
goToAdd(type) {
uni.setStorageSync('addPaymentType', type.name)
uni.redirectTo({
url: '/pages/payment-list/addPayment',
success: res => {},
fail: () => {},
complete: () => {}
});
},
goBack() {
uni.switchTab({
url: '/pages/serviceIndex/serviceIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
},
}
</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 20px;
box-sizing: border-box;
/* background-color: #fff; */
}
.topbox {
height: 80px;
width: 100%;
position: relative;
}
.titleImg {
width: 131px;
height: 37px;
position: absolute;
left: 20px;
bottom: 10px;
}
.payImg {
width: 250px;
height: 230px;
position: absolute;
right: -60px;
bottom: -100px;
}
.container {
/* padding: 15px; */
}
/* ===================== 欠费列表 ===================== */
.bill-list {
margin-bottom: 40rpx;
background-color: #fff;
padding: 15px;
border-radius: 5px;
}
.bill-item {
display: flex;
align-items: center;
background-color: #F6F9FE;
border-radius: 12rpx;
padding: 10px 10px 10px 0px;
margin-bottom: 20rpx;
}
.bill-info {
width: calc(90% - 50px);
flex: 1;
}
.billIcon {
width: 30px;
height: 30px;
margin: 10px;
}
.bill-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 10rpx;
display: flex;
}
.bill-desc {
font-size: 14px;
font-weight: 600;
color: #999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* 已欠费标签 */
.bill-status {
padding: 1px 8px;
border-radius: 15px;
font-size: 12px;
font-weight: 500;
color: #fff;
background-color: #E34D59;
margin-left: 5px;
}
/* 右侧箭头 */
.arrow {
width: 12rpx;
height: 12rpx;
border-right: 4rpx solid #ccc;
border-bottom: 4rpx solid #ccc;
transform: rotate(-45deg);
}
/* ===================== 新增缴费区域 ===================== */
.add-section {
background-color: #fff;
padding: 15px;
border-radius: 5px;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.record-link {
font-size: 14px;
color: #1677ff;
}
/* 网格列表 */
.grid-list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
gap: 13px;
}
.grid-item {
width: calc(25% - 30px);
background-color: #F6F9FE;
border-radius: 12rpx;
padding: 10px;
margin-bottom: 20rpx;
display: flex;
align-items: center;
flex-direction: column;
}
/* 图标容器 */
.icon-box {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background-color: #e6f0ff;
display: flex;
align-items: center;
justify-content: center;
/* margin-right: 24rpx; */
font-size: 40rpx;
}
.iconStyle {
width: 100%;
height: 100%;
}
.item-name {
font-size: 14px;
font-weight: 600;
color: #333;
}
</style>

View File

@@ -0,0 +1,351 @@
<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>
<Loading mask="true" click="true" ref="loading"></Loading>
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<!-- 累计缴费 -->
<view class="total-box">
<view class="total-title">累计缴费</view>
<view class="total-price">¥800.00</view>
<!-- 折线图 Canvas -->
<canvas canvas-id="chargeChart" class="chart-canvas"></canvas>
</view>
<!-- 缴费明细 -->
<view class="list-wrapper">
<!-- 按月份分组渲染 -->
<view class="month-group" v-for="(item, idx) in monthGroups" :key="idx">
<view class="month-title">
{{ item.month }} 缴费 ¥{{ item.total }}
</view>
<view class="item-list">
<view class="bill-item" v-for="bill in item.list" :key="bill.id">
<view class="bill-icon">
<text class="icon">{{ bill.icon }}</text>
</view>
<view class="bill-info">
<view class="name">{{ bill.name }}</view>
<view class="account">{{ bill.account }}</view>
</view>
<view class="bill-price">-{{ bill.amount }}</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
onReady: function(e) {},
components: {
},
computed: {
// 自动按月份分组
monthGroups() {
let map = {}
this.billList.forEach(bill => {
if (!map[bill.month]) {
map[bill.month] = {
month: bill.month,
total: 0,
list: []
}
}
map[bill.month].list.push(bill)
map[bill.month].total += bill.amount
})
return Object.values(map).sort((a, b) => b.month - a.month)
}
},
created() {
},
onShow() {
},
mounted() {},
onReady() {
this.$nextTick(() => {
this.drawLineChart();
})
},
data() {
return {
/* 设定状态栏默认高度 */
statusBarHeight: 20,
// 折线图数据
chart: {
months: ['1月', '2月', '3月', '4月', '5月', '6月'],
values: [100, 140, 230, 100, 130, 100]
},
// ====================== 核心5月6月放在一个list里 ======================
billList: [
// 5月数据
{
id: 1,
month: 5,
name: '燃气费',
account: '123123123123',
amount: 25,
icon: ''
},
{
id: 2,
month: 5,
name: '水费',
account: '123123123123',
amount: 25,
icon: ''
},
// 6月数据
{
id: 3,
month: 6,
name: '燃气费',
account: '123123123123',
amount: 30,
icon: ''
},
{
id: 4,
month: 6,
name: '水费',
account: '123123123123',
amount: 10,
icon: ''
},
{
id: 5,
month: 6,
name: '电费',
account: '123123123123',
amount: 30,
icon: '⚡'
}
]
}
},
methods: {
drawLineChart() {
const ctx = uni.createCanvasContext('chargeChart', this)
const canvasPage = uni.getSystemInfoSync();
const w = canvasPage.windowWidth - 30;
const h = canvasPage.windowHeight * 0.3;
const padding = 40
const stepX = (w - 60) / (this.chart.months.length - 1)
const maxVal = 250
ctx.setFillStyle('#999')
ctx.setFontSize(12)
ctx.setTextAlign('center')
// 绘制网格
ctx.beginPath()
ctx.setStrokeStyle('#d8d8d8')
ctx.setLineWidth(1)
for (let i = 0; i <= 5; i++) {
let y = padding + (h - padding * 2) * (1 - i / 5)
ctx.moveTo(40, y)
ctx.lineTo(w - 20, y)
ctx.fillText(i * 50 + '元', 20, y + 4)
}
ctx.stroke()
// 绘制X轴月份
this.chart.months.forEach((m, i) => {
let x = 40 + i * stepX
ctx.fillText(m, x, h - 20)
})
// 绘制折线
let points = []
this.chart.values.forEach((val, i) => {
let x = 40 + i * stepX
let y = padding + (h - padding * 2) * (1 - val / maxVal)
points.push({
x,
y
})
})
ctx.beginPath()
ctx.setStrokeStyle('#4080FF')
ctx.setLineWidth(2)
points.forEach((p, i) => {
if (i === 0) ctx.moveTo(p.x, p.y)
else ctx.lineTo(p.x, p.y)
})
ctx.stroke()
// 绘制圆点
points.forEach((p, i) => {
ctx.beginPath()
ctx.arc(p.x, p.y, 3, 0, 2 * Math.PI)
ctx.setFillStyle('#fff')
ctx.fill()
ctx.setStrokeStyle('#4080FF')
ctx.setLineWidth(2)
ctx.stroke()
ctx.setFillStyle('#4080FF')
ctx.setFontSize(13)
ctx.fillText(this.chart.values[i] + '元', p.x, p.y - 10)
})
ctx.draw()
},
goBack() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
},
}
</script>
<style lang="scss">
page {
background: #f2f1f6;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
background-color: #f9f9f9;
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 20px;
box-sizing: border-box;
background-color: #fff;
}
.total-box {
padding: 15px;
/* margin-bottom: 10px; */
}
.total-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.total-price {
font-size: 24px;
font-weight: bold;
margin-top: 6px;
margin-bottom: 10px;
}
.chart-canvas {
width: calc(100vw - 30px);
height: 30vh;
}
.list-wrapper {
padding: 0 15px;
}
.month-group {
padding-bottom: 15px;
border-bottom: 1px solid #f2f2f2;
}
.month-group:last-child {
border-bottom: none;
}
.month-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
}
.bill-item {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.bill-icon {
width: 40px;
height: 40px;
background: #e6efff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #4080FF;
margin-right: 12px;
font-size: 18px;
}
.bill-info {
flex: 1;
}
.name {
font-size: 14px;
color: #333;
font-weight: 600;
}
.account {
font-size: 12px;
color: #999;
margin-top: 4px;
}
.bill-price {
font-size: 16px;
color: #333;
}.status-bar{
width: 100vw;
height: 46px;
}
</style>

View File

@@ -0,0 +1,346 @@
<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>
<Loading mask="true" click="true" ref="loading"></Loading>
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<!-- 城市 + 搜索 -->
<view class="search-section">
<!-- 城市选择器 -->
<uni-data-picker placeholder="选择省市" popup-title="选择省市" :localdata="alladdress"
field="code as value, value as text" orderby="value asc" :step-searh="true" self-field="code"
parent-field="code" @change="onchange" v-model="cityValue" class="city-picker">
<view class="city-select">
<text class="city-text ellipsis">{{ selectedCity }}</text>
<text class="arrow-icon"></text>
</view>
</uni-data-picker>
<!-- 搜索框 -->
<!-- <view class="search-input">
<input v-model="keyword" placeholder="请输入缴费单位名称" placeholder-class="ph" />
</view> -->
<view class="search-box">
<input class="search-input" v-model="searchKey" placeholder="请输入缴费单位名称"
placeholder-class="input-placeholder" @input="onSearch" />
<uni-icons type="search" size="20" color="#999" />
</view>
</view>
<!-- <scroll-view scroll-y class="list-scroll"> -->
<view v-for="item in filterList">
<view class="group-title">{{item.name}}</view>
<view class="item" v-for="itemChild in item.children" :key="itemChild.id"
@click="selectItem(itemChild)">
{{ itemChild.name }}
</view>
</view>
<!-- </scroll-view> -->
</scroll-view>
</view>
</template>
<script>
// 引入外部城市数据
import Address from '@/static/js/chinaRegions/picker-region.js'
export default {
onReady: function(e) {},
components: {
},
computed: {
filterList() {
// 没有关键词直接返回全部
if (!this.searchKey) return this.companyList;
const key = this.searchKey.trim().toLowerCase();
// 过滤第一层 + 第二层
return this.companyList.filter(group => {
// 过滤子项:只要子项包含关键词就保留
const hasChild = group.children.some(child =>
child.name.toLowerCase().includes(key)
);
// 同时支持 分组名 搜索(不需要可删除)
const groupMatch = group.name.toLowerCase().includes(key);
return hasChild || groupMatch;
}).map(group => {
// 返回过滤后的子项
return {
...group,
children: group.children.filter(child =>
child.name.toLowerCase().includes(key)
)
};
});
}
},
created() {
},
onShow() {
},
onLoad() {
},
mounted() {},
onReady() {
this.$nextTick(() => {
})
},
data() {
return {
selectedCity: '选择城市',
cityValue: '',
alladdress: Address,
searchKey: '',
/* 设定状态栏默认高度 */
statusBarHeight: 20,
showPicker: false,
keyword: '',
// 列表:一个大数组
companyList: [{
id: 7,
name: '官方机构',
children: [{
id: 1,
name: "XX市燃气集团有限公司"
},
{
id: 2,
name: "XX市供水有限公司"
},
{
id: 3,
name: "XX供电服务中心"
},
{
id: 4,
name: "XX新能源服务公司"
},
{
id: 5,
name: "XX公共事业缴费中心"
},
{
id: 6,
name: "XX综合能源服务站"
}
]
},
{
id: 8,
name: '非智享日照提供的服务单位',
children: [{
id: 9,
name: "XX市燃气集团有限公司"
},
{
id: 10,
name: "XX能源集团"
},
]
}
]
}
},
methods: {
onchange(e) {
console.log('选中text数组:', e.detail.value)
let arr = e.detail.value
let selectedCity = ''
// 拼接省市区
// arr.forEach((item, index) => {
// if (index != arr.length - 1) {
// selectedCity = selectedCity + item.text + '/'
// } else {
// selectedCity = selectedCity + item.text
// }
// })
// 只显示城市判断
if (arr[1].text == '市辖区') {
selectedCity = arr[0].text
} else {
selectedCity = arr[1].text
}
this.selectedCity = selectedCity
},
// 搜索输入事件
onSearch() {
// 实时过滤computed 自动处理
},
goBack() {
uni.redirectTo({
url: '/pages/payment-list/paymentIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
},
}
</script>
<style lang="scss">
page {
background: #f2f1f6;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
background-color: #f9f9f9;
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 20px;
box-sizing: border-box;
background-color: #fff;
}
.search-section {
background-color: #fff;
padding: 10px;
display: flex;
}
/* 隐藏 uni-data-picker 原生样式,只保留点击功能 */
.city-picker {
display: block;
width: auto;
}
/* 自定义城市选择区域,完美还原「日照市 ▼」 */
.city-select {
display: flex;
align-items: center;
padding: 4px 0;
cursor: pointer;
width: 80px;
height: 35px;
}
.ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.city-text {
font-size: 14px;
/* 匹配截图字体大小 */
font-weight: 600;
color: #000000;
line-height: 1;
}
/* 自定义下拉箭头1:1 还原截图样式 */
.arrow-icon {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 8px solid #333333;
/* 纯黑实心三角,和截图一致 */
margin-top: 2px;
}
/* 搜索框 */
.search-box {
display: flex;
width: 100%;
align-items: center;
background-color: #f3f4f6;
border-radius: 50rpx;
/* margin: 0rpx 30rpx 20rpx 30rpx; */
padding: 0 15px;
margin: 0px 0px 0px 5px;
height: 70rpx;
}
.search-input {
flex: 1;
height: 100%;
font-size: 30rpx;
border: none;
background: transparent;
}
.input-placeholder {
color: #999;
font-size: 30rpx;
}
.search-icon {
font-size: 36rpx;
color: #999;
}
/* 列表 */
.list-scroll {
height: calc(100vh - 44px - 70px);
}
.group-title {
padding: 10px 15px;
font-size: 14px;
color: #666;
}
.item {
background: #fff;
padding: 10px 15px;
font-size: 14px;
border-bottom: 1px solid #f2f2f2;
}
.item:active {
background: #f2f2f2;
}
::v-deep .selected-item {
margin-left: 5px !important;
margin-right: 5px !important;
}
.status-bar {
width: 100vw;
height: 46px;
}
</style>