Forráskód Böngészése

Merge branch 'hqy筛选' of http://git.dayaedu.com/liushengqiang/music-score into kt-dev

黄琪勇 8 hónapja
szülő
commit
742524ca2d
100 módosított fájl, 2398 hozzáadás és 558 törlés
  1. 18 0
      dist/colexiu.html
  2. 1 0
      dist/css/index-11fe3793.css
  3. 1 0
      dist/css/index-3642c4ba.css
  4. 0 0
      dist/css/index-55dea78a.css
  5. 0 0
      dist/css/instrument-118f68d3.css
  6. 19 0
      dist/index.html
  7. 16 0
      dist/instrument.html
  8. 0 0
      dist/js/colexiu-eef4bdcf.js
  9. 0 0
      dist/js/colexiu-legacy-7a3eb6fe.js
  10. 0 0
      dist/js/gym-9c38e62c.js
  11. 0 0
      dist/js/gym-legacy-8d18cf10.js
  12. 1 0
      dist/js/index-0ce64b5e.js
  13. 1 0
      dist/js/index-143f6670.js
  14. 0 0
      dist/js/index-3c8c1460.js
  15. 1 0
      dist/js/index-5320fd21.js
  16. 1 0
      dist/js/index-5a1d7ebf.js
  17. 0 0
      dist/js/index-75b08da5.js
  18. 0 0
      dist/js/index-84588ddf.js
  19. 1 0
      dist/js/index-8af08a5d.js
  20. 1 0
      dist/js/index-a2a34d0e.js
  21. 1 0
      dist/js/index-a2b90afd.js
  22. 5 0
      dist/js/index-ca614e37.js
  23. 0 0
      dist/js/index-e766fb61.js
  24. 4 0
      dist/js/index-f4ee1fa7.js
  25. 1 0
      dist/js/index-legacy-099f655c.js
  26. 1 0
      dist/js/index-legacy-17369a91.js
  27. 0 0
      dist/js/index-legacy-21320314.js
  28. 0 0
      dist/js/index-legacy-281577ba.js
  29. 1 0
      dist/js/index-legacy-3dbcdd89.js
  30. 1 0
      dist/js/index-legacy-51075cdf.js
  31. 1 0
      dist/js/index-legacy-7317bfb1.js
  32. 1 0
      dist/js/index-legacy-7f311ce7.js
  33. 0 0
      dist/js/index-legacy-89a009a0.js
  34. 4 0
      dist/js/index-legacy-8e168346.js
  35. 1 0
      dist/js/index-legacy-b689f5f4.js
  36. 0 0
      dist/js/index-legacy-b955800c.js
  37. 5 0
      dist/js/index-legacy-cfa001ed.js
  38. 0 0
      dist/js/instrument-c9dd3e10.js
  39. 0 0
      dist/js/instrument-legacy-5ae60624.js
  40. 0 0
      dist/js/modeView-16c7d7e0.js
  41. 0 0
      dist/js/modeView-legacy-54057af4.js
  42. 0 0
      dist/js/orchestra-80468720.js
  43. 0 0
      dist/js/orchestra-legacy-95d50d5d.js
  44. 0 0
      dist/js/polyfills-fda21288.js
  45. 0 0
      dist/js/polyfills-legacy-241ca397.js
  46. 0 0
      dist/js/report-share-04161b62.js
  47. 0 0
      dist/js/report-share-legacy-276fb9cd.js
  48. 19 0
      dist/orchestra.html
  49. BIN
      dist/png/bg2_left_zs-028c8762.png
  50. BIN
      dist/png/d11-fd2f4334.png
  51. BIN
      dist/png/d7-a84641c8.png
  52. BIN
      dist/png/pitchHigh-8f66b326.png
  53. BIN
      dist/png/pitchLow-775a2f42.png
  54. BIN
      dist/png/r2-dc183ac4.png
  55. BIN
      dist/png/r3-b6dcd461.png
  56. 17 0
      dist/report-share.html
  57. 1 1
      osmd-extended
  58. 4 3
      src/helpers/calcSpeed.ts
  59. 302 15
      src/helpers/customMusicScore.ts
  60. 199 35
      src/helpers/formateMusic.ts
  61. 13 7
      src/helpers/metronome.ts
  62. 26 13
      src/page-instrument/App.tsx
  63. 9 0
      src/page-instrument/api.ts
  64. 9 1
      src/page-instrument/component/authorName/index.module.less
  65. 2 2
      src/page-instrument/component/authorName/index.tsx
  66. 282 0
      src/page-instrument/component/the-music-list/filterList.tsx
  67. BIN
      src/page-instrument/component/the-music-list/imgs/headImg.png
  68. BIN
      src/page-instrument/component/the-music-list/imgs/queding.png
  69. BIN
      src/page-instrument/component/the-music-list/imgs/quxiao.png
  70. BIN
      src/page-instrument/component/the-music-list/imgs/shouqi.png
  71. BIN
      src/page-instrument/component/the-music-list/imgs/sj.png
  72. BIN
      src/page-instrument/component/the-music-list/imgs/xiang.png
  73. BIN
      src/page-instrument/component/the-music-list/imgs/zhankai.png
  74. 300 63
      src/page-instrument/component/the-music-list/index.module.less
  75. 2 2
      src/page-instrument/component/the-music-list/index.tsx
  76. 44 27
      src/page-instrument/component/the-music-list/list.tsx
  77. BIN
      src/page-instrument/custom-plugins/guide-driver/images/practise/d11.png
  78. BIN
      src/page-instrument/custom-plugins/guide-driver/images/practise/d7.png
  79. BIN
      src/page-instrument/custom-plugins/guide-driver/images/report/r2.png
  80. BIN
      src/page-instrument/custom-plugins/guide-driver/images/report/r3.png
  81. 75 12
      src/page-instrument/custom-plugins/guide-driver/index.less
  82. 332 48
      src/page-instrument/custom-plugins/guide-driver/index.tsx
  83. 4 2
      src/page-instrument/custom-plugins/helper-model/recommendation/index.module.less
  84. 1 1
      src/page-instrument/custom-plugins/helper-model/recommendation/index.tsx
  85. 2 1
      src/page-instrument/custom-plugins/work-index/index.tsx
  86. 21 14
      src/page-instrument/evaluat-model/evaluat-result/index.tsx
  87. 11 8
      src/page-instrument/evaluat-model/index.tsx
  88. 4 3
      src/page-instrument/follow-model/index.tsx
  89. 156 84
      src/page-instrument/header-top/index.module.less
  90. 155 87
      src/page-instrument/header-top/index.tsx
  91. 6 2
      src/page-instrument/header-top/modeView.tsx
  92. 3 2
      src/page-instrument/header-top/settting/index.module.less
  93. 27 23
      src/page-instrument/header-top/settting/index.tsx
  94. 2 2
      src/page-instrument/header-top/speed/index.module.less
  95. 13 10
      src/page-instrument/header-top/speed/index.tsx
  96. 1 0
      src/page-instrument/simple-detail/index.tsx
  97. BIN
      src/page-instrument/view-detail/images/bg2_left_zs.png
  98. 159 11
      src/page-instrument/view-detail/index.module.less
  99. 109 78
      src/page-instrument/view-detail/index.tsx
  100. 1 1
      src/page-instrument/view-detail/loading.tsx

+ 18 - 0
dist/colexiu.html

@@ -2,7 +2,11 @@
 <html lang="en">
 <html lang="en">
 
 
 <head>
 <head>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
+=======
+  <script type="module" crossorigin src="./js/polyfills-fda21288.js"></script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 
 
   <meta charset="UTF-8" />
   <meta charset="UTF-8" />
   <link rel="icon" type="image/svg+xml" href="./vite.svg" />
   <link rel="icon" type="image/svg+xml" href="./vite.svg" />
@@ -40,12 +44,21 @@
       },
       },
     })
     })
   </script>
   </script>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/colexiu-7df1eb79.js"></script>
   <script type="module" crossorigin src="./js/colexiu-7df1eb79.js"></script>
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-38945c54.js">
   <link rel="modulepreload" crossorigin href="./js/index-38945c54.js">
   <link rel="modulepreload" crossorigin href="./js/index-8af08a5d.js">
   <link rel="modulepreload" crossorigin href="./js/index-8af08a5d.js">
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
+=======
+  <script type="module" crossorigin src="./js/colexiu-eef4bdcf.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-84588ddf.js">
+  <link rel="modulepreload" crossorigin href="./js/index-75b08da5.js">
+  <link rel="modulepreload" crossorigin href="./js/index-5320fd21.js">
+  <link rel="modulepreload" crossorigin href="./js/index-a2b90afd.js">
+  <link rel="stylesheet" href="./css/index-3642c4ba.css">
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
   <link rel="stylesheet" href="./css/colexiu-62f31c4f.css">
   <link rel="stylesheet" href="./css/colexiu-62f31c4f.css">
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
   <script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
   <script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
@@ -56,8 +69,13 @@
   <img id="loading" class="show" src="./loading.svg" alt="loading" />
   <img id="loading" class="show" src="./loading.svg" alt="loading" />
   
   
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+<<<<<<< HEAD
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/colexiu-legacy-6f74bd74.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/colexiu-legacy-6f74bd74.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+=======
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-241ca397.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/colexiu-legacy-7a3eb6fe.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 </body>
 </body>
 
 
 </html>
 </html>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/css/index-11fe3793.css


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/css/index-3642c4ba.css


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/css/index-55dea78a.css


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/css/instrument-118f68d3.css


+ 19 - 0
dist/index.html

@@ -2,7 +2,11 @@
 <html lang="ZH-cn">
 <html lang="ZH-cn">
 
 
 <head>
 <head>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
+=======
+  <script type="module" crossorigin src="./js/polyfills-fda21288.js"></script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 
 
   <meta charset="UTF-8">
   <meta charset="UTF-8">
   <link rel="icon" href="./favicon.ico" />
   <link rel="icon" href="./favicon.ico" />
@@ -75,6 +79,7 @@
       }
       }
     })
     })
   </script>
   </script>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/gym-a67c0780.js"></script>
   <script type="module" crossorigin src="./js/gym-a67c0780.js"></script>
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-38945c54.js">
   <link rel="modulepreload" crossorigin href="./js/index-38945c54.js">
@@ -82,6 +87,15 @@
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
+=======
+  <script type="module" crossorigin src="./js/gym-9c38e62c.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-84588ddf.js">
+  <link rel="modulepreload" crossorigin href="./js/index-75b08da5.js">
+  <link rel="modulepreload" crossorigin href="./js/index-5a1d7ebf.js">
+  <link rel="modulepreload" crossorigin href="./js/index-a2b90afd.js">
+  <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
+  <link rel="stylesheet" href="./css/index-3642c4ba.css">
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
   <link rel="stylesheet" href="./css/index-85f95688.css">
   <link rel="stylesheet" href="./css/index-85f95688.css">
   <link rel="stylesheet" href="./css/plyr-ad8ef5ae.css">
   <link rel="stylesheet" href="./css/plyr-ad8ef5ae.css">
   <link rel="stylesheet" href="./css/index-171cd132.css">
   <link rel="stylesheet" href="./css/index-171cd132.css">
@@ -98,8 +112,13 @@
   <img id="loading" class="show" src="./loading.svg" alt="loading" />
   <img id="loading" class="show" src="./loading.svg" alt="loading" />
   
   
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+<<<<<<< HEAD
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/gym-legacy-7bcdda99.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/gym-legacy-7bcdda99.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+=======
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-241ca397.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/gym-legacy-8d18cf10.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 </body>
 </body>
 
 
 </html>
 </html>

+ 16 - 0
dist/instrument.html

@@ -2,7 +2,11 @@
 <html lang="en">
 <html lang="en">
 
 
 <head>
 <head>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
+=======
+  <script type="module" crossorigin src="./js/polyfills-fda21288.js"></script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 
 
   <meta charset="UTF-8" />
   <meta charset="UTF-8" />
   <meta name="viewport"
   <meta name="viewport"
@@ -41,10 +45,17 @@
       })
       })
     }
     }
   </script>
   </script>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/instrument-687fc6b5.js"></script>
   <script type="module" crossorigin src="./js/instrument-687fc6b5.js"></script>
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
   <link rel="stylesheet" href="./css/instrument-9ce1010f.css">
   <link rel="stylesheet" href="./css/instrument-9ce1010f.css">
+=======
+  <script type="module" crossorigin src="./js/instrument-c9dd3e10.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-84588ddf.js">
+  <link rel="stylesheet" href="./css/index-3642c4ba.css">
+  <link rel="stylesheet" href="./css/instrument-118f68d3.css">
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
   <script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
   <script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
 </head>
 </head>
@@ -67,8 +78,13 @@
     var vConsole = new window.VConsole();
     var vConsole = new window.VConsole();
   </script>   -->
   </script>   -->
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+<<<<<<< HEAD
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/instrument-legacy-a1cbab87.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/instrument-legacy-a1cbab87.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+=======
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-241ca397.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/instrument-legacy-5ae60624.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 </body>
 </body>
 
 
 </html>
 </html>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/colexiu-eef4bdcf.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/colexiu-legacy-7a3eb6fe.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/gym-9c38e62c.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/gym-legacy-8d18cf10.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-0ce64b5e.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-143f6670.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-3c8c1460.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-5320fd21.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-5a1d7ebf.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-75b08da5.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-84588ddf.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-8af08a5d.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-a2a34d0e.js


+ 1 - 0
dist/js/index-a2b90afd.js

@@ -0,0 +1 @@
+import{b6 as l,d as i,h as e,bg as v,b9 as r,bb as d,bC as _,bc as m,bD as w,bf as u,bj as g,F as $}from"./index-84588ddf.js";const[y,A]=l("skeleton-title"),P={round:Boolean,titleWidth:r};var p=i({name:y,props:P,setup(t){return()=>e("h3",{class:A([{round:t.round}]),style:{width:v(t.titleWidth)}},null)}});const T=d(p);var z=T;const[B,D]=l("skeleton-avatar"),F={avatarSize:r,avatarShape:m("round")};var N=i({name:B,props:F,setup(t){return()=>e("div",{class:D([t.avatarShape]),style:_(t.avatarSize)},null)}});const R=d(N);var C=R;const s="100%",I={round:Boolean,rowWidth:{type:r,default:s}},[L,U]=l("skeleton-paragraph");var E=i({name:L,props:I,setup(t){return()=>e("div",{class:U([{round:t.round}]),style:{width:t.rowWidth}},null)}});const H=d(E);var O=H;const[j,c]=l("skeleton"),V="60%",q={row:w(0),round:Boolean,title:Boolean,titleWidth:r,avatar:Boolean,avatarSize:r,avatarShape:m("round"),loading:u,animate:u,rowWidth:{type:[Number,String,Array],default:s}};var x=i({name:j,inheritAttrs:!1,props:q,setup(t,{slots:o,attrs:h}){const f=()=>{if(t.avatar)return e(C,{avatarShape:t.avatarShape,avatarSize:t.avatarSize},null)},S=()=>{if(t.title)return e(z,{round:t.round,titleWidth:t.titleWidth},null)},b=n=>{const{rowWidth:a}=t;return a===s&&n===+t.row-1?V:Array.isArray(a)?a[n]:a},k=()=>Array(+t.row).fill("").map((n,a)=>e(O,{key:a,round:t.round,rowWidth:v(b(a))},null)),W=()=>o.template?o.template():e($,null,[f(),e("div",{class:c("content")},[S(),k()])]);return()=>{var n;return t.loading?e("div",g({class:c({animate:t.animate,round:t.round})},h),[W()]):(n=o.default)==null?void 0:n.call(o)}}});const J=d(x);export{J as S};

+ 5 - 0
dist/js/index-ca614e37.js

@@ -0,0 +1,5 @@
+<<<<<<<< HEAD:dist/js/index-f4ee1fa7.js
+import{d as i,g as l,n as d,bP as e,c,m as r,h as s,at as u}from"./index-067071d7.js";const m="_skeleton_vtlsh_1",f="_detail_vtlsh_12",p="_container_vtlsh_20",a={skeleton:m,detail:f,container:p},y=i({name:"music-list",setup(){const n=l(),t=d({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:e.staff,base64:""},{state:!1,name:"首调",type:e.firstTone,base64:""},{state:!1,name:"固定调",type:e.fixedTone,base64:""}]});c(()=>{window.appName="colexiu",r.xmlUrl=n.xmlUrl,t.isLoading=!1});const o=async()=>{console.log("渲染完成")};return()=>s("div",{class:a.detail},[s("div",{id:"scrollContainer",class:[a.container,"hideCursor"]},[!t.isLoading&&s(u,{onRendered:o},null)])])}});export{y as default};
+========
+import{d as i,g as l,n as d,bP as e,c,m as r,h as s,at as u}from"./index-84588ddf.js";const m="_skeleton_vtlsh_1",f="_detail_vtlsh_12",p="_container_vtlsh_20",a={skeleton:m,detail:f,container:p},y=i({name:"music-list",setup(){const n=l(),t=d({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:e.staff,base64:""},{state:!1,name:"首调",type:e.firstTone,base64:""},{state:!1,name:"固定调",type:e.fixedTone,base64:""}]});c(()=>{window.appName="colexiu",r.xmlUrl=n.xmlUrl,t.isLoading=!1});const o=async()=>{console.log("渲染完成")};return()=>s("div",{class:a.detail},[s("div",{id:"scrollContainer",class:[a.container,"hideCursor"]},[!t.isLoading&&s(u,{onRendered:o},null)])])}});export{y as default};
+>>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c:dist/js/index-ca614e37.js

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-e766fb61.js


+ 4 - 0
dist/js/index-f4ee1fa7.js

@@ -1 +1,5 @@
+<<<<<<<< HEAD:dist/js/index-f4ee1fa7.js
 import{d as i,g as l,n as d,bP as e,c,m as r,h as s,at as u}from"./index-067071d7.js";const m="_skeleton_vtlsh_1",f="_detail_vtlsh_12",p="_container_vtlsh_20",a={skeleton:m,detail:f,container:p},y=i({name:"music-list",setup(){const n=l(),t=d({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:e.staff,base64:""},{state:!1,name:"首调",type:e.firstTone,base64:""},{state:!1,name:"固定调",type:e.fixedTone,base64:""}]});c(()=>{window.appName="colexiu",r.xmlUrl=n.xmlUrl,t.isLoading=!1});const o=async()=>{console.log("渲染完成")};return()=>s("div",{class:a.detail},[s("div",{id:"scrollContainer",class:[a.container,"hideCursor"]},[!t.isLoading&&s(u,{onRendered:o},null)])])}});export{y as default};
 import{d as i,g as l,n as d,bP as e,c,m as r,h as s,at as u}from"./index-067071d7.js";const m="_skeleton_vtlsh_1",f="_detail_vtlsh_12",p="_container_vtlsh_20",a={skeleton:m,detail:f,container:p},y=i({name:"music-list",setup(){const n=l(),t=d({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:e.staff,base64:""},{state:!1,name:"首调",type:e.firstTone,base64:""},{state:!1,name:"固定调",type:e.fixedTone,base64:""}]});c(()=>{window.appName="colexiu",r.xmlUrl=n.xmlUrl,t.isLoading=!1});const o=async()=>{console.log("渲染完成")};return()=>s("div",{class:a.detail},[s("div",{id:"scrollContainer",class:[a.container,"hideCursor"]},[!t.isLoading&&s(u,{onRendered:o},null)])])}});export{y as default};
+========
+import{d as i,g as l,n as d,bP as e,c,m as r,h as s,at as u}from"./index-84588ddf.js";const m="_skeleton_vtlsh_1",f="_detail_vtlsh_12",p="_container_vtlsh_20",a={skeleton:m,detail:f,container:p},y=i({name:"music-list",setup(){const n=l(),t=d({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:e.staff,base64:""},{state:!1,name:"首调",type:e.firstTone,base64:""},{state:!1,name:"固定调",type:e.fixedTone,base64:""}]});c(()=>{window.appName="colexiu",r.xmlUrl=n.xmlUrl,t.isLoading=!1});const o=async()=>{console.log("渲染完成")};return()=>s("div",{class:a.detail},[s("div",{id:"scrollContainer",class:[a.container,"hideCursor"]},[!t.isLoading&&s(u,{onRendered:o},null)])])}});export{y as default};
+>>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c:dist/js/index-ca614e37.js

+ 1 - 0
dist/js/index-legacy-099f655c.js

@@ -0,0 +1 @@
+System.register(["./index-legacy-89a009a0.js"],(function(t,a){"use strict";var r,e,n,l,o,i,s,u,d,p,v,h;return{setters:[t=>{r=t.b6,e=t.d,n=t.h,l=t.bg,o=t.b9,i=t.bb,s=t.bC,u=t.bc,d=t.bD,p=t.bf,v=t.bj,h=t.F}],execute:function(){const[a,c]=r("skeleton-title"),S={round:Boolean,titleWidth:o};var m=e({name:a,props:S,setup:t=>()=>n("h3",{class:c([{round:t.round}]),style:{width:l(t.titleWidth)}},null)}),y=i(m);const[b,w]=r("skeleton-avatar"),W={avatarSize:o,avatarShape:u("round")};var f=e({name:b,props:W,setup:t=>()=>n("div",{class:w([t.avatarShape]),style:s(t.avatarSize)},null)}),g=i(f);const k="100%",z={round:Boolean,rowWidth:{type:o,default:k}},[A,B]=r("skeleton-paragraph");var j=e({name:A,props:z,setup:t=>()=>n("div",{class:B([{round:t.round}]),style:{width:t.rowWidth}},null)}),x=i(j);const[C,D]=r("skeleton"),F={row:d(0),round:Boolean,title:Boolean,titleWidth:o,avatar:Boolean,avatarSize:o,avatarShape:u("round"),loading:p,animate:p,rowWidth:{type:[Number,String,Array],default:k}};var N=e({name:C,inheritAttrs:!1,props:F,setup(t,{slots:a,attrs:r}){const e=()=>{if(t.avatar)return n(g,{avatarShape:t.avatarShape,avatarSize:t.avatarSize},null)},o=()=>{if(t.title)return n(y,{round:t.round,titleWidth:t.titleWidth},null)},i=a=>{const{rowWidth:r}=t;return r===k&&a===+t.row-1?"60%":Array.isArray(r)?r[a]:r};return()=>{var s;return t.loading?n("div",v({class:D({animate:t.animate,round:t.round})},r),[a.template?a.template():n(h,null,[e(),n("div",{class:D("content")},[o(),Array(+t.row).fill("").map(((a,r)=>n(x,{key:r,round:t.round,rowWidth:l(i(r))},null)))])])]):null==(s=a.default)?void 0:s.call(a)}}});t("S",i(N))}}}));

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-legacy-17369a91.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-legacy-21320314.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-legacy-281577ba.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-legacy-3dbcdd89.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-legacy-51075cdf.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-legacy-7317bfb1.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-legacy-7f311ce7.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-legacy-89a009a0.js


+ 4 - 0
dist/js/index-legacy-8e168346.js

@@ -1 +1,5 @@
+<<<<<<<< HEAD:dist/js/index-legacy-8e168346.js
 System.register(["./index-legacy-f170176b.js"],(function(e,t){"use strict";var i,n,a,o,r,s,d,l,c=document.createElement("style");return c.textContent="._skeleton_vtlsh_1{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:.53333rem .8rem;background-color:#fff;z-index:1000;--van-skeleton-paragraph-height: .8rem}._detail_vtlsh_12{width:100vw;height:100vh;overflow:hidden;overflow-y:auto;--header-height: 1.65333rem;background:var(--container-background)}._detail_vtlsh_12 ._container_vtlsh_20{margin:0 .26667rem;border-radius:.26667rem}._detail_vtlsh_12 #musicAndSelection{overflow:initial!important;height:initial!important;max-height:initial!important}\n",document.head.appendChild(c),{setters:[e=>{i=e.d,n=e.g,a=e.n,o=e.bP,r=e.c,s=e.m,d=e.h,l=e.at}],execute:function(){const t="_detail_vtlsh_12",c="_container_vtlsh_20";e("default",i({name:"music-list",setup(){const e=n(),i=a({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:o.staff,base64:""},{state:!1,name:"首调",type:o.firstTone,base64:""},{state:!1,name:"固定调",type:o.fixedTone,base64:""}]});r((()=>{window.appName="colexiu",s.xmlUrl=e.xmlUrl,i.isLoading=!1}));const h=async()=>{console.log("渲染完成")};return()=>d("div",{class:t},[d("div",{id:"scrollContainer",class:[c,"hideCursor"]},[!i.isLoading&&d(l,{onRendered:h},null)])])}}))}}}));
 System.register(["./index-legacy-f170176b.js"],(function(e,t){"use strict";var i,n,a,o,r,s,d,l,c=document.createElement("style");return c.textContent="._skeleton_vtlsh_1{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:.53333rem .8rem;background-color:#fff;z-index:1000;--van-skeleton-paragraph-height: .8rem}._detail_vtlsh_12{width:100vw;height:100vh;overflow:hidden;overflow-y:auto;--header-height: 1.65333rem;background:var(--container-background)}._detail_vtlsh_12 ._container_vtlsh_20{margin:0 .26667rem;border-radius:.26667rem}._detail_vtlsh_12 #musicAndSelection{overflow:initial!important;height:initial!important;max-height:initial!important}\n",document.head.appendChild(c),{setters:[e=>{i=e.d,n=e.g,a=e.n,o=e.bP,r=e.c,s=e.m,d=e.h,l=e.at}],execute:function(){const t="_detail_vtlsh_12",c="_container_vtlsh_20";e("default",i({name:"music-list",setup(){const e=n(),i=a({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:o.staff,base64:""},{state:!1,name:"首调",type:o.firstTone,base64:""},{state:!1,name:"固定调",type:o.fixedTone,base64:""}]});r((()=>{window.appName="colexiu",s.xmlUrl=e.xmlUrl,i.isLoading=!1}));const h=async()=>{console.log("渲染完成")};return()=>d("div",{class:t},[d("div",{id:"scrollContainer",class:[c,"hideCursor"]},[!i.isLoading&&d(l,{onRendered:h},null)])])}}))}}}));
+========
+System.register(["./index-legacy-89a009a0.js"],(function(e,t){"use strict";var i,n,a,o,r,s,d,l,c=document.createElement("style");return c.textContent="._skeleton_vtlsh_1{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:.53333rem .8rem;background-color:#fff;z-index:1000;--van-skeleton-paragraph-height: .8rem}._detail_vtlsh_12{width:100vw;height:100vh;overflow:hidden;overflow-y:auto;--header-height: 1.65333rem;background:var(--container-background)}._detail_vtlsh_12 ._container_vtlsh_20{margin:0 .26667rem;border-radius:.26667rem}._detail_vtlsh_12 #musicAndSelection{overflow:initial!important;height:initial!important;max-height:initial!important}\n",document.head.appendChild(c),{setters:[e=>{i=e.d,n=e.g,a=e.n,o=e.bP,r=e.c,s=e.m,d=e.h,l=e.at}],execute:function(){const t="_detail_vtlsh_12",c="_container_vtlsh_20";e("default",i({name:"music-list",setup(){const e=n(),i=a({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:o.staff,base64:""},{state:!1,name:"首调",type:o.firstTone,base64:""},{state:!1,name:"固定调",type:o.fixedTone,base64:""}]});r((()=>{window.appName="colexiu",s.xmlUrl=e.xmlUrl,i.isLoading=!1}));const h=async()=>{console.log("渲染完成")};return()=>d("div",{class:t},[d("div",{id:"scrollContainer",class:[c,"hideCursor"]},[!i.isLoading&&d(l,{onRendered:h},null)])])}}))}}}));
+>>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c:dist/js/index-legacy-cfa001ed.js

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
dist/js/index-legacy-b689f5f4.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/index-legacy-b955800c.js


+ 5 - 0
dist/js/index-legacy-cfa001ed.js

@@ -0,0 +1,5 @@
+<<<<<<<< HEAD:dist/js/index-legacy-8e168346.js
+System.register(["./index-legacy-f170176b.js"],(function(e,t){"use strict";var i,n,a,o,r,s,d,l,c=document.createElement("style");return c.textContent="._skeleton_vtlsh_1{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:.53333rem .8rem;background-color:#fff;z-index:1000;--van-skeleton-paragraph-height: .8rem}._detail_vtlsh_12{width:100vw;height:100vh;overflow:hidden;overflow-y:auto;--header-height: 1.65333rem;background:var(--container-background)}._detail_vtlsh_12 ._container_vtlsh_20{margin:0 .26667rem;border-radius:.26667rem}._detail_vtlsh_12 #musicAndSelection{overflow:initial!important;height:initial!important;max-height:initial!important}\n",document.head.appendChild(c),{setters:[e=>{i=e.d,n=e.g,a=e.n,o=e.bP,r=e.c,s=e.m,d=e.h,l=e.at}],execute:function(){const t="_detail_vtlsh_12",c="_container_vtlsh_20";e("default",i({name:"music-list",setup(){const e=n(),i=a({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:o.staff,base64:""},{state:!1,name:"首调",type:o.firstTone,base64:""},{state:!1,name:"固定调",type:o.fixedTone,base64:""}]});r((()=>{window.appName="colexiu",s.xmlUrl=e.xmlUrl,i.isLoading=!1}));const h=async()=>{console.log("渲染完成")};return()=>d("div",{class:t},[d("div",{id:"scrollContainer",class:[c,"hideCursor"]},[!i.isLoading&&d(l,{onRendered:h},null)])])}}))}}}));
+========
+System.register(["./index-legacy-89a009a0.js"],(function(e,t){"use strict";var i,n,a,o,r,s,d,l,c=document.createElement("style");return c.textContent="._skeleton_vtlsh_1{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:.53333rem .8rem;background-color:#fff;z-index:1000;--van-skeleton-paragraph-height: .8rem}._detail_vtlsh_12{width:100vw;height:100vh;overflow:hidden;overflow-y:auto;--header-height: 1.65333rem;background:var(--container-background)}._detail_vtlsh_12 ._container_vtlsh_20{margin:0 .26667rem;border-radius:.26667rem}._detail_vtlsh_12 #musicAndSelection{overflow:initial!important;height:initial!important;max-height:initial!important}\n",document.head.appendChild(c),{setters:[e=>{i=e.d,n=e.g,a=e.n,o=e.bP,r=e.c,s=e.m,d=e.h,l=e.at}],execute:function(){const t="_detail_vtlsh_12",c="_container_vtlsh_20";e("default",i({name:"music-list",setup(){const e=n(),i=a({isLoading:!0,isProductLoading:!1,product:[{state:!1,name:"五线谱",type:o.staff,base64:""},{state:!1,name:"首调",type:o.firstTone,base64:""},{state:!1,name:"固定调",type:o.fixedTone,base64:""}]});r((()=>{window.appName="colexiu",s.xmlUrl=e.xmlUrl,i.isLoading=!1}));const h=async()=>{console.log("渲染完成")};return()=>d("div",{class:t},[d("div",{id:"scrollContainer",class:[c,"hideCursor"]},[!i.isLoading&&d(l,{onRendered:h},null)])])}}))}}}));
+>>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c:dist/js/index-legacy-cfa001ed.js

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/instrument-c9dd3e10.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/instrument-legacy-5ae60624.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/modeView-16c7d7e0.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/modeView-legacy-54057af4.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/orchestra-80468720.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/orchestra-legacy-95d50d5d.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/polyfills-fda21288.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/polyfills-legacy-241ca397.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/report-share-04161b62.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/js/report-share-legacy-276fb9cd.js


+ 19 - 0
dist/orchestra.html

@@ -2,7 +2,11 @@
 <html lang="en">
 <html lang="en">
 
 
 <head>
 <head>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
+=======
+  <script type="module" crossorigin src="./js/polyfills-fda21288.js"></script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 
 
   <meta charset="UTF-8" />
   <meta charset="UTF-8" />
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
@@ -41,6 +45,7 @@
       transition: opacity .3s;
       transition: opacity .3s;
     }
     }
   </style>
   </style>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/orchestra-66a6ea06.js"></script>
   <script type="module" crossorigin src="./js/orchestra-66a6ea06.js"></script>
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-38945c54.js">
   <link rel="modulepreload" crossorigin href="./js/index-38945c54.js">
@@ -48,6 +53,15 @@
   <link rel="modulepreload" crossorigin href="./js/index-a2a34d0e.js">
   <link rel="modulepreload" crossorigin href="./js/index-a2a34d0e.js">
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
+=======
+  <script type="module" crossorigin src="./js/orchestra-80468720.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-84588ddf.js">
+  <link rel="modulepreload" crossorigin href="./js/index-75b08da5.js">
+  <link rel="modulepreload" crossorigin href="./js/index-5320fd21.js">
+  <link rel="modulepreload" crossorigin href="./js/index-5a1d7ebf.js">
+  <link rel="modulepreload" crossorigin href="./js/index-a2b90afd.js">
+  <link rel="stylesheet" href="./css/index-3642c4ba.css">
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
   <link rel="stylesheet" href="./css/index-85f95688.css">
   <link rel="stylesheet" href="./css/index-85f95688.css">
   <link rel="stylesheet" href="./css/orchestra-8bc1a9c0.css">
   <link rel="stylesheet" href="./css/orchestra-8bc1a9c0.css">
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
@@ -70,8 +84,13 @@
   </script>
   </script>
   
   
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+<<<<<<< HEAD
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/orchestra-legacy-a355e148.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/orchestra-legacy-a355e148.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+=======
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-241ca397.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/orchestra-legacy-95d50d5d.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 </body>
 </body>
 
 
 </html>
 </html>

BIN
dist/png/bg2_left_zs-028c8762.png


BIN
dist/png/d11-fd2f4334.png


BIN
dist/png/d7-a84641c8.png


BIN
dist/png/pitchHigh-8f66b326.png


BIN
dist/png/pitchLow-775a2f42.png


BIN
dist/png/r2-dc183ac4.png


BIN
dist/png/r3-b6dcd461.png


+ 17 - 0
dist/report-share.html

@@ -2,7 +2,11 @@
 <html lang="en">
 <html lang="en">
 
 
 <head>
 <head>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
   <script type="module" crossorigin src="./js/polyfills-4f399b55.js"></script>
+=======
+  <script type="module" crossorigin src="./js/polyfills-fda21288.js"></script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 
 
   <meta charset="UTF-8" />
   <meta charset="UTF-8" />
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
@@ -25,11 +29,19 @@
       transition: opacity .3s;
       transition: opacity .3s;
     }
     }
   </style>
   </style>
+<<<<<<< HEAD
   <script type="module" crossorigin src="./js/report-share-4fbb07df.js"></script>
   <script type="module" crossorigin src="./js/report-share-4fbb07df.js"></script>
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/index-067071d7.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="modulepreload" crossorigin href="./js/index-316df9ad.js">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
   <link rel="stylesheet" href="./css/index-11fe3793.css">
+=======
+  <script type="module" crossorigin src="./js/report-share-04161b62.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-84588ddf.js">
+  <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
+  <link rel="modulepreload" crossorigin href="./js/index-a2b90afd.js">
+  <link rel="stylesheet" href="./css/index-3642c4ba.css">
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
   <link rel="stylesheet" href="./css/plyr-ad8ef5ae.css">
   <link rel="stylesheet" href="./css/plyr-ad8ef5ae.css">
   <link rel="stylesheet" href="./css/report-share-0f4c3151.css">
   <link rel="stylesheet" href="./css/report-share-0f4c3151.css">
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
@@ -52,8 +64,13 @@
   </script>
   </script>
   
   
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+<<<<<<< HEAD
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-309efa15.js"></script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/report-share-legacy-ff5fcfcf.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
   <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/report-share-legacy-ff5fcfcf.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+=======
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-241ca397.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/report-share-legacy-276fb9cd.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 </body>
 </body>
 
 
 </html>
 </html>

+ 1 - 1
osmd-extended

@@ -1 +1 @@
-Subproject commit bab1ca04065946e20f10fa1aacdb0c25b533a6f2
+Subproject commit 4282eb7cbebffd4427350db176c3de0f37bf0fc4

+ 4 - 3
src/helpers/calcSpeed.ts

@@ -1,4 +1,5 @@
 import { OpenSheetMusicDisplay, SourceMeasure } from "/osmd-extended/src";
 import { OpenSheetMusicDisplay, SourceMeasure } from "/osmd-extended/src";
+import { onlyVisible } from "/src/helpers/formateMusic";
 
 
 export const noteDuration = {
 export const noteDuration = {
 	"1/2": 2,
 	"1/2": 2,
@@ -113,8 +114,8 @@ export type GradualItem = {
  * @param xml 始终按照第一分谱进行减慢速度的计算
  * @param xml 始终按照第一分谱进行减慢速度的计算
  */
  */
 export const getGradualLengthByXml = (xml: string) => {
 export const getGradualLengthByXml = (xml: string) => {
-	// const firstPartXml = onlyVisible(xml, 0)
-	const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
+	const firstPartXml = onlyVisible(xml, 0)
+	const xmlParse = new DOMParser().parseFromString(firstPartXml, "text/xml");
 	const measures = Array.from(xmlParse.querySelectorAll("measure"));
 	const measures = Array.from(xmlParse.querySelectorAll("measure"));
 	const notes = Array.from(xmlParse.querySelectorAll("note"));
 	const notes = Array.from(xmlParse.querySelectorAll("note"));
 	const words = Array.from(xmlParse.querySelectorAll("words"));
 	const words = Array.from(xmlParse.querySelectorAll("words"));
@@ -164,7 +165,7 @@ export const getGradualLengthByXml = (xml: string) => {
 		textContent: "",
 		textContent: "",
 		type: "metronome",
 		type: "metronome",
 		allDuration: 1,
 		allDuration: 1,
-		leftDuration: 1,
+		leftDuration: 0,
 		measureIndex: measures.length,
 		measureIndex: measures.length,
 	});
 	});
 
 

+ 302 - 15
src/helpers/customMusicScore.ts

@@ -268,6 +268,18 @@ export const limitSingleSvgPageHeight = () => {
 
 
 }
 }
 
 
+const isElementInViewport = (el: any) => {
+    const rect = el.getBoundingClientRect();
+    return (
+        rect.top >= 0 &&
+        rect.left >= 0 &&
+        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
+        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
+    );
+}
+const isNumeric = (str: any) => {
+	return /^\d+$/.test(str);
+  }
 // 谱面优化
 // 谱面优化
 export const resetFormate = () => {
 export const resetFormate = () => {
 	container.value = document.getElementById('scrollContainer')
 	container.value = document.getElementById('scrollContainer')
@@ -296,14 +308,23 @@ export const resetFormate = () => {
 		const paths: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure > .vf-stave path"));
 		const paths: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure > .vf-stave path"));
 		const dotModifiers: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure .vf-stopDot"));
 		const dotModifiers: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure .vf-stopDot"));
 		const staves: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure > .vf-stave"));
 		const staves: SVGAElement[] = Array.from(staffline.querySelectorAll(".vf-measure > .vf-stave"));
+		const numberVfTexts = Array.from((container.value as HTMLElement).querySelectorAll(".vf-text > text")); 
 
 
 		// 获取第一个线谱的y轴坐标
 		// 获取第一个线谱的y轴坐标
 		const firstLinePathY = paths[0]?.getBBox().y || 0
 		const firstLinePathY = paths[0]?.getBBox().y || 0
+		// D.C循环标记没有显示完全修复
 		// 反复标记 和 小节碰撞
 		// 反复标记 和 小节碰撞
-		const repetWord = ["To Coda", "D.S. al Coda", "Coda"];
+		const repetWord = ["To Coda", "D.S. al Coda", "Coda", "D.C."];
 		texts
 		texts
 			.filter((n) => repetWord.includes(n.textContent || ""))
 			.filter((n) => repetWord.includes(n.textContent || ""))
 			.forEach((t) => {
 			.forEach((t) => {
+				// console.log('文本123',t.textContent,'是否在可视区域内',isElementInViewport(t))
+				// D.C循环标记不在可视区域内,需要修复移动其位置信息
+				// if (t.textContent?.includes('D.C')) {
+				// 	if (!isElementInViewport(t)) {
+				// 		t.style.transform = `translateX(-40px)`;
+				// 	}
+				// }
 				vfbeams.forEach((curve) => {
 				vfbeams.forEach((curve) => {
 					const result = collisionDetection(t, curve);
 					const result = collisionDetection(t, curve);
 					const prePath: SVGAElement = t?.previousSibling as unknown as SVGAElement;
 					const prePath: SVGAElement = t?.previousSibling as unknown as SVGAElement;
@@ -430,13 +451,14 @@ export const resetFormate = () => {
 				label.textContent = labelText.replace('#','♯')
 				label.textContent = labelText.replace('#','♯')
 			}
 			}
 		});
 		});
-		dotModifiers.forEach((group: any) => {
-			if (state.musicRenderType === 'fixedTone') {
-				group.setAttribute('transform', 'translate(3,-12)')
-			} else {
-				group.setAttribute('transform', 'translate(3,-7)')
-			}
-		});
+		// numberVfTexts.forEach((label: any) => {
+		// 	const labelText = label.textContent as string
+		// 	if (isNumeric(labelText)) {
+		// 		const _y = Number(label.getAttribute("y"))
+		// 		const endY = firstLinePathY ? firstLinePathY - musicalDistance : _y
+		// 		label.setAttribute("y", endY)
+		// 	}
+		// })
 		const vftextBottom = Array.from(staffline.querySelectorAll(".vf-text > text")).filter((n: any) => n.getBBox().y > stafflineCenter);
 		const vftextBottom = Array.from(staffline.querySelectorAll(".vf-text > text")).filter((n: any) => n.getBBox().y > stafflineCenter);
 		const vflineBottom = Array.from(staffline.querySelectorAll(".vf-line")).filter((n: any) => n.getBBox().y > stafflineCenter);
 		const vflineBottom = Array.from(staffline.querySelectorAll(".vf-line")).filter((n: any) => n.getBBox().y > stafflineCenter);
 		// 去重
 		// 去重
@@ -573,8 +595,8 @@ export const resetFormate = () => {
 		if (!state.isCreateImg && !state.isPreView) {
 		if (!state.isCreateImg && !state.isPreView) {
 			staves.forEach((stave: any,i: number) => {
 			staves.forEach((stave: any,i: number) => {
 				const list = [
 				const list = [
-					Array.from(stave?.getElementsByTagName("text") || []),
 					Array.from(stave?.querySelectorAll(".vf-StaveSection") || []),
 					Array.from(stave?.querySelectorAll(".vf-StaveSection") || []),
+					Array.from(stave?.getElementsByTagName("text") || []),
 					Array.from(stave?.querySelectorAll(".vf-Volta") || []),
 					Array.from(stave?.querySelectorAll(".vf-Volta") || []),
 					Array.from(stave?.querySelectorAll(".vf-clef") || []),
 					Array.from(stave?.querySelectorAll(".vf-clef") || []),
 					Array.from(stave?.querySelectorAll(".vf-keysignature") || []),
 					Array.from(stave?.querySelectorAll(".vf-keysignature") || []),
@@ -591,8 +613,8 @@ export const resetFormate = () => {
 					}
 					}
 				} catch (error) {}
 				} catch (error) {}
 				const bbox = stave?.getBBox() || {};
 				const bbox = stave?.getBBox() || {};
-				const bgColor = state.isEvaluatReport ? '#132D4C' : '#609FCF';
-				const botColor = state.isEvaluatReport ? '#040D1E' : '#2B70A5';
+				const bgColor = state.isEvaluatReport ? '#132D4C' : state.isCbsView ? 'transparent' : '#609FCF';
+				const botColor = state.isEvaluatReport ? '#040D1E' : state.isCbsView ? 'transparent' : '#2B70A5';
 				const rect = `<rect class="vf-custom-bg" x="${bbox.x}" y="${bbox.y}" width="${bbox.width}" height="${bbox.height}" fill=${bgColor} />`
 				const rect = `<rect class="vf-custom-bg" x="${bbox.x}" y="${bbox.y}" width="${bbox.width}" height="${bbox.height}" fill=${bgColor} />`
 				const rectBottom = `<rect class="vf-custom-bot" x="${bbox.x}" y="${bbox.y+bbox.height}" width="${bbox.width}" height="7.5" fill=${botColor} />`
 				const rectBottom = `<rect class="vf-custom-bot" x="${bbox.x}" y="${bbox.y+bbox.height}" width="${bbox.width}" height="7.5" fill=${botColor} />`
 				// const filterDom = `<defs>
 				// const filterDom = `<defs>
@@ -603,10 +625,13 @@ export const resetFormate = () => {
 				const customG = `<g>${rect}${rectBottom}</g>`
 				const customG = `<g>${rect}${rectBottom}</g>`
 				try {
 				try {
 					if (list.length) {
 					if (list.length) {
-						list.forEach((_el: any) => {
+						for(const _el of list) {
+							if (_el?.parentElement?.classList?.contains('vf-StaveSection')) {
+								continue;
+							}
 							stave?.appendChild(_el)
 							stave?.appendChild(_el)
 							_el?.style?.removeProperty("display");
 							_el?.style?.removeProperty("display");
-						});
+						}
 					}
 					}
 				} catch (error) {}
 				} catch (error) {}
 				stave.innerHTML = customG + stave.innerHTML;
 				stave.innerHTML = customG + stave.innerHTML;
@@ -614,10 +639,47 @@ export const resetFormate = () => {
 			state.vfmeasures = state.vfmeasures.concat(vfmeasures);
 			state.vfmeasures = state.vfmeasures.concat(vfmeasures);
 		}
 		}
 
 
+		dotModifiers.forEach((group: any) => {
+			let parent = group?.parentElement; // 获取父元素
+			// 如果需要找更外层的祖先元素,可以一直迭代
+			while (parent && !parent.classList?.contains('vf-measure') && parent.tagName !== 'body' && parent) { // 假设你想找到最外层的 DIV
+				parent = parent.parentElement;
+			}
+			const parentY = parent?.querySelector('.vf-custom-bg')?.getBoundingClientRect()?.y || 0;
+			const dotY = group?.getBoundingClientRect()?.y || 0;
+			const distanceY = parentY - dotY;
+			const translateY = 15 - distanceY;
+			// console.log('距离111',translateY)
+			group.setAttribute('transform', `translate(3,${-translateY})`)
+			// if (state.musicRenderType === 'fixedTone') {
+			// 	// group.setAttribute('transform', 'translate(3,-12)')
+			// } else {
+			// 	// group.setAttribute('transform', 'translate(3,-7)')
+			// }
+		});
+
+		// 修复D.C、D.S等渲染位置不对的问题
+		const repairWord = ["D.S.", "D.C.", "Fine"];
+		[...vfmeasures].forEach((measure: any) => {
+			const needRepairTexts = measure.querySelectorAll('text').length ? Array.from(measure.querySelectorAll('text'))?.filter((item: any) => repairWord.includes(item?.textContent)) : [];
+			if (needRepairTexts.length) {
+				// 该小节结束位置的x坐标
+				const measureCoordinate = measure?.querySelector('.vf-custom-bg')?.getBBox() || null
+				const measureEndX = measureCoordinate ? measureCoordinate?.x + measureCoordinate?.width - 30 : 0;
+				needRepairTexts.forEach((text: any) => {
+					text?.setAttribute('x', measureEndX)
+				})
+			}
+		});
+
 	}
 	}
 	if (!state.isCombineRender && state.isSingleLine) {
 	if (!state.isCombineRender && state.isSingleLine) {
 		transSinglePage();
 		transSinglePage();
 	}
 	}
+	// 多行谱,拍号可能被遮挡,需要移动谱面的位置
+	if (!state.isSingleLine) {
+		transMultiPosition();
+	}
 	// setTimeout(() => this.resetGlobalText());
 	// setTimeout(() => this.resetGlobalText());
 };
 };
 
 
@@ -630,7 +692,10 @@ const transSinglePage = () => {
 			// 需要上移的距离
 			// 需要上移的距离
 			// console.log('need',svgPage.height,staffLine.height)
 			// console.log('need',svgPage.height,staffLine.height)
 			const rate = svgPage.height > 400 ? 1.2 : 2;
 			const rate = svgPage.height > 400 ? 1.2 : 2;
-			const needTransTop = (svgPage.height - staffLine.height) / rate;
+			let needTransTop = (svgPage.height - staffLine.height) / rate;
+			// 给个安全距离
+			const maxTop = staffLine.top - svgPage.top - 40
+			needTransTop = Math.min(maxTop, needTransTop)
 			// @ts-ignore
 			// @ts-ignore
 			document.getElementById('osmdSvgPage1').style.transform = `translateY(-${needTransTop}px)`;
 			document.getElementById('osmdSvgPage1').style.transform = `translateY(-${needTransTop}px)`;
 			// document.querySelector('.staffline').style.transform = `translateY(-${needTransTop}px)`;
 			// document.querySelector('.staffline').style.transform = `translateY(-${needTransTop}px)`;
@@ -641,6 +706,25 @@ const transSinglePage = () => {
 			// document.getElementById('osmdSvgPage1').style.transform = `translateY(${needTransDistance}px)`
 			// document.getElementById('osmdSvgPage1').style.transform = `translateY(${needTransDistance}px)`
 		}
 		}
 	}
 	}
+	if (state.isSimplePage) {
+		const svgPage = document?.getElementById('osmdSvgPage1')?.getBoundingClientRect();
+		const staffLine = document?.querySelector('.staffline')?.getBoundingClientRect();
+		if (svgPage && staffLine) {
+			const needY = svgPage.height - (staffLine.y+staffLine.height) - 10;
+			// @ts-ignore
+			document.getElementById('osmdSvgPage1').style.transform = `translateY(${needY}px)`;
+		}
+	}
+}
+
+const transMultiPosition = () => {
+	const svgPage = document?.getElementById('osmdSvgPage1')?.getBoundingClientRect();
+	const staffLine = document?.querySelector('.staffline')?.getBoundingClientRect();
+	if (svgPage && staffLine && staffLine.y < svgPage.y) {
+		const needY = svgPage.y - staffLine.y + 5;
+		// @ts-ignore
+		document.querySelector('.staffline').style.transform = `translateY(${needY}px)`;
+	}
 }
 }
 
 
 // 技巧文本
 // 技巧文本
@@ -1009,4 +1093,207 @@ export const setCustomNoteRealValue = () => {
     if (["12667", "12673"].includes(detailId)){
     if (["12667", "12673"].includes(detailId)){
         customData.customNoteCurrentTime = true
         customData.customNoteCurrentTime = true
     }
     }
-};
+};
+
+/** 转换简谱的全休止符和二分休止符 */
+export const transferJianNote = (measure: any, divisions: number, preBeats: number, preBeatType: number) => {
+	const multipleXs = preBeatType / 4;
+	const notes = measure.getElementsByTagName("note")
+	for (const note of notes) {
+		// 是否需要考虑带上附点
+		let needAddDot = true;
+		const noteType = note.getElementsByTagName("type")?.[0]?.textContent || '';
+		if ((noteType === 'whole' || noteType === 'half') && note.getElementsByTagName("rest").length) {
+			// 4/4拍,3/4拍
+			if (preBeatType === 4) {
+				let maxNumber = noteType === 'half' ? 2 : preBeats / multipleXs;
+				if (noteType === 'whole') {
+					// 有可能是全休止符,但是该小节又不是整小节都休止,此时这个全休止符不能按照整小节休止来计算
+					const noteDivisions = parseInt(note.getElementsByTagName("duration")[0]?.textContent);
+					if (noteDivisions/divisions !== preBeats) {
+						maxNumber = 4;
+					} else {
+						// 满足了时值,则不需要考虑加上附点
+						needAddDot = false;
+					}
+				}
+				// 如果音符带附点,需要判断处理下
+				if (note.getElementsByTagName("dot").length && needAddDot) {
+					maxNumber = noteType === 'whole' ? maxNumber + 2 : maxNumber + 1;
+				}
+				if (!Number.isInteger(maxNumber)) {
+					return;
+				}
+				// console.log('几个1/4音符',maxNumber)
+				let quarterNoteNumber = 1;
+				while (quarterNoteNumber <= maxNumber) {
+					const newnote = document.createElement('note');
+					newnote.innerHTML = `
+					<rest></rest>
+					<duration>${divisions}</duration>
+					<voice>1</voice>
+					<type>quarter</type>`
+					measure.insertBefore(newnote, note);
+					quarterNoteNumber += 1;
+				};
+				measure.removeChild(note);
+			} else if (preBeats === 3 && preBeatType === 8) {
+				const maxNumber = noteType === 'half' ? 2 : 3;
+				let quarterNoteNumber = 1;
+				while (quarterNoteNumber <= maxNumber) {
+					const newnote = document.createElement('note');
+					newnote.innerHTML = `
+					<rest></rest>
+					<duration>${divisions/2}</duration>
+					<voice>1</voice>
+					<type>eighth</type>`
+					measure.insertBefore(newnote, note);
+					quarterNoteNumber += 1;
+				};
+				measure.removeChild(note);
+			} else if (preBeats === 5 && preBeatType === 8) {
+				if (noteType === 'whole') {
+					const newnote = document.createElement('note');
+					newnote.innerHTML = `
+					<rest></rest>
+					<duration>${divisions+divisions/2}</duration>
+					<voice>1</voice>
+					<type>quarter</type>
+					<dot></dot>`
+					measure.insertBefore(newnote, note);
+					const newnote2 = document.createElement('note');
+					newnote2.innerHTML = `
+					<rest></rest>
+					<duration>${divisions}</duration>
+					<voice>1</voice>
+					<type>quarter</type>`
+					measure.insertBefore(newnote2, note);
+					measure.removeChild(note);
+				} else if (noteType === 'half') {
+					dealDotHalfNote(measure, divisions, note)
+				}
+			} else if (preBeats === 6 && preBeatType === 8) {
+				if (noteType === 'whole') {
+					const maxNumber = 2;
+					let quarterNoteNumber = 1;
+					while (quarterNoteNumber <= maxNumber) {
+						const newnote = document.createElement('note');
+						newnote.innerHTML = `
+						<rest></rest>
+						<duration>${divisions+divisions/2}</duration>
+						<voice>1</voice>
+						<type>quarter</type>
+						<dot></dot>`
+						measure.insertBefore(newnote, note);
+						quarterNoteNumber += 1;
+					};
+					measure.removeChild(note);
+				} else if (noteType === 'half') {
+					dealDotHalfNote(measure, divisions, note)		
+				}
+			} else if (preBeats === 7 && preBeatType === 8) {
+				if (noteType === 'whole') {
+					const newnote2 = document.createElement('note');
+					newnote2.innerHTML = `
+					<rest></rest>
+					<duration>${divisions+divisions/2}</duration>
+					<voice>1</voice>
+					<type>quarter</type>
+					<dot></dot>`
+					measure.insertBefore(newnote2, note);         					
+					const maxNumber = 2;
+					let quarterNoteNumber = 1;
+					while (quarterNoteNumber <= maxNumber) {
+						const newnote = document.createElement('note');
+						newnote.innerHTML = `
+						<rest></rest>
+						<duration>${divisions}</duration>
+						<voice>1</voice>
+						<type>quarter</type>`
+						measure.insertBefore(newnote, note);
+						quarterNoteNumber += 1;
+					};
+					measure.removeChild(note);
+				} else if (noteType === 'half') {
+					dealDotHalfNote(measure, divisions, note)
+				}
+			} else if (preBeats === 9 && preBeatType === 8) {
+				if (noteType === 'whole') {
+					const maxNumber = 3;
+					let quarterNoteNumber = 1;
+					while (quarterNoteNumber <= maxNumber) {
+						const newnote = document.createElement('note');
+						newnote.innerHTML = `
+						<rest></rest>
+						<duration>${divisions+divisions/2}</duration>
+						<voice>1</voice>
+						<type>quarter</type>
+						<dot></dot>`
+						measure.insertBefore(newnote, note);
+						quarterNoteNumber += 1;
+					};
+					measure.removeChild(note);
+				} else if (noteType === 'half') {
+					dealDotHalfNote(measure, divisions, note)
+				}
+			} else if (preBeats === 12 && preBeatType === 8) {
+				if (noteType === 'whole') {
+					const maxNumber = 4;
+					let quarterNoteNumber = 1;
+					while (quarterNoteNumber <= maxNumber) {
+						const newnote = document.createElement('note');
+						newnote.innerHTML = `
+						<rest></rest>
+						<duration>${divisions+divisions/2}</duration>
+						<voice>1</voice>
+						<type>quarter</type>
+						<dot></dot>`
+						measure.insertBefore(newnote, note);
+						quarterNoteNumber += 1;
+					};
+					measure.removeChild(note);
+				} else if (noteType === 'half') {
+					dealDotHalfNote(measure, divisions, note)
+				}
+			}
+		} 
+	}
+}
+
+/** 八几排的小节,二分休止符带附点 */
+const dealDotHalfNote = (measure: any, divisions: number, note: any) => {
+	// 如果音符带附点,需要判断处理下
+	if (note.getElementsByTagName("dot").length) {
+		const maxNumber = 2;
+		let quarterNoteNumber = 1;
+		while (quarterNoteNumber <= maxNumber) {
+			const newnote = document.createElement('note');
+			newnote.innerHTML = `
+			<rest></rest>
+			<duration>${divisions+divisions/2}</duration>
+			<voice>1</voice>
+			<type>quarter</type>
+			<dot></dot>`
+			measure.insertBefore(newnote, note);
+			quarterNoteNumber += 1;
+		};
+		measure.removeChild(note);
+	} else {
+		const newnote = document.createElement('note');
+		newnote.innerHTML = `
+		<rest></rest>
+		<duration>${divisions+divisions/2}</duration>
+		<voice>1</voice>
+		<type>quarter</type>
+		<dot></dot>`
+		measure.insertBefore(newnote, note);
+		const newnote2 = document.createElement('note');
+		newnote2.innerHTML = `
+		<rest></rest>
+		<duration>${divisions/2}</duration>
+		<voice>1</voice>
+		<type>eighth</type>`
+		measure.insertBefore(newnote2, note);
+		measure.removeChild(note);
+	}
+}

+ 199 - 35
src/helpers/formateMusic.ts

@@ -2,6 +2,7 @@ import dayjs from "dayjs";
 import duration from "dayjs/plugin/duration";
 import duration from "dayjs/plugin/duration";
 import state, { customData } from "/src/state";
 import state, { customData } from "/src/state";
 import { browser } from "../utils/index";
 import { browser } from "../utils/index";
+import { transferJianNote } from "/src/helpers/customMusicScore"
 import {
 import {
 	isSpecialMark,
 	isSpecialMark,
 	isSpeedKeyword,
 	isSpeedKeyword,
@@ -616,21 +617,66 @@ export const formatZoom = (num = 1) => {
 	return num * state.zoom;
 	return num * state.zoom;
 };
 };
 
 
+/** 妙极客多分轨的曲子,可能没有part-name标签,需要手动加上该标签 */
+export const xmlAddPartName = (xml: string) => {
+	if (!xml) return "";
+	const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
+	const scoreParts = Array.from(xmlParse.getElementsByTagName("score-part"));
+	for (const scorePart of scoreParts) {
+		if (scorePart.getElementsByTagName("part-name").length === 0) {
+			state.evxmlAddPartName = true;
+			const name = scorePart.getAttribute("id") || "";
+			const newPartName = `<part-name>${name}</part-name>`
+			// scorePart.prepend(newPartName);
+			scorePart.innerHTML = newPartName + scorePart.innerHTML;
+		} 
+		if (scorePart.getElementsByTagName("part-name").length && !scorePart.getElementsByTagName("part-name")?.[0]?.textContent?.trim() ) {
+			scorePart.getElementsByTagName("part-name")[0].textContent = scorePart.getAttribute("id") || "";
+		}
+	}
+	return new XMLSerializer().serializeToString(xmlParse);
+}
+
 /** 格式化曲谱
 /** 格式化曲谱
  * 1.全休止符的小节,没有音符默认加个全休止符
  * 1.全休止符的小节,没有音符默认加个全休止符
  */
  */
 export const formatXML = (xml: string, xmlUrl?: string): string => {
 export const formatXML = (xml: string, xmlUrl?: string): string => {
 	if (!xml) return "";
 	if (!xml) return "";
-	
 	const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
 	const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
 
 
+	// 声调
+	const fifths = xmlParse.getElementsByTagName("fifths");
+	if (fifths && fifths.length) {
+		// 是否是C调
+		state.isCTone = fifths[0].textContent === '0'
+	}
+
+	const endings = Array.from(xmlParse.getElementsByTagName("ending"));
+	for (const ending of endings) {
+		// if (ending.getAttribute('type') === 'stop') {
+		// 	// @ts-ignore
+		// 	ending.parentNode?.removeChild(ending.parentNode?.getElementsByTagName('bar-style')[0])
+		// }
+		// @ts-ignore
+		// ending.parentNode.parentNode?.removeChild(ending.parentNode)
+	}
+
 	const measures = Array.from(xmlParse.getElementsByTagName("measure"));
 	const measures = Array.from(xmlParse.getElementsByTagName("measure"));
 	const minutes: any = xmlParse.getElementsByTagName("per-minute");
 	const minutes: any = xmlParse.getElementsByTagName("per-minute");
 	let speeds: any = []
 	let speeds: any = []
 	for (const minute of minutes) {
 	for (const minute of minutes) {
-		if (minute.textContent && !!Number(minute.textContent)) {
-			speeds.push(Number(minute.textContent))
+		let measureSpeed = minute.textContent ? Number(minute.textContent) : 0;
+		// 速度带附点,需要转换成不带附点的速度值
+		const hasSpeedDot = Array.from(minute?.parentElement?.children || []).some((item: any) => item?.tagName === 'beat-unit-dot')
+		measureSpeed = hasSpeedDot ? measureSpeed + measureSpeed/2 : measureSpeed;
+		if (minute.textContent && measureSpeed) {
+			speeds.push(Number(measureSpeed))
 		}
 		}
+		// if (hasSpeedDot && measureSpeed) {
+		// 	minute.textContent = measureSpeed
+		// 	const dotDom = minute?.parentElement.querySelector('beat-unit-dot')
+		// 	minute?.parentElement?.removeChild(dotDom)
+		// }
 	}
 	}
 	speeds = [...new Set(speeds)]
 	speeds = [...new Set(speeds)]
 	const hasVaryingSpeed = speeds.length > 1 ? true : false
 	const hasVaryingSpeed = speeds.length > 1 ? true : false
@@ -669,6 +715,9 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
 	let speed = -1
 	let speed = -1
 	let beats = -1;
 	let beats = -1;
 	let beatType = -1;
 	let beatType = -1;
+	// 前面小节的拍子
+	let preBeats: number = 4;
+	let preBeatType: number = 4;
 	// 小节中如果没有节点默认为休止符
 	// 小节中如果没有节点默认为休止符
 	for (const measure of measures) {
 	for (const measure of measures) {
 		if (beats === -1 && measure.getElementsByTagName("beats").length) {
 		if (beats === -1 && measure.getElementsByTagName("beats").length) {
@@ -680,6 +729,11 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
 		if (speed === -1 && measure.getElementsByTagName('per-minute').length) {
 		if (speed === -1 && measure.getElementsByTagName('per-minute').length) {
 		  speed = Number(measure.getElementsByTagName('per-minute')[0]?.textContent)
 		  speed = Number(measure.getElementsByTagName('per-minute')[0]?.textContent)
 		}
 		}
+		// 当前小节的拍数
+		const currentBeats = measure.getElementsByTagName("beats").length ? measure.getElementsByTagName("beats")[0]?.textContent : preBeats;
+		const currentBeatType = measure.getElementsByTagName("beat-type").length ? measure.getElementsByTagName("beat-type")[0]?.textContent : preBeatType;
+		preBeats = Number(currentBeats);
+		preBeatType = Number(currentBeatType);
 		const divisions = parseInt(measure.getElementsByTagName("divisions")[0]?.textContent || "256");
 		const divisions = parseInt(measure.getElementsByTagName("divisions")[0]?.textContent || "256");
 		// 如果note节点里面有space节点,并且没有duration节点,代表这是一个空白节点,需要删除
 		// 如果note节点里面有space节点,并且没有duration节点,代表这是一个空白节点,需要删除
 		if (measure.getElementsByTagName("note").length && state.isEvxml) {
 		if (measure.getElementsByTagName("note").length && state.isEvxml) {
@@ -726,11 +780,14 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
           <voice>1</voice>
           <voice>1</voice>
           <type>whole</type>
           <type>whole</type>
         </note>`;
         </note>`;
+		} else if (state.musicRenderType !== 'staff') {
+			transferJianNote(measure, divisions, preBeats, preBeatType)
 		}
 		}
 	}
 	}
 	return new XMLSerializer().serializeToString(xmlParse);
 	return new XMLSerializer().serializeToString(xmlParse);
 };
 };
 
 
+
 /** 获取所有音符的时值,以及格式化音符 */
 /** 获取所有音符的时值,以及格式化音符 */
 export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 	const customNoteRealValue = customData.customNoteRealValue;
 	const customNoteRealValue = customData.customNoteRealValue;
@@ -789,11 +846,12 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 	let multipleRestMeasures = 0;
 	let multipleRestMeasures = 0;
 	let staveNoteIndex = 0;
 	let staveNoteIndex = 0;
 	let staveIndex = 0;
 	let staveIndex = 0;
-	let xmlNoteTime = 0  // xml上面的音符时间
 	let xmlMp3BeatFixTime = 0 // xml上节拍器的时间
 	let xmlMp3BeatFixTime = 0 // xml上节拍器的时间
 
 
 	let preNoteEndTime = 0; // 上一个音符的结束时间
 	let preNoteEndTime = 0; // 上一个音符的结束时间
 
 
+	let preNoteMeasureNumber = 0; // 上一个小节的number值
+
 	const _notes = [] as any[];
 	const _notes = [] as any[];
 	if (state.gradualTimes) {
 	if (state.gradualTimes) {
 		console.log("后台设置的渐慢小节时间", state.gradual, state.gradualTimes);
 		console.log("后台设置的渐慢小节时间", state.gradual, state.gradualTimes);
@@ -805,9 +863,16 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 	let differFrom = 0;
 	let differFrom = 0;
 	// let testIdx = 0;
 	// let testIdx = 0;
 	let repeatIdx = 0; // 循环的次数
 	let repeatIdx = 0; // 循环的次数
+	const firstTrackName = state.canSelectTracks[0] || "";
 	while (!iterator.EndReached) {
 	while (!iterator.EndReached) {
 		// console.log({ ...iterator });
 		// console.log({ ...iterator });
 		/** 多声轨合并显示,当前音符的时值取所有声轨中的最小值 */
 		/** 多声轨合并显示,当前音符的时值取所有声轨中的最小值 */
+		if (state.isCombineRender) {
+			iterator.currentVoiceEntries = iterator.currentVoiceEntries.filter((item: any) => {
+				const trackName = state.isEvxml && state.evxmlAddPartName ? item.parentVoice.parent.IdString || '' : item.parentVoice.parent.Name || '';
+				return trackName === firstTrackName
+			});
+		}
 		let minIndex = 0, elRealValue = 0
 		let minIndex = 0, elRealValue = 0
 		for (let index = 0; index < iterator.currentVoiceEntries.length; index++) {
 		for (let index = 0; index < iterator.currentVoiceEntries.length; index++) {
 			const element = iterator.currentVoiceEntries[index];
 			const element = iterator.currentVoiceEntries[index];
@@ -822,8 +887,10 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			}
 			}
 			elRealValue = element.notes[0].length.realValue
 			elRealValue = element.notes[0].length.realValue
 		}
 		}
+		if (minIndex !== 0 && state.isCombineRender && iterator.currentVoiceEntries[minIndex]) {
+			iterator.currentVoiceEntries[minIndex].Notes[0].NoteToGraphicalNoteObjectId = iterator.currentVoiceEntries?.[0].Notes[0].NoteToGraphicalNoteObjectId;
+		}
 		const voiceEntries = iterator.currentVoiceEntries?.[minIndex] ? [iterator.currentVoiceEntries?.[minIndex]] : [];
 		const voiceEntries = iterator.currentVoiceEntries?.[minIndex] ? [iterator.currentVoiceEntries?.[minIndex]] : [];
-
 		let currentVoiceEntries: any[] = [];
 		let currentVoiceEntries: any[] = [];
 		// 多分轨,当前小节最大音符数量
 		// 多分轨,当前小节最大音符数量
 		let maxNoteNum = 0;
 		let maxNoteNum = 0;
@@ -895,7 +962,8 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			if (state.multitrack > 0 && currentTime > note.length.realValue) {
 			if (state.multitrack > 0 && currentTime > note.length.realValue) {
 				currentTime = note.length.realValue;
 				currentTime = note.length.realValue;
 			}
 			}
-			note.maxNoteNum = maxNoteNum
+			note.maxNoteNum = maxNoteNum;
+			note.trackIndex = minIndex;
 			_notes.push({
 			_notes.push({
 				note,
 				note,
 				iterator: { ...iterator },
 				iterator: { ...iterator },
@@ -976,6 +1044,10 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			}
 			}
 
 
 			activeVerticalMeasureList = [note.sourceMeasure?.verticalMeasureList?.[0]] || [];
 			activeVerticalMeasureList = [note.sourceMeasure?.verticalMeasureList?.[0]] || [];
+			// 某些情况下,合并显示的妙极客曲子,note.sourceMeasure?.verticalMeasureList可能为空数组
+			if (state.isCombineRender && state.isEvxml && note.sourceMeasure?.verticalMeasureList.length === 0) {
+				activeVerticalMeasureList = osmd.GraphicSheet.MeasureList.find((item: any) => item[0]?.MeasureNumber === note.sourceMeasure.MeasureNumberXML) || [];
+			}
 			let currenrtVfVoices = activeVerticalMeasureList[0]?.vfVoices['1'] ? activeVerticalMeasureList[0]?.vfVoices['1'] : activeVerticalMeasureList[0]?.vfVoices['2'] ? activeVerticalMeasureList[0]?.vfVoices['2'] : null;
 			let currenrtVfVoices = activeVerticalMeasureList[0]?.vfVoices['1'] ? activeVerticalMeasureList[0]?.vfVoices['1'] : activeVerticalMeasureList[0]?.vfVoices['2'] ? activeVerticalMeasureList[0]?.vfVoices['2'] : null;
 			/**
 			/**
 			 * TODO:多分轨合并的小节,音符可能没有id,此时就去其它分轨找
 			 * TODO:多分轨合并的小节,音符可能没有id,此时就去其它分轨找
@@ -1113,7 +1185,7 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			// 当前音符的持续时长,当前音符的RealValue值*拍数*(60/后台设置的基准速度)
 			// 当前音符的持续时长,当前音符的RealValue值*拍数*(60/后台设置的基准速度)
 			let noteLength = gradualLength ? gradualLength : Math.min(vRealValue, NoteRealValue) * formatBeatUnit(beatUnit) * (60 / beatSpeed);
 			let noteLength = gradualLength ? gradualLength : Math.min(vRealValue, NoteRealValue) * formatBeatUnit(beatUnit) * (60 / beatSpeed);
 			// 小节时长
 			// 小节时长
-			const measureLength = vRealValue * vDenominator * (60 / beatSpeed);
+			const measureLength = vRealValue * 4 * (60 / beatSpeed);
 			// console.table({value: iterator.currentTimeStamp.realValue, vRealValue,NoteRealValue, noteLength,measureLength, MeasureNumberXML: note.sourceMeasure.MeasureNumberXML})
 			// console.table({value: iterator.currentTimeStamp.realValue, vRealValue,NoteRealValue, noteLength,measureLength, MeasureNumberXML: note.sourceMeasure.MeasureNumberXML})
 			// console.log(i, Math.min(vRealValue, NoteRealValue),noteLength,gradualLength, formatBeatUnit(beatUnit),beatSpeed, NoteRealValue * formatBeatUnit(beatUnit) * (60 / beatSpeed) )
 			// console.log(i, Math.min(vRealValue, NoteRealValue),noteLength,gradualLength, formatBeatUnit(beatUnit),beatSpeed, NoteRealValue * formatBeatUnit(beatUnit) * (60 / beatSpeed) )
 			/**
 			/**
@@ -1194,10 +1266,18 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 				multipleRestMeasures = 0;
 				multipleRestMeasures = 0;
 			}
 			}
 			if (multipleRestMeasures < totalMultipleRestMeasures) {
 			if (multipleRestMeasures < totalMultipleRestMeasures) {
-				multipleRestMeasures++;
+				if (note?.sourceMeasure?.MeasureNumberXML !== preNoteMeasureNumber) {
+					multipleRestMeasures++;
+				} else {
+					multipleRestMeasures = allNotes.length ? allNotes.last().multipleRestMeasures : 0;
+				}
 			} else {
 			} else {
-				multipleRestMeasures = 0;
-				totalMultipleRestMeasures = 0;
+				if (note?.sourceMeasure?.MeasureNumberXML !== preNoteMeasureNumber) {
+					multipleRestMeasures = 0;
+					totalMultipleRestMeasures = 0;
+				} else {
+					multipleRestMeasures = allNotes.length ? allNotes.last().multipleRestMeasures : 0;
+				}
 			}
 			}
 
 
 			// console.log(note.tie)
 			// console.log(note.tie)
@@ -1205,10 +1285,47 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			// console.log('频率',note?.pitch?.frequency,i)
 			// console.log('频率',note?.pitch?.frequency,i)
 			/**
 			/**
 			 * evxml的曲子,如果曲谱xml中带有times信息,则音符时值优先取times中的值
 			 * evxml的曲子,如果曲谱xml中带有times信息,则音符时值优先取times中的值
+			 * 曲子:1795013295024062466(春暖花开),如果音符有times信息,休止符没有times信息,此种规则是认为休止符不参与时值计算的,需要过滤掉该休止符
+			 * TODO:需要考虑唱名怎么处理,唱名是xml有多少个音符,就需要唱多少个,不能剔除
 			 */
 			 */
+			if (state.isEvxml && note.isRestFlag && note?.noteTimeInfo?.length === 0 && state.xmlHasTimes ) {
+				const idx = _notes.findIndex(item=>item.note === note);
+				let nextNoteTimes = _notes[idx+1]?.note?.noteTimeInfo?.[0]?.begin*1000 
+				let preNoteTImes = _notes[idx-1]?.note?.noteTimeInfo?.[0]?.end*1000
+				// 当下一个音符也没有时间的时候,再往下一个找
+				if(!nextNoteTimes && nextNoteTimes!==0){
+					let nextIndex = idx + 2
+					while(!nextNoteTimes && nextIndex<_notes.length){
+						nextNoteTimes = _notes[nextIndex]?.note?.noteTimeInfo?.[0]?.begin*1000
+						nextIndex ++
+					}
+					// 当最后音符就是没有打时间的休止小节,可能nextNoteTimes时间找不到,目前没有处理
+				}
+				if(!preNoteTImes && preNoteTImes!==0){
+					let preIndex = idx - 2
+					while(!preNoteTImes && preIndex>-1){
+						preNoteTImes = _notes[preIndex]?.note?.noteTimeInfo?.[0]?.end*1000
+						preIndex --
+					}
+					// 当没有找到preNoteTImes的时候 赋值为0 (当第一个音符就是没有打时间的休止小节会出现这种情况)
+					preNoteTImes || (preNoteTImes = 0)
+				}
+				const allowRange = Math.abs(nextNoteTimes - preNoteTImes)< 10;
+				if (allowRange) {
+					note.maxNoteNum = note.maxNoteNum - 1;
+					// 唱名时间补齐,当删除这个音符的时候,上个音符的持续时间要加上这个音符的时间
+					allNotes[allNotes.length - 1].noteLengthTime += noteLength
+					continue;
+				}
+			}
 			let evNoteStartTime = 0, evNoteEndTime = 0;
 			let evNoteStartTime = 0, evNoteEndTime = 0;
-			if (state.isEvxml && note?.noteTimeInfo?.length) {
-				const idx = noteIds.filter((item: any) => item === svgElement?.attrs.id)?.length || 0
+			if (state.isEvxml && note?.noteTimeInfo?.length ) {
+				let idx = noteIds.filter((item: any) => item === svgElement?.attrs.id)?.length || 0;
+				// 如果是合并的小节的休止符
+				if (note.isRestFlag && !svgElement && note?.NoteToGraphicalNoteObjectId) {
+					const customRestId = `rest-${note?.sourceMeasure?.MeasureNumberXML}-${note?.NoteToGraphicalNoteObjectId}`;
+					idx = noteIds.filter((item: any) => item === customRestId)?.length || 0;
+				}
 				evNoteStartTime = note?.noteTimeInfo[idx]?.begin
 				evNoteStartTime = note?.noteTimeInfo[idx]?.begin
 				evNoteEndTime = note?.noteTimeInfo[idx]?.end
 				evNoteEndTime = note?.noteTimeInfo[idx]?.end
 				if (evNoteStartTime) {
 				if (evNoteStartTime) {
@@ -1218,6 +1335,10 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 				// usetime = evNoteStartTime - fixtime
 				// usetime = evNoteStartTime - fixtime
 			}
 			}
 			svgElement?.attrs.id && noteIds.push(svgElement?.attrs.id)
 			svgElement?.attrs.id && noteIds.push(svgElement?.attrs.id)
+			// 如果是合并的休止小节,是没有渲染音符的,所以没有svgElement对象,也就没有id,此时需要添加自定义的一个id进度,便于多遍循环时,找到对应的noteTimeInfo里面的时间信息
+			if (note.isRestFlag && !svgElement && note?.NoteToGraphicalNoteObjectId) {
+				noteIds.push(`rest-${note?.sourceMeasure?.MeasureNumberXML}-${note?.NoteToGraphicalNoteObjectId}`)
+			}
 
 
 			// 如果该音符包含倚音,添加标记
 			// 如果该音符包含倚音,添加标记
 			let hasGraceNote = false;
 			let hasGraceNote = false;
@@ -1226,6 +1347,7 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			}
 			}
 			const filterRepeatIdx = allNotes.filter((item: any) => item.noteId === note.NoteToGraphicalNoteObjectId).length
 			const filterRepeatIdx = allNotes.filter((item: any) => item.noteId === note.NoteToGraphicalNoteObjectId).length
 			const nodeDetail = {
 			const nodeDetail = {
+				trackIndex: note.trackIndex, // 当前的音符属于第几条分轨
 				isStaccato: note.voiceEntry.isStaccato(),
 				isStaccato: note.voiceEntry.isStaccato(),
 				isRestFlag: note.isRestFlag,
 				isRestFlag: note.isRestFlag,
 				noteId: note.NoteToGraphicalNoteObjectId,
 				noteId: note.NoteToGraphicalNoteObjectId,
@@ -1274,14 +1396,15 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 				maxNoteNum: note.maxNoteNum, // 当前小节音符最多的分轨的音符数量
 				maxNoteNum: note.maxNoteNum, // 当前小节音符最多的分轨的音符数量
 				// repeatIdx: iterator.repeatIdx || 0, // 标记是第几遍循环,从0开始
 				// repeatIdx: iterator.repeatIdx || 0, // 标记是第几遍循环,从0开始
 				repeatIdx: filterRepeatIdx,
 				repeatIdx: filterRepeatIdx,
-				xmlNoteTime: retain(xmlNoteTime), // xml上音符开始时间 唱名用
-				xmlNoteEndTime: retain(xmlNoteTime + noteLength), //xml上音符结束时间 唱名用
+				noteLengthTime: noteLength, //当前音符时长
+				xmlNoteTime: 0, // xml上音符开始时间 唱名用
+				xmlNoteEndTime: 0, //xml上音符结束时间 唱名用
 				xmlMp3BeatFixTime,  //xml上节拍器的时间
 				xmlMp3BeatFixTime,  //xml上节拍器的时间
 				notBeatFixtime: state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime, // 不含节拍器的fixtime值 唱名用
 				notBeatFixtime: state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime, // 不含节拍器的fixtime值 唱名用
 				notBeatTime: state.isEvxml && evNoteStartTime ? retain(evNoteStartTime) : retain(relativeTime + (state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime)), // 不含节拍器的 音符开始时间
 				notBeatTime: state.isEvxml && evNoteStartTime ? retain(evNoteStartTime) : retain(relativeTime + (state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime)), // 不含节拍器的 音符开始时间
 				notBeatEndTime: state.isEvxml && evNoteEndTime ? retain(evNoteEndTime) : retain(relaEndtime + (state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime)) // 不含节拍器的 音符结束时间
 				notBeatEndTime: state.isEvxml && evNoteEndTime ? retain(evNoteEndTime) : retain(relaEndtime + (state.isOpenMetronome ? fixtime - xmlMp3BeatFixTime : fixtime)) // 不含节拍器的 音符结束时间
 			};
 			};
-			xmlNoteTime += noteLength
+			// console.log(i,'当前的小节',nodeDetail.MeasureNumberXML,totalMultipleRestMeasures,multipleRestMeasures)
 			// 如果是妙极客的曲子,并且第二遍循环播放需要等待时间,并且是第二遍循环的第一个小节的第一个音符
 			// 如果是妙极客的曲子,并且第二遍循环播放需要等待时间,并且是第二遍循环的第一个小节的第一个音符
 			// if (state.isEvxml && state.secondEvXmlBeginTime && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === 1 && nodeDetail.noteId === 0) {
 			// if (state.isEvxml && state.secondEvXmlBeginTime && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === 1 && nodeDetail.noteId === 0) {
 			// 	nodeDetail.time = nodeDetail.time + state.secondEvXmlBeginTime;
 			// 	nodeDetail.time = nodeDetail.time + state.secondEvXmlBeginTime;
@@ -1289,7 +1412,9 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			// 	usetime = usetime + state.secondEvXmlBeginTime;
 			// 	usetime = usetime + state.secondEvXmlBeginTime;
 			// 	relativeTime = relativeTime + state.secondEvXmlBeginTime;
 			// 	relativeTime = relativeTime + state.secondEvXmlBeginTime;
 			// }
 			// }
-			if (state.isEvxml && nodeDetail.repeatIdx && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === 1 && nodeDetail.noteId === 0) {
+			// if (state.isEvxml && nodeDetail.repeatIdx && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === 1 && nodeDetail.noteId === 0) {
+			const firstRepeatNodeId = allNotes.find((item: any) => item.MeasureNumberXML === state.timegapRepeatMeasureIndex)?.noteId || 0;
+			if (state.isEvxml && nodeDetail.repeatIdx && nodeDetail.i > 0 && nodeDetail.MeasureNumberXML === state.timegapRepeatMeasureIndex && nodeDetail.noteId === firstRepeatNodeId) {
 				const currentWaitTime = state.evXmlBeginArr[nodeDetail.repeatIdx] || 0;
 				const currentWaitTime = state.evXmlBeginArr[nodeDetail.repeatIdx] || 0;
 				nodeDetail.time = nodeDetail.time + currentWaitTime;
 				nodeDetail.time = nodeDetail.time + currentWaitTime;
 				nodeDetail.endtime = nodeDetail.endtime + currentWaitTime;
 				nodeDetail.endtime = nodeDetail.endtime + currentWaitTime;
@@ -1306,11 +1431,22 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			// console.log('👀看看endtime', nodeDetail.duration, relaEndtime, fixtime, i)
 			// console.log('👀看看endtime', nodeDetail.duration, relaEndtime, fixtime, i)
 			// console.log('音符时间',nodeDetail.i,nodeDetail.time,nodeDetail.endtime)
 			// console.log('音符时间',nodeDetail.i,nodeDetail.time,nodeDetail.endtime)
 			tickables = tickables.filter((tickable: any) => tickable.attrs?.type !== "GhostNote")
 			tickables = tickables.filter((tickable: any) => tickable.attrs?.type !== "GhostNote")
-			const maxNum = (state.isCombineRender && note.maxNoteNum) ? note.maxNoteNum : tickables.length;
+			let maxNum = (state.isCombineRender && note.maxNoteNum) ? note.maxNoteNum : tickables.length;
+			// 妙极客的曲子,一个休止小节内可能有多个休止符,此时maxNum是0,需要针对这种情况作处理
+			if (note.isRestFlag && maxNum === 0) {
+				maxNum = note.maxNoteNum;
+			}
 			nodeDetail.noteLength = maxNum || 1;
 			nodeDetail.noteLength = maxNum || 1;
 			allNotes.push(nodeDetail);
 			allNotes.push(nodeDetail);
 			allNoteId.push(nodeDetail.id);
 			allNoteId.push(nodeDetail.id);
-			measures.push(nodeDetail);
+
+			if ( measures.some((item: any) => item.MeasureNumberXML !== nodeDetail.MeasureNumberXML) ) {
+				measures = [];
+				measures.push(nodeDetail);
+				nodeDetail.measures = measures;
+			} else {
+				measures.push(nodeDetail);
+			}
 			/**
 			/**
 			 * bug: #9877
 			 * bug: #9877
 			 * 多分轨合并展示的曲子,不同分轨,同一小节音符的数量可能不能,不能只通过tickables的长度判断该小节的音符数量
 			 * 多分轨合并展示的曲子,不同分轨,同一小节音符的数量可能不能,不能只通过tickables的长度判断该小节的音符数量
@@ -1324,12 +1460,21 @@ export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 			}
 			}
 			preNoteEndTime = nodeDetail.endtime;
 			preNoteEndTime = nodeDetail.endtime;
 		}
 		}
+		preNoteMeasureNumber = note?.sourceMeasure?.MeasureNumberXML;
 		i++;
 		i++;
 	}
 	}
 	// 按照时间轴排序
 	// 按照时间轴排序
 	const sortArray = allNotes.sort((a, b) => a.relativeTime - b.relativeTime).map((item, index) => Object.assign(item,{i:index}));
 	const sortArray = allNotes.sort((a, b) => a.relativeTime - b.relativeTime).map((item, index) => Object.assign(item,{i:index}));
 	// const sortArray = allNotes.sort((a, b) => a.time - b.time).map((item, index) => ({ ...item, i: index }));
 	// const sortArray = allNotes.sort((a, b) => a.time - b.time).map((item, index) => ({ ...item, i: index }));
 	// const sortArray = allNotes.map((item, index) => ({ ...item, i: index }));
 	// const sortArray = allNotes.map((item, index) => ({ ...item, i: index }));
+	// 给 xmlNoteTime 和 xmlNoteEndTime 赋值
+	let xmlNoteTime = 0
+	sortArray.map(item => {
+		const noteLengthTime = item.noteLengthTime
+		item.xmlNoteTime = retain(xmlNoteTime)
+		item.xmlNoteEndTime = retain(xmlNoteTime + noteLengthTime)
+		xmlNoteTime += noteLengthTime
+	})
 	console.timeEnd("音符跑完时间");
 	console.timeEnd("音符跑完时间");
 	try {
 	try {
 		osmd.cursor.reset();
 		osmd.cursor.reset();
@@ -1435,16 +1580,19 @@ const customizationXml = (xmlParse: any) => {
 	const measures: any[] = Array.from(xmlParse.getElementsByTagName("measure"));
 	const measures: any[] = Array.from(xmlParse.getElementsByTagName("measure"));
 	const notes: any[] = Array.from(xmlParse.getElementsByTagName("note"));
 	const notes: any[] = Array.from(xmlParse.getElementsByTagName("note"));
 
 
-	// 获取音符最多的歌词数,用于自定义循环播放次数
-	let maxLyricNum = 0;
+	// 获取音符最多的歌词数,time最多的次数,取两者的最大值,用于自定义循环播放次数
+	let maxLyricNum = 0, maxTimeNum = 0;
 	if (notes && notes.length) {
 	if (notes && notes.length) {
 		for (const note of notes) {
 		for (const note of notes) {
 			if (maxLyricNum < note.getElementsByTagName("lyric").length) {
 			if (maxLyricNum < note.getElementsByTagName("lyric").length) {
 				maxLyricNum = note.getElementsByTagName("lyric").length
 				maxLyricNum = note.getElementsByTagName("lyric").length
 			}
 			}
+			if (maxTimeNum < note.getElementsByTagName("time").length) {
+				maxTimeNum = note.getElementsByTagName("time").length
+			}
 		}
 		}
 	}
 	}
-	state.maxLyricNum = maxLyricNum;
+	state.maxLyricNum = Math.max(maxLyricNum, maxTimeNum);
 	// state.osmd.EngravingRules.DYCustomRepeatCount = maxLyricNum;
 	// state.osmd.EngravingRules.DYCustomRepeatCount = maxLyricNum;
 	;(window as any).DYCustomRepeatCount = state.maxLyricNum;
 	;(window as any).DYCustomRepeatCount = state.maxLyricNum;
 	console.log('歌词次数',maxLyricNum)
 	console.log('歌词次数',maxLyricNum)
@@ -1489,20 +1637,26 @@ const customizationXml = (xmlParse: any) => {
 	 * 妙极客xml,多遍歌词循环的曲目,如果没有repeat标签,需要加上repeat标签
 	 * 妙极客xml,多遍歌词循环的曲目,如果没有repeat标签,需要加上repeat标签
 	 * */
 	 * */
 	if (maxLyricNum > 1) {
 	if (maxLyricNum > 1) {
-		const hasRepeat = xmlParse.querySelectorAll('repeat').length > 0
+		const hasRepeat = xmlParse.querySelectorAll('repeat').length > 0;
 		if (!hasRepeat) {
 		if (!hasRepeat) {
-			const lastMeasure = measures.last();
-			if (lastMeasure.getElementsByTagName('barline').length) {
-				const barlineDom = lastMeasure.getElementsByTagName('barline')[0]
-				barlineDom.innerHTML = barlineDom.innerHTML + `<repeat direction="backward" />`;
-			} else {
-				lastMeasure.innerHTML = lastMeasure.innerHTML + `
-				<barline location="right">
-					<bar-style>light-heavy</bar-style>
-					<repeat direction="backward" />
-				</barline>`
+			const parts = xmlParse.querySelectorAll('score-partwise>part')
+			if (parts.length) {
+				for (const part of parts) {
+					const currentMeasures = part.querySelectorAll('measure').length ? Array.from(part.querySelectorAll('measure')) : [];
+					const lastMeasure: any = currentMeasures.last();
+					if (lastMeasure?.getElementsByTagName('barline').length) {
+						const barlineDom = lastMeasure?.getElementsByTagName('barline')[0]
+						barlineDom.innerHTML = barlineDom.innerHTML + `<repeat direction="backward" />`;
+					} else {
+						lastMeasure.innerHTML = lastMeasure.innerHTML + `
+						<barline location="right">
+							<bar-style>light-heavy</bar-style>
+							<repeat direction="backward" />
+						</barline>`
+					}
+					// console.log(lastMeasure)
+				}
 			}
 			}
-			// console.log(lastMeasure)
 		}
 		}
 	}
 	}
 }
 }
@@ -1515,16 +1669,26 @@ const analyzeEvxml = (xmlParse: any, xmlUrl?: string) => {
 	const xmlNum2 = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[1]?.getAttribute('num');
 	const xmlNum2 = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[1]?.getAttribute('num');
 	const denNum2 = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[1]?.getAttribute('den');
 	const denNum2 = xmlParse.getElementsByTagName("timegap")[0]?.getElementsByTagName("values")[0]?.getElementsByTagName("item")[1]?.getAttribute('den');
 	const timeGaps: any = xmlParse.getElementsByTagName("timegap")?.length ? Array.from(xmlParse.getElementsByTagName("timegap")?.[0]?.getElementsByTagName("values")?.[0]?.getElementsByTagName("item")) : [];
 	const timeGaps: any = xmlParse.getElementsByTagName("timegap")?.length ? Array.from(xmlParse.getElementsByTagName("timegap")?.[0]?.getElementsByTagName("values")?.[0]?.getElementsByTagName("item")) : [];
+	state.xmlHasTimes = !!xmlParse.getElementsByTagName("times")?.length
 	// 第一个音符的起始时间
 	// 第一个音符的起始时间
 	const firstMeasure = xmlParse.getElementsByTagName("measure")[0];
 	const firstMeasure = xmlParse.getElementsByTagName("measure")[0];
 	if (firstMeasure) {
 	if (firstMeasure) {
 		const firstNoteBeginTime = firstMeasure.getElementsByTagName("times")[0]?.getElementsByTagName("time")[0]?.getAttribute('begin');
 		const firstNoteBeginTime = firstMeasure.getElementsByTagName("times")[0]?.getElementsByTagName("time")[0]?.getAttribute('begin');
 		state.evXmlBeginTime = firstNoteBeginTime ? firstNoteBeginTime / 1000 : xmlNum ? 60 / state.originSpeed * xmlNum * 4/denNum : 0;
 		state.evXmlBeginTime = firstNoteBeginTime ? firstNoteBeginTime / 1000 : xmlNum ? 60 / state.originSpeed * xmlNum * 4/denNum : 0;
 		state.secondEvXmlBeginTime = firstNoteBeginTime ? 0 : xmlNum2 ? 60 / state.originSpeed * xmlNum2 * 4/denNum2 : 0;
 		state.secondEvXmlBeginTime = firstNoteBeginTime ? 0 : xmlNum2 ? 60 / state.originSpeed * xmlNum2 * 4/denNum2 : 0;
-		const hasTimeGap = xmlParse.getElementsByTagName("timegap").length > 0;
+		const hasTimeGap = state.xmlHasTimeGap = xmlParse.getElementsByTagName("timegap").length > 0;
 		const hasTimes = xmlParse.getElementsByTagName("times").length > 0;
 		const hasTimes = xmlParse.getElementsByTagName("times").length > 0;
-
 		if (timeGaps && timeGaps.length && !firstNoteBeginTime) {
 		if (timeGaps && timeGaps.length && !firstNoteBeginTime) {
+			// 有timegap的曲子,需要找到是从哪一小节开始循环的,默认是从第一节开始循环
+			const startRepeat = Array.from(xmlParse.getElementsByTagName("repeat") || []).filter((item: any) => item?.getAttribute('direction') === 'forward')
+			const firstRepeat: any = startRepeat?.length ? startRepeat[0] : null;
+			if (firstRepeat) {
+				let parentElement = firstRepeat?.parentNode
+				while (parentElement && parentElement.tagName !== 'measure') {
+					parentElement = parentElement.parentNode
+				}
+				state.timegapRepeatMeasureIndex = parentElement?.getAttribute('number') ? Number(parentElement?.getAttribute('number')) : 1;
+			}
 			for (const timeGap of timeGaps) {
 			for (const timeGap of timeGaps) {
 				const num: any = timeGap?.getAttribute('num'), den: any = timeGap?.getAttribute('den');
 				const num: any = timeGap?.getAttribute('num'), den: any = timeGap?.getAttribute('den');
 				const startTime = num ? 60 / state.originSpeed * num * 4/den : 0;
 				const startTime = num ? 60 / state.originSpeed * num * 4/den : 0;

+ 13 - 7
src/helpers/metronome.ts

@@ -186,16 +186,16 @@ class Metronome {
 			if(state.playType === "play" && state.playSource === "music" && audioDataState.songCollection.beatSongEle){
 			if(state.playType === "play" && state.playSource === "music" && audioDataState.songCollection.beatSongEle){
 				return
 				return
 			}			
 			}			
-			if(state.playType === "play" && state.playSource === "background" && audioDataState.songCollection.betaBackgroundEle){
+			if(state.playType === "play" && state.playSource === "background" && audioDataState.songCollection.beatBackgroundEle){
 				return
 				return
 			}			
 			}			
-			if(state.playType === "sing" && state.playSource === "music" && audioDataState.songCollection.betaFanSongEle){
+			if(state.playType === "sing" && state.playSource === "music" && audioDataState.songCollection.beatFanSongEle){
 				return
 				return
 			}			
 			}			
-			if(state.playType === "sing" && state.playSource === "background" && audioDataState.songCollection.betaBanSongEle){
+			if(state.playType === "sing" && state.playSource === "background" && audioDataState.songCollection.beatBanSongEle){
 				return
 				return
 			}			
 			}			
-			if(state.playType === "sing" && state.playSource === "mingSong" && audioDataState.songCollection.betaMingSongEle){
+			if(state.playType === "sing" && state.playSource === "mingSong" && audioDataState.songCollection.beatMingSongEle){
 				return
 				return
 			}			
 			}			
 		}
 		}
@@ -286,10 +286,9 @@ class Metronome {
 			const measureListIndex = note?.noteElement?.sourceMeasure?.measureListIndex;
 			const measureListIndex = note?.noteElement?.sourceMeasure?.measureListIndex;
 			if (measureNumberXML > -1) {
 			if (measureNumberXML > -1) {
 				if (measureNumberXML != xmlNumber) {
 				if (measureNumberXML != xmlNumber) {
-					// 弱起的时候 根据音符结尾时间减去音符开头时间,得到的不是正常小节的时间,然后平均分配节拍之后,当前节拍间隔会非常短 这里弱起拿正常
-					// 妙极客的弱起不受这个影响
+					// 弱起的时候 根据音符结尾时间减去音符开头时间,得到的不是正常小节的时间,然后平均分配节拍之后,当前节拍间隔会非常短 这里弱起取整个小节的时间
 					let startTime = note.measures[0].time
 					let startTime = note.measures[0].time
-					if(!state.isEvxml && i === 0){
+					if(i === 0 && note.measures[0].difftime>0){
 						startTime = note.measures[note.measures.length - 1].endtime - note.measures[0].measureLength
 						startTime = note.measures[note.measures.length - 1].endtime - note.measures[0].measureLength
 					}
 					}
 					const m = {
 					const m = {
@@ -356,6 +355,13 @@ class Metronome {
 
 
 		let metroList: number[] = [];
 		let metroList: number[] = [];
 		const metroMeasure: any[] = [];
 		const metroMeasure: any[] = [];
+		console.log("节拍器 每一小节时间:", measures)
+		console.log("节拍器 间隔:", measures.map(item => {
+			return {
+				time: item.time,
+				measureNumberXML: item.measureNumberXML
+			}
+		}))
 		// 4.按照拍数将时长平均分配
 		// 4.按照拍数将时长平均分配
 		try {
 		try {
 			for (let i = 0; i < measures.length; i++) {
 			for (let i = 0; i < measures.length; i++) {

+ 26 - 13
src/page-instrument/App.tsx

@@ -55,7 +55,7 @@ export default defineComponent({
         setToken(query.Authorization);
         setToken(query.Authorization);
       }
       }
       if (window.location.href.includes("simple-detail")) {
       if (window.location.href.includes("simple-detail")) {
-        // 
+        //
       } else {
       } else {
         if (!getToken()) {
         if (!getToken()) {
           const res = await api_getToken();
           const res = await api_getToken();
@@ -98,19 +98,32 @@ export default defineComponent({
       const _loading = document.getElementById("loading");
       const _loading = document.getElementById("loading");
       _loading && document.body.removeChild(_loading);
       _loading && document.body.removeChild(_loading);
       // console.log(query);
       // console.log(query);
-      if (query.platform == "pc") document.body.addEventListener("keyup", (e: KeyboardEvent) => onKeyBoard(e));
-
-      // 禁用右键菜单
-      document.addEventListener("contextmenu", function (event) {
-        // event.preventDefault();
-      });
-      // 禁用浏览器快捷键
-      document.addEventListener("keydown", function (event) {
-        // 屏蔽 F12 和 Ctrl+Shift+I
-        if (event.key === "F12" || (event.ctrlKey && event.shiftKey && event.key === "I") || (event.metaKey && event.altKey && event.key === "I")) {
+      if (query.platform == "pc" || query.isPreView) {
+        document.body.addEventListener("keyup", (e: KeyboardEvent) => onKeyBoard(e));
+        // 禁用右键菜单
+        document.addEventListener("contextmenu", function (event) {
           event.preventDefault();
           event.preventDefault();
-        }
-      });
+        });
+        // 禁用浏览器快捷键
+        document.addEventListener("keydown", function (event) {
+          // 屏蔽 F12 和 Ctrl+Shift+I
+          if (event.key === "F12" || (event.ctrlKey && event.shiftKey && event.key === "I") || (event.metaKey && event.altKey && event.key === "I")) {
+            event.preventDefault();
+          }
+        });
+      }
+
+      // // 禁用右键菜单
+      // document.addEventListener("contextmenu", function (event) {
+      //   // event.preventDefault();
+      // });
+      // // 禁用浏览器快捷键
+      // document.addEventListener("keydown", function (event) {
+      //   // 屏蔽 F12 和 Ctrl+Shift+I
+      //   if (event.key === "F12" || (event.ctrlKey && event.shiftKey && event.key === "I") || (event.metaKey && event.altKey && event.key === "I")) {
+      //     event.preventDefault();
+      //   }
+      // });
     });
     });
 
 
     onUnmounted(() => {
     onUnmounted(() => {

+ 9 - 0
src/page-instrument/api.ts

@@ -64,6 +64,15 @@ export const api_musicSheetPage = (data: any) => {
   });
   });
 };
 };
 
 
+/** 获取教程和年级  */
+export const api_musicTagTree = () => {
+  return request.get("/musicTag/tree");
+};
+/** 获取标签  */
+export const api_musicSheetTag = () => {
+  return request.get("/musicSheetTag/queryList");
+};
+
 /**
 /**
  * 获取声部列表
  * 获取声部列表
  */
  */

+ 9 - 1
src/page-instrument/component/authorName/index.module.less

@@ -1,5 +1,5 @@
 .authorName{
 .authorName{
-    height: 1.8rem;
+    height: 1.8rem; // 与smoothAnimationBox高度对应
 }
 }
 .title{
 .title{
     width: 280px;
     width: 280px;
@@ -38,4 +38,12 @@
             }
             }
         }
         }
     }
     }
+}
+
+.blackTitle {
+    :global{
+        .van-notice-bar{
+            color: #000 !important;
+        }
+    }
 }
 }

+ 2 - 2
src/page-instrument/component/authorName/index.tsx

@@ -17,11 +17,11 @@ export default defineComponent({
             {
             {
                !smoothAnimationState.isShow.value && !state.isCombineRender && 
                !smoothAnimationState.isShow.value && !state.isCombineRender && 
                <div class={["authorName", styles.authorName]}>
                <div class={["authorName", styles.authorName]}>
-                  <div class={styles.title}>
+                  <div class={[styles.title, state.isCbsView && styles.blackTitle]}>
                      <NoticeBar text={state.examSongName} background="none" />
                      <NoticeBar text={state.examSongName} background="none" />
                   </div>
                   </div>
                   <div class={styles.authorCon}>
                   <div class={styles.authorCon}>
-                     <div class={styles.author}>
+                     <div class={[styles.author, state.isCbsView && styles.blackTitle]}>
                         {
                         {
                            state.isSingleLine ? 
                            state.isSingleLine ? 
                            <>
                            <>

+ 282 - 0
src/page-instrument/component/the-music-list/filterList.tsx

@@ -0,0 +1,282 @@
+import { defineComponent, PropType, computed, ref, nextTick, reactive } from "vue";
+import { api_musicTagTree, api_musicSheetTag, api_subjectList } from "../../api";
+import { Popover } from "vant"
+import styles from "./index.module.less";
+import headImg from "./imgs/headImg.png"
+import quedingImg from "./imgs/queding.png"
+import quxiaoImg from "./imgs/quxiao.png"
+import zhankaiImg from "./imgs/zhankai.png"
+import shouqiImg from "./imgs/shouqi.png"
+import sjImg from "./imgs/sj.png"
+import closeImg from "../../header-top/image/closeImg.png"
+import state, { IPlatform } from "/src/state";
+import { getQuery } from "/src/utils/queryString";
+
+export default defineComponent({
+	name: "filterList",
+    emits: ["close", "handleConfirm"],
+	setup(props, { emit }) {
+        const query: any = getQuery();
+        const queryObj = reactive({
+            audioPlayTypes:"",
+            sheetTag:"",
+            course:"",
+            grade:"",
+            subject: {
+                name: "",
+                id: ""
+            }
+        })
+        function handleRefresh(){
+            queryObj.audioPlayTypes = ""
+            queryObj.sheetTag = ""
+            queryObj.course = ""
+            queryObj.grade = ""
+            queryObj.subject = {
+                name: "",
+                id: ""
+            }
+            handleSubjectOne()
+        }
+        function handleConfirm() {
+            emit("handleConfirm",{
+                audioPlayTypes:  queryObj.audioPlayTypes ? queryObj.audioPlayTypes.split(",") : [],
+                musicTutorialIds: queryObj.grade ? queryObj.grade : queryObj.course,
+                musicTagIds: queryObj.sheetTag,
+                musicalInstrumentId: queryObj.subject.id
+            })
+        }
+        // 场景
+        const audioPlayTypesOption = [
+            { text: '全部', value: "" },
+            { text: '演奏', value: "PLAY" },
+            { text: '演唱', value: "SING" },
+            { text: '演奏+演唱', value: "PLAY,SING" },
+        ]
+        function handleSelAudioPlayTypes(item:any){
+            queryObj.audioPlayTypes = item.value
+        }
+        // 获取标签
+        getMusicSheetTag()
+        const sheetTagObj = ref<any[]>([])
+        function getMusicSheetTag(){
+            api_musicSheetTag().then(res=>{
+                if(res.code === 200){
+                    sheetTagObj.value = [{ name:"全部",id:""},...res.data]
+                }
+            })
+        }
+        function handleSelSheetTag(item:any){
+            queryObj.sheetTag = item.id
+        }
+        // 获取教程和年级
+        getMusicTagTree()
+        const courseObj = ref<any[]>([])
+        const gradeObj = ref<any[]>([])
+        function getMusicTagTree(){
+            api_musicTagTree().then(res=>{
+                if(res.code === 200){
+                    courseObj.value = [{ name:"全部",id:""},...res.data]
+                }
+            })
+        }
+        const isExpand = ref(false)
+        const computedCourseObj = computed(()=>{
+            return isExpand.value ? courseObj.value : courseObj.value.slice(0,5)
+        })
+        const courseDom = ref<HTMLDivElement>()
+        const borderBoxConDom = ref<HTMLDivElement>()
+        function handleExpand(){
+            isExpand.value = true
+            nextTick(()=>{
+                const childRect = courseDom.value!.getBoundingClientRect();
+                const parentRect = borderBoxConDom.value!.getBoundingClientRect();
+                const offsetTop = borderBoxConDom.value!.scrollTop + childRect.top - parentRect.top
+                borderBoxConDom.value!.scrollTo({
+                    top: offsetTop,
+                    behavior: 'smooth'
+                });
+            })
+        }
+        function handleSelCourse(item:any){
+            queryObj.course = item.id
+            queryObj.grade = ""
+            gradeObj.value = [{ name:"全部", id:""}, ...(item.children || [])]
+        }
+        function handleSelGrade(item:any){
+            queryObj.grade = item.id
+        }
+        // 获取乐器 
+        state.platform === IPlatform.PC && getSubjectList() // 老师端才加载乐器
+        const subjectList = ref<any[]>([])
+        function getSubjectList(){
+            api_subjectList({}).then(res => {
+                if(res.code === 200){
+                    subjectList.value = [...res.data.map((item:any)=>{
+                        return item.instruments.length > 1 ? Object.assign(item,{ isExpand: ref(false) }) : item
+                    })]
+                    // 赋默认值
+                    handleSubjectOne()
+                }
+            })
+        }
+        function handleSubjectOne(){
+            if(subjectList.value.length > 0){
+                const instruments = subjectList.value.reduce((arr, item) => {
+                    arr.push(...item.instruments)
+                    return arr
+                }, [])
+                const instrumentId = query.instrumentId
+                // 有id 就用id,没有就默认第一个
+                const instrumentObj = instrumentId ? instruments.find((i: any) => {
+                    return i.id === instrumentId
+                }) : instruments[0]
+                if(instrumentObj){
+                    queryObj.subject.id = instrumentObj.id
+                    queryObj.subject.name = instrumentObj.name
+                }
+            }
+        }
+        function isActiveSubjectPop(item:any) {
+            return item.instruments.some((i:any) => {
+                return i.id === queryObj.subject.id
+            })
+        }
+        function handleSelectPop(item: any) {
+            queryObj.subject.id = item.id
+            queryObj.subject.name = item.name
+        }
+		return () => (
+			<div class={[styles.filterList, styles[state.modeType], state.platform === IPlatform.PC && styles.isPc]}>
+                <div class={[styles.head, "top_draging"]}>
+                    <img class={styles.headTit} src={headImg} />
+				</div>
+                <img class={styles.closeImg} src={closeImg} onClick={()=>{ emit("close") }} />
+				<div class={styles.borderCon}>
+                    <div class={styles.borderBox}>
+                        <div ref={borderBoxConDom} class={styles.borderBoxCon}>
+                            {
+                                sheetTagObj.value.length > 1 &&
+                                    <>
+                                        <div class={styles.titCon}>
+                                            标签
+                                        </div>
+                                        <div class={styles.filterCon}>
+                                            {
+                                                sheetTagObj.value.map(item => {
+                                                    return <div class={[styles.tabBox, queryObj.sheetTag === item.id && styles.tabActive]} onClick={() => { handleSelSheetTag(item) }}>{item.name}</div>
+                                                })
+                                            }
+                                        </div>  
+                                    </>
+                            }                      
+                            <div class={styles.titCon}>
+                                场景
+                            </div>
+                            <div class={styles.filterCon}>
+                                {
+                                    audioPlayTypesOption.map(item => {
+                                        return <div class={[styles.tabBox, queryObj.audioPlayTypes === item.value && styles.tabActive]} onClick={() => { handleSelAudioPlayTypes(item) }}>{item.text}</div>
+                                    })
+                                }
+                            </div>
+                            {
+                                courseObj.value.length>1 &&
+                                    <>
+                                        <div ref={courseDom} class={styles.titCon}>
+                                            教程
+                                            {
+                                                isExpand.value &&                          
+                                                    <div class={styles.shouqiImg} onClick={() => {isExpand.value = false}}>
+                                                        收起
+                                                        <img src={shouqiImg} />
+                                                    </div>
+                                            }
+                                        </div>
+                                        <div class={[styles.filterCon, styles.courseType]}>
+                                            {
+                                                computedCourseObj.value.map(item => {
+                                                    return <div class={[styles.tabBox, queryObj.course === item.id && styles.tabActive]} onClick={() => { handleSelCourse(item) }}>{item.name}</div>
+                                                })
+                                            }
+                                            {
+                                                !isExpand.value && 
+                                                    <div class={[styles.tabBox, styles.zhankaiImg]} onClick={handleExpand}>
+                                                        查看更多
+                                                        <img src={zhankaiImg} />
+                                                    </div>
+                                            }
+                                        </div> 
+                                    </>
+                            }
+                            {
+                                gradeObj.value.length > 1 &&
+                                    <>
+                                        <div class={styles.titCon}>
+                                            年级
+                                        </div>
+                                        <div class={styles.filterCon}>
+                                            {
+                                                gradeObj.value.map(item => {
+                                                    return <div class={[styles.tabBox, queryObj.grade === item.id && styles.tabActive]} onClick={() => { handleSelGrade(item) }}>{item.name}</div>
+                                                })
+                                            }
+                                        </div>  
+                                    </>
+                            }   
+                            {
+                                subjectList.value.length>1 && queryObj.audioPlayTypes!=='SING' &&
+                                    <>
+                                        <div class={styles.titCon}>
+                                            乐器
+                                        </div>
+                                        <div class={styles.filterCon}>
+                                            {
+                                                subjectList.value.map(item => {
+                                                    return item.instruments.length > 1 ? 
+                                                        <Popover
+                                                            v-model:show={item.isExpand}
+                                                            trigger="click"
+                                                            class={styles.subjectPopover}
+                                                        >
+                                                            {{
+                                                                default: () => (
+                                                                    <div class={styles.tabPopoverBox}>
+                                                                        {
+                                                                            item.instruments.map((row: any) => {
+                                                                                return <div class={[styles.tabPopover, queryObj.subject.id === row.id && styles.active]} onClick={() => { 
+                                                                                    item.isExpand = false
+                                                                                    handleSelectPop(row) 
+                                                                                }}>{row.name}</div>
+                                                                            })
+                                                                        }
+                                                                    </div>
+                                                                ),                                                                
+                                                                reference: () => (
+                                                                    <div class={[styles.tabBox, styles.tabBoxPopCon, isActiveSubjectPop(item) && styles.tabActive]}>
+                                                                        <div class={[styles.tabBoxPop, item.isExpand && styles.actTabBoxPop]}>
+                                                                            <div>{isActiveSubjectPop(item)?queryObj.subject.name:item.name}</div>
+                                                                            <img class={styles.sjImg} src={sjImg} />
+                                                                        </div>
+                                                                    </div>
+                                                                )
+                                                            }}
+                                                        </Popover> 
+                                                        : 
+                                                        <div class={[styles.tabBox, queryObj.subject.id === item.instruments[0].id && styles.tabActive]} onClick={() => { handleSelectPop(item.instruments[0]) }}>{item.name}</div>
+                                                })
+                                            }
+                                        </div>   
+                                    </>
+                            }
+                        </div>
+                    </div>
+				</div>
+                <div class={styles.btnCon}>
+                    <img src={quxiaoImg} onClick={handleRefresh} />
+                    <img src={quedingImg} onClick={handleConfirm} />
+                </div>
+			</div>
+		);
+	},
+});

BIN
src/page-instrument/component/the-music-list/imgs/headImg.png


BIN
src/page-instrument/component/the-music-list/imgs/queding.png


BIN
src/page-instrument/component/the-music-list/imgs/quxiao.png


BIN
src/page-instrument/component/the-music-list/imgs/shouqi.png


BIN
src/page-instrument/component/the-music-list/imgs/sj.png


BIN
src/page-instrument/component/the-music-list/imgs/xiang.png


BIN
src/page-instrument/component/the-music-list/imgs/zhankai.png


+ 300 - 63
src/page-instrument/component/the-music-list/index.module.less

@@ -78,6 +78,17 @@
             }
             }
         }
         }
     }
     }
+    &.isPc{
+        padding: 20px 0;
+        :global{
+            .van-tabs__wrap{
+                display: none !important;
+            }
+            .van-tabs__content{
+                height: 100% !important;
+            }
+        }
+    }
 }
 }
 
 
 .wrap {
 .wrap {
@@ -139,70 +150,23 @@
         .dropdownMenu{
         .dropdownMenu{
             border-right: 1px solid #DADCE5;
             border-right: 1px solid #DADCE5;
             margin-right: 8px;
             margin-right: 8px;
-            :global{
-                .van-dropdown-menu__bar{
-                    height: 20px;
-                    background: transparent;
-                    box-shadow: initial;
-                    .van-dropdown-menu__item{
-                        padding: 0 8px 0 0;
-                    }
-                    .van-dropdown-menu__title{
-                        --van-gray-4: #0CA2EA;
-                        font-weight: 400;
-                        font-size: 14px;
-                        color: #0CA2EA;
-                        padding: 0 12px 0 0;
-                        &::after{
-                            right: 0;
-                            opacity: initial;
-                        }
-                    }
-                }
-                .van-dropdown-item.van-dropdown-item--down{
-                    left: 36px;
-                    width: 148px;
-                    margin-top: 7px;
-                    .van-dropdown-item__content{
-                        margin-left: 10px;
-                        padding: 0 10px;
-                        width: 128px;
-                        box-shadow: 0px 2px 14px 0px rgba(0,0,0,0.12);
-                        border-radius: 8px;
-                        .van-cell{
-                            margin-top: 6px;
-                            padding: 0;
-                            font-weight: 400;
-                            font-size: 14px;
-                            color: #323233;
-                            line-height: 32px;
-                            text-align: center;
-                            &::after{
-                                border: none;
-                            }
-                            &:last-child{
-                                margin-bottom: 6px;
-                            }
-                            &.van-dropdown-item__option--active{
-                                background: #EEF8FF;
-                                border-radius: 4px;
-                                color: #1CACF1;
-                                font-weight: 500;
-                            }
-                            .van-cell__value{
-                                display: none;
-                            }
-                        }
-                    }
-                }
+            flex-shrink: 0;
+            display: flex;
+            align-items: center;
+            cursor: pointer;
+            &:active{
+                opacity: 0.8;
             }
             }
-            &.currItem{
-                :global{
-                    .van-dropdown-menu__bar  .van-dropdown-menu__title{
-                        color: #1CACF1;
-                        --van-gray-4:#1CACF1;
-                    }
-                }
+            &>div{
+                font-weight: 400;
+                font-size: 14px;
+                color: #0CA2EA;
+                line-height: 20px;
+            }
+            &>img{
+                margin: 0 6px 0 4px;
+                width: 9px;
+                height: 5px;
             }
             }
         }
         }
     }
     }
@@ -211,6 +175,10 @@
             margin-top: 10px;
             margin-top: 10px;
             height: calc(100% - 44px);
             height: calc(100% - 44px);
             overflow-y: auto;
             overflow-y: auto;
+            &::-webkit-scrollbar {
+                width: 0;
+                display: none;
+            }
             .van-loading__circular{
             .van-loading__circular{
                 color: rgba(0,0,0,0.3);
                 color: rgba(0,0,0,0.3);
             }
             }
@@ -326,4 +294,273 @@
         color: rgba(0,0,0,0.46);
         color: rgba(0,0,0,0.46);
         margin-top: 10px;
         margin-top: 10px;
     }
     }
+}
+
+
+.filterList{
+    width: 408px;
+    height: 316px;
+    background: #B0D8FF;
+    box-shadow: inset 0px -2px 3px 0px #6BA5DD;
+    border-radius: 20px;
+    padding: 10px;
+    position: relative;
+    &.follow{
+        background: #BCE6F1;
+        box-shadow: inset 0px -2px 3px 0px #6397A4;
+        .borderCon{
+            background: #DAEFF5;
+            box-shadow: 0px 0px 3px 0px #98C4D0;
+            .borderBox{
+                border-color: #7CC2E0;
+            }
+        }
+        .btnCon{
+            background: linear-gradient( 180deg, rgba(213,232,255,0) 0%, rgba(218,239,245,0.73) 48%, #DAEFF5 100%);
+        }
+    }
+    &.evaluating{
+        background: #C4DAFF;
+        box-shadow: inset 0px -2px 3px 0px #6F86AD;
+        .borderCon{
+            background: #D5E2FF;
+            box-shadow: 0px 0px 3px 0px #889CBE;
+            .borderBox{
+                border-color: #91AAF9;
+            }
+        }
+        .btnCon{
+            background: linear-gradient( 180deg, rgba(213,232,255,0) 0%, rgba(213,226,255,0.73) 48%, #D5E2FF 100%);
+        }
+    }
+    &.isPc{
+        height:initial !important;
+        .borderBoxCon{
+            height: initial !important;
+            max-height: 70vh;
+        }
+    }
+    .head{
+        position: absolute;
+        top: -11px;
+        left: 50%;
+        transform: translateX(-50%);
+        width: 100%;
+        height: 45px;
+        display: flex;
+        justify-content: center;
+        .headTit{
+            width: 164px;
+            height: 100%;
+        }
+    }      
+    .closeImg{
+        position: absolute;
+        top: -9px;
+        right: -40px;
+        width: 32px;
+        height: 32px;
+        cursor: pointer;
+    }
+    .borderCon{
+        width: 100%;
+        height: 100%;
+        background: #D5E8FF;
+        box-shadow: 0px 0px 3px 0px #639ACF;
+        border-radius: 14px;
+        padding: 10px;
+        .borderBox{
+            padding-top: 10px;
+            padding-bottom: 1px;
+            width: 100%;
+            height: 100%;
+            border-radius: 10px 14px 14px 10px;
+            border: 1px dashed rgb(155,201,246);
+            .borderBoxCon{
+                padding: 0 10px 50px 10px;
+                width: 100%;
+                height: 100%;
+                overflow-y: auto;
+                &::-webkit-scrollbar {
+                    width: 0;
+                    display: none;
+                }
+            }
+            .titCon{
+                position: relative;
+                font-weight: 500;
+                font-size: 16px;
+                color: #333333;
+                line-height: 22px;
+                padding-left: 12px;
+                margin-top: 10px;
+                &::before{
+                    content: "";
+                    position: absolute;
+                    top: 50%;
+                    transform: translateY(-50%);
+                    left: 2px;
+                    width: 4px;
+                    height: 11px;
+                    background: #1CACF1;
+                    border-radius: 3px;
+                }
+                .shouqiImg{
+                    position: absolute;
+                    display: flex;
+                    justify-content: center;
+                    align-items: center;
+                    font-weight: 400;
+                    font-size: 12px;
+                    color: #333333;
+                    right: 0;
+                    top: 50%;
+                    transform: translateY(-50%);
+                    cursor: pointer;
+                    &:active{
+                        opacity: 0.8;
+                    }
+                    >img{
+                        margin-left: 2px;
+                        width: 11px;
+                        height: 10px;
+                    }
+                }
+            }
+            .filterCon{
+                display: flex;
+                flex-wrap: wrap;
+                margin-top: 8px;
+                margin-left: -10px;
+                width: calc(100% + 10px);
+                &.courseType{
+                    .tabBox{
+                        width: calc(50% - 10px);
+                        padding: 0 10px;
+                    }
+                }
+                .tabBox{
+                    cursor: pointer;
+                    width: calc(25% - 10px);
+                    height: 32px;
+                    margin-bottom: 8px;
+                    flex-shrink: 0;
+                    margin-left: 10px;
+                    background: #F6F6F6;
+                    border-radius: 6px;
+                    font-weight: 400;
+                    font-size: 12px;
+                    text-align: center;
+                    line-height: 32px;
+                    color: #333333;
+                    padding: 0 5px;
+                    white-space: nowrap;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                    &:active{
+                        opacity: 0.8;
+                    }
+                    &.tabActive{
+                        background: #EBF8FF;
+                        border: 1px solid rgba(28,172,241,0.5);
+                        font-weight: 600;
+                        color: #1CACF1;
+                    }
+                    &.zhankaiImg{
+                        display: flex;
+                        justify-content: center;
+                        align-items: center;
+                        >img{
+                            margin-left: 2px;
+                            width: 11px;
+                            height: 10px;
+                        }
+                    }
+                    &.tabBoxPopCon{
+                        width: 100%;
+                        margin-left: 0;
+                        margin-bottom: 0;
+                        .tabBoxPop{
+                            width: 100%;
+                            height: 100%;
+                            display: flex;
+                            justify-content: center;
+                            align-items: center;
+                            &.actTabBoxPop{
+                                .sjImg{
+                                    transform: rotate(180deg);
+                                }
+                            }
+                            &>div{
+                                white-space: nowrap;
+                                overflow: hidden;
+                                text-overflow: ellipsis;  
+                            }
+                            .sjImg{
+                                width: 9px;
+                                height: 5px;
+                                margin-left: 4px;
+                            }
+                        }
+                    }
+                }
+                :global{
+                    .van-popover__wrapper{
+                        width: calc(25% - 10px);
+                        height: 32px;
+                        margin-bottom: 8px;
+                        flex-shrink: 0;
+                        margin-left: 10px;
+                    }
+                }
+            }
+        }
+    }
+    .btnCon{
+        position: absolute;
+        left: 24px;
+        bottom: 21px;
+        padding: 10px 0;
+        width: calc(100% - 48px);
+        display: flex;
+        justify-content: center;
+        background: linear-gradient( 180deg, rgba(213,232,255,0) 0%, rgba(213,232,255,0.73) 48%, #D5E8FF 100%);
+        border-radius: 0px 0px 10px 10px;
+        &>img{
+            width: 139px;
+            height: 39px;
+            cursor: pointer;
+            &:active{
+                opacity: 0.8;
+            }
+            &:first-child{
+                margin-right: 10px;
+            }
+        }
+    }
+}
+.tabPopoverBox{
+    width: 120px;
+    background: #FFFFFF;
+    box-shadow: 0px 0px 18px 0px rgba(0,0,0,0.15);
+    border-radius: 8px;
+    padding: 8px;
+    .tabPopover{
+        cursor: pointer;
+        height: 32px;
+        border-radius: 4px;
+        font-weight: 400;
+        font-size: 14px;
+        color: #323233;
+        line-height: 32px;
+        text-align: center;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        &.active{
+            background: #EEF8FF;
+            color: #1CACF1;
+            font-weight: 500;
+        }
+    }
 }
 }

+ 2 - 2
src/page-instrument/component/the-music-list/index.tsx

@@ -9,7 +9,7 @@ import { getQuery } from "/src/utils/queryString";
 
 
 const query: any = getQuery();
 const query: any = getQuery();
 export const isMusicList = computed(()=>{
 export const isMusicList = computed(()=>{
-	return !(query.workRecord || query.modelType || state.platform === IPlatform.PC || query.isCbs)
+	return !(query.workRecord || query.isCbs)
 })
 })
 export const musicListShow = ref(false)
 export const musicListShow = ref(false)
 export default defineComponent({
 export default defineComponent({
@@ -18,7 +18,7 @@ export default defineComponent({
 		return () => (
 		return () => (
 			<>
 			<>
 				<Popup class={styles.popup} position="left" v-model:show={musicListShow.value} round overlay-style={{background:'rgba(0, 0, 0, 0.3)'}}>
 				<Popup class={styles.popup} position="left" v-model:show={musicListShow.value} round overlay-style={{background:'rgba(0, 0, 0, 0.3)'}}>
-					<div class={[styles.tabs, styles[state.modeType]]}>
+					<div class={[styles.tabs, styles[state.modeType], state.platform === IPlatform.PC && styles.isPc]}>
 						<Tabs>
 						<Tabs>
 							<Tab title="其他曲谱">
 							<Tab title="其他曲谱">
 								<List />
 								<List />

+ 44 - 27
src/page-instrument/component/the-music-list/list.tsx

@@ -1,13 +1,19 @@
-import { defineComponent, onMounted, reactive, watch } from "vue";
+import { defineComponent, onMounted, reactive, watch, ref} from "vue";
 import styles from "./index.module.less";
 import styles from "./index.module.less";
 import { api_musicSheetPage } from "../../api";
 import { api_musicSheetPage } from "../../api";
-import state, { togglePlay } from "/src/state";
-import { List, Image, Field, DropdownMenu, DropdownItem } from "vant";
+import state, { togglePlay, IPlatform } from "/src/state";
+import { List, Image, Field, DropdownMenu, DropdownItem, Popup } from "vant";
 import { postMessage } from "/src/utils/native-message";
 import { postMessage } from "/src/utils/native-message";
 import qs from "query-string";
 import qs from "query-string";
 import searImg from "./imgs/searImg.png"
 import searImg from "./imgs/searImg.png"
 import huoimg from "./imgs/huo.png"
 import huoimg from "./imgs/huo.png"
 import emptyImg from "./imgs/empty.png"
 import emptyImg from "./imgs/empty.png"
+import xiangImg from "./imgs/xiang.png"
+import FilterList from "./filterList"
+import { getQuery } from "/src/utils/queryString";
+import Dragbom from "/src/view/plugins/useDrag/dragbom";
+import { storeData } from "/src/store";
+import useDrag from "/src/view/plugins/useDrag/index";
 
 
 export default defineComponent({
 export default defineComponent({
   name: "TheMusicList-list",
   name: "TheMusicList-list",
@@ -18,6 +24,7 @@ export default defineComponent({
     },
     },
   },
   },
   setup(props) {
   setup(props) {
+    const query: any = getQuery();
     const forms = reactive({
     const forms = reactive({
       name: "",
       name: "",
       page: 1,
       page: 1,
@@ -25,7 +32,10 @@ export default defineComponent({
       musicSheetCategoriesId: state.bizMusicCategoryId,
       musicSheetCategoriesId: state.bizMusicCategoryId,
       recentFlag: props.recentFlag ? true : null,
       recentFlag: props.recentFlag ? true : null,
       excludeMusicId: props.recentFlag ? null : state.examSongId,
       excludeMusicId: props.recentFlag ? null : state.examSongId,
-      audioPlayTypes:""
+      audioPlayTypes: [],
+      musicTutorialIds: "",
+      musicTagIds: "",
+      musicalInstrumentId: query.instrumentId || ""
     });
     });
     const data = reactive({
     const data = reactive({
       isFocus: false,
       isFocus: false,
@@ -34,22 +44,12 @@ export default defineComponent({
       loading: false,
       loading: false,
       hasNext: true,
       hasNext: true,
     });
     });
-    const audioPlayTypesOption = [
-      { text: '全部场景', value: "" },
-      { text: '演奏', value: "PLAY" },
-      { text: '演唱', value: "SING" },
-      { text: '演奏+演唱', value: "PLAY,SING" },
-    ]
+    const filterShow = ref(false)
     const getList = async () => {
     const getList = async () => {
       if (!data.hasNext) return;
       if (!data.hasNext) return;
       data.loading = true;
       data.loading = true;
       try {
       try {
-        const res = await api_musicSheetPage({
-          ...forms,
-          ...{
-            audioPlayTypes: forms.audioPlayTypes ? forms.audioPlayTypes.split(",") : []
-          }
-        });
+        const res = await api_musicSheetPage(forms);
         if (res?.code === 200 && Array.isArray(res.data?.rows)) {
         if (res?.code === 200 && Array.isArray(res.data?.rows)) {
           data.list = [...data.list, ...res.data.rows];
           data.list = [...data.list, ...res.data.rows];
         }
         }
@@ -91,26 +91,32 @@ export default defineComponent({
           type: "fullscreen",
           type: "fullscreen",
         },
         },
       });
       });
-      location.href =
-        location.origin +
-        location.pathname +
-        "?" +
-        qs.stringify({
-          id: item.id,
-          _t: Date.now(),
-        });
+      let href = location.href.replace(/id=\d+/, `id=${item.id}`); // 替换id
+      href = href.replace(/instrumentId=\d+/, `instrumentId=${forms.musicalInstrumentId}`); // 替换乐器
+      location.href = href
+      location.reload()
     };
     };
     function formatNumber(num:number) {
     function formatNumber(num:number) {
       return num >= 10000 
       return num >= 10000 
           ? (num / 10000).toFixed(1).replace(/\.0$/, '') + "万" 
           ? (num / 10000).toFixed(1).replace(/\.0$/, '') + "万" 
           : num.toString();
           : num.toString();
     }
     }
+    // 拖动
+    const parentClassName = "musicListClass_drag";
+		const userId = storeData.user?.id ? String(storeData.user?.id) : "";
+		const positionInfo =
+        state.platform !== IPlatform.PC
+        ? {
+            styleDrag: { value: null },
+          }
+        : useDrag([`${parentClassName} .top_draging`, `${parentClassName} .bom_drag`], parentClassName, filterShow, userId);
     return () => (
     return () => (
       <div class={styles.wrap}>
       <div class={styles.wrap}>
         <div class={[styles.searchBox,data.isFocus && styles.isFocus]}>
         <div class={[styles.searchBox,data.isFocus && styles.isFocus]}>
-          <DropdownMenu class={[styles.dropdownMenu]} overlay={false}>
-							<DropdownItem onChange={handleQuery} v-model={forms.audioPlayTypes} options={audioPlayTypesOption}/>
-					</DropdownMenu>
+          <div class={styles.dropdownMenu} onClick={() => { filterShow.value = true }}>
+            <div>筛选</div>
+            <img src={xiangImg} />
+          </div>
           <img src={searImg} />
           <img src={searImg} />
           <Field placeholder="请输入曲目名称" v-model={forms.name} autocomplete="off" onFocus={()=>{ data.isFocus = true }} onBlur={()=>{ data.isFocus = false }} />
           <Field placeholder="请输入曲目名称" v-model={forms.name} autocomplete="off" onFocus={()=>{ data.isFocus = true }} onBlur={()=>{ data.isFocus = false }} />
           <div class={styles.searchBtn} onClick={handleQuery}>搜索</div>
           <div class={styles.searchBtn} onClick={handleQuery}>搜索</div>
@@ -152,6 +158,17 @@ export default defineComponent({
                   <span>暂无内容</span>
                   <span>暂无内容</span>
                 </div>}
                 </div>}
         </List>
         </List>
+        <Popup  style={positionInfo.styleDrag.value} v-model:show={filterShow.value} class="popup-custom van-scale center-closeBtn musicListClass_drag" transition="van-scale" teleport="body" overlay-style={{ background: "rgba(0, 0, 0, 0.3)" }}>
+          <FilterList onClose={() => { filterShow.value = false }} onHandleConfirm={(queryObj) => {
+            filterShow.value = false
+            forms.audioPlayTypes = queryObj.audioPlayTypes
+            forms.musicTutorialIds = queryObj.musicTutorialIds
+            forms.musicTagIds = queryObj.musicTagIds
+            forms.musicalInstrumentId = queryObj.musicalInstrumentId
+            handleQuery()
+          }}></FilterList>
+          {state.platform === IPlatform.PC && <Dragbom />}
+        </Popup>
       </div>
       </div>
     );
     );
   },
   },

BIN
src/page-instrument/custom-plugins/guide-driver/images/practise/d11.png


BIN
src/page-instrument/custom-plugins/guide-driver/images/practise/d7.png


BIN
src/page-instrument/custom-plugins/guide-driver/images/report/r2.png


BIN
src/page-instrument/custom-plugins/guide-driver/images/report/r3.png


+ 75 - 12
src/page-instrument/custom-plugins/guide-driver/index.less

@@ -4,22 +4,27 @@
 }
 }
 
 
 .popoverClass .driver-popover-next-btn {
 .popoverClass .driver-popover-next-btn {
-  width: 100px;
+  width: 102px;
   height: 34px;
   height: 34px;
   text-shadow: none;
   text-shadow: none;
   border: none;
   border: none;
   font-weight: 600;
   font-weight: 600;
   font-size: 13px;
   font-size: 13px;
-  color: #006ed1;
+  color: #006ed1 !important;
   text-align: center;
   text-align: center;
   position: absolute;
   position: absolute;
   background: url("./images/btn-next.png") no-repeat center transparent;
   background: url("./images/btn-next.png") no-repeat center transparent;
   background-size: contain;
   background-size: contain;
   background-color: transparent !important;
   background-color: transparent !important;
+  padding: 0;
+  font-family: inherit;
 }
 }
+
 .popoverClass .driver-popover-prev-btn {
 .popoverClass .driver-popover-prev-btn {
   font-weight: 600;
   font-weight: 600;
   font-size: 13px;
   font-size: 13px;
+  padding: 0;
+  font-family: inherit;
 }
 }
 
 
 .popoverClass .driver-popover-next-btn:hover,
 .popoverClass .driver-popover-next-btn:hover,
@@ -95,6 +100,18 @@
   }
   }
 }
 }
 
 
+.popoverClass11 {
+  width: 264px;
+  height: 245px;
+  background: url("./images/practise/d11.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 24px;
+    bottom: 23px;
+  }
+}
+
 .popoverClass4 {
 .popoverClass4 {
   width: 265px;
   width: 265px;
   height: 245px;
   height: 245px;
@@ -155,14 +172,37 @@
 }
 }
 
 
 .popoverClass7 {
 .popoverClass7 {
-  width: 267px;
-  height: 221px;
+  width: 306px;
+  height: 167px;
   background: url("./images/practise/d7.png") no-repeat center;
   background: url("./images/practise/d7.png") no-repeat center;
   background-size: contain;
   background-size: contain;
 
 
   .driver-popover-next-btn {
   .driver-popover-next-btn {
     right: 14px;
     right: 14px;
-    bottom: 18px;
+    bottom: -18px;
+  }
+
+  &.popoverClose {
+
+    .driver-popover-navigation-btns {
+      position: absolute;
+      bottom: -18px;
+      left: 0;
+      right: 15px;
+      justify-content: flex-start;
+    }
+
+    .driver-popover-next-btn {
+      // right: 14px;
+      // bottom: 18px;
+      position: relative;
+      top: 0;
+      right: 0;
+    }
+
+    .driver-popover-prev-btn {
+      margin-left: 14px;
+    }
   }
   }
 }
 }
 
 
@@ -176,6 +216,29 @@
     right: 14px;
     right: 14px;
     bottom: 18px;
     bottom: 18px;
   }
   }
+
+  &.popoverClose {
+
+    .driver-popover-navigation-btns {
+      position: absolute;
+      bottom: 23px;
+      left: 0;
+      right: 15px;
+      justify-content: flex-start;
+    }
+
+    .driver-popover-next-btn {
+      // right: 14px;
+      // bottom: 18px;
+      position: relative;
+      top: 0;
+      right: 0;
+    }
+
+    .driver-popover-prev-btn {
+      margin-left: 14px;
+    }
+  }
 }
 }
 
 
 .popoverClass8 {
 .popoverClass8 {
@@ -205,8 +268,8 @@
 }
 }
 
 
 .popoverClass10 {
 .popoverClass10 {
-  width: 264px;
-  height: 245px;
+  width: 257px;
+  height: 213px;
   background: url("./images/practise/d10.png") no-repeat center;
   background: url("./images/practise/d10.png") no-repeat center;
   background-size: contain;
   background-size: contain;
 
 
@@ -241,7 +304,7 @@
   .driver-popover-prev-btn {
   .driver-popover-prev-btn {
     border: 1px solid #fff;
     border: 1px solid #fff;
     border-radius: 100px;
     border-radius: 100px;
-    color: #fff;
+    color: #fff !important;
     background-color: transparent;
     background-color: transparent;
     font-weight: 400;
     font-weight: 400;
     text-shadow: none;
     text-shadow: none;
@@ -448,7 +511,7 @@
 
 
 .popoverClassReport1 {
 .popoverClassReport1 {
   width: 270px;
   width: 270px;
-  height: 143px;
+  height: 142px;
   background: url("./images/report/r1.png") no-repeat center;
   background: url("./images/report/r1.png") no-repeat center;
   background-size: contain;
   background-size: contain;
 
 
@@ -460,7 +523,7 @@
 
 
 .popoverClassReport2 {
 .popoverClassReport2 {
   width: 270px;
   width: 270px;
-  height: 143px;
+  height: 142px;
   background: url("./images/report/r2.png") no-repeat center;
   background: url("./images/report/r2.png") no-repeat center;
   background-size: contain;
   background-size: contain;
 
 
@@ -491,7 +554,7 @@
 
 
 .popoverClassReport3 {
 .popoverClassReport3 {
   width: 270px;
   width: 270px;
-  height: 143px;
+  height: 142px;
   background: url("./images/report/r3.png") no-repeat center;
   background: url("./images/report/r3.png") no-repeat center;
   background-size: contain;
   background-size: contain;
 
 
@@ -522,7 +585,7 @@
 
 
 .popoverClassReport4 {
 .popoverClassReport4 {
   width: 270px;
   width: 270px;
-  height: 143px;
+  height: 142px;
   background: url("./images/report/r5.png") no-repeat center;
   background: url("./images/report/r5.png") no-repeat center;
   background-size: contain;
   background-size: contain;
 
 

+ 332 - 48
src/page-instrument/custom-plugins/guide-driver/index.tsx

@@ -6,7 +6,8 @@ import { getGuidance, setGuidance } from "../guide-page/api";
 
 
 const endGuide = (guideInfo: any) => {
 const endGuide = (guideInfo: any) => {
   try {
   try {
-    setGuidance({ guideTag: "guideInfo", guideValue: JSON.stringify(guideInfo) });
+    // setGuidance({ guideTag: "guideInfo", guideValue: JSON.stringify(guideInfo) });
+    localStorage.setItem("guideInfo", JSON.stringify(guideInfo));
   } catch (e) {
   } catch (e) {
     console.log(e);
     console.log(e);
   }
   }
@@ -16,6 +17,8 @@ const endGuide = (guideInfo: any) => {
  * 按钮状态
  * 按钮状态
  */
  */
 type ButtonStatus = {
 type ButtonStatus = {
+  /** 是否显示播放按钮 */
+  playBtnStatus?: Boolean;
   /** 声部状态 */
   /** 声部状态 */
   subjectStatus?: Boolean;
   subjectStatus?: Boolean;
   /** 练习模式 */
   /** 练习模式 */
@@ -28,6 +31,8 @@ type ButtonStatus = {
   titleType?: String;
   titleType?: String;
   /** 原声 true 范唱 false */
   /** 原声 true 范唱 false */
   originPlayType?: Boolean;
   originPlayType?: Boolean;
+  /** 是否显示原音 */
+  originBtnStatus?: Boolean;
 };
 };
 
 
 /** 练习模式 */
 /** 练习模式 */
@@ -54,6 +59,18 @@ export const PractiseDriver = defineComponent({
 
 
     const driverOptions = (): Config => {
     const driverOptions = (): Config => {
       let length = 10;
       let length = 10;
+<<<<<<< HEAD
+=======
+
+      if (!props.statusAll.playBtnStatus) {
+        length -= 1;
+      }
+
+      if (!props.statusAll.originBtnStatus) {
+        length -= 1;
+      }
+
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
       // 显示指法
       // 显示指法
       if (!state.setting.displayFingering) {
       if (!state.setting.displayFingering) {
         length -= 1;
         length -= 1;
@@ -80,7 +97,11 @@ export const PractiseDriver = defineComponent({
           length -= 1;
           length -= 1;
         }
         }
       }
       }
+<<<<<<< HEAD
       console.log(props.statusAll, "statusAll", length);
       console.log(props.statusAll, "statusAll", length);
+=======
+      console.log(props.statusAll, "statusAll", length, state.setting.displayFingering);
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
 
 
       let options: Config = {
       let options: Config = {
         showProgress: false,
         showProgress: false,
@@ -96,6 +117,7 @@ export const PractiseDriver = defineComponent({
         onHighlighted: () => {
         onHighlighted: () => {
           driverNextStatus.value = false;
           driverNextStatus.value = false;
         },
         },
+<<<<<<< HEAD
         steps: [
         steps: [
           {
           {
             element: ".driver-1",
             element: ".driver-1",
@@ -116,6 +138,30 @@ export const PractiseDriver = defineComponent({
         ] as DriveStep[],
         ] as DriveStep[],
       };
       };
 
 
+=======
+        steps: [] as DriveStep[],
+      };
+
+      if (props.statusAll.playBtnStatus) {
+        options.steps?.push({
+          element: ".driver-1",
+          popover: {
+            title: "",
+            description: "",
+            popoverClass: "popoverClass popoverClass1",
+            align: "end",
+            side: "top",
+            nextBtnText: `下一步 (1/${length})`,
+            showButtons: ["next"],
+            onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+              options.config.stageRadius = 1000;
+              options.config.stagePadding = 0;
+            },
+          },
+        });
+      }
+
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
       if (props.statusAll.playType) {
       if (props.statusAll.playType) {
         options.steps?.push({
         options.steps?.push({
           element: ".driver-2",
           element: ".driver-2",
@@ -134,8 +180,8 @@ export const PractiseDriver = defineComponent({
         });
         });
       }
       }
 
 
-      options.steps?.push(
-        {
+      if (props.statusAll.originBtnStatus) {
+        options.steps?.push({
           element: ".driver-3",
           element: ".driver-3",
           popover: {
           popover: {
             title: "",
             title: "",
@@ -149,7 +195,9 @@ export const PractiseDriver = defineComponent({
               driverInitialPosition(popover, options);
               driverInitialPosition(popover, options);
             },
             },
           },
           },
-        },
+        });
+      }
+      options.steps?.push(
         {
         {
           element: ".driver-4",
           element: ".driver-4",
           popover: {
           popover: {
@@ -158,7 +206,7 @@ export const PractiseDriver = defineComponent({
             popoverClass: "popoverClass popoverClass4",
             popoverClass: "popoverClass popoverClass4",
             align: "start",
             align: "start",
             side: "top",
             side: "top",
-            nextBtnText: `下一步 (${options.steps.length + 2}/${length})`,
+            nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
             showButtons: ["next"],
             showButtons: ["next"],
             onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
             onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
               driverInitialPosition(popover, options);
               driverInitialPosition(popover, options);
@@ -173,7 +221,7 @@ export const PractiseDriver = defineComponent({
             popoverClass: "popoverClass popoverClass5",
             popoverClass: "popoverClass popoverClass5",
             align: "start",
             align: "start",
             side: "top",
             side: "top",
-            nextBtnText: `下一步 (${options.steps.length + 3}/${length})`,
+            nextBtnText: `下一步 (${options.steps.length + 2}/${length})`,
             showButtons: ["next"],
             showButtons: ["next"],
             onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
             onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
               driverInitialPosition(popover, options);
               driverInitialPosition(popover, options);
@@ -220,6 +268,7 @@ export const PractiseDriver = defineComponent({
           // 是否有指法图
           // 是否有指法图
           // 乐器方向不一样引导位置不一样
           // 乐器方向不一样引导位置不一样
           options.steps?.push({
           options.steps?.push({
+<<<<<<< HEAD
             element: ".driver-7",
             element: ".driver-7",
             popover: {
             popover: {
               title: "",
               title: "",
@@ -286,26 +335,167 @@ export const PractiseDriver = defineComponent({
           // 是否有指法图
           // 是否有指法图
           // 乐器方向不一样引导位置不一样
           // 乐器方向不一样引导位置不一样
           options.steps?.push({
           options.steps?.push({
+=======
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
             element: ".driver-7",
             element: ".driver-7",
             popover: {
             popover: {
               title: "",
               title: "",
               description: "",
               description: "",
-              popoverClass: `popoverClass ${state.fingeringInfo.direction === "transverse" ? "popoverClass7" : "popoverClass7-1"}`,
+              popoverClass: `popoverClass ${state.fingeringInfo.direction === "transverse" ? "popoverClass7 popoverClose" : "popoverClass7-1 popoverClose"}`,
               align: state.fingeringInfo.direction === "transverse" ? "start" : "center",
               align: state.fingeringInfo.direction === "transverse" ? "start" : "center",
               side: state.fingeringInfo.direction === "transverse" ? "top" : "left",
               side: state.fingeringInfo.direction === "transverse" ? "top" : "left",
+<<<<<<< HEAD
               nextBtnText: `下一步 (${options.steps?.length + 1}/${length})`,
               nextBtnText: `下一步 (${options.steps?.length + 1}/${length})`,
               showButtons: ["next"],
               showButtons: ["next"],
+=======
+              prevBtnText: "再看一遍",
+              doneBtnText: "完成",
+              showButtons: ["next", "previous"],
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
               onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
               onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
                 if (state.fingeringInfo.direction === "transverse") driverInitialPosition(popover, options);
                 if (state.fingeringInfo.direction === "transverse") driverInitialPosition(popover, options);
               },
               },
-              onCloseClick: () => {
+              onPrevClick: () => {
+                driverObj.drive(0);
+              },
+              onNextClick: () => {
                 onDriverClose();
                 onDriverClose();
               },
               },
             },
             },
           });
           });
+<<<<<<< HEAD
         }
         }
 
 
         if (!props.statusAll.modelTypeStatus) {
         if (!props.statusAll.modelTypeStatus) {
+=======
+        } else {
+          options.steps?.push({
+            element: ".driver-6",
+            popover: {
+              title: "",
+              description: "",
+              popoverClass: "popoverClass popoverClass6 popoverClose",
+              align: "start",
+              side: "top",
+              prevBtnText: "再看一遍",
+              doneBtnText: "完成",
+              showButtons: ["next", "previous"],
+              onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                driverInitialPosition(popover, options);
+              },
+              onPrevClick: () => {
+                driverObj.drive(0);
+              },
+              onNextClick: () => {
+                onDriverClose();
+              },
+            },
+          });
+        }
+      } else {
+        // 判断设置之后是否还有引导
+        if (!state.setting.displayFingering && !props.statusAll.backTitle && !props.statusAll.modelTypeStatus) {
+          options.steps?.push({
+            element: ".driver-6",
+            popover: {
+              title: "",
+              description: "",
+              popoverClass: "popoverClass popoverClass6 popoverClose",
+              align: "start",
+              side: "top",
+              prevBtnText: "再看一遍",
+              doneBtnText: "完成",
+              showButtons: ["next", "previous"],
+              onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                driverInitialPosition(popover, options);
+              },
+              onPrevClick: () => {
+                driverObj.drive(0);
+              },
+              onNextClick: () => {
+                onDriverClose();
+              },
+            },
+          });
+        } else if (state.setting.displayFingering && !props.statusAll.backTitle && !props.statusAll.modelTypeStatus) {
+          options.steps?.push({
+            element: ".driver-6",
+            popover: {
+              title: "",
+              description: "",
+              popoverClass: "popoverClass popoverClass6",
+              align: "start",
+              side: "top",
+              nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length,
+              showButtons: ["next"],
+              onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                driverInitialPosition(popover, options);
+              },
+            },
+          });
+          // 是否有指法图
+          // 乐器方向不一样引导位置不一样
+          options.steps?.push({
+            element: ".driver-7",
+            popover: {
+              title: "",
+              description: "",
+              popoverClass: `popoverClass ${state.fingeringInfo.direction === "transverse" ? "popoverClass7" : "popoverClass7-1"} popoverClose`,
+              align: state.fingeringInfo.direction === "transverse" ? "start" : "center",
+              side: state.fingeringInfo.direction === "transverse" ? "top" : "left",
+              prevBtnText: "再看一遍",
+              doneBtnText: "完成",
+              showButtons: ["next", "previous"],
+              onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                if (state.fingeringInfo.direction === "transverse") driverInitialPosition(popover, options);
+              },
+              onPrevClick: () => {
+                driverObj.drive(0);
+              },
+              onNextClick: () => {
+                onDriverClose();
+              },
+            },
+          });
+        } else if (props.statusAll.backTitle && !props.statusAll.modelTypeStatus) {
+          options.steps?.push({
+            element: ".driver-6",
+            popover: {
+              title: "",
+              description: "",
+              popoverClass: "popoverClass popoverClass6",
+              align: "start",
+              side: "top",
+              nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length,
+              showButtons: ["next"],
+              onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                driverInitialPosition(popover, options);
+              },
+            },
+          });
+          if (state.setting.displayFingering) {
+            // 是否有指法图
+            // 乐器方向不一样引导位置不一样
+            options.steps?.push({
+              element: ".driver-7",
+              popover: {
+                title: "",
+                description: "",
+                popoverClass: `popoverClass ${state.fingeringInfo.direction === "transverse" ? "popoverClass7" : "popoverClass7-1"}`,
+                align: state.fingeringInfo.direction === "transverse" ? "start" : "center",
+                side: state.fingeringInfo.direction === "transverse" ? "top" : "left",
+                nextBtnText: `下一步 (${options.steps?.length + 1}/${length})`,
+                showButtons: ["next"],
+                onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                  if (state.fingeringInfo.direction === "transverse") driverInitialPosition(popover, options);
+                },
+                onCloseClick: () => {
+                  onDriverClose();
+                },
+              },
+            });
+          }
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
           options.steps?.push({
           options.steps?.push({
             //props.statusAll.titleType === "TEXT" ? ".driver-8 .van-notice-bar__content" :
             //props.statusAll.titleType === "TEXT" ? ".driver-8 .van-notice-bar__content" :
             element: ".driver-8",
             element: ".driver-8",
@@ -315,6 +505,8 @@ export const PractiseDriver = defineComponent({
               popoverClass: "popoverClass popoverClass8 popoverClose",
               popoverClass: "popoverClass popoverClass8 popoverClose",
               align: "start",
               align: "start",
               side: "bottom",
               side: "bottom",
+<<<<<<< HEAD
+=======
               prevBtnText: "再看一遍",
               prevBtnText: "再看一遍",
               doneBtnText: "完成",
               doneBtnText: "完成",
               showButtons: ["next", "previous"],
               showButtons: ["next", "previous"],
@@ -340,6 +532,111 @@ export const PractiseDriver = defineComponent({
             },
             },
           });
           });
         } else {
         } else {
+          options.steps?.push({
+            element: ".driver-6",
+            popover: {
+              title: "",
+              description: "",
+              popoverClass: "popoverClass popoverClass6",
+              align: "start",
+              side: "top",
+              nextBtnText: `下一步 (${options.steps.length + 1}/${length})`, //"下一步6/" + length,
+              showButtons: ["next"],
+              onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                driverInitialPosition(popover, options);
+              },
+            },
+          });
+
+          if (state.setting.displayFingering) {
+            // 是否有指法图
+            // 乐器方向不一样引导位置不一样
+            options.steps?.push({
+              element: ".driver-7",
+              popover: {
+                title: "",
+                description: "",
+                popoverClass: `popoverClass ${state.fingeringInfo.direction === "transverse" ? "popoverClass7" : "popoverClass7-1"}`,
+                align: state.fingeringInfo.direction === "transverse" ? "start" : "center",
+                side: state.fingeringInfo.direction === "transverse" ? "top" : "left",
+                nextBtnText: `下一步 (${options.steps?.length + 1}/${length})`,
+                showButtons: ["next"],
+                onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                  if (state.fingeringInfo.direction === "transverse") driverInitialPosition(popover, options);
+                },
+                onCloseClick: () => {
+                  onDriverClose();
+                },
+              },
+            });
+          }
+
+          if (props.statusAll.backTitle) {
+            options.steps?.push({
+              //  .van-notice-bar__content
+              // element: ".driver-8 .van-notice-bar__content",
+              // props.statusAll.titleType === "TEXT" ? ".driver-8 .van-notice-bar__content" :
+              element: ".driver-8",
+              popover: {
+                title: "",
+                description: "",
+                popoverClass: "popoverClass popoverClass8",
+                align: "start",
+                side: "bottom",
+                nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
+                showButtons: ["next"],
+                onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                  if (props.statusAll.titleType === "TEXT") {
+                    options.config.stageRadius = 5;
+                    options.config.stagePadding = 5;
+                  } else {
+                    options.config.stageRadius = 1000;
+                    options.config.stagePadding = 0;
+                  }
+                  try {
+                    const rect = options.state.activeElement?.getBoundingClientRect();
+                    popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px";
+                  } catch {}
+                },
+              },
+            });
+          }
+
+          options.steps?.push({
+            element: ".driver-9",
+            popover: {
+              title: "",
+              description: "",
+              popoverClass: "popoverClass popoverClass9 popoverClose",
+              align: "end",
+              side: "bottom",
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
+              prevBtnText: "再看一遍",
+              doneBtnText: "完成",
+              showButtons: ["next", "previous"],
+              onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+                if (props.statusAll.titleType === "TEXT") {
+                  options.config.stageRadius = 5;
+                  options.config.stagePadding = 5;
+                } else {
+                  options.config.stageRadius = 1000;
+                  options.config.stagePadding = 0;
+                }
+                try {
+                  const rect = options.state.activeElement?.getBoundingClientRect();
+                  popover.wrapper.style.marginLeft = (rect?.width || 0) / 2 - 4 + "px";
+                } catch {}
+              },
+              onPrevClick: () => {
+                driverObj.drive(0);
+              },
+              onNextClick: () => {
+                onDriverClose();
+              },
+            },
+          });
+<<<<<<< HEAD
+        } else {
           options.steps?.push(
           options.steps?.push(
             {
             {
               //  .van-notice-bar__content
               //  .van-notice-bar__content
@@ -397,6 +694,8 @@ export const PractiseDriver = defineComponent({
               },
               },
             }
             }
           );
           );
+=======
+>>>>>>> ad48312a4218b12b77f39afa7da0b336de34b76c
         }
         }
       }
       }
 
 
@@ -421,15 +720,12 @@ export const PractiseDriver = defineComponent({
     const showCloseBtn = ref(false);
     const showCloseBtn = ref(false);
     const getAllGuidance = async () => {
     const getAllGuidance = async () => {
       try {
       try {
-        if (state.guideInfo) {
-          guideInfo.value = state.guideInfo;
+        // const res = await getGuidance({ guideTag: "guideInfo" });
+        const res = localStorage.getItem("guideInfo");
+        if (res) {
+          guideInfo.value = JSON.parse(res) || null;
         } else {
         } else {
-          const res = await getGuidance({ guideTag: "guideInfo" });
-          if (res.data) {
-            guideInfo.value = JSON.parse(res.data?.guideValue) || null;
-          } else {
-            guideInfo.value = {};
-          }
+          guideInfo.value = {};
         }
         }
 
 
         if (!(guideInfo.value && guideInfo.value.practiseDriver)) {
         if (!(guideInfo.value && guideInfo.value.practiseDriver)) {
@@ -614,16 +910,13 @@ export const FollowDriver = defineComponent({
     const showCloseBtn = ref(false);
     const showCloseBtn = ref(false);
     const getAllGuidance = async () => {
     const getAllGuidance = async () => {
       try {
       try {
-        if (state.guideInfo) {
-          guideInfo.value = state.guideInfo;
+        const res = localStorage.getItem("guideInfo");
+        if (res) {
+          guideInfo.value = JSON.parse(res) || null;
         } else {
         } else {
-          const res = await getGuidance({ guideTag: "guideInfo" });
-          if (res.data) {
-            guideInfo.value = JSON.parse(res.data?.guideValue) || null;
-          } else {
-            guideInfo.value = {};
-          }
+          guideInfo.value = {};
         }
         }
+
         if (!(guideInfo.value && guideInfo.value.followDriver)) {
         if (!(guideInfo.value && guideInfo.value.followDriver)) {
           document.addEventListener("click", handleClickOutside, true);
           document.addEventListener("click", handleClickOutside, true);
           nextTick(() => {
           nextTick(() => {
@@ -822,16 +1115,13 @@ export const EvaluatingDriver = defineComponent({
     const showCloseBtn = ref(false);
     const showCloseBtn = ref(false);
     const getAllGuidance = async () => {
     const getAllGuidance = async () => {
       try {
       try {
-        if (state.guideInfo) {
-          guideInfo.value = state.guideInfo;
+        const res = localStorage.getItem("guideInfo");
+        if (res) {
+          guideInfo.value = JSON.parse(res) || null;
         } else {
         } else {
-          const res = await getGuidance({ guideTag: "guideInfo" });
-          if (res.data) {
-            guideInfo.value = JSON.parse(res.data?.guideValue) || null;
-          } else {
-            guideInfo.value = {};
-          }
+          guideInfo.value = {};
         }
         }
+
         console.log(guideInfo.value, "guideInfo.value", showCloseBtn.value);
         console.log(guideInfo.value, "guideInfo.value", showCloseBtn.value);
         if (!(guideInfo.value && guideInfo.value.evaluatingDriver)) {
         if (!(guideInfo.value && guideInfo.value.evaluatingDriver)) {
           document.addEventListener("click", handleClickOutside, true);
           document.addEventListener("click", handleClickOutside, true);
@@ -1025,16 +1315,13 @@ export const EvaluatingResultDriver = defineComponent({
     const showCloseBtn = ref(false);
     const showCloseBtn = ref(false);
     const getAllGuidance = async () => {
     const getAllGuidance = async () => {
       try {
       try {
-        if (state.guideInfo) {
-          guideInfo.value = state.guideInfo;
+        const res = localStorage.getItem("guideInfo");
+        if (res) {
+          guideInfo.value = JSON.parse(res) || null;
         } else {
         } else {
-          const res = await getGuidance({ guideTag: "guideInfo" });
-          if (res.data) {
-            guideInfo.value = JSON.parse(res.data?.guideValue) || null;
-          } else {
-            guideInfo.value = {};
-          }
+          guideInfo.value = {};
         }
         }
+
         if (!(guideInfo.value && guideInfo.value.evaluatingResultDriver)) {
         if (!(guideInfo.value && guideInfo.value.evaluatingResultDriver)) {
           setTimeout(() => {
           setTimeout(() => {
             document.addEventListener("click", handleClickOutside, true);
             document.addEventListener("click", handleClickOutside, true);
@@ -1344,16 +1631,13 @@ export const EvaluatingReportDriver = defineComponent({
     const showCloseBtn = ref(false);
     const showCloseBtn = ref(false);
     const getAllGuidance = async () => {
     const getAllGuidance = async () => {
       try {
       try {
-        if (state.guideInfo) {
-          guideInfo.value = state.guideInfo;
+        const res = localStorage.getItem("guideInfo");
+        if (res) {
+          guideInfo.value = JSON.parse(res) || null;
         } else {
         } else {
-          const res = await getGuidance({ guideTag: "guideInfo" });
-          if (res.data) {
-            guideInfo.value = JSON.parse(res.data?.guideValue) || null;
-          } else {
-            guideInfo.value = {};
-          }
+          guideInfo.value = {};
         }
         }
+
         if (!(guideInfo.value && guideInfo.value.evaluatingReportDriver)) {
         if (!(guideInfo.value && guideInfo.value.evaluatingReportDriver)) {
           // 监听点击事件以实现点击空白区域跳转到下一步
           // 监听点击事件以实现点击空白区域跳转到下一步
           document.addEventListener("click", handleClickOutside, true);
           document.addEventListener("click", handleClickOutside, true);

+ 4 - 2
src/page-instrument/custom-plugins/helper-model/recommendation/index.module.less

@@ -114,9 +114,11 @@
                         }
                         }
                     }
                     }
                     .recommendationDropdownItem{
                     .recommendationDropdownItem{
-                        top: 106px !important;
-                        left: 14px;
+                        position: absolute !important; 
+                        top: 30px !important;
+                        left: -10px;
                         width: 172px;
                         width: 172px;
+                        height: 182px;
                         .van-dropdown-item__content{
                         .van-dropdown-item__content{
                             margin: 6px 0 0 10px;
                             margin: 6px 0 0 10px;
                             width: 152px;
                             width: 152px;

+ 1 - 1
src/page-instrument/custom-plugins/helper-model/recommendation/index.tsx

@@ -113,7 +113,7 @@ export default defineComponent({
 		}
 		}
 		return () => (
 		return () => (
 			<div class={[styles.recommendation,styles[state.modeType]]}>
 			<div class={[styles.recommendation,styles[state.modeType]]}>
-				<div class={styles.head}>
+				<div class={[styles.head, "top_draging"]}>
 					<img class={styles.headTit} src={headImg("recommendationName.png")} />
 					<img class={styles.headTit} src={headImg("recommendationName.png")} />
 					<img class={styles.closeImg} src={headImg("closeImg.png")} onClick={()=>{ emit("close") }} />
 					<img class={styles.closeImg} src={headImg("closeImg.png")} onClick={()=>{ emit("close") }} />
 				</div>
 				</div>

+ 2 - 1
src/page-instrument/custom-plugins/work-index/index.tsx

@@ -24,11 +24,12 @@ export const HANDLE_WORK_ADD = () => {
 
 
 // 刷新谱面后,设置作业选段
 // 刷新谱面后,设置作业选段
 export const resetSection = () => {
 export const resetSection = () => {
+	console.log('重新设置选段1111')
 	if (data.trainingType === "PRACTICE"){
 	if (data.trainingType === "PRACTICE"){
 		workHomeRef.value?.getWorkData();
 		workHomeRef.value?.getWorkData();
 	}
 	}
 	if (data.trainingType === "EVALUATION") {
 	if (data.trainingType === "EVALUATION") {
-		workHomeRef.value?.getWorkData();
+		workEvaluatRef.value?.getWorkData();
 	}
 	}
 	state.workSectionNeedReset = false;
 	state.workSectionNeedReset = false;
 };
 };

+ 21 - 14
src/page-instrument/evaluat-model/evaluat-result/index.tsx

@@ -49,7 +49,8 @@ export default defineComponent({
       /** 生成评测记录的时候,记录当前评测的谱面类型,用于评测报告默认展示的谱面类型 */
       /** 生成评测记录的时候,记录当前评测的谱面类型,用于评测报告默认展示的谱面类型 */
       evaluatingData.resultData.scoreData.musicType = state.musicRenderType;
       evaluatingData.resultData.scoreData.musicType = state.musicRenderType;
       // 评测的速度,如果是选段,则选选段开头小节的速度
       // 评测的速度,如果是选段,则选选段开头小节的速度
-      const evaluatSpeed = state.sectionStatus && state.section.length === 2 && state.section[0].measureSpeed ? state.section[0].measureSpeed * state.basePlayRate : state.speed;      
+      const evaluatSpeed = state.sectionStatus && state.section.length === 2 && state.section[0].measureSpeed ? state.section[0].measureSpeed * state.basePlayRate : state.speed;  
+      const rate = state.basePlayRate * state.originAudioPlayRate; // 播放倍率    
       const body = {
       const body = {
         deviceType: browser().android ? "ANDROID" : "IOS", // 设备类型
         deviceType: browser().android ? "ANDROID" : "IOS", // 设备类型
         intonation: evaluatingData.resultData.intonation, // 音准
         intonation: evaluatingData.resultData.intonation, // 音准
@@ -68,7 +69,9 @@ export default defineComponent({
         playTime: evaluatingData.resultData.playTime / 1000, // 播放时长
         playTime: evaluatingData.resultData.playTime / 1000, // 播放时长
         heardLevel: state.setting.evaluationDifficulty, // 听力等级
         heardLevel: state.setting.evaluationDifficulty, // 听力等级
         recordFilePath: evaluatingData.resultData.url, // 录音文件路径
         recordFilePath: evaluatingData.resultData.url, // 录音文件路径
-        delFlag: evaluatingData.oneselfCancleEvaluating
+        delFlag: evaluatingData.oneselfCancleEvaluating,
+        instrumentId: state.instrumentId,
+        playRate: rate
       };
       };
       data.saveLoading = true;
       data.saveLoading = true;
       const res = await api_musicPracticeRecordSave(body);
       const res = await api_musicPracticeRecordSave(body);
@@ -172,27 +175,31 @@ export default defineComponent({
                 <img src={zlycImg} class={[styles.ctrlsBtn, "evaluting-result-2"]} onClick={() => emit("close", "tryagain")} />
                 <img src={zlycImg} class={[styles.ctrlsBtn, "evaluting-result-2"]} onClick={() => emit("close", "tryagain")} />
                 {evaluatingData.resultData.recordId ? (
                 {evaluatingData.resultData.recordId ? (
                   <div class={styles.saveBtn}>
                   <div class={styles.saveBtn}>
-                    <img src={noSaveTips.value ? bczpJzImg : bczpImg} class={[styles.ctrlsBtn, "evaluting-result-3"]} style={{ opacity: state.isHideEvaluatReportSaveBtn ? 0.4 : 1 }} onClick={() => {
-                      if (!noSaveTips.value && !state.isHideEvaluatReportSaveBtn) {
-                        saveResult()
-                      }
-                    }} />
-                    {
-                      noSaveTips.value && state.noSavePopShow ? 
+                    <img
+                      src={noSaveTips.value ? bczpJzImg : bczpImg}
+                      class={[styles.ctrlsBtn, "evaluting-result-3"]}
+                      style={{ opacity: state.isHideEvaluatReportSaveBtn ? 0.4 : 1 }}
+                      onClick={() => {
+                        if (!noSaveTips.value && !state.isHideEvaluatReportSaveBtn) {
+                          saveResult();
+                        }
+                      }}
+                    />
+                    {noSaveTips.value && state.noSavePopShow ? (
                       <div class={[styles.noSaveTip]}>
                       <div class={[styles.noSaveTip]}>
                         <span class={styles.arrowIcon}></span>
                         <span class={styles.arrowIcon}></span>
                         <span>{noSaveTips.value}</span>
                         <span>{noSaveTips.value}</span>
-                        <i onClick={() => state.noSavePopShow = false}></i>
-                      </div> : null                   
-                    }
+                        <i onClick={() => (state.noSavePopShow = false)}></i>
+                      </div>
+                    ) : null}
                   </div>
                   </div>
-                ) : null }
+                ) : null}
                 <img src={ckzpImg} class={[styles.ctrlsBtn, "evaluting-result-4", data.saveLoading ? styles.disablued : ""]} onClick={() => emit("close", "look")} />
                 <img src={ckzpImg} class={[styles.ctrlsBtn, "evaluting-result-4", data.saveLoading ? styles.disablued : ""]} onClick={() => emit("close", "look")} />
               </div>
               </div>
             </div>
             </div>
 
 
             {/* 评测模式-结果弹窗 功能引导 加载音频完成 不是会员 */}
             {/* 评测模式-结果弹窗 功能引导 加载音频完成 不是会员 */}
-            {evaluatingData.resulstMode && !evaluatingData.hideResultModal && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isVip && <EvaluatingResultDriver />}
+            {evaluatingData.resulstMode && !evaluatingData.hideResultModal && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isVip && !data.saveLoading && <EvaluatingResultDriver saveBtn={evaluatingData.resultData.recordId ? true : false} />}
           </div>
           </div>
         )}
         )}
       </>
       </>

+ 11 - 8
src/page-instrument/evaluat-model/index.tsx

@@ -156,7 +156,7 @@ export default defineComponent({
           checkErjiTimer = null;
           checkErjiTimer = null;
           setTimeout(() => {
           setTimeout(() => {
             evaluatingData.earphoneMode = false;
             evaluatingData.earphoneMode = false;
-          }, 3000);
+          }, 1500);
         } else {
         } else {
           // 如果没有佩戴有限耳机,需要持续检测耳机状态
           // 如果没有佩戴有限耳机,需要持续检测耳机状态
           checkErjiTimer = setTimeout(() => {
           checkErjiTimer = setTimeout(() => {
@@ -415,15 +415,18 @@ export default defineComponent({
       // 如果是异常状态,先等待500ms再执行后续流程
       // 如果是异常状态,先等待500ms再执行后续流程
       if (evaluatingData.isErrorState && !state.setting.soundEffect) {
       if (evaluatingData.isErrorState && !state.setting.soundEffect) {
         // console.log('异常流程1')
         // console.log('异常流程1')
-        showLoadingToast({
-          message: "处理中",
-          duration: 1000,
-          overlay: true,
-          overlayClass: styles.scoreMode,
-        });
+        // showLoadingToast({
+        //   message: "处理中",
+        //   duration: 1000,
+        //   overlay: true,
+        //   overlayClass: styles.scoreMode,
+        // });
+        state.loadingText = "处理中…";
+				state.isLoading = true;
         await new Promise<void>((resolve) => {
         await new Promise<void>((resolve) => {
           setTimeout(() => {
           setTimeout(() => {
-            closeToast();
+            // closeToast();
+            state.isLoading = false;
             evaluatingData.isErrorState = false;
             evaluatingData.isErrorState = false;
             // console.log('异常流程2')
             // console.log('异常流程2')
             resolve();
             resolve();

+ 4 - 3
src/page-instrument/follow-model/index.tsx

@@ -42,17 +42,18 @@ export default defineComponent({
           followData.isBeginMask && <div class={styles.beginMask}></div>
           followData.isBeginMask && <div class={styles.beginMask}></div>
         }        
         }        
         <div class={[styles.operatingBtn, state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.operatingLeft : ""]}>
         <div class={[styles.operatingBtn, state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.operatingLeft : ""]}>
-          {!followData.start && (
+          {(!followData.start && !followData.practiceStart) && (
             <img
             <img
               class={[styles.iconBtn, "follow-1"]}
               class={[styles.iconBtn, "follow-1"]}
               src={headImg("icon_play.png")}
               src={headImg("icon_play.png")}
               onClick={() => {
               onClick={() => {
-                followData.start = true;
+                // followData.start = true;
+                followData.practiceStart = true;
                 handleFollowStart();
                 handleFollowStart();
               }}
               }}
             />
             />
           )}
           )}
-          {followData.start && (
+          {(followData.start || followData.practiceStart)&& (
             <>
             <>
               <img class={styles.iconBtn} src={headImg("icon_reset.png")} onClick={() => handleFollowEnd()} />
               <img class={styles.iconBtn} src={headImg("icon_reset.png")} onClick={() => handleFollowEnd()} />
               <img class={styles.iconBtn} src={headImg("submit.png")} onClick={() => handleFollowEnd()} />
               <img class={styles.iconBtn} src={headImg("submit.png")} onClick={() => handleFollowEnd()} />

+ 156 - 84
src/page-instrument/header-top/index.module.less

@@ -6,7 +6,8 @@
     flex-shrink: 0;
     flex-shrink: 0;
     margin-left: calc(-1 * var(--detailDataPaddingLeft));
     margin-left: calc(-1 * var(--detailDataPaddingLeft));
     padding: 0 30px;
     padding: 0 30px;
-    background: linear-gradient( 180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.6) 100%);
+    background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 100%);
+
     &.headerTopRight {
     &.headerTopRight {
         justify-content: flex-end;
         justify-content: flex-end;
     }
     }
@@ -25,59 +26,68 @@
     left: 30px;
     left: 30px;
     bottom: 20px;
     bottom: 20px;
     border-radius: 16px;
     border-radius: 16px;
-    background-color: rgba(12,51,107,0.61);
+    background-color: rgba(12, 51, 107, 0.61);
     padding: 6px 11px;
     padding: 6px 11px;
     align-items: center;
     align-items: center;
     display: flex;
     display: flex;
     opacity: 0;
     opacity: 0;
     transition: all .3s ease-in;
     transition: all .3s ease-in;
-    & > div{
+
+    &>div {
         margin-left: 4px;
         margin-left: 4px;
         font-weight: 500;
         font-weight: 500;
         font-size: 14px;
         font-size: 14px;
         line-height: 20px;
         line-height: 20px;
-        color: rgba(255,255,255,0.7);
-    }    
-    & > img{
+        color: rgba(255, 255, 255, 0.7);
+    }
+
+    &>img {
         width: 18px;
         width: 18px;
         height: 18px;
         height: 18px;
     }
     }
+
     &.modeWarnRight {
     &.modeWarnRight {
         left: inherit;
         left: inherit;
         right: 30px;
         right: 30px;
     }
     }
 }
 }
-.headTopLeftBox{
+
+.headTopLeftBox {
     position: fixed;
     position: fixed;
     top: 20px;
     top: 20px;
     left: 30px;
     left: 30px;
     display: flex;
     display: flex;
     align-items: center;
     align-items: center;
-    .img{
+
+    .img {
         width: 32px;
         width: 32px;
         height: 32px;
         height: 32px;
     }
     }
-    .listImg{
+
+    .listImg {
         margin-left: 16px;
         margin-left: 16px;
     }
     }
-    .title{
-        width: 216px;
+
+    .title {
+        width: 210px;
         margin-left: 10px;
         margin-left: 10px;
         position: relative;
         position: relative;
-        .symbolNote{
+
+        .symbolNote {
             max-width: calc(216px + 16px);
             max-width: calc(216px + 16px);
             position: absolute;
             position: absolute;
             top: 0;
             top: 0;
             left: 0;
             left: 0;
             content: "";
             content: "";
-            width: calc(var(--noticeBarWidth,100%) + 16px);
+            width: calc(var(--noticeBarWidth, 100%) + 16px);
             height: 100%;
             height: 100%;
             background: url("./image/sj.png") no-repeat;
             background: url("./image/sj.png") no-repeat;
             background-size: 9px 6px;
             background-size: 9px 6px;
-            background-position: center right;                   
+            background-position: center right;
         }
         }
-        :global{
-            .van-notice-bar{
+
+        :global {
+            .van-notice-bar {
                 height: 30px;
                 height: 30px;
                 line-height: 30px;
                 line-height: 30px;
                 padding: 0;
                 padding: 0;
@@ -87,12 +97,22 @@
             }
             }
         }
         }
     }
     }
+    
+    .blackTitle {
+        :global{
+            .van-notice-bar{
+                color: #000 !important;
+            }
+        }
+    }
+
     .hidenBack {
     .hidenBack {
         opacity: 0;
         opacity: 0;
         pointer-events: none;
         pointer-events: none;
     }
     }
 }
 }
 .modeChangeBox{
 .modeChangeBox{
+    cursor: pointer;
     position: fixed;
     position: fixed;
     top: 20px;
     top: 20px;
     right: 30px;
     right: 30px;
@@ -102,17 +122,20 @@
     display: flex;
     display: flex;
     align-items: center;
     align-items: center;
     padding: 0 10px;
     padding: 0 10px;
-    .img{
+
+    .img {
         width: 18px;
         width: 18px;
         height: 18px;
         height: 18px;
     }
     }
-    .title{
+
+    .title {
         margin-left: 6px;
         margin-left: 6px;
         font-weight: 500;
         font-weight: 500;
         font-size: 14px;
         font-size: 14px;
         color: #FFFFFF;
         color: #FFFFFF;
     }
     }
 }
 }
+
 .headRight {
 .headRight {
     display: flex;
     display: flex;
     align-items: center;
     align-items: center;
@@ -126,13 +149,16 @@
         align-items: center;
         align-items: center;
         cursor: pointer;
         cursor: pointer;
         margin-right: 30px;
         margin-right: 30px;
-        &:last-child{
+
+        &:last-child {
             margin-right: 0;
             margin-right: 0;
         }
         }
+
         .iconBtn {
         .iconBtn {
             width: 24px;
             width: 24px;
             height: 24px;
             height: 24px;
         }
         }
+
         span {
         span {
             margin-top: 3px;
             margin-top: 3px;
             font-weight: 500;
             font-weight: 500;
@@ -140,97 +166,130 @@
             color: #FFFFFF;
             color: #FFFFFF;
             line-height: 17px;
             line-height: 17px;
         }
         }
-        &:active{
-            >span{
+
+        &:active {
+            >span {
                 color: #34D6FF
                 color: #34D6FF
-            };
+            }
+
+            ;
         }
         }
-        &.playType:active{
-            >img:nth-child(1){
+
+        &.playType:active {
+            >img:nth-child(1) {
                 content: url("./image/performAct.png");
                 content: url("./image/performAct.png");
-            }            
-            >img:nth-child(2){
+            }
+
+            >img:nth-child(2) {
                 content: url("./image/singAct.png");
                 content: url("./image/singAct.png");
             }
             }
         }
         }
-        &.playSource:active{
-            >img:nth-child(1){
+
+        &.playSource:active {
+            >img:nth-child(1) {
                 content: url("./image/musicAct.png");
                 content: url("./image/musicAct.png");
-            }            
-            >img:nth-child(2){
+            }
+
+            >img:nth-child(2) {
                 content: url("./image/backgroundAct.png");
                 content: url("./image/backgroundAct.png");
-            }            
-        }      
-        &.songSource:active{
-            >img:nth-child(1){
+            }
+        }
+
+        &.songSource:active {
+            >img:nth-child(1) {
                 content: url("./image/music1Act.png");
                 content: url("./image/music1Act.png");
-            }            
-            >img:nth-child(2){
+            }
+
+            >img:nth-child(2) {
                 content: url("./image/background1Act.png");
                 content: url("./image/background1Act.png");
-            }            
-            >img:nth-child(3){
+            }
+
+            >img:nth-child(3) {
                 content: url("./image/mingsongAct.png");
                 content: url("./image/mingsongAct.png");
             }
             }
         }
         }
-        &.section:active{
-            >img{
+
+        &.section:active {
+            >img {
                 content: url("./image/section2.png");
                 content: url("./image/section2.png");
             }
             }
         }
         }
-        &.isSection{
-            >span{
+
+        &.isSection {
+            >span {
                 color: #34D6FF
                 color: #34D6FF
-            };
+            }
+
+            ;
         }
         }
-        &.speed:active{
-            >img:nth-child(1){
+
+        &.speed:active {
+            >img:nth-child(1) {
                 content: url("./image/tickonAct.png");
                 content: url("./image/tickonAct.png");
-            }            
-            >img:nth-child(2){
+            }
+
+            >img:nth-child(2) {
                 content: url("./image/tickoffAct.png");
                 content: url("./image/tickoffAct.png");
-            } 
+            }
         }
         }
-        &.isSpeed{
-            >img:nth-child(1){
+
+        &.isSpeed {
+            >img:nth-child(1) {
                 content: url("./image/tickonAct.png");
                 content: url("./image/tickonAct.png");
-            }            
-            >img:nth-child(2){
+            }
+
+            >img:nth-child(2) {
                 content: url("./image/tickoffAct.png");
                 content: url("./image/tickoffAct.png");
-            } 
-            >span{
+            }
+
+            >span {
                 color: #34D6FF
                 color: #34D6FF
-            }; 
-        }      
-        &.settingMode:active{
-            >img{
+            }
+
+            ;
+        }
+
+        &.settingMode:active {
+            >img {
                 content: url("./image/icon_menuAct.png");
                 content: url("./image/icon_menuAct.png");
-            }            
-        }  
-        &.isSettingMode{
-            >img{
+            }
+        }
+
+        &.isSettingMode {
+            >img {
                 content: url("./image/icon_menuAct.png");
                 content: url("./image/icon_menuAct.png");
-            }            
-            >span{
+            }
+
+            >span {
                 color: #34D6FF
                 color: #34D6FF
-            }; 
-        }  
-        &.musicSheet:active{
-            >img{
+            }
+
+            ;
+        }
+
+        &.musicSheet:active {
+            >img {
                 content: url("./image/shengguiAct.png");
                 content: url("./image/shengguiAct.png");
-            }            
-        }       
-        &.isMusicSheet{
-            >img{
+            }
+        }
+
+        &.isMusicSheet {
+            >img {
                 content: url("./image/shengguiAct.png");
                 content: url("./image/shengguiAct.png");
-            }            
-            >span{
+            }
+
+            >span {
                 color: #34D6FF
                 color: #34D6FF
-            }; 
+            }
+
+            ;
         }
         }
     }
     }
-    .metronomeBtn{
+
+    .metronomeBtn {
         position: relative;
         position: relative;
-        .speedCon{
+
+        .speedCon {
             transform: scale(0.83);
             transform: scale(0.83);
             transform-origin: left bottom;
             transform-origin: left bottom;
             padding: 2px;
             padding: 2px;
@@ -243,11 +302,13 @@
             background: #FFC121;
             background: #FFC121;
             border-radius: 120px 120px 120px 1px;
             border-radius: 120px 120px 120px 1px;
             border: 1px solid #FFFFFF;
             border: 1px solid #FFFFFF;
-            >img{
+
+            >img {
                 width: 15px;
                 width: 15px;
                 height: 11px;
                 height: 11px;
             }
             }
-            >div{
+
+            >div {
                 margin-left: 1px;
                 margin-left: 1px;
                 font-weight: 600;
                 font-weight: 600;
                 font-size: 12px;
                 font-size: 12px;
@@ -264,10 +325,12 @@
 }
 }
 
 
 .playBtn {
 .playBtn {
+    cursor: pointer;
     position: fixed;
     position: fixed;
     right: 30px;
     right: 30px;
     bottom: 12px;
     bottom: 12px;
     transition: bottom .2s ease;
     transition: bottom .2s ease;
+
     .btnWrap {
     .btnWrap {
         width: 50px;
         width: 50px;
         height: 50px;
         height: 50px;
@@ -278,6 +341,7 @@
             height: 100%;
             height: 100%;
         }
         }
     }
     }
+
     &.playLeftButton {
     &.playLeftButton {
         left: 30px !important;
         left: 30px !important;
         right: auto !important;
         right: auto !important;
@@ -289,7 +353,7 @@
         left: auto !important;
         left: auto !important;
         bottom: 12px !important;
         bottom: 12px !important;
     }
     }
-    
+
     .progress {
     .progress {
         position: absolute;
         position: absolute;
         left: 50%;
         left: 50%;
@@ -301,6 +365,7 @@
 }
 }
 
 
 .resetBtn {
 .resetBtn {
+    cursor: pointer;
     position: fixed;
     position: fixed;
     right: 100px;
     right: 100px;
     bottom: 12px;
     bottom: 12px;
@@ -351,11 +416,13 @@
     background: url(./image/bg.png) no-repeat;
     background: url(./image/bg.png) no-repeat;
     background-size: cover;
     background-size: cover;
     transition: all .3s;
     transition: all .3s;
-    &.hidden{
+
+    &.hidden {
         opacity: 0;
         opacity: 0;
         transform: translateY(100%);
         transform: translateY(100%);
         pointer-events: none;
         pointer-events: none;
     }
     }
+
     .back {
     .back {
         position: absolute;
         position: absolute;
         width: 38px;
         width: 38px;
@@ -364,6 +431,7 @@
         top: 17px;
         top: 17px;
         cursor: pointer;
         cursor: pointer;
     }
     }
+
     .name {
     .name {
         position: absolute;
         position: absolute;
         left: 50%;
         left: 50%;
@@ -372,6 +440,7 @@
         width: 87px;
         width: 87px;
         height: 21px;
         height: 21px;
     }
     }
+
     .modeBox {
     .modeBox {
         width: 100%;
         width: 100%;
         display: flex;
         display: flex;
@@ -380,13 +449,16 @@
         position: relative;
         position: relative;
         top: 50%;
         top: 50%;
         transform: translateY(-50%);
         transform: translateY(-50%);
-        &.twoModeBox{
+
+        &.twoModeBox {
             justify-content: center;
             justify-content: center;
-            > .modeImg + .modeImg{
+
+            >.modeImg+.modeImg {
                 margin-left: 150px;
                 margin-left: 150px;
             }
             }
         }
         }
         > .modeImg {
         > .modeImg {
+            cursor: pointer;
             width: calc((100% - 2*40px)/3);
             width: calc((100% - 2*40px)/3);
             max-width: 220px;
             max-width: 220px;
         }
         }
@@ -400,6 +472,6 @@
     opacity: 0;
     opacity: 0;
 }
 }
 
 
-.socketErrorStatus{
+.socketErrorStatus {
     top: 20vh;
     top: 20vh;
 }
 }

+ 155 - 87
src/page-instrument/header-top/index.tsx

@@ -9,7 +9,7 @@ import { Badge, Circle, Popover, Popup, showConfirmDialog, showToast, NoticeBar
 import Speed from "./speed";
 import Speed from "./speed";
 import { evaluatingData, handleStartEvaluat } from "/src/view/evaluating";
 import { evaluatingData, handleStartEvaluat } from "/src/view/evaluating";
 import Settting from "./settting";
 import Settting from "./settting";
-import state, { IPlatform, handleChangeSection, handleResetPlay, handleRessetState, togglePlay, IPlayState, refreshMusicSvg } from "/src/state";
+import state, { IPlatform, handleChangeSection, handleResetPlay, handleRessetState, togglePlay, IPlayState, refreshMusicSvg, EnumMusicRenderType } from "/src/state";
 import { getAudioCurrentTime } from "/src/view/audio-list";
 import { getAudioCurrentTime } from "/src/view/audio-list";
 import { followData, toggleFollow } from "/src/view/follow-practice";
 import { followData, toggleFollow } from "/src/view/follow-practice";
 import { api_back } from "/src/helpers/communication";
 import { api_back } from "/src/helpers/communication";
@@ -77,10 +77,10 @@ export const headTopData = reactive({
         return;
         return;
       }
       }
       // 评测模式,只有一行谱模式
       // 评测模式,只有一行谱模式
-      if (!state.isSingleLine) {
-        state.isSingleLine = true;
-        refreshMusicSvg();
-      }
+      // if (!state.isSingleLine) {
+      //   state.isSingleLine = true;
+      //   refreshMusicSvg();
+      // }
       smoothAnimationState.isShow.value = false; // 隐藏旋律线
       smoothAnimationState.isShow.value = false; // 隐藏旋律线
       state.playIngSpeed = state.originSpeed;
       state.playIngSpeed = state.originSpeed;
       handleStartEvaluat();
       handleStartEvaluat();
@@ -102,7 +102,7 @@ export const headTopData = reactive({
   // 改变模式之前的状态
   // 改变模式之前的状态
   oldPlayType: "play",
   oldPlayType: "play",
   // 记录切换模式前的状态
   // 记录切换模式前的状态
-  oldModeType: "practise" as "practise" | "follow" | "evaluating"
+  oldModeType: "practise" as "practise" | "follow" | "evaluating",
 });
 });
 
 
 export const headData = reactive({
 export const headData = reactive({
@@ -115,7 +115,7 @@ let resetBtn: ComputedRef<{
   disabled: boolean;
   disabled: boolean;
 }>;
 }>;
 // 点击切换的时候才触发提醒
 // 点击切换的时候才触发提醒
-let isClickMode = false
+let isClickMode = false;
 /**
 /**
  * 处理模式切换
  * 处理模式切换
  * @param oldPlayType   没改变之前的播放模式
  * @param oldPlayType   没改变之前的播放模式
@@ -138,13 +138,13 @@ export function handlerModeChange(oldPlayType: "play" | "sing", oldPlaySource: I
     resetBtn && (resetBtn.value.display = false);
     resetBtn && (resetBtn.value.display = false);
   }
   }
   // 当模式改变的时候  放在这里是因为需要等谱面加载完成之后再提示(点击按钮模式切换才提示)
   // 当模式改变的时候  放在这里是因为需要等谱面加载完成之后再提示(点击按钮模式切换才提示)
-  if(isClickMode){
+  if (isClickMode) {
     showToast({
     showToast({
       message: state.playType === "play" ? "已切换为演奏场景" : "已切换为演唱场景",
       message: state.playType === "play" ? "已切换为演奏场景" : "已切换为演唱场景",
       position: "top",
       position: "top",
       className: "selectionToast",
       className: "selectionToast",
     });
     });
-    isClickMode = false
+    isClickMode = false;
   }
   }
 }
 }
 // 模式切换之后重新给times赋值
 // 模式切换之后重新给times赋值
@@ -156,7 +156,7 @@ function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPla
   // 演奏向演唱切
   // 演奏向演唱切
   if (oldPlayType === "play" && playType === "sing") {
   if (oldPlayType === "play" && playType === "sing") {
     if (playSource === "mingSong") {
     if (playSource === "mingSong") {
-      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间
+      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间  注意这修改了之后给总控平台的时值也需要改
       state.fixtime = difftime;
       state.fixtime = difftime;
       state.times.map((item) => {
       state.times.map((item) => {
         item.time = item.xmlNoteTime + difftime;
         item.time = item.xmlNoteTime + difftime;
@@ -228,7 +228,7 @@ function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPla
     // 演唱之间切换
     // 演唱之间切换
     // 切到唱名时候
     // 切到唱名时候
     if (playSource === "mingSong") {
     if (playSource === "mingSong") {
-      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间
+      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间  注意这修改了之后给总控平台的时值也需要改
       state.fixtime = difftime;
       state.fixtime = difftime;
       state.times.map((item) => {
       state.times.map((item) => {
         item.time = item.xmlNoteTime + difftime;
         item.time = item.xmlNoteTime + difftime;
@@ -268,7 +268,8 @@ export default defineComponent({
     // 是否显示引导
     // 是否显示引导
     const showGuide = ref(false);
     const showGuide = ref(false);
     const showStudentGuide = ref(false);
     const showStudentGuide = ref(false);
-    let  displayFingeringCache = false // 指法缓存
+    const showWebGuide = ref(true);
+    let displayFingeringCache = false; // 指法缓存
     /** 设置按钮 */
     /** 设置按钮 */
     const settingBtn = computed(() => {
     const settingBtn = computed(() => {
       // 音频播放中 禁用
       // 音频播放中 禁用
@@ -366,7 +367,7 @@ export default defineComponent({
     /** 原声按钮 */
     /** 原声按钮 */
     const originBtn = computed(() => {
     const originBtn = computed(() => {
       // 没有音源不显示
       // 没有音源不显示
-      if(state.noMusicSource) return { display: false, disabled: false };
+      if (state.noMusicSource) return { display: false, disabled: false };
       // 选择模式,跟练模式 不显示
       // 选择模式,跟练模式 不显示
       //if (headTopData.modeType !== "show" || state.modeType === "follow") return { display: false, disabled: false };
       //if (headTopData.modeType !== "show" || state.modeType === "follow") return { display: false, disabled: false };
       if (state.modeType === "follow") return { display: false, disabled: false };
       if (state.modeType === "follow") return { display: false, disabled: false };
@@ -412,8 +413,8 @@ export default defineComponent({
         // 演唱和演奏 都有数据的时间不禁用
         // 演唱和演奏 都有数据的时间不禁用
         if (songIndex > 0 && index > 0) {
         if (songIndex > 0 && index > 0) {
           // 音频播放中 禁用
           // 音频播放中 禁用
-          if(state.playState === "play"){
-            return { display: true, disabled: true }
+          if (state.playState === "play") {
+            return { display: true, disabled: true };
           }
           }
           return { display: true, disabled: false };
           return { display: true, disabled: false };
         }
         }
@@ -429,9 +430,9 @@ export default defineComponent({
       if (state.isPercussion && state.platform === IPlatform.PC) return { display: false, disabled: false };
       if (state.isPercussion && state.platform === IPlatform.PC) return { display: false, disabled: false };
       if(state.isCombineRender) return { display: false, disabled: false };
       if(state.isCombineRender) return { display: false, disabled: false };
       // 没有音源不显示
       // 没有音源不显示
-      if(state.noMusicSource) return { display: false, disabled: false };
+      if (state.noMusicSource) return { display: false, disabled: false };
       // 不是演奏模式 影藏
       // 不是演奏模式 影藏
-      if(state.playType !== "play") return { display: false, disabled: false }
+      if (state.playType !== "play") return { display: false, disabled: false };
       // 选择模式, url设置模式 不显示
       // 选择模式, url设置模式 不显示
       if (headTopData.modeType !== "show" || !headTopData.showBack) return { display: false, disabled: false };
       if (headTopData.modeType !== "show" || !headTopData.showBack) return { display: false, disabled: false };
       // 跟练开始, 评测开始 播放开始 隐藏
       // 跟练开始, 评测开始 播放开始 隐藏
@@ -446,7 +447,7 @@ export default defineComponent({
     /** 播放按钮 */
     /** 播放按钮 */
     const playBtn = computed(() => {
     const playBtn = computed(() => {
       // 没有音源不显示
       // 没有音源不显示
-      if(state.noMusicSource) return { display: false, disabled: false };
+      if (state.noMusicSource) return { display: false, disabled: false };
       // 选择模式 不显示
       // 选择模式 不显示
       if (headTopData.modeType !== "show") return { display: false, disabled: false };
       if (headTopData.modeType !== "show") return { display: false, disabled: false };
       // 评测模式 不显示,跟练模式 不显示
       // 评测模式 不显示,跟练模式 不显示
@@ -462,7 +463,7 @@ export default defineComponent({
     /** 重播按钮 */
     /** 重播按钮 */
     resetBtn = computed(() => {
     resetBtn = computed(() => {
       // 没有音源不显示
       // 没有音源不显示
-      if(state.noMusicSource) return { display: false, disabled: false };
+      if (state.noMusicSource) return { display: false, disabled: false };
       // 选择模式 不显示
       // 选择模式 不显示
       if (headTopData.modeType !== "show") return { display: false, disabled: false };
       if (headTopData.modeType !== "show") return { display: false, disabled: false };
       // 评测模式 不显示,跟练模式 不显示
       // 评测模式 不显示,跟练模式 不显示
@@ -558,6 +559,16 @@ export default defineComponent({
       if (res?.data?.api === "setPlayState") {
       if (res?.data?.api === "setPlayState") {
         togglePlay("paused", true);
         togglePlay("paused", true);
       }
       }
+      if(res?.data?.api === 'togglePlayState') {
+        // if(state.playState === "play") {
+        //   togglePlay("paused");
+        // }
+        // if(state.playState === 'paused') {
+        //   togglePlay("play");
+        // }
+        console.log('togglePlayState', state.playState)
+        togglePlay(state.playState === "play" ? "paused" : "play");
+      }
       // 上课页面,按钮方向
       // 上课页面,按钮方向
       if (res?.data?.api === "imagePos") {
       if (res?.data?.api === "imagePos") {
         if (res?.data.data) {
         if (res?.data.data) {
@@ -579,8 +590,14 @@ export default defineComponent({
         ? {
         ? {
             styleDrag: { value: null },
             styleDrag: { value: null },
           }
           }
-        : useDrag([`${parentClassName} .top_drag`, `${parentClassName} .bom_drag`], parentClassName, toRef(headTopData, "settingMode"), userId);
-
+        : useDrag([`${parentClassName} .top_draging`, `${parentClassName} .bom_drag`], parentClassName, toRef(headTopData, "settingMode"), userId);
+    const speedClassName = "speedBoxClass_drag";
+    const speedInfo =
+      state.platform !== IPlatform.PC
+        ? {
+            styleDrag: { value: null },
+          }
+        : useDrag([`${speedClassName} .top_draging`, `${speedClassName} .bom_drag`], speedClassName, toRef(headData, "speedShow"), userId);
     onMounted(() => {
     onMounted(() => {
       getQueryModelSetModelType();
       getQueryModelSetModelType();
       window.addEventListener("message", changePlay);
       window.addEventListener("message", changePlay);
@@ -589,21 +606,38 @@ export default defineComponent({
       } else {
       } else {
         showStudentGuide.value = true;
         showStudentGuide.value = true;
       }
       }
+
+      if (query.showWebGuide === "false") {
+        showWebGuide.value = false;
+      }
+
+      document.addEventListener("keydown", (e: KeyboardEvent) => {
+        if (e.code === "Tab") {
+          e.stopPropagation();
+          e.preventDefault();
+          // onStartPlayState();
+          togglePlay(state.playState === "play" ? "paused" : "play");
+        }
+      });
     });
     });
 
 
     onUnmounted(() => {
     onUnmounted(() => {
       window.removeEventListener("message", changePlay);
       window.removeEventListener("message", changePlay);
     });
     });
-    const noticeBarWidth = ref<number>()
-    watch(()=>smoothAnimationState.isShow.value, ()=>{
-      // NoticeBar能不能滚动
-      if((smoothAnimationState.isShow.value || state.isCombineRender) && isMusicList.value){
-        nextTick(()=>{
-          const widthCon = (document.querySelector("#noticeBarRollDom .van-notice-bar__content") as any)?.offsetWidth || undefined
-          noticeBarWidth.value = widthCon
-        })
-      }
-    },{ immediate: true })
+    const noticeBarWidth = ref<number>();
+    watch(
+      () => smoothAnimationState.isShow.value,
+      () => {
+        // NoticeBar能不能滚动
+        if ((smoothAnimationState.isShow.value || state.isCombineRender) && isMusicList.value) {
+          nextTick(() => {
+            const widthCon = (document.querySelector("#noticeBarRollDom .van-notice-bar__content") as any)?.offsetWidth || undefined;
+            noticeBarWidth.value = widthCon;
+          });
+        }
+      },
+      { immediate: true }
+    );
     // 设置改变触发
     // 设置改变触发
     watch(state.setting, () => {
     watch(state.setting, () => {
       console.log(state.setting, "state.setting");
       console.log(state.setting, "state.setting");
@@ -654,61 +688,66 @@ export default defineComponent({
           }}
           }}
         >
         >
           {/* 返回和标题 */}
           {/* 返回和标题 */}
-          {
-            !(state.playState == "play" || followData.start || evaluatingData.startBegin) &&
-              <div id="noticeBarRollDom" class={styles.headTopLeftBox}>
-                <img src={iconBack} class={['headTopBackBtn', styles.img, !headTopData.showBack && styles.hidenBack]} onClick={handleBack} />
-                {
-                  smoothAnimationState.isShow.value || state.isCombineRender ?
-                    <div 
-                      style={
-                        noticeBarWidth.value ? {
-                          "--noticeBarWidth":noticeBarWidth.value + "px"
-                        } : {}
-                      }
-                      class={[styles.title, "driver-8"]} 
-                      onClick={()=>{
-                        isMusicList.value && (musicListShow.value = true)
-                      }}>
-                        {
-                          isMusicList.value && <div class={styles.symbolNote}></div>
+          {!(state.playState == "play" || followData.start || evaluatingData.startBegin) && (
+            <div id="noticeBarRollDom" class={styles.headTopLeftBox}>
+              {
+                !query.isMove && <img src={iconBack} class={["headTopBackBtn", styles.img, !headTopData.showBack && styles.hidenBack]} onClick={handleBack} />
+              }
+              {smoothAnimationState.isShow.value || state.isCombineRender ? (
+                <div
+                  style={
+                    noticeBarWidth.value
+                      ? {
+                          "--noticeBarWidth": noticeBarWidth.value + "px",
                         }
                         }
-                        <NoticeBar
-                          text={state.examSongName}
-                          background="none"
-                        />
-                    </div> :
-                    isMusicList.value &&
-                    <img src={listImg} class={[styles.img, styles.listImg, "driver-8"]} onClick={()=>{
-                      musicListShow.value = true
-                    }} />
-                }
-              </div>
-          }
+                      : {}
+                  }
+                  class={[styles.title, state.isCbsView && styles.blackTitle, "headeTopTitleBtn"]}
+                  onClick={() => {
+                    isMusicList.value && (musicListShow.value = true);
+                  }}
+                >
+                  {isMusicList.value && <div class={[styles.symbolNote, "driver-8"]}></div>}
+                  <NoticeBar text={state.examSongName} background="none" />
+                </div>
+              ) : (
+                isMusicList.value && (
+                  <img
+                    src={listImg}
+                    class={[styles.img, styles.listImg, "driver-8"]}
+                    onClick={() => {
+                      musicListShow.value = true;
+                    }}
+                  />
+                )
+              )}
+            </div>
+          )}
+
           {/* 模式切换 */}
           {/* 模式切换 */}
           {
           {
-            <div 
+            <div
               id={state.platform === IPlatform.PC ? "teacherTop-0" : "studnetT-0"}
               id={state.platform === IPlatform.PC ? "teacherTop-0" : "studnetT-0"}
               style={{ display: toggleBtn.value.display ? "" : "none" }}
               style={{ display: toggleBtn.value.display ? "" : "none" }}
-              class={["driver-9", styles.modeChangeBox, toggleBtn.value.disabled && styles.disabled]} 
+              class={["driver-9", styles.modeChangeBox, toggleBtn.value.disabled && styles.disabled]}
               onClick={() => {
               onClick={() => {
-                  headTopData.oldModeType = state.modeType
-                  handleRessetState();
-                  headTopData.modeType = "init";
+                headTopData.oldModeType = state.modeType;
+                handleRessetState();
+                headTopData.modeType = "init";
               }}
               }}
             >
             >
               <img class={styles.img} src={iconMode} />
               <img class={styles.img} src={iconMode} />
-              <div class={styles.title}>{state.modeType==="practise" ? '练习模式' : state.modeType==="follow" ? "跟练模式" : state.modeType==="evaluating" ? "评测模式" : ""}</div>
+              <div class={styles.title}>{state.modeType === "practise" ? "练习模式" : state.modeType === "follow" ? "跟练模式" : state.modeType === "evaluating" ? "评测模式" : ""}</div>
             </div>
             </div>
           }
           }
+
           {/* 模式提醒 */}
           {/* 模式提醒 */}
-          {
-            state.modeType === "practise" &&
+          {state.modeType === "practise" && (
             <div class={[styles.modeWarn, "practiseModeWarn", state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.modeWarnRight : ""]}>
             <div class={[styles.modeWarn, "practiseModeWarn", state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.modeWarnRight : ""]}>
-                <img src={state.playType === "play" ? headImg("perform1.png") : headImg("sing1.png")} />
-                <div>{state.playType === "play" ? "演奏场景" : "演唱场景"}</div>
-              </div>
-          }
+              <img src={state.playType === "play" ? headImg("perform1.png") : headImg("sing1.png")} />
+              <div>{state.playType === "play" ? "演奏场景" : "演唱场景"}</div>
+            </div>
+          )}
           {/* 功能按钮 */}
           {/* 功能按钮 */}
           <div
           <div
             class={[styles.headRight]}
             class={[styles.headRight]}
@@ -745,10 +784,10 @@ export default defineComponent({
             ) : null} */}
             ) : null} */}
             <div
             <div
               style={{ display: playTypeBtn.value.display ? "" : "none" }}
               style={{ display: playTypeBtn.value.display ? "" : "none" }}
-              class={["driver-2", styles.btn, playTypeBtn.value.disabled && styles.disabled,styles.playType]}
+              class={["driver-2", styles.btn, playTypeBtn.value.disabled && styles.disabled, styles.playType]}
               onClick={() => {
               onClick={() => {
                 const oldPlayType = state.playType;
                 const oldPlayType = state.playType;
-                headTopData.oldPlayType = oldPlayType
+                headTopData.oldPlayType = oldPlayType;
                 const oldPlaySource = state.playSource;
                 const oldPlaySource = state.playSource;
                 if (state.playType === "play") {
                 if (state.playType === "play") {
                   state.playType = "sing";
                   state.playType = "sing";
@@ -757,7 +796,7 @@ export default defineComponent({
                   state.playType = "play";
                   state.playType = "play";
                   state.playSource = state.music ? "music" : "background";
                   state.playSource = state.music ? "music" : "background";
                 }
                 }
-                isClickMode = true
+                isClickMode = true;
                 // 有指法并且显示指法的时候 切换到演唱模式 需要影藏指法
                 // 有指法并且显示指法的时候 切换到演唱模式 需要影藏指法
                 let isRefresh = false;
                 let isRefresh = false;
                 if (state.isShowFingering && state.fingeringInfo.name && (state.setting.displayFingering || displayFingeringCache)) {
                 if (state.isShowFingering && state.fingeringInfo.name && (state.setting.displayFingering || displayFingeringCache)) {
@@ -788,7 +827,7 @@ export default defineComponent({
             <div
             <div
               id={state.platform === IPlatform.PC ? "teacherTop-1" : "studnetT-1"}
               id={state.platform === IPlatform.PC ? "teacherTop-1" : "studnetT-1"}
               style={{ display: originBtn.value.display ? "" : "none" }}
               style={{ display: originBtn.value.display ? "" : "none" }}
-              class={["driver-3", styles.btn, originBtn.value.disabled && styles.disabled,state.playType === "play"?styles.playSource:styles.songSource]}
+              class={["driver-3", styles.btn, originBtn.value.disabled && styles.disabled, state.playType === "play" ? styles.playSource : styles.songSource]}
               onClick={() => {
               onClick={() => {
                 const oldPlayType = state.playType;
                 const oldPlayType = state.playType;
                 const oldPlaySource = state.playSource;
                 const oldPlaySource = state.playSource;
@@ -816,7 +855,12 @@ export default defineComponent({
               <img style={{ display: state.playSource === "mingSong" ? "" : "none" }} class={styles.iconBtn} src={headImg(`mingsong.png`)} />
               <img style={{ display: state.playSource === "mingSong" ? "" : "none" }} class={styles.iconBtn} src={headImg(`mingsong.png`)} />
               <span>{state.playSource === "music" ? (state.playType === "play" ? "原声" : "范唱") : state.playSource === "background" ? (state.playType === "play" ? "伴奏" : "伴唱") : "唱名"}</span>
               <span>{state.playSource === "music" ? (state.playType === "play" ? "原声" : "范唱") : state.playSource === "background" ? (state.playType === "play" ? "伴奏" : "伴唱") : "唱名"}</span>
             </div>
             </div>
-            <div id={state.platform === IPlatform.PC ? "teacherTop-2" : "studnetT-2"} style={{ display: selectBtn.value.display ? "" : "none" }} class={["driver-4", styles.btn, selectBtn.value.disabled && styles.disabled, styles.section, state.sectionStatus && styles.isSection]} onClick={() => handleChangeSection()}>
+            <div
+              id={state.platform === IPlatform.PC ? "teacherTop-2" : "studnetT-2"}
+              style={{ display: selectBtn.value.display ? "" : "none" }}
+              class={["driver-4", styles.btn, selectBtn.value.disabled && styles.disabled, styles.section, state.sectionStatus && styles.isSection]}
+              onClick={() => handleChangeSection()}
+            >
               <img style={{ display: state.section.length === 0 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section0.png`)} />
               <img style={{ display: state.section.length === 0 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section0.png`)} />
               <img style={{ display: state.section.length === 1 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section1.png`)} />
               <img style={{ display: state.section.length === 1 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section1.png`)} />
               <img style={{ display: state.section.length === 2 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section2.png`)} />
               <img style={{ display: state.section.length === 2 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section2.png`)} />
@@ -826,7 +870,7 @@ export default defineComponent({
               <>
               <>
                 <div
                 <div
                   style={{ display: metronomeBtn.value.display ? "" : "none" }}
                   style={{ display: metronomeBtn.value.display ? "" : "none" }}
-                  class={["driver-5", styles.btn, styles.metronomeBtn, metronomeBtn.value.disabled && styles.disabled,headData.speedShow && styles.isSpeed,styles.speed]}
+                  class={["driver-5", styles.btn, styles.metronomeBtn, metronomeBtn.value.disabled && styles.disabled, headData.speedShow && styles.isSpeed, styles.speed]}
                   onClick={async () => {
                   onClick={async () => {
                     headData.speedShow = !headData.speedShow;
                     headData.speedShow = !headData.speedShow;
                   }}
                   }}
@@ -840,7 +884,7 @@ export default defineComponent({
                   </div>
                   </div>
                 </div>
                 </div>
                 {
                 {
-                  <Popup v-model:show={headData.speedShow} class="popup-custom van-scale center-closeBtn settingBoxClass_drag" transition="van-scale" teleport="body" style={positionInfo.styleDrag.value} overlay-style={{ background: "rgba(0, 0, 0, 0.3)" }}>
+                  <Popup v-model:show={headData.speedShow} class="popup-custom van-scale center-closeBtn speedBoxClass_drag" transition="van-scale" teleport="body" style={speedInfo.styleDrag.value} overlay-style={{ background: "rgba(0, 0, 0, 0.3)" }}>
                     <Speed />
                     <Speed />
                     {state.platform === IPlatform.PC && <Dragbom showGuide={!state.guideInfo?.teacherDrag} onGuideDone={handleGuide} />}
                     {state.platform === IPlatform.PC && <Dragbom showGuide={!state.guideInfo?.teacherDrag} onGuideDone={handleGuide} />}
                   </Popup>
                   </Popup>
@@ -870,7 +914,7 @@ export default defineComponent({
             ) : null} */}
             ) : null} */}
             {state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert && (
             {state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert && (
               <div
               <div
-                class={[styles.btn, state.playState === "play" && fingeringBtn.value.disabled && styles.disabled,toggleMusicSheet.show&&styles.isMusicSheet,styles.musicSheet]}
+                class={[styles.btn, state.playState === "play" && fingeringBtn.value.disabled && styles.disabled, toggleMusicSheet.show && styles.isMusicSheet, styles.musicSheet, "driver-10"]}
                 onClick={() => {
                 onClick={() => {
                   toggleMusicSheet.toggle(true);
                   toggleMusicSheet.toggle(true);
                 }}
                 }}
@@ -879,7 +923,12 @@ export default defineComponent({
                 <span>声部</span>
                 <span>声部</span>
               </div>
               </div>
             )}
             )}
-            <div id={state.platform === IPlatform.PC ? "teacherTop-6" : "studnetT-6"} style={{ display: settingBtn.value.display ? "" : "none" }} class={["driver-6", styles.btn, settingBtn.value.disabled && styles.disabled,headTopData.settingMode&&styles.isSettingMode,styles.settingMode]} onClick={() => (headTopData.settingMode = true)}>
+            <div
+              id={state.platform === IPlatform.PC ? "teacherTop-6" : "studnetT-6"}
+              style={{ display: settingBtn.value.display ? "" : "none" }}
+              class={["driver-6", styles.btn, settingBtn.value.disabled && styles.disabled, headTopData.settingMode && styles.isSettingMode, styles.settingMode]}
+              onClick={() => (headTopData.settingMode = true)}
+            >
               <img class={styles.iconBtn} src={headImg("icon_menu.png")} />
               <img class={styles.iconBtn} src={headImg("icon_menu.png")} />
               <span>设置</span>
               <span>设置</span>
             </div>
             </div>
@@ -905,7 +954,21 @@ export default defineComponent({
             playBtn.value.disabled && styles.disabled,
             playBtn.value.disabled && styles.disabled,
             state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.playLeftButton : state.platform === IPlatform.PC && state.musicScoreBtnDirection === "right" ? styles.playRightButton : "",
             state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.playLeftButton : state.platform === IPlatform.PC && state.musicScoreBtnDirection === "right" ? styles.playRightButton : "",
           ]}
           ]}
-          onClick={() => togglePlay(state.playState === "play" ? "paused" : "play")}
+          onClick={() => {
+            // C调能播放唱名,非C调时,只有谱面类型是首调时,才能播放唱名
+            if (!state.isCTone && state.playSource === 'mingSong') {
+              const notPlayDesc = state.musicRenderType === EnumMusicRenderType.staff ? '该曲目的五线谱目前还不支持播放唱名' : state.musicRenderType === EnumMusicRenderType.fixedTone ? '该曲目的固定调目前还不支持播放唱名' : '';
+              if (notPlayDesc) {
+                showToast({
+                  message: notPlayDesc,
+                  position: "top",
+                  className: "selectionToast",
+                });
+                return
+              }
+            }
+            togglePlay(state.playState === "play" ? "paused" : "play")
+          }}
         >
         >
           <div class={styles.btnWrap}>
           <div class={styles.btnWrap}>
             <img style={{ display: state.playState === "play" ? "none" : "" }} class={styles.iconBtn} src={headImg("icon_play.png")} />
             <img style={{ display: state.playState === "play" ? "none" : "" }} class={styles.iconBtn} src={headImg("icon_play.png")} />
@@ -938,17 +1001,22 @@ export default defineComponent({
         {isAllBtnsStudent.value && !query.isCbs && showGuideIndex.value && <StudentTop></StudentTop>} */}
         {isAllBtnsStudent.value && !query.isCbs && showGuideIndex.value && <StudentTop></StudentTop>} */}
 
 
         {/* 练习模式功能引导 加载音频完成 不是会员 */}
         {/* 练习模式功能引导 加载音频完成 不是会员 */}
-        {state.modeType === "practise" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && (
+        {state.modeType === "practise" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && showWebGuide.value && (
           <PractiseDriver
           <PractiseDriver
             statusAll={{
             statusAll={{
+              playBtnStatus: playBtn.value.display,
               subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
               subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
               modelTypeStatus: toggleBtn.value.display,
               modelTypeStatus: toggleBtn.value.display,
               playType: playTypeBtn.value.display,
               playType: playTypeBtn.value.display,
+              originPlayType: state.playType === "play" ? true : false,
+              originBtnStatus: originBtn.value.display,
+              backTitle: !(state.playState == "play" || followData.start || evaluatingData.startBegin) && isMusicList.value,
+              titleType: smoothAnimationState.isShow.value ? "TEXT" : isMusicList.value ? "IMG" : "NONE",
             }}
             }}
           />
           />
         )}
         )}
         {/* 跟练模式功能引导 加载音频完成 不是会员 */}
         {/* 跟练模式功能引导 加载音频完成 不是会员 */}
-        {state.modeType === "follow" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && (
+        {state.modeType === "follow" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && showWebGuide.value && (
           <FollowDriver
           <FollowDriver
             statusAll={{
             statusAll={{
               subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
               subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
@@ -956,7 +1024,7 @@ export default defineComponent({
           />
           />
         )}
         )}
         {/* 评测模式功能引导 加载音频完成 不是会员 */}
         {/* 评测模式功能引导 加载音频完成 不是会员 */}
-        {state.modeType === "evaluating" && headTopData.modeType !== "init" && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && evaluatingData.websocketState && !evaluatingData.startBegin && evaluatingData.checkEnd && (
+        {state.modeType === "evaluating" && headTopData.modeType !== "init" && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && evaluatingData.websocketState && !evaluatingData.startBegin && evaluatingData.checkEnd && showWebGuide.value && (
           <EvaluatingDriver
           <EvaluatingDriver
             statusAll={{
             statusAll={{
               subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
               subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
@@ -966,4 +1034,4 @@ export default defineComponent({
       </>
       </>
     );
     );
   },
   },
-});
+});

+ 6 - 2
src/page-instrument/header-top/modeView.tsx

@@ -107,7 +107,9 @@ export default defineComponent({
           src={backImg}
           src={backImg}
           class={styles.back}
           class={styles.back}
           onClick={() => {
           onClick={() => {
-            smoothAnimationState.isShow.value = state.melodyLine;
+            if(state.isSingleLine){
+              smoothAnimationState.isShow.value = state.melodyLine;
+            }
             // 返回的时候 跳转到之前记录的模式
             // 返回的时候 跳转到之前记录的模式
             if(headTopData.oldModeType !== "practise"){
             if(headTopData.oldModeType !== "practise"){
               // 点击评测模式进入评测模块的需要检测耳机状态,通过返回按钮进入评测模块的,不检测耳机状态
               // 点击评测模式进入评测模块的需要检测耳机状态,通过返回按钮进入评测模块的,不检测耳机状态
@@ -120,7 +122,9 @@ export default defineComponent({
         <img src={nameImg} class={styles.name} />
         <img src={nameImg} class={styles.name} />
         <div class={[styles.modeBox, ((!state.isPercussion && !state.enableEvaluation) || (state.isPercussion && state.enableEvaluation) || (state.isPercussion && !state.enableEvaluation)) && styles.twoModeBox]}>
         <div class={[styles.modeBox, ((!state.isPercussion && !state.enableEvaluation) || (state.isPercussion && state.enableEvaluation) || (state.isPercussion && !state.enableEvaluation)) && styles.twoModeBox]}>
           <Vue3Lottie ref={modeImgDom1} class={styles.modeImg} animationData={lxMode} autoPlay={false} loop={true} onClick={() => {
           <Vue3Lottie ref={modeImgDom1} class={styles.modeImg} animationData={lxMode} autoPlay={false} loop={true} onClick={() => {
-            smoothAnimationState.isShow.value = state.melodyLine;
+            if(state.isSingleLine){
+              smoothAnimationState.isShow.value = state.melodyLine;
+            }
             headTopData.handleChangeModeType("practise")
             headTopData.handleChangeModeType("practise")
             } }></Vue3Lottie>
             } }></Vue3Lottie>
           {!state.isPercussion && <Vue3Lottie ref={modeImgDom2} class={styles.modeImg} animationData={glMode} autoPlay={false} loop={true} onClick={() => headTopData.handleChangeModeType("follow")}></Vue3Lottie>}
           {!state.isPercussion && <Vue3Lottie ref={modeImgDom2} class={styles.modeImg} animationData={glMode} autoPlay={false} loop={true} onClick={() => headTopData.handleChangeModeType("follow")}></Vue3Lottie>}

+ 3 - 2
src/page-instrument/header-top/settting/index.module.less

@@ -256,6 +256,7 @@
                                 font-weight: 600;
                                 font-weight: 600;
                                 font-size: 15px;
                                 font-size: 15px;
                                 color: #1CACF1;
                                 color: #1CACF1;
+                                caret-color: #1cacf1;
                             }
                             }
                         }
                         }
                     }
                     }
@@ -276,8 +277,8 @@
                     width: 118px;
                     width: 118px;
                     height: 39px;
                     height: 39px;
                     cursor: pointer;
                     cursor: pointer;
-                    &:first-child{
-                        margin-right: 20px;
+                    & + img{
+                        margin-left: 20px;
                     }
                     }
                 }
                 }
             }
             }

+ 27 - 23
src/page-instrument/header-top/settting/index.tsx

@@ -3,7 +3,7 @@ import styles from "./index.module.less"
 import { headImg } from "../image";
 import { headImg } from "../image";
 import { headTopData } from "../index"
 import { headTopData } from "../index"
 import { Switch, showToast, Field, Popup, Slider } from "vant";
 import { Switch, showToast, Field, Popup, Slider } from "vant";
-import state, { refreshMusicSvg, IPlatform } from "/src/state"
+import state, { refreshMusicSvg, IPlatform, checkMoveNoSave } from "/src/state"
 import { api_closeCamera, api_openCamera, api_savePicture } from "/src/helpers/communication";
 import { api_closeCamera, api_openCamera, api_savePicture } from "/src/helpers/communication";
 import { smoothAnimationState} from "/src/page-instrument/view-detail/smoothAnimation"
 import { smoothAnimationState} from "/src/page-instrument/view-detail/smoothAnimation"
 import Recommendation from "../../custom-plugins/helper-model/recommendation";
 import Recommendation from "../../custom-plugins/helper-model/recommendation";
@@ -32,7 +32,7 @@ export default defineComponent({
 			? {
 			? {
 				styleDrag: { value: null },
 				styleDrag: { value: null },
 			  }
 			  }
-			: useDrag([`${parentClassName} .top_drag`, `${parentClassName} .bom_drag`], parentClassName, toRef(helperData, "recommendationShow"), userId);
+			: useDrag([`${parentClassName} .top_draging`, `${parentClassName} .bom_drag`], parentClassName, toRef(helperData, "recommendationShow"), userId);
 
 
 		// 完成拖动弹窗引导页
 		// 完成拖动弹窗引导页
 		const handleGuide = async () => {
 		const handleGuide = async () => {
@@ -66,7 +66,7 @@ export default defineComponent({
 
 
 		return () => (
 		return () => (
 			<div class={[styles.settting, styles[state.modeType]]}>
 			<div class={[styles.settting, styles[state.modeType]]}>
-                <div class={styles.head}>
+                <div class={[styles.head, "top_draging"]}>
 					<img class={styles.headTit} src={headImg("settingName.png")} />
 					<img class={styles.headTit} src={headImg("settingName.png")} />
 					<img class={styles.closeImg} src={headImg("closeImg.png")} onClick={()=>{ headTopData.settingMode = false }} />
 					<img class={styles.closeImg} src={headImg("closeImg.png")} onClick={()=>{ headTopData.settingMode = false }} />
 				</div>
 				</div>
@@ -87,12 +87,24 @@ export default defineComponent({
                                 </div>
                                 </div>
                         }                        
                         }                        
                         {
                         {
+                            state.isSingleLine && state.modeType === "practise" && !state.isCombineRender && !state.isPercussion && 
+                                <div class={styles.cellBox}>
+                                <div class={styles.tit}>旋律线</div>
+                                    <Switch 
+                                        v-model={smoothAnimationState.isShow.value}
+                                        onChange={(value) => {
+                                            state.melodyLine = value
+                                        }}                                        
+                                    ></Switch>
+                                </div>   
+                        }
+                        {
                             state.modeType === 'practise' && state.mingSong && state.mingSongGirl &&
                             state.modeType === 'practise' && state.mingSong && state.mingSongGirl &&
                             <div class={styles.cellBox}>
                             <div class={styles.cellBox}>
                                 <div class={styles.tit}>唱名类型</div>
                                 <div class={styles.tit}>唱名类型</div>
                                 <div class={styles.radioBox}>
                                 <div class={styles.radioBox}>
                                     {
                                     {
-                                        [{name:'男生',value:1}, {name:'女生',value:0}].map(item=>{
+                                        [{name:'男声',value:1}, {name:'女声',value:0}].map(item=>{
                                             return <div class={ audioData.mingSongType===item.value && styles.active } onClick={ ()=>{ 
                                             return <div class={ audioData.mingSongType===item.value && styles.active } onClick={ ()=>{ 
                                                 if(audioData.mingSongType === item.value){
                                                 if(audioData.mingSongType === item.value){
                                                     return
                                                     return
@@ -104,19 +116,7 @@ export default defineComponent({
                                     }
                                     }
                                 </div>
                                 </div>
                             </div>                     
                             </div>                     
-                        }
-                        {
-                            state.isSingleLine && state.modeType === "practise" && !state.isCombineRender && !state.isPercussion && 
-                                <div class={styles.cellBox}>
-                                <div class={styles.tit}>旋律线</div>
-                                    <Switch 
-                                        v-model={smoothAnimationState.isShow.value}
-                                        onChange={(value) => {
-                                            state.melodyLine = value
-                                        }}                                        
-                                    ></Switch>
-                                </div>   
-                        }                           
+                        }                        
                         {
                         {
                             state.modeType === "evaluating" && 
                             state.modeType === "evaluating" && 
                             <>                       
                             <>                       
@@ -202,20 +202,21 @@ export default defineComponent({
                         }
                         }
                         {/** 练习模式才有单行/多行谱切换功能,跟练、评测只有单行谱模式 */}
                         {/** 练习模式才有单行/多行谱切换功能,跟练、评测只有单行谱模式 */}
                         {
                         {
-                            state.modeType === 'practise' ? 
+                            ["practise", "evaluating"].includes(state.modeType) ? 
                             <div class={styles.cellBox}>
                             <div class={styles.cellBox}>
                                 <div class={styles.tit}>切换谱面</div>
                                 <div class={styles.tit}>切换谱面</div>
                                 <div class={styles.radioBox}>
                                 <div class={styles.radioBox}>
                                     {
                                     {
                                         [{name:'单行谱',value:true},{name:'多行谱',value:false}].map(item=>{
                                         [{name:'单行谱',value:true},{name:'多行谱',value:false}].map(item=>{
-                                            return <div class={ state.isSingleLine===item.value && styles.active } onClick={ ()=>{ 
+                                            return <div class={ state.isSingleLine===item.value && styles.active } onClick={ async ()=>{ 
                                                 if(state.isSingleLine === item.value){
                                                 if(state.isSingleLine === item.value){
                                                     return
                                                     return
                                                 }
                                                 }
+                                                await checkMoveNoSave();
                                                 headTopData.settingMode = false
                                                 headTopData.settingMode = false
-                                                state.isSingleLine = item.value 
                                                 // resetRenderMusicScore(state.musicRenderType)
                                                 // resetRenderMusicScore(state.musicRenderType)
                                                 const _time = setTimeout(() => {
                                                 const _time = setTimeout(() => {
+                                                    state.isSingleLine = item.value 
                                                     clearTimeout(_time)
                                                     clearTimeout(_time)
                                                     refreshMusicSvg();
                                                     refreshMusicSvg();
                                                 }, 100);
                                                 }, 100);
@@ -233,14 +234,15 @@ export default defineComponent({
                                 <div class={styles.radioBox}>
                                 <div class={styles.radioBox}>
                                     {
                                     {
                                         notationList.value.map(item=>{
                                         notationList.value.map(item=>{
-                                            return <div class={ state.musicRenderType===item.value && styles.active } onClick={ ()=>{ 
+                                            return <div class={ state.musicRenderType===item.value && styles.active } onClick={ async ()=>{ 
                                                 if(state.musicRenderType === item.value){
                                                 if(state.musicRenderType === item.value){
                                                     return
                                                     return
                                                 }
                                                 }
+                                                await checkMoveNoSave();
                                                 headTopData.settingMode = false
                                                 headTopData.settingMode = false
-                                                state.musicRenderType = item.value as any
                                                 // resetRenderMusicScore(state.musicRenderType)
                                                 // resetRenderMusicScore(state.musicRenderType)
                                                 const _time = setTimeout(() => {
                                                 const _time = setTimeout(() => {
+                                                    state.musicRenderType = item.value as any
                                                     clearTimeout(_time)
                                                     clearTimeout(_time)
                                                     refreshMusicSvg();
                                                     refreshMusicSvg();
                                                 }, 100);
                                                 }, 100);
@@ -253,7 +255,9 @@ export default defineComponent({
 
 
                         <div class={styles.cellBtnBox}>
                         <div class={styles.cellBtnBox}>
                             <img  src={headImg("tpbz.png")} onClick={() => (helperData.screenModelShow = true)} />
                             <img  src={headImg("tpbz.png")} onClick={() => (helperData.screenModelShow = true)} />
-                            <img  src={headImg("yjfk.png")} onClick={() => (helperData.recommendationShow = true)} />
+                            {
+                                !query.isCbs && <img  src={headImg("yjfk.png")} onClick={() => (helperData.recommendationShow = true)} />
+                            }
                         </div>
                         </div>
                     </div>  
                     </div>  
                 </div>
                 </div>

+ 2 - 2
src/page-instrument/header-top/speed/index.module.less

@@ -168,7 +168,6 @@
             .speedSel{
             .speedSel{
                 margin-top: 20px;
                 margin-top: 20px;
                 padding-bottom: 18px;
                 padding-bottom: 18px;
-                border-bottom: 1px solid #D5E0ED;
                 display: flex;
                 display: flex;
                 justify-content: space-between;
                 justify-content: space-between;
                 & > div{
                 & > div{
@@ -191,7 +190,8 @@
                 pointer-events: none;
                 pointer-events: none;
             }
             }
             .metronome{
             .metronome{
-                margin-top: 18px;
+                padding-top: 18px;
+                border-top: 1px solid #D5E0ED;
                 display: flex;
                 display: flex;
                 justify-content: space-between;
                 justify-content: space-between;
                 align-items: center;
                 align-items: center;

+ 13 - 10
src/page-instrument/header-top/speed/index.tsx

@@ -106,7 +106,7 @@ export default defineComponent({
 		};
 		};
 		return () => (
 		return () => (
 			<div class={[styles.speedContainer, styles[state.modeType]]}>
 			<div class={[styles.speedContainer, styles[state.modeType]]}>
-				<div class={styles.head}>
+				<div class={[styles.head, "top_draging"]}>
 					<img class={styles.headTit} src={headImg("headTit.png")} />
 					<img class={styles.headTit} src={headImg("headTit.png")} />
 					<img class={styles.closeImg} src={headImg("closeImg.png")} onClick={()=>{ headData.speedShow = false }} />
 					<img class={styles.closeImg} src={headImg("closeImg.png")} onClick={()=>{ headData.speedShow = false }} />
 				</div>
 				</div>
@@ -136,15 +136,18 @@ export default defineComponent({
 							<div onClick={()=>{ speed.value = 100 }}>100</div>
 							<div onClick={()=>{ speed.value = 100 }}>100</div>
 							<div onClick={()=>{ speed.value = 110 }}>110</div>
 							<div onClick={()=>{ speed.value = 110 }}>110</div>
 						</div>
 						</div>
-						<div class={styles.metronome}>
-							<div class={styles.tit}>节拍器</div>
-							<Switch 
-								class={switchLoading.value ? styles.switchLoading : ''}
-								v-model:modelValue={metronomeDisable.value} 
-								loading={switchLoading.value}
-								onChange={toggleSwitch}			
-							></Switch>
-						</div>
+						{
+							state.isMixBeat && 
+							<div class={styles.metronome}>
+								<div class={styles.tit}>节拍器</div>
+								<Switch 
+									class={switchLoading.value ? styles.switchLoading : ''}
+									v-model:modelValue={metronomeDisable.value} 
+									loading={switchLoading.value}
+									onChange={toggleSwitch}			
+								></Switch>
+							</div>
+						}
 					</div>
 					</div>
 				</div>
 				</div>
 			</div>
 			</div>

+ 1 - 0
src/page-instrument/simple-detail/index.tsx

@@ -43,6 +43,7 @@ export default defineComponent({
 				if (currentTime === 0) {
 				if (currentTime === 0) {
 					// 坐标和小节都改为初始值
 					// 坐标和小节都改为初始值
 					setTimeout(() => {
 					setTimeout(() => {
+						detailData.currentTime = 0
 						state.activeNoteIndex = 0
 						state.activeNoteIndex = 0
 						state.activeMeasureIndex = state.times[0].MeasureNumberXML;
 						state.activeMeasureIndex = state.times[0].MeasureNumberXML;
 						handlePlaying(true);
 						handlePlaying(true);

BIN
src/page-instrument/view-detail/images/bg2_left_zs.png


+ 159 - 11
src/page-instrument/view-detail/index.module.less

@@ -10,6 +10,20 @@
     --van-skeleton-paragraph-height: .8rem;
     --van-skeleton-paragraph-height: .8rem;
 }
 }
 
 
+:global {
+
+    // .headHeight>.driver-active-element,
+    // #noticeBarRollDom>.driver-active-element,
+    // :not(body):has(>.headHeight),
+    // :not(body):has(>#noticeBarRollDom),
+    body .headeTopTitleBtn,
+    body #noticeBarRollDom {
+        overflow: initial !important;
+    }
+
+
+}
+
 .detail {
 .detail {
     position: relative;
     position: relative;
     width: 100vw;
     width: 100vw;
@@ -17,6 +31,7 @@
     overflow: hidden;
     overflow: hidden;
     --header-height: 80px;
     --header-height: 80px;
     --pc-header-height: 72px;
     --pc-header-height: 72px;
+
     // &.practise{
     // &.practise{
     //     background: url("./images/bg1.png") no-repeat;
     //     background: url("./images/bg1.png") no-repeat;
     //     background-size: 100% 100%;
     //     background-size: 100% 100%;
@@ -36,7 +51,17 @@
         width: 100%;
         width: 100%;
         height: 100%;
         height: 100%;
         object-fit: cover; /* 保持宽高比 */
         object-fit: cover; /* 保持宽高比 */
+        &.practise{
+            background-color: #213793;
+        }        
+        &.follow{
+            background-color: #114067;
+        }        
+        &.evaluating{
+            background-color: #142979;
+        }
     }
     }
+
     .headHeight {
     .headHeight {
         position: absolute;
         position: absolute;
         bottom: 0;
         bottom: 0;
@@ -47,15 +72,18 @@
 
 
         &.headHide {
         &.headHide {
             margin-bottom: calc(0Px - var(--header-height));
             margin-bottom: calc(0Px - var(--header-height));
-            :global{
-                .practiseModeWarn{
+
+            :global {
+                .practiseModeWarn {
                     opacity: 1;
                     opacity: 1;
+
                     img {
                     img {
                         opacity: 0.7;
                         opacity: 0.7;
                     }
                     }
                 }
                 }
             }
             }
         }
         }
+
     }
     }
 
 
     .container {
     .container {
@@ -66,17 +94,20 @@
         transition: height .2s;
         transition: height .2s;
         transition: padding-bottom .2s;
         transition: padding-bottom .2s;
         overflow: hidden;
         overflow: hidden;
-        :global{
+
+        :global {
             #musicAndSelection {
             #musicAndSelection {
-                // 其他位置 这个高度留白是36,这里加了一点,让旋律线靠下一点
-                padding-top: 40px;
+                --musicAndSelectionTop: 40px;
+                padding-top: var(--musicAndSelectionTop);
             }
             }
         }
         }
     }
     }
+
     .pcContainer {
     .pcContainer {
         // height: calc(100vh - var(--header-height) - var(--pc-header-height));
         // height: calc(100vh - var(--header-height) - var(--pc-header-height));
     }
     }
-    .fingeringCon{
+
+    .fingeringCon {
         transition: scale 0.2s;
         transition: scale 0.2s;
     }
     }
 }
 }
@@ -177,33 +208,116 @@
 
 
 .preViewDetail {
 .preViewDetail {
     background: #fff !important;
     background: #fff !important;
+
     >.pageBg {
     >.pageBg {
         display: none;
         display: none;
     }
     }
+
     .headHeight {
     .headHeight {
         background: #fff !important;
         background: #fff !important;
     }
     }
+
     .container {
     .container {
         height: 100%;
         height: 100%;
         padding-bottom: 0 !important;
         padding-bottom: 0 !important;
         padding-right: 0 !important;
         padding-right: 0 !important;
+        padding-left: 0 !important;
     }
     }
+
     :global {
     :global {
+        .authorName {
+            display: none !important;
+        }
+        #musicAndSelection{
+            padding-top: 0 !important;
+        }
         #osmdCanvasPage1 {
         #osmdCanvasPage1 {
             padding-bottom: 0 !important;
             padding-bottom: 0 !important;
         }
         }
+
         #cursorImg-0 {
         #cursorImg-0 {
             opacity: 0 !important;
             opacity: 0 !important;
         }
         }
+
         .noteActive {
         .noteActive {
             path {
             path {
                 fill: #000000;
                 fill: #000000;
                 stroke: #000000;
                 stroke: #000000;
             }
             }
+
+            rect {
+                stroke: #000000;
+            }
+        }
+        .lyricActive {
+            text {
+                fill: #000000;
+                stroke: #000000;
+            }
+        }
+        .voiceActive {
             rect {
             rect {
+                fill: #000000;
                 stroke: #000000;
                 stroke: #000000;
             }
             }
         }
         }
+        .rectActive {
+            fill: #000000;
+            stroke: #000000;
+        }
+    }
+}
+
+.cbsViewDetail {
+    background: #fff !important;
+
+    >.pageBg {
+        display: none;
+    }
+
+    .headHeight {
+        // background: #fff !important;
+    }
+
+    :global {
+        #cursorImg-0 {
+            opacity: 0 !important;
+        }
+        .noteActive {
+            path {
+                fill: #0097FF;
+                stroke: #0097FF;
+            }
+
+            rect {
+                stroke: #0097FF;
+            }
+        }
+        .lyricActive {
+            text {
+                fill: #0097FF;
+                stroke: #0097FF;
+            }
+        }
+        .voiceActive {
+            rect {
+                fill: #0097FF;
+                stroke: #0097FF;
+            }
+        }
+        .rectActive {
+            fill: #0097FF;
+            stroke: #0097FF;
+        }
+        #selectionBgBox {
+            display: none;
+        }
+        .vf-numbered_note_lines {
+            rect {
+                fill: #000;
+                stroke: #000;
+            }
+        }
     }
     }
 }
 }
 
 
@@ -221,29 +335,62 @@
     }
     }
 }
 }
 
 
+@keyframes rotate {
+    from {
+        transform: rotate(0deg);
+    }
+    to {
+        transform: rotate(360deg);
+    }
+}
 .loadingPop {
 .loadingPop {
     position: fixed;
     position: fixed;
     left: 0;
     left: 0;
     top: 0;
     top: 0;
     right: 0;
     right: 0;
     bottom: 0;
     bottom: 0;
-    width: 100vw;
-    height: 100vh;
+    width: 100%;
+    min-width: 100vw;
+    height: 100%;
+    min-height: 100vh;
     display: flex;
     display: flex;
     flex-direction: column;
     flex-direction: column;
     justify-content: center;
     justify-content: center;
     align-items: center;
     align-items: center;
     z-index: 10000;
     z-index: 10000;
     background: rgba(0, 0, 0, .6);
     background: rgba(0, 0, 0, .6);
-    &.isPreView{
-        background:transparent;
-        .loadingTip{
+
+    &.isPreView {
+        background: transparent;
+
+        .loadingTip {
             color: #999;
             color: #999;
         }
         }
     }
     }
+    .loadingCssBox{
+        width: 27px;
+        height: 27px;
+        display: flex;
+        justify-content: space-between;
+        flex-wrap: wrap;
+        align-content: space-between;
+        margin-bottom: 24px;
+        animation: rotate 1.5s linear infinite;
+        .loadingCssItem{
+            width: 11px;
+            height: 11px;
+            border-radius: 50%;
+            background: #20BDFF;
+            opacity: 0.5;
+            &:nth-child(2){
+                opacity:1;
+            }
+        }
+    }
     .lottie{
     .lottie{
         width: 120px;
         width: 120px;
     }
     }
+
     .loadingTip {
     .loadingTip {
         font-size: 14px;
         font-size: 14px;
         color: #fff;
         color: #fff;
@@ -256,6 +403,7 @@
     left: 0px;
     left: 0px;
     top: 0;
     top: 0;
 }
 }
+
 .bg2Right {
 .bg2Right {
     width: 52px;
     width: 52px;
     position: absolute;
     position: absolute;

+ 109 - 78
src/page-instrument/view-detail/index.tsx

@@ -9,7 +9,7 @@ import MusicScore from "../../view/music-score";
 import TestCheck from "/src/view/music-score/testCheck";
 import TestCheck from "/src/view/music-score/testCheck";
 import { sysMusicScoreAccompanimentQueryPage } from "../api";
 import { sysMusicScoreAccompanimentQueryPage } from "../api";
 import EvaluatModel from "../evaluat-model";
 import EvaluatModel from "../evaluat-model";
-import HeaderTop, {handlerModeChange} from "../header-top";
+import HeaderTop, { handlerModeChange } from "../header-top";
 import styles from "./index.module.less";
 import styles from "./index.module.less";
 import { api_cloudAccompanyMessage, api_cloudLoading, api_keepScreenLongLight, api_openCamera, api_openWebView, api_setEventTracking, api_setRequestedOrientation, api_setStatusBarVisibility, isSpecialShapedScreen } from "/src/helpers/communication";
 import { api_cloudAccompanyMessage, api_cloudLoading, api_keepScreenLongLight, api_openCamera, api_openWebView, api_setEventTracking, api_setRequestedOrientation, api_setStatusBarVisibility, isSpecialShapedScreen } from "/src/helpers/communication";
 import { getQuery } from "/src/utils/queryString";
 import { getQuery } from "/src/utils/queryString";
@@ -28,16 +28,17 @@ import { storeData } from "/src/store";
 import ViewFigner from "../view-figner";
 import ViewFigner from "../view-figner";
 import { recalculateNoteData } from "/src/view/selection";
 import { recalculateNoteData } from "/src/view/selection";
 import ToggleMusicSheet from "/src/view/plugins/toggleMusicSheet";
 import ToggleMusicSheet from "/src/view/plugins/toggleMusicSheet";
-import { setCustomGradual, setCustomNoteRealValue } from "/src/helpers/customMusicScore"
+import { setCustomGradual, setCustomNoteRealValue } from "/src/helpers/customMusicScore";
 import { usePageVisibility } from "@vant/use";
 import { usePageVisibility } from "@vant/use";
-import { initMidi } from "/src/helpers/midiPlay"
-import TheAudio from "/src/components/the-audio"
+import { initMidi } from "/src/helpers/midiPlay";
+import TheAudio from "/src/components/the-audio";
 import tickWav from "/src/assets/tick.mp3";
 import tickWav from "/src/assets/tick.mp3";
-import AuthorName from "../component/authorName"
-import { initSmoothAnimation } from "./smoothAnimation"
-import EmptyMusic, { isEmptyMusicShow } from "./emptyMusic"
+import AuthorName from "../component/authorName";
+import { initSmoothAnimation } from "./smoothAnimation";
+import EmptyMusic, { isEmptyMusicShow } from "./emptyMusic";
 import { position } from "html2canvas/dist/types/css/property-descriptors/position";
 import { position } from "html2canvas/dist/types/css/property-descriptors/position";
 import Loading from "./loading"
 import Loading from "./loading"
+import LoadingCss from "./loadingCss"
 // import bgJson from "./images/index.json";
 // import bgJson from "./images/index.json";
 import bg2Left from "./images/bg2_left_zs.png";
 import bg2Left from "./images/bg2_left_zs.png";
 import bg2Right from "./images/bg2_right_zs.png";
 import bg2Right from "./images/bg2_right_zs.png";
@@ -117,21 +118,21 @@ export default defineComponent({
       }
       }
     };
     };
     onBeforeMount(async () => {
     onBeforeMount(async () => {
-      console.time("渲染加载耗时");
+      // console.time("渲染加载耗时");
       api_keepScreenLongLight();
       api_keepScreenLongLight();
       getAPPData();
       getAPPData();
       api_setStatusBarVisibility();
       api_setStatusBarVisibility();
       const settting = store.get("musicscoresetting");
       const settting = store.get("musicscoresetting");
       if (settting) {
       if (settting) {
         //state.setting = settting;
         //state.setting = settting;
-        Object.assign(state.setting, settting)
+        Object.assign(state.setting, settting);
         //state.setting.beatVolume = state.setting.beatVolume || 50
         //state.setting.beatVolume = state.setting.beatVolume || 50
-        state.setting.beatVolume = 50
+        state.setting.beatVolume = 50;
         if (state.setting.camera) {
         if (state.setting.camera) {
           const res = await api_openCamera();
           const res = await api_openCamera();
           // 没有授权
           // 没有授权
           if (res?.content?.reson) {
           if (res?.content?.reson) {
-            state.setting.camera = false
+            state.setting.camera = false;
             store.set("musicscoresetting", state.setting);
             store.set("musicscoresetting", state.setting);
           }
           }
         }
         }
@@ -161,16 +162,17 @@ export default defineComponent({
     onMounted(async () => {
     onMounted(async () => {
       (window as any).appName = "colexiu";
       (window as any).appName = "colexiu";
       const id = query.id || "43554";
       const id = query.id || "43554";
+      state.isCbsView = query.isCbs;
       // 如果是纯预览模式,0.65倍缩放谱面
       // 如果是纯预览模式,0.65倍缩放谱面
-      state.isPreView = query.isPreView
+      state.isPreView = query.isPreView;
       if (state.isPreView) {
       if (state.isPreView) {
-        state.zoom = 0.65
+        state.zoom = query.zoom  || 0.65
       }
       }
-      if (id == '1814218144844087298' && state.isSingleLine) {
-        state.zoom = 0.7
+      if (id == "1814218144844087298" && state.isSingleLine) {
+        state.zoom = 0.7;
       }
       }
       // 只有总控平台和预览 默认是多行谱
       // 只有总控平台和预览 默认是多行谱
-      (state.isPreView || query.isCbs) && (state.isSingleLine = false)
+      //(state.isPreView || query.isCbs) && (state.isSingleLine = false)
       // Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => {
       // Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => {
       //   getMusicInfo(values[0]);
       //   getMusicInfo(values[0]);
       // });
       // });
@@ -178,16 +180,27 @@ export default defineComponent({
       try { 
       try { 
         await getMusicDetail(id);
         await getMusicDetail(id);
       } catch (err) {
       } catch (err) {
-        console.error(err)
+        console.error(err);
         state.isLoading = false;
         state.isLoading = false;
         isEmptyMusicShow.value = true
         isEmptyMusicShow.value = true
+        // 需要向外面(iframe)派发计时器数据的时候触发
+        if(query.isbeatTimes){
+          console.log("webApi_beatTimes",err)
+          window.parent.postMessage(
+            {
+              api: "webApi_beatTimes",
+              data: "节拍器时值错误!!"
+            },
+            "*"
+          );
+        }
         return
         return
       }
       }
       detailData.isLoading = false;
       detailData.isLoading = false;
       // 如果后台设置了不显示指法,关闭指法开关   如果默认进来是演奏模式 不显示指法开关
       // 如果后台设置了不显示指法,关闭指法开关   如果默认进来是演奏模式 不显示指法开关
       if (!state.isShowFingering || state.playType === "sing") {
       if (!state.isShowFingering || state.playType === "sing") {
-        state.setting.displayFingering = false
-      }      
+        state.setting.displayFingering = false;
+      }
       // api_setEventTracking();
       // api_setEventTracking();
     });
     });
 
 
@@ -207,15 +220,15 @@ export default defineComponent({
       //   handleSetSpeed(saveSpeed);
       //   handleSetSpeed(saveSpeed);
       // }
       // }
       setCustomGradual();
       setCustomGradual();
-			setCustomNoteRealValue();
+      setCustomNoteRealValue();
       state.times = formateTimes(osmd);
       state.times = formateTimes(osmd);
       // state.times = resetFrequency(state.times);
       // state.times = resetFrequency(state.times);
       state.times = setNoteHalfTone(state.times);
       state.times = setNoteHalfTone(state.times);
-      state.xmlHasLyric = state.times.some((item: any) => item?.formatLyricsEntries?.length)
+      state.xmlHasLyric = state.times.some((item: any) => item?.formatLyricsEntries?.length);
       console.log("🚀 ~ state.times:", state.times, state.subjectId, state);
       console.log("🚀 ~ state.times:", state.times, state.subjectId, state);
       nextTick(() => {
       nextTick(() => {
         state.activeMeasureIndex = state.times[0].MeasureNumberXML;
         state.activeMeasureIndex = state.times[0].MeasureNumberXML;
-      })
+      });
       // 一行谱
       // 一行谱
       if (state.isSingleLine) {
       if (state.isSingleLine) {
         // 音符添加位置信息bbox
         // 音符添加位置信息bbox
@@ -224,69 +237,70 @@ export default defineComponent({
         initSmoothAnimation();
         initSmoothAnimation();
       }
       }
       // 初始化midi音频信息
       // 初始化midi音频信息
-      const songEndTime = state.times[state.times.length - 1 || 0]?.endtime || 0
+      const songEndTime = state.times[state.times.length - 1 || 0]?.endtime || 0;
       if (state.isAppPlay) {
       if (state.isAppPlay) {
-        const durationNum = songEndTime
-        initMidi(durationNum, state.midiUrl)
+        const durationNum = songEndTime;
+        initMidi(durationNum, state.midiUrl);
       }
       }
-      state.measureTime = state.times[0]?.measureLength || 0
+      state.measureTime = state.times[0]?.measureLength || 0;
       try {
       try {
         metronomeData.metro = new Metronome();
         metronomeData.metro = new Metronome();
         metronomeData.metro.init(state.times);
         metronomeData.metro.init(state.times);
       } catch (error) {}
       } catch (error) {}
 
 
       // 需要向外面(iframe)派发计时器数据的时候触发
       // 需要向外面(iframe)派发计时器数据的时候触发
-      if(query.isbeatTimes){
-        const { isOpenMetronome, isSingOpenMetronome } = state
-        const {xmlMp3BeatFixTime} = state.times[0] 
-        const singBeatTime: number[][] = []
-        const beatTime = metronomeData.metroMeasure.map(metroMeasure => {
-          const singBeat:number[] = []
+      if (query.isbeatTimes) {
+        const { isOpenMetronome, isSingOpenMetronome } = state;
+        const { xmlMp3BeatFixTime, difftime } = state.times[0];
+        const singBeatTime: number[][] = [];
+        const beatTime = metronomeData.metroMeasure.map((metroMeasure) => {
+          const singBeat: number[] = [];
           const beatTimeItem = metroMeasure.map((item: any) => {
           const beatTimeItem = metroMeasure.map((item: any) => {
-            let singTime = item.time
-            if(isSingOpenMetronome && !isOpenMetronome){
-              singTime += xmlMp3BeatFixTime
-            } else if(!isSingOpenMetronome && isOpenMetronome){
-              singTime -= xmlMp3BeatFixTime
+            let singTime = item.time;
+            if (isSingOpenMetronome && !isOpenMetronome) {
+              singTime += xmlMp3BeatFixTime;
+            } else if (!isSingOpenMetronome && isOpenMetronome) {
+              singTime -= xmlMp3BeatFixTime;
             }
             }
-            singBeat.push(singTime)
-            return item.time
-          })
-          singBeatTime.push(singBeat)
-          return beatTimeItem
-        })
+            singBeat.push(singTime);
+            return item.time;
+          });
+          singBeatTime.push(singBeat);
+          return beatTimeItem;
+        });
         //改为唱名
         //改为唱名
-        state.fixtime = 0
-        state.times.map(item => {
-          item.time = item.xmlNoteTime
-          item.endtime = item.xmlNoteEndTime
-          item.fixtime = 0
-        })
-        metronomeData.metro.calculation(state.times)
-        const mingBeatTime:number[][] = metronomeData.metroMeasure.map(metroMeasure => {
+        state.fixtime = difftime;
+        state.times.map((item) => {
+          item.time = item.xmlNoteTime + difftime;
+          item.endtime = item.xmlNoteEndTime + difftime;
+          item.fixtime = difftime;
+        });
+        metronomeData.metro.calculation(state.times);
+        const mingBeatTime: number[][] = metronomeData.metroMeasure.map((metroMeasure) => {
           const beatTimeItem = metroMeasure.map((item: any) => {
           const beatTimeItem = metroMeasure.map((item: any) => {
-            return item.time
-          })
-          return beatTimeItem
-        })
-        console.log("webApi_beatTimes",{beatTime,singBeatTime,mingBeatTime})
+            return item.time;
+          });
+          return beatTimeItem;
+        });
+        const webApi_beatTimes = { beatTime, singBeatTime, mingBeatTime, isBeatTime:!state.isEvxml, isSingBeatTime:!state.isEvxml, isMingBeatTime:!state.isEvxml }
+        console.log("webApi_beatTimes", webApi_beatTimes);
         window.parent.postMessage(
         window.parent.postMessage(
           {
           {
             api: "webApi_beatTimes",
             api: "webApi_beatTimes",
-            data: JSON.stringify({beatTime,singBeatTime,mingBeatTime})
+            data: JSON.stringify(webApi_beatTimes),
           },
           },
           "*"
           "*"
         );
         );
-        throw new Error("webApi_beatTimes 完成");
+        return
       }
       }
       // 刷新时值
       // 刷新时值
-      handlerModeChange("play", "music")
+      handlerModeChange("play", "music");
       /**
       /**
        * 2024.1.25
        * 2024.1.25
        * 设置节拍器,跟练需要播放系统节拍器,所以不需要判断needTick状态
        * 设置节拍器,跟练需要播放系统节拍器,所以不需要判断needTick状态
        */
        */
       // if (state.needTick) {
       // if (state.needTick) {
-        handleInitTick(osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4);
+      handleInitTick(osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4, osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.denominator);
       // }
       // }
       // api_cloudLoading();
       // api_cloudLoading();
       // state.playBtnDirection = query.imagePos === 'left' ? 'left' : 'right';
       // state.playBtnDirection = query.imagePos === 'left' ? 'left' : 'right';
@@ -308,6 +322,23 @@ export default defineComponent({
       // pushAppMusic();
       // pushAppMusic();
       // console.timeEnd("渲染加载耗时");
       // console.timeEnd("渲染加载耗时");
     };
     };
+    function handleOnRendered(osmd: any) {
+      try{
+        handleRendered(osmd)
+      }catch(err:any){
+        // 需要向外面(iframe)派发计时器数据的时候触发
+        if(query.isbeatTimes){
+          console.log("webApi_beatTimes",err)
+          window.parent.postMessage(
+            {
+              api: "webApi_beatTimes",
+              data: "节拍器时值错误!!"
+            },
+            "*"
+          );
+        }
+      }
+    }
     /** 指法配置 */
     /** 指法配置 */
     const fingerConfig = computed<any>(() => {
     const fingerConfig = computed<any>(() => {
       if (state.setting.displayFingering && state.fingeringInfo?.name) {
       if (state.setting.displayFingering && state.fingeringInfo?.name) {
@@ -329,7 +360,7 @@ export default defineComponent({
             }
             }
           };
           };
         } else {
         } else {
-          console.log('指法',state.playBtnDirection,state.platform)
+          console.log("指法", state.playBtnDirection, state.platform);
           // 老师端,竖向指法,需要根据功能按钮方向进行设置
           // 老师端,竖向指法,需要根据功能按钮方向进行设置
           if (state.platform === IPlatform.PC) {
           if (state.platform === IPlatform.PC) {
             return {
             return {
@@ -373,13 +404,12 @@ export default defineComponent({
       () => state.setting.displayFingering,
       () => state.setting.displayFingering,
       () => {
       () => {
         if (state.fingeringInfo.direction === "vertical") {
         if (state.fingeringInfo.direction === "vertical") {
-          
           // if (state.setting.displayFingering) {
           // if (state.setting.displayFingering) {
           //   state.musicScoreBtnDirection = state.playBtnDirection === 'left' ? 'right' : 'left'
           //   state.musicScoreBtnDirection = state.playBtnDirection === 'left' ? 'right' : 'left'
           // } else {
           // } else {
           //   state.musicScoreBtnDirection = state.playBtnDirection
           //   state.musicScoreBtnDirection = state.playBtnDirection
           // }
           // }
-          state.musicScoreBtnDirection = state.playBtnDirection
+          state.musicScoreBtnDirection = state.playBtnDirection;
         }
         }
       }
       }
     );
     );
@@ -412,9 +442,9 @@ export default defineComponent({
     );
     );
     // 监听跟练的开启状态
     // 监听跟练的开启状态
     watch(
     watch(
-      () => followData.start,
+      () => followData.practiceStart,
       () => {
       () => {
-        headerColumnHide.value = followData.start;
+        headerColumnHide.value = followData.practiceStart;
       }
       }
     );
     );
     // 监听开始评测状态
     // 监听开始评测状态
@@ -485,11 +515,11 @@ export default defineComponent({
     };
     };
     return () => (
     return () => (
       <div
       <div
-        class={[styles.detail, styles[state.modeType], state.setting.eyeProtection && "eyeProtection", (state.platform === IPlatform.PC && state.zoom > 0.8) && styles.PC, state.isPreView && styles.preViewDetail]}
+        class={[styles.detail, styles[state.modeType], state.setting.eyeProtection && "eyeProtection", state.platform === IPlatform.PC && state.zoom > 0.8 && styles.PC, state.isPreView && styles.preViewDetail, state.isCbsView && styles.cbsViewDetail]}
         style={{
         style={{
-          '--detailDataPaddingLeft': detailData.paddingLeft,
+          "--detailDataPaddingLeft": detailData.paddingLeft,
           paddingLeft: detailData.paddingLeft,
           paddingLeft: detailData.paddingLeft,
-          background: state.setting.camera ? `rgba(${state.setting.eyeProtection ? "253,244,229" : "255,255,255"} ,${state.setting.cameraOpacity / 100}) !important` : "",
+          background: state.setting.camera && state.modeType === 'evaluating' ? `rgba(${state.setting.eyeProtection ? "253,244,229" : "255,255,255"} ,${state.setting.cameraOpacity / 100}) !important` : "",
         }}
         }}
       >
       >
         {bgJsonData.value ? 
         {bgJsonData.value ? 
@@ -497,14 +527,17 @@ export default defineComponent({
             style={{opacity: state.setting.camera && state.modeType === 'evaluating' ? state.setting.cameraOpacity / 100 : 1}} 
             style={{opacity: state.setting.camera && state.modeType === 'evaluating' ? state.setting.cameraOpacity / 100 : 1}} 
             class={styles.pageBg} 
             class={styles.pageBg} 
             src={state.modeType === 'practise' ? bgJsonData.value[1] : state.modeType === 'evaluating' ? bgJsonData.value[2] : state.modeType === 'follow' ? bgJsonData.value[3] : ''} 
             src={state.modeType === 'practise' ? bgJsonData.value[1] : state.modeType === 'evaluating' ? bgJsonData.value[2] : state.modeType === 'follow' ? bgJsonData.value[3] : ''} 
-          /> : null    
+          /> : <div 
+                style={{opacity: state.setting.camera && state.modeType === 'evaluating' ? state.setting.cameraOpacity / 100 : 1}}  
+                class={[styles.pageBg, styles[state.modeType]]} >
+              </div>    
         }
         }
         {
         {
-          state.modeType === 'evaluating' ? <>
+          state.modeType === 'evaluating' ? (<>
             <img src={bg2Left} class={styles.bg2Left} />
             <img src={bg2Left} class={styles.bg2Left} />
             <img src={bg2Right} class={styles.bg2Right} />
             <img src={bg2Right} class={styles.bg2Right} />
-          </> : null
-        }
+          </>
+        ) : null}
         {/* 骨架屏 */}
         {/* 骨架屏 */}
         {/* <Transition name="van-fade">
         {/* <Transition name="van-fade">
           {detailData.skeletonLoading && (
           {detailData.skeletonLoading && (
@@ -516,10 +549,7 @@ export default defineComponent({
         {/* 曲目加载错误的缺省 */}
         {/* 曲目加载错误的缺省 */}
         <EmptyMusic></EmptyMusic>
         <EmptyMusic></EmptyMusic>
         {/** 功能按钮 */}
         {/** 功能按钮 */}
-        {
-          !state.isPreView && 
-          <div class={[styles.headHeight, headerColumnHide.value && styles.headHide]}>{state.musicRendered && <HeaderTop />}</div>
-        }
+        {!state.isPreView && <div class={["headHeight", styles.headHeight, headerColumnHide.value && styles.headHide]}>{state.musicRendered && <HeaderTop />}</div>}
         <div
         <div
           id="scrollContainer"
           id="scrollContainer"
           style={{ ...fingerConfig.value.container }}
           style={{ ...fingerConfig.value.container }}
@@ -539,9 +569,9 @@ export default defineComponent({
           {!detailData.isLoading && 
           {!detailData.isLoading && 
             <MusicScore 
             <MusicScore 
               ref={musicScoreRef}
               ref={musicScoreRef}
-              musicColor={state.isPreView ? '#000000' : '#FFFFFF'}
+              musicColor={state.isPreView || state.isCbsView ? '#000000' : '#FFFFFF'}
               showPartNames={state.isCombineRender}
               showPartNames={state.isCombineRender}
-              onRendered={handleRendered} 
+              onRendered={handleOnRendered} 
             > 
             > 
               {/* 旋律线关闭时候的 标题和作者 */}
               {/* 旋律线关闭时候的 标题和作者 */}
               <AuthorName></AuthorName>
               <AuthorName></AuthorName>
@@ -610,6 +640,7 @@ export default defineComponent({
           </>
           </>
         )}
         )}
         <Loading tipText={state.loadingText} />
         <Loading tipText={state.loadingText} />
+        <LoadingCss />
         <Popup
         <Popup
           zIndex={5050}
           zIndex={5050}
           teleport="body"
           teleport="body"

+ 1 - 1
src/page-instrument/view-detail/loading.tsx

@@ -18,7 +18,7 @@ export default defineComponent({
    setup(props) {
    setup(props) {
       return () =>
       return () =>
          (
          (
-            <div class={[styles.loadingPop, state.isPreView && styles.isPreView]} style={{display:state.isLoading? "flex" : "none"}}>
+            <div class={[styles.loadingPop, (state.isPreView || state.isCbsView) && styles.isPreView]} style={{display:state.isLoading? "flex" : "none"}}>
                <img class={styles.lottie} src={animGif} />
                <img class={styles.lottie} src={animGif} />
                {/* <Vue3Lottie class={styles.lottie} animationData={animBg}></Vue3Lottie> */}
                {/* <Vue3Lottie class={styles.lottie} animationData={animBg}></Vue3Lottie> */}
                <div class={styles.loadingTip}>{props.tipText}</div>
                <div class={styles.loadingTip}>{props.tipText}</div>

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott