Преглед на файлове

Merge branch 'ktyq-online-1.8.7' of http://git.dayaedu.com/liushengqiang/music-score into feature-mjk

TIANYONG преди 1 година
родител
ревизия
43ca37ba00
променени са 49 файла, в които са добавени 1620 реда и са изтрити 445 реда
  1. 9 9
      dist/colexiu.html
  2. 5 0
      dist/flexible.js
  3. 10 10
      dist/index.html
  4. 11 11
      dist/instrument.html
  5. 11 11
      dist/orchestra.html
  6. 6 6
      dist/report-share.html
  7. 3 0
      src/helpers/formateMusic.ts
  8. 59 0
      src/hooks/useDrag/dragbom.tsx
  9. BIN
      src/hooks/useDrag/img/left.png
  10. BIN
      src/hooks/useDrag/img/modalDragBg.png
  11. BIN
      src/hooks/useDrag/img/modalDragBg2.png
  12. BIN
      src/hooks/useDrag/img/modalDragBgLeft.png
  13. BIN
      src/hooks/useDrag/img/modalDragBgRight.png
  14. BIN
      src/hooks/useDrag/img/modalDragDone.png
  15. BIN
      src/hooks/useDrag/img/right.png
  16. 88 0
      src/hooks/useDrag/index.module.less
  17. 163 0
      src/hooks/useDrag/index.ts
  18. 39 0
      src/hooks/useDrag/useDragGuidance.ts
  19. 43 4
      src/page-instrument/custom-plugins/guide-page/teacher-bootom.tsx
  20. 1 1
      src/page-instrument/follow-model/index.module.less
  21. 4 0
      src/page-instrument/header-top/index.module.less
  22. 2 2
      src/page-instrument/header-top/index.tsx
  23. 1 1
      src/page-instrument/header-top/music-type/index.tsx
  24. 2 1
      src/page-instrument/view-detail/index.tsx
  25. 38 17
      src/page-instrument/view-figner/change-subject/index.module.less
  26. 105 11
      src/page-instrument/view-figner/change-subject/index.tsx
  27. BIN
      src/page-instrument/view-figner/image/btnBg.png
  28. BIN
      src/page-instrument/view-figner/image/icon_shuo_v.png
  29. BIN
      src/page-instrument/view-figner/image/noteImg.png
  30. BIN
      src/page-instrument/view-figner/image/subJect-bg2.png
  31. BIN
      src/page-instrument/view-figner/image/subJect-bg3.png
  32. BIN
      src/page-instrument/view-figner/image/subject-bg1.png
  33. BIN
      src/page-instrument/view-figner/image/subject-btn1.png
  34. BIN
      src/page-instrument/view-figner/image/subject-btn2.png
  35. 251 5
      src/page-instrument/view-figner/index.module.less
  36. 622 258
      src/page-instrument/view-figner/index.tsx
  37. 2 2
      src/state.ts
  38. 2 2
      src/view/fingering/fingering-config.ts
  39. 1 1
      src/view/music-score/index.tsx
  40. 11 0
      src/view/plugins/toggleMusicSheet/choosePartName/index.module.less
  41. 2 2
      src/view/plugins/toggleMusicSheet/choosePartName/index.tsx
  42. 22 8
      src/view/plugins/useDrag/dragbom.tsx
  43. BIN
      src/view/plugins/useDrag/img/modalDragBgLeft.png
  44. BIN
      src/view/plugins/useDrag/img/modalDragBgRight.png
  45. 18 0
      src/view/plugins/useDrag/index.module.less
  46. 6 0
      src/view/plugins/useDrag/index.ts
  47. 1 1
      src/view/selection/index.tsx
  48. 0 0
      stats.html
  49. 82 82
      vite.config.ts

+ 9 - 9
dist/colexiu.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-ca45d81b.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-817dd552.js"></script>
 
   <meta charset="UTF-8" />
   <link rel="icon" type="image/svg+xml" href="./vite.svg" />
@@ -40,12 +40,12 @@
       },
     })
   </script>
-  <script type="module" crossorigin src="./js/colexiu-2404c3f0.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-7fa3864d.js">
-  <link rel="modulepreload" crossorigin href="./js/index-c82a77d7.js">
-  <link rel="modulepreload" crossorigin href="./js/index-74accf7a.js">
-  <link rel="modulepreload" crossorigin href="./js/index-f5441714.js">
-  <link rel="stylesheet" href="./css/index-5cdcded6.css">
+  <script type="module" crossorigin src="./js/colexiu-20b9170a.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-b554af8f.js">
+  <link rel="modulepreload" crossorigin href="./js/index-f1b28e23.js">
+  <link rel="modulepreload" crossorigin href="./js/index-6869c597.js">
+  <link rel="modulepreload" crossorigin href="./js/index-4e940986.js">
+  <link rel="stylesheet" href="./css/index-14f2d759.css">
   <link rel="stylesheet" href="./css/index-d42b0794.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>
@@ -57,8 +57,8 @@
   <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 crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-a2ca5f88.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/colexiu-legacy-1e5002bc.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-8891b9b0.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/colexiu-legacy-9872cd8a.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 5 - 0
dist/flexible.js

@@ -6,6 +6,11 @@
     b / i > 640 && (b = 640 * i);
     b / i < 375 && (b = 375 * i);
     var c = b / 10;
+    // 老师端,fontsize计算
+    // if (window.location.search.includes('platform=pc') || window.location.search.includes('platform=PC')) {
+    //   c = width / 21.7;
+    // }
+    // console.log('fontSize:',c,'屏幕宽度:',width,'老师端:',window.location.search.includes('platform=pc'))
     f.style.fontSize = c + "px", k.rem = a.rem = c
     window.fontSize = c
   }

+ 10 - 10
dist/index.html

@@ -2,7 +2,7 @@
 <html lang="ZH-cn">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-ca45d81b.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-817dd552.js"></script>
 
   <meta charset="UTF-8">
   <link rel="icon" href="./favicon.ico" />
@@ -75,14 +75,14 @@
       }
     })
   </script>
-  <script type="module" crossorigin src="./js/gym-fd251339.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-7fa3864d.js">
-  <link rel="modulepreload" crossorigin href="./js/index-c82a77d7.js">
-  <link rel="modulepreload" crossorigin href="./js/instruments-cb07e5d7.js">
-  <link rel="modulepreload" crossorigin href="./js/index-7981bdb9.js">
-  <link rel="modulepreload" crossorigin href="./js/index-f5441714.js">
+  <script type="module" crossorigin src="./js/gym-142c677b.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-b554af8f.js">
+  <link rel="modulepreload" crossorigin href="./js/index-f1b28e23.js">
+  <link rel="modulepreload" crossorigin href="./js/instruments-594da20e.js">
+  <link rel="modulepreload" crossorigin href="./js/index-4e194734.js">
+  <link rel="modulepreload" crossorigin href="./js/index-4e940986.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
-  <link rel="stylesheet" href="./css/index-5cdcded6.css">
+  <link rel="stylesheet" href="./css/index-14f2d759.css">
   <link rel="stylesheet" href="./css/index-d42b0794.css">
   <link rel="stylesheet" href="./css/index-85f95688.css">
   <link rel="stylesheet" href="./css/plyr-ad8ef5ae.css">
@@ -100,8 +100,8 @@
   <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 crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-a2ca5f88.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/gym-legacy-f26a3750.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-8891b9b0.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/gym-legacy-7afc7ecd.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 11 - 11
dist/instrument.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-ca45d81b.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-817dd552.js"></script>
 
   <meta charset="UTF-8" />
   <meta name="viewport"
@@ -40,15 +40,15 @@
       })
     }
   </script>
-  <script type="module" crossorigin src="./js/instrument-d541df92.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-7fa3864d.js">
-  <link rel="modulepreload" crossorigin href="./js/index-c82a77d7.js">
-  <link rel="modulepreload" crossorigin href="./js/index-74accf7a.js">
-  <link rel="modulepreload" crossorigin href="./js/instruments-cb07e5d7.js">
-  <link rel="modulepreload" crossorigin href="./js/index-f12d04aa.js">
-  <link rel="stylesheet" href="./css/index-5cdcded6.css">
+  <script type="module" crossorigin src="./js/instrument-37052fd4.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-b554af8f.js">
+  <link rel="modulepreload" crossorigin href="./js/index-f1b28e23.js">
+  <link rel="modulepreload" crossorigin href="./js/index-6869c597.js">
+  <link rel="modulepreload" crossorigin href="./js/instruments-594da20e.js">
+  <link rel="modulepreload" crossorigin href="./js/index-51523712.js">
+  <link rel="stylesheet" href="./css/index-14f2d759.css">
   <link rel="stylesheet" href="./css/index-d42b0794.css">
-  <link rel="stylesheet" href="./css/instrument-c4bf8181.css">
+  <link rel="stylesheet" href="./css/instrument-87e75e39.css">
   <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>
 </head>
@@ -66,8 +66,8 @@
 
   
   <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 crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-a2ca5f88.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/instrument-legacy-27ac3a95.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-8891b9b0.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/instrument-legacy-79bab25b.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 11 - 11
dist/orchestra.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-ca45d81b.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-817dd552.js"></script>
 
   <meta charset="UTF-8" />
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
@@ -41,14 +41,14 @@
       transition: opacity .3s;
     }
   </style>
-  <script type="module" crossorigin src="./js/orchestra-2c238eef.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-7fa3864d.js">
-  <link rel="modulepreload" crossorigin href="./js/index-c82a77d7.js">
-  <link rel="modulepreload" crossorigin href="./js/index-74accf7a.js">
-  <link rel="modulepreload" crossorigin href="./js/index-7981bdb9.js">
-  <link rel="modulepreload" crossorigin href="./js/index-f5441714.js">
-  <link rel="modulepreload" crossorigin href="./js/index-f12d04aa.js">
-  <link rel="stylesheet" href="./css/index-5cdcded6.css">
+  <script type="module" crossorigin src="./js/orchestra-0606108a.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-b554af8f.js">
+  <link rel="modulepreload" crossorigin href="./js/index-f1b28e23.js">
+  <link rel="modulepreload" crossorigin href="./js/index-6869c597.js">
+  <link rel="modulepreload" crossorigin href="./js/index-4e194734.js">
+  <link rel="modulepreload" crossorigin href="./js/index-4e940986.js">
+  <link rel="modulepreload" crossorigin href="./js/index-51523712.js">
+  <link rel="stylesheet" href="./css/index-14f2d759.css">
   <link rel="stylesheet" href="./css/index-d42b0794.css">
   <link rel="stylesheet" href="./css/index-85f95688.css">
   <link rel="stylesheet" href="./css/orchestra-8bc1a9c0.css">
@@ -72,8 +72,8 @@
   </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 crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-a2ca5f88.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/orchestra-legacy-b879e7f9.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-8891b9b0.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/orchestra-legacy-4ad1aabe.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 6 - 6
dist/report-share.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-ca45d81b.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-817dd552.js"></script>
 
   <meta charset="UTF-8" />
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
@@ -25,10 +25,10 @@
       transition: opacity .3s;
     }
   </style>
-  <script type="module" crossorigin src="./js/report-share-4a82a9fe.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-7fa3864d.js">
+  <script type="module" crossorigin src="./js/report-share-e31e675f.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-b554af8f.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
-  <link rel="stylesheet" href="./css/index-5cdcded6.css">
+  <link rel="stylesheet" href="./css/index-14f2d759.css">
   <link rel="stylesheet" href="./css/plyr-ad8ef5ae.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>
@@ -51,8 +51,8 @@
   </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 crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-a2ca5f88.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/report-share-legacy-d6c4fde5.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule crossorigin id="vite-legacy-polyfill" src="./js/polyfills-legacy-8891b9b0.js"></script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/report-share-legacy-82dd7614.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 3 - 0
src/helpers/formateMusic.ts

@@ -677,6 +677,9 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
 		}
 	}
 	// 如果曲谱详情接口没有返回速度,则取xml第一小节的速度,如果取不到,则取默认速度:100
+	if (!speed || speed == -1) {
+		speed = 100
+	}
 	if (!state.originSpeed) {
 		state.originSpeed = state.speed = speed || 100
 	}

+ 59 - 0
src/hooks/useDrag/dragbom.tsx

@@ -0,0 +1,59 @@
+import { defineComponent, computed, reactive, onMounted } from 'vue';
+import styles from './index.module.less';
+// 底部拖动区域
+export default defineComponent({
+  name: 'dragBom',
+  emits: ["guideDone"],
+	props: {
+		/** 是否显示引导 */
+		showGuide: {
+			type: Boolean,
+			default: false,
+		},
+	},
+  setup(props, { emit }) {
+    const data = reactive({
+      guidePos: "bottom" as "bottom" | "left" | "right",
+    });
+
+    const initGuidePos = () => {
+      const pageHeight = document.documentElement.clientHeight || document.body.clientHeight;
+      const pageWidth = document.documentElement.clientWidth || document.body.clientWidth;
+      const guideHeight = document.querySelector('.bom_guide')?.clientHeight || 0;
+      const guideWidth = document.querySelector('.bom_guide')?.clientWidth || 0;
+      const dragBBox = document.querySelector('.bom_drag')?.getBoundingClientRect();
+      const dragTop = dragBBox?.top || 0;
+      const dragLeft = dragBBox?.left || 0;
+      // 引导页出现在下边
+      if (pageHeight - dragTop > guideHeight) {
+        data.guidePos = "bottom"
+      } else {
+        // 引导页出现在左边or右边
+        data.guidePos = dragLeft > guideWidth ? "left" : "right"
+      }
+    }
+    onMounted(() => {
+      setTimeout(() => {
+        initGuidePos();
+      }, 0);
+    });
+    return () => (
+      <>
+      <div class={[styles.dragbomBox,"dragbomBox"]}>
+        <div class={[styles.dragBom, 'bom_drag']}>
+          <div class={styles.box}></div>
+          <div class={[styles.box, styles.right]}></div>
+        </div>
+      </div>
+        {
+          props.showGuide && 
+          <div class={[styles.guide, data.guidePos === "left" && styles.guideLeft, data.guidePos === "right" && styles.guideRight, 'bom_guide']} onClick={() => emit("guideDone")}>
+            <div class={styles.guideBg}></div>
+            <div class={styles.guideDone} onClick={(e) => {e.stopPropagation();emit("guideDone")}}></div>
+          </div>          
+        }
+
+      </>
+    );
+  }
+});

BIN
src/hooks/useDrag/img/left.png


BIN
src/hooks/useDrag/img/modalDragBg.png


BIN
src/hooks/useDrag/img/modalDragBg2.png


BIN
src/hooks/useDrag/img/modalDragBgLeft.png


BIN
src/hooks/useDrag/img/modalDragBgRight.png


BIN
src/hooks/useDrag/img/modalDragDone.png


BIN
src/hooks/useDrag/img/right.png


+ 88 - 0
src/hooks/useDrag/index.module.less

@@ -0,0 +1,88 @@
+.dragbomBox{
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  height: 36px;
+  width: 100%;
+  padding: 0 14px 0 15px;
+}
+.dragBom {
+  width: 100%;
+  height: 21px;
+  display: flex;
+  justify-content: space-between;
+  border-radius: 0 0 7px 7px;
+  overflow: hidden;
+  .box {
+    width: 21px;
+    height: 100%;
+    background: url('./img/left.png') no-repeat;
+    background-size: 100% 100%;
+    &.right {
+      background: url('./img/right.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+}
+.guide {
+  position: absolute;
+  left: 0;
+  top: calc(100% - 10px);
+  z-index: 3000;
+  &::before {
+    content: "";
+    display: block;
+    position: fixed;
+    left: -100vw;
+    top: -100vh;
+    z-index: 9;
+    width: 200vw;
+    height: 200vh;
+    background: rgba(0,0,0,0.2);
+  }
+  .guideBg {
+    position: relative;
+    z-index: 99;
+    width: 200px;
+    height: 102px;
+    background: url('./img/modalDragBg.png') no-repeat;
+    background-size: 100% 100%;
+  }
+  .guideDone {
+    position: absolute;
+    z-index: 99;
+    left: 34.6%;
+    top: 72.2%;
+    width: 50px;
+    height: 20px;
+    background: url('./img/modalDragDone.png') no-repeat;
+    background-size: 100% 100%;
+    cursor: pointer;
+  }
+  &.guideTop {
+    top: initial;
+    bottom: 2px;
+    .guideBg {
+      background: url('./img/modalDragBg2.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+  &.guideLeft {
+    top: initial;
+    left: -186px;
+    bottom: -4px;
+    .guideBg {
+      background: url('./img/modalDragBgLeft.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+  &.guideRight {
+    top: initial;
+    left: calc(100% - 12px);
+    bottom: -4px;
+    .guideBg {
+      background: url('./img/modalDragBgRight.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+}

+ 163 - 0
src/hooks/useDrag/index.ts

@@ -0,0 +1,163 @@
+// 弹窗拖动
+import { ref, Ref, watch, nextTick, computed } from 'vue';
+
+type posType = {
+  top: number;
+  left: number;
+};
+
+/**
+ * @params classList  可拖动地方的class值,也为唯一值
+ * @params boxClass  容器class值必须为唯一值,这个class和useid拼接 作为缓存主键
+ * @params dragShow  弹窗是否显示
+ * @params userId    当前用户id
+ */
+export default function useDrag(
+  classList: string[],
+  boxClass: string,
+  dragShow: Ref<boolean>,
+  userId: string
+) {
+  const pos = ref<posType>({
+    top: -1, // -1 为初始值 代表没有缓存 默认居中
+    left: -1
+  });
+  const useIdDargClass = userId + boxClass;
+  watch(dragShow, () => {
+    if (dragShow.value) {
+      // 初始化pos值
+      initPos();
+      window.addEventListener('resize', refreshPos);
+      nextTick(() => {
+        const boxClassDom = document.querySelector(
+          `.${boxClass}`
+        ) as HTMLElement;
+        if (!boxClassDom) {
+          return;
+        }
+        classList.map((className: string) => {
+          const classDom = document.querySelector(
+            `.${className}`
+          ) as HTMLElement;
+          if (classDom) {
+            classDom.style.cursor = 'move';
+            drag(classDom, boxClassDom, pos);
+          }
+        });
+      });
+    } else {
+      window.removeEventListener('resize', refreshPos);
+      setCachePos(useIdDargClass, pos.value);
+    }
+  });
+  const styleDrag = computed(() => {
+    // 没有设置拖动的时候保持原本的
+    return pos.value.left === -1 && pos.value.top === -1
+      ? {}
+      : {
+          position: 'fixed',
+          left: `${pos.value.left}px`,
+          top: `${pos.value.top}px`,
+          transform: 'initial',
+          transformOrigin: 'initial',
+          margin: 'initial',
+          transition: 'initial'
+        };
+  });
+  function initPos() {
+    const posCache = getCachePos(useIdDargClass);
+    // 有缓存 用缓存的值,没有缓存用默认
+    if (posCache) {
+      pos.value = posCache;
+      nextTick(() => {
+        refreshPos();
+      });
+    }
+  }
+  function refreshPos() {
+    if(pos.value.left === -1 && pos.value.top === -1){
+      return
+    }
+    const boxClassDom = document.querySelector(`.${boxClass}`) as HTMLElement;
+    if (!boxClassDom) return;
+    const parentElementRect = boxClassDom.getBoundingClientRect();
+    const clientWidth = document.documentElement.clientWidth;
+    const clientHeight = document.documentElement.clientHeight;
+    const { top, left } = pos.value;
+    const maxLeft = clientWidth - parentElementRect.width;
+    const maxTop = clientHeight - parentElementRect.height;
+    let moveX = left;
+    let moveY = top;
+    const minLeft = 0;
+    const minTop = 0;
+    moveX = moveX < minLeft ? minLeft : moveX > maxLeft ? maxLeft : moveX;
+    moveY = moveY < minTop ? minTop : moveY > maxTop ? maxTop : moveY;
+    pos.value = {
+      top: moveY,
+      left: moveX
+    };
+  }
+  return {
+    pos,
+    styleDrag
+  };
+}
+
+// 拖动
+function drag(el: HTMLElement, parentElement: HTMLElement, pos: Ref<posType>) {
+  function mousedown(e: MouseEvent) {
+    const parentElementRect = parentElement.getBoundingClientRect();
+    const downX = e.clientX;
+    const downY = e.clientY;
+    const clientWidth = document.documentElement.clientWidth;
+    const clientHeight = document.documentElement.clientHeight;
+    const maxLeft = clientWidth - parentElementRect.width;
+    const maxTop = clientHeight - parentElementRect.height;
+    const minLeft = 0;
+    const minTop = 0;
+    function onMousemove(e: MouseEvent) {
+      let moveX = parentElementRect.left + (e.clientX - downX);
+      let moveY = parentElementRect.top + (e.clientY - downY);
+      moveX = moveX < minLeft ? minLeft : moveX > maxLeft ? maxLeft : moveX;
+      moveY = moveY < minTop ? minTop : moveY > maxTop ? maxTop : moveY;
+      pos.value = {
+        top: moveY,
+        left: moveX
+      };
+    }
+    function onMouseup() {
+      document.removeEventListener('mousemove', onMousemove);
+      document.removeEventListener('mouseup', onMouseup);
+    }
+    document.addEventListener('mousemove', onMousemove);
+    document.addEventListener('mouseup', onMouseup);
+  }
+  el.addEventListener('mousedown', mousedown);
+}
+
+// 缓存
+const localStorageName = 'dragCachePos';
+function getCachePos(useIdDargClass: string): null | undefined | posType {
+  const localCachePos = localStorage.getItem(localStorageName);
+  if (localCachePos) {
+    try {
+      return JSON.parse(localCachePos)[useIdDargClass];
+    } catch {
+      return null;
+    }
+  }
+  return null;
+}
+function setCachePos(useIdDargClass: string, pos: posType) {
+  const localCachePos = localStorage.getItem(localStorageName);
+  let cachePosObj: Record<string, any> = {};
+  if (localCachePos) {
+    try {
+      cachePosObj = JSON.parse(localCachePos);
+    } catch {
+      //
+    }
+  }
+  cachePosObj[useIdDargClass] = pos;
+  localStorage.setItem(localStorageName, JSON.stringify(cachePosObj));
+}

+ 39 - 0
src/hooks/useDrag/useDragGuidance.ts

@@ -0,0 +1,39 @@
+import { getGuidance, setGuidance } from "../../page-instrument/custom-plugins/guide-page/api"
+import { ref } from "vue"
+
+export default function useDragGuidance() {
+   // 引导页
+   const guidanceShow = ref(false)
+   let guideInfoData: Record<string, any> = {}
+   getGuidanceShow()
+   async function getGuidanceShow() {
+      try {
+         const res = await getGuidance({ guideTag: "guideInfo" })
+         if (res.code === 200) {
+            if (res.data) {
+               const guideInfo = JSON.parse(res.data?.guideValue) || null
+               if (guideInfo) {
+                  guideInfoData = guideInfo
+                  guidanceShow.value = !guideInfo.teacherDrag
+               }
+            } else {
+               guidanceShow.value = true
+            }
+         }
+      } catch (e) {
+         console.log(e)
+      }
+   }
+   function setGuidanceShow() {
+      try {
+         setGuidance({ guideTag: "guideInfo", guideValue: JSON.stringify(Object.assign(guideInfoData, { teacherDrag: true })) })
+         guidanceShow.value = false
+      } catch (e) {
+         console.log(e)
+      }
+   }
+   return {
+      guidanceShow,
+      setGuidanceShow
+   }
+}

+ 43 - 4
src/page-instrument/custom-plugins/guide-page/teacher-bootom.tsx

@@ -6,7 +6,7 @@ import { getImage } from "./images";
 import { getQuery } from "/src/utils/queryString";
 import {getGuidance,setGuidance} from './api'
 import { headTopData } from "/src/page-instrument/header-top/index";
-import state from "/src/state";
+import state, { IPlatform } from "/src/state";
 
 export default defineComponent({
 	name: "aiTeacher-guide",
@@ -15,7 +15,46 @@ export default defineComponent({
 		const data = reactive({
 			box: {},
 			show: false,
-			steps: [
+			steps: state.platform === IPlatform.PC ? [
+				{
+					img: getImage("aiTeacher2.png"),
+					eleRect: {
+						top: "-3rem",
+					},
+					imgStyle: {
+						left: "-0.7rem",
+						width: "6.48rem",
+						height: "3.01rem",
+					},
+					btnsStyle: {
+						bottom: ".9rem",
+						left: ".9rem",
+						transform: "scale(.83)",
+					},
+					boxStyle: {
+						borderRadius: "40px",
+					},
+				},
+				{
+					img: getImage("aiTeacher3.png"),
+					eleRect: {
+						top: "-3rem",
+					},
+					imgStyle: {
+						left: "-0.7rem",
+						width: "6.48rem",
+						height: "3rem",
+					},
+					btnsStyle: {
+						bottom: ".9rem",
+						left: ".8rem",
+						transform: "scale(.83)",
+					},
+					boxStyle: {
+						borderRadius: "40px",
+					},
+				}
+			] : [
 				{
 					eleRect: {
 						left: "4.5rem",
@@ -142,7 +181,7 @@ export default defineComponent({
 		// } else {
 		// 	tipShow.value = true;
 		// }
-		const steps = ["modeType-box", "modeType-0", "modeType-1", "modeType-2"];
+		const steps = state.platform === IPlatform.PC ? ["modeType-0", "modeType-1"] : ["modeType-box", "modeType-0", "modeType-1", "modeType-2"];
 		const getStepELe = () => {
 			console.log(steps[data.step]);
 			const ele: HTMLElement = document.getElementById(steps[data.step])!;
@@ -168,7 +207,7 @@ export default defineComponent({
 			getStepELe();
 		});
 		const handleNext = () => {
-			if (data.step >= 3) {
+			if (data.step >= 3 || (state.platform === IPlatform.PC && data.step >= 1)) {
 				endGuide();
 				return;
 			}

+ 1 - 1
src/page-instrument/follow-model/index.module.less

@@ -41,7 +41,7 @@
 .pcEndBtn {
   width: 36px;
   height: 36px;
-  left: 32px;
+  left: 46px;
   bottom: 12px !important;
   margin-left: initial;
 }

+ 4 - 0
src/page-instrument/header-top/index.module.less

@@ -253,4 +253,8 @@
             pointer-events: auto;
         }
     }
+}
+
+.pcTransPop {
+    z-index: 999 !important;
 }

+ 2 - 2
src/page-instrument/header-top/index.tsx

@@ -291,7 +291,7 @@ export default defineComponent({
     const changePlay = (res: any) => {
       // console.log('监听上课页面message',res)
       if (res?.data?.api === "setPlayState") {
-        togglePlay("paused");
+        togglePlay("paused","courseware");
       }
 
       // 菜单状态
@@ -518,7 +518,7 @@ export default defineComponent({
             </Popover>
             {
               state.enableNotation ? 
-              <Popover trigger="manual" v-model:show={headData.musicTypeShow} placement={state.platform === IPlatform.PC ? "top-end" : "bottom-end"} overlay={false} offset={state.platform === IPlatform.PC ? [0,40] : [0,8]}>
+              <Popover trigger="manual" v-model:show={headData.musicTypeShow} class={state.platform === IPlatform.PC && styles.pcTransPop} placement={state.platform === IPlatform.PC ? "top-end" : "bottom-end"} overlay={false} offset={state.platform === IPlatform.PC ? [0,40] : [0,8]}>
                 {{
                   reference: () => (
                     <div

+ 1 - 1
src/page-instrument/header-top/music-type/index.tsx

@@ -83,7 +83,7 @@ export default defineComponent({
 						<div>固定调</div>
 					</div>
 				</div>
-				<Popup teleport="body" closeOnClickOverlay={false} defaultStyle={false} v-model:show={musicTypeData.show} class="transBoxClass_drag" style={positionInfo.styleDrag.value}>
+				<Popup teleport="body" closeOnClickOverlay={true} defaultStyle={false} v-model:show={musicTypeData.show} class="transBoxClass_drag" style={positionInfo.styleDrag.value}>
 					<TheComfirm tip="设置成功,是否立即重新加载?" onClose={handleResult} />
 					{ state.platform === IPlatform.PC && <Dragbom showGuide={!state.guideInfo?.teacherDrag} onGuideDone={handleGuide}  /> }
 				</Popup>

+ 2 - 1
src/page-instrument/view-detail/index.tsx

@@ -375,9 +375,10 @@ export default defineComponent({
       detailData.fingerPreView = false;
       detailData.fingerPreViewGuide = false;
     };
+    console.log(1111222,state.zoom)
     return () => (
       <div
-        class={[styles.detail, state.setting.eyeProtection && "eyeProtection", state.platform === IPlatform.PC && styles.PC, state.isPreView && styles.preViewDetail, state.isSingleLine && styles.singleLineDetail]}
+        class={[styles.detail, state.setting.eyeProtection && "eyeProtection", (state.platform === IPlatform.PC && state.zoom > 0.8) && styles.PC, state.isPreView && styles.preViewDetail, state.isSingleLine && styles.singleLineDetail]}
         style={{
           paddingLeft: detailData.paddingLeft,
           background: state.setting.camera ? `rgba(${state.setting.eyeProtection ? "253,244,229" : "255,255,255"} ,${state.setting.cameraOpacity / 100}) !important` : "",

+ 38 - 17
src/page-instrument/view-figner/change-subject/index.module.less

@@ -1,12 +1,13 @@
 .changeSubject {
-  padding: 18px 0;
+  padding: 49px 17px 19px 24px;
+
 }
 
 .changeSubjectContainer {
-  height: 217px;
+  height: 187px;
   overflow-x: hidden;
   overflow-y: auto;
-  padding: 0 15px;
+  padding: 0;
 
   &::-webkit-scrollbar {
     display: none;
@@ -19,7 +20,7 @@
 
   font-size: 16px;
   font-weight: 500;
-  color: #333333;
+  color: #AE8967;
   line-height: 22px;
 
   &::before {
@@ -27,7 +28,7 @@
     display: inline-block;
     width: 4px;
     height: 11px;
-    background: #1CACF1;
+    background: #D5AD89;
     border-radius: 3px;
     margin-right: 6px;
   }
@@ -37,18 +38,18 @@
   display: flex;
   align-items: center;
   flex-wrap: wrap;
-  padding-top: 18px;
+  padding-top: 7px;
 
   .subjectItem {
     width: 31%;
     height: 34px;
     line-height: 34px;
     text-align: center;
-    background: #F6F6F6;
+    // background: #F6F6F6;
     border-radius: 50px;
     font-size: 13px;
     color: #333333;
-    border: 1px solid #F6F6F6;
+    border: 1px solid #D8D8D8;
     margin-bottom: 12px;
 
     &:nth-child(3n + 2) {
@@ -75,12 +76,13 @@
 
 
     &.active {
-      border: 1px solid #1CACF1;
-      background: #EBF8FF;
-      color: #1CACF1;
+      background: #FFF6E7;
+      border-radius: 16px;
+      border: 1px solid #AE8967;
+      color: #A98464;
 
       &::after {
-        border-bottom: 4px solid #1CACF1;
+        border-bottom: 4px solid #C4A78D;
         transform: translateY(-2px) rotate(0deg);
       }
     }
@@ -90,14 +92,33 @@
 }
 
 .btnGroups {
-  border-top: 1px solid #F2F2F2;
+  border-top: 1px solid #EBEBEB;
   display: flex;
   align-items: center;
-  padding: 18px 15px 0;
+  padding: 8px 15px 0;
+
+  // :global {
+  //   .van-button+.van-button {
+  //     margin-left: 15px;
+  //   }
+  // }
 
-  :global {
-    .van-button+.van-button {
-      margin-left: 15px;
+  .btn {
+    width: 143px;
+    height: 44px;
+
+    &+.btn {
+      margin-left: 9px;
     }
   }
+
+  .resetBtn {
+    background: url('../image/subject-btn1.png') no-repeat center;
+    background-size: contain;
+  }
+
+  .confirmBtn {
+    background: url('../image/subject-btn2.png') no-repeat center;
+    background-size: contain;
+  }
 }

+ 105 - 11
src/page-instrument/view-figner/change-subject/index.tsx

@@ -1,4 +1,4 @@
-import { defineComponent, onMounted, reactive } from "vue";
+import { defineComponent, onMounted, reactive, watch } from "vue";
 import styles from "./index.module.less";
 import { Button, showToast } from "vant";
 
@@ -22,22 +22,57 @@ export default defineComponent({
       selectList: [] as any,
     });
 
+    // subject 变化时候 重新刷新
+    watch(()=>props.subject,()=>{
+      selectItem()
+    })
     //
     const selectItem = () => {
-      const i: any = props.subjectList.find((item: any) => item.value === props.subject);
-      if (i) {
-        state.subjectValue = i.id;
-        state.instrumentCode = i.value;
-        state.selectList = [];
+      // const i: any = props.subjectList.find((item: any) => item.value === props.subject);
+      // if (i) {
+      //   state.subjectValue = i.id;
+      //   state.instrumentCode = i.value;
+      //   state.selectList = [];
+      // }
+      // const i: any = props.subjectList.find((item: any) => item.value === props.subject);
+      let i: any = {};
+      props.subjectList.forEach((item: any) => {
+        if (Array.isArray(item.children)) {
+          item.children.forEach((child: any) => {
+            if (child.value === props.subject) {
+              i = {
+                ...child,
+                parentId: item.id,
+              };
+              state.instrumentCode = child.value;
+              state.subjectValue = item.id;
+              state.selectList = item.children || [];
+            }
+          });
+        }
+      });
+      if (!i) {
+        props.subjectList.forEach((item: any) => {
+          if (item.children && item.children.length > 0) {
+            item.children.forEach((child: any) => {
+              if (child.value === props.subject) {
+                state.instrumentCode = child.value;
+                state.subjectValue = item.id;
+                state.selectList = item.children;
+              }
+            });
+          }
+        });
       }
     };
 
     onMounted(() => {
+      console.log(props.subjectList, "subjectList", props.subject);
       selectItem();
     });
     return () => (
       <div class={styles.changeSubject}>
-        <div class={styles.changeSubjectContainer}>
+        {/* <div class={styles.changeSubjectContainer}>
           <div class={styles.title}>乐器</div>
 
           <div class={styles.subjectContainer}>
@@ -57,12 +92,71 @@ export default defineComponent({
               </div>
             ))}
           </div>
+        </div> */}
+        <div class={[styles.changeSubjectContainer,"changeSubjectContainer_pc"]}>
+          <div class={styles.title}>声部</div>
+
+          <div class={styles.subjectContainer}>
+            {props.subjectList.map((item: any) => (
+              <div
+                class={[styles.subjectItem, item.children.length > 0 && styles.arrow, item.id === state.subjectValue && styles.active]}
+                onClick={() => {
+                  if (item.children.length <= 0) {
+                    state.instrumentCode = "";
+                  }
+                  state.subjectValue = item.id;
+                  state.selectList = item.children;
+                  if (state.selectList.length > 0) {
+                    state.instrumentCode = state.selectList[0].value;
+                  }
+                }}
+              >
+                {item.text}
+              </div>
+            ))}
+          </div>
+
+          {state.selectList.length > 0 && (
+            <>
+              <div class={styles.title}>乐器</div>
+              <div class={styles.subjectContainer}>
+                {state.selectList.map((item: any) => (
+                  <div
+                    class={[styles.subjectItem, item.value === state.instrumentCode && styles.active]}
+                    onClick={() => {
+                      state.instrumentCode = item.value;
+                    }}
+                  >
+                    {item.text}
+                  </div>
+                ))}
+              </div>
+            </>
+          )}
         </div>
 
-        <div class={styles.btnGroups}>
-          <Button
+        <div class={[styles.btnGroups,"btnGroups_pc"]}>
+          <div
+            class={[styles.btn, styles.resetBtn]}
+            onClick={() => {
+              emit("close");
+              selectItem();
+            }}
+          ></div>
+          <div
+            class={[styles.btn, styles.confirmBtn]}
+            onClick={() => {
+              if (state.selectList.length > 0 && !state.instrumentCode) {
+                showToast("请选择乐器");
+                return;
+              }
+              emit("confirm", state.instrumentCode || state.subjectValue);
+            }}
+          ></div>
+          {/* <Button
             round
             block
+            class={styles.resetBtn}
             onClick={() => {
               emit("close");
               selectItem();
@@ -74,7 +168,7 @@ export default defineComponent({
             type="primary"
             block
             round
-            color="linear-gradient(90deg, #44C9FF 0%, #259CFE 100%)"
+            class={styles.confirmBtn}
             onClick={() => {
               if (state.selectList.length > 0 && !state.instrumentCode) {
                 showToast("请选择乐器");
@@ -84,7 +178,7 @@ export default defineComponent({
             }}
           >
             确认
-          </Button>
+          </Button> */}
         </div>
       </div>
     );

BIN
src/page-instrument/view-figner/image/btnBg.png


BIN
src/page-instrument/view-figner/image/icon_shuo_v.png


BIN
src/page-instrument/view-figner/image/noteImg.png


BIN
src/page-instrument/view-figner/image/subJect-bg2.png


BIN
src/page-instrument/view-figner/image/subJect-bg3.png


BIN
src/page-instrument/view-figner/image/subject-bg1.png


BIN
src/page-instrument/view-figner/image/subject-btn1.png


BIN
src/page-instrument/view-figner/image/subject-btn2.png


+ 251 - 5
src/page-instrument/view-figner/index.module.less

@@ -108,6 +108,28 @@
             }
         }
     }
+    .tipsOverlay{
+        width: 57%;
+        height: 100%;
+        position: fixed;
+        top: 0;
+        left: 0;
+        z-index: 2009;
+        animation: bgIn 0.2s 0.2s forwards;
+    }
+    &.fingerRight .tipsPcBg.tips{
+        animation: bgIn 0.15s 0.25s forwards;
+        border-radius:0;
+        background-image: url('./image/icon_shuo_v.png') !important;
+    }
+    @keyframes bgIn {
+        0%{
+            background-color: initial;
+        }
+        100%{
+            background-color: rgba(0,0,0,0.5);
+        }
+    }
 }
 
 .popoverContainer {
@@ -238,11 +260,130 @@
         display: flex;
         flex-direction: column;
     }
-
+    .userTab{
+        display: flex;
+        justify-content: center;
+        width: 100%;
+        .userTabBox{
+            width: 100%;
+            .notes{
+                padding-bottom: 10px;
+                height: initial;
+                .lastNoteContent{
+                    border-radius: 0 !important; 
+                    .noteBox{
+                        border-radius: 0 !important;
+                    }
+                }
+                .noteContent{
+                    padding: 0 10px;
+                }
+                .changeMusBtn{
+                    margin-right: 8px;
+                    text-align: center;
+                    width: 42px;
+                    background: linear-gradient( 180deg, #F4EFED 0%, #D9CEC7 100%);
+                    box-shadow: 0px 1px 2px 0px #9F9690, inset 0px -2px 0px 0px #CDC0B5, inset 0px 2px 1px 0px #FFFFFF;
+                    border-radius: 21px;
+                    font-weight: 600;
+                    font-size: 12px;
+                    color: #616161;
+                    line-height: 16px;
+                    padding: 7px 6px;
+                    height: 46px;
+                }
+                .backBtn{
+                    line-height: 32px;
+                }
+            }
+            .optionBtns{
+                padding-bottom: 0;
+            }
+            :global{
+                .van-tabs__wrap{
+                    width: 100%;
+                    display: flex;
+                    justify-content: center;
+                    height: 30px;
+                    .van-tabs__nav{
+                        width: 120px;
+                        background-color: initial;
+                        border-bottom: 2px solid rgba(82,138,214,0.15);
+                        height: initial;
+                        padding-bottom: initial;
+                        .van-tab{
+                            font-weight: 400;
+                            font-size: 15px;
+                            color: #616161;
+                            &.van-tab--active{
+                                font-weight: 600;
+                                color: #616161;
+                            }
+                        }
+                        .van-tabs__line{
+                            width: 32px;
+                            bottom: -2px;
+                            height: 2px;
+                            background: #528AD6;
+                            border-radius: 3px;
+                        }
+                    }
+                }
+                .van-tabs__content{
+                    padding-top: 16px;
+                    height: 130px;
+                    .van-tab__panel{
+                        height: 100%;
+                    }
+                }
+            }
+            .btnBox{
+                height: 100%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                margin-top: -16px;
+                .btnCon{
+                    border-radius: 17px;
+                    display: flex;
+                    background: rgba(255, 255, 255, 0.5);
+                    padding: 6px 5px 3px 6px;
+                    .btnGr{
+                        background: url("./image/btnBg.png") no-repeat;
+                        background-size: 100% 100%;
+                        width: 93px;
+                        height: 56px;
+                        display: flex;
+                        flex-direction: column;
+                        align-items: center;
+                        justify-content: center;
+                        cursor: pointer;
+                        margin-left: 5px;
+                        &:first-child{
+                            margin-left: 0;
+                        }
+                        >img{
+                            width: 19px;
+                            height: 19px;
+                        }
+                        >span{
+                            font-weight: 500;
+                            font-size: 14px;
+                            color: #616161;
+                            line-height: 20px;
+                        }
+                    }
+                }
+            }
+        }
+    }
     .boxFinger {
         flex: 1;
         padding-top: 50px;
         overflow: hidden;
+        &.pcBoxFinger{
+            padding-top: 10px !important;
+        }
     }
 
 
@@ -419,7 +560,45 @@
 
     }
 }
-
+.btnGrToggleBtn{
+    font-weight: 600;
+    font-size: 12px;
+    color: #fff;
+    >div{
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        z-index: 10;
+        &.nameBox{
+            padding-top: 2px;
+            .name{
+                font-size: 10px;
+            }
+            .noteKey{
+                font-size: 12px;
+                position: relative;
+                color: #ffffff;
+            }
+            .dot {
+                display: inline-block;
+                position: absolute;
+                top: 0px;
+                &.botDot{
+                    top: initial;
+                    bottom: -2px;
+                }
+            }
+        }
+    }
+    .name{
+        display: flex;
+    }
+    .arrowImg{
+        margin-top: 2px;
+        width: 9px;
+        height: 5px;
+    }
+}
 .notes {
     position: relative;
     display: flex;
@@ -957,7 +1136,14 @@
         .dot {
             display: inline-block;
             position: absolute;
-            top: 0;
+            left: 50%;
+            transform: translateX(-50%);
+            &.topDot {
+                top: 0;
+            }
+            &.bottomDot {
+                top: initial;
+            }
         }
 
         .noteName {
@@ -1261,9 +1447,11 @@
 
 .changeSubjectPopup {
     width: 375px;
-    // height: 310px;
-    background: #FFFFFF;
+    height: 307px;
+    background: url('./image/subject-bg1.png') no-repeat center;
     border-radius: 12px;
+    background-size: contain;
+    overflow: initial;
 }
 
 .linkSourceClass {
@@ -1301,4 +1489,62 @@
     // .backBtn {
     //     display: none;
     // }
+}
+.dragTopBox{
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 40px;
+    width: 100%; 
+}
+:global{
+    .changeSubjectShowBoxClass_drag{
+        height: 307px !important;
+        background: url('./image/subject-bg2.png') no-repeat center !important;
+        background-size: contain !important;
+        .dragbomBox{
+            height: 37px;
+        }
+        .changeSubjectContainer_pc{
+            height: 168px !important;
+        }
+        .btnGroups_pc{
+            padding-top: 12px !important;
+        }
+    }
+    .tnoteShowBoxClass_drag{
+        padding: 49px 17px 30px 24px;
+        width: 375px;
+        overflow: initial;
+        height: 247px !important;
+        background: url('./image/subject-bg3.png') no-repeat center !important;
+        background-size: contain !important;
+        .dragbomBox{
+            height: 37px;
+        }
+        .toneTitle_pc{
+            display: none;
+        }
+        .tipContentbox_pc{
+            background-color: initial;
+            &::after{
+                display: none;
+            }
+            .tipContent_pc{
+                border:none;
+                .tipWrap_pc{
+                    height: 116px !important;
+                    flex: initial;
+                    overflow-y: auto;
+                    &::-webkit-scrollbar {
+                        display: none;
+                    }
+                }
+                .toneAction_pc{
+                    padding-bottom: 0 !important;
+                    padding-top: 12px !important;
+                }
+            }
+        }
+    }
 }

Файловите разлики са ограничени, защото са твърде много
+ 622 - 258
src/page-instrument/view-figner/index.tsx


+ 2 - 2
src/state.ts

@@ -652,10 +652,10 @@ export const skipNotePlay = async (itemIndex: number, isStart = false) => {
  * 切换曲谱播放状态
  * @param playState 可选: 默认 undefined, 需要切换的状态 play:播放, paused: 暂停
  */
-export const togglePlay = async (playState?: "play" | "paused") => {
+export const togglePlay = async (playState?: "play" | "paused", sourceType?: string) => {
   // 如果mp3资源还在加载中,给出提示
   if (!state.isAppPlay && !state.audioDone) {
-    showToast('音频资源加载中,请稍后')
+    if (sourceType !== 'courseware') showToast('音频资源加载中,请稍后')
     return
   }
   // midi播放

+ 2 - 2
src/view/fingering/fingering-config.ts

@@ -474,7 +474,7 @@ export const subjectFingering = (subjectId: number | string): IFingering => {
         code: "陶笛",
         hasTizhi: false,
         id: 39,
-      };      
+      };
     case "melodica": // 口风琴
       return {
         name: "melodica",
@@ -704,7 +704,7 @@ export const getFingeringConfig = async (type: IVocals | undefined): Promise<ITy
         styles: {
           marginTop: "auto",
         },
-      };      
+      };
     case "melodica":
       const melodica = await import(`./fingering-img/melodica/index.json`);
       return {

+ 1 - 1
src/view/music-score/index.tsx

@@ -116,7 +116,7 @@ export default defineComponent({
 			// osmd.EngravingRules.CompactMode = true // 紧凑模式
 			osmd.EngravingRules.PageRightMargin = state.isSingleLine ? (window.innerWidth+200)/10 : 2;
 			osmd.EngravingRules.FixedMeasureWidth = state.isSingleLine ? true : false; // 是否固定小节的宽度(小节同一宽度渲染)
-			osmd.EngravingRules.PageTopMargin = state.platform === IPlatform.PC ? 8 : 10; // 老师端顶部间距
+			osmd.EngravingRules.PageTopMargin = state.platform === IPlatform.PC ? 9 : 10; // 老师端顶部间距
 			osmd.EngravingRules.PageTopMarginNarrow = 3;
 			osmd.EngravingRules.PageLeftMargin = 2;
 			// 老师端上课页面,左右两边有功能按钮,所以左右边距需要加大

+ 11 - 0
src/view/plugins/toggleMusicSheet/choosePartName/index.module.less

@@ -63,6 +63,16 @@
         //height: 80% !important;
       }
     }
+    &.pcPicker {
+      :global {
+        .van-ellipsis {
+          font-size: 20PX;
+        }
+        .van-picker-column__item {
+          height: 60px;
+        }
+      }
+    }
   }
 
   .button {
@@ -77,6 +87,7 @@
     height: 380PX;
     border-radius: 16PX;
     .button {
+      width: 40%;
       margin-bottom: 30PX;
     }
     .title {

+ 2 - 2
src/view/plugins/toggleMusicSheet/choosePartName/index.tsx

@@ -46,7 +46,7 @@ export default defineComponent({
         </div>
         <Picker
           ref={myPicker}
-          class={styles.picker}
+          class={[styles.picker, state.platform === IPlatform.PC && styles.pcPicker]}
           defaultIndex={props.partIndex}
           v-model={selValues.value}
           showToolbar={false}
@@ -59,7 +59,7 @@ export default defineComponent({
           }}
         />
         <Button class={styles.button} type="primary" round block onClick={() => {
-            console.log(1111,selectIndex.value)
+            // console.log(1111,selectIndex.value)
             if (partIndexChanged.value) {
               emit('close', selectIndex.value)
             } else {

+ 22 - 8
src/view/plugins/useDrag/dragbom.tsx

@@ -1,4 +1,4 @@
-import { defineComponent, computed, reactive, onMounted } from 'vue';
+import { defineComponent, computed, reactive, onMounted, nextTick } from 'vue';
 import styles from './index.module.less';
 // 底部拖动区域
 export default defineComponent({
@@ -13,17 +13,31 @@ export default defineComponent({
 	},
   setup(props, { emit }) {
     const data = reactive({
-      guidePos: "bottom" as "bottom" | "top",
+      guidePos: "bottom" as "bottom" | "left" | "right",
     });
 
     const initGuidePos = () => {
       const pageHeight = document.documentElement.clientHeight || document.body.clientHeight;
-      const guideHeight = document.querySelector('.bom_guide')?.getBoundingClientRect().height || 0;
-      const dragTop = document.querySelector('.bom_drag')?.getBoundingClientRect()?.top || 0;
-      data.guidePos = pageHeight - dragTop < guideHeight ? "top" : "bottom";
+      const pageWidth = document.documentElement.clientWidth || document.body.clientWidth;
+      const guideHeight = document.querySelector('.bom_guide')?.clientHeight || 0;
+      const guideWidth = document.querySelector('.bom_guide')?.clientWidth || 0;
+      const dragBBox = document.querySelector('.bom_drag')?.getBoundingClientRect();
+      const dragTop = dragBBox?.top || 0;
+      const dragLeft = dragBBox?.left || 0;
+      // 引导页出现在下边
+      if (pageHeight - dragTop > guideHeight) {
+        data.guidePos = "bottom"
+      } else {
+        // 引导页出现在左边or右边
+        data.guidePos = dragLeft > guideWidth ? "left" : "right"
+      }
     }
     onMounted(() => {
-      initGuidePos();
+      nextTick(() => {
+        setTimeout(() => {
+          initGuidePos();
+        }, 0);
+      });
     });
     return () => (
       <>
@@ -33,9 +47,9 @@ export default defineComponent({
         </div>
         {
           props.showGuide && 
-          <div class={[styles.guide, data.guidePos === "top" && styles.guideTop, 'bom_guide']}>
+          <div class={[styles.guide, data.guidePos === "left" && styles.guideLeft, data.guidePos === "right" && styles.guideRight, 'bom_guide']} onClick={() => emit("guideDone")}>
             <div class={styles.guideBg}></div>
-            <div class={styles.guideDone} onClick={() => emit("guideDone")}></div>
+            <div class={styles.guideDone}></div>
           </div>          
         }
 

BIN
src/view/plugins/useDrag/img/modalDragBgLeft.png


BIN
src/view/plugins/useDrag/img/modalDragBgRight.png


+ 18 - 0
src/view/plugins/useDrag/index.module.less

@@ -64,4 +64,22 @@
       background-size: 100% 100%;
     }
   }
+  &.guideLeft {
+    top: initial;
+    left: -180px;
+    bottom: -5px;
+    .guideBg {
+      background: url('./img/modalDragBgLeft.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+  &.guideRight {
+    top: initial;
+    left: calc(100% - 12px);
+    bottom: -5px;
+    .guideBg {
+      background: url('./img/modalDragBgRight.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
 }

+ 6 - 0
src/view/plugins/useDrag/index.ts

@@ -69,9 +69,15 @@ export default function useDrag(
     // 有缓存 用缓存的值,没有缓存用默认
     if (posCache) {
       pos.value = posCache;
+      nextTick(() => {
+        refreshPos();
+      });
     }
   }
   function refreshPos() {
+    if (pos.value.left === -1 && pos.value.top === -1) {
+      return;
+    }
     const boxClassDom = document.querySelector(`.${boxClass}`) as HTMLElement;
     if (!boxClassDom) return;
     const parentElementRect = boxClassDom.getBoundingClientRect();

+ 1 - 1
src/view/selection/index.tsx

@@ -263,7 +263,7 @@ export default defineComponent({
 										styles.position,
 										showClass.value(item),
 										scoreItem ? `scoreItemLeve${scoreItem.leve}` : "",
-										state.platform === IPlatform.PC ? styles.linePC : '',
+										(state.platform === IPlatform.PC && state.zoom > 0.8) ? styles.linePC : '',
 									]}
 									style={item.staveBox}
 									onClick={() => handleSelection(item)}

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
stats.html


+ 82 - 82
vite.config.ts

@@ -4,90 +4,90 @@ import vueJsx from "@vitejs/plugin-vue-jsx";
 import legacy from "@vitejs/plugin-legacy";
 import { resolve } from "path";
 import postCssPxToRem from "postcss-pxtorem";
-import { visualizer } from 'rollup-plugin-visualizer';
-import viteCompression from 'vite-plugin-compression';
+import { visualizer } from "rollup-plugin-visualizer";
+import viteCompression from "vite-plugin-compression";
 
 // https://vitejs.dev/config/
 export default defineConfig({
-	base: "./",
-	resolve: {},
-	// assetsInclude: ['**/*.html'],
-	plugins: [
-		// mkcert(), // 本地https
-		legacy({
-			targets: ['Chrome 63'],
-			additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
-			modernPolyfills: true
-		  }),
-		vue(),
-		vueJsx(),
-		visualizer({ open: true }), // 自动开启分析页面
-	],
-	css: {
-		postcss: {
-			plugins: [
-				postCssPxToRem({
-					rootValue: 37.5,
-					propList: ["*"],
-					selectorBlackList: [".norem"],
-				}),
-			],
-		},
-	},
-	build: {
-		rollupOptions: {
-			input: {
-				gym: resolve(__dirname, "index.html"),
-				colexiu: resolve(__dirname, "colexiu.html"),
-				orchestra: resolve(__dirname, "orchestra.html"),
-				"report-share": resolve(__dirname, "report-share.html"),
-				instrument: resolve(__dirname, "instrument.html"),
-			},
-			output: {
-				chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
-				entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
-				assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
-			},
-		},
-	},
-	server: {
-		cors: true,
-		port: 3000,
-		// https: true,
-		proxy: {
-			"^/gym/.*": {
-				target: "https://mstutest.dayaedu.com",
-				// target: "https://online.dayaedu.com",
-				changeOrigin: true,
-				rewrite: (path) => path.replace(/^\/gym/, ""),
-			},
-			"^/colexiu/.*": {
-				target: "https://dev.colexiu.com",
-				// target: "https://online.colexiu.com",
-				changeOrigin: true,
-				rewrite: (path) => path.replace(/^\/colexiu/, ""),
-			},
-			"^/orchestra/.*": {
-				target: "https://test.lexiaoya.cn",
-				changeOrigin: true,
-				rewrite: (path) => path.replace(/^\/orchestra/, ""),
-			},
-			"^/instrument/.*": {
-				// target: "https://kt.colexiu.com",
-				// target: "https://test.lexiaoya.cn",
-				// target: "https://dev.kt.colexiu.com",
-				target: "https://test.resource.colexiu.com", // 内容平台开发环境,内容平台开发,需在url链接上加上isCbs=true
-				// target: "https://dev.resource.colexiu.com",
-				// target: "https://test.kt.colexiu.com",
-				// target: "https://mec.colexiu.com",
-				changeOrigin: true,
-				rewrite: (path) => path.replace(/^\/instrument/, ""),
-			},
-		},
-	},
-	preview:{
-		port: 3000,
-		host: '192.168.3.114'
-	}
+  base: "./",
+  resolve: {},
+  // assetsInclude: ['**/*.html'],
+  plugins: [
+    // mkcert(), // 本地https
+    legacy({
+      targets: ["Chrome 63"],
+      additionalLegacyPolyfills: ["regenerator-runtime/runtime"],
+      modernPolyfills: true,
+    }),
+    vue(),
+    vueJsx(),
+    visualizer({ open: true }), // 自动开启分析页面
+  ],
+  css: {
+    postcss: {
+      plugins: [
+        postCssPxToRem({
+          rootValue: 37.5,
+          propList: ["*"],
+          selectorBlackList: [".norem"],
+        }),
+      ],
+    },
+  },
+  build: {
+    rollupOptions: {
+      input: {
+        gym: resolve(__dirname, "index.html"),
+        colexiu: resolve(__dirname, "colexiu.html"),
+        orchestra: resolve(__dirname, "orchestra.html"),
+        "report-share": resolve(__dirname, "report-share.html"),
+        instrument: resolve(__dirname, "instrument.html"),
+      },
+      output: {
+        chunkFileNames: "js/[name]-[hash].js", // 引入文件名的名称
+        entryFileNames: "js/[name]-[hash].js", // 包的入口文件名称
+        assetFileNames: "[ext]/[name]-[hash].[ext]", // 资源文件像 字体,图片等
+      },
+    },
+  },
+  server: {
+    cors: true,
+    port: 3000,
+    // https: true,
+    proxy: {
+      "^/gym/.*": {
+        target: "https://mstutest.dayaedu.com",
+        // target: "https://online.dayaedu.com",
+        changeOrigin: true,
+        rewrite: (path) => path.replace(/^\/gym/, ""),
+      },
+      "^/colexiu/.*": {
+        target: "https://dev.colexiu.com",
+        // target: "https://online.colexiu.com",
+        changeOrigin: true,
+        rewrite: (path) => path.replace(/^\/colexiu/, ""),
+      },
+      "^/orchestra/.*": {
+        target: "https://test.lexiaoya.cn",
+        changeOrigin: true,
+        rewrite: (path) => path.replace(/^\/orchestra/, ""),
+      },
+      "^/instrument/.*": {
+        // target: "https://kt.colexiu.com",
+        // target: "https://test.lexiaoya.cn",
+        target: "https://kt.colexiu.com",
+        // target: "https://test.resource.colexiu.com", // 内容平台开发环境,内容平台开发,需在url链接上加上isCbs=true
+        // target: "https://dev.resource.colexiu.com",
+        // target: "https://test.kt.colexiu.com",
+        // target: "https://mec.colexiu.com",
+        changeOrigin: true,
+        rewrite: (path) => path.replace(/^\/instrument/, ""),
+      },
+    },
+  },
+  preview: {
+    port: 3000,
+    host: "192.168.3.114",
+  },
 });
 // vite.config.js

Някои файлове не бяха показани, защото твърде много файлове са промени