This commit is contained in:
wangyuxin
2026-04-21 17:24:52 +08:00
parent b8fcaff48c
commit fb08057489
36 changed files with 630 additions and 329 deletions

View File

@@ -0,0 +1,486 @@
<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>
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<!-- 累计缴费 -->
<view class="total-box">
<view class="top-box">
<view class="total-title">累计缴费</view>
<view class="total-price">¥800.00</view>
</view>
<!-- 折线图 Canvas -->
<!-- <canvas canvas-id="chargeChart" class="chart-canvas"></canvas> -->
<view class="chart-box">
<view v-if="chartData.length === 0" class="empty-state">
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
<text class="empty-text">
{{ '暂无数据'}}
</text>
</view>
<!-- 循环6个月柱状图 -->
<view class="chart-item" v-for="(item,index) in chartData" :key="index">
<!-- 柱子顶部金额文字 -->
<view class="chart-label">{{ item.price }}</view>
<!-- 柱状图柱子 -->
<view class="chart-bar" :style="{ height: barHeight(item.price) }"></view>
<!-- 底部月份文字 -->
<view class="chart-month">{{ item.month }}</view>
</view>
</view>
</view>
<!-- 缴费明细 -->
<view class="list-wrapper">
<!-- 按月份分组渲染 -->
<view v-if="monthGroups.length === 0" class="empty-state">
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
<text class="empty-text">
{{ '暂无数据'}}
</text>
</view>
<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">
<image class="iconStyle" :src="bill.icon"></image>
</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,
// 完全对应你图片的数据
chartData: [{
month: '1月',
price: 250
},
{
month: '2月',
price: 130
},
{
month: '3月',
price: 220
},
{
month: '4月',
price: 250
},
{
month: '5月',
price: 100
},
{
month: '6月',
price: 130
}
],
maxPrice: 250, // 最大值(基准高度)
barMaxHeight: 300, // 柱子最大高度rpx
// canvas折线图数据
chart: {
months: ['1月', '2月', '3月', '4月', '5月', '6月'],
values: [100, 140, 230, 100, 130, 100]
},
billList: [
// 5月数据
{
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",
},
// 6月数据
{
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",
}
]
}
},
methods: {
// 计算每个柱子自适应高度(按金额比例换算)
barHeight(price) {
const height = (price / this.maxPrice) * this.barMaxHeight
return `${height}rpx`
},
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: '/pageSubPack/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: linear-gradient(to left bottom, #e2efff 0%, #f9f9f9 50%);
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 40rpx;
box-sizing: border-box;
/* background-color: #fff; */
}
.total-box {
margin-bottom: 30rpx;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
color: #ccc;
}
.empty-text {
font-size: 32rpx;
color: #999;
margin-top: 20rpx;
margin-bottom: 10rpx;
}
.top-box {
display: flex;
justify-content: space-between;
align-items: center;
}
.total-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.total-price {
font-size: 48rpx;
font-weight: bold;
margin-top: 10rpx;
margin-bottom: 20rpx;
}
.chart-canvas {
width: calc(100vw - 60rpx);
height: 30vh;
}
.list-wrapper {
padding: 10rpx 0rpx;
}
.month-group {
border-bottom: 2rpx solid #f2f2f2;
padding: 30rpx;
background-color: #fff;
margin-bottom: 30rpx;
border-radius: 10rpx;
}
.month-title {
font-size: 32rpx;
font-weight: 600;
margin-bottom: 30rpx;
}
.bill-item {
display: flex;
align-items: center;
margin-bottom: 30rpx;
padding-bottom: 30rpx;
border-bottom: 1px solid #ebebeb;
}
.bill-item:last-child {
border-bottom: none;
margin-bottom: 0rpx;
padding-bottom: 0rpx;
}
.bill-icon {
width: 80rpx;
height: 80rpx;
/* background: #e6efff; */
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #4080FF;
margin-right: 24rpx;
font-size: 36rpx;
}
.iconStyle {
width: 100%;
height: 100%;
}
.bill-info {
flex: 1;
}
.name {
font-size: 28rpx;
color: #333;
font-weight: 600;
}
.account {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
.bill-price {
font-size: 32rpx;
color: #333;
}
.status-bar {
width: 100vw;
height: 46px;
}
</style>
<style scoped>
/* 图表外层容器 横向排列 */
.chart-box {
width: 100%;
height: 444rpx;
display: flex;
align-items: flex-end;
justify-content: space-around;
/* padding: 40rpx 20rpx; */
box-sizing: border-box;
}
/* 单个柱子单元:垂直排列 文字+柱子+月份 */
.chart-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
width: 120rpx;
font-size: 24rpx;
}
/* 顶部金额标签 */
.chart-label {
font-size: 32rpx;
color: #333;
margin-bottom: 20rpx;
}
/* 蓝色圆角柱子 完全还原原图顶部圆角 */
.chart-bar {
width: 40rpx;
background: #3388ff;
border-radius: 40rpx 40rpx 0 0;
/* 只有顶部圆角!和原图一模一样 */
}
/* 底部月份文字 */
.chart-month {
font-size: 32rpx;
color: #666;
margin-top: 24rpx;
}
</style>