You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ExamSphere/admin/teacherInfo.vue

382 lines
13 KiB

<template>
<div style="line-height: 4;">
<el-row class="search-bar" justify="start" align="middle" >
<el-input placeholder="请输入关键词进行搜索" clearable v-model="keyword" class="search-input"
@keyup.enter="handleSearch"
suffix-icon="Search"
>
</el-input>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button type="primary" @click="handleAdd">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
<el-button type="danger" @click="handeleBatchDel">
<el-icon><Delete /></el-icon>
<span>批量删除</span>
</el-button>
</el-row>
<el-table :data="tableData" stripe style="width: 100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="ID" width="160" align="center" />
<el-table-column prop="username" label="用户名" width="160" align="center" />
<el-table-column prop="avatar" label="头像" align="center">
<template #default="{ row }">
<img
v-if="row.avatar"
:src="row.avatar"
alt="头像"
class="avatar-img"
/>
<span v-else>无头像</span>
</template>
</el-table-column>
<el-table-column prop="gender" label="性别" width="160" align="center" />
<el-table-column prop="email" label="邮箱" width="160" align="center" />
<el-table-column prop="address" label="地区" align="center" />
<el-table-column prop="mobile" label="手机" width="160" align="center" />
<el-table-column prop="role" label="角色" width="160" align="center" />
<el-table-column label="操作" width="160">
<template v-slot="scope">
<el-button type="success" plain @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="danger" plain @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="demo-pagination-block">
<el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" :page-sizes="[2, 4, 6, 8]"
layout="total, sizes, prev, pager, next, jumper" :total="total"
@size-change="handleSizeChange(pageSize)" @current-change="handleCurrentChange(pageNum)" />
</div>
<el-dialog v-model="isDialogVisibleAdd" title="添加用户" width="400px">
<el-form label-width="auto">
<el-upload class="avatar-uploader" action="http://localhost:8080/file/upload" :show-file-list="false"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
<img v-if="formData.avatar" width="100px" height="100px" :src="formData.avatar" class="avatar">
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
<el-form label-width="auto" style="max-width: 600px">
<el-form-item label="用户名">
<el-input v-model="formData.username" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="密码">
<el-input v-model="formData.password" placeholder="请输入密码" show-password />
</el-form-item>
<el-form-item label="性别">
<el-radio-group v-model="formData.gender">
<el-radio label="男">男</el-radio>
<el-radio label="女">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="formData.email" placeholder="请填写邮箱" />
</el-form-item>
<el-form-item label="地区">
<el-cascader :options="pcaTextArr" v-model="formData.address" placeholder="请选择地区"
:props="{ checkStrictly: true }" />
</el-form-item>
<el-form-item label="绑定手机">
<el-input v-model="formData.mobile" placeholder="请输入手机号" />
</el-form-item>
<el-form-item label="角色">
<el-radio-group v-model="formData.role">
<el-radio label="student">学生</el-radio>
<el-radio label="teacher">教师</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</el-form>
<template #footer>
<el-button @click="isDialogVisibleAdd = false">取消</el-button>
<el-button type="primary" @click="confirmAdd">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="isDialogVisibleEdit" title="编辑用户" width="400px">
<el-form label-width="auto">
<el-upload class="avatar-uploader" action="http://localhost:8080/file/upload" :show-file-list="false"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
<img v-if="formData.avatar" width="100px" height="100px" :src="formData.avatar" class="avatar">
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
<el-form label-width="auto" style="max-width: 600px">
<el-form-item label="用户名">
<el-input v-model="formData.username" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="密码">
<el-input v-model="formData.password" placeholder="请输入密码" show-password />
</el-form-item>
<el-form-item label="性别">
<el-radio-group v-model="formData.gender">
<el-radio label="男">男</el-radio>
<el-radio label="女">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="地区">
<el-cascader :options="pcaTextArr" v-model="formData.address" placeholder="请选择地区"
:props="{ checkStrictly: true }" />
</el-form-item>
<el-form-item label="绑定手机">
<el-input v-model="formData.mobile" placeholder="请输入手机号" />
</el-form-item>
<el-form-item label="角色">
<el-radio-group v-model="formData.role">
<el-radio label="user">用户</el-radio>
<el-radio label="admin">管理员</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</el-form>
<template #footer>
<el-button @click="isDialogVisibleEdit = false">取消</el-button>
<el-button type="primary" @click="confirmEdit">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="isDialogVisibleDelete" title="警告" width="500px" center>
<span>确定删除此用户信息吗?</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="isDialogVisibleDelete = false">取消</el-button>
<el-button type="primary" @click="confirmDelete()">
确定
</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="isDialogVisibleBatchDel" title="警告" width="500px" center>
<span>确定批量删除这些用户信息吗?</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="isDialogVisibleBatchDel=false">取消</el-button>
<el-button type="primary" @click="confirmBatchDel()">
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import request from '../../request';
import { onMounted } from 'vue';
import { pcaTextArr } from 'element-china-area-data';
import { ElMessage } from 'element-plus';
const isDialogVisibleAdd = ref(false)
const isDialogVisibleEdit = ref(false)
const isDialogVisibleDelete = ref(false)
const isDialogVisibleBatchDel = ref(false)
const multipleSelection = ref([])
const tableData = ref([])
const formData = reactive({
id: '',
username: '',
password: '',
gender: '',
email: '',
address: [],
mobile: '',
role: '',
avatar:'',
});
const keyword = ref('');
const pageNum = ref(1)
const pageSize = ref(6)
const total = ref(0)
const handleSearch = () => {
pageNum.value = 1; // 搜索时从第一页开始
loadPageData();
};
const loadPageData = () => {
request.get("http://localhost:8080/user/teacher?pageNum=" + pageNum.value + "&pageSize=" + pageSize.value +
"&keyword=" + keyword.value)
.then((res) => {
if (res.data.code == '200') {
tableData.value = res.data.data.records;
total.value = res.data.data.total;
}
})
.catch((err) => console.error(err));
};
const handleSizeChange = (newPageSize) => {
console.log(pageSize)
pageSize.value = newPageSize
loadPageData()
}
const handleCurrentChange = (newPageNum) => {
console.log(pageNum)
pageNum.value = newPageNum
loadPageData()
}
onMounted(() => {
loadPageData();
});
const handleAdd = () => {
formData.id = '';
formData.username = '';
formData.password = '';
formData.gender = '';
formData.email = '';
formData.address = [];
formData.mobile = '';
formData.role = '';
formData.avatar='';
isDialogVisibleAdd.value = true
}
const confirmAdd = () => {
request.post('http://localhost:8080/user', {
username: formData.username,
password: formData.password,
gender:formData.gender,
email: formData.email,
address: formData.address.join(' '),
mobile: formData.mobile,
role: formData.role,
avatar:formData.avatar
})
.then((res) => {
if (res.data.code == '200') {
ElMessage.success('用户信息新增成功');
loadPageData();
} else {
ElMessage.error('用户信息新增失败');
}
})
.catch((error) => {
console.error('用户信息新增失败:', error);
ElMessage.error('用户信息新增失败,请稍后再试');
});
isDialogVisibleAdd.value = false;
}
const handleEdit = (row) => {
const { id, username, password, gender, email, address, mobile, role, avatar } = row;
formData.id = id;
formData.username = username;
formData.password = password;
formData.gender = gender;
formData.email = email;
formData.address = address?address.split(' '):''; // 假设地址是用空格分隔的字符串
formData.mobile = mobile;
formData.role = role;
formData.avatar=avatar;
isDialogVisibleEdit.value = true
}
const confirmEdit = () => {
request.post("http://localhost:8080/user", {
id: formData.id,
username: formData.username,
password:formData.password,
gender: formData.gender,
email: formData.email,
address: formData.address?formData.address.join(' '):'',
mobile: formData.mobile,
role: formData.role,
avatar:formData.avatar
})
.then((res) => {
if (res.data.code == '200') {
ElMessage.success('用户信息修改成功');
loadPageData();
} else {
ElMessage.error('用户信息修改失败');
}
})
.catch((error) => {
console.error('用户信息修改失败:', error);
ElMessage.error('用户信息修改失败,请稍后再试');
});
isDialogVisibleEdit.value = false;
}
const delId = ref(-1)
const handleDelete = (row) => {
delId.value = row.id
isDialogVisibleDelete.value = true
}
const confirmDelete = () => {
request.delete(`http://localhost:8080/user/${delId.value}`).then(res => {
if (res.data.code == '200') {
ElMessage.success("删除成功")
loadPageData()
} else {
ElMessage.error("删除失败")
}
})
isDialogVisibleDelete.value = false
}
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
const handeleBatchDel = () => {
isDialogVisibleBatchDel.value = true
}
const confirmBatchDel = () => {
let ids = multipleSelection.value.map(v => v.id)
if(ids.length==0){
ElMessage.error("未选择任何用户信息,删除失败")
isDialogVisibleBatchDel.value = false
return;
}
request.post("http://localhost:8080/user/del/batch", ids).then(res => {
if (res.data.code == '200') {
ElMessage.success("批量删除成功")
loadPageData()
} else {
ElMessage.error("批量删除失败")
}
})
isDialogVisibleBatchDel.value = false
}
const handleAvatarSuccess = (response) => {
if (response && response.data) {
formData.avatar = response.data; // 后端返回完整路径
ElMessage.success("头像上传成功");
} else {
ElMessage.error("上传失败,请联系管理员");
}
};
const beforeAvatarUpload = (file) => {
const isJPGorPNG = file.type === 'image/jpeg' || file.type === 'image/png';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPGorPNG) {
ElMessage.error("上传头像图片只能是 JPG/PNG 格式!");
}
if (!isLt2M) {
ElMessage.error("上传头像图片大小不能超过 2MB!");
}
return isJPGorPNG && isLt2M;
};
</script>
<style scoped>
.search-bar {
width: 100%;
padding: 20px 30px;
display: flex;
justify-content: flex-start;
align-items: center;
gap: 20px;
}
.search-input {
width: 300px;
}
.demo-pagination-block+.demo-pagination-block {
margin-top: 10px;
}
.avatar-img{
width: 100px;
height: 100px
}
</style>