P4-新增员工功能开发
1.需求分析
页面功能分析:后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。点击【添加员工】按钮,跳转到新增页面如下
2.数据模型
2.1数据模型分析
新增员工,其实就是将我们新增页面录入的员工数据插入到employee。注意,表中对应username字段加入了唯一约束,因为username是员工登录账号,必须是唯一的。
2.2数据库表设计
-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` bigint(20) NOT NULL COMMENT '主键',
`name` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '姓名',
`username` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '用户名',
`password` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '密码',
`phone` varchar(11) COLLATE utf8_bin NOT NULL COMMENT '手机号',
`sex` varchar(2) COLLATE utf8_bin NOT NULL COMMENT '性别',
`id_number` varchar(18) COLLATE utf8_bin NOT NULL COMMENT '身份证号',
`status` int(11) NOT NULL DEFAULT '1' COMMENT '状态 0:禁用,1:正常',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`update_user` bigint(20) NOT NULL COMMENT '修改人',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='员工信息';
-- ----------------------------
-- Records of employee
-- ----------------------------
————————————————
版权声明:本文为CSDN博主「学无止境DayDayUp」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45498432/article/details/124764670
3.代码开发
3.1程序执行流程分析
- 页面发送Ajax请求,将新增员工页面中输入的数据以JSON的形式提交到服务器
- 服务端Controller接收页面提交的数据,并调用Service将数据保存
- Service调用Mapper操作数据库,保存数据。
3.1前端页面代码
3.1.1员工管理页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入样式 -->
<link rel="stylesheet" href="../../plugins/element-ui/index.css" />
<link rel="stylesheet" href="../../styles/common.css" />
<link rel="stylesheet" href="../../styles/page.css" />
<style>
#member-app .notAdmin::after{
border: 0 !important;
}
</style>
</head>
<body>
<div class="dashboard-container" id="member-app">
<div class="container">
<div class="tableBar">
<el-input
v-model="input"
placeholder="请输入员工姓名"
style="width: 250px"
clearable
@keyup.enter.native="handleQuery"
>
<i
slot="prefix"
class="el-input__icon el-icon-search"
style="cursor: pointer"
@click="handleQuery"
></i>
</el-input>
<el-button
type="primary"
@click="addMemberHandle('add')"
>
+ 添加员工
</el-button>
</div>
<el-table
:data="tableData"
stripe
class="tableBox"
>
<el-table-column
prop="name"
label="员工姓名"
></el-table-column>
<el-table-column
prop="username"
label="账号"
></el-table-column>
<el-table-column
prop="phone"
label="手机号"
></el-table-column>
<el-table-column label="账号状态">
<template slot-scope="scope">
{{ String(scope.row.status) === '0' ? '已禁用' : '正常' }}
</template>
</el-table-column>
<el-table-column
label="操作"
width="160"
align="center"
>
<template slot-scope="scope">
<el-button
type="text"
size="small"
class="blueBug"
@click="addMemberHandle(scope.row.id)"
:class="{notAdmin:user !== 'admin'}"
>
编辑
</el-button>
<el-button
type="text"
size="small"
class="delBut non"
@click="statusHandle(scope.row)"
v-if="user === 'admin'"
>
{{ scope.row.status == '1' ? '禁用' : '启用' }}
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
class="pageList"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="counts"
:current-page.sync="page"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</div>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="../../plugins/vue/vue.js"></script>
<!-- 引入组件库 -->
<script src="../../plugins/element-ui/index.js"></script>
<!-- 引入axios -->
<script src="../../plugins/axios/axios.min.js"></script>
<script src="../../js/request.js"></script>
<script src="../../api/member.js"></script>
<script>
new Vue({
el: '#member-app',
data() {
return {
input: '',
counts: 0,
page: 1,
pageSize: 10,
tableData : [],
id : '',
status : '',
}
},
computed: {},
created() {
this.init()
this.user = JSON.parse(localStorage.getItem('userInfo')).username
},
mounted() {
},
methods: {
async init () {
const params = {
page: this.page,
pageSize: this.pageSize,
name: this.input ? this.input : undefined
}
await getMemberList(params).then(res => {
if (String(res.code) === '1') {
this.tableData = res.data.records || []
this.counts = res.data.total
}
}).catch(err => {
this.$message.error('请求出错了:' + err)
})
},
handleQuery() {
this.page = 1;
this.init();
},
// 添加
addMemberHandle (st) {
if (st === 'add'){
window.parent.menuHandle({
id: '2',
url: '/backend/page/member/add.html',
name: '添加员工'
},true)
} else {
window.parent.menuHandle({
id: '2',
url: '/backend/page/member/add.html?id='+st,
name: '修改员工'
},true)
}
},
//状态修改
statusHandle (row) {
this.id = row.id
this.status = row.status
this.$confirm('确认调整该账号的状态?', '提示', {
'confirmButtonText': '确定',
'cancelButtonText': '取消',
'type': 'warning'
}).then(() => {
enableOrDisableEmployee({ 'id': this.id, 'status': !this.status ? 1 : 0 }).then(res => {
console.log('enableOrDisableEmployee',res)
if (String(res.code) === '1') {
this.$message.success('账号状态更改成功!')
this.handleQuery()
}
}).catch(err => {
this.$message.error('请求出错了:' + err)
})
})
},
handleSizeChange (val) {
this.pageSize = val
this.init()
},
handleCurrentChange (val) {
this.page = val
this.init()
}
}
})
</script>
</body>
</html>
3.1.2添加员工页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入样式 -->
<link rel="stylesheet" href="../../plugins/element-ui/index.css" />
<link rel="stylesheet" href="../../styles/common.css" />
<link rel="stylesheet" href="../../styles/page.css" />
</head>
<body>
<div class="addBrand-container" id="member-add-app">
<div class="container">
<el-form
ref="ruleForm"
:model="ruleForm"
:rules="rules"
:inline="false"
label-width="180px"
class="demo-ruleForm"
>
<el-form-item label="账号:" prop="username">
<el-input v-model="ruleForm.username" placeholder="请输入账号" maxlength="20"/>
</el-form-item>
<el-form-item
label="员工姓名:"
prop="name"
>
<el-input
v-model="ruleForm.name"
placeholder="请输入员工姓名"
maxlength="20"
/>
</el-form-item>
<el-form-item
label="手机号:"
prop="phone"
>
<el-input
v-model="ruleForm.phone"
placeholder="请输入手机号"
maxlength="20"
/>
</el-form-item>
<el-form-item
label="性别:"
prop="sex"
>
<el-radio-group v-model="ruleForm.sex">
<el-radio label="男"></el-radio>
<el-radio label="女"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label="身份证号:"
prop="idNumber"
>
<el-input
v-model="ruleForm.idNumber"
placeholder="请输入身份证号"
maxlength="20"
/>
</el-form-item>
<div class="subBox address">
<el-form-item>
<el-button @click="goBack()">
取消
</el-button>
<el-button
type="primary"
@click="submitForm('ruleForm', false)"
>
保存
</el-button>
<el-button
v-if="actionType == 'add'"
type="primary"
class="continue"
@click="submitForm('ruleForm', true)"
>
保存并继续添加
</el-button>
</el-form-item>
</div>
</el-form>
</div>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="../../plugins/vue/vue.js"></script>
<!-- 引入组件库 -->
<script src="../../plugins/element-ui/index.js"></script>
<!-- 引入axios -->
<script src="../../plugins/axios/axios.min.js"></script>
<script src="../../js/request.js"></script>
<script src="../../api/member.js"></script>
<script src="../../js/validate.js"></script>
<script src="../../js/index.js"></script>
<script>
new Vue({
el: '#member-add-app',
data() {
return {
id: '',
actionType : '',
ruleForm : {
'name': '',
'phone': '',
'sex': '男',
'idNumber': '',
username: ''
}
}
},
computed: {
rules () {
return {
//账号
username: [
{
required: true, 'validator': checkUserName, trigger: 'blur'
}
],
//姓名
name: [{ required: true, 'validator': checkName, 'trigger': 'blur' }],
'phone': [{ 'required': true, 'validator': checkPhone, 'trigger': 'blur' }],
'idNumber': [{ 'required': true, 'validator': validID, 'trigger': 'blur' }]
}
}
},
created() {
this.id = requestUrlParam('id')
this.actionType = this.id ? 'edit' : 'add'
if (this.id) {
this.init()
}
},
mounted() {
},
methods: {
async init () {
queryEmployeeById(this.id).then(res => {
console.log(res)
if (String(res.code) === '1') {
console.log(res.data)
this.ruleForm = res.data
this.ruleForm.sex = res.data.sex === '0' ? '女' : '男'
// this.ruleForm.password = ''
} else {
this.$message.error(res.msg || '操作失败')
}
})
},
submitForm (formName, st) {
this.$refs[formName].validate((valid) => {
if (valid) {
if (this.actionType === 'add') {
const params = {
...this.ruleForm,
sex: this.ruleForm.sex === '女' ? '0' : '1'
}
addEmployee(params).then(res => {
if (res.code === 1) {
this.$message.success('员工添加成功!')
if (!st) {
this.goBack()
} else {
this.ruleForm = {
username: '',
'name': '',
'phone': '',
// 'password': '',
// 'rePassword': '',/
'sex': '男',
'idNumber': ''
}
}
} else {
this.$message.error(res.msg || '操作失败')
}
}).catch(err => {
this.$message.error('请求出错了:' + err)
})
} else {
const params = {
...this.ruleForm,
sex: this.ruleForm.sex === '女' ? '0' : '1'
}
editEmployee(params).then(res => {
if (res.code === 1) {
this.$message.success('员工信息修改成功!')
this.goBack()
} else {
this.$message.error(res.msg || '操作失败')
}
}).catch(err => {
this.$message.error('请求出错了:' + err)
})
}
} else {
console.log('error submit!!')
return false
}
})
},
goBack(){
window.parent.menuHandle({
id: '2',
url: '/backend/page/member/list.html',
name: '员工管理'
},false)
}
}
})
</script>
</body>
</html>
3.1.3 添加员工js代码
// 新增---添加员工
function addEmployee (params) {
return $axios({
url: '/employee',
method: 'post',
data: { ...params }
})
}
3.2后端方法实现代码
3.2.1 Controller层代码
-
根据Ajax请求和js代码 填写路径信息
-
根据页面代码 对应的数据 res 判断返回值 res.code
/** * 新增员工 * 根据Ajax请求和js代码 填写路径信息 * @param employee * @return 根据页面代码 对应的数据 res 判断返回值 res.code */ @PostMapping public R<String> save(HttpServletRequest request ,@RequestBody Employee employee){ log.info("新增员工,员工信息:{}",employee.toString()); //设置初始密码:123456,需要进行md5加密处理 employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes())); //创建时间,更新时间,设置为当前时间 employee.setCreateTime(LocalDateTime.now()); employee.setUpdateTime(LocalDateTime.now()); //创建人,即当前登录用户 //获取当前登录用户的id Long empId = (Long) request.getSession().getAttribute("employee"); employee.setCreateUser(empId); //最后的更新人 employee.setUpdateUser(empId); //保存 employeeService.save(employee); return R.success("新增员工成功"); }
-
username是唯一的,需要解决在添加时账号重复问题,采用异常处理(全局异常)
package com.jq.commom; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.sql.SQLIntegrityConstraintViolationException; /** * 全局异常处理器 * 基于代理 * @ControllerAdvice() :通知 ,拦截哪些controller * @ResponseBody :方法返回JSON数据 * @ExceptionHandler() :里面是要处理的哪种异常 */ @ControllerAdvice(annotations = {RestController.class, Controller.class}) @ResponseBody @Slf4j public class GlobalExceptionHandler { /** * 异常处理方法 * @return */ @ExceptionHandler(SQLIntegrityConstraintViolationException.class) public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){ log.error(ex.getMessage()); //解决username重复问题,使username唯一 if (ex.getMessage().contains("Duplicate entry")){ //对ERROR 964 --- [nio-8080-exec-4] : Duplicate entry 'zhangsan' for key 'employee.idx_username' 按照空格分割 String[] split = ex.getMessage().split(" "); //'zhangsan' split[2] String msg="账号"+split[2]+"已存在"; return R.error(msg); } return R.error("未知错误"); } }
3.2.2 Service层
package com.jq.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jq.entity.Employee;
public interface EmployeeService extends IService<Employee> {
}
3.3小结
- 前端页面发送请求,提交参数
- 后端服务处理,给前端页面响应数据