Jelajahi Sumber

Merge branch 'feature-tianyong' of http://git.dayaedu.com/tianyong/gym-music-score into hqyDev

黄琪勇 8 bulan lalu
induk
melakukan
9a23410eb2

+ 5 - 5
src/helpers/formateMusic.ts

@@ -366,7 +366,7 @@ export const onlyVisible = (xml: string, partIndex: number): string => {
 	const detailId = state.examSongId + "";
 	const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
 	const partList = xmlParse.getElementsByTagName("part-list")?.[0]?.getElementsByTagName("score-part") || [];
-	//const partListNames = Array.from(partList).map((item) => item.getElementsByTagName("part-name")?.[0]?.textContent?.trim() || "");
+	const partListNames = Array.from(partList).map((item) => item.getElementsByTagName("part-name")?.[0]?.textContent?.trim() || "");
 	const parts: any = xmlParse.getElementsByTagName("part");
 	// const firstTimeInfo = parts[0]?.getElementsByTagName('metronome')[0]?.parentElement?.parentElement?.cloneNode(true)
 	const firstMeasures = [...parts[0]?.getElementsByTagName("measure")];
@@ -376,10 +376,10 @@ export const onlyVisible = (xml: string, partIndex: number): string => {
 	const rehearsals = [...parts[0]?.getElementsByTagName("rehearsal")];
 
 	/** 第一分谱如果是约定的配置分谱则跳过 */
-	// if (partListNames[0]?.toLocaleUpperCase?.() === "COMMON") {
-	// 	partIndex++;
-	// 	partListNames.shift();
-	// }
+	if (partListNames[0]?.toLocaleUpperCase?.() === "COMMON") {
+		partIndex++;
+		partListNames.shift();
+	}
 	const visiblePartInfo = partList[partIndex];
 	// console.log(visiblePartInfo, partIndex)
 	// 根据后台已选择的分轨筛选出能切换的声轨

+ 2 - 0
src/page-instrument/api.ts

@@ -32,6 +32,7 @@ export const studentQueryUserInfo = async () => {
       const data = res.data
       res.data = {
         instrumentId: "",
+        specialInstrumentIds: [],
         phone:data.phone,
         clientType:"web",
         id:data.id,
@@ -45,6 +46,7 @@ export const studentQueryUserInfo = async () => {
       const data = res.data.student
       res.data = {
         instrumentId: res.data.instrumentId ? res.data.instrumentId.split(',')[0] : "",
+        specialInstrumentIds: res.data.instrumentId ? res.data.instrumentId.split(',') : [],
         phone:data.phone,
         clientType:"STUDENT",
         id:data.id,

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

@@ -85,8 +85,9 @@ export default defineComponent({
     const noSaveTips = computed(() => {
       let tipContent = '';
       const rate = state.basePlayRate * state.originAudioPlayRate; // 播放倍率
-      if (query.workRecord || state.section.length === 2 || state.isAppPlay || rate != 1 || !state.accompany) {
-        tipContent = query.workRecord ? '评测作业暂不支持保存作品噢~' : (!state.accompany || state.isAppPlay) ? '该曲目暂不支持保存作品噢~' : state.section.length === 2 ? '选段后暂不支持保存作品噢~' : rate != 1 ? '调速后暂不支持保存作品噢~' : '';
+      console.log('123456',state.systemType)
+      if (query.workRecord || state.section.length === 2 || state.isAppPlay || rate != 1 || !state.accompany || state.systemType === 'teacher' || state.systemType === 'web') {
+        tipContent = (state.systemType === 'teacher' || state.systemType === 'web') ? '暂不支持保存作品噢~' : query.workRecord ? '评测作业暂不支持保存作品噢~' : (!state.accompany || state.isAppPlay) ? '该曲目暂不支持保存作品噢~' : state.section.length === 2 ? '选段后暂不支持保存作品噢~' : rate != 1 ? '调速后暂不支持保存作品噢~' : '';
       }
       return tipContent
     })

+ 5 - 1
src/page-instrument/header-top/settting/index.tsx

@@ -3,7 +3,7 @@ import styles from "./index.module.less"
 import { headImg } from "../image";
 import { headTopData } from "../index"
 import { Switch, showToast, Field, Popup, Slider } from "vant";
-import state, { refreshMusicSvg, IPlatform, checkMoveNoSave, handleGuide } from "/src/state"
+import state, { refreshMusicSvg, IPlatform, checkMoveNoSave, handleGuide, resetCursorPosition } from "/src/state"
 import { api_closeCamera, api_openCamera, api_savePicture } from "/src/helpers/communication";
 import { smoothAnimationState} from "/src/page-instrument/view-detail/smoothAnimation"
 import Recommendation from "../../custom-plugins/helper-model/recommendation";
@@ -103,8 +103,12 @@ export default defineComponent({
                                     {
                                         metronomeList.value.map(item=>{
                                             return <div class={ metronomeData.cursorMode===item.value && styles.active } onClick={ ()=>{
+                                                if (metronomeData.cursorMode === item.value) {
+                                                    return
+                                                }
                                                  // 切换光标模式
                                                 metronomeData.cursorMode = item.value
+                                                resetCursorPosition()
                                             }}>{item.name}</div>
                                         })
                                     }

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

@@ -38,7 +38,7 @@ export default defineComponent({
 				state.speed = Math.floor(speed.value);
 				// handleSetSpeed(speed.value);
 				if (state.playState === 'paused') {
-					const currentItem: any = (state.sectionStatus && state.section.length === 2) ? state.sectionFirst || state.section[0] : state.times[state.activeNoteIndex];
+					const currentItem: any = (state.sectionStatus && state.section.length === 2) ? state.section[0] : state.times[state.activeNoteIndex];
 					state.basePlayRate = currentItem?.measureSpeed ? state.speed / currentItem.measureSpeed : state.speed / state.originSpeed;
 				}
 			}

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

@@ -116,7 +116,7 @@
         // opacity: var(--corsor-opacity);
         //transform: translateX(10PX);
         z-index: 1 !important;
-        // opacity: 0; // 新版小酷AI不显示光标指针
+        opacity: 0 !important; // 新版小酷AI不显示光标指针
     }
 
     .staff {

+ 58 - 9
src/state.ts

@@ -665,10 +665,13 @@ export const onEnded = () => {
 };
 
 // 根据当前小节动态设置,右上角展示的速度
-const dynamicShowPlaySpeed = (index: number) => {
+const dynamicShowPlaySpeed = (index: number, isPlaying?: boolean) => {
   if (!headerColumnHide.value) {
-    // console.log('动态计算速度')
     const item: any = state.times[index];
+    if (state.sectionFirst && state.section.length === 2 && item.MeasureNumberXML === state.sectionFirst.MeasureNumberXML) {
+      state.speed = Math.floor(state.section[0].measureSpeed * state.basePlayRate) || state.speed
+      return;
+    }
     if (item && item.measureSpeed ) {
       // console.log('速度1',item.measureSpeed)
       const newSpeed = Math.floor(state.basePlayRate * item.measureSpeed)
@@ -771,7 +774,7 @@ const handlePlaying = () => {
       }
     }
     gotoNext(item);
-    dynamicShowPlaySpeed(item.i);
+    dynamicShowPlaySpeed(item.i, true);
   }
 
   // 评测不播放叮咚节拍器
@@ -1055,6 +1058,16 @@ export const gotoNext = (note: any, skipNote?: boolean) => {
   state.activeNoteIndex = num;
   state.activeMeasureIndex = note.MeasureNumberXML;
   osmd.cursor.activeMeasureNum = note.MeasureNumberXML;
+  // 赋值音符id
+  osmd.cursor.noteGraphicalId = state.times[state.activeNoteIndex].id;
+  // 设置光标位置
+  nextTick(() => {
+      if (osmd.cursor.noteGraphicalId) {
+      const { x, y } = document.getElementById(`vf-${osmd.cursor.noteGraphicalId}`)?.getBoundingClientRect() || { x: 0, y: 0}
+      osmd.cursor.cursorElement.style.left = x + "px";
+      // cursorElement.style.top = y + "px";
+    }
+  })
   dynamicShowPlaySpeed(state.activeNoteIndex);
   if (prev && num - prev === 1) {
     // console.log('跳转音符',11111,osmd.cursor)
@@ -1444,6 +1457,13 @@ const getMusicInfo = async (res: any) => {
   } else {
     (window as any).DYFirstTrackName = '';
   }
+  // 如果是作业模式,需要默认渲染当前学生声部对应的声轨
+  if (state.isHomeWork && storeData.user?.instrumentId) {
+    const currentTrack = res.data.musicSheetSoundList.find((item: any) => item.musicalInstrumentId === storeData.user?.instrumentId)?.track;
+    if (currentTrack) {
+      partIndex = tracks.findIndex(item => item === currentTrack) || partIndex
+    }
+  }
   // 设置音源  track 为当前的声轨 index为当前的
   const { track, index, musicalInstrumentId } = state.isSimplePage ? { track:tracks[0], index:0, musicalInstrumentId: '' } : initMusicSource(res.data, tracks, partIndex, workRecordInstrumentId)
   // 这里返回的track可能和实际的对不上,所以重新筛选一下
@@ -1481,10 +1501,17 @@ function initMusicSource(data: any, tracks: string[], partIndex: number, workRec
     accompanyObj = musicSheetAccompanimentList.find((item: any) => {
       return item.audioPlayType === "PLAY"
     })
-    // 是否全声部(isAllSubject)为true 时候没有乐器只有一个原音(比如节奏练习,这个曲子全部乐器都支持);当前用户有乐器就匹配  不然取第一个原音
-    musicObj = musicSheetSoundList.find((item: any) => {
-      return isAllSubject ? item.audioPlayType === "PLAY" : (item.audioPlayType === "PLAY" && item.musicalInstrumentId == instrumentId)
-    })
+    // 如果specialInstrumentIds有多个,是打击乐的声部,打击乐声部可能有多个乐器id
+    if (storeData.user?.specialInstrumentIds?.length > 1) {
+      musicObj = musicSheetSoundList.find((item: any) => {
+        return isAllSubject ? item.audioPlayType === "PLAY" : (item.audioPlayType === "PLAY" && storeData.user?.specialInstrumentIds?.includes(item.musicalInstrumentId))
+      })
+    } else {
+      // 是否全声部(isAllSubject)为true 时候没有乐器只有一个原音(比如节奏练习,这个曲子全部乐器都支持);当前用户有乐器就匹配  不然取第一个原音
+      musicObj = musicSheetSoundList.find((item: any) => {
+        return isAllSubject ? item.audioPlayType === "PLAY" : (item.audioPlayType === "PLAY" && item.musicalInstrumentId == instrumentId)
+      })
+    }
     // 当没有找到原音的时候,并且instrumentId没有值的时候,取默认第一个乐器
     if(!musicObj && !instrumentId){
       musicObj = musicSheetSoundList.find((item: any) => {
@@ -2246,7 +2273,7 @@ watch(
   }
 )
 
-		// 完成拖动弹窗引导页
+// 完成拖动弹窗引导页
 export const handleGuide = async () => {
     const guideInfoStore = localStorage.getItem('guideInfo') ? JSON.parse(localStorage.getItem('guideInfo')) : {};
     guideInfoStore.teacherDrag = true;
@@ -2256,4 +2283,26 @@ export const handleGuide = async () => {
     } catch (e) {
       console.log(e);
     }
-};
+};
+
+export const resetCursorPosition = () => {
+  if (metronomeData.cursorMode === 1) {
+    const currentActive = document.querySelector(`.dotActive`);
+    currentActive?.classList.remove('dotActive');
+    const currentDot = document.querySelector(`.noteIndex_${state.activeNoteIndex}`)
+    if (currentDot) {
+      currentDot.classList.add('dotActive')
+    }
+  } else {
+    const currentActive = document.querySelector(`.dotActive`);
+    currentActive?.classList.remove('dotActive');
+  }
+}
+
+
+watch(
+  () => state.activeNoteIndex,
+  () => {
+    resetCursorPosition();
+  }
+);

+ 2 - 0
src/store.ts

@@ -23,6 +23,8 @@ type IUser = {
   schoolInfos?: any[];
   // 当前用户 绑定 的乐器
   instrumentId?: string;
+  // 如果学生的声部是打击乐,打击乐可能会有多个乐器id,
+  specialInstrumentIds?: any[];
   // 性别
   gender?: 1|0;
 };

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

@@ -2,7 +2,7 @@ import { computed, defineComponent, onMounted, reactive, ref, onUnmounted } from
 import { formatXML, onlyVisible } from "../../helpers/formateMusic";
 // // @ts-ignore
 import { OpenSheetMusicDisplay } from "/osmd-extended/src";
-import state, { EnumMusicRenderType, IPlatform } from "/src/state";
+import state, { EnumMusicRenderType, IPlatform, resetCursorPosition } from "/src/state";
 import Selection from "../selection";
 import styles from "./index.module.less";
 import queryString from "query-string";
@@ -229,6 +229,7 @@ export default defineComponent({
 				await init();
 				musicData.showSelection = true;
 				state.isLoading = false
+				resetCursorPosition()
 			}, 60);
 		}
 		expose({

+ 52 - 2
src/view/selection/index.module.less

@@ -54,8 +54,8 @@
     position: absolute;
     height: 120%;
     background-color: rgba(45, 199, 170, 1);
-    min-height: 58PX;
-    height: 58PX;
+    min-height: 40px;
+    height: 40px;
     top: 50%;
     // width: 14PX;
     width: 2PX !important;
@@ -298,6 +298,22 @@
         }
 
     }
+
+    .dotActive {
+        // background: #01C1B5;
+        :global {
+            .node-dot::before{
+                content: "";
+                position: absolute;
+                left: 50%;
+                top: 50%;
+                width: 2PX;
+                height: 40px;
+                transform: translate(-50%, -50%);
+                background: #2DC7AA;
+            }
+        }
+    }
 }
 
 .linePC {
@@ -317,6 +333,7 @@
     // background: #07c160;
 }
 
+
 // 阴影
 .staveBgContainer{
     position: absolute;
@@ -332,4 +349,37 @@
         opacity: 0.7;
         margin-top: -4px;
     }
+}
+
+.middleZoom {
+    .line {
+        height: 50px;
+    }
+    :global {
+        .node-dot::before{
+            height: 50px;
+        }
+    }
+}
+
+.bigZoom {
+    .line {
+        height: 60px;
+    }
+    :global {
+        .node-dot::before{
+            height: 60px;
+        }
+    }
+}
+
+.largeZoom {
+    .line {
+        height: 70px;
+    }
+    :global {
+        .node-dot::before{
+            height: 70px;
+        }
+    }
 }

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

@@ -240,6 +240,7 @@ export default defineComponent({
 			}
 			return []
 		})
+
 		onMounted(() => {
 			selectData.notes = [];
 			selectData.staves = [];
@@ -266,7 +267,8 @@ export default defineComponent({
 					id="selectionBox"
 					class={[
 						styles.selectionContainer,
-						isPad && styles.isPad
+						isPad && styles.isPad,
+						state.zoom == 1.25 ? styles.middleZoom : state.zoom == 1.5 ? styles.bigZoom : state.zoom == 1.75 ? styles.largeZoom : ''
 					]}
 					onClick={(e: Event) => e.stopPropagation()}
 				>