feat: v1.2 数据可视化与统计增强

新增功能:
- uCharts 集成,支持环形图和折线图
- 统计页分类占比环形图
- 统计页每日趋势折线图
- 统计页增加最大单笔和对比上月指标
- 首页今日支出卡片

组件:
- ChartWrapper 通用图表组件(支持 pie/line/column)
- 支持 H5 和微信小程序双端

依赖:
- 新增 @qiun/ucharts 图表库
This commit is contained in:
2026-05-29 16:28:50 +08:00
parent c7f29aa7a7
commit 7f8b301f95
6 changed files with 2969 additions and 1249 deletions

View File

@@ -0,0 +1,93 @@
<template>
<view class="chart-wrap">
<canvas
:canvas-id="canvasId"
:id="canvasId"
class="chart-canvas"
:style="{ width: width + 'rpx', height: height + 'rpx' }"
@tap="onTap"
></canvas>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, nextTick } from 'vue'
// @ts-ignore
import uCharts from '@qiun/ucharts/u-charts.min.js'
const props = defineProps<{
canvasId: string
type: 'pie' | 'line' | 'column'
chartData: any
width?: number
height?: number
}>()
const emit = defineEmits(['tap'])
let chartInstance: any = null
function drawChart() {
if (!props.chartData) return
const query = uni.createSelectorQuery().in(getCurrentInstance()?.proxy)
query.select(`#${props.canvasId}`)
.fields({ node: true, size: true })
.exec((res) => {
if (!res[0]) return
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = uni.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
const config: any = {
context: ctx,
canvas2d: true,
pixelRatio: dpr,
width: res[0].width,
height: res[0].height,
animation: true,
background: '#FFFFFF',
padding: [15, 15, 15, 15],
...props.chartData
}
chartInstance = new uCharts(config)
})
}
import { getCurrentInstance } from 'vue'
function onTap(e: any) {
chartInstance?.touchLegend(e)
emit('tap', e)
}
onMounted(() => {
nextTick(() => {
setTimeout(drawChart, 100)
})
})
watch(() => props.chartData, () => {
nextTick(() => {
setTimeout(drawChart, 100)
})
}, { deep: true })
</script>
<style lang="scss" scoped>
.chart-wrap {
width: 100%;
display: flex;
justify-content: center;
}
.chart-canvas {
display: block;
}
</style>