liushengqiang 2 gadi atpakaļ
vecāks
revīzija
29a0d2ddf8

+ 1 - 1
src/page-colexiu/evaluat-model/index.tsx

@@ -218,7 +218,7 @@ export default defineComponent({
 				</Transition>
 				<Transition name="pop-center">
 					{evaluatingData.websocketState && evaluatingData.startBegin && (
-						<div class={styles.endBtn} onClick={() => handleEndBegin(false)}>
+						<div class={styles.endBtn} onClick={() => handleEndBegin()}>
 							<img src={iconEvaluat.evaluatingEnd} />
 						</div>
 					)}

+ 1 - 1
src/page-gym/evaluat-model/index.tsx

@@ -232,7 +232,7 @@ export default defineComponent({
 							</div>
 						)}
 						{evaluatingData.startBegin && (
-							<div class={[styles.btn, styles.endBtn]} onClick={() => handleEndBegin(false)}>
+							<div class={[styles.btn, styles.endBtn]} onClick={() => handleEndBegin()}>
 								<Icon name="success" />
 								<span>结束演奏</span>
 							</div>

+ 7 - 7
src/page-orchestra/custom-plugins/unitTest/index.tsx

@@ -34,7 +34,7 @@ export default defineComponent({
 	name: "unitTest",
 	setup() {
 		const questionExtendsInfo = ref<IquestionExtendsInfo>({ difficulty: "" });
-    /** 隐藏评测功能 */
+		/** 隐藏评测功能 */
 		const handleHide = (list: string[]) => {
 			const ids = list;
 			for (let i = 0; i < ids.length; i++) {
@@ -55,9 +55,9 @@ export default defineComponent({
 		const getUnitData = async () => {
 			const search = getQuery();
 			if (!search.questionId) return "";
-      handleHide(["tips-step-0", "tips-step-2", "selectionBox"])
-      handleStartEvaluat();
-      handleCloseModeMode()
+			handleHide(["tips-step-0", "tips-step-2", "selectionBox"]);
+			handleStartEvaluat();
+			handleCloseModeMode();
 			try {
 				const res: any = await request.get(`/examinationQuestion/detail?examinationQuestionId=${search.questionId}`);
 				questionExtendsInfo.value = JSON.parse(res?.data?.questionExtendsInfo) || {};
@@ -72,7 +72,7 @@ export default defineComponent({
 		const getlessonTrainingData = async () => {
 			const search = getQuery();
 			if (!search.lessonTrainingId) return;
-      handleHide([ "tips-step-2", "selectionBox"])
+			handleHide(["tips-step-3", "selectionBox"]);
 			try {
 				const res: any = await request.post(`/studentLessonTraining/trainingRecord/${search.courseScheduleId}?userId=${storeData.user?.id}`);
 				if (Array.isArray(res?.data?.trainings)) {
@@ -95,11 +95,11 @@ export default defineComponent({
 			const endNotes = state.times.filter((n: any) => n.MeasureNumberXML == questionExtendsInfo.value.end);
 			const startNote = startNotes[0];
 			const endNote = endNotes[endNotes.length - 1];
-			  // console.log('🚀 ~ activeNote', startNote, endNote, questionExtendsInfo.value.end)
+			// console.log('🚀 ~ activeNote', startNote, endNote, questionExtendsInfo.value.end)
 			if (startNote && endNote) {
 				state.isSelectMeasureMode = true;
 				// 设置小节
-				hanldeDirectSelection([startNote, endNote])
+				hanldeDirectSelection([startNote, endNote]);
 				// 设置评测难度
 				if (difficultyData[questionExtendsInfo.value.difficulty!]) {
 					state.setting.evaluationDifficulty = difficultyData[questionExtendsInfo.value.difficulty!];

+ 1 - 0
src/page-orchestra/detail/index.tsx

@@ -113,6 +113,7 @@ export default defineComponent({
 			// 设置指法
 			state.fingeringInfo = subjectFingering(state.subjectId);
 			// console.log("🚀 ~ state.fingeringInfo:", state.fingeringInfo, state.subjectId, state.track)
+			// state.isOpenPrepare = true
 		};
 
 		const setCustom = () => {

+ 2 - 2
src/page-orchestra/evaluat-model/evaluat-result/index.tsx

@@ -36,7 +36,7 @@ export default defineComponent({
 
 				<div class={styles.fraction}>
 					<img class={styles.bg} src={iconBg.value} />
-					<div class={styles.headerButton}>
+					<div style={{display: state.isSelectMeasureMode ? 'none' : ''}} class={styles.headerButton}>
 						<div class={styles.headBtn} onClick={() => emit("close", "update")}>
 							<img src={iconUpload} />
 							上传
@@ -74,7 +74,7 @@ export default defineComponent({
 
 						<div class={styles.tips}>{evaluatingData.resultData.clxtip}</div>
 						<div class={styles.ctrls}>
-							<img src={imgs.btn1} class={styles.ctrlsBtn} onClick={() => emit("close", "practise")} />
+							<img style={{display: state.isSelectMeasureMode ? 'none' : ''}} src={imgs.btn1} class={styles.ctrlsBtn} onClick={() => emit("close", "practise")} />
 							<img src={imgs.btn2} class={styles.ctrlsBtn} onClick={() => emit("close", "tryagain")} />
 							<img src={imgs.btn3} class={styles.ctrlsBtn} onClick={() => emit("close", "look")} />
 						</div>

+ 21 - 19
src/page-orchestra/evaluat-model/index.tsx

@@ -60,28 +60,26 @@ export default defineComponent({
 
 		/** 生成评测曲谱数据 */
 		const formatTimes = () => {
-			let starTime = 0
+			let starTime = 0;
 			let ListenMode = false;
 			let dontEvaluatingMode = false;
 			let skip = false;
 			const datas = [];
-			let times = state.times
+			let times = state.times;
 			/** 如果为选段模式,评测 */
 			if (state.isSelectMeasureMode) {
-				const startIndex = state.times.findIndex(
-				  (n: any) => n.noteId == state.section[0].noteId
-				)
-				const endIndex = state.times.findIndex(
-				  (n: any) => n.noteId == state.section[1].noteId
-				)
+				const startIndex = state.times.findIndex((n: any) => n.noteId == state.section[0].noteId);
+				const endIndex = state.times.findIndex((n: any) => n.noteId == state.section[1].noteId);
 				times = state.times.filter((n: any, index: number) => {
-				  return index >= startIndex && index <= endIndex
-				})
-				starTime = times[0].sourceRelativeTime || times[0].relativeTime
-				// console.log("🚀 ~ times", times)
-			  }
-			for (let index = 0; index < state.times.length; index++) {
-				const item = state.times[index];
+					return index >= startIndex && index <= endIndex;
+				});
+				starTime = times[0].sourceRelativeTime || times[0].relativeTime;
+				console.log("🚀 ~ times", times);
+			}
+			let measureIndex = -1;
+			let recordMeasure = -1;
+			for (let index = 0; index < times.length; index++) {
+				const item = times[index];
 				const note = getNoteByMeasuresSlursStart(item);
 				const rate = state.speed / state.originSpeed;
 				const difftime = item.difftime;
@@ -111,6 +109,10 @@ export default defineComponent({
 				}
 				// console.log(note.measureOpenIndex, item.measureOpenIndex, note);
 				// console.log("skip", skip)
+				if (note.measureOpenIndex != recordMeasure) {
+					measureIndex++
+					recordMeasure = note.measureOpenIndex
+				  }
 				const data = {
 					timeStamp: (start * 1000) / rate,
 					duration: ((end * 1000) / rate - (start * 1000) / rate) * noteRate,
@@ -118,10 +120,10 @@ export default defineComponent({
 					nextFrequency: item.nextFrequency,
 					prevFrequency: item.prevFrequency,
 					// 重复的情况index会自然累加,render的index是谱面渲染的index
-					measureIndex: note.measureOpenIndex,
+					measureIndex: measureIndex,
 					measureRenderIndex: item.measureListIndex,
 					dontEvaluating: ListenMode || dontEvaluatingMode || item.skipMode,
-					musicalNotesIndex: item.i,
+					musicalNotesIndex: index,
 					denominator: note.noteElement?.Length.denominator,
 					isOrnament: !!note?.voiceEntry?.ornamentContainer,
 				};
@@ -152,7 +154,7 @@ export default defineComponent({
 			};
 			await connectWebsocket(content);
 			state.playSource = "music";
-			console.log('连接成功')
+			console.log("连接成功");
 		};
 
 		/** 评测结果按钮处理 */
@@ -226,7 +228,7 @@ export default defineComponent({
 				</Transition>
 				<Transition name="pop-center">
 					{evaluatingData.websocketState && evaluatingData.startBegin && (
-						<div class={styles.endBtn} onClick={() => handleEndBegin(false)}>
+						<div class={styles.endBtn} onClick={() => handleEndBegin()}>
 							<img src={iconEvaluat.evaluatingEnd} />
 						</div>
 					)}

+ 1 - 1
src/page-orchestra/main.ts

@@ -15,7 +15,7 @@ import "./theme.css";
 	setStoreData({
 		isApp: u.includes("ORCHESTRAAPPI") || u.includes("ORCHESTRAAPPA"),
 		platformApi: u.includes("ORCHESTRATEACHER") ? "/api-teacher" : u.includes("ORCHESTRASTUDENT") ? "/api-student" : "/api-backend",
-		platformType: u.includes("ORCHESTRATEACHER") ? "TEACHER" : u.includes("ORCHESTRASTUDENT") ? "STUDENT" : "WEB",
+		platformType: 'STUDENT',// u.includes("ORCHESTRATEACHER") ? "TEACHER" : u.includes("ORCHESTRASTUDENT") ? "STUDENT" : "WEB",
 		proxy: import.meta.env.DEV ? "/orchestra" : ""
 	});
 })();

+ 92 - 65
src/state.ts

@@ -3,7 +3,7 @@ import { reactive } from "vue";
 import { OpenSheetMusicDisplay } from "../osmd-extended/src";
 import { metronomeData } from "./helpers/metronome";
 import { GradualNote, GradualTimes, GradualVersion } from "./type";
-import { handleEndBegin, handleStartEvaluat, sendEvaluatingOffsetTime } from "./view/evaluating";
+import { handleEndEvaluat, handleStartEvaluat, sendEvaluatingOffsetTime } 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";
@@ -11,12 +11,12 @@ import { toggleFollow } from "./view/follow-practice";
 
 /** 入门 | 进阶 | 大师 */
 export type IDifficulty = "BEGINNER" | "ADVANCED" | "PERFORMER";
-export type IMusicRenderType = 'staff' | 'firstTone' | 'fixedTone'
-export const musicscoresettingKey = "musicscoresetting"
+export type IMusicRenderType = "staff" | "firstTone" | "fixedTone";
+export const musicscoresettingKey = "musicscoresetting";
 
 const state = reactive({
 	appName: "" as "GYM" | "COLEXIU",
-	musicRenderType: 'staff' as IMusicRenderType, 
+	musicRenderType: "staff" as IMusicRenderType,
 	/**曲谱是否渲染完成 */
 	musicRendered: false,
 	/** 当前曲谱数据ID, 和曲谱ID不一致 */
@@ -120,7 +120,7 @@ const state = reactive({
 		/** 开启伴奏 */
 		enableAccompaniment: false,
 		/** 反应时间 */
-		reactionTimeMs: 0
+		reactionTimeMs: 0,
 	},
 	/** 节拍器的时间 */
 	fixtime: 0,
@@ -145,7 +145,7 @@ const state = reactive({
 	/** 缩放 */
 	zoom: 0.8,
 	/** 练习,评测是否是选段模式 */
-	isSelectMeasureMode: false
+	isSelectMeasureMode: false,
 });
 /** 音频加载完成 */
 export const onLoadedmetadata = (evt: Event) => {
@@ -168,34 +168,42 @@ const setStep = () => {
 };
 /** 开始播放 */
 export const onPlay = () => {
-	state.playEnd = false
+	state.playEnd = false;
 	setStep();
 	if (state.modeType === "evaluating") {
 		let currentTime = getAudioCurrentTime();
 		// 选段评测模式
 		if (state.isSelectMeasureMode) {
-			currentTime = currentTime - state.section[0].time
-		  }
+			currentTime = currentTime - state.section[0].time;
+		}
 		sendEvaluatingOffsetTime(currentTime);
 	}
 };
 /** 播放中事件 */
 export const onTimeupdate = (evt: Event) => {};
+
+/** 播放模式结束自动重播 */
+const autoResetPlay = () => {
+	// 没有开启自动重播, 不是练习模式
+	if (!state.setting.repeatAutoPlay || state.modeType !== "practise") return;
+	skipNotePlay(0, true);
+	scrollViewNote();
+	setTimeout(() => {
+		togglePlay("play");
+	}, 1000);
+};
+
 /** 播放完成事件 */
 export const onEnded = () => {
-	state.playEnd = true
-	handleStopPlay();
-	if (state.modeType === "evaluating") {
-		handleEndBegin(true);
-	}
-	// 重复自动播放如果为开启,自动开始播放, 且是练习模式
-	if (state.setting.repeatAutoPlay && state.modeType === "practise") {
-		skipNotePlay(0, true)
-		scrollViewNote();
-		setTimeout(() => {
-			togglePlay("play");
-		}, 1000);
-	}
+	// 修改状态为结束
+	state.playEnd = true;
+	state.playState = "paused";
+	// 结束播放
+	audioListStart(state.playState);
+	// 调用结束评测
+	handleEndEvaluat();
+	// 调用自动重复播放
+	autoResetPlay();
 };
 
 /**
@@ -205,27 +213,25 @@ const handlePlaying = (_item?: any) => {
 	const currentTime = getAudioCurrentTime();
 	const duration = getAudioDuration();
 	state.playProgress = (currentTime / duration) * 100;
-	const item = _item ? _item : getNote(currentTime);
+	let item = _item ? _item : getNote(currentTime);
 
 	if (item) {
 		// 选段状态下
 		if (state.sectionStatus && state.section.length === 2) {
-			let startItemIndex = state.section[0].i;
-			let startXmlIndex = state.section[0].MeasureNumberXML;
-			// 开启预备拍
-			if (state.sectionFirst) {
-				startItemIndex = state.sectionFirst.i;
-				startXmlIndex = state.sectionFirst.MeasureNumberXML;
-			}
-			if (item.MeasureNumberXML < startXmlIndex || item.MeasureNumberXML > state.section[1].MeasureNumberXML) {
-				console.log('选段播放结束')
+			// 如果开启了预备拍
+			const selectStartItem = state.sectionFirst ? state.sectionFirst : state.section[0];
+			const selectEndItem = state.section[1];
+
+			if (currentTime < selectStartItem.time || currentTime > selectEndItem.endtime) {
+				console.log("选段播放结束");
 				// 如果为选段评测模式
-				if (state.isSelectMeasureMode) {
-					onEnded()
+				if (state.modeType === 'evaluating' && state.isSelectMeasureMode) {
+					onEnded();
+					return;
 				}
-				skipNotePlay(startItemIndex);
+				item = selectStartItem;
+				setAudioCurrentTime(selectStartItem.time);
 				
-				return;
 			}
 		}
 		gotoNext(item);
@@ -242,7 +248,7 @@ export const skipNotePlay = (itemIndex: number, isStart = false) => {
 	}
 	// console.log("🚀 ~ itemTime:", itemTime);
 	if (item) {
-		setAudioCurrentTime(itemTime)
+		setAudioCurrentTime(itemTime);
 		handlePlaying(item);
 	}
 };
@@ -260,8 +266,8 @@ export const togglePlay = async (playState?: "play" | "paused") => {
 		// 节拍器返回false, 取消播放
 		if (!tickend) {
 			state.playState = "paused";
-			return false
-		};
+			return false;
+		}
 	}
 	// 如果选段没有结束, 直接开始播放,清空选段状态
 	if (state.playState == "play") {
@@ -270,7 +276,7 @@ export const togglePlay = async (playState?: "play" | "paused") => {
 		}
 	}
 	audioListStart(state.playState);
-	return true
+	return true;
 };
 /** 结束播放 */
 export const handleStopPlay = () => {
@@ -278,6 +284,16 @@ export const handleStopPlay = () => {
 	audioListStart(state.playState);
 };
 
+/** 重置播放为开始 */
+export const resetPlaybackToStart = () => {
+	// 如果为选段状态
+	if (state.sectionStatus && state.section.length === 2) {
+		state.section = formateSelectMearure(state.section);
+		return
+	}
+	skipNotePlay(0, true);
+}
+
 /** 跳转到指定音符 */
 export const gotoCustomNote = (index: number) => {
 	try {
@@ -314,8 +330,8 @@ export const gotoNext = (note: any) => {
 export const getNote = (currentTime: number) => {
 	const times = state.times;
 	const len = state.times.length;
-	/** 播放超过了最后一个音符的时间,直接结束 */
-	if (currentTime > times[len - 1].endtime + 1) {
+	/** 播放超过了最后一个音符的时间,直接结束, 2秒误差 */
+	if (currentTime > times[len - 1].endtime + 2) {
 		onEnded();
 		return;
 	}
@@ -337,7 +353,7 @@ export const getNote = (currentTime: number) => {
 
 /** 重播 */
 export const handleResetPlay = () => {
-	skipNotePlay(0, true);
+	resetPlaybackToStart()
 };
 /** 设置速度 */
 export const handleSetSpeed = (speed: number) => {
@@ -376,21 +392,39 @@ export const handleChangeSection = () => {
 	});
 };
 
+/** 效验并格式化选段小节 */
+const formateSelectMearure = (_list: any[]): any[] => {
+	if (!_list.length) return [];
+	const list = _list.sort((a, b) => a.time - b.time);
+	const startXml = list[0]?.MeasureNumberXML;
+	const endXml = list.last()?.MeasureNumberXML;
+	const selectStartMeasure = state.times.filter((n: any) => startXml === n.MeasureNumberXML) || [];
+	const selectEndMeasure = state.times.filter((n: any) => endXml === n.MeasureNumberXML) || [];
+	// 没有找到选段小节
+	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);
+	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 = state.section.sort((a, b) => a.time - b.time);
-			let startItemINdex = state.section[0].index;
-			// 开启预备拍
-			if (state.isOpenPrepare) {
-				const startXmlIndex = state.section[0].MeasureNumberXML;
-				state.sectionFirst = state.times.find((n: any) => startXmlIndex - n.MeasureNumberXML === 1);
-				startItemINdex = state.sectionFirst ? state.sectionFirst.i : startItemINdex;
-			}
-			skipNotePlay(startItemINdex);
+			state.section = formateSelectMearure(state.section);
 			state.sectionToast?.close();
 			state.sectionToast = null;
 		}
@@ -399,20 +433,13 @@ export const handleSelection = (item: any) => {
 		state.sectionToast.message = "请选择结束小节";
 	}
 };
+
 /** 直接设置选段 */
 export const hanldeDirectSelection = (list: any[]) => {
-	if(!Array.isArray(list) || list.length !== 2) return
+	if (!Array.isArray(list) || list.length !== 2) return;
 	state.sectionStatus = true;
-	state.section = list.sort((a, b) => a.time - b.time);
-	let startItemINdex = state.section[0].i;
-	// 开启预备拍
-	if (state.isOpenPrepare) {
-		const startXmlIndex = state.section[0].MeasureNumberXML;
-		state.sectionFirst = state.times.find((n: any) => startXmlIndex - n.MeasureNumberXML === 1);
-		startItemINdex = state.sectionFirst ? state.sectionFirst.i : startItemINdex;
-	}
-	skipNotePlay(startItemINdex);
-}
+	state.section = formateSelectMearure(list);
+};
 let offsetTop = 0;
 /**
  * 窗口内滚动到音符的区域
@@ -448,8 +475,8 @@ export const handleRessetState = () => {
 		handleStartEvaluat();
 	} else if (state.modeType === "practise") {
 		togglePlay("paused");
-	} else if (state.modeType === 'follow') {
-		toggleFollow(false)
+	} else if (state.modeType === "follow") {
+		toggleFollow(false);
 	}
 };
 export default state;

+ 30 - 27
src/view/evaluating/index.tsx

@@ -1,6 +1,6 @@
 import { Snackbar } from "@varlet/ui";
 import { closeToast, showLoadingToast } from "vant";
-import { defineComponent, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref, watch } from "vue";
+import { defineComponent, onBeforeUnmount, onMounted, onUnmounted, reactive, ref, watch } from "vue";
 import { getLeveByScore, getLeveByScoreMeasure, IEvaluatings } from "./evaluatResult";
 import {
 	cancelEvaluating,
@@ -15,7 +15,7 @@ import {
 	startSoundCheck,
     api_openWebView,
 } from "/src/helpers/communication";
-import state, { handleStopPlay, togglePlay } from "/src/state";
+import state, { handleStopPlay, resetPlaybackToStart, togglePlay } from "/src/state";
 import { IPostMessage } from "/src/utils/native-message";
 export const evaluatingData = reactive({
     /** 评测模块是否加载完成 */
@@ -81,33 +81,22 @@ const checkUseEarphone = async () => {
 	return res?.content?.checkIsWired || false;
 };
 
-const handleSoundEffect = (res?: IPostMessage) => {
-	if (res?.content) {
-		const { header, body } = res.content;
-		if (header.commond === "checking") {
-			evaluatingData.soundEffectFrequency = body.frequency;
-		}
-	}
-};
-
 /**
  * 开始录音
  */
 const handleStartSoundCheck = () => {
-	sendResult(handleSoundEffect);
 	startSoundCheck();
 };
 /** 结束录音 */
 export const handleEndSoundCheck = () => {
 	endSoundCheck();
-	removeResult(handleSoundEffect);
 };
 
 /** 连接websocket */
 export const connectWebsocket = async (content: any) => {
 	evaluatingData.websocketState = false;
 	try {
-		// console.log("🚀 ~ content:", JSON.stringify(content))
+		console.log("🚀 ~ content:", content,JSON.stringify(content))
 	} catch (error) {}
 	const res = await startEvaluating(content);
 	// console.log("🚀 ~ res:", res)
@@ -167,9 +156,15 @@ const handleScoreResult = (res?: IPostMessage) => {
 	if (res?.content) {
 		console.log("🚀 ~ 评测返回:", res);
 		const { header, body } = res.content;
+		// 效音返回
+		if (header.commond === "checking") {
+			evaluatingData.soundEffectFrequency = body.frequency;
+		}
+		// 小节评分返回
 		if (header?.commond === "measureScore") {
 			addMeasureScore(body);
 		}
+		// 评测结束返回
 		if (header?.commond === "overall") {
 			// console.log("评测结束", body);
             evaluatingData.resulstMode = true
@@ -177,8 +172,7 @@ const handleScoreResult = (res?: IPostMessage) => {
                 ...body,
                 ...getLeveByScore(body.score)
             }
-            console.log("🚀 ~ evaluatingData.resultData:", evaluatingData.resultData)
-			removeResult(handleScoreResult);
+            // console.log("🚀 ~ evaluatingData.resultData:", evaluatingData.resultData)
 			closeToast();
 		}
 	}
@@ -189,24 +183,25 @@ export const handleStartBegin = async () => {
 	evaluatingData.startBegin = true;
     evaluatingData.evaluatings = {};
     evaluatingData.resultData = {};
-	sendResult(handleScoreResult);
-	await startRecording();
+	evaluatingData.backtime = Date.now();
+	resetPlaybackToStart()
 	const playState = await togglePlay("play");
 	// 取消播放
 	if (!playState){
 		evaluatingData.startBegin = false;
 		return
 	}
-	evaluatingData.backtime = Date.now();
+	await startRecording();
+	
 };
 
 /**
  * 结束评测
- * @param isEnd 是否是自动播放停止, 默认: false
  */
-export const handleEndBegin = (isEnd = false) => {
-	// 没有开始评测,不评分
-	if (!evaluatingData.startBegin) return
+export const handleEndEvaluat = () => {
+	console.log('触发结束')
+	// 没有开始评测 , 不是评测模式 , 不评分
+	if (!evaluatingData.startBegin || state.modeType !== 'evaluating') return
 	evaluatingData.startBegin = false;
 	endEvaluating({
 		musicScoreId: state.examSongId,
@@ -216,8 +211,14 @@ export const handleEndBegin = (isEnd = false) => {
 		duration: 0,
 		forbidClick: true,
 	});
+}
 
-	if (isEnd) return;
+/**
+ * 结束评测
+ * @param isEnd 是否是自动播放停止, 默认: false
+ */
+export const handleEndBegin = () => {
+	handleEndEvaluat()
 	handleStopPlay();
 };
 
@@ -238,8 +239,6 @@ export const handleCancelEvaluat = () => {
 	});
     // 取消评测
 	cancelEvaluating();
-    // 卸载评测监听
-    removeResult(handleScoreResult);
     // 停止播放
     handleStopPlay();
 };
@@ -257,7 +256,7 @@ export const handleViewReport = () => {
 export default defineComponent({
 	name: "evaluating",
 	setup() {
-        onBeforeMount(() => {
+        onMounted(() => {
 			evaluatingData.resultData = {}
             // evaluatingData.resultData = {...getLeveByScore(90), score: 30, intonation: 10, cadence: 30, integrity: 40}
             // console.log("🚀 ~ evaluatingData.resultData:", evaluatingData.resultData)
@@ -265,7 +264,11 @@ export default defineComponent({
             evaluatingData.soundEffectFrequency = 0
             evaluatingData.checkStep = 0
             evaluatingData.rendered = true
+			sendResult(handleScoreResult);
         })
+		onUnmounted(() => {
+			removeResult(handleScoreResult)
+		})
 		return () => <div></div>;
 	},
 });

+ 11 - 12
src/view/follow-practice/index.tsx

@@ -1,5 +1,5 @@
-import { defineComponent, onMounted, onUnmounted, reactive, ref, } from "vue";
-import state, { gotoNext } from "/src/state";
+import { defineComponent, onMounted, onUnmounted, reactive, ref } from "vue";
+import state, { gotoNext, resetPlaybackToStart } from "/src/state";
 import { IPostMessage } from "/src/utils/native-message";
 import { api_cloudFollowTime, api_cloudToggleFollow } from "/src/helpers/communication";
 import { storeData } from "/src/store";
@@ -52,27 +52,26 @@ const onClear = () => {
 
 /** 开始跟练 */
 export const handleFollowStart = async () => {
-  if (!storeData.isApp){
-    Snackbar({
-      content: '请在APP端使用',
-      type: 'warning',
-    })
-    return
-  }
+	if (!storeData.isApp) {
+		Snackbar({
+			content: "请在APP端使用",
+			type: "warning",
+		});
+		return;
+	}
 	onClear();
 	followData.start = true;
 	followData.index = 0;
 	followData.list = [];
-	gotoNext(state.times[0]);
+	resetPlaybackToStart();
 	await openToggleRecord(true);
-  setStep()
+	setStep();
 };
 /** 结束跟练 */
 export const handleFollowEnd = () => {
 	followData.start = false;
 	openToggleRecord(false);
 	followData.index = 0;
-	gotoNext(state.times[0]);
 };
 
 // 下一个