|
|
@ -0,0 +1,765 @@
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
|
|
import {onMounted, ref} from 'vue'
|
|
|
|
|
|
|
|
import {CirclePlusFilled, Delete, Edit, RefreshLeft, Search, UploadFilled} from "@element-plus/icons-vue"
|
|
|
|
|
|
|
|
import {deleteStudents, getStudentById, pageStudent, saveStudent, updateStudent, upload, download} from '@/api/student.js'
|
|
|
|
|
|
|
|
import {ElMessage, ElMessageBox} from "element-plus"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const tableData = ref([])
|
|
|
|
|
|
|
|
const total = ref(0)
|
|
|
|
|
|
|
|
const currentPage = ref(1)
|
|
|
|
|
|
|
|
const pageSize = ref(10)
|
|
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
|
|
const loadingEditDialog = ref(false)
|
|
|
|
|
|
|
|
const loadingSaveDialog = ref(false)
|
|
|
|
|
|
|
|
const loadingUpload = ref(false)
|
|
|
|
|
|
|
|
const loadingDownload = ref(false)
|
|
|
|
|
|
|
|
const addStudentDialogVisible = ref(false)
|
|
|
|
|
|
|
|
const editStudentDialogVisible = ref(false)
|
|
|
|
|
|
|
|
const ruleFormRef = ref()
|
|
|
|
|
|
|
|
const formSize = ref('default')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const pageQueryForm = ref({
|
|
|
|
|
|
|
|
no: '',
|
|
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
|
|
gender: '',
|
|
|
|
|
|
|
|
className: '',
|
|
|
|
|
|
|
|
exactQuery: false,
|
|
|
|
|
|
|
|
createTime: '',
|
|
|
|
|
|
|
|
updateTime: '',
|
|
|
|
|
|
|
|
orderBy: '',
|
|
|
|
|
|
|
|
orderRule: ''
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const studentForm = ref({
|
|
|
|
|
|
|
|
id: '',
|
|
|
|
|
|
|
|
no: '',
|
|
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
|
|
gender: '',
|
|
|
|
|
|
|
|
className: '',
|
|
|
|
|
|
|
|
points: ''
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const multipleSelection = ref([])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handlePageQuery = async ({prop = null, order = null}) => {
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (prop && order) {
|
|
|
|
|
|
|
|
if (prop !== 'Empty' && order !== 'Empty') {
|
|
|
|
|
|
|
|
pageQueryForm.value.orderBy = prop
|
|
|
|
|
|
|
|
pageQueryForm.value.orderRule = (order === 'ascending' ? 'ASC' : 'DESC')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
pageQueryForm.value.orderBy = ''
|
|
|
|
|
|
|
|
pageQueryForm.value.orderRule = ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const queryParams = {
|
|
|
|
|
|
|
|
...pageQueryForm.value,
|
|
|
|
|
|
|
|
page: currentPage.value,
|
|
|
|
|
|
|
|
pageSize: pageSize.value
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const response = await pageStudent(queryParams)
|
|
|
|
|
|
|
|
if (response.code === 1) {
|
|
|
|
|
|
|
|
tableData.value = response.data.records
|
|
|
|
|
|
|
|
total.value = response.data.total
|
|
|
|
|
|
|
|
// ElMessage.success('查询成功')
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error('查询失败,原因: ' + response.msg)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
|
|
handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const resetQueryForm = () => {
|
|
|
|
|
|
|
|
pageQueryForm.value = {
|
|
|
|
|
|
|
|
no: '',
|
|
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
|
|
gender: '',
|
|
|
|
|
|
|
|
major: '',
|
|
|
|
|
|
|
|
className: '',
|
|
|
|
|
|
|
|
exactQuery: false,
|
|
|
|
|
|
|
|
createTime: '',
|
|
|
|
|
|
|
|
updateTime: ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
currentPage.value = 1
|
|
|
|
|
|
|
|
handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const resetStudentForm = () => {
|
|
|
|
|
|
|
|
studentForm.value = {
|
|
|
|
|
|
|
|
no: '',
|
|
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
|
|
gender: '',
|
|
|
|
|
|
|
|
major: '',
|
|
|
|
|
|
|
|
className: '',
|
|
|
|
|
|
|
|
points: ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleSelectionChange = (val) => {
|
|
|
|
|
|
|
|
multipleSelection.value = val
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleDelete = (row) => {
|
|
|
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
|
|
|
'删除不可撤销,继续吗?',
|
|
|
|
|
|
|
|
'警告',
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
confirmButtonText: '继续',
|
|
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
|
|
type: 'warning',
|
|
|
|
|
|
|
|
}).then(async () => {
|
|
|
|
|
|
|
|
const response = await deleteStudents(row.id)
|
|
|
|
|
|
|
|
if (response.code == 1) {
|
|
|
|
|
|
|
|
ElMessage.success('删除成功')
|
|
|
|
|
|
|
|
await handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error('删除失败')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
|
|
ElMessage.info('删除取消')
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleBatchDelete = () => {
|
|
|
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
|
|
|
'删除不可撤销,继续吗?',
|
|
|
|
|
|
|
|
'警告',
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
confirmButtonText: '继续',
|
|
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
|
|
type: 'warning',
|
|
|
|
|
|
|
|
}).then(async () => {
|
|
|
|
|
|
|
|
const ids = multipleSelection.value.map(item => item.id)
|
|
|
|
|
|
|
|
const response = await deleteStudents(ids)
|
|
|
|
|
|
|
|
if (response.code === 1) {
|
|
|
|
|
|
|
|
ElMessage.success('删除成功')
|
|
|
|
|
|
|
|
await handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error('删除失败')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
|
|
ElMessage.info('删除取消')
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleAddStudent = async () => {
|
|
|
|
|
|
|
|
if (!ruleFormRef.value) return
|
|
|
|
|
|
|
|
await ruleFormRef.value.validate(async (valid, fields) => {
|
|
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
|
|
|
loadingSaveDialog.value = true
|
|
|
|
|
|
|
|
const response = await saveStudent(studentForm.value)
|
|
|
|
|
|
|
|
if (response.code === 1) {
|
|
|
|
|
|
|
|
ElMessage.success('保存成功')
|
|
|
|
|
|
|
|
addStudentDialogVisible.value = false
|
|
|
|
|
|
|
|
await handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(response.msg || '保存失败')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
loadingSaveDialog.value = false
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleEditStudent = async (row) => {
|
|
|
|
|
|
|
|
loadingEditDialog.value = true
|
|
|
|
|
|
|
|
resetStudentForm()
|
|
|
|
|
|
|
|
editStudentDialogVisible.value = true
|
|
|
|
|
|
|
|
const response = await getStudentById(row.id)
|
|
|
|
|
|
|
|
// console.log(response.data.className)
|
|
|
|
|
|
|
|
studentForm.value = {
|
|
|
|
|
|
|
|
...response.data,
|
|
|
|
|
|
|
|
className: response.data.className.toString(),
|
|
|
|
|
|
|
|
points: response.data.points.toString()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
loadingEditDialog.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleCommitStudent = async () => {
|
|
|
|
|
|
|
|
if (!ruleFormRef.value) return
|
|
|
|
|
|
|
|
await ruleFormRef.value.validate(async (valid, fields) => {
|
|
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
|
|
|
loadingSaveDialog.value = true
|
|
|
|
|
|
|
|
const response = await updateStudent(studentForm.value)
|
|
|
|
|
|
|
|
if (response.code === 1) {
|
|
|
|
|
|
|
|
ElMessage.success('保存成功')
|
|
|
|
|
|
|
|
editStudentDialogVisible.value = false
|
|
|
|
|
|
|
|
await handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(response.msg || '保存失败')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
loadingSaveDialog.value = false
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleSizeChange = (val) => {
|
|
|
|
|
|
|
|
pageSize.value = val
|
|
|
|
|
|
|
|
currentPage.value = 1
|
|
|
|
|
|
|
|
handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleCurrentChange = (val) => {
|
|
|
|
|
|
|
|
currentPage.value = val
|
|
|
|
|
|
|
|
handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const rules = {
|
|
|
|
|
|
|
|
no: [
|
|
|
|
|
|
|
|
{required: true, message: '请输入学号', trigger: 'change'},
|
|
|
|
|
|
|
|
{max: 20, message: '最大长度应为 20 个字符', trigger: 'change'}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
name: [
|
|
|
|
|
|
|
|
{required: true, message: '请输入姓名', trigger: 'change'},
|
|
|
|
|
|
|
|
{max: 20, message: '最大长度为 20 个字符', trigger: 'change'}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
gender: [
|
|
|
|
|
|
|
|
{required: true, message: '请输入选择性别', trigger: 'change'}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
className: [
|
|
|
|
|
|
|
|
{required: false, message: '请输入班级', trigger: 'change'},
|
|
|
|
|
|
|
|
{max: 20, message: '最大长度为 20 个字符', trigger: 'change'}
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
points: [
|
|
|
|
|
|
|
|
{max: 16, message: '最大为 16 位', trigger: 'change'}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const formatGender = (row) => {
|
|
|
|
|
|
|
|
return row.gender === 0 ? '男' : '女'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const gender_options = [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
value: '',
|
|
|
|
|
|
|
|
label: '全部'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
value: '0',
|
|
|
|
|
|
|
|
label: '男'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
value: '1',
|
|
|
|
|
|
|
|
label: '女'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const shortcuts = [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text: '近一周',
|
|
|
|
|
|
|
|
value: () => {
|
|
|
|
|
|
|
|
const end = new Date()
|
|
|
|
|
|
|
|
const start = new Date()
|
|
|
|
|
|
|
|
start.setDate(start.getDate() - 7)
|
|
|
|
|
|
|
|
return [start, end]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text: '近一月',
|
|
|
|
|
|
|
|
value: () => {
|
|
|
|
|
|
|
|
const end = new Date()
|
|
|
|
|
|
|
|
const start = new Date()
|
|
|
|
|
|
|
|
start.setMonth(start.getMonth() - 1)
|
|
|
|
|
|
|
|
return [start, end]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text: '近三月',
|
|
|
|
|
|
|
|
value: () => {
|
|
|
|
|
|
|
|
const end = new Date()
|
|
|
|
|
|
|
|
const start = new Date()
|
|
|
|
|
|
|
|
start.setMonth(start.getMonth() - 3)
|
|
|
|
|
|
|
|
return [start, end]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const beforeUpload = (file) => {
|
|
|
|
|
|
|
|
const isExcel = file.type === 'application/vnd.ms-excel' ||
|
|
|
|
|
|
|
|
file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
|
|
|
|
|
|
if (!isExcel) {
|
|
|
|
|
|
|
|
ElMessage.error('只能上传 Excel 文件!')
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleUpload = async ({file}) => {
|
|
|
|
|
|
|
|
loadingUpload.value = true
|
|
|
|
|
|
|
|
const formData = new FormData()
|
|
|
|
|
|
|
|
formData.append('file', file)
|
|
|
|
|
|
|
|
const response = await upload(formData)
|
|
|
|
|
|
|
|
if (response.code === 1) {
|
|
|
|
|
|
|
|
ElMessage.success('导入成功')
|
|
|
|
|
|
|
|
await handlePageQuery({prop: 'Empty', order: 'Empty'})
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error('导入失败,原因: ' + response.msg)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
loadingUpload.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleDownload = async () => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
loadingDownload.value = true
|
|
|
|
|
|
|
|
const response = await download();
|
|
|
|
|
|
|
|
const blob = new Blob([response.data], { type: response.data.type });
|
|
|
|
|
|
|
|
const downloadLink = document.createElement('a');
|
|
|
|
|
|
|
|
downloadLink.href = URL.createObjectURL(blob);
|
|
|
|
|
|
|
|
downloadLink.download = 'students.xlsx';
|
|
|
|
|
|
|
|
document.body.appendChild(downloadLink);
|
|
|
|
|
|
|
|
downloadLink.click();
|
|
|
|
|
|
|
|
document.body.removeChild(downloadLink);
|
|
|
|
|
|
|
|
ElMessage.success('导出成功');
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error('Download failed:', error);
|
|
|
|
|
|
|
|
ElMessage.error('导出失败');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
loadingDownload.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
|
|
<el-card v-loading="loading">
|
|
|
|
|
|
|
|
<div class="query-form">
|
|
|
|
|
|
|
|
<el-form :model="pageQueryForm" label-width="80px" class="filter-form">
|
|
|
|
|
|
|
|
<!-- 第一行:学号、姓名、性别 -->
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
|
|
|
<el-form-item label="学号">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model="pageQueryForm.no"
|
|
|
|
|
|
|
|
placeholder="请输入学号"
|
|
|
|
|
|
|
|
clearable
|
|
|
|
|
|
|
|
class="custom-input"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="姓名">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model="pageQueryForm.name"
|
|
|
|
|
|
|
|
placeholder="请输入姓名"
|
|
|
|
|
|
|
|
clearable
|
|
|
|
|
|
|
|
class="custom-input"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="性别">
|
|
|
|
|
|
|
|
<el-select
|
|
|
|
|
|
|
|
v-model="pageQueryForm.gender"
|
|
|
|
|
|
|
|
placeholder="请选择性别"
|
|
|
|
|
|
|
|
clearable
|
|
|
|
|
|
|
|
class="custom-input"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-option
|
|
|
|
|
|
|
|
v-for="item in gender_options"
|
|
|
|
|
|
|
|
:key="item.value"
|
|
|
|
|
|
|
|
:label="item.label"
|
|
|
|
|
|
|
|
:value="item.value"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 第二行:时间 -->
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
|
|
|
<el-form-item label="创建时间" class="date-item">
|
|
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
|
|
v-model="pageQueryForm.createTime"
|
|
|
|
|
|
|
|
type="datetimerange"
|
|
|
|
|
|
|
|
:shortcuts="shortcuts"
|
|
|
|
|
|
|
|
range-separator="至"
|
|
|
|
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
|
|
|
|
class="date-picker"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item label="最后操作" class="date-item">
|
|
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
|
|
v-model="pageQueryForm.updateTime"
|
|
|
|
|
|
|
|
type="datetimerange"
|
|
|
|
|
|
|
|
:shortcuts="shortcuts"
|
|
|
|
|
|
|
|
range-separator="至"
|
|
|
|
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
|
|
|
|
class="date-picker"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 第三行:按钮 -->
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
|
|
|
<div class="button-wrapper">
|
|
|
|
|
|
|
|
<el-button type="primary" :icon="Search" @click="handlePageQuery({prop: 'Empty', order: 'Empty'})">查询</el-button>
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
|
|
@click="resetQueryForm"
|
|
|
|
|
|
|
|
:icon="RefreshLeft"
|
|
|
|
|
|
|
|
:disabled="pageQueryForm.no === '' && pageQueryForm.name === '' &&
|
|
|
|
|
|
|
|
pageQueryForm.className === '' && pageQueryForm.exactQuery === false && pageQueryForm.gender === '' &&
|
|
|
|
|
|
|
|
pageQueryForm.updateTime === '' && pageQueryForm.createTime === ''"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
重置
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="table-toolbar">
|
|
|
|
|
|
|
|
<el-button type="danger" :icon="Delete" @click="handleBatchDelete" :disabled="!multipleSelection.length">
|
|
|
|
|
|
|
|
批量删除
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" :icon="CirclePlusFilled" @click="resetStudentForm(); addStudentDialogVisible = true">
|
|
|
|
|
|
|
|
新增学生
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
<el-upload
|
|
|
|
|
|
|
|
:auto-upload="true"
|
|
|
|
|
|
|
|
:show-file-list="false"
|
|
|
|
|
|
|
|
:http-request="handleUpload"
|
|
|
|
|
|
|
|
:before-upload="beforeUpload"
|
|
|
|
|
|
|
|
accept=".xlsx,.xls"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-button type="primary" :icon="UploadFilled" style="margin-left: 12px" :loading="loadingUpload">
|
|
|
|
|
|
|
|
导 入
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</el-upload>
|
|
|
|
|
|
|
|
<el-button type="primary" style="margin-left: 12px" @click="handleDownload" :loading="loadingDownload">
|
|
|
|
|
|
|
|
<i class="iconfont yaya-download" style="font-size: 10px"></i>
|
|
|
|
|
|
|
|
导 出
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-table
|
|
|
|
|
|
|
|
:data="tableData"
|
|
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
|
|
@selection-change="handleSelectionChange"
|
|
|
|
|
|
|
|
@sort-change="handlePageQuery"
|
|
|
|
|
|
|
|
border
|
|
|
|
|
|
|
|
stripe
|
|
|
|
|
|
|
|
class="student-table"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-table-column type="selection" width="40"/>
|
|
|
|
|
|
|
|
<el-table-column prop="no" label="学号" sortable="custom" width="120" show-overflow-tooltip/>
|
|
|
|
|
|
|
|
<el-table-column prop="name" label="姓名" sortable="custom" width="120" show-overflow-tooltip/>
|
|
|
|
|
|
|
|
<el-table-column prop="gender" label="性别" :formatter="formatGender" sortable="custom"/>
|
|
|
|
|
|
|
|
<el-table-column prop="className" label="班级" sortable="custom" width="120" show-overflow-tooltip/>
|
|
|
|
|
|
|
|
<el-table-column prop="points" label="积分" sortable="custom" show-overflow-tooltip/>
|
|
|
|
|
|
|
|
<el-table-column prop="createTime" label="创建时间" sortable="custom" width="180"/>
|
|
|
|
|
|
|
|
<el-table-column prop="updateTime" label="最后操作时间" sortable="custom" width="180"/>
|
|
|
|
|
|
|
|
<el-table-column label="操作" width="120" fixed="right">
|
|
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
|
|
<el-button type="primary" :icon="Edit" circle title="编辑" @click="handleEditStudent(scope.row)"/>
|
|
|
|
|
|
|
|
<el-button type="danger" :icon="Delete" circle @click="handleDelete(scope.row)" title="删除"/>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
<div class="pagination-container">
|
|
|
|
|
|
|
|
<el-pagination
|
|
|
|
|
|
|
|
v-model:current-page="currentPage"
|
|
|
|
|
|
|
|
v-model:page-size="pageSize"
|
|
|
|
|
|
|
|
:page-sizes="[10, 20, 30, 40]"
|
|
|
|
|
|
|
|
:total="total"
|
|
|
|
|
|
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
|
|
|
|
|
|
@size-change="handleSizeChange"
|
|
|
|
|
|
|
|
@current-change="handleCurrentChange"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-dialog
|
|
|
|
|
|
|
|
v-model="addStudentDialogVisible"
|
|
|
|
|
|
|
|
title="新增学生"
|
|
|
|
|
|
|
|
width="460px"
|
|
|
|
|
|
|
|
:close-on-click-modal="false"
|
|
|
|
|
|
|
|
destroy-on-close
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-form
|
|
|
|
|
|
|
|
ref="ruleFormRef"
|
|
|
|
|
|
|
|
:model="studentForm"
|
|
|
|
|
|
|
|
:rules="rules"
|
|
|
|
|
|
|
|
label-position="right"
|
|
|
|
|
|
|
|
label-width="80px"
|
|
|
|
|
|
|
|
:size="formSize"
|
|
|
|
|
|
|
|
status-icon
|
|
|
|
|
|
|
|
class="add-student-form"
|
|
|
|
|
|
|
|
v-loading="loadingSaveDialog"
|
|
|
|
|
|
|
|
element-loading-text="保存中..."
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-form-item label="学号" prop="no">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.no"
|
|
|
|
|
|
|
|
placeholder="请输入学号"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="姓名" prop="name">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.name"
|
|
|
|
|
|
|
|
placeholder="请输入姓名"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="性别" prop="gender">
|
|
|
|
|
|
|
|
<el-radio-group v-model="studentForm.gender">
|
|
|
|
|
|
|
|
<el-radio-button :value="0">男</el-radio-button>
|
|
|
|
|
|
|
|
<el-radio-button :value="1">女</el-radio-button>
|
|
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="班级" prop="className">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.className"
|
|
|
|
|
|
|
|
placeholder="请输入班级"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="积分" prop="points">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.points"
|
|
|
|
|
|
|
|
placeholder="请输入积分,默认为 0"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<div class="dialog-footer">
|
|
|
|
|
|
|
|
<el-button @click="addStudentDialogVisible = false">取 消</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="handleAddStudent">
|
|
|
|
|
|
|
|
确 定
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 编辑学生信息-->
|
|
|
|
|
|
|
|
<el-dialog
|
|
|
|
|
|
|
|
v-model="editStudentDialogVisible"
|
|
|
|
|
|
|
|
title="编辑学生"
|
|
|
|
|
|
|
|
width="460px"
|
|
|
|
|
|
|
|
:close-on-click-modal="false"
|
|
|
|
|
|
|
|
destroy-on-close
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-form
|
|
|
|
|
|
|
|
ref="ruleFormRef"
|
|
|
|
|
|
|
|
:model="studentForm"
|
|
|
|
|
|
|
|
:rules="rules"
|
|
|
|
|
|
|
|
label-position="right"
|
|
|
|
|
|
|
|
label-width="80px"
|
|
|
|
|
|
|
|
:size="formSize"
|
|
|
|
|
|
|
|
status-icon
|
|
|
|
|
|
|
|
v-loading="loadingEditDialog"
|
|
|
|
|
|
|
|
element-loading-text="加载中..."
|
|
|
|
|
|
|
|
class="edit-student-form"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-form-item label="学 号" prop="no">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.no"
|
|
|
|
|
|
|
|
placeholder="请输入学号"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="姓 名" prop="name">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.name"
|
|
|
|
|
|
|
|
placeholder="请输入姓名"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="性别" prop="gender">
|
|
|
|
|
|
|
|
<el-radio-group v-model="studentForm.gender">
|
|
|
|
|
|
|
|
<el-radio-button :value="0">男</el-radio-button>
|
|
|
|
|
|
|
|
<el-radio-button :value="1">女</el-radio-button>
|
|
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="班级" prop="className">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.className"
|
|
|
|
|
|
|
|
placeholder="请输入班级"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-form-item label="积分" prop="points">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-model.trim="studentForm.points"
|
|
|
|
|
|
|
|
placeholder="请输入积分,默认为 0"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<div class="dialog-footer">
|
|
|
|
|
|
|
|
<el-button @click="editStudentDialogVisible = false">取 消</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="handleCommitStudent" :loading="loadingSaveDialog">
|
|
|
|
|
|
|
|
确 定
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
|
|
.query-form {
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.filter-form {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.form-row {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.form-row :deep(.el-form-item) {
|
|
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.button-wrapper {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.date-item {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.custom-input {
|
|
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.date-picker {
|
|
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-form-item__label) {
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input__wrapper),
|
|
|
|
|
|
|
|
:deep(.el-select__wrapper) {
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 1px #dcdfe6 inset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input__wrapper:hover),
|
|
|
|
|
|
|
|
:deep(.el-select__wrapper:hover) {
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 1px #c0c4cc inset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 调整日期选择器的响应式布局 */
|
|
|
|
|
|
|
|
@media screen and (max-width: 1400px) {
|
|
|
|
|
|
|
|
.date-item {
|
|
|
|
|
|
|
|
flex: 0 0 calc(50% - 10px);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.date-picker {
|
|
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.form-buttons {
|
|
|
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.student-table :deep(th) {
|
|
|
|
|
|
|
|
text-align: center !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.student-table :deep(.cell) {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.table-toolbar {
|
|
|
|
|
|
|
|
margin: 16px 0;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-container {
|
|
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-card__body) {
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-form-item) {
|
|
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-table) {
|
|
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-dialog {
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-dialog__body {
|
|
|
|
|
|
|
|
padding: 20px 40px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-form-item {
|
|
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-form-item:last-child {
|
|
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.dialog-footer {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
padding-top: 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.dialog-footer .el-button {
|
|
|
|
|
|
|
|
min-width: 100px;
|
|
|
|
|
|
|
|
margin-left: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-form-item :deep(.el-form-item__content) {
|
|
|
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 调整输入框宽度 */
|
|
|
|
|
|
|
|
.el-input {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 确保单选按钮组对齐 */
|
|
|
|
|
|
|
|
.el-radio-group {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.edit-student-form {
|
|
|
|
|
|
|
|
min-height: 300px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.add-student-form {
|
|
|
|
|
|
|
|
min-height: 300px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|