import OHeader from '@/components/o-header' import OSticky from '@/components/o-sticky' import { defineComponent, nextTick, onMounted, onUnmounted, reactive, ref, watch } from 'vue' import styles from './music-detail.module.less' import { Button, Image, Picker, Popup, Skeleton } from 'vant' import iconBg from './images/music-img-default.png' import iconDownload from './images/icon-download.png' import iconChange from './images/icon-change.png' import iconMusic from './images/icon-music.png' import { postMessage } from '@/helpers/native-message' import request from '@/helpers/request' import { state } from '@/state' import { useRoute } from 'vue-router' import Plyr from 'plyr' import 'plyr/dist/plyr.css' import deepClone from '@/helpers/deep-clone' import StaffChange from './staff-change' import Download from './download' import { svgtopng } from './formatSvgToImg' import requestOrigin from 'umi-request' import { getInstrumentName } from '@/constant/instruments' import { formatXML, getCustomInfo, onlyVisible } from './instrument' export default defineComponent({ name: 'music-detail', setup() { const route = useRoute() const audioRef = ref() const player = ref(null) const partColumns = ref([]) const staffData = reactive({ details: {} as any, status: false, open: false, audioReady: false, iframeSrc: '', isComberRender: false, // 是否为 musicXml: [] as any, instrumentName: '', iframeRef: null as any, imgs: [] as any, radio: 'staff' as any, partList: [] as any[], partNames: [] as any[], selectedPartName: '' as any, selectedPartIndex: 0, partXmlIndex: 0 }) const loading = ref(false) const downloadStatus = ref(false) const showImg = ref([] as any) watch( () => staffData.radio, (val: string) => { if (val == 'first') { showImg.value = deepClone(staffData.details.musicFirstSvg?.split(',') || []) } else if (val == 'fixed') { showImg.value = deepClone(staffData.details.musicJianSvg?.split(',') || []) } else { showImg.value = deepClone(staffData.details.musicImg?.split(',') || []) } } ) const musicIframeLoad = async () => { const iframeRef: any = document.getElementById('staffIframeRef') if (iframeRef && iframeRef.contentWindow.renderXml) { const res = await requestOrigin.get(staffData.details.xmlFileUrl, { mode: 'cors' }) const parseXmlInfo = getCustomInfo(res) const xml = formatXML(parseXmlInfo.parsedXML) if (staffData.isComberRender) { iframeRef.contentWindow.renderXml(xml, staffData.partXmlIndex, staffData.isComberRender) } else { const currentXml = onlyVisible(xml, staffData.partXmlIndex) iframeRef.contentWindow.renderXml( currentXml, staffData.partXmlIndex, staffData.isComberRender ) } // iframeRef.contentWindow.renderXml(staffData.details.xmlFileUrl, staffData.partXmlIndex) } } const resetRender = async () => { const iframeRef: any = document.getElementById('staffIframeRef') if (iframeRef && iframeRef.contentWindow.renderXml) { loading.value = true // iframeRef.contentWindow.resetRender(staffData.partXmlIndex) // const res = await requestOrigin.get(staffData.details.xmlFileUrl, { mode: 'cors' }) // const parseXmlInfo = getCustomInfo(res) // const xml = formatXML(parseXmlInfo.parsedXML) // const currentXml = onlyVisible(xml, staffData.selectedPartIndex) // iframeRef.contentWindow.renderXml(currentXml, staffData.selectedPartIndex) const res = await requestOrigin.get(staffData.details.xmlFileUrl, { mode: 'cors' }) const parseXmlInfo = getCustomInfo(res) const xml = formatXML(parseXmlInfo.parsedXML) if (staffData.isComberRender) { iframeRef.contentWindow.renderXml(xml, staffData.partXmlIndex, staffData.isComberRender) } else { const currentXml = onlyVisible(xml, staffData.partXmlIndex) iframeRef.contentWindow.renderXml(currentXml, 0, staffData.isComberRender) } } } const resetRenderPage = (type: string, xmlUrl: string) => { const iframeRef: any = document.getElementById('staffIframeRef') if (iframeRef && iframeRef.contentWindow.renderXml) { iframeRef.contentWindow.resetRenderPage(type, xmlUrl) } } const renderStaff = async () => { try { // staffData.iframeSrc = `https://mantest.dayaedu.com/accompany/osmd/index.html` staffData.iframeSrc = `${location.origin}${location.pathname}osmd/index.html` } catch (error) { // } } const getPartNames = async (xmlUrl: string) => { const partNames: string[] = [] try { const res = await requestOrigin.get(xmlUrl, { mode: 'cors' }) const xml: any = new DOMParser().parseFromString(res, 'text/xml') for (const item of xml.getElementsByTagName('part-name')) { if (item.textContent) { partNames.push(item.textContent) } } } catch (error) { // } return partNames.filter((text: string) => text.toLocaleUpperCase() !== 'COMMON') || [] } const toDetail = async (row: any) => { if (row.musicSheetType === 'SINGLE') { loading.value = false return } staffData.partNames = await getPartNames(row.xmlFileUrl) let partList = row.background || [] partList = partList.filter( (item: any) => !item.track?.toLocaleUpperCase()?.includes('COMMON') ) partColumns.value = partList.map((item: any, index: number) => { const instrumentName = getInstrumentName(item.track) const xmlIndex = staffData.partNames.findIndex((name: any) => name === item.track) return { text: item.track + (instrumentName ? `(${instrumentName})` : ''), instrumentName: instrumentName, xmlIndex, value: index } }) // 初始化数据 const defaultShowStaff = partColumns.value[staffData.selectedPartIndex] staffData.selectedPartName = defaultShowStaff.instrumentName staffData.partXmlIndex = defaultShowStaff.xmlIndex } const getMusicDetail = async () => { loading.value = true try { if (!route.query.id) return const { data } = await request.get( state.platformApi + '/musicSheet/detail/' + route.query.id ) staffData.details = data || {} showImg.value = staffData.details.musicImg?.split(',') || [] staffData.isComberRender = data.musicSubject === '1' nextTick(async () => { if (data.audioFileUrl) { initAudio() } else { await toDetail(staffData.details) renderStaff() } }) } catch (e) { // console.log(e) } } const initAudio = async () => { const controls = [ // 'play-large', 'play', 'progress', 'captions', // 'fullscreen', 'current-time', 'duration' ] player.value = new Plyr(audioRef.value, { controls: controls }) player.value.on('ready', () => { staffData.audioReady = true player.value.muted = false nextTick(async () => { // if (staffData.details.musicSheetType === 'SINGLE') { // loading.value = false // return // } await toDetail(staffData.details) renderStaff() }) }) } //进入云练习 const openView = async (item: any) => { const src = `${location.origin}/orchestra-music-score/?id=${item.id}&part-index=${staffData.selectedPartIndex}` console.log('🚀 ~ src:', src) postMessage({ api: 'openAccompanyWebView', content: { url: src, orientation: 0, isHideTitle: true, statusBarTextColor: false, isOpenLight: true } }) } const onSubmit = () => { player.value?.pause() openView(staffData.details) } const showLoading = async (e: any) => { if (e.data?.api === 'musicStaffRender') { try { const osmdImg = e.data.osmdImg const imgs: any = [] for (let i = 0; i < osmdImg.length; i++) { const img: any = await svgtopng(osmdImg[i].img, osmdImg[i].width, osmdImg[i].height) imgs.push(img) } showImg.value = imgs } catch (e) { // } loading.value = e.data.loading } } onMounted(async () => { await getMusicDetail() window.addEventListener('message', showLoading) }) onUnmounted(() => { window.removeEventListener('message', showLoading) }) return () => (

{staffData.details.musicSheetName} {staffData.details.musicSheetType === 'CONCERT' && staffData.selectedPartName ? `(${staffData.selectedPartName})` : ''}

{staffData.details.composer}

{/* {staffData.details?.musicSheetType === 'CONCERT' ? ( <> */} {loading.value && ( <> )} {/* */} {/* // ) : ( // <> // {showImg.value.length > 0 && ( // <> // // // )} // // )} */}
{staffData.details.id && (
{staffData.details?.audioFileUrl && (
)}
{ if (loading.value) return downloadStatus.value = true }} > 下载
{staffData.details?.musicSheetType === 'CONCERT' ? (
{ if (loading.value) return staffData.open = true }} > 声轨
) : (
{ if (loading.value) return staffData.status = true }} > 转谱
)}
)} (staffData.status = false)} onChange={(type: string) => { // 更改预览状态 staffData.radio = type staffData.status = false if (type == 'first') { loading.value = true resetRenderPage('first', staffData.details.xmlFileUrl) } else if (type == 'fixed') { loading.value = true resetRenderPage('fixed', staffData.details.xmlFileUrl) } else { loading.value = true resetRenderPage('staff', staffData.details.xmlFileUrl) } }} /> {downloadStatus.value && ( )} { staffData.open = false staffData.selectedPartIndex = value.selectedValues[0] staffData.selectedPartName = value.selectedOptions[0].instrumentName staffData.partXmlIndex = value.selectedOptions[0].xmlIndex // openView({ id: staffData.instrumentName }) nextTick(() => { resetRender() }) }} onCancel={() => (staffData.open = false)} />
) } })