import { Popup, Skeleton } from "vant"; import { computed, defineComponent, nextTick, onBeforeMount, onBeforeUnmount, onMounted, reactive, Transition, watch, watchEffect } from "vue"; import { formateTimes } from "../../helpers/formateMusic"; import Metronome, { metronomeData } from "../../helpers/metronome"; import state, { EnumMusicRenderType, evaluatCreateMusicPlayer, handleSetSpeed, IAudioState, IPlatform, isRhythmicExercises, resetPlaybackToStart, togglePlay } from "/src/state"; import { browser, setGlobalData } from "../../utils"; import AudioList from "../../view/audio-list"; import MusicScore, { resetMusicScore } from "../../view/music-score"; 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 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" const calcCeilFrequency = (frequency: number) => { if (frequency) return frequency * 1000 * 2 / 1000; return 0 }; /** 需要处理频率的乐器 */ const resetFrequency = (list: any[]) => { const instrumentNames = ["ocarina", "pan-flute", "piccolo", "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 default defineComponent({ name: "music-list", setup() { const query: any = getQuery(); const detailData = reactive({ isLoading: true, skeletonLoading: true, paddingLeft: "", headerHide: false, fingerPreView: 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(() => { api_keepScreenLongLight(); getAPPData(); api_setStatusBarVisibility(); const settting = store.get("musicscoresetting"); if (settting) { state.setting = settting; if (state.setting.camera) { api_openCamera(); } } }); //给app传伴奏 const pushAppMusic = () => { api_cloudAccompanyMessage(state.accompany); }; // console.log(route.params, query) /** 获取曲谱数据 */ const getMusicInfo = (res: any) => { const index = query["part-index"] ? parseInt(query["part-index"] as string) : 0; const musicData = res.data.background[index] || {}; const musicInfo = { ...res.data, music: musicData.audioFileUrl || res.data.audioFileUrl, accompany: musicData.metronomeUrl || res.data.metronomeUrl, musicSheetId: musicData.musicSheetId || res.data.id, track: musicData.track || res.data.track, }; console.log("🚀 ~ musicInfo:", musicInfo); setState(musicInfo, index); setCustom(); detailData.isLoading = false; }; const setState = (data: any, index: number) => { state.appName = "COLEXIU"; state.detailId = data.id; state.xmlUrl = data.xmlFileUrl; state.partIndex = index; state.trackId = data.track; state.subjectId = data.musicSubject; state.categoriesId = data.categoriesId; state.categoriesName = data.musicTagNames; state.enableEvaluation = data.canEvaluate ? true : false; state.examSongId = data.id + ""; state.examSongName = data.musicSheetName; state.coverImg = data.titleImg ?? ""; // 解析扩展字段 if (data.extConfigJson) { try { state.extConfigJson = JSON.parse(data.extConfigJson as string); } catch (error) { console.error("解析扩展字段错误:", error); } } state.isOpenMetronome = data.mp3Type === "MP3_METRONOME" ? true : false; // 曲子包含节拍器,就不开启节拍器 state.needTick = data.mp3Type === "MP3_METRONOME" ? false : true; state.isShowFingering = data.showFingering ? true : false; state.music = data.music; state.accompany = data.accompany; state.midiUrl = data.midiUrl; state.parentCategoriesId = data.musicTag; state.musicSheetCategoriesId = data.musicSheetCategoriesId; state.playMode = data.audioType === "MP3" ? "MP3" : "MIDI"; state.originSpeed = state.speed = data.playSpeed; const track = data.code || data.track; state.track = track ? track.replace(/ /g, "").toLocaleLowerCase() : ""; state.enableNotation = data.notation ? true : false; // console.log("🚀 ~ state.subjectId:", state.subjectId, state.track as any , state.subjectId) // 是否打击乐 // state.isPercussion = // state.subjectId == 23 || // state.subjectId == 113 || // state.subjectId == 121 || // isRhythmicExercises(); // 设置指法 const code = mappingVoicePart(state.trackId, "INSTRUMENT"); state.fingeringInfo = subjectFingering(code); console.log("🚀 ~ state.fingeringInfo:", state.fingeringInfo, state.trackId, state.track); // 检测是否原音和伴奏都有 if (!state.music || !state.accompany) { state.playSource = state.music ? "music" : "background"; } // 如果是PC端,放大曲谱 state.platform = query.platform?.toLocaleUpperCase() || ""; if (state.platform === IPlatform.PC) { state.zoom = query.zoom || 1.5; } //课堂乐器, 渲染类型: 五线谱, 简谱 state.musicRenderType = query.musicRenderType || EnumMusicRenderType.firstTone; console.log('state对象', state) }; const setCustom = () => { if (state.extConfigJson.multitrack) { setGlobalData("multitrack", state.extConfigJson.multitrack); } }; onMounted(() => { (window as any).appName = "colexiu"; const id = query.id || "43554"; Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => { getMusicInfo(values[0]); }); api_setEventTracking(); }); /** 渲染完成 */ const handleRendered = (osmd: any) => { 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] || (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM; // 加载本地缓存的速度 if (saveSpeed) { handleSetSpeed(saveSpeed); } state.times = formateTimes(osmd); state.times = resetFrequency(state.times); state.times = setNoteHalfTone(state.times); console.log("🚀 ~ state.times:", state.times, state.subjectId, state); try { metronomeData.metro = new Metronome(); metronomeData.metro.init(state.times); } catch (error) {} // 设置节拍器 if (state.needTick) { const beatLengthInMilliseconds = (60 / state.speed) * 1000; // console.log(state.speed, osmd?.Sheet?.SheetPlaybackSetting?.beatLengthInMilliseconds , (60 / state.speed) * 1000) handleInitTick(beatLengthInMilliseconds, osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4); } api_cloudLoading(); state.musicRendered = true; evaluatCreateMusicPlayer(); resetPlaybackToStart(); pushAppMusic(); }; /** 指法配置 */ const fingerConfig = computed(() => { if (state.setting.displayFingering && state.fingeringInfo?.name) { if (state.fingeringInfo.direction === "transverse") { return { container: { paddingBottom: state.platform === IPlatform.PC ? `calc(${state.fingeringInfo.height} + ${state.attendHideMenu ? "0px" : "1.8rem"})` : state.fingeringInfo.height, }, fingerBox: { height: state.fingeringInfo.height, }, }; } 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") { nextTick(() => { resetMusicScore(); }); } } ); 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; } sendParentMessage(state.playState); } ); /** 指法预览切换 */ watch( () => detailData.fingerPreView, () => { console.log(2342); window.parent.postMessage( { api: "api_fingerPreView", state: detailData.fingerPreView, }, "*" ); } ); onMounted(() => { window.addEventListener("resize", resetMusicScore); }); onBeforeUnmount(() => { window.removeEventListener("resize", resetMusicScore); }); 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; }; return () => (
{detailData.skeletonLoading && (
)}
{state.musicRendered && }
{ e.stopPropagation(); if (state.playState === "play" && state.platform != IPlatform.PC) { detailData.headerHide = !detailData.headerHide; } }} > {/* 曲谱渲染 */} {!detailData.isLoading && } {/* 指法 */} {state.setting.displayFingering && state.fingeringInfo?.name && (
handleOpenFignerView()} />
)}
{/* 节拍器 */} {state.needTick && } {/* 播放 */} {!detailData.isLoading && } {/* 评测 */} {state.modeType === "evaluating" && ( <> {evaluatingData.rendered && } )} {/* 跟练模式 */} {state.modeType === "follow" && ( <> )} {/* 切换曲谱 */} {!query.lessonTrainingId && !query.questionId && ( )} {state.musicRendered && ( <> {/* 统计训练时长 */} {storeData.isApp && } {/* 作业 */} {query.workRecord && } {/* 曲谱列表 */} {state.playState == "play" || followData.start || evaluatingData.startBegin || query.workRecord || query.modelType || state.platform === IPlatform.PC ? null : } )} { detailData.fingerPreViewGuide = true; }} >
); }, });