import { Popup, Skeleton } from "vant"; import { computed, defineComponent, nextTick, onBeforeMount, onBeforeUnmount, onMounted, onUnmounted, 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, { handlerModeChange } 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, { resetSection } from "../custom-plugins/work-index"; import TheMusicList, { isMusicList } from "../component/the-music-list"; import { storeData } from "/src/store"; import ViewFigner from "../view-figner"; 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"; import EmptyMusic, { isEmptyMusicShow } from "./emptyMusic"; import { position } from "html2canvas/dist/types/css/property-descriptors/position"; import Loading from "./loading" import ExerciseStatistics from "../custom-plugins/ExerciseStatistics" import { musicData } from "/src/view/music-score" import Vip from "/src/page-instrument/component/vip" import { getSvgPngToSize } from "/src/helpers/svgToPng" // import bgJson from "./images/index.json"; // 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 const fingerRef = ref(); export const headerColumnHide = ref(false); // 是否隐藏功能按钮,播放时自动隐藏 export default defineComponent({ name: "music-list", setup() { const browsInfo = browser(); const query: any = getQuery(); const detailData = reactive({ isLoading: true, skeletonLoading: true, paddingLeft: "0px", 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 = 27 + "px"; } } }; console.time('加载过程') onBeforeMount(async () => { // console.time("渲染加载耗时"); api_keepScreenLongLight(); getAPPData(); api_setStatusBarVisibility(); const settting = store.get("musicscoresetting"); if (settting) { //state.setting = settting; Object.assign(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); }; const changePlay = (res: any) => { if (res?.data?.api === 'setPlayState') { console.log('父页面的切换事件关闭播放') if (state.playState === "play") { togglePlay("paused") } } }; // console.log(route.params, query) onMounted(async () => { (window as any).appName = "colexiu"; const id = query.id || "43554"; state.isCbsView = query.isCbs; state.isHomeWork = query.workRecord || query.evaluatingRecord; // 如果是纯预览模式,0.65倍缩放谱面 state.isPreView = query.isPreView; state.isWeb = query.systemType === 'web'; if (state.isPreView) { state.zoom = query.zoom || 0.65 } if (id == "1814218144844087298" && state.isSingleLine) { state.zoom = 0.7; } // 只有总控平台和预览 默认是多行谱 //(state.isPreView || query.isCbs) && (state.isSingleLine = false) // Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => { // getMusicInfo(values[0]); // }); window.addEventListener('message', changePlay) const guideInfoStore = localStorage.getItem('guideInfo') ? JSON.parse(localStorage.getItem('guideInfo')) : {}; state.guideInfo = guideInfoStore try { await getMusicDetail(id); } catch (err) { console.error(err); state.isLoading = false; isEmptyMusicShow.value = true // 需要向外面(iframe)派发计时器数据的时候触发 if(query.isbeatTimes){ console.log("webApi_beatTimes",err) window.parent.postMessage( { api: "webApi_beatTimes", data: "节拍器时值错误!!" }, "*" ); } return } detailData.isLoading = false; // 如果后台设置了不显示指法,关闭指法开关 如果默认进来是演奏模式 不显示指法开关 if (!state.isShowFingering || state.playType === "sing") { state.setting.displayFingering = false; } // api_setEventTracking(); }); onUnmounted(() => { window.removeEventListener('message', changePlay) }); /** 渲染完成 */ const handleRendered = (osmd: any) => { api_cloudLoading(); console.timeEnd("渲染加载耗时"); console.timeLog('加载过程','谱面渲染完成') state.isLoading = false 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); // state.times = resetFrequency(state.times); state.times = setNoteHalfTone(state.times); state.xmlHasLyric = state.times.some((item: any) => item?.formatLyricsEntries?.length); console.log("🚀 ~ state.times:", state.times, state.subjectId, state); nextTick(() => { state.activeMeasureIndex = state.times[0].MeasureNumberXML; }); // 一行谱 if (state.isSingleLine) { // 音符添加位置信息bbox addNoteBBox(state.times); // 一行谱创建 动画 initSmoothAnimation(); } // 初始化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) { console.log(error, "err") } // 需要向外面(iframe)派发计时器数据的时候触发 if (query.isbeatTimes) { const { isOpenMetronome, isSingOpenMetronome } = state; const { xmlMp3BeatFixTime, difftime } = state.times[0]; const singBeatTime: number[][] = []; const beatTime = metronomeData.metroMeasure.map((metroMeasure) => { const singBeat: number[] = []; const beatTimeItem = metroMeasure.map((item: any) => { let singTime = item.time; if (isSingOpenMetronome && !isOpenMetronome) { singTime += xmlMp3BeatFixTime; } else if (!isSingOpenMetronome && isOpenMetronome) { singTime -= xmlMp3BeatFixTime; } singBeat.push(singTime); return item.time; }); singBeatTime.push(singBeat); return beatTimeItem; }); //改为唱名 state.fixtime = difftime; state.times.map((item) => { item.time = item.xmlNoteTime + difftime; item.endtime = item.xmlNoteEndTime + difftime; item.fixtime = difftime; }); metronomeData.metro.calculation(state.times); const mingBeatTime: number[][] = metronomeData.metroMeasure.map((metroMeasure) => { const beatTimeItem = metroMeasure.map((item: any) => { return item.time; }); return beatTimeItem; }); const webApi_beatTimes = { beatTime, singBeatTime, mingBeatTime, isBeatTime:!state.isEvxml, isSingBeatTime:!state.isEvxml, isMingBeatTime:!state.isEvxml } console.log("webApi_beatTimes", webApi_beatTimes); window.parent.postMessage( { api: "webApi_beatTimes", data: JSON.stringify(webApi_beatTimes), }, "*" ); return } // 刷新时值 handlerModeChange("play", "music"); /** * 2024.1.25 * 设置节拍器,跟练需要播放系统节拍器,所以不需要判断needTick状态 */ // if (state.needTick) { handleInitTick(); // } // api_cloudLoading(); // state.playBtnDirection = query.imagePos === 'left' ? 'left' : 'right'; // 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; // } // 管乐迷曲谱详情页,需要下载A4尺寸的图片 setTimeout(() => { if (query.downPng === 'A4' && state.partIndex != 999) { const imgList = getSvgPngToSize(state.osmd) console.log('A4', imgList) window.parent.postMessage({ api: 'musicStaffRender', loading: false, osmdImg: imgList }, '*'); } }, 100); state.musicScoreBtnDirection = state.playBtnDirection; state.musicRendered = true; evaluatCreateMusicPlayer(); resetPlaybackToStart(); // 需要重新设置作业选段 if (state.workSectionNeedReset) { resetSection(); } // pushAppMusic(); // console.timeEnd("渲染加载耗时"); }; function handleOnRendered(osmd: any) { try{ handleRendered(osmd) }catch(err:any){ console.log(err, "err") // 需要向外面(iframe)派发计时器数据的时候触发 if(query.isbeatTimes){ console.log("webApi_beatTimes",err) window.parent.postMessage( { api: "webApi_beatTimes", data: "节拍器时值错误!!" }, "*" ); } } } /** 指法配置 */ const fingerConfig = computed(() => { if (state.setting.displayFingering && state.fingeringInfo?.name) { // 横向指法 console.log("横向指法", state.fingeringInfo.name); if (state.fingeringInfo.direction === "transverse") { return { container: { //paddingBottom: headerColumnHide.value ? state.fingeringInfo.height : state.fingeringInfo.scaleData?.offset paddingBottom: state.fingeringInfo.height }, // 横向指法,跟练&评测模式,默认展示贴底展示 // fingerBox: headerColumnHide.value ? { // height: state.fingeringInfo.height // } : { // height: state.fingeringInfo.height, // transform: `scale(${state.fingeringInfo.scaleData?.scale})` // } fingerBox: { height: state.fingeringInfo.height } }; } else { console.log("竖向指法", state.fingeringInfo.name, 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: state.fingeringInfo.name === "hulusi-flute" ? "86%" : "80%", right: state.playBtnDirection === "right" ? "initial" : 0, left: state.playBtnDirection === "right" ? 0 : "initial", top: (state.fingeringInfo.name === "ocarina" || state.fingeringInfo.name === "whistling") ? "60px" : state.fingeringInfo.name === "hulusi-flute" ? "10px" : (state.fingeringInfo.name === "baroque-recorder" || state.fingeringInfo.name === "piccolo") ? "36px" : "10%", }, }; } else { return { container: { paddingLeft: state.fingeringInfo.width, }, fingerBox: { position: "absolute", width: state.fingeringInfo.width, height: state.fingeringInfo.name === "hulusi-flute" ? "86%" : "80%", left: 0, top: (state.fingeringInfo.name === "ocarina" || state.fingeringInfo.name === "whistling") ? "60px" : state.fingeringInfo.name === "hulusi-flute" ? "10px" : (state.fingeringInfo.name === "baroque-recorder" || state.fingeringInfo.name === "piccolo") ? "36px" : "10%", }, }; } } } 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, () => { _timeColumnHide && clearTimeout(_timeColumnHide) headerColumnHide.value = state.playState === "play" ? true : false; sendParentMessage(state.playState); } ); // 监听跟练的开启状态 watch( () => followData.practiceStart, () => { _timeColumnHide && clearTimeout(_timeColumnHide) headerColumnHide.value = followData.practiceStart; } ); // 监听开始评测状态 watch( () => evaluatingData.startBegin, () => { _timeColumnHide && clearTimeout(_timeColumnHide) headerColumnHide.value = evaluatingData.startBegin; } ); /** 指法预览切换 */ 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 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; }; let _timeColumnHide: NodeJS.Timeout return () => (
0.8 && styles.PC, state.isPreView && styles.preViewDetail, state.isCbsView && styles.cbsViewDetail]} style={{ "--detailDataPaddingLeft": detailData.paddingLeft, paddingLeft: detailData.paddingLeft, background: state.setting.camera && state.modeType === 'evaluating' ? `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" || followData.start || evaluatingData.startBegin) { _timeColumnHide && clearTimeout(_timeColumnHide) headerColumnHide.value = !headerColumnHide.value; if(!headerColumnHide.value){ _timeColumnHide = setTimeout(() => { _timeColumnHide && clearTimeout(_timeColumnHide) headerColumnHide.value = true }, 3000); } } }} > {/* 曲谱渲染 */} {!detailData.isLoading && {/* 旋律线关闭时候的 标题和作者 */} { musicData.showSelection && } {/* 节拍器 */} {!detailData.isLoading && !detailData.skeletonLoading && } } {/* { state.musicRendered && } */} {/* 指法 */} {state.setting.displayFingering && state.fingeringInfo?.name && !state.isPreView && state.isShowFingering && (
handleOpenFignerView()} />
)}
{/* 曲目渲染完成,再去下载mp3资源 */} {!detailData.isLoading && } {/* {!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 && ( <> {/* 统计训练时长 */} {/* 今日练习统计 */} {state.systemType === "student" && } {/* 作业 */} {state.isHomeWork && } {/* 曲谱列表 */} {isMusicList.value && } )} {/* vip */} { !detailData.isLoading && } { detailData.fingerPreViewAnimation = false; }} onOpen={() => { detailData.fingerPreViewAnimation = true; }} onOpened={() => { detailData.fingerPreViewGuide = true; }} > {detailData.fingerPreViewAnimation && }
); }, });