瀏覽代碼

Merge branch 'feature-tianyong-newVersion' into ktyq-test-new

TIANYONG 1 年之前
父節點
當前提交
a3d6be250a

+ 5 - 0
src/helpers/communication.ts

@@ -511,6 +511,11 @@ export const api_remove_finishDelayCheck = (callback: any) => {
 	removeListenerMessage("finishDelayCheck", callback);
 };
 
+/** 取消监听APP取消延迟检测 */
+export const api_remove_cancelDelayCheck = (callback: any) => {
+	removeListenerMessage("cancelDelayCheck", callback);
+};
+
 /** 监听APP播放进度 */
 export const simple_playProgress = (callback: any) => {
 	listenerMessage("api_playProgress", callback);

+ 1 - 1
src/helpers/customMusicScore.ts

@@ -574,7 +574,7 @@ export const resetFormate = () => {
 		}
 
 	}
-	if (!state.isCombineRender) {
+	if (!state.isCombineRender && state.isSingleLine) {
 		transSinglePage();
 	}
 	// setTimeout(() => this.resetGlobalText());

+ 3 - 1
src/page-instrument/evaluat-model/evaluat-result/index.tsx

@@ -48,6 +48,8 @@ export default defineComponent({
       console.log("结束", evaluatingData.resultData);
       /** 生成评测记录的时候,记录当前评测的谱面类型,用于评测报告默认展示的谱面类型 */
       evaluatingData.resultData.scoreData.musicType = state.musicRenderType;
+      // 评测的速度,如果是选段,则选选段开头小节的速度
+      const evaluatSpeed = state.sectionStatus && state.section.length === 2 && state.section[0].measureSpeed ? state.section[0].measureSpeed * state.basePlayRate : state.speed;      
       const body = {
         deviceType: browser().android ? "ANDROID" : "IOS", // 设备类型
         intonation: evaluatingData.resultData.intonation, // 音准
@@ -57,7 +59,7 @@ export default defineComponent({
         behaviorId: getBehaviorId(), // 行为id
         sourceTime: getAudioDuration(), // 音频时长
         partIndex: state.partIndex, // 音轨
-        speed: state.speed, // 速度
+        speed: evaluatSpeed, // 速度
         practiceSource: query.workRecord ? "LESSON_TRAINING" : "EVALUATION", // 练习来源
         score: evaluatingData.resultData.score, // 分数
         clientType: storeData.user.clientType, // 客户端类型

+ 30 - 7
src/page-instrument/evaluat-model/index.tsx

@@ -1,5 +1,5 @@
 import { Transition, defineComponent, onMounted, reactive, watch, defineAsyncComponent, computed, onUnmounted } from "vue";
-import { connectWebsocket, evaluatingData, handleEndBegin, handleStartBegin, handleStartEvaluat, handleViewReport, startCheckDelay, checkUseEarphone, handleCancelEvaluat, checkMinInterval } from "/src/view/evaluating";
+import { connectWebsocket, evaluatingData, handleEndBegin, handleStartBegin, handleStartEvaluat, handleViewReport, startCheckDelay, checkUseEarphone, handleCancelEvaluat, checkMinInterval, handleEndEvaluat } from "/src/view/evaluating";
 import Earphone from "./earphone";
 import styles from "./index.module.less";
 import SoundEffect from "./sound-effect";
@@ -10,7 +10,7 @@ import { getNoteByMeasuresSlursStart } from "/src/helpers/formateMusic";
 import { Icon, Popup, showToast, closeToast, showLoadingToast } from "vant";
 import EvaluatResult from "./evaluat-result";
 import EvaluatAudio from "./evaluat-audio";
-import { api_getDeviceDelay, api_openAdjustRecording, api_proxyServiceMessage, api_videoUpdate, getEarphone, api_back, api_startDelayCheck, api_cancelDelayCheck, api_closeDelayCheck, api_finishDelayCheck, api_retryEvaluating, api_remove_finishDelayCheck } from "/src/helpers/communication";
+import { api_getDeviceDelay, api_openAdjustRecording, api_proxyServiceMessage, api_videoUpdate, getEarphone, api_back, api_startDelayCheck, api_cancelDelayCheck, api_remove_cancelDelayCheck, api_closeDelayCheck, api_finishDelayCheck, api_retryEvaluating, api_remove_finishDelayCheck } from "/src/helpers/communication";
 import EvaluatShare from "./evaluat-share";
 import { Vue3Lottie } from "vue3-lottie";
 import startData from "./data/start.json";
@@ -266,6 +266,8 @@ export default defineComponent({
       // rate = parseFloat(rate.toFixed(2));
       console.log("速度比例", rate, "速度", state.speed);
       calculateInfo = formatTimes();
+      // 评测的速度,如果是选段,则选选段开头小节的速度
+      const evaluatSpeed = state.sectionStatus && state.section.length === 2 && state.section[0].measureSpeed ? state.section[0].measureSpeed * state.basePlayRate : state.speed;
       const content = {
         musicXmlInfos: calculateInfo.datas,
         subjectId: state.musicalCode,
@@ -278,7 +280,7 @@ export default defineComponent({
         clientId: storeData.platformType === "STUDENT" ? "student" : storeData.platformType === "TEACHER" ? "teacher" : "education",
         hertz: state.setting.frequency,
         reactionTimeMs: state.setting.reactionTimeMs ? Number(state.setting.reactionTimeMs) : 0,
-        speed: state.speed,
+        speed: evaluatSpeed,
         heardLevel: state.setting.evaluationDifficulty,
         // beatLength: Math.round((state.fixtime * 1000) / rate),
         beatLength: actualBeatLength,
@@ -327,8 +329,8 @@ export default defineComponent({
       } else if (type === "selfCancel") {
         // 再来一次,需要手动取消评测,不生成评测记录,不显示评测结果弹窗
         evaluatingData.oneselfCancleEvaluating = true;
-        handleCancelEvaluat();
-        startBtnHandle();
+        // handleCancelEvaluat();
+        handleEndEvaluat(true, 'selfCancel');
       }
       resetPlaybackToStart();
       evaluatingData.resulstMode = false;
@@ -443,6 +445,18 @@ export default defineComponent({
       }
     );
 
+    // 手动取消评测,需要自动再次评测
+    watch(
+      () => evaluatingData.hideResultModal,
+      (val) => {
+        if (val && evaluatingData.oneselfCancleEvaluating) {
+          setTimeout(() => {
+            startBtnHandle();
+          }, 500);
+        }
+      }
+    );
+
     onMounted(async () => {
       // 如果打开了延迟检测开关,需要先发送开始检测的消息
       const delayData = await api_getDeviceDelay();
@@ -462,6 +476,7 @@ export default defineComponent({
     
     onUnmounted(() => {
       api_remove_finishDelayCheck(handleFinishDelayCheck);
+      api_remove_cancelDelayCheck(handleCancelDelayCheck);
 			clearTimeout(checkErjiTimer);
       checkErjiTimer = null;
 		});
@@ -482,12 +497,20 @@ export default defineComponent({
             <>
               <img class={styles.iconBtn} src={headImg("icon_reset.png")} onClick={() => {
                 // 校验评测最小间隔时间
-                checkMinInterval()
+                const currentTime = +new Date();
+                // 开始评测和结束评测的间隔时间小于800毫秒,则不处理
+                if (currentTime - evaluatingData.recordingTime < 800) {
+                  return;
+                }
                 handleEvaluatResult("selfCancel")
               }} />
               <img class={styles.iconBtn} src={headImg("submit.png")} onClick={() => {
                 // 校验评测最小间隔时间
-                checkMinInterval()
+                const currentTime = +new Date();
+                // 开始评测和结束评测的间隔时间小于800毫秒,则不处理
+                if (currentTime - evaluatingData.recordingTime < 800) {
+                  return;
+                }
                 handleEndBegin()
               }} />
             </>

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

@@ -150,6 +150,10 @@
                     }
                 }
             }
+            .disableSpend {
+                opacity: 0.4;
+                pointer-events: none;
+            }
             .metronome{
                 margin-top: 18px;
                 display: flex;

+ 4 - 3
src/page-instrument/header-top/speed/index.tsx

@@ -5,12 +5,13 @@ import { headData } from "../index"
 import { headImg } from "../image";
 import state, { handleSetSpeed, resetBaseRate } from "../../../state";
 import { metronomeData } from "../../../helpers/metronome"; 
+import { getQuery } from "/src/utils/queryString";
 
 export default defineComponent({
 	name: "speed",
 	setup() {
 		const speed = ref(state.speed);
-
+		const query: any = getQuery();
 		const minusSpeed = () => {
 			let canSpeed = Math.max(speed.value - 1, 45);
 			canSpeed = Math.min(canSpeed, 270);
@@ -58,7 +59,7 @@ export default defineComponent({
 				<div class={styles.content}>
 					<div class={styles.conBox}>
 						<div class={styles.tit}>速度</div>
-						<div class={styles.spendCon}>
+						<div class={[styles.spendCon, query.workRecord && styles.disableSpend]}>
 							<img src={headImg("cutImg.png")} class={[styles.btn]} onClick={minusSpeed} />
 							<div class={styles.sliderCon}>
 								<Slider class={styles.slider} max={270} min={speed.value < 45 ? speed.value : 45} v-model={speed.value}>
@@ -73,7 +74,7 @@ export default defineComponent({
 							</div>
 							<img src={headImg("addImg.png")} class={[styles.btn]} onClick={plusSpeed} />	
 						</div>
-						<div class={styles.speedSel}>
+						<div class={[styles.speedSel, query.workRecord && styles.disableSpend]}>
 							<div onClick={resetCurrentSpeed}>原速</div>
 							<div onClick={()=>{ speed.value = 70 }}>70</div>
 							<div onClick={()=>{ speed.value = 80 }}>80</div>

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

@@ -107,7 +107,7 @@ export default defineComponent({
         const { isSpecialShapedScreen, notchHeight } = screenData.content;
         if (isSpecialShapedScreen) {
           // 安卓取刘海值
-          detailData.paddingLeft = browsInfo.android ? notchHeight : 26 + "px";
+          detailData.paddingLeft = 27 + "px";
         }
       }
     };

+ 18 - 13
src/page-instrument/view-detail/smoothAnimation/index.ts

@@ -19,11 +19,11 @@ type smoothAnimationType = {
    osmdCanvasPageDom: null | HTMLElement
    osdmScrollDom: null | HTMLElement
    osdmScrollDomWith: number
+   osdmScrollDomOffsetWidth: number
    selectionBoxDom: null | HTMLElement
    pointsPos: pointsPosType
    translateXNum: number
    aveSpeed: number
-   clientWidth: number
 }
 
 const _numberOfSegments = 58 // 中间切割线的个数
@@ -39,11 +39,11 @@ export const smoothAnimationState = {
    osmdCanvasPageDom: null,
    osdmScrollDom: null,
    osdmScrollDomWith: 0,
+   osdmScrollDomOffsetWidth: 0,
    selectionBoxDom: null,
    pointsPos: [], // 计算之后的点坐标数组
    translateXNum: 0, // 当前谱面的translateX的距离   谱面的位置信息 由translateX和scrollLeft的偏移一起决定
-   aveSpeed: 0, // 谱面的一帧的平均速度
-   clientWidth: 0 // 屏幕宽度
+   aveSpeed: 0 // 谱面的一帧的平均速度
 } as smoothAnimationType
 
 // 监听显示与隐藏
@@ -104,10 +104,12 @@ export function destroySmoothAnimation() {
       smoothBotDom: null,
       osmdCanvasPageDom: null,
       osdmScrollDom: null,
+      osdmScrollDomWith: 0,
+      osdmScrollDomOffsetWidth: 0,
+      selectionBoxDom: null,
       pointsPos: [],
       translateXNum: 0,
-      aveSpeed: 0,
-      clientWidth: 0
+      aveSpeed: 0
    })
 }
 
@@ -181,9 +183,12 @@ export function moveSmoothAnimation(progress: number, activeIndex: number, isMov
  */
 function move_osmd(nowPointsPos: pointsPosType[0]) {
    const speed = smoothAnimationState.aveSpeed * (state.speed / 60)
-   const clientWidth = smoothAnimationState.clientWidth
-   const clientMidWidth = smoothAnimationState.clientWidth / 2
-   const { left, right, width } = smoothAnimationState.smoothBotDom!.getBoundingClientRect()
+   // 视口宽度
+   const clientWidth = smoothAnimationState.osdmScrollDomWith
+   const clientMidWidth = clientWidth / 2
+   let { left, right, width } = smoothAnimationState.smoothBotDom!.getBoundingClientRect()
+   left -= smoothAnimationState.osdmScrollDomOffsetWidth
+   right -= smoothAnimationState.osdmScrollDomOffsetWidth
    const midBotNum = left + width / 2
    // 分阶段移动
    if (right > clientWidth) {
@@ -253,10 +258,11 @@ function smoothAnimationMove(pos: { x: number; y: number }, pointsPos: pointsPos
    smoothAnimationState.canvasCtx && drawSmoothCurve(smoothAnimationState.canvasCtx, pointsPos, progresspointsPos)
 }
 /**
- * 计算屏幕宽度
+ * 计算视口宽度
  */
-function calcClientWidth() {
-   smoothAnimationState.clientWidth = document.body.clientWidth
+export function calcClientWidth() {
+   smoothAnimationState.osdmScrollDomWith = smoothAnimationState.osdmScrollDom?.offsetWidth || 0
+   smoothAnimationState.osdmScrollDomOffsetWidth = smoothAnimationState.osdmScrollDom?.offsetLeft || 0
 }
 /**
  * 创建dom
@@ -265,7 +271,6 @@ function createSmoothAnimation() {
    // osdmScrollDom
    const osdmScrollDom = document.querySelector("#musicAndSelection") as HTMLElement
    smoothAnimationState.osdmScrollDom = osdmScrollDom
-   smoothAnimationState.osdmScrollDomWith = osdmScrollDom?.offsetWidth | 0
    // osmdCanvasPage
    const osmdCanvasPageDom = document.querySelector("#osmdCanvasPage1") as HTMLElement
    smoothAnimationState.osmdCanvasPageDom = osmdCanvasPageDom
@@ -285,7 +290,7 @@ function createSmoothAnimation() {
    const smoothCanvasDom = document.createElement("canvas")
    smoothCanvasDom.className = "smoothCanvas"
    smoothAnimationState.canvasDom = smoothCanvasDom
-   smoothAnimationState.canvasDomWith = osmdCanvasPageDom?.offsetWidth | 0
+   smoothAnimationState.canvasDomWith = osmdCanvasPageDom?.offsetWidth || 0
    smoothCanvasDom.width = smoothAnimationState.canvasDomWith
    smoothCanvasDom.height = smoothAnimationState.canvasDomHeight
    smoothAnimationState.canvasCtx = smoothCanvasDom.getContext("2d")

文件差異過大導致無法顯示
+ 0 - 0
src/page-instrument/view-evaluat-report/component/share-top/image/audioBga.json


二進制
src/page-instrument/view-evaluat-report/component/share-top/image/videobg.png


+ 12 - 3
src/page-instrument/view-evaluat-report/component/share-top/index.module.less

@@ -6,7 +6,9 @@
     height: 100%;
     flex-shrink: 0;
     padding: 10px 22px;
-    background-color: rgba(6, 34, 87, 0.45);
+    background-color: rgba(6, 34, 87, 0.8);
+    backdrop-filter: blur(3px);
+    -webkit-backdrop-filter: blur(3px);
     position: relative;
 }
 
@@ -120,7 +122,7 @@
     position: absolute;
     left: 50%;
     top: 50%;
-    transform: translate(-50%, -50%);
+    transform: translate(-35%, -50%);
 
     .cItem {
         width: 64px;
@@ -231,6 +233,7 @@
             border-radius: 16px;
             width: 100%;
             height: 100%;
+            box-shadow: 4px -3px 6px 0px #B2E8FF;
 
             .plyr__control.plyr__control--overlaid {
                 width: 48px;
@@ -247,6 +250,9 @@
             .plyr__controls {
                 background: initial;
                 padding: 0 20px 13px;
+                opacity: 1 !important;
+                transform: translateY(0) !important;
+                pointer-events: initial !important;
 
                 .plyr__controls__item.plyr__control {
                     padding: 0;
@@ -296,6 +302,7 @@
                         width: 12px;
                         height: 12px;
                         margin-top: -4px;
+                        box-shadow: initial;
                     }
 
                     .plyr__progress__buffer {
@@ -332,6 +339,7 @@
         background-size: 100% 100%;
         position: relative;
         border-radius: 16px;
+        box-shadow: 4px -3px 6px 0px #B2E8FF;
 
         .audioBga {
             width: 100%;
@@ -358,6 +366,7 @@
                 height: initial;
                 left: 0;
                 bottom: 0;
+                box-shadow: initial;
             }
         }
 
@@ -442,7 +451,7 @@
         position: absolute;
         width: 154px;
         left: 50%;
-        top: -6px;
+        top: -5px;
         transform: translateX(-50%);
     }
 }

+ 3 - 3
src/page-instrument/view-evaluat-report/component/share-top/index.tsx

@@ -227,7 +227,7 @@ export default defineComponent({
               {/* <div class={styles.lcName}>{state.examSongName}</div> */}
               <Title class={styles.lcName} text={state.examSongName} rightView={false} />
               <div class={styles.lcScore}>
-                {level[scoreData.value.heardLevel]}|综合分数:{scoreData.value.score}分
+                {level[scoreData.value.heardLevel]}|速度:{scoreData.value.speed}|综合分数:{scoreData.value.score}分
               </div>
             </div>
           </div>
@@ -307,7 +307,7 @@ export default defineComponent({
           {/* 五线谱,简谱类型提示  */}
           {scoreData.value.musicType === "staff" ? (
             <>
-              {state.isPercussion ? null : (
+              {(
                 <div class={styles.demos}>
                   {itemType.value === "intonation" && (
                     <>
@@ -368,7 +368,7 @@ export default defineComponent({
             </>
           ) : (
             <>
-              {state.isPercussion ? null : (
+              {(
                 <div class={styles.demos}>
                   {itemType.value === "intonation" && (
                     <>

+ 18 - 13
src/page-instrument/view-evaluat-report/index.tsx

@@ -71,6 +71,7 @@ export default defineComponent({
       integrity: 0,
       intonation: 0,
       score: 0,
+      speed: 0,
       heardLevel: "",
       itemType: "intonation",
       musicType: "staff",
@@ -163,6 +164,7 @@ export default defineComponent({
     };
 
     onMounted(async () => {
+      state.isEvaluatReport = true;
       const res = await api_musicPracticeRecordDetail(query.id);
       state.partIndex = Number(res?.data?.partIndex);
       let resultData = {} as any;
@@ -174,7 +176,7 @@ export default defineComponent({
       // console.log("🚀 ~ resultData:", resultData);
       // @ts-ignore
       // resultData.musicalNotesPlayStats?.notesData.forEach((item) => item.rhythmicAssessment.result = 'EARLY')
-      console.log('结果11')
+      console.log('结果11',resultData)
       detailData.musicalNotesPlayStats = resultData.musicalNotesPlayStats?.notesData || [];
       detailData.userMeasureScore = resultData.userMeasureScore || {};
 
@@ -183,8 +185,8 @@ export default defineComponent({
       scoreData.integrity = res.data?.integrity;
       scoreData.intonation = res.data?.intonation;
       scoreData.score = res.data?.score;
+      scoreData.speed = res.data?.speed;
       scoreData.videoFilePath = res.data?.videoFilePath || res.data?.recordFilePath;
-      state.isEvaluatReport = true;
       await getMusicDetail(resultData.musicalNotesPlayStats?.examSongId);
       // 从练习记录进入评测报告,默认显示五线谱
       // if (!query.musicRenderType) {
@@ -193,6 +195,8 @@ export default defineComponent({
       // 评测报告展示什么类型的谱面
       state.isSingleLine = false;
       scoreData.musicType = query.musicRenderType ? query.musicRenderType : resultData.musicType ? resultData.musicType : state.musicRenderType;
+      // @ts-ignore
+      state.musicRenderType = scoreData.musicType;
       detailData.isLoading = false;
       // Promise.all([
       // 	getMusicSheetDetail(resultData.musicalNotesPlayStats?.examSongId),
@@ -272,7 +276,11 @@ export default defineComponent({
           const stemEl = document.getElementById("vf-" + active.id + "-stem");
           let errType = scoreData.itemType === "cadence" ? note.rhythmicAssessment.result : note.pitchAssessment.result;
           // console.log(1111222,errType)
-          const isNeedCopyElement = scoreData.itemType === "integrity" ? false : ["HIGH", "LOW", "EARLY", "LATE"].includes(errType);
+          /**
+           * 新版小酷AI不需要在当前的音符复制出来一个音符,所以注释掉isNeedCopyElement和copySvg
+           */
+          // const isNeedCopyElement = scoreData.itemType === "integrity" ? false : ["HIGH", "LOW", "EARLY", "LATE"].includes(errType);
+          const isNeedCopyElement = false;
           if (scoreData.itemType === "integrity") {
             errType = errType = note.pitchAssessment.result === "HIGH" || note.pitchAssessment.result === "LOW" || note.pitchAssessment.result === "WRONG" ? "RIGHT" : errType;
           }
@@ -295,14 +303,14 @@ export default defineComponent({
             if (scoreData.musicType === "staff") {
               stemEl?.classList.add(colorsClass.RIGHT);
               svgEl?.classList.add(colorsClass.RIGHT);
-              copySvg = svgEl.querySelector(".vf-notehead")!.cloneNode(true) as SVGSVGElement;
+              // copySvg = svgEl.querySelector(".vf-notehead")!.cloneNode(true) as SVGSVGElement;
             } else {
               //copySvg = svgEl.querySelector('.vf-numbered-note-head')!.cloneNode(true) as SVGSVGElement
 
               if (isNeedCopyElement) {
                 svgEl?.classList.add(styles.inaccuracy);
                 const targetId = errType === "HIGH" ? "topSvg" : errType === "LOW" ? "bottomSvg" : errType === "EARLY" ? "leftSvg" : errType === "LATE" ? "rightSvg" : "";
-                copySvg = document.getElementById(targetId)!.cloneNode(true) as SVGSVGElement;
+                // copySvg = document.getElementById(targetId)!.cloneNode(true) as SVGSVGElement;
                 const { width, height } = svgEl.getBoundingClientRect() || {};
                 // @ts-ignore
                 let { x, y } = svgEl?.getBBox() || {};
@@ -322,18 +330,15 @@ export default defineComponent({
               // svgEl.prepend(rect);
             }
             if (scoreData.musicType === "staff") {
-              copySvg.style.transform = getOffsetPosition(errType);
-              //svgEl.style.opacity = '.7'
+              // copySvg.style.transform = getOffsetPosition(errType);
               if (stemEl) {
-                //stemEl.style.opacity = '.7'
+                //
               }
             }
-            copySvg.id = "vf-" + active.id + "-copy";
-            copySvg?.classList.add(colorsClass[errType]);
-            // stemEl?.classList.add(colorsClass.RIGHT)
+            // copySvg.id = "vf-" + active.id + "-copy";
+            // copySvg?.classList.add(colorsClass[errType]);
             // @ts-ignore
-            state.osmd?.container.querySelector("svg")!.insertAdjacentElement("afterbegin", copySvg);
-            // svgEl?.parentElement?.appendChild(copySvg)
+            // state.osmd?.container.querySelector("svg")!.insertAdjacentElement("afterbegin", copySvg);
           }
         }, 300);
       }

+ 6 - 4
src/state.ts

@@ -15,7 +15,7 @@ import { getMusicSheetDetail } from "./utils/baseApi"
 import { getQuery } from "/src/utils/queryString";
 import { followData, skipNotePractice } from "/src/view/follow-practice/index"
 import { changeSongSourceByBate } from "/src/view/audio-list"
-import { moveSmoothAnimation, smoothAnimationState, moveSmoothAnimationByPlayTime, moveTranslateXNum, destroySmoothAnimation } from "/src/page-instrument/view-detail/smoothAnimation"
+import { moveSmoothAnimation, smoothAnimationState, moveSmoothAnimationByPlayTime, moveTranslateXNum, destroySmoothAnimation, calcClientWidth } from "/src/page-instrument/view-detail/smoothAnimation"
 import { storeData } from "/src/store";
 import { downloadXmlStr } from "./view/music-score"
 import { musicScoreRef } from "/src/page-instrument/view-detail/index"
@@ -1545,6 +1545,9 @@ const setState = (data: any, index: number) => {
    * STAVE("五线谱"),JIAN("固定调"),FIRST("首调"),
    */
   musicalRenderType = data.scoreType === 'STAVE' ? 'staff' : data.scoreType === 'JIAN' ? 'fixedTone' : data.scoreType === 'FIRST' ? '' : 'firstTone';
+  if (!state.isEvaluatReport) {
+    state.musicRenderType = query.musicRenderType || musicalRenderType || EnumMusicRenderType.firstTone;  
+  }
   state.musicRenderType = query.musicRenderType || musicalRenderType || EnumMusicRenderType.firstTone;  
   /**
    * TODO:摇篮曲特殊处理
@@ -1858,6 +1861,7 @@ watch(
 
 /** 刷新谱面 */
 export const refreshMusicSvg = () => {
+  clearSelection();
   resetBaseRate();
   state.activeMeasureIndex = -1;
   // 销毁旋律线
@@ -1872,9 +1876,7 @@ watch(
     // 有字符 并且是竖向指法 并且是一行谱
     if(state.fingeringInfo?.name && state.fingeringInfo.direction === "vertical" && state.isSingleLine){
       nextTick(() => {
-        if (smoothAnimationState.osdmScrollDom) {
-          smoothAnimationState.osdmScrollDomWith = smoothAnimationState.osdmScrollDom.offsetWidth | 0
-        }
+        calcClientWidth()
       })
     }
     // 如果有指法,并且是竖向指法时,切换指法时,谱面宽度变化,需要重新渲染谱面

+ 10 - 7
src/view/evaluating/index.tsx

@@ -486,9 +486,10 @@ const recordStartTimePoint = async (res?: IPostMessage) => {
 /**
  * 结束评测
  * @param isComplete 是否完整评测
+ * @param endType 结束类型,selfCancel:是否是自己取消本次评测
  * @returns
  */
-export const handleEndEvaluat = (isComplete = false) => {
+export const handleEndEvaluat = (isComplete = false, endType?: string) => {
   // 没有开始评测 , 不是评测模式 , 不评分
   if (!evaluatingData.startBegin || state.modeType !== "evaluating") return;
   // 结束录音
@@ -504,12 +505,14 @@ export const handleEndEvaluat = (isComplete = false) => {
       message: "完整演奏结束才算作业分数!",
     });
   } else {
-    showLoadingToast({
-      message: "评分中",
-      duration: 0,
-      overlay: true,
-      overlayClass: styles.scoreMode,
-    });
+    if (!endType) {
+      showLoadingToast({
+        message: "评分中",
+        duration: 0,
+        overlay: true,
+        overlayClass: styles.scoreMode,
+      });
+    }
   }
   setTimeout(() => {
     evaluatingData.startBegin = false;

+ 3 - 2
src/view/follow-practice/index.tsx

@@ -103,7 +103,8 @@ export const handleFollowStart = async () => {
 	const res = await api_cloudToggleFollow("start");
 	// 用户没有授权,需要重置状态
 	if (res?.content?.reson) {
-		// 
+		followData.isBeginMask = false
+		followData.start = false;
 	} else {
 		// 跟练模式开始前,增加播放系统节拍器
 		const tickend = await handleStartTick();
@@ -145,7 +146,7 @@ const clearRightNoteColor = () => {
 	const leftVal = document.getElementById(`vf-${noteId}`)?.getBoundingClientRect()?.left || 0;
 	state.times.forEach((item: any) => {
 		const note: HTMLElement = document.getElementById(`vf-${item.id}`)!;
-		if (note?.getBoundingClientRect()?.left > leftVal) {
+		if (note?.getBoundingClientRect()?.left >= leftVal) {
 			note.classList.remove("follow-up", "follow-down", "follow-error", "follow-success");
 		}
 	});

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

@@ -10,6 +10,7 @@ import { getGradualLengthByXml } from "/src/helpers/calcSpeed";
 import { resetFormate, resetGivenFormate, setGlobalMusicSheet } from "/src/helpers/customMusicScore"
 import { setGlobalData } from "/src/utils";
 import Loading from "/src/view/audio-list/loading"
+import { storeData } from "/src/store";
 
 export const musicRenderTypeKey = "musicRenderType";
 let osmd: any = null;
@@ -122,7 +123,7 @@ export default defineComponent({
 				osmd.EngravingRules.BreathMarkDistance = 0.1; 
 				osmd.EngravingRules.PageBottomMargin = 0;
 			} else {
-				osmd.EngravingRules.PageTopMargin = 3; // 顶部间距
+				osmd.EngravingRules.PageTopMargin = state.isEvaluatReport && storeData.isApp ? 24 : state.isEvaluatReport ? 7 : 3; // 顶部间距
 				osmd.EngravingRules.PageTopMarginNarrow = 3;
 				osmd.EngravingRules.PageLeftMargin = 2;
 				osmd.EngravingRules.PageRightMargin = 2;

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

@@ -1,9 +1,10 @@
-import { PropType, computed, defineComponent, ref, toRefs, onMounted } from 'vue'
+import { PropType, computed, defineComponent, ref, toRefs, onMounted, watch } from 'vue'
 import { Picker, Button, Icon } from 'vant'
 import styles from './index.module.less'
 import state, { IPlatform } from "/src/state";
 import changeName from "./imgs/changeName.png"
 import { headImg } from "/src/page-instrument/header-top/image";
+import { toggleMusicSheet } from "../index"
 
 export default defineComponent({
   name: 'choosePartName',
@@ -38,6 +39,18 @@ export default defineComponent({
     onMounted(() => {
 			// console.log(myPicker.value,99999,selValues.value,props.partIndex)
 		});
+
+    watch(
+      () => toggleMusicSheet.show,
+      () => {
+        if (toggleMusicSheet.show) {
+          selectIndex.value = partIndex.value
+          selValues.value = [partIndex.value]
+        }
+        //console.log('声轨',selValues.value,partIndex.value,selectIndex.value)
+      }
+    );
+
     return () => (
       <div class={[styles.container, state.platform === IPlatform.PC && styles.pcContainer, styles[state.modeType]]}>
         <div class={styles.head}>
@@ -56,7 +69,7 @@ export default defineComponent({
               columns={columns.value}
               visibleItemCount={Math.ceil(document.body.clientHeight / 40 / 3)}
               onChange={(row) => {
-                // console.log(1111,'选择的索引', row)
+                console.log(1111,'选择的索引', row)
                 if (!partIndexChanged.value) partIndexChanged.value = true
                 selectIndex.value = row.selectedValues[0]
               }}

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

@@ -1,4 +1,4 @@
-import { computed, defineComponent, reactive, toRef } from 'vue'
+import { computed, defineComponent, reactive, toRef, watch } from 'vue'
 import styles from './index.module.less'
 import { Icon, Popup } from 'vant'
 import ChoosePartName from './choosePartName'
@@ -22,7 +22,6 @@ export default defineComponent({
   name: 'ToggleMusicSheet',
   setup() {
     const query = getQuery();
-
     const partListNames = computed(() => {
       let partList = state.partListNames || []
       partList = partList.filter((item: any) => !item?.toLocaleUpperCase()?.includes('COMMON'))

部分文件因文件數量過多而無法顯示