<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance } from 'element-plus'
import { Delete, Edit } from '@element-plus/icons-vue'
import { queryPageApi, addApi, queryInfoApi, updateApi, deleteApi } from '@/api/clazz'
// 类型定义
interface Clazz {
id?: number
name: string
room: string
beginDate: string
endDate: string
masterId: number | null
subject: number
masterName?: string
status?: string
}
// 表单引用
const formRef = ref<FormInstance>()
// 响应式数据
const loading = ref(false)
const dialogVisible = ref(false)
const dialogTitle = ref('新增班级')
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const selectedIds = ref<number[]>([])
// 查询条件
const queryParams = reactive({
begin: '',
end: '',
name: '',
})
// 班级表单数据
const clazzForm = reactive<Clazz>({
name: '',
room: '',
beginDate: '',
endDate: '',
masterId: null,
subject: 1,
})
// 班级列表
const clazzList = ref<Clazz[]>([])
// 学科选项
const subjectOptions = [
{ label: 'Java', value: 1 },
{ label: '前端', value: 2 },
{ label: '大数据', value: 3 },
{ label: 'Python', value: 4 },
{ label: 'Go', value: 5 },
{ label: '嵌入式', value: 6 },
]
// 计算是否选择了班级
const hasSelection = computed(() => selectedIds.value.length > 0)
// 加载班级数据
const loadClazzData = async () => {
loading.value = true
try {
const res = await queryPageApi(
queryParams.begin,
queryParams.end,
queryParams.name,
currentPage.value,
pageSize.value,
)
if (res.code === 1) {
clazzList.value = res.data.rows
total.value = res.data.total
selectedIds.value = []
} else {
ElMessage.error(res.msg || '数据加载失败')
}
} catch (error) {
console.error('加载数据出错:', error)
ElMessage.error('网络请求异常')
} finally {
loading.value = false
}
}
// 处理查询
const handleQuery = () => {
currentPage.value = 1
loadClazzData()
}
// 重置查询
const resetQuery = () => {
queryParams.begin = ''
queryParams.end = ''
queryParams.name = ''
handleQuery()
}
// 打开新增对话框
const openAddDialog = () => {
dialogTitle.value = '新增班级'
Object.assign(clazzForm, {
id: undefined,
name: '',
room: '',
beginDate: '',
endDate: '',
masterId: null,
subject: 1,
})
dialogVisible.value = true
}
// 打开编辑对话框
const openEditDialog = async (id: number) => {
dialogTitle.value = '编辑班级'
try {
const res = await queryInfoApi(id)
if (res.code === 1) {
Object.assign(clazzForm, res.data)
dialogVisible.value = true
} else {
ElMessage.error('获取班级信息失败')
}
} catch (error) {
console.error('获取班级信息出错:', error)
ElMessage.error('网络请求异常')
}
}
// 提交表单
const submitForm = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
if (clazzForm.id) {
const res = await updateApi(clazzForm)
if (res.code === 1) {
ElMessage.success('更新成功')
dialogVisible.value = false
loadClazzData()
} else {
ElMessage.error(res.msg || '更新失败')
}
} else {
const res = await addApi(clazzForm)
if (res.code === 1) {
ElMessage.success('新增成功')
dialogVisible.value = false
loadClazzData()
} else {
ElMessage.error(res.msg || '新增失败')
}
}
} catch (error) {
console.error('表单验证失败:', error)
}
}
// 处理选择变化
const handleSelectionChange = (selection: Clazz[]) => {
selectedIds.value = selection.map((item) => item.id!) as number[]
}
// 删除班级
const handleDelete = (ids: number | number[]) => {
const deleteIds = Array.isArray(ids) ? ids : [ids]
const message =
deleteIds.length > 1
? `确定要删除选中的 ${deleteIds.length} 个班级吗?`
: '确定要删除该班级吗?'
ElMessageBox.confirm(message, '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
const res = await deleteApi(deleteIds)
if (res.code === 1) {
ElMessage.success('删除成功')
loadClazzData()
} else {
ElMessage.error(res.msg || '删除失败')
}
})
.catch(() => {})
}
// 分页变化处理
const handleSizeChange = (val: number) => {
pageSize.value = val
loadClazzData()
}
const handleCurrentChange = (val: number) => {
currentPage.value = val
loadClazzData()
}
// 初始化加载数据
onMounted(loadClazzData)
</script>
<template>
<div class="app-container">
<div class="header">
<h2>班级管理</h2>
<div class="actions">
<el-form :model="queryParams" inline>
<el-form-item label="班级名称">
<el-input
v-model="queryParams.name"
placeholder="请输入班级名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="开课时间">
<el-date-picker
v-model="queryParams.begin"
type="date"
placeholder="选择开始日期"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="结课时间">
<el-date-picker
v-model="queryParams.end"
type="date"
placeholder="选择结束日期"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<div class="buttons">
<el-button type="primary" @click="openAddDialog">
<el-icon><plus /></el-icon> 新增班级
</el-button>
<el-button type="danger" :disabled="!hasSelection" @click="handleDelete(selectedIds)">
<el-icon><delete /></el-icon> 批量删除
</el-button>
</div>
</div>
</div>
<!-- 班级表格 -->
<el-table
:data="clazzList"
v-loading="loading"
border
stripe
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column prop="name" label="班级名称" min-width="150" align="center" />
<el-table-column prop="room" label="教室" width="120" align="center" />
<el-table-column prop="beginDate" label="开课时间" width="120" align="center" />
<el-table-column prop="endDate" label="结课时间" width="120" align="center" />
<el-table-column prop="masterName" label="班主任" width="120" align="center" />
<el-table-column label="学科" width="100" align="center">
<template #default="{ row }">
<el-tag type="info">
{{ subjectOptions.find((item) => item.value === row.subject)?.label || '未知' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="状态" width="100" align="center">
<template #default="{ row }">
<el-tag :type="row.status || '未开始'">
{{ row.status || '未开始' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180" align="center" fixed="right">
<template #default="{ row }">
<el-button type="primary" size="small" @click="openEditDialog(row.id)" :icon="Edit"
>编辑</el-button
>
<el-button type="danger" size="small" @click="handleDelete(row.id)" :icon="Delete"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<div class="pagination">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[5, 10, 20, 50]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="600px"
@closed="formRef?.resetFields()"
>
<el-form
ref="formRef"
:model="clazzForm"
label-width="100px"
:rules="{
name: [{ required: true, message: '请输入班级名称', trigger: 'blur' }],
room: [{ required: true, message: '请输入教室', trigger: 'blur' }],
beginDate: [{ required: true, message: '请选择开课时间', trigger: 'change' }],
endDate: [{ required: true, message: '请选择结课时间', trigger: 'change' }],
subject: [{ required: true, message: '请选择学科', trigger: 'change' }],
}"
>
<el-form-item label="班级名称" prop="name">
<el-input v-model="clazzForm.name" placeholder="请输入班级名称" />
</el-form-item>
<el-form-item label="教室" prop="room">
<el-input v-model="clazzForm.room" placeholder="请输入教室" />
</el-form-item>
<el-form-item label="开课时间" prop="beginDate">
<el-date-picker
v-model="clazzForm.beginDate"
type="date"
placeholder="选择开课日期"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="结课时间" prop="endDate">
<el-date-picker
v-model="clazzForm.endDate"
type="date"
placeholder="选择结课日期"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="学科" prop="subject">
<el-select v-model="clazzForm.subject" placeholder="请选择学科" style="width: 100%">
<el-option
v-for="item in subjectOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="班主任ID">
<el-input
v-model.number="clazzForm.masterId"
type="number"
placeholder="请输入班主任ID"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<style scoped>
.app-container {
padding: 20px;
background-color: #f5f7fa;
min-height: 100vh;
}
.header {
background: #fff;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}
.header h2 {
margin: 0 0 20px 0;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
color: #333;
}
.actions {
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: space-between;
align-items: center;
}
.buttons {
display: flex;
gap: 10px;
margin-top: 10px;
}
.el-table {
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}
.pagination {
display: flex;
justify-content: center;
margin-top: 20px;
padding: 15px;
background: #fff;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}
.el-form-item {
margin-bottom: 18px;
}
@media (max-width: 768px) {
.actions {
flex-direction: column;
align-items: flex-start;
}
.buttons {
width: 100%;
justify-content: flex-start;
}
}
</style>
帮我分析下以上项目具体使用了什么技术,实现了什么功能,主要的难点是什么
最新发布