diff --git a/src/components/FormField/components/Spreadsheet/index.js b/src/components/FormField/components/Spreadsheet/index.js index 7b9343f..98efc27 100644 --- a/src/components/FormField/components/Spreadsheet/index.js +++ b/src/components/FormField/components/Spreadsheet/index.js @@ -4,6 +4,24 @@ import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'; import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US'; import '@univerjs/preset-sheets-core/lib/index.css'; +const TAG_RE = /^\{\{gepafin_field:[^|]+\|[^}]+}}$/; + +const buildTagMap = (workbookData) => { + const map = {}; + if (!workbookData?.sheets) return map; + const sheetId = workbookData.sheetOrder?.[0]; + const sheet = sheetId ? workbookData.sheets[sheetId] : Object.values(workbookData.sheets)[0]; + if (!sheet?.cellData) return map; + Object.entries(sheet.cellData).forEach(([r, row]) => { + Object.entries(row).forEach(([c, cell]) => { + if (typeof cell.f === 'string' && TAG_RE.test(cell.f)) { + map[`${r}:${c}`] = { v: cell.v, f: cell.f }; + } + }); + }); + return map; +}; + const parseWorkbook = (val) => { if (!val) return null; if (typeof val === 'object' && val.sheets) return val; @@ -23,6 +41,8 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => { const univerRef = useRef(null); const univerAPIRef = useRef(null); const saveTimerRef = useRef(null); + const isRestoringRef = useRef(false); + const tagCellMapRef = useRef({}); useEffect(() => { if (!containerRef.current) return; @@ -43,8 +63,40 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => { univerAPIRef.current = univerAPI; const initialData = parseWorkbook(defaultValue) || parseWorkbook(template) || { name: 'Sheet' }; + tagCellMapRef.current = buildTagMap(initialData); univerAPI.createWorkbook(initialData); + const restoreTagCells = () => { + if (isRestoringRef.current) return; + const wb = univerAPIRef.current?.getActiveWorkbook(); + if (!wb) return; + const sheet = wb.getActiveSheet(); + if (!sheet) return; + const saved = wb.save(); + if (!saved?.sheets) return; + const sheetId = saved.sheetOrder?.[0]; + const sheetData = sheetId ? saved.sheets[sheetId] : Object.values(saved.sheets)[0]; + if (!sheetData?.cellData) return; + + const restorations = []; + Object.entries(sheetData.cellData).forEach(([r, row]) => { + Object.entries(row).forEach(([c, cell]) => { + if (typeof cell.v === 'string' && TAG_RE.test(cell.v)) { + const orig = tagCellMapRef.current[`${r}:${c}`]; + if (orig) restorations.push({ r: +r, c: +c, v: orig.v, f: orig.f }); + } + }); + }); + + if (restorations.length === 0) return; + isRestoringRef.current = true; + restorations.forEach(({ r, c, v, f }) => { + sheet.getRange(r, c, 1, 1).setValues([[{ v, f }]]); + }); + isRestoringRef.current = false; + }; + + let restoreTimer; univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, () => { clearTimeout(saveTimerRef.current); saveTimerRef.current = setTimeout(() => { @@ -53,10 +105,13 @@ const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => { setDataFn(fieldName, wb.save()); } }, 300); + clearTimeout(restoreTimer); + restoreTimer = setTimeout(restoreTagCells, 80); }); return () => { clearTimeout(saveTimerRef.current); + clearTimeout(restoreTimer); if (univerRef.current) { univerRef.current.dispose(); univerRef.current = null; diff --git a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js index 010b3c9..b5752c5 100644 --- a/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js +++ b/src/pages/BandoFormsEdit/components/BuilderElementSettings/components/ElementSettingSpreadsheet/index.js @@ -12,6 +12,8 @@ import { useStoreValue } from '../../../../../../store'; // tools import { xlsxToWorkbookData } from '../../../../../BandoEdit/components/BandoEditFormStep3Excel/xlsxToWorkbookData'; +const TAG_RE = /^\{\{gepafin_field:([^|]+)\|([^}]+)}}$/; + const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { const callFormFields = useStoreValue('callFormFields'); const [tagTooltip, setTagTooltip] = useState(null); @@ -19,6 +21,7 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { const univerRef = useRef(null); const univerAPIRef = useRef(null); const formFieldsRef = useRef([]); + const isRestoringRef = useRef(false); const mousePos = useRef({ x: 0, y: 0 }); const fileInputRef = useRef(null); @@ -60,11 +63,54 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { univerRef.current = univer; univerAPIRef.current = univerAPI; - // Disable adding new sheets + // Restore tag cells whose display value was overwritten by raw tag on blur + const restoreTagCells = () => { + if (isRestoringRef.current) return; + const wb = univerAPIRef.current?.getActiveWorkbook(); + if (!wb) return; + const sheet = wb.getActiveSheet(); + if (!sheet) return; + const saved = wb.save(); + if (!saved?.sheets) return; + const sheetId = saved.sheetOrder?.[0]; + const sheetData = sheetId ? saved.sheets[sheetId] : Object.values(saved.sheets)[0]; + if (!sheetData?.cellData) return; + + const restorations = []; + Object.entries(sheetData.cellData).forEach(([r, row]) => { + Object.entries(row).forEach(([c, cell]) => { + const match = typeof cell.v === 'string' && cell.v.match(TAG_RE); + if (match) { + const tagIds = match[1].split(','); + const type = match[2]; + const field = formFieldsRef.current.find(f => + f.ids.some(id => tagIds.includes(String(id))) + ); + const displayValue = type === 'value' + ? (field?.placeholder || '') + : (field?.label || match[1]); + restorations.push({ r: +r, c: +c, v: displayValue, f: cell.v }); + } + }); + }); + + if (restorations.length === 0) return; + isRestoringRef.current = true; + restorations.forEach(({ r, c, v, f }) => { + sheet.getRange(r, c, 1, 1).setValues([[{ v, f }]]); + }); + isRestoringRef.current = false; + }; + + let restoreTimer; + + // Disable adding new sheets; also schedule tag-cell restoration after each command univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, (event) => { if (event.id === 'sheet.command.insert-sheet') { event.cancel = true; } + clearTimeout(restoreTimer); + restoreTimer = setTimeout(restoreTagCells, 80); }); // Context menu: "Inserisci variabile GEPAFIN" @@ -113,6 +159,7 @@ const ElementSettingSpreadsheet = ({ value, name, setDataFn }) => { setTagTooltip(null); } }); + }, []); // refs are stable // Keep formFieldsRef in sync with store value