Merge remote-tracking branch 'origin/main' into board-0117
This commit is contained in:
commit
62a63f2113
49
src/common/common.js
Normal file
49
src/common/common.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
작성자 : 공현지
|
||||
작성일 : 2025-01-17
|
||||
수정자 :
|
||||
수정일 :
|
||||
설명 : 공통 스크립트
|
||||
*/
|
||||
import Quill from 'quill';
|
||||
|
||||
/*
|
||||
*템플릿 사용법 : $common.변수
|
||||
*setup() 사용법 :
|
||||
const { appContext } = getCurrentInstance();
|
||||
const $common = appContext.config.globalProperties.$common;
|
||||
$common.변수
|
||||
*/
|
||||
const common = {
|
||||
// JSON 문자열로 Delta 타입을 변환
|
||||
contentToHtml(content) {
|
||||
try {
|
||||
if (content.startsWith('{') || content.startsWith('[')) {
|
||||
// Delta 형식으로 변환
|
||||
const delta = JSON.parse(content);
|
||||
const quill = new Quill(document.createElement('div'));
|
||||
quill.setContents(delta);
|
||||
return quill.root.innerHTML; // HTML 반환
|
||||
}
|
||||
return content; // 이미 HTML일 경우 그대로 반환
|
||||
} catch (error) {
|
||||
console.error('콘텐츠 변환 오류:', error);
|
||||
return content; // 오류 발생 시 원본 반환
|
||||
}
|
||||
},
|
||||
// Delta 타입을 JSON 문자열로 변환
|
||||
deltaAsJson(content) {
|
||||
if (content && content.ops) {
|
||||
return JSON.stringify(content.ops); // Delta 객체에서 ops 속성만 JSON 문자열로 변환
|
||||
}
|
||||
console.error('잘못된 Delta 객체:', content);
|
||||
return null; // Delta 객체가 아니거나 ops가 없을 경우 null 반환
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
install(app) {
|
||||
app.config.globalProperties.$common = common;
|
||||
}
|
||||
};
|
||||
@ -46,20 +46,27 @@
|
||||
</div>
|
||||
<!-- 에디터가 표시될 div -->
|
||||
<div ref="editor"></div>
|
||||
|
||||
<!-- Alert 메시지 표시 -->
|
||||
<div class="invalid-feedback" :class="isAlert ? 'd-block' : ''">내용을 확인해주세요.</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Quill from 'quill';
|
||||
import 'quill/dist/quill.snow.css';
|
||||
import { onMounted, ref, watch, defineEmits } from 'vue';
|
||||
import { onMounted, ref, watch, defineEmits, defineProps } from 'vue';
|
||||
import $api from '@api';
|
||||
|
||||
const props = defineProps({
|
||||
isAlert: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const editor = ref(null);
|
||||
const font = ref('nanum-gothic');
|
||||
const fontSize = ref('16px');
|
||||
const emit = defineEmits(['update:data']);
|
||||
|
||||
onMounted(() => {
|
||||
const Font = Quill.import('formats/font');
|
||||
Font.whitelist = ['nanum-gothic', 'd2coding', 'consolas', 'serif', 'monospace'];
|
||||
@ -83,21 +90,23 @@ onMounted(() => {
|
||||
quillInstance.format('size', fontSize.value);
|
||||
|
||||
quillInstance.on('text-change', () => {
|
||||
emit('update:data', quillInstance.root.innerHTML);
|
||||
const delta = quillInstance.getContents(); // Get Delta format
|
||||
emit('update:data', delta);
|
||||
});
|
||||
|
||||
watch([font, fontSize], () => {
|
||||
quillInstance.format('font', font.value);
|
||||
quillInstance.format('size', fontSize.value);
|
||||
});
|
||||
// 이미지 업로드
|
||||
let imageUrls = new Set();
|
||||
|
||||
// Handle image upload
|
||||
let imageUrls = new Set();
|
||||
quillInstance.getModule('toolbar').addHandler('image', () => {
|
||||
selectLocalImage();
|
||||
});
|
||||
quillInstance.on('text-change', (delta, oldDelta, source) => {
|
||||
emit('update:data', quillInstance.root.innerHTML);
|
||||
// Emit Delta when content changes
|
||||
emit('update:data', quillInstance.getContents());
|
||||
delta.ops.forEach(op => {
|
||||
if (op.insert && typeof op.insert === 'object' && op.insert.image) {
|
||||
const imageUrl = op.insert.image;
|
||||
@ -107,13 +116,11 @@ onMounted(() => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
async function selectLocalImage() {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('type', 'file');
|
||||
input.setAttribute('accept', 'image/*');
|
||||
input.click();
|
||||
|
||||
input.onchange = () => {
|
||||
const file = input.files[0];
|
||||
if (file) {
|
||||
@ -136,7 +143,7 @@ onMounted(() => {
|
||||
}
|
||||
async function uploadImageToServer(formData) {
|
||||
try {
|
||||
const response = await $api.post('img/upload', formData, { isFormData: true });
|
||||
const response = await $api.post('quilleditor/upload', formData, { isFormData: true });
|
||||
const imageUrl = response.data.data;
|
||||
return imageUrl;
|
||||
} catch (error) {
|
||||
@ -144,7 +151,6 @@ onMounted(() => {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function checkForDeletedImages() {
|
||||
const editorImages = document.querySelectorAll('#editor img');
|
||||
const currentImages = new Set(Array.from(editorImages).map(img => img.src));
|
||||
@ -156,12 +162,9 @@ onMounted(() => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import 'quill/dist/quill.snow.css';
|
||||
|
||||
.ql-editor {
|
||||
min-height: 300px;
|
||||
font-family: 'Nanum Gothic', sans-serif;
|
||||
|
||||
@ -5,6 +5,7 @@ import App from './App.vue'
|
||||
import router from '@/router'
|
||||
import dayjs from '@p/dayjs'
|
||||
import ToastModal from '@c/modal/ToastModal.vue';
|
||||
import common from '@/common/common.js'
|
||||
|
||||
const pinia = createPinia()
|
||||
pinia.use(piniaPersist)
|
||||
@ -12,6 +13,7 @@ pinia.use(piniaPersist)
|
||||
const app = createApp(App)
|
||||
app.use(router)
|
||||
.use(pinia)
|
||||
.use(common)
|
||||
.use(dayjs)
|
||||
.component('ToastModal',ToastModal)
|
||||
.mount('#app')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user