SyuanYu пре 2 година
родитељ
комит
de0a29af15

+ 2 - 1
frontend/.env

@@ -7,6 +7,7 @@ VITE_APP_DOMAIN_DEV=dev.ai-anchor.com # 測試
 VITE_APP_DOMAIN_STAG=stag.ai-anchor.com
 VITE_APP_DOMAIN_PROD=cloud.choozmo.com
 VITE_APP_NAME=AI anchor
-VITE_APP_ENV=production
+# VITE_APP_ENV=dev # 本地
+VITE_APP_ENV=production # 正式
 # VUE_APP_ENV=staging
 # VUE_APP_ENV=production

+ 1 - 1
frontend/src/api.ts

@@ -85,7 +85,7 @@ export const api = {
       const href = URL.createObjectURL(response.data);
       const link = document.createElement('a');
       link.href = href;
-      link.setAttribute('download', `${data.file_name}_hr.png`); //or any other extension
+      link.setAttribute('download', `${data.file_name}_hr.png`);
       document.body.appendChild(link);
       link.click();
       document.body.removeChild(link);

+ 16 - 12
frontend/src/stores/main.ts

@@ -6,7 +6,7 @@ import { getLocalToken, removeLocalToken, saveLocalToken } from "@/utils";
 import type { AppNotification } from '@/interfaces';
 import type { IUserProfile, IUserProfileCreate, IUserProfileUpdate, MainState, Video, VideoCreate, ArticleCreate, Image, ImageDownload } from '@/interfaces';
 import i18n from '@/plugins/i18n'
-import WS from "@/stores/ws";
+import { wsUrl } from "@/env";
 
 const defaultState: MainState = {
   isLoggedIn: null,
@@ -259,8 +259,8 @@ export const useMainStore = defineStore("MainStoreId", {
     async uploadImage(file: File[]) {
       const mainStore = useMainStore();
       try {
-        const loadingNotification = { content: i18n.global.t("sending"), showProgress: true };
-        mainStore.addNotification(loadingNotification);
+        // const loadingNotification = { content: i18n.global.t("sending"), showProgress: true };
+        // mainStore.addNotification(loadingNotification);
         const response = (
           await Promise.all([
             api.uploadImage(mainStore.token, file),
@@ -279,7 +279,7 @@ export const useMainStore = defineStore("MainStoreId", {
             // localStorage.setItem('imagesList', JSON.stringify(this.images));
           })
         );
-        mainStore.removeNotification(loadingNotification);
+        // mainStore.removeNotification(loadingNotification);
         mainStore.addNotification({
           content: i18n.global.t("fileReceived"),
           color: "success",
@@ -306,8 +306,9 @@ export const useMainStore = defineStore("MainStoreId", {
       this.images.push(payload);
     },
     finishImage(payload: string) {
+      const WS = new WebSocket(`${wsUrl}/api/v1/images/sr`);
       let image = this.images.filter(e => {
-        return e.stored_file_name === payload
+        return payload.includes(e.stored_file_name)
       });
 
       if (image) {
@@ -316,13 +317,16 @@ export const useMainStore = defineStore("MainStoreId", {
         })
       }
 
-      // 全部完成後關閉 WebSocket
-      // let processing = this.images.find(e => e.state !== "completed")
-      // if (!processing) {
-      //   setTimeout(() => {
-      //     WS.close();
-      //   }, 1000)
-      // }
+      // 全部完成後回傳 WebSocket
+      let processing = this.images.find(e => e.state !== "completed");
+      console.log('processing', processing);
+
+      if (!processing) {
+        setTimeout(() => {
+          // WS.close();
+          WS.send("unsubscribe");
+        }, 1000)
+      }
 
       return !this.images.some(e => e.state === "completed")
     },

+ 0 - 5
frontend/src/stores/ws.ts

@@ -1,5 +0,0 @@
-import { wsUrl } from "@/env";
-
-const WS = new WebSocket(`${wsUrl}/api/v1/images/sr`);
-
-export default WS;

+ 1 - 1
frontend/src/views/Login.vue

@@ -137,7 +137,7 @@ onMounted(() => {
               <span></span>
             </section>
 
-            <div class="w-100 mx-auto mt-5" style="max-width: 280px">
+            <div class="w-100 mx-auto mt-5" style="max-width: 235px">
               <GoogleLogin
                 :callback="callback"
                 prompt

+ 31 - 6
frontend/src/views/main/Image.vue

@@ -1,18 +1,31 @@
 <script setup lang="ts">
-import { ref, reactive, onMounted } from "vue";
+import { ref, reactive, onMounted, watch } from "vue";
 import { useMainStore } from "@/stores/main";
 import { required } from "@/utils";
 import { useI18n } from "vue-i18n";
 import type { ImageDownload } from "@/interfaces";
 import Dialog from "@/components/Dialog.vue";
-import WS from "@/stores/ws";
+import { wsUrl } from "@/env";
 
+const WS = new WebSocket(`${wsUrl}/api/v1/images/sr`);
 const mainStore = useMainStore();
 const { t } = useI18n();
 const valid = ref(true);
 const Form = ref();
 let imgFiles = ref();
 let imgList: any[] = reactive([]);
+let loading = ref(false);
+let imgInput = ref(true);
+
+watch(imgFiles, (newVal, oldVal) => {
+  if (newVal) {
+    if (!newVal.length) {
+      imgInput.value = true;
+    } else {
+      imgInput.value = false;
+    }
+  }
+});
 
 // props
 let dialog = reactive({
@@ -23,10 +36,10 @@ let dialog = reactive({
 
 async function Submit() {
   WS.send("subscribe");
-
+  loading.value = true;
   setTimeout(() => {
     dialog.show = true;
-  }, 2000);
+  }, 500);
   await mainStore.uploadImage(imgFiles.value);
   (Form as any).value.reset();
   for (let i = 0; i < mainStore.images.length; i++) {
@@ -53,7 +66,10 @@ onMounted(() => {
 
   // webSocket
   WS.onmessage = function (e) {
-    mainStore.finishImage(e.data);
+    setTimeout(() => {
+      mainStore.finishImage(e.data);
+      loading.value = false;
+    }, 1000);
   };
 });
 
@@ -113,8 +129,14 @@ const headers = [
             multiple
             label="請選擇圖片"
             prepend-icon="add_photo_alternate"
+            accept=".jpg, .png"
+            :rules="[(imgFiles) => imgFiles.length || '']"
           ></v-file-input>
 
+          <small class="d-block" style="margin: -15px 0 0 40px"
+            >支援格式:JPEG、PNG</small
+          >
+
           <!-- <p>請點擊加入圖片並開始優化</p> -->
         </v-form>
       </v-card-text>
@@ -125,6 +147,8 @@ const headers = [
           color="primary"
           class="px-5"
           prepend-icon="file_upload"
+          :loading="loading"
+          :disabled="imgInput"
           @click="Submit()"
           >上傳</v-btn
         >
@@ -154,6 +178,7 @@ const headers = [
         <template v-slot:item.stored_file_name="{ item }">
           <v-btn
             flat
+            :disabled="item.raw.state !== 'completed'"
             @click="downloadImg(item.raw.file_name, item.raw.stored_file_name)"
           >
             <v-icon icon="crop_original" />
@@ -214,4 +239,4 @@ const headers = [
     margin-top: 20px;
   }
 }
-</style>
+</style>

+ 5 - 1
frontend/src/views/main/Progress.vue

@@ -44,7 +44,11 @@ onMounted(async () => {
         <h3>{{ t("progress") }}</h3>
       </v-toolbar-title>
     </v-toolbar>
-    <v-data-table :headers="headers" :items="videos">
+    <v-data-table
+      :headers="headers"
+      :items="videos"
+      :sort-by="[{ key: 'id', order: 'desc' }]"
+    >
       <template v-slot:item.progress_state="{ item }">
         <span v-if="item.raw.progress_state === 'completed'">
           <v-icon icon="check_circle" color="success" />