Browse Source

Merge branch 'hqyDev' of http://git.dayaedu.com/huangqiyong/pptList into test-online

黄琪勇 4 days ago
parent
commit
2dd8bab51d

+ 8 - 3
src/api/pptOperate.ts

@@ -1,10 +1,15 @@
 import { httpAxios } from "@/api/ApiInstance"
+import { type queryParamsType } from "@/queryParams/"
 
 //根据id获取课程信息
-export const getTeacherChapterKnowledgeMaterial = (id: string) => {
+export const getTeacherChapterKnowledgeMaterial = (id: string, fromType: queryParamsType["fromType"]) => {
   return httpAxios.axioseRquest({
-    method: "get",
-    url: `/edu-app/teacherChapterKnowledgeMaterial/detail/${id}`
+    method: "post",
+    url: "/edu-app/teacherChapterKnowledgeMaterial/detail",
+    data: {
+      id,
+      fromType
+    }
   })
 }
 

+ 22 - 20
src/plugins/directive/tooltip.ts

@@ -1,9 +1,9 @@
-import type { Directive, DirectiveBinding } from 'vue'
-import tippy, { type Instance, type Placement } from 'tippy.js'
+import type { Directive, DirectiveBinding } from "vue"
+import tippy, { type Instance, type Placement } from "tippy.js"
 
-import './tooltip.scss'
+import "./tooltip.scss"
 
-const TOOLTIP_INSTANCE = 'TOOLTIP_INSTANCE'
+const TOOLTIP_INSTANCE = "TOOLTIP_INSTANCE"
 
 interface CustomHTMLElement extends HTMLElement {
   [TOOLTIP_INSTANCE]?: Instance
@@ -17,46 +17,48 @@ interface BindingValue {
   delay?: Delay
 }
 
+function isTouchDevice() {
+  return "ontouchstart" in window || navigator.maxTouchPoints > 0 || window.matchMedia("(pointer: coarse)").matches
+}
+
 const TooltipDirective: Directive = {
   mounted(el: CustomHTMLElement, binding: DirectiveBinding<BindingValue | string>) {
-    let content = ''
-    let placement: Placement = 'top'
+    let content = ""
+    let placement: Placement = "top"
     let delay: Delay = [300, 0]
 
-    if (typeof binding.value === 'string') {
+    if (typeof binding.value === "string") {
       content = binding.value
-    }
-    else {
+    } else {
       content = binding.value.content
       if (binding.value.placement !== undefined) placement = binding.value.placement
       if (binding.value.delay !== undefined) delay = binding.value.delay
     }
-
     el[TOOLTIP_INSTANCE] = tippy(el, {
+      trigger: isTouchDevice() ? "" : "mouseenter focus", // 触摸设备不需要 tooltip
       content,
-      theme: 'tooltip',
+      theme: "tooltip",
       duration: 100,
-      animation: 'scale',
+      animation: "scale",
       allowHTML: true,
       placement,
-      delay,
+      delay
     })
   },
 
   updated(el: CustomHTMLElement, binding: DirectiveBinding<BindingValue | string>) {
-    let content = ''
-    if (typeof binding.value === 'string') {
+    let content = ""
+    if (typeof binding.value === "string") {
       content = binding.value
-    }
-    else {
+    } else {
       content = binding.value.content
     }
     if (el[TOOLTIP_INSTANCE]) el[TOOLTIP_INSTANCE].setContent(content)
   },
-  
+
   unmounted(el: CustomHTMLElement) {
     if (el[TOOLTIP_INSTANCE]) el[TOOLTIP_INSTANCE].destroy()
-  },
+  }
 }
 
-export default TooltipDirective
+export default TooltipDirective

+ 1 - 1
src/plugins/loadingBar/loadingBar.vue

@@ -81,7 +81,7 @@ body.h-loadingBarBody {
     position: absolute;
     top: 50%;
     left: 50%;
-    transform: translate(-50%, -100%);
+    transform: translate(-50%, -50%);
     z-index: 1;
     display: flex;
     flex-direction: column;

+ 5 - 2
src/queryParams/index.ts

@@ -2,16 +2,19 @@ import { reactive } from "vue"
 import router from "@/router"
 
 /** 维护其他系统过来的特殊字段  这里用来记录,以免其他系统传过来的参数混乱 不好维护 */
-type queryParamsType = {
+export type queryParamsType = {
   hideFullScreen: boolean
+  fromType: "PLATFORM" | "TEACHER" | "CLASS"
 }
 const queryParams = reactive<queryParamsType>({
-  hideFullScreen: false // 隐藏预览时候的全屏按钮
+  hideFullScreen: false, // 隐藏预览时候的全屏按钮
+  fromType: "TEACHER"
 })
 
 export function initQueryParams() {
   const query = router.currentRoute.value.query
   queryParams.hideFullScreen = !!query.hideFullScreen
+  query.fromType && (queryParams.fromType = query.fromType as any)
 }
 
 export default queryParams

+ 0 - 4
src/router/index.ts

@@ -4,7 +4,6 @@ import NProgress from "@/plugins/nprogress"
 import { ElMessage } from "element-plus"
 import { getToken, CODE401 } from "@/libs/auth"
 import userStore from "@/store/user"
-import { initQueryParams } from "@/queryParams"
 
 const userStoreHook = userStore()
 
@@ -72,7 +71,4 @@ router.afterEach(() => {
   NProgress.done()
 })
 
-router.isReady().then(() => {
-  initQueryParams()
-})
 export default router

+ 5 - 0
src/router/routers.ts

@@ -17,6 +17,11 @@ export const constRoutes: Array<RouteRecordRaw> = [
     component: () => import("@/views/pptScreen")
   },
   {
+    path: "/mobileScreen",
+    name: "mobile",
+    component: () => import("@/views/mobileScreen")
+  },
+  {
     path: "/login",
     name: "login",
     component: () => import("@/viewsframe/login")

+ 8 - 7
src/store/pptWork.ts

@@ -9,10 +9,13 @@ import fileUpload from "@/utils/oss-file-upload"
 import { ElMessage } from "element-plus"
 import { toBlob } from "html-to-image"
 import { useSlidesStore } from "@/store"
+import queryParams, { initQueryParams } from "@/queryParams"
 
 type pptWork = { id: string; coverImg: string; jsonUrl: string; isSave: boolean }
+
 const useStore = defineStore("pptWork", {
   state: (): pptWork => {
+    initQueryParams()
     const route = useRoute()
     return {
       id: route.query.id as string,
@@ -26,7 +29,7 @@ const useStore = defineStore("pptWork", {
     async initPPTData() {
       if (this.id) {
         LoadingBar.loading(true, "资源加载中,请稍等...")
-        const res = await httpAjaxErrMsg(getTeacherChapterKnowledgeMaterial, this.id)
+        const res = await httpAjaxErrMsg(getTeacherChapterKnowledgeMaterial, this.id, queryParams.fromType)
         if (res.code === 200) {
           const { dataJson, chapterLessonCoursewareName } = res.data || {}
           const { coverImg, jsonUrl } = JSON.parse(dataJson)
@@ -44,11 +47,11 @@ const useStore = defineStore("pptWork", {
       }
     },
     async updatePPT() {
+      LoadingBar.loading(true, "课件保存中,请稍等...")
       await this.updateCoverImg()
       const { blob } = getJsonToBlob()
-      fileUpload(`${this.id}ppt`, blob, `${this.id}/`, false)
+      fileUpload(`${this.id}ppt`, blob, `${this.id}/`, false, { isLoading: false })
         .then(url => {
-          LoadingBar.loading(true, "课件保存中,请稍等...")
           httpAjaxErrMsg(putTeacherChapterKnowledgeMaterial, {
             id: this.id,
             dataJson: JSON.stringify({
@@ -68,6 +71,7 @@ const useStore = defineStore("pptWork", {
           })
         })
         .catch(() => {
+          LoadingBar.loading(false)
           ElMessage({
             showClose: true,
             message: "保存失败!",
@@ -76,19 +80,16 @@ const useStore = defineStore("pptWork", {
         })
     },
     async updateCoverImg() {
-      LoadingBar.loading(true, "资源上传中")
       try {
         const coverImgDom = document.querySelector("#thumbnailSlide_0") as HTMLElement
         if (coverImgDom) {
           const dataBlob = await toBlob(coverImgDom)
           if (dataBlob) {
-            const url = await fileUpload(`${this.id}coverImg`, dataBlob, `${this.id}/`, false)
+            const url = await fileUpload(`${this.id}coverImg`, dataBlob, `${this.id}/`, false, { isLoading: false })
             url && (this.coverImg = url)
           }
         }
-        LoadingBar.loading(false)
       } catch (err) {
-        LoadingBar.loading(false)
         console.log(err, "上传coverImg错误")
       }
     }

+ 1 - 1
src/store/screen.ts

@@ -1,7 +1,7 @@
 import { defineStore } from "pinia"
 
 export interface ScreenState {
-  mode: "pptEditor" | "pptScreen" // 编辑模式还是 ppt预览模式
+  mode: "pptEditor" | "pptScreen" | "mobileScreen" // 编辑模式还是 ppt预览模式
   screening: boolean
 }
 

+ 12 - 5
src/utils/oss-file-upload.ts

@@ -6,8 +6,15 @@ import loadingBar from "@/plugins/loadingBar"
 const tencentBucket = "daya-online-1303457149"
 const ossType = "tencent"
 
-export default async function fileUpload(fileName: string, file: Blob, filePath: string, isAddTimestamp = true) {
-  loadingBar.loading(true, "资源上传中")
+export default async function fileUpload(
+  fileName: string,
+  file: Blob,
+  filePath: string,
+  isAddTimestamp = true,
+  loadingBarOpt?: { isLoading: boolean; text?: string }
+) {
+  loadingBarOpt || (loadingBarOpt = { isLoading: true })
+  loadingBarOpt.isLoading && loadingBar.loading(true, loadingBarOpt.text || "资源上传中")
   // 上传名称加上时间戳
   if (isAddTimestamp) {
     fileName = addTimestampBeforeExtension(fileName)
@@ -20,18 +27,18 @@ export default async function fileUpload(fileName: string, file: Blob, filePath:
         file,
         filePath
       })
-      loadingBar.loading(false)
+      loadingBarOpt.isLoading && loadingBar.loading(false)
       if (resUpload.statusCode === 200) {
         return resUpload.Location.includes("http") ? resUpload.Location : `https://${resUpload.Location}`
       } else {
         return Promise.reject("")
       }
     } catch {
-      loadingBar.loading(false)
+      loadingBarOpt.isLoading && loadingBar.loading(false)
       return Promise.reject("")
     }
   } else {
-    loadingBar.loading(false)
+    loadingBarOpt.isLoading && loadingBar.loading(false)
     return Promise.reject("")
   }
 }

+ 2 - 2
src/views/Editor/Thumbnails/index.vue

@@ -70,8 +70,8 @@
             <div class="thumbnail">
               <ThumbnailSlide :id="`thumbnailSlide_${index}`" :slide="element" :size="180" :visible="index < slidesLoadLimit" />
               <div class="tools" v-if="slideIndex === index">
-                <img src="./imgs/play.png" @click="enterScreening" alt="" />
-                <img src="./imgs/add.png" @click="createSlide" alt="" />
+                <img v-tooltip="'预览'" src="./imgs/play.png" @click="enterScreening" alt="" />
+                <img v-tooltip="'添加幻灯片'" src="./imgs/add.png" @click="createSlide" alt="" />
               </div>
             </div>
 

+ 8 - 2
src/views/Screen/BaseView.vue

@@ -23,7 +23,13 @@
       <IconRightTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execNext()" />
     </div>
 
-    <div class="tools-right" :class="{ visible: rightToolsVisible }" @mouseleave="rightToolsVisible = false" @mouseenter="rightToolsVisible = true">
+    <!-- <div
+      class="tools-right"
+      v-if="screenStore.mode !== 'mobileScreen'"
+      :class="{ visible: rightToolsVisible }"
+      @mouseleave="rightToolsVisible = false"
+      @mouseenter="rightToolsVisible = true"
+    >
       <div class="content">
         <div class="tool-btn page-number" @click="slideThumbnailModelVisible = true">幻灯片 {{ slideIndex + 1 }} / {{ slides.length }}</div>
         <IconWrite class="tool-btn" v-tooltip="'画笔工具'" @click="writingBoardToolVisible = true" />
@@ -36,7 +42,7 @@
         </template>
         <IconPower v-if="screenStore.mode === 'pptEditor'" class="tool-btn" v-tooltip="'结束放映'" @click="exitScreening()" />
       </div>
-    </div>
+    </div> -->
   </div>
 </template>
 

+ 2 - 0
src/views/mobileScreen/index.ts

@@ -0,0 +1,2 @@
+import mobileScreen from "./mobileScreen.vue"
+export default mobileScreen

+ 36 - 2
src/views/mobileScreen/mobileScreen.vue

@@ -1,6 +1,10 @@
 <template>
-  <div class="mobileScreen">
-    <Screen v-if="!initLoading" />
+  <div class="mobileScreen" @click="toolVisible = false">
+    <template v-if="!initLoading">
+      <Screen />
+      <MobileThumbnails v-if="toolVisible" class="thumbnails" />
+      <IconListView class="tool-icon" @click.stop="toolVisible = !toolVisible" />
+    </template>
   </div>
 </template>
 
@@ -9,9 +13,12 @@ import { ref } from "vue"
 import Screen from "../Screen/index.vue"
 import usePptWork from "@/store/pptWork"
 import { useScreenStore } from "@/store"
+import MobileThumbnails from "../Mobile/MobileThumbnails.vue"
+
 const screenStore = useScreenStore()
 
 const initLoading = ref(true)
+const toolVisible = ref(false)
 
 const usePptWorkHook = usePptWork()
 
@@ -26,5 +33,32 @@ usePptWorkHook.initPPTData().then(() => {
 .mobileScreen {
   width: 100%;
   height: 100%;
+  .thumbnails {
+    width: 100%;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    z-index: 99;
+    background-color: rgba($color: #1d1d1d, $alpha: 0.7);
+    overflow: auto !important;
+    animation: slideInUp 0.15s;
+  }
+
+  @keyframes slideInUp {
+    from {
+      transform: translateY(100%);
+    }
+    to {
+      transform: translateY(0);
+    }
+  }
+  .tool-icon {
+    position: fixed;
+    bottom: 8px;
+    right: 8px;
+    font-size: 25px;
+    color: #666;
+    z-index: 10;
+  }
 }
 </style>

+ 1 - 1
vite.config.ts

@@ -28,7 +28,7 @@ export default defineConfig({
     proxy: {
       // 正则表达式写法
       "^/pptApi/.*": {
-        target: "https://test.kt.colexiu.com",
+        target: "https://dev.kt.colexiu.com",
         changeOrigin: true,
         rewrite: path => path.replace(/^\/pptApi/, "")
       }