/** * 差异比较工具函数 * 用于编辑时最小化传参,只传递修改过的字段 */ /** * 深度比较两个值是否相等 * @param val1 值1 * @param val2 值2 * @returns 是否相等 */ export function isEqual(val1: any, val2: any): boolean { // 处理 null 和 undefined if (val1 === val2) return true; if (val1 == null || val2 == null) return val1 == val2; // 处理基本类型 if (typeof val1 !== 'object' || typeof val2 !== 'object') { return val1 === val2; } // 处理数组 if (Array.isArray(val1) && Array.isArray(val2)) { if (val1.length !== val2.length) return false; return val1.every((item, index) => isEqual(item, val2[index])); } // 处理对象 if (Array.isArray(val1) !== Array.isArray(val2)) return false; const keys1 = Object.keys(val1); const keys2 = Object.keys(val2); if (keys1.length !== keys2.length) return false; return keys1.every((key) => isEqual(val1[key], val2[key])); } /** * 比较两个对象,返回差异部分 * @param original 原始数据 * @param current 当前数据 * @param options 配置选项 * @returns 差异数据对象 */ export function getChangedFields>( original: T, current: T, options?: { /** 需要包含的字段(即使没有变化也会包含) */ alwaysInclude?: string[]; /** 需要排除的字段(即使有变化也不会包含) */ exclude?: string[]; /** 字段值转换器,用于提交前转换值 */ transformers?: Record any>; } ): Partial { const { alwaysInclude = [], exclude = [], transformers = {} } = options || {}; const changed: Partial = {}; // 遍历当前数据的所有字段 const allKeys = new Set([...Object.keys(original), ...Object.keys(current)]); allKeys.forEach((key) => { // 排除指定字段 if (exclude.includes(key)) return; const originalValue = original[key]; const currentValue = current[key]; // 检查是否需要始终包含 if (alwaysInclude.includes(key)) { const value = transformers[key] ? transformers[key](currentValue) : currentValue; (changed as any)[key] = value; return; } // 比较值是否变化 if (!isEqual(originalValue, currentValue)) { const value = transformers[key] ? transformers[key](currentValue) : currentValue; (changed as any)[key] = value; } }); return changed; } /** * 创建一个用于保存和比较表单数据的工具 * @returns 工具对象 */ export function createFormDiff>() { let originalData: T | null = null; return { /** * 保存原始数据 * @param data 原始数据 */ saveOriginal(data: T) { // 深拷贝保存原始数据 originalData = JSON.parse(JSON.stringify(data)); }, /** * 获取原始数据 * @returns 原始数据 */ getOriginal(): T | null { return originalData; }, /** * 获取变化的字段 * @param current 当前数据 * @param options 配置选项 * @returns 差异数据对象 */ getChanges( current: T, options?: { alwaysInclude?: string[]; exclude?: string[]; transformers?: Record any>; } ): Partial { if (!originalData) { // 如果没有原始数据,返回所有当前数据 return { ...current }; } return getChangedFields(originalData, current, options); }, /** * 检查是否有变化 * @param current 当前数据 * @param exclude 排除的字段 * @returns 是否有变化 */ hasChanges(current: T, exclude?: string[]): boolean { if (!originalData) return true; const changes = getChangedFields(originalData, current, { exclude }); return Object.keys(changes).length > 0; }, /** * 重置原始数据 */ reset() { originalData = null; }, }; }