From 756e0321f8e209c1efa50604d3f9804d3f60c99e Mon Sep 17 00:00:00 2001 From: Yu Sung <hwchon1234@gmail.com> Date: Wed, 24 Apr 2024 14:22:41 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8B=9C=EB=A6=AC=EC=A6=88=EC=97=90=20?= =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EC=B6=94=EA=B0=80=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/audio_content_series.js | 10 +- src/views/Content/ContentSeriesDetail.vue | 295 ++++++++++++++++++++-- 2 files changed, 284 insertions(+), 21 deletions(-) diff --git a/src/api/audio_content_series.js b/src/api/audio_content_series.js index a2c19c5..b7bfbe6 100644 --- a/src/api/audio_content_series.js +++ b/src/api/audio_content_series.js @@ -34,6 +34,13 @@ async function getSeriesContent(seriesId, page) { ); } +async function searchContentNotInSeries(seriesId, searchWord) { + return Vue.axios.get( + "/creator-admin/audio-content/series/content/search?series_id=" + seriesId + + "&search_word=" + searchWord + ) +} + async function addingContentToTheSeries(seriesId, contentIdList) { return Vue.axios.post( "/creator-admin/audio-content/series/add/content", @@ -56,5 +63,6 @@ export { getSeriesDetail, getSeriesContent, addingContentToTheSeries, - removeContentInTheSeries + removeContentInTheSeries, + searchContentNotInSeries } diff --git a/src/views/Content/ContentSeriesDetail.vue b/src/views/Content/ContentSeriesDetail.vue index b0263b7..2810713 100644 --- a/src/views/Content/ContentSeriesDetail.vue +++ b/src/views/Content/ContentSeriesDetail.vue @@ -12,7 +12,8 @@ 제목 : {{ series_detail.title }} </v-card-text> <v-card-text> - 소개 : <vue-show-more-text + 소개 : + <vue-show-more-text :text="series_detail.introduction" :lines="2" /> @@ -42,27 +43,18 @@ </v-col> <v-col cols="8"> <v-row> - <v-col cols="6" /> - <v-col cols="3"> + <v-col cols="8" /> + <v-col cols="4"> <v-btn block color="#3bb9f1" dark depressed + @click="showAddContent" > 콘텐츠 추가 </v-btn> </v-col> - <v-col cols="3"> - <v-btn - block - color="#3bb9f1" - dark - depressed - > - 콘텐츠 등록 - </v-btn> - </v-col> </v-row> <v-row> <v-col v-if="series_content_list.length > 0"> @@ -91,9 +83,9 @@ > <td align="center"> <v-img - max-width="100" - max-height="100" :src="content.coverImage" + max-width="100" + class="content-cover-image" /> </td> <td align="center"> @@ -110,7 +102,7 @@ <td align="center"> <v-btn color="#3bb9f1" - @click="removeContentInSeries(content)" + @click="deleteConfirm(content)" > 삭제 </v-btn> @@ -119,6 +111,20 @@ </tbody> </template> </v-simple-table> + <br><br> + <v-row + v-if="total_page > 0" + class="text-center" + > + <v-col> + <v-pagination + v-model="page" + :length="total_page" + circle + @input="next" + /> + </v-col> + </v-row> </v-col> <v-col v-else @@ -131,6 +137,150 @@ </v-row> </v-container> + <v-dialog + v-model="show_add_series_content" + max-width="1000px" + persistent + > + <v-card> + <v-card-title> + 콘텐츠 추가 + </v-card-title> + <v-card-text> + <v-text-field + v-model="search_word" + label="콘텐츠 제목" + @keyup.enter="searchContentNotInSeries" + > + <v-btn + slot="append" + color="#3bb9f1" + dark + @click="searchContentNotInSeries" + > + 검색 + </v-btn> + </v-text-field> + </v-card-text> + <v-card-text v-if="search_content_list.length > 0 || add_content_list.length > 0"> + <v-row> + <v-col> + 검색결과 + <v-simple-table> + <template v-slot:default> + <thead> + <tr> + <th class="text-center"> + 제목 + </th> + <th /> + </tr> + </thead> + <tbody> + <tr + v-for="content in search_content_list" + :key="content.contentId" + > + <td>{{ content.title }}</td> + <td> + <v-btn + color="#3bb9f1" + @click="addContent(content)" + > + 추가 + </v-btn> + </td> + </tr> + </tbody> + </template> + </v-simple-table> + </v-col> + <v-col v-if="add_content_list.length > 0"> + 추가할 콘텐츠 + <v-simple-table> + <template> + <thead> + <tr> + <th class="text-center"> + 제목 + </th> + <th /> + </tr> + </thead> + <tbody> + <tr + v-for="content in add_content_list" + :key="content.contentId" + > + <td>{{ content.title }}</td> + <td> + <v-btn + color="#3bb9f1" + @click="removeContent(content)" + > + 제거 + </v-btn> + </td> + </tr> + </tbody> + </template> + </v-simple-table> + </v-col> + </v-row> + </v-card-text> + <v-card-actions v-show="!is_loading"> + <v-spacer /> + <v-btn + color="blue darken-1" + text + @click="cancel" + > + 취소 + </v-btn> + <v-btn + color="blue darken-1" + text + @click="addContentInSeries" + > + 추가 + </v-btn> + </v-card-actions> + </v-card> + </v-dialog> + + <v-dialog + v-model="show_delete_confirm_dialog" + max-width="400px" + persistent + > + <v-card> + <v-card-text /> + <v-card-text v-if="selected_series_content !== null"> + {{ selected_series_content.title }} 삭제하시겠습니까? + </v-card-text> + <v-card-text v-else> + 삭제하시겠습니까? + </v-card-text> + <v-card-actions v-show="!is_loading"> + <v-spacer /> + <v-btn + color="blue darken-1" + text + @click="deleteCancel" + > + 취소 + </v-btn> + <v-btn + color="blue darken-1" + text + @click="removeContentInSeries" + > + 확인 + </v-btn> + </v-card-actions> + </v-card> + </v-dialog> + <v-dialog v-model="is_loading" max-width="400px" @@ -166,13 +316,24 @@ export default { selected_series_content: null, page: 1, total_page: 0, + + search_word: '', + add_content_list: [], + search_content_list: [], + show_add_series_content: false, + + show_delete_confirm_dialog: false, } }, async created() { this.series_id = this.$route.params.seriesId - await this.getSeriesDetail() - await this.getSeriesContentList() + if (this.series_id !== undefined && this.series_id > 0) { + await this.getSeriesDetail() + await this.getSeriesContentList() + } else { + this.$router.go(-1); + } }, methods: { @@ -184,6 +345,91 @@ export default { this.$dialog.notify.success(message) }, + cancel() { + this.search_word = '' + this.add_content_list = [] + this.search_content_list = [] + this.selected_series_content = null + this.show_add_series_content = false + this.show_delete_confirm_dialog = false + }, + + deleteConfirm(series_content) { + this.selected_series_content = series_content + this.show_delete_confirm_dialog = true + }, + + deleteCancel() { + this.cancel(); + }, + + showAddContent() { + this.show_add_series_content = true + }, + + addContent(content) { + this.search_content_list = this.search_content_list.filter((item) => { + return item.contentId !== content.contentId + }); + this.add_content_list.push(content) + }, + + removeContent(content) { + this.add_content_list = this.add_content_list.filter((item) => { + return item.contentId !== content.contentId + }); + this.search_content_list.push(content) + }, + + async searchContentNotInSeries() { + if (this.search_word.length < 2) { + this.notifyError('검색어를 2글자 이상 입력하세요.') + return + } + + this.is_loading = true + + try { + const res = await api.searchContentNotInSeries(this.series_id, this.search_word) + + if (res.data.success === true) { + this.search_content_list = res.data.data + if (res.data.data.length <= 0) { + this.notifyError('검색결과가 없습니다.') + } + } else { + this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.') + } + } catch (e) { + this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.') + } finally { + this.is_loading = false + } + }, + + async addContentInSeries() { + this.is_loading = true + const contentIdList = this.add_content_list.map((item) => { + return item.contentId + }) + + try { + const res = await api.addingContentToTheSeries(this.series_id, contentIdList) + if (res.status === 200 && res.data.success === true) { + this.cancel() + this.page = 1 + this.total_page = 0 + await this.getSeriesContentList() + } else { + this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.') + } + } catch (e) { + this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.') + } finally { + this.is_loading = false + } + }, + async getSeriesDetail() { this.is_loading = true @@ -201,6 +447,10 @@ export default { } }, + async next() { + await this.getSeriesContentList() + }, + async getSeriesContentList() { try { const res = await api.getSeriesContent(this.series_id, this.page) @@ -221,16 +471,17 @@ export default { } }, - async removeContentInSeries(content) { + async removeContentInSeries() { this.is_loading = true try { - const res = await api.removeContentInTheSeries(this.series_id, content.contentId) + const res = await api.removeContentInTheSeries(this.series_id, this.selected_series_content.contentId) if (res.status === 200 && res.data.success === true) { this.page = 1 this.total_page = 0 this.series_content_list = [] + this.cancel() this.notifySuccess('삭제되었습니다.') await this.getSeriesContentList() } else { @@ -255,6 +506,10 @@ export default { aspect-ratio: 1/1.4; } +.content-cover-image { + aspect-ratio: 1; +} + .no-series-content { height: 50vh; margin-top: 100px;