feat(class): 添加班级删除功能

- 在班级列表表格中新增“操作”列,添加删除按钮
- 实现删除班级的接口调用逻辑
- 删除成功后刷新班级列表
- 删除当前选中班级时清空选中状态
- 添加成功和失败的用户提示信息
This commit is contained in:
lbw
2025-12-15 15:25:35 +08:00
parent 84239d0199
commit 7aebff5f6a
13 changed files with 245 additions and 21 deletions

View File

@@ -5,4 +5,17 @@ export function getClassList(page, size) {
page: page,
pageSize: size
})
}
export function addClass(name, gradeId) {
return axios.post('/class/add', {
title: name,
gradeId: gradeId
})
}
export function deleteClass(id) {
return axios.post('/class/delete', {
id: id
})
}

View File

@@ -0,0 +1,86 @@
<template>
<el-dialog v-model="visible" title="新增班级" width="480px" :close-on-click-modal="false">
<div class="space-y-4" v-loading="loading">
<el-form label-width="80px">
<el-form-item label="班级名称">
<el-input v-model="name" placeholder="请输入班级名称,如:二班" clearable />
</el-form-item>
<el-form-item label="年级">
<el-select v-model="gradeId" placeholder="请选择年级" style="width: 260px">
<el-option v-for="g in gradeOptions" :key="g.id" :label="g.title" :value="g.id" />
</el-select>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="flex justify-end gap-2">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" :disabled="!canSubmit" @click="handleSubmit">确定</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { getGradeList } from '@/api/grade'
import { addClass } from '@/api/class'
const props = defineProps({
modelValue: { type: Boolean, default: false },
defaultGradeId: { type: [Number, String], default: null }
})
const emit = defineEmits(['update:modelValue', 'success'])
const visible = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
const loading = ref(false)
const name = ref('')
const gradeId = ref(null)
const gradeOptions = ref([])
const canSubmit = computed(() => name.value.trim().length > 0 && !!gradeId.value)
async function fetchGrades() {
loading.value = true
try {
const res = await getGradeList(1, 100)
const d = res?.data
gradeOptions.value = Array.isArray(d?.data) ? d.data : []
if (props.defaultGradeId && !gradeId.value) {
gradeId.value = Number(props.defaultGradeId)
}
} finally {
loading.value = false
}
}
async function handleSubmit() {
if (!canSubmit.value) return
loading.value = true
try {
await addClass(name.value.trim(), Number(gradeId.value))
ElMessage.success('新增班级成功')
emit('success')
visible.value = false
} finally {
loading.value = false
}
}
watch(
() => props.modelValue,
(v) => {
if (v) {
name.value = ''
gradeId.value = props.defaultGradeId ? Number(props.defaultGradeId) : null
fetchGrades()
}
}
)
</script>
<style scoped></style>

View File

@@ -16,12 +16,22 @@
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="title" label="班级名称" min-width="120" />
<el-table-column prop="gradeName" label="年级" min-width="120" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button type="danger" size="small" @click.stop="onDeleteClass(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-4 flex justify-end">
<el-pagination background layout="prev, pager, next, sizes, total" :total="totalCount"
:page-size="pageSize" :current-page="pageNo" @current-change="handlePageChange"
@size-change="handleSizeChange" />
</div>
<div class="mt-3 flex justify-end">
<el-button type="primary" @click="showAddClassDialog = true">新增班级</el-button>
</div>
<AddClassDialog v-model="showAddClassDialog" :default-grade-id="selectedGradeId"
@success="fetchClasses" />
</div>
</div>
@@ -35,18 +45,13 @@
selectedGradeId }})</el-tag>
<el-button type="primary" @click="fetchStudents">查询</el-button>
<el-button @click="resetStudentFilters">重置</el-button>
<el-button type="success" :disabled="selectedStudentIds.length === 0" @click="showGenerateDialog = true">
<el-button type="success" :disabled="selectedStudentIds.length === 0"
@click="showGenerateDialog = true">
生成试题
</el-button>
</div>
<el-table
ref="studentTableRef"
:data="students"
border
class="w-full"
v-loading="studentLoading"
@selection-change="onStudentSelectionChange"
>
<el-table ref="studentTableRef" :data="students" border class="w-full"
v-loading="studentLoading" @selection-change="onStudentSelectionChange">
<el-table-column type="selection" width="48" />
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="name" label="姓名" min-width="120" />
@@ -58,22 +63,20 @@
:total="studentTotalCount" :page-size="studentPageSize" :current-page="studentPageNo"
@current-change="handleStudentPageChange" @size-change="handleStudentSizeChange" />
</div>
<ExamGenerateDialog
v-model="showGenerateDialog"
:student-ids="selectedStudentIds"
:default-grade-id="selectedGradeId"
/>
<ExamGenerateDialog v-model="showGenerateDialog" :student-ids="selectedStudentIds"
:default-grade-id="selectedGradeId" />
</div>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6" v-loading="gradeLoading">
<div class="text-lg font-semibold mb-4">年级列表</div>
<el-table ref="gradeTableRef" :data="grades" border class="w-full" highlight-current-row row-key="id"
:current-row-key="selectedGradeId" @row-click="onGradeRowClick">
<el-table ref="gradeTableRef" :data="grades" border class="w-full" highlight-current-row
row-key="id" :current-row-key="selectedGradeId" @row-click="onGradeRowClick">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="title" label="年级名称" min-width="160" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button type="danger" size="small" @click.stop="onDeleteGrade(row)">删除</el-button>
<el-button type="danger" size="small"
@click.stop="onDeleteGrade(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -98,10 +101,11 @@
<script setup>
import Header from '@/layouts/components/Header.vue'
import { ref, onMounted } from 'vue'
import { getClassList } from '@/api/class'
import { getGradeList, deleteGrade } from '@/api/grade'
import { getClassList, deleteClass } from '@/api/class'
import { getGradeList } from '@/api/grade'
import { getStudentList } from '@/api/student'
import ExamGenerateDialog from '@/layouts/components/ExamGenerateDialog.vue'
import AddClassDialog from '@/layouts/components/AddClassDialog.vue'
import AddGradeDialog from '@/layouts/components/AddGradeDialog.vue'
const classes = ref([])
@@ -112,6 +116,7 @@ const loading = ref(false)
const classTableRef = ref(null)
const selectedClassId = ref(null)
const selectedClassTitle = ref('')
const showAddClassDialog = ref(false)
const grades = ref([])
const gradePageNo = ref(1)
@@ -228,6 +233,20 @@ function onGradeRowClick(row) {
studentPageNo.value = 1
fetchStudents()
}
async function onDeleteClass(row) {
try {
await deleteClass(row.id)
ElMessage.success('删除成功')
if (selectedClassId.value === row.id) {
selectedClassId.value = null
selectedClassTitle.value = ''
classTableRef.value?.setCurrentRow()
}
await fetchClasses()
} catch (e) {
ElMessage.error('删除失败')
}
}
function resetStudentFilters() {
studentName.value = ''
selectedClassId.value = null