专栏首页cwl_JavaSaaS-用户管理

SaaS-用户管理

4 用户管理

4.1 需求分析

用户其实就是saas企业访问的员工,对企业员工完成基本的CRUD操作 表结构如下:

CREATE TABLE `bs_user` (
 `id` varchar(40) NOT NULL COMMENT 'ID',
 `mobile` varchar(40) NOT NULL COMMENT '手机号码',
 `username` varchar(255) NOT NULL COMMENT '用户名称',
 `password` varchar(255) DEFAULT NULL COMMENT '密码',
 `enable_state` int(2) DEFAULT '1' COMMENT '启用状态 0是禁用,1是启用',
 `create_time` datetime DEFAULT NULL COMMENT '创建时间',
 `department_id` varchar(40) DEFAULT NULL COMMENT '部门ID',
 `time_of_entry` datetime DEFAULT NULL COMMENT '入职时间',
 `form_of_employment` int(1) DEFAULT NULL COMMENT '聘用形式',
 `work_number` varchar(20) DEFAULT NULL COMMENT '工号',
 `form_of_management` varchar(8) DEFAULT NULL COMMENT '管理形式',
 `working_city` varchar(16) DEFAULT NULL COMMENT '工作城市',
 `correction_time` datetime DEFAULT NULL COMMENT '转正时间',
 `in_service_status` int(1) DEFAULT NULL COMMENT '在职状态 1.在职 2.离职',
 `company_id` varchar(40) DEFAULT NULL COMMENT '企业ID',
 `company_name` varchar(40) DEFAULT NULL,
 `department_name` varchar(40) DEFAULT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `idx_user_phone` (`mobile`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

4.2 配置系统微服务

(1)搭建系统微服务模块(ihrm_system),pom引入依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ihrm</groupId>
            <artifactId>ihrm_common</artifactId>
             <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

(2)配置application.yml

server:
 port: 9002
spring:
 application:
   name: ihrm-system #指定服务名
 datasource:
   driver-class-name: com.mysql.jdbc.Driver
   url: jdbc:mysql://localhost:3306/ihrm?useUnicode=true&characterEncoding=utf8
   username: root
   password: 111111
 jpa:
   database: MySQL
   show-sql: true
   open-in-view: true

(3)配置启动类

import com.ihrm.common.utils.IdWorker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;

//1.配置springboot的包扫描
@SpringBootApplication(scanBasePackages = "com.ihrm")
//2.配置jpa注解的扫描
@EntityScan(value="com.ihrm.domain.system")
public class SystemApplication {
    /**
     * 启动方法
     */
    public static void main(String[] args) {
        SpringApplication.run(SystemApplication.class,args);
    }

    @Bean
    public IdWorker idWorker() {
        return new IdWorker();
    }
}

4.3 后端用户基本操作

(1)实体类

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 用户实体类
 */
@Entity
@Table(name = "bs_user")
@Getter
@Setter
public class User implements Serializable {
    private static final long serialVersionUID = 4297464181093070302L;
    /**
     * ID
     */
    @Id
    private String id;
    /**
     * 手机号码
     */
    private String mobile;
    /**
     * 用户名称
     */
    private String username;
    /**
     * 密码
     */
    private String password;

    /**
     * 启用状态 0为禁用 1为启用
     */
    private Integer enableState;
    /**
     * 创建时间
     */
    private Date createTime;

    private String companyId;

    private String companyName;

    /**
     * 部门ID
     */
    private String departmentId;

    /**
     * 入职时间
     */
    private Date timeOfEntry;

    /**
     * 聘用形式
     */
    private Integer formOfEmployment;

    /**
     * 工号
     */
    private String workNumber;

    /**
     * 管理形式
     */
    private String formOfManagement;

    /**
     * 工作城市
     */
    private String workingCity;

    /**
     * 转正时间
     */
    private Date correctionTime;

    /**
     * 在职状态 1.在职  2.离职
     */
    private Integer inServiceStatus;

    private String departmentName;

    /**
     *  JsonIgnore
     *     : 忽略json转化
     */
    @JsonIgnore
    @ManyToMany
    @JoinTable(name="pe_user_role",joinColumns={@JoinColumn(name="user_id",referencedColumnName="id")},
            inverseJoinColumns={@JoinColumn(name="role_id",referencedColumnName="id")}
    )
    private Set<Role> roles = new HashSet<Role>();//用户与角色   多对多
}

(2)持久化层

import com.ihrm.domain.system.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface UserDao extends JpaRepository<User,String>,JpaSpecificationExecutor<User> {
}

(3)业务逻辑层

import com.ihrm.common.utils.IdWorker;
import com.ihrm.domain.system.User;
import com.ihrm.system.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private IdWorker idWorker;

    /**
     * 1.保存用户
     */
    public void save(User user) {
        //设置主键的值
        String id = idWorker.nextId()+"";
        user.setPassword("123456");//设置初始密码
        user.setEnableState(1);
        user.setId(id);
        //调用dao保存部门
        userDao.save(user);
    }

    /**
     * 2.更新用户
     */
    public void update(User user) {
        //1.根据id查询部门
        User target = userDao.findById(user.getId()).get();
        //2.设置部门属性
        target.setUsername(user.getUsername());
        target.setPassword(user.getPassword());
        target.setDepartmentId(user.getDepartmentId());
        target.setDepartmentName(user.getDepartmentName());
        //3.更新部门
        userDao.save(target);
    }

    /**
     * 3.根据id查询用户
     */
    public User findById(String id) {
        return userDao.findById(id).get();
    }

    /**
     * 4.查询全部用户列表
     *      参数:map集合的形式
     *          hasDept
     *          departmentId
     *          companyId
     *
     */
    public Page findAll(Map<String,Object> map,int page, int size) {
        //1.需要查询条件
        Specification<User> spec = new Specification<User>() {
            /**
             * 动态拼接查询条件
             * @return
             */
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<>();
                //根据请求的companyId是否为空构造查询条件
                if(!StringUtils.isEmpty(map.get("companyId"))) {
                    list.add(criteriaBuilder.equal(root.get("companyId").as(String.class),(String)map.get("companyId")));
                }
                //根据请求的部门id构造查询条件
                if(!StringUtils.isEmpty(map.get("departmentId"))) {
                    list.add(criteriaBuilder.equal(root.get("departmentId").as(String.class),(String)map.get("departmentId")));
                }
                if(!StringUtils.isEmpty(map.get("hasDept"))) {
                    //根据请求的hasDept判断  是否分配部门 0未分配(departmentId = null),1 已分配 (departmentId != null)
                    if("0".equals((String) map.get("hasDept"))) {
                        list.add(criteriaBuilder.isNull(root.get("departmentId")));
                    }else {
                        list.add(criteriaBuilder.isNotNull(root.get("departmentId")));
                    }
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };

        //2.分页
        Page<User> pageUser = userDao.findAll(spec, new PageRequest(page-1, size));
        return pageUser;
    }

    /**
     * 5.根据id删除用户
     */
    public void deleteById(String id) {
        userDao.deleteById(id);
    }
}

(4)控制器层

import com.ihrm.common.controller.BaseController;
import com.ihrm.common.entity.PageResult;
import com.ihrm.common.entity.Result;
import com.ihrm.common.entity.ResultCode;

import com.ihrm.domain.system.User;
import com.ihrm.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import javax.websocket.server.PathParam;
import java.util.List;
import java.util.Map;

//1.解决跨域
@CrossOrigin
//2.声明restContoller
@RestController
//3.设置父路径
@RequestMapping(value="/sys")
public class UserController extends BaseController {

    @Autowired
    private UserService userService;

    /**
     * 保存
     */
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public Result save(@RequestBody User user) {
        //1.设置保存的企业id
        user.setCompanyId(companyId);
        user.setCompanyName(companyName);
        //2.调用service完成保存企业
        userService.save(user);
        //3.构造返回结果
        return new Result(ResultCode.SUCCESS);
    }

    /**
     * 查询企业的部门列表
     * 指定企业id
     */
    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public Result findAll(int page, int size, @RequestParam Map map) {
        //1.获取当前的企业id
        map.put("companyId",companyId);
        //2.完成查询
        Page<User> pageUser = userService.findAll(map,page,size);
        //3.构造返回结果
        PageResult pageResult = new PageResult(pageUser.getTotalElements(),pageUser.getContent());
        return new Result(ResultCode.SUCCESS, pageResult);
    }

    /**
     * 根据ID查询user
     */
    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    public Result findById(@PathVariable(value = "id") String id) {
        User user = userService.findById(id);
        return new Result(ResultCode.SUCCESS, user);
    }

    /**
     * 修改User
     */
    @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
    public Result update(@PathVariable(value = "id") String id, @RequestBody User user) {
        //1.设置修改的部门id
        user.setId(id);
        //2.调用service更新
        userService.update(user);
        return new Result(ResultCode.SUCCESS);
    }

    /**
     * 根据id删除
     */
    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    public Result delete(@PathVariable(value = "id") String id) {
        userService.deleteById(id);
        return new Result(ResultCode.SUCCESS);
    }
}

4.4 前端用户基本操作

4.4.2 配置接口请求路径

config/index.js 中通过proxyTable配置代理转发的请求后端地址

    '/api/sys': {
        target: 'http://localhost:9002/sys',
        changeOrigin: true,
        pathRewrite: {
          '^/api/sys': ''
       }
     },

4.4.1 导入员工模块

注册模块

import employees from '@/module-employees/' // 员工管理
Vue.use(employees, store)

/src/api/base/ 下配置API(user.js)

import {createAPI} from '@/utils/request'
export const list = data => createAPI('/sys/user', 'get', data)
export const simple = data => createAPI('/sys/user/simple', 'get', data)
export const add = data => createAPI('/sys/user', 'post', data)
export const update = data => createAPI(`/sys/user/${data.id}`, 'put', data)
export const remove = data => createAPI(`/sys/user/${data.id}`, 'delete', data)
export const detail = data => createAPI(`/sys/user/${data.id}`, 'get', data)

4.4.2 用户列表展示

(1) 页面代码

 <el-table :data="dataList" fit style="width: 100%;" border>
          <el-table-column type="index" :index="1" label="序号" width="150"> </el-tablecolumn>
          <el-table-column sortable prop="username" label="姓名" width="150"></el-tablecolumn>
          <el-table-column sortable prop="mobile" label="手机号" width="150"></el-tablecolumn>
          <el-table-column sortable prop="workNumber" label="工号" width="120"></eltable-column>
           <el-table-column sortable prop="formOfEmployment" label="聘用形势"
width="200"></el-table-column>
          <el-table-column sortable prop="departmentName" label="部门" width="200"></eltable-column>
          <el-table-column sortable prop="timeOfEntry" label="入职时间" width="150">
</el-table-column>
          <el-table-column sortable label="状态" width="120">
            <template slot-scope="scope">
              <el-switch
              v-model="scope.row.accountStatus"
              active-color="#13ce66"
              inactive-color="#ff4949"
               @change="handleStatus(scope.row)">
              </el-switch>
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" align="center" width="220">
            <template slot-scope="scope">
              <router-link :to="{'path':'/employees/details/' + scope.row.id}"
class="el-button el-button--text el-button--small">
               查看
              </router-link>
              <el-button @click="handleDelete(scope.row)" type="text" size="small">删除
</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页 -->
        <div class="pagination">
          <PageTool :paginationPage="requestParameters.page"
:paginationPagesize="requestParameters.pagesize" :total="counts"
@pageChange="handleCurrentChange" @pageSizeChange="handleSizeChange">
          </PageTool>
        </div>

(2) js构造数据

import constantApi from '@/api/constant/employees'
import {list,remove} from "@/api/base/users"
import PageTool from './../../components/page/page-tool'
import employeesAdd from './../components/add'
var _this = null
export default {
  name: 'employeesList',
  components: {
    PageTool,employeesAdd
 },
  data() {
    return {
      employeesAdd: 'employeesAdd',
      baseData: constantApi,
      dataList: [],
      counts: '',
       requestParameters:{
        page: 1,
        pagesize: 10,
     }    
   }
 },
  methods: {
    // 业务方法
    doQuery(params) {
        list(this.requestParameters).then(res => {
          this.dataList = res.data.data.rows
          this.counts = res.data.data.total
       })
   }
 },
  // 创建完毕状态
  created: function() {
    this.doQuery()
 },
}

4.4.4 用户详情

(1) 配置路由

 {
        path: 'details/:id',
        component: _import('employees/pages/employees-details'),
        // hidden: true // 是否显示在左侧菜单
        name: 'details',
        meta: {
          title: '详情'
       }
     }

(2) 完成用户详情页面

<template>
  <div class="dashboard-container">
    <div class="app-container">
      <el-card :style="{minHeight:boxHeight}">
          <el-tabs v-model="activeName" class="infoPosin">
            <el-tab-pane name="first" class="rInfo">
              <span slot="label">登录账户设置</span>
              <component v-bind:is="accountInfo" :objId='objId' ref="user"></component>
            </el-tab-pane>
            <el-tab-pane name="two" class="rInfo">
                <span slot="label">个人详情</span>
            </el-tab-pane>
            <el-tab-pane name="third" class="rInfo">
                <span slot="label">岗位信息</span>
            </el-tab-pane>
               </el-tabs>
      </el-card>
    </div>
  </div>
</template>
<script>
import accountInfo from './../components/details-account-info'
export default {
  name: 'employeesDetails',
  components: { accountInfo},
  data() {
    return {
      accountInfo:'accountInfo',
      activeName: 'first',
      objId: this.$route.params.id,
      dataList: []
   }
 }
}</script>

(3) 用户信息组件

<template>
  <div class="boxInfo">
    <!-- 表单内容 -->
    <div class="formInfo">
      <div>
        <!-- 头部信息  -->
        <div class="userInfo">
             <div class="headInfo clearfix">
               <div class="headText">
                 <el-form ref="formData" :model="formData" label-width="215px">
                     <el-form-item label="姓名:">
                       <el-input v-model="formData.username" placeholder="请输入"
class="inputW"></el-input>
                     </el-form-item>
                     <el-form-item label="密码:">
                       <el-input v-model="formData.password" placeholder="请输入"
class="inputW"></el-input>
                    </el-form-item>
                    <el-form-item label="部门:">
                        <el-input
                          placeholder="请选择"
                          v-model="formData.departmentName"
                          icon="caret-bottom"
                          class="inputW"
                          @click.native="isShowSelect = !isShowSelect">
                        </el-input>
                        <input v-model="formData.departmentId" type="hidden" >
                        <el-tree v-if="isShowSelect"
                         :expand-on-click-node="false"
                         :data="inspectionObjectOptions"
                         :props="{label:'name'}"
                          default-expand-all
                         :filter-node-method="filterNode"
                           @node-click="handleNodeClick"
                          class="objectTree"
                          ref="tree2">
                        </el-tree>
                    </el-form-item>
                      <el-form-item>
                        <el-button type="primary" @click="saveData">更新</el-button>
                        <router-link :to="{'path':'/employees/index'}" class="el-button 
el-button--text el-button--small">
                          取消
                        </router-link>
                      </el-form-item>
                 </el-form>
               </div>
             </div>
        </div>
      </div>
    </div>
    </div>
</template>
<script>
import constantApi from '@/api/constant/employees'
import {detail,update} from "@/api/base/users"
import { organList } from '@/api/base/departments'
export default {
  name: 'accountInfo',
  props: ['objId'],
  data() {
    return {
      baseData: constantApi,
      inspectionObjectOptions: [],
      isShowSelect:false,
      formData: {
        id: this.objId,
     }
   }
 },
  methods: {
    handleNodeClick(data) {
      this.formData.departmentName = data.name
      this.formData.departmentId = data.id
      this.isShowSelect = false
   },
    // 获取详情
    getObjInfo() {
      detail({ id: this.objId }).then(res => {
          this.formData = res.data.data
     })
      },
    saveData(obj) {
      update(this.formData)
       .then(res => {
          this.formData = res.data
          this.$message.success('保存成功!')
          this.getObjInfo()
     })
   },
 },
  // 创建完毕状态
  created: function() {
    this.getObjInfo()
    organList().then(ret => {
      this.inspectionObjectOptions.push(ret.data.data)
   })
 }
}</script>

4.4.3 用户的新增

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 快速学习-SpringBoot整合Junit

    SpringRunner继承自SpringJUnit4ClassRunner,使用哪一个Spring提供的测试测试引擎都可以

    cwl_java
  • 快速学习Shiro-Shiro的入门

    认证:身份认证/登录,验证用户是不是拥有相应的身份。基于shiro的认证,是通过subject的login方法完成用户认证工作的 (1)在resource目录...

    cwl_java
  • ElasticSearch(7.2.2)- es集群的基本核心概念

    cwl_java
  • 百度语音识别api使用python进行调用

    百度语音现在是比较方便的接口,具体说明请看官方文档,本文分两个部分,先是使用python实现录音,然后再使用百度语音api进行识别上传。

    十四君
  • mybatis 延迟加载(懒加载)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    多凡
  • Spring Boot 2.X(七):Spring Cache 使用

    Spring Cache 提供了 @Cacheable 、@CachePut 、@CacheEvict 、@Caching 等注解,在方法上使用。通过注解 Ca...

    朝雾轻寒
  • SpringCloud gateway全局异常处理,以及后台的服务异常response的异常包装

    gateway自己服务的全局异常处理,参考这篇https://segmentfault.com/a/1190000016854364?utm_source=ta...

    天涯泪小武
  • 资源读取配置 原

    南郭先生
  • Spring Controller单元测试

    SpringMVC controller测试较简单,从功能角度划分,可分为两种。一种是调用请求路径测试,另一种是直接调用Controller方法测试。 调用请求...

    YGingko
  • 脑洞大开之采用HTML5+SignalR2.0(.Net)实现原生Web视频

    前言  - -,我又来了,今天废话不多说,我们直接来实现Web视频聊天. 采用的技术如下: HTML5 WebRTC SignalR2.2.0 localRes...

    GuZhenYin

扫码关注云+社区

领取腾讯云代金券