|
@@ -7,7 +7,8 @@ import {
|
|
|
onMounted,
|
|
|
onUnmounted,
|
|
|
reactive,
|
|
|
- ref
|
|
|
+ ref,
|
|
|
+ watch
|
|
|
} from 'vue';
|
|
|
import styles from './index.module.less';
|
|
|
import icon_back from './images/icon_back.png';
|
|
@@ -21,7 +22,8 @@ import {
|
|
|
NModal,
|
|
|
NPopselect,
|
|
|
NSpace,
|
|
|
- NSpin
|
|
|
+ NSpin,
|
|
|
+ NPopover
|
|
|
} from 'naive-ui';
|
|
|
import TheSearch from '/src/components/TheSearch';
|
|
|
import { IMusicItem } from './type';
|
|
@@ -33,6 +35,7 @@ import icon_favitor from '/src/common/images/icon-collect-default.png';
|
|
|
import icon_favitorActive from '/src/common/images/icon-collect-active.png';
|
|
|
import icon_default from './images/icon_default.png';
|
|
|
import icon_close from './images/icon-close.png';
|
|
|
+import icon_trans from './images/icon_trans.png'
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
import PlayItem from './component/play-item';
|
|
|
import PlayLoading from './component/play-loading';
|
|
@@ -50,6 +53,8 @@ import TheEmpty from '/src/components/TheEmpty';
|
|
|
import { state } from '/src/state';
|
|
|
import { useResizeObserver } from '@vueuse/core';
|
|
|
import { vaildMusicScoreUrl } from '/src/utils/urlUtils';
|
|
|
+import { getInstrumentName, sortMusical } from '/src/utils'
|
|
|
+
|
|
|
export default defineComponent({
|
|
|
name: 'XiaokuMusic',
|
|
|
setup() {
|
|
@@ -79,7 +84,11 @@ export default defineComponent({
|
|
|
showPreivew: false,
|
|
|
previewUrl: '',
|
|
|
showCloseBtn: true,
|
|
|
- iframeSrc: ''
|
|
|
+ iframeSrc: '',
|
|
|
+ showMusicImg: 'staff' as 'staff' | 'first' | 'fixed', // 显示哪种曲谱
|
|
|
+ trackList: [] as any, // 可筛选的分轨信息
|
|
|
+ showTransBtn: true, // 是否显示转谱按钮
|
|
|
+ trackName: '切换声轨' as any, // 分轨名字
|
|
|
});
|
|
|
const showGuide = ref(false);
|
|
|
const userStore = useUserStore();
|
|
@@ -183,6 +192,7 @@ export default defineComponent({
|
|
|
}
|
|
|
});
|
|
|
obv.observe(spinRef.value);
|
|
|
+ analyzeXml();
|
|
|
window.addEventListener('message', iframeHandle);
|
|
|
});
|
|
|
onUnmounted(() => {
|
|
@@ -296,11 +306,19 @@ export default defineComponent({
|
|
|
// 'origin',
|
|
|
// `${origin}/instrument/?id=${details.id}&modelType=practise&modeType=json&Authorization=${token}&isPreView=true&part-index=${data.musicInstrumentIndex}`
|
|
|
// );
|
|
|
+ const musicRenderType =
|
|
|
+ data.showMusicImg === 'first'
|
|
|
+ ? 'firstTone'
|
|
|
+ : data.showMusicImg === 'fixed'
|
|
|
+ ? 'fixedTone'
|
|
|
+ : data.showMusicImg === 'staff'
|
|
|
+ ? 'staff'
|
|
|
+ : 'firstTone';
|
|
|
data.iframeSrc = `${vaildMusicScoreUrl()}/instrument/?id=${
|
|
|
details.id
|
|
|
}&modelType=practise&modeType=json&Authorization=${token}&isPreView=true&part-index=${
|
|
|
data.musicInstrumentIndex
|
|
|
- }`;
|
|
|
+ }&musicRenderType=${musicRenderType}`;
|
|
|
};
|
|
|
|
|
|
/** 音频控制 */
|
|
@@ -323,6 +341,123 @@ export default defineComponent({
|
|
|
handleFavitor();
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+ const _actions = [
|
|
|
+ {
|
|
|
+ value: 'staff',
|
|
|
+ label: '五线谱'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'first',
|
|
|
+ label: '首调'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'fixed',
|
|
|
+ label: '固定调'
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 解析xml,获取分轨信息
|
|
|
+ const analyzeXml = async () => {
|
|
|
+ const details: any = data.list[data.listActive];
|
|
|
+ if (details.musicalInstruments?.length > 1) {
|
|
|
+ if (details.xmlFileUrl) {
|
|
|
+ const res = await fetch(details.xmlFileUrl).then((response) => response.text());
|
|
|
+ filterTracks(res)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // showMusicImg: 'first' as 'staff' | 'first' | 'fixed',
|
|
|
+ const { defaultScore, transferFlag } = details.musicalInstruments[0] || {}
|
|
|
+ let musicImgType: 'staff' | 'first' | 'fixed' = 'staff';
|
|
|
+ musicImgType = defaultScore === 'STAVE' ? 'staff' : defaultScore === 'JIAN' ? 'fixed' : defaultScore === 'FIRST' ? 'first' : 'staff'
|
|
|
+ data.showMusicImg = musicImgType
|
|
|
+ data.showTransBtn = transferFlag
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 过滤出能切换的分轨
|
|
|
+ const filterTracks = (xml: any) => {
|
|
|
+ const xmlParse = new DOMParser().parseFromString(xml, 'text/xml');
|
|
|
+ const partList =
|
|
|
+ xmlParse
|
|
|
+ .getElementsByTagName('part-list')?.[0]
|
|
|
+ ?.getElementsByTagName('score-part') || [];
|
|
|
+ const partListNames = Array.from(partList).map(
|
|
|
+ item =>
|
|
|
+ item.getElementsByTagName('part-name')?.[0]?.textContent?.trim() || ''
|
|
|
+ );
|
|
|
+ const parts: any = xmlParse.getElementsByTagName('part');
|
|
|
+
|
|
|
+ /** 第一分谱如果是约定的配置分谱则跳过 */
|
|
|
+ if (partListNames[0]?.toLocaleUpperCase?.() === 'COMMON') {
|
|
|
+ partListNames.shift();
|
|
|
+ }
|
|
|
+ // 根据后台已选择的分轨筛选出能切换的声轨
|
|
|
+ const multiTracksSelection: any =
|
|
|
+ data.list[data.listActive]?.multiTracksSelection;
|
|
|
+ const canSelectTracks = multiTracksSelection
|
|
|
+ ? multiTracksSelection?.split(',')
|
|
|
+ : [];
|
|
|
+ const arr = partListNames
|
|
|
+ .map((item: any, index: number) => {
|
|
|
+ // 该声轨能否被选
|
|
|
+ const canselect =
|
|
|
+ canSelectTracks.length == 0 || canSelectTracks.includes(item)
|
|
|
+ ? true
|
|
|
+ : false;
|
|
|
+ // console.log(canselect,index)
|
|
|
+ const instrumentName = getInstrumentName(item);
|
|
|
+ const sortId = sortMusical(instrumentName, index);
|
|
|
+ return {
|
|
|
+ label: item + (instrumentName ? `(${instrumentName})` : ''),
|
|
|
+ value: index,
|
|
|
+ sortId,
|
|
|
+ canselect,
|
|
|
+ track: item
|
|
|
+ };
|
|
|
+ })
|
|
|
+ .filter((item: any) => item.canselect)
|
|
|
+ .sort((a: any, b: any) => a.sortId - b.sortId);
|
|
|
+ data.trackList = arr;
|
|
|
+ let track = arr.find(
|
|
|
+ (item: any) => item.value === data.musicInstrumentIndex
|
|
|
+ )?.track;
|
|
|
+ track = track
|
|
|
+ .replace(/[0-9]+/g, '')
|
|
|
+ .replace(/\s/g, '')
|
|
|
+ .toLocaleLowerCase();
|
|
|
+ let musicRenderType: 'staff' | 'first' | 'fixed' = 'first';
|
|
|
+ let canTrans = true;
|
|
|
+ data.list[data.listActive]?.musicalInstruments.forEach((item: any) => {
|
|
|
+ if (item.code.toLocaleLowerCase() === track) {
|
|
|
+ musicRenderType =
|
|
|
+ item.defaultScore === 'STAVE'
|
|
|
+ ? 'staff'
|
|
|
+ : item.defaultScore === 'JIAN'
|
|
|
+ ? 'fixed'
|
|
|
+ : item.defaultScore === 'FIRST'
|
|
|
+ ? 'first'
|
|
|
+ : 'first';
|
|
|
+ canTrans = item.transferFlag;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ data.showTransBtn = canTrans;
|
|
|
+ data.showMusicImg = musicRenderType;
|
|
|
+ };
|
|
|
+ watch(
|
|
|
+ () => data.listActive,
|
|
|
+ async () => {
|
|
|
+ data.musicInstrumentIndex = 0;
|
|
|
+ analyzeXml();
|
|
|
+ }
|
|
|
+ );
|
|
|
+ watch(
|
|
|
+ () => data.musicInstrumentIndex,
|
|
|
+ async () => {
|
|
|
+ data.trackName = data.trackList.find((item: any) => item.value === data.musicInstrumentIndex)?.label || '切换声轨'
|
|
|
+ musicIframeLoad();
|
|
|
+ }
|
|
|
+ );
|
|
|
return () => (
|
|
|
<div class={styles.container}>
|
|
|
<NSpace align="center" wrapItem={false} size={16}>
|
|
@@ -549,6 +684,7 @@ export default defineComponent({
|
|
|
<div class={styles.musicName}>
|
|
|
{activeItem.value.musicSheetName}
|
|
|
</div>
|
|
|
+
|
|
|
<img
|
|
|
id="music-2"
|
|
|
style={{
|
|
@@ -561,9 +697,20 @@ export default defineComponent({
|
|
|
// const origin = /(localhost|192)/.test(location.host)
|
|
|
// ? 'https://test.lexiaoya.cn'
|
|
|
// : location.origin;
|
|
|
+ // 默认进页面显示对应的曲谱
|
|
|
+ let lineType = 'staff';
|
|
|
+ if (data.showMusicImg === 'first') {
|
|
|
+ lineType = 'firstTone';
|
|
|
+ } else if (data.showMusicImg === 'fixed') {
|
|
|
+ lineType = 'fixedTone';
|
|
|
+ } else if (data.showMusicImg === 'staff') {
|
|
|
+ lineType = 'staff';
|
|
|
+ }
|
|
|
const src = `${vaildMusicScoreUrl()}/instrument?v=${+new Date()}&platform=pc&showGuide=true&id=${
|
|
|
activeItem.value.id
|
|
|
- }&Authorization=${user.getToken}`;
|
|
|
+ }&Authorization=${user.getToken}&musicRenderType=${lineType}&showGuide=true&part-index=${
|
|
|
+ data.musicInstrumentIndex
|
|
|
+ }`;
|
|
|
if (
|
|
|
window.matchMedia('(display-mode: standalone)').matches
|
|
|
) {
|
|
@@ -583,23 +730,35 @@ export default defineComponent({
|
|
|
style={{ display: activeItem.value.id ? '' : 'none' }}>
|
|
|
{isEnsemble.value && (
|
|
|
<NPopselect
|
|
|
- options={musicalInstruments.value}
|
|
|
+ options={data.trackList}
|
|
|
trigger="hover"
|
|
|
v-model:value={data.musicInstrumentIndex}
|
|
|
- onUpdate:value={(val: any) => {
|
|
|
- if (val === data.musicInstrumentIndex) return;
|
|
|
-
|
|
|
- musicIframeLoad();
|
|
|
+ onUpdate:value={async (val: any) => {
|
|
|
+ //
|
|
|
}}
|
|
|
// key={item.id}
|
|
|
class={[styles.popSelect]}>
|
|
|
<NButton round class={[styles.textBtn]}>
|
|
|
- 切换声轨
|
|
|
+ {data.trackName}
|
|
|
<i class={styles.iconArrow}></i>
|
|
|
</NButton>
|
|
|
</NPopselect>
|
|
|
)}
|
|
|
-
|
|
|
+ {/* 转谱按钮 */}
|
|
|
+ { data.showTransBtn &&
|
|
|
+ <NPopselect
|
|
|
+ options={_actions}
|
|
|
+ trigger="hover"
|
|
|
+ v-model:value={data.showMusicImg}
|
|
|
+ onUpdate:value={async (val: any) => {
|
|
|
+ data.showMusicImg = val;
|
|
|
+ musicIframeLoad();
|
|
|
+ }}
|
|
|
+ // key={item.id}
|
|
|
+ class={[styles.popTrans]}>
|
|
|
+ <img class={[styles.transBtn]} src={icon_trans} />
|
|
|
+ </NPopselect>
|
|
|
+ }
|
|
|
<div class={styles.favitor} onClick={() => handleFavitor()}>
|
|
|
<Transition name="favitor" mode="out-in">
|
|
|
{activeItem.value.favitor ? (
|