import { PropType, computed, defineComponent, nextTick, onBeforeMount, onMounted, onUnmounted, reactive, ref, toRef } from "vue";
import styles from "./index.module.less";
import icons from "./image/icons.json";
import { FIGNER_INSTRUMENT_DATA, FIGNER_INSTRUMENT_REALKEY, IFIGNER_INSTRUMENT_Note } from "/src/view/figner-preview";
import { ITypeFingering, IVocals, getFingeringConfig, mappingVoicePart, subjectFingering } from "/src/view/fingering/fingering-config";
import { Howl } from "howler";
import { storeData } from "/src/store";
import { api_back, api_cloudLoading, api_setRequestedOrientation, api_setStatusBarVisibility, isSpecialShapedScreen } from "/src/helpers/communication";
import Hammer from "hammerjs";
import { Button, Icon, Loading, Popover, Popup, Progress, Space, showToast } from "vant";
import GuideIndex from "./guide/guide-index";
import { getQuery } from "/src/utils/queryString";
import { browser } from "/src/utils";
import { usePageVisibility } from "@vant/use";
import { watch } from "vue";
import icon_loading_img from "./image/icon_loading_img.png";
import noteImg from "./image/noteImg.png";
import state, { IPlatform } from "/src/state";
import { api_musicalInstrumentList, api_subjectList, getSubjectList } from "../api";
import ChangeSubject from "./change-subject";
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",
  emits: ["close"],
  props: {
    show: {
      type: Boolean,
      default: true,
    },
    isComponent: {
      type: Boolean,
      default: false,
    },
    subject: {
      type: String as PropType<IVocals>,
      default: "",
    },
  },
  setup(props, { emit }) {
    const query = getQuery();
    const browsInfo = browser();
    const tempCode = query.code ? query.code.split(",")[0] : "";
    const code = mappingVoicePart(tempCode, "INSTRUMENT");
    const subject = props.isComponent ? props.subject || "pan-flute" : code || "pan-flute";
    const data = reactive({
      linkSource: query.linkSource, // 来源，目前只有课件里使用
      loading: true,
      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,
      activeToneName: "",
      soundFonts: {} as any,
      viewIndex: 0,
      viewTotal: 1,
      noteAudio: null as unknown as Howl,
      transform: {
        scale: 1,
        x: 0,
        y: 0,
        startScale: 1,
        startX: 0,
        startY: 0,
        transition: "",
      },
      tipShow: false,
      tips: [] as IFIGNER_INSTRUMENT_Note[],

      tnoteShow: false,
      loadingSoundFonts: true,
      loadingSoundProgress: 0,

      changeSubjectShow: false,

      huaweiPad: navigator?.userAgent?.includes("UAWEIVRD-W09") ? true : false,
      paddingTop: "",
      paddingLeft: "",
      subjects: [] as any,
      fingeringModeList: [
        {
          text: "指法模式",
          value: "fingeringMode",
          icon: icons.icon_click,
        },
        {
          text: "听音模式",
          value: "listenMode",
          icon: icons.icon_listen,
        },
        {
          text: "音阶模式",
          value: "scaleMode",
          icon: icons.icon_mode,
        },
      ],
      fingeringMode: query.type || ("scaleMode" as "fingeringMode" | "listenMode" | "scaleMode"), // 模式
      noteType: "all" as "#c" | "all", // 音调
      loadingDom: false, // 切换乐器时需要重置
      loadingImg: false, // 切换模式，加载图片
      domOverlapping: false, // 元素是否被遮住
      domOverImgPropery: {
        width: "100%",
        height: "100%",
      } as any,
    });
    const fingerData = reactive({
      relationshipIndex: 0,
      subject: null as unknown as ITypeFingering,
      fingeringInfo: subjectFingering(data.subject),
    });
    if (!props.isComponent) {
      state.fingeringInfo = fingerData.fingeringInfo;
    }

    const getAPPData = async (type: "top" | "left") => {
      const screenData = await isSpecialShapedScreen();
      if (screenData?.content) {
        console.log("🚀 ~ screenData:", screenData.content);
        const { isSpecialShapedScreen, notchHeight } = screenData.content;
        if (isSpecialShapedScreen) {
          if (type === "top") {
            data.paddingTop = 25 + "px";
          }
          if (type === "left") {
            data.paddingLeft = 25 + "px";
          }
        }
      }
    };

    const getHeadTop = () => {
      if (fingerData.fingeringInfo.orientation === 1) {
        getAPPData("top");
      }
      if (fingerData.fingeringInfo.orientation === 0) {
        getAPPData("left");
      }
    };

    const getNotes = () => {
      const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA];
      if (fignerData) {
        data.tones = fignerData.tones || [];
        if (data.tones.length) {
          data.activeTone = data.tones[0];
          data.popupActiveTone = data.tones[0];
        }
        data.tips = fignerData.tips || [];
        setNotes();
        setTimeout(() => {
          data.loading = false;
        }, 600);
      }
    };
    const setNotes = () => {
      const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA];
      if (fignerData) {
        const tempNotes = fignerData[`list${data.activeTone.realName || ""}`];
        const appendNote: any = [];
        tempNotes.forEach((note: any) => {
          note.steps = new Array(Math.abs(note.step)).fill(1);
          if (FIGNER_INSTRUMENT_REALKEY.includes(note.realKey)) {
            appendNote.push(note);
          }
        });
        // 判断是音符状态
        data.notes = data.noteType === "#c" ? appendNote : tempNotes;
        // data.notes = fignerData[`list${data.activeTone.realName || ""}`];
        data.notePoints = FINER_INSTRUMENT_POINT[data.subject];
      }
    };
    const getFingeringData = async () => {
      const subject: any = data.subject + (data.viewIndex === 0 ? "" : data.viewIndex);
      console.log("🚀 ~ subject:模式", subject, data.viewIndex, data.fingeringMode);
      fingerData.subject = await getFingeringConfig(subject);
    };
    const createAudio = (url: string) => {
      return new Promise((resolve, reject) => {
        const noteAudio = new Howl({
          src: url,
          loop: true,
          onload: () => {
            resolve(noteAudio);
          },
          onloaderror: () => {
            reject(new Error(`加载音频失败`));
          },
        });
      });
    };
    const getSounFonts = async () => {
      const pathname = /(192|localhost)/.test(location.origin) ? "/" : location.pathname;
      data.loadingSoundFonts = true;
      try {
        data.loadingSoundProgress = 0;
        for (let i = 0; i < data.notes.length; i++) {
          const note = data.notes[i];
          // console.log("🚀 ~ note:", i);
          let url = `${pathname}soundfonts/${data.subject}/`;
          url += note.realName;
          url += ".mp3";
          data.soundFonts[note.realKey] = await createAudio(url);
          data.loadingSoundProgress = Math.floor(((i + 1) / data.notes.length) * 100);
        }
        data.loadingSoundProgress = 100;
      } catch (e: any) {
        //
        showToast(e.message);
      }
      api_cloudLoading();
      data.loadingSoundFonts = false;
    };

    // const selectSubjectType = (subject: string) => {
    //   data.subjects.forEach((item: any) => {
    //     if (item.value === subject) {
    //       item.className = styles.selected;
    //     } else {
    //       item.className = "";
    //     }
    //   });
    // };

    // 切换当前模式
    const onChangeFingeringModel = (e: any) => {
      e.stopPropagation();
      //
      if (playAction.listenLock) return;
      if (playAction.showAnswerLoading) return;
      data.loadingImg = true;
      if (data.fingeringMode === "scaleMode") {
        if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) {
          data.viewIndex = 1;
        } else {
          data.viewIndex = 0;
        }
        const o: any = {
          "pan-flute": 2,
          ocarina: 2,
          whistling: 2,
          piccolo: 2,
          "hulusi-flute": 2,
          "baroque-recorder": 2,
        };
        data.viewTotal = o[data.subject] || 1;
        data.fingeringMode = "listenMode";
      } else if (data.fingeringMode === "listenMode") {
        data.fingeringMode = "fingeringMode";
      } else if (data.fingeringMode === "fingeringMode") {
        data.fingeringMode = "scaleMode";
        data.viewIndex = 0;
        data.noteType = "all";
      }
      data.tipShow = false;
      resetElement();
      resetMode(true, 0);
      setTimeout(() => {
        __init(false);
      }, 100);
    };

    const __init = async (loadSong = true) => {
      data.loadingDom = true;
      getNotes();
      // selectSubjectType(data.subject);

      if (data.fingeringMode === "fingeringMode") {
        if (data.subject === "pan-flute") {
          data.viewIndex = 3;
        } else if (["pan-flute", "ocarina", "melodica", "whistling"].includes(data.subject)) {
          data.viewIndex = 1;
        }
      } else {
        if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) {
          data.viewIndex = 1;
        }
      }

      const o: any = {
        "pan-flute": 2,
        ocarina: 2,
        whistling: 2,
        piccolo: 2,
        "hulusi-flute": 2,
        "baroque-recorder": 2,
      };
      data.viewTotal = o[data.subject] || 1;
      getFingeringData();
      getHeadTop();
      if (loadSong) {
        await getSounFonts();
      }

      data.loadingDom = false;
      data.loadingImg = false;

      // 初始化获取元素宽高
      onResize();
    };

    // 获取声部
    const getSubjects = async () => {
      try {
        // api_subjectList
        // const subjects = await api_musicalInstrumentList({
        //   enableFlag: true,
        // });

        // const rows = subjects.data || [];
        // rows.forEach((row: any) => {
        //   const tempList: any = {
        //     text: row.name,
        //     value: mappingVoicePart(row.code, "INSTRUMENT"), // mappingVoicePart(row.code, "INSTRUMENT"),
        //     id: row.id,
        //   };
        //   data.subjects.push(tempList);
        // });

        const subjects = await api_subjectList({
          enableFlag: true,
          delFlag: 0,
          page: 1,
          rows: 999,
        });

        const rows = subjects.data || [];
        const tempSubjects: any[] = [];
        rows.forEach((row: any) => {
          const tempList: any = {
            text: row.name,
            value: "", // mappingVoicePart(row.code, "INSTRUMENT"),
            id: row.id,
            children: [] as any,
          };
          if (Array.isArray(row.instruments)) {
            row.instruments.forEach((i: any) => {
              const code = i.code ? i.code.split(",") : [];
              tempList.children.push({
                text: i.name,
                id: i.id,
                value: mappingVoicePart(code[0] || "", "INSTRUMENT"),
              });
            });
          }
          tempSubjects.push(tempList);
        });
        console.log(data.subject, "data.subject");
        data.subjects = tempSubjects;
      } catch (e) {
        //
        console.log(e, "e");
      }
    };

    onBeforeMount(async () => {
      if (browser().isApp) {
        state.platform = "APP" as IPlatform;
      } else {
        state.platform = query.platform?.toLocaleUpperCase() || "";
      }

      if (state.platform === IPlatform.PC) {
        document.title = "听音练习";
      }
      await getSubjects();
      __init();
    });

    // 播放时间
    let noteTimer: any = null;
    /**
     * 播放音频
     * @param item 音频节点
     * @param showNote 是否显示对应的指法
     * @param isScrollShowNote 是否滚动到对应播放的位置
     * @param autoStop 是否自动停止
     * @returns
     */
    const noteClick = (item: IFIGNER_INSTRUMENT_Note, showNote = true, isScrollShowNote = false, autoStop = false, callBack?: any) => {
      // console.log('音高', item.realKey)
      if (data.noteAudio) {
        data.noteAudio.stop();
        if (data.realKey === item.realKey) {
          data.realKey = 0;
          data.noteAudio = null as unknown as Howl;
          return;
        }

        clearTimeout(noteTimer);
      }
      if (showNote) {
        data.realKey = item.realKey;
      }
      // 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 = () => {
      if (data.noteAudio) {
        data.noteAudio.stop();
        data.realKey = 0;
        data.noteAudio = null as unknown as Howl;
      }
    };

    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,
      handleStop();
      if (props.isComponent) {
        // 返回的时候默认横屏
        // api_setRequestedOrientation(0);
        emit("close");
        return;
      } else if (state.platform === IPlatform.PC) {
        console.log(1, query);
        if (query.matchMedia == 1) {
          // 老师端，首页
          window.parent.postMessage(
            {
              api: "iframe_exit",
            },
            "*"
          );
          return;
        } else {
          window.close();
          return;
        }

        // if (fingerData.fingeringInfo.orientation === 0) {
        // 	api_setRequestedOrientation(1);
        // }
      }
      // 不在APP中,
      if (!storeData.isApp) {
        window.close();
        return;
      }
      api_back();
    };

    // 排箫，默认0.9显示
    const setDefaultScale = () => {
      if (data.subject === "pan-flute") {
        data.transform.scale = 0.9;
        data.transform.startScale = 0.9;
      }
    };

    onMounted(() => {
      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();
      // console.log("🚀 ~ fingeringContainer:", fingeringContainer);
      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")]);

      let dragTimeout: any;

      mc.on("panstart pinchstart", function (ev) {
        isDragging.value = true;
        clearTimeout(dragTimeout);
        data.transform.transition = "";
      });
      mc.on("panmove pinchmove", function (ev) {
        if (ev.type === "pinchmove") {
          // console.log("🚀 ~ ev:", ev.type, ev.scale, ev.deltaX, ev.deltaY);
          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);
        }
      });
    };
    const resetElement = () => {
      data.transform.transition = "all 0.3s";
      nextTick(() => {
        data.transform.scale = data.subject === "pan-flute" ? 0.9 : 1;
        data.transform.x = 0;
        data.transform.y = 0;
        data.transform.startScale = data.subject === "pan-flute" ? 0.9 : 1;
        data.transform.startX = 0;
        data.transform.startY = 0;
        data.domOverlapping = false;
      });
    };

    // 判断乐器是否移动
    const instrumentTranstion = computed(() => {
      const transform = data.transform;

      let scale = 1;
      if (data.subject === "pan-flute") {
        scale = 0.9;
      }
      if (transform.scale !== scale || transform.x !== 0 || transform.y !== 0 || transform.startScale !== scale || transform.startX !== 0 || transform.startY !== 0) {
        return true;
      } else {
        return false;
      }
    });

    const pageVisible = usePageVisibility();
    watch(
      () => pageVisible.value,
      (val) => {
        if (val === "hidden") {
          clearTimeout(playAction.timer);
          playAction.listenLock = false;
          playAction.listenTipsStatus = false;
          playAction.exampleAnser = {};
          resetMode(true, 0);
          handleStop();
          gaumntPause();
        }
      }
    );
    watch(
      () => data.tipShow,
      (val: any) => {
        if (!val) {
          onResize();
        }
      }
    );
    /** 课件播放 */
    const changePlay = (res: any) => {
      if (res?.data?.api === "setPlayState") {
        clearTimeout(playAction.timer);
        playAction.listenLock = false;
        playAction.listenTipsStatus = false;
        playAction.exampleAnser = {};
        resetMode(true, 0);
        handleStop();
        gaumntPause();
        // 重置乐器
        if (res?.data?.data?.code) {
          data.subject = code;
          data.viewIndex = 0;
          data.tipShow = false;
          data.loadingDom = true;
          fingerData.fingeringInfo = subjectFingering(data.subject);
          data.activeTone = {} as any;
          data.popupActiveTone = {} as any;
          resetElement();
          // 设置屏幕方向
          setTimeout(() => {
            __init();
          }, 100);
        }
      } else if (res.data.api === "startPlayState") {
        onStartPlayState();
      }
    };

    const onStartPlayState = () => {
      if (!localStorage.getItem("fingerGuideKey")) return;
      if (!(props.show && !data.loading && !data.loadingSoundFonts)) return;
      if (data.changeSubjectShow) return;
      if (data.fingeringMode === "fingeringMode" || data.fingeringMode === "listenMode") {
        onActionPlay();
      }
    };

    const noteBoxRef = ref();
    const scrollNoteBox = (type: "left" | "right") => {
      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",
      });
    };

    const playStatus = reactive({
      gamut: false, // 是否播放音阶
      gamutTimer: null as any, // 播放音阶定时器
      answer: false, // 是否显示答案
      action: false, // 是否开始播放
    });

    /** 音符切换 */
    const noteChangeShow = () => {
      if (playStatus.action) {
        if (playAction.listenLock) return;
        playAction.resetAction = true;
        resetMode(true, 0);
      }
      // // 播放音阶时不能切换
      // if (playStatus.gamut) return;
      // // 开始答题不能切换
      // if (playStatus.action) return;
      playStatus.gamut = false;
      gaumntPause();
      if (data.noteType === "all") {
        data.noteType = "#c";
      } else {
        data.noteType = "all";
      }
      getNotes();

      setTimeout(() => {
        (noteBoxRef.value as unknown as HTMLElement).scroll({
          left: 0,
          top: 0,
          behavior: "smooth",
        });
      }, 0);
      setTimeout(() => {
        playAction.resetAction = false;
      }, 2000);
    };

    // 开始播放音阶
    const onGamutPlayOrPause = async () => {
      playAction.resetAction = false;
      if (playStatus.gamut) {
        playStatus.gamut = false;
        gaumntPause();
      } else {
        // 不管当前显示在哪个音老师滚动到开始位置
        (noteBoxRef.value as unknown as HTMLElement).scroll({
          left: 0,
          top: 0,
          behavior: "smooth",
        });
        playStatus.gamut = true;
        const notes = data.notes;
        let scrollCount = 0;
        for (let i = 0; i < notes.length; i++) {
          if (!playStatus.gamut) return false;
          const activeDom = document.querySelectorAll(".note-class")[i] as any;
          if (activeDom.offsetLeft >= noteBoxRef.value.offsetWidth + (noteBoxRef.value.offsetWidth / 2) * scrollCount - activeDom.offsetWidth) {
            scrollNoteBox("right");
            scrollCount++;
          }
          await gaumtPlay(notes[i]);
        }

        // // 处理播放到最后一个
        setTimeout(() => {
          playStatus.gamut = false;
          gaumntPause();
        }, 667);
      }
    };
    const gaumtPlay = (note: any, status?: boolean) => {
      return new Promise((resolve) => {
        playStatus.gamutTimer = setTimeout(() => {
          if (playStatus.gamut || status) {
            noteClick(note);
          }
          resolve(note);
        }, 667);
      });
    };
    const gaumntPause = () => {
      clearTimeout(playStatus.gamutTimer);
      if (data.noteAudio) {
        data.noteAudio.stop();
        data.realKey = 0;
        data.noteAudio = null as unknown as Howl;
      }
    };

    /** 开始播放 */
    const playAction = reactive({
      exampleAnser: {} as any, // 示例声音
      standardAnswer: {} as any, // 标准答案key
      showAnswerLoading: false, // 显示按答案中
      listenModeStatus: false, // 是否开始了模式
      listenLock: false,
      listenTipsStatus: false, // 开始播放状态
      resetAction: false, // 是否重置
      /** 0: 未答，1: 答对，2: 答错 */
      userAnswerStatus: 0 as 0 | 1 | 2, // 用户回答状态
      userAnswer: {} as any, // 用户答的数据
      timer: null as any,
    });
    const onActionPlay = async () => {
      playAction.resetAction = false;
      if (playAction.listenLock) return;
      if (playAction.showAnswerLoading) return;
      playStatus.action = true;
      playStatus.answer = true;
      // 先暂停播放声音
      gaumntPause();
      if (data.fingeringMode === "fingeringMode") {
        onFingeringMode();
      } else if (data.fingeringMode === "listenMode") {
        if (playAction.listenModeStatus) {
          playAction.listenLock = true;
          await fingeringPlay(playAction.standardAnswer, 1500, false);
          gaumntPause();
          playAction.listenLock = false;
        } else {
          onListenMode();
        }
      }
    };

    // 指法模式
    const fingeringPlay = (note: any, timer = 1500, showNote = true) => {
      return new Promise((resolve) => {
        noteClick(note, showNote);
        playAction.timer = setTimeout(() => {
          resolve(note);
        }, timer);
      });
    };
    const onFingeringMode = () => {
      const randomIndex = Math.floor(Math.random() * data.notes.length);
      playAction.standardAnswer = data.notes[randomIndex];
      data.realKey = data.notes[randomIndex].realKey;
      if (playAction.listenModeStatus) {
        return;
      }
      playAction.listenModeStatus = true; // 是否开始听音
      playAction.listenLock = true; // 锁
      playAction.listenTipsStatus = true;
      playAction.timer = setTimeout(() => {
        playAction.listenTipsStatus = false;
        playAction.listenLock = false; // 锁
      }, 2000);
    };
    // 听音模式
    const onListenMode = async () => {
      playAction.listenModeStatus = true; // 是否开始听音
      playAction.listenLock = true; // 锁
      playAction.listenTipsStatus = true;
      // 设置并保存示例数据
      let randomIndex = data.notes.findIndex((item: any) => item.realKey === 69); // Math.floor(Math.random() * data.notes.length);

      playAction.exampleAnser = data.notes[randomIndex];
      data.realKey = playAction.exampleAnser.realKey;
      scrollAnswer(playAction.exampleAnser.realKey);
      await fingeringPlay(playAction.exampleAnser);
      data.realKey = 0;
      playAction.exampleAnser = {};
      gaumntPause();
      playAction.timer = setTimeout(async () => {
        // 设置答题数据
        randomIndex = Math.floor(Math.random() * data.notes.length);
        playAction.standardAnswer = data.notes[randomIndex];
        await fingeringPlay(data.notes[randomIndex], 1500, false);
        gaumntPause();
        playAction.listenLock = false;
        playAction.listenTipsStatus = false;
      }, 1000);
    };

    // 显示答案
    const onShowAnswer = async () => {
      if (playAction.listenLock) return;
      playAction.showAnswerLoading = true;
      scrollAnswer(playAction.standardAnswer.realKey);
      await fingeringPlay(playAction.standardAnswer);
      resetMode(true, 0);
      // }
    };
    // 滚动到对应答案位置
    const scrollAnswer = (realKey?: any) => {
      const tempRealKey = realKey || data.realKey;
      const index = data.notes.findIndex((item: any) => item.realKey === tempRealKey);
      const activeDom = document.querySelectorAll(".note-class")[index] as any;
      if (activeDom) {
        const aWidth = activeDom.offsetWidth;
        const width = noteBoxRef.value.offsetWidth;
        const aLeft = Math.max(activeDom?.offsetLeft - aWidth, 0);
        (noteBoxRef.value as unknown as HTMLElement).scroll({
          left: Math.max(aLeft - width / 2, 0),
          top: 0,
          behavior: "smooth",
        });
      }
    };

    /**
     * 重置播放状态
     * @param status 是否全部重置
     * @param timer 延时时长（默认2s）
     */
    const resetMode = (status = true, timer = 2000) => {
      // 2秒钟后重置
      setTimeout(() => {
        gaumntPause();
        if (status) {
          playAction.standardAnswer = {};
          playAction.showAnswerLoading = false;
          playAction.userAnswerStatus = 0;
          playAction.userAnswer = {};
          playAction.listenModeStatus = false;
          playStatus.action = false;
          playStatus.answer = false;
          playStatus.gamut = false;
          data.realKey = 0;
        } else {
          playAction.userAnswerStatus = 0;
          playAction.userAnswer = {};
        }
      }, timer);
    };

    /** 滚轮缩放 */

    const handleWheel = (e: WheelEvent) => {
      e.preventDefault();
      if (e.deltaY > 0) {
        data.transform.scale -= 0.1;
        if (data.transform.scale <= 0.5) {
          data.transform.scale = 0.5;
        }
      } else {
        data.transform.scale += 0.1;
        if (data.transform.scale >= 2) {
          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);
      document.addEventListener("keydown", (e: KeyboardEvent) => {
        if (e.code === "Tab") {
          e.stopPropagation();
          e.preventDefault();
          // onStartPlayState();
          // 判断是否在应用中
          window.parent.postMessage(
            {
              api: "documentBodyKeyup",
              code: "Tab",
            },
            "*"
          );
        }
      });
    });

    onUnmounted(() => {
      window.removeEventListener("message", changePlay);
      window.removeEventListener("resize", onResize);
      const fingeringContainer = document.getElementById("fingeringContainer");
      fingeringContainer?.removeEventListener("wheel", handleWheel);
      document.title = "Ai学练";
    });

    const containerBox = computed(() => {
      if (state.platform === IPlatform.PC || query.modelType) {
        return {
          paddingTop: "1.3rem",
          paddingBottom: "",
        };
      }
      if (data.fingeringMode === "scaleMode") {
        if (data.subject === "hulusi-flute") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: ".5rem",
          };
        } else if (data.subject === "piccolo" || data.subject === "baroque-recorder") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: ".5rem",
          };
        } else if (data.subject === "pan-flute") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: "0",
          };
        } else if (data.subject === "ocarina" || data.subject === "whistling") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: "0",
          };
        } else if (data.subject === "melodica") {
          return {
            paddingTop: "1.8rem",
            paddingBottom: "0.2rem",
          };
        } else {
          return {
            paddingTop: "",
            paddingBottom: "",
          };
        }
      } else {
        if (data.subject === "hulusi-flute") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: "0rem",
          };
        } else if (data.subject === "piccolo" || data.subject === "baroque-recorder") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: ".5rem",
          };
        } else if (data.subject === "pan-flute") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: "0",
          };
        } else if (data.subject === "ocarina" || data.subject === "whistling") {
          return {
            paddingTop: "1.3rem",
            paddingBottom: "0",
          };
        } else if (data.subject === "melodica") {
          return {
            paddingTop: "1.8rem",
            paddingBottom: "0.2rem",
          };
        } else {
          return {
            paddingTop: "",
            paddingBottom: "",
          };
        }
      }
    });

    const listenText = computed(() => {
      if (data.fingeringMode === "fingeringMode") {
        if (playStatus.action) {
          return "换一换";
        } else {
          return "开始练习";
        }
      } else if (data.fingeringMode === "listenMode") {
        if (playStatus.action) {
          return "再听一遍";
        } else {
          return "开始听音";
        }
      }
      return "开始听音";
    });

    const modeText = computed(() => {
      let text = "";
      let icon = icons.icon_mode;
      data.fingeringModeList.forEach((item: any) => {
        if (item.value === data.fingeringMode) {
          text = item.text;
          icon = item.icon;
        }
      });
      return {
        text,
        icon,
      };
    });

    // 屏幕方向 0 竖，1 横
    const orientationDirection = computed(() => {
      return ["hulusi-flute", "piccolo", "baroque-recorder"].includes(data.subject) ? 1 : 0;
    });

    const resultImg = (note: any) => {
      if (data.realKey === note.realKey && !playStatus.action) {
        return {
          icon: icons.icon_btn_ylow,
          status: false,
        };
      } else if (playAction.exampleAnser.realKey === note.realKey) {
        return {
          icon: icons.icon_btn_ylow,
          status: false,
        };
      } else if (playAction.standardAnswer.realKey === note.realKey) {
        // 没有开始答题
        if (!playStatus.action) {
          return {
            icon: icons.icon_btn_ylow,
            status: false,
          };
        }
        // 显示答案中
        if (playAction.showAnswerLoading) {
          return {
            icon: icons.icon_btn_green,
            status: true,
          };
        }
        // 用户答对
        if (playAction.userAnswerStatus === 1) {
          return {
            icon: icons.icon_btn_green,
            status: true,
          };
        }
      } else {
        // 用户答错
        if (playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey) {
          return {
            icon: icons.icon_btn_red,
            status: true,
          };
        }
      }
      return {
        icon: icons.icon_btn_blue,
        status: true,
      };
    };
    const userTabActive = ref<"1" | "2">("1");
    const userTabs = [
      {
        name: "音阶",
        value: "1",
      },
      {
        name: "功能",
        value: "2",
      },
    ];
    // 引导页
    const { guidanceShow, setGuidanceShow } = useDragGuidance();
    // 切换乐器弹窗
    let changeSubjectShowBoxDragData: any;
    let changeSubjectShowBoxClass: string;
    if (query.platform === "pc") {
      changeSubjectShowBoxClass = "changeSubjectShowBoxClass_drag";
      changeSubjectShowBoxDragData = useDrag([`${changeSubjectShowBoxClass} .dragTopBox`, `${changeSubjectShowBoxClass} .dragbomBox`], changeSubjectShowBoxClass, toRef(data, "changeSubjectShow"), storeData.user.id as string);
    }
    // 移调弹窗
    let tnoteShowBoxDragData: any;
    let tnoteShowBoxClass: string;
    if (query.platform === "pc") {
      tnoteShowBoxClass = "tnoteShowBoxClass_drag";
      tnoteShowBoxDragData = useDrag([`${tnoteShowBoxClass} .dragTopBox`, `${tnoteShowBoxClass} .dragbomBox`], tnoteShowBoxClass, toRef(data, "tnoteShow"), storeData.user.id as string);
    }
    return () => {
      const relationship = fingerData.subject?.relationship?.[data.realKey] || [];
      const rs: number[] = Array.isArray(relationship[1]) ? relationship[fingerData.relationshipIndex] : relationship;
      const canTizhi = Array.isArray(relationship[1]);
      return (
        <div
          class={[styles.fingerBox, state.platform !== IPlatform.PC && !query.modelType && fingerData.fingeringInfo.orientation === 1 ? styles.fingerBottom : styles.fingerRight, data.linkSource === "class" ? styles.linkSourceClass : ""]}
          onClick={() => {
            if (data.linkSource === "class") {
              window.parent.postMessage(
                {
                  api: "clickViewFigner",
                },
                "*"
              );
            }
          }}
        >
          {/* 老师端过来隐藏 */}
          {query.platform !== "pc" && (
            <div
              class={styles.head}
              style={{
                paddingTop: data.paddingTop && !browser().ios ? data.paddingTop : "",
                paddingLeft: data.paddingLeft && !browser().ios ? data.paddingLeft : "",
              }}
            >
              <div class={styles.left}>
                <button class={[styles.backBtn]} onClick={() => handleBack()}>
                  <img src={icons.icon_back} />
                </button>

                <div
                  class={[styles.baseBtn, styles.changeInstrumentBtn]}
                  onClick={(e) => {
                    e.stopPropagation();
                    //
                    // 播放音阶时不能切换
                    if (playStatus.gamut) {
                      return;
                    }
                    // 开始答题不能切换
                    if (playAction.listenLock) {
                      return;
                    }

                    data.changeSubjectShow = true;
                  }}
                >
                  <img src={icons.icon_change_instrument} />
                  <span>切换乐器</span>
                </div>
                <div class={styles.baseBtn} onClick={onChangeFingeringModel}>
                  <img src={modeText.value.icon} />
                  <span>{modeText.value.text}</span>
                </div>
                {/*  */}
              </div>
              {/*  */}
            </div>
          )}
          <div
            class={styles.fingerContent}
            style={{
              paddingTop: data.paddingTop ? data.paddingTop : "",
              paddingLeft: data.paddingLeft ? data.paddingLeft : "",
            }}
          >
            <div class={styles.wrapFinger}>
              <div
                id="fingeringContainer"
                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,
                }}
              >
                <div
                  style={{
                    transform: `translate3d(${data.transform.x}px,${data.transform.y}px,0px) scale(${data.transform.scale})`,
                    transition: data.transform.transition,
                  }}
                  class={[styles.fingeringContainer]}
                >
                  <div class={styles.imgs}>
                    {!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 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, data.domOverlapping && data.notePoints?.length > 0 && styles.usrTabOverlaping]} id="fullInstrumentUserTab">
                  <Tabs v-model:active={userTabActive.value} class={styles.userTabBox}>
                    {userTabs.map((item) => {
                      return (
                        <Tab title={item.name} name={item.value}>
                          {item.value === "1" ? (
                            <>
                              <div
                                class={styles.notes}
                                style={{
                                  paddingLeft: data.paddingLeft ? data.paddingLeft : "",
                                }}
                              >
                                {playAction.listenTipsStatus && <div class={[styles.tipsT, data.fingeringMode === "fingeringMode" ? styles.playTips2 : styles.playTips]}></div>}
                                {playAction.userAnswerStatus === 1 && <div class={[styles.tipsT, styles.playSuccess]}></div>}
                                {playAction.userAnswerStatus === 2 && <div class={[styles.tipsT, styles.playError]}></div>}
                                {playAction.resetAction && <div class={[styles.tipsT, styles.playTips5]}></div>}
                                <div class={[styles.backBtn, styles.changeMusBtn]} onClick={() => handleBack()}>
                                  <span>返回</span>
                                </div>
                                <div class={styles.changeMusBtn} onClick={onChangeFingeringModel}>
                                  <span>{modeText.value.text}</span>
                                </div>
                                <div
                                  class={[styles.noteContent, data.fingeringMode !== "scaleMode" && orientationDirection.value === 0 && styles.noteContentOther, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad]}
                                  onClick={(e: any) => {
                                    e.stopPropagation();
                                  }}
                                >
                                  {((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && (
                                    <Button
                                      class={styles.noteBtn}
                                      onClick={(e: any) => {
                                        e.stopPropagation();
                                        scrollNoteBox("left");
                                      }}
                                    >
                                      <Icon name="arrow-left" />
                                    </Button>
                                  )}
                                  {/* 判断是否为音阶模式 */}
                                  {data.fingeringMode !== "scaleMode" && (
                                    <div draggable={false} class={styles.note} onClick={noteChangeShow}>
                                      <img draggable={false} src={data.noteType === "all" ? icons.icon_btn_orange : icons.icon_btn_orange2} />
                                    </div>
                                  )}
                                  {!!data.tones.length && data.fingeringMode === "scaleMode" && (
                                    <>
                                      {fingerData.fingeringInfo.name == "hulusi-flute" ? (
                                        <div id="finger-note-1" class={[styles.note, styles.btnGrToggleBtn]} onClick={() => (data.tnoteShow = true)}>
                                          <img draggable={false} src={noteImg} />
                                          <div class={styles.nameBox}>
                                            <div class={styles.name}>全按作</div>
                                            <div class={[styles.noteKey, styles.noteKeyBtn]}>
                                              {data.activeTone.step > 0 ? <span class={styles.dot}></span> : null}
                                              <div class={styles.noteName}>
                                                <sup>{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")}</sup>
                                                {data.activeTone.key}
                                              </div>
                                              {data.activeTone.step < 0 ? <span class={[styles.dot, styles.botDot]}></span> : null}
                                            </div>
                                          </div>
                                        </div>
                                      ) : (
                                        <div id="finger-note-1" class={[styles.note, styles.btnGrToggleBtn]} onClick={() => (data.tnoteShow = true)}>
                                          <img draggable={false} src={noteImg} />
                                          <div>
                                            <div class={styles.name}>
                                              <div>
                                                <sup>{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")}</sup>
                                                {data.activeTone.name}
                                              </div>
                                              调
                                            </div>
                                          </div>
                                        </div>
                                      )}
                                    </>
                                  )}
                                  {/* [styles.noteContent, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad] */}
                                  <div class={styles.lastNoteContent}>
                                    <div ref={noteBoxRef} class={styles.noteBox}>
                                      {data.notes.map((note: IFIGNER_INSTRUMENT_Note, index: number) => {
                                        const steps = new Array(Math.abs(note.step)).fill(1);
                                        return (
                                          <div
                                            id={index == 0 ? "finger-note-0" : ""}
                                            draggable={false}
                                            class={[styles.note, "note-class"]}
                                            key={note.realKey}
                                            // 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} />

                                            {playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey)) ? <span class={styles.showAnswer}></span> : ""}
                                            {playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey ? <span class={[styles.showAnswer, styles.errorAnswer]}></span> : ""}
                                            <div
                                              class={[
                                                styles.noteKey,
                                                ((data.realKey === note.realKey && !playStatus.action) ||
                                                  (playStatus.action && playAction.exampleAnser.realKey === note.realKey) ||
                                                  (playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey))) ||
                                                  (playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey)) &&
                                                  styles.keyActive,
                                              ]}
                                            >
                                              {/* 显示对应的点 */}
                                              {note.step > 0 ? steps.map((n: any) => <span class={styles.dot}></span>) : null}

                                              <div class={styles.noteName}>
                                                <sup>{note.mark && (note.mark === "rise" ? "#" : "b")}</sup>
                                                {note.key}
                                              </div>
                                              {/* 显示对应的点 */}
                                              {note.step < 0 ? steps.map((n: any) => <span class={styles.dot}></span>) : null}
                                            </div>
                                          </div>
                                        );
                                      })}
                                    </div>
                                  </div>
                                  {((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && (
                                    <Button
                                      class={styles.noteBtn}
                                      onClick={(e: any) => {
                                        e.stopPropagation();
                                        scrollNoteBox("right");
                                      }}
                                    >
                                      <Icon name="arrow" />
                                    </Button>
                                  )}
                                </div>
                              </div>
                              {data.fingeringMode !== "scaleMode" && (
                                <div
                                  class={styles.optionBtns}
                                  onClick={(e: any) => {
                                    e.stopPropagation();
                                  }}
                                >
                                  <Button class={[styles.oBtn, styles.gamut, playStatus.action && styles.disabled]} round onClick={onGamutPlayOrPause}>
                                    {playStatus.gamut ? "暂停" : "播放音阶"}
                                  </Button>
                                  <Button class={[styles.oBtn, styles.play, playStatus.gamut && styles.disabled]} round onClick={onActionPlay}>
                                    {listenText.value}
                                  </Button>
                                  <Button class={[styles.oBtn, styles.success, !playStatus.answer && styles.disabled]} round onClick={onShowAnswer}>
                                    显示答案
                                  </Button>
                                </div>
                              )}
                            </>
                          ) : (
                            <>
                              <div class={styles.btnBox}>
                                <div class={styles.btnCon}>
                                  <div
                                    class={[styles.btnGr]}
                                    onClick={(e) => {
                                      e.stopPropagation();
                                      //
                                      // 播放音阶时不能切换
                                      if (playStatus.gamut) {
                                        return;
                                      }
                                      // 开始答题不能切换
                                      if (playAction.listenLock) {
                                        return;
                                      }

                                      data.changeSubjectShow = true;
                                    }}
                                  >
                                    <img src={icons.icon_change_instrument} />
                                    <span>切换乐器</span>
                                  </div>
                                  {data.subject !== "melodica" && data.fingeringMode === "scaleMode" && (
                                    <div
                                      class={styles.btnGr}
                                      onClick={() => {
                                        data.viewIndex++;
                                        if (data.viewIndex > data.viewTotal) {
                                          if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) {
                                            data.viewIndex = 1;
                                          } else {
                                            data.viewIndex = 0;
                                          }
                                        }

                                        getFingeringData();
                                      }}
                                    >
                                      <img src={icons.icon_toggle} />
                                      <span>视图</span>
                                    </div>
                                  )}
                                  <div
                                    class={styles.btnGr}
                                    onClick={() => {
                                      resetElement();
                                      data.tipShow = !data.tipShow;
                                      onResize();
                                    }}
                                  >
                                    <img src={icons.icon_2_1} />
                                    <span>说明</span>
                                  </div>
                                  {instrumentTranstion.value && (
                                    <div class={[styles.btnGr]} onClick={() => resetElement()}>
                                      <img src={icons.icon_2_0} />
                                      <span>还原</span>
                                    </div>
                                  )}
                                </div>
                              </div>
                            </>
                          )}
                        </Tab>
                      );
                    })}
                  </Tabs>
                </div>
              ) : (
                <div class={[data.domOverlapping && data.notePoints?.length > 0 && styles.usrTabOverlapingNotes]} id="fullInstrumentUserTab">
                  <div
                    class={[styles.notes]}
                    style={{
                      paddingLeft: data.paddingLeft ? data.paddingLeft : "",
                    }}
                  >
                    {playAction.listenTipsStatus && <div class={[styles.tipsT, data.fingeringMode === "fingeringMode" ? styles.playTips2 : styles.playTips]}></div>}
                    {playAction.userAnswerStatus === 1 && <div class={[styles.tipsT, styles.playSuccess]}></div>}
                    {playAction.userAnswerStatus === 2 && <div class={[styles.tipsT, styles.playError]}></div>}
                    {playAction.resetAction && <div class={[styles.tipsT, styles.playTips5]}></div>}
                    {((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && (
                      <Button
                        class={styles.noteBtn}
                        onClick={(e: any) => {
                          e.stopPropagation();
                          scrollNoteBox("left");
                        }}
                      >
                        <Icon name="arrow-left" />
                      </Button>
                    )}
                    <div
                      class={[styles.noteContent, data.fingeringMode !== "scaleMode" && orientationDirection.value === 0 && styles.noteContentOther, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad]}
                      onClick={(e: any) => {
                        e.stopPropagation();
                      }}
                    >
                      {/* 判断是否为音阶模式 */}
                      {data.fingeringMode !== "scaleMode" && (
                        <div draggable={false} class={styles.note} onClick={noteChangeShow}>
                          <img draggable={false} src={data.noteType === "all" ? icons.icon_btn_orange : icons.icon_btn_orange2} />
                        </div>
                      )}

                      {/* [styles.noteContent, browsInfo.ios ? "" : styles.noteContentWrap, data.huaweiPad && styles.huaweiPad] */}
                      <div class={styles.lastNoteContent}>
                        <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 (
                              <div
                                id={index == 0 ? "finger-note-0" : ""}
                                draggable={false}
                                class={[styles.note, "note-class"]}
                                key={note.realKey}
                                // 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} />

                                {playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey)) ? <span class={styles.showAnswer}></span> : ""}
                                {playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey ? <span class={[styles.showAnswer, styles.errorAnswer]}></span> : ""}
                                <div
                                  class={[
                                    styles.noteKey,
                                    ((data.realKey === note.realKey && !playStatus.action) ||
                                      (playStatus.action && playAction.exampleAnser.realKey === note.realKey) ||
                                      (playStatus.action && ((playAction.showAnswerLoading && playAction.standardAnswer.realKey === note.realKey) || (playAction.userAnswerStatus === 1 && playAction.userAnswer.realKey === note.realKey))) ||
                                      (playStatus.action && playAction.userAnswerStatus === 2 && playAction.userAnswer.realKey === note.realKey)) &&
                                      styles.keyActive,
                                  ]}
                                >
                                  {/* 显示对应的点 */}
                                  {note.step > 0 ? steps.map((n: any) => <span class={styles.dot}></span>) : null}

                                  <div class={styles.noteName}>
                                    <sup>{note.mark && (note.mark === "rise" ? "#" : "b")}</sup>
                                    {note.key}
                                  </div>
                                  {/* 显示对应的点 */}
                                  {note.step < 0 ? steps.map((n: any) => <span class={styles.dot}></span>) : null}
                                </div>
                              </div>
                            );
                          })}
                        </div>
                      </div>
                    </div>
                    {((data.noteType !== "#c" && (orientationDirection.value === 0 || (orientationDirection.value === 1 && state.platform === IPlatform.PC))) || (orientationDirection.value === 1 && state.platform === IPlatform.APP)) && (
                      <Button
                        class={styles.noteBtn}
                        onClick={(e: any) => {
                          e.stopPropagation();
                          scrollNoteBox("right");
                        }}
                      >
                        <Icon name="arrow" />
                      </Button>
                    )}
                  </div>
                  {data.fingeringMode !== "scaleMode" && (
                    <div
                      class={styles.optionBtns}
                      onClick={(e: any) => {
                        e.stopPropagation();
                      }}
                    >
                      <Button class={[styles.oBtn, styles.gamut, playStatus.action && styles.disabled]} round onClick={onGamutPlayOrPause}>
                        {playStatus.gamut ? "暂停" : "播放音阶"}
                      </Button>
                      <Button class={[styles.oBtn, styles.play, playStatus.gamut && styles.disabled]} round onClick={onActionPlay}>
                        {listenText.value}
                      </Button>
                      <Button class={[styles.oBtn, styles.success, !playStatus.answer && styles.disabled]} round onClick={onShowAnswer}>
                        显示答案
                      </Button>
                    </div>
                  )}
                </div>
              )}
            </div>
            {/* 老师端过来隐藏 */}
            {query.platform !== "pc" && (
              <div
                class={styles.fixedRightBtns}
                style={{
                  paddingTop: data.paddingTop ? data.paddingTop : "",
                  paddingLeft: data.paddingLeft ? data.paddingLeft : "",
                }}
                onClick={(e: any) => {
                  e.stopPropagation();
                }}
              >
                <div class={styles.rightBtn}>
                  {data.subject !== "melodica" && data.fingeringMode === "scaleMode" && (
                    <div
                      class={styles.baseBtn}
                      onClick={() => {
                        data.viewIndex++;
                        if (data.viewIndex > data.viewTotal) {
                          if (["pan-flute", "ocarina", "whistling"].includes(data.subject)) {
                            data.viewIndex = 1;
                          } else {
                            data.viewIndex = 0;
                          }
                        }
                        getFingeringData();
                      }}
                    >
                      <img src={icons.icon_toggle} />
                      <span>视图</span>
                    </div>
                  )}
                  <div
                    class={styles.baseBtn}
                    onClick={() => {
                      resetElement();
                      data.tipShow = !data.tipShow;
                      onResize();
                    }}
                  >
                    <img src={icons.icon_2_1} />
                    <span>说明</span>
                  </div>

                  {!!data.tones.length && data.fingeringMode === "scaleMode" && (
                    <>
                      {fingerData.fingeringInfo.name == "hulusi-flute" ? (
                        <div id="finger-note-1" class={[styles.baseBtn, styles.toggleBtnhulusi, styles.active]} onClick={() => (data.tnoteShow = true)}>
                          <div>
                            全按作
                            <div class={[styles.noteKey, styles.noteKeyBtn]}>
                              {data.activeTone.step > 0 ? <span class={[styles.topDot, styles.dot]}></span> : null}

                              <div class={styles.noteName}>
                                <sup>{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")}</sup>
                                {data.activeTone.key}
                              </div>
                              {data.activeTone.step < 0 ? <span class={[styles.bottomDot, styles.dot]}></span> : null}
                            </div>
                          </div>
                          <img src={icons.icon_arrow} />
                        </div>
                      ) : (
                        <div id="finger-note-1" class={[styles.baseBtn, styles.toggleBtnhulusi2, styles.active]} onClick={() => (data.tnoteShow = true)}>
                          <div class={styles.oterhD}>
                            <div>
                              <div style={{ marginTop: "-4px" }}>
                                <sup>{data.activeTone.mark && (data.activeTone.mark === "rise" ? "#" : "b")}</sup>
                                {data.activeTone.name}
                              </div>
                              调
                            </div>
                            <img src={icons.icon_arrow} />
                          </div>
                        </div>
                      )}
                    </>
                  )}
                </div>

                <div class={[styles.baseBtn, !instrumentTranstion.value && styles.resetBtn]} style={{ marginTop: "8px" }} onClick={() => resetElement()}>
                  <img src={icons.icon_2_0} />
                  <span>还原</span>
                </div>
              </div>
            )}
            {/* 老师端加上遮罩点击关闭 */}
            {query.platform === "pc" && data.tipShow && (
              <div
                class={[styles.tipsOverlay, data.tipShow ? styles.tipsOverlayBg : ""]}
                onClick={() => {
                  data.tipShow = false;
                }}
              ></div>
            )}
            <div class={[styles.tips, data.loadingDom ? styles.hiddens : "", data.tipShow ? "" : styles.tipHidden, query.platform === "pc" && data.tipShow ? styles.tipsPcBg : ""]}>
              <div class={styles.tipTitle}>
                <div class={styles.tipTitleName}>{fingerData.fingeringInfo.code}使用说明</div>
                <Button
                  class={styles.tipClose}
                  onClick={(e: any) => {
                    e.stopPropagation();
                    data.tipShow = false;
                  }}
                >
                  <Icon name="cross" size={19} color="#fff" />
                </Button>
              </div>
              <div class={styles.iconBook}></div>
              <div class={styles.tipContentbox}>
                <div class={styles.tipContent}>
                  {data.tips.map((tip, tipIndex) => (
                    <div class={styles.tipItem}>
                      <div class={styles.iconWrap}>
                        <div class={styles.tipItemIcon}>{tipIndex + 1}</div>
                      </div>
                      <div>
                        {tip.name}: {tip.realName}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            </div>
            {data.loadingSoundFonts && (
              <div class={styles.loading}>
                <div class={styles.loadingWrap}>
                  <img class={styles.loadingIcon} src={icon_loading_img} />
                  <Progress percentage={data.loadingSoundProgress} />
                  <div class={styles.loadingTip}>加载中，请稍后…</div>
                </div>
              </div>
            )}
          </div>

          <Popup
            class={["tonePopup", tnoteShowBoxClass]}
            style={query.platform === "pc" ? tnoteShowBoxDragData.styleDrag.value : {}}
            v-model:show={data.tnoteShow}
            position={state.platform === IPlatform.PC ? "center" : !query.modelType && fingerData.fingeringInfo.orientation === 1 ? "bottom" : "right"}
          >
            <div class={styles.tones}>
              <div class={[styles.toneTitle, "toneTitle_pc"]}>
                <div class={styles.tipTitleName}>移调</div>
                <Button
                  class={styles.tipClose}
                  onClick={(e: any) => {
                    e.stopPropagation();
                    data.tnoteShow = false;
                  }}
                >
                  <Icon name="cross" size={19} color="#fff" />
                </Button>
              </div>
              <div class={[styles.tipContentbox, "tipContentbox_pc"]}>
                <div class={[styles.tipContent, "tipContent_pc"]}>
                  <div class={[styles.tipWrap, "tipWrap_pc"]}>
                    <Space size={0} class={styles.toneContent}>
                      {data.tones.map((tone: IFIGNER_INSTRUMENT_Note) => {
                        const steps = new Array(Math.abs(tone.step)).fill(1);
                        return (
                          <Button
                            class={[fingerData.fingeringInfo.name == "hulusi-flute" && styles.hulusiBtn]}
                            round
                            plain
                            type={data.popupActiveTone.realName === tone.realName ? "primary" : "default"}
                            onClick={(e: any) => {
                              e.stopPropagation();
                              data.popupActiveTone = tone;
                              setNotes();
                            }}
                          >
                            {fingerData.fingeringInfo.name == "hulusi-flute" ? (
                              <div style={{ display: "flex", alignItems: "center" }}>
                                全按作
                                <div class={[styles.noteKey, styles.hulusiNoteKey]}>
                                  {tone.step > 0 ? <span class={styles.dot}></span> : null}
                                  <div class={styles.noteName} style={{ fontSize: "0.25rem" }}>
                                    <sup>{tone.mark && (tone.mark === "rise" ? "#" : "b")}</sup>
                                    {tone.key}
                                  </div>
                                  {tone.step < 0 ? <span class={styles.dot}></span> : null}
                                </div>
                              </div>
                            ) : (
                              <div class={styles.noteName}>
                                <sup>{tone.mark && (tone.mark === "rise" ? "#" : "b")}</sup>
                                {tone.name}
                              </div>
                            )}
                          </Button>
                        );
                      })}
                    </Space>
                  </div>
                  <div class={[styles.toneAction, "toneAction_pc"]}>
                    <img
                      onClick={(e: any) => {
                        e.stopPropagation();
                        data.tnoteShow = false;
                      }}
                      src={icons.icon_action_cancel}
                    />
                    <img
                      onClick={(e: any) => {
                        e.stopPropagation();
                        data.activeTone = data.popupActiveTone;
                        setNotes();
                        data.tnoteShow = false;
                      }}
                      src={icons.icon_action_confirm}
                    />
                  </div>
                </div>
              </div>
            </div>
            {query.platform === "pc" && (
              <>
                <div class={[styles.dragTopBox, "dragTopBox"]}></div>
                <Dragbom showGuide={guidanceShow.value} onGuideDone={setGuidanceShow}></Dragbom>
              </>
            )}
          </Popup>

          <Popup
            style={query.platform === "pc" ? changeSubjectShowBoxDragData.styleDrag.value : {}}
            v-model:show={data.changeSubjectShow}
            class={[styles.changeSubjectPopup, query.platform === "pc" && styles.changeSubjectPopupPc, changeSubjectShowBoxClass]}
            closeOnClickOverlay={query.platform === "pc" ? false : true}
            onClick={(e: any) => {
              e.stopPropagation();
            }}
          >
            <ChangeSubject
              changeSubjectShow={data.changeSubjectShow}
              subjectList={data.subjects}
              subject={data.subject}
              onClose={() => (data.changeSubjectShow = false)}
              onConfirm={(code: any) => {
                if (data.subject === code) {
                  data.changeSubjectShow = false;
                  return;
                }
                const originalSubject = JSON.parse(JSON.stringify(data.subject));
                data.subject = code;
                data.viewIndex = 0;
                data.tipShow = false;
                data.loadingDom = true;
                fingerData.fingeringInfo = subjectFingering(data.subject);
                data.activeTone = {} as any;
                data.noteType = "all";
                resetElement();
                resetMode(true, 0);
                // api_setRequestedOrientation(orientationDirection.value);

                data.changeSubjectShow = false;
                // 设置屏幕方向
                setTimeout(() => {
                  const before = ["hulusi-flute", "piccolo", "baroque-recorder"].includes(originalSubject) ? 0 : 0;
                  if (orientationDirection.value !== before) {
                    data.paddingTop = "";
                    data.paddingLeft = "";
                  }

                  __init();
                }, 100);
              }}
            />
            {query.platform === "pc" && (
              <>
                <div class={[styles.dragTopBox, "dragTopBox"]}></div>
                <Dragbom showGuide={guidanceShow.value} onGuideDone={setGuidanceShow}></Dragbom>
              </>
            )}
          </Popup>

          {props.show && !data.loading && !data.loadingSoundFonts && <GuideIndex fingeringMode={data.fingeringMode} showGuide={false} list={["finger"]} />}
        </div>
      );
    };
  },
});
