瑞吉外卖项目学习笔记: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程序执行流程分析

  1. 页面发送Ajax请求,将新增员工页面中输入的数据以JSON的形式提交到服务器
  2. 服务端Controller接收页面提交的数据,并调用Service将数据保存
  3. 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层代码

  1. 根据Ajax请求和js代码 填写路径信息

  2. 根据页面代码 对应的数据 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("新增员工成功");
        }
    
  3. 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小结

  1. 前端页面发送请求,提交参数
  2. 后端服务处理,给前端页面响应数据
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值