lex-xin 1 месяц назад
Родитель
Сommit
696244fbad
2 измененных файлов с 104 добавлено и 60 удалено
  1. 100 60
      src/views/cloudPractice/cloudPractice.tsx
  2. 4 0
      src/views/cloudPractice/index.module.scss

+ 100 - 60
src/views/cloudPractice/cloudPractice.tsx

@@ -1,7 +1,7 @@
 import { computed, defineComponent, nextTick, onMounted, reactive, ref, shallowRef } from "vue"
 import styles from "./index.module.scss"
 import NavContainer from "@/businessComponents/navContainer"
-import { ElEmpty, ElScrollbar } from "element-plus"
+import { ElEmpty, ElMessage, ElScrollbar } from "element-plus"
 import Dictionary from "@/components/dictionary"
 import MyInput from "@/components/myInput"
 import { NImage, NPopselect, NSpin, NTooltip } from "naive-ui"
@@ -36,8 +36,8 @@ import userStore from "@/store/modules/user"
 import PlayLoading from "./component/play-loading"
 import PracticeForm from "@/businessComponents/practiceForm"
 import { saveAs } from "file-saver"
-// import JSZip, { file } from "jszip"
-// import { svgtopng } from "./formatSvgToImg"
+import JSZip, { file } from "jszip"
+import { svgtopng } from "./formatSvgToImg"
 
 export default defineComponent({
    name: "cloudPractice",
@@ -155,6 +155,7 @@ export default defineComponent({
          }
       })
 
+      const downloadStatus = ref(false)
       const loading = ref(false)
       const staffLoading = ref(false)
       const storeData = shallowRef<any[]>([])
@@ -861,61 +862,85 @@ export default defineComponent({
       }
 
       // // 获取文件blob格式
-      // const getFileBlob = (url: string) => {
-      //    return new Promise((resolve, reject) => {
-      //       const request = new XMLHttpRequest()
-      //       request.open("GET", url, true)
-      //       request.responseType = "blob"
-      //       request.onload = (res: any) => {
-      //          if (res.target.status == 200) {
-      //             resolve(res.target.response)
-      //          } else {
-      //             reject(res)
-      //          }
-      //       }
-      //       request.send()
-      //    })
-      // }
+      const imgToCanvas = async (url: string) => {
+         const img = document.createElement("img")
+         img.setAttribute("crossOrigin", "anonymous")
+         // 为了处理base64 和 连接加载不同的
+         if (url && typeof url == "string" && url.includes("data:image")) {
+            img.src = url
+         } else {
+            img.src = url + `?t=${+new Date()}`
+         }
+
+         // 防止跨域引起的 Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
+         await new Promise(resolve => (img.onload = resolve))
+         // 创建canvas DOM元素,并设置其宽高和图片一样
+         const canvas = document.createElement("canvas")
+         canvas.width = img.width
+         canvas.height = img.height
+         // 坐标(0,0) 表示从此处开始绘制,相当于偏移。
+         const ctx = canvas.getContext("2d") as CanvasRenderingContext2D
+
+         ctx.fillStyle = "rgb(255, 255, 255)"
+         ctx.fillStyle = "#fff"
+         ctx.fillRect(0, 0, img.width, img.height)
+         ctx.drawImage(img, 0, 0)
+         return canvas
+      }
+
+      const getFileBlob = async (url: string, type = "image/png") => {
+         const canvas: any = await imgToCanvas(url)
+         return new Promise((resolve, reject) => {
+            canvas.toBlob((blob: Blob) => {
+               if (blob) {
+                  resolve(blob)
+               } else {
+                  reject(new Error("转换失败"))
+               }
+            }, type)
+         })
+      }
 
       // // 多个文件下载
-      // const downLoadMultiFile = (files: any, filesName: string) => {
-      //    const zip = new JSZip()
-      //    const result = []
-      //    for (const i in files) {
-      //       const promise = getFileBlob(files[i].url).then((res: any) => {
-      //          zip.file(files[i].name, res, { binary: true })
-      //       })
-      //       result.push(promise)
-      //    }
-      //    Promise.all(result)
-      //       .then(() => {
-      //          zip.generateAsync({ type: "blob" }).then(res => {
-      //             saveAs(res, filesName ? filesName + ".zip" : `文件夹${Date.now()}.zip`)
-      //          })
-      //       })
-      //       .catch(() => {
-      //          //  message.error('下载失败');
-      //       })
-
-      //    // downloadStatus.value = false;
-      // }
+      const downLoadMultiFile = (files: any, filesName: string) => {
+         const zip = new JSZip()
+         const result = []
+         for (const i in files) {
+            const promise = getFileBlob(files[i].url).then((res: any) => {
+               console.log(res, "res")
+               zip.file(files[i].name, res, { binary: true })
+            })
+            result.push(promise)
+         }
+         Promise.all(result)
+            .then(() => {
+               zip.generateAsync({ type: "blob" }).then(res => {
+                  saveAs(res, filesName ? filesName + ".zip" : `文件夹${Date.now()}.zip`)
+               })
+            })
+            .catch(() => {
+               ElMessage.error("下载失败")
+            })
+
+         downloadStatus.value = false
+      }
 
       const showLoading = async (e: any) => {
          if (e.data?.api === "musicStaffRender") {
-            // try {
-            //    const osmdImg = e.data.osmdImg
-            //    const imgs = []
-            //    for (let i = 0; i < osmdImg.length; i++) {
-            //       const img = await svgtopng(osmdImg[i].img, osmdImg[i].width, osmdImg[i].height)
-            //       imgs.push({
-            //          url: img,
-            //          name: i + "-" + Date.now()
-            //       })
-            //    }
-            //    state.imgs = imgs
-            // } catch (e) {
-            //    // console.log(e);
-            // }
+            try {
+               const osmdImg = e.data.osmdImg
+               const imgs = []
+               for (let i = 0; i < osmdImg.length; i++) {
+                  const img = await svgtopng(osmdImg[i].img, osmdImg[i].width, osmdImg[i].height)
+                  imgs.push({
+                     url: img,
+                     name: i + 1 + ".png"
+                  })
+               }
+               state.imgs = imgs
+            } catch (e) {
+               // console.log(e);
+            }
             staffLoading.value = e.data.loading
          }
       }
@@ -940,23 +965,27 @@ export default defineComponent({
 
       /** 下载图片 */
       const onDownload = () => {
+         if (downloadStatus.value) return
          const musicName =
             activeItem.value.name +
-            (activeItem.value.musicSheetType === "CONCERT" &&
-               (state.selectedPartName || state.selectedTrack ? `(${state.selectedPartName || state.selectedTrack})` : ""))
-
+            ((activeItem.value.musicSheetType === "CONCERT" && state.selectedPartName) || state.selectedTrack
+               ? `(${state.selectedPartName || state.selectedTrack})`
+               : "")
+         downloadStatus.value = true
          if (state.musicPdfUrl) {
             // 发起Fetch请求
             fetch(state.musicPdfUrl)
                .then(response => response.blob())
                .then(blob => {
                   saveAs(blob, musicName)
+                  downloadStatus.value = false
                })
                .catch(() => {
-                  //   message.error('下载失败');
+                  ElMessage.error("下载失败")
+                  downloadStatus.value = false
                })
          } else {
-            // downLoadMultiFile(state.imgs, musicName)
+            downLoadMultiFile(state.imgs, musicName)
          }
       }
 
@@ -1243,9 +1272,20 @@ export default defineComponent({
                   />
 
                   <div class={styles.rightBtns} style={{ display: activeItem.value.id ? "" : "none" }}>
-                     <div style={{ display: state.musicPdfUrl ? "" : "none" }}>
+                     <div
+                     // style={{ display: state.musicPdfUrl ? "" : "none" }}
+                     >
                         <NTooltip showArrow={false}>
-                           {{ trigger: () => <img onClick={onDownload} class={styles.transBtn} src={iconDownload as any} />, default: "下载曲谱" }}
+                           {{
+                              trigger: () => (
+                                 <img
+                                    onClick={onDownload}
+                                    class={[styles.transBtn, downloadStatus.value && styles.disableBtn]}
+                                    src={iconDownload as any}
+                                 />
+                              ),
+                              default: "下载曲谱"
+                           }}
                         </NTooltip>
                      </div>
                      <div style={{ display: activeItem.value.musicSheetType === "CONCERT" ? "" : "none" }}>

+ 4 - 0
src/views/cloudPractice/index.module.scss

@@ -508,6 +508,10 @@
             opacity: 0.7;
          }
       }
+      .disableBtn {
+         opacity: 0.7;
+         cursor: not-allowed
+      }
    }
 
    // .popSelect {