SyuanYu 1 年之前
父節點
當前提交
375ec96ffe

+ 0 - 3
src/components/Map.vue

@@ -19,9 +19,6 @@ onMounted(() => {
   });
 
   store.$subscribe((mutation, state) => {
-    console.log("state >>>", state);
-    console.log("state mapLocation >>>", state.mapLocation.lat);
-
     if (state.mapLocation.lat) {
       const newCenter = {
         lat: state.mapLocation.lat,

+ 1 - 0
src/language/en.json

@@ -272,6 +272,7 @@
     "auto_fill_location_address": "Auto-fill Location Address",
     "auto_fill_location_name": "Auto-fill Location Name",
     "cover_image": "Cover Image",
+    "portfolio_image": "Portfolio Image",
     "upload_course_cover_image": "Upload Course Cover Image",
     "upload_portfolio_image": "Upload Portfolio Image",
     "choose_image": "Choose Image",

+ 1 - 0
src/language/zh.json

@@ -271,6 +271,7 @@
     "auto_fill_location_address": "自動帶入據點地址",
     "auto_fill_location_name": "自動帶入據點名稱",
     "cover_image": "課程封面",
+    "portfolio_image": "工藝成品圖",
     "upload_course_cover_image": "上傳課程封面",
     "upload_portfolio_image": "上傳工藝成品圖",
     "choose_image": "選擇相片上傳",

+ 0 - 1
src/router/index.js

@@ -387,7 +387,6 @@ router.beforeEach((to, from, next) => {
     if (haveToken) {
       next(); // 允許使用者訪問目標頁面
     } else {
-      console.log('>> 沒有token');
       store.loginDialog = true; // 開啟登入視窗
       next(); // 若無 token 直接輸入網址前往時,將重定向至首頁
     }

+ 2 - 2
src/views/CollegeGroup/Cross.vue

@@ -298,7 +298,7 @@ async function handleSearch() {
 
   <p class="cooming-soon">「籌備中 cooming soon」</p> -->
 
-  <!-- <h2 class="title pb-10">{{ t("craft_plus") }}</h2>
+  <h2 class="title pb-10">{{ t("craft_plus") }}</h2>
 
   <div class="craftplus-item mb-6"></div>
 
@@ -307,7 +307,7 @@ async function handleSearch() {
     width="100%"
     height="600"
     frameborder="0"
-  ></iframe> -->
+  ></iframe>
 
   <!-- <div class="craftplus-item mb-6"></div> -->
 

+ 27 - 0
src/views/Courses/Create.vue

@@ -928,6 +928,12 @@ function deleteEvent(index) {
 // 個人資料之同意提供
 let consent_1 = ref(false);
 let consent_2 = ref(false);
+
+// 移除上傳圖片
+function removeImg(index) {
+  portfolioImg.value.splice(index, 1);
+  portfolioImgUrl.value.splice(index, 1);
+}
 </script>
 
 <template>
@@ -2776,6 +2782,17 @@ let consent_2 = ref(false);
                                 class="d-flex fill-height align-center justify-center"
                               >
                                 <img :src="portfolioImgUrl[index]" alt="" />
+
+                                <button
+                                  @click="removeImg(index)"
+                                  class="position-absolute remove-btn"
+                                >
+                                  <v-icon
+                                    color="error"
+                                    size="38"
+                                    icon="mdi-close-circle-outline"
+                                  ></v-icon>
+                                </button>
                                 <!-- <v-scale-transition>
                               <v-icon
                                 v-if="isSelected"
@@ -3153,4 +3170,14 @@ input[type="checkbox"] {
     line-height: 2em;
   }
 }
+
+.remove-btn {
+  top: 3px;
+  right: 3px;
+  &:hover {
+    .v-icon {
+      opacity: 0.8;
+    }
+  }
+}
 </style>

+ 16 - 6
src/views/Crafts.vue

@@ -354,7 +354,7 @@ async function getImediaVideo() {
     const response = await axios.post(url);
     const list = JSON.parse(response.data.data);
     list.data.map((item) => {
-      if (item.video_link) {
+      if (item.video_link && item.enabled && item.permission === 1) {
         imedia.list.push(item);
       }
     });
@@ -363,13 +363,15 @@ async function getImediaVideo() {
     console.log("list category", list.category[0]);
     categoryList.value = [];
     list.category[0].categories.map((item) => {
-      // console.log('item',item);
-      // media_category_id
       let data = {
         id: item.media_category_id,
         title: item.name[1].zh_TW,
       };
-      categoryList.value.push(data);
+
+      // 排除空的影片類別 (permission !== 1 && enabled !== 1)
+      if (item.media_category_id !== 1227 && item.media_category_id !== 1205) {
+        categoryList.value.push(data);
+      }
     });
     console.log("categoryList.value", categoryList.value);
 
@@ -451,7 +453,7 @@ const restorationArticles = reactive({
         </v-row>
 
         <!-- 線上工藝 -->
-        <!-- <h2 class="mb-16 pb-5">{{ t("college_group_4") }}</h2>
+        <h2 class="mb-16 pb-5">{{ t("college_group_4") }}</h2>
 
         <v-row class="mt-16">
           <v-col md="2" cols="12">
@@ -533,6 +535,14 @@ const restorationArticles = reactive({
                         <div class="video-box">
                           <video controls>
                             <source
+                              v-if="
+                                item.video_link.video_source.mp4.length === 1
+                              "
+                              :src="`${item.video_link.video_source.mp4[0]}?api_access_key=08c9cdf9-a1d6-4997-943c-4f08f34ed2f7`"
+                              type="video/mp4"
+                            />
+                            <source
+                              v-else
                               :src="`${
                                 item.video_link.video_source.mp4[3]
                                   ? item.video_link.video_source.mp4[3]
@@ -566,7 +576,7 @@ const restorationArticles = reactive({
               :length="imediatotalPagesOnline"
             ></v-pagination>
           </v-col>
-        </v-row> -->
+        </v-row>
 
         <!-- 線上體驗課程 -->
         <h2 class="mb-16 pb-5">

+ 0 - 22
src/views/Home.vue

@@ -144,28 +144,6 @@ async function getClass() {
 
   console.log("schoolState url", url);
 
-  // if (schoolState.value) {
-  //   let location = "";
-
-  //   if (selectedCounty.value && selectedDistrict.value) {
-  //     location = `${selectedCounty.value}${selectedDistrict.value}`;
-  //     console.log("location &&", location);
-  //   } else if (selectedCounty.value) {
-  //     location = `${selectedCounty.value}`;
-  //     console.log("location >>", location);
-  //   }
-
-  //   if (schoolKeyword.value !== "" && location !== "") {
-  //     url += `&keyword=${schoolKeyword.value}&location_keyword=${location}`;
-  //   } else if (schoolKeyword.value === "" && location !== "") {
-  //     url += `&location_keyword=${location}`;
-  //   } else if (schoolKeyword.value !== "" && location === "") {
-  //     url += `&keyword=${schoolKeyword.value}`;
-  //   }
-
-  //   console.log("url", url);
-  // }
-
   try {
     const response = await axios.get(assignState.value ? assignUrl : url);
     totalPages.value = store.getTotalPages(response.data.total_num, 4);

+ 120 - 8
src/views/User/Courses.vue

@@ -240,6 +240,8 @@ let course = reactive({
   introduction: "", // 課程簡介
   organizer: "", // 主辦單位
   cover_img_file: "", // 課程圖片
+  work_imgs: "", // 作品集圖片
+  origin_work_imgs: "", // 原有作品集圖片(api回傳)
   group_id: 2, // 學群編號(技藝)
   group_sort: "", // 學群細分
   special_class_list_name: "",
@@ -252,9 +254,18 @@ let course = reactive({
 
 let classNameId = ref(null);
 let courseLoading = ref(false);
-let coverImgLoading = ref(false);
 let enCode = ref(null);
 
+// 封面圖片
+let coverImg = ref("");
+let coverImgUrl = ref("");
+let coverImgLoading = ref(false);
+
+// 作品集圖片
+let portfolioImg = ref([]);
+let portfolioImgUrl = ref([]);
+let portfolioImgLoading = ref(false);
+
 // 取得課程
 async function getCourse(id) {
   classNameId.value = id;
@@ -268,13 +279,11 @@ async function getCourse(id) {
       `${store.apiUrl}/api/get_class_name?class_name_id=${id}&access_token=${token}`
     );
 
-    // console.log('課程資料',response);
     courses.list = response.data.classes;
     console.log("課程資料", courses.list);
     let coursesData = response.data.classes[0];
     enCode.value = coursesData.encode;
     console.log("coursesData", coursesData);
-    // classNameId.value = coursesData.class_name_id;
 
     // 存入課程資料
     for (const key in coursesData) {
@@ -290,6 +299,21 @@ async function getCourse(id) {
           coverImgLoading.value = false;
         }, 1500);
       }
+
+      if (coursesData["work_imgs"] !== "") {
+        course.origin_work_imgs = coursesData["work_imgs"];
+        portfolioImgLoading.value = true;
+        let workImgs = JSON.parse(coursesData["work_imgs"].replace(/'/g, '"'));
+
+        portfolioImgUrl.value = [];
+        workImgs.map((item) => {
+          portfolioImgUrl.value.push(`${store.imgUrl}/${item}`);
+        });
+
+        setTimeout(() => {
+          portfolioImgLoading.value = false;
+        }, 1500);
+      }
     }
 
     console.log("最終 course", course);
@@ -310,13 +334,26 @@ async function saveCourse() {
   delete course.access_token;
 
   course["class_name_id"] = classNameId.value;
+
+  // 封面圖片
   if (coverImg.value) {
     course["cover_img_file"] = coverImg.value;
   }
 
+  // 作品集圖片
+  if (portfolioImg.value.length) {
+    course.work_imgs = portfolioImg.value;
+  }
+
   const formData = new FormData();
   for (const key in course) {
-    formData.append(key, course[key]);
+    if (key === "work_imgs") {
+      course.work_imgs.forEach((file) => {
+        formData.append("work_imgs", file);
+      });
+    } else {
+      formData.append(key, course[key]);
+    }
   }
 
   try {
@@ -337,19 +374,20 @@ async function saveCourse() {
 
 // 上傳圖片 Input
 const coverImgRef = ref(null);
+const portfolioImgRef = ref(null);
 
 const fileInputClick = (ref) => {
   if (ref === "cover") {
     if (coverImgRef.value) {
       coverImgRef.value[0].click();
     }
+  } else if (ref === "portfolio") {
+    if (portfolioImgRef.value) {
+      portfolioImgRef.value[0].click();
+    }
   }
 };
 
-// 封面圖片
-let coverImg = ref("");
-let coverImgUrl = ref("");
-
 const handleCoverImg = (event) => {
   const file = event.target.files[0];
   if (file) {
@@ -358,6 +396,25 @@ const handleCoverImg = (event) => {
   }
 };
 
+const handlePortfolioImg = (files) => {
+  console.log("portfolioImg.value", portfolioImg.value);
+  console.log("files", files);
+  for (let index = 0; index < files.length; index++) {
+    const file = files[index];
+    console.log("file", file);
+    let url = URL.createObjectURL(file);
+    portfolioImgUrl.value.push(url);
+  }
+};
+
+watch(portfolioImg, (newFiles) => {
+  console.log("newFiles", newFiles);
+  if (newFiles.length > 0) {
+    handlePortfolioImg(newFiles);
+  }
+  console.log("portfolioImg", portfolioImg.value);
+});
+
 // 取得所有課堂
 async function getAllSession(id) {
   console.log("getAllSession id", id);
@@ -1678,6 +1735,61 @@ async function closeClass(id) {
                                       />
                                     </div>
                                   </v-col>
+
+                                  <v-col cols="12" class="me-auto">
+                                    <v-label class="d-block">
+                                      <p class="d-flex">
+                                        {{ t("form.portfolio_image") }}
+                                        <span class="mark">*</span>
+                                      </p>
+
+                                      <v-file-input
+                                        multiple
+                                        v-model="portfolioImg"
+                                        id="portfolioImgRef"
+                                        ref="portfolioImgRef"
+                                        label="File input"
+                                        variant="outlined"
+                                        :placeholder="t('form.choose_image')"
+                                        @change="handlePortfolioImg"
+                                        style="display: none"
+                                      ></v-file-input>
+                                    </v-label>
+
+                                    <v-btn
+                                      @click="fileInputClick('portfolio')"
+                                      color="purple"
+                                      class="my-5"
+                                    >
+                                      {{ t("form.choose_image") }}
+                                    </v-btn>
+
+                                    <div class="step-01 image-preview">
+                                      <div
+                                        class="d-flex justify-center"
+                                        v-if="portfolioImgLoading"
+                                      >
+                                        <v-progress-circular
+                                          color="grey-lighten-4"
+                                          indeterminate
+                                        ></v-progress-circular>
+                                      </div>
+
+                                      <v-row
+                                        v-if="
+                                          portfolioImgUrl !== '' &&
+                                          !portfolioImgLoading
+                                        "
+                                      >
+                                        <v-col
+                                          cols="6"
+                                          v-for="img in portfolioImgUrl"
+                                        >
+                                          <img :src="img" alt="上傳圖片預覽" />
+                                        </v-col>
+                                      </v-row>
+                                    </div>
+                                  </v-col>
                                 </v-row>
                               </v-card-text>
                               <v-card-actions class="d-flex justify-center">

+ 0 - 1
src/views/User/Passport.vue

@@ -50,7 +50,6 @@ async function getRecord() {
   // await store.getProfile();
   console.log("store.userInfo", store.userInfo);
   let userId = store.userInfo.user_id;
-  console.log("userId >>>", userId);
   try {
     const response = await axios.get(
       `${store.apiUrl}/api/get_attend_record?user_id=${userId}`