2
0
Просмотр исходного кода

🐛 fix(stock-chart): 修复空数据处理和优化数据过滤逻辑

- 在useProfitCalculator中添加stockData空数组检查,避免获取最新数据时出错
- 在useStockDataFilter中添加fullData空数组检查,防止未初始化时的索引问题
- 重命名dayNum为selectedDays、offsetNum为trainingProgress,使状态命名更清晰
- 修改数据过滤逻辑,将数据分为历史天数和训练日两部分,确保至少显示365天历史数据
- 添加getTrainingInfo方法,提供训练进度相关信息
- 在useTradeRecords中添加stockData空数组检查,避免交易时出错
yourname 6 месяцев назад
Родитель
Сommit
9606f34fa0

+ 2 - 2
src/client/mobile/components/stock/components/stock-chart/src/hooks/useProfitCalculator.ts

@@ -47,9 +47,9 @@ export function useProfitCalculator(stockData: StockData[], trades: TradeRecord[
     
     
     // 获取当日行情数据
     // 获取当日行情数据
     // 如果没有指定currentDate,则使用最新一天的数据
     // 如果没有指定currentDate,则使用最新一天的数据
-    const currentStockData = currentDate ? 
+    const currentStockData = currentDate ?
       stockData.find((data: StockData) => data.d === currentDate) :
       stockData.find((data: StockData) => data.d === currentDate) :
-      stockData[stockData.length - 1];
+      stockData.length > 0 ? stockData[stockData.length - 1] : undefined;
 
 
     const dailyStats = currentStockData ? {
     const dailyStats = currentStockData ? {
       date: currentStockData.d, // 添加日期
       date: currentStockData.d, // 添加日期

+ 62 - 30
src/client/mobile/components/stock/components/stock-chart/src/hooks/useStockDataFilter.ts

@@ -2,61 +2,93 @@ import { useState, useCallback } from 'react';
 import type { StockData } from '../types/index';
 import type { StockData } from '../types/index';
 
 
 export function useStockDataFilter(fullData: StockData[]) {
 export function useStockDataFilter(fullData: StockData[]) {
-  const [dayNum, setDayNum] = useState(120); // 默认120天
-  const [offsetNum, setOffsetNum] = useState(120); // 默认偏移120天
+  const [selectedDays, setSelectedDays] = useState(120); // 默认120天
+  const [trainingProgress, setTrainingProgress] = useState(0); // 训练日进度
   const [isInitialized, setIsInitialized] = useState(false);
   const [isInitialized, setIsInitialized] = useState(false);
 
 
   const filterData = useCallback(() => {
   const filterData = useCallback(() => {
-    if (!isInitialized) {
-      return []; // 未初始化时返回空数组
+    if (!isInitialized || fullData.length === 0) {
+      return []; // 未初始化或数据为空时返回空数组
     }
     }
 
 
-    const arrLen = fullData.length;
-    // 从最后一天开始往前数 offsetNum 天
-    let endIndex = arrLen - offsetNum;
-    // 从 endIndex 再往前数 dayNum 天
-    let startIndex = endIndex - dayNum;
+    const totalDays = fullData.length;
     
     
-    // 确保索引在有效范围内
-    startIndex = Math.max(0, startIndex);
-    endIndex = Math.max(dayNum, endIndex); // 确保至少显示 dayNum 天的数据
+    // 计算训练日部分:从当前日期往前推选择的天数到当前日期
+    const trainingStartIndex = totalDays - selectedDays;
+    const trainingEndIndex = Math.min(
+      trainingStartIndex + trainingProgress,
+      totalDays
+    );
     
     
-    return fullData.slice(startIndex, endIndex);
-  }, [fullData, dayNum, offsetNum, isInitialized]);
+    // 计算历史天数部分:从训练日开始日期往前推至少365天
+    const historyEndIndex = trainingStartIndex;
+    const historyStartIndex = Math.max(0, historyEndIndex - Math.max(selectedDays, 365));
+    
+    // 确保索引有效
+    if (historyStartIndex >= historyEndIndex) {
+      return []; // 没有历史数据时返回空数组
+    }
+    
+    // 合并历史天数和已加载的训练日数据
+    const historyData = fullData.slice(historyStartIndex, historyEndIndex);
+    const trainingData = fullData.slice(trainingStartIndex, trainingEndIndex);
+    
+    return [...historyData, ...trainingData];
+  }, [fullData, selectedDays, trainingProgress, isInitialized]);
 
 
   const moveToNextDay = useCallback(() => {
   const moveToNextDay = useCallback(() => {
     return new Promise<string>((resolve) => {
     return new Promise<string>((resolve) => {
-      setOffsetNum((prev: number) => {
-        const newOffset = Math.max(0, prev - 1);
-        // 计算新的结束索引
-        const endIndex = fullData.length - newOffset;
+      setTrainingProgress((prev) => {
+        const newProgress = prev + 1;
+        const totalDays = fullData.length;
+        const trainingStartIndex = totalDays - selectedDays;
+        const trainingEndIndex = Math.min(
+          trainingStartIndex + newProgress,
+          totalDays
+        );
+        
         // 返回最新日期
         // 返回最新日期
-        const nextDate = fullData[endIndex - 1]?.d || '';
+        const nextDate = fullData[trainingEndIndex - 1]?.d || '';
         resolve(nextDate);
         resolve(nextDate);
-        return newOffset;
+        return newProgress;
       });
       });
     });
     });
-  }, [fullData]);
+  }, [fullData, selectedDays]);
 
 
-  const resetOffset = useCallback(() => {
-    setOffsetNum(0);
+  const resetTrainingProgress = useCallback(() => {
+    setTrainingProgress(0);
   }, []);
   }, []);
 
 
-  const setDayNumWithOffset = useCallback((num: number) => {
-    setDayNum(num);
-    setOffsetNum(num);
+  const setDayNumWithTraining = useCallback((days: number) => {
+    setSelectedDays(days);
+    setTrainingProgress(0); // 重置训练进度
   }, []);
   }, []);
 
 
   const initializeView = useCallback(() => {
   const initializeView = useCallback(() => {
     setIsInitialized(true);
     setIsInitialized(true);
   }, []);
   }, []);
 
 
+  // 获取当前训练进度信息
+  const getTrainingInfo = useCallback(() => {
+    const totalDays = fullData.length;
+    const trainingStartIndex = totalDays - selectedDays;
+    const totalTrainingDays = Math.min(selectedDays, totalDays - trainingStartIndex);
+    
+    return {
+      currentProgress: trainingProgress,
+      totalTrainingDays,
+      remainingDays: totalTrainingDays - trainingProgress,
+      isTrainingComplete: trainingProgress >= totalTrainingDays
+    };
+  }, [fullData, selectedDays, trainingProgress]);
+
   return {
   return {
     filteredData: filterData(),
     filteredData: filterData(),
     moveToNextDay,
     moveToNextDay,
-    resetOffset,
-    setDayNum: setDayNumWithOffset,
+    resetTrainingProgress,
+    setDayNum: setDayNumWithTraining,
     initializeView,
     initializeView,
-    isInitialized
+    isInitialized,
+    trainingInfo: getTrainingInfo()
   };
   };
-} 
+}

+ 3 - 0
src/client/mobile/components/stock/components/stock-chart/src/hooks/useTradeRecords.ts

@@ -11,6 +11,9 @@ export function useTradeRecords(stockData: StockData[]) {
     if (type === 'BUY' && hasBought) return;
     if (type === 'BUY' && hasBought) return;
     if (type === 'SELL' && !hasBought) return;
     if (type === 'SELL' && !hasBought) return;
 
 
+    // 确保有数据才能进行交易
+    if (stockData.length === 0) return;
+
     const currentDate = stockData[stockData.length - 1]?.d;
     const currentDate = stockData[stockData.length - 1]?.d;
     if (!currentDate) return;
     if (!currentDate) return;