import { Field, FieldVersion, FieldVersionChange } from '../types/field'; /** * 地块版本管理工具 */ // 生成唯一ID const generateId = () => { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; }; // 比较两个值是否不同 const isDifferent = (oldValue: any, newValue: any): boolean => { if (Array.isArray(oldValue) && Array.isArray(newValue)) { return JSON.stringify(oldValue) !== JSON.stringify(newValue); } return oldValue !== newValue; }; // 检测字段变更 const detectChanges = (oldField: Partial, newField: Partial): FieldVersionChange[] => { const changes: FieldVersionChange[] = []; // 需要监控的字段 const monitoredFields = [ 'name', 'code', 'area', 'perimeter', 'location', 'soilType', 'landUseType', 'plantingMode', 'owner', 'ownerPhone', 'contractPeriod', 'certificateNumber', 'tags', 'status', 'elevation', 'slope', 'aspect', 'waterSource', 'remarks', ]; for (const field of monitoredFields) { const oldValue = (oldField as any)[field]; const newValue = (newField as any)[field]; if (isDifferent(oldValue, newValue)) { changes.push({ field, oldValue, newValue, }); } } return changes; }; // 检测边界变更 const isBoundaryChanged = (oldCoordinates: any[], newCoordinates: any[]): boolean => { if (!oldCoordinates || !newCoordinates) return false; if (oldCoordinates.length !== newCoordinates.length) return true; return JSON.stringify(oldCoordinates) !== JSON.stringify(newCoordinates); }; /** * 创建版本记录 */ export const createFieldVersion = ( oldField: Field | null, newField: Field, changeType: FieldVersion['changeType'], changedBy: string, remarks?: string ): FieldVersion | null => { // 如果是新建,创建初始版本 if (changeType === 'create') { return { id: generateId(), fieldId: newField.id, version: 1, changeType: 'create', changes: [], coordinates: newField.coordinates, attributes: { ...newField }, changedBy, changedAt: new Date().toISOString(), remarks: remarks || '创建地块', }; } // 如果没有旧数据,无法比较 if (!oldField) return null; // 检测变更 const attributeChanges = detectChanges(oldField, newField); const boundaryChanged = isBoundaryChanged(oldField.coordinates, newField.coordinates); // 如果有边界变更,添加到变更列表 if (boundaryChanged) { attributeChanges.push({ field: 'coordinates', oldValue: oldField.coordinates.length, newValue: newField.coordinates.length, }); } // 如果没有任何变更,不创建版本 if (attributeChanges.length === 0 && !boundaryChanged) { return null; } // 确定变更类型 let finalChangeType = changeType; if (changeType === 'update-boundary' || changeType === 'update-attributes') { // 自动检测 if (boundaryChanged && attributeChanges.length > 1) { finalChangeType = 'update-boundary'; // 边界变更优先 } else if (boundaryChanged) { finalChangeType = 'update-boundary'; } else { finalChangeType = 'update-attributes'; } } return { id: generateId(), fieldId: newField.id, version: (oldField.currentVersion || 0) + 1, changeType: finalChangeType, changes: attributeChanges, coordinates: boundaryChanged ? newField.coordinates : undefined, attributes: { ...newField }, changedBy, changedAt: new Date().toISOString(), remarks, }; }; /** * 保存版本到localStorage */ export const saveFieldVersion = (version: FieldVersion): void => { try { const key = `field_versions_${version.fieldId}`; const data = localStorage.getItem(key); let versions: FieldVersion[] = data ? JSON.parse(data) : []; // 添加新版本 versions.push(version); // 保存 localStorage.setItem(key, JSON.stringify(versions)); } catch (error) { console.error('保存版本失败:', error); throw error; } }; /** * 加载地块的所有版本 */ export const loadFieldVersions = (fieldId: string): FieldVersion[] => { try { const key = `field_versions_${fieldId}`; const data = localStorage.getItem(key); return data ? JSON.parse(data) : []; } catch (error) { console.error('加载版本失败:', error); return []; } }; /** * 获取特定版本 */ export const getFieldVersion = (fieldId: string, version: number): FieldVersion | null => { const versions = loadFieldVersions(fieldId); return versions.find(v => v.version === version) || null; }; /** * 从版本恢复地块数据 */ export const restoreFromVersion = (version: FieldVersion): Partial => { if (!version.attributes) { throw new Error('版本数据不完整'); } const restored: Partial = { ...version.attributes }; // 如果有边界数据,使用版本的边界 if (version.coordinates) { restored.coordinates = version.coordinates; } return restored; }; /** * 删除地块的所有版本记录 */ export const deleteFieldVersions = (fieldId: string): void => { try { const key = `field_versions_${fieldId}`; localStorage.removeItem(key); } catch (error) { console.error('删除版本失败:', error); } }; /** * 获取版本统计信息 */ export const getVersionStatistics = (fieldId: string) => { const versions = loadFieldVersions(fieldId); return { total: versions.length, byType: versions.reduce((acc, v) => { acc[v.changeType] = (acc[v.changeType] || 0) + 1; return acc; }, {} as Record), latestVersion: versions.length > 0 ? Math.max(...versions.map(v => v.version)) : 0, }; };