| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720 |
- import {
- computed,
- defineComponent,
- onMounted,
- reactive,
- ref,
- toRef,
- TransitionGroup,
- watch
- } from 'vue';
- import styles from './index.module.less';
- import iconChange from '../images/icon-change.png';
- import iconDownload from '../images/icon-download.png';
- import iconStaff from '../images/icon-staff.png';
- import staff from '../images/staff/staff.png'
- import staffActive from '../images/staff/staff-active.png'
- import first from '../images/staff/first.png'
- import firstActive from '../images/staff/first-active.png'
- import fixed from '../images/staff/fixed.png'
- import fixedActive from '../images/staff/fixed-active.png'
- import { Button, NoticeBar, Popover, showLoadingToast, showToast } from 'vant';
- import { state } from '@/state';
- import {
- getInstrumentName,
- sortMusical,
- vaildMusicScoreUrl
- } from '@/helpers/utils';
- import { storage } from '@/helpers/storage';
- import { ACCESS_TOKEN } from '@/store/mutation-types';
- import { promisefiyPostMessage } from '@/helpers/native-message';
- import html2canvas from 'html2canvas';
- import { addWatermark, convasToImg } from '@/views/co-ai/imageFunction';
- export default defineComponent({
- name: 'music-detail',
- props: {
- item: {
- type: Object,
- default: () => ({})
- }
- },
- emits: ['handleGoto'],
- setup(props, { emit }) {
- const item = toRef(props.item);
- const data = reactive({
- musicPdfUrl: '',
- iframeSrc: '',
- selectMusicInstrumentIndex: 0,
- popoverShow: false,
- showChangeVoice: false,
- /** 显示哪种曲谱 */
- showMusicImg: 'staff' as 'staff' | 'first' | 'fixed',
- trackList: [] as any, // 可筛选的分轨信息
- showTransBtn: true // 是否显示转谱按钮
- });
- const downRef = ref();
- watch(
- () => props.item,
- () => {
- item.value = props.item;
- data.musicPdfUrl = ''
- data.iframeSrc = ''
- console.log(props.item, 'item')
- __init();
- }
- );
- const _actions = computed(() => {
- const details = item.value;
- let { scoreType, isConvertibleScore } = details || {};
- let action: any[] = [
- {
- value: 'first',
- text: '首调',
- icon: first
- },
- {
- value: 'fixed',
- text: '固定调',
- icon: fixed
- }
- ];
- if (
- !(
- ['JIAN', 'FIRST'].includes(scoreType) && isConvertibleScore === false
- ) &&
- !(isConvertibleScore === undefined || isConvertibleScore === null)
- ) {
- action.unshift({
- value: 'staff',
- text: '五线谱',
- icon: staff
- });
- }
- action.forEach((item: any) => {
- if(item.value === data.showMusicImg) {
- if(item.value === 'first') {
- item.icon = firstActive
- } else if(item.value == 'fixed') {
- item.icon = fixedActive
- } else if(item.value === 'staff') {
- item.icon = staffActive
- }
- }
- })
- return action.map((item, index) => {
- return {
- ...item,
- color:
- data.showMusicImg === item.value ? 'var(--van-primary-color)' : '',
- className: data.showMusicImg === item.value ? 'fontBlod' : ''
- };
- });
- });
- const trackList = computed(() => {
- return data.trackList.map((item: any) => {
- return {
- ...item,
- color:
- data.selectMusicInstrumentIndex === item.value ? 'var(--van-primary-color)' : '',
- className: data.selectMusicInstrumentIndex === item.value ? 'fontBlod' : ''
- };
- });
- })
- /** 保存图片 */
- const handleSave = async () => {
- if (data.musicPdfUrl) {
- const songName = item.value?.musicSheetName;
- promisefiyPostMessage({
- api: 'downloadFile',
- content: {
- downloadUrl: data.musicPdfUrl,
- fileName: songName
- }
- });
- return;
- }
- showLoadingToast({ message: '正在保存', duration: 0 });
- try {
- html2canvas(downRef.value, {
- backgroundColor: '#fff',
- allowTaint: true,
- useCORS: true
- })
- .then(async canvas => {
- // 添加水印
- const waterCanvasImg = await addWatermark(canvas);
- // canvas转图片
- const dataURL = await convasToImg(waterCanvasImg);
- console.log(dataURL, 'dataURL');
- setTimeout(() => {
- showToast('已保存到相册');
- }, 500);
- await promisefiyPostMessage({
- api: 'savePicture',
- content: {
- base64: dataURL
- }
- });
- })
- .catch(() => {
- setTimeout(() => {
- showToast('保存失败');
- }, 500);
- });
- } catch (error) {
- setTimeout(() => {
- showToast('保存失败');
- }, 500);
- }
- };
- // 根据musicSheetType返回的值,判断是否显示切换声轨按钮
- const isEnsemble = computed(() => {
- if (item.value) {
- const musicSheetType = item.value?.musicSheetType;
- if (musicSheetType === 'SINGLE') {
- return false;
- } else {
- return true;
- }
- } else {
- return false;
- }
- });
- // 判断 值当前有没有图片
- const isMusicImg = computed(() => {
- const musicsData = item.value;
- if (data.showMusicImg === 'first' && musicsData?.musicFirstImg) {
- return true;
- }
- if (data.showMusicImg === 'fixed' && musicsData?.musicJianImg) {
- return true;
- }
- if (musicsData?.musicImg) {
- return true;
- }
- return false;
- });
- // 判断是否可转谱 - 为空也可以转谱
- const checkConverTible = (isConvertibleScore: any, scoreType: string) => {
- if (
- isConvertibleScore ||
- isConvertibleScore === '' ||
- isConvertibleScore === undefined ||
- isConvertibleScore === null ||
- (['JIAN', 'FIRST'].includes(scoreType) && !isConvertibleScore)
- ) {
- return true;
- } else {
- return false;
- }
- };
- // 解析xml,获取分轨信息
- const analyzeXml = async () => {
- const details = item.value;
- // console.log(details?.musicSheetType, 'details?.musicSheetType');
- if (details?.musicSheetType === 'CONCERT') {
- if (details.xmlFileUrl) {
- const res = await fetch(details.xmlFileUrl).then(response =>
- response.text()
- );
- filterTracks(res);
- }
- } else {
- // showMusicImg: 'first' as 'staff' | 'first' | 'fixed',
- const { scoreType, isConvertibleScore } = details || {};
- let musicImgType: 'staff' | 'first' | 'fixed' = 'first';
- musicImgType =
- scoreType === 'STAVE'
- ? 'staff'
- : scoreType === 'JIAN'
- ? 'fixed'
- : scoreType === 'FIRST'
- ? 'first'
- : 'first';
- data.showMusicImg = musicImgType;
- data.showTransBtn = checkConverTible(isConvertibleScore, scoreType);
- }
- };
- /** 获取分轨名称 */
- const getInstrumentNameCode = (instruments: any, name = '') => {
- name = name.toLocaleLowerCase().replace(/ /g, '').replace(/\d*/gi, '');
- if (!name) return '';
- for (let key of instruments) {
- const _key = key.toLocaleLowerCase().replace(/ /g, '');
- // if (_key.includes(name)) {
- // return key
- // }
- if (_key === name) {
- return _key;
- }
- }
- // for (let key of instruments) {
- // const _key = key.toLocaleLowerCase().replace(/ /g, '')
- // if (name.includes(_key)) {
- // return key
- // }
- // }
- return '';
- };
- // 通过乐器编码返回乐器编号
- const instrumentCodeToInstrumentId = (
- subjectList: Array<any>,
- code: string
- ) => {
- const codeIdMap = new Map<string, []>() as any;
- const codeMapKeys: string[] = [];
- subjectList.forEach((data: any) => {
- if (data.enableFlag) {
- const codes = data.code?.split(/[,,]/);
- codes.forEach((code: string) => {
- let codeTemp = code?.replace(/ /g, '').toLowerCase();
- codeMapKeys.push(codeTemp);
- if (codeIdMap.has(codeTemp)) {
- codeIdMap.get(codeTemp).push(data.id + '');
- } else {
- const arr = [] as any;
- arr.push(data.id + '');
- codeIdMap.set(codeTemp, arr);
- }
- });
- }
- });
- if (!code) {
- return '';
- }
- code = code && code?.replace(/ /g, '').toLowerCase();
- const tempCode = getInstrumentNameCode(codeMapKeys, code);
- if (codeIdMap.has(tempCode)) {
- const result = codeIdMap.get(tempCode);
- // console.log('result:', result);
- return result[0] || '';
- }
- return '';
- };
- // 初始化编号
- const initUserDefaultInstrument = () => {
- const userInstrumentId = state.user.data.instrumentId;
- const item = data.trackList.find(
- (track: any) => track.instrumentId === userInstrumentId + ''
- );
- data.selectMusicInstrumentIndex = item ? item.value : 0;
- };
- // 过滤出能切换的分轨
- const filterTracks = (xml: any) => {
- const xmlParse = new DOMParser().parseFromString(xml, 'text/xml');
- const partList: any =
- xmlParse
- .getElementsByTagName('part-list')?.[0]
- ?.getElementsByTagName('score-part') || [];
- const partListNames = Array.from(partList).map(
- (item: any) =>
- item.getElementsByTagName('part-name')?.[0]?.textContent?.trim() ||
- item.getAttribute('id') ||
- ''
- );
- const parts: any = xmlParse.getElementsByTagName('part');
- /** 第一分谱如果是约定的配置分谱则跳过 */
- if (partListNames[0]?.toLocaleUpperCase?.() === 'COMMON') {
- partListNames.shift();
- }
- // 根据后台已选择的分轨筛选出能切换的声轨
- const multiTracksSelection = item.value?.multiTracksSelection;
- const canSelectTracks = multiTracksSelection
- ? multiTracksSelection?.split(',')
- : [];
- const musicalInstruments = item.value?.musicalInstruments || [];
- const arr = partListNames
- .map((item: any, index: number) => {
- // 该声轨能否被选
- const canselect =
- canSelectTracks.length == 0 || canSelectTracks.includes(item)
- ? true
- : false;
- const instrumentName = getInstrumentName(item);
- const instrumentId = instrumentCodeToInstrumentId(
- musicalInstruments,
- item
- );
- const sortId = sortMusical(instrumentName, index);
- return {
- text: item + (instrumentName ? `(${instrumentName})` : ''),
- value: index,
- instrumentId,
- sortId,
- canselect,
- track: item
- };
- })
- .filter((item: any) => item.canselect);
- //.sort((a: any, b: any) => a.sortId - b.sortId);
- data.trackList = arr;
- // 是否显示总谱
- const selectMusic = item.value;
- if (selectMusic) {
- const musicalInstruments = selectMusic.musicalInstruments || [];
- if (selectMusic.isScoreRender) {
- data.trackList.unshift({
- text: '总谱',
- value: 999,
- sortId: 0,
- canselect: true,
- track: 999
- });
- if (selectMusic.defaultScoreRender) {
- data.selectMusicInstrumentIndex = 999;
- } else {
- initUserDefaultInstrument();
- }
- } else {
- initUserDefaultInstrument();
- }
- }
- const details = item.value;
- const { scoreType, isConvertibleScore } = details || {};
- let musicImgType: 'staff' | 'first' | 'fixed' = 'first';
- musicImgType =
- scoreType === 'STAVE'
- ? 'staff'
- : scoreType === 'JIAN'
- ? 'fixed'
- : scoreType === 'FIRST'
- ? 'first'
- : 'first';
- data.showMusicImg = musicImgType;
- data.showTransBtn = checkConverTible(isConvertibleScore, scoreType);
- };
- const musicIframeLoad = () => {
- const token = storage.get(ACCESS_TOKEN);
- const details = item.value;
- if (!details?.id) {
- data.iframeSrc = '';
- return;
- }
- // 如果在配置里面匹配不到,则默认显示五线谱
- const musicRenderType =
- data.showMusicImg === 'first'
- ? 'firstTone'
- : data.showMusicImg === 'fixed'
- ? 'fixedTone'
- : data.showMusicImg === 'staff'
- ? 'staff'
- : 'staff';
- // pdf
- const musicSheetType = details?.musicSheetType;
- let musicPdfUrl = '';
- if (
- musicSheetType === 'SINGLE' ||
- data.selectMusicInstrumentIndex === 999
- ) {
- if (data.showMusicImg === 'first') {
- musicPdfUrl = details.firstPdfUrl;
- } else if (data.showMusicImg === 'fixed') {
- musicPdfUrl = details.jianPdfUrl;
- } else {
- musicPdfUrl = details.musicPdfUrl;
- }
- } else {
- const trackList = data.trackList || [];
- const selectTrack = trackList.find(
- (item: any) => item.value === data.selectMusicInstrumentIndex
- );
- const background = details.background || [];
- const selectItem = background.find(
- (item: any) =>
- item.track === selectTrack?.track && item.audioPlayType === 'PLAY'
- );
- if (selectItem) {
- if (data.showMusicImg === 'first') {
- musicPdfUrl = selectItem.firstPdfUrl;
- } else if (data.showMusicImg === 'fixed') {
- musicPdfUrl = selectItem.jianPdfUrl;
- } else {
- musicPdfUrl = selectItem.musicPdfUrl;
- }
- }
- }
- data.musicPdfUrl = musicPdfUrl;
- if (musicPdfUrl) {
- // data.iframeSrc = `/pdf/web/viewer.html?file=${encodeURIComponent(data.musicPdfUrl)}&t=${Date.now()}`;
- data.iframeSrc = `${location.origin}${
- location.pathname
- }pdf/web/viewer.html?file=${encodeURIComponent(
- data.musicPdfUrl
- )}&t=${Date.now()}`;
- } else {
- // const origin = /(localhost|192)/.test(location.host)
- // ? 'https://test.lexiaoya.cn'
- // : location.origin;
- // data.iframeSrc = `${origin}/instrument/?id=${details.id}&modelType=practise&modeType=json&Authorization=${token}&isPreView=true&part-index=${data.selectMusicInstrumentIndex}&musicRenderType=${musicRenderType}`;
- data.iframeSrc = `${vaildMusicScoreUrl()}/instrument/?id=${
- details?.id
- }&modelType=practise&modeType=json&Authorization=${token}&isPreView=true&part-index=${
- data.selectMusicInstrumentIndex
- }&musicRenderType=${musicRenderType}&zoom=0.6`;
- }
- // console.log('地址', data.iframeSrc, isEnsemble.value , data.musicPdfUrl , !isMusicImg.value);
- };
- const __init = async () => {
- await analyzeXml();
- musicIframeLoad();
- };
- /** 去云练习 */
- const handleGoto = () => {
- emit('handleGoto', item.value, data.showMusicImg, data.selectMusicInstrumentIndex)
- };
- onMounted(() => {
- __init();
- });
- return () => (
- <div class={styles.musicDetail}>
- <div class={styles.musicContainer}>
- <div class={styles.container}>
- <div
- class={styles['right-musicName']}
- style={{
- opacity: !data.musicPdfUrl ? '1' : '0',
- height: !data.musicPdfUrl ? 'auto' : '0'
- }}>
- <NoticeBar
- text={item.value?.musicSheetName}
- class={styles.noticeBar}
- background="none"
- />
- </div>
- {data.iframeSrc &&
- (isEnsemble.value || data.musicPdfUrl || !isMusicImg.value) ? (
- <div class={styles.iframeSection}>
- <>
- {item.value?.id ? (
- data.musicPdfUrl ? (
- <iframe
- id="staffIframeRef"
- style={{
- width: '100%',
- paddingTop: '4px'
- // opacity: loading.value ? 0 : 1
- }}
- src={data.iframeSrc}></iframe>
- ) : (
- <iframe
- id="staffIframeRef"
- style={{
- width: '100%'
- // opacity: loading.value ? 0 : 1
- }}
- src={data.iframeSrc}></iframe>
- )
- ) : (
- ''
- )}
- </>
- </div>
- ) : (
- <div class={styles.imgSection}>
- {data.showMusicImg === 'first' ? (
- <>
- {item.value?.musicFirstImg
- ?.split(',')
- .map((item: any, index: number) => {
- return (
- <img
- class={styles.staff}
- src={item}
- key={item}
- crossorigin="anonymous"
- />
- );
- })}
- </>
- ) : data.showMusicImg === 'fixed' ? (
- <>
- <TransitionGroup name="van-fade">
- {item.value?.musicJianImg
- ?.split(',')
- .map((item: any, index: number) => {
- return (
- <img
- class={styles.staff}
- src={item}
- key={item}
- crossorigin="anonymous"
- />
- );
- })}
- </TransitionGroup>
- </>
- ) : (
- <>
- {item.value?.musicImg
- ?.split(',')
- .map((item: any, index: number) => {
- return (
- <img
- class={styles.staff}
- src={item + '?v=' + Date.now()}
- key={item}
- crossorigin="anonymous"
- />
- );
- })}
- </>
- )}
- </div>
- )}
- </div>
- <div class={styles.container} ref={downRef} style={{
- display: 'block',
- height: 'auto',
- }}>
- <div
- class={styles['right-musicName']}
- style={{
- opacity: !data.musicPdfUrl ? '1' : '0',
- height: !data.musicPdfUrl ? 'auto' : '0'
- }}>
- <div class={styles.name}>{item.value?.musicSheetName}</div>
- </div>
- <div>
- {data.showMusicImg === 'first' ? (
- <>
- {item.value?.musicFirstImg
- ?.split(',')
- .map((item: any, index: number) => {
- return (
- <img
- class={styles.staff}
- src={item}
- key={item}
- crossorigin="anonymous"
- />
- );
- })}
- </>
- ) : data.showMusicImg === 'fixed' ? (
- <>
- <TransitionGroup name="van-fade">
- {item.value?.musicJianImg
- ?.split(',')
- .map((item: any, index: number) => {
- return (
- <img
- class={styles.staff}
- src={item}
- key={item}
- crossorigin="anonymous"
- />
- );
- })}
- </TransitionGroup>
- </>
- ) : (
- <>
- {item.value?.musicImg
- ?.split(',')
- .map((item: any, index: number) => {
- return (
- <img
- class={styles.staff}
- src={item + '?v=' + Date.now()}
- key={item}
- crossorigin="anonymous"
- />
- );
- })}
- </>
- )}
- </div>
- </div>
- </div>
- <div class={styles.btnGroup}>
- <div class={styles.operation}>
- {isEnsemble.value && (
- <Popover
- v-model:show={data.showChangeVoice}
- class={'transferStaff transferStaffSection'}
- actions={trackList.value}
- placement="top-start"
- onSelect={(item: any) => {
- // console.log(item, 'item')
- data.selectMusicInstrumentIndex = item.value
- data.showChangeVoice = false;
- musicIframeLoad();
- }}>
- {{
- reference: () => (
- <div class={[styles.item, styles.itemPopover]}>
- <img src={iconChange} class={styles.icon} />
- <span>声部</span>
- </div>
- )
- }}
- </Popover>
- )}
- {data.showTransBtn && (
- <Popover
- v-model:show={data.popoverShow}
- class={'transferStaff'}
- actions={_actions.value}
- placement="top-start"
- onSelect={(item: any) => {
- data.showMusicImg = item.value;
- data.popoverShow = false;
- musicIframeLoad();
- }}>
- {{
- reference: () => (
- <div class={[styles.item, styles.itemPopover]}>
- <img src={iconStaff} class={styles.icon} />
- <span>转谱</span>
- </div>
- )
- }}
- </Popover>
- )}
- {!isEnsemble.value && (isMusicImg.value || data.musicPdfUrl) && (
- <div class={styles.item} onClick={handleSave}>
- <img src={iconDownload} class={styles.icon} />
- <span>下载</span>
- </div>
- )}
- </div>
- <Button round class={styles.goBtn} onClick={handleGoto}>
- 立即练习
- </Button>
- </div>
- </div>
- );
- }
- });
|