|
@@ -333,13 +333,16 @@ const state = reactive({
|
|
|
banSong: "",
|
|
|
/** 唱名 */
|
|
|
mingSong: "",
|
|
|
+ /** 唱名女 如果有男唱名的情况下*/
|
|
|
+ mingSongGirl:"",
|
|
|
/** 节拍器音乐资源 */
|
|
|
beatSong: {
|
|
|
music: "",
|
|
|
accompany: "",
|
|
|
fanSong: "",
|
|
|
banSong: "",
|
|
|
- mingSong: ""
|
|
|
+ mingSong: "",
|
|
|
+ mingSongGirl: ""
|
|
|
},
|
|
|
/** midiURL */
|
|
|
midiUrl: "",
|
|
@@ -481,7 +484,13 @@ const state = reactive({
|
|
|
/** 乐器code,用于评测传参 */
|
|
|
musicalCode: '' as any,
|
|
|
/** 合奏曲目是否合并展示 */
|
|
|
- isCombineRender: false,
|
|
|
+ isCombineRender: false,
|
|
|
+ /** 是否支持总谱 */
|
|
|
+ isScoreRender: false,
|
|
|
+ /** 是否默认显示总谱 */
|
|
|
+ defaultScoreRender: false,
|
|
|
+ /** 没有音源字段 */
|
|
|
+ noMusicSource: false,
|
|
|
/** 小节的持续时长,以后台设置的播放速度计算 */
|
|
|
measureTime: 0,
|
|
|
/** 跟练模式,节拍器播放的时间 */
|
|
@@ -1313,17 +1322,20 @@ export const getMusicDetail = async (id: string, type?: string) => {
|
|
|
|
|
|
|
|
|
const getMusicInfo = async (res: any) => {
|
|
|
+ // 是否支持总谱
|
|
|
+ state.isScoreRender = res.data?.isScoreRender
|
|
|
+ // 是否默认显示总谱
|
|
|
+ state.defaultScoreRender = res.data?.defaultScoreRender
|
|
|
+ const partIndex = query["part-index"] ? parseInt(query["part-index"]) : -1 // -1为partIndex没有值的时候
|
|
|
+ /* 获取声轨列表 */
|
|
|
const xmlString = await fetch(res.data.xmlFileUrl).then((response) => response.text());
|
|
|
downloadXmlStr.value = xmlString //给musice-score 赋值xmlString 以免加载2次
|
|
|
const tracks = xmlToTracks(xmlString) //获取声轨列表
|
|
|
- let index = query["part-index"] ? parseInt(query["part-index"]) : 0
|
|
|
- const musicObj = state.isSimplePage ? {} : initMusicSource(res.data, tracks[index]) //当前part-index找不到声源的时候以第一个为准
|
|
|
- index = tracks.findIndex(item => { // 筛选出当前的index
|
|
|
- return item === musicObj?.track
|
|
|
- })
|
|
|
+ // 设置音源 track 为当前的声轨 index为当前的
|
|
|
+ const { track, index } = state.isSimplePage ? { track:tracks[0], index:0} : initMusicSource(res.data, tracks, partIndex)
|
|
|
const musicInfo = {
|
|
|
...res.data,
|
|
|
- track: musicObj?.track
|
|
|
+ track
|
|
|
};
|
|
|
console.log("🚀 ~ musicInfo:", musicInfo);
|
|
|
setState(musicInfo, index);
|
|
@@ -1341,15 +1353,16 @@ function xmlToTracks(xmlString: string) {
|
|
|
}, []);
|
|
|
}
|
|
|
// 设置音源
|
|
|
-function initMusicSource(data: any, track?: string) {
|
|
|
+function initMusicSource(data: any, tracks: string[], partIndex: number) {
|
|
|
+ let track:string,index:number
|
|
|
const { instrumentId } = storeData.user
|
|
|
let { musicSheetType, isAllSubject, musicSheetSoundList, musicSheetAccompanimentList } = data
|
|
|
musicSheetSoundList || (musicSheetSoundList = [])
|
|
|
musicSheetAccompanimentList || (musicSheetAccompanimentList = [])
|
|
|
let musicObj, accompanyObj, fanSongObj, banSongObj
|
|
|
- // 独奏
|
|
|
+ /* 独奏 */
|
|
|
if (musicSheetType === "SINGLE") {
|
|
|
- // 适用声部(instrumentId)为true 时候没有乐器只有一个原音;当前用户有乐器就匹配 不然取第一个原音
|
|
|
+ // 适用声部(isAllSubject)为true 时候没有乐器只有一个原音;当前用户有乐器就匹配 不然取第一个原音
|
|
|
musicObj = musicSheetSoundList.find((item: any) => {
|
|
|
return (isAllSubject || !instrumentId) ? item.audioPlayType === "PLAY" : (item.audioPlayType === "PLAY" && item.musicalInstrumentId == instrumentId)
|
|
|
})
|
|
@@ -1363,22 +1376,70 @@ function initMusicSource(data: any, track?: string) {
|
|
|
banSongObj = musicSheetAccompanimentList.find((item: any) => {
|
|
|
return item.audioPlayType === "SING"
|
|
|
})
|
|
|
+ accompanyObj = musicSheetAccompanimentList.find((item: any) => {
|
|
|
+ return item.audioPlayType === "PLAY"
|
|
|
+ })
|
|
|
+ track = musicObj?.track //没有原音的时候track为空 不显示指法
|
|
|
+ index = tracks.findIndex(item => {
|
|
|
+ return item === track
|
|
|
+ })
|
|
|
} else {
|
|
|
- // 合奏 合奏根据声轨来区分原音
|
|
|
- musicObj = track ? musicSheetSoundList.find((item: any) => {
|
|
|
- return item.track === track
|
|
|
- }) : musicSheetSoundList[0]
|
|
|
+ /* 合奏 */
|
|
|
+ // 支持总谱 并且当前是总谱。partIndex是999时候,或者默认是总谱并且partIndex为-1时候 -1就是partIndex没有值
|
|
|
+ if(state.isScoreRender && (partIndex===999 || (state.defaultScoreRender && partIndex===-1))){
|
|
|
+ // 总谱渲染
|
|
|
+ state.isCombineRender = true
|
|
|
+ state.partListNames = tracks
|
|
|
+ banSongObj = musicSheetAccompanimentList.find((item: any) => {
|
|
|
+ return item.audioPlayType === "SING"
|
|
|
+ })
|
|
|
+ // 先取scoreAudioFileUrl的值
|
|
|
+ if(banSongObj?.scoreAudioFileUrl){
|
|
|
+ banSongObj.audioFileUrl = banSongObj.scoreAudioFileUrl
|
|
|
+ banSongObj.audioBeatMixUrl = banSongObj.scoreAudioBeatMixUrl
|
|
|
+ }
|
|
|
+ accompanyObj = musicSheetAccompanimentList.find((item: any) => {
|
|
|
+ return item.audioPlayType === "PLAY"
|
|
|
+ })
|
|
|
+ // 先取scoreAudioFileUrl的值
|
|
|
+ if(accompanyObj?.scoreAudioFileUrl){
|
|
|
+ accompanyObj.audioFileUrl = accompanyObj.scoreAudioFileUrl
|
|
|
+ accompanyObj.audioBeatMixUrl = accompanyObj.scoreAudioBeatMixUrl
|
|
|
+ }
|
|
|
+ track = "总谱"
|
|
|
+ index = 999
|
|
|
+ }else{
|
|
|
+ // 合奏只显示一个声轨
|
|
|
+ track = tracks[partIndex===-1?0:partIndex]
|
|
|
+ // 根据当前的声轨 取数据
|
|
|
+ musicObj = musicSheetSoundList.find((item: any) => {
|
|
|
+ return item.audioPlayType === "PLAY" && item.track === track
|
|
|
+ })
|
|
|
+ fanSongObj = musicSheetSoundList.find((item: any) => {
|
|
|
+ return item.audioPlayType === "SING" && item.track === track
|
|
|
+ })
|
|
|
+ banSongObj = musicSheetAccompanimentList.find((item: any) => {
|
|
|
+ return item.audioPlayType === "SING"
|
|
|
+ })
|
|
|
+ accompanyObj = musicSheetAccompanimentList.find((item: any) => {
|
|
|
+ return item.audioPlayType === "PLAY"
|
|
|
+ })
|
|
|
+ index = tracks.findIndex(item => {
|
|
|
+ return item === track
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
- accompanyObj = musicSheetAccompanimentList.find((item: any) => {
|
|
|
- return item.audioPlayType === "PLAY"
|
|
|
- })
|
|
|
// 当没有任何曲目的时候报错
|
|
|
- if (!musicObj?.audioFileUrl && !accompanyObj?.audioFileUrl && !fanSongObj?.audioFileUrl && !banSongObj?.audioFileUrl && !fanSongObj?.solmizationFileUrl) {
|
|
|
- // 并且是midi没有midi文件的时候
|
|
|
- if(data.playMode === "MIDI" && !data.midiFileUrl) {
|
|
|
- // 是预览的时候 不报错
|
|
|
- if(!query.isPreView){
|
|
|
- throw new Error("该曲目无任何音源");
|
|
|
+ if (!musicObj?.audioFileUrl && !accompanyObj?.audioFileUrl && !fanSongObj?.audioFileUrl && !banSongObj?.audioFileUrl && !fanSongObj?.solmizationFileUrl && !fanSongObj?.femaleSolmizationFileUrl) {
|
|
|
+ state.noMusicSource = true // 没有音源文件
|
|
|
+ // 独奏的时候
|
|
|
+ if(musicSheetType === "SINGLE"){
|
|
|
+ // 并且是midi没有midi文件的时候
|
|
|
+ if(data.playMode === "MIDI" && !data.midiFileUrl) {
|
|
|
+ // 是预览的时候 不报错
|
|
|
+ if(!query.isPreView){
|
|
|
+ throw new Error("该曲目无任何音源");
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1387,16 +1448,31 @@ function initMusicSource(data: any, track?: string) {
|
|
|
accompany: accompanyObj?.audioFileUrl,
|
|
|
fanSong: fanSongObj?.audioFileUrl,
|
|
|
banSong: banSongObj?.audioFileUrl,
|
|
|
- mingSong: fanSongObj?.solmizationFileUrl
|
|
|
})
|
|
|
+ // 如果没有男唱名
|
|
|
+ if(!fanSongObj?.solmizationFileUrl){
|
|
|
+ state.mingSong = fanSongObj?.femaleSolmizationFileUrl
|
|
|
+ }else{
|
|
|
+ state.mingSong = fanSongObj?.solmizationFileUrl
|
|
|
+ state.mingSongGirl = fanSongObj?.femaleSolmizationFileUrl
|
|
|
+ }
|
|
|
Object.assign(state.beatSong, {
|
|
|
music: musicObj?.audioBeatMixUrl,
|
|
|
accompany: accompanyObj?.audioBeatMixUrl,
|
|
|
fanSong: fanSongObj?.audioBeatMixUrl,
|
|
|
- banSong: banSongObj?.audioBeatMixUrl,
|
|
|
- mingSong: fanSongObj?.solmizationBeatUrl
|
|
|
+ banSong: banSongObj?.audioBeatMixUrl
|
|
|
})
|
|
|
- return musicObj
|
|
|
+ // 如果没有男唱名
|
|
|
+ if(!fanSongObj?.solmizationBeatUrl){
|
|
|
+ state.beatSong.mingSong = fanSongObj?.femaleSolmizationBeatUrl
|
|
|
+ }else{
|
|
|
+ state.beatSong.mingSong = fanSongObj?.solmizationBeatUrl
|
|
|
+ state.beatSong.mingSongGirl = fanSongObj?.femaleSolmizationBeatUrl
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ index,
|
|
|
+ track
|
|
|
+ }
|
|
|
}
|
|
|
const setState = (data: any, index: number) => {
|
|
|
// 根据当前文件有没有 设置当前的播放模式
|
|
@@ -1443,8 +1519,6 @@ const setState = (data: any, index: number) => {
|
|
|
state.cbsExamSongId = data.id + "";
|
|
|
state.examSongName = data.name;
|
|
|
state.coverImg = data.musicCover ?? "";
|
|
|
- // 单声部多声轨合并展示
|
|
|
- state.isCombineRender = data.musicSheetType === "SINGLE" && data.musicSheetSoundList?.length > 1
|
|
|
// 如果是simple页面,只显示单轨
|
|
|
if (state.isSimplePage) {
|
|
|
state.isCombineRender = false;
|
|
@@ -1713,7 +1787,9 @@ export const fillWordColor = () => {
|
|
|
const currentLyrics: SVGAElement[] = Array.from(document.querySelectorAll(`.lyric${currentNote?.noteId}`));
|
|
|
currentLyrics.forEach((lyric, index) => {
|
|
|
const lyricIndex = lyric.getAttribute('lyricIndex');
|
|
|
- if ((index === currentNote.repeatIdx && currentNote.repeatIdx + 1 == lyricIndex) || (currentNote.repeatIdx > 0 && currentNote.formatLyricsEntries?.length === 1)) {
|
|
|
+ // bug:#10942,如果需要反复唱的小节,只有一遍歌词,反复唱的时候,歌词都需要高亮
|
|
|
+ const onlyOneLyric = currentNote.measures?.every((item: any) => item?.formatLyricsEntries?.length <= 1);
|
|
|
+ if ((index === currentNote.repeatIdx && currentNote.repeatIdx + 1 == lyricIndex) || (currentNote.repeatIdx != index && !onlyOneLyric && currentNote.repeatIdx + 1 == lyricIndex) || (currentNote.repeatIdx > 0 && currentNote.formatLyricsEntries?.length === 1 && onlyOneLyric)) {
|
|
|
lyric?.classList.add('lyricActive')
|
|
|
}
|
|
|
// if ((index === currentNote.repeatIdx && currentNote.repeatIdx + 1 == lyricIndex)) {
|