ソースを参照

修改音频播放,多条

tanshanming 8 ヶ月 前
コミット
568a013067

+ 12 - 17
src/libs/globalFunction/file.js

@@ -203,11 +203,11 @@ const fileFunction = {
 	 * @param {*} imgInfoList 多个图片列表
 	 */
 	handleImgPreview(currentIndex, imgInfo = {}, imgInfoList = []) {
-		console.log('handleImgPreview', currentIndex, imgInfo, imgInfoList)
-		console.log('handleImgPreview--', router.currentRoute.value.query.fileType)
+		const myResourceStore = useMyResourceStore()
+		const fileType = myResourceStore.getQuery.fileType
 		// 图片分类下 - 传递整个页面的图片列表;非图片分类下 - 由单个图片构建图片列表
 		const imgList =
-			router.currentRoute.value.query.fileType && Number(router.currentRoute.value.query.fileType) === 1
+			fileType && Number(fileType) === 1
 				? imgInfoList.map((item) => {
 						return {
 							...item,
@@ -222,10 +222,7 @@ const fileFunction = {
 							downloadLink: this.getDownloadFilePath(imgInfo)
 						}
 				  ]
-		const defaultIndex =
-			router.currentRoute.value.query.fileType && Number(router.currentRoute.value.query.fileType) === 1
-				? currentIndex
-				: 0
+		const defaultIndex = fileType && Number(fileType) === 1 ? currentIndex : 0
 
 		fileOperationPlugins.openBox.imgPreview({ imgList, defaultIndex })
 	},
@@ -236,9 +233,11 @@ const fileFunction = {
 	 * @param {*} videoInfoList 多个视频列表
 	 */
 	handleVideoPreview(currentIndex, videoInfo = {}, videoInfoList = []) {
+		const myResourceStore = useMyResourceStore()
+		const fileType = myResourceStore.getQuery.fileType
 		// 视频分类下 - 传递整个页面的视频列表;非视频分类下 - 由单个视频构建视频列表
 		const videoList =
-			router.currentRoute.value.query.fileType && Number(router.currentRoute.value.query.fileType) === 3
+			fileType && Number(fileType) === 3
 				? videoInfoList.map((item) => {
 						return {
 							...item,
@@ -253,10 +252,7 @@ const fileFunction = {
 							downloadLink: this.getDownloadFilePath(videoInfo)
 						}
 				  ]
-		const defaultIndex =
-			router.currentRoute.value.query.fileType && Number(router.currentRoute.value.query.fileType) === 3
-				? currentIndex
-				: 0
+		const defaultIndex = fileType && Number(fileType) === 3 ? currentIndex : 0
 		fileOperationPlugins.openBox.videoPreview({ videoList, defaultIndex })
 	},
 	/**
@@ -266,9 +262,11 @@ const fileFunction = {
 	 * @param {*} audioInfoList 多个音频列表
 	 */
 	handleAudioPreview(currentIndex, audioInfo = {}, audioInfoList = []) {
+		const myResourceStore = useMyResourceStore()
+		const fileType = myResourceStore.getQuery.fileType
 		// 音频分类下 - 传递整个页面的音频列表;非音频分类下 - 由单个音频构建音频列表
 		const audioList =
-			router.currentRoute.value.query.fileType && Number(router.currentRoute.value.query.fileType) === 4
+			fileType && Number(fileType) === 4
 				? audioInfoList.map((item) => {
 						return {
 							...item,
@@ -283,10 +281,7 @@ const fileFunction = {
 							downloadLink: this.getDownloadFilePath(audioInfo)
 						}
 				  ]
-		const defaultIndex =
-			router.currentRoute.value.query.fileType && Number(router.currentRoute.value.query.fileType) === 4
-				? currentIndex
-				: 0
+		const defaultIndex = fileType && Number(fileType) === 4 ? currentIndex : 0
 		fileOperationPlugins.openBox.audioPreview({ audioList, defaultIndex })
 	},
 	/**

+ 69 - 39
src/views/myResource/file/box/audioPreview/BoxMask.vue

@@ -17,9 +17,9 @@
 							&nbsp;&nbsp;下方向键 - 音量减小<br />
 						</div>
 					</template>
-					<i class="tip-icon anticon anticon-bulb"></i>
+					<BulbOutlined class="tip-icon" />
 				</a-tooltip>
-				<i class="close-icon anticon anticon-close" title="关闭(Escape)" @click="handleClosePreview"></i>
+				<CloseOutlined class="close-icon" title="关闭(Escape)" @click="handleClosePreview" />
 			</div>
 			<audio
 				ref="audioRef"
@@ -108,28 +108,28 @@
 			<!-- 底部音乐控件 -->
 			<div class="control-wrapper">
 				<div class="control-left">
-					<i
-						class="operate-icon iconfont icon-shangyishou"
+					<StepBackwardOutlined
+						class="operate-icon"
 						title="上一个(按左方向键)"
 						@click="handleChangeAudioIndex('pre')"
-					></i>
-					<i
-						class="operate-icon play-icon iconfont icon-icon-7"
+					/>
+					<PlayCircleOutlined
+						class="operate-icon play-icon"
 						v-show="!isPlay"
 						title="播放(按空格键)"
 						@click="handleClickPlayIcon"
-					></i>
-					<i
-						class="operate-icon pause-icon iconfont icon-icon-3"
+					/>
+					<PauseCircleOutlined
+						class="operate-icon pause-icon"
 						v-show="isPlay"
 						title="暂停(按空格键)"
 						@click="handleClickPauseIcon"
-					></i>
-					<i
-						class="operate-icon iconfont icon-xiayishou"
+					/>
+					<StepForwardOutlined
+						class="operate-icon"
 						title="下一个(按右方向键)"
 						@click="handleChangeAudioIndex('next')"
-					></i>
+					/>
 					<a-slider
 						class="progress-bar control-item"
 						v-model:value="currentTime"
@@ -145,22 +145,21 @@
 					>
 				</div>
 				<div class="control-right">
-					<i
-						class="operate-icon cycle-type iconfont"
-						:class="cycleTypeMap[String(cycleType)].icon"
+					<ReloadOutlined
+						class="operate-icon cycle-type"
 						:title="cycleTypeMap[String(cycleType)].text"
 						@click="handleChangeCycleType"
-					></i>
+					/>
 					<a
 						class="operate-icon download-link"
 						:href="$file.getDownloadFilePath(activeFileObj)"
 						target="_blank"
 						title="下载"
 					>
-						<i class="download-icon anticon anticon-download"></i>
+						<DownloadOutlined class="download-icon" />
 					</a>
-					<i
-						class="operate-icon share-icon anticon anticon-share-alt"
+					<ShareAltOutlined
+						class="operate-icon share-icon"
 						title="分享"
 						@click.stop="
 							$openDialog.shareFile({
@@ -171,12 +170,13 @@
 								]
 							})
 						"
-					></i>
-					<i
-						class="operate-icon volume-icon control-item iconfont"
-						:class="volume === 0 ? 'icon-jingyin01' : 'icon-yinliang101'"
-						@click="handleClickVolumeIcon"
-					></i>
+					/>
+					<template v-if="volume === 0">
+						<AudioMutedOutlined class="operate-icon volume-icon control-item" @click="handleClickVolumeIcon" />
+					</template>
+					<template v-else>
+						<SoundOutlined class="operate-icon volume-icon control-item" @click="handleClickVolumeIcon" />
+					</template>
 					<a-slider
 						class="volume-bar control-item"
 						v-model:value="volume"
@@ -198,7 +198,19 @@
 	import { Base64 } from 'js-base64'
 	import waveGif from '@/assets/images/myResource/audio/wave.gif'
 	import musicImg from '@/assets/images/myResource/file/file_music.png'
-
+	import {
+		BulbOutlined,
+		CloseOutlined,
+		StepBackwardOutlined,
+		PlayCircleOutlined,
+		PauseCircleOutlined,
+		StepForwardOutlined,
+		ReloadOutlined,
+		DownloadOutlined,
+		ShareAltOutlined,
+		SoundOutlined,
+		AudioMutedOutlined
+	} from '@ant-design/icons-vue'
 	const { proxy } = getCurrentInstance()
 
 	// 定义响应式数据
@@ -352,22 +364,40 @@
 						...res.data.music,
 						duration: res.data.music.trackLength
 					}
+					if (!audioInfo.value.lyrics) {
+						lyricsList.value = []
+						return
+					}
 					// Base64 解码为 lrc 格式的歌词文件
 					let lyricsStr = Base64.decode(audioInfo.value.lyrics)
 					if (lyricsStr.includes('[offset:0]')) {
 						// 有歌词,从标志位 [offset:0] 下一行开始截取
-						lyricsStr = lyricsStr.split('[offset:0]\n')[1]
+						lyricsStr = lyricsStr.split('[offset:0]')[1]
 					}
 					lyricsList.value = lyricsStr
 						.split('\n')
-						.map((item) => {
-							const line = item.split('[')[1].split(']')
-							return {
-								time: line[0], //  当前行歌词开始播放的秒数
-								text: line[1] //  当前歌词文本
+						.map((item, index) => {
+							// 检查行是否包含 [ 和 ] 字符
+							if (item && item.includes('[') && item.includes(']')) {
+								try {
+									const parts = item.split('[')
+									if (parts.length > 1) {
+										const line = parts[1].split(']')
+										if (line.length > 1) {
+											return {
+												time: line[0], //  当前行歌词开始播放的秒数
+												text: line[1].trim() //  当前歌词文本
+											}
+										}
+									}
+								} catch (error) {
+									console.error('解析歌词行出错:', item, error)
+								}
 							}
+							// 如果解析失败或格式不符合要求,返回null
+							return null
 						})
-						.filter((item) => item.text !== '')
+						.filter((item) => item !== null && item.text !== '')
 					lyricsList.value = lyricsList.value.map((item, index) => {
 						return {
 							...item,
@@ -516,7 +546,7 @@
 				case 3: {
 					let newActiveIndex = 0
 					do {
-						newActiveIndex = Math.floor(Math.random() * (props.audioList.value.length - 1)) + 1
+						newActiveIndex = Math.floor(Math.random() * (props.audioList.length - 1)) + 1
 					} while (activeIndex.value === newActiveIndex)
 					activeIndex.value = newActiveIndex
 					break
@@ -524,12 +554,12 @@
 				default: {
 					if (type === 'pre') {
 						if (activeIndex.value === 0) {
-							activeIndex.value = props.audioList.value.length - 1
+							activeIndex.value = props.audioList.length - 1
 						} else {
 							activeIndex.value--
 						}
 					} else if (type === 'next') {
-						if (activeIndex.value === props.audioList.value.length - 1) {
+						if (activeIndex.value === props.audioList.length - 1) {
 							activeIndex.value = 0
 						} else {
 							activeIndex.value++
@@ -561,7 +591,7 @@
 	 */
 	function handleClosePreview() {
 		visible.value = false
-		callback('cancel')
+		props.callback('cancel')
 	}
 
 	// 暴露给父组件的方法和属性

+ 0 - 6
src/views/myResource/file/box/uploadFile/Box.vue

@@ -141,7 +141,6 @@
 				}
 				return (data.uploaded || []).indexOf(chunk.offset + 1) >= 0
 			} else {
-				console.log(objMessage.message)
 				return true
 			}
 		},
@@ -192,24 +191,20 @@
 	const handlePrepareUpload = async () => {
 		// options.value.headers.token = getCookies(getConfig().tokenKeyName)
 		await nextTick()
-		console.log('uploadProps.uploadWay', uploadProps.uploadWay)
 		switch (uploadProps.uploadWay) {
 			case 1: {
 				if (uploadBtn.value?.$el) {
-					console.log('执行上传', uploadBtn.value.$el)
 					uploadBtn.value.$el.click()
 				}
 				break
 			}
 			case 2: {
 				if (uploadDirBtn.value?.$el) {
-					console.log('执行目录', uploadDirBtn.value.$el)
 					uploadDirBtn.value.$el.click()
 				}
 				break
 			}
 			case 3: {
-				console.log('执行粘贴', uploadDirBtn.value.$el)
 				pasteImg.value.src = ''
 				pasteImg.value.name = ''
 				pasteImgObj.value = null
@@ -220,7 +215,6 @@
 	}
 
 	const handlePaste = (event) => {
-		console.log('onDrop--', event)
 		let pasteItems = (event.clipboardData || window.clipboardData).items
 		if (pasteItems && pasteItems.length) {
 			let imgObj = pasteItems[0].getAsFile()

+ 2 - 27
src/views/myResource/resourceLibrary/file/AsideMenu.vue

@@ -153,8 +153,7 @@
 </template>
 
 <script setup>
-	import { ref, computed, watch, onMounted, getCurrentInstance } from 'vue'
-	import { useRouter, useRoute } from 'vue-router'
+	import { ref, computed, onMounted, getCurrentInstance } from 'vue'
 	import { useMyResourceStore } from '@/store/myResource'
 	import {
 		FolderOutlined,
@@ -172,11 +171,9 @@
 
 	// 获取当前实例,用于访问全局属性
 	const { proxy } = getCurrentInstance()
-	const router = useRouter()
-	const route = useRoute()
 	const myResourceStore = useMyResourceStore()
 
-	const emit = defineEmits([''])
+	const emit = defineEmits(['onNavigateTo'])
 
 	// 数据
 	const isDrawer = ref(false) // 控制移动端菜单抽屉是否显示
@@ -224,30 +221,8 @@
 		return myResourceStore.screenWidth
 	})
 
-	// 监听路由变化,更新activeIndex
-	// watch(
-	// 	() => route.query.fileType,
-	// 	(newValue) => {
-	// 		activeIndex.value = [String(newValue || '0')]
-	// 		console.log('activeIndex', activeIndex.value)
-	// 		document.title = `${myFileMenuMap[Number(newValue || 0)]} - ${proxy.$RESOURCE_CONFIG.siteName}`
-	// 		isDrawer.value = false
-	// 	}
-	// )
-
-	// // 监听收缩状态变化,存储在 localStorage 中,保证页面刷新时仍然保存设置的状态
-	// watch(isCollapse, (newValue) => {
-	// 	localStorage.setItem('qiwen_is_collapse', newValue)
-	// 	if (screenWidth.value <= 768 && newValue) {
-	// 		isDrawer.value = true
-	// 		isCollapse.value = false
-	// 	}
-	// })
-
 	// 导航到指定路由
 	const navigateTo = (route) => {
-		console.log('route==', route)
-		// router.push(route)
 		emit('onNavigateTo', route)
 	}
 

+ 19 - 13
src/views/myResource/resourceLibrary/file/FileList.vue

@@ -110,7 +110,6 @@
 	// 当前所在路径
 	const filePath = computed(() => {
 		// return route.query.filePath ? route.query.filePath : '/'
-		console.log('filePath', myResourceStore.getQuery.filePath)
 		return myResourceStore.getQuery.filePath ? myResourceStore.getQuery.filePath : '/'
 	})
 
@@ -124,20 +123,9 @@
 		return myResourceStore.screenWidth
 	})
 	const navigateTo = (path) => {
-		// fileList.value.navigateTo(path)
-		console.log('navigateTo 变化', path)
-		//     {
-		// "name": "resourceLibrary",
-		// "query": {
-		//     "fileType": 2
-		// }
 		if (path.name && path.name == 'resourceLibrary') {
-			// if (path.query.fileType == 0) {
-
-			// }
 			myResourceStore.changeQuery(path.query)
 			fileType.value = path.query.fileType
-
 			setPageCount()
 			getTableDataByType()
 		}
@@ -282,7 +270,7 @@
 	/**
 	 * 表格数据获取相关事件 | 分页组件 | 页大小改变时
 	 */
-	const handleSizeChange = (pageSize) => {
+	const handleSizeChange = (current, pageSize) => {
 		pageData.value.pageCount = pageSize
 		getTableDataByType()
 	}
@@ -377,6 +365,10 @@
 	@import '@/style/myResource/varibles.less';
 
 	.file-list-wrapper {
+		display: flex;
+		flex-direction: column;
+		height: 100%;
+
 		.header {
 			padding: 0;
 		}
@@ -385,12 +377,22 @@
 			margin-bottom: 8px;
 		}
 
+		/* 添加这个样式,让文件列表区域自适应填充剩余空间并处理溢出 */
+		:deep(.file-table-wrapper),
+		:deep(.file-grid-wrapper),
+		.image-model {
+			flex: 1;
+			overflow-y: auto;
+			min-height: 0; /* 确保flex布局正常工作 */
+		}
+
 		.pagination-wrapper {
 			position: relative;
 			border-top: 1px solid @BorderBase;
 			height: 44px;
 			line-height: 44px;
 			text-align: center;
+			flex-shrink: 0; /* 防止分页组件被压缩 */
 
 			.current-page-count {
 				position: absolute;
@@ -400,6 +402,10 @@
 				font-size: 13px;
 				color: @RegularText;
 			}
+
+			:deep(.ant-select-dropdown) {
+				min-width: 90px !important;
+			}
 		}
 	}
 </style>

+ 0 - 122
src/views/myResource/resourceLibrary/file/test.vue

@@ -1,122 +0,0 @@
-<template>
-	<uploader
-		:options="options"
-		:file-status-text="statusText"
-		class="uploader-example"
-		ref="uploaderRef"
-		@file-complete="fileComplete"
-		@complete="complete"
-	>
-		<uploader-unsupport></uploader-unsupport>
-		<!-- 选择按钮 在这里隐藏 -->
-		<uploader-btn class="select-file-btn" :attrs="attrs" ref="uploadBtn"> 选择文件 </uploader-btn>
-		<uploader-btn class="select-file-btn" :attrs="attrs" :directory="true" ref="uploadDirBtn"> 选择目录 </uploader-btn>
-
-		<!-- <uploader-unsupport></uploader-unsupport>-->
-		<uploader-drop>
-			<p>Drop files here to upload or</p>
-			<uploader-btn>select files</uploader-btn>
-			<uploader-btn :attrs="attrs">select images</uploader-btn>
-			<uploader-btn :directory="true">select folder</uploader-btn>
-		</uploader-drop>
-		<uploader-list></uploader-list>
-	</uploader>
-</template>
-
-<script setup>
-	import { ref, onMounted, nextTick } from 'vue'
-	const props = defineProps({
-		uploadWay: Number,
-		callback: Function,
-		serviceEl: Object,
-		callType: Number,
-		params: Object
-	})
-	// refs
-	const uploaderRef = ref(null)
-	const uploadBtn = ref(null)
-	const uploadDirBtn = ref(null)
-	// 响应式数据
-	const options = ref({
-		target: '//localhost:3000/upload', // '//jsonplaceholder.typicode.com/posts/',
-		testChunks: false
-	})
-
-	const attrs = ref({
-		accept: 'image/*'
-	})
-
-	const statusText = ref({
-		success: 'success',
-		error: 'error',
-		uploading: 'uploading',
-		paused: 'paused',
-		waiting: 'waiting'
-	})
-
-	const handlePrepareUpload = async () => {
-		// options.value.headers.token = getCookies(getConfig().tokenKeyName)
-		await nextTick()
-		switch (props.uploadWay) {
-			case 1: {
-				if (uploadBtn.value?.$el) {
-					uploadBtn.value.$el.click()
-				}
-				break
-			}
-			case 2: {
-				if (uploadDirBtn.value?.$el) {
-					uploadDirBtn.value.$el.click()
-				}
-				break
-			}
-			case 3: {
-				pasteImg.value.src = ''
-				pasteImg.value.name = ''
-				pasteImgObj.value = null
-				dropBoxShow.value = true
-				break
-			}
-		}
-	}
-
-	// 方法
-	const complete = () => {
-		console.log('complete', arguments)
-	}
-
-	const fileComplete = () => {
-		console.log('file complete', arguments)
-	}
-
-	// 生命周期钩子
-	onMounted(() => {
-		nextTick(() => {
-			window.uploader = uploaderRef.value.uploader
-		})
-	})
-
-	// 暴露方法给父组件(如果需要)
-	defineExpose({
-		handlePrepareUpload
-	})
-</script>
-
-<style>
-	.uploader-example {
-		width: 880px;
-		padding: 15px;
-		margin: 40px auto 0;
-		font-size: 12px;
-		box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
-	}
-	.uploader-example .uploader-btn {
-		margin-right: 4px;
-	}
-	.uploader-example .uploader-list {
-		max-height: 440px;
-		overflow: auto;
-		overflow-x: hidden;
-		overflow-y: auto;
-	}
-</style>

+ 0 - 4
src/views/myResource/resourceLibrary/index.vue

@@ -7,7 +7,6 @@
 			<a-layout-content>
 				<a-layout-content class="content-main">
 					<FileList ref="fileList"></FileList>
-					<!-- <Test></Test> -->
 				</a-layout-content>
 			</a-layout-content>
 		</a-layout>
@@ -21,14 +20,11 @@
 
 	const asideMenu = ref(null)
 	const fileList = ref(null)
-
-	// import Test from './file/test.vue'
 	const myResourceStore = useMyResourceStore()
 	// 显示拖拽上传文件遮罩
 	const showUploadMask = (e) => {
 		e.stopPropagation()
 		e.preventDefault()
-		console.log('showUploadMask')
 		myResourceStore.toggleUploadMask()
 	}
 	const onNavigateTo = (path) => {