zhangsq před 8 měsíci
rodič
revize
599f33c444

+ 281 - 0
src/components/customPagination.vue

@@ -0,0 +1,281 @@
+<template>
+	<div class="pagination" v-if="!hideOnSinglePage ? true : total !== 1">
+		<span>{{ showTotal(totalNum) }}</span>
+		<a-button
+			type="link"
+			style="padding: 0; font-size: 14px"
+			:disabled="isDisabled('leftOutLined')"
+			@click="previousPage"
+		>
+			<template #icon><leftOutlined class="icon" /></template>
+		</a-button>
+		<span
+			v-for="pageIndex in pageRangeArr"
+			:title="pageIndex"
+			:key="pageIndex"
+			class="pageIndex"
+			@click="jumpCurrentPage(pageIndex)"
+			:class="{ active: totalNum && pageIndex === currentPage }"
+		>
+			{{ pageIndex }}
+		</span>
+		<a-button type="link" :disabled="isDisabled('rightOutlined')" style="padding: 0; font-size: 14px" @click="nextPage">
+			<template #icon><rightOutlined class="icon" /></template>
+		</a-button>
+		<a-select
+			class="sizeChanger"
+			v-model:value="pageSize"
+			:size="size"
+			@change="handleSizeChange"
+			v-if="isShowSizeChanger"
+		>
+			<a-select-option v-for="item in pageSizeOptions" :key="item"> {{ item }}条/页 </a-select-option>
+		</a-select>
+		<span v-if="totalPage > 1 && showQuickJumper" class="jumpPage"
+			>跳至<a-input
+				v-model:value="inputIndex"
+				:size="size"
+				class="toInputIndex"
+				@blur="() => quickJumpPage(inputIndex)"
+				@keyup.enter="quickJumpPage(inputIndex)"
+			/>页</span
+		>
+	</div>
+</template>
+
+<script setup>
+import { ref, computed, watch } from 'vue'
+import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue'
+const props = defineProps({
+	total: {
+		type: Number,
+		required: true,
+		default: 0
+	},
+	pageSize: {
+		type: Number,
+		default: 10
+	},
+	current: {
+		type: Number,
+		default: 1
+	},
+	pageSizeOptions: {
+		type: Array,
+		default: () => ['10', '20', '30', '40', '50', '200', '500']
+	},
+	showQuickJumper: {
+		type: Boolean,
+		default: false
+	},
+	showSizeChanger: {
+		type: Boolean
+	},
+	hideOnSinglePage: {
+		type: Boolean,
+		default: false
+	},
+	showTotal: {
+		type: Function,
+		default: () => ''
+	},
+	size: {
+		type: String,
+		default: ''
+	}
+})
+
+const emit = defineEmits(['change', 'showSizeChange'])
+const currentPage = ref(props.current)
+const pageSize = ref(String(props.pageSize))
+const totalNum = ref(props.total)
+const inputIndex = ref('')
+const isShowSizeChanger = ref(false)
+
+const pageRangeStart = ref(1)
+
+const isDisabled = (type) => {
+	switch (type) {
+		case 'leftOutLined':
+			return currentPage.value === 1
+		case 'rightOutlined':
+			return currentPage.value === totalPage.value
+		default:
+			break
+	}
+}
+
+const handleSizeChange = (size) => {
+	pageRangeStart.value = 1
+	currentPage.value = 1
+	emit('showSizeChange', currentPage.value, Number(size))
+}
+
+watch(
+	() => props.total,
+	(val) => {
+		totalNum.value = val
+		isShowSizeChanger.value = props.showSizeChanger ? true : val > 50
+	},
+	{ immediate: true }
+)
+
+watch(
+	() => props.pageSize,
+	(val) => {
+		pageSize.value = String(val)
+	}
+)
+
+watch(
+	() => props.current,
+	(val) => {
+		if (val === 1) {
+			quickJumpPage(1)
+		}
+	}
+)
+
+const pageRangeEnd = computed(() => Math.min(pageRangeStart.value + 9, totalPage.value))
+
+const pageRangeArr = computed(() => {
+	const start = pageRangeStart.value
+	const end = pageRangeEnd.value
+	const pages = []
+	for (let i = start; i <= end; i++) {
+		pages.push(i)
+	}
+	return pages
+})
+
+const totalPage = computed(() => {
+	return !totalNum.value ? 1 : Math.ceil(totalNum.value / pageSize.value)
+})
+
+// 点击页码
+const jumpCurrentPage = (page) => {
+	// 不重复请求
+	if (page === currentPage.value) return
+	if (page === totalPage.value) {
+		currentPage.value = page
+		emit('change', currentPage.value)
+	} else {
+		if (page >= 1 && page < totalPage.value) {
+			currentPage.value = page
+			if ((page <= pageRangeStart.value && page !== 1) || page >= pageRangeEnd.value) {
+				pageRangeStart.value = Math.max(1, page - 5)
+			}
+			emit('change', currentPage.value)
+		}
+	}
+}
+// 上一页
+const previousPage = () => {
+	if (currentPage.value > 1) {
+		currentPage.value--
+		if (currentPage.value < pageRangeStart.value) {
+			pageRangeStart.value = Math.max(1, currentPage.value - 5)
+		}
+		emit('change', currentPage.value)
+	}
+}
+// 下一页
+const nextPage = () => {
+	if (currentPage.value < totalPage.value) {
+		currentPage.value++
+		if (currentPage.value > pageRangeEnd.value && currentPage.value !== totalNum.value) {
+			pageRangeStart.value = Math.max(1, currentPage.value - 5)
+		}
+		emit('change', currentPage.value)
+	}
+}
+
+// 快速跳转
+const quickJumpPage = (pageIndex) => {
+	let index = Number(pageIndex)
+	let isInteger = Number.isInteger(index)
+	if (!index || !isInteger) {
+		inputIndex.value = ''
+		return
+	} else {
+		pageRangeStart.value = 1
+		if (index >= 1 && index < totalPage.value) {
+			pageRangeStart.value = Math.max(1, index - 5)
+			currentPage.value = index
+		} else {
+			if (index >= totalPage.value) {
+				if (totalPage.value < 10) {
+					pageRangeStart.value = 1
+				} else {
+					pageRangeStart.value = totalPage.value - (totalPage.value % 10) - 4
+				}
+				currentPage.value = totalPage.value
+			} else if (index < 1) {
+				pageRangeStart.value = 1
+				currentPage.value = 1
+			}
+		}
+		inputIndex.value = ''
+	}
+	emit('change', currentPage.value)
+}
+</script>
+<style  scoped>
+.pagination {
+	user-select: none;
+	display: flex;
+	align-items: center;
+	flex-wrap: wrap;
+}
+.icon {
+	font-size: 12px;
+}
+
+.ant-btn-link {
+	color: #212325;
+	font-size: 12px;
+	&:hover {
+		color: #4458fe;
+	}
+}
+.ant-btn-link[disabled],
+.ant-btn-link[disabled]:hover,
+.ant-btn-link[disabled]:focus,
+.ant-btn-link[disabled]:active {
+	color: rgba(0, 0, 0, 0.25);
+}
+.pagination span.active {
+	color: #4458fe;
+}
+:deep(.ant-select select) {
+	border-radius: 6px;
+}
+.pageIndex {
+	display: inline-block;
+	min-width: 32px;
+	height: 30px;
+	line-height: 30px;
+	text-align: center;
+	cursor: pointer;
+	border-radius: 6px;
+	font-size: 14px;
+	padding: 0 6px;
+}
+.pageIndex:hover {
+	color: #4458fe;
+}
+.sizeChanger {
+	margin-left: 8px;
+}
+.jumpPage {
+	margin-left: 8px;
+}
+.toInputIndex {
+	width: 48px;
+	margin: 0 8px;
+}
+.disabledBgc {
+	color: rgba(0, 0, 0, 0.25);
+	cursor: not-allowed;
+}
+</style>

+ 52 - 11
src/views/InventoryReview/index.vue

@@ -58,10 +58,22 @@
 				</template>
 			</template>
 		</a-table>
+		<a-modal v-model:visible="judgeVisible" title="审核" @ok="handleOk" @cancel="handleCancel">
+			<p style="text-align: center">
+				审核结果:
+				<a-select
+					v-model:value="finalResult"
+					style="width: 100px"
+					:options="classify_results"
+					placeholder="请选择审核结果"
+				>
+				</a-select>
+			</p>
+		</a-modal>
 		<div class="dis-flex-end margin-top">
 			<CustomPagination
 				:total="pagination.total"
-				:current="pagination.current"
+				:current="pagination.pageNum"
 				:pageSize="pagination.pageSize"
 				:showQuickJumper="true"
 				:showSizeChanger="true"
@@ -80,7 +92,9 @@ import CustomPagination from '@/components/customPagination.vue'
 // 状态管理
 const activeKey = ref('pending')
 const loading = ref(false)
-const formState = ref({
+const judgeVisible = ref(false)
+const finalResult = ref(null)
+const formState = reactive({
 	fileName: null,
 	examineStatus: null,
 	orgName: null
@@ -145,27 +159,38 @@ const columns = [
 ]
 
 const dataSource = ref([])
+const classify_results = ref([
+	{ value: '1', label: '通过' },
+	{ value: '0', label: '驳回' }
+])
 
 const pagination = reactive({
 	pageSize: 10,
 	pageNum: 1,
 	total: 0
 })
-
-// 行选择配置
-const rowSelection = ref({
-	selectedRowKeys: [],
-	onChange: (selectedRowKeys) => {
-		rowSelection.value.selectedRowKeys = selectedRowKeys
+//勾选的ID列表
+const selectedRowKeys = ref([])
+//列表勾选
+const rowSelection = computed(() => {
+	return {
+		selectedRowKeys: unref(selectedRowKeys),
+		onChange: onSelectChange,
+		hideDefaultSelections: true
 	}
 })
+//勾选方法
+const onSelectChange = (changaRowKeys) => {
+	selectedRowKeys.value = changaRowKeys
+}
+
 // 翻页
 const handlePageChange = (page) => {
 	pagination.pageNum = page
 	getListData()
 }
 // 每页条数
-const handlePageSizeChange = (current, size) => {
+const handlePageSizeChange = (pageNum, size) => {
 	pagination.pageNum = 1
 	pagination.pageSize = size
 	getListData()
@@ -192,11 +217,27 @@ const getListData = () => {
 // 方法
 const handleSearch = () => {
 	// 处理搜索逻辑
+	getListData()
 }
 
+//批量审批
 const handleBatchApprove = () => {
-	// 处理批量审核逻辑
-	console.log('批量审核:', rowSelection.value.selectedRowKeys)
+	judgeVisible.value = true
+}
+const handleOk = () => {
+	if (!finalResult.value) {
+		message.error('请选择审核类型')
+	}
+	const idList = selectedRowKeys.value
+	const params = []
+	idList.forEach((res) => {
+		params.push({
+			id: res,
+			result: finalResult.value
+		})
+	})
+	loading.value = true
+	return
 }
 
 const handleExportDetails = () => {

+ 435 - 10
src/views/myResources/index.vue

@@ -1,16 +1,441 @@
 <template>
-	<div class="page-container">
-		<!-- 页面内容将放在这里 -->
-		<span>我的资源</span>
-	</div>
+	<a-card>
+		<!-- 标签页 -->
+		<a-tabs v-model:activeKey="activeKey" @change="tabChange">
+			<a-tab-pane key="unpublished" tab="未发布"></a-tab-pane>
+			<a-tab-pane key="pending" tab="待审核"></a-tab-pane>
+			<a-tab-pane key="published" tab="已发布"></a-tab-pane>
+			<a-tab-pane key="recycle" tab="回收站"></a-tab-pane>
+		</a-tabs>
+
+		<!-- 搜索和操作区域 -->
+		<a-row :gutter="16" style="margin-bottom: 16px">
+			<a-col :span="8">
+				<a-input v-model:value="searchValue" placeholder="请输入资源名称" style="width: 200px" />
+				<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-col :span="16" style="text-align: right">
+				<a-button type="primary" @click="showUploadModal">+ 上传资源</a-button>
+			</a-col>
+		</a-row>
+
+		<!-- 表格 -->
+		<a-table
+			:columns="currentColumns"
+			:data-source="currentDataSource"
+			:pagination="false"
+			:row-key="(record) => record.id"
+		>
+			<template #bodyCell="{ column, record }">
+				<!-- 状态列 -->
+				<template v-if="column.key === 'status'">
+					<span v-if="record.status === 'processing'">
+						<a-badge status="processing" text="处理中" />
+					</span>
+					<span v-else-if="record.status === 'uploaded'">
+						<a-badge status="success" text="已上传" />
+					</span>
+					<span v-else-if="record.status === 'pending'">
+						<a-badge status="default" text="待审核" />
+					</span>
+					<span v-else-if="record.status === 'published'">
+						<a-badge status="success" text="已发布" />
+					</span>
+					<span v-else-if="record.status === 'deleted'">
+						<a-badge status="error" text="已删除" />
+					</span>
+				</template>
+
+				<!-- 操作列 -->
+				<template v-else-if="column.key === 'action'">
+					<div class="editable-cell">
+						<template v-if="activeKey === 'unpublished'">
+							<a @click="handlePublish(record)">发布</a>
+							<a-divider type="vertical" />
+							<a-dropdown>
+								<a class="ant-dropdown-link"> 更多 <DownOutlined /> </a>
+								<template #overlay>
+									<a-menu>
+										<a-menu-item>
+											<a href="javascript:;">播放</a>
+										</a-menu-item>
+										<a-menu-item>
+											<a href="javascript:;">下载</a>
+										</a-menu-item>
+										<a-menu-item>
+											<a href="javascript:;">编辑</a>
+										</a-menu-item>
+										<a-menu-item>
+											<a href="javascript:;">删除</a>
+										</a-menu-item>
+									</a-menu>
+								</template>
+							</a-dropdown>
+						</template>
+
+						<template v-else-if="activeKey === 'pending'">
+							<a @click="handleAudit(record)">审核</a>
+							<a-divider type="vertical" />
+							<a-dropdown>
+								<a class="ant-dropdown-link"> 更多 <DownOutlined /> </a>
+								<template #overlay>
+									<a-menu>
+										<a-menu-item>
+											<a href="javascript:;">查看</a>
+										</a-menu-item>
+									</a-menu>
+								</template>
+							</a-dropdown>
+						</template>
+
+						<template v-else-if="activeKey === 'published'">
+							<a @click="handlePermission(record)">权限</a>
+							<a-divider type="vertical" />
+							<a-dropdown>
+								<a class="ant-dropdown-link"> 更多 <DownOutlined /> </a>
+								<template #overlay>
+									<a-menu>
+										<a-menu-item>
+											<a href="javascript:;">查看</a>
+										</a-menu-item>
+										<a-menu-item>
+											<a href="javascript:;">编辑</a>
+										</a-menu-item>
+										<a-menu-item>
+											<a href="javascript:;">删除</a>
+										</a-menu-item>
+									</a-menu>
+								</template>
+							</a-dropdown>
+						</template>
+
+						<template v-else-if="activeKey === 'recycle'">
+							<a @click="handleRestore(record)">恢复</a>
+							<a-divider type="vertical" />
+							<a-dropdown>
+								<a class="ant-dropdown-link"> 更多 <DownOutlined /> </a>
+								<template #overlay>
+									<a-menu>
+										<a-menu-item>
+											<a href="javascript:;">彻底删除</a>
+										</a-menu-item>
+									</a-menu>
+								</template>
+							</a-dropdown>
+						</template>
+					</div>
+				</template>
+			</template>
+		</a-table>
+
+		<!-- 上传资源模态框 -->
+		<a-modal v-model:visible="uploadModalVisible" title="上传资源" @ok="handleUploadOk" @cancel="handleUploadCancel">
+			<a-upload
+				:multiple="true"
+				:before-upload="beforeUpload"
+				:file-list="fileList"
+				:remove="handleRemove"
+				:on-change="handleChange"
+			>
+				<div class="upload-area">
+					<a-icon type="cloud-upload" style="font-size: 60px; color: #3ca9f5"></a-icon>
+					<p>将文件拖到此处或点击上传</p>
+					<p>按住Ctrl可同时多选,支持上传PPT/word/excel/pdf/mp4/zip/rar,单个文件不能超过2G</p>
+				</div>
+			</a-upload>
+
+			<!-- 文件上传状态展示 -->
+			<ul v-if="fileList.length">
+				<li v-for="(file, index) in fileList" :key="index" class="file-item">
+					<span>{{ file.name }}</span>
+					<a-progress :percent="file.percent || 0" />
+					<span v-if="file.status === 'done'">已完成</span>
+					<span v-else-if="file.status === 'error'">上传失败</span>
+					<span v-else-if="file.status === 'uploading'">上传中...</span>
+				</li>
+			</ul>
+		</a-modal>
+		<releaseModal v-if="releaseVisible" @close="releaseVisible = false"></releaseModal>
+	</a-card>
 </template>
 
-<script setup>
-	// 这里可以引入所需的逻辑和组件
-</script>
+  <script setup>
+import { ref } from 'vue'
+import { DownOutlined } from '@ant-design/icons-vue'
+import { Modal, Upload } from 'ant-design-vue'
+import releaseModal from './releaseModal.vue'
+// 数据源
+const dataSource = ref([
+	{
+		id: 1,
+		name: '资源名称资源名称',
+		format: 'mp4',
+		uploadTime: '2020-11-25 23:26:08',
+		status: 'processing', // processing, uploaded, pending, published, deleted
+		department: '航空理论系',
+		major: '商务服务',
+		courseType: '选修'
+	},
+	{
+		id: 2,
+		name: '资源名称资源名称',
+		format: 'mp4',
+		uploadTime: '2020-11-25 23:26:08',
+		status: 'pending', // processing, uploaded, pending, published, deleted
+		department: '航空理论系1',
+		major: '商务服务',
+		courseType: '选修'
+	},
+	{
+		id: 3,
+		name: '资源名称资源名称',
+		format: 'mp4',
+		uploadTime: '2020-11-25 23:26:08',
+		status: 'published', // processing, uploaded, pending, published, deleted
+		department: '航空理论系2',
+		major: '商务服务',
+		courseType: '选修'
+	}
+])
+
+// 当前激活的标签页
+const activeKey = ref('unpublished')
+//发布按钮状态
+const releaseVisible = ref(false)
+
+// 搜索值
+const searchValue = ref('')
 
-<style scoped>
-	.page-container {
-		padding: 20px;
+// 列定义
+const columnsUnpublished = [
+	{
+		title: '编号',
+		dataIndex: 'id',
+		key: 'id'
+	},
+	{
+		title: '资源名称',
+		dataIndex: 'name',
+		key: 'name'
+	},
+	{
+		title: '课件格式',
+		dataIndex: 'format',
+		key: 'format'
+	},
+	{
+		title: '上传时间',
+		dataIndex: 'uploadTime',
+		key: 'uploadTime'
+	},
+	{
+		title: '状态',
+		key: 'status'
+	},
+	{
+		title: '操作',
+		key: 'action'
 	}
+]
+
+const columnsPending = [
+	{
+		title: '编号',
+		dataIndex: 'id',
+		key: 'id'
+	},
+	{
+		title: '资源名称',
+		dataIndex: 'name',
+		key: 'name'
+	},
+	{
+		title: '所属院系',
+		dataIndex: 'department',
+		key: 'department'
+	},
+	{
+		title: '所属专业',
+		dataIndex: 'major',
+		key: 'major'
+	},
+	{
+		title: '课程类型',
+		dataIndex: 'courseType',
+		key: 'courseType'
+	},
+	{
+		title: '课件格式',
+		dataIndex: 'format',
+		key: 'format'
+	},
+	{
+		title: '上传时间',
+		dataIndex: 'uploadTime',
+		key: 'uploadTime'
+	},
+	{
+		title: '状态',
+		key: 'status'
+	},
+	{
+		title: '操作',
+		key: 'action'
+	}
+]
+
+const columnsPublished = [...columnsPending]
+const columnsRecycle = [...columnsPending]
+
+const currentColumns = computed(() => {
+	switch (activeKey.value) {
+		case 'unpublished':
+			return columnsUnpublished
+		case 'pending':
+			return columnsPending
+		case 'published':
+			return columnsPublished
+		case 'recycle':
+			return columnsRecycle
+		default:
+			return []
+	}
+})
+
+const currentDataSource = computed(() => {
+	return dataSource.value.filter((item) => {
+		if (activeKey.value === 'unpublished') {
+			return ['processing', 'uploaded'].includes(item.status)
+		} else if (activeKey.value === 'pending') {
+			return item.status === 'pending'
+		} else if (activeKey.value === 'published') {
+			return item.status === 'published'
+		} else if (activeKey.value === 'recycle') {
+			return item.status === 'deleted'
+		}
+		return false
+	})
+})
+
+// 方法
+const handleSearch = () => {
+	console.log('Search:', searchValue.value)
+}
+
+const handleReset = () => {
+	searchValue.value = ''
+}
+const tabChange = () => {
+	// dataSource.value = []
+}
+
+const handleUpload = () => {
+	console.log('Upload Resource')
+}
+
+const handlePublish = (record) => {
+	console.log('Publish:', record)
+	releaseVisible.value = true
+}
+
+const handleAudit = (record) => {
+	console.log('Audit:', record)
+}
+
+const handlePermission = (record) => {
+	console.log('Permission:', record)
+}
+
+const handleRestore = (record) => {
+	console.log('Restore:', record)
+}
+
+// 上传资源模态框
+const uploadModalVisible = ref(false)
+
+// 文件列表
+const fileList = ref([])
+
+// 显示上传模态框
+const showUploadModal = () => {
+	uploadModalVisible.value = true
+}
+
+// 关闭模态框
+const handleUploadCancel = () => {
+	uploadModalVisible.value = false
+	fileList.value = []
+}
+
+// 确认上传
+const handleUploadOk = () => {
+	// 这里可以添加实际的上传逻辑
+	console.log('Upload confirmed:', fileList.value)
+	uploadModalVisible.value = false
+	fileList.value = []
+}
+
+// 上传前的钩子函数
+const beforeUpload = (file) => {
+	const isLt2G = file.size / 1024 / 1024 / 1024 < 2
+	if (!isLt2G) {
+		Modal.error({ content: '文件大小不能超过 2GB!' })
+	}
+	return isLt2G
+}
+
+// 移除文件
+const handleRemove = (file) => {
+	const index = fileList.value.indexOf(file)
+	const newFileList = fileList.value.slice()
+	newFileList.splice(index, 1)
+	fileList.value = newFileList
+}
+
+// 文件状态改变时的处理函数
+const handleChange = ({ file, fileList: newFileList }) => {
+	fileList.value = newFileList
+
+	if (file.status === 'uploading') {
+		file.percent = 0
+	}
+
+	if (file.status === 'done') {
+		Modal.success({ content: '文件上传成功' })
+	} else if (file.status === 'error') {
+		Modal.error({ content: '文件上传失败' })
+	}
+}
+</script>
+
+  <style scoped>
+.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>

+ 156 - 0
src/views/myResources/releaseModal.vue

@@ -0,0 +1,156 @@
+<template>
+	<!-- 上传资源模态框 -->
+	<a-modal v-model:visible="uploadModalVisible" title="上传资源" @ok="handleUploadOk" @cancel="handleUploadCancel">
+		<a-form :model="uploadForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+			<a-form-item label="资源名称" name="resourceName">
+				<a-input v-model:value="uploadForm.resourceName" placeholder="请输入资源名称" />
+			</a-form-item>
+
+			<a-form-item label="资源类型" name="resourceType">
+				<a-select v-model:value="uploadForm.resourceType" placeholder="请选择资源类型">
+					<a-select-option value="type1">类型1</a-select-option>
+					<a-select-option value="type2">类型2</a-select-option>
+					<!-- 其他选项 -->
+				</a-select>
+			</a-form-item>
+
+			<a-form-item label="课程名称" name="courseName">
+				<a-input v-model:value="uploadForm.courseName" placeholder="请输入课程名称" />
+			</a-form-item>
+
+			<a-form-item label="课程介绍" name="courseDescription">
+				<a-textarea v-model:value="uploadForm.courseDescription" placeholder="请输入课程介绍" :rows="4" />
+			</a-form-item>
+
+			<a-form-item label="上传封面" name="coverImage">
+				<a-upload
+					:before-upload="beforeUploadCover"
+					:file-list="coverFileList"
+					:remove="handleRemoveCover"
+					:on-change="handleChangeCover"
+					list-type="picture-card"
+				>
+					<div v-if="coverFileList.length < 1">
+						<plus-outlined />
+						<div class="ant-upload-text">上传图片</div>
+					</div>
+				</a-upload>
+			</a-form-item>
+		</a-form>
+
+		<!-- 文件上传状态展示 -->
+		<ul v-if="fileList.length">
+			<li v-for="(file, index) in fileList" :key="index" class="file-item">
+				<span>{{ file.name }}</span>
+				<a-progress :percent="file.percent || 0" />
+				<span v-if="file.status === 'done'">已完成</span>
+				<span v-else-if="file.status === 'error'">上传失败</span>
+				<span v-else-if="file.status === 'uploading'">上传中...</span>
+			</li>
+		</ul>
+	</a-modal>
+</template>
+<script setup>
+import { ref, reactive } from 'vue'
+import { Modal, Upload } from 'ant-design-vue'
+import { PlusOutlined } from '@ant-design/icons-vue'
+const emit = defineEmits(['close'])
+// 表单数据
+const uploadForm = reactive({
+	resourceName: '',
+	resourceType: '',
+	courseName: '',
+	courseDescription: '',
+	coverImage: ''
+})
+
+// 封面文件列表
+const coverFileList = ref([])
+const fileList = ref([])
+
+const uploadModalVisible = ref(true)
+
+// 显示上传模态框
+// const showUploadModal = () => {
+// 	uploadModalVisible.value = true
+// }
+
+// 关闭模态框
+const handleUploadCancel = () => {
+	uploadModalVisible.value = false
+	Object.assign(uploadForm, {
+		resourceName: '',
+		resourceType: '',
+		courseName: '',
+		courseDescription: '',
+		coverImage: ''
+	})
+	fileList.value = []
+	coverFileList.value = []
+	emit('close')
+}
+
+// 确认上传
+const handleUploadOk = () => {
+	// 这里可以添加实际的上传逻辑
+	console.log('Upload confirmed:', uploadForm, fileList.value, coverFileList.value)
+	uploadModalVisible.value = false
+	Object.assign(uploadForm, {
+		resourceName: '',
+		resourceType: '',
+		courseName: '',
+		courseDescription: '',
+		coverImage: ''
+	})
+	fileList.value = []
+	coverFileList.value = []
+}
+
+// 上传封面前的钩子函数
+const beforeUploadCover = (file) => {
+	const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
+	if (!isJpgOrPng) {
+		Modal.error({ content: '仅支持上传jpg/png格式文件!' })
+	}
+	const isLt500K = file.size / 1024 < 500
+	if (!isLt500K) {
+		Modal.error({ content: '单个文件不能超过500kb!' })
+	}
+	return isJpgOrPng && isLt500K
+}
+
+// 移除封面文件
+const handleRemoveCover = (file) => {
+	const index = coverFileList.value.indexOf(file)
+	const newFileList = coverFileList.value.slice()
+	newFileList.splice(index, 1)
+	coverFileList.value = newFileList
+}
+
+// 封面文件状态改变时的处理函数
+const handleChangeCover = ({ file, fileList: newFileList }) => {
+	coverFileList.value = newFileList
+}
+</script>
+<style scoped>
+.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>

+ 238 - 9
src/views/taskProgress/index.vue

@@ -1,16 +1,245 @@
 <template>
-	<div class="page-container">
-		<!-- 页面内容将放在这里 -->
-		<span>我的智商</span>
+	<div class="resource-page">
+		<!-- 筛选条件区域 -->
+		<a-card title="筛选条件" :bordered="false">
+			<!-- 院系选择 -->
+			<div class="filter-group">
+				<span class="filter-label">所选院系:</span>
+				<a-radio-group v-model:value="selectedDepartment" button-style="solid">
+					<a-radio-button value="全部">全部</a-radio-button>
+					<a-radio-button value="航空理论系">航空理论系</a-radio-button>
+					<!-- 更多选项 -->
+				</a-radio-group>
+				<a-link style="float: right" @click="toggleDepartmentOptions">{{
+					isDepartmentExpanded ? '收起' : '展开'
+				}}</a-link>
+			</div>
+			<div v-if="isDepartmentExpanded" class="expanded-options">
+				<a-radio-button value="军事理论系">军事理论系</a-radio-button>
+				<a-radio-button value="政治工作系">政治工作系</a-radio-button>
+				<a-radio-button value="机务工程系">机务工程系</a-radio-button>
+				<a-radio-button value="航空机务系">航空机务系</a-radio-button>
+			</div>
+
+			<!-- 课程选择 -->
+			<div class="filter-group" style="margin-top: 16px">
+				<span class="filter-label">所选课程:</span>
+				<a-radio-group v-model:value="selectedCourse" button-style="solid">
+					<a-radio-button value="全部">全部</a-radio-button>
+					<a-radio-button value="初级飞行训练">初级飞行训练</a-radio-button>
+					<!-- 更多选项 -->
+				</a-radio-group>
+				<a-link style="float: right" @click="toggleCourseOptions">{{ isCourseExpanded ? '收起' : '展开' }}</a-link>
+			</div>
+			<div v-if="isCourseExpanded" class="expanded-options">
+				<a-radio-button value="高级飞行训练">高级飞行训练</a-radio-button>
+				<a-radio-button value="实弹训练">实弹训练</a-radio-button>
+				<a-radio-button value="低空战术飞行">低空战术飞行</a-radio-button>
+				<!-- 更多选项 -->
+			</div>
+
+			<!-- 课程类型选择 -->
+			<div class="filter-group" style="margin-top: 16px">
+				<span class="filter-label">课程类型:</span>
+				<a-radio-group v-model:value="selectedCourseType" button-style="solid">
+					<a-radio-button value="全部">全部</a-radio-button>
+					<a-radio-button value="热门资源">热门资源</a-radio-button>
+					<!-- 更多选项 -->
+				</a-radio-group>
+				<a-link style="float: right" @click="toggleCourseTypeOptions">{{
+					isCourseTypeExpanded ? '收起' : '展开'
+				}}</a-link>
+			</div>
+
+			<!-- 课件格式选择 -->
+			<div class="filter-group" style="margin-top: 16px">
+				<span class="filter-label">课件格式:</span>
+				<a-radio-group v-model:value="selectedFileType" button-style="solid">
+					<a-radio-button value="全部">全部</a-radio-button>
+					<a-radio-button value="ppt">PPT</a-radio-button>
+					<!-- 更多选项 -->
+				</a-radio-group>
+				<a-link style="float: right" @click="toggleFileTypeOptions">{{ isFileTypeExpanded ? '收起' : '展开' }}</a-link>
+			</div>
+			<div v-if="isFileTypeExpanded" class="expanded-options">
+				<a-radio-button value="word">Word</a-radio-button>
+				<a-radio-button value="excel">Excel</a-radio-button>
+				<a-radio-button value="pdf">PDF</a-radio-button>
+				<!-- 更多选项 -->
+			</div>
+
+			<!-- 已选条件展示 -->
+			<div style="margin-top: 20px">
+				已选条件:
+				<a-tag closable v-for="tag in selectedTags" :key="tag" @close="handleTagClose(tag)">
+					{{ tag }}
+				</a-tag>
+				<a-link style="margin-left: 10px" @click="clearFilters">清除筛选</a-link>
+			</div>
+		</a-card>
+
+		<!-- 资源列表区域 -->
+		<a-row :gutter="16" style="margin-top: 20px">
+			<a-col :span="18">
+				<div style="display: flex; align-items: center; margin-bottom: 16px">
+					<span>共计 {{ filteredResources.length }} 个资源</span>
+					<a-button type="primary" style="margin-left: 16px">最新</a-button>
+					<a-button style="margin-left: 8px">热门</a-button>
+					<a-input-search placeholder="输入资源关键词" style="margin-left: auto; width: 300px" @search="onSearch" />
+				</div>
+				<a-row :gutter="16">
+					<a-col :span="8" v-for="(resource, index) in filteredResources" :key="index">
+						<a-card :title="resource.title" style="margin-bottom: 16px">
+							<template #cover>
+								<img alt="example" :src="resource.cover" style="height: 150px" />
+							</template>
+							<p>{{ resource.description }}</p>
+							<p>来源学校: {{ resource.school }}</p>
+							<p>姓名: {{ resource.author }}</p>
+							<p>日期: {{ resource.date }}</p>
+							<p>观看次数: {{ resource.views }}</p>
+						</a-card>
+					</a-col>
+				</a-row>
+			</a-col>
+			<a-col :span="6">
+				<a-card title="资源推荐" style="margin-bottom: 16px">
+					<a-list item-layout="horizontal" :data-source="recommendedResources">
+						<template #renderItem="{ item }">
+							<a-list-item>
+								<a-list-item-meta>
+									<template #avatar>
+										<a-avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
+									</template>
+									<template #title>
+										<a href="https://www.antgroup.com">{{ item.title }}</a>
+									</template>
+									<template #description>
+										<span>发布日期: {{ item.date }}</span>
+										<span style="margin-left: 20px">观看次数: {{ item.views }}</span>
+									</template>
+								</a-list-item-meta>
+							</a-list-item>
+						</template>
+					</a-list>
+				</a-card>
+			</a-col>
+		</a-row>
 	</div>
 </template>
 
-<script setup>
-	// 这里可以引入所需的逻辑和组件
-</script>
+  <script setup>
+import { ref, computed, watch } from 'vue'
 
-<style scoped>
-	.page-container {
-		padding: 20px;
+// 模拟数据
+const resources = [
+	{
+		title: '学术交流英语',
+		description: '学术交流英语描述',
+		school: '来源学校',
+		author: '姓名',
+		date: '05-22 10:49',
+		views: '10000',
+		cover: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
 	}
+	// 更多资源项...
+]
+
+const recommendedResources = [
+	{
+		title: '资源名称',
+		date: '05-22',
+		views: '10000'
+	}
+	// 更多推荐资源项...
+]
+
+// 筛选条件
+const selectedDepartment = ref('全部')
+const selectedCourse = ref('全部')
+const selectedCourseType = ref('全部')
+const selectedFileType = ref('全部')
+const searchKeyword = ref('')
+
+const selectedTags = ref([])
+
+// 展开/收起状态
+const isDepartmentExpanded = ref(false)
+const isCourseExpanded = ref(false)
+const isCourseTypeExpanded = ref(false)
+const isFileTypeExpanded = ref(false)
+
+// 过滤资源
+const filteredResources = computed(() => {
+	return resources.filter((resource) => {
+		const deptMatch = selectedDepartment.value === '全部' || resource.department === selectedDepartment.value
+		const courseMatch = selectedCourse.value === '全部' || resource.course === selectedCourse.value
+		const typeMatch = selectedCourseType.value === '全部' || resource.type === selectedCourseType.value
+		const formatMatch = selectedFileType.value === '全部' || resource.format === selectedFileType.value
+
+		return deptMatch && courseMatch && typeMatch && formatMatch
+	})
+})
+
+// 清除筛选条件
+const clearFilters = () => {
+	selectedDepartment.value = '全部'
+	selectedCourse.value = '全部'
+	selectedCourseType.value = '全部'
+	selectedFileType.value = '全部'
+	selectedTags.value = []
+}
+
+// 处理标签关闭
+const handleTagClose = (tag) => {
+	selectedTags.value = selectedTags.value.filter((t) => t !== tag)
+	if (tag === selectedDepartment.value) selectedDepartment.value = '全部'
+	else if (tag === selectedCourse.value) selectedCourse.value = '全部'
+	else if (tag === selectedCourseType.value) selectedCourseType.value = '全部'
+	else if (tag === selectedFileType.value) selectedFileType.value = '全部'
+}
+
+// 搜索功能
+const onSearch = (value) => {
+	console.log('search:', value)
+	// 这里可以添加搜索逻辑
+}
+
+// 切换展开/收起状态
+const toggleDepartmentOptions = () => {
+	isDepartmentExpanded.value = !isDepartmentExpanded.value
+}
+
+const toggleCourseOptions = () => {
+	isCourseExpanded.value = !isCourseExpanded.value
+}
+
+const toggleCourseTypeOptions = () => {
+	isCourseTypeExpanded.value = !isCourseTypeExpanded.value
+}
+
+const toggleFileTypeOptions = () => {
+	isFileTypeExpanded.value = !isFileTypeExpanded.value
+}
+</script>
+
+  <style scoped>
+.resource-page {
+	padding: 20px;
+}
+
+.filter-group {
+	display: flex;
+	align-items: center;
+}
+
+.filter-label {
+	margin-right: 10px;
+}
+
+.expanded-options {
+	display: flex;
+	flex-wrap: wrap;
+	margin-top: 8px;
+}
 </style>