용어집 수정
This commit is contained in:
parent
bd91e0a72d
commit
3d41dc7730
2
public/vendor/css/rtl/theme-default.css
vendored
2
public/vendor/css/rtl/theme-default.css
vendored
File diff suppressed because one or more lines are too long
@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<!-- 카테고리 중복 -->
|
||||
<div class="invalid-feedback" :class="isCateAlert ? 'display-block' : ''">
|
||||
카테고리 중복입니다.
|
||||
카테고리는 중복이거나 공백이면 안됩니다. 확인해주세요.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<li class="mt-5 card p-5">
|
||||
<DictWrite
|
||||
v-if="isWriteVisible"
|
||||
@close="isWriteVisible = false"
|
||||
v-if="writeStore.isItemActive(item.WRDDICSEQ)"
|
||||
@close="writeStore.closeAll();"
|
||||
:dataList="cateList"
|
||||
@addWord="editWord"
|
||||
:NumValue="item.WRDDICSEQ"
|
||||
@ -35,7 +35,9 @@
|
||||
class="rounded-circle user-avatar"
|
||||
:src="getProfileImage(item.author.profileImage)"
|
||||
alt="최초 작성자"
|
||||
:style="{ borderColor: item.author.color}"/>
|
||||
:style="{ borderColor: item.author.color}"
|
||||
@error="setDefaultImage"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-0 small fw-medium">{{ formattedDate(item.author.createdAt) }}</p>
|
||||
@ -52,7 +54,9 @@
|
||||
class="rounded-circle user-avatar"
|
||||
:src="getProfileImage(item.lastEditor.profileImage)"
|
||||
alt="최근 작성자"
|
||||
:style="{ borderColor: item.lastEditor.color}"/>
|
||||
:style="{ borderColor: item.lastEditor.color}"
|
||||
@error="setDefaultImage"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-0 small fw-medium">{{ formattedDate(item.lastEditor.updatedAt) }}</p>
|
||||
@ -62,7 +66,7 @@
|
||||
</div>
|
||||
|
||||
<div class="edit-btn" v-if="userStore.user.role !== 'ROLE_ADMIN'">
|
||||
<EditBtn @click="toggleWriteVisible" />
|
||||
<EditBtn @click="writeStore.toggleItem(item.WRDDICSEQ)" />
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
@ -75,8 +79,10 @@ import EditBtn from '@/components/button/EditBtn.vue';
|
||||
import $api from '@api';
|
||||
import DictWrite from './DictWrite.vue';
|
||||
import { formattedDate } from "@/common/formattedDate";
|
||||
|
||||
import { useUserInfoStore } from '@s/useUserInfoStore';
|
||||
import { useWriteVisibleStore } from '@s/writeVisible';
|
||||
|
||||
const writeStore = useWriteVisibleStore();
|
||||
|
||||
// 유저 구분
|
||||
const userStore = useUserInfoStore();
|
||||
@ -107,13 +113,13 @@ const props = defineProps({
|
||||
const emit = defineEmits(['update:cateList','refreshWordList', 'updateChecked']);
|
||||
|
||||
// 글 수정 상태
|
||||
const isWriteVisible = ref(false);
|
||||
// const isWriteVisible = ref(false);
|
||||
|
||||
|
||||
// 글 수정 toggle
|
||||
const toggleWriteVisible = () => {
|
||||
isWriteVisible.value = !isWriteVisible.value;
|
||||
};
|
||||
// const toggleWriteVisible = () => {
|
||||
// isWriteVisible.value = !isWriteVisible.value;
|
||||
// };
|
||||
|
||||
//카테고리 등록 수정
|
||||
// const addCategory = (data) => {
|
||||
@ -176,7 +182,8 @@ const editWord = (data) => {
|
||||
.then((res) => {
|
||||
if (res.data.data === 1) {
|
||||
toastStore.onToast('✅ 용어가 수정되었습니다.', 's');
|
||||
isWriteVisible.value = false;
|
||||
// isWriteVisible.value = false;
|
||||
writeStore.closeAll();
|
||||
emit('refreshWordList');
|
||||
} else {
|
||||
console.warn('⚠️ 서버 응답이 예상과 다릅니다:', res.data);
|
||||
@ -191,9 +198,6 @@ const editWord = (data) => {
|
||||
|
||||
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
||||
|
||||
// 날짜 포맷
|
||||
// const formatDate = (dateString) => new Date(dateString).toLocaleString();
|
||||
|
||||
// 프로필 이미지
|
||||
const defaultProfile = "/img/icons/icon.png";
|
||||
|
||||
@ -201,6 +205,10 @@ const getProfileImage = (profilePath) => {
|
||||
return profilePath && profilePath.trim() ? `${baseUrl}upload/img/profile/${profilePath}` : defaultProfile;
|
||||
};
|
||||
|
||||
const setDefaultImage = (event) => {
|
||||
event.target.src = defaultProfile;
|
||||
};
|
||||
|
||||
|
||||
// 체크 상태 변경 시 부모로 전달
|
||||
const toggleCheck = (event) => {
|
||||
|
||||
@ -65,6 +65,7 @@ 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';
|
||||
// import { clearConfig } from 'dompurify';
|
||||
// import { useUserInfoStore } from '@s/useUserInfoStore';
|
||||
|
||||
// 유저 구분
|
||||
@ -153,21 +154,33 @@ const onChange = (newValue) => {
|
||||
//용어 등록
|
||||
const saveWord = () => {
|
||||
//validation
|
||||
console.log('computedTitle.value', computedTitle.value);
|
||||
let computedTitleTrim;
|
||||
|
||||
if(computedTitle.value != undefined){
|
||||
computedTitleTrim = computedTitle.value.trim()
|
||||
}
|
||||
|
||||
// 용어 체크
|
||||
if(computedTitle.value == undefined){
|
||||
if(computedTitleTrim == undefined || computedTitleTrim == ''){
|
||||
wordTitleAlert.value = true;
|
||||
return;
|
||||
} else {
|
||||
wordTitleAlert.value = false;
|
||||
}
|
||||
|
||||
// 내용 확인
|
||||
let inserts = [];
|
||||
if(inserts.length === 0 && content.value?.ops?.length > 0){
|
||||
inserts = content.value.ops.map(op => op.insert.trim());
|
||||
}
|
||||
|
||||
// 내용 체크
|
||||
if(content.value == ''){
|
||||
if(content.value == '' || inserts.join('') === ''){
|
||||
wordContentAlert.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const wordData = {
|
||||
id: props.NumValue || null,
|
||||
title: computedTitle.value,
|
||||
@ -181,12 +194,26 @@ const saveWord = () => {
|
||||
|
||||
// 카테고리 focusout 이벤트 핸들러 추가
|
||||
const handleCategoryFocusout = (value) => {
|
||||
const valueTrim = value.trim();
|
||||
|
||||
const existingCategory = props.dataList.find(item => item.label === value);
|
||||
const existingCategory = props.dataList.find(item => item.label === valueTrim);
|
||||
// console.log('existingCategory', existingCategory);
|
||||
|
||||
if (existingCategory) {
|
||||
// console.log('이미 존재하는 카테고리입니다:', value);
|
||||
// 카테고리 입력시 공백
|
||||
if(valueTrim == ''){
|
||||
//alert('공백 ㄴㄴ');
|
||||
addCategoryAlert.value = true;
|
||||
|
||||
// 공백시 강제 focus
|
||||
setTimeout(() => {
|
||||
const inputElement = categoryInputRef.value?.$el?.querySelector('input');
|
||||
if (inputElement) {
|
||||
inputElement.focus();
|
||||
}
|
||||
}, 0);
|
||||
|
||||
|
||||
}else if (existingCategory) {
|
||||
addCategoryAlert.value = true;
|
||||
|
||||
// 중복시 강제 focus
|
||||
|
||||
48
src/stores/writeVisible.js
Normal file
48
src/stores/writeVisible.js
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
작성자 : 조대원
|
||||
작성일 : 2025-02-27
|
||||
수정자 :
|
||||
수정일 :
|
||||
설명 : 용어집 작성, 수정 공통관리
|
||||
*/
|
||||
import { ref } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
export const useWriteVisibleStore = defineStore('writeVisible', () => {
|
||||
// 현재 열려있는 항목의 ID를 저장 (열린 것이 없으면 null)
|
||||
const activeItemId = ref(null);
|
||||
|
||||
// 특정 항목의 열림/닫힘 상태 확인
|
||||
function isItemActive(itemId) {
|
||||
return activeItemId.value === itemId;
|
||||
}
|
||||
|
||||
// 항목 토글 - 현재 열려있으면 닫고, 닫혀있으면 열기
|
||||
function toggleItem(itemId) {
|
||||
if (activeItemId.value === itemId) {
|
||||
// 현재 열려있는 항목을 다시 클릭하면 닫기
|
||||
activeItemId.value = null;
|
||||
} else {
|
||||
// 다른 항목 클릭시 해당 항목을 열고 이전 항목은 자동으로 닫힘
|
||||
activeItemId.value = itemId;
|
||||
}
|
||||
}
|
||||
|
||||
// 특정 항목 강제로 열기 (다른 항목은 닫힘)
|
||||
function setActiveItem(itemId) {
|
||||
activeItemId.value = itemId;
|
||||
}
|
||||
|
||||
// 모든 항목 닫기
|
||||
function closeAll() {
|
||||
activeItemId.value = null;
|
||||
}
|
||||
|
||||
return {
|
||||
activeItemId,
|
||||
isItemActive,
|
||||
toggleItem,
|
||||
setActiveItem,
|
||||
closeAll
|
||||
};
|
||||
});
|
||||
@ -14,7 +14,7 @@
|
||||
<!-- 단어 갯수, 작성하기 -->
|
||||
<div class="mt-4">
|
||||
단어 : {{ total }}
|
||||
<WriteButton @click="toggleWriteForm" />
|
||||
<WriteButton @click="writeStore.toggleItem(999999)" />
|
||||
</div>
|
||||
|
||||
<!-- ㄱ ㄴ ㄷ ㄹ -->
|
||||
@ -28,8 +28,8 @@
|
||||
</div>
|
||||
|
||||
<!-- 작성 -->
|
||||
<div v-if="isWriteVisible" class="mt-5">
|
||||
<DictWrite @close="isWriteVisible = false" :dataList="cateList" @addWord="addWord"/>
|
||||
<div v-if="writeStore.isItemActive(999999)" class="mt-5">
|
||||
<DictWrite @close="writeStore.closeAll()" :dataList="cateList" @addWord="addWord"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -78,9 +78,13 @@
|
||||
import commonApi from '@/common/commonApi';
|
||||
import { useToastStore } from '@s/toastStore';
|
||||
import { useUserInfoStore } from '@s/useUserInfoStore';
|
||||
import { useWriteVisibleStore } from '@s/writeVisible';
|
||||
|
||||
// 작성창 구분
|
||||
const writeStore = useWriteVisibleStore();
|
||||
|
||||
// 유저 구분
|
||||
const userStore = useUserInfoStore();
|
||||
// const userStore = useUserInfoStore();
|
||||
|
||||
const { appContext } = getCurrentInstance();
|
||||
const $common = appContext.config.globalProperties.$common;
|
||||
@ -118,7 +122,7 @@
|
||||
const searchText = ref('');
|
||||
|
||||
// 작성
|
||||
const isWriteVisible = ref(false);
|
||||
// const isWriteVisible = ref(false);
|
||||
|
||||
// 데이터 로드
|
||||
onMounted(() => {
|
||||
@ -168,9 +172,9 @@
|
||||
}
|
||||
|
||||
// 작성 toggle
|
||||
const toggleWriteForm = () => {
|
||||
isWriteVisible.value = !isWriteVisible.value;
|
||||
};
|
||||
// const toggleWriteForm = () => {
|
||||
// isWriteVisible.value = !isWriteVisible.value;
|
||||
// };
|
||||
|
||||
//카테고리 등록
|
||||
// const addCategory = (data) =>{
|
||||
@ -197,15 +201,14 @@
|
||||
const addWord = (wordData, data) => {
|
||||
let category = null;
|
||||
// 카테고리 체크
|
||||
const existingCategory = cateList.value.find(item => item.label === data);
|
||||
if (existingCategory) {
|
||||
console.log('카테고리 중복');
|
||||
const existingCategory = cateList.value.find(item => item.label === data.trim());
|
||||
|
||||
if (existingCategory) {
|
||||
//카테고리 있을시 그냥 저장
|
||||
category = existingCategory.label == '' ? wordData.category : existingCategory.value;
|
||||
} else {
|
||||
//카테고리 없을시 카테고리 와 용어 둘다 저장
|
||||
console.log('카테고리 없음');
|
||||
// console.log('카테고리 없음');
|
||||
const lastCategory = cateList.value[cateList.value.length - 1];
|
||||
category = lastCategory ? lastCategory.value + 1 : 600101;
|
||||
}
|
||||
@ -224,7 +227,8 @@
|
||||
axios.post('worddict/insertWord', payload).then(res => {
|
||||
if (res.data.status === 'OK') {
|
||||
toastStore.onToast('용어가 등록 되었습니다.', 's');
|
||||
isWriteVisible.value = false;
|
||||
// isWriteVisible.value = false;
|
||||
writeStore.closeAll();
|
||||
getwordList();
|
||||
const newCategory = { label: data, value: category }; // 여기서 data 사용
|
||||
cateList.value = [newCategory, ...cateList.value];
|
||||
@ -234,7 +238,8 @@
|
||||
axios.post('worddict/insertWord', payload).then(res => {
|
||||
if (res.data.status === 'OK') {
|
||||
toastStore.onToast('용어가 등록 되었습니다.', 's');
|
||||
isWriteVisible.value = false;
|
||||
// isWriteVisible.value = false;
|
||||
writeStore.closeAll();
|
||||
getwordList();
|
||||
}
|
||||
});
|
||||
@ -268,7 +273,8 @@
|
||||
.then(res => {
|
||||
if (res.data.status == 'OK') {
|
||||
toastStore.onToast('용어 삭제가 완료되었습니다.', 's');
|
||||
isWriteVisible.value = false;
|
||||
// isWriteVisible.value = false;
|
||||
writeStore.closeAll();
|
||||
getwordList();
|
||||
|
||||
// 삭제 후 초기화
|
||||
@ -277,7 +283,7 @@
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('삭제 요청 중 오류 발생:', error);
|
||||
// console.error('삭제 요청 중 오류 발생:', error);
|
||||
toastStore.onToast('오류가 발생했습니다. 다시 시도해주세요.', 'e');
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user