165 lines
5.7 KiB
Vue
165 lines
5.7 KiB
Vue
<template>
|
|
<div class="container-xxl flex-grow-1 container-p-y">
|
|
<div class="card">
|
|
<div class="pb-4 rounded-top">
|
|
<div class="container py-12 px-xl-10 px-4" style="padding-bottom: 0px !important">
|
|
<h3 class="text-center mb-2 mt-4">글 수정</h3>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-12">
|
|
<div class="card-body">
|
|
<!-- 제목 입력 -->
|
|
<FormInput title="제목" name="title" :is-essential="true" :is-alert="titleAlert" v-model="title" />
|
|
|
|
<!-- 첨부파일 업로드 -->
|
|
<FormFile
|
|
title="첨부파일"
|
|
name="files"
|
|
:is-alert="attachFilesAlert"
|
|
@update:data="handleFileUpload"
|
|
@update:isValid="isFileValid = $event"
|
|
/>
|
|
|
|
<!-- 실시간 반영된 파일 개수 표시 -->
|
|
<p class="text-muted mt-1">첨부파일: {{ fileCount }} / 5개</p>
|
|
<p v-if="fileError" class="text-danger">{{ fileError }}</p>
|
|
|
|
<ul class="list-group mt-2" v-if="attachFiles.length">
|
|
<li
|
|
v-for="(file, index) in attachFiles"
|
|
:key="index"
|
|
class="list-group-item d-flex justify-content-between align-items-center"
|
|
>
|
|
{{ file.name }}
|
|
<button class="close-btn" @click="removeFile(index)">✖</button>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- 내용 입력 -->
|
|
<div class="mb-4">
|
|
<label for="html5-tel-input" class="col-md-2 col-form-label">
|
|
내용
|
|
<span class="text-red">*</span>
|
|
<div class="invalid-feedback" :class="contentAlert ? 'display-block' : ''">내용을 확인해주세요.</div>
|
|
</label>
|
|
<div class="col-md-12">
|
|
<QEditor
|
|
v-if="contentLoaded"
|
|
@update:data="content = $event"
|
|
@update:imageUrls="imageUrls = $event"
|
|
:initialData="content"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 버튼 -->
|
|
<div class="mb-4 d-flex justify-content-end">
|
|
<button type="button" class="btn btn-info right" @click="goList">
|
|
<i class="bx bx-left-arrow-alt"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-primary ms-1" @click="updateBoard">
|
|
<i class="bx bx-check"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import QEditor from '@c/editor/QEditor.vue';
|
|
import FormInput from '@c/input/FormInput.vue';
|
|
import { ref, onMounted } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import axios from '@api';
|
|
|
|
// 상태 변수
|
|
const title = ref('');
|
|
const content = ref('');
|
|
|
|
// 경고 상태
|
|
const titleAlert = ref(false);
|
|
const contentAlert = ref(false);
|
|
const contentLoaded = ref(false); //
|
|
|
|
// 라우터
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
const currentBoardId = ref(route.params.id); // 라우트에서 ID 가져오기
|
|
// 게시물 데이터 로드
|
|
const fetchBoardDetails = async () => {
|
|
try {
|
|
const response = await axios.get(`board/${currentBoardId.value}`);
|
|
const data = response.data.data;
|
|
|
|
if (!data) {
|
|
console.error('API에서 게시물 데이터를 반환하지 않았습니다.');
|
|
return;
|
|
}
|
|
|
|
// 데이터 설정
|
|
title.value = data.title || '제목 없음';
|
|
content.value = data.content || '내용 없음';
|
|
contentLoaded.value = true;
|
|
} catch (error) {
|
|
console.error('게시물 가져오기 오류:', error.response || error.message);
|
|
}
|
|
};
|
|
|
|
// 목록 페이지로 이동
|
|
const goList = () => {
|
|
router.push('/board');
|
|
};
|
|
|
|
// 게시물 수정
|
|
const updateBoard = async () => {
|
|
// 유효성 검사
|
|
if (!title.value) {
|
|
titleAlert.value = true;
|
|
return;
|
|
}
|
|
titleAlert.value = false;
|
|
|
|
if (!content.value) {
|
|
contentAlert.value = true;
|
|
return;
|
|
}
|
|
contentAlert.value = false;
|
|
|
|
try {
|
|
// 수정 데이터 전송
|
|
const boardData = {
|
|
LOCBRDTTL: title.value,
|
|
LOCBRDCON: JSON.stringify(content.value),
|
|
LOCBRDSEQ: currentBoardId.value,
|
|
};
|
|
|
|
await axios.put(`board/${currentBoardId.value}`, boardData);
|
|
|
|
alert('게시물이 수정되었습니다.');
|
|
goList();
|
|
} catch (error) {
|
|
console.error('게시물 수정 중 오류 발생:', error);
|
|
alert('게시물 수정에 실패했습니다.');
|
|
}
|
|
};
|
|
|
|
// 컴포넌트 마운트 시 데이터 로드
|
|
onMounted(() => {
|
|
if (currentBoardId.value) {
|
|
fetchBoardDetails();
|
|
} else {
|
|
console.error('잘못된 게시물 ID:', currentBoardId.value);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.text-red {
|
|
color: red;
|
|
text-align: center;
|
|
}
|
|
</style>
|