fix:修复业绩走势折线图展示问题

This commit is contained in:
hzm
2026-03-17 08:53:49 +08:00
parent ba1687bf97
commit 02669020bc
2 changed files with 41 additions and 22 deletions

View File

@@ -779,20 +779,29 @@ export const fetchFundHistory = async (code, range = '1m') => {
if (Array.isArray(trend) && trend.length) { if (Array.isArray(trend) && trend.length) {
const startMs = start.startOf('day').valueOf(); const startMs = start.startOf('day').valueOf();
// end 可能是当日任意时刻,这里用 end-of-day 包含最后一天
const endMs = end.endOf('day').valueOf(); const endMs = end.endOf('day').valueOf();
const out = trend // 若起始日没有净值,则往前推到最近一日有净值的数据作为有效起始
.filter((d) => d && typeof d.x === 'number' && d.x >= startMs && d.x <= endMs) const validTrend = trend
.filter((d) => d && typeof d.x === 'number' && Number.isFinite(Number(d.y)) && d.x <= endMs)
.sort((a, b) => a.x - b.x);
const startDayEndMs = startMs + 24 * 60 * 60 * 1000 - 1;
const hasPointOnStartDay = validTrend.some((d) => d.x >= startMs && d.x <= startDayEndMs);
let effectiveStartMs = startMs;
if (!hasPointOnStartDay) {
const lastBeforeStart = validTrend.filter((d) => d.x < startMs).pop();
if (lastBeforeStart) effectiveStartMs = lastBeforeStart.x;
}
const out = validTrend
.filter((d) => d.x >= effectiveStartMs && d.x <= endMs)
.map((d) => { .map((d) => {
const value = Number(d.y); const value = Number(d.y);
if (!Number.isFinite(value)) return null;
const date = dayjs(d.x).tz(TZ).format('YYYY-MM-DD'); const date = dayjs(d.x).tz(TZ).format('YYYY-MM-DD');
return { date, value }; return { date, value };
}) });
.filter(Boolean);
// 解析 Data_grandTotal 为多条对比曲线,保存在数组属性 out.grandTotalSeries 上 // 解析 Data_grandTotal 为多条对比曲线,使用同一有效起始日
if (Array.isArray(grandTotal) && grandTotal.length) { if (Array.isArray(grandTotal) && grandTotal.length) {
const grandTotalSeries = grandTotal const grandTotalSeries = grandTotal
.map((series) => { .map((series) => {
@@ -801,7 +810,7 @@ export const fetchFundHistory = async (code, range = '1m') => {
const points = series.data const points = series.data
.filter((item) => Array.isArray(item) && typeof item[0] === 'number') .filter((item) => Array.isArray(item) && typeof item[0] === 'number')
.map(([ts, val]) => { .map(([ts, val]) => {
if (ts < startMs || ts > endMs) return null; if (ts < effectiveStartMs || ts > endMs) return null;
const numVal = Number(val); const numVal = Number(val);
if (!Number.isFinite(numVal)) return null; if (!Number.isFinite(numVal)) return null;
const date = dayjs(ts).tz(TZ).format('YYYY-MM-DD'); const date = dayjs(ts).tz(TZ).format('YYYY-MM-DD');
@@ -814,7 +823,6 @@ export const fetchFundHistory = async (code, range = '1m') => {
.filter(Boolean); .filter(Boolean);
if (grandTotalSeries.length) { if (grandTotalSeries.length) {
// 给数组挂一个属性,供前端图表组件读取
out.grandTotalSeries = grandTotalSeries; out.grandTotalSeries = grandTotalSeries;
} }
} }

View File

@@ -62,9 +62,14 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
const [error, setError] = useState(null); const [error, setError] = useState(null);
const chartRef = useRef(null); const chartRef = useRef(null);
const hoverTimeoutRef = useRef(null); const hoverTimeoutRef = useRef(null);
const clearActiveIndexRef = useRef(null);
const [hiddenGrandSeries, setHiddenGrandSeries] = useState(() => new Set()); const [hiddenGrandSeries, setHiddenGrandSeries] = useState(() => new Set());
const [activeIndex, setActiveIndex] = useState(null); const [activeIndex, setActiveIndex] = useState(null);
useEffect(() => {
clearActiveIndexRef.current = () => setActiveIndex(null);
});
const chartColors = useMemo(() => getChartThemeColors(theme), [theme]); const chartColors = useMemo(() => getChartThemeColors(theme), [theme]);
useEffect(() => { useEffect(() => {
@@ -161,8 +166,11 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
grandAccent3, grandAccent3,
chartColors.text, chartColors.text,
]; ];
const grandDatasets = grandTotalSeries.map((series, idx) => { // 隐藏第一条对比线(数据与图示);第二条用原第一条颜色,第三条用原第二条,顺延
const color = grandColors[idx % grandColors.length]; const visibleGrandSeries = grandTotalSeries.filter((_, idx) => idx > 0);
const grandDatasets = visibleGrandSeries.map((series, displayIdx) => {
const color = grandColors[displayIdx % grandColors.length];
const idx = displayIdx + 1; // 原始索引,用于 hiddenGrandSeries 的 key
const key = `${series.name || 'series'}_${idx}`; const key = `${series.name || 'series'}_${idx}`;
const isHidden = hiddenGrandSeries.has(key); const isHidden = hiddenGrandSeries.has(key);
const pointsByDate = new Map(series.points.map(p => [p.date, p.value])); const pointsByDate = new Map(series.points.map(p => [p.date, p.value]));
@@ -374,6 +382,7 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
chart.tooltip.setActiveElements([], { x: 0, y: 0 }); chart.tooltip.setActiveElements([], { x: 0, y: 0 });
} }
chart.update(); chart.update();
clearActiveIndexRef.current?.();
}, 2000); }, 2000);
} }
}, },
@@ -606,17 +615,19 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
)} )}
</div> </div>
{Array.isArray(data.grandTotalSeries) && {Array.isArray(data.grandTotalSeries) &&
data.grandTotalSeries.map((series, idx) => { data.grandTotalSeries
// 与折线数据使用同一套对比色,且排除红/绿 .filter((_, idx) => idx > 0)
const legendAccent3 = theme === 'light' ? '#f97316' : '#fb923c'; .map((series, displayIdx) => {
const legendColors = [ const idx = displayIdx + 1;
primaryColor, const legendAccent3 = theme === 'light' ? '#f97316' : '#fb923c';
chartColors.muted, const legendColors = [
legendAccent3, primaryColor,
chartColors.text, chartColors.muted,
]; legendAccent3,
const color = legendColors[idx % legendColors.length]; chartColors.text,
const key = `${series.name || 'series'}_${idx}`; ];
const color = legendColors[displayIdx % legendColors.length];
const key = `${series.name || 'series'}_${idx}`;
const isHidden = hiddenGrandSeries.has(key); const isHidden = hiddenGrandSeries.has(key);
let valueText = '--'; let valueText = '--';
if (!isHidden && currentIndex != null && data[currentIndex]) { if (!isHidden && currentIndex != null && data[currentIndex]) {