227 lines
5.7 KiB
Vue
227 lines
5.7 KiB
Vue
<template>
|
|
<div v-if="dataList.length > 0">
|
|
<FormSelect
|
|
class="me-5"
|
|
name="cate"
|
|
title="카테고리"
|
|
:data="dataList"
|
|
:is-common="true"
|
|
@update:data="selectCategory = $event"
|
|
@change="onChange"
|
|
:value="formValue"
|
|
:is-essential="false"
|
|
/>
|
|
<div v-if="!isDisabled" class="add-btn">
|
|
<PlusBtn @click="toggleInput"/>
|
|
</div>
|
|
</div>
|
|
<div v-if="dataList.length === 0 || showInput">
|
|
<FormInput
|
|
class="me-5 parent-class "
|
|
ref="categoryInputRef"
|
|
title="새 카테고리"
|
|
:isLabel="dataList.length === 0 ?true : false"
|
|
name="새 카테고리"
|
|
@update:modelValue="addCategory = $event"
|
|
:is-cate-alert="addCategoryAlert"
|
|
@focusout="handleCategoryFocusout(addCategory)"
|
|
|
|
/>
|
|
</div>
|
|
<FormInput class="me-5"
|
|
title="용어"
|
|
type="text"
|
|
name="word"
|
|
:is-essential="true"
|
|
:is-alert="wordTitleAlert"
|
|
:modelValue="titleValue"
|
|
@update:modelValue="wordTitle = $event"
|
|
:disabled="isDisabled"
|
|
@keyup="ValidHandler('title')"
|
|
/>
|
|
<div>
|
|
<QEditor class="" @keyup="ValidHandler('content')" @update:data="handleContentUpdate" @update:imageUrls="imageUrls = $event" :is-alert="wordContentAlert" :initialData="contentValue"/>
|
|
<div class="text-end mt-5">
|
|
<button class="btn btn-primary" @click="saveWord">
|
|
<i class="bx bx-check"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { defineProps, computed, ref, defineEmits } from 'vue';
|
|
|
|
import QEditor from '@/components/editor/QEditor.vue';
|
|
import FormInput from '@/components/input/FormInput.vue';
|
|
import FormSelect from '@/components/input/FormSelect.vue';
|
|
import PlusBtn from '../button/PlusBtn.vue';
|
|
|
|
const emit = defineEmits(['close','addCategory','addWord']);
|
|
|
|
//용어제목
|
|
const wordTitle = ref('');
|
|
const addCategory = ref('');
|
|
const content = ref('');
|
|
const imageUrls = ref([]);
|
|
|
|
//용어 Vaildation용
|
|
const wordTitleAlert = ref(false);
|
|
const wordContentAlert = ref(false);
|
|
const addCategoryAlert = ref(false);
|
|
|
|
//선택 카테고리
|
|
const selectCategory = ref('');
|
|
|
|
// 제목 상태
|
|
const computedTitle = computed(() =>
|
|
wordTitle.value === '' ? props.titleValue : wordTitle.value
|
|
);
|
|
|
|
// 카테고리 상태
|
|
const selectedCategory = computed(() =>
|
|
selectCategory.value === '' ? props.formValue : selectCategory.value
|
|
|
|
);
|
|
|
|
// 카테고리 입력 중복 ref
|
|
const categoryInputRef = ref(null);
|
|
|
|
const props = defineProps({
|
|
dataList: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
NumValue : {
|
|
type: Number
|
|
},
|
|
formValue : {
|
|
type:[String, Number]
|
|
},
|
|
titleValue : {
|
|
type:String,
|
|
},contentValue : {
|
|
type:String,
|
|
},
|
|
isDisabled: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
});
|
|
|
|
// 카테고리 입력 창
|
|
const showInput = ref(false);
|
|
|
|
// 카테고리 입력 토글
|
|
const toggleInput = () => {
|
|
showInput.value = !showInput.value;
|
|
};
|
|
|
|
const onChange = (newValue) => {
|
|
selectCategory.value = newValue.target.value;
|
|
};
|
|
|
|
const ValidHandler = (field) => {
|
|
if(field == 'title'){
|
|
wordTitleAlert.value = false;
|
|
}
|
|
if(field == 'content'){
|
|
wordContentAlert.value = false;
|
|
}
|
|
|
|
}
|
|
const handleContentUpdate = (newContent) => {
|
|
content.value = newContent;
|
|
ValidHandler("content"); // 유효성 검사 실행
|
|
};
|
|
|
|
//용어 등록
|
|
const saveWord = () => {
|
|
let valid = true;
|
|
//validation
|
|
let computedTitleTrim;
|
|
|
|
if(computedTitle.value != undefined){
|
|
computedTitleTrim = computedTitle.value.trim()
|
|
}
|
|
|
|
// 용어 체크
|
|
if(computedTitleTrim == undefined || computedTitleTrim == ''){
|
|
wordTitleAlert.value = true;
|
|
valid = false;
|
|
} else {
|
|
wordTitleAlert.value = false;
|
|
}
|
|
|
|
// 내용 확인
|
|
let inserts = [];
|
|
if (inserts.length === 0 && content.value?.ops?.length > 0) {
|
|
inserts = content.value.ops.map(op =>
|
|
typeof op.insert === 'string' ? op.insert.trim() : op.insert
|
|
);
|
|
}
|
|
// 내용 체크
|
|
if(content.value == '' || inserts.join('') === ''){
|
|
wordContentAlert.value = true;
|
|
valid = false;
|
|
}else{
|
|
wordContentAlert.value = false;
|
|
}
|
|
const wordData = {
|
|
id: props.NumValue || null,
|
|
title: computedTitle.value.trim(),
|
|
category: selectedCategory.value,
|
|
content: content.value,
|
|
};
|
|
if(valid){
|
|
emit('addWord', wordData, addCategory.value.trim() === ''
|
|
? (isNaN(selectedCategory.value) ? selectedCategory.value : Number(selectedCategory.value))
|
|
: addCategory.value);
|
|
}
|
|
}
|
|
|
|
// 카테고리 focusout 이벤트 핸들러 추가
|
|
const handleCategoryFocusout = (value) => {
|
|
if (!value || value.trim() === '') {
|
|
return;
|
|
}
|
|
const valueTrim = value.trim();
|
|
const existingCategory = props.dataList.find(item => item.label === valueTrim);
|
|
|
|
if (existingCategory) {
|
|
addCategoryAlert.value = true;
|
|
|
|
// 중복 시 강제 focus
|
|
setTimeout(() => {
|
|
const inputElement = categoryInputRef.value?.$el?.querySelector('input');
|
|
if (inputElement) {
|
|
inputElement.focus();
|
|
}
|
|
}, 0);
|
|
} else {
|
|
addCategoryAlert.value = false;
|
|
}
|
|
};
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
.dict-w {
|
|
width: 83%;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.btn-margin {
|
|
margin-top: 2.5rem
|
|
}
|
|
}
|
|
.add-btn {
|
|
position: absolute;
|
|
right: 0.7rem;
|
|
top: 1.2rem;
|
|
}
|
|
.parent-class {
|
|
justify-content: flex-end;
|
|
}
|
|
</style>
|