import { PropType, Transition, defineComponent, ref } from 'vue'; import styles from './index.module.less'; import { ImageRenderToolbarProps, NButton, NCard, NImage, NModal, NSpace, NSpin, NTooltip, useMessage } from 'naive-ui'; import iconImage from '@common/images/icon-image.png'; import iconVideo from '@common/images/icon-video.png'; import iconAudio from '@common/images/icon-audio.png'; import iconMusic from '@common/images/icon-music.png'; import iconPPT from '@common/images/icon-ppt.png'; import iconOther from '@common/images/icon-other.png'; import iconCollectDefault from '@common/images/icon-collect-default.png'; import iconCollectActive from '@common/images/icon-collect-active.png'; import iconDownload from '@common/images/icon-download.png'; import TheNoticeBar from '../TheNoticeBar'; import AudioPlayer from './audio-player'; import VideoPlayer from './video-player'; import { PageEnum } from '/src/enums/pageEnum'; import { api_musicSheetDetail } from '/src/api/user'; import JSZip, { file } from 'jszip'; import { saveAs } from 'file-saver'; // LISTEN:听音,RHYTHM:节奏,THEORY:乐理知识,MUSIC_WIKI:曲目 INSTRUMENT:乐器 MUSICIAN:音乐家) type itemType = { id: string | number; type: | 'IMG' | 'VIDEO' | 'SONG' | 'MUSIC' | 'PPT' | 'LISTEN' | 'RHYTHM' | 'THEORY' | 'MUSIC_WIKI' | 'INSTRUMENT' | 'MUSICIAN'; coverImg: string; content?: string; title: string; isCollect: boolean; audioPlayTypeArray?: string[]; isSelected: boolean; // 精选 exist?: boolean; // 是否已经选 }; export default defineComponent({ name: 'card-type', props: { // 是否是选中状态 isActive: { type: Boolean, default: false }, /** 是否可以拖拽 */ draggable: { type: Boolean, default: false }, // 是否可以收藏 isCollect: { type: Boolean, default: true }, // 是否显示收藏 isShowCollect: { type: Boolean, default: true }, // 是否显示添加按钮 isShowAdd: { type: Boolean, default: false }, // 是否禁用添加按钮 isShowAddDisabled: { type: Boolean, default: false }, // 鼠标移动上面的时候是否自动播放,或者可以点击 disabledMouseHover: { type: Boolean, default: true }, // 是否预览 isPreview: { type: Boolean, default: true }, item: { type: Object as PropType, default: () => ({}) }, /** 是否下架 */ offShelf: { type: Boolean, default: false }, /** 是否可以下载 */ isDownload: { type: Boolean, default: false }, audioPlayTypeSize: { type: String as PropType<'default' | 'small'>, deafult: 'default' } }, /** * @type {string} click 点击事件 * @type {string} collect 收藏 * @type {string} add 添加 * @type {string} offShelf 下架 */ emits: ['click', 'collect', 'add', 'offShelf'], setup(props, { emit }) { const message = useMessage(); const isAnimation = ref(false); const downloadStatus = ref(false); const formatType = (type: string) => { let typeImg = iconOther; switch (type) { case 'IMG': typeImg = iconImage; break; case 'VIDEO': typeImg = iconVideo; break; case 'SONG': typeImg = iconAudio; break; case 'MUSIC': typeImg = iconMusic; break; case 'PPT': typeImg = iconPPT; break; } return typeImg; }; // 获取文件blob格式 const getFileBlob = (url: string) => { return new Promise((resolve, reject) => { const request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'blob'; request.onload = (res: any) => { if (res.target.status == 200) { resolve(res.target.response); } else { reject(res); } }; request.send(); }); }; // 多个文件下载 const downLoadMultiFile = (files: any, filesName: string) => { const zip = new JSZip(); const result = []; for (const i in files) { const promise = getFileBlob(files[i].url).then((res: any) => { zip.file(files[i].name, res, { binary: true }); }); result.push(promise); } Promise.all(result) .then(() => { zip.generateAsync({ type: 'blob' }).then(res => { saveAs( res, filesName ? filesName + Date.now() + '.zip' : `文件夹${Date.now()}.zip` ); }); }) .catch(() => { message.error('下载失败'); }); downloadStatus.value = false; }; const downloadFile = (filename: string, fileUrl: string) => { // 发起Fetch请求 fetch(fileUrl) .then(response => response.blob()) .then(blob => { saveAs(blob, filename); setTimeout(() => { downloadStatus.value = false; }, 100); }) .catch(() => { message.error('下载失败'); }); downloadStatus.value = false; }; const getFileName = (url: any) => { // 使用正则表达式获取文件名 const tempUrl = url.split('?'); const fileNameRegex = /\/([^\\/]+)$/; // 匹配最后一个斜杠后的内容 const match = tempUrl[0].match(fileNameRegex); if (match) { return match[1]; } else { return ''; } }; const onDownload = async (e: MouseEvent) => { e.stopPropagation(); e.preventDefault(); const item = props.item; if (!item.content) { message.error('下载失败'); return; } if (downloadStatus.value) return false; downloadStatus.value = true; const suffix: any = item.content?.split('.'); const fileName = item.title + '.' + suffix[suffix?.length - 1]; if (item.type === 'MUSIC') { const { data } = await api_musicSheetDetail(item.content); const urls = []; if (data.xmlFileUrl) { urls.push({ url: data.xmlFileUrl, name: getFileName(data.xmlFileUrl) }); } if (data.background && data.background.length > 0) { data.background.forEach((item: any) => { urls.push({ url: item.audioFileUrl, name: getFileName(item.audioFileUrl) }); }); } downLoadMultiFile(urls, item.title); // setTimeout(() => { // downloadStatus.value = false; // }, 1000); } else { downloadFile(fileName, item.content); } }; return () => (
emit('click', props.item)} key={props.item.id} draggable={!props.draggable ? false : props.item.exist ? false : true} class={[ styles['card-section'], 'card-section-container', !props.draggable ? '' : props.item.exist ? '' : styles.cardDrag ]} onMouseenter={() => { isAnimation.value = true; }} onMouseleave={() => { isAnimation.value = false; }} onDragstart={(e: any) => { e.dataTransfer.setData('text', JSON.stringify(props.item)); }}> {/* 判断是否下架 */} {props.offShelf && (

该资源已被下架

{ e.stopPropagation(); emit('offShelf'); }}> 确认
)} {{ cover: () => ( <> {/* 图片 */} {props.item.type === 'IMG' && ( { return [ nodes.prev, nodes.next, nodes.rotateCounterclockwise, nodes.rotateClockwise, nodes.resizeToOriginalSize, nodes.zoomOut, nodes.close ]; }} /> )} {/* 乐谱 */} {props.item.type === 'MUSIC' && ( <> {props.item.audioPlayTypeArray?.includes('PLAY') && ( {{ trigger: () => ( ), default: '演奏场景' }} )} {props.item.audioPlayTypeArray?.includes('SING') && ( {{ trigger: () => ( ), default: '演唱场景' }} )} )} {/* 音频 */} {props.item.type === 'SONG' && ( )} {/* 视频 */} {props.item.type === 'VIDEO' && ( )} {/* ppt */} {props.item.type === 'PPT' && ( )} {/* 节奏练习 */} {props.item.type === 'RHYTHM' && ( )} {/* 听音练习 */} {props.item.type === 'LISTEN' && ( )} {/* 乐理 */} {props.item.type === 'THEORY' && ( )} {/* 名曲 */} {props.item.type === 'MUSIC_WIKI' && ( )} {/* 乐器 */} {props.item.type === 'INSTRUMENT' && ( )} {/* 音乐家 */} {props.item.type === 'MUSICIAN' && ( )} ), footer: () => (
{/* 收藏 */}
{props.isDownload && (
)} {props.isShowCollect && (
{ e.stopPropagation(); e.preventDefault(); // 判断是否可以收藏 if (props.isCollect) { emit('collect', props.item); } }}> {props.item.isCollect ? ( ) : ( )}
)}
{/* 精选 */} {props.item.isSelected && ( )} {/* 添加按钮 */} {props.isShowAdd && (props.item.exist ? ( { e.stopPropagation(); e.preventDefault(); emit('add', props.item); }}> {props.item.exist ? '已添加' : '添加'} ) : ( !props.isShowAddDisabled && ( { e.stopPropagation(); e.preventDefault(); emit('add', props.item); }}> {props.item.exist ? '已添加' : '添加'} ) ))}
) }}
); } });