diff --git a/src/components/search/SearchBar.vue b/src/components/search/SearchBar.vue index 9a68666..03bfb3a 100644 --- a/src/components/search/SearchBar.vue +++ b/src/components/search/SearchBar.vue @@ -1,17 +1,8 @@ diff --git a/src/views/board/BoardEdit.vue b/src/views/board/BoardEdit.vue index 8be6961..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,15 +183,9 @@ attachFiles.value.filter(f => f.id), // 기존 파일(id 있는 것만) originalFiles.value ); - console.log(isTitleChanged); - console.log(isContentChanged); - console.log(isFilesChanged); - return isTitleChanged || isContentChanged || isFilesChanged; - }); - watch(isChanged, (val) => { - console.log('🔄 isChanged changed:', val); - }); + return isTitleChanged || isContentChanged || isFilesChanged ; + }); // 파일 비교 함수 function isSameFiles(current, original) { @@ -200,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; }; @@ -362,6 +388,7 @@ onMounted(async () => { if (currentBoardId.value) { fetchBoardDetails(); + } else { console.error('잘못된 게시물 ID:', currentBoardId.value); } diff --git a/src/views/board/BoardList.vue b/src/views/board/BoardList.vue index a3bf5ad..cd3ee2f 100644 --- a/src/views/board/BoardList.vue +++ b/src/views/board/BoardList.vue @@ -4,7 +4,7 @@
- +
diff --git a/src/views/board/BoardView.vue b/src/views/board/BoardView.vue index c81248b..a29c575 100644 --- a/src/views/board/BoardView.vue +++ b/src/views/board/BoardView.vue @@ -78,10 +78,9 @@ style="line-height: 1.6" v-html="$common.contentToHtml(boardContent)" >
-
-
+
-
+
-