Browse Source

Merge branch 'gyt-feature-tianyong' into online

TIANYONG 1 year ago
parent
commit
fe74a36356

+ 1 - 1
osmd-extended/src/MusicalScore/Graphical/JustifiedMusicSystemBuilder.ts

@@ -147,7 +147,7 @@ export class JustifiedMusicSystemBuilder extends MusicSystemBuilder {
                 totalWidth += measureWidth
                 // console.log(idx , totalWidth, systemSpace )
                 const appName = (window as any)?.appName || '';
-                if (appName?.toLocaleUpperCase() === 'GYM') {
+                if (appName?.toLocaleUpperCase() === 'GYM' || (window as any)?.customSectionAmount) {
                     // 修改 部分曲谱修改换行小节数
                     let wrapNum = (window as any).GYM?.wrapNum;
                     wrapNum = Number(wrapNum) > 0 ? Number(wrapNum) : 6

+ 8 - 0
src/helpers/utils.ts

@@ -195,3 +195,11 @@ export const isEncoded = (uri: string) => {
   uri = uri || '';
   return uri !== decodeURI(uri);
 }
+
+/** 设置全局通信 */
+export const setGlobalData = (_key: string, _value: any) => {
+  if (!_key || !_value) return;
+  const GYM = (window as any).GYM || {};
+  GYM[_key] = _value
+  ;(window as any).GYM = GYM
+}

+ 17 - 1
src/pages/detail/helpers.ts

@@ -217,6 +217,7 @@ export const getAllNodes = (osmd: any) => {
     let skipNextNote = false
     let multipleRestMeasures = 0
     // const useedmeasures: Set<number> = new Set()
+
     while (!iterator.endReached) {
       // 为获取所有节点有修改源码currentVoiceEntries仅返回可见第一行,请搜索“修改为 仅根据当前可见声部第一行跳转”可找到位置
       // 多声部仅循环一次,以第一声部为准
@@ -230,8 +231,22 @@ export const getAllNodes = (osmd: any) => {
         cursorBox.w = cursorImg.offsetWidth
         cursorBox.h = cursorImg.offsetHeight
       }
-      const voiceEntries = iterator.currentVoiceEntries?.[0] ? [iterator.currentVoiceEntries?.[0]] : []
+      /** 多声轨合并显示,当前音符的时值取所有声轨中的最小值 */
+      let minIndex = 0, elRealValue = 0
+      if (state.isCombineRender) {
+        for (let index = 0; index < iterator.currentVoiceEntries.length; index++) {
+          const element = iterator.currentVoiceEntries[index];
+          if (element.notes[0].length.realValue < elRealValue) {
+            minIndex = index
+          }
+          elRealValue = element.notes[0].length.realValue
+        }
+      }
+      let voiceEntries = iterator.currentVoiceEntries?.[0] ? [iterator.currentVoiceEntries?.[0]] : []
       const voiceEntries2 = iterator.currentVoiceEntries?.[1]
+      if (state.isCombineRender) {
+        voiceEntries = iterator.currentVoiceEntries?.[minIndex] ? [iterator.currentVoiceEntries?.[minIndex]] : []
+      }
       let skipMode = false
       for (const v of voiceEntries) {
         // 始终只取第一个声部中第一个音符的时间
@@ -629,6 +644,7 @@ export const getAllNodes = (osmd: any) => {
           }
           nodeDetail.realKey = formatRealKey(note.halfTone - fixedKey * 12, nodeDetail)
           nodeDetail.duration = nodeDetail.endtime - nodeDetail.time
+          // console.log(i,nodeDetail.duration)
           const tickables = activeVerticalMeasureList[0]?.vfVoices['1']?.tickables || []
           const sublength = note.sourceMeasure.verticalMeasureList?.[0]?.staffEntries?.length || tickables.length
           nodeDetail.noteLength = sublength || 1

+ 1 - 1
src/pages/detail/section-box/index.tsx

@@ -283,7 +283,7 @@ export default defineComponent({
                   </>
                 )}
                 <div class={[styles.noteBase, styles.noteRight]}>
-                  <Icon name="success" size="16" color="var(--primary-color)" />
+                  <Icon name="success" size="16" color="#2DC7AA" />
                 </div>
                 <div class={[styles.noteBase, styles.noteError]}>
                   <Icon name="cross" size="16" color="red" />

+ 2 - 0
src/pages/detail/state.ts

@@ -88,6 +88,8 @@ const state = reactive({
   isLessonTrain: false,
   /** 是否隐藏评测报告弹窗,保存演奏按钮,默认不隐藏 */
   isHideEvaluatReportSaveBtn: false,    
+  /** 合奏曲目是否合并展示 */
+  isCombineRender: false,
 })
 
 export const isRhythmicExercises = (musicName?: string) => {

+ 2 - 2
src/pages/report/index.module.less

@@ -134,8 +134,8 @@
 .intonation_high,
 .intonation_low{
   path{
-    fill: #FFAB25;
-    stroke: #FFAB25;
+    fill: #977CFF;
+    stroke: #977CFF;
   }
 }
 

+ 6 - 6
src/subpages/colexiu-report/header/index.tsx

@@ -219,11 +219,11 @@ export default defineComponent({
               {active.value === 'pitch' && (
                 <>
                   <div>
-                    <Note fill="#FFAB25" shadow x={-3} y={0} />
+                    <Note fill="#977CFF" shadow x={-3} y={0} />
                     <span>音高了</span>
                   </div>
                   <div>
-                    <Note fill="#FFAB25" shadow x={-1} y={-2} />
+                    <Note fill="#977CFF" shadow x={-1} y={-2} />
                     <span>音低了</span>
                   </div>
                 </>
@@ -294,14 +294,14 @@ export default defineComponent({
               />
               <GridItem
                 vSlots={{
-                  text: () => <span>音符重影(色在上):音高了</span>,
-                  icon: () => <Note fill="#FFAB25" shadow x={-3} y={0} />,
+                  text: () => <span>音符重影(色在上):音高了</span>,
+                  icon: () => <Note fill="#977CFF" shadow x={-3} y={0} />,
                 }}
               />
               <GridItem
                 vSlots={{
-                  text: () => <span>音符重影(色在下):音低了</span>,
-                  icon: () => <Note fill="#FFAB25" shadow x={-1} y={-2} />,
+                  text: () => <span>音符重影(色在下):音低了</span>,
+                  icon: () => <Note fill="#977CFF" shadow x={-1} y={-2} />,
                 }}
               />
               <GridItem

+ 1 - 1
src/subpages/colexiu/buttons/evaluating.tsx

@@ -309,7 +309,7 @@ const getEvaluationCriteria = () => {
  * @param num 频率
  * @returns 转化后频率
  */
-const formatPitch = (num?: number): number => {
+export const formatPitch = (num?: number): number => {
   if (!num) {
     return -1
   }

+ 1 - 0
src/subpages/colexiu/buttons/index.tsx

@@ -277,6 +277,7 @@ export default defineComponent({
             <>
               <Button
                 class={classNames(styles.button, styles.hasText, styles.minPadding)}
+                disabled={detailState.isCombineRender}
                 onClick={() => {
                   // 切换光标模式
                   let mode = metronomeData.cursorMode

+ 1 - 0
src/subpages/colexiu/index.tsx

@@ -389,6 +389,7 @@ export default defineComponent({
                     style={musicSheetStyle}
                     score={score.value}
                     isSoundEffect={true}
+                    showPartNames={detailState.isCombineRender}
                     EngravingRules={{
                       DYMusicScoreType: SettingState.sett.type,
                     }}

+ 34 - 0
src/subpages/colexiu/popups/follow/index.module.less

@@ -4,6 +4,18 @@
       fill: green;
     }
   }
+  .follow-down{
+    .vf-note path{
+      fill:#977CFF !important;
+      stroke: #977CFF !important;
+    }
+  }
+  .follow-up{
+    .vf-note path{
+      fill:rgb(255, 0, 0) !important;
+      stroke: rgb(255, 0, 0) !important;
+    }
+  }  
 }
 .follow {
   position: fixed;
@@ -77,3 +89,25 @@
   font-size: 12px;
   color: #fff;
 }
+
+.noteState {
+  position: fixed;
+  bottom: 0;
+  right: 10PX;
+  width: 100Px;
+  height: 30Px;
+  background-color: rgba(0, 0, 0, 0.3);
+  z-index: 1000;
+  border-radius: 4Px;
+  display: flex;
+  align-items: center;
+  justify-content: space-evenly;
+  color: #fff;
+
+  .dot {
+      width: 13Px;
+      height: 10Px;
+      border-radius: 50%;
+      transform: rotate(-20deg);
+  }
+}

+ 26 - 9
src/subpages/colexiu/popups/follow/index.tsx

@@ -11,6 +11,8 @@ import state, { refreshView, setCurrentTime } from '/src/pages/detail/runtime'
 import detailState from '/src/pages/detail/state'
 import iconFollwBtn from './icons/icon-follwBtn.png'
 import { unitTestData } from '/src/subpages/colexiu/unitTest/index'
+import { formatPitch } from '/src/subpages/colexiu/buttons/evaluating'
+
 // 显示或隐藏播放按钮
 const togglePlayer = (show: boolean = false) => {
   let globalPlayer: HTMLElement = document.querySelector('#globalPlayer')!
@@ -79,9 +81,11 @@ const onClear = () => {
   detailState.times.forEach((item) => {
     const note: HTMLElement = document.querySelector(`div[data-vf=vf${item.id}]`)!
     if (note) {
-      note.classList.remove('follow-error')
-      note.classList.remove('follow-success')
-      // note.classList.add('follow-error')
+      note.classList.remove('follow-up', 'follow-down', 'follow-error', 'follow-success')
+    }
+    const _note: HTMLElement = document.getElementById(`vf-${item.id}`)!
+    if (_note) {
+      _note.classList.remove('follow-up', 'follow-down')
     }
   })
 }
@@ -147,6 +151,8 @@ const getNoteIndex = (): any => {
     id: item.id,
     min: item.frequency - (item.frequency - item.noteElement.pitch.prevFrequency) * 0.1,
     max: item.frequency + (item.noteElement.pitch.nextFrequency - item.frequency) * 0.1,
+    duration: item.duration,
+    baseFrequency: formatPitch(item.noteElement.pitch.frequency),
   }
 }
 let checking = false
@@ -172,25 +178,30 @@ const checked = () => {
       next()
       data.index += 1
       data.list = data.list.slice(i + 1)
-      setColor(item, true)
+      setColor(item, '', true)
       checking = false
       return
     }
   }
-  setColor(item)
+  setColor(item, audioFrequency.value > item.baseFrequency ? 'follow-up' : 'follow-down')
   checking = false
 }
-const setColor = (item: any, isRight = false) => {
+
+const setColor = (item: any, state: 'follow-up' | 'follow-down' | '', isRight = false) => {
   const note: HTMLElement = document.querySelector(`div[data-vf=vf${item.id}]`)!
   if (note) {
+    note.classList.remove('follow-up', 'follow-down', 'follow-error', 'follow-success')
     if (isRight) {
-      note.classList.remove('follow-error')
       note.classList.add('follow-success')
     } else {
-      note.classList.remove('follow-success')
-      note.classList.add('follow-error')
+      note.classList.add('follow-error', state)
     }
   }
+  const _note: HTMLElement = document.getElementById(`vf-${item.id}`)!
+  if (_note) {
+    _note.classList.remove('follow-up', 'follow-down')
+    state && _note.classList.add(state)
+  }
 }
 
 export default defineComponent({
@@ -225,6 +236,12 @@ export default defineComponent({
               ></Button>
             )}
           </Transition>
+          <div style={{ display: data.start ? "" : "none" }} class={styles.noteState}>
+            <span style={{ background: "#977CFF" }} class={styles.dot}></span>
+            <span>低</span>
+            <span style={{ background: "rgb(255, 0, 0)" }} class={styles.dot}></span>
+            <span>高</span>
+          </div>          
           {/* <div class={styles.title}>
             <span>音符频率: {noteFrequency.value.toFixed(2)}</span>
             <span style={{ color: 'red', marginLeft: '10px' }}>拾音频率: {audioFrequency.value.toFixed(2)}</span>

+ 14 - 2
src/subpages/colexiu/uses/use-app.ts

@@ -10,7 +10,7 @@ import { listenerMessage, postMessage } from '/src/helpers/native-message'
 import audiosInstance from '/src/helpers/multiple-audio'
 import { formatXML, onlyVisible, getCustomInfo } from '/src/pages/detail/helpers'
 import { MusicSheelDetail, ShaeetStatusType } from '../index.d'
-import { browser, getRequestHostname, isEncoded } from '/src/helpers/utils'
+import { browser, getRequestHostname, isEncoded, setGlobalData } from '/src/helpers/utils'
 import formatId, { formatdata, getSubjectIdCode } from '../fingering/format-id'
 import { evaluatStopPlay } from '../buttons/evaluating'
 import state from '/src/pages/detail/state'
@@ -43,7 +43,12 @@ export const useXml = async (url: string, detail: MusicSheelDetail) => {
       score.value = formatXML(parseXmlInfo.parsedXML, {
         title: detail.musicSheetName,
       })
-      score.value = onlyVisible(score.value, partIndex)
+      // 多种乐器分轨合并显示
+      if (state.isCombineRender) {
+        setGlobalData('wrapNum', 4)
+      } else {
+        score.value = onlyVisible(score.value, partIndex)
+      }
       state.partIndex = partIndex
     }
     state.gradual = getGradualLengthByXml(xml)
@@ -171,6 +176,13 @@ export const useDetail = (id: number | string): [Ref<ShaeetStatusType>, Ref<Musi
       // 设置是否特殊曲谱, 是特殊曲谱取反(不理解之前的思考逻辑), 使用后台设置的速度
       detailState.isSpecialBookCategory = !classids.includes(res.data.musicSheetCategoriesId) 
       detailState.subjectId = Number(musicInfo.musicSubject)
+      // 打击乐声部下的曲目,需要合并展示所有分轨
+      if (Number(res.data.musicSubject) === 1 && res.data.background?.length > 1) {
+        state.isCombineRender = true
+        // 开启自定义每行显示的小节数
+        ;(window as any).customSectionAmount = true
+        setGlobalData('multitrack', res.data.background?.length)
+      }
       ;(window as any).DYSubjectId = formatId(data.value.code as any)
       status.value = 'success'