TIANYONG 8 months ago
parent
commit
05b51d5309
36 changed files with 2032 additions and 620 deletions
  1. 10 9
      dist/colexiu.html
  2. 9 8
      dist/index.html
  3. 9 9
      dist/instrument.html
  4. 11 10
      dist/orchestra.html
  5. 7 6
      dist/report-share.html
  6. 5 0
      instrument.html
  7. 35 30
      src/hooks/useDrag/dragbom.tsx
  8. 32 21
      src/hooks/useDrag/index.ts
  9. 0 1
      src/hooks/useDrag/useDragGuidance.ts
  10. 1 0
      src/page-instrument/component/mode-type-mode/index.tsx
  11. BIN
      src/page-instrument/custom-plugins/guide-driver/images/evaluating/e4.png
  12. BIN
      src/page-instrument/custom-plugins/guide-driver/images/practise/d10.png
  13. 130 0
      src/page-instrument/custom-plugins/guide-driver/index.less
  14. 0 0
      src/page-instrument/custom-plugins/guide-driver/index.module.less
  15. 408 242
      src/page-instrument/custom-plugins/guide-driver/index.tsx
  16. 4 0
      src/page-instrument/evaluat-model/evaluat-result/index.tsx
  17. 35 17
      src/page-instrument/header-top/index.tsx
  18. 119 126
      src/page-instrument/header-top/modeView.tsx
  19. 8 0
      src/page-instrument/view-figner/change-subject/index.module.less
  20. 12 7
      src/page-instrument/view-figner/change-subject/index.tsx
  21. 488 0
      src/page-instrument/view-figner/fingeringPoint.ts
  22. 255 60
      src/page-instrument/view-figner/index.module.less
  23. 436 68
      src/page-instrument/view-figner/index.tsx
  24. 3 3
      src/state.ts
  25. 2 2
      src/view/fingering/fingering-config.ts
  26. 0 0
      src/view/fingering/fingering-img/hulusi-flute/index.json
  27. 9 0
      src/view/fingering/fingering-img/hulusi-flute0/index.json
  28. 0 0
      src/view/fingering/fingering-img/melodica/index.json
  29. 0 0
      src/view/fingering/fingering-img/melodica1/index.json
  30. 0 0
      src/view/fingering/fingering-img/pan-flute/index.json
  31. 0 0
      src/view/fingering/fingering-img/pan-flute1/index.json
  32. 0 0
      src/view/fingering/fingering-img/pan-flute2/index.json
  33. 0 0
      src/view/fingering/fingering-img/pan-flute3/index.json
  34. 3 1
      src/view/fingering/index.tsx
  35. 1 0
      src/view/selection/index.module.less
  36. 0 0
      stats.html

+ 10 - 9
dist/colexiu.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-7c3d5f60.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-cfb574f0.js"></script>
 
   <meta charset="UTF-8" />
   <link rel="icon" type="image/svg+xml" href="./vite.svg" />
@@ -40,12 +40,13 @@
       },
     })
   </script>
-  <script type="module" crossorigin src="./js/colexiu-817dd032.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-763e8b6a.js">
-  <link rel="modulepreload" crossorigin href="./js/index-624d1810.js">
-  <link rel="modulepreload" crossorigin href="./js/index-d6925e45.js">
-  <link rel="stylesheet" href="./css/index-ccf6117c.css">
-  <link rel="stylesheet" href="./css/colexiu-e8b419b5.css">
+  <script type="module" crossorigin src="./js/colexiu-234f0b98.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-f30bced8.js">
+  <link rel="modulepreload" crossorigin href="./js/index-563e1186.js">
+  <link rel="modulepreload" crossorigin href="./js/index-faeb03f1.js">
+  <link rel="modulepreload" crossorigin href="./js/index-236e13a9.js">
+  <link rel="stylesheet" href="./css/index-cfe86983.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">!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>
@@ -55,8 +56,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-95755a14.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/colexiu-legacy-587fa4ae.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-40f75a59.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 9 - 8
dist/index.html

@@ -2,7 +2,7 @@
 <html lang="ZH-cn">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-7c3d5f60.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-cfb574f0.js"></script>
 
   <meta charset="UTF-8">
   <link rel="icon" href="./favicon.ico" />
@@ -75,12 +75,13 @@
       }
     })
   </script>
-  <script type="module" crossorigin src="./js/gym-a1294940.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-763e8b6a.js">
-  <link rel="modulepreload" crossorigin href="./js/index-624d1810.js">
-  <link rel="modulepreload" crossorigin href="./js/index-1dc5c539.js">
+  <script type="module" crossorigin src="./js/gym-94329614.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-f30bced8.js">
+  <link rel="modulepreload" crossorigin href="./js/index-563e1186.js">
+  <link rel="modulepreload" crossorigin href="./js/index-22f26d47.js">
+  <link rel="modulepreload" crossorigin href="./js/index-236e13a9.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
-  <link rel="stylesheet" href="./css/index-ccf6117c.css">
+  <link rel="stylesheet" href="./css/index-cfe86983.css">
   <link rel="stylesheet" href="./css/index-85f95688.css">
   <link rel="stylesheet" href="./css/plyr-ad8ef5ae.css">
   <link rel="stylesheet" href="./css/index-171cd132.css">
@@ -97,8 +98,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-95755a14.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/gym-legacy-9c45ea39.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-097b0596.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 9 - 9
dist/instrument.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-7c3d5f60.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-cfb574f0.js"></script>
 
   <meta charset="UTF-8" />
   <meta name="viewport"
@@ -41,10 +41,10 @@
       })
     }
   </script>
-  <script type="module" crossorigin src="./js/instrument-e3875fa3.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-763e8b6a.js">
-  <link rel="stylesheet" href="./css/index-ccf6117c.css">
-  <link rel="stylesheet" href="./css/instrument-f3d1af9e.css">
+  <script type="module" crossorigin src="./js/instrument-dd2ce7b4.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-f30bced8.js">
+  <link rel="stylesheet" href="./css/index-cfe86983.css">
+  <link rel="stylesheet" href="./css/instrument-9ce1010f.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>
@@ -64,11 +64,11 @@
   <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
   <script>
     // VConsole will be exported to `window.VConsole` by default.
-    // var vConsole = new window.VConsole();
-  </script>
+    var vConsole = new window.VConsole();
+  </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-95755a14.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/instrument-legacy-4b1cdc45.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-e02d6237.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 11 - 10
dist/orchestra.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-7c3d5f60.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-cfb574f0.js"></script>
 
   <meta charset="UTF-8" />
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
@@ -41,14 +41,15 @@
       transition: opacity .3s;
     }
   </style>
-  <script type="module" crossorigin src="./js/orchestra-fb7429c2.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-763e8b6a.js">
-  <link rel="modulepreload" crossorigin href="./js/index-624d1810.js">
-  <link rel="modulepreload" crossorigin href="./js/index-d6925e45.js">
-  <link rel="modulepreload" crossorigin href="./js/index-1dc5c539.js">
-  <link rel="stylesheet" href="./css/index-ccf6117c.css">
+  <script type="module" crossorigin src="./js/orchestra-30fef581.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-f30bced8.js">
+  <link rel="modulepreload" crossorigin href="./js/index-563e1186.js">
+  <link rel="modulepreload" crossorigin href="./js/index-faeb03f1.js">
+  <link rel="modulepreload" crossorigin href="./js/index-22f26d47.js">
+  <link rel="modulepreload" crossorigin href="./js/index-236e13a9.js">
+  <link rel="stylesheet" href="./css/index-cfe86983.css">
   <link rel="stylesheet" href="./css/index-85f95688.css">
-  <link rel="stylesheet" href="./css/orchestra-8e05e751.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">!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>
@@ -69,8 +70,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-95755a14.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/orchestra-legacy-56a35f49.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-702b578f.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 7 - 6
dist/report-share.html

@@ -2,7 +2,7 @@
 <html lang="en">
 
 <head>
-  <script type="module" crossorigin src="./js/polyfills-7c3d5f60.js"></script>
+  <script type="module" crossorigin src="./js/polyfills-cfb574f0.js"></script>
 
   <meta charset="UTF-8" />
   <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
@@ -25,10 +25,11 @@
       transition: opacity .3s;
     }
   </style>
-  <script type="module" crossorigin src="./js/report-share-ad36c120.js"></script>
-  <link rel="modulepreload" crossorigin href="./js/index-763e8b6a.js">
+  <script type="module" crossorigin src="./js/report-share-2b948aea.js"></script>
+  <link rel="modulepreload" crossorigin href="./js/index-f30bced8.js">
   <link rel="modulepreload" crossorigin href="./js/plyr.min-c8c2777b.js">
-  <link rel="stylesheet" href="./css/index-ccf6117c.css">
+  <link rel="modulepreload" crossorigin href="./js/index-236e13a9.js">
+  <link rel="stylesheet" href="./css/index-cfe86983.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 +52,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-95755a14.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./js/report-share-legacy-7001a7f7.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-d1f9ef4f.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 5 - 0
instrument.html

@@ -53,6 +53,11 @@
   </script>
 
   <script type="module" src="/src/page-instrument/main.ts"></script>
+  <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
+  <script>
+    // VConsole will be exported to `window.VConsole` by default.
+    var vConsole = new window.VConsole();
+  </script>  
 </body>
 
 </html>

+ 35 - 30
src/hooks/useDrag/dragbom.tsx

@@ -1,16 +1,16 @@
-import { defineComponent, computed, reactive, onMounted } from 'vue';
-import styles from './index.module.less';
+import { defineComponent, computed, reactive, onMounted } from "vue";
+import styles from "./index.module.less";
 // 底部拖动区域
 export default defineComponent({
-  name: 'dragBom',
+  name: "dragBom",
   emits: ["guideDone"],
-	props: {
-		/** 是否显示引导 */
-		showGuide: {
-			type: Boolean,
-			default: false,
-		},
-	},
+  props: {
+    /** 是否显示引导 */
+    showGuide: {
+      type: Boolean,
+      default: false,
+    },
+  },
   setup(props, { emit }) {
     const data = reactive({
       guidePos: "bottom" as "bottom" | "left" | "right",
@@ -19,19 +19,20 @@ export default defineComponent({
     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 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 dragHeight = dragBBox?.height || 0;
       const dragLeft = dragBBox?.left || 0;
       // 引导页出现在下边
-      if (pageHeight - dragTop > guideHeight) {
-        data.guidePos = "bottom"
+      if (pageHeight - dragTop - dragHeight > guideHeight) {
+        data.guidePos = "bottom";
       } else {
         // 引导页出现在左边or右边
-        data.guidePos = dragLeft > guideWidth ? "left" : "right"
+        data.guidePos = dragLeft > guideHeight ? "left" : "right";
       }
-    }
+    };
     onMounted(() => {
       setTimeout(() => {
         initGuidePos();
@@ -39,21 +40,25 @@ export default defineComponent({
     });
     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 class={[styles.dragbomBox, "dragbomBox"]}>
+          <div class={[styles.dragBom, "bom_drag"]}>
+            <div class={styles.box}></div>
+            <div class={[styles.box, styles.right]}></div>
+          </div>
         </div>
-      </div>
-        {
-          props.showGuide && 
-          <div class={[styles.guide, data.guidePos === "left" && styles.guideLeft, data.guidePos === "right" && styles.guideRight, 'bom_guide']} onClick={() => emit("guideDone")}>
+        {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>          
-        }
-
+            <div
+              class={styles.guideDone}
+              onClick={(e) => {
+                e.stopPropagation();
+                emit("guideDone");
+              }}
+            ></div>
+          </div>
+        )}
       </>
     );
-  }
+  },
 });

+ 32 - 21
src/hooks/useDrag/index.ts

@@ -55,14 +55,14 @@ export default function useDrag(
     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'
-        };
+        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);
@@ -75,7 +75,7 @@ export default function useDrag(
     }
   }
   function refreshPos() {
-    if(pos.value.left === -1 && pos.value.top === -1){
+    if (pos.value.left === -1 && pos.value.top === -1) {
       return
     }
     const boxClassDom = document.querySelector(`.${boxClass}`) as HTMLElement;
@@ -105,19 +105,22 @@ export default function useDrag(
 
 // 拖动
 function drag(el: HTMLElement, parentElement: HTMLElement, pos: Ref<posType>) {
-  function mousedown(e: MouseEvent) {
+  function onDown(e: MouseEvent | TouchEvent) {
+    const isTouchEv = isTouchEvent(e);
+    const event = isTouchEv ? e.touches[0] : e;
     const parentElementRect = parentElement.getBoundingClientRect();
-    const downX = e.clientX;
-    const downY = e.clientY;
+    const downX = event.clientX;
+    const downY = event.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);
+    function onMove(e: MouseEvent | TouchEvent) {
+      const event = isTouchEvent(e) ? e.touches[0] : e;
+      let moveX = parentElementRect.left + (event.clientX - downX);
+      let moveY = parentElementRect.top + (event.clientY - downY);
       moveX = moveX < minLeft ? minLeft : moveX > maxLeft ? maxLeft : moveX;
       moveY = moveY < minTop ? minTop : moveY > maxTop ? maxTop : moveY;
       pos.value = {
@@ -125,14 +128,22 @@ function drag(el: HTMLElement, parentElement: HTMLElement, pos: Ref<posType>) {
         left: moveX
       };
     }
-    function onMouseup() {
-      document.removeEventListener('mousemove', onMousemove);
-      document.removeEventListener('mouseup', onMouseup);
+    function onUp() {
+      document.removeEventListener(
+        isTouchEv ? 'touchmove' : 'mousemove',
+        onMove
+      );
+      document.removeEventListener(isTouchEv ? 'touchend' : 'mouseup', onUp);
     }
-    document.addEventListener('mousemove', onMousemove);
-    document.addEventListener('mouseup', onMouseup);
+    document.addEventListener(isTouchEv ? 'touchmove' : 'mousemove', onMove);
+    document.addEventListener(isTouchEv ? 'touchend' : 'mouseup', onUp);
   }
-  el.addEventListener('mousedown', mousedown);
+  el.addEventListener('mousedown', onDown);
+  el.addEventListener('touchstart', onDown);
+}
+
+function isTouchEvent(e: MouseEvent | TouchEvent): e is TouchEvent {
+  return window.TouchEvent && e instanceof window.TouchEvent;
 }
 
 // 缓存

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

@@ -34,7 +34,6 @@ export default function useDragGuidance() {
    }
    return {
       guidanceShow,
-      guideInfoData,
       setGuidanceShow
    }
 }

+ 1 - 0
src/page-instrument/component/mode-type-mode/index.tsx

@@ -48,6 +48,7 @@ export default defineComponent({
       // console.log("🚀 ~ student:", student);
       if (storeData.user.vipMember) {
         data.showVip = false;
+        state.isVip = false;
         openGuid();
       }
     };

BIN
src/page-instrument/custom-plugins/guide-driver/images/evaluating/e4.png


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


+ 130 - 0
src/page-instrument/custom-plugins/guide-driver/index.less

@@ -17,6 +17,10 @@
   background-size: contain;
   background-color: transparent !important;
 }
+.popoverClass .driver-popover-prev-btn {
+  font-weight: 600;
+  font-size: 13px;
+}
 
 .popoverClass .driver-popover-next-btn:hover,
 .popoverClass .driver-popover-prev-btn:hover,
@@ -184,6 +188,13 @@
     right: 24px;
     bottom: -48px;
   }
+
+  &.popoverClose {
+    .driver-popover-next-btn {
+      bottom: 0;
+      right: 0;
+    }
+  }
 }
 
 .popoverClass9 {
@@ -193,6 +204,19 @@
   background-size: contain;
 }
 
+.popoverClass10 {
+  width: 264px;
+  height: 245px;
+  background: url("./images/practise/d10.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 24px;
+    bottom: 23px;
+  }
+}
+
+
 .popoverClose {
   .driver-popover-navigation-btns {
     position: absolute;
@@ -241,6 +265,53 @@
   }
 }
 
+.popoverClassF2 {
+  width: 264px;
+  height: 245px;
+  background: url("./images/follow/f2.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 24px;
+    bottom: 23px;
+  }
+}
+
+.popoverClassF3 {
+  width: 264px;
+  height: 245px;
+  background: url("./images/follow/f3.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 24px;
+    bottom: 23px;
+  }
+
+  &.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;
+    }
+  }
+}
+
 .popoverClassE1 {
   width: 257px;
   height: 247px;
@@ -253,6 +324,65 @@
   }
 }
 
+.popoverClassE2 {
+  width: 257px;
+  height: 235px;
+  background: url("./images/evaluating/e4.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 17px;
+    bottom: 22px;
+  }
+}
+
+.popoverClassE3 {
+  width: 264px;
+  height: 245px;
+  background: url("./images/evaluating/e2.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 24px;
+    bottom: 23px;
+  }
+}
+
+.popoverClassE4 {
+  width: 264px;
+  height: 245px;
+  background: url("./images/evaluating/e3.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 24px;
+    bottom: 23px;
+  }
+
+  &.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;
+    }
+  }
+}
+
 .popoverClassER1 {
   width: 257px;
   height: 178px;

+ 0 - 0
src/page-instrument/custom-plugins/guide-driver/index.module.less


File diff suppressed because it is too large
+ 408 - 242
src/page-instrument/custom-plugins/guide-driver/index.tsx


+ 4 - 0
src/page-instrument/evaluat-model/evaluat-result/index.tsx

@@ -27,6 +27,7 @@ import { browser, getBehaviorId } from "/src/utils";
 import { api_musicPracticeRecordSave } from "../../api";
 import { getAudioDuration } from "/src/view/audio-list";
 import { debounce } from "/src/utils";
+import { EvaluatingResultDriver } from "../../custom-plugins/guide-driver";
 
 export default defineComponent({
   name: "evaluatResult",
@@ -184,6 +185,9 @@ export default defineComponent({
                 <img src={ckzpImg} class={[styles.ctrlsBtn, "evaluting-result-4", data.saveLoading ? styles.disablued : ""]} onClick={() => emit("close", "look")} />
               </div>
             </div>
+
+            {/* 评测模式-结果弹窗 功能引导 加载音频完成 不是会员 */}
+            {evaluatingData.resulstMode && !evaluatingData.hideResultModal && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isVip && <EvaluatingResultDriver />}
           </div>
         )}
       </>

+ 35 - 17
src/page-instrument/header-top/index.tsx

@@ -31,7 +31,7 @@ import { getGuidance, setGuidance } from "../custom-plugins/guide-page/api";
 import ModeView from "./modeView";
 import { smoothAnimationState } from "../view-detail/smoothAnimation";
 import { isMusicList, musicListShow } from "../component/the-music-list";
-import { EvaluatingDriver, EvaluatingResultDriver, FollowDriver, PractiseDriver } from "../custom-plugins/guide-driver";
+import { EvaluatingDriver, FollowDriver, PractiseDriver } from "../custom-plugins/guide-driver";
 
 /** 头部数据和方法 */
 export const headTopData = reactive({
@@ -698,24 +698,24 @@ export default defineComponent({
                   state.playSource = state.music ? "music" : "background";
                 }
                 // 有指法并且显示指法的时候 切换到演唱模式 需要影藏指法
-                let isRefresh = false
-                if(state.isShowFingering && state.fingeringInfo.name && (state.setting.displayFingering || displayFingeringCache)){
-                  if(state.playType === "sing"){
-                    state.setting.displayFingering = false
-                    displayFingeringCache = true
+                let isRefresh = false;
+                if (state.isShowFingering && state.fingeringInfo.name && (state.setting.displayFingering || displayFingeringCache)) {
+                  if (state.playType === "sing") {
+                    state.setting.displayFingering = false;
+                    displayFingeringCache = true;
                   } else {
-                    state.setting.displayFingering = displayFingeringCache
-                    displayFingeringCache = false
+                    state.setting.displayFingering = displayFingeringCache;
+                    displayFingeringCache = false;
                   }
                   // 如果是竖屏指法和一行谱的时候 改变指法值的时候state 会调用刷新 refreshMusicSvg 所以下面不调用
                   if (state.fingeringInfo.direction === "vertical" && !state.isSingleLine) {
-                    isRefresh = true
+                    isRefresh = true;
                   }
                 }
                 // 有歌词的时候,切换播放模式,需要重新渲染谱面  指法不刷新谱面的时候
                 if (state.xmlHasLyric && !isRefresh) {
                   refreshMusicSvg();
-                } else if(!isRefresh) {
+                } else if (!isRefresh) {
                   handlerModeChange(oldPlayType, oldPlaySource, true);
                 }
                 showToast({
@@ -749,7 +749,7 @@ export default defineComponent({
                 }
                 handlerModeChange(oldPlayType, oldPlaySource);
                 showToast({
-                  message: state.playType === "play" ? (state.playSource === "music"?"已切换为原声":"已切换为伴奏") : (state.playSource === "music"?"已切换为范唱":(state.playSource === "background"?"已切换为伴唱":"已切换为唱名")),
+                  message: state.playType === "play" ? (state.playSource === "music" ? "已切换为原声" : "已切换为伴奏") : state.playSource === "music" ? "已切换为范唱" : state.playSource === "background" ? "已切换为伴唱" : "已切换为唱名",
                   position: "top",
                   className: "selectionToast",
                 });
@@ -874,14 +874,32 @@ export default defineComponent({
         {isAllBtnsStudent.value && !query.isCbs && showGuideIndex.value && <StudentTop></StudentTop>} */}
 
         {/* 练习模式功能引导 加载音频完成 不是会员 */}
-        {state.modeType === "practise" && !query.isCbs && state.audioDone && !state.isVip && <PractiseDriver />}
+        {state.modeType === "practise" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && (
+          <PractiseDriver
+            statusAll={{
+              subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
+              modelTypeStatus: toggleBtn.value.display,
+              playType: playTypeBtn.value.display,
+            }}
+          />
+        )}
         {/* 跟练模式功能引导 加载音频完成 不是会员 */}
-        {state.modeType === "follow" && !query.isCbs && state.audioDone && !state.isVip && <FollowDriver />}
+        {state.modeType === "follow" && headTopData.modeType !== "init" && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && (
+          <FollowDriver
+            statusAll={{
+              subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
+            }}
+          />
+        )}
         {/* 评测模式功能引导 加载音频完成 不是会员 */}
-        {state.modeType === "evaluating" && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isVip && <EvaluatingDriver />}
-        {/* 评测模式-结果弹窗 功能引导 加载音频完成 不是会员 */}
-        {state.modeType === "evaluating" && evaluatingData.resulstMode && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isVip && <EvaluatingResultDriver />}
+        {state.modeType === "evaluating" && headTopData.modeType !== "init" && !evaluatingData.earphoneMode && !query.isCbs && state.audioDone && !state.isLoading && !state.isVip && evaluatingData.websocketState && !evaluatingData.startBegin && evaluatingData.checkEnd && (
+          <EvaluatingDriver
+            statusAll={{
+              subjectStatus: state.musicRendered && !query.lessonTrainingId && !query.questionId && state.isConcert,
+            }}
+          />
+        )}
       </>
     );
   },
-});
+});

+ 119 - 126
src/page-instrument/header-top/modeView.tsx

@@ -1,135 +1,128 @@
-import { defineComponent, onMounted, watch, reactive, ref, nextTick } from "vue"
-import styles from "./index.module.less"
-import backImg from "./image/back.png"
-import nameImg from "./image/zt.png"
-import lxMode from "./image/lxMode.json"
-import glMode from "./image/glMode.json"
-import pcMode from "./image/pcMode.json"
-import { headTopData } from "./index"
-import TheVip from "../custom-plugins/the-vip"
-import { getQuery } from "/src/utils/queryString"
-import { storeData } from "/src/store"
-import state from "/src/state"
-import { studentQueryUserInfo } from "../api"
-import { usePageVisibility } from "@vant/use"
+import { defineComponent, onMounted, watch, reactive, ref, nextTick } from "vue";
+import styles from "./index.module.less";
+import backImg from "./image/back.png";
+import nameImg from "./image/zt.png";
+import lxMode from "./image/lxMode.json";
+import glMode from "./image/glMode.json";
+import pcMode from "./image/pcMode.json";
+import { headTopData } from "./index";
+import TheVip from "../custom-plugins/the-vip";
+import { getQuery } from "/src/utils/queryString";
+import { storeData } from "/src/store";
+import state from "/src/state";
+import { studentQueryUserInfo } from "../api";
+import { usePageVisibility } from "@vant/use";
 import { Vue3Lottie } from "vue3-lottie";
 import { popImgs, hanldeConfirmPop, hanldeClosePop, evaluatingData } from "/src/view/evaluating"
 import { Popup } from "vant";
 import AbnormalPop from "/src/view/abnormal-pop";
 
 export default defineComponent({
-   name: "modeView",
-   setup() {
-      const query = getQuery()
-      const data = reactive({
-         showPC: false,
-         showStudent: false,
-         showVip: false
-      })
-      const modeImgDom1 = ref()
-      const modeImgDom2 = ref()
-      const modeImgDom3 = ref()
-      const openGuid = () => {
-         // 加载后 判断 端口号 加载对应的引导
-         if (storeData.platformType !== "STUDENT" || storeData.user.clientType !== "STUDENT") {
-            // PC
-            data.showPC = true
-         } else {
-            // 从课堂乐器学生端课件预览默认不显示会员
-            if (storeData.user.vipMember || state.paymentType === "FREE" || query.showCourseMember === "true") {
-               // 学生端
-               data.showStudent = true
-            } else {
-               // vip
-               data.showVip = true
-            }
-         }
+  name: "modeView",
+  setup() {
+    const query = getQuery();
+    const data = reactive({
+      showPC: false,
+      showStudent: false,
+      showVip: false,
+    });
+    const modeImgDom1 = ref();
+    const modeImgDom2 = ref();
+    const modeImgDom3 = ref();
+    const openGuid = () => {
+      // 加载后 判断 端口号 加载对应的引导
+      if (storeData.platformType !== "STUDENT" || storeData.user.clientType !== "STUDENT") {
+        // PC
+        data.showPC = true;
+      } else {
+        // 从课堂乐器学生端课件预览默认不显示会员
+        if (storeData.user.vipMember || state.paymentType === "FREE" || query.showCourseMember === "true") {
+          // 学生端
+          data.showStudent = true;
+        } else {
+          // vip
+          data.showVip = true;
+          state.isVip = true;
+        }
       }
+    };
 
-      const getUserInfo = async () => {
-         const res = await studentQueryUserInfo()
-         const student = res?.data || {}
-         storeData.user.vipMember = student.vipMember
-         // console.log("🚀 ~ student:", student);
-         if (storeData.user.vipMember) {
-            data.showVip = false
-            openGuid()
-         }
+    const getUserInfo = async () => {
+      const res = await studentQueryUserInfo();
+      const student = res?.data || {};
+      storeData.user.vipMember = student.vipMember;
+      // console.log("🚀 ~ student:", student);
+      if (storeData.user.vipMember) {
+        data.showVip = false;
+        state.isVip = false;
+        openGuid();
       }
-      const pageVisible = usePageVisibility()
-      watch(
-         () => pageVisible.value,
-         val => {
-            if (val === "visible") {
-               if (storeData.user.vipMember) return
-               console.log("页面显示")
-               getUserInfo()
-            }
-         }
-      )
-      watch(() => headTopData.modeType, (value,oldValue) => {
-         // headTopData.modeType 值 刚开始是 ""  所以 第一次切换时候不触发播放动画
-         if(!oldValue) return
-         nextTick(()=>{
-            if(value === "show"){
-               modeImgDom1.value?.pause()
-               modeImgDom2.value?.pause()
-               modeImgDom3.value?.pause()
-            }else if(value === "init"){
-               modeImgDom1.value?.play()
-               modeImgDom2.value?.play()
-               modeImgDom3.value?.play()
-            }
-         })
-      })
-      onMounted(() => {
-         openGuid()
-      })
-      watch(
-         () => evaluatingData.socketErrorStatus,
-         () => {
-           if (evaluatingData.socketErrorStatus === 2) {
-             setTimeout(() => {
-               evaluatingData.socketErrorPop = false;
-             }, 1000);
-           }
-         }
-       );      
-      return () => (
-         <div class={[styles.modeView, headTopData.modeType !== "init" && styles.hidden]}>
-            <img
-               src={backImg}
-               class={styles.back}
-               onClick={() => {
-                  headTopData.modeType = "show"
-               }}
-            />
-            <img src={nameImg} class={styles.name} />
-            <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={() => headTopData.handleChangeModeType("practise")}></Vue3Lottie>
-               {
-                  !state.isPercussion && <Vue3Lottie ref={modeImgDom2} class={styles.modeImg} animationData={glMode} autoPlay={false} loop={true} onClick={() => headTopData.handleChangeModeType("follow")}></Vue3Lottie>
-               }
-               {
-                  state.enableEvaluation && <Vue3Lottie ref={modeImgDom3} class={styles.modeImg} animationData={pcMode} autoPlay={false} loop={true} onClick={() => headTopData.handleChangeModeType("evaluating")}></Vue3Lottie>
-               }
-            </div>
-            {data.showVip && <TheVip />}
-            {/** 延迟检测中途,socket出错,网络提示弹窗 */}
-            <div>
-               <Popup teleport="body" closeOnClickOverlay={false} class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={evaluatingData.socketErrorPop}>
-                  <AbnormalPop onConfirm={hanldeConfirmPop} onClose={hanldeClosePop} />
-               </Popup>
-            </div>            
-         </div>
-      )
-   }
-})
+    };
+    const pageVisible = usePageVisibility();
+    watch(
+      () => pageVisible.value,
+      (val) => {
+        if (val === "visible") {
+          if (storeData.user.vipMember) return;
+          console.log("页面显示");
+          getUserInfo();
+        }
+      }
+    );
+    watch(
+      () => headTopData.modeType,
+      (value, oldValue) => {
+        // headTopData.modeType 值 刚开始是 ""  所以 第一次切换时候不触发播放动画
+        if (!oldValue) return;
+        nextTick(() => {
+          if (value === "show") {
+            modeImgDom1.value?.pause();
+            modeImgDom2.value?.pause();
+            modeImgDom3.value?.pause();
+          } else if (value === "init") {
+            modeImgDom1.value?.play();
+            modeImgDom2.value?.play();
+            modeImgDom3.value?.play();
+          }
+        });
+      }
+    );
+    onMounted(() => {
+      openGuid();
+    });
+    watch(
+      () => evaluatingData.socketErrorStatus,
+      () => {
+        if (evaluatingData.socketErrorStatus === 2) {
+          setTimeout(() => {
+            evaluatingData.socketErrorPop = false;
+          }, 1000);
+        }
+      }
+    );      
+    return () => (
+      <div class={[styles.modeView, headTopData.modeType !== "init" && styles.hidden]}>
+        <img
+          src={backImg}
+          class={styles.back}
+          onClick={() => {
+            headTopData.modeType = "show";
+          }}
+        />
+        <img src={nameImg} class={styles.name} />
+        <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={() => headTopData.handleChangeModeType("practise")}></Vue3Lottie>
+          {!state.isPercussion && <Vue3Lottie ref={modeImgDom2} class={styles.modeImg} animationData={glMode} autoPlay={false} loop={true} onClick={() => headTopData.handleChangeModeType("follow")}></Vue3Lottie>}
+          {state.enableEvaluation && <Vue3Lottie ref={modeImgDom3} class={styles.modeImg} animationData={pcMode} autoPlay={false} loop={true} onClick={() => headTopData.handleChangeModeType("evaluating")}></Vue3Lottie>}
+        </div>
+        {data.showVip && <TheVip />}
+        {/** 延迟检测中途,socket出错,网络提示弹窗 */}
+        <div>
+            <Popup teleport="body" closeOnClickOverlay={false} class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={evaluatingData.socketErrorPop}>
+              <AbnormalPop onConfirm={hanldeConfirmPop} onClose={hanldeClosePop} />
+            </Popup>
+        </div>         
+      </div>
+    );
+  },
+});

+ 8 - 0
src/page-instrument/view-figner/change-subject/index.module.less

@@ -1,6 +1,12 @@
 .changeSubject {
   padding: 49px 17px 19px 24px;
 
+
+  &.changeSubjectPc {
+    // .changeSubjectContainer {
+    //   height: 140px;
+    // }
+  }
 }
 
 .changeSubjectContainer {
@@ -51,6 +57,7 @@
     color: #333333;
     border: 1px solid #D8D8D8;
     margin-bottom: 12px;
+    cursor: pointer;
 
     &:nth-child(3n + 2) {
       margin-left: 2.333%;
@@ -106,6 +113,7 @@
   .btn {
     width: 143px;
     height: 44px;
+    cursor: pointer;
 
     &+.btn {
       margin-left: 9px;

+ 12 - 7
src/page-instrument/view-figner/change-subject/index.tsx

@@ -1,6 +1,7 @@
 import { defineComponent, onMounted, reactive, watch } from "vue";
 import styles from "./index.module.less";
 import { Button, showToast } from "vant";
+import { getQuery } from "/src/utils/queryString";
 
 export default defineComponent({
   name: "change-subject",
@@ -16,6 +17,7 @@ export default defineComponent({
   },
   emits: ["close", "confirm"],
   setup(props, { emit }) {
+    const query = getQuery();
     const state = reactive({
       subjectValue: null as any,
       instrumentCode: null as any,
@@ -23,9 +25,12 @@ export default defineComponent({
     });
 
     // subject 变化时候 重新刷新
-    watch(()=>props.subject,()=>{
-      selectItem()
-    })
+    watch(
+      () => props.subject,
+      () => {
+        selectItem();
+      }
+    );
     //
     const selectItem = () => {
       // const i: any = props.subjectList.find((item: any) => item.value === props.subject);
@@ -67,11 +72,11 @@ export default defineComponent({
     };
 
     onMounted(() => {
-      console.log(props.subjectList, "subjectList", props.subject);
+      console.log(props.subjectList, "subjectList", props.subject, query);
       selectItem();
     });
     return () => (
-      <div class={styles.changeSubject}>
+      <div class={[styles.changeSubject, query.platform === "pc" && styles.changeSubjectPc]}>
         {/* <div class={styles.changeSubjectContainer}>
           <div class={styles.title}>乐器</div>
 
@@ -93,7 +98,7 @@ export default defineComponent({
             ))}
           </div>
         </div> */}
-        <div class={[styles.changeSubjectContainer,"changeSubjectContainer_pc"]}>
+        <div class={[styles.changeSubjectContainer, "changeSubjectContainer_pc"]}>
           <div class={styles.title}>声部</div>
 
           <div class={styles.subjectContainer}>
@@ -135,7 +140,7 @@ export default defineComponent({
           )}
         </div>
 
-        <div class={[styles.btnGroups,"btnGroups_pc"]}>
+        <div class={[styles.btnGroups, "btnGroups_pc"]}>
           <div
             class={[styles.btn, styles.resetBtn]}
             onClick={() => {

+ 488 - 0
src/page-instrument/view-figner/fingeringPoint.ts

@@ -0,0 +1,488 @@
+export const FINER_INSTRUMENT_POINT = {
+  "pan-flute": [
+    {
+      key: 5,
+      name: "G",
+      octave: 4,
+      step: -1,
+      realKey: 55,
+      realName: "G4",
+      style: { width: '5.6%' }
+    },
+    {
+      key: 6,
+      name: "A",
+      octave: 4,
+      step: -1,
+      realKey: 57,
+      realName: "A4",
+      style: { width: '5.3%', height: '93.3%' }
+    },
+    {
+      key: 7,
+      name: "B",
+      octave: 4,
+      step: -1,
+      realKey: 59,
+      realName: "B4",
+      style: { width: '5.4%', height: '88%' }
+    },
+    {
+      key: 1,
+      name: "C",
+      octave: 5,
+      step: 0,
+      realKey: 60,
+      realName: "C5",
+      style: { width: '5.3%', height: '82%' }
+    },
+    {
+      key: 2,
+      name: "D",
+      octave: 5,
+      step: 0,
+      realKey: 62,
+      realName: "D5",
+      style: { width: '5.2%', height: '76.6%' }
+    },
+    {
+      key: 3,
+      name: "E",
+      octave: 5,
+      step: 0,
+      realKey: 64,
+      realName: "E5",
+      style: { width: '5%', height: '70.6%' }
+    },
+    {
+      key: 4,
+      name: "F",
+      octave: 5,
+      step: 0,
+      realKey: 65,
+      realName: "F5",
+      style: { width: '5.2%', height: '64%' }
+    },
+    {
+      key: 5,
+      name: "G",
+      octave: 5,
+      step: 0,
+      realKey: 67,
+      realName: "G5",
+      style: { width: '5%', height: '59%' }
+    },
+    {
+      key: 6,
+      name: "A",
+      octave: 5,
+      step: 0,
+      realKey: 69,
+      realName: "A5",
+      style: { width: '4.7%', height: '55%' }
+
+    },
+    {
+      key: 7,
+      name: "B",
+      octave: 5,
+      step: 0,
+      realKey: 71,
+      realName: "B5",
+      style: { width: '4.8%', height: '51%' }
+    },
+    {
+      key: 1,
+      name: "C",
+      octave: 6,
+      step: 1,
+      realKey: 72,
+      realName: "C6",
+      style: { width: '5%', height: '47.6%' }
+    },
+    {
+      key: 2,
+      name: "D",
+      octave: 6,
+      step: 1,
+      realKey: 74,
+      realName: "D6",
+      style: { width: '4.8%', height: '45%' }
+    },
+    {
+      key: 3,
+      name: "E",
+      octave: 6,
+      step: 1,
+      realKey: 76,
+      realName: "E6",
+      style: { width: '4.7%', height: '42.6%' }
+    },
+    {
+      key: 4,
+      name: "F",
+      octave: 6,
+      step: 1,
+      realKey: 77,
+      realName: "F6",
+      style: { width: '4.6%', height: '40.6%' }
+    },
+    {
+      key: 5,
+      name: "G",
+      octave: 6,
+      step: 1,
+      realKey: 79,
+      realName: "G6",
+      style: { width: '4.6%', height: '38%' }
+    },
+    {
+      key: 6,
+      name: "A",
+      octave: 6,
+      step: 1,
+      realKey: 81,
+      realName: "A6",
+      style: { width: '4%', height: '36.6%' }
+    },
+    {
+      key: 7,
+      name: "B",
+      octave: 6,
+      step: 1,
+      realKey: 83,
+      realName: "B6",
+      style: { width: '4.4%', height: '35%' }
+    },
+    {
+      key: 1,
+      name: "C",
+      octave: 7,
+      step: 2,
+      realKey: 84,
+      realName: "C7",
+      style: { width: '4%', height: '33%' }
+    },
+    {
+      key: 2,
+      name: "D",
+      octave: 7,
+      step: 2,
+      realKey: 86,
+      realName: "D7",
+      style: { width: '4%', height: '31%' }
+    },
+    {
+      key: 3,
+      name: "E",
+      octave: 7,
+      step: 2,
+      realKey: 88,
+      realName: "E7",
+      style: { width: '4%', height: '30%' }
+    },
+    {
+      key: 4,
+      name: "F",
+      octave: 7,
+      step: 2,
+      realKey: 89,
+      realName: "F7",
+      style: { width: '4%', height: '29%' }
+    },
+  ],
+  melodica: [
+    {
+      key: 4,
+      name: "F",
+      octave: 4,
+      step: -1,
+      realKey: 53,
+      realName: "F4",
+    },
+    {
+      key: 5,
+      name: "G",
+      octave: 4,
+      step: -1,
+      realKey: 55,
+      realName: "G4",
+      children: {
+        key: 5,
+        name: "G",
+        octave: 4,
+        step: -1,
+        realKey: 54,
+        mark: "fall",
+        realName: "Gb4",
+        style: { marginLeft: '-48%' }
+      },
+    },
+
+    {
+      key: 6,
+      name: "A",
+      octave: 4,
+      step: -1,
+      realKey: 57,
+      realName: "A4",
+      children: {
+        key: 6,
+        name: "A",
+        octave: 4,
+        step: -1,
+        realKey: 56,
+        mark: "fall",
+        realName: "Ab4",
+        style: { marginLeft: '-29%' }
+      },
+    },
+    {
+      key: 7,
+      name: "B",
+      octave: 4,
+      step: -1,
+      realKey: 59,
+      realName: "B4",
+      children: {
+        key: 7,
+        name: "B",
+        octave: 4,
+        step: -1,
+        realKey: 58,
+        mark: "fall",
+        realName: "Bb4",
+        style: { marginLeft: '-11%' }
+      },
+    },
+    {
+      key: 1,
+      name: "C",
+      octave: 5,
+      step: 0,
+      realKey: 60,
+      realName: "C5",
+    },
+
+    {
+      key: 2,
+      name: "D",
+      octave: 5,
+      step: 0,
+      realKey: 62,
+      realName: "D5",
+      children: {
+        key: 2,
+        name: "D",
+        octave: 5,
+        step: 0,
+        realKey: 61,
+        mark: "fall",
+        realName: "Db5",
+        style: { marginLeft: '-36%' }
+      },
+    },
+
+    {
+      key: 3,
+      name: "E",
+      octave: 5,
+      step: 0,
+      realKey: 64,
+      realName: "E5",
+      children: {
+        key: 3,
+        name: "E",
+        octave: 5,
+        step: 0,
+        realKey: 63,
+        mark: "fall",
+        realName: "Eb5",
+        style: { marginLeft: '-22%' }
+      },
+    },
+    {
+      key: 4,
+      name: "F",
+      octave: 5,
+      step: 0,
+      realKey: 65,
+      realName: "F5",
+    },
+
+    {
+      key: 5,
+      name: "G",
+      octave: 5,
+      step: 0,
+      realKey: 67,
+      realName: "G5",
+      children: {
+        key: 5,
+        name: "G",
+        octave: 5,
+        step: 0,
+        realKey: 66,
+        mark: "fall",
+        realName: "Gb5",
+        style: { marginLeft: '-47%' }
+      },
+    },
+    {
+      key: 6,
+      name: "A",
+      octave: 5,
+      step: 0,
+      realKey: 69,
+      realName: "A5",
+      children: {
+        key: 6,
+        name: "A",
+        octave: 5,
+        step: 0,
+        realKey: 68,
+        mark: "fall",
+        realName: "Ab5",
+        style: { marginLeft: '-29%' }
+      },
+    },
+
+    {
+      key: 7,
+      name: "B",
+      octave: 5,
+      step: 0,
+      realKey: 71,
+      realName: "B5",
+      children: {
+        key: 7,
+        name: "B",
+        octave: 5,
+        step: 0,
+        realKey: 70,
+        mark: "fall",
+        realName: "Bb5",
+        style: { marginLeft: '-11%' }
+      },
+    },
+    {
+      key: 1,
+      name: "C",
+      octave: 6,
+      step: 1,
+      realKey: 72,
+      realName: "C6",
+    },
+
+    {
+      key: 2,
+      name: "D",
+      octave: 6,
+      step: 1,
+      realKey: 74,
+      realName: "D6",
+      children: {
+        key: 2,
+        name: "D",
+        octave: 6,
+        step: 1,
+        realKey: 73,
+        mark: "fall",
+        realName: "Db6",
+        style: { marginLeft: '-34%' }
+      },
+    },
+
+    {
+      key: 3,
+      name: "E",
+      octave: 6,
+      step: 1,
+      realKey: 76,
+      realName: "E6",
+      children: {
+        key: 3,
+        name: "E",
+        octave: 6,
+        step: 1,
+        realKey: 75,
+        mark: "fall",
+        realName: "Eb6",
+        style: { marginLeft: '-23%' }
+      },
+    },
+    {
+      key: 4,
+      name: "F",
+      octave: 6,
+      step: 1,
+      realKey: 77,
+      realName: "F6",
+    },
+
+    {
+      key: 5,
+      name: "G",
+      octave: 6,
+      step: 1,
+      realKey: 79,
+      realName: "G6",
+      children: {
+        key: 5,
+        name: "G",
+        octave: 6,
+        step: 1,
+        realKey: 78,
+        mark: "fall",
+        realName: "Gb6",
+        style: { marginLeft: '-47%' }
+      },
+    },
+
+    {
+      key: 6,
+      name: "A",
+      octave: 6,
+      step: 1,
+      realKey: 81,
+      realName: "A6",
+      children: {
+        key: 6,
+        name: "A",
+        octave: 6,
+        step: 1,
+        realKey: 80,
+        mark: "fall",
+        realName: "Ab6",
+        style: { marginLeft: '-29%' }
+      },
+    },
+
+    {
+      key: 7,
+      name: "B",
+      octave: 6,
+      step: 1,
+      realKey: 83,
+      realName: "B6",
+      children: {
+        key: 7,
+        name: "B",
+        octave: 6,
+        step: 1,
+        realKey: 82,
+        mark: "fall",
+        realName: "Bb6",
+        style: { marginLeft: '-11%' }
+      },
+    },
+    {
+      key: 1,
+      name: "C",
+      octave: 7,
+      step: 2,
+      realKey: 84,
+      realName: "C7",
+    },
+  ]
+} as any

+ 255 - 60
src/page-instrument/view-figner/index.module.less

@@ -108,7 +108,8 @@
             }
         }
     }
-    .tipsOverlay{
+
+    .tipsOverlay {
         width: 57%;
         height: 100%;
         position: fixed;
@@ -117,17 +118,20 @@
         z-index: 2009;
         animation: bgIn 0.2s 0.2s forwards;
     }
-    &.fingerRight .tipsPcBg.tips{
+
+    &.fingerRight .tipsPcBg.tips {
         animation: bgIn 0.15s 0.25s forwards;
-        border-radius:0;
+        border-radius: 0;
         background-image: url('./image/icon_shuo_v.png') !important;
     }
+
     @keyframes bgIn {
-        0%{
+        0% {
             background-color: initial;
         }
-        100%{
-            background-color: rgba(0,0,0,0.5);
+
+        100% {
+            background-color: rgba(0, 0, 0, 0.5);
         }
     }
 }
@@ -192,7 +196,7 @@
     pointer-events: none;
     padding-right: 18px;
     padding-top: env(safe-area-inset-top);
-    z-index: 5;
+    z-index: 11;
 
     .backBtn {
         margin-right: 14px;
@@ -260,29 +264,37 @@
         display: flex;
         flex-direction: column;
     }
-    .userTab{
+
+    .userTab {
         display: flex;
         justify-content: center;
         width: 100%;
-        .userTabBox{
+        position: relative;
+
+        .userTabBox {
             width: 100%;
-            .notes{
+
+            .notes {
                 padding-bottom: 10px;
                 height: initial;
-                .lastNoteContent{
-                    border-radius: 0 !important; 
-                    .noteBox{
+
+                .lastNoteContent {
+                    border-radius: 0 !important;
+
+                    .noteBox {
                         border-radius: 0 !important;
                     }
                 }
-                .noteContent{
+
+                .noteContent {
                     padding: 0 10px;
                 }
-                .changeMusBtn{
+
+                .changeMusBtn {
                     margin-right: 8px;
                     text-align: center;
                     width: 42px;
-                    background: linear-gradient( 180deg, #F4EFED 0%, #D9CEC7 100%);
+                    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;
@@ -292,35 +304,42 @@
                     padding: 7px 6px;
                     height: 46px;
                 }
-                .backBtn{
+
+                .backBtn {
                     line-height: 32px;
                 }
             }
-            .optionBtns{
+
+            .optionBtns {
                 padding-bottom: 0;
             }
-            :global{
-                .van-tabs__wrap{
+
+            :global {
+                .van-tabs__wrap {
                     width: 100%;
                     display: flex;
                     justify-content: center;
                     height: 30px;
-                    .van-tabs__nav{
+
+                    .van-tabs__nav {
                         width: 120px;
                         background-color: initial;
-                        border-bottom: 2px solid rgba(82,138,214,0.15);
+                        border-bottom: 2px solid rgba(82, 138, 214, 0.15);
                         height: initial;
                         padding-bottom: initial;
-                        .van-tab{
+
+                        .van-tab {
                             font-weight: 400;
                             font-size: 15px;
                             color: #616161;
-                            &.van-tab--active{
+
+                            &.van-tab--active {
                                 font-weight: 600;
                                 color: #616161;
                             }
                         }
-                        .van-tabs__line{
+
+                        .van-tabs__line {
                             width: 32px;
                             bottom: -2px;
                             height: 2px;
@@ -329,26 +348,31 @@
                         }
                     }
                 }
-                .van-tabs__content{
+
+                .van-tabs__content {
                     padding-top: 16px;
                     height: 130px;
-                    .van-tab__panel{
+
+                    .van-tab__panel {
                         height: 100%;
                     }
                 }
             }
-            .btnBox{
+
+            .btnBox {
                 height: 100%;
                 display: flex;
                 justify-content: center;
                 align-items: center;
                 margin-top: -16px;
-                .btnCon{
+
+                .btnCon {
                     border-radius: 17px;
                     display: flex;
                     background: rgba(255, 255, 255, 0.5);
                     padding: 6px 5px 3px 6px;
-                    .btnGr{
+
+                    .btnGr {
                         background: url("./image/btnBg.png") no-repeat;
                         background-size: 100% 100%;
                         width: 93px;
@@ -359,14 +383,17 @@
                         justify-content: center;
                         cursor: pointer;
                         margin-left: 5px;
-                        &:first-child{
+
+                        &:first-child {
                             margin-left: 0;
                         }
-                        >img{
+
+                        >img {
                             width: 19px;
                             height: 19px;
                         }
-                        >span{
+
+                        >span {
                             font-weight: 500;
                             font-size: 14px;
                             color: #616161;
@@ -376,14 +403,38 @@
                 }
             }
         }
+
+
+        &.usrTabOverlaping {
+            visibility: hidden;
+            opacity: 0;
+            // &::after {
+            //     position: absolute;
+            //     content: '';
+            //     left: 0;
+            //     top: 0;
+            //     width: 100%;
+            //     height: 100%;
+            //     background: linear-gradient(180deg, rgba(222, 213, 208, 0) 0%, rgba(210, 199, 194, 0.93) 27%, #C5B8B3 100%);
+            //     z-index: 9;
+            // }
+        }
+
     }
+
     .boxFinger {
         flex: 1;
         padding-top: 50px;
         overflow: hidden;
-        &.pcBoxFinger{
+
+        &.pcBoxFinger {
             padding-top: 10px !important;
         }
+
+        &.boxFingerOverlapping {
+            overflow: visible;
+            z-index: 10;
+        }
     }
 
 
@@ -396,7 +447,7 @@
     position: relative;
     z-index: 11;
     flex-shrink: 0;
-    transition: all .3s;
+    transition: all .2s;
     // background-color: rgba(190, 166, 140, 1);
     background-size: 100% 100%;
     background-repeat: no-repeat;
@@ -560,45 +611,72 @@
 
     }
 }
-.btnGrToggleBtn{
+
+.btnGrToggleBtn {
     font-weight: 600;
     font-size: 12px;
     color: #fff;
-    >div{
+
+    >div {
         display: flex;
         flex-direction: column;
         align-items: center;
         z-index: 10;
-        &.nameBox{
+
+        &.nameBox {
             padding-top: 2px;
-            .name{
+
+            .name {
                 font-size: 10px;
             }
-            .noteKey{
+
+            .noteKey {
                 font-size: 12px;
                 position: relative;
                 color: #ffffff;
             }
+
             .dot {
                 display: inline-block;
                 position: absolute;
                 top: 0px;
-                &.botDot{
+
+                &.botDot {
                     top: initial;
                     bottom: -2px;
                 }
             }
         }
     }
-    .name{
+
+    .name {
         display: flex;
     }
-    .arrowImg{
+
+    .arrowImg {
         margin-top: 2px;
         width: 9px;
         height: 5px;
     }
 }
+
+.usrTabOverlapingNotes {
+    position: relative;
+    visibility: hidden;
+    opacity: 0;
+    // &::after {
+    //     position: absolute;
+    //     content: '';
+    //     left: 0;
+    //     top: 0;
+    //     width: 100%;
+    //     height: 100%;
+    //     background: linear-gradient(180deg, rgba(222, 213, 208, 0) 0%, rgba(210, 199, 194, 0.93) 17%, #C5B8B3 100%);
+    //     z-index: 9;
+    // }
+}
+
+
 .notes {
     position: relative;
     display: flex;
@@ -608,6 +686,8 @@
     flex-shrink: 0;
     cursor: pointer;
 
+
+
     &.paddingLeft {
         padding-left: 20Px;
     }
@@ -669,7 +749,7 @@
     .noteBox {
         display: flex;
         overflow-y: hidden;
-        overflow-x: auto;
+        overflow-x: hidden;
         border-radius: 0 25px 25px 0;
         z-index: 9;
 
@@ -952,6 +1032,98 @@
         max-width: 100%;
         max-height: 100%;
     }
+
+    // .fullContent {
+    //     position: absolute;
+    //     left: 50%;
+    //     top: 50%;
+    //     transform: translate(-50%, -50%);
+    //     display: block;
+    //     width: 100%;
+
+    //     .showImgNk {
+    //         position: absolute;
+    //         top: 0;
+    //         left: 0;
+    //         width: 100%;
+    //     }
+
+    //     img {
+    //         width: 100%;
+    //     }
+    // }
+}
+
+.fingeringPointSection {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    z-index: 10;
+
+    .p1 {
+        position: relative;
+        // background: red;
+        cursor: pointer;
+        pointer-events: auto;
+    }
+
+    .p2 {
+        position: absolute;
+        top: 0;
+        z-index: 1;
+        left: 0;
+        cursor: pointer;
+        pointer-events: auto;
+    }
+
+    &>div {
+        width: 100%;
+        height: 100%;
+        display: flex;
+        align-items: flex-start;
+        justify-content: space-between;
+    }
+
+    .pan-flute {
+        padding: 28.5% 3.3% 3.1% 3.8%;
+        justify-content: flex-start;
+
+        &.pan-flute-back {
+            flex-direction: row-reverse;
+            justify-content: space-evenly;
+        }
+
+        .p1 {
+            // background-color: rgba(255, 0, 0, .3);
+            width: 3.4%;
+            height: 100%;
+        }
+    }
+
+    .melodica {
+        padding: 0.9% 3.6% 3% 10.7%;
+
+        .p1 {
+            position: relative;
+            width: 5.2%;
+            // background-color: rgba(255, 0, 0, .3);
+            height: 100%;
+        }
+
+        .p2 {
+            position: absolute;
+            top: 0;
+            width: 54%;
+            height: 58%;
+            // background-color: rgba(0, 0, 255, .3);
+            z-index: 1;
+            left: 0;
+            margin-left: -8%;
+        }
+    }
+
+
 }
 
 .tizhi {
@@ -996,6 +1168,7 @@
     top: 50%;
     right: auto;
     transform: translateY(-50%);
+    z-index: 11;
 
 
     .baseBtn {
@@ -1138,9 +1311,11 @@
             position: absolute;
             left: 50%;
             transform: translateX(-50%);
+
             &.topDot {
                 top: 0;
             }
+
             &.bottomDot {
                 top: initial;
             }
@@ -1452,6 +1627,12 @@
     border-radius: 12px;
     background-size: contain;
     overflow: initial;
+
+    :global {
+        .bom_guide::before {
+            background-color: rgba(0, 0, 0, 0);
+        }
+    }
 }
 
 .linkSourceClass {
@@ -1490,57 +1671,71 @@
     //     display: none;
     // }
 }
-.dragTopBox{
+
+.dragTopBox {
     position: absolute;
     top: 0;
     left: 0;
     height: 40px;
-    width: 100%; 
+    width: 100%;
 }
-:global{
-    .changeSubjectShowBoxClass_drag{
+
+:global {
+    .changeSubjectShowBoxClass_drag {
         height: 307px !important;
         background: url('./image/subject-bg2.png') no-repeat center !important;
         background-size: contain !important;
-        .dragbomBox{
+
+        .dragbomBox {
             height: 37px;
         }
-        .changeSubjectContainer_pc{
+
+        .changeSubjectContainer_pc {
             height: 168px !important;
         }
-        .btnGroups_pc{
+
+        .btnGroups_pc {
             padding-top: 12px !important;
         }
     }
-    .tnoteShowBoxClass_drag{
+
+    .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{
+
+        .dragbomBox {
             height: 37px;
         }
-        .toneTitle_pc{
+
+        .toneTitle_pc {
             display: none;
         }
-        .tipContentbox_pc{
+
+        .tipContentbox_pc {
             background-color: initial;
-            &::after{
+
+            &::after {
                 display: none;
             }
-            .tipContent_pc{
-                border:none;
-                .tipWrap_pc{
+
+            .tipContent_pc {
+                border: none;
+
+                .tipWrap_pc {
                     height: 116px !important;
                     flex: initial;
                     overflow-y: auto;
+
                     &::-webkit-scrollbar {
                         display: none;
                     }
                 }
-                .toneAction_pc{
+
+                .toneAction_pc {
                     padding-bottom: 0 !important;
                     padding-top: 12px !important;
                 }

+ 436 - 68
src/page-instrument/view-figner/index.tsx

@@ -22,6 +22,7 @@ import { Tabs, Tab } from "vant";
 import useDrag from "/src/hooks/useDrag";
 import Dragbom from "/src/hooks/useDrag/dragbom";
 import useDragGuidance from "/src/hooks/useDrag/useDragGuidance";
+import { FINER_INSTRUMENT_POINT } from "./fingeringPoint";
 
 export default defineComponent({
   name: "viewFigner",
@@ -51,6 +52,7 @@ export default defineComponent({
       subject: subject as any,
       realKey: 0,
       notes: [] as IFIGNER_INSTRUMENT_Note[],
+      notePoints: [] as any, // 显示的点
       tones: [] as IFIGNER_INSTRUMENT_Note[],
       activeTone: {} as IFIGNER_INSTRUMENT_Note,
       popupActiveTone: {} as IFIGNER_INSTRUMENT_Note,
@@ -102,6 +104,11 @@ export default defineComponent({
       noteType: "all" as "#c" | "all", // 音调
       loadingDom: false, // 切换乐器时需要重置
       loadingImg: false, // 切换模式,加载图片
+      domOverlapping: false, // 元素是否被遮住
+      domOverImgPropery: {
+        width: "100%",
+        height: "100%",
+      } as any,
     });
     const fingerData = reactive({
       relationshipIndex: 0,
@@ -166,6 +173,7 @@ export default defineComponent({
         // 判断是音符状态
         data.notes = data.noteType === "#c" ? appendNote : tempNotes;
         // data.notes = fignerData[`list${data.activeTone.realName || ""}`];
+        data.notePoints = FINER_INSTRUMENT_POINT[data.subject];
       }
     };
     const getFingeringData = async () => {
@@ -251,6 +259,7 @@ export default defineComponent({
         data.noteType = "all";
       }
       data.tipShow = false;
+      resetElement();
       resetMode(true, 0);
       setTimeout(() => {
         __init(false);
@@ -291,6 +300,9 @@ export default defineComponent({
 
       data.loadingDom = false;
       data.loadingImg = false;
+
+      // 初始化获取元素宽高
+      onResize();
     };
 
     // 获取声部
@@ -383,13 +395,17 @@ export default defineComponent({
       __init();
     });
 
+    // 播放时间
+    let noteTimer: any = null;
     /**
      * 播放音频
      * @param item 音频节点
      * @param showNote 是否显示对应的指法
+     * @param isScrollShowNote 是否滚动到对应播放的位置
+     * @param autoStop 是否自动停止
      * @returns
      */
-    const noteClick = (item: IFIGNER_INSTRUMENT_Note, showNote = true) => {
+    const noteClick = (item: IFIGNER_INSTRUMENT_Note, showNote = true, isScrollShowNote = false, autoStop = false, callBack?: any) => {
       // console.log('音高', item.realKey)
       if (data.noteAudio) {
         data.noteAudio.stop();
@@ -398,14 +414,27 @@ export default defineComponent({
           data.noteAudio = null as unknown as Howl;
           return;
         }
+
+        clearTimeout(noteTimer);
       }
       if (showNote) {
         data.realKey = item.realKey;
       }
-      console.log("key:", item.realKey, data.soundFonts);
+      // console.log("key:", item.realKey, data.soundFonts);
       data.noteAudio = data.soundFonts[item.realKey];
       if (data.noteAudio) {
+        clearTimeout(noteTimer);
         data.noteAudio.play();
+        if (isScrollShowNote) scrollAnswer(item.realKey);
+
+        // 判断是否自动停止播放停止
+        if (autoStop) return;
+        noteTimer = setTimeout(() => {
+          handleStop();
+          if (callBack && typeof callBack === "function") {
+            callBack(item);
+          }
+        }, 300);
       }
     };
     const handleStop = () => {
@@ -416,6 +445,106 @@ export default defineComponent({
       }
     };
 
+    const isLongPress = ref(false); // 是否长按
+    const isTouchStart = ref(false); // 是否长按
+    let isTouch = false;
+    let timerNoteId: any;
+    const longPressDuration = 200;
+
+    const onLongPress = () => {
+      console.log("长按检测成功!");
+      isLongPress.value = true;
+      clearTimeout(noteTimer);
+    };
+    // 开始长按检测
+    const startNotePress = async (note: any, isScrollShowNote = true) => {
+      if (playStatus.gamut) return;
+      if (playAction.listenLock) return;
+      if (playAction.showAnswerLoading) return;
+      timerNoteId = setTimeout(onLongPress, longPressDuration);
+      // 为了处理希沃白板垃圾事件
+      if (isTouchStart.value) return;
+      isTouchStart.value = true;
+      if (playStatus.action) {
+        playAction.userAnswer = note;
+        // 判断用户答题
+        const userResult = note.realKey === playAction.standardAnswer.realKey ? 1 : 2;
+        playAction.userAnswerStatus = userResult;
+        playAction.listenLock = true;
+        data.realKey = note.realKey;
+        noteClick(note, true, isScrollShowNote, false, playCallBack);
+      } else {
+        handleStop();
+        noteClick(note, true, isScrollShowNote);
+      }
+    };
+
+    // 取消长按检测
+    const cancelNotePress = async (note: any, isScrollShowNote = true) => {
+      if (timerNoteId !== null) {
+        clearTimeout(timerNoteId);
+        timerNoteId = null;
+      }
+
+      if (isLongPress.value) {
+        handleStop();
+        playCallBack(note);
+      }
+
+      if (isLongPress.value) {
+        isLongPress.value = false;
+      }
+      isTouchStart.value = false;
+
+      console.log(isLongPress.value, timerNoteId, note.realName);
+    };
+
+    const playCallBack = (note: any) => {
+      if (playAction.listenLock) {
+        const userResult = note.realKey === playAction.standardAnswer.realKey ? 1 : 2;
+        resetMode(userResult === 1 ? true : false, 0);
+        data.realKey = 0;
+        // 如果是指法模式显示完之后要还原
+        if (data.fingeringMode === "fingeringMode" && userResult === 2) {
+          // 延迟显示,因为重置的时候有一个异步操作
+          setTimeout(() => {
+            data.realKey = playAction.standardAnswer.realKey;
+          }, 10);
+        }
+        playAction.listenLock = false;
+      }
+    };
+
+    /** 点击音符播放 */
+    const noteInstrumentPlay = async (note: any, isScroll = false) => {
+      // 判断是否在播放音阶
+      if (playStatus.gamut) return;
+      if (playAction.listenLock) return;
+      if (playAction.showAnswerLoading) return;
+      if (playStatus.action) {
+        playAction.userAnswer = note;
+        // 判断用户答题
+        const userResult = note.realKey === playAction.standardAnswer.realKey ? 1 : 2;
+        playAction.userAnswerStatus = userResult;
+        playAction.listenLock = true;
+        data.realKey = note.realKey;
+        await fingeringPlay(note, 1000);
+        resetMode(userResult === 1 ? true : false, 0);
+        data.realKey = 0;
+
+        // 如果是指法模式显示完之后要还原
+        if (data.fingeringMode === "fingeringMode" && userResult === 2) {
+          // 延迟显示,因为重置的时候有一个异步操作
+          setTimeout(() => {
+            data.realKey = playAction.standardAnswer.realKey;
+          }, 10);
+        }
+        playAction.listenLock = false;
+      } else {
+        noteClick(note, true, isScroll);
+      }
+    };
+
     /** 返回 */
     const handleBack = () => {
       // platform: query.platform,
@@ -465,6 +594,16 @@ export default defineComponent({
       loadElement();
       api_setStatusBarVisibility();
     });
+
+    // 判断两个元素是否重叠
+    const isElementOverlapping = (el1: any, el2: any) => {
+      const rect1 = el1?.getBoundingClientRect();
+      const rect2 = el2?.getBoundingClientRect();
+      return !(rect1.right < rect2.left || rect1.left > rect2.right || rect1.bottom < rect2.top || rect1.top > rect2.bottom);
+    };
+
+    // 是否在拖拽
+    const isDragging = ref(false);
     const loadElement = () => {
       const fingeringContainer = document.getElementById("fingeringContainer");
       setDefaultScale();
@@ -472,9 +611,12 @@ export default defineComponent({
       const mc = new Hammer.Manager(fingeringContainer as HTMLElement);
       mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
       mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get("pan")]);
-      // mc.get("pan").set({ direction: Hammer.DIRECTION_ALL });
-      // mc.get("pinch").set({ enable: true });
+
+      let dragTimeout: any;
+
       mc.on("panstart pinchstart", function (ev) {
+        isDragging.value = true;
+        clearTimeout(dragTimeout);
         data.transform.transition = "";
       });
       mc.on("panmove pinchmove", function (ev) {
@@ -483,19 +625,40 @@ export default defineComponent({
           data.transform.scale = ev.scale * data.transform.startScale;
           data.transform.x = data.transform.startX + ev.deltaX;
           data.transform.y = data.transform.startY + ev.deltaY;
+
+          // 使用示例
+          const element1 = document.getElementById("fullInstrumentImg");
+          const element2 = document.getElementById("fullInstrumentUserTab");
+          data.domOverlapping = isElementOverlapping(element1, element2);
         }
         if (ev.type === "panmove") {
           // console.log("🚀 ~ ev:", ev.type, ev.deltaX, ev.deltaY);
           data.transform.x = data.transform.startX + ev.deltaX;
           data.transform.y = data.transform.startY + ev.deltaY;
+
+          // 使用示例
+          const element1 = document.getElementById("fullInstrumentImg");
+          const element2 = document.getElementById("fullInstrumentUserTab");
+          data.domOverlapping = isElementOverlapping(element1, element2);
         }
       });
+      mc.on("panend pinchend", function (ev) {
+        dragTimeout = setTimeout(() => {
+          isDragging.value = false;
+        }, 100); // 设置一个短暂的延迟以确保拖拽操作结束
+      });
       //
       mc.on("hammer.input", function (ev) {
         if (ev.isFinal) {
+          // isDragging.value = false;
           data.transform.startScale = data.transform.scale;
           data.transform.startX = data.transform.x;
           data.transform.startY = data.transform.y;
+
+          // 使用示例
+          const element1 = document.getElementById("fullInstrumentImg");
+          const element2 = document.getElementById("fullInstrumentUserTab");
+          data.domOverlapping = isElementOverlapping(element1, element2);
         }
       });
     };
@@ -508,6 +671,7 @@ export default defineComponent({
         data.transform.startScale = data.subject === "pan-flute" ? 0.9 : 1;
         data.transform.startX = 0;
         data.transform.startY = 0;
+        data.domOverlapping = false;
       });
     };
 
@@ -541,6 +705,14 @@ export default defineComponent({
         }
       }
     );
+    watch(
+      () => data.tipShow,
+      (val: any) => {
+        if (!val) {
+          onResize();
+        }
+      }
+    );
     /** 课件播放 */
     const changePlay = (res: any) => {
       if (res?.data?.api === "setPlayState") {
@@ -571,7 +743,38 @@ export default defineComponent({
 
     const noteBoxRef = ref();
     const scrollNoteBox = (type: "left" | "right") => {
-      const width = noteBoxRef.value.offsetWidth / 2;
+      const domOffsetWidth = noteBoxRef.value.offsetWidth;
+      const width = domOffsetWidth / 2;
+      const scrollLeft: any = noteBoxRef.value.scrollLeft;
+      // 判断是否移动到最左边
+      if (width >= scrollLeft && type === "left") {
+        // 不管当前显示在哪个音老师滚动到开始位置
+        (noteBoxRef.value as unknown as HTMLElement).scroll({
+          left: 0,
+          top: 0,
+          behavior: "smooth",
+        });
+        return;
+      }
+      // 处理在部分手机点击左右会超出范围
+      if (type === "right") {
+        // 遍历子元素并累加它们的宽度
+        let childElementsWidth = 0;
+        for (let i = 0; i < noteBoxRef.value.children.length; i++) {
+          childElementsWidth += noteBoxRef.value.children[i].offsetWidth;
+        }
+        // 判断是否移动到最右边
+        if (width > childElementsWidth - scrollLeft - domOffsetWidth) {
+          // 不管当前显示在哪个音老师滚动到开始位置
+          (noteBoxRef.value as unknown as HTMLElement).scroll({
+            left: noteBoxRef.value.scrollWidth,
+            top: 0,
+            behavior: "smooth",
+          });
+          return;
+        }
+      }
+
       (noteBoxRef.value as unknown as HTMLElement).scrollBy({
         left: type === "left" ? -width : width,
         behavior: "smooth",
@@ -606,6 +809,13 @@ export default defineComponent({
       getNotes();
 
       setTimeout(() => {
+        (noteBoxRef.value as unknown as HTMLElement).scroll({
+          left: 0,
+          top: 0,
+          behavior: "smooth",
+        });
+      }, 0);
+      setTimeout(() => {
         playAction.resetAction = false;
       }, 2000);
     };
@@ -801,6 +1011,7 @@ export default defineComponent({
     };
 
     /** 滚轮缩放 */
+
     const handleWheel = (e: WheelEvent) => {
       e.preventDefault();
       if (e.deltaY > 0) {
@@ -814,16 +1025,39 @@ export default defineComponent({
           data.transform.scale = 2;
         }
       }
+
+      // 使用示例
+      setTimeout(() => {
+        const element1 = document.getElementById("fullInstrumentImg");
+        const element2 = document.getElementById("fullInstrumentUserTab");
+        data.domOverlapping = isElementOverlapping(element1, element2);
+      }, 0);
     };
 
+    const onResize = () => {
+      nextTick(() => {
+        setTimeout(() => {
+          const element1: any = document.querySelector("#fullInstrumentImg");
+          // console.log(element1, "element1");
+          const rect = element1?.getBoundingClientRect();
+          data.domOverImgPropery = {
+            ...rect,
+            width: rect.width * (1 / data.transform.scale) + "px",
+            height: rect.height * (1 / data.transform.scale) + "px",
+          };
+        }, 330);
+      });
+    };
     onMounted(() => {
       window.addEventListener("message", changePlay);
+      window.addEventListener("resize", onResize);
       const fingeringContainer = document.getElementById("fingeringContainer");
       fingeringContainer?.addEventListener("wheel", handleWheel);
     });
 
     onUnmounted(() => {
       window.removeEventListener("message", changePlay);
+      window.removeEventListener("resize", onResize);
       const fingeringContainer = document.getElementById("fingeringContainer");
       fingeringContainer?.removeEventListener("wheel", handleWheel);
       document.title = "Ai学练";
@@ -1085,7 +1319,7 @@ export default defineComponent({
             <div class={styles.wrapFinger}>
               <div
                 id="fingeringContainer"
-                class={[styles.boxFinger, query.platform === "pc" ? styles.pcBoxFinger : ""]}
+                class={[styles.boxFinger, query.platform === "pc" ? styles.pcBoxFinger : "", data.domOverlapping && data.notePoints?.length > 0 && styles.boxFingerOverlapping]}
                 style={{
                   paddingTop: containerBox.value.paddingTop,
                   paddingBottom: containerBox.value.paddingBottom,
@@ -1099,21 +1333,132 @@ export default defineComponent({
                   class={[styles.fingeringContainer]}
                 >
                   <div class={styles.imgs}>
-                    {!data.loadingImg && <img src={data.fingeringMode === "scaleMode" ? fingerData.subject?.json?.full : fingerData.subject?.json?.full1} />}
+                    {!data.loadingImg && <img id="fullInstrumentImg" src={data.fingeringMode === "scaleMode" ? fingerData.subject?.json?.full : fingerData.subject?.json?.full1} />}
+
                     {rs.map((key: number | string, index: number) => {
                       const nk: string = typeof key === "string" ? key.replace("active-", "") : String(key);
-                      return <img data-index={nk} src={fingerData.subject?.json?.[nk]} />;
+                      return <img class={styles.showImgNk} data-index={nk} src={fingerData.subject?.json?.[nk]} />;
                     })}
                     <div style={{ left: data.viewIndex == 2 ? "0" : "64%" }} class={[styles.tizhi, canTizhi && styles.canDisplay]} onClick={() => (fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)}>
                       替指
                     </div>
                     <div id="finger-note-2" style={{ left: "50%", transform: "translateX(-50%)" }} class={styles.tizhi} onClick={() => (fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)}></div>
+
+                    {data.notePoints?.length > 0 && (
+                      <div
+                        class={[styles.fingeringPointSection]}
+                        style={{
+                          width: data.domOverImgPropery.width,
+                          height: data.domOverImgPropery.height,
+                        }}
+                      >
+                        <div class={[styles[data.subject], data.viewIndex === 2 && data.subject === "pan-flute" && styles["pan-flute-back"]]}>
+                          {data.notePoints.map((point: any) => (
+                            <div
+                              class={styles.p1}
+                              style={point.style}
+                              // onClick={(e: any) => {
+                              //   e.stopPropagation();
+                              //   if (isDragging.value) return;
+                              //   noteInstrumentPlay(point, true);
+                              // }}
+                              onMousedown={(e: any) => {
+                                e.stopPropagation();
+                                e.preventDefault();
+                                console.log("onMousedown", e);
+                                if (isTouch) return;
+                                startNotePress(point);
+                              }}
+                              onMouseup={(e: any) => {
+                                e.stopPropagation();
+                                e.preventDefault();
+                                // console.log("onMouseup", e);
+                                if (isTouch) return;
+                                cancelNotePress(point);
+                              }}
+                              onMouseleave={(e: any) => {
+                                e.stopPropagation();
+                                e.preventDefault();
+                                // console.log("onMouseleave", e);
+                                if (isTouch) return;
+                                cancelNotePress(point);
+                              }}
+                              onTouchstart={(e: any) => {
+                                e.stopPropagation();
+                                e.preventDefault();
+                                // console.log("onTouchstart", e);
+                                isTouch = true;
+                                startNotePress(point);
+                              }}
+                              onTouchend={(e: any) => {
+                                e.stopPropagation();
+                                e.preventDefault();
+                                // console.log("onTouchend", e);
+                                cancelNotePress(point);
+                              }}
+                              onTouchcancel={(e: any) => {
+                                e.stopPropagation();
+                                e.preventDefault();
+                                // console.log("onTouchcancel", e);
+                                cancelNotePress(point);
+                              }}
+                            >
+                              {point.children && (
+                                <div
+                                  class={styles.p2}
+                                  // onClick={(e: any) => {
+                                  //   e.stopPropagation();
+                                  //   if (isDragging.value) return;
+                                  //   noteInstrumentPlay(point.children, true);
+                                  // }}
+                                  onMousedown={(e: any) => {
+                                    e.stopPropagation();
+                                    e.preventDefault();
+                                    if (isTouch) return;
+                                    startNotePress(point.children);
+                                  }}
+                                  onMouseup={(e: any) => {
+                                    e.stopPropagation();
+                                    e.preventDefault();
+                                    if (isTouch) return;
+                                    cancelNotePress(point.children);
+                                  }}
+                                  onMouseleave={(e: any) => {
+                                    e.stopPropagation();
+                                    e.preventDefault();
+                                    if (isTouch) return;
+                                    cancelNotePress(point.children);
+                                  }}
+                                  onTouchstart={(e: any) => {
+                                    e.stopPropagation();
+                                    e.preventDefault();
+                                    isTouch = true;
+                                    startNotePress(point.children);
+                                  }}
+                                  onTouchend={(e: any) => {
+                                    e.stopPropagation();
+                                    e.preventDefault();
+                                    cancelNotePress(point.children);
+                                  }}
+                                  onTouchcancel={(e: any) => {
+                                    e.stopPropagation();
+                                    e.preventDefault();
+                                    cancelNotePress(point.children);
+                                  }}
+                                  style={point.children.style}
+                                ></div>
+                              )}
+                            </div>
+                          ))}
+                        </div>
+                      </div>
+                    )}
                   </div>
                 </div>
               </div>
               {/* 老师端过来隐藏 */}
               {query.platform === "pc" ? (
-                <div class={styles.userTab}>
+                <div class={[styles.userTab, data.domOverlapping && data.notePoints?.length > 0 && styles.usrTabOverlaping]} id="fullInstrumentUserTab">
                   <Tabs v-model:active={userTabActive.value} class={styles.userTabBox}>
                     {userTabs.map((item) => {
                       return (
@@ -1203,33 +1548,42 @@ export default defineComponent({
                                             draggable={false}
                                             class={[styles.note, "note-class"]}
                                             key={note.realKey}
-                                            onClick={async () => {
-                                              // 判断是否在播放音阶
-                                              if (playStatus.gamut) return;
-                                              if (playAction.listenLock) return;
-                                              if (playAction.showAnswerLoading) return;
-                                              if (playStatus.action) {
-                                                playAction.userAnswer = note;
-                                                // 判断用户答题
-                                                const userResult = note.realKey === playAction.standardAnswer.realKey ? 1 : 2;
-                                                playAction.userAnswerStatus = userResult;
-                                                playAction.listenLock = true;
-                                                data.realKey = note.realKey;
-                                                await fingeringPlay(note, 1000);
-                                                resetMode(userResult === 1 ? true : false, 0);
-                                                data.realKey = 0;
-
-                                                // 如果是指法模式显示完之后要还原
-                                                if (data.fingeringMode === "fingeringMode" && userResult === 2) {
-                                                  // 延迟显示,因为重置的时候有一个异步操作
-                                                  setTimeout(() => {
-                                                    data.realKey = playAction.standardAnswer.realKey;
-                                                  }, 10);
-                                                }
-                                                playAction.listenLock = false;
-                                              } else {
-                                                noteClick(note);
-                                              }
+                                            // onClick={async () => {
+                                            //   noteInstrumentPlay(note);
+                                            // }}
+                                            onMousedown={(e: any) => {
+                                              e.stopPropagation();
+                                              e.preventDefault();
+                                              if (isTouch) return;
+                                              startNotePress(note, false);
+                                            }}
+                                            onMouseup={(e: any) => {
+                                              e.stopPropagation();
+                                              e.preventDefault();
+                                              if (isTouch) return;
+                                              cancelNotePress(note, false);
+                                            }}
+                                            onMouseleave={(e: any) => {
+                                              e.stopPropagation();
+                                              e.preventDefault();
+                                              if (isTouch) return;
+                                              cancelNotePress(note, false);
+                                            }}
+                                            onTouchstart={(e: any) => {
+                                              e.stopPropagation();
+                                              e.preventDefault();
+                                              isTouch = true;
+                                              startNotePress(note, false);
+                                            }}
+                                            onTouchend={(e: any) => {
+                                              e.stopPropagation();
+                                              e.preventDefault();
+                                              cancelNotePress(note, false);
+                                            }}
+                                            onTouchcancel={(e: any) => {
+                                              e.stopPropagation();
+                                              e.preventDefault();
+                                              cancelNotePress(note, false);
                                             }}
                                           >
                                             <img draggable={false} src={resultImg(note).icon} />
@@ -1329,6 +1683,7 @@ export default defineComponent({
                                             data.viewIndex = 0;
                                           }
                                         }
+
                                         getFingeringData();
                                       }}
                                     >
@@ -1341,6 +1696,7 @@ export default defineComponent({
                                     onClick={() => {
                                       resetElement();
                                       data.tipShow = !data.tipShow;
+                                      onResize();
                                     }}
                                   >
                                     <img src={icons.icon_2_1} />
@@ -1362,9 +1718,9 @@ export default defineComponent({
                   </Tabs>
                 </div>
               ) : (
-                <>
+                <div class={[data.domOverlapping && data.notePoints?.length > 0 && styles.usrTabOverlapingNotes]} id="fullInstrumentUserTab">
                   <div
-                    class={styles.notes}
+                    class={[styles.notes]}
                     style={{
                       paddingLeft: data.paddingLeft ? data.paddingLeft : "",
                     }}
@@ -1399,7 +1755,7 @@ export default defineComponent({
 
                       {/* [styles.noteContent, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad] */}
                       <div class={styles.lastNoteContent}>
-                        <div ref={noteBoxRef} class={styles.noteBox}>
+                        <div ref={noteBoxRef} class={styles.noteBox} id="noteBox">
                           {data.notes.map((note: IFIGNER_INSTRUMENT_Note, index: number) => {
                             const steps = new Array(Math.abs(note.step)).fill(1);
                             return (
@@ -1408,33 +1764,42 @@ export default defineComponent({
                                 draggable={false}
                                 class={[styles.note, "note-class"]}
                                 key={note.realKey}
-                                onClick={async () => {
-                                  // 判断是否在播放音阶
-                                  if (playStatus.gamut) return;
-                                  if (playAction.listenLock) return;
-                                  if (playAction.showAnswerLoading) return;
-                                  if (playStatus.action) {
-                                    playAction.userAnswer = note;
-                                    // 判断用户答题
-                                    const userResult = note.realKey === playAction.standardAnswer.realKey ? 1 : 2;
-                                    playAction.userAnswerStatus = userResult;
-                                    playAction.listenLock = true;
-                                    data.realKey = note.realKey;
-                                    await fingeringPlay(note, 1000);
-                                    resetMode(userResult === 1 ? true : false, 0);
-                                    data.realKey = 0;
-
-                                    // 如果是指法模式显示完之后要还原
-                                    if (data.fingeringMode === "fingeringMode" && userResult === 2) {
-                                      // 延迟显示,因为重置的时候有一个异步操作
-                                      setTimeout(() => {
-                                        data.realKey = playAction.standardAnswer.realKey;
-                                      }, 10);
-                                    }
-                                    playAction.listenLock = false;
-                                  } else {
-                                    noteClick(note);
-                                  }
+                                // onClick={async () => {
+                                //   noteInstrumentPlay(note);
+                                // }}
+                                onMousedown={(e: any) => {
+                                  e.stopPropagation();
+                                  e.preventDefault();
+                                  if (isTouch) return;
+                                  startNotePress(note, false);
+                                }}
+                                onMouseup={(e: any) => {
+                                  e.stopPropagation();
+                                  e.preventDefault();
+                                  if (isTouch) return;
+                                  cancelNotePress(note, false);
+                                }}
+                                onMouseleave={(e: any) => {
+                                  e.stopPropagation();
+                                  e.preventDefault();
+                                  if (isTouch) return;
+                                  cancelNotePress(note, false);
+                                }}
+                                onTouchstart={(e: any) => {
+                                  e.stopPropagation();
+                                  e.preventDefault();
+                                  isTouch = true;
+                                  startNotePress(note, false);
+                                }}
+                                onTouchend={(e: any) => {
+                                  e.stopPropagation();
+                                  e.preventDefault();
+                                  cancelNotePress(note, false);
+                                }}
+                                onTouchcancel={(e: any) => {
+                                  e.stopPropagation();
+                                  e.preventDefault();
+                                  cancelNotePress(note, false);
                                 }}
                               >
                                 <img draggable={false} src={resultImg(note).icon} />
@@ -1497,7 +1862,7 @@ export default defineComponent({
                       </Button>
                     </div>
                   )}
-                </>
+                </div>
               )}
             </div>
             {/* 老师端过来隐藏 */}
@@ -1537,6 +1902,7 @@ export default defineComponent({
                     onClick={() => {
                       resetElement();
                       data.tipShow = !data.tipShow;
+                      onResize();
                     }}
                   >
                     <img src={icons.icon_2_1} />
@@ -1726,7 +2092,8 @@ export default defineComponent({
           <Popup
             style={query.platform === "pc" ? changeSubjectShowBoxDragData.styleDrag.value : {}}
             v-model:show={data.changeSubjectShow}
-            class={[styles.changeSubjectPopup, changeSubjectShowBoxClass]}
+            class={[styles.changeSubjectPopup, query.platform === "pc" && styles.changeSubjectPopupPc, changeSubjectShowBoxClass]}
+            closeOnClickOverlay={query.platform === "pc" ? false : true}
             onClick={(e: any) => {
               e.stopPropagation();
             }}
@@ -1747,6 +2114,7 @@ export default defineComponent({
                 data.loadingDom = true;
                 fingerData.fingeringInfo = subjectFingering(data.subject);
                 data.activeTone = {} as any;
+                data.noteType = "all";
                 resetElement();
                 resetMode(true, 0);
                 // api_setRequestedOrientation(orientationDirection.value);

+ 3 - 3
src/state.ts

@@ -1284,8 +1284,8 @@ export const evaluatCreateMusicPlayer = () => {
   return api_createMusicPlayer({
     musicSrc: state.accompany || state.music, // 曲谱音频url
     // tuneSrc: "https://oss.dayaedu.com/cloud-coach/1686725501654check_music1_(1).mp3", //效音音频url
-    tuneSrc: "https://oss.dayaedu.com/MECMP/1722336027096.mp3", //效音音频url
-    checkFrequence: 787,
+    tuneSrc: "https://oss.dayaedu.com/MECMP/1722593665681.mp3", //效音音频url
+    checkFrequence: 496,
   });
 };
 
@@ -1418,7 +1418,7 @@ const setState = (data: any, index: number) => {
   /**
    * 单曲,指法根据用户当前的乐器来显示,如果没有则取musicSheetSoundList第一个track
    */
-  let musicalCode = !storeData.user?.instrumentId ? data.musicSheetSoundList.find((item:any)=>{ return item.audioPlayType === "PLAY" })?.track || '' : data.musicSheetSoundList?.find((item: any) => item?.musicalInstrumentId == storeData.user?.instrumentId && item.audioPlayType === "PLAY")?.track || '';
+  let musicalCode = !storeData.user?.instrumentId ? data.musicSheetSoundList?.find((item:any)=>{ return item.audioPlayType === "PLAY" })?.track || '' : data.musicSheetSoundList?.find((item: any) => item?.musicalInstrumentId == storeData.user?.instrumentId && item.audioPlayType === "PLAY")?.track || '';
   const pitchSubject = musicalInstrumentCodeInfo.find((n) => n.code.toLocaleLowerCase() === subjectCode.toLocaleLowerCase())
   const pitchMusical = musicalInstrumentCodeInfo.find((n) => n.code.toLocaleLowerCase() === musicalCode.toLocaleLowerCase())
   state.subjectCodeId = pitchSubject ? pitchSubject.id : 0

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

@@ -525,7 +525,7 @@ export const subjectFingering = (subjectId: number | string): IFingering => {
   }
 };
 
-export const getFingeringConfig = async (type: IVocals | undefined): Promise<ITypeFingering> => {
+export const getFingeringConfig = async (type: IVocals | undefined, source?: string): Promise<ITypeFingering> => {
   switch (type) {
     case "flute":
       const flute = await import(`./fingering-img/flute/index.json`);
@@ -614,7 +614,7 @@ export const getFingeringConfig = async (type: IVocals | undefined): Promise<ITy
         width: "180px",
       };
     case "hulusi-flute":
-      const hulusi = await import(`./fingering-img/hulusi-flute/index.json`);
+      const hulusi = source === 'musicDetail' ? await import(`./fingering-img/hulusi-flute0/index.json`) : await import(`./fingering-img/hulusi-flute/index.json`);
       return {
         json: hulusi.default,
         relationship: relationships.hulusi,

File diff suppressed because it is too large
+ 0 - 0
src/view/fingering/fingering-img/hulusi-flute/index.json


File diff suppressed because it is too large
+ 9 - 0
src/view/fingering/fingering-img/hulusi-flute0/index.json


File diff suppressed because it is too large
+ 0 - 0
src/view/fingering/fingering-img/melodica/index.json


File diff suppressed because it is too large
+ 0 - 0
src/view/fingering/fingering-img/melodica1/index.json


File diff suppressed because it is too large
+ 0 - 0
src/view/fingering/fingering-img/pan-flute/index.json


File diff suppressed because it is too large
+ 0 - 0
src/view/fingering/fingering-img/pan-flute1/index.json


File diff suppressed because it is too large
+ 0 - 0
src/view/fingering/fingering-img/pan-flute2/index.json


File diff suppressed because it is too large
+ 0 - 0
src/view/fingering/fingering-img/pan-flute3/index.json


+ 3 - 1
src/view/fingering/index.tsx

@@ -13,7 +13,9 @@ export default defineComponent({
       delay: 0,
     });
     const getFingeringData = async () => {
-      fingerData.subject = await getFingeringConfig(state.fingeringInfo.name);
+      // 葫芦丝的指法,云教练页面和听音练习页面,展示的不一样,需要区分
+      const source = state.fingeringInfo.name === 'hulusi-flute' ? 'musicDetail' : '';
+      fingerData.subject = await getFingeringConfig(state.fingeringInfo.name, source);
       console.log("🚀 ~ fingerData.subject:", fingerData.subject);
     };
     onBeforeMount(() => {

+ 1 - 0
src/view/selection/index.module.less

@@ -141,6 +141,7 @@
     background-color: #FFC121;
     color: #673207;
     font-size: 14px;
+    font-weight: 600;
 }
 
 .noteFollow {

File diff suppressed because it is too large
+ 0 - 0
stats.html


Some files were not shown because too many files changed in this diff