import { TransitionGroup, computed, defineComponent, nextTick, onMounted, reactive, ref, watch } from 'vue'; import styles from './index.module.less'; import MSearch from '@/components/m-search'; // import icon_play from '@/common/images/icon_play.svg'; import { Empty, Icon, List, Loading, NoticeBar, Popover, Popup, showLoadingToast, showToast } from 'vant'; import icon_back from './image/icon_back.svg'; import icon_down from '@/common/images/icon_down.svg'; // import icon_jianpu from '@/common/images/icon_jianpu.svg'; import icon_jianpuActive from '@/common/images/icon_jianpuActive.svg'; import icons from '@/common/images/index.json'; import { listenerMessage, postMessage, promisefiyPostMessage } from '@/helpers/native-message'; import html2canvas from 'html2canvas'; import { api_musicSheetCategoriesPage, api_musicSheetPage, api_subjectList } from './api'; import { state } from '@/state'; import MEmpty from '@/components/m-empty'; import Coaiguide from '@/custom-plugins/guide-page/coai-guide'; import TheVip from '@/components/the-vip'; import request from '@/helpers/request'; import { useRoute } from 'vue-router'; import { addWatermark, convasToImg, imgToCanvas } from './imageFunction'; import ChangeVoice from './change-voice'; import { storage } from '@/helpers/storage'; import { ACCESS_TOKEN } from '@/store/mutation-types'; import { sortMusical, getInstrumentName, vaildMusicScoreUrl } from '@/helpers/utils'; export default defineComponent({ name: 'co-ai', setup() { const route = useRoute(); const categorForms = reactive({ page: 1, rows: 999, subjectId: state.user.data?.subjectId || '', musicTagIds: route.query.musicTagId ? [route.query.musicTagId] : [] }); const musicForms = reactive({ page: 1, rows: 20, status: 1, keyword: '', // 关键词 musicSheetCategoriesId: route.query.id as any, musicalInstrumentId: '' }); const data = reactive({ musicSheetCategoriesName: route.query.name as any, /** 教材Index */ typeIndex: 0, /** 音乐Index */ musicIndex: 0, /** 显示哪种曲谱 */ showMusicImg: 'staff' as 'staff' | 'first' | 'fixed', popoverShow: false, popoverMusicShow: false, /** 教材列表 */ types: [] as any[], /** 音乐列表 */ musics: [] as any[], loading: true, finshed: false, showChangeVoice: false, selectMusicInstrumentIndex: 0, iframeSrc: '', searchNoticeShow: false, searchNotice: { left: '', top: '', width: '', height: '' }, showVip: false, vipMember: state.user.data?.vipMember, subjectStatus: false, subjectList: [], subjectItem: {} as any, // 当前乐器, trackList: [] as any, // 可筛选的分轨信息 showTransBtn: true // 是否显示转谱按钮 }); const downRef = ref(); const showGuide = ref(false); const _actions = computed(() => { return [ { value: 'staff', text: '五线谱' }, { value: 'first', text: '首调' }, { value: 'fixed', text: '固定调' } ].map((item, index) => { return { ...item, color: data.showMusicImg === item.value ? 'var(--van-primary-color)' : '', className: data.showMusicImg === item.value ? 'fontBlod' : '' }; }); }); const _types = computed(() => { return data.types.map((item: any) => { return { ...item, color: musicForms.musicSheetCategoriesId == item.value ? 'var(--van-primary-color)' : '', className: musicForms.musicSheetCategoriesId == item.value ? 'fontBlod' : '' }; }); }); // 返回 const goback = () => { postMessage({ api: 'goBack' }); }; /** 去云教练 */ const handleGoto = () => { if (!data.vipMember) { data.showVip = true; return; } // 默认进页面显示对应的曲谱 let lineType = 'staff'; if (data.showMusicImg === 'first') { lineType = 'firstTone'; } else if (data.showMusicImg === 'fixed') { lineType = 'fixedTone'; } else if (data.showMusicImg === 'staff') { lineType = 'staff'; } let src = `${vaildMusicScoreUrl()}/instrument?id=${ data.musics[data.musicIndex]?.id }&musicRenderType=${lineType}&showGuide=true&part-index=${ data.selectMusicInstrumentIndex }`; postMessage({ api: 'openAccompanyWebView', content: { url: src, orientation: 0, isHideTitle: true, statusBarTextColor: false, isOpenLight: true, c_orientation: 0 // 0 横屏 1 竖屏 } }); }; /** 保存图片 */ const handleSave = async () => { 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); } }; /** 获取音乐教材列表 */ const getMusicSheetCategories = async () => { try { const res = await api_musicSheetCategoriesPage({ ...categorForms }); if (res.code === 200 && Array.isArray(res?.data?.rows)) { const temp: any = []; res.data.rows.forEach((item: any) => { temp.push({ value: item.id, text: item.name }); }); data.types = temp; } } catch (error) { console.log('🚀 ~ error:', error); } }; /** 获取曲谱列表 */ const getMusicList = async () => { data.loading = true; try { const res = await api_musicSheetPage({ ...musicForms, musicalInstrumentId: data.subjectItem.value || null }); if (res.code === 200) { if (Array.isArray(res?.data?.rows)) { data.musics = [...data.musics, ...res.data.rows]; data.finshed = !res.data.next; } else { data.finshed = true; } } else showGuide.value = true; } catch (error) { console.log('🚀 ~ error:', error); } data.loading = false; }; const handleReset = () => { musicForms.page = 1; data.musics = []; getMusicList(); }; const spinRef = ref(); const handleResh = () => { if (data.loading || data.finshed) return; musicForms.page = musicForms.page + 1; getMusicList(); }; const musicIframeLoad = () => { const token = storage.get(ACCESS_TOKEN); const details = data.musics[data.musicIndex]; // 如果在配置里面匹配不到,则默认显示五线谱 const musicRenderType = data.showMusicImg === 'first' ? 'firstTone' : data.showMusicImg === 'fixed' ? 'fixedTone' : data.showMusicImg === 'staff' ? 'staff' : 'staff'; 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}`; }; const setSearchBox = () => { const el = document.querySelector('.searchNotice .van-field__control'); if (el) { const rect = el.getBoundingClientRect(); data.searchNotice.left = rect.x + 'px'; data.searchNotice.top = rect.y + 'px'; data.searchNotice.width = rect.width + 'px'; data.searchNotice.height = rect.height + 'px'; } }; const isEnsemble = computed(() => { const musics = data.musics[data.musicIndex]?.musicalInstruments; if (musics && musics.length) { let list: any = []; const arr = musics.forEach((item: any) => { list.push({ name: item.name, code: item.code }); }); } if (musics && musics.length > 1) { return true; } else { return false; } }); const getSubjecList = async () => { try { let subjectIds = state.user.data?.subjectId || ''; subjectIds = subjectIds.split(','); const subjectId = subjectIds[0] || ''; const res = await api_subjectList({ enableFlag: true, delFlag: 0, page: 1, subjectId: subjectId || '', rows: 999 }); if (subjectId) { const result = res.data || []; let tempSubjects: any = []; result.forEach((item: any) => { const instruments = item.instruments || []; if (Number(subjectId) === item.id && instruments.length > 0) { instruments.forEach((child: any, index: number) => { tempSubjects.push({ text: child.name, value: child.id, className: index === 0 ? 'selected' : '' }); }); } }); data.subjectList = tempSubjects; if (tempSubjects.length > 0) { data.subjectItem = tempSubjects[0]; } } } catch { // } }; // 解析xml,获取分轨信息 const analyzeXml = async () => { const details = data.musics[data.musicIndex]; 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 = data.musics[data.musicIndex]?.multiTracksSelection; const canSelectTracks = multiTracksSelection ? multiTracksSelection?.split(',') : []; console.log(canSelectTracks, partListNames); 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 { text: 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.selectMusicInstrumentIndex )?.track; track = track .replace(/[0-9]+/g, '') .replace(/\s/g, '') .toLocaleLowerCase(); // 如果在配置里面匹配不到,则默认显示五线谱 let musicRenderType: 'staff' | 'first' | 'fixed' = 'staff'; let canTrans = true; data.musics[data.musicIndex]?.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.musicIndex, async () => { data.selectMusicInstrumentIndex = 0; analyzeXml(); } ); onMounted(async () => { // 安卓的状态栏 postMessage({ api: 'setStatusBarVisibility', content: { isVisibility: 0 } }); await getSubjecList(); await getMusicSheetCategories(); await getMusicList(); const obv = new IntersectionObserver(entries => { if (entries[0].intersectionRatio > 0) { handleResh(); } }); nextTick(() => { spinRef.value && obv.observe(spinRef.value); }); const getUserInfo = async () => { const res = await request.get('/edu-app/user/getUserInfo', { initRequest: true, // 初始化接口 requestType: 'form', hideLoading: true }); if (res?.code === 200) { data.vipMember = res.data.vipMember; } }; analyzeXml(); listenerMessage('webViewOnResume', () => { console.log('页面显示'); getUserInfo(); data.typeIndex = 0; data.musicIndex = 0; handleReset(); }); setSearchBox(); }); return () => (
{ // data.showMusicImg = item.value; if (item.value == musicForms.musicSheetCategoriesId) { return; } data.musics = []; musicForms.musicSheetCategoriesId = item.value; data.musicSheetCategoriesName = item.text; data.popoverMusicShow = false; getMusicList(); }}> {{ reference: () => ( {data.musicSheetCategoriesName} ) }}
(data.searchNoticeShow = false)} onBlur={val => { musicForms.keyword = val?.trim() || ''; requestAnimationFrame(() => { requestAnimationFrame(() => { if (musicForms.keyword) { data.searchNoticeShow = true; } }); }); }} onSearch={val => { if (!data.loading) { musicForms.keyword = val; handleReset(); } }}> {{ left: () => data.subjectItem.value && data.subjectList.length > 1 && (
{ data.subjectList.forEach((c: any) => { c.className = ''; }); data.subjectItem = { ...item, className: 'selected' }; handleReset(); }}> {{ reference: () => (
{data.subjectItem.text}
) }}
) }}
{data.musics.map((item: any, index: number) => { return (
{ data.musicIndex = index; musicIframeLoad(); }}> { const el = e.target as HTMLImageElement; el.setAttribute('loaded', 'true'); }} />
{item.usedNum}
{item.composer || '佚名'}
{/* */}
); })} {!data.finshed && (
)} {!data.loading && data.musics.length === 0 && (
)}
{isEnsemble.value && (
(data.showChangeVoice = true)}> 切换声轨
)}
{data.musics[data.musicIndex]?.musicSheetName}
{/* ensembleDetail */} {isEnsemble.value ? (
<> {/* {loading.value && (

加载中...

)} */} {/* */}
) : ( <> {data.showMusicImg === 'first' ? ( <> {data.musics[data.musicIndex]?.musicFirstImg ?.split(',') .map((item: any, index: number) => { return ( {data.musics[data.musicIndex]?.musicJianImg ?.split(',') .map((item: any, index: number) => { return ( { return ( { if (val) { postMessage({ api: 'openWebView', content: { url: `${location.origin}${location.pathname}#/member-center`, orientation: 1 } }); } data.showVip = false; }} /> {data.showChangeVoice && ( (data.showChangeVoice = false)} onConfirm={async (index: number) => { data.selectMusicInstrumentIndex = index; await analyzeXml(); musicIframeLoad(); data.showChangeVoice = false; }} /> )}
); } });