SpringBoot + vue 管理系统
文章目录
-
-
- SpringBoot + vue 管理系统
-
- 1、成品效果展示
- 2、项目准备
- 3、项目开发
-
- 3.1、部门管理
-
- 3.1.1、前端核心代码
- 3.1.2、后端代码实现
- 3.2、员工管理
-
- 3.2.1、前端核心代码
- 3.2.2、后端代码实现
- 3.3、班级管理
-
- 3.3.1、前端核心代码
- 3.3.2、后端代码实现
- 3.4、学生管理
-
- 3.4.1、前端核心代码
- 3.4.2、后端代码实现
- 3.5、数据统计
-
- 3.5.1、前端核心代码
- 3.5.2、后端代码实现
- 3.6、登录功能
-
- 3.6.1、前端核心代码
- 3.6.2、后端代码实现
-
1、成品效果展示
SpringBoot + vue 管理系统
2、项目准备
环境准备
步骤:
-
准备数据库表
-
创建springboot工程,引入对应的起步依赖(web、mybatis、mysql驱动、lombok)
-
配置文件application.properties中引入mybatis的配置信息,准备对应的实体类
-
准备对应的Mapper、Service(接口、实现类)、Controller基础结构
– 部门管理
create table dept(
id int unsigned primary key auto_increment comment ‘主键ID’,
name varchar(10) not null unique comment ‘部门名称’,
create_time datetime not null comment ‘创建时间’,
update_time datetime not null comment ‘修改时间’
) comment ‘部门表’;insert into dept (id, name, create_time, update_time) values(1,‘学工部’,now(),now()),
(2,‘教研部’,now(),now()),
(3,‘咨询部’,now(),now()),
(4,‘就业部’,now(),now()),
(5,‘人事部’,now(),now());– 员工管理(带约束)
create table emp (
id int unsigned primary key auto_increment comment ‘ID’,
username varchar(20) not null unique comment ‘用户名’,
password varchar(32) default ‘123456’ comment ‘密码’,
name varchar(10) not null comment ‘姓名’,
gender tinyint unsigned not null comment ‘性别, 说明: 1 男, 2 女’,
image varchar(300) comment ‘图像’,
job tinyint unsigned comment ‘职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师’,
entrydate date comment ‘入职时间’,
dept_id int unsigned comment ‘部门ID’,
create_time datetime not null comment ‘创建时间’,
update_time datetime not null comment ‘修改时间’
) comment ‘员工表’;INSERT INTO emp
(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) VALUES
(1,‘jinyong’,‘123456’,‘金庸’,1,‘1.jpg’,4,‘2000-01-01’,2,now(),now()),
(2,‘zhangwuji’,‘123456’,‘张无忌’,1,‘2.jpg’,2,‘2015-01-01’,2,now(),now()),
(3,‘yangxiao’,‘123456’,‘杨逍’,1,‘3.jpg’,2,‘2008-05-01’,2,now(),now()),
(4,‘weiyixiao’,‘123456’,‘韦一笑’,1,‘4.jpg’,2,‘2007-01-01’,2,now(),now()),
(5,‘changyuchun’,‘123456’,‘常遇春’,1,‘5.jpg’,2,‘2012-12-05’,2,now(),now()),
(6,‘xiaozhao’,‘123456’,‘小昭’,2,‘6.jpg’,3,‘2013-09-05’,1,now(),now()),
(7,‘jixiaofu’,‘123456’,‘纪晓芙’,2,‘7.jpg’,1,‘2005-08-01’,1,now(),now()),
(8,‘zhouzhiruo’,‘123456’,‘周芷若’,2,‘8.jpg’,1,‘2014-11-09’,1,now(),now()),
(9,‘dingminjun’,‘123456’,‘丁敏君’,2,‘9.jpg’,1,‘2011-03-11’,1,now(),now()),
(10,‘zhaomin’,‘123456’,‘赵敏’,2,‘10.jpg’,1,‘2013-09-05’,1,now(),now()),
(11,‘luzhangke’,‘123456’,‘鹿杖客’,1,‘11.jpg’,5,‘2007-02-01’,3,now(),now()),
(12,‘hebiweng’,‘123456’,‘鹤笔翁’,1,‘12.jpg’,5,‘2008-08-18’,3,now(),now()),
(13,‘fangdongbai’,‘123456’,‘方东白’,1,‘13.jpg’,5,‘2012-11-01’,3,now(),now()),
(14,‘zhangsanfeng’,‘123456’,‘张三丰’,1,‘14.jpg’,2,‘2002-08-01’,2,now(),now()),
(15,‘yulianzhou’,‘123456’,‘俞莲舟’,1,‘15.jpg’,2,‘2011-05-01’,2,now(),now()),
(16,‘songyuanqiao’,‘123456’,‘宋远桥’,1,‘16.jpg’,2,‘2007-01-01’,2,now(),now()),
(17,‘chenyouliang’,‘123456’,‘陈友谅’,1,‘17.jpg’,NULL,‘2015-03-21’,NULL,now(),now());CREATE TABLE clazz (
id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT ‘ID,主键’,
name varchar(30) NOT NULL UNIQUE COMMENT ‘班级名称’,
room varchar(20) DEFAULT NULL COMMENT ‘班级教室’,
begin_date date NOT NULL COMMENT ‘开课时间’,
end_date date NOT NULL COMMENT ‘结课时间’,
master_id int unsigned NOT NULL COMMENT ‘班主任ID, 关联员工表ID’,
create_time datetime NOT NULL COMMENT ‘创建时间’,
update_time datetime NOT NULL COMMENT ‘修改时间’
) COMMENT ‘班级表’;INSERT INTO clazz VALUES (1,‘黄埔班一期’,‘212’,‘2023-04-30’,‘2023-06-29’,10,‘2023-06-01 17:08:23’,‘2023-06-01 17:39:58’),
(2,‘黄埔班二期’,‘211’,‘2023-06-25’,‘2023-12-31’,1,‘2023-06-01 17:34:16’,‘2023-06-01 17:43:43’),
(3,‘黄埔班三期’,‘210’,‘2023-07-10’,‘2024-01-20’,3,‘2023-06-01 17:45:12’,‘2023-06-01 17:45:12’),
(4,‘JavaEE就业165期’,‘108’,‘2023-06-15’,‘2023-12-25’,6,‘2023-06-01 17:45:40’,‘2023-06-01 17:45:40’),
(5,‘JavaEE就业166期’,‘105’,‘2023-07-20’,‘2024-02-20’,20,‘2023-06-01 17:46:10’,‘2023-06-01 17:46:10’),
(6,‘黄埔四期’,‘209’,‘2023-08-01’,‘2024-02-15’,7,‘2023-06-01 17:51:21’,‘2023-06-01 17:51:21’);CREATE TABLE student (
id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT ‘ID,主键’,
name varchar(10) NOT NULL COMMENT ‘姓名’,
no char(10) NOT NULL UNIQUE COMMENT ‘学号’,
gender tinyint unsigned NOT NULL COMMENT ‘性别, 1: 男, 2: 女’,
phone varchar(11) NOT NULL UNIQUE COMMENT ‘手机号’,
degree tinyint unsigned DEFAULT NULL COMMENT ‘最高学历, 1:初中, 2:高中, 3:大专, 4:本科, 5:硕士, 6:博士’,
violation_count tinyint unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘违纪次数’,
violation_score tinyint unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘违纪扣分’,
clazz_id int unsigned NOT NULL COMMENT ‘班级ID, 关联班级表ID’,
create_time datetime NOT NULL COMMENT ‘创建时间’,
update_time datetime NOT NULL COMMENT ‘修改时间’
) COMMENT ‘学生表’;INSERT INTO student VALUES (1,‘Tom’,‘2023001001’,1,‘18909091212’,4,0,0,1,‘2023-06-01 18:28:58’,‘2023-06-01 18:28:58’),
(2,‘Cat’,‘2023001002’,2,‘18909092345’,3,0,0,1,‘2023-06-01 18:34:57’,‘2023-06-01 18:34:57’),
(3,‘Lily’,‘2023001003’,2,‘13309230912’,4,2,5,1,‘2023-06-01 18:35:23’,‘2023-06-01 19:37:42’),
(4,‘Jerry’,‘2023001004’,1,‘15309232323’,4,1,2,1,‘2023-06-01 18:35:48’,‘2023-06-01 19:37:35’),
(6,‘Nacos’,‘2023002001’,1,‘18809091212’,1,3,10,2,‘2023-06-01 18:57:32’,‘2023-06-01 19:37:29’);
生成的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tlias</groupId><artifactId>web-tlias</artifactId><version>0.0.1-SNAPSHOT</version><name>web-tlias</name><description>web-tlias</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.6</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.0</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
<!-- pagehelper分页查询插件--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.2</version></dependency><!-- 阿里云oss依赖--><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.2</version></dependency>
<!-- jwt依赖--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.tlias.WebTliasApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
</project>
创建项目工程目录结构
配置文件application.yml
server:port: 8080mybatis:mapper-locations: classpath:mappers/*xmltype-aliases-package: com.tlias.entityconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: truespring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/tliasusername: rootpassword: 123456servlet:multipart:max-file-size: 10MBmax-request-size: 100MBpagehelper:reasonable: truealiyun:oss:endpoint: https://oss-cn-beijing.aliyuncs.comaccessKeyId: you_acesskeyaccessKeySecret: you_accessKeySecretbucketName: tlias-lwj
设置统一返回数据
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {private int code;private String msg;private Object data;public static Result success() {return new Result(1, "success", null);}public static Result success(Object data) {return new Result(1, "success", data);}public static Result error(String msg) {return new Result(0,msg,null);}}
构建一个vue项目
3、项目开发
功能模块分为六部分:班级管理、学员管理、部门管理、员工管理、员工信息统计、学员信息统计
3.1、部门管理
开发的部门管理功能包含:
- 查询部门
- 删除部门
- 新增部门
- 更新部门
3.1.1、前端核心代码
<template><div style="margin-top: 20px; margin: 50px; margin-right: 100px"><!-- 按钮 --><el-row><el-buttonstyle="float: right"type="primary"@click="dialogFormVisible = true; dept={}">+ 新增部门</el-button></el-row><br><!-- 数据表格 --><template><el-tablehighlight-current-rowref="multipleTable":data="tableData"tooltip-effect="dark"style="width: 100%"border><el-table-column type="index" width="100" label="序号" header-align="center" align="center"> </el-table-column><el-table-column prop="name" label="部门名称" header-align="center" align="center"></el-table-column><el-table-column label="最后操作时间" header-align="center" align="center"><template slot-scope="scope">{{scope.row.updateTime ? scope.row.updateTime.replace('T',' '):''}}</template></el-table-column><el-table-column label="操作" width="420" header-align="center" align="center"><template slot-scope="scope"><el-buttonsize="mini"type="primary"plain@click="selectById(scope.row.id)">编辑</el-button><el-buttonsize="mini"type="danger"plain@click="deleteById(scope.row.id)">删除</el-button></template></el-table-column></el-table></template><!-- 新建对话框 --><el-dialog title="保存部门" :visible.sync="dialogFormVisible" ><el-form :model="dept" :rules="rules" ref="dept"><el-form-item label="部门名称" :label-width="formLabelWidth" prop="name"><el-input v-model="dept.name" placeholder="请输入部门名称" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="cancel('dept')">取 消</el-button><el-button type="primary" @click="save('dept')">确 定</el-button></div></el-dialog></div>
</template><script>
import { findAll, add, update, deleteById, selectById } from "@/api/dept.js";export default {data() {return {formLabelWidth: "120px",dialogFormVisible: false, //控制对话框是否可见dept: {name: "",},tableData: [],rules: {name: [{ required: true, message: '请输入部门名称', trigger: 'blur' },{ min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }]} };},methods: {//删除部门deleteById(id) {this.$confirm("确认删除?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {deleteById(id).then((result) => {if(result.data.code == 1){this.$message({message: "恭喜你,删除成功",type: "success",});}else{this.$message.error(result.data.msg);}//重新查询数据this.init();});}).catch(() => {this.$message({type: "info",message: "已取消删除",});});},//根据ID查询部门 -- 回显selectById(id) {this.dialogFormVisible = true;selectById(id).then((result) => {this.dept = result.data.data;});},//保存方法save(formName) {this.$refs[formName].validate((valid) => {if(valid){let operator ;if (this.dept.id) {operator = update(this.dept); // 修改}else{operator = add(this.dept); //添加 }operator.then((result) => {if (result.data.code == 1) {//修改成功this.$message.success("恭喜你,保存成功");//重新查询数据this.init();// 关闭新建窗口this.dialogFormVisible = false;// 清空模型数据this.dept = {};} else {this.$message.error(result.data.msg);}});}})},//初始化 - 查询全部init() {findAll().then((result) => {console.log(result);if (result.data.code == 1) {this.tableData = result.data.data;}});},cancel(formName){this.dialogFormVisible = false;this.$refs[formName].resetFields();}},mounted() {//当页面加载完成后自动执行。this.init();},
};
</script>
3.1.2、后端代码实现
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {private Integer id;private String name;private LocalDateTime createTime;private LocalDateTime updateTime;
}
controller层
@RestController
@RequestMapping("depts")
@Slf4j
public class DeptController {@Autowiredprivate DeptService service;/*** 查询部门* @return*/@GetMappingpublic Result getDept(){log.info("查询部门数据");List<Dept> list = service.getDeptList();return Result.success(list);}/*** 根据id删除部门* @param id* @return*/@DeleteMapping("/{id}")public Result deleteDeptById(@PathVariable("id") Integer id){log.info("删除部门id {}",id);service.deleteDeptById(id);return Result.success();}/*** 新增部门* @param dept* @return*/@PostMappingpublic Result save(@RequestBody Dept dept){log.info("新增部门 {}",dept);service.save(dept);return Result.success();}/*** 根据id查询部门* @param id* @return*/@GetMapping("/{id}")public Result selectDeptById(@PathVariable("id") Integer id){log.info("根据id查询部门{}",id);Dept dept = service.selectDeptById(id);return Result.success(dept);}/*** 修改部门* @param dept* @return*/@PutMappingpublic Result update(@RequestBody Dept dept){log.info("修改部门信息{}",dept);service.update(dept);return Result.success();}
}
service层
service接口
public interface DeptService {/*** 查询部门* @return*/List<Dept> getDeptList();/*** 删除部门* @param id*/void deleteDeptById(Integer id);/*** 新增部门* @param dept*/void save(Dept dept);/*** 根据id查询部门* @param id* @return*/Dept selectDeptById(Integer id);/*** 修改部门信息* @param dept*/void update(Dept dept);
}
serviceImpl
@Service
public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper;@Autowiredprivate EmpMapper empMapper;/*** 查询部门** @return*/@Overridepublic List<Dept> getDeptList() {List<Dept> list = deptMapper.getDeptList();return list;}/*** 删除部门** @param id*/@Overridepublic void deleteDeptById(Integer id) {Integer result = empMapper.selectEmpByDeptId(id);if (result < 1 ){throw new RuntimeException("不能删除部门,部门下面存在员工");}deptMapper.deleteDeptById(id);}/*** 新增部门** @param dept*/@Overridepublic void save(Dept dept) {//添加修改时间dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.save(dept);}/*** 根据id查询部门** @param id* @return*/@Overridepublic Dept selectDeptById(Integer id) {Dept dept = deptMapper.selectDeptById(id);return dept;}/*** 修改部门信息** @param dept*/@Overridepublic void update(Dept dept) {dept.setUpdateTime(LocalDateTime.now());deptMapper.update(dept);}
}
mapper层
@Mapper
public interface DeptMapper {/*** 查询部门* @return*/@Select("select * from dept")List<Dept> getDeptList();/*** 删除部门* @param id*/@Delete("delete from dept where id = #{id}")void deleteDeptById(Integer id);/*** 新增部门* @param dept*/@Insert("insert into dept values (null,#{name},#{createTime},#{updateTime})")void save(Dept dept);/*** 根据id查询部门* @param id* @return*/@Select("select * from dept where id = #{id}")Dept selectDeptById(Integer id);/*** 修改部门信息* @param dept*/@Update("update dept set name = #{name},update_time = #{updateTime} where id = #{id}")void update(Dept dept);
}
3.2、员工管理
我们可以把员工管理功能分为:
- 分页查询
- 带条件的分页查询
- 删除员工
- 新增员工
- 修改员工
3.2.1、前端核心代码
<template><div class="app-container"><!--搜索表单--><el-form :inline="true" :model="searchEmp" class="demo-form-inline"><el-form-item label="姓名"><el-inputv-model="searchEmp.name"placeholder="请输入员工姓名"></el-input></el-form-item><el-form-item label="性别"><el-select v-model="searchEmp.gender" placeholder="请选择"><el-option label="男" value="1"></el-option><el-option label="女" value="2"></el-option></el-select></el-form-item><el-form-item label="入职时间"><el-date-pickerv-model="entrydate"clearablevalue-format="yyyy-MM-dd"type="daterange"placeholder="选择日期"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"style="width: 400px; margin-left: 20px"></el-date-picker></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">查询</el-button><el-button type="info" @click="clear">清空</el-button></el-form-item></el-form><!--按钮--><el-row><el-button type="danger" size="medium" @click="deleteByIds">- 批量删除</el-button><el-button type="primary" size="medium" @click="dialogVisible = true; emp = { image: ''};" >+ 新增员工</el-button></el-row><!--添加数据对话框表单--><el-dialog ref="form" title="编辑员工" :visible.sync="dialogVisible" width="30%"><el-form :model="emp" :rules="rules" ref="emp" label-width="80px" size="mini"><el-form-item label="用户名" prop="username"><el-input v-model="emp.username"></el-input></el-form-item><el-form-item label="员工姓名" prop="name"><el-input v-model="emp.name"></el-input></el-form-item><el-form-item label="性别" prop="gender"><el-select v-model="emp.gender" placeholder="请选择" style="width:100%" ><el-optionv-for="item in genderList":key="item.value":label="item.name":value="item.id"/></el-select></el-form-item><el-form-item label="头像"><el-uploadclass="avatar-uploader"action="/api/upload":headers="token"name="image":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload"><img v-if="emp.image" :src="emp.image" class="avatar" /><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></el-form-item><el-form-item label="职位"><el-select v-model="emp.job" placeholder="请选择" value-key="emp.job" style="width:100%"><el-optionv-for="item in jobList":key="item.value":label="item.name":value="item.id"/></el-select></el-form-item><el-form-item label="入职日期"><el-date-pickerv-model="emp.entrydate"clearabletype="date"value-format="yyyy-MM-dd" placeholder="选择日期"size="small"style="width:100%"></el-date-picker></el-form-item><el-form-item label="归属部门"><el-select v-model="emp.deptId" placeholder="请选择" style="width:100%"><!-- <el-option label="学工部" value="1"></el-option><el-option label="教研部" value="2"></el-option>--><el-optionv-for="item in deptList":key="item.value":label="item.name":value="item.id"/></el-select></el-form-item><el-form-item><el-button type="primary" @click="save('emp')">提交</el-button><el-button @click="cancel('emp')">取消</el-button></el-form-item></el-form></el-dialog><br><!--表格--><template><el-table :data="tableData" style="width: 100%" border @selection-change="handleSelectionChange"><el-table-column type="selection" width="55" align="center"></el-table-column><el-table-column prop="name" label="姓名" align="center"></el-table-column><el-table-column prop="image" label="头像" align="center"><template slot-scope="{ row }"><el-image style="width: auto; height: 40px; border: none; cursor: pointer" :src="row.image"></el-image></template></el-table-column><el-table-column align="center" label="性别"><template slot-scope="scope"><span style="margin-right: 10px">{{scope.row.gender == "1" ? "男" : "女"}}</span></template></el-table-column><el-table-column align="center" label="职位"><template slot-scope="scope"><span style="margin-right: 10px" v-if="scope.row.job == 1">班主任</span><span style="margin-right: 10px" v-if="scope.row.job == 2">讲师</span><span style="margin-right: 10px" v-if="scope.row.job == 3">学工主管</span><span style="margin-right: 10px" v-if="scope.row.job == 4">教研主管</span></template></el-table-column><el-table-column align="center" label="日职日期"><template slot-scope="scope">{{ scope.row.entrydate }}</template></el-table-column><el-table-column align="center" label="最后操作时间"><template slot-scope="scope">{{scope.row.updateTime ? scope.row.updateTime.replace('T',' '):''}}</template></el-table-column><el-table-column align="center" label="操作"><template slot-scope="scope"><el-button type="primary" size="small" @click="update(scope.row.id)">编辑</el-button><el-button type="danger" size="small" @click="deleteById(scope.row.id)">删除</el-button></template></el-table-column></el-table></template><br><!--分页工具条--><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":background="background":current-page="currentPage":page-sizes="[5, 10, 15, 20]":page-size="5"layout="total, sizes, prev, pager, next, jumper":total="totalCount"></el-pagination></div>
</template><script>
import { page, add, update, deleteById, selectById } from "@/api/emp.js";
import { findAll } from "@/api/dept.js";
import { getToken } from '@/utils/auth';export default {data() {return {background: true,// 每页显示的条数pageSize: 5,// 总记录数totalCount: 100,// 当前页码currentPage: 1,// 添加数据对话框是否展示的标记dialogVisible: false,// 品牌模型数据searchEmp: {name: "",gender: "",},emp: {username: "",name: "",gender: "",image: "",job: "",entrydate: "",deptId: ""},deptList: [],genderList: [{id: 1,name: "男"},{id: 2,name: "女"}],jobList: [{id: 1,name: "班主任"},{id: 2,name: "讲师"},{id: 3, name: "学工主管"},{id: 4,name: "教研主管"}],beginTime: "",endTime: "",entrydate: "",// 被选中的id数组selectedIds: [],// 复选框选中数据集合multipleSelection: [],// 表格数据tableData: [],token: {token: getToken()},rules: {username: [{required: true, message: '请输入用户名', trigger: 'blur' },{min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }],name: [{required: true, message: '请输入姓名', trigger: 'blur' },{min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }],gender: [{required: true, message: '请选择性别', trigger: 'change' }]}};},mounted() {this.page(); //当页面加载完成后,发送异步请求,获取数据findAll().then((result) => {this.deptList = result.data.data;});},methods: {// 查询分页数据page() {page(this.searchEmp.name,this.searchEmp.gender,this.beginTime,this.endTime,this.currentPage,this.pageSize).then((res) => {this.totalCount = res.data.data.total;this.tableData = res.data.data.rows;});},// 复选框选中后执行的方法handleSelectionChange(val) {this.multipleSelection = val;},// 查询方法onSubmit() {this.currentPage = 1;this.page();},clear(){this.searchEmp = {name: "", gender: ""};this.beginTime = "",this.endTime = "";this.entrydate = "";this.page();},// 添加数据save(formName) {//校验表单this.$refs[formName].validate((valid) => {if (valid) {let operator;if (this.emp.id) {//修改operator = update(this.emp);} else { //新增operator = add(this.emp);}operator.then((resp) => {if (resp.data.code == 1) {this.dialogVisible = false;this.page();this.$message({ message: "恭喜你,保存成功", type: "success" });this.emp = { image: "" };} else {this.$message.error(resp.data.msg);}});}});},update(id) {//1. 打开窗口this.dialogVisible = true;//2. 发送请求selectById(id).then((result) => {if (result.data.code == 1) {this.emp = result.data.data;this.emp;}});},//分页handleSizeChange(val) {// 重新设置每页显示的条数this.pageSize = val;this.page();},handleCurrentChange(val) {// 重新设置当前页码this.currentPage = val;this.page();},//删除员工信息deleteById(id){this.$confirm("此操作将删除该数据, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {//2. 发送AJAX请求deleteById(id).then((resp) => {if (resp.data.code == 1) {//删除成功this.$message.success("恭喜你,删除成功");this.page();} else {this.$message.error(resp.data.msg);}});}).catch(() => {//用户点击取消按钮this.$message.info("已取消删除");});},// 批量删除员工信息deleteByIds() {// 弹出确认提示框this.$confirm("此操作将删除该数据, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {//用户点击确认按钮//1. 创建id数组, 从 this.multipleSelection 获取即可for (let i = 0; i < this.multipleSelection.length; i++) {this.selectedIds[i] = this.multipleSelection[i].id;}//2. 发送AJAX请求deleteById(this.selectedIds).then((resp) => {if (resp.data.code == "1") {//删除成功this.$message.success("恭喜你,删除成功");this.page();} else {this.$message.error(resp.data.msg);}});}).catch(() => {//用户点击取消按钮this.$message.info("已取消删除");});},cancel(formName){this.dialogVisible = false;this.$refs[formName].resetFields();},//文件上传相关handleAvatarSuccess(res, file) {this.emp.image = res.data;},beforeAvatarUpload(file) {const isJPG = file.type === "image/jpeg";const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG) {this.$message.error("上传头像图片只能是 JPG 格式!");}if (!isLt2M) {this.$message.error("上传头像图片大小不能超过 2MB!");}return isJPG && isLt2M;},},watch: {entrydate(val) {if (val && val.length >= 2) {this.beginTime = val[0];this.endTime = val[1];} else {this.beginTime = "";this.endTime = "";}},},
};
</script>
<style>
.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;
}
.avatar-uploader .el-upload:hover {border-color: #409eff;
}
.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 100px;height: 100px;line-height: 100px;text-align: center;
}
.avatar {width: 100px;height: 100px;display: block;
}
</style>
3.2.2、后端代码实现
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp {private Integer id;private String username;private String password;private String name;private Short gender;private String image;private Short job;private LocalDate entrydate;private Integer deptId;private LocalDateTime createTime;private LocalDateTime updateTime;
}
controller
@RestController
@RequestMapping("/emps")
@Slf4j
public class EmpController {@Autowiredprivate EmpService service;/*** 分页查询* @param page* @param pageSize* @param name* @param gender* @param begin* @param end* @return*/@GetMappingpublic Result page(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize,String name, Short gender,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("员工分页查询 page = {},pageSize = {}", page, pageSize);PageBean pageBean = service.page(page,pageSize,name,gender,begin,end);return Result.success(pageBean);}/*** 删除* @param ids* @return*/@DeleteMapping("/{ids}")public Result deleteByIds(@PathVariable("ids") List<Integer> ids){log.info("删除 ids = {}", ids);service.deleteByIds(ids);return Result.success();}/*** 新增员工* @param emp* @return*/@PostMappingpublic Result save(@RequestBody Emp emp){log.info("新增员工 {}", emp);service.save(emp);return Result.success();}/*** 根据id查询员工* @param id* @return*/@GetMapping("/{id}")public Result selectById(@PathVariable Integer id){log.info("根据id查询员工");Emp emp = service.selectById(id);return Result.success(emp);}@PutMappingpublic Result update(@RequestBody Emp emp){log.info("修改员工{}",emp);service.update(emp);return Result.success();}@GetMapping("/list")public Result selectAll(){log.info("查询全部员工");List<Emp> list = service.selectAll();return Result.success(list);}
}
service层
public interface EmpService {/*** 员工分页查询** @param page* @param pageSize* @param name* @param gender* @param begin* @param end* @return*/PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);/*** 删除* @param ids*/void deleteByIds(List<Integer> ids);/*** 新增员工* @param emp*/void save(Emp emp);/*** 根据id查询员工* @param id* @return*/Emp selectById(Integer id);/*** 修改员工* @param emp*/void update(Emp emp);/*** 查询全部员工* @return*/List<Emp> selectAll();/*** 员工登录* @param emp* @return*/Emp login(Emp emp);
}@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;@Overridepublic PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {//设置分页参数PageHelper.startPage(page,pageSize);//进行查询List<Emp> list = empMapper.list(name,gender,begin,end);//获取分页结果Page<Emp> empPage = (Page<Emp>) list;return new PageBean(empPage.getTotal(),empPage.getResult());}/*** 删除** @param ids*/@Overridepublic void deleteByIds(List<Integer> ids) {empMapper.deleteByIds(ids);}/*** 新增员工** @param emp*/@Overridepublic void save(Emp emp) {emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());empMapper.save(emp);}/*** 根据id查询员工** @param id* @return*/@Overridepublic Emp selectById(Integer id) {Emp emp = empMapper.selectById(id);return emp;}/*** 修改员工** @param emp*/@Overridepublic void update(Emp emp) {emp.setUpdateTime(LocalDateTime.now());empMapper.update(emp);}/*** 查询全部员工** @return*/@Overridepublic List<Emp> selectAll() {List<Emp> list = empMapper.selectAll();return list;}/*** 员工登录** @param emp* @return*/@Overridepublic Emp login(Emp emp) {return empMapper.getEmpByUsernameAndPassword(emp);}
}
mapper层
@Mapper
public interface EmpMapper {/*** 查询部门下是否有员工* @param id* @return*/@Select("select count(*) from emp where dept_id = #{id}")Integer selectEmpByDeptId(Integer id);/*** 查询*/
// @Select("select * from emp")List<Emp> list(@Param("name") String name,@Param("gender") Short gender,@Param("begin") LocalDate begin,@Param("end") LocalDate end);/*** 删除* @param ids*/void deleteByIds(@Param("ids") List<Integer> ids);/*** 新增员工* @param emp*/@Insert("insert into emp values (null,#{username},#{password},#{name},#{gender}" +",#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")void save(Emp emp);/*** 根据id查询员工* @param id* @return*/@Select("select * from emp where id = #{id}")Emp selectById(Integer id);/*** 修改员工* @param emp*/@Update("update emp set username = #{username},password = #{password}," +"name = #{name},gender = #{gender},image = #{image},job = #{job}," +"entrydate = #{entrydate},dept_id = #{deptId},create_time = #{createTime}," +"emp.update_time = #{updateTime} where id = #{id}")void update(Emp emp);/*** 查询全部员工* @return*/@Select("select * from emp")List<Emp> selectAll();/*** 员工性别统计* @return*/List<PieChartData> getEmpGenderData();/*** 员工职位统计* @return*/@Select("select (case job
" +" when 1 then '班主任'" +" when 2 then '讲师'" +" when 3 then '学工主管'" +" when 4 then '教研主管'" +" when 4 then '咨询师'" +" else '无' end) as job," +" count(*) as jobcount" +" from emp" +" group by job")List<Map<String,Object>> getEmpJobData();/*** 员工登录* @param emp* @return*/@Select("select * from emp where username = #{username} and password = #{password}")Emp getEmpByUsernameAndPassword(Emp emp);
}
mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.tlias.mapper.EmpMapper"><delete id="deleteByIds">delete from empwhere id in<foreach collection="ids" open="(" close=")" item="id" separator=",">#{id}</foreach></delete><select id="list" resultType="com.tlias.entity.Emp">select * from emp<where><if test="name != null and name != ''">name like concat('%',#{name},'%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if></where>order by update_time desc</select><select id="getEmpGenderData" resultType="com.tlias.entity.PieChartData">select if(gender = 1,'男性员工','女性员工') as 'name',count(*) as 'value' from emp group by gender;</select></mapper>
因为需要涉及到oss文件上传所以我们还需要整合
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class aliyunOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;
}@Component
public class aliyunUtils {@Autowiredprivate aliyunOssProperties properties;public String upload(MultipartFile multipartFile) throws IOException {String endpoint = properties.getEndpoint();String accessKeyId = properties.getAccessKeyId();String accessKeySecret = properties.getAccessKeySecret();String bucketName = properties.getBucketName();//生成上传名称String originalFilename = multipartFile.getOriginalFilename();String objectName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId,accessKeySecret);try {InputStream inputStream = multipartFile.getInputStream();// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "//" +objectName;} finally {if (ossClient != null) {ossClient.shutdown();}}}
}
3.3、班级管理
开发的班级管理功能包含:
- 查询班级
- 删除班级
- 新增班级
- 更新班级
3.3.1、前端核心代码
<template><div style="margin-top: 20px; margin: 50px; margin-right: 100px"><!-- 按钮 --><el-row><el-button style="float: right" type="primary" @click="dialogFormVisible = true; dept = {}">+ 新增班级</el-button></el-row><br><!-- 数据表格 --><template><el-table highlight-current-row ref="multipleTable" :data="tableData" tooltip-effect="dark" style="width: 100%"border><el-table-column type="index" width="100" label="序号" header-align="center" align="center"> </el-table-column><el-table-column prop="name" label="班级名称" header-align="center" align="center"></el-table-column><el-table-column prop="room" label="上课教室" header-align="center" align="center"></el-table-column><el-table-column label="开课时间" header-align="center" align="center"><template slot-scope="scope">{{ scope.row.beginDate ? scope.row.beginDate.replace('T', ' ') : '' }}</template></el-table-column><el-table-column label="结课时间" header-align="center" align="center"><template slot-scope="scope">{{ scope.row.endDate ? scope.row.endDate.replace('T', ' ') : '' }}</template></el-table-column><el-table-column label="创建时间" header-align="center" align="center"><template slot-scope="scope">{{ scope.row.createTime ? scope.row.createTime.replace('T', ' ') : '' }}</template></el-table-column><el-table-column label="最后操作时间" header-align="center" align="center"><template slot-scope="scope">{{ scope.row.updateTime ? scope.row.updateTime.replace('T', ' ') : '' }}</template></el-table-column><!-- <el-table-column prop="masterId" label="教师id" header-align="center" align="center"></el-table-column> --><el-table-column label="操作" width="420" header-a lign="center" align="center"><template slot-scope="scope"><el-button size="mini" type="primary" plain @click="selectById(scope.row.id)">编辑</el-button><el-button size="mini" type="danger" plain @click="deleteById(scope.row.id)">删除</el-button></template></el-table-column></el-table></template><!-- 新建对话框 --><el-dialog title="保存班级" :visible.sync="dialogFormVisible"><el-form :model="clazz" :rules="rules" ref="clazz"><el-form-item label="班级名称" prop="name"><el-input v-model="clazz.name" placeholder="请输入班级名称" autocomplete="off"></el-input></el-form-item><el-form-item label="教室" prop="room"><el-input v-model="clazz.room" placeholder="请输入教室" autocomplete="off"></el-input></el-form-item><el-form-item label="开始日期" prop="beginDate"><el-date-picker v-model="clazz.beginDate" type="date" placeholder="选择开始日期"></el-date-picker></el-form-item><el-form-item label="结束日期" prop="endDate"><el-date-picker v-model="clazz.endDate" type="date" placeholder="选择结束日期"></el-date-picker></el-form-item><!-- <el-form-item label="班主任ID" prop="masterId"><el-input v-model="clazz.masterId" placeholder="请输入班主任ID" autocomplete="off"></el-input></el-form-item> --></el-form><div slot="footer" class="dialog-footer"><el-button @click="cancel('clazz')">取 消</el-button><el-button type="primary" @click="save('clazz')">确 定</el-button></div></el-dialog></div>
</template><script>
import { findAll, add, update, deleteById, selectById } from "@/api/clazz.js";export default {data() {return {formLabelWidth: "120px",dialogFormVisible: false, //控制对话框是否可见clazz: {name: "",room: "",beginDate: "",endDate: "",masterId: ""},tableData: [],rules: {name: [{ required: true, message: '请输入部门名称', trigger: 'blur' },{ min: 2, max: 20, message: '长度在 2 到 10 个字符', trigger: 'blur' }],room: [{ required: true, message: '请输入教室', trigger: 'blur' }],beginDate: [{ required: true, message: '请选择开始日期', trigger: 'change' }],endDate: [{ required: true, message: '请选择结束日期', trigger: 'change' }],// masterId: [// { required: true, message: '请输入班主任ID', trigger: 'blur' }// ]}};},methods: {//删除部门deleteById(id) {this.$confirm("确认删除?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {deleteById(id).then((result) => {if (result.data.code == 1) {this.$message({message: "恭喜你,删除成功",type: "success",});} else {this.$message.error(result.data.msg);}//重新查询数据this.init();});}).catch(() => {this.$message({type: "info",message: "已取消删除",});});},//根据ID查询部门 -- 回显selectById(id) {this.dialogFormVisible = true;selectById(id).then((result) => {this.clazz = result.data.data;});},//保存方法save(formName) {this.$refs[formName].validate((valid) => {if (valid) {let operator;if (this.clazz.id) {operator = update(this.clazz); // 修改} else {operator = add(this.clazz); //添加 }operator.then((result) => {if (result.data.code == 1) {//修改成功this.$message.success("恭喜你,保存成功");//重新查询数据this.init();// 关闭新建窗口this.dialogFormVisible = false;// 清空模型数据this.clazz = {};} else {this.$message.error(result.data.msg);}});}})},//初始化 - 查询全部init() {findAll().then((result) => {console.log(result);if (result.data.code == 1) {this.tableData = result.data.data;}});},cancel(formName) {this.dialogFormVisible = false;this.$refs[formName].resetFields();}},mounted() {//当页面加载完成后自动执行。this.init();},
};
</script>
<style></style>
3.3.2、后端代码实现
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Clazz {private Integer id;private String name;private String room;private LocalDate beginDate;private LocalDate endDate;private Integer masterId;private LocalDateTime createTime;private LocalDateTime updateTime;
}
controller层
@RestController
@RequestMapping("/clazzs")
@Slf4j
public class ClazzController {@Autowiredprivate ClazzService clazzService;/*** 查询所有* @return*/@GetMappingpublic Result findAll(){log.info("findAll...");List<Clazz> list = clazzService.findAll();return Result.success(list);}/*** 新增班级* @param clazz* @return*/@PostMappingpublic Result save(@RequestBody Clazz clazz){log.info("save{}",clazz);clazzService.save(clazz);return Result.success();}/*** 根据id删除班级* @param id* @return*/@DeleteMapping("/{id}")public Result deleteById(@PathVariable Long id){log.info("deleteById...{}",id);clazzService.deleteById(id);return Result.success();}/*** 根据id查询班级*/@GetMapping("/{id}")public Result findById(@PathVariable Long id){log.info("findById...{}",id);Clazz clazz = clazzService.findById(id);return Result.success(clazz);}/*** 更新班级* @param clazz* @return*/@PutMappingpublic Result update(@RequestBody Clazz clazz){log.info("update...{}",clazz);clazzService.update(clazz);return Result.success();}
}
service
public interface ClazzService {/*** 查询所有班级* @return*/List<Clazz> findAll();/*** 新增班级* @param clazz*/void save(Clazz clazz);/*** 根据id删除班级* @param id*/void deleteById(Long id);/*** 根据id查询班级* @param id* @return*/Clazz findById(Long id);/*** 更新班级* @param clazz*/void update(Clazz clazz);
}@Service
public class ClazzServiceImpl implements ClazzService {@Autowiredprivate ClazzMapper clazzMapper;/*** 查询所有班级** @return*/@Overridepublic List<Clazz> findAll() {List<Clazz> clazzList = clazzMapper.findAll();return clazzList;}/*** 新增班级** @param clazz*/@Overridepublic void save(Clazz clazz) {clazz.setCreateTime(LocalDateTime.now());clazz.setUpdateTime(LocalDateTime.now());clazzMapper.save(clazz);}/*** 根据id删除班级** @param id*/@Overridepublic void deleteById(Long id) {clazzMapper.deleteById(id);}/*** 根据id查询班级** @param id* @return*/@Overridepublic Clazz findById(Long id) {Clazz clazz = clazzMapper.findById(id);return clazz;}/*** 更新班级** @param clazz*/@Overridepublic void update(Clazz clazz) {clazz.setUpdateTime(LocalDateTime.now());clazzMapper.update(clazz);}
}
mapper层
@Mapper
public interface ClazzMapper {/*** 查询所有班级* @return*/@Select("select * from clazz")List<Clazz> findAll();/*** 新增班级* @param clazz*/@Insert("insert into clazz values (null,#{name},#{room},#{beginDate},#{endDate},#{masterId}," +"#{createTime},#{updateTime})")void save(Clazz clazz);/*** 根据id删除班级* @param id*/@Delete("delete from clazz where id = #{id}")void deleteById(Long id);/*** 根据id查询班级* @param id* @return*/@Select("select * from clazz where id = #{id};")Clazz findById(Long id);/*** 更新班级* @param clazz*/@Update("update clazz set name = #{name},room = #{room},begin_date = #{beginDate}," +"end_date = #{endDate},master_id = #{masterId} where id = #{id}")void update(Clazz clazz);
}
3.4、学生管理
我们可以把员工管理功能分为:
- 分页查询
- 带条件的分页查询
- 删除员工
- 新增员工
- 修改员工
3.4.1、前端核心代码
<template><div class="app-container"><!--搜索表单--><el-form :inline="true" :model="searchStudent" class="demo-form-inline"><el-form-item label="姓名"><el-inputv-model="searchStudent.name"placeholder="请输入学生姓名"></el-input></el-form-item><el-form-item label="性别"><el-select v-model="searchStudent.gender" placeholder="请选择"><el-option label="男" value="1"></el-option><el-option label="女" value="2"></el-option></el-select></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">查询</el-button><el-button type="info" @click="clear">清空</el-button></el-form-item></el-form><!--按钮--><el-row><el-button type="danger" size="medium" @click="deleteByIds">- 批量删除</el-button><el-button type="primary" size="medium" @click="dialogVisible = true; student = { image: ''};" >+ 新增学生</el-button></el-row><!--添加数据对话框表单--><el-dialog ref="form" title="编辑学生" :visible.sync="dialogVisible" width="30%"><el-form :model="student" :rules="rules" ref="student" label-width="80px" size="mini"><el-form-item label="姓名" prop="name"><el-input v-model="student.name"></el-input></el-form-item><el-form-item label="学号" prop="no"><el-input v-model="student.no"></el-input></el-form-item><el-form-item label="性别" prop="gender"><el-select v-model="student.gender" placeholder="请选择" style="width:100%" ><el-optionv-for="item in genderList":key="item.value":label="item.name":value="item.id"/></el-select></el-form-item><el-form-item label="手机" prop="phone"><el-input v-model="student.phone"></el-input></el-form-item><el-form-item label="班级" prop="phone"><el-input v-model="student.clazzId"></el-input></el-form-item><!-- <el-form-item label="头像"><el-uploadclass="avatar-uploader"action="/api/upload":headers="token"name="image":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload"><img v-if="emp.image" :src="emp.image" class="avatar" /><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></el-form-item> --><!-- <el-form-item label="职位"><el-select v-model="emp.job" placeholder="请选择" value-key="emp.job" style="width:100%"><el-optionv-for="item in jobList":key="item.value":label="item.name":value="item.id"/></el-select></el-form-item> -->
<!-- <el-form-item label="入职日期"><el-date-pickerv-model="emp.entrydate"clearabletype="date"value-format="yyyy-MM-dd" placeholder="选择日期"size="small"style="width:100%"></el-date-picker></el-form-item> --><!-- <el-form-item label="班级"><el-select v-model="student.clazzId" placeholder="请选择" style="width:100%"><el-optionv-for="item in clazzList":key="item.value":label="item.name":value="item.id"/></el-select></el-form-item> --><el-form-item><el-button type="primary" @click="save('student')">提交</el-button><el-button @click="cancel('student')">取消</el-button></el-form-item></el-form></el-dialog><br><!--表格--><template><el-table :data="tableData" style="width: 100%" border @selection-change="handleSelectionChange"><el-table-column type="selection" width="55" align="center"></el-table-column><el-table-column prop="name" label="姓名" align="center"></el-table-column><!-- <el-table-column prop="image" label="头像" align="center"><template slot-scope="{ row }"><el-image style="width: auto; height: 40px; border: none; cursor: pointer" :src="row.image"></el-image></template></el-table-column> --><el-table-column prop="no" label="学号" align="center"></el-table-column><el-table-column prop="phone" label="手机" align="center"></el-table-column><el-table-column align="center" label="性别"><template slot-scope="scope"><span style="margin-right: 10px">{{scope.row.gender == "1" ? "男" : "女"}}</span></template></el-table-column><!-- <el-table-column prop="degree" label="学年" align="center"></el-table-column> --><!-- <el-table-column prop="violationCount" label="违纪总数" align="center"></el-table-column> --><!-- <el-table-column prop="violationScore" label="违纪分数" align="center"></el-table-column> --><el-table-column prop="clazzId" label="班级" align="center"></el-table-column><!-- <el-table-column align="center" label="职位"><template slot-scope="scope"><span style="margin-right: 10px" v-if="scope.row.job == 1">班主任</span><span style="margin-right: 10px" v-if="scope.row.job == 2">讲师</span><span style="margin-right: 10px" v-if="scope.row.job == 3">学工主管</span><span style="margin-right: 10px" v-if="scope.row.job == 4">教研主管</span></template></el-table-column> --><el-table-column align="center" label="入学日期"><template slot-scope="scope">{{ scope.row.createTime ? scope.row.createTime.replace('T', ' ') : '' }}</template></el-table-column><!-- <el-table-column align="center" label="最后操作时间"><template slot-scope="scope">{{scope.row.updateTime ? scope.row.updateTime.replace('T',' '):''}}</template></el-table-column> --><el-table-column align="center" label="操作"><template slot-scope="scope"><el-button type="primary" size="small" @click="update(scope.row.id)">编辑</el-button><el-button type="danger" size="small" @click="deleteById(scope.row.id)">删除</el-button></template></el-table-column></el-table></template><br><!--分页工具条--><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":background="background":current-page="currentPage":page-sizes="[5, 10, 15, 20]":page-size="5"layout="total, sizes, prev, pager, next, jumper":total="totalCount"></el-pagination></div>
</template><script>
import { page, add, update, deleteById, selectById , findAll} from "@/api/student.js";
// import { findAll } from "@/api/dept.js";
import { getToken } from '@/utils/auth';export default {data() {return {background: true,// 每页显示的条数pageSize: 5,// 总记录数totalCount: 100,// 当前页码currentPage: 1,// 添加数据对话框是否展示的标记dialogVisible: false,// 模型数据searchStudent: {name: "",gender: ""},student: {name: "",no: "",gender: "",phone: "",degree: "",violationCount: "",violationScore: "",clazzId: ""},clazzList: [],genderList: [{id: 1,name: "男"},{id: 2,name: "女"}],selectedIds: [],// 复选框选中数据集合multipleSelection: [],// 表格数据tableData: [],token: {token: getToken()},rules: {name: [{required: true, message: '请输入姓名', trigger: 'blur' },{min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }],gender: [{required: true, message: '请选择性别', trigger: 'change' }]}};},mounted() {this.page(); //当页面加载完成后,发送异步请求,获取数据findAll().then((result) => {this.deptList = result.data.data;});},methods: {// 查询分页数据page() {page(this.searchStudent.name,this.searchStudent.gender,// this.beginTime,// this.endTime,this.currentPage,this.pageSize).then((res) => {this.totalCount = res.data.data.total;this.tableData = res.data.data.rows;});},// 复选框选中后执行的方法handleSelectionChange(val) {this.multipleSelection = val;},// 查询方法onSubmit() {this.currentPage = 1;this.page();},clear(){this.searchStudent = {name: "", gender: ""};this.page();},// 添加数据save(formName) {//校验表单this.$refs[formName].validate((valid) => {if (valid) {let operator;if (this.student.id) {//修改operator = update(this.student);} else { //新增operator = add(this.student);}operator.then((resp) => {if (resp.data.code == 1) {this.dialogVisible = false;this.page();this.$message({ message: "恭喜你,保存成功", type: "success" });this.student = { image: "" };} else {this.$message.error(resp.data.msg);}});}});},update(id) {//1. 打开窗口this.dialogVisible = true;//2. 发送请求selectById(id).then((result) => {if (result.data.code == 1) {this.student = result.data.data;this.student;}});},//分页handleSizeChange(val) {// 重新设置每页显示的条数this.pageSize = val;this.page();},handleCurrentChange(val) {// 重新设置当前页码this.currentPage = val;this.page();},//删除员工信息deleteById(id){this.$confirm("此操作将删除该数据, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {//2. 发送AJAX请求deleteById(id).then((resp) => {if (resp.data.code == 1) {//删除成功this.$message.success("恭喜你,删除成功");this.page();} else {this.$message.error(resp.data.msg);}});}).catch(() => {//用户点击取消按钮this.$message.info("已取消删除");});},// 批量删除员工信息deleteByIds() {// 弹出确认提示框this.$confirm("此操作将删除该数据, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {//用户点击确认按钮//1. 创建id数组, 从 this.multipleSelection 获取即可for (let i = 0; i < this.multipleSelection.length; i++) {this.selectedIds[i] = this.multipleSelection[i].id;}//2. 发送AJAX请求deleteById(this.selectedIds).then((resp) => {if (resp.data.code == "1") {//删除成功this.$message.success("恭喜你,删除成功");this.page();} else {this.$message.error(resp.data.msg);}});}).catch(() => {//用户点击取消按钮this.$message.info("已取消删除");});},cancel(formName){this.dialogVisible = false;this.$refs[formName].resetFields();},//文件上传相关handleAvatarSuccess(res, file) {this.student.image = res.data;},beforeAvatarUpload(file) {const isJPG = file.type === "image/jpeg";const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG) {this.$message.error("上传头像图片只能是 JPG 格式!");}if (!isLt2M) {this.$message.error("上传头像图片大小不能超过 2MB!");}return isJPG && isLt2M;},},watch: {entrydate(val) {if (val && val.length >= 2) {this.beginTime = val[0];this.endTime = val[1];} else {this.beginTime = "";this.endTime = "";}},},
};
</script>
<style>
.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;
}
.avatar-uploader .el-upload:hover {border-color: #409eff;
}
.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 100px;height: 100px;line-height: 100px;text-align: center;
}
.avatar {width: 100px;height: 100px;display: block;
}
</style>
3.4.2、后端代码实现
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {private Integer id;private String name;private String no;private Short gender;private String phone;private Short degree;private Short violationCount;private Short violationScore;private Short clazzId;private LocalDateTime createTime;private LocalDateTime updateTime;
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentData {private List categoryList;private List dataList;
}
controller
package com.tlias.controller;import com.github.pagehelper.Page;
import com.tlias.entity.PageBean;
import com.tlias.entity.Student;
import com.tlias.result.Result;
import com.tlias.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/students")
@Slf4j
public class StudentController {@Autowiredprivate StudentService studentService;@GetMappingpublic Result page(String name, Short gender,@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize){log.info("员工分页查询 page={},pageSize={}", page, pageSize);PageBean pageBean = studentService.page(page,pageSize,name,gender);return Result.success(pageBean);}/*** 查询全部* @return*/@GetMapping("/list")public Result findAll(){log.info("findAll...");List<Student> studentList = studentService.findAll();return Result.success(studentList);}/*** 新增学生* @param student* @return*/@PostMapping()public Result save(@RequestBody Student student){log.info("save student...{}",student);studentService.save(student);return Result.success();}/*** 根据id查询学生* @param id* @return*/@GetMapping("/{id}")public Result findById(@PathVariable Long id){log.info("findById...{}",id);Student student = studentService.findById(id);return Result.success(student);}/*** 修改学生* @param student* @return*/@PutMappingpublic Result update(@RequestBody Student student){log.info("update student...{}",student);studentService.update(student);return Result.success();}/*** 删除* @param ids* @return*/@DeleteMapping("/{ids}")public Result deleteById(@PathVariable List<Integer> ids){log.info("deleteById...{}",ids);studentService.deleteById(ids);return Result.success();}}
service
public interface StudentService {/*** 分页查询* @param page* @param pageSize* @param name* @param gender* @return*/PageBean page(Integer page, Integer pageSize, String name, Short gender);/*** 查询全部* @return*/List<Student> findAll();/*** 新增学生* @param student*/void save(Student student);/*** 根据id查询学生* @param id* @return*/Student findById(Long id);/*** 修改学生* @param student*/void update(Student student);/*** 根据id删除* @param ids*/void deleteById(List<Integer> ids);
}@Service
public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper studentMapper;/*** 分页查询** @param page* @param pageSize* @param name* @param gender* @return*/@Overridepublic PageBean page(Integer page, Integer pageSize, String name, Short gender) {PageHelper.startPage(page,pageSize);List<Student> list = studentMapper.page(name,gender);Page<Student> studentPage = (Page<Student>) list;return new PageBean(studentPage.getTotal(),studentPage.getResult());}/*** 查询全部** @return*/@Overridepublic List<Student> findAll() {List<Student> studentList = studentMapper.findAll();return studentList;}/*** 新增学生** @param student*/@Overridepublic void save(Student student) {student.setCreateTime(LocalDateTime.now());student.setUpdateTime(LocalDateTime.now());studentMapper.save(student);}/*** 根据id查询学生** @param id* @return*/@Overridepublic Student findById(Long id) {return studentMapper.findById(id);}/*** 修改学生** @param student*/@Overridepublic void update(Student student) {student.setUpdateTime(LocalDateTime.now());studentMapper.update(student);}/*** 根据id删除** @param ids*/@Overridepublic void deleteById(List<Integer> ids) {studentMapper.deleteById(ids);}}
mapper
@Mapper
public interface StudentMapper {@Select("SELECT clazz.`name` as 'class',COUNT(student.clazz_id) as 'classcount' " +"FROM clazz LEFT JOIN student ON student.clazz_id = clazz.id GROUP BY clazz.`name` ;")List<Map<String, Object>> getStudentData();/*** 分页查询* @param name* @param gender* @return*/List<Student> page(@Param("name") String name,@Param("gender") Short gender);/*** 查询全部* @return*/@Select("select * from student")List<Student> findAll();/*** 新增学生* @param student*/@Insert("insert into student(name, no, gender, phone,clazz_id, create_time, update_time) " +"value(#{name},#{no},#{gender},#{phone},#{clazzId},#{createTime},#{updateTime})")void save(Student student);/*** 根据id查询学生* @param id* @return*/@Select("select * from student where id = #{id};")Student findById(Long id);/*** 修改学生* @param student*/@Update("update student set name = #{name},no = #{no},gender = #{gender}," +"phone = #{phone},clazz_id = #{clazzId} where id = #{id}")void update(Student student);/*** 根据id删除* @param ids*/void deleteById(@Param("ids") List<Integer> ids);
}<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.tlias.mapper.StudentMapper"><delete id="deleteById">delete from student where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete><select id="page" resultType="com.tlias.entity.Student">select * from student<where><if test="name != null and name != ''">name like concat('%',#{name},'%')</if><if test="gender != null">and gender != #{gender}</if></where></select>
</mapper>
3.5、数据统计
3.5.1、前端核心代码
<template><div class="chart-container"><div style="width: 50%; "><h1>员工性别统计</h1> <br><div id="myChart1" style="width: 100%; height: 500px"></div></div><div style="width: 50%; "><h1>员工职位统计</h1> <br><div id="myChart2" style="width: 100%; height: 500px"></div></div></div>
</template><script>
import * as echarts from 'echarts'
import { getGenderData, getJobData } from "@/api/report.js";export default {data() {return {genderCountList: [],jobCategoryList:[],jobDataList:[]}},mounted() { this.getGenderData(); //获取员工性别统计数据this.getJobData(); //获取员工职位统计数据},methods: {//获取员工性别统计数据getGenderData(){getGenderData().then((result) => {if(result.data.code == 1){this.genderCountList = result.data.data;this.initChart1();}});},//获取员工职位统计数据getJobData(){getJobData().then((result) => {if(result.data.code == 1){this.jobCategoryList = result.data.data.categoryList;this.jobDataList = result.data.data.dataList;this.initChart2();}});},initChart1() {// 获取图表容器, 创建图表实例let myChart = echarts.init(document.querySelector('#myChart1'));let option = {tooltip: {trigger: 'item'},legend: {top: '5%',left: 'center'},series: [{name: '员工性别统计',type: 'pie',radius: ['40%', '70%'],avoidLabelOverlap: false,itemStyle: {borderRadius: 10,borderColor: '#fff',borderWidth: 2},label: {show: false,position: 'center'},emphasis: {label: {show: true,fontSize: 40,fontWeight: 'bold'}},labelLine: {show: false},data: this.genderCountList}]};// 绘制图表myChart.setOption(option);},initChart2() {// 获取图表容器, 创建图表实例let myChart = echarts.init(document.querySelector('#myChart2'));let option = {xAxis: {type: 'category',data: this.jobCategoryList},yAxis: {type: 'value'},series: [{data: this.jobDataList,type: 'bar'}]};// 绘制图表myChart.setOption(option);}}
};
</script><style>h1 {text-align: center;}.chart-container {display: flex;}.chart-container > div {flex: 1;}
</style>
3.5.2、后端代码实现
实体类
@Data
public class PieChartData {private String name;private String value;
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentData {private List categoryList;private List dataList;
}
controller
@RestController
@RequestMapping("/report")
@Slf4j
public class ReportController {@Autowiredprivate ReportService service;@GetMapping("/empGenderData")public Result getEmpGenderData(){log.info("员工性别信息信息");List<PieChartData> list = service.getEmpGenderData();return Result.success(list);}@GetMapping("/empJobData")public Result getEmpJobData(){log.info("员工职位信息");JobData jobData = service.getEmpJobData();return Result.success(jobData);}@GetMapping("/studentData")public Result getStudentData(){log.info("学员人数统计");StudentData studentData = service.getStudentData();return Result.success(studentData);}
}
service层
public interface ReportService {/*** 员工性别统计* @return*/List<PieChartData> getEmpGenderData();/*** 员工职位信息统计* @return*/JobData getEmpJobData();/*** 学员统计* @return*/StudentData getStudentData();
}@Service
public class ReportServiceImpl implements ReportService {@Autowiredprivate EmpMapper empMapper;@Autowiredprivate StudentMapper studentMapper;/*** 员工性别统计** @return*/@Overridepublic List<PieChartData> getEmpGenderData() {List<PieChartData> list = empMapper.getEmpGenderData();return list;}/*** 员工职位信息统计** @return*/@Overridepublic JobData getEmpJobData() {List<Map<String,Object>> mapList = empMapper.getEmpJobData();System.out.println(mapList);if (!CollectionUtils.isEmpty(mapList)) {List<Object> categoryList = mapList.stream().map(map -> {return map.get("job");}).collect(Collectors.toList());List<Object> dataList = mapList.stream().map(map -> {return map.get("jobcount");}).collect(Collectors.toList());JobData jobData = new JobData();jobData.setCategoryList(categoryList);jobData.setDataList(dataList);System.out.println(jobData);return jobData;}return null;}/*** 学员统计** @return*/@Overridepublic StudentData getStudentData() {List<Map<String,Object>> mapList = studentMapper.getStudentData();System.out.println(mapList);if (!CollectionUtils.isEmpty(mapList)){List<Object> categoryList = mapList.stream().map(map -> {return map.get("class");}).collect(Collectors.toList());List<Object> dataList = mapList.stream().map(map -> {return map.get("classcount");}).collect(Collectors.toList());return new StudentData(categoryList,dataList);}return null;}
}
3.6、登录功能
我们已经实现了部门管理、员工管理的基本功能,但是大家会发现,我们并没有登录,就直接访问到了后台。 这是不安全的,所以要做登录认证。 最终我们要实现的效果就是用户必须登录之后,才可以访问后台系统中的功能
JWT令牌最典型的应用场景就是登录认证:
- 在浏览器发起请求来执行登录操作,此时会访问登录的接口,如果登录成功之后,我们需要生成一个jwt令牌,将生成的 jwt令牌返回给前端。
- 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。
- 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处理。
在JWT登录认证的场景中我们发现,整个流程当中涉及到两步操作:
- 在登录成功之后,要生成令牌。
- 每一次请求当中,要接收令牌并对令牌进行校验。
3.6.1、前端核心代码
<template><div class="login-container"><el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left"><div class="title-container"><h3 class="title">Tlias智能学习辅助系统</h3></div><el-form-item prop="username"><span class="svg-container"><svg-icon icon-class="user" /></span><el-inputref="username"v-model="loginForm.username"placeholder="Username"name="username"type="text"tabindex="1"auto-complete="on"/></el-form-item><el-form-item prop="password"><span class="svg-container"><svg-icon icon-class="password" /></span><el-input:key="passwordType"ref="password"v-model="loginForm.password":type="passwordType"placeholder="Password"name="password"tabindex="2"auto-complete="on"@keyup.enter.native="handleLogin"/><span class="show-pwd" @click="showPwd"><svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /></span></el-form-item><el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button></el-form></div>
</template><script>
import { validUsername } from '@/utils/validate'
import { login } from '@/api/user'
import { setToken } from '@/utils/auth'
export default {name: 'Login',data() {//用户名校验规则const validateUsername = (rule, value, callback) => {if (!validUsername(value)) {callback(new Error('请输入正确的用户名'))} else {callback()}}//用户名校验规则const validatePassword = (rule, value, callback) => {if (value.length < 6) {callback(new Error('密码长度至少为6位'))} else {callback()}}//数据模型return {loginForm: {username: 'jinyong',password: '123456'},loginRules: {username: [{ required: true, trigger: 'blur', validator: validateUsername }],password: [{ required: true, trigger: 'blur', validator: validatePassword }]},loading: false,passwordType: 'password',redirect: undefined}},methods: {//展示密码showPwd() {if (this.passwordType === 'password') {this.passwordType = ''} else {this.passwordType = 'password'}this.$nextTick(() => {this.$refs.password.focus()})},//登录方法handleLogin() {this.$refs.loginForm.validate(valid => {if (valid) {this.loading = true//调用登录后端接口login(this.loginForm).then((result) => {console.log(result)if (result.data.code == 1) {setToken(result.data.data);console.log('login success');this.$router.push('/');} else {this.$message.error(result.data.msg);this.loading = false}});} else {console.log('error submit!!')return false}})}}
}
</script><style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */$bg:#283443;
$light_gray:#fff;
$cursor: #fff;@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {.login-container .el-input input {color: $cursor;}
}/* reset element-ui css */
.login-container {.el-input {display: inline-block;height: 47px;width: 85%;input {background: transparent;border: 0px;-webkit-appearance: none;border-radius: 0px;padding: 12px 5px 12px 15px;color: $light_gray;height: 47px;caret-color: $cursor;&:-webkit-autofill {box-shadow: 0 0 0px 1000px $bg inset !important;-webkit-text-fill-color: $cursor !important;}}}.el-form-item {border: 1px solid rgba(255, 255, 255, 0.1);background: rgba(0, 0, 0, 0.1);border-radius: 5px;color: #454545;}
}
</style><style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;.login-container {min-height: 100%;width: 100%;background-color: $bg;overflow: hidden;.login-form {position: relative;width: 520px;max-width: 100%;padding: 160px 35px 0;margin: 0 auto;overflow: hidden;}.tips {font-size: 14px;color: #fff;margin-bottom: 10px;span {&:first-of-type {margin-right: 16px;}}}.svg-container {padding: 6px 5px 6px 15px;color: $dark_gray;vertical-align: middle;width: 30px;display: inline-block;}.title-container {position: relative;.title {font-size: 26px;color: $light_gray;margin: 0px auto 40px auto;text-align: center;font-weight: bold;font-family: '楷体';}}.show-pwd {position: absolute;right: 10px;top: 7px;font-size: 16px;color: $dark_gray;cursor: pointer;user-select: none;}
}
</style>
3.6.2、后端代码实现
创建工具类,实现jwt令牌的发放和解析
public class JwtUtils {private static String signKey = "jwtHelloWorld";private static Long expire = 60 * 60 * 1000L;public static String generateToken(Map<String, Object> claims) {String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, signKey).setExpiration(new Date(System.currentTimeMillis() + expire)).compact();return token;}public static Claims parseToken(String token) {Claims claims = Jwts.parser().setSigningKey(signKey).parseClaimsJws(token).getBody();return claims;}
}
创建拦截器,进行拦截
/*** 自定义拦截器*/
@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1、获取请求urlString url = request.getRequestURI().toString();//3、获取请求头中的tokenString token = request.getHeader("token");if (!StringUtils.hasLength(token)){ //不存在log.info("获取令牌为空");Result notLogin = Result.error("NOT_LOGIN");String json = JSONObject.toJSONString(notLogin);response.getWriter().write(json);return false;}//4、解析token,失败则未登录try {Claims claims = JwtUtils.parseToken(token);} catch (Exception e) {log.info("解析令牌错误");Result notLogin = Result.error("NOT_LOGIN");String json = JSONObject.toJSONString(notLogin);response.getWriter().write(json);return false;}//5、放行return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion");}
}
controller层
@RestController
@Slf4j
public class LoginController {@Autowiredprivate EmpService empService;@PostMapping("/login")public Result login(@RequestBody Emp emp){log.info("员工登录{}",emp);Emp empLogin = empService.login(emp);if (empLogin != null){Map<String, Object> map = new HashMap<>();map.put("id", empLogin.getId());map.put("username", empLogin.getUsername());String token = JwtUtils.generateToken(map);return Result.success(token);}return Result.error("查无此用户");}
}