| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- <template>
- <div class="page-content">
- <h2 class="title">课程列表</h2>
- <course-search v-show="showSearchBar" @search="getCourseData"></course-search>
- <el-card class="art-table-card" shadow="never">
- <ArtTableHeader v-model:showSearchBar="showSearchBar" :loading="loading" @refresh="() => getCourseData({})" layout="search,refresh">
- <template #left>
- <ElSpace wrap>
- <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">
- <div style="width: 110px">全选({{ selectCourses.length }} / {{ courseData.length }})</div>
- </el-checkbox>
- <el-button v-ripple type="primary" :icon="Plus" @click="() => router.push({ path: '/course/detail/0' })"> 新增课程 </el-button>
- <el-button v-ripple type="default" :icon="Upload" @click="courseImportHandle"> 导入课程 </el-button>
- <el-button v-ripple type="default" :icon="Download" :disabled="selectCourses.length === 0" @click="exportCourseHandle"> 导出课程 </el-button>
- <el-button v-ripple type="danger" :icon="Delete" :disabled="selectCourses.length === 0" @click="batchDeleteHandle"> 删除课程 </el-button>
- <el-button v-ripple type="default" :icon="CopyDocument" :disabled="selectCourses.length === 0" @click="copyCourseHandle"> 复制课程 </el-button>
- </ElSpace>
- </template>
- </ArtTableHeader>
- <course-list :data="courseData" :loading="loading" @handle="(type, item) => courseHandle(type, item)" :checkedCourse="selectCourses" @update:checkedList="handleCheckedChange"></course-list>
- </el-card>
- <course-import ref="courseImportRef"></course-import>
- </div>
- </template>
- <script lang="ts" setup>
- import { ref } from 'vue'
- import { CourseServer, type Course } from '@/api/course.api'
- import courseSearch from './course-search.vue'
- import courseList from './course-list.vue'
- import courseImport from './course-import.vue'
- import { Plus, Upload, Download, Delete, CopyDocument } from '@element-plus/icons-vue'
- import { router } from '@/router'
- import { CheckboxValueType, ElMessageBox } from 'element-plus'
- // 搜索项
- const showSearchBar = ref<boolean>(false)
- // 导入课程
- const courseImportRef = ref()
- const courseImportHandle = () => courseImportRef?.value.show()
- // 选择的课程Id
- const selectCourses = ref<string[]>([])
- // 是否全选
- const checkAll = computed({
- get: () => selectCourses.value.length === courseData.value.length && courseData.value.length > 0,
- set: (val: boolean) => (selectCourses.value = val ? [...courseData.value.map((item) => item.courseID)] : [])
- })
- // 是否半选
- const isIndeterminate = computed(() => {
- const checkedCount = selectCourses.value.length
- return checkedCount > 0 && checkedCount < courseData.value.length
- })
- // 处理子组件更新
- const handleCheckedChange = (newList: string[]) => {
- selectCourses.value = newList
- }
- // 全选复选框变更(其实 computed setter 已处理,此函数可省略,但保留以兼容 @change)
- const handleCheckAllChange = (val: CheckboxValueType) => {
- const checked = val as boolean
- selectCourses.value = checked ? [...courseData.value.map((item) => String(item.courseID))] : []
- }
- const courseData = ref<Course[]>([])
- const loading = ref(false)
- const getCourseData = async (params: Record<string, unknown>) => {
- loading.value = true
- const { data } = await CourseServer.list(params)
- courseData.value = data!
- loading.value = false
- }
- const courseHandle = (type: string, item: Course) => {
- switch (type) {
- case 'delete':
- CourseServer.delete(item.courseID).then(() => {
- ElMessage.success('删除成功')
- getCourseData({})
- })
- break
- case 'copy':
- CourseServer.copy(item.courseID).then(() => {
- ElMessage.success('复制成功')
- getCourseData({})
- })
- break
- case 'detail':
- router.push({ path: '/course/detail/' + item.courseID, query: { edit: `${false}` } })
- break
- case 'edit':
- router.push({ path: '/course/detail/' + item.courseID, query: { edit: `${true}` } })
- break
- default:
- ElMessage.error('未知操作')
- break
- }
- }
- const copyCourseHandle = async () => {
- if (selectCourses.value.length === 0) {
- ElMessage.warning('请选择要复制的课程')
- return
- }
- CourseServer.copyBatch(selectCourses.value).then(() => {
- ElMessage.success('复制成功')
- })
- }
- const exportCourseHandle = async () => {
- if (selectCourses.value.length === 0) {
- ElMessage.warning('请选择要导出的课程')
- return
- }
- CourseServer.export(selectCourses.value).then(() => {
- ElMessage.success('导出成功')
- })
- }
- const batchDeleteHandle = async () => {
- if (selectCourses.value.length === 0) {
- ElMessage.warning('请选择要删除的课程')
- return
- }
- ElMessageBox.confirm(`确定删除选中的 ${selectCourses.value.length} 条课程吗?`, '删除确认', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- CourseServer.deleteBatch(selectCourses.value).then(() => {
- ElMessage.success('删除成功')
- getCourseData({})
- })
- })
- }
- onMounted(async () => {
- getCourseData({})
- })
- </script>
- <style lang="scss" scoped>
- .title {
- margin-bottom: 5px;
- font-size: 18px;
- font-weight: 500;
- &.m-15 {
- margin-top: 15px;
- }
- }
- </style>
|