web-app/src/contexts/CaseDataContext.jsx
@@ -3,7 +3,7 @@
 * 提供案件数据的全局状态管理和localStorage持久化
 */
import React, { createContext, useContext, useState, useEffect } from 'react';
import React, { createContext, useContext, useState, useEffect, useRef } from 'react';
import { message } from 'antd';
import ProcessAPIService from '../services/ProcessAPIService';
import { getMergedParams } from '../utils/urlParams';
@@ -22,10 +22,12 @@
 */
export const CaseDataProvider = ({ children }) => {
  const [caseData, setCaseData] = useState(null);
  const [processNodes, setProcessNodes] = useState([]);  // 流程节点数据
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [taskStartTime, setTaskStartTime] = useState(null);  // 任务开始时间
  const [isTaskTimeFallback, setIsTaskTimeFallback] = useState(false);  // 是否降级模式
  const [hasLoaded, setHasLoaded] = useState(false);  // 防止重复加载
  /**
   * 从localStorage读取数据
@@ -97,13 +99,10 @@
   * 加载案件数据
   */
  const loadCaseData = async (forceRefresh = false) => {
    // 如果不是强制刷新,先尝试从localStorage读取
    if (!forceRefresh) {
      const cachedData = loadFromStorage();
      if (cachedData) {
        setCaseData(cachedData);
        console.log('Loaded case data from localStorage');
      }
    // 防止重复加载(除非强制刷新)
    if (hasLoaded && !forceRefresh) {
      console.log('Data already loaded, skipping...');
      return;
    }
    setLoading(true);
@@ -127,8 +126,16 @@
      // 提取timeline数据
      const timelineData = response.timeline || response.data?.timeline || response;
      // 提取nodes数据(确保为数组)
      const nodesData = response.nodes || response.data?.nodes || [];
      console.log('API Response:', response);
      console.log('Extracted nodesData:', nodesData);
      // 更新状态
      setCaseData(timelineData);
      setProcessNodes(Array.isArray(nodesData) ? nodesData : []);  // 确保为数组
      setHasLoaded(true);  // 标记已加载
      
      // 保存到localStorage
      saveToStorage(timelineData);
@@ -144,23 +151,19 @@
      // 显示错误提示
      message.error('加载案件数据失败,请稍后重试');
      
      // 如果localStorage有数据,尝试使用缓存
      const cachedData = loadFromStorage();
      if (cachedData && !forceRefresh) {
        message.warning('已加载历史数据');
        setCaseData(cachedData);
        // 缓存数据也加载任务时间
        await loadTaskTime(cachedData);
      } else {
        // 使用Mock数据
        console.log('使用Mock数据');
      // 使用Mock数据(缓存数据不包含nodes,所以统一使用Mock)
      console.log('===== 使用Mock数据 =====');
        const mockData = mockTimelineData.data.timeline;
      const mockNodes = mockTimelineData.data.nodes || [];
      console.log('mockData:', mockData);
      console.log('mockNodes:', mockNodes);
        setCaseData(mockData);
      setProcessNodes(mockNodes);
        saveToStorage(mockData);
      setHasLoaded(true);
        
        // Mock数据也加载任务时间
        await loadTaskTime(mockData);
      }
    } finally {
      setLoading(false);
    }
@@ -173,17 +176,33 @@
    loadCaseData(true);
  };
  // 防止重复加载的引用标识
  const loadInitRef = useRef(false);
  /**
   * 组件挂载时加载数据
   */
  useEffect(() => {
    console.log('===== CaseDataContext useEffect triggered =====');
    console.log('loadInitRef.current:', loadInitRef.current);
    console.log('hasLoaded:', hasLoaded);
    console.log('processNodes:', processNodes);
    // StrictMode下防止双重调用
    if (!loadInitRef.current) {
      loadInitRef.current = true;
      console.log('Calling loadCaseData()...');
    loadCaseData();
    } else {
      console.log('loadCaseData() skipped due to loadInitRef.current === true');
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []); // 只在挂载时执行一次
  // 提供的值
  const value = {
    caseData,
    processNodes,      // 流程节点数据
    loading,
    error,
    refreshData,