| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- <template>
- <div>
- <div class="inner--headers">
- <h2>{{ pageId }}</h2>
- <div class="bread--crumbs--wrap">
- <span>홈</span>
- <span>고객센터</span>
- <span>{{ pageId }}</span>
- </div>
- </div>
- <div class="data--list--wrap">
- <div class="item--list--wrap">
- <!-- 문의 상세 카드 -->
- <div class="cs--detail--wrap">
- <div class="cs--detail--header">
- <div class="status-badge" :class="getStatusClass(csDetail.STATUS)">
- {{ csDetail.STATUS == '0' ? '답변대기' : '답변완료' }}
- </div>
- <div class="inquiry-meta">
- <span class="category-badge">{{ getCategoryName(csDetail.CATEGORY) }}</span>
- <span class="date">{{ formatDate(csDetail.REGDATE) }}</span>
- </div>
- </div>
- <div class="cs--detail--content">
- <h3 class="inquiry-title">{{ csDetail.TITLE }}</h3>
-
- <div class="inquiry-info">
- <div class="info-item">
- <span class="label">작성자</span>
- <span class="value">{{ csDetail.NICK_NAME || csDetail.COMPANY_NAME || '알 수 없음' }}</span>
- </div>
- <div class="info-item">
- <span class="label">등록일</span>
- <span class="value">{{ formatDetailDate(csDetail.REGDATE) }}</span>
- </div>
- </div>
- <div class="inquiry-content">
- <h4>문의 내용</h4>
- <div class="content-text" v-html="formatContent(csDetail.CONTENT)"></div>
- </div>
- <!-- 첨부파일 -->
- <div v-if="csDetail.FILE_NAME" class="attachment-section">
- <h4>첨부파일</h4>
- <div class="attachment-item">
- <i class="mdi mdi-paperclip"></i>
- <span class="file-name">{{ csDetail.FILE_NAME_ORIGIN }}</span>
- <v-btn class="download-btn" size="small" @click="downloadFile">
- <i class="mdi mdi-download"></i>
- 다운로드
- </v-btn>
- </div>
- </div>
- <!-- 답변 섹션 -->
- <div v-if="csDetail.STATUS == '1'" class="answer-section">
- <h4>답변</h4>
- <div class="answer-content">
- <div class="answer-meta">
- <span class="admin-badge">관리자</span>
- <span class="answer-date">{{ formatDetailDate(csDetail.ANSWER_REGDATE) }}</span>
- </div>
- <div class="answer-text" v-html="formatContent(csDetail.ADMIN_ANSWER)"></div>
- </div>
- </div>
- <!-- 답변 작성 섹션 (관리자만) -->
- <div class="answer-write-section" v-if="useAtStore.auth.seq === '2' && csDetail.STATUS == '0'">
- <h4>답변 작성</h4>
- <div class="answer-write-form">
- <v-textarea
- v-model="answerContent"
- placeholder="답변 내용을 입력하세요."
- rows="4"
- variant="outlined"
- hide-details
- ></v-textarea>
- <div class="answer-actions">
- <v-btn
- class="submit-answer-btn"
- color="primary"
- @click="submitAnswer"
- :loading="isSubmitting"
- >
- 답변 등록
- </v-btn>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 하단 버튼 -->
- <div class="view-btm-btn">
- <div class="btn-l">
- <v-btn class="custom-btn btn-list" @click="listLocated">
- <i class="mdi mdi-format-list-bulleted"></i>목록
- </v-btn>
- </div>
- <div class="btn-r">
- <!-- 필요시 수정/삭제 버튼 추가 -->
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import useAxios from "@/composables/useAxios";
- import dayjs from 'dayjs';
- /************************************************************************
- | 레이아웃
- ************************************************************************/
- definePageMeta({
- layout: "default",
- });
- /************************************************************************
- | 스토어
- ************************************************************************/
- const useDtStore = useDetailStore();
- const useAtStore = useAuthStore();
- /************************************************************************
- | 전역
- ************************************************************************/
- const { $toast, $log, $dayjs, $eventBus } = useNuxtApp();
- const router = useRouter();
- const pageId = ref("문의 상세");
- // CS 상세 정보
- const csDetail = ref({
- SEQ: '',
- USER_SEQ: '',
- CATEGORY: '',
- TITLE: '',
- CONTENT: '',
- STATUS: '',
- REGDATE: '',
- FILE_NAME: '',
- FILE_NAME_ORIGIN: '',
- ANSWER: '',
- ANSWER_DATE: '',
- NICK_NAME: '',
- COMPANY_NAME: ''
- });
- // 답변 작성 관련
- const answerContent = ref('');
- const isSubmitting = ref(false);
- const isAdmin = computed(() => {
- // 관리자 권한 체크 (실제 권한 체크 로직에 맞게 수정 필요)
- return useAtStore.auth.seq === '2';
- });
- /************************************************************************
- | 함수(METHODS)
- ************************************************************************/
- const listLocated = () => {
- router.push({
- path: "/view/common/cs",
- });
- };
- const getCategoryName = (category) => {
- switch(category) {
- case 'D': return '기능문의';
- case 'E': return '기타문의';
- }
- };
- const getStatusClass = (status) => {
- switch(status) {
- case '0': return 'status-waiting';
- case '1': return 'status-completed';
- default: return '';
- }
- };
- const formatDate = (dateStr) => {
- if (!dateStr) return '';
- const date = new Date(dateStr);
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, '0');
- const day = String(date.getDate()).padStart(2, '0');
- return `${year}.${month}.${day}`;
- };
- const formatDetailDate = (dateStr) => {
- if (!dateStr) return '';
- return dayjs(dateStr).format('YYYY년 MM월 DD일 HH:mm');
- };
- const formatContent = (content) => {
- if (!content) return '';
- return content.replace(/\n/g, '<br>');
- };
- const downloadFile = () => {
- if (csDetail.value.FILE_NAME) {
- window.open(`https://shopdeli.mycafe24.com/cs/download/${csDetail.value.FILE_NAME}`, '_blank');
- }
- };
- const fnDetail = () => {
- let req = {
- seq: useDtStore.boardInfo.seq,
- };
-
- useAxios()
- .get(`/cs/detail/${req.seq}`)
- .then((res) => {
- csDetail.value = res.data;
- })
- .catch((error) => {
- console.error('CS 상세 조회 실패:', error);
- $toast.error('문의 상세 정보를 불러올 수 없습니다.');
- });
- };
- const submitAnswer = async () => {
- if (!answerContent.value.trim()) {
- $toast.error('답변 내용을 입력해주세요.');
- return;
- }
- isSubmitting.value = true;
-
- try {
- const response = await useAxios().post('/cs/answer', {
- CS_SEQ: csDetail.value.SEQ,
- ANSWER: answerContent.value,
- ADMIN_SEQ: useAtStore.auth.seq,
- });
- if (response.data.status === 'success') {
- $toast.success('답변이 등록되었습니다.');
- answerContent.value = '';
- // 상세 정보 다시 불러오기
- fnDetail();
- }
- } catch (error) {
- console.error('답변 등록 실패:', error);
- $toast.error('답변 등록에 실패했습니다.');
- } finally {
- isSubmitting.value = false;
- }
- };
- /************************************************************************
- | 라이프사이클
- ************************************************************************/
- onMounted(() => {
- fnDetail();
- });
- </script>
|