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.
382 lines
13 KiB
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/student?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> |