初学vue的时候写的,采用的是npm形式引入vue和element-ui,后端逻辑使用Django来写的,对于测试开发学习些测试平台,是个很好的入门文章。
写完后台的样子如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="./css/index.css">
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js">script>
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
head>
<body>
<div id="app">
<el-container>
<el-header style="height: 80px;">学习信息管理系统el-header>
<el-container>
<el-aside width="200px">
<el-menu default-active="2" class="el-menu-vertical-demo">
<el-menu-item index="1">
<i class="el-icon-menu">i>
<span slot="title">班级管理span>
el-menu-item>
<el-menu-item index="2">
<i class="el-icon-user">i>
<span slot="title">学生信息span>
el-menu-item>
<el-menu-item index="3">
<i class="el-icon-s-custom">i>
<span slot="title">讲师信息span>
el-menu-item>
<el-menu-item index="4">
<i class="el-icon-document">i>
<span slot="title">课程管理span>
el-menu-item>
el-menu>
el-aside>
<el-container>
<el-main>
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首页el-breadcrumb-item>
<el-breadcrumb-item>学生信息el-breadcrumb-item>
el-breadcrumb>
<el-form :inline="true" style="margin-top: 40px;">
<el-row>
<el-col :span="12">
<el-form-item label="查询条件:">
<el-input v-model="inputStr" placeholder="请输入查询条件" style="width: 320px;">
el-input>
el-form-item>
el-col>
<el-col :span="8" style="text-align: right;padding-right: 10px;">
<el-button-group>
<el-button type="primary" icon="el-icon-search" @click="queryStudents()">查询
el-button>
<el-button type="primary" icon="el-icon-document-copy"
@click="getAllStudents()">全部el-button>
<el-button type="primary" icon="el-icon-circle-plus-outline"
@click="addStudent()">添加el-button>
el-button-group>
el-col>
<el-col :span="2">
<el-upload :show-file-list="false" :http-request="uploadExcelPost">
<el-button type="primary">导入Excelel-button>
el-upload>
el-col>
<el-col :span="2">
<el-upload>
<el-button type="primary" @click="exportToExcel()">导出Excelel-button>
el-upload>
el-col>
el-row>
el-form>
<el-table :data="pageStudents" border style="width: 100%" size="mini"
@selection-change="handleSelectionChange">
<el-table-column type="selection">
el-table-column>
<el-table-column type="index" label="序号" align="center" width="60">
el-table-column>
<el-table-column prop="sno" label="学号" align="center" width="80">
el-table-column>
<el-table-column prop="name" label="姓名" align="center" width="80">
el-table-column>
<el-table-column prop="gender" label="性别" align="center" width="80">
el-table-column>
<el-table-column prop="birthday" label="出生日期" align="center" width="120">
el-table-column>
<el-table-column prop="mobile" label="手机号码" align="center" width="120">
el-table-column>
<el-table-column prop="email" label="邮箱地址" width="160">
el-table-column>
<el-table-column prop="address" label="住址">
el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button type="success" icon="el-icon-more" @click="viewStudent(scope.row)"
circle>el-button>
<el-button type="primary" icon="el-icon-edit" @click="updateStudent(scope.row)"
circle>el-button>
<el-button type="danger" icon="el-icon-delete" @click="deleteStudent(scope.row)"
circle>el-button>
template>
el-table-column>
el-table>
<el-row style="margin-top: 10px;" size="mini">
<el-col :span="8" style="text-align: left;">
<el-button type="danger" icon="el-icon-delete" @click="deleteStudents()">批量删除
el-button>
el-col>
<el-col :span="16" style="text-align: right;">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="currentpage" :page-sizes="[5, 10, 50, 100]" :page-size="pagesize"
layout="total, sizes, prev, pager, next, jumper" :total="total">
el-pagination>
el-col>
el-row>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="50%"
:close-on-click-modal="false" @close="closeDialogForm('studentForm')">
<el-form :model="studentForm" :rules="rules" :inline="true" ref="studentForm"
tyle="margin-left: 20px;" label-width="110px" label-position="right" size="mini">
<el-upload class="avatar-uploader" :show-file-list="false"
:http-request="uploadPicturePost" :disabled="isView" style="text-align: center; margin: 20px;">
<img v-if="studentForm.image" :src="studentForm.imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon">i>
el-upload>
<el-form-item label="学号:" prop="sno">
<el-input v-model="studentForm.sno" :disabled="isView||isEdit"
suffix-icon="el-icon-edit">el-input>
el-form-item>
<el-form-item label="姓名:" prop="name">
<el-input v-model="studentForm.name" :disabled="isView" suffix-icon="el-icon-edit">
el-input>
el-form-item>
<el-form-item label="性别:" prop="gender">
<el-select v-model="studentForm.gender" :disabled="isView" placeholder="请选择性别">
<el-option label="男" value="男">el-option>
<el-option label="女" value="女">el-option>
el-select>
el-form-item>
<el-form-item label="选择日期:" prop="birthday">
<el-date-picker v-model="studentForm.birthday" value-format="yyyy-MM-dd"
:disabled="isView" type="date" placeholder="选择日期" style="width: 93%;">
el-date-picker>
el-form-item>
<el-form-item label="手机号码:" prop="mobile">
<el-input v-model="studentForm.mobile" :disabled="isView"
suffix-icon="el-icon-edit">el-input>
el-form-item>
<el-form-item label="邮箱地址:" prop="email">
<el-input v-model="studentForm.email" :disabled="isView" suffix-icon="el-icon-edit">
el-input>
el-form-item>
<el-form-item label="家庭住址:" prop="address">
<el-input v-model="studentForm.address" :disabled="isView"
suffix-icon="el-icon-edit" style="width: 272%;">el-input>
el-form-item>
el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" v-show="!isView"
@click="submitStudentForm('studentForm')">确定el-button>
<el-button type="info" size="mini" @click="closeDialogForm('studentForm')">取消
el-button>
span>
el-dialog>
el-main>
<el-footer style="height: 30px;">学习信息管理系统 版权所有:2020-09-22el-footer>
el-container>
el-container>
el-container>
div>
body>
html>
<script src="./js/index.js">script>
const app = new Vue({
el: '#app',
data() {
//校验学号是否存在!
const rulesSNo = (rule, value, callback) => {
if (this.isEdit) {
callback();
}
axios.post(
this.baseURL + "sno/check/",
{
sno: value,
}
)
.then((res) => {
if (res.data.code === 200) {
if (res.data.exists) {
callback(new Error("学号已经存在!"))
} else {
callback();
}
} else {
callback(new Error("校验学号后端出现异常"))
}
}
)
.catch();
}
return {
msg: 'hello, vue!!!',
students: [], // 学生数量
pageStudents: [], //分页后的每页学生数量
selectStudents: [], //选择复选框选择时选中的学生
baseURL: "http://127.0.0.1:8000/",
total: 0,
currentpage: 1,
pagesize: 10,
inputStr: "",
dialogVisible: false,
dialogTitle: "",
isEdit: false,
isView: false,
studentForm: {
sno: "",
name: "",
gender: "",
birthday: "",
mobile: "",
email: "",
address: "",
image: "",
imageUrl: "",
},
rules: {
sno: [
{ required: true, message: "学号不能为空", trigger: "blur" },
{ pattern: /^[9][5]\d{3}/, message: "学号必须是95开头的五位数", trigger: "blur" },
{ validator: rulesSNo, trigger: "blur" },
],
name: [
{ required: true, message: "姓名不能为空", trigger: "blur" },
{ pattern: /^[\u4e00-\u9fa5]{2,5}$/, message: "姓名必须是2到5个汉字", trigger: "blur" },
],
gender: [
{ required: true, message: "性别不能为空", trigger: "change" },
],
birthday: [
{ required: true, message: "出生日期不能为空", trigger: "change" },
],
mobile: [
{ required: true, message: "手机号码不能为空", trigger: "blur" },
{ pattern: /^[1][35789]\d{9}$/, message: "手机号码必须要符合规范", trigger: "blur" },
],
email: [
{ required: true, message: "邮箱地址不能为空", trigger: "blur" },
{ pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/, message: "邮箱地址必须要符合规范", trigger: "blur" },
],
address: [
{ required: true, message: "家庭地址不能为空", trigger: "blur" },
],
},
}
},
mounted() {
//获取所有学生信息
this.getStudents();
},
methods: {
//获取所有学生的信息
getStudents: function () {
//记录this的地址
let that = this
//使用Axios实现Ajax请求
axios
.get(that.baseURL + "student/")
.then(function (res) {
//把数据给students
if (res.data.code == 200) {
//把数据给students
that.students = res.data.data;
that.total = res.data.data.length;
that.getPageStudents();
//提示
that.$message({
showClose: true,
message: '数据加载成功',
type: 'success'
});
} else {
that.$message({
showClose: true,
message: '错了哦,这是一条错误消息',
type: 'error'
});
}
})
.catch(function (err) {
console.log(err);
});
},
//获得当前页的数据
getPageStudents() {
//清空pageStudents中的数据
this.pageStudents = [];
for (let i = (this.currentpage - 1) * this.pagesize; i < this.total; i++) {
this.pageStudents.push(this.students[i]);
if (this.pageStudents.length == this.pagesize) break;
}
},
//查询全部
getAllStudents() {
this.inputStr = "";
this.getStudents();
},
//根据学号查询
getImageBySno(sno) {
for (oneStudent of this.students) {
if (oneStudent.sno == sno) {
return oneStudent.image;
}
}
},
//添加学生信息
addStudent(row) {
this.dialogTitle = "添加学生信息";
this.dialogVisible = true;
},
//查看学生信息
viewStudent(row) {
this.dialogTitle = "查看学生信息";
this.dialogVisible = true;
this.isView = true;
this.studentForm = JSON.parse(JSON.stringify(row));
this.studentForm.image = this.getImageBySno(row.sno);
this.studentForm.imageUrl = this.baseURL + 'media/' + this.studentForm.image;
},
//更新学生信息
updateStudent(row) {
this.dialogTitle = "更新学生信息";
this.dialogVisible = true;
this.isEdit = true;
this.studentForm = JSON.parse(JSON.stringify(row))
this.studentForm.image = this.getImageBySno(row.sno);
this.studentForm.imageUrl = this.baseURL + 'media/' + this.studentForm.image;
},
closeDialogForm(formName) {
//重置表单校验
this.$refs[formName].resetFields();
//清空
this.studentForm.sno = "";
this.studentForm.name = "";
this.studentForm.gender = "";
this.studentForm.birthday = "";
this.studentForm.mobile = "";
this.studentForm.email = "";
this.studentForm.address = "";
this.studentForm.image = "";
this.studentForm.imageUrl = "";
this.dialogVisible = false;
this.isEdit = false;
this.isView = false;
},
submitStudentForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
if (this.isEdit) {
//修改
this.sumbitUpdateStudent();
} else {
//添加
this.submitAddStudent();
}
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
//添加到数据库的函数
submitAddStudent() {
let that = this;
axios
.post(that.baseURL + 'student/add/', that.studentForm)
.then(res => {
//执行成功
if (res.data.code === 200) {
// 获取所有学生信息
that.students = res.data.data;
// 获取记录条数
that.total = res.data.data.length;
// 获取分页信息
that.getPageStudents();
//提示
that.$message({
message: '数据修改成功',
type: 'success'
});
// 关闭dialo弹窗
this.closeDialogForm('studentForm');
} else {
that.$message.error(res.data.msg);
}
})
.catch(err => {
console.log(err);
that.$message.error("修改时获取后端数据异常");
})
},
//修改更新到数据库
sumbitUpdateStudent() {
let that = this;
axios
.post(that.baseURL + 'student/update/', that.studentForm)
.then(res => {
//执行成功
if (res.data.code === 200) {
// 获取所有学生信息
that.students = res.data.data;
// 获取记录条数
that.total = res.data.data.length;
// 获取分页信息
that.getPageStudents();
//提示
that.$message({
message: '数据加载成功',
type: 'success'
});
// 关闭dialo弹窗
this.closeDialogForm('studentForm');
} else {
that.$message.error(res.data.msg);
}
})
.catch(err => {
console.log(err);
that.$message.error("获取后端数据异常");
})
},
deleteStudent(row) {
//等待确认
this.$confirm('是否确认删除学生信息【学号:' + row.sno + '\t姓名:' + row.name + '】', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//确认删除响应事件
let that = this
//调用后端接口
axios.post(that.baseURL + 'student/delete/', { sno: row.sno })
.then(res => {
//执行成功
if (res.data.code === 200) {
// 获取所有学生信息
that.students = res.data.data;
// 获取记录条数
that.total = res.data.data.length;
// 获取分页信息
that.getPageStudents();
//提示
that.$message({
message: '数据删除成功',
type: 'success'
});
} else {
that.$message.error(res.data.msg);
}
})
.catch(err => {
console.log(err);
that.$message.error("删除数据时后端数据异常: " + str(err));
});
this.$message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
//批量删除
deleteStudents(row) {
//等待确认
this.$confirm('是否确认删除' + this.selectStudents.length + '个学生信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//确认删除响应事件
let that = this
//调用后端接口
axios.post(that.baseURL + 'students/delete/', { student: that.selectStudents })
.then(res => {
//执行成功
if (res.data.code === 200) {
// 获取所有学生信息
that.students = res.data.data;
// 获取记录条数
that.total = res.data.data.length;
// 获取分页信息
that.getPageStudents();
//提示
that.$message({
message: '数据批量删除成功',
type: 'success'
});
} else {
that.$message.error(res.data.msg);
}
})
.catch(err => {
console.log(err);
that.$message.error("删除数据时后端数据异常: " + err);
});
this.$message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
//选择学生头像后点击确定触发的事件
uploadPicturePost(file) {
let that = this;
// 定义一个formdata的类
let fileReq = new FormData();
//把照片传进去
fileReq.append('avatar', file.file);
//使用Axios发起Ajax请求
axios({
method: 'post',
url: that.baseURL + 'upload/',
data: fileReq
}).then(res => {
//根据code判断是否成功
if (res.data.code === 200) {
that.studentForm.image = res.data.name;
that.studentForm.imageUrl = that.baseURL + 'media/' + res.data.name;
that.$message({
message: '上传头像成功',
type: 'success'
});
} else {
//失败提示
that.$message.error(res.data.msg);
}
}).catch(err => {
console.log(err);
that.$message.error("上传头像时后端数据异常: " + err);
});
},
//查询学生信息
queryStudents() {
// 使用ajax请求,post传递inputstr
let that = this
axios
.post(
that.baseURL + "student/query/",
{
inputstr: that.inputStr
}
)
.then(function (res) {
if (res.data.code == 200) {
that.students = res.data.data;
that.total = res.data.data.length;
that.getPageStudents();
//提示
that.$message({
showClose: true,
message: '数据加载成功',
type: 'success'
});
} else {
that.$message({
showClose: true,
message: '错了哦,这是一条错误消息',
type: 'error'
});
}
})
.catch(function (err) {
console.log(err);
that.$message({
showClose: true,
message: err,
type: 'error'
});
});
},
//上传excel文件
uploadExcelPost(file) {
let that = this;
let fileReq = new FormData();
fileReq.append('excel', file.file);
//使用Axios发起Ajax请求
axios({
method: 'post',
url: that.baseURL + 'excel/import/',
data: fileReq
}).then(res => {
//根据code判断是否成功
if (res.data.code === 200) {
that.students = res.data.data;
that.total = res.data.data.length;
//分页
that.getPageStudents();
//弹出框体显示结果
this.$alert('本次导入完成,成功:' + res.data.success + " 失败: " + res.data.error, '导入结果展示', {
confirmButtonText: '确定',
});
//打印失败明细
console.log("本次导入失败的学号: ")
console.log(res.data.errors)
} else {
//失败提示
that.$message.error(res.data.msg);
}
}).catch(err => {
console.log(err);
that.$message.error("导入exccel时后端数据异常: " + err);
});
},
//导出excel
exportToExcel() {
let that = this;
axios.get(that.baseURL + 'excel/export/')
.then(res => {
if (res.data.code === 200) {
let url = that.baseURL + 'media/' + res.data.name;
console.log(url)
//下载
window.open(url);
} else {
//失败提示
that.$message.error(res.data.msg);
}
})
.catch(err => {
console.log(err);
that.$message.error("导出exccel时后端数据异常: " + err);
});
},
//分页时修改每页的行数
handleSizeChange(size) {
this.pagesize = size;
this.getPageStudents();
},
//调整当前的页码
handleCurrentChange(pageNumber) {
this.currentpage = pageNumber;
this.getPageStudents();
},
handleSelectionChange(data) {
this.selectStudents = data
console.log(this.selectStudents)
},
},
})
html,
body,
#app,
.el-container {
margin: 0px;
padding: 0px;
height: 100%;
}
.el-header {
background-color: #b3c0d1;
color: #333;
text-align: left;
line-height: 80px;
font-size: 36px;
font-weight: bold;
}
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
line-height: 30px;
}
.el-aside {
background-color: #d3dce6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #e9eef3;
color: #333;
}
body > .el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
.el-dialog .avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.el-dialog .avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.el-dialog .avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.el-dialog .avatar {
width: 178px;
height: 178px;
display: block;
}
后端代码:
https://download.csdn.net/download/tt75281920/13203474