From 9035d339ac9940e2a18bbe8b4d306454598a6c7b Mon Sep 17 00:00:00 2001 From: dyhj625 Date: Fri, 28 Mar 2025 16:32:53 +0900 Subject: [PATCH] =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=97=90=EB=94=94?= =?UTF-8?q?=ED=84=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/board/BoardEdit.vue | 78 ++++++++++++++++++++++++----------- src/views/board/BoardView.vue | 6 +-- 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/views/board/BoardEdit.vue b/src/views/board/BoardEdit.vue index 65fdd6a..6383e51 100644 --- a/src/views/board/BoardEdit.vue +++ b/src/views/board/BoardEdit.vue @@ -55,7 +55,7 @@
{ + content.value = data; + + if (isFirstContentUpdate.value) { + originalContent.value = structuredClone(data); + isFirstContentUpdate.value = false; + contentInitialized.value = true; + } +}; - function extractPlainText(delta) { - if (!delta || !Array.isArray(delta.ops)) return ''; - return delta.ops - .filter(op => typeof op.insert === 'string') - .map(op => op.insert.trim()) - .join(' ') - .trim(); + function isDeltaChanged(current, original) { + const Delta = Quill.import('delta'); + const currentDelta = new Delta(current || []); + const originalDelta = new Delta(original || []); + + const diff = originalDelta.diff(currentDelta); + if (!diff || diff.ops.length === 0) return false; + + // 텍스트만 비교해서 완전 동일한지 확인 + const getPlainText = (delta) => + (delta.ops || []) + .filter(op => typeof op.insert === 'string') + .map(op => op.insert) + .join(''); + + const getImages = (delta) => + (delta.ops || []) + .filter(op => typeof op.insert === 'object' && op.insert.image) + .map(op => op.insert.image); + + const textCurrent = getPlainText(currentDelta); + const textOriginal = getPlainText(originalDelta); + + const imgsCurrent = getImages(currentDelta); + const imgsOriginal = getImages(originalDelta); + + const textEqual = textCurrent === textOriginal; + const imageEqual = JSON.stringify(imgsCurrent) === JSON.stringify(imgsOriginal); + + return !(textEqual && imageEqual); // 둘 다 같아야 false } const isChanged = computed(() => { + if (!contentInitialized.value) return false; const isTitleChanged = title.value !== originalTitle.value; - const currentPlainText = extractPlainText(content.value); - const isContentChanged = currentPlainText !== originalPlainText.value; - - const currentAttachedFiles = attachFiles.value.filter(f => f.id); + const isContentChanged = isDeltaChanged(content.value, originalContent.value); const isFilesChanged = attachFiles.value.some(f => !f.id) || // id 없는 새 파일이 있는 경우 delFileIdx.value.length > 0 || // 삭제된 파일이 있는 경우 @@ -147,12 +183,9 @@ attachFiles.value.filter(f => f.id), // 기존 파일(id 있는 것만) originalFiles.value ); - return isTitleChanged || isContentChanged || isFilesChanged; - }); - watch(isChanged, (val) => { - //console.log('🔄 isChanged changed:', val); - }); + return isTitleChanged || isContentChanged || isFilesChanged ; + }); // 파일 비교 함수 function isSameFiles(current, original) { @@ -197,15 +230,11 @@ title.value = boardData.title || '제목 없음'; content.value = boardData.content || '내용 없음'; originalTitle.value = title.value; + originalContent.value = structuredClone(boardData.content); + contentInitialized.value = true; contentLoaded.value = true; }; - watch(content, (val) => { - if (contentLoaded.value && !originalPlainText.value) { - originalPlainText.value = extractPlainText(val); - } - }, { immediate: true }); - const handleUpdateEditorImg = item => { editorUploadedImgList.value = item; }; @@ -359,6 +388,7 @@ onMounted(async () => { if (currentBoardId.value) { fetchBoardDetails(); + } else { console.error('잘못된 게시물 ID:', currentBoardId.value); } diff --git a/src/views/board/BoardView.vue b/src/views/board/BoardView.vue index 2a7c81e..a29c575 100644 --- a/src/views/board/BoardView.vue +++ b/src/views/board/BoardView.vue @@ -80,7 +80,7 @@ >
-
+
-
+
-