Ver Fonte

更新合奏添加图片

lex há 1 ano atrás
pai
commit
2446181031

+ 115 - 0
package-lock.json

@@ -12,6 +12,7 @@
         "@vant/use": "^1.3.6",
         "@vueuse/core": "^8.4.1",
         "browserslist": "^4.20.2",
+        "canvg": "^4.0.1",
         "classnames": "^2.3.1",
         "clean-deep": "^3.4.0",
         "cos-js-sdk-v5": "^1.4.21",
@@ -2107,6 +2108,16 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@types/offscreencanvas": {
+      "version": "2019.7.1",
+      "resolved": "https://registry.npmmirror.com/@types/offscreencanvas/-/offscreencanvas-2019.7.1.tgz",
+      "integrity": "sha512-+HSrJgjBW77ALieQdMJvXhRZUIRN1597L+BKvsyeiIlHHERnqjcuOLyodK3auJ3Y3zRezNKtKAhuQWYJfEgFHQ=="
+    },
+    "node_modules/@types/raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmmirror.com/@types/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-1jJ3OO8FXHCcuVXCuO1EMC/MjDuT6/cxgsMw/UebkO9afnL99Y5QTpUjk7+flK4G5FzBVJEgDKL5eFtoxJs9MQ=="
+    },
     "node_modules/@types/through": {
       "version": "0.0.30",
       "resolved": "https://registry.npmmirror.com/@types/through/-/through-0.0.30.tgz",
@@ -3183,6 +3194,22 @@
       ],
       "license": "CC-BY-4.0"
     },
+    "node_modules/canvg": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/canvg/-/canvg-4.0.1.tgz",
+      "integrity": "sha512-5gD/d6SiCCT7baLnVr0hokYe93DfcHW2rSqdKOuOQD84YMlyfttnZ8iQsThTdX6koYam+PROz/FuQTo500zqGw==",
+      "dependencies": {
+        "@types/offscreencanvas": "^2019.6.4",
+        "@types/raf": "^3.4.0",
+        "raf": "^3.4.1",
+        "rgbcolor": "^1.0.1",
+        "stackblur-canvas": "^2.0.0",
+        "svg-pathdata": "^6.0.3"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
     "node_modules/capital-case": {
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/capital-case/-/capital-case-1.0.4.tgz",
@@ -7630,6 +7657,11 @@
         "node": ">=8"
       }
     },
+    "node_modules/performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+    },
     "node_modules/picocolors": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
@@ -8057,6 +8089,14 @@
       ],
       "license": "MIT"
     },
+    "node_modules/raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+      "dependencies": {
+        "performance-now": "^2.1.0"
+      }
+    },
     "node_modules/rangetouch": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/rangetouch/-/rangetouch-2.0.1.tgz",
@@ -8289,6 +8329,14 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/rgbcolor": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz",
+      "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
+      "engines": {
+        "node": ">= 0.8.15"
+      }
+    },
     "node_modules/rimraf": {
       "version": "3.0.2",
       "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
@@ -8541,6 +8589,14 @@
         "node": ">=6"
       }
     },
+    "node_modules/stackblur-canvas": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.6.0.tgz",
+      "integrity": "sha512-8S1aIA+UoF6erJYnglGPug6MaHYGo1Ot7h5fuXx4fUPvcvQfcdw2o/ppCse63+eZf8PPidSu4v1JnmEVtEDnpg==",
+      "engines": {
+        "node": ">=0.1.14"
+      }
+    },
     "node_modules/strict-uri-encode": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
@@ -8719,6 +8775,14 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/svg-pathdata": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+      "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
     "node_modules/svg-tags": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -11311,6 +11375,16 @@
       "integrity": "sha512-A8F30k2gYJ/6e07spSCPpkuZu79LCnkPTvqmIWQzNGcrzwFKpVOydG41lNt5wZXjSI149qjyzC2L1+F2PD/NUA==",
       "dev": true
     },
+    "@types/offscreencanvas": {
+      "version": "2019.7.1",
+      "resolved": "https://registry.npmmirror.com/@types/offscreencanvas/-/offscreencanvas-2019.7.1.tgz",
+      "integrity": "sha512-+HSrJgjBW77ALieQdMJvXhRZUIRN1597L+BKvsyeiIlHHERnqjcuOLyodK3auJ3Y3zRezNKtKAhuQWYJfEgFHQ=="
+    },
+    "@types/raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmmirror.com/@types/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-1jJ3OO8FXHCcuVXCuO1EMC/MjDuT6/cxgsMw/UebkO9afnL99Y5QTpUjk7+flK4G5FzBVJEgDKL5eFtoxJs9MQ=="
+    },
     "@types/through": {
       "version": "0.0.30",
       "resolved": "https://registry.npmmirror.com/@types/through/-/through-0.0.30.tgz",
@@ -12015,6 +12089,19 @@
       "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz",
       "integrity": "sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg=="
     },
+    "canvg": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/canvg/-/canvg-4.0.1.tgz",
+      "integrity": "sha512-5gD/d6SiCCT7baLnVr0hokYe93DfcHW2rSqdKOuOQD84YMlyfttnZ8iQsThTdX6koYam+PROz/FuQTo500zqGw==",
+      "requires": {
+        "@types/offscreencanvas": "^2019.6.4",
+        "@types/raf": "^3.4.0",
+        "raf": "^3.4.1",
+        "rgbcolor": "^1.0.1",
+        "stackblur-canvas": "^2.0.0",
+        "svg-pathdata": "^6.0.3"
+      }
+    },
     "capital-case": {
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/capital-case/-/capital-case-1.0.4.tgz",
@@ -14985,6 +15072,11 @@
       "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
       "dev": true
     },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+    },
     "picocolors": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
@@ -15286,6 +15378,14 @@
       "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
       "dev": true
     },
+    "raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+      "requires": {
+        "performance-now": "^2.1.0"
+      }
+    },
     "rangetouch": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/rangetouch/-/rangetouch-2.0.1.tgz",
@@ -15453,6 +15553,11 @@
       "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
       "dev": true
     },
+    "rgbcolor": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz",
+      "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw=="
+    },
     "rimraf": {
       "version": "3.0.2",
       "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
@@ -15620,6 +15725,11 @@
       "resolved": "https://registry.npmmirror.com/split-on-first/-/split-on-first-1.1.0.tgz",
       "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="
     },
+    "stackblur-canvas": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.6.0.tgz",
+      "integrity": "sha512-8S1aIA+UoF6erJYnglGPug6MaHYGo1Ot7h5fuXx4fUPvcvQfcdw2o/ppCse63+eZf8PPidSu4v1JnmEVtEDnpg=="
+    },
     "strict-uri-encode": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
@@ -15723,6 +15833,11 @@
       "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
       "dev": true
     },
+    "svg-pathdata": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+      "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw=="
+    },
     "svg-tags": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz",

+ 1 - 0
package.json

@@ -25,6 +25,7 @@
     "@vant/use": "^1.3.6",
     "@vueuse/core": "^8.4.1",
     "browserslist": "^4.20.2",
+    "canvg": "^4.0.1",
     "classnames": "^2.3.1",
     "clean-deep": "^3.4.0",
     "cos-js-sdk-v5": "^1.4.21",

+ 78 - 54
public/osmd/index.html

@@ -2,70 +2,94 @@
 <html lang="en">
 
 <head>
-    <meta charset="UTF-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Document</title>
-    <script src="./opensheetmusicdisplay.min.js"></script>
-    <style>
-        * {
-            margin: 0;
-            padding: 0;
-        }
+  <meta charset="UTF-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Document</title>
+  <script src="./opensheetmusicdisplay.min.js"></script>
+  <style>
+    * {
+      margin: 0;
+      padding: 0;
+    }
 
-        body {
-            padding-bottom: 60px;
-            height: 600px;
-            overflow: hidden;
-        }
+    body {
+      padding-bottom: 60px;
+      height: 600px;
+      overflow: hidden;
+    }
 
-        .vf-text {
-            display: none;
-        }
-    </style>
+    .vf-text {
+      display: none;
+    }
+  </style>
 </head>
 
 <body>
-    <div id="osmdContainer" />
-    <script>
-        var osmd = new opensheetmusicdisplay.OpenSheetMusicDisplay("osmdContainer");
-        osmd.setOptions({
-            backend: "svg",
-            drawTitle: false,
-            drawPartNames: true,
-            // drawingParameters: "compacttight" // don't display title, composer etc., smaller margins
-        });
-        function render(){
-            osmd.render();
-            window.parent.postMessage({
-                api: 'musicStaffRender',
-                loading: false
-            }, '*');
+  <div id="osmdContainer" />
+  <script>
+    var osmd = new opensheetmusicdisplay.OpenSheetMusicDisplay("osmdContainer");
+    osmd.setOptions({
+      backend: "svg",
+      drawTitle: false,
+      drawPartNames: true,
+      drawLyricist: false,
+      drawComposer: false
+      // drawingParameters: "compacttight" // don't display title, composer etc., smaller margins
+    });
+    function getSvgPngToSize(osmd) {
+      if (osmd) {
+        const imgList = ''
+        if (osmd.Drawer.Backends.length > 0) {
+          var backend = osmd.Drawer.Backends[0]
+          var state = backend.ctx.state;
+          var width = backend.ctx.width / state.scale.x;
+          var height = backend.ctx.height / state.scale.y;
+          var cont = new XMLSerializer().serializeToString(
+            backend.ctx.svg
+          )
+          return {
+            img: cont,
+            width: width,
+            height: height
+          }
         }
+      } else {
+        console.log('没有OSMD')
+      }
+    }
+    function render() {
+      osmd.render();
+      window.parent.postMessage({
+        api: 'musicStaffRender',
+        loading: false,
+        osmdImg: getSvgPngToSize(osmd)
+      }, '*');
+    }
 
-        function renderXml(xmlUrl, partIndex) {
-            osmd
-                .load(xmlUrl)
-                .then(
-                    function () {
-                        for (let i = 0; i < osmd.Sheet.Instruments.length; i++) {
-                            // console.log(osmd.Sheet.Instruments[i].Name);
-                            osmd.Sheet.Instruments[i].Visible = i === partIndex;
-                        }
-                        osmd.zoom = .5
-                        render();
-                    }
-                );
-        }
-        function resetRender(partIndex) {
+    function renderXml(xmlUrl, partIndex) {
+      osmd
+        .load(xmlUrl)
+        .then(
+          function () {
             for (let i = 0; i < osmd.Sheet.Instruments.length; i++) {
-                // console.log(osmd.Sheet.Instruments[i].Name);
-                osmd.Sheet.Instruments[i].Visible = i === partIndex;
+              // console.log(osmd.Sheet.Instruments[i].Name);
+              osmd.Sheet.Instruments[i].Visible = i === partIndex;
             }
+            osmd.zoom = .5
             render();
-            
-        }
-    </script>
+          }
+        );
+    }
+    function resetRender(partIndex) {
+      for (let i = 0; i < osmd.Sheet.Instruments.length; i++) {
+        // console.log(osmd.Sheet.Instruments[i].Name);
+        osmd.Sheet.Instruments[i].Visible = i === partIndex;
+      }
+      render();
+
+    }
+  </script>
 </body>
 
 </html>

+ 2 - 2
src/helpers/oss-file-upload.ts

@@ -28,7 +28,7 @@ const tencentBucket = 'daya-online-1303457149'
  * @param oss 服务商 ks3 tencent
  * @returns ”{'signatur'':'',''kssAccessKeyI'':'',''policy': '' }“
  */
-export const getUploadSign = async (params: any) => {
+export const getUploadSign = async (params: any, hideLoading = false) => {
   const { bucketName, filename, postData } = params
   const ossType = ossSwitch
   let bucket = bucketName
@@ -46,6 +46,7 @@ export const getUploadSign = async (params: any) => {
     tempPostData = postData
   }
   return request.post(state.platformApi + '/open/getUploadSign', {
+    hideLoading,
     data: {
       postData: tempPostData,
       pluginName: ossType,
@@ -198,7 +199,6 @@ export const onOnlyFileUpload = async (action: string, params: any) => {
   } else {
     let file = ''
     let errorObj: any = null
-    console.log(params, 'params')
     const cos = new COS({
       Domain: 'https://oss.dayaedu.com',
       // getAuthorization 必选参数

+ 30 - 0
src/tenant/music/music-detail/formatSvgToImg.ts

@@ -0,0 +1,30 @@
+import { Canvg, presets } from 'canvg'
+
+const preset = presets.offscreen()
+const blobToBase64 = (blob: any) => {
+  return new Promise((resolve, _) => {
+    const reader = new FileReader()
+    reader.onloadend = () => resolve(reader.result)
+    reader.readAsDataURL(blob)
+  })
+}
+
+export const svgtopng = async (svg: any, width: any, height: any) => {
+  const canvas = new OffscreenCanvas(width, height)
+  const ctx = canvas.getContext('2d')!
+  const v = await Canvg.fromString(ctx!, svg, preset)
+
+  /**
+   * Resize SVG to fit in given size.
+   * @param width
+   * @param height
+   * @param preserveAspectRatio
+   */
+  v.resize(width * 2, height * 2, 'xMidYMid meet')
+
+  // Render only first frame, ignoring animations and mouse.
+  await v.start()
+  const blob = await canvas.convertToBlob()
+  const base64 = await blobToBase64(blob)
+  return base64
+}

+ 5 - 0
src/tenant/music/music-detail/new-index.module.less

@@ -366,6 +366,7 @@
     color: #333;
     font-size: 15px;
     margin-top: 4px;
+    margin-bottom: 120px;
   }
 
   :global {
@@ -646,4 +647,8 @@
 .staffChange {
   --van-popup-close-icon-color: #4C4949;
   --van-popup-close-icon-size: 18px;
+}
+
+.staffIframe {
+  // margin-top: -60px;
 }

+ 80 - 28
src/tenant/music/music-detail/new-index.tsx

@@ -58,6 +58,7 @@ import 'plyr/dist/plyr.css'
 import Download from './download'
 import { getInstrumentName } from '@/constant/instruments'
 import { getUploadSign, onOnlyFileUpload } from '@/helpers/oss-file-upload'
+import { svgtopng } from './formatSvgToImg'
 
 export default defineComponent({
   name: 'new-index',
@@ -300,9 +301,52 @@ export default defineComponent({
         }
       })
     }
-    const showLoading = (e: any) => {
-      console.log(e)
+
+    const tenantObj = reactive({
+      policy: '',
+      signature: '',
+      key: '',
+      kssAccessKeyId: '',
+      acl: 'public-read',
+      name: ''
+    })
+
+    const showLoading = async (e: any) => {
+      // console.log(e, 'showLoading')
       if (e.data?.api === 'musicStaffRender') {
+        const osmdImg = e.data.osmdImg
+        showImg = []
+        const img = await svgtopng(osmdImg.img, osmdImg.width, osmdImg.height)
+        const fileName =
+          route.query.id + state.user.data.userId + +new Date() + '.png'
+
+        const obj = {
+          filename: fileName,
+          bucketName: 'cloud-coach',
+          postData: {
+            filename: fileName,
+            acl: 'public-read',
+            key: fileName
+          }
+        }
+        const { data } = await getUploadSign(obj, true)
+
+        const dataObj = {
+          policy: data.policy,
+          signature: data.signature,
+          key: fileName,
+          KSSAccessKeyId: data.kssAccessKeyId,
+          acl: 'public-read',
+          name: fileName
+        }
+        const files = base64ToBlob(img)
+        const ossUploadUrl = getOssUploadUrl('cloud-coach')
+        const imgurl = await onOnlyFileUpload(ossUploadUrl, {
+          ...dataObj,
+          file: files
+        })
+        showImg = [imgurl]
+
         loading.value = e.data.loading
       }
     }
@@ -542,9 +586,11 @@ export default defineComponent({
       partIndex: 0,
       partList: [] as any[]
     })
+    const osmdPreviewRef = ref()
     /** 渲染五线谱 */
     const renderStaff = () => {
-      staffData.iframeSrc = `${location.origin}${location.pathname}osmd/index.html`
+      staffData.iframeSrc = `${location.origin}/osmd/index.html`
+      // staffData.iframeSrc = `${location.origin}${location.pathname}osmd/index.html`
       staffData.musicXml = musicDetail.value?.xmlFileUrl || ''
       staffData.partList = musicDetail.value?.background || []
       staffData.instrumentName = getInstrumentName(
@@ -636,31 +682,31 @@ export default defineComponent({
           </div>
           <div
             class={[
-              styles.alumCollect,
-              musicDetail.value?.musicSheetType === 'CONCERT'
-                ? styles.alumCollectCencert
-                : ''
+              styles.alumCollect
+              // musicDetail.value?.musicSheetType === 'CONCERT'
+              //   ? styles.alumCollectCencert
+              //   : ''
             ]}
           >
             <div class={styles.alumCollectItem} onClick={onShare}>
               <Image src={iconShare} />
               <span>分享</span>
             </div>
-            {musicDetail.value?.musicSheetType !== 'CONCERT' && (
-              <div
-                class={styles.alumCollectItem}
-                onClick={() => {
-                  if (showImg.length > 0) {
-                    downloadStatus.value = true
-                  } else {
-                    Toast('暂无图片')
-                  }
-                }}
-              >
-                <img src={iconDownload} />
-                <span>下载</span>
-              </div>
-            )}
+            {/* {musicDetail.value?.musicSheetType !== 'CONCERT' && ( */}
+            <div
+              class={styles.alumCollectItem}
+              onClick={() => {
+                if (showImg.length > 0) {
+                  downloadStatus.value = true
+                } else {
+                  Toast('暂无图片')
+                }
+              }}
+            >
+              <img src={iconDownload} />
+              <span>下载</span>
+            </div>
+            {/* )} */}
 
             <div
               class={styles.alumCollectItem}
@@ -735,19 +781,23 @@ export default defineComponent({
           {musicDetail.value?.musicSheetType === 'CONCERT' ? (
             <>
               {loading.value && (
-                <>
+                <div>
                   <Vue3Lottie
                     animationData={AstronautJSON}
                     class={styles.finch}
                   ></Vue3Lottie>
                   <p class={styles.finchLoad}>加载中...</p>
-                </>
+                </div>
               )}
               <iframe
                 id="staffIframeRef"
+                style={{
+                  opacity: loading.value ? 0 : 1
+                }}
                 src={staffData.iframeSrc}
                 onLoad={musicIframeLoad}
               ></iframe>
+              {/* <OsmdPreview ref={osmdPreviewRef} /> */}
             </>
           ) : (
             <>
@@ -890,10 +940,12 @@ export default defineComponent({
         </Popup>
 
         <Popup v-model:show={downloadStatus.value} position="bottom" round>
-          <Download
-            imgList={JSON.parse(JSON.stringify(showImg))}
-            musicSheetName={musicDetail.value.musicSheetName}
-          />
+          {downloadStatus.value && (
+            <Download
+              imgList={JSON.parse(JSON.stringify(showImg))}
+              musicSheetName={musicDetail.value.musicSheetName}
+            />
+          )}
         </Popup>
 
         <Popup

+ 76 - 17
src/views/music/music-detail/index.module.less

@@ -1,7 +1,8 @@
-.base > div {
+.base>div {
   background: url(./header-bg.png) no-repeat top center;
   // background-attachment: fixed;
 }
+
 .detail {
   overflow: hidden;
   --van-nav-bar-background-color: transparent;
@@ -21,17 +22,20 @@
     }
   }
 }
+
 .base {
   :global(.van-sticky--fixed) {
     box-shadow: 10px 10px 10px var(--box-shadow-color);
   }
 }
+
 .shareBtn {
   display: flex;
   align-items: flex-start;
   color: #fff;
   font-size: 14px;
   line-height: 20px !important;
+
   :global(.van-image) {
     width: 18px;
     height: 18px;
@@ -48,6 +52,7 @@
   object-fit: cover;
   filter: blur(10px);
 }
+
 .bgContent {
   position: absolute;
   top: 0;
@@ -57,41 +62,46 @@
   backdrop-filter: blur(20px);
   -webkit-backdrop-filter: blur(20px);
 }
+
 .musicContent {
   position: relative;
   width: 100%;
   height: 500px;
   overflow: hidden;
+
   &::after {
     content: ' ';
     position: absolute;
     bottom: 0;
     left: 0;
     right: 0;
-    background: linear-gradient(
-      180deg,
-      rgba(255, 255, 255, 0) 0%,
-      #ffffff 100%
-    );
+    background: linear-gradient(180deg,
+        rgba(255, 255, 255, 0) 0%,
+        #ffffff 100%);
     height: 287px;
   }
+
   .musicTitle {
     text-align: center;
     font-size: 16px;
   }
+
   .musicImg {
     width: 100%;
   }
+
   .finch {
     width: 150px;
     margin: 80px auto 0;
   }
+
   .finchLoad {
     text-align: center;
     color: #333;
     font-size: 15px;
     margin-top: 4px;
   }
+
   :global {
     iframe {
       // visibility: hidden;
@@ -99,6 +109,7 @@
       width: 100%;
       height: 500px;
       overflow: hidden;
+
       body {
         ::-webkit-scrollbar-thumb {
           background-color: #efeff0;
@@ -118,6 +129,7 @@
   box-shadow: 0px 0px 6px 0px rgba(229, 229, 229, 0.7);
   overflow: hidden;
 }
+
 .videoOperation {
   position: absolute;
   left: 0;
@@ -125,6 +137,7 @@
   bottom: 5px;
   z-index: 1;
 }
+
 .audition {
   display: flex;
   align-items: center;
@@ -136,6 +149,7 @@
   font-weight: 600;
   color: #ff731d;
   height: 18px;
+
   img {
     margin-top: -2px;
     width: 21px;
@@ -143,6 +157,7 @@
     margin-right: 11px;
   }
 }
+
 .collect {
   display: flex;
   align-items: center;
@@ -150,17 +165,20 @@
   padding: 11px;
   font-size: 14px;
   color: #666666;
+
   .userInfo {
     display: flex;
     align-items: center;
     padding: 3px 6px;
     background: #d5f3ee;
     border-radius: 16px;
+
     img {
       width: 26px;
       height: 26px;
       border-radius: 50%;
     }
+
     span {
       padding-left: 8px;
       max-width: 60px;
@@ -170,15 +188,18 @@
       color: #2dc7aa;
     }
   }
+
   .collectSection {
     display: flex;
     align-items: center;
+
     img {
       margin-top: -2px;
       margin-left: 5px;
       width: 18px;
       height: 18px;
     }
+
     :global {
       .van-icon {
         font-size: 20px;
@@ -203,10 +224,12 @@
   display: flex;
   align-items: center;
   justify-content: space-between;
-  & > div {
+
+  &>div {
     display: flex;
     align-items: center;
     line-height: 1;
+
     img {
       width: 20px;
       height: 20px;
@@ -221,6 +244,7 @@
   padding: 16px;
   z-index: 11;
 }
+
 .musicContainer {
   position: relative;
   // padding: 16px 0 0;
@@ -239,24 +263,28 @@
   padding: 11px 12px;
   background: #ffffff;
   border-radius: 10px;
+
   // border: 1px solid #2dc7aa;
   .icon {
     width: 36px;
     height: 36px;
     border-radius: 10px;
   }
+
   .info {
     margin-left: 14px;
     flex: 1;
     margin-right: 14px;
     word-break: break-all;
-    > h4 {
+
+    >h4 {
       color: var(--music-list-item-title-color);
       font-size: 14px;
       font-weight: 600;
       width: 200px;
     }
-    > p {
+
+    >p {
       color: var(--music-list-item-mate-color);
       line-height: 17px;
     }
@@ -292,16 +320,19 @@
     height: 72px;
     border-radius: 10px;
   }
+
   .info {
     margin-left: 6px;
     flex: 1;
     word-break: break-all;
-    > h4 {
+
+    >h4 {
       color: var(--music-list-item-title-color);
       font-size: 16px;
       font-weight: 600;
     }
-    > p {
+
+    >p {
       color: var(--music-list-item-mate-color);
       line-height: 17px;
     }
@@ -321,6 +352,7 @@
   color: #ffffff;
   line-height: 24px;
 }
+
 .buttonDiscount {
   position: absolute;
   top: -18px;
@@ -342,10 +374,12 @@
   overflow: hidden;
   flex-shrink: 0;
 }
+
 .musicInfo {
   padding-top: 23px !important;
   padding-bottom: 23px !important;
   margin-bottom: 10px;
+
   .coomposer {
     padding-top: 2px;
     padding-left: 6px;
@@ -354,11 +388,13 @@
     overflow: hidden;
     text-overflow: ellipsis;
   }
+
   .tag {
     flex-shrink: 0;
     padding: 2px 4px 0;
     border-radius: 4px;
-    & + .tag {
+
+    &+.tag {
       margin-left: 5px;
     }
   }
@@ -368,14 +404,16 @@
     flex: 1;
     margin-right: 14px;
     word-break: break-all;
-    > h4 {
+
+    >h4 {
       font-size: 16px;
       font-weight: bold;
       color: #1a1a1a;
-      width: 175px;
+      width: 160px;
       padding-bottom: 3px;
     }
-    > p {
+
+    >p {
       font-size: 12px;
       color: #999;
       line-height: 17px;
@@ -388,6 +426,7 @@
     justify-content: center;
     align-items: center;
     font-size: 12px;
+
     img {
       height: 24px;
       width: 24px;
@@ -399,6 +438,7 @@
     margin-left: 5px;
     flex-shrink: 0;
   }
+
   .songAlbum {
     width: 15px;
     height: 15px;
@@ -418,15 +458,18 @@
   display: flex;
   align-items: center;
   justify-content: space-between;
+
   // height: 45px;
   .priceSection {
     font-size: 14px;
     font-weight: 400;
     color: #999999;
+
     .price {
       font-size: 22px;
       font-weight: bold;
       color: #ff4e19;
+
       i {
         font-style: normal;
         font-size: 16px;
@@ -441,19 +484,22 @@
   display: flex;
   align-items: center;
   justify-content: flex-end;
+
   :global {
     .van-button {
       padding: 0 22px;
       font-weight: 600;
 
-      & + .van-button {
+      &+.van-button {
         margin-left: 12px;
       }
     }
   }
+
   .primry {
     box-shadow: 0px 2px 7px 0px rgba(45, 199, 170, 0.25);
   }
+
   .member {
     box-shadow: 0px 2px 7px 0px rgba(187, 156, 83, 0.25);
   }
@@ -470,6 +516,7 @@
   line-height: 20px;
   text-align: center;
   padding-top: 60px;
+
   .emptyImg {
     width: 172px;
   }
@@ -478,6 +525,7 @@
 .staffContainer {
   // text-align: center;
   padding: 15px 15px 24px;
+
   .staffTitle {
     padding-bottom: 25px;
     font-size: 16px;
@@ -489,34 +537,41 @@
     width: 32px;
     height: 20px;
   }
+
   .name {
     padding-left: 17px;
     font-size: 13px;
     font-weight: 500;
     color: #333333;
   }
+
   .boxStyle {
     background: transparent !important;
     width: 15px;
     height: 15px;
     border: transparent !important;
   }
+
   .active {
     background: #f7f8f9;
     border-radius: 8px;
+
     .name {
       color: #2dc7aa;
     }
   }
+
   :global {
     .van-cell {
       padding: 9px 16px 9px;
       margin-bottom: 6px;
+
       &:hover,
       &:active,
       &.active {
         background: #f7f8f9;
         border-radius: 8px;
+
         .name {
           color: #2dc7aa;
         }
@@ -526,10 +581,12 @@
         margin-bottom: 0;
       }
     }
+
     .van-cell__value {
       display: flex;
       justify-content: flex-end;
     }
+
     .van-checkbox {
       overflow: inherit;
       height: 18px;
@@ -537,14 +594,16 @@
       align-items: center;
       justify-content: flex-end;
     }
+
     .van-checkbox__icon {
       height: 15px;
       line-height: 15px;
       display: inline-block;
       vertical-align: middle;
     }
+
     .van-checkbox__label {
       line-height: 15px;
     }
   }
-}
+}

+ 63 - 30
src/views/music/music-detail/index.tsx

@@ -65,6 +65,7 @@ import 'plyr/dist/plyr.css'
 import Download from './download'
 import { getInstrumentName } from '@/constant/instruments'
 import { getUploadSign, onOnlyFileUpload } from '@/helpers/oss-file-upload'
+import { svgtopng } from '@/tenant/music/music-detail/formatSvgToImg'
 
 export const getAssetsHomeFile = (fileName: string) => {
   const path = `../component/images/${fileName}`
@@ -314,10 +315,41 @@ export default defineComponent({
         }
       })
     }
-    const showLoading = (e: any) => {
-      console.log(e)
+    const showLoading = async (e: any) => {
       if (e.data?.api === 'musicStaffRender') {
         loading.value = e.data.loading
+        const osmdImg = e.data.osmdImg
+        showImg = []
+        const img = await svgtopng(osmdImg.img, osmdImg.width, osmdImg.height)
+        const fileName =
+          route.query.id + state.user.data.userId + +new Date() + '.png'
+
+        const obj = {
+          filename: fileName,
+          bucketName: 'cloud-coach',
+          postData: {
+            filename: fileName,
+            acl: 'public-read',
+            key: fileName
+          }
+        }
+        const { data } = await getUploadSign(obj, true)
+
+        const dataObj = {
+          policy: data.policy,
+          signature: data.signature,
+          key: fileName,
+          KSSAccessKeyId: data.kssAccessKeyId,
+          acl: 'public-read',
+          name: fileName
+        }
+        const files = base64ToBlob(img)
+        const ossUploadUrl = getOssUploadUrl('cloud-coach')
+        const imgurl = await onOnlyFileUpload(ossUploadUrl, {
+          ...dataObj,
+          file: files
+        })
+        showImg = [imgurl]
       }
     }
     onMounted(async () => {
@@ -662,40 +694,38 @@ export default defineComponent({
                 ),
                 value: () => (
                   <>
-                    <div
-                      class="van-cell__value"
-                      style={{
-                        display:
-                          musicDetail.value?.musicSheetType === 'SINGLE'
-                            ? ''
-                            : 'none'
-                      }}
-                    >
-                      {musicDetail.value?.notation ? (
-                        <span
-                          class={styles.download}
-                          onClick={() => {
-                            staff.status = true
-                          }}
-                        >
-                          <img src={iconChangeStaff} />
-                          <span>转谱</span>
-                        </span>
-                      ) : null}
+                    {musicDetail.value?.notation ? (
                       <span
                         class={styles.download}
                         onClick={() => {
-                          if (showImg.length > 0) {
-                            downloadStatus.value = true
-                          } else {
-                            Toast('暂无图片')
-                          }
+                          staff.status = true
+                        }}
+                        style={{
+                          display:
+                            musicDetail.value?.musicSheetType !== 'CONCERT'
+                              ? ''
+                              : 'none'
                         }}
                       >
-                        <img src={iconDownload} />
-                        <span>下载曲谱</span>
+                        <img src={iconChangeStaff} />
+                        <span>转谱</span>
                       </span>
-                    </div>
+                    ) : null}
+
+                    <span
+                      class={styles.download}
+                      onClick={() => {
+                        if (showImg.length > 0) {
+                          downloadStatus.value = true
+                        } else {
+                          Toast('暂无图片')
+                        }
+                      }}
+                    >
+                      <img src={iconDownload} />
+                      <span>下载曲谱</span>
+                    </span>
+
                     <span
                       style={{
                         display:
@@ -745,6 +775,9 @@ export default defineComponent({
                   )}
                   <iframe
                     id="staffIframeRef"
+                    style={{
+                      opacity: loading.value ? 0 : 1
+                    }}
                     src={staffData.iframeSrc}
                     onLoad={musicIframeLoad}
                   ></iframe>

+ 49 - 0
yarn.lock

@@ -1083,6 +1083,16 @@
   "resolved" "https://registry.npmmirror.com/@types/numeral/-/numeral-2.0.2.tgz"
   "version" "2.0.2"
 
+"@types/offscreencanvas@^2019.6.4":
+  "integrity" "sha512-+HSrJgjBW77ALieQdMJvXhRZUIRN1597L+BKvsyeiIlHHERnqjcuOLyodK3auJ3Y3zRezNKtKAhuQWYJfEgFHQ=="
+  "resolved" "https://registry.npmmirror.com/@types/offscreencanvas/-/offscreencanvas-2019.7.1.tgz"
+  "version" "2019.7.1"
+
+"@types/raf@^3.4.0":
+  "integrity" "sha512-1jJ3OO8FXHCcuVXCuO1EMC/MjDuT6/cxgsMw/UebkO9afnL99Y5QTpUjk7+flK4G5FzBVJEgDKL5eFtoxJs9MQ=="
+  "resolved" "https://registry.npmmirror.com/@types/raf/-/raf-3.4.1.tgz"
+  "version" "3.4.1"
+
 "@types/through@*":
   "integrity" "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg=="
   "resolved" "https://registry.npmmirror.com/@types/through/-/through-0.0.30.tgz"
@@ -1714,6 +1724,18 @@
   "resolved" "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz"
   "version" "1.0.30001363"
 
+"canvg@^4.0.1":
+  "integrity" "sha512-5gD/d6SiCCT7baLnVr0hokYe93DfcHW2rSqdKOuOQD84YMlyfttnZ8iQsThTdX6koYam+PROz/FuQTo500zqGw=="
+  "resolved" "https://registry.npmmirror.com/canvg/-/canvg-4.0.1.tgz"
+  "version" "4.0.1"
+  dependencies:
+    "@types/offscreencanvas" "^2019.6.4"
+    "@types/raf" "^3.4.0"
+    "raf" "^3.4.1"
+    "rgbcolor" "^1.0.1"
+    "stackblur-canvas" "^2.0.0"
+    "svg-pathdata" "^6.0.3"
+
 "capital-case@^1.0.4":
   "integrity" "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A=="
   "resolved" "https://registry.npmmirror.com/capital-case/-/capital-case-1.0.4.tgz"
@@ -3802,6 +3824,11 @@
   "resolved" "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz"
   "version" "4.0.0"
 
+"performance-now@^2.1.0":
+  "integrity" "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+  "resolved" "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz"
+  "version" "2.1.0"
+
 "picocolors@^1.0.0":
   "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
   "resolved" "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz"
@@ -4050,6 +4077,13 @@
   "resolved" "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz"
   "version" "1.2.3"
 
+"raf@^3.4.1":
+  "integrity" "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA=="
+  "resolved" "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz"
+  "version" "3.4.1"
+  dependencies:
+    "performance-now" "^2.1.0"
+
 "rangetouch@^2.0.1":
   "integrity" "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA=="
   "resolved" "https://registry.npmmirror.com/rangetouch/-/rangetouch-2.0.1.tgz"
@@ -4192,6 +4226,11 @@
   "resolved" "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz"
   "version" "1.3.0"
 
+"rgbcolor@^1.0.1":
+  "integrity" "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw=="
+  "resolved" "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz"
+  "version" "1.0.1"
+
 "rimraf@^3.0.2":
   "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="
   "resolved" "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz"
@@ -4390,6 +4429,11 @@
   "resolved" "https://registry.npmmirror.com/split-on-first/-/split-on-first-1.1.0.tgz"
   "version" "1.1.0"
 
+"stackblur-canvas@^2.0.0":
+  "integrity" "sha512-8S1aIA+UoF6erJYnglGPug6MaHYGo1Ot7h5fuXx4fUPvcvQfcdw2o/ppCse63+eZf8PPidSu4v1JnmEVtEDnpg=="
+  "resolved" "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.6.0.tgz"
+  "version" "2.6.0"
+
 "strict-uri-encode@^2.0.0":
   "integrity" "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="
   "resolved" "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz"
@@ -4483,6 +4527,11 @@
   "resolved" "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
   "version" "1.0.0"
 
+"svg-pathdata@^6.0.3":
+  "integrity" "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw=="
+  "resolved" "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz"
+  "version" "6.0.3"
+
 "svg-tags@^1.0.0":
   "integrity" "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA=="
   "resolved" "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz"