import { Popup, Skeleton } from "vant"; import { computed, defineComponent, nextTick, onBeforeMount, onBeforeUnmount, onMounted, reactive, Transition, watch, watchEffect, defineAsyncComponent, ref } from "vue"; import { formateTimes } from "../../helpers/formateMusic"; import Metronome, { metronomeData } from "../../helpers/metronome"; import state, { EnumMusicRenderType, evaluatCreateMusicPlayer, handleSetSpeed, IAudioState, IPlatform, isRhythmicExercises, resetPlaybackToStart, togglePlay, getMusicDetail, addNoteBBox } from "/src/state"; import { browser, setGlobalData } from "../../utils"; import AudioList from "../../view/audio-list"; import MusicScore from "../../view/music-score"; import TestCheck from "/src/view/music-score/testCheck"; 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 { getQuery } from "/src/utils/queryString"; import Evaluating, { evaluatingData } from "/src/view/evaluating"; import MeasureSpeed from "/src/view/plugins/measure-speed"; import { mappingVoicePart, subjectFingering } from "/src/view/fingering/fingering-config"; import Fingering from "/src/view/fingering"; import store from "store"; import Tick, { handleInitTick } from "/src/view/tick"; import FollowPractice, { followData } from "/src/view/follow-practice"; import FollowModel from "../follow-model"; import RecordingTime from "../custom-plugins/recording-time"; import WorkIndex from "../custom-plugins/work-index"; import TheMusicList, { isMusicList } from "../component/the-music-list"; import { storeData } from "/src/store"; import ViewFigner from "../view-figner"; import { recalculateNoteData } from "/src/view/selection"; import ToggleMusicSheet from "/src/view/plugins/toggleMusicSheet"; import { setCustomGradual, setCustomNoteRealValue } from "/src/helpers/customMusicScore" import { usePageVisibility } from "@vant/use"; import { initMidi } from "/src/helpers/midiPlay" import TheAudio from "/src/components/the-audio" import tickWav from "/src/assets/tick.mp3"; import AuthorName from "../component/authorName" import { initSmoothAnimation } from "./smoothAnimation" const DelayCheck = defineAsyncComponent(() => import('/src/page-instrument/evaluat-model/delay-check') ) /** * 特殊教材分类id */ export const classids = [1, 2, 6, 7, 8, 9, 3, 10, 11, 12, 13, 4, 14, 15, 16, 17, 30, 31, 35, 36, 46, 108]; // 大雅金唐, 竖笛教程, 声部训练展开的分类ID const calcCeilFrequency = (frequency: number) => { if (frequency < 0) return frequency; if (frequency) return (frequency * 1000 * 2) / 1000; return 0; }; /** 需要处理频率的乐器 */ const resetFrequency = (list: any[]) => { // const instrumentNames = ["ocarina", "pan-flute", "piccolo", "hulusi-flute"]; const instrumentNames = ["ocarina", "pan-flute", "hulusi-flute"]; if (!state.fingeringInfo?.name || !instrumentNames.includes(state.fingeringInfo.name)) return list; // console.log(state.subjectId, state.fingeringInfo.name, instrumentNames); for (let i = 0; i < list.length; i++) { if (list[i].prevFrequency) list[i].prevFrequency = calcCeilFrequency(list[i].prevFrequency); if (list[i].frequency) list[i].frequency = calcCeilFrequency(list[i].frequency); if (list[i].nextFrequency) list[i].nextFrequency = calcCeilFrequency(list[i].nextFrequency); } return list; }; /** * 乐器指法处理 */ const setNoteHalfTone = (list: any[]) => { const instrumentNames = ["hulusi-flute"]; // ["ocarina", "pan-flute", "piccolo"]; 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 const musicScoreRef = ref(); export default defineComponent({ name: "music-list", setup() { const query: any = getQuery(); const detailData = reactive({ isLoading: true, skeletonLoading: true, paddingLeft: "", headerHide: false, fingerPreView: false, fingerPreViewAnimation: 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(async () => { console.time("渲染加载耗时"); api_keepScreenLongLight(); getAPPData(); api_setStatusBarVisibility(); const settting = store.get("musicscoresetting"); if (settting) { state.setting = settting; //state.setting.beatVolume = state.setting.beatVolume || 50 state.setting.beatVolume = 50 if (state.setting.camera) { const res = await api_openCamera(); // 没有授权 if (res?.content?.reson) { state.setting.camera = false store.set("musicscoresetting", state.setting); } } } }); //给app传伴奏 const pushAppMusic = () => { api_cloudAccompanyMessage(state.accompany); }; // console.log(route.params, query) onMounted(async () => { (window as any).appName = "colexiu"; const id = query.id || "43554"; // 如果是纯预览模式,0.65倍缩放谱面 state.isPreView = query.isPreView if (state.isPreView) { state.zoom = 0.65 } state.isSingleLine = query.isSingleLine === "true" ? true : false; // 一行谱模式 // Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => { // getMusicInfo(values[0]); // }); await getMusicDetail(id); detailData.isLoading = false; // 如果后台设置了不显示指法,关闭指法开关 if (!state.isShowFingering) { state.setting.displayFingering = false } // api_setEventTracking(); }); /** 渲染完成 */ const handleRendered = (osmd: any) => { api_cloudLoading(); console.timeEnd("渲染加载耗时"); 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] || state.speed || (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM; // 加载本地缓存的速度 if (saveSpeed) { handleSetSpeed(saveSpeed); } setCustomGradual(); setCustomNoteRealValue(); state.times = formateTimes(osmd); // 一行谱 if (state.isSingleLine) { // 音符添加位置信息bbox addNoteBBox(state.times); // 一行谱创建 动画 initSmoothAnimation(); } // state.times = resetFrequency(state.times); state.times = setNoteHalfTone(state.times); console.log("🚀 ~ state.times:", state.times, state.subjectId, state); // 初始化midi音频信息 const songEndTime = state.times[state.times.length - 1 || 0]?.endtime || 0 if (state.isAppPlay) { const durationNum = songEndTime initMidi(durationNum, state.midiUrl) } state.measureTime = state.times[0]?.measureLength || 0 try { metronomeData.metro = new Metronome(); metronomeData.metro.init(state.times); } catch (error) {} // 需要向外面(iframe)派发计时器数据的时候触发 if(query.isbeatTimes){ const { isOpenMetronome, isSingOpenMetronome } = state const { xmlMp3BeatFixTime } = metronomeData const singBeatTime: number[][] = [] const beatTime = metronomeData.metroMeasure.map(metroMeasure => { const singBeat:number[] = [] const beatTimeItem = metroMeasure.map((item: any) => { let singTime = item.time if(!state.isEvxml){ if(isSingOpenMetronome && !isOpenMetronome){ singTime += xmlMp3BeatFixTime } else if(!isSingOpenMetronome && isOpenMetronome){ singTime -= xmlMp3BeatFixTime } } singBeat.push(singTime) return item.time }) singBeatTime.push(singBeat) return beatTimeItem }) console.log("webApi_beatTimes",{beatTime,singBeatTime}) window.parent.postMessage( { api: "webApi_beatTimes", data: JSON.stringify({beatTime,singBeatTime}) }, "*" ); } /** * 2024.1.25 * 设置节拍器,跟练需要播放系统节拍器,所以不需要判断needTick状态 */ // if (state.needTick) { const beatLengthInMilliseconds = (60 / state.speed) * 1000; handleInitTick(beatLengthInMilliseconds, osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4); // } // api_cloudLoading(); state.playBtnDirection = query.imagePos === 'right' ? 'right' : 'left'; state.isAttendClass = (query.imagePos === 'left' || query.imagePos === 'right') ? true : false; // if (state.fingeringInfo.direction === "vertical" && state.setting.displayFingering) { // state.musicScoreBtnDirection = state.playBtnDirection === 'right' ? 'left' : 'right'; // } else { // state.musicScoreBtnDirection = state.playBtnDirection; // } state.musicScoreBtnDirection = state.playBtnDirection; state.musicRendered = true; evaluatCreateMusicPlayer(); resetPlaybackToStart(); // pushAppMusic(); // console.timeEnd("渲染加载耗时"); }; /** 指法配置 */ const fingerConfig = computed(() => { if (state.setting.displayFingering && state.fingeringInfo?.name) { if (state.fingeringInfo.direction === "transverse") { return { container: { paddingBottom: detailData.headerHide ? state.fingeringInfo.height : state.fingeringInfo.scaleData?.offset }, fingerBox: detailData.headerHide ? { height: state.fingeringInfo.height } : { height: state.fingeringInfo.height, transform: `scale(${state.fingeringInfo.scaleData?.scale})` } }; } else { console.log('指法',state.playBtnDirection,state.platform) // 老师端,竖向指法,需要根据功能按钮方向进行设置 if (state.platform === IPlatform.PC) { return { container: { paddingRight: state.playBtnDirection === "right" ? "initial" : state.fingeringInfo.width, paddingLeft: state.playBtnDirection === "right" ? state.fingeringInfo.width : "initial", }, fingerBox: { position: "absolute", width: state.fingeringInfo.width, height: "100%", right: state.playBtnDirection === "right" ? "initial" : 0, left: state.playBtnDirection === "right" ? 0 : "initial", top: 0, }, }; } 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") { // if (state.setting.displayFingering) { // state.musicScoreBtnDirection = state.playBtnDirection === 'left' ? 'right' : 'left' // } else { // state.musicScoreBtnDirection = state.playBtnDirection // } state.musicScoreBtnDirection = state.playBtnDirection } } ); 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; // } 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, }, "*" ); } ); const pageVisible = usePageVisibility(); watch( () => pageVisible.value, (val) => { if (val === "hidden") { // 如果是播放状态,需要暂停播放 // console.log("页面隐藏停止播放"); if (state.playState === "play") { togglePlay("paused"); } } } ); 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; }; // 模式样式 const modeClass = computed(() => { const modeType = state.modeType if(modeType === "practise"){ return styles.practise } if(modeType === "evaluating"){ return styles.evaluating } if(modeType === "follow"){ return styles.follow } }) return () => (
0.8) && styles.PC, state.isPreView && styles.preViewDetail]} style={{ paddingLeft: detailData.paddingLeft, background: state.setting.camera ? `rgba(${state.setting.eyeProtection ? "253,244,229" : "255,255,255"} ,${state.setting.cameraOpacity / 100}) !important` : "", }} > {/* 骨架屏 */} {detailData.skeletonLoading && (
)}
{/** 功能按钮 */} { !state.isPreView &&
{state.musicRendered && }
}
{ e.stopPropagation(); // if (state.playState === "play" && state.platform != IPlatform.PC) { // detailData.headerHide = !detailData.headerHide; // } if (state.playState === "play") { detailData.headerHide = !detailData.headerHide; } }} > {/* 曲谱渲染 */} {!detailData.isLoading && {/* 旋律线关闭时候的 标题和作者 */} {/* 节拍器 */} {!detailData.isLoading && !detailData.skeletonLoading && } } {/* { state.musicRendered && } */} {/* 指法 */} {state.setting.displayFingering && state.fingeringInfo?.name && !state.isPreView && state.isShowFingering && (
handleOpenFignerView()} />
)}
{/* 曲目渲染完成,再去下载mp3资源 */} {!detailData.isLoading && !detailData.skeletonLoading && } {/* {!detailData.isLoading && } */} {/* 预加载延迟检测组建 */} {!detailData.isLoading && !detailData.skeletonLoading && evaluatingData.preloadJson && !evaluatingData.jsonLoadDone && (
)} {/* 评测 */} {state.modeType === "evaluating" && ( <> {evaluatingData.rendered && } )} {/* 跟练模式 */} {state.modeType === "follow" && ( <> )} {/* 切换曲谱 */} {!query.lessonTrainingId && !query.questionId && state.isConcert && } {state.musicRendered && !state.isPreView && ( <> {/* 统计训练时长 */} {storeData.isApp && } {/* 作业 */} {query.workRecord && } {/* 曲谱列表 */} {isMusicList.value && } )} { detailData.fingerPreViewAnimation = false; }} onOpen={() => { detailData.fingerPreViewAnimation = true; }} onOpened={() => { detailData.fingerPreViewGuide = true; }} > {detailData.fingerPreViewAnimation && }
); }, });