Files
hms/apps/miniprogram/src/components/TrendChart/index.tsx
iven 50eae8b809 feat(miniprogram): 温润东方风全面 UI 重设计
73 文件变更,覆盖全部 40 个页面 SCSS + TabBar 图标 + 组件样式。
统一赤陶主色 #C4623A + 暖米背景 + 衬线标题字体 + 12px 圆角体系。
2026-04-28 00:19:52 +08:00

128 lines
3.3 KiB
TypeScript

import React, { useEffect, useRef, useCallback } from 'react';
import { View, Text } from '@tarojs/components';
import EcCanvas from '../EcCanvas';
import type { EcCanvasRef } from '../EcCanvas';
import './index.scss';
interface TrendChartProps {
data: { date: string; value: number }[];
referenceMin?: number;
referenceMax?: number;
unit?: string;
height?: number;
}
export default function TrendChart({
data,
referenceMin,
referenceMax,
unit = '',
height = 500,
}: TrendChartProps) {
const chartRef = useRef<EcCanvasRef>(null);
const getOption = useCallback(() => {
if (!data || data.length === 0) return null;
const series: any[] = [];
const markArea: any = {};
if (referenceMin != null && referenceMax != null) {
markArea.data = [
[
{
yAxis: referenceMin,
itemStyle: { color: 'rgba(5,150,105,0.08)' },
},
{ yAxis: referenceMax },
],
];
}
series.push({
type: 'line',
data: data.map((d) => d.value),
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: { color: '#0891B2', width: 2 },
itemStyle: { color: '#0891B2' },
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(8,145,178,0.15)' },
{ offset: 1, color: 'rgba(8,145,178,0.01)' },
],
},
},
markArea: markArea.data
? { silent: true, data: markArea.data }
: undefined,
markPoint:
referenceMin != null && referenceMax != null
? {
data: data
.filter((d) => d.value < referenceMin || d.value > referenceMax)
.map((d) => ({
coord: [data.indexOf(d), d.value],
itemStyle: { color: '#DC2626' },
symbolSize: 12,
})),
}
: undefined,
});
return {
grid: { left: 45, right: 15, top: 20, bottom: 30 },
xAxis: {
type: 'category',
data: data.map((d) => d.date.slice(5)),
axisLabel: { fontSize: 10, color: '#94A3B8' },
axisLine: { lineStyle: { color: '#E5E7EB' } },
},
yAxis: {
type: 'value',
axisLabel: { fontSize: 10, color: '#94A3B8' },
splitLine: { lineStyle: { color: '#F3F4F6' } },
},
tooltip: {
trigger: 'axis',
formatter: (params: any) => {
const p = params[0];
const idx = p.dataIndex;
return `${data[idx]?.date || ''}\n${p.value}${unit ? ' ' + unit : ''}`;
},
},
series,
};
}, [data, referenceMin, referenceMax, unit]);
useEffect(() => {
if (chartRef.current && data && data.length > 0) {
const option = getOption();
if (option) {
chartRef.current.setOption(option);
}
}
}, [data, getOption]);
if (!data || data.length === 0) {
return (
<View className='trend-chart-empty'>
<Text className='trend-chart-empty-text'></Text>
</View>
);
}
return (
<View className='trend-chart' style={{ height: `${height}rpx` }}>
<EcCanvas canvasId='trend-chart-canvas' ref={chartRef} height={height} />
</View>
);
}