|
@@ -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" }}>
|