소스 검색

Merge branch 'iteration-0810' into online

liushengqiang 1 년 전
부모
커밋
64306eb71d

+ 5 - 10
package-lock.json

@@ -6789,8 +6789,7 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
       "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
-      "dev": true,
-      "requires": {}
+      "dev": true
     },
     "@octokit/plugin-rest-endpoint-methods": {
       "version": "7.1.2",
@@ -6948,8 +6947,7 @@
     "@vant/use": {
       "version": "1.5.1",
       "resolved": "https://registry.npmjs.org/@vant/use/-/use-1.5.1.tgz",
-      "integrity": "sha512-Zxd7lDz/LliVYEQi3PR9a8CQa/kGCVzF0u9hqDMaTlgXlbG0wHMFPllrcG0ThR6bfs8xrYVuSFM9pJn6HSoUGQ==",
-      "requires": {}
+      "integrity": "sha512-Zxd7lDz/LliVYEQi3PR9a8CQa/kGCVzF0u9hqDMaTlgXlbG0wHMFPllrcG0ThR6bfs8xrYVuSFM9pJn6HSoUGQ=="
     },
     "@varlet/icons": {
       "version": "2.9.5",
@@ -7012,8 +7010,7 @@
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.1.0.tgz",
       "integrity": "sha512-++9JOAFdcXI3lyer9UKUV4rfoQ3T1RN8yDqoCLar86s0xQct5yblxAE+yWgRnU5/0FOlVCpTZpYSBV/bGWrSrQ==",
-      "dev": true,
-      "requires": {}
+      "dev": true
     },
     "@vitejs/plugin-vue-jsx": {
       "version": "3.0.1",
@@ -8433,8 +8430,7 @@
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/postcss-pxtorem/-/postcss-pxtorem-6.0.0.tgz",
       "integrity": "sha512-ZRXrD7MLLjLk2RNGV6UA4f5Y7gy+a/j1EqjAfp9NdcNYVjUMvg5HTYduTjSkKBkRkfqbg/iKrjMO70V4g1LZeg==",
-      "dev": true,
-      "requires": {}
+      "dev": true
     },
     "proxy-from-env": {
       "version": "1.1.0",
@@ -9098,8 +9094,7 @@
     "ws": {
       "version": "8.13.0",
       "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
-      "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
-      "requires": {}
+      "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA=="
     },
     "yallist": {
       "version": "3.1.1",

+ 96 - 63
src/page-instrument/App.tsx

@@ -1,4 +1,4 @@
-import { computed, defineComponent, onBeforeMount, onMounted } from "vue";
+import { computed, defineComponent, onBeforeMount, onMounted, onUnmounted } from "vue";
 import { RouterView } from "vue-router";
 import TheError from "../components/The-error";
 import { setUserInfo, storeData } from "../store";
@@ -9,67 +9,100 @@ import { api_cloudLoading, api_getToken } from "../helpers/communication";
 import { showToast } from "vant";
 
 export default defineComponent({
-	name: "App",
-	setup() {
-		const query: any = getQuery();
-		/** 获取用户信息 */
-		const getUserInfo = async () => {
-			return await studentQueryUserInfo();
-		};
-		const setUser = async () => {
-			try {
-				const res = await getUserInfo();
-				if (res?.code === 5000) {
-					const browserInfo = browser();
-					showToast(res.message);
-					if (browserInfo.isApp) {
-						postMessage({ api: "login" });
-					} else {
-						if (/(192|localhost)/.test(location.origin)) {
-							return;
-						}
-						window.location.href = `${location.origin}/classroom`;
-					}
-					return;
-				}
-				const student = res?.data || {};
-				setUserInfo(student);
-				storeData.platformType = student.clientType === "STUDENT" ? "STUDENT" : "";
-			} catch (error) {
-				storeData.status = "error";
-				api_cloudLoading();
-				console.log("🚀 ~ error:", error);
-			}
-		};
-		onBeforeMount(async () => {
-			if (query.Authorization) {
-				setToken(query.Authorization);
-			}
-			if (!getToken()) {
-				const res = await api_getToken();
-				if (res?.content) {
-					const content = res.content;
-					const token = content.tokenType + " " + content.accessToken;
-					setToken(token);
-				}
-			}
-			if (query.productXmlImg) {
-				storeData.status = "login";
-				return;
-			}
-			setUser();
-			setBehaviorId(getRandomKey());
-		});
-		onMounted(() => {
-			const _loading = document.getElementById("loading");
-			_loading && document.body.removeChild(_loading);
-		});
+  name: "App",
+  setup() {
+    const query: any = getQuery();
+    /** 获取用户信息 */
+    const getUserInfo = async () => {
+      return await studentQueryUserInfo();
+    };
+    const setUser = async () => {
+      try {
+        const res = await getUserInfo();
+        if (res?.code === 5000) {
+          const browserInfo = browser();
+          showToast(res.message);
+          if (browserInfo.isApp) {
+            postMessage({ api: "login" });
+          } else {
+            if (/(192|localhost)/.test(location.origin)) {
+              return;
+            }
+            // 判断是否在应用中
+            window.parent.postMessage(
+              {
+                api: "onLogin",
+              },
+              "*"
+            );
+            setTimeout(() => {
+              window.location.href = `${location.origin}/classroom`
+            }, 500)
+          }
+          return;
+        }
+        const student = res?.data || {};
+        setUserInfo(student);
+        storeData.platformType = student.clientType === "STUDENT" ? "STUDENT" : "";
+      } catch (error) {
+        storeData.status = "error";
+        api_cloudLoading();
+        console.log("🚀 ~ error:", error);
+      }
+    };
+    onBeforeMount(async () => {
+      if (query.Authorization) {
+        setToken(query.Authorization);
+      }
+      if (!getToken()) {
+        const res = await api_getToken();
+        if (res?.content) {
+          const content = res.content;
+          const token = content.tokenType + " " + content.accessToken;
+          setToken(token);
+        }
+      }
+      if (query.productXmlImg) {
+        storeData.status = "login";
+        return;
+      }
+      setUser();
+      setBehaviorId(getRandomKey());
+    });
 
-		const inited = computed(() => {
-			return storeData.status === "login";
-		});
-		return () => (
-			<>{storeData.status === "error" ? <TheError /> : inited.value ? <RouterView /> : null}</>
-		);
-	},
+    const onKeyBoard = (e: KeyboardEvent) => {
+      if (e.code === "ArrowLeft") {
+        window.parent.postMessage(
+          {
+            api: "documentBodyKeyup",
+            code: "ArrowLeft",
+          },
+          "*"
+        );
+      } else if (e.code === "ArrowRight") {
+        window.parent.postMessage(
+          {
+            api: "documentBodyKeyup",
+            code: "ArrowRight",
+          },
+          "*"
+        );
+      }
+    };
+    onMounted(() => {
+      const _loading = document.getElementById("loading");
+      _loading && document.body.removeChild(_loading);
+      // console.log(query);
+      if (query.platform == "pc") document.body.addEventListener("keyup", (e: KeyboardEvent) => onKeyBoard(e));
+    });
+
+    onUnmounted(() => {
+      if (query.platform == "pc") document.body.removeEventListener("keyup", onKeyBoard);
+    });
+
+    const inited = computed(() => {
+      return storeData.status === "login";
+    });
+    return () => <>{storeData.status === "error" ? <TheError /> : inited.value ? <RouterView /> : null}</>;
+  },
 });

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

@@ -9,6 +9,16 @@
     padding-bottom: 0;
     transform: translateY(-100%);
     animation: headerDown .3s .5s ease-in-out forwards;
+
+    &.headRightTop {
+        transition: margin-top .2s ease;
+        margin-top: 0;
+    }
+
+    &.headRightTopHide {
+        transition: margin-top .2s ease;
+        margin-top: 12px;
+    }
 }
 
 @keyframes headerDown {
@@ -23,21 +33,26 @@
     height: 100%;
     padding: 0 11px 0 6px;
     cursor: pointer;
+
     img {
         display: block;
         width: 24px;
         height: 24px;
     }
 }
-.hidenBack{
+
+.hidenBack {
     opacity: 0;
     pointer-events: none;
 }
+
 .headRight {
     display: flex;
     align-items: flex-end;
     margin-left: auto;
     height: 100%;
+
+
 }
 
 .btn {
@@ -53,6 +68,7 @@
     border-radius: 4px;
     color: #999;
     cursor: pointer;
+
     .iconBtn {
         display: block;
         width: 25px;
@@ -80,6 +96,7 @@
     }
 
 }
+
 .disabled {
     pointer-events: none;
     opacity: .5;
@@ -102,6 +119,7 @@
     position: fixed;
     right: 32px;
     bottom: 32px;
+    transition: bottom .2s ease;
 
     .btnWrap {
         width: 36px;
@@ -113,26 +131,41 @@
             height: 100%;
         }
     }
-    &.playButton{
+
+    &.playButton {
         left: 32px !important;
         right: auto !important;
+        bottom: 12px !important;
+    }
+
+    &.playButtonHide {
+        transition: bottom .2s ease;
+        bottom: 60px !important;
     }
-    
+
 }
 
 .resetBtn {
     position: fixed;
     right: 88px;
     bottom: 32px;
+    transition: bottom .2s ease;
 
     .iconBtn {
         display: block;
         width: 36px;
         height: 36px;
     }
-    &.pauseButton{
+
+    &.pauseButton {
         left: 88px !important;
         right: auto !important;
+        bottom: 12px !important;
+    }
+
+    &.playButtonHide {
+        transition: bottom .2s ease;
+        bottom: 60px !important;
     }
 }
 

+ 411 - 508
src/page-instrument/header-top/index.tsx

@@ -1,13 +1,4 @@
-import {
-	Transition,
-	computed,
-	defineComponent,
-	onMounted,
-	onUnmounted,
-	reactive,
-	ref,
-	watch,
-} from "vue";
+import { Transition, computed, defineComponent, onMounted, onUnmounted, reactive, ref, watch } from "vue";
 import styles from "./index.module.less";
 
 import iconBack from "./image/icon-back.svg";
@@ -17,13 +8,7 @@ import { Badge, Circle, Popover, Popup, showConfirmDialog } from "vant";
 import Speed from "./speed";
 import { evaluatingData, handleStartEvaluat } from "/src/view/evaluating";
 import Settting from "./settting";
-import state, {
-	IPlatform,
-	handleChangeSection,
-	handleResetPlay,
-	handleRessetState,
-	togglePlay,
-} from "/src/state";
+import state, { IPlatform, handleChangeSection, handleResetPlay, handleRessetState, togglePlay } from "/src/state";
 import { getAudioCurrentTime } from "/src/view/audio-list";
 import { followData, toggleFollow } from "/src/view/follow-practice";
 import { api_back } from "/src/helpers/communication";
@@ -40,501 +25,419 @@ import "../component/the-modal-tip/index.module.less";
 
 /** 头部数据和方法 */
 export const headTopData = reactive({
-	/** 模式 */
-	modeType: "" as "init" | "show",
-	/** 显示返回按钮 */
-	showBack: true,
-	/** 设置弹窗 */
-	settingMode: false,
-	/** 切换模式 */
-	handleChangeModeType(value: "practise" | "follow" | "evaluating") {
-		if (value === "evaluating") {
-			// 如果是pc端, 评测模式暂不可用
-			if (state.platform === IPlatform.PC) {
-				showConfirmDialog({
-					className: "modalTip",
-					title: "温馨提示",
-					message: "该功能暂未开放,敬请期待!",
-					showCancelButton: false,
-				});
-				return;
-			}
-			handleStartEvaluat();
-		} else if (value === "follow") {
-			toggleFollow();
-		}
-		headTopData.modeType = "show";
-	},
+  /** 模式 */
+  modeType: "" as "init" | "show",
+  /** 显示返回按钮 */
+  showBack: true,
+  /** 设置弹窗 */
+  settingMode: false,
+  /** 切换模式 */
+  handleChangeModeType(value: "practise" | "follow" | "evaluating") {
+    if (value === "evaluating") {
+      // 如果是pc端, 评测模式暂不可用
+      if (state.platform === IPlatform.PC) {
+        showConfirmDialog({
+          className: "modalTip",
+          title: "温馨提示",
+          message: "该功能暂未开放,敬请期待!",
+          showCancelButton: false,
+        });
+        return;
+      }
+      handleStartEvaluat();
+    } else if (value === "follow") {
+      toggleFollow();
+    }
+    headTopData.modeType = "show";
+  },
 });
 
 export const headData = reactive({
-	speedShow: false,
-	musicTypeShow: false,
+  speedShow: false,
+  musicTypeShow: false,
 });
 
 export default defineComponent({
-	name: "header-top",
-	emits: ["close"],
-	setup(props, { emit }) {
-		const query = getQuery();
-		// 是否显示引导
-		const showGuide = ref(false);
-		const showStudentGuide = ref(false);
-		/** 设置按钮 */
-		const settingBtn = computed(() => {
-			// 音频播放中 禁用
-			if (state.playState === "play") return { display: true, disabled: true };
-			// 评测开始 禁用, 跟练开始 禁用
-			if (evaluatingData.startBegin || followData.start) return { display: true, disabled: true };
-
-			return {
-				display: true,
-				disabled: false,
-			};
-		});
-
-		/** 转谱按钮 */
-		const converBtn = computed(() => {
-			// 音频播放中 禁用
-			if (state.playState === "play") return { display: true, disabled: true };
-			// 评测开始 禁用
-			if (evaluatingData.startBegin || followData.start) return { display: true, disabled: true };
-
-			return {
-				disabled: false,
-				display: true,
-			};
-		});
-
-		/** 速度按钮 */
-		const speedBtn = computed(() => {
-			// 选择模式, 跟练模式  不显示
-			if (headTopData.modeType !== "show" || state.modeType === "follow")
-				return { display: false, disabled: true };
-			// 评测模式, 音频播放中 禁用
-			if (state.modeType === "evaluating" || state.playState === "play")
-				return { display: true, disabled: true };
-
-			return {
-				disabled: false,
-				display: true,
-			};
-		});
-
-		/** 指法按钮 */
-		const fingeringBtn = computed(() => {
-			// 没有指法 选择模式 评测模式 跟练模式 不显示
-			if (
-				headTopData.modeType !== "show" ||
-				!state.fingeringInfo.name ||
-				["evaluating", "follow"].includes(state.modeType)
-			)
-				return { display: false, disabled: true };
-			// 音频播放中 禁用
-			if (state.playState === "play") return { display: true, disabled: true };
-
-			return {
-				disabled: false,
-				display: true,
-			};
-		});
-
-		/** 摄像头按钮 */
-		const cameraBtn = computed(() => {
-			// 选择模式 不显示
-			if (headTopData.modeType !== "show" || state.modeType !== "evaluating")
-				return { display: false, disabled: true };
-			// 音频播放中 禁用
-			if (state.playState === "play") return { display: true, disabled: true };
-
-			return {
-				disabled: false,
-				display: true,
-			};
-		});
-
-		/** 选段按钮 */
-		const selectBtn = computed(() => {
-			// 选择模式 不显示
-			if (headTopData.modeType !== "show" || ["evaluating", "follow"].includes(state.modeType))
-				return { display: false, disabled: true };
-			// 音频播放中 禁用
-			if (state.playState === "play") return { display: true, disabled: true };
-
-			return {
-				disabled: false,
-				display: true,
-			};
-		});
-
-		/** 原声按钮 */
-		const originBtn = computed(() => {
-			// 选择模式,跟练模式 不显示
-			if (headTopData.modeType !== "show" || state.modeType === "follow")
-				return { display: false, disabled: false };
-			// 评测开始 禁用
-			if (state.modeType === "evaluating") return { display: false, disabled: true };
-			// 原声, 伴奏 少一个,就不能切换
-			if (!state.music || !state.accompany) return { display: true, disabled: true };
-
-			return {
-				disabled: false,
-				display: true,
-			};
-		});
-
-		/** 模式切换按钮 */
-		const toggleBtn = computed(() => {
-			// 选择模式, url设置模式 不显示
-			if (headTopData.modeType !== "show" || !headTopData.showBack)
-				return { display: false, disabled: false };
-			// 跟练开始, 评测开始 禁用
-			if (followData.start || evaluatingData.startBegin) return { display: true, disabled: true };
-
-			return {
-				display: true,
-				disabled: false,
-			};
-		});
-
-		/** 播放按钮 */
-		const playBtn = computed(() => {
-			// 选择模式 不显示
-			if (headTopData.modeType !== "show") return { display: false, disabled: false };
-			// 评测模式 不显示,跟练模式 不显示
-			if (["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
-
-			return {
-				display: true,
-				disabled: false,
-			};
-		});
-
-		/** 重播按钮 */
-		const resetBtn = computed(() => {
-			// 选择模式 不显示
-			if (headTopData.modeType !== "show") return { display: false, disabled: false };
-			// 评测模式 不显示,跟练模式 不显示
-			if (["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
-			// 播放状态 不显示
-			if (state.playState === "play") return { display: false, disabled: true };
-			// 播放进度为0 不显示
-			const currentTime = getAudioCurrentTime();
-			if (!currentTime) return { display: false, disabled: true };
-
-			return {
-				display: true,
-				disabled: false,
-			};
-		});
-
-		const isAllBtns = computed(() => {
-			const flag =
-				converBtn.value.display &&
-				speedBtn.value.display &&
-				selectBtn.value.display &&
-				originBtn.value.display &&
-				toggleBtn.value.display &&
-				showGuide.value;
-			return flag;
-		});
-
-		const isAllBtnsStudent = computed(() => {
-			const flag =
-				converBtn.value.display &&
-				speedBtn.value.display &&
-				selectBtn.value.display &&
-				originBtn.value.display &&
-				toggleBtn.value.display &&
-				showStudentGuide.value;
-
-			return flag;
-		});
-		const browInfo = browser();
-		/** 返回 */
-		const handleBack = () => {
-			HANDLE_WORK_ADD();
-			// 不在APP中,
-			if (!storeData.isApp) {
-				window.close();
-				return;
-			}
-			if ((browInfo.iPhone || browInfo.ios) && query.workRecord) {
-				setTimeout(() => {
-					api_back();
-				}, 550);
-				return;
-			}
-			api_back();
-		};
-
-		/** 根据参数设置模式 */
-		const getQueryModelSetModelType = () => {
-			/** 作业模式 start, 如果为作业模式不处理,让作业模块处理 */
-			if (query.workRecord) {
-				return;
-			}
-			/** 作业模式 end */
-			if (query.modelType) {
-				if (query.modelType === "practise") {
-					headTopData.handleChangeModeType("practise");
-				} else if (query.modelType === "evaluating") {
-					headTopData.handleChangeModeType("evaluating");
-				}
-				headTopData.showBack = false;
-			} else {
-				setTimeout(() => {
-					headTopData.modeType = "init";
-				}, 500);
-			}
-		};
-
-		/** 课件播放 */
-		const changePlay = (res: any) => {
-			if (res?.data?.api === "setPlayState") {
-				togglePlay("paused");
-			}
-		};
-
-		onMounted(() => {
-			getQueryModelSetModelType();
-			window.addEventListener("message", changePlay);
-			if (state.platform === IPlatform.PC) {
-				showGuide.value = true;
-			} else {
-				showStudentGuide.value = true;
-			}
-		});
-
-		onUnmounted(() => {
-			window.removeEventListener("message", changePlay);
-		});
-
-		// 设置改变触发
-		watch(state.setting, () => {
-			console.log(state.setting, "state.setting");
-			store.set("musicscoresetting", state.setting);
-		});
-
-		return () => (
-			<>
-				<div class={[styles.headerTop]}>
-					<div
-						class={[styles.back, "headTopBackBtn", !headTopData.showBack && styles.hidenBack]}
-						onClick={handleBack}
-					>
-						<img src={iconBack} />
-					</div>
-					{query.iscurseplay === "play" ? null : (
-						<Title class="pcTitle" text={state.examSongName} rightView={false} />
-					)}
-
-					<div class={styles.headRight}>
-						<div
-							id={state.platform === IPlatform.PC ? "teacherTop-0" : "studnetT-0"}
-							style={{ display: toggleBtn.value.display ? "" : "none" }}
-							class={[styles.btn, toggleBtn.value.disabled && styles.disabled]}
-							onClick={() => {
-								handleRessetState();
-								headTopData.modeType = "init";
-							}}
-						>
-							<img class={styles.iconBtn} src={headImg(`modeType.svg`)} />
-							<span>模式</span>
-						</div>
-
-						<div
-							id={state.platform === IPlatform.PC ? "teacherTop-1" : "studnetT-1"}
-							style={{ display: originBtn.value.display ? "" : "none" }}
-							class={[styles.btn, originBtn.value.disabled && styles.disabled]}
-							onClick={() => {
-								state.playSource = state.playSource === "music" ? "background" : "music";
-							}}
-						>
-							<img
-								style={{ display: state.playSource === "music" ? "" : "none" }}
-								class={styles.iconBtn}
-								src={headImg(`music.svg`)}
-							/>
-							<img
-								style={{ display: state.playSource === "music" ? "none" : "" }}
-								class={styles.iconBtn}
-								src={headImg(`background.svg`)}
-							/>
-							<span>{state.playSource === "music" ? "原声" : "伴奏"}</span>
-						</div>
-						<div
-							id={state.platform === IPlatform.PC ? "teacherTop-2" : "studnetT-2"}
-							style={{ display: selectBtn.value.display ? "" : "none" }}
-							class={[styles.btn, selectBtn.value.disabled && styles.disabled]}
-							onClick={() => handleChangeSection()}
-						>
-							<img
-								style={{ display: state.section.length === 0 ? "" : "none" }}
-								class={styles.iconBtn}
-								src={headImg(`section0.svg`)}
-							/>
-							<img
-								style={{ display: state.section.length === 1 ? "" : "none" }}
-								class={styles.iconBtn}
-								src={headImg(`section1.svg`)}
-							/>
-							<img
-								style={{ display: state.section.length === 2 ? "" : "none" }}
-								class={styles.iconBtn}
-								src={headImg(`section2.svg`)}
-							/>
-							<span>选段</span>
-						</div>
-						<div
-							id={state.platform === IPlatform.PC ? "teacherTop-3" : "studnetT-3"}
-							style={{ display: fingeringBtn.value.display ? "" : "none" }}
-							class={[styles.btn, fingeringBtn.value.disabled && styles.disabled]}
-							onClick={() => {
-								state.setting.displayFingering = !state.setting.displayFingering;
-							}}
-						>
-							<img
-								style={{ display: state.setting.displayFingering ? "" : "none" }}
-								class={styles.iconBtn}
-								src={headImg(`icon_evaluatingOn.svg`)}
-							/>
-							<img
-								style={{ display: state.setting.displayFingering ? "none" : "" }}
-								class={styles.iconBtn}
-								src={headImg(`icon_evaluatingOff.svg`)}
-							/>
-							<span>指法</span>
-						</div>
-
-						<Popover
-							trigger="manual"
-							v-model:show={headData.speedShow}
-							placement="bottom"
-							overlay={false}
-						>
-							{{
-								reference: () => (
-									<div
-										id={state.platform === IPlatform.PC ? "teacherTop-4" : "studnetT-4"}
-										style={{ display: speedBtn.value.display ? "" : "none" }}
-										class={[styles.btn, speedBtn.value.disabled && styles.disabled]}
-										onClick={(e: Event) => {
-											e.stopPropagation();
-											headData.speedShow = !headData.speedShow;
-										}}
-									>
-										<Badge class={styles.badge} content={state.speed}>
-											<img class={styles.iconBtn} src={headImg("icon_speed.svg")} />
-										</Badge>
-										<span>速度</span>
-									</div>
-								),
-								default: () => <Speed />,
-							}}
-						</Popover>
-						<Popover
-							trigger="manual"
-							v-model:show={headData.musicTypeShow}
-							placement="bottom-end"
-							overlay={false}
-						>
-							{{
-								reference: () => (
-									<div
-										id={state.platform === IPlatform.PC ? "teacherTop-5" : "studnetT-5"}
-										style={{ display: converBtn.value.display ? "" : "none" }}
-										class={[styles.btn, converBtn.value.disabled && styles.disabled]}
-										onClick={(e: Event) => {
-											e.stopPropagation();
-											headData.musicTypeShow = !headData.musicTypeShow;
-										}}
-									>
-										<img class={styles.iconBtn} src={headImg("icon_zhuanpu.svg")} />
-										<span>{state.musicRenderType === "staff" ? "转谱" : "转谱"}</span>
-									</div>
-								),
-								default: () => <MusicType />,
-							}}
-						</Popover>
-
-						<div
-							id={state.platform === IPlatform.PC ? "teacherTop-6" : "studnetT-6"}
-							style={{ display: settingBtn.value.display ? "" : "none" }}
-							class={[styles.btn, settingBtn.value.disabled && styles.disabled]}
-							onClick={() => (headTopData.settingMode = true)}
-						>
-							<img class={styles.iconBtn} src={headImg("icon_menu.svg")} />
-							<span>设置</span>
-						</div>
-					</div>
-				</div>
-
-				{/* 播放按钮 */}
-				<div
-					id="studnetT-7"
-					style={{ display: playBtn.value.display ? "" : "none" }}
-					class={[
-						styles.btn,
-						styles.playBtn,
-						playBtn.value.disabled && styles.disabled,
-						state.platform === IPlatform.PC && styles.playButton,
-					]}
-					onClick={() => togglePlay()}
-				>
-					<div class={styles.btnWrap}>
-						<img
-							style={{ display: state.playState === "play" ? "none" : "" }}
-							class={styles.iconBtn}
-							src={headImg("icon_play.svg")}
-						/>
-						<img
-							style={{ display: state.playState === "play" ? "" : "none" }}
-							class={styles.iconBtn}
-							src={headImg("icon_pause.svg")}
-						/>
-						<Circle
-							style={{ opacity: state.playState === "play" ? 1 : 0 }}
-							class={styles.progress}
-							stroke-width={80}
-							currentRate={state.playProgress}
-							rate={100}
-							color="#FFC830"
-						/>
-					</div>
-				</div>
-
-				{/* 重播按钮 */}
-				<div
-					id="tips-step-9"
-					style={{ display: resetBtn.value.display ? "" : "none" }}
-					class={[
-						styles.btn,
-						styles.resetBtn,
-						resetBtn.value.disabled && styles.disabled,
-						state.platform === IPlatform.PC && styles.pauseButton,
-					]}
-					onClick={() => handleResetPlay()}
-				>
-					<img class={styles.iconBtn} src={headImg("icon_resetbtn.svg")} />
-				</div>
-
-				<Popup
-					v-model:show={headTopData.settingMode}
-					class="popup-custom van-scale center-closeBtn"
-					transition="van-scale"
-					teleport="body"
-					closeable
-				>
-					<Settting />
-				</Popup>
-
-				{/* 模式切换 */}
-				<ModeTypeMode />
-				{/* isAllBtns */}
-				{isAllBtns.value && <TeacherTop></TeacherTop>}
-				{isAllBtnsStudent.value && <StudentTop></StudentTop>}
-			</>
-		);
-	},
+  name: "header-top",
+  emits: ["close"],
+  setup(props, { emit }) {
+    const query = getQuery();
+    // 是否显示引导
+    const showGuide = ref(false);
+    const showStudentGuide = ref(false);
+
+    /** 设置按钮 */
+    const settingBtn = computed(() => {
+      // 音频播放中 禁用
+      if (state.playState === "play") return { display: true, disabled: true };
+      // 评测开始 禁用, 跟练开始 禁用
+      if (evaluatingData.startBegin || followData.start) return { display: true, disabled: true };
+
+      return {
+        display: true,
+        disabled: false,
+      };
+    });
+
+    /** 转谱按钮 */
+    const converBtn = computed(() => {
+      // 音频播放中 禁用
+      if (state.playState === "play") return { display: true, disabled: true };
+      // 评测开始 禁用
+      if (evaluatingData.startBegin || followData.start) return { display: true, disabled: true };
+
+      return {
+        disabled: false,
+        display: true,
+      };
+    });
+
+    /** 速度按钮 */
+    const speedBtn = computed(() => {
+      // 选择模式, 跟练模式  不显示
+      if (headTopData.modeType !== "show" || state.modeType === "follow") return { display: false, disabled: true };
+      // 评测模式, 音频播放中 禁用
+      if (state.modeType === "evaluating" || state.playState === "play") return { display: true, disabled: true };
+
+      return {
+        disabled: false,
+        display: true,
+      };
+    });
+
+    /** 指法按钮 */
+    const fingeringBtn = computed(() => {
+      // 没有指法 选择模式 评测模式 跟练模式 不显示
+      if (headTopData.modeType !== "show" || !state.fingeringInfo.name || ["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
+      // 音频播放中 禁用
+      if (state.playState === "play") return { display: true, disabled: true };
+
+      return {
+        disabled: false,
+        display: true,
+      };
+    });
+
+    /** 摄像头按钮 */
+    const cameraBtn = computed(() => {
+      // 选择模式 不显示
+      if (headTopData.modeType !== "show" || state.modeType !== "evaluating") return { display: false, disabled: true };
+      // 音频播放中 禁用
+      if (state.playState === "play") return { display: true, disabled: true };
+
+      return {
+        disabled: false,
+        display: true,
+      };
+    });
+
+    /** 选段按钮 */
+    const selectBtn = computed(() => {
+      // 选择模式 不显示
+      if (headTopData.modeType !== "show" || ["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
+      // 音频播放中 禁用
+      if (state.playState === "play") return { display: true, disabled: true };
+
+      return {
+        disabled: false,
+        display: true,
+      };
+    });
+
+    /** 原声按钮 */
+    const originBtn = computed(() => {
+      // 选择模式,跟练模式 不显示
+      if (headTopData.modeType !== "show" || state.modeType === "follow") return { display: false, disabled: false };
+      // 评测开始 禁用
+      if (state.modeType === "evaluating") return { display: false, disabled: true };
+      // 原声, 伴奏 少一个,就不能切换
+      if (!state.music || !state.accompany) return { display: true, disabled: true };
+
+      return {
+        disabled: false,
+        display: true,
+      };
+    });
+
+    /** 模式切换按钮 */
+    const toggleBtn = computed(() => {
+      // 选择模式, url设置模式 不显示
+      if (headTopData.modeType !== "show" || !headTopData.showBack) return { display: false, disabled: false };
+      // 跟练开始, 评测开始 禁用
+      if (followData.start || evaluatingData.startBegin) return { display: true, disabled: true };
+
+      return {
+        display: true,
+        disabled: false,
+      };
+    });
+
+    /** 播放按钮 */
+    const playBtn = computed(() => {
+      // 选择模式 不显示
+      if (headTopData.modeType !== "show") return { display: false, disabled: false };
+      // 评测模式 不显示,跟练模式 不显示
+      if (["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
+
+      return {
+        display: true,
+        disabled: false,
+      };
+    });
+
+    /** 重播按钮 */
+    const resetBtn = computed(() => {
+      // 选择模式 不显示
+      if (headTopData.modeType !== "show") return { display: false, disabled: false };
+      // 评测模式 不显示,跟练模式 不显示
+      if (["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: true };
+      // 播放状态 不显示
+      if (state.playState === "play") return { display: false, disabled: true };
+      // 播放进度为0 不显示
+      const currentTime = getAudioCurrentTime();
+      if (!currentTime) return { display: false, disabled: true };
+
+      return {
+        display: true,
+        disabled: false,
+      };
+    });
+
+    const isAllBtns = computed(() => {
+      const flag = converBtn.value.display && speedBtn.value.display && selectBtn.value.display && originBtn.value.display && toggleBtn.value.display && showGuide.value;
+      return flag;
+    });
+
+    const isAllBtnsStudent = computed(() => {
+      const flag = converBtn.value.display && speedBtn.value.display && selectBtn.value.display && originBtn.value.display && toggleBtn.value.display && showStudentGuide.value;
+
+      return flag;
+    });
+    const browInfo = browser();
+    /** 返回 */
+    const handleBack = () => {
+      HANDLE_WORK_ADD();
+      // 不在APP中,
+      if (!storeData.isApp) {
+        window.close();
+        return;
+      }
+      if ((browInfo.iPhone || browInfo.ios) && query.workRecord) {
+        setTimeout(() => {
+          api_back();
+        }, 550);
+        return;
+      }
+      api_back();
+    };
+
+    /** 根据参数设置模式 */
+    const getQueryModelSetModelType = () => {
+      /** 作业模式 start, 如果为作业模式不处理,让作业模块处理 */
+      if (query.workRecord) {
+        return;
+      }
+      /** 作业模式 end */
+      if (query.modelType) {
+        if (query.modelType === "practise") {
+          headTopData.handleChangeModeType("practise");
+        } else if (query.modelType === "evaluating") {
+          headTopData.handleChangeModeType("evaluating");
+        }
+        headTopData.showBack = false;
+      } else {
+        setTimeout(() => {
+          headTopData.modeType = "init";
+        }, 500);
+      }
+    };
+
+    /** 课件播放 */
+    const changePlay = (res: any) => {
+      if (res?.data?.api === "setPlayState") {
+        togglePlay("paused");
+      }
+
+      // 菜单状态
+      if ((state.platform === IPlatform.PC && res?.data?.api) === "attendClassBarStatus") {
+        state.attendHideMenu = res?.data?.hideMenu;
+      }
+    };
+
+    onMounted(() => {
+      getQueryModelSetModelType();
+      window.addEventListener("message", changePlay);
+      if (state.platform === IPlatform.PC) {
+        showGuide.value = true;
+      } else {
+        showStudentGuide.value = true;
+      }
+    });
+
+    onUnmounted(() => {
+      window.removeEventListener("message", changePlay);
+    });
+
+    // 设置改变触发
+    watch(state.setting, () => {
+      console.log(state.setting, "state.setting");
+      store.set("musicscoresetting", state.setting);
+    });
+
+    return () => (
+      <>
+        <div
+          class={[styles.headerTop, state.platform === IPlatform.PC && styles.headRightTop, state.platform === IPlatform.PC && !state.attendHideMenu && styles.headRightTopHide]}
+          onClick={(e: Event) => {
+            e.stopPropagation();
+            if (state.platform === IPlatform.PC) {
+              // 显示隐藏菜单
+              window.parent.postMessage(
+                {
+                  api: "onAttendToggleMenu",
+                },
+                "*"
+              );
+            }
+          }}
+        >
+          <div class={[styles.back, "headTopBackBtn", !headTopData.showBack && styles.hidenBack]} onClick={handleBack}>
+            <img src={iconBack} />
+          </div>
+          {query.iscurseplay === "play" ? null : <Title class="pcTitle" text={state.examSongName} rightView={false} />}
+
+          <div
+            class={[styles.headRight]}
+            onClick={(e: Event) => {
+              e.stopPropagation();
+            }}
+          >
+            <div
+              id={state.platform === IPlatform.PC ? "teacherTop-0" : "studnetT-0"}
+              style={{ display: toggleBtn.value.display ? "" : "none" }}
+              class={[styles.btn, toggleBtn.value.disabled && styles.disabled]}
+              onClick={() => {
+                handleRessetState();
+                headTopData.modeType = "init";
+              }}
+            >
+              <img class={styles.iconBtn} src={headImg(`modeType.svg`)} />
+              <span>模式</span>
+            </div>
+
+            <div
+              id={state.platform === IPlatform.PC ? "teacherTop-1" : "studnetT-1"}
+              style={{ display: originBtn.value.display ? "" : "none" }}
+              class={[styles.btn, originBtn.value.disabled && styles.disabled]}
+              onClick={() => {
+                state.playSource = state.playSource === "music" ? "background" : "music";
+              }}
+            >
+              <img style={{ display: state.playSource === "music" ? "" : "none" }} class={styles.iconBtn} src={headImg(`music.svg`)} />
+              <img style={{ display: state.playSource === "music" ? "none" : "" }} class={styles.iconBtn} src={headImg(`background.svg`)} />
+              <span>{state.playSource === "music" ? "原声" : "伴奏"}</span>
+            </div>
+            <div id={state.platform === IPlatform.PC ? "teacherTop-2" : "studnetT-2"} style={{ display: selectBtn.value.display ? "" : "none" }} class={[styles.btn, selectBtn.value.disabled && styles.disabled]} onClick={() => handleChangeSection()}>
+              <img style={{ display: state.section.length === 0 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section0.svg`)} />
+              <img style={{ display: state.section.length === 1 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section1.svg`)} />
+              <img style={{ display: state.section.length === 2 ? "" : "none" }} class={styles.iconBtn} src={headImg(`section2.svg`)} />
+              <span>选段</span>
+            </div>
+            <div
+              id={state.platform === IPlatform.PC ? "teacherTop-3" : "studnetT-3"}
+              style={{ display: fingeringBtn.value.display ? "" : "none" }}
+              class={[styles.btn, fingeringBtn.value.disabled && styles.disabled]}
+              onClick={() => {
+                state.setting.displayFingering = !state.setting.displayFingering;
+              }}
+            >
+              <img style={{ display: state.setting.displayFingering ? "" : "none" }} class={styles.iconBtn} src={headImg(`icon_evaluatingOn.svg`)} />
+              <img style={{ display: state.setting.displayFingering ? "none" : "" }} class={styles.iconBtn} src={headImg(`icon_evaluatingOff.svg`)} />
+              <span>指法</span>
+            </div>
+
+            <Popover trigger="manual" v-model:show={headData.speedShow} placement="bottom" overlay={false}>
+              {{
+                reference: () => (
+                  <div
+                    id={state.platform === IPlatform.PC ? "teacherTop-4" : "studnetT-4"}
+                    style={{ display: speedBtn.value.display ? "" : "none" }}
+                    class={[styles.btn, speedBtn.value.disabled && styles.disabled]}
+                    onClick={(e: Event) => {
+                      e.stopPropagation();
+                      headData.speedShow = !headData.speedShow;
+                    }}
+                  >
+                    <Badge class={styles.badge} content={state.speed}>
+                      <img class={styles.iconBtn} src={headImg("icon_speed.svg")} />
+                    </Badge>
+                    <span>速度</span>
+                  </div>
+                ),
+                default: () => <Speed />,
+              }}
+            </Popover>
+            <Popover trigger="manual" v-model:show={headData.musicTypeShow} placement="bottom-end" overlay={false}>
+              {{
+                reference: () => (
+                  <div
+                    id={state.platform === IPlatform.PC ? "teacherTop-5" : "studnetT-5"}
+                    style={{ display: converBtn.value.display ? "" : "none" }}
+                    class={[styles.btn, converBtn.value.disabled && styles.disabled]}
+                    onClick={(e: Event) => {
+                      e.stopPropagation();
+                      headData.musicTypeShow = !headData.musicTypeShow;
+                    }}
+                  >
+                    <img class={styles.iconBtn} src={headImg("icon_zhuanpu.svg")} />
+                    <span>{state.musicRenderType === "staff" ? "转谱" : "转谱"}</span>
+                  </div>
+                ),
+                default: () => <MusicType />,
+              }}
+            </Popover>
+
+            <div id={state.platform === IPlatform.PC ? "teacherTop-6" : "studnetT-6"} style={{ display: settingBtn.value.display ? "" : "none" }} class={[styles.btn, settingBtn.value.disabled && styles.disabled]} onClick={() => (headTopData.settingMode = true)}>
+              <img class={styles.iconBtn} src={headImg("icon_menu.svg")} />
+              <span>设置</span>
+            </div>
+          </div>
+        </div>
+
+        {/* 播放按钮 */}
+        <div
+          id="studnetT-7"
+          style={{ display: playBtn.value.display ? "" : "none" }}
+          class={[styles.btn, styles.playBtn, playBtn.value.disabled && styles.disabled, state.platform === IPlatform.PC && styles.playButton, state.platform === IPlatform.PC && !state.attendHideMenu && styles.playButtonHide]}
+          onClick={() => togglePlay()}
+        >
+          <div class={styles.btnWrap}>
+            <img style={{ display: state.playState === "play" ? "none" : "" }} class={styles.iconBtn} src={headImg("icon_play.svg")} />
+            <img style={{ display: state.playState === "play" ? "" : "none" }} class={styles.iconBtn} src={headImg("icon_pause.svg")} />
+            <Circle style={{ opacity: state.playState === "play" ? 1 : 0 }} class={styles.progress} stroke-width={80} currentRate={state.playProgress} rate={100} color="#FFC830" />
+          </div>
+        </div>
+
+        {/* 重播按钮 */}
+        <div
+          id="tips-step-9"
+          style={{ display: resetBtn.value.display ? "" : "none" }}
+          class={[styles.btn, styles.resetBtn, resetBtn.value.disabled && styles.disabled, state.platform === IPlatform.PC && styles.pauseButton, state.platform === IPlatform.PC && !state.attendHideMenu && styles.playButtonHide]}
+          onClick={() => handleResetPlay()}
+        >
+          <img class={styles.iconBtn} src={headImg("icon_resetbtn.svg")} />
+        </div>
+
+        <Popup v-model:show={headTopData.settingMode} class="popup-custom van-scale center-closeBtn" transition="van-scale" teleport="body" closeable>
+          <Settting />
+        </Popup>
+
+        {/* 模式切换 */}
+        <ModeTypeMode />
+        {/* isAllBtns */}
+        {isAllBtns.value && <TeacherTop></TeacherTop>}
+        {isAllBtnsStudent.value && <StudentTop></StudentTop>}
+      </>
+    );
+  },
 });

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

@@ -35,7 +35,8 @@
         height: calc(100vh - var(--header-height));
         margin: 0 10px;
         border-radius: 10px;
-        transition: height .3s;
+        transition: height .2s;
+        transition: padding-bottom .2s;
         overflow: hidden;
     }
 }

+ 360 - 412
src/page-instrument/view-detail/index.tsx

@@ -1,28 +1,8 @@
 import { Popup, Skeleton } from "vant";
-import {
-	computed,
-	defineComponent,
-	nextTick,
-	onBeforeMount,
-	onBeforeUnmount,
-	onMounted,
-	reactive,
-	Transition,
-	watch,
-	watchEffect,
-} from "vue";
+import { computed, defineComponent, nextTick, onBeforeMount, onBeforeUnmount, onMounted, reactive, Transition, watch, watchEffect } from "vue";
 import { formateTimes } from "../../helpers/formateMusic";
 import Metronome, { metronomeData } from "../../helpers/metronome";
-import state, {
-	EnumMusicRenderType,
-	evaluatCreateMusicPlayer,
-	handleSetSpeed,
-	IAudioState,
-	IPlatform,
-	isRhythmicExercises,
-	resetPlaybackToStart,
-	togglePlay,
-} from "/src/state";
+import state, { EnumMusicRenderType, evaluatCreateMusicPlayer, handleSetSpeed, IAudioState, IPlatform, isRhythmicExercises, resetPlaybackToStart, togglePlay } from "/src/state";
 import { browser, setGlobalData } from "../../utils";
 import AudioList from "../../view/audio-list";
 import MusicScore, { resetMusicScore } from "../../view/music-score";
@@ -30,17 +10,7 @@ import { sysMusicScoreAccompanimentQueryPage } from "../api";
 import EvaluatModel from "../evaluat-model";
 import HeaderTop from "../header-top";
 import styles from "./index.module.less";
-import {
-	api_cloudAccompanyMessage,
-	api_cloudLoading,
-	api_keepScreenLongLight,
-	api_openCamera,
-	api_openWebView,
-	api_setEventTracking,
-	api_setRequestedOrientation,
-	api_setStatusBarVisibility,
-	isSpecialShapedScreen,
-} from "/src/helpers/communication";
+import { api_cloudAccompanyMessage, api_cloudLoading, api_keepScreenLongLight, api_openCamera, api_openWebView, api_setEventTracking, api_setRequestedOrientation, api_setStatusBarVisibility, isSpecialShapedScreen } from "/src/helpers/communication";
 import { getQuery } from "/src/utils/queryString";
 import Evaluating, { evaluatingData } from "/src/view/evaluating";
 import MeasureSpeed from "/src/view/plugins/measure-speed";
@@ -62,416 +32,394 @@ import { recalculateNoteData } from "/src/view/selection";
  */
 const instrumentSubject = [120];
 const resetFrequency = (list: any[]) => {
-	if (!instrumentSubject.includes(state.subjectId)) return list;
-	for (let i = 0; i < list.length; i++) {
-		if (list[i].prevFrequency) list[i].prevFrequency = list[i].prevFrequency * 2;
-		if (list[i].frequency) list[i].frequency = list[i].frequency * 2;
-		if (list[i].nextFrequency) list[i].nextFrequency = list[i].nextFrequency * 2;
-	}
-	return list;
+  if (!instrumentSubject.includes(state.subjectId)) return list;
+  for (let i = 0; i < list.length; i++) {
+    if (list[i].prevFrequency) list[i].prevFrequency = list[i].prevFrequency * 2;
+    if (list[i].frequency) list[i].frequency = list[i].frequency * 2;
+    if (list[i].nextFrequency) list[i].nextFrequency = list[i].nextFrequency * 2;
+  }
+  return list;
 };
 
 /**
  * 乐器指法处理
  */
 const setNoteHalfTone = (list: any[]) => {
-	const instrumentNames = ["hulusi-flute"];
-	if (!state.fingeringInfo?.name || !instrumentNames.includes(state.fingeringInfo.name)) return list;
-	for (let i = 0; i < list.length; i++) {
-		const note = list[i];
-		if (note.realKey === 0) continue;
-		note.realKey = note.realKey + 12;
-	}
-	return list;
+  const instrumentNames = ["hulusi-flute"];
+  if (!state.fingeringInfo?.name || !instrumentNames.includes(state.fingeringInfo.name)) return list;
+  for (let i = 0; i < list.length; i++) {
+    const note = list[i];
+    if (note.realKey === 0) continue;
+    note.realKey = note.realKey + 12;
+  }
+  return list;
 };
 
 export default defineComponent({
-	name: "music-list",
-	setup() {
-		const query: any = getQuery();
+  name: "music-list",
+  setup() {
+    const query: any = getQuery();
 
-		const detailData = reactive({
-			isLoading: true,
-			skeletonLoading: true,
-			paddingLeft: "",
-			headerHide: false,
-			fingerPreView: false,
-			orientation: 0,
-			fingerPreViewGuide: false,
-		});
-		const getAPPData = async () => {
-			const screenData = await isSpecialShapedScreen();
-			if (screenData?.content) {
-				// console.log("🚀 ~ screenData:", screenData.content);
-				const { isSpecialShapedScreen, notchHeight } = screenData.content;
-				if (isSpecialShapedScreen) {
-					detailData.paddingLeft = 25 + "px";
-				}
-			}
-		};
-		onBeforeMount(() => {
-			api_keepScreenLongLight();
-			getAPPData();
-			api_setStatusBarVisibility();
-			const settting = store.get("musicscoresetting");
-			if (settting) {
-				state.setting = settting;
-				if (state.setting.camera) {
-					api_openCamera();
-				}
-			}
-		});
+    const detailData = reactive({
+      isLoading: true,
+      skeletonLoading: true,
+      paddingLeft: "",
+      headerHide: false,
+      fingerPreView: false,
+      orientation: 0,
+      fingerPreViewGuide: false,
+    });
+    const getAPPData = async () => {
+      const screenData = await isSpecialShapedScreen();
+      if (screenData?.content) {
+        // console.log("🚀 ~ screenData:", screenData.content);
+        const { isSpecialShapedScreen, notchHeight } = screenData.content;
+        if (isSpecialShapedScreen) {
+          detailData.paddingLeft = 25 + "px";
+        }
+      }
+    };
+    onBeforeMount(() => {
+      api_keepScreenLongLight();
+      getAPPData();
+      api_setStatusBarVisibility();
+      const settting = store.get("musicscoresetting");
+      if (settting) {
+        state.setting = settting;
+        if (state.setting.camera) {
+          api_openCamera();
+        }
+      }
+    });
 
-		//给app传伴奏
-		const pushAppMusic = () => {
-			api_cloudAccompanyMessage(state.accompany);
-		};
-		// console.log(route.params, query)
-		/** 获取曲谱数据 */
-		const getMusicInfo = (res: any) => {
-			const index = query["part-index"] ? parseInt(query["part-index"] as string) : 0;
-			const musicData = res.data.background[index] || {};
-			const musicInfo = {
-				...res.data,
-				music: musicData.audioFileUrl || res.data.audioFileUrl,
-				accompany: musicData.metronomeUrl || res.data.metronomeUrl,
-				musicSheetId: musicData.musicSheetId || res.data.id,
-				track: musicData.track || res.data.track,
-			};
-			console.log("🚀 ~ musicInfo:", musicInfo);
-			setState(musicInfo, index);
-			setCustom();
-			detailData.isLoading = false;
-		};
+    //给app传伴奏
+    const pushAppMusic = () => {
+      api_cloudAccompanyMessage(state.accompany);
+    };
+    // console.log(route.params, query)
+    /** 获取曲谱数据 */
+    const getMusicInfo = (res: any) => {
+      const index = query["part-index"] ? parseInt(query["part-index"] as string) : 0;
+      const musicData = res.data.background[index] || {};
+      const musicInfo = {
+        ...res.data,
+        music: musicData.audioFileUrl || res.data.audioFileUrl,
+        accompany: musicData.metronomeUrl || res.data.metronomeUrl,
+        musicSheetId: musicData.musicSheetId || res.data.id,
+        track: musicData.track || res.data.track,
+      };
+      console.log("🚀 ~ musicInfo:", musicInfo);
+      setState(musicInfo, index);
+      setCustom();
+      detailData.isLoading = false;
+    };
 
-		const setState = (data: any, index: number) => {
-			state.appName = "COLEXIU";
-			state.detailId = data.id;
-			state.xmlUrl = data.xmlFileUrl;
-			state.partIndex = index;
-			state.subjectId = data.musicSubject;
-			state.categoriesId = data.categoriesId;
-			state.categoriesName = data.musicTagNames;
-			state.enableEvaluation = data.canEvaluate ? true : false;
-			state.examSongId = data.id + "";
-			state.examSongName = data.musicSheetName;
-			// 解析扩展字段
-			if (data.extConfigJson) {
-				try {
-					state.extConfigJson = JSON.parse(data.extConfigJson as string);
-				} catch (error) {
-					console.error("解析扩展字段错误:", error);
-				}
-			}
-			state.isOpenMetronome = data.mp3Type === "MP3_METRONOME" ? true : false;
-			// 曲子包含节拍器,就不开启节拍器
-			state.needTick = data.mp3Type === "MP3_METRONOME" ? false : true;
-			state.isShowFingering = data.showFingering ? true : false;
-			state.music = data.music;
-			state.accompany = data.accompany;
-			state.midiUrl = data.midiUrl;
-			state.parentCategoriesId = data.musicTag;
-			state.musicSheetCategoriesId = data.musicSheetCategoriesId;
-			state.playMode = data.audioType === "MP3" ? "MP3" : "MIDI";
-			state.originSpeed = state.speed = data.playSpeed;
-			const track = data.code || data.track;
-			state.track = track ? track.replace(/ /g, "").toLocaleLowerCase() : "";
-			state.enableNotation = data.notation ? true : false;
+    const setState = (data: any, index: number) => {
+      state.appName = "COLEXIU";
+      state.detailId = data.id;
+      state.xmlUrl = data.xmlFileUrl;
+      state.partIndex = index;
+      state.subjectId = data.musicSubject;
+      state.categoriesId = data.categoriesId;
+      state.categoriesName = data.musicTagNames;
+      state.enableEvaluation = data.canEvaluate ? true : false;
+      state.examSongId = data.id + "";
+      state.examSongName = data.musicSheetName;
+      // 解析扩展字段
+      if (data.extConfigJson) {
+        try {
+          state.extConfigJson = JSON.parse(data.extConfigJson as string);
+        } catch (error) {
+          console.error("解析扩展字段错误:", error);
+        }
+      }
+      state.isOpenMetronome = data.mp3Type === "MP3_METRONOME" ? true : false;
+      // 曲子包含节拍器,就不开启节拍器
+      state.needTick = data.mp3Type === "MP3_METRONOME" ? false : true;
+      state.isShowFingering = data.showFingering ? true : false;
+      state.music = data.music;
+      state.accompany = data.accompany;
+      state.midiUrl = data.midiUrl;
+      state.parentCategoriesId = data.musicTag;
+      state.musicSheetCategoriesId = data.musicSheetCategoriesId;
+      state.playMode = data.audioType === "MP3" ? "MP3" : "MIDI";
+      state.originSpeed = state.speed = data.playSpeed;
+      const track = data.code || data.track;
+      state.track = track ? track.replace(/ /g, "").toLocaleLowerCase() : "";
+      state.enableNotation = data.notation ? true : false;
 
-			// console.log("🚀 ~ state.subjectId:", state.subjectId, state.track as any , state.subjectId)
-			// 是否打击乐
-			// state.isPercussion =
-			// 	state.subjectId == 23 ||
-			// 	state.subjectId == 113 ||
-			// 	state.subjectId == 121 ||
-			// 	isRhythmicExercises();
+      // console.log("🚀 ~ state.subjectId:", state.subjectId, state.track as any , state.subjectId)
+      // 是否打击乐
+      // state.isPercussion =
+      // 	state.subjectId == 23 ||
+      // 	state.subjectId == 113 ||
+      // 	state.subjectId == 121 ||
+      // 	isRhythmicExercises();
 
-			// 设置指法
-			const code = mappingVoicePart(state.subjectId, "INSTRUMENT");
-			state.fingeringInfo = subjectFingering(code);
-			console.log("🚀 ~ state.fingeringInfo:", state.fingeringInfo, state.subjectId, state.track);
+      // 设置指法
+      const code = mappingVoicePart(state.subjectId, "INSTRUMENT");
+      state.fingeringInfo = subjectFingering(code);
+      console.log("🚀 ~ state.fingeringInfo:", state.fingeringInfo, state.subjectId, state.track);
 
-			// 检测是否原音和伴奏都有
-			if (!state.music || !state.accompany) {
-				state.playSource = state.music ? "music" : "background";
-			}
+      // 检测是否原音和伴奏都有
+      if (!state.music || !state.accompany) {
+        state.playSource = state.music ? "music" : "background";
+      }
 
-			// 如果是PC端,放大曲谱
-			state.platform = query.platform?.toLocaleUpperCase() || "";
-			if (state.platform === IPlatform.PC) {
-				state.zoom = query.zoom || 1.5;
-			}
+      // 如果是PC端,放大曲谱
+      state.platform = query.platform?.toLocaleUpperCase() || "";
+      if (state.platform === IPlatform.PC) {
+        state.zoom = query.zoom || 1.5;
+      }
 
-			//课堂乐器,默认简谱
-			state.musicRenderType = EnumMusicRenderType.firstTone;
-		};
+      //课堂乐器,默认简谱
+      state.musicRenderType = EnumMusicRenderType.firstTone;
+    };
 
-		const setCustom = () => {
-			if (state.extConfigJson.multitrack) {
-				setGlobalData("multitrack", state.extConfigJson.multitrack);
-			}
-		};
+    const setCustom = () => {
+      if (state.extConfigJson.multitrack) {
+        setGlobalData("multitrack", state.extConfigJson.multitrack);
+      }
+    };
 
-		onMounted(() => {
-			(window as any).appName = "colexiu";
-			const id = query.id || "43554";
-			Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => {
-				getMusicInfo(values[0]);
-			});
-			api_setEventTracking();
-		});
+    onMounted(() => {
+      (window as any).appName = "colexiu";
+      const id = query.id || "43554";
+      Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => {
+        getMusicInfo(values[0]);
+      });
+      api_setEventTracking();
+    });
 
-		/** 渲染完成 */
-		const handleRendered = (osmd: any) => {
-			detailData.skeletonLoading = false;
-			state.osmd = osmd;
-			// 没有设置速度使用读取的速度
-			if (state.originSpeed === 0) {
-				state.originSpeed = state.speed = (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM || 100;
-			}
-			const saveSpeed =
-				(store.get("speeds") || {})[state.examSongId] ||
-				(osmd as any).bpm ||
-				osmd.Sheet.userStartTempoInBPM;
-			// 加载本地缓存的速度
-			if (saveSpeed) {
-				handleSetSpeed(saveSpeed);
-			}
-			state.times = formateTimes(osmd);
-			state.times = resetFrequency(state.times);
-			state.times = setNoteHalfTone(state.times);
-			console.log("🚀 ~ state.times:", state.times, state.subjectId);
-			try {
-				metronomeData.metro = new Metronome();
-				metronomeData.metro.init(state.times);
-			} catch (error) {}
-			// 设置节拍器
-			if (state.needTick) {
-				const beatLengthInMilliseconds = (60 / state.speed) * 1000;
-				// console.log(state.speed, osmd?.Sheet?.SheetPlaybackSetting?.beatLengthInMilliseconds , (60 / state.speed) * 1000)
-				handleInitTick(
-					beatLengthInMilliseconds,
-					osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4
-				);
-			}
-			api_cloudLoading();
+    /** 渲染完成 */
+    const handleRendered = (osmd: any) => {
+      detailData.skeletonLoading = false;
+      state.osmd = osmd;
+      // 没有设置速度使用读取的速度
+      if (state.originSpeed === 0) {
+        state.originSpeed = state.speed = (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM || 100;
+      }
+      const saveSpeed = (store.get("speeds") || {})[state.examSongId] || (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM;
+      // 加载本地缓存的速度
+      if (saveSpeed) {
+        handleSetSpeed(saveSpeed);
+      }
+      state.times = formateTimes(osmd);
+      state.times = resetFrequency(state.times);
+      state.times = setNoteHalfTone(state.times);
+      console.log("🚀 ~ state.times:", state.times, state.subjectId);
+      try {
+        metronomeData.metro = new Metronome();
+        metronomeData.metro.init(state.times);
+      } catch (error) {}
+      // 设置节拍器
+      if (state.needTick) {
+        const beatLengthInMilliseconds = (60 / state.speed) * 1000;
+        // console.log(state.speed, osmd?.Sheet?.SheetPlaybackSetting?.beatLengthInMilliseconds , (60 / state.speed) * 1000)
+        handleInitTick(beatLengthInMilliseconds, osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4);
+      }
+      api_cloudLoading();
 
-			state.musicRendered = true;
+      state.musicRendered = true;
 
-			evaluatCreateMusicPlayer();
-			resetPlaybackToStart();
+      evaluatCreateMusicPlayer();
+      resetPlaybackToStart();
 
-			pushAppMusic();
-		};
-		/** 指法配置 */
-		const fingerConfig = computed<any>(() => {
-			if (state.setting.displayFingering && state.fingeringInfo?.name) {
-				if (state.fingeringInfo.direction === "transverse") {
-					return {
-						container: {
-							paddingBottom: state.fingeringInfo.height,
-						},
-						fingerBox: {
-							height: state.fingeringInfo.height,
-						},
-					};
-				} else {
-					return {
-						container: {
-							paddingRight: state.fingeringInfo.width,
-						},
-						fingerBox: {
-							position: "absolute",
-							width: state.fingeringInfo.width,
-							height: "100%",
-							right: 0,
-							top: 0,
-						},
-					};
-				}
-			}
-			return {
-				container: {},
-				fingerBox: {},
-			};
-		});
+      pushAppMusic();
+    };
+    /** 指法配置 */
+    const fingerConfig = computed<any>(() => {
+      if (state.setting.displayFingering && state.fingeringInfo?.name) {
+        if (state.fingeringInfo.direction === "transverse") {
+          return {
+            container: {
+              paddingBottom: state.platform === IPlatform.PC ? `calc(${state.fingeringInfo.height} + ${state.attendHideMenu ? "0px" : "1.8rem"})` : state.fingeringInfo.height,
+            },
+            fingerBox: {
+              height: state.fingeringInfo.height,
+            },
+          };
+        } else {
+          return {
+            container: {
+              paddingRight: state.fingeringInfo.width,
+            },
+            fingerBox: {
+              position: "absolute",
+              width: state.fingeringInfo.width,
+              height: "100%",
+              right: 0,
+              top: 0,
+            },
+          };
+        }
+      }
+      return {
+        container: {},
+        fingerBox: {},
+      };
+    });
 
-		// 监听指法显示
-		watch(
-			() => state.setting.displayFingering,
-			() => {
-				if (state.fingeringInfo.direction === "vertical") {
-					nextTick(() => {
-						resetMusicScore();
-					});
-				}
-			}
-		);
-		watch(
-			() => state.setting.soundEffect,
-			() => {
-				store.set("musicscoresetting", state.setting);
-			}
-		);
-		/**播放状态改变时,向父页面发送事件 */
-		const sendParentMessage = (playState: IAudioState) => {
-			window.parent.postMessage(
-				{
-					api: "headerTogge",
-					playState: playState,
-				},
-				"*"
-			);
-		};
-		// 监听播放状态
-		watch(
-			() => state.playState,
-			() => {
-				if (state.platform != IPlatform.PC) {
-					detailData.headerHide = state.playState === "play" ? true : false;
-				}
-				sendParentMessage(state.playState);
-			}
-		);
-		/** 指法预览切换 */
-		watch(
-			() => detailData.fingerPreView,
-			() => {
-				console.log(2342);
-				window.parent.postMessage(
-					{
-						api: "api_fingerPreView",
-						state: detailData.fingerPreView,
-					},
-					"*"
-				);
-			}
-		);
-		onMounted(() => {
-			window.addEventListener("resize", resetMusicScore);
-		});
-		onBeforeUnmount(() => {
-			window.removeEventListener("resize", resetMusicScore);
-		});
-		const browsInfo = browser();
-		const handleOpenFignerView = () => {
-			if (!query.modelType) {
-				detailData.orientation = state.fingeringInfo.orientation || 0;
-				api_setRequestedOrientation(detailData.orientation);
-			}
-			// const url = `${
-			// 	/(192|localhost)/.test(location.origin)
-			// 		? "http://192.168.3.114:3000/instrument.html"
-			// 		: location.origin + location.pathname
-			// }#/view-figner`;
-			// console.log("🚀 ~ url:", url);
-			// api_openWebView({
-			// 	url: url,
-			// 	orientation: state.fingeringInfo.orientation || 0,
-			// });
+    // 监听指法显示
+    watch(
+      () => state.setting.displayFingering,
+      () => {
+        if (state.fingeringInfo.direction === "vertical") {
+          nextTick(() => {
+            resetMusicScore();
+          });
+        }
+      }
+    );
+    watch(
+      () => state.setting.soundEffect,
+      () => {
+        store.set("musicscoresetting", state.setting);
+      }
+    );
+    /**播放状态改变时,向父页面发送事件 */
+    const sendParentMessage = (playState: IAudioState) => {
+      window.parent.postMessage(
+        {
+          api: "headerTogge",
+          playState: playState,
+        },
+        "*"
+      );
+    };
+    // 监听播放状态
+    watch(
+      () => state.playState,
+      () => {
+        if (state.platform != IPlatform.PC) {
+          detailData.headerHide = state.playState === "play" ? true : false;
+        }
+        sendParentMessage(state.playState);
+      }
+    );
+    /** 指法预览切换 */
+    watch(
+      () => detailData.fingerPreView,
+      () => {
+        console.log(2342);
+        window.parent.postMessage(
+          {
+            api: "api_fingerPreView",
+            state: detailData.fingerPreView,
+          },
+          "*"
+        );
+      }
+    );
+    onMounted(() => {
+      window.addEventListener("resize", resetMusicScore);
+    });
+    onBeforeUnmount(() => {
+      window.removeEventListener("resize", resetMusicScore);
+    });
+    const browsInfo = browser();
+    const handleOpenFignerView = () => {
+      if (!query.modelType) {
+        detailData.orientation = state.fingeringInfo.orientation || 0;
+        api_setRequestedOrientation(detailData.orientation);
+      }
+      // const url = `${
+      // 	/(192|localhost)/.test(location.origin)
+      // 		? "http://192.168.3.114:3000/instrument.html"
+      // 		: location.origin + location.pathname
+      // }#/view-figner`;
+      // console.log("🚀 ~ url:", url);
+      // api_openWebView({
+      // 	url: url,
+      // 	orientation: state.fingeringInfo.orientation || 0,
+      // });
 
-			if (state.playState === "play") {
-				togglePlay("paused");
-				setTimeout(() => {
-					detailData.fingerPreView = true;
-				}, 500);
-				return;
-			}
-			detailData.fingerPreView = true;
-		};
-		const handleCloseFignerView = () => {
-			if (!query.modelType && detailData.orientation == 1) {
-				api_setRequestedOrientation(0);
-			}
-			detailData.fingerPreView = false;
-			detailData.fingerPreViewGuide = false;
-		};
-		return () => (
-			<div
-				class={[
-					styles.detail,
-					state.setting.eyeProtection && "eyeProtection",
-					state.platform === IPlatform.PC && styles.PC,
-				]}
-				style={{
-					paddingLeft: detailData.paddingLeft,
-					opacity: state.setting.camera ? `${state.setting.cameraOpacity / 100}` : "",
-				}}
-			>
-				<Transition name="van-fade">
-					{detailData.skeletonLoading && (
-						<div class={styles.skeleton}>
-							<Skeleton row={8} />
-						</div>
-					)}
-				</Transition>
-				<div class={[styles.headHeight, detailData.headerHide && styles.headHide]}>
-					{state.musicRendered && <HeaderTop />}
-				</div>
-				<div
-					id="scrollContainer"
-					style={{ ...fingerConfig.value.container, height: detailData.headerHide ? "100vh" : "" }}
-					class={[
-						styles.container,
-						!state.setting.displayCursor && "hideCursor",
-						browsInfo.xiaomi && styles.xiaomi,
-					]}
-					onClick={(e: Event) => {
-						if (state.playState === "play" && state.platform != IPlatform.PC) {
-							detailData.headerHide = !detailData.headerHide;
-						}
-					}}
-				>
-					{/* 曲谱渲染 */}
-					{!detailData.isLoading && <MusicScore onRendered={handleRendered} />}
+      if (state.playState === "play") {
+        togglePlay("paused");
+        setTimeout(() => {
+          detailData.fingerPreView = true;
+        }, 500);
+        return;
+      }
+      detailData.fingerPreView = true;
+    };
+    const handleCloseFignerView = () => {
+      if (!query.modelType && detailData.orientation == 1) {
+        api_setRequestedOrientation(0);
+      }
+      detailData.fingerPreView = false;
+      detailData.fingerPreViewGuide = false;
+    };
+    return () => (
+      <div
+        class={[styles.detail, state.setting.eyeProtection && "eyeProtection", state.platform === IPlatform.PC && styles.PC]}
+        style={{
+          paddingLeft: detailData.paddingLeft,
+          opacity: state.setting.camera ? `${state.setting.cameraOpacity / 100}` : "",
+        }}
+      >
+        <Transition name="van-fade">
+          {detailData.skeletonLoading && (
+            <div class={styles.skeleton}>
+              <Skeleton row={8} />
+            </div>
+          )}
+        </Transition>
+        <div class={[styles.headHeight, detailData.headerHide && styles.headHide]}>{state.musicRendered && <HeaderTop />}</div>
+        <div
+          id="scrollContainer"
+          style={{ ...fingerConfig.value.container, height: detailData.headerHide ? "100vh" : "" }}
+          class={[styles.container, !state.setting.displayCursor && "hideCursor", browsInfo.xiaomi && styles.xiaomi]}
+          onClick={(e: Event) => {
+            e.stopPropagation();
+            if (state.playState === "play" && state.platform != IPlatform.PC) {
+              detailData.headerHide = !detailData.headerHide;
+            }
+          }}
+        >
+          {/* 曲谱渲染 */}
+          {!detailData.isLoading && <MusicScore onRendered={handleRendered} />}
 
-					{/* 指法 */}
-					{state.setting.displayFingering && state.fingeringInfo?.name && (
-						<div style={{ ...fingerConfig.value.fingerBox }}>
-							<Fingering onOpen={() => handleOpenFignerView()} />
-						</div>
-					)}
-				</div>
+          {/* 指法 */}
+          {state.setting.displayFingering && state.fingeringInfo?.name && (
+            <div style={{ ...fingerConfig.value.fingerBox }}>
+              <Fingering onOpen={() => handleOpenFignerView()} />
+            </div>
+          )}
+        </div>
 
-				{/* 节拍器 */}
-				{state.needTick && <Tick />}
+        {/* 节拍器 */}
+        {state.needTick && <Tick />}
 
-				{/* 播放 */}
-				{!detailData.isLoading && <AudioList />}
+        {/* 播放 */}
+        {!detailData.isLoading && <AudioList />}
 
-				{/* 评测 */}
-				{state.modeType === "evaluating" && (
-					<>
-						<Evaluating />
-						{evaluatingData.rendered && <EvaluatModel />}
-					</>
-				)}
+        {/* 评测 */}
+        {state.modeType === "evaluating" && (
+          <>
+            <Evaluating />
+            {evaluatingData.rendered && <EvaluatModel />}
+          </>
+        )}
 
-				{/* 跟练模式 */}
-				{state.modeType === "follow" && (
-					<>
-						<FollowPractice />
-						<FollowModel />
-					</>
-				)}
+        {/* 跟练模式 */}
+        {state.modeType === "follow" && (
+          <>
+            <FollowPractice />
+            <FollowModel />
+          </>
+        )}
 
-				{state.musicRendered && (
-					<>
-						{/* 统计训练时长 */}
-						{storeData.isApp && <RecordingTime />}
-						{/* 作业 */}
-						{query.workRecord && <WorkIndex />}
-						{/* 曲谱列表 */}
-						{state.playState == "play" ||
-						followData.start ||
-						evaluatingData.startBegin ||
-						query.workRecord ||
-						query.modelType ||
-						state.platform === IPlatform.PC ? null : (
-							<TheMusicList />
-						)}
-					</>
-				)}
+        {state.musicRendered && (
+          <>
+            {/* 统计训练时长 */}
+            {storeData.isApp && <RecordingTime />}
+            {/* 作业 */}
+            {query.workRecord && <WorkIndex />}
+            {/* 曲谱列表 */}
+            {state.playState == "play" || followData.start || evaluatingData.startBegin || query.workRecord || query.modelType || state.platform === IPlatform.PC ? null : <TheMusicList />}
+          </>
+        )}
 
 				<Popup
 					zIndex={5050}

+ 434 - 441
src/state.ts

@@ -6,13 +6,7 @@ import { GradualNote, GradualTimes, GradualVersion } from "./type";
 import { handleEndEvaluat, handleStartEvaluat } from "./view/evaluating";
 import { IFingering } from "src/view/fingering/fingering-config";
 import { handleStartTick } from "./view/tick";
-import {
-	audioListStart,
-	getAudioCurrentTime,
-	getAudioDuration,
-	setAudioCurrentTime,
-	setAudioPlaybackRate,
-} from "./view/audio-list";
+import { audioListStart, getAudioCurrentTime, getAudioDuration, setAudioCurrentTime, setAudioPlaybackRate } from "./view/audio-list";
 import { toggleFollow } from "./view/follow-practice";
 import { browser, setStorageSpeed } from "./utils";
 import { api_createMusicPlayer } from "./helpers/communication";
@@ -21,12 +15,12 @@ import { api_createMusicPlayer } from "./helpers/communication";
 export type IDifficulty = "BEGINNER" | "ADVANCED" | "PERFORMER";
 /** 渲染类型: 五线谱,简谱 */
 export enum EnumMusicRenderType {
-	/** 五线谱 */
-	staff = "staff",
-	/** 简谱 */
-	firstTone = "firstTone",
-	/** 固定音高 */
-	fixedTone = "fixedTone",
+  /** 五线谱 */
+  staff = "staff",
+  /** 简谱 */
+  firstTone = "firstTone",
+  /** 固定音高 */
+  fixedTone = "fixedTone",
 }
 export const musicscoresettingKey = "musicscoresetting";
 /** 有声音的是那个音源 */
@@ -36,259 +30,261 @@ export type IAudioState = "play" | "paused";
 
 /** 来源 */
 export enum IPlatform {
-	APP = "APP",
-	PC = "PC",
+  APP = "APP",
+  PC = "PC",
 }
 
 const state = reactive({
-	/** 来源 : PC , app */
-	platform: "" as IPlatform,
-	appName: "" as "GYM" | "COLEXIU",
-	musicRenderType: EnumMusicRenderType.staff as EnumMusicRenderType,
-	/**曲谱是否渲染完成 */
-	musicRendered: false,
-	/** 当前曲谱数据ID, 和曲谱ID不一致 */
-	detailId: "",
-	/** 曲谱资源URL */
-	xmlUrl: "",
-	/** 声部ID */
-	subjectId: 0 as number,
-	/** 分类ID */
-	categoriesId: 0,
-	/** 分类名称 */
-	categoriesName: "",
-	/** 是否支持评测 */
-	enableEvaluation: true,
-	/** 是否支持转谱 */
-	enableNotation: false,
-	/** 曲谱ID */
-	examSongId: "",
-	/** 曲谱名称 */
-	examSongName: "",
-	/** 扩展字段 */
-	extConfigJson: {} as any,
-	/** 扩展样式字段 */
-	extStyleConfigJson: {} as any,
-	/** 是否开启节拍器 */
-	isOpenMetronome: false,
-	/** 是否显示指法 */
-	isShowFingering: false,
-	/** 原音 */
-	music: "",
-	/** 伴奏 */
-	accompany: "",
-	/** midiURL */
-	midiUrl: "",
-	/** 父分ID */
-	parentCategoriesId: 0,
-	/** 分类ID */
-	musicSheetCategoriesId: 0,
-	/** 资源类型: mp3 | midi */
-	playMode: "MP3" as "MP3" | "MIDI",
-	/** 设置的速度 */
-	speed: 0,
-	/** 曲谱音频正常的速度 */
-	originSpeed: 0,
-	/** 分轨名称 */
-	track: "",
-	/** 当前显示声部索引 */
-	partIndex: 0,
-	/** 是否需要节拍器 */
-	needTick: false,
-	/** 曲谱实例 */
-	osmd: null as unknown as OpenSheetMusicDisplay,
-	/**是否是特殊乐谱类型, 主要针对管乐迷  */
-	isSpecialBookCategory: false,
-	/** 播放状态 */
-	playState: "paused" as IAudioState,
-	/** 播放结束状态 */
-	playEnd: false,
-	/** 播放那个: 原音,伴奏 */
-	playSource: "music" as IPlayState,
-	/** 播放进度 */
-	playProgress: 0,
-	/** 激活的note index */
-	activeNoteIndex: 0,
-	/** 激活的小节 */
-	activeMeasureIndex: 0,
-	/** 选段状态 */
-	sectionStatus: false,
-	/** 选段数据 */
-	section: [] as any[],
-	/** 选段背景 */
-	sectionBoundingBoxs: [] as any[],
-	/** 开启选段预备 */
-	isOpenPrepare: false,
-	/** 选段预备 */
-	sectionFirst: null as any,
-	/** 音符数据 */
-	times: [] as any[],
-	/** 播放模式 */
-	modeType: "practise" as "practise" | "follow" | "evaluating",
-	/** 设置 */
-	setting: {
-		/** 效音提醒 */
-		soundEffect: true,
-		/** 护眼模式 */
-		eyeProtection: false,
-		/** 摄像头 */
-		camera: false,
-		/** 摄像头透明度 */
-		cameraOpacity: 70,
-		/** 循环播放 */
-		repeatAutoPlay: true,
-		/** 显示指法 */
-		displayFingering: true,
-		/** 显示光标 */
-		displayCursor: true,
-		/** 频率 */
-		frequency: 442,
-		/** 评测难度 */
-		evaluationDifficulty: "ADVANCED" as IDifficulty,
-		/** 保存到相册 */
-		saveToAlbum: false,
-		/** 开启伴奏 */
-		enableAccompaniment: true,
-		/** 反应时间 */
-		reactionTimeMs: 0,
-	},
-	/** 节拍器的时间 */
-	fixtime: 0,
-	/** 指法信息 */
-	fingeringInfo: {} as IFingering,
-	/** 滚动容器的ID */
-	scrollContainer: "musicAndSelection",
-	/** 是否是打击乐 */
-	isPercussion: false,
-	/** 是否重复节拍器的时间 */
-	repeatedBeats: 0,
-	/**当前曲谱中所有声部名字 */
-	partListNames: [] as string[],
-	/** 渐变速度信息 */
-	gradual: [] as GradualNote[],
-	/** 渐变速度版本 */
-	gradualVersion: GradualVersion.BASE as GradualVersion,
-	/** 渐变时间信息 */
-	gradualTimes: null as GradualTimes,
-	/** 单声部多声轨 */
-	multitrack: 0,
-	/** 缩放 */
-	zoom: 0.8,
-	/** 渲染曲谱比例 */
-	musicZoom: 1,
-	/** 练习,评测是否是选段模式 */
-	isSelectMeasureMode: false,
-	/** 是否是评分显示 */
-	isReport: false,
+  /** 来源 : PC , app */
+  platform: "" as IPlatform,
+  /** 课堂乐器老师端上课菜单状态 */
+  attendHideMenu: false,
+  appName: "" as "GYM" | "COLEXIU",
+  musicRenderType: EnumMusicRenderType.staff as EnumMusicRenderType,
+  /**曲谱是否渲染完成 */
+  musicRendered: false,
+  /** 当前曲谱数据ID, 和曲谱ID不一致 */
+  detailId: "",
+  /** 曲谱资源URL */
+  xmlUrl: "",
+  /** 声部ID */
+  subjectId: 0 as number,
+  /** 分类ID */
+  categoriesId: 0,
+  /** 分类名称 */
+  categoriesName: "",
+  /** 是否支持评测 */
+  enableEvaluation: true,
+  /** 是否支持转谱 */
+  enableNotation: false,
+  /** 曲谱ID */
+  examSongId: "",
+  /** 曲谱名称 */
+  examSongName: "",
+  /** 扩展字段 */
+  extConfigJson: {} as any,
+  /** 扩展样式字段 */
+  extStyleConfigJson: {} as any,
+  /** 是否开启节拍器 */
+  isOpenMetronome: false,
+  /** 是否显示指法 */
+  isShowFingering: false,
+  /** 原音 */
+  music: "",
+  /** 伴奏 */
+  accompany: "",
+  /** midiURL */
+  midiUrl: "",
+  /** 父分ID */
+  parentCategoriesId: 0,
+  /** 分类ID */
+  musicSheetCategoriesId: 0,
+  /** 资源类型: mp3 | midi */
+  playMode: "MP3" as "MP3" | "MIDI",
+  /** 设置的速度 */
+  speed: 0,
+  /** 曲谱音频正常的速度 */
+  originSpeed: 0,
+  /** 分轨名称 */
+  track: "",
+  /** 当前显示声部索引 */
+  partIndex: 0,
+  /** 是否需要节拍器 */
+  needTick: false,
+  /** 曲谱实例 */
+  osmd: null as unknown as OpenSheetMusicDisplay,
+  /**是否是特殊乐谱类型, 主要针对管乐迷  */
+  isSpecialBookCategory: false,
+  /** 播放状态 */
+  playState: "paused" as IAudioState,
+  /** 播放结束状态 */
+  playEnd: false,
+  /** 播放那个: 原音,伴奏 */
+  playSource: "music" as IPlayState,
+  /** 播放进度 */
+  playProgress: 0,
+  /** 激活的note index */
+  activeNoteIndex: 0,
+  /** 激活的小节 */
+  activeMeasureIndex: 0,
+  /** 选段状态 */
+  sectionStatus: false,
+  /** 选段数据 */
+  section: [] as any[],
+  /** 选段背景 */
+  sectionBoundingBoxs: [] as any[],
+  /** 开启选段预备 */
+  isOpenPrepare: false,
+  /** 选段预备 */
+  sectionFirst: null as any,
+  /** 音符数据 */
+  times: [] as any[],
+  /** 播放模式 */
+  modeType: "practise" as "practise" | "follow" | "evaluating",
+  /** 设置 */
+  setting: {
+    /** 效音提醒 */
+    soundEffect: true,
+    /** 护眼模式 */
+    eyeProtection: false,
+    /** 摄像头 */
+    camera: false,
+    /** 摄像头透明度 */
+    cameraOpacity: 70,
+    /** 循环播放 */
+    repeatAutoPlay: true,
+    /** 显示指法 */
+    displayFingering: true,
+    /** 显示光标 */
+    displayCursor: true,
+    /** 频率 */
+    frequency: 442,
+    /** 评测难度 */
+    evaluationDifficulty: "ADVANCED" as IDifficulty,
+    /** 保存到相册 */
+    saveToAlbum: false,
+    /** 开启伴奏 */
+    enableAccompaniment: true,
+    /** 反应时间 */
+    reactionTimeMs: 0,
+  },
+  /** 节拍器的时间 */
+  fixtime: 0,
+  /** 指法信息 */
+  fingeringInfo: {} as IFingering,
+  /** 滚动容器的ID */
+  scrollContainer: "musicAndSelection",
+  /** 是否是打击乐 */
+  isPercussion: false,
+  /** 是否重复节拍器的时间 */
+  repeatedBeats: 0,
+  /**当前曲谱中所有声部名字 */
+  partListNames: [] as string[],
+  /** 渐变速度信息 */
+  gradual: [] as GradualNote[],
+  /** 渐变速度版本 */
+  gradualVersion: GradualVersion.BASE as GradualVersion,
+  /** 渐变时间信息 */
+  gradualTimes: null as GradualTimes,
+  /** 单声部多声轨 */
+  multitrack: 0,
+  /** 缩放 */
+  zoom: 0.8,
+  /** 渲染曲谱比例 */
+  musicZoom: 1,
+  /** 练习,评测是否是选段模式 */
+  isSelectMeasureMode: false,
+  /** 是否是评分显示 */
+  isReport: false,
 });
 const browserInfo = browser();
 let offset_duration = 0;
 /** 自定义数据 */
 export const customData = reactive({
-	/** 自定义音符时值 */
-	customNoteRealValue: [] as any,
-	/** 自定义音符按读取到的时值 */
-	customNoteCurrentTime: false,
+  /** 自定义音符时值 */
+  customNoteRealValue: [] as any,
+  /** 自定义音符按读取到的时值 */
+  customNoteCurrentTime: false,
 });
 /** 在渲染前后计算光标应该走到的音符 */
 const setStep = () => {
-	if (state.playState !== "play") {
-		console.log("暂停播放");
-		return;
-	}
-	let startTime = Date.now();
-	requestAnimationFrame(() => {
-		const endTime = Date.now();
-		// 渲染时间大于16.6,就会让页面卡顿, 如果渲染时间大与16.6就下一个渲染帧去计算
-		if (endTime - startTime < 16.7) {
-			handlePlaying();
-			setStep();
-		} else {
-			setTimeout(() => {
-				handlePlaying();
-				setStep();
-			}, 16.7);
-		}
-	});
+  if (state.playState !== "play") {
+    console.log("暂停播放");
+    return;
+  }
+  let startTime = Date.now();
+  requestAnimationFrame(() => {
+    const endTime = Date.now();
+    // 渲染时间大于16.6,就会让页面卡顿, 如果渲染时间大与16.6就下一个渲染帧去计算
+    if (endTime - startTime < 16.7) {
+      handlePlaying();
+      setStep();
+    } else {
+      setTimeout(() => {
+        handlePlaying();
+        setStep();
+      }, 16.7);
+    }
+  });
 };
 /** 开始播放 */
 export const onPlay = () => {
-	console.log("开始播放");
-	state.playEnd = false;
-	offset_duration = browserInfo.xiaomi ? 0.2 : 0.08;
-	setStep();
+  console.log("开始播放");
+  state.playEnd = false;
+  offset_duration = browserInfo.xiaomi ? 0.2 : 0.08;
+  setStep();
 };
 
 /** 播放模式结束自动重播 */
 const autoResetPlay = () => {
-	if (state.modeType !== "practise") return;
-	skipNotePlay(0, true);
-	// 没有开启自动重播, 不是练习模式
-	if (!state.setting.repeatAutoPlay) return;
-	scrollViewNote();
-	setTimeout(() => {
-		togglePlay("play");
-	}, 1000);
+  if (state.modeType !== "practise") return;
+  skipNotePlay(0, true);
+  // 没有开启自动重播, 不是练习模式
+  if (!state.setting.repeatAutoPlay) return;
+  scrollViewNote();
+  setTimeout(() => {
+    togglePlay("play");
+  }, 1000);
 };
 
 /** 播放完成事件 */
 export const onEnded = () => {
-	console.log("音频播放结束");
-	// 修改状态为结束
-	state.playEnd = true;
-	state.playState = "paused";
-	// 结束播放
-	audioListStart(state.playState);
-	// 调用结束评测
-	handleEndEvaluat(true);
-	// 调用自动重复播放
-	autoResetPlay();
+  console.log("音频播放结束");
+  // 修改状态为结束
+  state.playEnd = true;
+  state.playState = "paused";
+  // 结束播放
+  audioListStart(state.playState);
+  // 调用结束评测
+  handleEndEvaluat(true);
+  // 调用自动重复播放
+  autoResetPlay();
 };
 
 /**
  * 播放一直触发的事件
  */
 const handlePlaying = () => {
-	const currentTime = getAudioCurrentTime();
-	const duration = getAudioDuration();
-	state.playProgress = (currentTime / duration) * 100;
-	let item = getNote(currentTime);
+  const currentTime = getAudioCurrentTime();
+  const duration = getAudioDuration();
+  state.playProgress = (currentTime / duration) * 100;
+  let item = getNote(currentTime);
 
-	if (item) {
-		// 选段状态下
-		if (state.sectionStatus && state.section.length === 2) {
-			// 如果开启了预备拍
-			const selectStartItem = state.sectionFirst ? state.sectionFirst : state.section[0];
-			const selectEndItem = state.section[1];
+  if (item) {
+    // 选段状态下
+    if (state.sectionStatus && state.section.length === 2) {
+      // 如果开启了预备拍
+      const selectStartItem = state.sectionFirst ? state.sectionFirst : state.section[0];
+      const selectEndItem = state.section[1];
 
-			if (Math.abs(selectEndItem.endtime - currentTime) < offset_duration) {
-				console.log("选段播放结束");
-				// 如果为选段评测模式
-				if (state.modeType === "evaluating" && state.isSelectMeasureMode) {
-					onEnded();
-					return;
-				}
-				item = selectStartItem;
-				setAudioCurrentTime(selectStartItem.time, selectStartItem.i);
-			}
-		}
-		gotoNext(item);
-	}
+      if (Math.abs(selectEndItem.endtime - currentTime) < offset_duration) {
+        console.log("选段播放结束");
+        // 如果为选段评测模式
+        if (state.modeType === "evaluating" && state.isSelectMeasureMode) {
+          onEnded();
+          return;
+        }
+        item = selectStartItem;
+        setAudioCurrentTime(selectStartItem.time, selectStartItem.i);
+      }
+    }
+    gotoNext(item);
+  }
 
-	metronomeData.metro?.sound(currentTime);
+  metronomeData.metro?.sound(currentTime);
 };
 /** 跳转到指定音符开始播放 */
 export const skipNotePlay = (itemIndex: number, isStart = false) => {
-	const item = state.times[itemIndex];
-	let itemTime = item.time;
-	if (isStart) {
-		itemTime = 0;
-	}
-	if (item) {
-		setAudioCurrentTime(itemTime, itemIndex);
-		gotoNext(item);
-		metronomeData.metro?.sound(itemTime);
-	}
+  const item = state.times[itemIndex];
+  let itemTime = item.time;
+  if (isStart) {
+    itemTime = 0;
+  }
+  if (item) {
+    setAudioCurrentTime(itemTime, itemIndex);
+    gotoNext(item);
+    metronomeData.metro?.sound(itemTime);
+  }
 };
 
 /**
@@ -296,236 +292,233 @@ export const skipNotePlay = (itemIndex: number, isStart = false) => {
  * @param playState 可选: 默认 undefined, 需要切换的状态 play:播放, paused: 暂停
  */
 export const togglePlay = async (playState?: "play" | "paused") => {
-	state.playState = playState ? playState : state.playState === "paused" ? "play" : "paused";
-	// 设置为开始播放时, 如果需要节拍,先播放节拍器
-	if (state.playState === "play" && state.needTick) {
-		const tickend = await handleStartTick();
-		// console.log("🚀 ~ tickend:", tickend)
-		// 节拍器返回false, 取消播放
-		if (!tickend) {
-			state.playState = "paused";
-			return false;
-		}
-	}
-	// 如果选段没有结束, 直接开始播放,清空选段状态
-	if (state.playState == "play") {
-		if (state.sectionStatus && state.section.length < 2) {
-			clearSelection();
-		}
-	}
-	audioListStart(state.playState);
-	return true;
+  state.playState = playState ? playState : state.playState === "paused" ? "play" : "paused";
+  // 设置为开始播放时, 如果需要节拍,先播放节拍器
+  if (state.playState === "play" && state.needTick) {
+    const tickend = await handleStartTick();
+    // console.log("🚀 ~ tickend:", tickend)
+    // 节拍器返回false, 取消播放
+    if (!tickend) {
+      state.playState = "paused";
+      return false;
+    }
+  }
+  // 如果选段没有结束, 直接开始播放,清空选段状态
+  if (state.playState == "play") {
+    if (state.sectionStatus && state.section.length < 2) {
+      clearSelection();
+    }
+  }
+  audioListStart(state.playState);
+  return true;
 };
 /** 结束播放 */
 export const handleStopPlay = () => {
-	state.playState = "paused";
-	audioListStart(state.playState);
+  state.playState = "paused";
+  audioListStart(state.playState);
 };
 
 /** 重置播放为开始 */
 export const resetPlaybackToStart = () => {
-	// 如果为选段状态
-	if (state.sectionStatus && state.section.length === 2) {
-		state.section = formateSelectMearure(state.section);
-		return;
-	}
-	skipNotePlay(0, true);
+  // 如果为选段状态
+  if (state.sectionStatus && state.section.length === 2) {
+    state.section = formateSelectMearure(state.section);
+    return;
+  }
+  skipNotePlay(0, true);
 };
 
 /** 跳转到指定音符 */
 export const gotoCustomNote = (index: number) => {
-	try {
-		state.osmd.cursor.reset();
-	} catch (error) {}
-	for (let i = 0; i < index; i++) {
-		state.osmd.cursor.next();
-	}
+  try {
+    state.osmd.cursor.reset();
+  } catch (error) {}
+  for (let i = 0; i < index; i++) {
+    state.osmd.cursor.next();
+  }
 };
 const setCursorPosition = (note: any, cursor: any) => {
-	if (
-		state.musicRenderType === EnumMusicRenderType.firstTone ||
-		state.musicRenderType === EnumMusicRenderType.fixedTone
-	) {
-		nextTick(() => {
-			let bbox = note.bbox;
-			if (!bbox) {
-				const musicContainer = document.getElementById("musicAndSelection")?.getBoundingClientRect() || {
-					x: 0,
-					y: 0,
-				};
-				const parentLeft = musicContainer.x || 0;
-				const noteEle = document.querySelector(`#vf-${note.svgElement?.attrs?.id}`);
-				if (noteEle) {
-					const noteHead = noteEle.querySelector(".vf-numbered-note-head");
-					const noteHeadBbox = noteHead?.getBoundingClientRect?.();
-					if (noteHeadBbox) {
-						note.bbox = {
-							left: noteHeadBbox.x - parentLeft - noteHeadBbox.width / 4,
-							width: noteHeadBbox.width * 1.5,
-						};
-						bbox = note.bbox;
-					}
-				}
-			}
-			if (!bbox) return;
-			const baseW = state.platform === IPlatform.PC ? 29 : 18;
-			const width = (bbox.width - baseW) / 3;
-			cursor.cursorElement.style.left = bbox.left + "px";
-			cursor.cursorElement.style.transform = `translateX(${width}px)`;
-		});
-	}
+  if (state.musicRenderType === EnumMusicRenderType.firstTone || state.musicRenderType === EnumMusicRenderType.fixedTone) {
+    nextTick(() => {
+      let bbox = note.bbox;
+      if (!bbox) {
+        const musicContainer = document.getElementById("musicAndSelection")?.getBoundingClientRect() || {
+          x: 0,
+          y: 0,
+        };
+        const parentLeft = musicContainer.x || 0;
+        const noteEle = document.querySelector(`#vf-${note.svgElement?.attrs?.id}`);
+        if (noteEle) {
+          const noteHead = noteEle.querySelector(".vf-numbered-note-head");
+          const noteHeadBbox = noteHead?.getBoundingClientRect?.();
+          if (noteHeadBbox) {
+            note.bbox = {
+              left: noteHeadBbox.x - parentLeft - noteHeadBbox.width / 4,
+              width: noteHeadBbox.width * 1.5,
+            };
+            bbox = note.bbox;
+          }
+        }
+      }
+      if (!bbox) return;
+      const baseW = state.platform === IPlatform.PC ? 29 : 18;
+      const width = (bbox.width - baseW) / 3;
+      cursor.cursorElement.style.left = bbox.left + "px";
+      cursor.cursorElement.style.transform = `translateX(${width}px)`;
+    });
+  }
 };
 /** 跳转到下一个音符 */
 export const gotoNext = (note: any) => {
-	const num = note.i;
+  const num = note.i;
 
-	if (state.activeNoteIndex === note.i) {
-		try {
-			setCursorPosition(note, state.osmd.cursor);
-		} catch (error) {
-			console.log(error);
-		}
-		return;
-	}
-	const osmd = state.osmd;
-	let prev = state.activeNoteIndex;
-	state.activeNoteIndex = num;
-	state.activeMeasureIndex = note.MeasureNumberXML;
+  if (state.activeNoteIndex === note.i) {
+    try {
+      setCursorPosition(note, state.osmd.cursor);
+    } catch (error) {
+      console.log(error);
+    }
+    return;
+  }
+  const osmd = state.osmd;
+  let prev = state.activeNoteIndex;
+  state.activeNoteIndex = num;
+  state.activeMeasureIndex = note.MeasureNumberXML;
 
-	if (prev && num - prev === 1) {
-		osmd.cursor.next();
-	} else if (prev && num - prev > 0) {
-		while (num - prev > 0) {
-			prev++;
-			osmd.cursor.next();
-		}
-	} else {
-		gotoCustomNote(num);
-	}
-	try {
-		setCursorPosition(note, state.osmd.cursor);
-	} catch (error) {
-		console.log(error);
-	}
+  if (prev && num - prev === 1) {
+    osmd.cursor.next();
+  } else if (prev && num - prev > 0) {
+    while (num - prev > 0) {
+      prev++;
+      osmd.cursor.next();
+    }
+  } else {
+    gotoCustomNote(num);
+  }
+  try {
+    setCursorPosition(note, state.osmd.cursor);
+  } catch (error) {
+    console.log(error);
+  }
 
-	scrollViewNote();
+  scrollViewNote();
 };
 /** 获取指定音符 */
 export const getNote = (currentTime: number) => {
-	const times = state.times;
-	const len = state.times.length;
-	/** 播放超过了最后一个音符的时间,直接结束, 2秒误差 */
-	if (currentTime > times[len - 1].endtime + 2) {
-		onEnded();
-		return;
-	}
-	let _item = null as any;
-	for (let i = state.activeNoteIndex; i < len; i++) {
-		const item = times[i];
-		const prevItem = times[i - 1];
-		if (currentTime >= item.time) {
-			if (!prevItem || item.time != prevItem.time) {
-				_item = item;
-			}
-		} else {
-			break;
-		}
-	}
-	// console.log("activeNoteIndex", currentTime, state.activeNoteIndex, _item.i);
-	return _item;
+  const times = state.times;
+  const len = state.times.length;
+  /** 播放超过了最后一个音符的时间,直接结束, 2秒误差 */
+  if (currentTime > times[len - 1].endtime + 2) {
+    onEnded();
+    return;
+  }
+  let _item = null as any;
+  for (let i = state.activeNoteIndex; i < len; i++) {
+    const item = times[i];
+    const prevItem = times[i - 1];
+    if (currentTime >= item.time) {
+      if (!prevItem || item.time != prevItem.time) {
+        _item = item;
+      }
+    } else {
+      break;
+    }
+  }
+  // console.log("activeNoteIndex", currentTime, state.activeNoteIndex, _item.i);
+  return _item;
 };
 
 /** 重播 */
 export const handleResetPlay = () => {
-	resetPlaybackToStart();
-	// 如果是暂停, 直接播放
-	togglePlay("play");
+  resetPlaybackToStart();
+  // 如果是暂停, 直接播放
+  togglePlay("play");
 };
 /** 设置速度 */
 export const handleSetSpeed = (speed: number) => {
-	setStorageSpeed(state.examSongId, speed);
-	state.speed = speed;
+  setStorageSpeed(state.examSongId, speed);
+  state.speed = speed;
 };
 /** 清除选段状态 */
 export const clearSelection = () => {
-	state.sectionStatus = false;
-	state.section = [];
-	closeToast();
+  state.sectionStatus = false;
+  state.section = [];
+  closeToast();
 };
 
 /** 开启选段 */
 export const handleChangeSection = () => {
-	// 如果开启了选段,再次点击取消选段
-	if (state.sectionStatus) {
-		togglePlay("paused");
-		skipNotePlay(0, true);
-		clearSelection();
-		return;
-	}
-	state.sectionStatus = true;
-	// 开启
-	if (state.sectionStatus) {
-		togglePlay("paused");
-	}
-	showToast({
-		message: "请选择开始小节",
-		duration: 0,
-		position: "top",
-		className: "selectionToast",
-	});
+  // 如果开启了选段,再次点击取消选段
+  if (state.sectionStatus) {
+    togglePlay("paused");
+    skipNotePlay(0, true);
+    clearSelection();
+    return;
+  }
+  state.sectionStatus = true;
+  // 开启
+  if (state.sectionStatus) {
+    togglePlay("paused");
+  }
+  showToast({
+    message: "请选择开始小节",
+    duration: 0,
+    position: "top",
+    className: "selectionToast",
+  });
 };
 
 /** 效验并格式化选段小节 */
 const formateSelectMearure = (_list: any[]): any[] => {
-	if (!_list.length) return [];
-	const list = _list.sort((a, b) => a.time - b.time);
-	const startXml = list[0]?.measureOpenIndex;
-	const endXml = list.last()?.measureOpenIndex;
-	const selectStartMeasure = state.times.filter((n: any) => startXml === n.measureOpenIndex) || [];
-	const selectEndMeasure = state.times.filter((n: any) => endXml === n.measureOpenIndex) || [];
-	// 没有找到选段小节
-	if (!selectStartMeasure.length || !selectEndMeasure.length) {
-		clearSelection();
-		return [];
-	}
-	list[0] = selectStartMeasure[0];
-	list[1] = selectEndMeasure.last();
-	let startItemINdex = list[0].i;
-	// 开启预备拍
-	if (state.isOpenPrepare) {
-		const startXmlIndex = list[0].MeasureNumberXML;
-		state.sectionFirst = state.times.find((n: any) => startXmlIndex - n.MeasureNumberXML === 1);
-		startItemINdex = state.sectionFirst ? state.sectionFirst.i : startItemINdex;
-	}
-	skipNotePlay(startItemINdex, startItemINdex === 0);
-	return list;
+  if (!_list.length) return [];
+  const list = _list.sort((a, b) => a.time - b.time);
+  const startXml = list[0]?.measureOpenIndex;
+  const endXml = list.last()?.measureOpenIndex;
+  const selectStartMeasure = state.times.filter((n: any) => startXml === n.measureOpenIndex) || [];
+  const selectEndMeasure = state.times.filter((n: any) => endXml === n.measureOpenIndex) || [];
+  // 没有找到选段小节
+  if (!selectStartMeasure.length || !selectEndMeasure.length) {
+    clearSelection();
+    return [];
+  }
+  list[0] = selectStartMeasure[0];
+  list[1] = selectEndMeasure.last();
+  let startItemINdex = list[0].i;
+  // 开启预备拍
+  if (state.isOpenPrepare) {
+    const startXmlIndex = list[0].MeasureNumberXML;
+    state.sectionFirst = state.times.find((n: any) => startXmlIndex - n.MeasureNumberXML === 1);
+    startItemINdex = state.sectionFirst ? state.sectionFirst.i : startItemINdex;
+  }
+  skipNotePlay(startItemINdex, startItemINdex === 0);
+  return list;
 };
 
 /** 选择选段 */
 export const handleSelection = (item: any) => {
-	if (!state.sectionStatus || state.section.length > 1) return;
-	if (state.section.length !== 2 && item) {
-		state.section.push(item);
-		if (state.section.length === 2) {
-			state.section = formateSelectMearure(state.section);
-			closeToast();
-		}
-	}
-	if (state.section.length === 1) {
-		showToast({
-			message: "请选择结束小节",
-			duration: 0,
-			position: "top",
-			className: "selectionToast",
-		});
-	}
+  if (!state.sectionStatus || state.section.length > 1) return;
+  if (state.section.length !== 2 && item) {
+    state.section.push(item);
+    if (state.section.length === 2) {
+      state.section = formateSelectMearure(state.section);
+      closeToast();
+    }
+  }
+  if (state.section.length === 1) {
+    showToast({
+      message: "请选择结束小节",
+      duration: 0,
+      position: "top",
+      className: "selectionToast",
+    });
+  }
 };
 
 /** 直接设置选段 */
 export const hanldeDirectSelection = (list: any[]) => {
-	if (!Array.isArray(list) || list.length !== 2) return;
-	state.sectionStatus = true;
-	state.section = formateSelectMearure(list);
+  if (!Array.isArray(list) || list.length !== 2) return;
+  state.sectionStatus = true;
+  state.section = formateSelectMearure(list);
 };
 let offsetTop = 0;
 /**
@@ -534,44 +527,44 @@ let offsetTop = 0;
  * @returns void
  */
 export const scrollViewNote = () => {
-	const cursorElement = document.getElementById("cursorImg-0")!;
-	const musicAndSelection = document.getElementById(state.scrollContainer)!;
-	if (!cursorElement || !musicAndSelection || offsetTop === cursorElement.offsetTop) return;
-	offsetTop = cursorElement.offsetTop;
-	if (offsetTop > 50) {
-		musicAndSelection.scrollTo({
-			top: (offsetTop - 50) * state.musicZoom,
-			behavior: "smooth",
-		});
-	} else {
-		musicAndSelection.scrollTo({
-			top: 0,
-			behavior: "smooth",
-		});
-	}
+  const cursorElement = document.getElementById("cursorImg-0")!;
+  const musicAndSelection = document.getElementById(state.scrollContainer)!;
+  if (!cursorElement || !musicAndSelection || offsetTop === cursorElement.offsetTop) return;
+  offsetTop = cursorElement.offsetTop;
+  if (offsetTop > 50) {
+    musicAndSelection.scrollTo({
+      top: (offsetTop - 50) * state.musicZoom,
+      behavior: "smooth",
+    });
+  } else {
+    musicAndSelection.scrollTo({
+      top: 0,
+      behavior: "smooth",
+    });
+  }
 };
 
 /** 检测是否是节奏练习 */
 export const isRhythmicExercises = () => {
-	return state.examSongName.indexOf("节奏练习") > -1;
+  return state.examSongName.indexOf("节奏练习") > -1;
 };
 
 /** 重置状态 */
 export const handleRessetState = () => {
-	if (state.modeType === "evaluating") {
-		handleStartEvaluat();
-	} else if (state.modeType === "practise") {
-		togglePlay("paused");
-	} else if (state.modeType === "follow") {
-		toggleFollow(false);
-	}
+  if (state.modeType === "evaluating") {
+    handleStartEvaluat();
+  } else if (state.modeType === "practise") {
+    togglePlay("paused");
+  } else if (state.modeType === "follow") {
+    toggleFollow(false);
+  }
 };
 export default state;
 
 /** 初始化评测音频 */
 export const evaluatCreateMusicPlayer = () => {
-	return api_createMusicPlayer({
-		musicSrc: state.accompany || state.music, // 曲谱音频url
-		tuneSrc: "https://cloud-coach.ks3-cn-beijing.ksyuncs.com/1686725501654check_music1_(1).mp3", //效音音频url
-	});
+  return api_createMusicPlayer({
+    musicSrc: state.accompany || state.music, // 曲谱音频url
+    tuneSrc: "https://cloud-coach.ks3-cn-beijing.ksyuncs.com/1686725501654check_music1_(1).mp3", //效音音频url
+  });
 };