浏览代码

课件管理

zjq 1 月之前
父节点
当前提交
03afdfb28d

+ 60 - 0
src/api/courseware/index.ts

@@ -0,0 +1,60 @@
+/*
+ * @Author: zjq
+ * @description 课件管理
+ */
+import request from '@/utils/request';
+
+/**
+ * @description 新增课件
+ * @param {object} data
+ */
+export const addCourseware = (data: object) => {
+    return request({
+        url: '/api/v1/Sourcewares/Add',
+        method: 'post',
+        data,
+    });
+};
+/**
+ * @description 编辑课件
+ * @param {object} data
+ */
+export const editCourseware = (data: object) => {
+    return request({
+        url: '/api/v1/Sourcewares/Update',
+        method: 'put',
+        data,
+    });
+};
+/**
+ * @description 删除课件
+ * @param {object} data
+ */
+export const deleteCourseware = (data: object) => {
+    return request({
+        url: '/api/v1/Sourcewares/Delete',
+        method: 'delete',
+        data,
+    });
+};
+/**
+ * @description 获取课件列表
+ * @param {object} params
+ */
+export const getCoursewareData = (params?: object) => {
+    return request({
+        url: '/api/v1/Sourcewares/GetPagedList',
+        method: 'post',
+        data: params,
+    });
+};
+/**
+ * @description 查询课件详情
+ * @param {object} Id
+ */
+export const getCoursewareDetail = (Id: string) => {
+    return request({
+        url: `/api/v1/Sourcewares/Get?id=${Id}`,
+        method: 'get',
+    });
+};

+ 105 - 0
src/views/courseware/index/components/Course-edit.vue

@@ -0,0 +1,105 @@
+<template>
+	<el-dialog title="编辑课件" v-model="state.dialogVisible" draggable append-to-body destroy-on-close @close="close" width="500px">
+		<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" v-loading="state.loading">
+			<el-row :gutter="10">
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="课件名称" prop="name" :rules="[{ required: true, message: '请填写课件名称', trigger: 'blur' }]">
+						<el-input v-model="state.ruleForm.name" placeholder="请填写课件名称" clearable></el-input>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="课件分类" prop="categoryId" :rules="[{ required: false, message: '请选择课件分类', trigger: 'change' }]">
+						<el-cascader
+							:options="state.treeData"
+							filterable
+							:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
+							placeholder="请选择课件分类"
+							clearable
+							class="w100"
+							v-model="state.ruleForm.categoryId"
+							ref="cascadeRef"
+						>
+						</el-cascader>
+					</el-form-item>
+				</el-col>
+			</el-row>
+		</el-form>
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="closeDialog" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref } from 'vue';
+import { ElMessage, FormInstance } from 'element-plus';
+import { excludeSelfById } from '@/utils/tools';
+import other from '@/utils/other';
+import { getCoursewareDetail, editCourseware } from '@/api/courseware/index';
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['updateList']);
+
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false, // 弹窗
+	ruleForm: {
+        id: '', // 课件ID
+		name: '', // 课件名称
+        categoryId: '', // 课件类型ID
+        attachmentId: '', // 课件附件ID
+        sourcewareType: '', // 课件格式
+	},
+	treeData: [], // 课件类型树形数据
+	loading: false, // 加载
+});
+// 打开弹窗
+const ruleFormRef = ref<any>(); // 表单ref
+const openDialog = async (row: any, treeData: any) => {
+    console.log(treeData);
+	try {
+		state.dialogVisible = true;
+		const { result } = await getCoursewareDetail(row.id);
+		state.ruleForm = result;
+		state.treeData = other.deepClone(treeData);
+		// state.treeData = excludeSelfById(state.treeData, row.categoryId);
+	} catch (error) {
+		// 打印错误信息
+		console.error(error);
+	}
+};
+const close = () => {
+	ruleFormRef.value?.clearValidate();
+	ruleFormRef.value?.resetFields();
+};
+// 关闭弹窗
+const closeDialog = () => {
+	state.dialogVisible = false;
+};
+// 保存
+const onSubmit = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+		editCourseware(state.ruleForm)
+			.then(() => {
+				closeDialog(); // 关闭弹窗
+				ElMessage.success('操作成功');
+				state.loading = false;
+				emit('updateList');
+			})
+			.catch(() => {
+				state.loading = false;
+			});
+	});
+};
+// 暴露变量
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>

+ 199 - 0
src/views/courseware/index/components/Course-upload.vue

@@ -0,0 +1,199 @@
+<template>
+	<el-dialog v-model="state.dialogVisible" width="50%" draggable title="课件上传" @close="close">
+		<el-upload
+			class="upload-demo"
+			v-model:file-list="fileList"
+			:action="action"
+			:multiple="true"
+			:accept="fileTypeAccept"
+			:on-exceed="handleExceed"
+			ref="uploadListRef"
+			name="fileData"
+			:on-change="handleChangeFile"
+			:on-success="updateSuccess"
+			:disabled="uploadingDisabled"
+			:on-error="onUploadError"
+			:limit="fileLimit"
+			:on-remove="handRemove"
+			:before-upload="beforeUpload"
+			drag
+		>
+			<SvgIcon name="ele-UploadFilled" size="42px" />
+			<div class="el-upload__text">点击或将文件拖拽到这里上传</div>
+			<template #tip>
+				<div class="el-upload__tip">大小限制:20M</div>
+			</template>
+		</el-upload>
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="closeDialog" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onSave" :loading="uploadingDisabled" :disabled="disabled">{{uploadingDisabled ? '上传中...' : '确 定'}}</el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+
+<script setup lang="ts" name="parameterAdd">
+import { computed, reactive, ref } from 'vue';
+import { ElMessageBox, ElMessage, UploadFile, UploadFiles, UploadUserFile } from 'element-plus';
+import Other from '@/utils/other';
+import { addCourseware } from '@/api/courseware/index';
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['updateList']);
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false,
+	ruleForm: {
+		settingName: '', // 参数名称
+		code: '', // 参数
+		settingValue: '', // 参数值
+		sort: 1, // 排序
+		remark: '', // 参数说明
+	},
+});
+
+const fileTypeAccept = '.doc,.rar,.jpg,.pdf,.mp3,.xls,.xlsx,.zip,.docx,.wmv,.mp4,.png,.svg,.avi,.jpeg,.m4a,.txt,.wps';
+const action = computed(() => {
+	return import.meta.env.VITE_API_UPLOAD_URL + '/file/uploadinside?source=hotline';
+	// return 'http://171.94.154.2:50105/hlfs/file/upload?source=hotline';
+});
+
+const fileList = ref<EmptyArrayType>([]);
+const uploadListRef = ref<RefType>(); // 上传组件ref
+const disabled = computed(() => {
+	return fileList.value.length === 0;
+});
+// 格式化数据
+const formatData = (data: any) => {
+	return data.map((v: any) => {
+		return {
+			name: v.name,
+			fileName: v.name,
+            categoryId: v?.categoryId,
+			attachmentId: v?.response?.result.id,
+            sourcewareType: v?.raw?.type,
+			path: v?.response?.result?.path,
+			url: import.meta.env.VITE_API_UPLOAD_URL + v?.response?.result?.path,
+			allPath: import.meta.env.VITE_API_UPLOAD_URL + v?.response?.result?.path,
+		};
+	});
+};
+// 更新数据
+const transformData = ref<EmptyArrayType>([]);
+const updateData = () => {
+    console.log(fileList.value);
+	transformData.value = formatData(Other.deepClone(fileList.value));
+};
+
+//文件限制
+const fileLimit = ref(5);
+const handleExceed = (files: any, uploadFiles: UploadUserFile[]) => {
+	ElMessage.warning(`当前限制最多上传 ${fileLimit.value} 个文件,已经上传了${uploadFiles.length}个文件,本次选择了 ${files.length} 个文件。`);
+	setTimeout(() => {
+		uploadLoading.value = false; // 模拟上传过程
+		uploadingDisabled.value = false;
+	}, 100);
+};
+
+//限制文件大小
+const handleChangeFile = (file: any, fileList: any) => {
+	//限制上传文件大小
+	setTimeout(() => {
+		updateData();
+	}, 100);
+	if (!file) return;
+	const isLt2M = file.size / 1024 / 1024 < 20;
+	if (!isLt2M) {
+		const currIdx = fileList.indexOf(file);
+		fileList.splice(currIdx, 1);
+		ElMessage.warning(`文件超过了最大限度 20MB!`);
+		setTimeout(() => {
+			uploadLoading.value = false; // 模拟上传过程
+			uploadingDisabled.value = false;
+		}, 100);
+		return false;
+	}
+};
+// 删除文件
+const handRemove = () => {
+	setTimeout(() => {
+		updateData();
+	}, 100);
+};
+// 上传失败
+const onUploadError = (error: Error, uploadFile: UploadFile) => {
+	try {
+		const errMessage = JSON.parse(error.message)?.message ?? `文件 ${uploadFile.name} 上传失败`;
+		// 从文件列表中移除失败的文件
+		fileList.value = fileList.value.filter((item) => item.response);
+		console.error(`文件 ${uploadFile.name} 上传失败`);
+		ElMessage.error(errMessage);
+	} catch (e) {
+		ElMessage.error(`文件 ${uploadFile.name} 上传失败`);
+	}
+	setTimeout(() => {
+		updateData();
+		uploadLoading.value = false; // 模拟上传过程
+		uploadingDisabled.value = false;
+	}, 100);
+};
+
+const uploadLoading = ref(false);
+const uploadingDisabled = ref(false);
+const beforeUpload = () => {
+    console.log()
+	uploadLoading.value = true; // 模拟上传过程
+	uploadingDisabled.value = true;
+};
+
+// 上传成功
+const updateSuccess = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
+	if (response.result.path) {
+		fileList.value = uploadFiles;
+		setTimeout(() => {
+			updateData();
+			uploadLoading.value = false;
+			uploadingDisabled.value = false;
+		}, 100);
+	} else {
+		uploadListRef.value.handleRemove(uploadFile);
+		ElMessage.error('上传失败');
+	}
+};
+
+// 打开弹窗
+const ruleFormRef = ref<RefType>();
+const openDialog = () => {
+	state.dialogVisible = true;
+};
+// 关闭
+const close = () => {
+	ruleFormRef.value?.resetFields();
+	fileList.value = [];
+};
+// 关闭弹窗
+const closeDialog = () => {
+	state.dialogVisible = false;
+};
+// 保存
+const onSave = () => {
+    transformData.value.forEach((item: Object) => {
+        addCourseware(item)
+		.then(() => {
+			ElMessage.success('保存成功');
+			closeDialog();
+			emit('updateList');
+		})
+		.catch((err: any) => {
+			console.log(err, 'err');
+			closeDialog();
+		});
+    });
+};
+// 暴露变量
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>

+ 344 - 0
src/views/courseware/index/index.vue

@@ -0,0 +1,344 @@
+<template>
+	<div class="plan-index-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<splitpanes class="h100" :horizontal="horizontal">
+				<pane min-size="16" max-size="25" size="16">
+					<el-scrollbar ref="scrollBarRef" noresiz>
+						<el-skeleton :loading="state.typeLoading" animated :rows="10">
+							<template #default>
+								<v-tree-search
+									:data="state.typeOptions"
+									titleField="name"
+									keyField="id"
+									selectable
+									searchPlaceholder="课件分类名称"
+									@select="selectType"
+									@unselect="unSelectType"
+									ref="treeSearchRef"
+								>
+									<template #node="{ node }">
+										<span>{{ node.name }}</span>
+									</template>
+								</v-tree-search>
+							</template>
+						</el-skeleton>
+					</el-scrollbar>
+				</pane>
+				<pane class="h100" style="display: flex; flex: 1; flex-direction: column">
+					<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent :disabled="state.tableLoading">
+						<el-form-item label="课件名称" prop="Title">
+							<el-input v-model="state.queryParams.Title" placeholder="课件名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
+						</el-form-item>
+						<el-form-item label="格式" prop="FileType">
+							<el-select v-model="state.queryParams.FileType" placeholder="请选择" @change="handleQuery" :disabled="state.tableLoading">
+                                <el-option
+                                    v-for="item in state.filesTypeSelect"
+                                    :key="item"
+                                    :label="item"
+                                    :value="item"
+                                />
+                            </el-select>
+						</el-form-item>
+						<el-form-item>
+							<el-button type="primary" @click="handleQuery" :loading="state.tableLoading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+                            <el-button @click="resetQuery(ruleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置</el-button>
+						</el-form-item>
+					</el-form>
+					<vxe-toolbar
+						ref="toolbarRef"
+						:loading="state.tableLoading"
+						custom
+						:refresh="{
+							queryMethod: handleQuery,
+						}"
+					>
+						<template #buttons>
+							<el-button type="primary" @click="onAdd" v-auth="'course:index:add'" :loading="state.tableLoading">
+								<SvgIcon name="ele-Upload" class="mr5" />上传课件
+							</el-button>
+                            <el-button type="primary" plain @click="onBatchDownload" v-auth="'course:index:batchDownload'" :loading="state.tableLoading" :disabled="isChecked">
+                                <SvgIcon name="ele-Download" class="mr5" />批量下载
+                            </el-button>
+							<el-button type="danger" plain @click="onBatchDelete" v-auth="'course:index:batchDelete'" :loading="state.tableLoading" :disabled="isChecked">
+                                <SvgIcon name="ele-Delete" class="mr5" />批量删除
+                            </el-button>
+						</template>
+					</vxe-toolbar>
+					<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+						<vxe-table
+							border
+							:loading="state.tableLoading"
+							:data="state.tableData"
+							:column-config="{ resizable: true }"
+							:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
+							ref="tableRef"
+							height="auto"
+							auto-resize
+							show-overflow
+							:print-config="{}"
+							:scrollY="{ enabled: true, gt: 100 }"
+							id="courseManage"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+							@checkbox-all="selectAllChangeEvent"
+							@checkbox-change="selectChangeEvent"
+						>
+							<vxe-column type="checkbox" width="50" align="center"></vxe-column>
+							<vxe-column field="name" title="课件名称" min-width="200"></vxe-column>
+							<vxe-column field="sourcewareType" title="课件格式" width="150"></vxe-column>
+							<vxe-column field="creatorName" title="创建人" width="150"></vxe-column>
+							<vxe-column field="creationTime" title="创建时间" width="160">
+								<template #default="{ row }">
+									{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+								</template>
+							</vxe-column>
+							<vxe-column title="操作" fixed="right" width="180" align="center" :show-overflow="false">
+								<template #default="{ row }">
+                                    <el-button link type="primary" @click="onDownload(row)" title="预览下载" v-auth="'course:index:download'">
+										预览下载
+									</el-button>
+									<el-button link type="primary" @click="onEdit(row)" title="编辑" v-auth="'course:index:edit'">
+										编辑
+									</el-button>
+									<el-button link type="danger" @click="onRowDel(row)" title="删除" v-auth="'course:index:delete'">
+										删除
+									</el-button>
+								</template>
+							</vxe-column>
+						</vxe-table>
+					</div>
+					<pagination
+						@pagination="queryList"
+						:total="state.total"
+						v-model:current-page="state.queryParams.PageIndex"
+						v-model:page-size="state.queryParams.PageSize"
+						:disabled="state.tableLoading"
+					/>
+				</pane>
+			</splitpanes>
+		</div>
+		
+		<!-- 编辑课件 -->
+		<course-edit ref="courseEditRef" @updateList="handleQuery" />
+		<!-- 上传课件 -->
+		<course-upload ref="courseUploadRef" @updateList="handleQuery" />
+	</div>
+</template>
+
+<script lang="tsx" setup name="coursewareManage">
+import { ref, reactive, onMounted, defineAsyncComponent, computed } from 'vue';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { useRouter } from 'vue-router';
+import type { FormInstance } from 'element-plus';
+import { formatDate } from '@/utils/formatTime';
+import { Splitpanes, Pane } from 'splitpanes';
+import 'splitpanes/dist/splitpanes.css';
+import Other from '@/utils/other';
+import { downloadFileByStream } from '@/utils/tools';
+import { VxeUI } from 'vxe-pc-ui';
+import { VTreeSearch } from '@wsfe/vue-tree';
+import {deleteCourseware, getCoursewareData} from '@/api/courseware/index';
+import { coursewareTreeList } from '@/api/courseware/type';
+import { fileDownloadByUrl } from '@/api/public/file';
+
+// 引入组件
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+const CourseEdit = defineAsyncComponent(() => import('@/views/courseware/index/components/Course-edit.vue')); // 课件编辑
+const CourseUpload = defineAsyncComponent(() => import('@/views/courseware/index/components/Course-upload.vue')); // 课件上传
+
+const router = useRouter(); //路由
+const horizontal = ref(false);
+
+// 定义变量内容
+const state = reactive<any>({
+	queryParams: {
+		PageIndex: 1, //页码
+		PageSize: 20, //每页条数
+        CourseWareTypeID: null, // 课件类型
+		Title: null, //课件名称
+        FileType: null, // 课件格式
+	},
+	typeLoading: false, // 类型loading
+	typeOptions: [], // 类型数据
+    filesTypeSelect: ["doc","rar","jpg","pdf","mp3","xls","xlsx","zip","docx","wmv","mp4","png","svg","avi","jpeg","m4a","txt","wps"],
+	tableData: [], //表格数据
+	total: 0, //总条数
+	loading: false, //表格loading
+	tableLoading: false, //表格loading
+});
+/** 搜索按钮操作 节流操作 */
+const handleQuery = () => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+};
+// 获取课件分类
+const getCoursewareType = async () => {
+	state.typeLoading = true;
+	try {
+		const { result } = await coursewareTreeList();
+		state.typeOptions = result ?? [];
+		state.typeLoading = false;
+	} catch (error) {
+		state.typeLoading = false;
+	}
+};
+/** 获取课件列表 */
+const requestParams = ref<EmptyObjectType>({});
+const queryList = () => {
+	state.tableLoading = true;
+	requestParams.value = Other.deepClone(state.queryParams);
+	requestParams.value.name = state.queryParams.Title || '';
+	requestParams.value.sourcewareType = state.queryParams.FileType || '';
+	requestParams.value.sourcewareCategoryId = state.queryParams.CourseWareTypeID || '';
+	Reflect.deleteProperty(requestParams.value, 'Title'); 
+	Reflect.deleteProperty(requestParams.value, 'FileType'); 
+	Reflect.deleteProperty(requestParams.value, 'CourseWareTypeID'); 
+    console.log(requestParams.value)
+	getCoursewareData(requestParams.value)
+		.then((response: any) => {
+            console.log(response)
+			state.tableData = response?.result.items ?? [];
+			state.total = response?.result.pagination.totalCount;
+			state.tableLoading = false;
+		})
+		.catch(() => {
+			state.tableLoading = false;
+		});
+};
+// 选择分类
+const selectType = (data: any) => {
+	state.queryParams.CourseWareTypeID = data.id;
+	handleQuery();
+};
+// 取消选择
+const unSelectType = () => {
+	state.queryParams.CourseWareTypeID = null;
+	handleQuery();
+};
+/** 重置按钮操作 */
+const drawerRuleFormRef = ref();
+const ruleFormRef = ref<RefType>(); // 表单ref
+const drawer = ref(false);
+const treeSearchRef = ref<RefType>();
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	ruleFormRef.value?.resetFields();
+	treeSearchRef.value.clearKeyword(); // 清空搜索关键词
+	treeSearchRef.value.search(); // 搜索
+	resetNode();
+	setTimeout(() => {
+		treeSearchRef.value.setExpandAll(false); // 默认全部收起
+	}, 300);
+};
+// 重置选中的节点
+const resetNode = () => {
+	state.queryParams.CourseWareTypeID = null;
+	handleQuery();
+};
+// 上传课件
+const courseUploadRef = ref<RefType>(); // 修改ref
+const onAdd = () => {
+	courseUploadRef.value.openDialog();
+};
+// 批量下载
+const onBatchDownload = () => {
+
+}
+// 批量删除
+const onBatchDelete = () => {
+	const ids = checkTable.value.map((item: any) => item.id);
+    ElMessageBox.confirm(`您确定要删除选中的课件?`, '提示', {
+		confirmButtonText: '确定',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		autofocus: false,
+	})
+		.then(() => {
+			deleteCourseware({ ids: ids }).then(() => {
+				queryList();
+				ElMessage.success('删除成功');
+			});
+		})
+		.catch(() => {});
+}
+// 预览下载
+const onDownload = (row: any) => {
+	ElMessageBox.confirm(`您确定要下载课件,是否继续?`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		cancelButtonClass: 'default-button',
+		autofocus: false,
+	})
+		.then(() => {
+			fileDownloadByUrl({
+				Source: 'hotline',
+				Id: row.attachmentId,
+			}).then((res: any) => {
+				let blob: Blob = new Blob([res.data], { type: res.data.type }); // 创建blob 设置blob文件类型 data 设置为后端返回的文件(例如mp3,jpeg) type:这里设置后端返回的类型 为 mp3
+				let down: HTMLAnchorElement = document.createElement('a'); // 创建A标签
+				let href: string = window.URL.createObjectURL(blob); // 创建下载的链接
+				down.href = href; // 下载地址
+				down.download = row.name // 下载文件名
+				document.body.appendChild(down);
+				down.click(); // 模拟点击A标签
+				document.body.removeChild(down); // 下载完成移除元素
+				window.URL.revokeObjectURL(href); // 释放blob对象
+			});
+		})
+		.catch(() => {});
+};
+// 修改课件弹窗
+const courseEditRef = ref<RefType>(); // 修改ref
+const onEdit  = (row: any) => {
+	courseEditRef.value.openDialog(row, state.typeOptions);
+};
+// 删除当前行
+const onRowDel = (row: any) => {
+  const typeName = row.name.replace(/<span class="keyword-highlight">(.*?)<\/span>/g, '$1');
+	ElMessageBox.confirm(`是否确认删除:${typeName}?删除后不可恢复`, '提示', {
+		confirmButtonText: '确定',
+		cancelButtonText: '取消',
+		type: 'warning',
+	})
+        .then(() => {
+			deleteCourseware({id: row.id}).then(() => {
+				ElMessage.success('删除成功');
+				queryList();
+			});
+		})
+		.catch(() => {});
+};
+// 表格选中状态
+const tableRef = ref<RefType>();
+const checkTable = ref<EmptyArrayType>([]);
+const selectAllChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '所有勾选事件' : '所有取消事件', records);
+	}
+};
+
+const selectChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '勾选事件' : '取消事件', records);
+	}
+};
+const isChecked = computed(() => {
+	return !Boolean(checkTable.value.length);
+});
+const toolbarRef = ref<RefType>();
+onMounted(() => {
+	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+	getCoursewareType();
+});
+</script>

+ 2 - 2
src/views/courseware/type/index.vue

@@ -65,8 +65,8 @@
 					</vxe-column>
 					<vxe-column title="操作" fixed="right" width="180" align="center" :show-overflow="false">
 						<template #default="{ row }">
-							<el-button link type="primary" @click="onOpenEdit(row)" title="编辑" v-auth="'courseware:type:edit'"> 编辑 </el-button>
-							<el-button link type="danger" @click="onDelete(row)" title="删除" v-auth="'courseware:type:delete'"> 删除 </el-button>
+							<el-button link type="primary" @click="onOpenEdit(row)" title="编辑" v-if="row.name != '未分类'" v-auth="'courseware:type:edit'"> 编辑 </el-button>
+							<el-button link type="danger" @click="onDelete(row)" title="删除" v-if="row.name != '未分类'" v-auth="'courseware:type:delete'"> 删除 </el-button>
 						</template>
 					</vxe-column>
 				</vxe-table>