diff --git a/public/css/custom.css b/public/css/custom.css index 854336c..b4f78ff 100644 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -1,6 +1,70 @@ /* 여기에 light css 작성 */ - +/* 에러페이지 */ +/* 전체 화면을 덮는 스타일 */ +.error-page { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: #fff; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + color: #000; + font-family: 'Poppins', sans-serif; + z-index: 9999 !important; +} +/* 오류 메시지 컨텐츠 */ +.error-content { + text-align: center; + animation: fadeIn 0.8s ease-in-out; +} +/* 에러 이미지 */ +.error-image { + width: 280px; /* 이미지 크기 */ + margin-bottom: 20px; +} +/* 에러 코드 스타일 */ +.error-content h1 { + font-size: 6rem; + font-weight: bold; + color: #ff8c00; /* 오렌지 */ + text-shadow: 2px 2px 8px rgba(255, 140, 0, 0.3); + margin-bottom: 60px; +} +/* 홈으로 돌아가기 버튼 */ +.home-btn { + display: inline-block; + padding: 10px 28px; + font-size: 1rem; + font-weight: bold; + text-decoration: none; + color: #fff; + background: rgba(105, 108, 255, 0.9); + border-radius: 30px; + transition: 0.3s ease-in-out; + box-shadow: 0 4px 15px rgba(105, 108, 255, 0.5); +} +/* 버튼 호버 효과 */ +.home-btn:hover { + background: linear-gradient(90deg, orange, #ff8c00); + box-shadow: 0 0 20px rgba(255, 140, 0, 1); + transform: scale(1.05); +} +/* 페이드 인 애니메이션 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} /* 휴가 */ .fc-daygrid-event { diff --git a/public/img/icons/illustrations/page-misc-error-light.png b/public/img/icons/illustrations/page-misc-error-light.png deleted file mode 100644 index 02dac04..0000000 Binary files a/public/img/icons/illustrations/page-misc-error-light.png and /dev/null differ diff --git a/src/common/axios-interceptor.js b/src/common/axios-interceptor.js index 2068cb7..b1e6b52 100644 --- a/src/common/axios-interceptor.js +++ b/src/common/axios-interceptor.js @@ -51,6 +51,10 @@ $api.interceptors.response.use( // 오류 응답 처리 if (error.response) { switch (error.response.status) { + case 400: + toastStore.onToast('잘못된 요청입니다.', 'e'); + router.push('/error/400'); // 🚀 400 에러 발생 시 자동 이동 + break; case 401: if (!error.config.headers.isLogin) { // toastStore.onToast('인증이 필요합니다.', 'e'); @@ -62,9 +66,11 @@ $api.interceptors.response.use( break; case 404: toastStore.onToast('요청한 페이지를 찾을 수 없습니다.', 'e'); + router.push('/error/404'); break; case 500: toastStore.onToast('서버 오류가 발생했습니다.', 'e'); + router.push('/error/500'); break; default: toastStore.onToast('알 수 없는 오류가 발생했습니다.', 'e'); diff --git a/src/components/input/FormInput.vue b/src/components/input/FormInput.vue index daae332..931ff2e 100644 --- a/src/components/input/FormInput.vue +++ b/src/components/input/FormInput.vue @@ -5,28 +5,29 @@ *
- +
+ +
{{ title }}을 확인해주세요.
-
카테고리 중복입니다.
- - diff --git a/src/views/board/BoardEdit.vue b/src/views/board/BoardEdit.vue index 4b19c15..4813cb9 100644 --- a/src/views/board/BoardEdit.vue +++ b/src/views/board/BoardEdit.vue @@ -85,11 +85,13 @@ import { ref, onMounted, computed, watch, inject } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import { useToastStore } from '@s/toastStore'; + import { useBoardAccessStore } from '@s/useBoardAccessStore'; import axios from '@api'; // 공통 const $common = inject('common'); const toastStore = useToastStore(); + const accessStore = useBoardAccessStore(); // 상태 변수 const title = ref(''); @@ -117,22 +119,29 @@ // 게시물 데이터 로드 const fetchBoardDetails = async () => { - try { - const response = await axios.get(`board/${currentBoardId.value}`); - const data = response.data.data; + // 수정 데이터 전송 + const password = accessStore.password; + const params = { + password: password || '', + }; + //const response = await axios.get(`board/${currentBoardId.value}`); + const { data } = await axios.post(`board/${currentBoardId.value}`, params); - // 기존 첨부파일 추가 - if (data.hasAttachment && data.attachments.length > 0) { - attachFiles.value = addDisplayFileName([...data.attachments]); - } - - // 데이터 설정 - title.value = data.title || '제목 없음'; - content.value = data.content || '내용 없음'; - contentLoaded.value = true; - } catch (error) { - console.error('게시물 가져오기 오류:', error.response || error.message); + if (data.code !== 200) { + toastStore.onToast(data.message, 'e'); + router.go(-1); + return; } + const boardData = data.data; + // 기존 첨부파일 추가 + if (boardData.hasAttachment && boardData.attachments.length > 0) { + attachFiles.value = addDisplayFileName([...boardData.attachments]); + } + + // 데이터 설정 + title.value = boardData.title || '제목 없음'; + content.value = boardData.content || '내용 없음'; + contentLoaded.value = true; }; // 기존 첨부파일명을 노출 @@ -144,6 +153,7 @@ // 목록 페이지로 이동 const goList = () => { + accessStore.$reset(); router.push('/board'); }; @@ -218,43 +228,42 @@ const updateBoard = async () => { if (checkValidation()) return; - try { - // 수정 데이터 전송 - const boardData = { - LOCBRDTTL: title.value.trim(), - LOCBRDCON: JSON.stringify(content.value), - LOCBRDSEQ: currentBoardId.value, - }; + // 수정 데이터 전송 + const boardData = { + LOCBRDTTL: title.value.trim(), + LOCBRDCON: JSON.stringify(content.value), + LOCBRDSEQ: currentBoardId.value, + }; - // 업로드 된 첨부파일의 삭제목록 - if (delFileIdx.value && delFileIdx.value.length > 0) { - boardData.delFileIdx = [...delFileIdx.value]; - } + // 업로드 된 첨부파일의 삭제목록 + if (delFileIdx.value && delFileIdx.value.length > 0) { + boardData.delFileIdx = [...delFileIdx.value]; + } - const fileArray = newFileFilter(attachFiles); - const formData = new FormData(); + const fileArray = newFileFilter(attachFiles); + const formData = new FormData(); - // formData에 boardData 추가 - Object.entries(boardData).forEach(([key, value]) => { - formData.append(key, value); - }); + // formData에 boardData 추가 + Object.entries(boardData).forEach(([key, value]) => { + formData.append(key, value); + }); - // formData에 새로 추가한 파일 추가 - fileArray.forEach((file, idx) => { - formData.append('files', file); - }); + // formData에 새로 추가한 파일 추가 + fileArray.forEach((file, idx) => { + formData.append('files', file); + }); - await axios.put(`board/${currentBoardId.value}`, formData, { isFormData: true }); + const { data } = await axios.put(`board/${currentBoardId.value}`, formData, { isFormData: true }); + if (data.code === 200 && data.data === true) { toastStore.onToast('게시물이 수정되었습니다.', 's'); goList(); - } catch (error) { - console.error('게시물 수정 중 오류 발생:', error); - toastStore.onToast('게시물 수정에 실패했습니다.'); + } else { + toastStore.onToast('게시물 수정에 실패했습니다.', 'e'); } }; // 컴포넌트 마운트 시 데이터 로드 - onMounted(() => { + onMounted(async () => { if (currentBoardId.value) { fetchBoardDetails(); } else { diff --git a/src/views/board/BoardView.vue b/src/views/board/BoardView.vue index 20af8e2..4eed1f8 100644 --- a/src/views/board/BoardView.vue +++ b/src/views/board/BoardView.vue @@ -139,6 +139,7 @@ import { useRoute, useRouter } from 'vue-router'; import { useUserInfoStore } from '@/stores/useUserInfoStore'; import { useToastStore } from '@s/toastStore'; + import { useBoardAccessStore } from '@s/useBoardAccessStore'; import axios from '@api'; const $common = inject('common'); @@ -161,6 +162,8 @@ const router = useRouter(); const userStore = useUserInfoStore(); const toastStore = useToastStore(); + const accessStore = useBoardAccessStore(); + const currentBoardId = ref(Number(route.params.id)); const unknown = computed(() => profileName.value === '익명'); const currentUserId = computed(() => userStore?.user?.id); // 현재 로그인한 사용자 id @@ -242,21 +245,25 @@ // 게시물 상세 데이터 불러오기 const fetchBoardDetails = async () => { - const response = await axios.get(`board/${currentBoardId.value}`); - const data = response.data.data; - - profileName.value = data.author || '익명'; - authorId.value = data.authorId; - boardTitle.value = data.title || '제목 없음'; - boardContent.value = data.content || ''; - profileImg.value = data.profileImg || ''; - date.value = data.date || ''; - views.value = data.cnt || 0; - likes.value = data.likeCount || 0; - dislikes.value = data.dislikeCount || 0; - attachment.value = data.hasAttachment || null; - commentNum.value = data.commentCount || 0; - attachments.value = data.attachments || []; + const { data } = await axios.get(`board/${currentBoardId.value}`); + if (data?.data) { + const boardData = data.data; + profileName.value = boardData.author || '익명'; + authorId.value = boardData.authorId; + boardTitle.value = boardData.title || '제목 없음'; + boardContent.value = boardData.content || ''; + profileImg.value = boardData.profileImg || ''; + date.value = boardData.date || ''; + views.value = boardData.cnt || 0; + likes.value = boardData.likeCount || 0; + dislikes.value = boardData.dislikeCount || 0; + attachment.value = boardData.hasAttachment || null; + commentNum.value = boardData.commentCount || 0; + attachments.value = boardData.attachments || []; + } else { + toastStore.onToast(data.message, 'e'); + router.back(); + } }; // 좋아요, 싫어요 @@ -603,20 +610,23 @@ } try { - const response = await axios.post(`board/${currentBoardId.value}/password`, { + const { data } = await axios.post(`board/${currentBoardId.value}/password`, { LOCBRDPWD: password.value, LOCBRDSEQ: currentBoardId.value, }); - if (response.data.code === 200 && response.data.data === true) { + if (data.code === 200 && data.data === true) { + accessStore.setBoardPassword(password.value); boardPasswordAlert.value = ''; isPassword.value = false; if (lastClickedButton.value === 'edit') { router.push({ name: 'BoardEdit', params: { id: currentBoardId.value } }); + return; } else if (lastClickedButton.value === 'delete') { await deletePost(); } + accessStore.$reset(); lastClickedButton.value = null; } else { boardPasswordAlert.value = '비밀번호가 일치하지 않습니다.'; diff --git a/src/views/error/Error400.vue b/src/views/error/Error400.vue new file mode 100644 index 0000000..9f1c61b --- /dev/null +++ b/src/views/error/Error400.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/views/error/Error404.vue b/src/views/error/Error404.vue new file mode 100644 index 0000000..1ee5a81 --- /dev/null +++ b/src/views/error/Error404.vue @@ -0,0 +1,13 @@ + + + diff --git a/src/views/error/Error500.vue b/src/views/error/Error500.vue new file mode 100644 index 0000000..4e0730a --- /dev/null +++ b/src/views/error/Error500.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/views/voteboard/voteBoardList.vue b/src/views/voteboard/voteBoardList.vue index 0f5dd38..aa077ae 100644 --- a/src/views/voteboard/voteBoardList.vue +++ b/src/views/voteboard/voteBoardList.vue @@ -1,21 +1,28 @@