From 8572f8e49f2374314c363f409e2549d7398c1960 Mon Sep 17 00:00:00 2001
From: Yu Sung <hwchon1234@gmail.com>
Date: Fri, 8 Mar 2024 03:13:21 +0900
Subject: [PATCH] =?UTF-8?q?=EC=8B=9C=EA=B7=B8=EB=8B=88=EC=B2=98=20?=
 =?UTF-8?q?=EC=BA=94=20=EB=93=B1=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/api/signature.js           |  23 ++
 src/router/index.js            |   5 +
 src/views/Can/CanSignature.vue | 421 +++++++++++++++++++++++++++++++++
 3 files changed, 449 insertions(+)
 create mode 100644 src/api/signature.js
 create mode 100644 src/views/Can/CanSignature.vue

diff --git a/src/api/signature.js b/src/api/signature.js
new file mode 100644
index 0000000..8eb7405
--- /dev/null
+++ b/src/api/signature.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+
+async function getSignatureList(page) {
+    return Vue.axios.get('/admin/live/signature-can?page=' + (page - 1) + "&size=20");
+}
+
+async function createSignature(formData) {
+    return Vue.axios.post('/admin/live/signature-can', formData, {
+        headers: {
+            "Content-Type": "multipart/form-data",
+        },
+    });
+}
+
+async function modifySignature(formData) {
+    return Vue.axios.put('/admin/live/signature-can', formData, {
+        headers: {
+            "Content-Type": "multipart/form-data",
+        },
+    });
+}
+
+export { getSignatureList, createSignature, modifySignature }
diff --git a/src/router/index.js b/src/router/index.js
index 287dd63..50be377 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -115,6 +115,11 @@ const routes = [
                 name: 'CanCoupon',
                 component: () => import(/* webpackChunkName: "coin" */ '../views/Can/CanCoupon.vue')
             },
+            {
+                path: '/can/signature',
+                name: 'CanSignature',
+                component: () => import(/* webpackChunkName: "coin" */ '../views/Can/CanSignature.vue')
+            },
             {
                 path: '/calculate/live',
                 name: 'CalculateLive',
diff --git a/src/views/Can/CanSignature.vue b/src/views/Can/CanSignature.vue
new file mode 100644
index 0000000..e172015
--- /dev/null
+++ b/src/views/Can/CanSignature.vue
@@ -0,0 +1,421 @@
+<template>
+  <div>
+    <v-toolbar dark>
+      <v-spacer />
+      <v-toolbar-title>시그니처 관리</v-toolbar-title>
+      <v-spacer />
+    </v-toolbar>
+
+    <br>
+
+    <v-container>
+      <v-row>
+        <v-col cols="10" />
+        <v-col>
+          <v-btn
+            block
+            color="#9970ff"
+            dark
+            depressed
+            @click="showWriteDialog"
+          >
+            시그니처 등록
+          </v-btn>
+        </v-col>
+      </v-row>
+      <v-row>
+        <v-col>
+          <v-data-table
+            :headers="headers"
+            :items="signature_list"
+            :loading="is_loading"
+            :items-per-page="-1"
+            item-key="id"
+            class="elevation-1"
+            hide-default-footer
+          >
+            <template v-slot:item.id="{ item }">
+              {{ item.id }}
+            </template>
+
+            <template v-slot:item.nickname="{ item }">
+              {{ item.nickname }}
+            </template>
+
+            <template v-slot:item.can="{ item }">
+              {{ item.can }}
+            </template>
+
+            <template v-slot:item.image="{ item }">
+              <v-img
+                :src="item.image"
+                max-width="200"
+                max-height="200"
+                align="center"
+              />
+            </template>
+          </v-data-table>
+        </v-col>
+      </v-row>
+      <v-row class="text-center">
+        <v-col>
+          <v-pagination
+            v-model="page"
+            :length="total_page"
+            circle
+            @input="next"
+          />
+        </v-col>
+      </v-row>
+    </v-container>
+    <v-row>
+      <v-dialog
+        v-model="show_write_dialog"
+        max-width="1000px"
+        persistent
+      >
+        <v-card>
+          <v-card-title v-if="selected_signature_can !== null">
+            시그니처 캔 수정
+          </v-card-title>
+          <v-card-title v-else>
+            시그니처 캔 등록
+          </v-card-title>
+
+          <v-card-text>
+            <v-row align="center">
+              <v-col cols="4">
+                크리에이터 번호
+              </v-col>
+              <v-col cols="8">
+                <v-text-field
+                  v-model="creator_id"
+                  label="크리에이터 번호"
+                />
+              </v-col>
+            </v-row>
+          </v-card-text>
+
+          <v-card-text>
+            <v-row align="center">
+              <v-col cols="4">
+                캔
+              </v-col>
+              <v-col cols="8">
+                <v-text-field
+                  v-model="can"
+                  label="캔"
+                />
+              </v-col>
+            </v-row>
+          </v-card-text>
+
+          <v-card-text>
+            <v-row align="center">
+              <v-col cols="4">
+                이미지
+              </v-col>
+              <v-col cols="8">
+                <div class="image-select">
+                  <label for="image">
+                    이미지 불러오기
+                  </label>
+                  <v-file-input
+                    id="image"
+                    v-model="image"
+                    @change="imageAdd"
+                  />
+                </div>
+                <img
+                  v-if="image_url"
+                  :src="image_url"
+                  alt=""
+                  class="image-preview"
+                >
+              </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
+              v-if="selected_signature_can !== null"
+              color="blue darken-1"
+              text
+              @click="modifySignatureCan"
+            >
+              수정
+            </v-btn>
+            <v-btn
+              v-else
+              color="blue darken-1"
+              text
+              @click="validate"
+            >
+              등록
+            </v-btn>
+          </v-card-actions>
+        </v-card>
+      </v-dialog>
+    </v-row>
+  </div>
+</template>
+
+<script>
+import * as api from "@/api/signature";
+
+export default {
+  name: "CanSignature",
+
+  data() {
+    return {
+      is_loading: false,
+      is_modify: false,
+      show_write_dialog: false,
+
+      signature_list: [],
+
+      page: 1,
+      total_page: 0,
+
+      can: 0,
+      image: null,
+      image_url: null,
+      creator_id: null,
+      is_active: null,
+      selected_signature_can: null,
+
+      headers: [
+        {
+          text: '순번',
+          align: 'center',
+          sortable: false,
+          value: 'id',
+        },
+        {
+          text: '닉네임',
+          align: 'center',
+          sortable: false,
+          value: 'nickname',
+        },
+        {
+          text: '캔',
+          align: 'center',
+          sortable: false,
+          value: 'can',
+        },
+        {
+          text: '이미지',
+          align: 'center',
+          sortable: false,
+          value: 'image',
+        },
+      ],
+    }
+  },
+
+  async created() {
+    await this.getSignatureList();
+  },
+
+  methods: {
+    notifyError(message) {
+      this.$dialog.notify.error(message)
+    },
+
+    notifySuccess(message) {
+      this.$dialog.notify.success(message)
+    },
+
+    imageAdd(payload) {
+      const file = payload;
+      if (file) {
+        this.image_url = URL.createObjectURL(file)
+        URL.revokeObjectURL(file)
+      } else {
+        this.image_url = null
+      }
+    },
+
+    showWriteDialog() {
+      this.show_write_dialog = true
+    },
+
+    showModifyDialog(item) {
+      this.selected_signature_can = item
+      this.is_active = item.is_active
+      this.image_url = item.image;
+      this.show_write_dialog = true
+    },
+
+    validate() {
+      if (
+        this.can === 0 ||
+        this.image === null ||
+        this.creator_id === null
+      ) {
+        this.notifyError('내용을 입력하세요')
+      } else {
+        this.submit()
+      }
+    },
+
+    cancel() {
+      this.show_write_dialog = false
+      this.image = null
+      this.image_url = null
+      this.creator_id = null
+      this.can = 0
+      this.is_active = null
+      this.selected_signature_can = null
+    },
+
+    async getSignatureList() {
+      this.isLoading = true
+
+      try {
+        let res = await api.getSignatureList(this.page);
+
+        if (res.status === 200 && res.data.success === true) {
+          const data = res.data.data
+
+          const total_page = Math.ceil(data.totalCount / 20)
+          this.signature_list = data.items
+
+          if (total_page <= 0)
+            this.total_page = 1
+          else
+            this.total_page = total_page
+        }
+      } catch (e) {
+        this.notifyError("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
+      } finally {
+        this.isLoading = false
+      }
+    },
+
+    async submit() {
+      if (this.is_loading) return;
+
+      this.is_loading = true
+
+      try {
+        const formData = new FormData()
+        formData.append("can", this.can)
+        formData.append("image", this.image)
+        formData.append("creator_id", this.creator_id)
+
+        const res = await api.createSignature(formData)
+        if (res.status === 200 && res.data.success === true) {
+          this.cancel()
+          this.notifySuccess(res.data.message || '등록되었습니다.')
+
+          this.page = 1
+          await this.getSignatureList()
+        } else {
+          this.is_loading = false
+          this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
+        }
+      } catch (e) {
+        this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
+        this.is_loading = false
+      } finally {
+        this.is_loading = false
+      }
+    },
+
+    async modifySignatureCan() {
+      if (this.is_loading) return;
+
+      this.is_loading = true
+
+      try {
+        const formData = new FormData()
+        formData.append("id", this.selected_signature_can.id)
+
+        if (this.image !== null) {
+          formData.append("image", this.image)
+        }
+
+        if (this.selected_signature_can.isActive !== this.is_active) {
+          formData.append("isActive", this.is_active)
+        }
+
+        const res = await api.modifySignature(formData)
+        if (res.status === 200 && res.data.success === true) {
+          this.cancel()
+          this.notifySuccess(res.data.message || '수정되었습니다.')
+          this.page = 1
+          await this.getSignatureList()
+        } else {
+          this.notifyError(res.data.message || '알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
+          this.is_loading = false
+        }
+      } catch (e) {
+        this.notifyError('알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.')
+        this.is_loading = false
+      } finally {
+        this.is_loading = false
+      }
+    },
+
+    async next() {
+      await this.getSignatureList();
+    }
+  }
+}
+</script>
+
+<style scoped>
+.image-select label {
+  display: inline-block;
+  padding: 10px 20px;
+  background-color: #232d4a;
+  color: #fff;
+  vertical-align: middle;
+  font-size: 15px;
+  cursor: pointer;
+  border-radius: 5px;
+}
+
+.v-file-input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+  border: 0;
+}
+
+.image-preview {
+  max-width: 100%;
+  width: 250px;
+  object-fit: cover;
+  margin-top: 10px;
+}
+
+.v-card__text {
+  margin-top: 20px;
+}
+
+.v-card__actions {
+  margin-top: 100px;
+}
+
+.v-card__actions > .v-btn {
+  font-size: 20px;
+
+}
+
+td img {
+  display: block;
+  margin: 10px auto;
+}
+</style>
-- 
2.40.1