콘텐츠 카테고리 관리 UI 추가

This commit is contained in:
Yu Sung 2024-02-06 21:50:19 +09:00
parent 82674796e8
commit 565205be92
3 changed files with 423 additions and 0 deletions

28
src/api/category.js Normal file
View File

@ -0,0 +1,28 @@
import Vue from 'vue';
async function saveCategory(title) {
return Vue.axios.post('/category', {title: title, contentIdList: []});
}
async function modifyCategory(title, categoryId) {
return Vue.axios.put('/category', {
categoryId: categoryId,
title: title,
addContentIdList: [],
removeContentIdList: []
});
}
async function deleteCategory(categoryId) {
return Vue.axios.delete('/category/' + categoryId)
}
async function getCategoryList(creatorId) {
return Vue.axios.get('/category?creatorId=' + creatorId)
}
async function updateCategoryOrders(ids) {
return Vue.axios.put('/category/orders', {ids: ids})
}
export {saveCategory, modifyCategory, deleteCategory, getCategoryList, updateCategoryOrders}

View File

@ -20,6 +20,11 @@ const routes = [
name: 'ContentList',
component: () => import(/* webpackChunkName: "content" */ '../views/Content/ContentList.vue')
},
{
path: '/content/category/list',
name: 'ContentCategoryList',
component: () => import(/* webpackChunkName: "content" */ '../views/Content/ContentCategoryList.vue')
},
{
path: '/calculate/live',
name: 'CalculateLive',

View File

@ -0,0 +1,390 @@
<template>
<div>
<v-container>
<v-row>
<v-col cols="3">
<v-btn
block
color="#3bb9f1"
dark
depressed
@click="showCreateCategoryDialog"
>
카테고리 추가
</v-btn>
<br><br>
<draggable
:list="category_list"
class="list-group"
@end="onDropCategoryCallback()"
>
<v-list
v-for="category in category_list"
:key="category.category"
class="py-0"
rounded
>
<v-list-item :class="{ 'category-selected-item': category === selected_category }">
<v-list-item-title @click="clickCategory(category)">
{{ category.category }}
</v-list-item-title>
<v-list-item-icon @click="clickModifyCategory(category)">
<v-icon>mdi-pencil</v-icon>
</v-list-item-icon>
</v-list-item>
</v-list>
</draggable>
</v-col>
<v-col cols="1" />
<v-col cols="8">
<v-row>
<v-col cols="9" />
<v-col cols="3">
<v-btn
block
color="#3bb9f1"
dark
depressed
@click="showAddContent"
>
콘텐츠 추가
</v-btn>
</v-col>
</v-row>
<br><br>
<p v-if="selected_category !== null && selected_category !== undefined">
선택된 카테고리 : {{ selected_category.category }}
</p>
<p v-else>
카테고리를 선택해 주세요
</p>
<v-data-table
:headers="headers"
:items="content_list"
:loading="is_loading"
:items-per-page="-1"
item-key="id"
class="elevation-1"
hide-default-footer
>
<template v-slot:body="props">
<draggable
v-model="props.items"
tag="tbody"
>
<tr
v-for="(item, index) in props.items"
:key="index"
>
<td>
<img
:src="item.image"
alt=""
height="100"
width="100"
>
</td>
<td><h3>{{ item.title }}</h3></td>
<td>
<h3 v-if="item.isAdult">
O
</h3>
<h3 v-else>
X
</h3>
</td>
<td>
<v-btn
:disabled="is_loading"
>
삭제
</v-btn>
</td>
</tr>
</draggable>
</template>
</v-data-table>
</v-col>
</v-row>
</v-container>
<v-container>
<v-row>
<v-dialog
v-model="show_create_category_dialog"
max-width="1000px"
persistent
>
<v-card>
<v-card-title v-if="modify_category">
카테고리 수정
</v-card-title>
<v-card-title v-else>
카테고리 추가
</v-card-title>
<v-card-text>
<v-text-field
v-model="title"
label="카테고리 제목"
required
/>
</v-card-text>
<v-card-actions v-show="!is_loading">
<v-spacer />
<v-btn
color="blue darken-1"
text
@click="cancelCreateCategory"
>
취소
</v-btn>
<v-btn
v-if="modify_category"
color="blue darken-1"
text
@click="deleteCategory"
>
삭제
</v-btn>
<v-btn
v-if="modify_category"
color="blue darken-1"
text
@click="modifyCategory"
>
수정
</v-btn>
<v-btn
v-else
color="blue darken-1"
text
@click="saveCategory"
>
등록
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</v-container>
<v-container>
<v-row />
</v-container>
</div>
</template>
<script>
import Draggable from 'vuedraggable';
import * as api from "@/api/category";
export default {
name: "ContentCategoryList",
components: {Draggable},
data() {
return {
is_loading: false,
show_add_content_dialog: false,
show_create_category_dialog: false,
modify_category: false,
title: '',
selected_category: null,
modify_selected_category: null,
category_list: [],
content_list: [],
headers: [
{
text: '커버이미지',
align: 'center',
sortable: false,
value: 'image',
},
{
text: '제목',
align: 'center',
sortable: false,
value: 'title',
},
{
text: '19금',
align: 'center',
sortable: false,
value: 'isAdult',
},
{
text: '관리',
align: 'center',
sortable: false,
value: 'management'
},
]
}
},
async created() {
await this.getCategoryList()
},
methods: {
notifyError(message) {
this.$dialog.notify.error(message)
},
notifySuccess(message) {
this.$dialog.notify.success(message)
},
showCreateCategoryDialog() {
if (this.category_list.length >= 10) {
this.notifyError('카테고리는 최대 10개 까지 등록 가능합니다.')
return
}
this.show_create_category_dialog = true
},
showAddContent() {
if (this.selected_category === null || this.selected_category === undefined) {
this.notifyError('카테고리를 선택하세요')
return
}
this.show_add_content_dialog = true
},
cancelCreateCategory() {
this.title = ''
this.modify_category = false
this.modify_selected_category = null
this.show_create_category_dialog = false
},
clickCategory(category) {
this.selected_category = category
},
clickModifyCategory(category) {
this.modify_category = true
this.modify_selected_category = category
this.title = category.category
this.show_create_category_dialog = true
},
async getCategoryList() {
this.is_loading = true
try {
let res = await api.getCategoryList(this.$store.state.accountStore.userId)
if (res.data.success === true) {
this.category_list = res.data.data
} else {
this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
}
} catch (e) {
this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
} finally {
this.is_loading = false
}
},
async saveCategory() {
if (this.title.trim().length <= 0) {
this.notifyError("제목을 입력하세요")
return
}
if (this.is_loading) return;
try {
this.is_loading = true
let res = await api.saveCategory(this.title)
if (res.data.success === true) {
this.title = ''
this.category_list = []
this.selected_category = null
this.cancelCreateCategory()
await this.getCategoryList()
} else {
this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
}
} catch (e) {
this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
} finally {
this.is_loading = false
}
},
async deleteCategory() {
try {
this.is_loading = true
let res = await api.deleteCategory(this.modify_selected_category.categoryId)
if (res.data.success === true) {
this.title = ''
this.category_list = []
this.selected_category = null
this.cancelCreateCategory()
await this.getCategoryList()
} else {
this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
}
} catch (e) {
this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
} finally {
this.is_loading = false
}
},
async modifyCategory() {
if (this.title.trim().length <= 0) {
this.notifyError("제목을 입력하세요")
return
}
if (this.is_loading) return;
try {
this.is_loading = true
let res = await api.modifyCategory(this.title, this.modify_selected_category.categoryId)
if (res.data.success === true) {
this.title = ''
this.category_list = []
this.selected_category = null
this.cancelCreateCategory()
await this.getCategoryList()
} else {
this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
}
} catch (e) {
this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
} finally {
this.is_loading = false
}
},
async onDropCategoryCallback() {
const ids = this.category_list.map((category) => {
return category.categoryId
})
const res = await api.updateCategoryOrders(ids)
if (res.status === 200 && res.data.success === true) {
this.notifySuccess('수정되었습니다.')
} else {
this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
}
},
}
}
</script>
<style scoped>
.category-selected-item {
background-color: #3bb9f1;
color: white !important;
}
</style>