Ver código fonte

课件的回显和保存

黄琪勇 4 meses atrás
pai
commit
27d92a227d

+ 18 - 0
src/api/pptOperate.ts

@@ -0,0 +1,18 @@
+import { httpAxios } from "@/api/ApiInstance"
+
+//根据id获取课程信息
+export const getTeacherChapterKnowledgeMaterial = (id: string) => {
+  return httpAxios.axioseRquest({
+    method: "get",
+    url: `/edu-app/teacherChapterKnowledgeMaterial/detail/${id}`
+  })
+}
+
+// 保存信息
+export const putTeacherChapterKnowledgeMaterial = (data: { id: string; dataJson: string }) => {
+  return httpAxios.axioseRquest({
+    method: "post",
+    url: "/edu-app/teacherChapterKnowledgeMaterial/savePptJson",
+    data
+  })
+}

+ 4 - 16
src/hooks/useExport.ts

@@ -1,28 +1,16 @@
 import { ref } from "vue"
-import { storeToRefs } from "pinia"
-import { useSlidesStore } from "@/store"
-import message from "@/utils/message"
 import { addCourseWareTask } from "@/worker/useCoursewaresWorker"
 import { downloadFile } from "@/libs/tools"
+import { getJsonToBlob } from "@/libs/jsonTool"
 
 export default () => {
-  const slidesStore = useSlidesStore()
-  const { slides, theme, viewportRatio, title, viewportSize } = storeToRefs(slidesStore)
-
   const exporting = ref(false)
   const exportProgress = ref(0)
 
   // 导出PPTX文件
   const exportPPTX = () => {
-    const json = {
-      width: viewportSize.value,
-      height: viewportSize.value * viewportRatio.value,
-      slides: slides.value,
-      theme: theme.value
-    }
-    const blob = new Blob([JSON.stringify(json)])
+    const { blob, title } = getJsonToBlob()
     const url = URL.createObjectURL(blob)
-
     exportProgress.value = 0
     exporting.value = true
     addCourseWareTask(
@@ -31,8 +19,8 @@ export default () => {
         extra: {
           id: "",
           type: "pptx",
-          outputName: `${title.value}.pptx`,
-          name: title.value,
+          outputName: `${title}.pptx`,
+          name: title,
           jsonUrl: url
         }
       },

+ 30 - 14
src/hooks/useHistorySnapshot.ts

@@ -1,27 +1,43 @@
-import { debounce, throttle} from 'lodash'
-import { useSnapshotStore } from '@/store'
+import { debounce, throttle } from "lodash"
+import { useSnapshotStore } from "@/store"
+import usePptWork from "@/store/pptWork"
 
 export default () => {
   const snapshotStore = useSnapshotStore()
-
+  const usePptWorkHook = usePptWork()
   // 添加历史快照(历史记录)
-  const addHistorySnapshot = debounce(function() {
-    snapshotStore.addSnapshot()
-  }, 300, { trailing: true })
+  const addHistorySnapshot = debounce(
+    function () {
+      usePptWorkHook.isSave = false
+      snapshotStore.addSnapshot()
+    },
+    300,
+    { trailing: true }
+  )
 
   // 重做
-  const redo = throttle(function() {
-    snapshotStore.reDo()
-  }, 100, { leading: true, trailing: false })
+  const redo = throttle(
+    function () {
+      usePptWorkHook.isSave = false
+      snapshotStore.reDo()
+    },
+    100,
+    { leading: true, trailing: false }
+  )
 
   // 撤销
-  const undo = throttle(function() {
-    snapshotStore.unDo()
-  }, 100, { leading: true, trailing: false })
+  const undo = throttle(
+    function () {
+      usePptWorkHook.isSave = false
+      snapshotStore.unDo()
+    },
+    100,
+    { leading: true, trailing: false }
+  )
 
   return {
     addHistorySnapshot,
     redo,
-    undo,
+    undo
   }
-}
+}

+ 21 - 18
src/hooks/useImport.ts

@@ -1,13 +1,12 @@
 import { ref, onMounted } from "vue"
-import { useSlidesStore } from "@/store"
-import message from "@/utils/message"
-import axios from "axios"
 
-import { getHttpJson } from "@/libs/jsonTool"
+import { getHttpJson, jsonToPpt } from "@/libs/jsonTool"
 import { initWorker, addCourseWareTask, getRunJobIds } from "@/worker/useCoursewaresWorker"
+import { ElMessage } from "element-plus"
+import useHistorySnapshot from "@/hooks/useHistorySnapshot"
 
 export default () => {
-  const slidesStore = useSlidesStore()
+  const { addHistorySnapshot } = useHistorySnapshot()
   const importing = ref(false)
   const importProgress = ref(0)
   onMounted(() => {
@@ -47,34 +46,38 @@ export default () => {
             getHttpJson(e.extra.url).then(res => {
               if (res.code === 200) {
                 jsonToPpt(res.data)
+                addHistorySnapshot()
                 importing.value = false
               } else {
                 importing.value = false
-                message.error("导入失败!")
+                ElMessage({
+                  showClose: true,
+                  message: "导入失败!",
+                  type: "error"
+                })
               }
             })
           } else if (e.status !== "doing") {
             importing.value = false
-            message.error("导入失败!")
+            ElMessage({
+              showClose: true,
+              message: "导入失败!",
+              type: "error"
+            })
           }
         }
       }
     ).catch(err => {
       importing.value = false
-      message.error("导入失败!")
+      ElMessage({
+        showClose: true,
+        message: "导入失败!",
+        type: "error"
+      })
       console.log(err)
     })
   }
-  // 处理导入数据
-  function jsonToPpt(jsonData: Record<string, any>) {
-    console.log(jsonData, "导入json数据")
-    const { width, theme, slides } = jsonData
-    slidesStore.updateSlideIndex(0)
-    slidesStore.setViewportSize(width || 1920)
-    slidesStore.setViewportRatio(theme.viewportRatio)
-    slidesStore.setTheme(theme)
-    slidesStore.setSlides(slides)
-  }
+
   return {
     importPPTXFile,
     importing,

+ 27 - 0
src/libs/jsonTool.ts

@@ -1,4 +1,6 @@
 import axios from "axios"
+import { useSlidesStore } from "@/store"
+import { slides as slidesData } from "@/mocks/slides"
 /**
  * http 请求json
  */
@@ -28,3 +30,28 @@ export function getHttpJson(url: string): Promise<{ code: number; data: Record<s
       })
   })
 }
+
+export function jsonToPpt(jsonData: Record<string, any>) {
+  const slidesStore = useSlidesStore()
+  const { width, theme, slides } = jsonData
+  slidesStore.updateSlideIndex(0)
+  slidesStore.setViewportSize(width || 1920)
+  slidesStore.setViewportRatio(theme.viewportRatio)
+  slidesStore.setTheme(theme)
+  slidesStore.setSlides(slides.length ? slides : slidesData)
+}
+
+export function getJsonToBlob() {
+  const slidesStore = useSlidesStore()
+  const { slides, theme, viewportRatio, viewportSize, title } = slidesStore
+  const json = {
+    width: viewportSize,
+    height: viewportSize * viewportRatio,
+    slides: slides,
+    theme: Object.assign(theme, { viewportRatio })
+  }
+  return {
+    blob: new Blob([JSON.stringify(json)]),
+    title
+  }
+}

+ 4 - 3
src/mocks/layout.ts

@@ -1,19 +1,20 @@
 /* eslint-disable max-lines */
 
 import type { Slide } from "@/types/slides"
+import { nanoid } from "nanoid"
 
 export const layouts: Slide[] = [
   {
-    id: "template",
+    id: nanoid(10),
     elements: [
       {
         type: "text",
-        id: "ztXt5soL6B",
+        id: nanoid(10),
         left: 809.8,
         top: 345.5256570713392,
         width: 300.3754693366708,
         height: 110,
-        content: "<p style=''><span style='font-size: 60px;'>我是模板</span></p>",
+        content: "<p style=''><span style='font-size: 60px;'>默认模板</span></p>",
         rotate: 0,
         defaultFontName: "Microsoft Yahei",
         defaultColor: "#333333",

+ 2 - 1
src/mocks/slides.ts

@@ -1,8 +1,9 @@
 import type { Slide } from "@/types/slides"
+import { nanoid } from "nanoid"
 
 export const slides: Slide[] = [
   {
-    id: "test-slide-1",
+    id: nanoid(10),
     elements: [],
     background: {
       type: "solid",

+ 79 - 0
src/store/pptWork.ts

@@ -0,0 +1,79 @@
+import { defineStore } from "pinia"
+import { store } from "./index"
+import { getTeacherChapterKnowledgeMaterial, putTeacherChapterKnowledgeMaterial } from "@/api/pptOperate"
+import { httpAjaxErrMsg } from "@/plugins/httpAjax"
+import { useRoute } from "vue-router"
+import LoadingBar from "@/plugins/loadingBar"
+import { getHttpJson, jsonToPpt, getJsonToBlob } from "@/libs/jsonTool"
+import fileUpload from "@/utils/oss-file-upload"
+import { ElMessage } from "element-plus"
+
+type pptWork = { id: string; coverImg: string; jsonUrl: string; isSave: boolean }
+const useStore = defineStore("pptWork", {
+  state: (): pptWork => {
+    return {
+      id: "",
+      coverImg: "",
+      jsonUrl: "",
+      isSave: false // 当前是否保存,用来关闭页面时候判断 提不提示
+    }
+  },
+  actions: {
+    /** 初始化 */
+    async initPPTData() {
+      const route = useRoute()
+      const id = route.query.id as string | undefined
+      if (id) {
+        LoadingBar.loading(true, "资源加载中,请稍等...")
+        const res = await httpAjaxErrMsg(getTeacherChapterKnowledgeMaterial, id)
+        if (res.code === 200) {
+          const { id, dataJson } = res.data || {}
+          const { coverImg, jsonUrl } = JSON.parse(dataJson)
+          this.id = id
+          this.coverImg = coverImg || ""
+          if (jsonUrl) {
+            const jsonRes = await getHttpJson(jsonUrl)
+            if (jsonRes.code === 200) {
+              jsonToPpt(jsonRes.data)
+            }
+          }
+        }
+        LoadingBar.loading(false)
+      }
+    },
+    updatePPT() {
+      const { blob, title } = getJsonToBlob()
+      fileUpload(title, blob)
+        .then(url => {
+          LoadingBar.loading(true, "课件保存中,请稍等...")
+          httpAjaxErrMsg(putTeacherChapterKnowledgeMaterial, {
+            id: this.id,
+            dataJson: JSON.stringify({
+              coverImg: this.coverImg,
+              jsonUrl: url
+            })
+          }).then(res => {
+            if (res.code === 200) {
+              this.isSave = true
+              ElMessage({
+                showClose: true,
+                message: "保存成功!",
+                type: "success"
+              })
+            }
+            LoadingBar.loading(false)
+          })
+        })
+        .catch(() => {
+          ElMessage({
+            showClose: true,
+            message: "保存失败!",
+            type: "error"
+          })
+        })
+    }
+  }
+})
+export default () => {
+  return useStore(store)
+}

+ 13 - 2
src/views/Editor/EditorHeader/index.vue

@@ -46,8 +46,8 @@
     </div>
 
     <div class="right">
-      <div class="cancelBtn">取消</div>
-      <div class="saveBtn">保存课件</div>
+      <div class="cancelBtn" @click="handleClose">取消</div>
+      <div class="saveBtn" @click="handleSave">保存课件</div>
     </div>
 
     <Drawer :width="320" v-model:visible="hotkeyDrawerVisible" placement="right">
@@ -73,6 +73,7 @@ import Popover from "@/components/Popover.vue"
 import PopoverMenuItem from "@/components/PopoverMenuItem.vue"
 import { ref, computed } from "vue"
 import { ElMessageBox } from "element-plus"
+import usePptWork from "@/store/pptWork"
 
 const slidesStore = useSlidesStore()
 const { title } = storeToRefs(slidesStore)
@@ -114,6 +115,16 @@ const fullscreenSpinData = computed(() => {
     }
   }
 })
+
+const usePptWorkHook = usePptWork()
+/* 保存课件 */
+function handleSave() {
+  usePptWorkHook.updatePPT()
+}
+/* 关闭页面 */
+function handleClose() {
+  window.close()
+}
 </script>
 
 <style lang="scss" scoped>

+ 13 - 2
src/views/pptEditor/pptEditor.vue

@@ -13,19 +13,30 @@ import { storeToRefs } from "pinia"
 import { useScreenStore, useMainStore, useSnapshotStore } from "@/store"
 import { LOCALSTORAGE_KEY_DISCARDED_DB } from "@/configs/storage"
 import { deleteDiscardedDB } from "@/utils/database"
+import usePptWork from "@/store/pptWork"
 
+const usePptWorkHook = usePptWork()
 const mainStore = useMainStore()
 const snapshotStore = useSnapshotStore()
 const { databaseId } = storeToRefs(mainStore)
 const { screening } = storeToRefs(useScreenStore())
 
 if (import.meta.env.MODE !== "development") {
-  window.onbeforeunload = () => false
+  // 没有保存的时候 关闭页面提示
+  window.onbeforeunload = () => {
+    if (!usePptWorkHook.isSave) {
+      return false
+    }
+  }
 }
 
-onMounted(async () => {
+// 初始化 ppt数据
+usePptWorkHook.initPPTData().then(async () => {
   await deleteDiscardedDB()
   snapshotStore.initSnapshotDatabase()
+})
+
+onMounted(async () => {
   mainStore.setAvailableFonts()
 })
 

+ 5 - 14
src/views/pptScreen/pptScreen.vue

@@ -7,23 +7,14 @@
 <script setup lang="ts">
 import Screen from "../Screen/index.vue"
 import { ref } from "vue"
-import { useSlidesStore } from "@/store"
-import { getHttpJson } from "@/libs/jsonTool"
-
-const slidesStore = useSlidesStore()
+import usePptWork from "@/store/pptWork"
 
 const initLoading = ref(true)
 
-getHttpJson("data.json").then(res => {
-  if (res.code === 200) {
-    const { width, theme, slides } = res.data
-    console.log(res.data)
-    slidesStore.setViewportSize(width)
-    slidesStore.setViewportRatio(theme.viewportRatio)
-    slidesStore.setTheme(theme)
-    slidesStore.setSlides(slides)
-    initLoading.value = false
-  }
+const usePptWorkHook = usePptWork()
+// 初始化 ppt数据
+usePptWorkHook.initPPTData().then(() => {
+  initLoading.value = false
 })
 </script>