123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- import {
- computed,
- defineComponent,
- nextTick,
- onMounted,
- onUnmounted,
- reactive,
- ref
- } from 'vue';
- import styles from './detail.module.less';
- import CBreadcrumb from '/src/components/CBreadcrumb';
- import { useRoute } from 'vue-router';
- import { NScrollbar, NSpin, NTabPane, NTabs } from 'naive-ui';
- import SearchGroupResources from './search-group-resources';
- import TheSearch from '/src/components/TheSearch';
- import TheEmpty from '/src/components/TheEmpty';
- import { api_musicSheetPage } from '../xiaoku-ai/api';
- import { formatUsedNum } from '.';
- import { vaildMusicScoreUrl } from '/src/utils/urlUtils';
- import { exitFullscreen, fscreen } from '/src/utils';
- import { state as baseState } from '/src/state';
- import { useUserStore } from '/src/store/modules/users';
- import PreviewWindow from '../preview-window';
- export default defineComponent({
- name: 'xiaoku-detail',
- setup() {
- const route = useRoute();
- const userStore = useUserStore();
- const routerList = ref([
- { name: 'AI学练', path: '/xiaoku-list' },
- { name: '曲目列表', path: '' }
- ]);
- const forms = reactive({
- page: 1,
- rows: 32,
- status: true,
- searchType: ''
- });
- const state = reactive({
- countPage: 1,
- loading: true,
- finshed: false,
- reshing: false,
- tabName: '' as '' | 'RECOMMEND' | 'HOT' | 'NEW',
- list: [] as any,
- allSearch: {
- name: '',
- musicTagIds: '',
- audioPlayTypes: null as any,
- bookVersionId: null as any,
- musicalInstrumentId: null as any,
- subjectId: null
- },
- hotSearch: {
- name: '',
- musicalInstrumentId: null as any
- },
- newSearch: {
- name: '',
- musicalInstrumentId: null as any
- },
- recommendSearch: {
- name: '',
- musicalInstrumentId: null as any
- },
- previewModal: false,
- previewParams: {
- type: '',
- src: ''
- } as any
- });
- const searchValue = computed(() => {
- if (state.tabName === 'RECOMMEND') {
- return state.recommendSearch.name;
- } else if (state.tabName === 'HOT') {
- return state.hotSearch.name;
- } else if (state.tabName === 'NEW') {
- return state.newSearch.name;
- } else {
- return state.allSearch.name;
- }
- });
- const musicalInstrumentId = computed(() => {
- let id = state.allSearch.musicalInstrumentId;
- if (state.tabName === 'RECOMMEND') {
- id = state.recommendSearch.musicalInstrumentId;
- } else if (state.tabName === 'HOT') {
- id = state.hotSearch.musicalInstrumentId;
- } else if (state.tabName === 'NEW') {
- id = state.newSearch.musicalInstrumentId;
- }
- return id;
- });
- const onSearch = async (item: any) => {
- forms.page = 1;
- state.reshing = true;
- state.finshed = false;
- state.list = [];
- const { subjectId, ...res } = item;
- if (state.tabName === 'HOT') {
- state.hotSearch = Object.assign(state.hotSearch, {
- musicalInstrumentId: subjectId
- });
- } else if (state.tabName == 'NEW') {
- state.newSearch = Object.assign(state.newSearch, {
- musicalInstrumentId: subjectId
- });
- } else if (state.tabName === 'RECOMMEND') {
- state.recommendSearch = Object.assign(state.recommendSearch, {
- musicalInstrumentId: subjectId
- });
- } else {
- state.allSearch = Object.assign(state.allSearch, {
- ...res,
- musicalInstrumentId: subjectId,
- subjectId: null
- });
- }
- getList();
- nextTick(() => {
- __initSpin();
- });
- };
- const spinRef = ref();
- const handleResh = () => {
- if (state.loading || state.finshed) return;
- forms.page = forms.page + 1;
- getList();
- };
- const getList = async () => {
- if (forms.page == 1) {
- state.loading = true;
- }
- let res = {} as any;
- const { ...result } = forms;
- let params = {
- ...result,
- searchType: state.tabName
- } as any;
- if (state.tabName === 'RECOMMEND') {
- params = Object.assign(params, state.recommendSearch);
- params.rows = 60;
- params.page = 1;
- } else if (state.tabName === 'HOT') {
- params = Object.assign(params, state.hotSearch);
- params.rows = 60;
- params.page = 1;
- } else if (state.tabName === 'NEW') {
- params = Object.assign(params, state.newSearch);
- params.rows = 60;
- params.page = 1;
- } else {
- params.name = state.allSearch.name;
- const { ...more } = state.allSearch;
- params = Object.assign(params, { ...more });
- }
- try {
- res = await api_musicSheetPage(params);
- } catch (error) {
- console.log(error);
- }
- if (state.reshing) {
- state.list = [];
- state.reshing = false;
- }
- if (res?.code === 200 && Array.isArray(res?.data?.rows)) {
- const tempResult = res?.data?.rows || [];
- tempResult.forEach((item: any) => {
- item.audioPlayTypeArray = item.audioPlayTypes
- ? item.audioPlayTypes.split(',')
- : [];
- if (item.musicSheetName) {
- const regex = new RegExp(params.name, 'gi');
- const highlightedText = item.musicSheetName.replace(
- regex,
- `<span>$&</span>`
- );
- item.musicNameReg = highlightedText;
- }
- });
- state.list = [...state.list, ...res.data.rows];
- state.finshed = forms.page >= res.data.pages;
- state.countPage = res.data.pages;
- } else {
- state.finshed = true;
- }
- state.loading = false;
- };
- const __initSpin = () => {
- // const obv = new IntersectionObserver(entries => {
- // if (entries[0].intersectionRatio > 0) {
- // handleResh();
- // }
- // });
- // obv.observe(spinRef.value);
- };
- // 查看详情
- const onDetail = (item: any) => {
- // 默认进页面显示对应的曲谱
- // let lineType = item.scoreType || 'FIRST';
- const lineType =
- item.scoreType === 'FIRST'
- ? 'firstTone'
- : item.scoreType === 'JIAN'
- ? 'fixedTone'
- : item.scoreType === 'STAVE'
- ? 'staff'
- : 'firstTone';
- let src = `${vaildMusicScoreUrl()}/instrument?v=${+new Date()}&platform=pc&id=${
- item.id
- }&Authorization=${
- userStore.getToken
- }&musicRenderType=${lineType}&showGuide=true&part-index=${0}`;
- let musicalInstrumentId = '';
- if (state.tabName === 'RECOMMEND') {
- musicalInstrumentId = state.recommendSearch.musicalInstrumentId;
- } else if (state.tabName === 'HOT') {
- musicalInstrumentId = state.hotSearch.musicalInstrumentId;
- } else if (state.tabName === 'NEW') {
- musicalInstrumentId = state.newSearch.musicalInstrumentId;
- } else {
- musicalInstrumentId = state.allSearch.musicalInstrumentId;
- }
- if (musicalInstrumentId) {
- src += '&instrumentId=' + musicalInstrumentId;
- }
- if (window.matchMedia('(display-mode: standalone)').matches) {
- baseState.application = window.matchMedia(
- '(display-mode: standalone)'
- ).matches;
- state.previewModal = true;
- fscreen();
- state.previewParams = {
- type: 'music',
- src
- };
- } else {
- window.open(src, +new Date() + '');
- }
- };
- const iframeHandle = (ev: MessageEvent) => {
- if (ev.data?.api === 'back') {
- exitFullscreen();
- state.previewModal = !state.previewModal;
- }
- };
- onMounted(async () => {
- if (route.query.type) {
- state.tabName = route.query.type as any;
- }
- // getList();
- __initSpin();
- window.addEventListener('message', iframeHandle);
- });
- onUnmounted(() => {
- window.removeEventListener('message', iframeHandle);
- });
- return () => (
- <div class={styles.xiaokuDetail}>
- <CBreadcrumb list={routerList.value}></CBreadcrumb>
- <div class={styles.detailContainer}>
- <NTabs
- paneClass={styles.paneTitle}
- justifyContent="start"
- // animated
- paneWrapperClass={styles.paneWrapperContainer}
- v-model:value={state.tabName}
- onUpdate:value={(val: any) => {
- forms.page = 1;
- state.finshed = false;
- state.reshing = true;
- state.list = [];
- if (musicalInstrumentId.value) {
- getList();
- __initSpin();
- }
- }}
- v-slots={{
- suffix: () => (
- <TheSearch
- placeholder="请输入曲目名称"
- round
- value={searchValue.value}
- onUpdate:value={(val: string) => {
- // 重置搜索条件
- if (state.tabName === 'RECOMMEND') {
- state.recommendSearch.name = val;
- } else if (state.tabName === 'HOT') {
- state.hotSearch.name = val;
- } else if (state.tabName === 'NEW') {
- state.newSearch.name = val;
- } else {
- state.allSearch.name = val;
- }
- }}
- class={styles.inputSearch}
- onSearch={val => {
- if (state.tabName === 'RECOMMEND') {
- state.recommendSearch.name = val;
- } else if (state.tabName === 'HOT') {
- state.hotSearch.name = val;
- } else if (state.tabName === 'NEW') {
- state.newSearch.name = val;
- } else {
- state.allSearch.name = val;
- }
- forms.page = 1;
- state.finshed = false;
- state.list = [];
- getList();
- }}
- />
- )
- }}>
- <NTabPane name={``} tab={'全部曲目'}></NTabPane>
- <NTabPane name={`RECOMMEND`} tab={'推荐曲目'}></NTabPane>
- <NTabPane name={`HOT`} tab={'热门曲目'}></NTabPane>
- <NTabPane name={`NEW`} tab={'最新曲目'}></NTabPane>
- </NTabs>
- <NScrollbar
- class={[
- [
- styles.wrapList,
- !state.loading &&
- state.list.length === 0 &&
- styles.wrapListEmpty
- ]
- ]}
- onScroll={async (e: any) => {
- if (state.tabName) {
- return;
- }
- const clientHeight = e.target?.clientHeight;
- const scrollTop = e.target?.scrollTop;
- const scrollHeight = e.target?.scrollHeight;
- // 是否到底,是否加载完
- if (
- clientHeight + scrollTop + 20 >= scrollHeight &&
- !state.finshed &&
- !state.loading
- ) {
- if (forms.page >= state.countPage) return;
- forms.page = forms.page + 1;
- await getList();
- }
- }}>
- {/* , state.tabName ? styles.searchSectionHide : '' */}
- <NSpin show={state.loading}>
- <div
- class={[
- styles.loadingSection,
- !state.loading &&
- state.list.length === 0 &&
- styles.loadingSectionEmpty
- ]}>
- <div class={[styles.searchSection]}>
- <SearchGroupResources
- type={state.tabName}
- musicalInstrumentId={musicalInstrumentId.value}
- onSearch={(val: any) => {
- onSearch(val);
- }}
- />
- </div>
- {state.list.length > 0 && (
- <div
- class={[
- styles.sectionContainer
- // state.tabName && styles.noSearchContainer
- ]}>
- {state.list.map((item: any) => (
- <div
- class={styles.sectionItem}
- onClick={() => onDetail(item)}>
- <div class={styles.img}>
- <img
- referrerpolicy="no-referrer"
- src={item.titleImg}
- />
- </div>
- <div class={styles.infos}>
- <div
- class={styles.topName}
- v-html={item.musicNameReg}></div>
- <div class={styles.types}>
- <div class={styles.hot}>
- <span>{formatUsedNum(item.usedNum)}</span>
- </div>
- {item.audioPlayTypes?.includes('SING') && (
- <div class={styles.sing}>演唱</div>
- )}
- {item.audioPlayTypes?.includes('PLAY') && (
- <div class={styles.song}>演奏</div>
- )}
- <div class={styles.author}>{item.composer}</div>
- </div>
- </div>
- </div>
- ))}
- </div>
- )}
- {/* <div
- // ref={spinRef}
- class={[styles.loadingWrap, (state.finshed || !state.loading) && styles.showLoading]}>
- <NSpin show={true}></NSpin>
- </div> */}
- {!state.loading && state.list.length === 0 && (
- <div class={styles.empty}>
- <TheEmpty></TheEmpty>
- </div>
- )}
- </div>
- </NSpin>
- </NScrollbar>
- </div>
- {/* 应用内预览或上课 */}
- <PreviewWindow
- v-model:show={state.previewModal}
- type="music"
- params={state.previewParams}
- />
- </div>
- );
- }
- });
|