于添 4 miesięcy temu
rodzic
commit
53ab9f2557

+ 3 - 2
src/components/Editor/index.vue

@@ -54,7 +54,8 @@
 		fileUploadFunction: {
 			type: Function,
 			default: undefined
-		}
+		},
+
 	})
 	const init = ref({
 		language_url: '/tinymce/langs/zh_CN.js',
@@ -123,7 +124,7 @@
 		emit('onClick', e, tinymce)
 	}
 	onMounted(() => {
-		tinymce.init({})
+		tinymce.init(init)
 	})
 </script>
 <style scoped>

+ 1 - 0
src/views/forum/detail.vue

@@ -47,6 +47,7 @@
 						<span>{{ detailObj.forumSupportEnv.osVersion }}</span>
 					</a-descriptions-item>
 				</a-descriptions>
+<!--				船锚-->
 				<div class="htmlContent" v-html="detailObj.postContent"></div>
 				<a-divider />
 				<div class="flc">

+ 21 - 18
src/views/forum/form.vue

@@ -1,7 +1,7 @@
 <template>
 	<xn-form-container
 		:title="formData.id ? '编辑帖子' : '增加帖子'"
-		:height="550"
+		:height="600"
 		:get-container="false"
 		:visible="visible"
 		:destroy-on-close="true"
@@ -10,7 +10,7 @@
 		:mask="false"
 		style="width: 960px; left: calc(50% - 960px / 2)"
 	>
-		<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+		<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical" style="margin-bottom: 20px">
 			<a-row :gutter="16">
 				<a-col :span="8">
 					<a-form-item label="标题:" name="postTitle">
@@ -172,29 +172,32 @@
 	const formRules = {
 		postTitle: [required('请输入标题'),],
 		typeId: [required('请选择分类')],
-		postContent: [required('请输入内容'),{ max: 200, message: '不能超过200个字符' }]
+		// postContent: [required('请输入内容'),{ max: 200, message: '不能超过200个字符' }]
+		postContent: [required('请输入内容')]
 	}
 
 	const categoryOptions = tool.dictList('MENU_TYPE')
 	const visibleOptions = tool.dictList('MENU_VISIBLE')
 	// 验证并提交数据
 	const onSubmit = () => {
+ 		formRef.value.validate().then((valid, errors) => {
+
+				submitLoading.value = true
+				if (formData.value.appointUserArr && formData.value.appointUserArr.length > 1) {
+					formData.value.appointUser = formData.value.appointUserArr.join(',')
+				}
+				forumApi
+					.submitForm(formData.value, formData.value.postId)
+					.then(() => {
+						onClose()
+						submitLoading.value = false
+						emit('successful')
+					})
+					.finally(() => {
+						submitLoading.value = false
+					})
+
 
-		formRef.value.validate().then(() => {
-			submitLoading.value = true
-			if (formData.value.appointUserArr && formData.value.appointUserArr.length > 1) {
-				formData.value.appointUser = formData.value.appointUserArr.join(',')
-			}
-			forumApi
-				.submitForm(formData.value, formData.value.postId)
-				.then(() => {
-					onClose()
-					submitLoading.value = false
-					emit('successful')
-				})
-				.finally(() => {
-					submitLoading.value = false
-				})
 		})
 	}
 

+ 1 - 1
src/views/forum/index.vue

@@ -70,7 +70,7 @@
 						<div class="forum-list-type">
 							{{ postName(record.postType) }} {{ record.typeName ? '|' : '' }} {{ record.typeName }}
 						</div>
-						<div class="forum-list-content one-line" v-html="record.postContent"></div>
+<!--						<div class="forum-list-content one-line" v-html="record.postContent"></div>-->
 					</template>
 					<template v-if="column.dataIndex === 'lastReplyUserAvatar'">
 						<div v-if="record.replyCount==0">

+ 2 - 1
src/views/forum/replyForm.vue

@@ -81,8 +81,9 @@
 	const visibleOptions = tool.dictList('MENU_VISIBLE')
 	// 验证并提交数据
 	const onSubmit = () => {
-		submitLoading.value = true
+
 		formRef.value.validate().then(() => {
+			submitLoading.value = true
 			let params = {}
 			if (formData.value.formType) {
 				params = {

+ 2 - 1
src/views/forum/reportForm.vue

@@ -120,8 +120,9 @@
 	const visibleOptions = tool.dictList('MENU_VISIBLE')
 	// 验证并提交数据
 	const onSubmit = () => {
-		submitLoading.value = true
+
 		formRef.value.validate().then(() => {
+			submitLoading.value = true
 			forumApi
 				.reportinfoAdd({
 					...formData.value,

+ 457 - 400
src/views/resourceDetails/components/VideoDetails.vue

@@ -3,21 +3,63 @@
 		<h1>{{ resName }}</h1>
 		<div class="user-info-container">
 			<a-card :bordered="false" class="boxShadow cardBox mr-3 flex-3">
-				<div class="video-info">
-					<div style="height: 600px">
-						<div v-if="isImageFile(resSrc)" style="width: 100%; height: 100%">
-							<a-image width="100%" height="100%" :src="fileSrc(resSrc)" :preview="true" />
-						</div>
-						<div v-if="isVideoFile(resSrc)" style="width: 100%; height: 100%">
-							<video :src="fileSrc(resSrc)" controls style="width: 100%; height: 100%" />
-						</div>
-						<div v-if="isDocumentFile(resSrc)" style="width: 100%; height: 100%">
-							<FilePreviewer v-if="resSrc" :fileUrl="fileSrc(resSrc)" :fileName="resName" :fileType="fileType" />
-						</div>
-						<div class="imgBox" v-if="itemData.id && unknownFile">
-							<a-image height="100%" :src="unknownFile" :preview="false" />
-						</div>
+				<!--					<div style="height: 600px">-->
+				<!--						<div v-if="isImageFile(resSrc)" style="width: 100%; height: 100%">-->
+				<!--							<a-image width="100%" height="100%" :src="fileSrc(resSrc)" :preview="true" />-->
+				<!--						</div>-->
+				<!--						<div v-if="isVideoFile(resSrc)" style="width: 100%; height: 100%">-->
+				<!--							<video :src="fileSrc(resSrc)" controls style="width: 100%; height: 100%" />-->
+				<!--						</div>-->
+				<!--						<div v-if="isDocumentFile(resSrc)" style="width: 100%; height: 100%">-->
+				<!--							<FilePreviewer v-if="resSrc" :fileUrl="fileSrc(resSrc)" :fileName="resName" :fileType="fileType" />-->
+				<!--						</div>-->
+				<!--						<div class="imgBox" v-if="itemData.id && unknownFile">-->
+				<!--							<a-image height="100%" :src="unknownFile" :preview="false" />-->
+				<!--						</div>-->
+				<!--					</div>-->
+				<div class="video-info" style="width: 850px">
+					<div
+						v-if="['jpg', 'bmp', 'png', 'jpeg'].includes(videoFormat)"
+						style="width: 850px; height: 350px"
+					>
+						<!-- <img :src="imgs + itemData.coverImagePath" style="width: 100%; height: 100%" /> -->
+						<!-- <img :v-lazy="imagess" style="width: 100%; height: 100%" /> -->
+						<a-image width="850px" height="350px" :src="resSrc" :preview="true"/>
+						<!-- <image :src="resSrc" style="object-fit: cover" /> -->
+					</div>
+					<!-- "wmv","avi","flv","mpeg","mpg","rmvb","mov","mkv" -->
+					<div
+						v-else-if="['mkv', 'mp4', 'wmv', 'avi', 'flv', 'mpeg', 'mpg', 'rmvb', 'mov'].includes(videoFormat)"
+						style="width: 850px; height: 350px"
+					>
+						<video :src="resSrc" controls style="width: 100%; height: 100%"/>
+					</div>
+					<!-- "doc","docx","ppt","pptx","xls","xlsx" -->
+					<div
+						v-else-if="['docx', 'doc', 'ppt', 'pptx', 'xls', 'xlsx', 'pdf'].includes(videoFormat)"
+						style="width: 850px; height: 350px"
+					>
+						<!-- <PDF :src="resSrc" :width="850" :height="350" /> -->
+						<FilePreviewer :fileUrl="resSrc" :fileName="resName" :fileType="fileType"/>
+						<!-- <a-image width="200px" height="220px" :src="pdfRes" :preview="false" @click="handleDownload(resSrc)" /> -->
+						<!-- <a-button type="primary" @click="handleDownload(resSrc)">去预览</a-button> -->
+					</div>
+
+					<div
+						v-else
+						style="width: 850px; height: 350px;	border: 1px solid #dfe2e5; display: flex; justify-content: center; align-items: center"
+					>
+						<span style="display: block">本资源格式不可预览</span>
+						<!-- <PDF :src="resSrc" :width="850" :height="350" /> -->
+						<!-- <a-image width="200px" height="220px" :src="pdfRes" :preview="false" @click="handleDownload(resSrc)" /> -->
+						<!-- <a-button type="primary" @click="handleDownload(resSrc)">去预览</a-button> -->
 					</div>
+					<div class="imgBox" v-if="itemData.id && unknownFile">
+						<a-image height="100%" :src="unknownFile" :preview="false"/>
+					</div>
+					<div style="height: 20px"></div>
+
+
 					<!-- 用户信息部分 -->
 					<div class="user-info" style="display: flex; flex-direction: column">
 						<div style="display: flex; align-items: center; justify-content: space-between; width: 100%">
@@ -52,13 +94,14 @@
 										style="display: flex; align-items: center; cursor: pointer; margin-right: 5px"
 										@click="handlerShareDialog"
 									>
-										<ExportOutlined />
+										<ExportOutlined/>
 										<div style="width: 10px"></div>
 										<button class="share-btn">分享资源</button>
 									</div>
-									<div style="display: flex; align-items: center; cursor: pointer" @click="handlerCollection">
-										<StarOutlined v-if="starTag == false" />
-										<StarFilled v-if="starTag == true" />
+									<div style="display: flex; align-items: center; cursor: pointer"
+										 @click="handlerCollection">
+										<StarOutlined v-if="starTag == false"/>
+										<StarFilled v-if="starTag == true"/>
 										<div style="width: 10px"></div>
 										<button class="favorite-btn">收藏资源</button>
 									</div>
@@ -115,405 +158,419 @@
 </template>
 
 <script setup>
-	import { ref } from 'vue'
-	import { Tag, Typography, Space, message } from 'ant-design-vue'
-	import ShareDialog from './ShareDialog.vue'
-	import { addViewCount, detail, add, cancel, queryList, resourcecentreDetail, getShareLink } from '@/api/portal'
-	import { useRoute, useRouter } from 'vue-router'
-	import sysConfig from '@/config/index'
-	import pdfRes from '@/assets/images/pdf.png'
-	import FilePreviewer from './FilePreviewer.vue'
-	import EventBus from '@/utils/EventBus'
-	import tool from '@/utils/tool'
-	import { isVideoFile, isImageFile, isDocumentFile } from '@/utils/fileUtil'
-	const route = useRoute()
-	const router = useRouter()
-	const props = defineProps({
-		isState: {
-			type: Number,
-			default: () => null
+import {ref} from 'vue'
+import {Tag, Typography, Space, message} from 'ant-design-vue'
+import ShareDialog from './ShareDialog.vue'
+import {addViewCount, detail, add, cancel, queryList, resourcecentreDetail, getShareLink} from '@/api/portal'
+import {useRoute, useRouter} from 'vue-router'
+import sysConfig from '@/config/index'
+import pdfRes from '@/assets/images/pdf.png'
+import FilePreviewer from './FilePreviewer.vue'
+import EventBus from '@/utils/EventBus'
+import tool from '@/utils/tool'
+import {isVideoFile, isImageFile, isDocumentFile} from '@/utils/fileUtil'
+
+const route = useRoute()
+const router = useRouter()
+const props = defineProps({
+	isState: {
+		type: Number,
+		default: () => null
+	}
+})
+const itemData = ref({})
+const starTag = ref(false)
+const ShareDialogRef = ref(null)
+const resSrc = ref('')
+const fileType = ref('')
+const resName = ref('资源名称')
+
+const teacherName = ref('王某某')
+const department = ref('学院本级-航空机务教研室-三级架构名')
+const major = ref('初级飞行训练')
+const courseType = ref('必修')
+const videoFormat = ref('MP4')
+const videoDuration = ref('59:34')
+const videoSize = ref('598M')
+const releaseTime = ref('2025-10-01 11:33:59')
+
+const talkNum = ref(0)
+const collectNum = ref(0)
+
+const tags = ref(['标签名称1', '标签名称2', '标签名称3', '标签名称4', '标签名称5'])
+const emit = defineEmits(['selectTab', 'onGetPageCommentNew'])
+const listUnpublishedView = ref(null)
+const handleDownload = (src) => {
+	window.open(src)
+}
+const handlerShareDialog = () => {
+	getShareLink({id: route.query.id})
+		.then((res) => {
+			if (res.code == 200) {
+				ShareDialogRef.value.open(res.data.shareLink)
+			}
+		})
+		.catch((err) => {
+		})
+}
+const handlerCollection = async () => {
+	const id = route.query.id
+	if (id != undefined && id != '') {
+		if (starTag.value == true) {
+			await cancel({resourceId: id})
+			message.success('取消收藏')
+			upDataDetailsNum()
+		} else {
+			await add({resourceId: id})
+			message.success('收藏成功')
+			upDataDetailsNum()
 		}
-	})
-	const itemData = ref({})
-	const starTag = ref(false)
-	const ShareDialogRef = ref(null)
-	const resSrc = ref('')
-	const fileType = ref('')
-	const resName = ref('资源名称')
-
-	const teacherName = ref('王某某')
-	const department = ref('学院本级-航空机务教研室-三级架构名')
-	const major = ref('初级飞行训练')
-	const courseType = ref('必修')
-	const videoFormat = ref('MP4')
-	const videoDuration = ref('59:34')
-	const videoSize = ref('598M')
-	const releaseTime = ref('2025-10-01 11:33:59')
-
-	const talkNum = ref(0)
-	const collectNum = ref(0)
-
-	const tags = ref(['标签名称1', '标签名称2', '标签名称3', '标签名称4', '标签名称5'])
-	const emit = defineEmits(['selectTab', 'onGetPageCommentNew'])
-	const listUnpublishedView = ref(null)
-	const handleDownload = (src) => {
-		window.open(src)
-	}
-	const handlerShareDialog = () => {
-		getShareLink({ id: route.query.id })
-			.then((res) => {
-				if (res.code == 200) {
-					ShareDialogRef.value.open(res.data.shareLink)
+		queryList({resourceId: id})
+			.then((ress) => {
+				if (ress.data == true) {
+					starTag.value = true
+				} else {
+					starTag.value = false
 				}
 			})
-			.catch((err) => {})
+			.catch((err) => {
+				console.log(err)
+			})
 	}
-	const handlerCollection = async () => {
-		const id = route.query.id
-		if (id != undefined && id != '') {
-			if (starTag.value == true) {
-				await cancel({ resourceId: id })
-				message.success('取消收藏')
-				upDataDetailsNum()
-			} else {
-				await add({ resourceId: id })
-				message.success('收藏成功')
-				upDataDetailsNum()
-			}
-			queryList({ resourceId: id })
-				.then((ress) => {
-					if (ress.data == true) {
-						starTag.value = true
-					} else {
-						starTag.value = false
-					}
+}
+
+const setData = (data) => {
+	itemData.value = data
+}
+const fileSrc = computed(() => (e) => sysConfig.FILE_URL + e)
+const imageUrl = new URL(`@/assets/images/fileImg/file.png`, import.meta.url).href
+const unknownFile = computed((e) => {
+	if (!isImageFile(resSrc.value) && !isVideoFile(resSrc.value) && !isDocumentFile(resSrc.value)) {
+		return imageUrl
+	}
+})
+const getData = (item) => {
+	detail({id: item.id})
+		.then((res) => {
+			if (res.code == 200) {
+				itemData.value = res.data
+				courseType.value = itemData.value.resourceALLTypeName.split(',').join('/')
+				department.value = itemData.value.collegeAllIdName.split(',').join('/')
+				teacherName.value = itemData.value.resourceCreaterUserName
+				resName.value = itemData.value.fileName
+
+				videoFormat.value = itemData.value.suffix
+
+				releaseTime.value = itemData.value.uploadTime
+
+				videoSize.value = itemData.value.FILESIZE ? itemData.value.FILESIZE + 'b' : ''
+
+				tags.value = []
+				itemData.value.keywordList.forEach((item) => {
+					tags.value.push(item.wordName)
 				})
-				.catch((err) => {
-					console.log(err)
-				})
-		}
-	}
-
-	const setData = (data) => {
-		itemData.value = data
-	}
-	const fileSrc = computed(() => (e) => sysConfig.FILE_URL + e)
-	const imageUrl = new URL(`@/assets/images/fileImg/file.png`, import.meta.url).href
-	const unknownFile = computed((e) => {
-		if (!isImageFile(resSrc.value) && !isVideoFile(resSrc.value) && !isDocumentFile(resSrc.value)) {
-			return imageUrl
-		}
-	})
-	const getData = (item) => {
-		detail({ id: item.id })
-			.then((res) => {
-				if (res.code == 200) {
-					itemData.value = res.data
-					courseType.value = itemData.value.resourceALLTypeName.split(',').join('/')
-					department.value = itemData.value.collegeAllIdName.split(',').join('/')
-					teacherName.value = itemData.value.resourceCreaterUserName
-					resName.value = itemData.value.fileName
-
-					videoFormat.value = itemData.value.suffix
-
-					releaseTime.value = itemData.value.uploadTime
-
-					videoSize.value = itemData.value.FILESIZE ? itemData.value.FILESIZE + 'b' : ''
 
-					tags.value = []
-					itemData.value.keywordList.forEach((item) => {
-						tags.value.push(item.wordName)
-					})
+				resSrc.value = itemData.value.priviewFileUrl
+				fileType.value = itemData.value.suffix
 
-					resSrc.value = itemData.value.priviewFileUrl
-					fileType.value = itemData.value.suffix
+				emit('onGetPageCommentNew', {
+					resourceType: itemData.value.resourceType,
+					resourceTwoType: itemData.value.resourceTwoType
+				})
 
-					emit('onGetPageCommentNew', {
-						resourceType: itemData.value.resourceType,
-						resourceTwoType: itemData.value.resourceTwoType
+				const isDump = route.query.isDump
+				const id = route.query.id
+				const resourceInfo = itemData.value
+				if (isDump == 1) {
+					coursestudentburialpoint({
+						userFileId: resourceInfo.id, //文件资源id
+						fileName: resourceInfo.fileName, //文件名称
+						fileId: resourceInfo.fileId, //文件id
+						filePath: resourceInfo.fileUrl, //文件路经
+						funcType: '3', //3
+						type: '5', //5
+						resourceRecord: id //资源记录id
 					})
-
-					const isDump = route.query.isDump
-					const id = route.query.id
-					const resourceInfo = itemData.value
-					if (isDump == 1) {
-						coursestudentburialpoint({
-							userFileId: resourceInfo.id, //文件资源id
-							fileName: resourceInfo.fileName, //文件名称
-							fileId: resourceInfo.fileId, //文件id
-							filePath: resourceInfo.fileUrl, //文件路经
-							funcType: '3', //3
-							type: '5', //5
-							resourceRecord: id //资源记录id
-						})
-					}
 				}
-			})
-			.catch((err) => {})
-	}
+			}
+		})
+		.catch((err) => {
+		})
+}
+
+const upDataList = (item) => {
+	resourcecentreDetail({id: item.id})
+		.then((res) => {
+			if (res.code == 200) {
+				talkNum.value = res.data.commentNum
+				collectNum.value = res.data.collectNum
+			}
+		})
+		.catch((err) => {
+		})
+}
 
-	const upDataList = (item) => {
-		resourcecentreDetail({ id: item.id })
+const fetchData = () => {
+	const id = route.query.id
+	if (id != undefined && id != '') {
+		queryList({resourceId: id})
 			.then((res) => {
-				if (res.code == 200) {
-					talkNum.value = res.data.commentNum
-					collectNum.value = res.data.collectNum
+				if (res.data == true) {
+					starTag.value = true
+				} else {
+					starTag.value = false
 				}
 			})
-			.catch((err) => {})
-	}
-
-	const fetchData = () => {
-		const id = route.query.id
-		if (id != undefined && id != '') {
-			queryList({ resourceId: id })
-				.then((res) => {
-					if (res.data == true) {
-						starTag.value = true
-					} else {
-						starTag.value = false
-					}
-				})
-				.catch((err) => {
-					console.log(err)
-				})
-			getData({ id: id })
-			upDataList({ id: id })
+			.catch((err) => {
+				console.log(err)
+			})
+		getData({id: id})
+		upDataList({id: id})
+	}
+}
+watch(
+	() => route,
+	(newRoute) => {
+		fetchData() // 手动刷新数据的方法
+	},
+	{deep: true, immediate: true}
+)
+onMounted(() => {
+	fetchData()
+})
+
+const upDataDetailsNum = () => {
+	const id = route.query.id
+	if (id != undefined && id != '') {
+		upDataList({id: id})
+	}
+}
+const openResourceDetailsInner = (data) => {
+	router.push({
+		path: '/student/resourceDetails',
+		query: {
+			id: data.id,
+			t: new Date().getTime()
 		}
-	}
-	watch(
-		() => route,
-		(newRoute) => {
-			fetchData() // 手动刷新数据的方法
-		},
-		{ deep: true, immediate: true }
-	)
-	onMounted(() => {
-		fetchData()
 	})
-
-	const upDataDetailsNum = () => {
-		const id = route.query.id
-		if (id != undefined && id != '') {
-			upDataList({ id: id })
-		}
-	}
-	const openResourceDetailsInner = (data) => {
-		router.push({
-			path: '/student/resourceDetails',
-			query: {
-				id: data.id,
-				t: new Date().getTime()
-			}
-		})
-	}
-	defineExpose({
-		setData
-	})
-
-	EventBus.off('upDataDetailsNum', upDataDetailsNum)
-	EventBus.on('upDataDetailsNum', upDataDetailsNum)
-	EventBus.off('openResourceDetailsInner', openResourceDetailsInner)
-	EventBus.on('openResourceDetailsInner', openResourceDetailsInner)
+}
+defineExpose({
+	setData
+})
+
+EventBus.off('upDataDetailsNum', upDataDetailsNum)
+EventBus.on('upDataDetailsNum', upDataDetailsNum)
+EventBus.off('openResourceDetailsInner', openResourceDetailsInner)
+EventBus.on('openResourceDetailsInner', openResourceDetailsInner)
 </script>
 
 <style scoped>
-	.tab-switcher {
-		display: flex;
-		border-radius: 20px;
-		border: 1px solid #1e90ff;
-		overflow: hidden;
-	}
-
-	.tab-switcher div {
-		padding: 2px 20px;
-		background-color: #f5f5f5;
-
-		cursor: pointer;
-	}
-
-	.tab-switcher div.active {
-		background-color: #1e90ff;
-		color: white;
-	}
-
-	.user-info {
-		display: flex;
-		align-items: center;
-		width: 100%;
-		padding: 20px;
-	}
-
-	.resource-container {
-		width: 100%;
-		margin: 0 auto;
-		padding: 20px;
-		border: 1px solid #dfe2e5;
-	}
-
-	.user-avatar {
-		width: 40px;
-		height: 40px;
-		background: #1e90ff;
-		border-radius: 50%;
-		margin-right: 10px;
-	}
-
-	.user-details {
-		flex: 1;
-	}
-
-	.user-name {
-		font-size: 13px;
-		font-weight: bold;
-	}
-
-	.publish-time {
-		font-size: 12px;
-		color: #999;
-		margin-top: 5px;
-	}
-
-	.metrics {
-		display: flex;
-		align-items: center;
-		justify-content: center;
-	}
-
-	.metric-item {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		padding-left: 10px;
-		padding-right: 10px;
-	}
-
-	.metric-item span:first-child {
-		font-size: 18px;
-		font-weight: bold;
-	}
-
-	.metric-item span:last-child {
-		font-size: 12px;
-		color: #666;
-	}
-
-	.actions {
-		display: flex;
-	}
-
-	.share-btn,
-	.favorite-btn {
-		background-color: transparent;
-		border: none;
-		cursor: pointer;
-	}
-
-	.course-info {
-		margin-top: 20px;
-		line-height: 1.6;
-		display: flex;
-		width: 100%;
-	}
-
-	.liene {
-		height: 35px;
-		width: 1px;
-		background: #00000018;
-	}
-
-	.resource-container {
-		width: 100%;
-		margin: 0 auto;
-		padding: 20px;
-		border: 1px solid #dfe2e5;
-	}
-
-	h1 {
-		margin-bottom: 20px;
-	}
-
-	.ant-descriptions {
-		margin-top: 20px;
-	}
-
-	.ant-typography-title {
-		margin-top: 20px;
-	}
-
-	.ant-typography-paragraph {
-		margin-top: 10px;
-	}
-
-	.ant-space {
-		margin-top: 10px;
-	}
-	.video-info {
-		height: 100%; /* 确保填满容器高度 */
-		flex: 1;
-	}
-
-	.user-info-container {
-		display: flex;
-		align-items: stretch;
-	}
-
-	.resInfoTitile {
-		width: 5px;
-		height: 20px;
-		background-color: #1e90ff;
-		margin-right: 5px;
-	}
-
-	.tallList {
-		display: flex;
-		flex-direction: column;
-		width: 100%;
-		height: 200px;
-		border: 1px solid #dfe2e5;
-		padding: 20px;
-		margin-top: 10px;
-	}
-
-	.tallListInfo {
-		color: rgba(0, 0, 0, 0.116);
-		font-size: 12px;
-	}
-	.titleBox {
-		display: flex;
-		align-items: center;
-	}
-	.lableBox {
-		display: flex;
-		align-items: center;
-		margin: 16px 0;
-	}
-	.lableName {
-		font-weight: bold;
-		margin-right: 10px;
-	}
-	.lableVal {
-		display: block;
-		width: 200px;
-		margin-left: 6px;
-	}
-	.boxShadow {
-		border: 1px solid rgba(0, 0, 0, 0.04);
-		border-radius: 4px;
-	}
-	:deep(.cardBox .ant-card-body) {
-		padding: 0;
-	}
-	.flex-3 {
-		flex: 3;
-	}
-	.flex-1 {
-		flex: 1;
-	}
-	.imgBox {
-		height: 100%;
-		display: flex;
-		justify-content: center;
-		align-items: center;
-	}
+.tab-switcher {
+	display: flex;
+	border-radius: 20px;
+	border: 1px solid #1e90ff;
+	overflow: hidden;
+}
+
+.tab-switcher div {
+	padding: 2px 20px;
+	background-color: #f5f5f5;
+
+	cursor: pointer;
+}
+
+.tab-switcher div.active {
+	background-color: #1e90ff;
+	color: white;
+}
+
+.user-info {
+	display: flex;
+	align-items: center;
+	width: 100%;
+	padding: 20px;
+}
+
+.resource-container {
+	width: 100%;
+	margin: 0 auto;
+	padding: 20px;
+	border: 1px solid #dfe2e5;
+}
+
+.user-avatar {
+	width: 40px;
+	height: 40px;
+	background: #1e90ff;
+	border-radius: 50%;
+	margin-right: 10px;
+}
+
+.user-details {
+	flex: 1;
+}
+
+.user-name {
+	font-size: 13px;
+	font-weight: bold;
+}
+
+.publish-time {
+	font-size: 12px;
+	color: #999;
+	margin-top: 5px;
+}
+
+.metrics {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.metric-item {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	padding-left: 10px;
+	padding-right: 10px;
+}
+
+.metric-item span:first-child {
+	font-size: 18px;
+	font-weight: bold;
+}
+
+.metric-item span:last-child {
+	font-size: 12px;
+	color: #666;
+}
+
+.actions {
+	display: flex;
+}
+
+.share-btn,
+.favorite-btn {
+	background-color: transparent;
+	border: none;
+	cursor: pointer;
+}
+
+.course-info {
+	margin-top: 20px;
+	line-height: 1.6;
+	display: flex;
+	width: 100%;
+}
+
+.liene {
+	height: 35px;
+	width: 1px;
+	background: #00000018;
+}
+
+.resource-container {
+	width: 100%;
+	margin: 0 auto;
+	padding: 20px;
+	border: 1px solid #dfe2e5;
+}
+
+h1 {
+	margin-bottom: 20px;
+}
+
+.ant-descriptions {
+	margin-top: 20px;
+}
+
+.ant-typography-title {
+	margin-top: 20px;
+}
+
+.ant-typography-paragraph {
+	margin-top: 10px;
+}
+
+.ant-space {
+	margin-top: 10px;
+}
+
+.video-info {
+	height: 100%; /* 确保填满容器高度 */
+	flex: 1;
+}
+
+.user-info-container {
+	display: flex;
+	align-items: stretch;
+}
+
+.resInfoTitile {
+	width: 5px;
+	height: 20px;
+	background-color: #1e90ff;
+	margin-right: 5px;
+}
+
+.tallList {
+	display: flex;
+	flex-direction: column;
+	width: 100%;
+	height: 200px;
+	border: 1px solid #dfe2e5;
+	padding: 20px;
+	margin-top: 10px;
+}
+
+.tallListInfo {
+	color: rgba(0, 0, 0, 0.116);
+	font-size: 12px;
+}
+
+.titleBox {
+	display: flex;
+	align-items: center;
+}
+
+.lableBox {
+	display: flex;
+	align-items: center;
+	margin: 16px 0;
+}
+
+.lableName {
+	font-weight: bold;
+	margin-right: 10px;
+}
+
+.lableVal {
+	display: block;
+	width: 200px;
+	margin-left: 6px;
+}
+
+.boxShadow {
+	border: 1px solid rgba(0, 0, 0, 0.04);
+	border-radius: 4px;
+}
+
+:deep(.cardBox .ant-card-body) {
+	padding: 0;
+}
+
+.flex-3 {
+	flex: 3;
+}
+
+.flex-1 {
+	flex: 1;
+}
+
+.imgBox {
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
 </style>