广州矛调粤政易端
xusd
7 days ago d27794814b69d18aeb8ee96a46cae91d5613570c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { useEffect, useRef } from 'react';
 
/**
 * 表单缓存管理器组件 - 仅提供逻辑功能,无UI渲染
 * 
 * @param {Object} props 组件属性
 * @param {Object} props.form 表单实例,用于获取表单数据
 * @param {string} props.cacheKey 缓存的键名
 * @param {string} props.storageType 存储类型,可选值: 'sessionStorage'|'localStorage',默认为'sessionStorage'
 * @param {Array} props.fieldsToWatch 需要监听变化的字段列表,如果为空则监听所有字段
 * @param {Array} props.excludedFields 不应该被自动更新的字段列表,这些字段的值将被保留
 * @param {number} props.debounceTime 防抖时间(毫秒),默认为500毫秒
 * @param {Function} props.onCacheUpdated 缓存更新后的回调函数
 * @returns {null} 不渲染任何UI元素
 */
const FormCacheManager = ({
  form,
  cacheKey = 'form_cache',
  storageType = 'sessionStorage',
  fieldsToWatch = [], 
  excludedFields = [],
  debounceTime = 500,
  onCacheUpdated
}) => {
  // 使用ref保存定时器
  const timerRef = useRef(null);
 
  // 存储表单数据到指定的存储中
  const saveFormToCache = (formData) => {
    try {
      const storage = storageType === 'localStorage' ? localStorage : sessionStorage;
      
      // 获取现有缓存数据
      let existingCache = {};
      try {
        const existingCacheStr = storage.getItem(cacheKey);
        if (existingCacheStr) {
          existingCache = JSON.parse(existingCacheStr);
        }
      } catch (error) {
        console.error('读取现有缓存失败:', error);
      }
      
      // 从现有缓存中提取需要保留的字段
      const preservedFields = {};
      if (excludedFields.length > 0 && Object.keys(existingCache).length > 0) {
        excludedFields.forEach(field => {
          if (existingCache[field] !== undefined) {
            preservedFields[field] = existingCache[field];
          }
        });
      }
      
      // 合并新表单数据和需要保留的字段
      const updatedCache = {
        ...formData,
        ...preservedFields  // 保留的字段会覆盖formData中的同名字段
      };
      
      // 保存更新后的缓存
      storage.setItem(cacheKey, JSON.stringify(updatedCache));
      
      if (onCacheUpdated && typeof onCacheUpdated === 'function') {
        onCacheUpdated(updatedCache);
      }
      
      console.log(`表单数据已缓存到${storageType},键名: ${cacheKey},保留的字段:`, preservedFields);
    } catch (error) {
      console.error('缓存表单数据失败:', error);
    }
  };
 
  // 创建防抖函数
  const debouncedUpdate = () => {
    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => {
      if (form) {
        const currentValues = form.getFieldsValue(fieldsToWatch.length > 0 ? fieldsToWatch : true);
        saveFormToCache(currentValues);
      }
    }, debounceTime);
  };
 
  // 设置初始保存
  useEffect(() => {
    // 确保form存在
    if (!form) {
      console.error('FormCacheManager: form属性是必需的');
      return;
    }
    
    // 给表单一些时间初始化,然后再进行第一次缓存
    // 这样可以避免覆盖之前的缓存
    const initTimer = setTimeout(() => {
      // 初始保存一次表单值
      debouncedUpdate();
    }, 500); // 延迟500ms,确保表单已完全初始化
    
    // 组件卸载时清除定时器
    return () => {
      if (timerRef.current) clearTimeout(timerRef.current);
      clearTimeout(initTimer);
    };
  }, [form, cacheKey, storageType, fieldsToWatch, excludedFields, debounceTime, onCacheUpdated]);
 
  // 监听表单控件的DOM事件
  useEffect(() => {
    if (!form || !form.getFieldInstance) return;
    
    const formNode = document.querySelector('form');
    if (!formNode) return;
    
    // 监听表单元素的输入和变化事件
    const handleFormChange = () => {
      debouncedUpdate();
    };
    
    formNode.addEventListener('input', handleFormChange);
    formNode.addEventListener('change', handleFormChange);
    
    return () => {
      formNode.removeEventListener('input', handleFormChange);
      formNode.removeEventListener('change', handleFormChange);
    };
  }, [form]);
 
  // 逻辑组件不需要渲染任何内容
  return null;
};
 
export default FormCacheManager;