fix: 修复统计图表不显示与对比上月Infinity问题

- ChartWrapper: 添加 type 属性修复 uCharts 不渲染
- ChartWrapper: 使用 pixelRatio=1 避免双重缩放导致字体线条过大
- ChartWrapper: 统一 fontSize/fontColor/padding 配置
- ChartWrapper: 挂载时保存实例引用避免异步回调中 getCurrentInstance 返回 undefined
- stats: Number() 强制类型转换避免字符串导致 Infinity
- stats: !prev 宽松判断覆盖 null/undefined/0 除零情况
- stores: fetchOverview/fetchCategoryStats/fetchTrend 确保数据字段为数字
This commit is contained in:
2026-06-03 11:30:41 +08:00
parent db81ad8eb2
commit 9162b2c87c
3 changed files with 117 additions and 41 deletions

View File

@@ -1,6 +1,7 @@
<template>
<view class="chart-wrap">
<canvas
type="2d"
:canvas-id="canvasId"
:id="canvasId"
class="chart-canvas"
@@ -25,6 +26,8 @@ const props = withDefaults(defineProps<{
const emit = defineEmits(['tap'])
// 挂载时保存实例引用,避免异步回调中 getCurrentInstance 返回 undefined
const instance = getCurrentInstance()
let chartInstance: any = null
function drawChart() {
@@ -39,6 +42,43 @@ function drawChart() {
// #endif
}
function buildConfig(ctx: any, canvas2d: boolean, cssWidth: number, cssHeight: number) {
// canvas 已通过 ctx.scale(dpr) 处理缩放uCharts 用 pixelRatio=1 避免双重缩放
const base: any = {
type: props.type,
context: ctx,
canvas2d,
pixelRatio: 1,
width: cssWidth,
height: cssHeight,
animation: true,
background: '#FFFFFF',
padding: [20, 20, 20, 20],
fontSize: 10,
fontColor: '#8B7E7E',
title: { show: false },
subtitle: { show: false },
legend: { show: false },
dataLabel: false,
enableScroll: false,
...props.chartData
}
// 饼图开启数据标签
if (props.type === 'pie') {
base.dataLabel = true
base.padding = [30, 30, 30, 30]
}
// 折线图/柱状图坐标轴字体
if (props.type === 'line' || props.type === 'column') {
base.xAxis = { fontSize: 10, ...base.xAxis }
base.yAxis = { fontSize: 10, ...base.yAxis }
}
return base
}
function drawChartH5() {
try {
const canvas = document.querySelector(`#${props.canvasId}`) as HTMLCanvasElement
@@ -53,19 +93,7 @@ function drawChartH5() {
canvas.height = rect.height * dpr
ctx.scale(dpr, dpr)
const config: any = {
context: ctx,
canvas2d: true,
pixelRatio: dpr,
width: rect.width,
height: rect.height,
animation: true,
background: '#FFFFFF',
padding: [15, 15, 15, 15],
...props.chartData
}
chartInstance = new uCharts(config)
chartInstance = new uCharts(buildConfig(ctx, true, rect.width, rect.height))
} catch (e) {
console.error('[Chart] H5 draw error:', e)
}
@@ -73,11 +101,18 @@ function drawChartH5() {
function drawChartMP() {
try {
const query = uni.createSelectorQuery().in(getCurrentInstance()?.proxy)
if (!instance?.proxy) return
const query = uni.createSelectorQuery().in(instance.proxy)
query.select(`#${props.canvasId}`)
// @ts-ignore
.fields({ node: true, size: true })
.exec((res) => {
if (!res || !res[0]) return
.exec((res: any) => {
if (!res || !res[0] || !res[0].node) {
console.warn('[Chart] Canvas node not found, fallback to old API')
drawChartMPLegacy()
return
}
const canvas = res[0].node
const ctx = canvas.getContext('2d')
@@ -87,22 +122,29 @@ function drawChartMP() {
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)
chartInstance = new uCharts(buildConfig(ctx, true, res[0].width, res[0].height))
})
} catch (e) {
console.error('[Chart] MP draw error:', e)
drawChartMPLegacy()
}
}
// 兼容旧版小程序 canvas API
function drawChartMPLegacy() {
try {
const ctx = uni.createCanvasContext(props.canvasId, instance?.proxy)
if (!ctx) return
const query = uni.createSelectorQuery().in(instance?.proxy)
query.select(`#${props.canvasId}`)
.boundingClientRect((rect: any) => {
if (!rect) return
chartInstance = new uCharts(buildConfig(ctx, false, rect.width, rect.height))
})
.exec()
} catch (e) {
console.error('[Chart] MP legacy draw error:', e)
}
}