水费缴费部分代码同步

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

@@ -128,6 +128,43 @@ export const getManagePhoneData = (data) => {
export const uploadFileUploadImage = (data) => {
return post(`/api/resident/file/uploadImage`, data)
}
// 水电表
export const getTopUpSelectByResident = (data) => {
console.log(data);
return get(`/api/topUp/selectByResident/${data.residentUserId}`, data)
}
// 绑定设备
export const getTopUpBindDevice = (data) => {
return post(`/api/topUp/bindDevice/${data.deviceCode}/${data.residentUserId}/${data.openid}/${data.deviceType}`,
data)
}
// 充值调用
// /${data.rechargeAmount}/${data.type}/${data.deviceCode}
export const getTopUp = (data) => {
return post(`/api/topUp`, data)
}
export const getopenIdByCode = (data) => {
return get(`/api/topUp/getOpenIdByCode?code=${data.code}`, data)
}
// 微信支付调用
export const getToWxPay = (data) => {
return post(`/api/topUp/wxPay/${data.orderId}/${data.openid}`, data)
}
// 缴费记录查询
export const getTopupRecordWithStat = (data) => {
return get(
`/api/topUp/topupRecordWithStat?residentUserId=${data.residentUserId}&pageNum=${data.pageNum}&pageSize=${data.pageSize}`,
data)
}
export const postInsertOpenId = (data) => {
return post(`/api/resident/auth/insertOpenId`, data)
}
export const postSubscribeAuth = (data) => {
return post(`/api/wx/subscribeAuth/auth`, data)
}
// 添加车辆
export const postCar = (data) => {
return post(`/api/resident/car`, data)

View File

@@ -181,6 +181,7 @@
residentId: uni.getStorageSync('userId')
}).then(res => {
uni.hideLoading()
console.log(res);
if (res.code === 200) {
uni.showToast({
title: '提交成功',
@@ -195,10 +196,17 @@
icon: 'none'
})
}
}).catch(err => {
uni.hideLoading()
uni.showToast({
title: err.msg || '网络异常',
icon: 'none'
})
})
}
}
})
}
const loadParkingSpaceDetail = async () => {
// 防重复请求

View File

@@ -4,7 +4,7 @@
<uni-nav-bar title="我的车辆" left-icon="left" @clickLeft="goBack" backgroundColor="transparent" :border="false">
</uni-nav-bar>
<scroll-view class="page" scroll-y="true">
<scroll-view class="page" scroll-y="true" @scrolltolower="getList" refresher-enabled="true" :refresher-triggered="isRefreshing" @refresherrefresh="onRefresh">
<view v-if="carList.length === 0" class="empty-state">
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
<text class="empty-text">暂无数据</text>
@@ -40,36 +40,25 @@
import {
getMyCarList
} from '@/pageSubPack/api/apiSub.js'
import {
onReachBottom,
onPullDownRefresh
} from '@dcloudio/uni-app'
const statusBarHeight = ref(20)
const defaultCarImg = "http://47.104.199.163:9090/images/propertyImgs/defaultCarImg.png"
const carList = ref([])
const loadingMore = ref(false)
const noMoreData = ref(false)
const isRefreshing = ref(false)
const pageNum = ref(1)
const pageSize = ref(10)
// ==================== 上拉加载更多(页面生命周期) ====================
onReachBottom(() => {
getList()
})
// ==================== 下拉刷新 ====================
const refresh = () => {
// 重置所有状态
pageNum = 1
pageSize = 10
noMoreData = false
houseList = []
loadingMore = false
const onRefresh = () => {
isRefreshing.value = true
pageNum.value = 1
noMoreData.value = false
carList.value = []
loadingMore.value = false
getList()
}
onPullDownRefresh(() => {
refresh()
})
// 页面加载时请求第一页
onMounted(() => {
@@ -110,7 +99,10 @@
console.error('列表接口报错:', err)
} finally {
loadingMore.value = false
uni.stopPullDownRefresh() // 关闭下拉刷新
// 关闭 refresher 下拉刷新状态
if (isRefreshing.value) {
isRefreshing.value = false
}
}
}

View File

@@ -5,7 +5,7 @@
</uni-nav-bar>
<!-- -->
<scroll-view class="page" scroll-y="true">
<scroll-view class="page" scroll-y="true" @scrolltolower="getList" refresher-enabled="true" :refresher-triggered="isRefreshing" @refresherrefresh="onRefresh">
<view v-if="houseList.length === 0" class="empty-state">
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
<text class="empty-text">
@@ -48,8 +48,6 @@
<switch class="no-cross-switch" :checked="item.isDefault==1" color="#1677ff"
@change="onSwitchChange($event,item)" @click.stop />
</view>
<!-- <text v-if="item.showSetDefault" class="set-default"
@click="setDefault(item.id)">设为默认</text> -->
</view>
</view>
</view>
@@ -70,10 +68,6 @@
onMounted,
} from 'vue'
import {
onReachBottom,
onPullDownRefresh
} from '@dcloudio/uni-app'
import {
getMyHouseList,
setMyHouseDefault
@@ -83,6 +77,7 @@
const houseList = ref([])
const loadingMore = ref(false)
const noMoreData = ref(false)
const isRefreshing = ref(false)
const pageNum = ref(1)
const pageSize = ref(10)
@@ -123,28 +118,22 @@
console.error('列表接口报错:', err)
} finally {
loadingMore.value = false
uni.stopPullDownRefresh() // 关闭下拉刷新
// 关闭 refresher 下拉刷新状态
if (isRefreshing.value) {
isRefreshing.value = false
}
}
}
// ==================== 上拉加载更多(页面生命周期) ====================
onReachBottom(() => {
getList()
})
// ==================== 下拉刷新 ====================
const refresh = () => {
// 重置所有状态
pageNum = 1
pageSize = 10
noMoreData = false
houseList = []
loadingMore = false
const onRefresh = () => {
isRefreshing.value = true
pageNum.value = 1
noMoreData.value = false
houseList.value = []
loadingMore.value = false
getList()
}
onPullDownRefresh(() => {
refresh()
})
// 页面加载时请求第一页
onMounted(() => {

View File

@@ -3,7 +3,7 @@
<view class="status-bar"></view>
<uni-nav-bar title="我的车位" left-icon="left" @clickLeft="goBack" backgroundColor="transparent" :border="false">
</uni-nav-bar>
<scroll-view class="page" scroll-y="true">
<scroll-view class="page" scroll-y="true" @scrolltolower="getList" refresher-enabled="true" :refresher-triggered="isRefreshing" @refresherrefresh="onRefresh">
<view v-if="parkingSpaceList.length === 0" class="empty-state">
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
<text class="empty-text">暂无数据</text>
@@ -69,32 +69,19 @@
import {
getCarList
} from '@/pageSubPack/api/apiSub.js'
import {
onReachBottom,
onPullDownRefresh
} from '@dcloudio/uni-app'
const statusBarHeight = ref(20)
const parkingSpaceList = ref([])
// ==================== 上拉加载更多(页面生命周期) ====================
onReachBottom(() => {
getList()
})
// ==================== 下拉刷新 ====================
const refresh = () => {
// 重置所有状态
pageNum = 1
pageSize = 10
noMoreData = false
parkingSpaceList = []
loadingMore = false
const onRefresh = () => {
isRefreshing.value = true
pageNum.value = 1
noMoreData.value = false
parkingSpaceList.value = []
loadingMore.value = false
getList()
}
onPullDownRefresh(() => {
refresh()
})
// 页面加载时请求第一页
onMounted(() => {
@@ -103,6 +90,7 @@
const loadingMore = ref(false)
const noMoreData = ref(false)
const isRefreshing = ref(false)
const pageNum = ref(1)
const pageSize = ref(10)
@@ -142,7 +130,10 @@
console.error('列表接口报错:', err)
} finally {
loadingMore.value = false
uni.stopPullDownRefresh() // 关闭下拉刷新
// 关闭 refresher 下拉刷新状态
if (isRefreshing.value) {
isRefreshing.value = false
}
}
}

View File

@@ -72,7 +72,8 @@
let parkingLotId = uni.getStorageSync('parkingLotId')
if (!parkingLotId) return
getResidentCarAreaManageParkingListByAreaId({
areaId: parkingLotId
areaId: parkingLotId,
}).then(res => {
if (res.code === 200) {
dataList.value = (res.rows || []).map(item => {
@@ -92,6 +93,7 @@
}
const selectedParking = (item) => {
console.log(item);
if (checkType.value == '停车场') {
selectedParkingLot.value = item.id
} else if (checkType.value == '车位编号') {

View File

@@ -7,18 +7,18 @@
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<view class="card-box">
<!-- 头部水费标题+水滴图标 -->
<!-- 头部物业费A标题+水滴图标 -->
<view class="card-header">
<image class="iconStyle"
:src="paymentType==''?'http://47.104.199.163:9090/images/propertyImgs/water.png':'http://47.104.199.163:9090/images/propertyImgs/electric.png'">
:src="paymentType=='物业费A'?'https://wuyeadmin.bugtc.com/images/propertyImgs/water.png':'https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png'">
</image>
<text class="card-title">{{paymentType+'费'}}</text>
<text class="card-title">{{paymentType}}</text>
</view>
<!-- 分割线 -->
<view class="line"></view>
<view class="input-item">
<view class="input-label">缴费单位</view>
<text class="company-name">XXXXXXXX燃气有限公司</text>
<text class="company-name">花开物业</text>
</view>
<!-- 分割线 -->
<view class="line"></view>
@@ -31,7 +31,7 @@
v-model="deviceNo" />
<!-- 右边扫码图标 text标签直接用 双端不乱码 -->
<image class="scanTheCodeIconStyle"
src="http://47.104.199.163:9090/images/propertyImgs/scanTheCodeIcon.png" @click="scanCode">
src="https://wuyeadmin.bugtc.com/images/propertyImgs/scanTheCodeIcon.png" @click="scanCode">
</image>
</view>
</view>
@@ -89,20 +89,18 @@
onPullDownRefresh
} from '@dcloudio/uni-app'
import {
getTopUpBindDevice,
getopenIdByCode
} from '/pageSubPack/api/apiSub.js'
// 响应式数据
const paymentType = ref(uni.getStorageSync('addPaymentType'))
const deviceNo = ref('')
const isAgree = ref(false)
const scanResult = ref('')
// 生命周期
onMounted(() => {})
// 协议勾选
const handleAgreeChange = (e) => {
isAgree.value = e.detail.value.length > 0
}
// 扫码
const scanCode = async () => {
try {
@@ -118,7 +116,6 @@
// 扫码成功,赋值
deviceNo.value = res.result
scanResult.value = res.result
uni.hideLoading()
uni.showToast({
title: '扫码成功',
@@ -135,7 +132,7 @@
}
// 提交缴费
const goPay = () => {
const goPay = async () => {
if (!deviceNo.value) {
uni.showToast({
title: '请输入设备号',
@@ -143,42 +140,70 @@
})
return
}
// if (!isAgree.value) {
// uni.showToast({
// title: '请同意协议',
// icon: 'none'
// })
// return
// }
uni.showModal({
title: '确认提交',
content: '确认要提交吗?',
success: (res) => {
success: async (res) => {
if (res.confirm) {
uni.showLoading({
title: '提交中...',
mask: true
})
setTimeout(() => {
try {
// // 获取 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 = uni.getStorageSync('openid')
await getTopUpBindDevice({
deviceType: paymentType.value=='物业费A'?'2':'1',
deviceCode: deviceNo.value,
openid: openid,
residentUserId: uni.getStorageSync('userId')
})
uni.hideLoading()
uni.showToast({
title: '提交成功',
icon: 'success'
})
}, 1000)
setTimeout(() => {
uni.hideLoading()
goNext()
}, 2500)
}, 1500)
} catch (err) {
uni.hideLoading()
uni.showToast({
title: `${err}`,
icon: 'none'
})
console.error('绑定设备失败:', err)
}
}
}
})
}
const handleProtocol = () => {
}
// 跳转成功页
const goNext = () => {
uni.redirectTo({
@@ -223,7 +248,7 @@
padding: 32rpx;
}
/* 头部水费标题 */
/* 头部物业费A标题 */
.card-header {
display: flex;
align-items: center;
@@ -350,7 +375,7 @@
padding: 32rpx;
}
/* 头部水费标题 */
/* 头部物业费A标题 */
.card-header {
display: flex;
align-items: center;

View File

@@ -13,7 +13,7 @@
<view class="header-card">
<view class="header-icon">
<image class="iconStyle"
:src="paymentType=='燃气'?'http://47.104.199.163:9090/images/propertyImgs/gas.png':'http://47.104.199.163:9090/images/propertyImgs/heating.png'">
:src="paymentType=='燃气'?'https://wuyeadmin.bugtc.com/images/propertyImgs/gas.png':'https://wuyeadmin.bugtc.com/images/propertyImgs/heating.png'">
></image>
</view>
<text class="header-title">{{paymentType+'费'}}</text>
@@ -187,9 +187,7 @@
// 返回
const goBack = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
uni.redirectTo({ url: '/pageSubPack/payment-list/paymentIndex' });
}
</script>
<style lang="scss">

View File

@@ -58,9 +58,7 @@
// 方法
const goBack = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
uni.redirectTo({ url: '/pageSubPack/payment-list/paymentIndex' });
}
</script>

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
}
// 选择银行卡
const selectBank = (item) => {
selectedBank.value = item
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 inputPassword = (num) => {
if (password.value.length >= 6) return
password.value += num.toString()
// 满6位自动提交
if (password.value.length === 6) {
handleConfirmPay()
// 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])
}
}
// 删除密码
const deletePassword = () => {
password.value = password.value.slice(0, -1)
}
// 确认支付(模拟)
const handleConfirmPay = () => {
uni.showLoading({
title: '支付中...',
mask: true
})
}
// 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; */

View File

@@ -11,52 +11,64 @@
<!-- 1. 物业费详情页 -->
<view class="pay-page">
<!-- 未欠费 -->
<view class="amount-section">
<image src="http://47.104.199.163:9090/images/propertyImgs/noArrears.png" class="background-image-style"></image>
<!-- v-if="arrearsPayment=='暖气费'" -->
<view class="no-arrears-section">
<image src="https://wuyeadmin.bugtc.com/images/propertyImgs/noArrears.png"
class="background-image-style"></image>
<text class="noArrearsText">暂未查到欠费</text>
<view class="recordText">
<text>{{'最近缴费'+lastPayTime}}</text>
<text>{{'最近充值'+paymentItem.LastRechargeTime || '-'}}</text>
<text class="lineStyle">{{'|'}}</text>
<text>{{'缴费金额:'+lastPayNum+'元'}}</text>
<text>{{'充值金额:'+paymentItem.LastRechargeAmount+'元' || '-'}}</text>
</view>
</view>
<!-- <view>
<view class="amount-section">
<text class="amount-text">{{'¥'+ Math.abs(paymentItem.balance || 0).toFixed(2)}}</text>
</view>
<view style="border-bottom: 2rpx solid #ededed;margin:10rpx 0rpx;"></view>
</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>
<text
class="info-value">{{paymentItem.villageName+ paymentItem.fullAddress || '-' }}</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">CT物业</text>
<text class="info-value">花开物业</text>
</view>
<view class="info-item">
<text class="info-label">可用余额</text>
<text class="info-value">0.00</text>
<text class="info-value">{{ Math.abs(paymentItem.balance || 0).toFixed(2) }}</text>
</view>
</view>
<view v-else>
<view class="info-item" v-if="arrearsPayment=='暖气费'">
<view class="info-item">
<text class="info-label">房屋</text>
<text class="info-value">桂花园别墅2号楼2层</text>
<text class="info-value">{{ paymentItem.fullAddress || '-' }}</text>
</view>
<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-value">花开物业</text>
</view>
<view class="info-item">
<text class="info-label">可用余额</text>
<text class="info-value">{{ Math.abs(paymentItem.balance || 0).toFixed(2) }}</text>
</view>
</view>
</view>
@@ -67,8 +79,9 @@
</template>
<script setup>
import {
import {
ref,
reactive,
onMounted,
computed
@@ -82,32 +95,31 @@ import {
onPullDownRefresh
} from '@dcloudio/uni-app'
// 响应式数据
const lastPayTime = ref('2022-11-29')
const lastPayNum = ref('2022.00')
const statusBarHeight = ref(20)
const arrearsPayment = ref(uni.getStorageSync('arrearsPayment'))
// 响应式数据
const statusBarHeight = ref(20)
const paymentItem = reactive(uni.getStorageSync('arrearsPayment') || {})
const arrearsPayment = computed(() => paymentItem.type || '缴费')
// 生命周期
onShow(() => {})
onMounted(() => {})
onReady(() => {})
// 生命周期
onShow(() => {})
onMounted(() => {})
onReady(() => {})
// 方法
const goBack = () => {
// 方法
const goBack = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
}
});
}
// 以下为原代码保留的方法(未使用但保持功能完整)
const handlePay = () => {}
const closePasswordModal = () => {}
const selectBank = () => {}
const inputPassword = () => {}
const deletePassword = () => {}
const handleConfirmPay = () => {}
const handleBackToList = () => {}
// 以下为原代码保留的方法(未使用但保持功能完整)
const handlePay = () => {}
const closePasswordModal = () => {}
const selectBank = () => {}
const inputPassword = () => {}
const deletePassword = () => {}
const handleConfirmPay = () => {}
const handleBackToList = () => {}
</script>
<style lang="scss">
@@ -136,6 +148,11 @@ const handleBackToList = () => {}
}
.amount-section {
padding: 60rpx 0;
text-align: center;
}
.no-arrears-section {
padding: 30rpx 0;
text-align: center;
display: flex;
@@ -144,6 +161,12 @@ const handleBackToList = () => {}
color: #999999;
}
.amount-text {
font-size: 56rpx;
font-weight: 600;
color: #007aff;
}
.background-image-style {
width: 466rpx;
height: 250rpx;

View File

@@ -1,30 +1,27 @@
<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="http://47.104.199.163:9090/images/propertyImgs/payTitle.png"></image>
<image class="payImg" src="http://47.104.199.163:9090/images/propertyImgs/payImg.png"></image>
<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 v-if="paymentList.length === 0" class="empty-state">
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
<text class="empty-text">
{{ '暂无数据'}}
</text>
</view> -->
<view class="bill-item" @click="goToBill(item)" v-for="item,index in paymentList" :key="index">
<image class="billIcon" :src="item.icon"></image>
<image class="billIcon" src="https://wuyeadmin.bugtc.com/images/propertyImgs/water.png"
v-if="item.type=='物业费A'"></image>
<image class="billIcon" src="https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png"
v-if="item.type=='物业费B'"></image>
<view class="bill-info">
<view class="bill-title">{{item.name}}
<view class="bill-status debt" v-if="item.status=='已欠费'">已欠费</view>
<view class="bill-title">{{item.type}}
<view class="bill-status debt" v-if="item.balance<0">已欠费</view>
</view>
<view class="bill-desc">{{item.address}}</view>
<view class="bill-desc">{{item.villageName+item.buildingName+item.fullAddress}}</view>
</view>
<view class="arrow"></view>
@@ -40,15 +37,25 @@
<view class="grid-list">
<view class="grid-item" v-for="(item, index) in addList" :key="index"
@click="goToAdd(item)">
<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> -->
<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>
@@ -70,82 +77,162 @@
onUnload,
onPullDownRefresh
} from '@dcloudio/uni-app'
import {
getTopUpSelectByResident,
getopenIdByCode,
postInsertOpenId,
postSubscribeAuth
} from '/pageSubPack/api/apiSub.js'
// 响应式数据
const statusBarHeight = ref(20)
// const subscribeAuth = ref(uni.getStorageSync('subscribeAuth') || '')
const paymentList = ref([{
id: 1,
name: '物业费',
status: '已欠费',
address: '桂花园别墅2号楼2层',
icon: "http://47.104.199.163:9090/images/propertyImgs/property.png",
},
{
id: 2,
name: '暖气费',
status: '',
address: '山东省日照市东港区桂花园别墅2号楼2层',
icon: "http://47.104.199.163:9090/images/propertyImgs/heating.png",
},
{
id: 3,
name: '电费',
status: '已欠费',
address: '山东省日照市东港区桂花园别墅2号楼2层',
icon: "http://47.104.199.163:9090/images/propertyImgs/electric.png",
}
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: '物业费B',
// status: '已欠费',
// address: '山东省日照市东港区桂花园别墅2号楼2层',
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png",
// }
])
const addList = ref([{
name: "燃气",
type: "gas",
icon: "http://47.104.199.163:9090/images/propertyImgs/gas.png",
iconClass: "gas"
},
const addList = ref([
// {
// name: "燃气",
// type: "gas",
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/gas.png",
// iconClass: "gas"
// },
{
name: "",
name: "物业费A",
type: "water",
icon: "http://47.104.199.163:9090/images/propertyImgs/water.png",
icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/water.png",
iconClass: "water"
},
{
name: "物业",
type: "property",
icon: "http://47.104.199.163:9090/images/propertyImgs/property.png",
iconClass: "property"
},
{
name: "电",
type: "electric",
icon: "http://47.104.199.163:9090/images/propertyImgs/electric.png",
iconClass: "electric"
},
// {
// name: "物业",
// type: "property",
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/property.png",
// iconClass: "property"
// },
// {
// name: "物业费B",
// type: "electric",
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png",
// iconClass: "electric"
// },
{
name: "车位",
type: "parking",
icon: "http://47.104.199.163:9090/images/propertyImgs/parkingIcon.png",
iconClass: "parking"
}
// {
// name: "车位",
// type: "parking",
// icon: "https://wuyeadmin.bugtc.com/images/propertyImgs/parkingIcon.png",
// iconClass: "parking"
// }
])
const postOpenId = async () => {
// 获取 openid
try {
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
uni.setStorageSync('openid', openid)
await postInsertOpenId({
openid: uni.getStorageSync('openid'),
residentUserId: uni.getStorageSync('userId')
})
} catch (err) {
uni.showToast({
title: `${err}`,
icon: 'none'
})
console.error('列表接口报错:', err)
}
}
onShow(() => {
// 不再自动请求订阅消息,改为用户点击触发
})
// 生命周期
onReady(() => {})
onShow(() => {})
onLoad(() => {})
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}`,
icon: 'none'
})
console.error('列表接口报错:', err)
} finally {
}
}
// 方法
const goToBill = (item) => {
uni.setStorageSync('arrearsPayment', item.name)
if (item.status == '已欠费') {
uni.setStorageSync('arrearsPayment', item)
// if (item.balance < 0) {
// uni.redirectTo({
// url: '/pageSubPack/payment-list/arrearsPayment'
// })
// } else {
// uni.redirectTo({
// url: '/pageSubPack/payment-list/noArrearsPayment'
// })
// }
uni.redirectTo({
url: '/pageSubPack/payment-list/arrearsPayment'
})
} else {
uni.redirectTo({
url: '/pageSubPack/payment-list/noArrearsPayment'
})
}
}
@@ -160,7 +247,7 @@
uni.redirectTo({
url: '/pageSubPack/payment-list/selectPaymentEntity'
})
} else if (type.name == '' || type.name == '') {
} else if (type.name == '物业费A' || type.name == '物业费B') {
uni.redirectTo({
url: '/pageSubPack/payment-list/addHydropower'
})
@@ -342,7 +429,7 @@
}
.grid-item {
width: calc(25% - 60rpx);
width: calc(25% - 50rpx);
background-color: #F6F9FE;
border-radius: 12rpx;
padding: 20rpx;
@@ -373,6 +460,20 @@
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;

View File

@@ -11,7 +11,7 @@
<view class="total-box">
<view class="top-box">
<view class="total-title">累计缴费</view>
<view class="total-price">¥800.00</view>
<view class="total-price">¥{{ totalAmount }}</view>
</view>
<view class="chart-box">
@@ -51,7 +51,11 @@
<view class="item-list">
<view class="bill-item" v-for="bill in item.list" :key="bill.id">
<view class="bill-icon">
<image class="iconStyle" :src="bill.icon"></image>
<image class="iconStyle" src="https://wuyeadmin.bugtc.com/images/propertyImgs/water.png"
v-if="bill.name=='物业费A'"></image>
<image class="iconStyle" src="https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png"
v-if="bill.name=='物业费B'"></image>
</view>
<view class="bill-info">
<view class="name">{{ bill.name }}</view>
@@ -83,84 +87,97 @@
onPullDownRefresh
} from '@dcloudio/uni-app'
import {
getTopupRecordWithStat
} from '/pageSubPack/api/apiSub.js'
// 响应式数据
const statusBarHeight = ref(20)
const chartData = ref([{
month: '1月',
price: 250
},
{
month: '2月',
price: 130
},
{
month: '3月',
price: 220
},
{
month: '4月',
price: 250
},
{
month: '5月',
price: 100
},
{
month: '6月',
price: 130
}
])
const maxPrice = ref(250)
const pageNum = ref(1)
const pageSize = ref(10)
const totalAmount = ref('0.00')
const chartData = ref([])
const maxPrice = ref(100)
const barMaxHeight = ref(300)
const chart = ref({
months: ['1月', '2月', '3月', '4月', '5月', '6月'],
values: [100, 140, 230, 100, 130, 100]
})
const billList = ref([])
const billList = ref([{
id: 1,
month: 5,
name: '燃气费',
account: '123123123123',
amount: 25,
icon: "http://47.104.199.163:9090/images/propertyImgs/gas.png"
},
{
id: 2,
month: 5,
name: '水费',
account: '123123123123',
amount: 25,
icon: "http://47.104.199.163:9090/images/propertyImgs/water.png"
},
{
id: 3,
month: 6,
name: '燃气费',
account: '123123123123',
amount: 30,
icon: "http://47.104.199.163:9090/images/propertyImgs/gas.png"
},
{
id: 4,
month: 6,
name: '水费',
account: '123123123123',
amount: 10,
icon: "http://47.104.199.163:9090/images/propertyImgs/water.png"
},
{
id: 5,
month: 6,
name: '电费',
account: '123123123123',
amount: 30,
icon: "http://47.104.199.163:9090/images/propertyImgs/electric.png"
// 图标映射
const iconMap = {
'物业费A': 'https://wuyeadmin.bugtc.com/images/propertyImgs/water.png',
'物业费B': 'https://wuyeadmin.bugtc.com/images/propertyImgs/electric.png',
'物业费': 'https://wuyeadmin.bugtc.com/images/propertyImgs/property.png',
'暖气费': 'https://wuyeadmin.bugtc.com/images/propertyImgs/heating.png',
'燃气费': 'https://wuyeadmin.bugtc.com/images/propertyImgs/gas.png'
}
// 获取缴费记录
const getRecords = async () => {
try {
const res = await getTopupRecordWithStat({
residentUserId: uni.getStorageSync('userId'),
pageNum: pageNum.value,
pageSize: pageSize.value
})
if (res.code === 200) {
const records = res.data.records || []
// 转换记录格式
billList.value = records.map(item => ({
id: item.id,
month: item.rechargeTime && item.rechargeTime.split('-')[1] ? parseInt(item.rechargeTime.split('-')[1], 10) : 1,
name: item.type == 1 ? '物业费B' : item.type == 2 ? '物业费A' : '',
account: item.deviceCode || '-',
amount: Number(item.rechargeAmount) || 0,
icon: iconMap[item.type == 1 ? '物业费B' : item.type == 2 ? '物业费A' : ''] || 'https://wuyeadmin.bugtc.com/images/propertyImgs/water.png'
}))
// 累计缴费金额
const total = records.reduce((sum, item) => sum + (Number(item.rechargeAmount) || 0), 0)
totalAmount.value = total.toFixed(2)
// 更新图表数据(根据 records 计算最近6个月
updateChartData()
}
} catch (err) {
console.error('获取缴费记录失败', err)
}
}
// 更新图表数据(根据 records 计算最近6个月
const updateChartData = () => {
// 按月份汇总金额
const monthTotal = {}
billList.value.forEach(bill => {
const monthKey = bill.month
if (!monthTotal[monthKey]) {
monthTotal[monthKey] = 0
}
monthTotal[monthKey] += bill.amount
})
// 取最近6个月当前月往前
const now = new Date()
const currentMonth = now.getMonth() + 1 // 1-12
const currentYear = now.getFullYear()
const months = []
for (let i = 0; i < 6; i++) {
let month = currentMonth - i
let year = currentYear
if (month <= 0) {
month += 12
year -= 1
}
months.push({
month,
year
})
}
chartData.value = months.map((m, i) => ({
month: (m.year + '').slice(-2) + '年' + m.month + '月',
year: m.year,
sortMonth: m.year * 12 + m.month,
price: monthTotal[m.month] || 0,
index: i
})).sort((a, b) => a.sortMonth - b.sortMonth)
const prices = chartData.value.map(c => c.price)
maxPrice.value = Math.max(...prices, 100)
}
])
// 计算属性 —— 月份分组
const monthGroups = computed(() => {
@@ -182,9 +199,10 @@
// 生命周期
onShow(() => {})
onMounted(() => {})
onReady(() => {
drawLineChart()
onLoad(() => {
getRecords()
})
onReady(() => {})
// 方法
const barHeight = (price) => {
@@ -192,81 +210,10 @@
return `${height}rpx`
}
const drawLineChart = () => {
// #ifdef MP-WEIXIN
const ctx = uni.createCanvasContext('chargeChart')
// #endif
// #ifndef MP-WEIXIN
const ctx = uni.createCanvasContext('chargeChart', this)
// #endif
const canvasPage = uni.getSystemInfoSync();
const w = canvasPage.windowWidth - 30;
const h = canvasPage.windowHeight * 0.3;
const padding = 40
const stepX = (w - 60) / (chart.value.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()
chart.value.months.forEach((m, i) => {
let x = 40 + i * stepX
ctx.fillText(m, x, h - 20)
})
let points = []
chart.value.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(chart.value.values[i] + '元', p.x, p.y - 10)
})
ctx.draw()
}
const goBack = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
});
}
</script>
@@ -443,7 +390,7 @@
}
.chart-month {
font-size: 32rpx;
font-size: 26rpx;
color: #666;
margin-top: 24rpx;
}

View File

@@ -233,9 +233,7 @@
const onSearch = () => {}
const goBack = () => {
uni.redirectTo({
url: '/pageSubPack/payment-list/paymentIndex'
})
uni.redirectTo({ url: '/pageSubPack/payment-list/paymentIndex' });
}
</script>