From 194f9246ef0171aa4f9f241f4ec506260de89b0b Mon Sep 17 00:00:00 2001
From: hzm <934585316@qq.com>
Date: Tue, 24 Feb 2026 21:36:56 +0800
Subject: [PATCH 1/3] =?UTF-8?q?feat:=20y=E8=BD=B4=E5=9D=90=E6=A0=87?=
=?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=B7=A6=E4=BE=A7=E5=B1=95=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/components/FundIntradayChart.jsx | 51 ++++++++++++++++++++++++----
app/components/FundTrendChart.jsx | 45 +++++++++++++++++++++---
2 files changed, 84 insertions(+), 12 deletions(-)
diff --git a/app/components/FundIntradayChart.jsx b/app/components/FundIntradayChart.jsx
index 4d11516..24748cd 100644
--- a/app/components/FundIntradayChart.jsx
+++ b/app/components/FundIntradayChart.jsx
@@ -1,6 +1,6 @@
'use client';
-import { useMemo } from 'react';
+import { useMemo, useRef, useEffect } from 'react';
import {
Chart as ChartJS,
CategoryScale,
@@ -27,6 +27,9 @@ ChartJS.register(
* referenceNav: 参考净值(最新单位净值),用于计算涨跌幅;未传则用当日第一个估值作为参考。
*/
export default function FundIntradayChart({ series = [], referenceNav }) {
+ const chartRef = useRef(null);
+ const hoverTimeoutRef = useRef(null);
+
const chartData = useMemo(() => {
if (!series.length) return { labels: [], datasets: [] };
const labels = series.map((d) => d.time);
@@ -91,7 +94,7 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
},
y: {
display: true,
- position: 'right',
+ position: 'left',
grid: { color: '#1f2937', drawBorder: false },
ticks: {
color: '#9ca3af',
@@ -100,11 +103,45 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
}
}
},
- onHover: (event, chartElement) => {
- event.native.target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
+ onHover: (event, chartElement, chart) => {
+ const target = event?.native?.target;
+ if (target) {
+ target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
+ }
+
+ const currentChart = chart || chartRef.current;
+ if (!currentChart) return;
+
+ if (hoverTimeoutRef.current) {
+ clearTimeout(hoverTimeoutRef.current);
+ hoverTimeoutRef.current = null;
+ }
+
+ if (chartElement[0]) {
+ hoverTimeoutRef.current = setTimeout(() => {
+ const c = chartRef.current || currentChart;
+ if (!c) return;
+ c.setActiveElements([]);
+ if (c.tooltip) {
+ c.tooltip.setActiveElements([], { x: 0, y: 0 });
+ }
+ c.update();
+ if (target) {
+ target.style.cursor = 'default';
+ }
+ }, 2000);
+ }
}
}), []);
+ useEffect(() => {
+ return () => {
+ if (hoverTimeoutRef.current) {
+ clearTimeout(hoverTimeoutRef.current);
+ }
+ };
+ }, []);
+
const plugins = useMemo(() => [{
id: 'crosshair',
afterDraw: (chart) => {
@@ -157,9 +194,9 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
const valueStr = typeof val === 'number' ? `${val >= 0 ? '+' : ''}${val.toFixed(2)}%` : String(val);
const vw = ctx.measureText(valueStr).width + 8;
ctx.fillStyle = prim;
- ctx.fillRect(rightX - vw, y - 8, vw, 16);
+ ctx.fillRect(leftX, y - 8, vw, 16);
ctx.fillStyle = bgText;
- ctx.fillText(valueStr, rightX - vw / 2, y);
+ ctx.fillText(valueStr, leftX + vw / 2, y);
}
ctx.restore();
}
@@ -191,7 +228,7 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
{displayDate && 估值日期 {displayDate}}
-
+
);
diff --git a/app/components/FundTrendChart.jsx b/app/components/FundTrendChart.jsx
index f8edc06..3a6a45d 100644
--- a/app/components/FundTrendChart.jsx
+++ b/app/components/FundTrendChart.jsx
@@ -35,6 +35,7 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const chartRef = useRef(null);
+ const hoverTimeoutRef = useRef(null);
useEffect(() => {
// If collapsed, don't fetch data unless we have no data yet
@@ -198,7 +199,7 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
},
y: {
display: true,
- position: 'right',
+ position: 'left',
grid: {
color: '#1f2937',
drawBorder: false,
@@ -217,8 +218,42 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
mode: 'index',
intersect: false,
},
- onHover: (event, chartElement) => {
- event.native.target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
+ onHover: (event, chartElement, chart) => {
+ const target = event?.native?.target;
+ if (target) {
+ target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
+ }
+
+ const currentChart = chart || chartRef.current;
+ if (!currentChart) return;
+
+ if (hoverTimeoutRef.current) {
+ clearTimeout(hoverTimeoutRef.current);
+ hoverTimeoutRef.current = null;
+ }
+
+ if (chartElement[0]) {
+ hoverTimeoutRef.current = setTimeout(() => {
+ const c = chartRef.current || currentChart;
+ if (!c) return;
+ c.setActiveElements([]);
+ if (c.tooltip) {
+ c.tooltip.setActiveElements([], { x: 0, y: 0 });
+ }
+ c.update();
+ if (target) {
+ target.style.cursor = 'default';
+ }
+ }, 2000);
+ }
+ }
+ };
+ }, []);
+
+ useEffect(() => {
+ return () => {
+ if (hoverTimeoutRef.current) {
+ clearTimeout(hoverTimeoutRef.current);
}
};
}, []);
@@ -360,10 +395,10 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
const valueStr = (typeof value === 'number' ? value.toFixed(2) : value) + '%';
const valWidth = ctx.measureText(valueStr).width + 8;
ctx.fillStyle = primaryColor;
- ctx.fillRect(rightX - valWidth, y - 8, valWidth, 16);
+ ctx.fillRect(leftX, y - 8, valWidth, 16);
ctx.fillStyle = '#0f172a'; // --background
ctx.textAlign = 'center';
- ctx.fillText(valueStr, rightX - valWidth / 2, y);
+ ctx.fillText(valueStr, leftX + valWidth / 2, y);
}
}
From 42327fc110e86b534c29e8035801a8db918322d6 Mon Sep 17 00:00:00 2001
From: hzm <934585316@qq.com>
Date: Tue, 24 Feb 2026 22:05:11 +0800
Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E6=8A=98=E7=BA=BF=E5=9B=BE2?=
=?UTF-8?q?=E7=A7=92=E5=90=8E=E8=87=AA=E5=8A=A8=E5=A4=B1=E7=84=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/components/FundIntradayChart.jsx | 19 +++++++++----
app/components/FundTrendChart.jsx | 40 +++++++++++++++++-----------
2 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/app/components/FundIntradayChart.jsx b/app/components/FundIntradayChart.jsx
index 24748cd..6fb79a9 100644
--- a/app/components/FundIntradayChart.jsx
+++ b/app/components/FundIntradayChart.jsx
@@ -105,19 +105,28 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
},
onHover: (event, chartElement, chart) => {
const target = event?.native?.target;
- if (target) {
- target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
- }
-
const currentChart = chart || chartRef.current;
if (!currentChart) return;
+ const tooltipActive = currentChart.tooltip?._active ?? [];
+ const activeElements = currentChart.getActiveElements
+ ? currentChart.getActiveElements()
+ : [];
+ const hasActive =
+ (chartElement && chartElement.length > 0) ||
+ (tooltipActive && tooltipActive.length > 0) ||
+ (activeElements && activeElements.length > 0);
+
+ if (target) {
+ target.style.cursor = hasActive ? 'crosshair' : 'default';
+ }
+
if (hoverTimeoutRef.current) {
clearTimeout(hoverTimeoutRef.current);
hoverTimeoutRef.current = null;
}
- if (chartElement[0]) {
+ if (hasActive) {
hoverTimeoutRef.current = setTimeout(() => {
const c = chartRef.current || currentChart;
if (!c) return;
diff --git a/app/components/FundTrendChart.jsx b/app/components/FundTrendChart.jsx
index 3a6a45d..56acd9d 100644
--- a/app/components/FundTrendChart.jsx
+++ b/app/components/FundTrendChart.jsx
@@ -220,10 +220,25 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
},
onHover: (event, chartElement, chart) => {
const target = event?.native?.target;
+ const currentChart = chart || chartRef.current;
+ if (!currentChart) return;
+
+ const tooltipActive = currentChart.tooltip?._active ?? [];
+ const activeElements = currentChart.getActiveElements
+ ? currentChart.getActiveElements()
+ : [];
+ const hasActive =
+ (chartElement && chartElement.length > 0) ||
+ (tooltipActive && tooltipActive.length > 0) ||
+ (activeElements && activeElements.length > 0);
+
if (target) {
- target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
+ target.style.cursor = hasActive ? 'crosshair' : 'default';
}
+ // 仅用于桌面端 hover 改变光标,不在这里做 2 秒清除,避免移动端 hover 事件不稳定
+ },
+ onClick: (_event, _elements, chart) => {
const currentChart = chart || chartRef.current;
if (!currentChart) return;
@@ -232,20 +247,15 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
hoverTimeoutRef.current = null;
}
- if (chartElement[0]) {
- hoverTimeoutRef.current = setTimeout(() => {
- const c = chartRef.current || currentChart;
- if (!c) return;
- c.setActiveElements([]);
- if (c.tooltip) {
- c.tooltip.setActiveElements([], { x: 0, y: 0 });
- }
- c.update();
- if (target) {
- target.style.cursor = 'default';
- }
- }, 2000);
- }
+ hoverTimeoutRef.current = setTimeout(() => {
+ const c = chartRef.current || currentChart;
+ if (!c) return;
+ c.setActiveElements([]);
+ if (c.tooltip) {
+ c.tooltip.setActiveElements([], { x: 0, y: 0 });
+ }
+ c.update();
+ }, 2000);
}
};
}, []);
From 048bd8db57800a7afb307ba63c2fb5c3b554788b Mon Sep 17 00:00:00 2001
From: hzm <934585316@qq.com>
Date: Tue, 24 Feb 2026 23:03:03 +0800
Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E6=8A=98?=
=?UTF-8?q?=E7=BA=BF=E5=9B=BE2=E7=A7=92=E5=90=8E=E8=87=AA=E5=8A=A8?=
=?UTF-8?q?=E5=A4=B1=E7=84=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/components/FundTrendChart.jsx | 41 +++++++++++++++++--------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/app/components/FundTrendChart.jsx b/app/components/FundTrendChart.jsx
index 56acd9d..2cefd7c 100644
--- a/app/components/FundTrendChart.jsx
+++ b/app/components/FundTrendChart.jsx
@@ -238,25 +238,7 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
// 仅用于桌面端 hover 改变光标,不在这里做 2 秒清除,避免移动端 hover 事件不稳定
},
- onClick: (_event, _elements, chart) => {
- const currentChart = chart || chartRef.current;
- if (!currentChart) return;
-
- if (hoverTimeoutRef.current) {
- clearTimeout(hoverTimeoutRef.current);
- hoverTimeoutRef.current = null;
- }
-
- hoverTimeoutRef.current = setTimeout(() => {
- const c = chartRef.current || currentChart;
- if (!c) return;
- c.setActiveElements([]);
- if (c.tooltip) {
- c.tooltip.setActiveElements([], { x: 0, y: 0 });
- }
- c.update();
- }, 2000);
- }
+ onClick: () => {}
};
}, []);
@@ -270,6 +252,27 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
const plugins = useMemo(() => [{
id: 'crosshair',
+ afterEvent: (chart, args) => {
+ const { event, replay } = args || {};
+ if (!event || replay) return; // 忽略动画重放
+
+ const type = event.type;
+ if (type === 'mousemove' || type === 'click') {
+ if (hoverTimeoutRef.current) {
+ clearTimeout(hoverTimeoutRef.current);
+ hoverTimeoutRef.current = null;
+ }
+
+ hoverTimeoutRef.current = setTimeout(() => {
+ if (!chart) return;
+ chart.setActiveElements([]);
+ if (chart.tooltip) {
+ chart.tooltip.setActiveElements([], { x: 0, y: 0 });
+ }
+ chart.update();
+ }, 2000);
+ }
+ },
afterDraw: (chart) => {
const ctx = chart.ctx;
const datasets = chart.data.datasets;