Browse Source

Merge branch 'dev' of http://192.168.1.245:11111/shanming/onlineEducation-front into dev

zhangsq 8 tháng trước cách đây
mục cha
commit
c5b9a3d0b2

+ 1 - 1
.env.development

@@ -8,7 +8,7 @@ VITE_TITLE = Snowy
 # VITE_API_BASEURL = http://192.168.31.14:9003
 VITE_API_BASEURL = http://192.168.31.81:9003
 VITE_FILEURL = http://192.168.1.245:10005/education/
-# VITE_API_BASEURL = http://192.168.31.14:9003
+VITE_API_BASEURL = http://192.168.31.14:9003
 # VITE_API_BASEURL = http://192.168.31.6:9003
 
 # 本地端口

+ 1 - 0
.gitignore

@@ -1 +1,2 @@
 /node_modules
+/package-lock.json

+ 1 - 1
pnpm-lock.yaml

@@ -5112,7 +5112,7 @@ snapshots:
     dependencies:
       is-arguments: 1.2.0
       is-date-object: 1.1.0
-      is-regex: 1.1.4
+      is-regex: 1.2.1
       object-is: 1.1.6
       object-keys: 1.1.1
       regexp.prototype.flags: 1.5.4

+ 10 - 0
src/api/myFavorites/index.js

@@ -0,0 +1,10 @@
+import { baseRequest } from '@/utils/newRequest'
+
+const request = (url, ...arg) => baseRequest(`/api/webapp/` + url, ...arg)
+
+export default {
+	// 获取资管理审核括列表
+	page(data) {
+		return request('/disk/collect/selectPageList', data, 'get')
+	}
+}

+ 4 - 0
src/api/portal/index.js

@@ -31,3 +31,7 @@ export const deleteComment = (p) => request('disk/comment/delete', p, 'post')
 export const pageComment = (p) => request('disk/comment/page', p, 'get')
 //点赞
 export const giveComment = (p) => request('disk/comment/give', p, 'get')
+//取消点赞
+export const giveCancelComment = (p) => request('disk/comment/giveCancel', p, 'get')
+//资源中心的详情
+export const resourcecentreDetail = (p) => request('disk/resourcecentre/detail', p, 'get')

+ 3 - 3
src/router/portal.js

@@ -29,19 +29,19 @@ const portal = [
 	{
 		name: 'portal',
 		path: '/portal',
-		component: () => import('@/portal/index.vue'),
+		component: () => import('@/views/portal/index.vue'),
 		children: [
 			{
 				name: 'portal.resourceCenter',
 				path: '/portal/resourceCenter',
 				hide: true,
-				component: () => import('@/resourceCenter/index.vue')
+				component: () => import('@/views/resourceCenter/index.vue')
 			},
 			{
 				name: 'portal.resourceDetails',
 				path: '/portal/resourceDetails',
 				hide: true,
-				component: () => import('@/resourceDetails/index.vue')
+				component: () => import('@/views/resourceDetails/index.vue')
 			},
 			{
 				name: 'portal.personalResources',

+ 643 - 7
src/views/myFavorites/index.vue

@@ -1,16 +1,652 @@
 <template>
-	<div class="page-container">
-		<!-- 页面内容将放在这里 -->
-		<span>我的收藏</span>
-	</div>
+	<a-card>
+		<!-- 搜索和操作区域 -->
+		<a-row :gutter="16" style="margin-bottom: 16px">
+			<a-col :span="18">
+				<a-input v-model:value="formState.fileName" placeholder="请输入资源名称" style="width: 150px" />
+				<a-button type="primary" style="margin-left: 8px" @click="handleSearch">查询</a-button>
+				<a-button style="margin-left: 8px" @click="handleReset">重置</a-button>
+			</a-col>
+		</a-row>
+
+		<!-- 表格 -->
+		<a-table
+			:columns="currentColumns"
+			:data-source="dataSource"
+			:pagination="false"
+			:loading="loading"
+			bordered
+			:row-key="(record) => record.id"
+			:row-selection="rowSelection"
+		>
+			<template #bodyCell="{ column, text, record }">
+				<template
+					v-if="
+						['fileName', 'collegeIdName', 'majorIdName', 'resourceTypeName', 'suffix', 'uploadTime'].includes(
+							column.dataIndex
+						)
+					"
+				>
+					<div class="multiLine-ellipsis" :title="text">{{ text || '-' }}</div>
+				</template>
+				<!-- 状态列 -->
+				<template v-if="column.key === 'verifyStatus'">
+					<span v-if="record.verifyStatus === '0'">
+						<a-badge status="processing" text="未发布" />
+					</span>
+					<span v-else-if="record.verifyStatus === 'uploaded'">
+						<a-badge status="success" text="已上传" />
+					</span>
+					<span v-else-if="record.verifyStatus === '1'">
+						<a-badge status="default" text="待审核" />
+					</span>
+					<span v-else-if="record.verifyStatus === '2'">
+						<a-badge status="success" text="已发布" />
+					</span>
+					<span v-else-if="record.verifyStatus === '4'">
+						<a-badge status="error" text="已删除" />
+					</span>
+				</template>
+				<template v-if="column.dataIndex === 'fileUrl'">
+					<!-- 动态图标 + 格式提示 -->
+					<a-tooltip :title="`${record.suffix || '未知'}`">
+						<component
+							:is="fileTypeIcons[record.suffix?.toLowerCase()] || fileTypeIcons['*']"
+							:style="{ fontSize: '24px', color: getIconColor(record.suffix) }"
+						/>
+					</a-tooltip>
+				</template>
+				<!-- 操作列 -->
+				<template v-else-if="column.key === 'action'">
+					<div class="editable-cell">
+						<a  @click="handlePublish(record)">查看</a>
+					</div>
+				</template>
+			</template>
+		</a-table>
+		<div class="dis-flex-sb margin-top">
+			<div>
+				<CustomPagination
+					:total="pagination.total"
+					:current="pagination.pageNum"
+					:pageSize="pagination.pageSize"
+					:showQuickJumper="true"
+					:showSizeChanger="true"
+					:showTotal="(total) => `共 ${total} 条数据`"
+					@change="handlePageChange"
+					@showSizeChange="handlePageSizeChange"
+				/>
+			</div>
+		</div>
+		<!-- 权限树模态框 -->
+		<permissionTree v-if="permissionTreeVisible" @close="permissionTreeVisible = false"></permissionTree>
+		<!-- 审核播放模态框 -->
+		<auditModal
+			v-if="auditModalVisible"
+			:recordData="publishedData"
+			:isAudit="auditState"
+			@confirm="auditConfirm"
+			@close="auditModalVisible = false"
+		></auditModal>
+		<!-- 资源上传模态框 -->
+		<resourceUpload
+			v-if="uploadModalVisible"
+			:isState="isState"
+			:resourcesId="editResourcesId"
+			@close="uploadModalVisible = false"
+			@getList="getList"
+		></resourceUpload>
+		<!-- 发布模态框 -->
+		<releaseModal v-if="releaseVisible" @close="releaseVisible = false" @confirm="releaseConfirm"></releaseModal>
+	</a-card>
 </template>
 
 <script setup>
-	// 这里可以引入所需的逻辑和组件
+	import { useRouter, useRoute } from 'vue-router'
+	import { ref, onMounted } from 'vue'
+	import { DownOutlined } from '@ant-design/icons-vue'
+	import myFavoritesApi from '@/api/myFavorites'
+	import tool from '@/utils/tool'
+	import {
+		FileOutlined,
+		FileImageOutlined,
+		FilePdfOutlined,
+		FileWordOutlined,
+		FileExcelOutlined,
+		FilePptOutlined,
+		FileTextOutlined,
+		FileZipOutlined,
+		PlaySquareOutlined
+	} from '@ant-design/icons-vue'
+	// eslint-disable-next-line vue/no-setup-props-destructure
+	const { pageType } = defineProps({
+		pageType: {
+			type: String,
+			default: () => {}
+		}
+	})
+	const router = useRouter()
+	const fileTypeIcons = {
+		// 图片类
+		jpg: 'FileImageOutlined',
+		jpeg: 'FileImageOutlined',
+		png: 'FileImageOutlined',
+		gif: 'FileImageOutlined',
+
+		// 文档类
+		pdf: 'FilePdfOutlined',
+		ppt: 'FilePptOutlined',
+		pptx: 'FilePptOutlined',
+		doc: 'FileWordOutlined',
+		docx: 'FileWordOutlined',
+		xls: 'FileExcelOutlined',
+		xlsx: 'FileExcelOutlined',
+		txt: 'FileTextOutlined',
+
+		// 视频类
+		mp4: 'PlaySquareOutlined',
+		mov: 'PlaySquareOutlined',
+
+		// 压缩包
+		zip: 'FileZipOutlined',
+		rar: 'FileZipOutlined',
+
+		// 默认图标
+		'*': 'FileOutlined'
+	}
+	// 数据源
+	const dataSource = ref([])
+	//发布按钮状态
+	const releaseVisible = ref(false)
+	const permissionTreeVisible = ref(false) //权限树
+	const auditModalVisible = ref(false) //播放审核
+	const isPublishBulk = ref(false) //是否批量发布
+	const loading = ref(false) // 列表loading
+	const isState = ref(0) //是否是编辑  0:新增 1:编辑
+	const editResourcesId = ref(null) //资源id
+	// 搜索值
+	const searchValue = ref('')
+	//课程类型
+	const courseTypeOptions = tool.dictList('COURSE_TYPE')
+	const suffixTypeOptions = ref([])
+	const pagination = reactive({
+		pageSize: 10,
+		pageNum: 1,
+		total: 0
+	})
+	const formState = reactive({
+		fileName: null,
+		verifyStatus: '0',
+		resourcesId: null,
+		// majorId: null, //专业
+		collegeId: null, //院校一级id
+		collegeTwoId: null, //院校二级id
+		collegeThreeId: null, //院校三级id
+		resourceType: null,
+		suffix: null
+	})
+	// 添加选择状态
+	const majorIdName = ref([])
+	const majorOptions = ref([]) //专业
+	const selectedRowKeys = ref([])
+	const selectedRows = ref([])
+	const publishedData = ref([]) //当前点击数据
+	// 行选择配置
+	const rowSelection = computed(() => {
+		return {
+			selectedRowKeys: selectedRowKeys.value,
+			onChange: (keys, rows) => {
+				selectedRowKeys.value = keys
+				selectedRows.value = rows
+			},
+			onSelectAll: (selected, selectedRows, changeRows) => {
+				if (selected) {
+					// 全选当前页
+					selectedRowKeys.value = dataSource.value.map((item) => item.id)
+					selectedRows.value = dataSource.value
+				} else {
+					// 取消全选
+					selectedRowKeys.value = []
+					selectedRows.value = []
+				}
+			},
+			onSelectInvert: () => {
+				// 反选当前页
+				const allKeys = dataSource.value.map((item) => item.id)
+				const newSelectedKeys = allKeys.filter((key) => !selectedRowKeys.value.includes(key))
+				selectedRowKeys.value = newSelectedKeys
+				selectedRows.value = dataSource.value.filter((item) => newSelectedKeys.includes(item.id))
+			}
+		}
+	})
+	// 列定义
+	const columnsUnpublished = [
+		{
+			title: '资源名称',
+			align: 'center',
+			dataIndex: 'fileName',
+			key: 'fileName'
+		},
+		{
+			title: '资源类型',
+			align: 'center',
+			dataIndex: 'resourceTypeName',
+			key: 'resourceTypeName'
+		},
+		{
+			title: '浏览量',
+			dataIndex: 'viewCount',
+			align: 'center',
+			key: 'viewCount'
+		},
+		{
+			title: '用户名',
+			align: 'center',
+			dataIndex: 'userName',
+			key: 'userName'
+		},
+		{
+			title: '操作',
+			align: 'center',
+			key: 'action'
+		}
+	]
+
+	const columnsPending = [
+		{
+			title: '编号',
+			dataIndex: 'id',
+			align: 'center',
+			key: 'id'
+		},
+		{
+			title: '资源名称',
+			align: 'center',
+			dataIndex: 'fileName',
+			key: 'fileName'
+		},
+		{
+			title: '所属院系',
+			align: 'center',
+			dataIndex: 'collegeAllIdName',
+			key: 'collegeAllIdName'
+		},
+
+		{
+			title: '资源类型',
+			align: 'center',
+			dataIndex: 'resourceTypeName',
+			key: 'resourceTypeName'
+		},
+		{
+			title: '资源格式',
+			align: 'center',
+			dataIndex: 'suffix',
+			key: 'suffix'
+		},
+		{
+			title: '上传时间',
+			align: 'center',
+			dataIndex: 'uploadTime',
+			key: 'uploadTime'
+		},
+		{
+			title: '状态',
+			align: 'center',
+			key: 'verifyStatus'
+		},
+		{
+			title: '资源缩略图',
+			align: 'center',
+			dataIndex: 'fileUrl',
+			key: 'fileUrl'
+		},
+		{
+			title: '操作',
+			align: 'center',
+			key: 'action'
+		}
+	]
+
+	const columnsPublished = [...columnsPending]
+	const columnsRecycle = [...columnsPending]
+	const collegeMajorOptions = ref([]) //院校下拉数据
+	const resourceTypeOptions = ref([]) //资源类型下拉数据
+	const fileformatOptions = ref([]) //资源格式下拉数据
+	const currentColumns = computed(() => {
+		switch (formState.verifyStatus) {
+			case '0':
+				return columnsUnpublished
+			case '1':
+				return columnsPending
+			case '2':
+				return columnsPublished
+			case '3':
+				return columnsPublished
+			case '4':
+				return columnsRecycle
+			default:
+				return []
+		}
+	})
+	const getIconColor = (suffix) => {
+		const type = suffix?.toLowerCase()
+		if (['jpg', 'jpeg', 'png', 'gif'].includes(type)) return '#ff4d4f' // 图片红色
+		if (['pdf'].includes(type)) return '#f5222d' // PDF红色
+		if (['ppt', 'pptx'].includes(type)) return '#fa8c16' // PPT橙色
+		if (['doc', 'docx'].includes(type)) return '#1890ff' // Word蓝色
+		if (['xls', 'xlsx'].includes(type)) return '#52c41a' // Excel绿色
+		return '#666' // 默认灰色
+	}
+	const getListData = () => {
+		loading.value = true
+		let params = {
+			current: pagination.pageNum,
+			size: pagination.pageSize,
+			fileName: formState.fileName
+		};
+		myFavoritesApi
+			.page(params)
+			.then((res) => {
+				dataSource.value = res.data.records
+				pagination.total = res.data.total
+				loading.value = false
+			})
+			.catch((err) => {
+				console.log(err)
+				dataSource.value = []
+				pagination.total = 0
+				loading.value = false
+			})
+	}
+	const changeCollegeMajor = (value, selectedOptions) => {
+		console.log('Selected:', value, selectedOptions)
+		majorIdName.value = selectedOptions.map((it) => it.name).join('/')
+		formState.collegeId = value[0] || null
+		formState.collegeTwoId = value[1] || null
+		formState.collegeThreeId = value[2] || null
+		if (selectedOptions.length) {
+			// 获取选中的最后一级
+			const lastSelected = selectedOptions[selectedOptions.length - 1]
+			console.log(lastSelected, '最后一级id')
+			getCollegeMajor(lastSelected.id)
+		}
+	}
+	const getList = () => {
+		getListData()
+		uploadModalVisible.value = false
+	}
+
+	// 方法
+	const handleSearch = () => {
+		console.log('Search:', searchValue.value)
+		getListData()
+	}
+
+	const handleReset = () => {
+		searchValue.value = null
+		majorIdName.value = null
+		formState.fileName = null
+		formState.resourceType = null
+		formState.suffix = null
+		formState.collegeTwoId = null
+		// formState.majorId = null
+		formState.collegeId = null
+		formState.collegeThreeId = null
+		getListData()
+	}
+	const tabChange = () => {
+		dataSource.value = []
+		getListData()
+	}
+	//发布
+	const handlePublish = (record) => {
+		publishedData.value = record;
+		router.push({
+			path: '/portal/resourceDetails',
+			query: {
+				id: record.resourceId
+			}
+		})
+	}
+	// 批量发布方法
+	const batchPublish = () => {
+		if (selectedRows.value.length === 0) {
+			message.warning('请至少选择一条记录')
+			return
+		}
+		isState.value = 0
+		isPublishBulk.value = true
+		releaseVisible.value = true
+	}
+	// 全选当前页数据
+	const selectAll = () => {
+		selectedRowKeys.value = dataSource.value.map((item) => item.id)
+		selectedRows.value = dataSource.value
+	}
+
+	// 反选当前页数据
+	const invertSelection = () => {
+		const allKeys = dataSource.value.map((item) => item.id)
+		const newSelectedKeys = allKeys.filter((key) => !selectedRowKeys.value.includes(key))
+		selectedRowKeys.value = newSelectedKeys
+		selectedRows.value = dataSource.value.filter((item) => newSelectedKeys.includes(item.id))
+	}
+	//发布确定
+	const releaseConfirm = (obj) => {
+		console.log(obj, selectedRows.value, '传回来的数据')
+		releaseVisible.value = false
+		if (isPublishBulk.value) {
+			// const batchParams = selectedRows.value.map((item) => ({
+			// 	id: item.id,
+			// 	coverImage: item.coverImage,
+			// 	resourceDesc: item.resourceDesc,
+			// 	verifyStatus: 1
+			// }))
+			const params = {
+				ids: selectedRows.value.map((item) => item.id).join(','),
+				coverImage: obj.coverImageId,
+				resourceDesc: obj.resourceDesc,
+				verifyStatus: 1
+			}
+			console.log(params, '批量发布参数')
+			// handleRelease(params)
+		} else {
+			const params = {
+				ids: publishedData.value.id,
+				coverImage: obj.coverImageId,
+				resourceDesc: obj.resourceDesc,
+				verifyStatus: 1
+			}
+			console.log(params, '发布参数')
+			handleRelease(params)
+		}
+	}
+	// updateStatus接口调用
+	const handleRelease = (Params) => {
+		resourceAuditApi
+			.updateStatus(Params)
+			.then((res) => {
+				getListData()
+				selectedRowKeys.value = []
+			})
+			.catch((err) => {
+				console.error(err)
+			})
+	}
+	const auditState = ref(null)
+	const handleAudit = (record) => {
+		console.log('Audit:', record)
+		publishedData.value = record
+		auditState.value = true
+		auditModalVisible.value = true
+	}
+	const handleView = (record) => {
+		publishedData.value = record
+		auditState.value = false
+		auditModalVisible.value = true
+	}
+	const handleDownload = (record) => {
+		resourceAuditApi
+			.downloadfile({
+				userFileId: record.fileId,
+				shareBatchNum: record.shareBatchNum == null ? '' : record.shareBatchNum,
+				extractionCode: record.extractionCode == null ? '' : record.extractionCode,
+				admin: true
+			})
+			.then((res) => {
+				console.log('下载成功:', res)
+				// 创建Blob对象
+				const url = window.URL.createObjectURL(new Blob([res]))
+				const link = document.createElement('a')
+				link.href = url
+				link.download = record.fileName || `file_${record.id}.${record.suffix}`
+				document.body.appendChild(link)
+				link.click()
+				window.URL.revokeObjectURL(url)
+				document.body.removeChild(link)
+			})
+			.catch((err) => {
+				console.error(err)
+			})
+	}
+
+	const handlePermission = (record) => {
+		console.log('Permission:', record)
+		permissionTreeVisible.value = true
+	}
+	const auditConfirm = (obj) => {
+		console.log('auditConfirm:', obj)
+		const params = {
+			ids: obj.id,
+			verifyStatus: obj.auditResult
+		}
+		resourceAuditApi
+			.updateStatus(params)
+			.then((res) => {
+				if (res.code == 200) {
+					auditModalVisible.value = false
+				}
+				getListData()
+			})
+			.catch((err) => {
+				console.error(err)
+			})
+	}
+
+	const handleDelete = (record) => {
+		console.log('Delete:', record)
+	}
+	const handleRestore = (record) => {
+		const params = {
+			ids: record.id,
+			verifyStatus: 0
+		}
+		resourceAuditApi
+			.updateStatus(params)
+			.then((res) => {
+				getListData()
+			})
+			.catch((err) => {
+				console.error(err)
+			})
+	}
+	//资源编辑
+	const edit = (record) => {
+		console.log('Restore:', record)
+		uploadModalVisible.value = true
+		isState.value = 1
+		editResourcesId.value = record.id
+	}
+	//资源删除
+	const resourcesDelete = (record) => {
+		if (formState.verifyStatus == 4) {
+			const params = [
+				{
+					id: record.id
+				}
+			]
+			resourceAuditApi
+				.deletefile(params)
+				.then((res) => {
+					getListData()
+				})
+				.catch((err) => {
+					console.error(err)
+				})
+		} else {
+			const params = {
+				ids: record.id,
+				verifyStatus: 4
+			}
+			resourceAuditApi
+				.updateStatus(params)
+				.then((res) => {
+					getListData()
+				})
+				.catch((err) => {
+					console.error(err)
+				})
+		}
+	}
+
+	// 上传资源模态框
+	const uploadModalVisible = ref(false)
+
+	// 显示上传模态框
+	const showUploadModal = () => {
+		isState.value = 0
+		uploadModalVisible.value = true
+	}
+	// 翻页
+	const handlePageChange = (page) => {
+		pagination.pageNum = page
+		getListData()
+	}
+	// 每页条数
+	const handlePageSizeChange = (pageNum, size) => {
+		pagination.pageNum = 1
+		pagination.pageSize = size
+		getListData()
+	}
+
+	onMounted(() => {
+		// if (pageType == 'economize') {
+		// 	formState.verifyStatus = '1'
+		// }
+	//	getFileformat()
+	//	getResourceTypeTree()
+		getListData()
+	})
 </script>
 
 <style scoped>
-	.page-container {
-		padding: 20px;
+	.editable-cell {
+		position: relative;
+	}
+
+	.ant-dropdown-link {
+		margin-left: 8px;
+	}
+
+	.upload-area {
+		border: 2px dashed #3ca9f5;
+		padding: 40px;
+		text-align: center;
+	}
+
+	.upload-area p {
+		margin: 10px 0;
+	}
+
+	.file-item {
+		display: flex;
+		align-items: center;
+		margin: 10px 0;
+	}
+
+	.file-item .ant-progress {
+		flex: 1;
+		margin: 0 10px;
 	}
 </style>

+ 0 - 2
src/views/portal/index.vue

@@ -62,8 +62,6 @@
 		// 	images.value = 'http://192.168.1.245:10005/education/2025/7/2/1940361083973906434.jpg'
 		// }, 10000)
 	})
-	EventBus.off('openResourceDetails', handleOpenResourceDetails)
-	EventBus.on('openResourceDetails', handleOpenResourceDetails)
 </script>
 
 <style scoped>

+ 42 - 6
src/views/resourceCenter/components/ResourceList.vue

@@ -12,7 +12,7 @@
 
 			<a-input-search
 				v-model:value="currentPage.queryInfo"
-				placeholder="输入资源关键词"
+				placeholder="输入资源关键词"
 				style="width: 200px"
 				@search="onSearch"
 			/>
@@ -21,8 +21,21 @@
 			<a-col :span="8" v-for="(item, index) in resources" :key="index">
 				<div style="border-radius: 10px 10px 5px 5px; border: 1px solid #dcdcdc">
 					<div style="display: flex; position: relative">
-						<div class="resource" @click="handleItem(item)">
-							<a-image
+						<div
+							class="resource"
+							@click="handleItem(item)"
+							:style="{
+								backgroundSize: 'cover',
+								backgroundPosition: 'center',
+								backgroundImage:
+									'url(' +
+									(item.coverImagePath != '' && sysConfig.FILE_URL + item.coverImagePath
+										? sysConfig.FILE_URL + item.coverImagePath
+										: '') +
+									')'
+							}"
+						>
+							<!-- <a-image
 								style="width: 100%; height: 100%"
 								:src="
 									item.coverImagePath != '' && sysConfig.FILE_URL + item.coverImagePath
@@ -31,7 +44,7 @@
 								"
 								alt=""
 								:preview="false"
-							></a-image>
+							></a-image> -->
 							<PlayCircleOutlined
 								:style="{ fontSize: '40px', color: 'white' }"
 								style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%)"
@@ -219,8 +232,31 @@
 		justify-content: center;
 		align-items: center;
 		cursor: pointer;
+		position: relative;
+		overflow: hidden;
+	}
+	.resource::before {
+		content: '';
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		background-color: transparent;
+		transition: background-color 0.6s ease;
+		z-index: 1;
 	}
-	.resource:hover {
-		background: #0000008c;
+
+	.resource:hover::before {
+		background-color: rgba(0, 0, 0, 0.4); /* 悬停变暗 */
+	}
+
+	/* 图标或其他内容要放在最上层 */
+	.resource > * {
+		position: relative;
+		z-index: 2;
 	}
+	/* .resource:hover {
+		background-color: #ffffff8c;
+	} */
 </style>

+ 15 - 3
src/views/resourceCenter/components/SidebarRecommend.vue

@@ -3,7 +3,19 @@
 		<div class="recommend-container">
 			<h3>资源推荐</h3>
 			<div v-for="(item, index) in recommendations" :key="index" class="recommend-item" @click="handlerItem(item)">
-				<div class="item"></div>
+				<div
+					class="item"
+					:style="{
+						backgroundSize: 'cover',
+						backgroundPosition: 'center',
+						backgroundImage:
+							'url(' +
+							(item.coverImagePath != '' && sysConfig.FILE_URL + item.coverImagePath
+								? sysConfig.FILE_URL + item.coverImagePath
+								: '') +
+							')'
+					}"
+				></div>
 				<div style="display: flex; flex-direction: column; justify-content: space-between; margin-left: 10px">
 					<span style="font-weight: bold; font-size: 12px; margin-top: 5px">{{ item.fileName }}</span>
 					<div style="display: flex; justify-content: center; align-items: space-between">
@@ -29,6 +41,7 @@
 	const emit = defineEmits(['handlerItem'])
 	import { list } from '@/api/portal'
 	import tool from '@/utils/tool'
+	import sysConfig from '@/config/index'
 	const currentPage = reactive({
 		current: 1,
 		size: 6
@@ -147,8 +160,7 @@
 		color: #666;
 	}
 	.item {
-		width: 100px;
+		min-width: 100px;
 		height: 70px;
-		background-color: rgba(5, 5, 5, 0.219);
 	}
 </style>

+ 31 - 5
src/views/resourceDetails/components/TallItem.vue

@@ -20,8 +20,8 @@
 								<span style="margin-left: 5px">{{ props.item.childSize }}</span>
 							</div>
 							<div style="margin-left: 15px">
-								<!-- <LikeFilled /> -->
-								<LikeOutlined style="cursor: pointer" @click="handerfollw" />
+								<LikeFilled v-if="item.giveNumSelf > 0" style="cursor: pointer" @click="handerfollwDecrease" />
+								<LikeOutlined v-if="item.giveNumSelf == 0" style="cursor: pointer" @click="handerfollw" />
 								<span style="margin-left: 5px">{{ props.item.giveNum }}</span>
 							</div>
 						</div>
@@ -48,8 +48,12 @@
 								<span style="margin-left: 5px">10</span>
 							</div> -->
 								<div style="margin-left: 15px">
-									<!-- <LikeFilled /> -->
-									<LikeOutlined style="cursor: pointer" @click="handerfollwChild(item)" />
+									<LikeFilled
+										v-if="item.giveNumSelf > 0"
+										style="cursor: pointer"
+										@click="handerfollwChildDecrease(item)"
+									/>
+									<LikeOutlined v-if="item.giveNumSelf == 0" style="cursor: pointer" @click="handerfollwChild(item)" />
 									<span style="margin-left: 5px">{{ item.giveNum }}</span>
 								</div>
 							</div>
@@ -74,7 +78,17 @@
 	import { ref } from 'vue'
 	import TabSwitcher from './TabSwitcher.vue'
 	import EventBus from '@/utils/EventBus'
-	import { addViewCount, detail, add, cancel, queryList, pageComment, addComment, giveComment } from '@/api/portal'
+	import {
+		addViewCount,
+		detail,
+		add,
+		cancel,
+		queryList,
+		pageComment,
+		addComment,
+		giveComment,
+		giveCancelComment
+	} from '@/api/portal'
 	const emit = defineEmits(['selectTab'])
 
 	// id: 1,
@@ -111,6 +125,8 @@
 		console.log('查询内容', form)
 		tallTag.value == true ? (tallTag.value = false) : (tallTag.value = true)
 		EventBus.emit('closeInput', null, props.item.id)
+
+		EventBus.emit('upDataDetailsNum')
 		//....
 
 		// listUnpublishedView.value.setData(tableData.value)
@@ -126,10 +142,20 @@
 		await giveComment({ id: props.item.id })
 		EventBus.emit('onGetPageComment')
 	}
+	const handerfollwDecrease = async () => {
+		await giveCancelComment({ id: props.item.id })
+		EventBus.emit('onGetPageComment')
+	}
+	//增加
 	const handerfollwChild = async (item) => {
 		await giveComment({ id: item.id })
 		EventBus.emit('onGetPageComment')
 	}
+	//减少
+	const handerfollwChildDecrease = async (item) => {
+		await giveCancelComment({ id: item.id })
+		EventBus.emit('onGetPageComment')
+	}
 	const handerPublish = () => {
 		tallTag.value = false
 		emit('publish', { resourceId: props.id, id: props.item.id, talk: talk.value })

+ 2 - 1
src/views/resourceDetails/components/TallList.vue

@@ -6,7 +6,7 @@
 				<span class="tallListInfo">文明上网理性发言,请遵守评论服务协议</span>
 			</div>
 			<!-- 切换 -->
-			<div>
+			<div v-if="false">
 				<div style="display: flex">
 					<div style="display: flex; flex-direction: column; margin-left: 10px; margin-right: 10px">
 						<div
@@ -188,6 +188,7 @@
 			.then((res) => {
 				getPageComment()
 				talk.value = ''
+				EventBus.emit('upDataDetailsNum')
 			})
 			.catch((err) => {
 				console.log(err)

+ 38 - 6
src/views/resourceDetails/components/VideoDetails.vue

@@ -5,7 +5,7 @@
 		<div class="user-info-container">
 			<div class="video-info" style="width: 850px">
 				<div
-					v-if="videoFormat == 'jpg' || videoFormat == 'bmp' || videoFormat == 'png' || videoFormat == 'jepg'"
+					v-if="videoFormat == 'jpg' || videoFormat == 'bmp' || videoFormat == 'png' || videoFormat == 'jpeg'"
 					style="width: 850px; height: 350px"
 				>
 					<!-- <img :src="imgs + itemData.coverImagePath" style="width: 100%; height: 100%" /> -->
@@ -45,7 +45,7 @@
 				>
 					<!-- <PDF :src="resSrc" :width="850" :height="350" /> -->
 
-					<a-image width="200px" height="220px" :src="pdf" :preview="false" @click="handleDownload(resSrc)" />
+					<a-image width="200px" height="220px" :src="pdfRes" :preview="false" @click="handleDownload(resSrc)" />
 					<!-- <a-button type="primary" @click="handleDownload(resSrc)">去预览</a-button> -->
 				</div>
 
@@ -69,12 +69,12 @@
 								</div>
 								<div class="liene"></div>
 								<div class="metric-item">
-									<span>1000</span>
+									<span>{{ talkNum }}</span>
 									<span>评论</span>
 								</div>
 								<div class="liene"></div>
 								<div class="metric-item">
-									<span>1000</span>
+									<span>{{ collectNum }}</span>
 									<span>收藏</span>
 								</div>
 							</div>
@@ -164,10 +164,13 @@
 	// import PDF from 'vue-pdf'
 	import { Tag, Typography, Space, message } from 'ant-design-vue'
 	import ShareDialog from './ShareDialog.vue'
-	import { addViewCount, detail, add, cancel, queryList } from '@/api/portal'
+	import { addViewCount, detail, add, cancel, queryList, resourcecentreDetail } from '@/api/portal'
 	import { useRoute } from 'vue-router'
 	import sysConfig from '@/config/index'
-	import pdf from '@/assets/images/pdf.png'
+	import pdfRes from '@/assets/images/pdf.png'
+	import EventBus from '@/utils/EventBus'
+	// import pdfView from 'pdfvuer'
+	// import 'pdfvuer/dist/pdfvuer.css'
 
 	// const props = defineProps({
 	// 	itemData: {
@@ -189,6 +192,9 @@
 	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 courseDescription = ref(
 	// 	'“我们正步入一个数据或许比软件更重要的新时代。——Tim O’ Reilly” 运用数据是精准刻画事物、呈现发展规律的主要手段,分析数据展示规律,把思想变得更精细!——“弹指之间·享受创新”,通过4周学习,你将掌握利用Python语言表示、清洗、统计和展示数据的能力。'
 	// )
@@ -210,9 +216,11 @@
 			if (starTag.value == true) {
 				await cancel({ resourceId: id })
 				message.success('取消收藏')
+				upDataDetailsNum()
 			} else {
 				await add({ resourceId: id })
 				message.success('收藏成功')
+				upDataDetailsNum()
 			}
 			queryList({ resourceId: id })
 				.then((ress) => {
@@ -264,6 +272,19 @@
 			})
 			.catch((err) => {})
 	}
+
+	const upDataList = (item) => {
+		console.log('upDataList', item)
+		resourcecentreDetail({ id: item.id })
+			.then((res) => {
+				if (res.code == 200) {
+					talkNum.value = res.data.commentNum
+					collectNum.value = res.data.collectNum
+				}
+			})
+			.catch((err) => {})
+	}
+
 	onMounted(() => {
 		getList()
 		const id = route.query.id
@@ -280,12 +301,23 @@
 					console.log(err)
 				})
 			getData({ id: id })
+			upDataList({ id: id })
 		}
 	})
 
+	const upDataDetailsNum = () => {
+		const id = route.query.id
+		if (id != undefined && id != '') {
+			upDataList({ id: id })
+		}
+	}
+
 	defineExpose({
 		setData
 	})
+
+	EventBus.off('upDataDetailsNum', upDataDetailsNum)
+	EventBus.on('upDataDetailsNum', upDataDetailsNum)
 </script>
 
 <style scoped>

+ 1 - 1
vite.config.js

@@ -52,7 +52,7 @@ export default defineConfig(({ command, mode }) => {
 			port: envConfig.VITE_PORT,
 			proxy: {
 				'/api': {
-					target: 'http://192.168.31.81:9003',
+					target: 'http://192.168.31.14:9003',
 					ws: false,
 					changeOrigin: true
 					// rewrite: (path) => path.replace(/^\/api/, '')