수정 에디터

This commit is contained in:
dyhj625 2025-03-28 16:32:53 +09:00
parent d47ee95f56
commit 9035d339ac
2 changed files with 57 additions and 27 deletions

View File

@ -55,7 +55,7 @@
<div class="col-md-12">
<QEditor
v-if="contentLoaded"
@update:data="content = $event"
@update:data="handleEditorDataUpdate"
@update:imageUrls="imageUrls = $event"
@update:uploadedImgList="handleUpdateEditorImg"
@update:deleteImgIndexList="handleDeleteEditorImg"
@ -89,6 +89,7 @@
import { useToastStore } from '@s/toastStore';
import { useBoardAccessStore } from '@s/useBoardAccessStore';
import axios from '@api';
import Quill from 'quill';
//
const $common = inject('common');
@ -121,25 +122,60 @@
const editorDeleteImgList = ref([]);
const originalTitle = ref('');
const originalPlainText = ref('');
const originalContent = ref({});
const originalFiles = ref([]);
const contentInitialized = ref(false);
//
const isFirstContentUpdate = ref(true);
//
const handleEditorDataUpdate = (data) => {
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);
}

View File

@ -80,7 +80,7 @@
></div>
<!-- 좋아요 버튼 -->
<div v-if="unknown" class="row justify-content-center my-10">
<div v-if="unknown || authorId" class="row justify-content-center my-10">
<BoardRecommendBtn
:bigBtn="true"
:boardId="currentBoardId"
@ -92,7 +92,7 @@
@updateReaction="handleUpdateReaction"
/>
</div>
<div v-if="unknown" >
<div v-if="unknown || authorId" >
<!-- 댓글 입력 영역 -->
<BoardCommentArea
:profileName="profileName"
@ -106,7 +106,7 @@
</div>
<!-- 댓글 목록 -->
<div v-if="unknown" class="card-footer">
<div v-if="unknown || authorId" class="card-footer">
<BoardCommentList
:unknown="unknown"
:comments="commentsWithAuthStatus"