知识点:

理解RBAC模型的基本概念及设计思路
了解SAAS-HRM中权限控制的需求及表结构分析
完成组织机构的基本CRUD操作
完成用户管理的基本CRUD操作
完成角色管理的基本CRUD操作

1 组织机构管理

1.1 需求分析

1.1.1 需求分析

实现企业组织结构管理,实现部门的基本CRUD操作

1.1.2 数据库表设计

CREATE TABLE `co_department` (
`id` varchar(40) NOT NULL,
`company_id` varchar(255) NOT NULL COMMENT '企业ID',
`pid` varchar(255) DEFAULT NULL COMMENT '父级部门ID',
`name` varchar(255) NOT NULL COMMENT '部门名称',
`code` varchar(255) NOT NULL COMMENT '部门编码',
`category` varchar(255) DEFAULT NULL COMMENT '部门类别',
`manager_id` varchar(255) DEFAULT NULL COMMENT '负责人ID',
`city` varchar(255) DEFAULT NULL COMMENT '城市',
`introduce` text COMMENT '介绍',
`create_time` datetime NOT NULL COMMENT '创建时间',
`manager` varchar(40) DEFAULT NULL COMMENT '部门负责人',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

1.2 微服务实现

1.2.1 实现基本CRUD操作

(1)实体类
在ihrm_common_model工程的com.zdw.ihrm.domain.company 包下创建Department实体类

package com.zdw.ihrm.domain.company;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;/*** (Department)实体类*/
@Entity
@Table(name = "co_department")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department implements Serializable {private static final long serialVersionUID = -9084332495284489553L;//ID@Idprivate String id;/*** 父级ID*/private String pid;/*** 企业ID*/private String companyId;/*** 部门名称*/private String name;/*** 部门编码,同级部门不可重复*/private String code;/*** 负责人ID*/private String managerId;/***  负责人名称*/private String manager;/*** 介绍*/private String introduce;/*** 创建时间*/private Date createTime;
}

创建查询所有的时候,返回的实体类:DeptListResult

package com.zdw.ihrm.domain.company.response;import com.zdw.ihrm.domain.company.Company;
import com.zdw.ihrm.domain.company.Department;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.util.List;/*** Create By zdw on 2019/8/11*/
@Getter
@Setter
@NoArgsConstructor
public class DeptListResult {private String companyId;private String companyName;private String companyManage;//公司联系人private List<Department> depts;public DeptListResult(Company company, List depts) {this.companyId = company.getId();this.companyName = company.getName();this.companyManage = company.getLegalRepresentative();//公司联系人this.depts = depts;}
}

(2)持久化层dao

在ihrm_company工程的包com.zdw.ihrm.company.dao下面创建:DepartmentDao

package com.zdw.ihrm.company.dao;import com.zdw.ihrm.domain.company.Department;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;/*** Create By zdw on 2019/8/11*/
public interface DepartmentDao extends JpaRepository<Department,String>,JpaSpecificationExecutor<Department> {
}

(3)业务层

在ihrm_company工程的包com.zdw.ihrm.company.service下面创建:DepartmentService

package com.zdw.ihrm.company.service;import com.ihrm.common.utils.IdWorker;
import com.zdw.ihrm.company.dao.DepartmentDao;
import com.zdw.ihrm.domain.company.Department;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.Date;
import java.util.List;/*** Create By zdw on 2019/8/11*/
@Service
public class DepartmentService {@Autowiredprivate DepartmentDao departmentDao;@Autowiredprivate IdWorker idWorker;/*** 添加部门*/public void save(Department department) {//填充其他参数department.setId(idWorker.nextId() + "");department.setCreateTime(new Date());departmentDao.save(department);}/*** 更新部门信息*/public void update(Department department) {Department sourceDepartment = departmentDao.findById(department.getId()).get();sourceDepartment.setName(department.getName());sourceDepartment.setPid(department.getPid());sourceDepartment.setManagerId(department.getManagerId());sourceDepartment.setIntroduce(department.getIntroduce());sourceDepartment.setManager(department.getManager());departmentDao.save(sourceDepartment);}/*** 根据ID获取部门信息** @param id 部门ID* @return 部门信息*/public Department findById(String id) {Optional<Company> optional = companyDao.findById(id);if(optional.isPresent()){return optional.get();}else{return null;}}/*** 删除部门** @param id 部门ID*/public void delete(String id) {departmentDao.deleteById(id);}/*** 获取部门列表*/public List<Department> findAll(String companyId) {/*** 用户构造查询条件*      1.只查询companyId*      2.很多的地方都需要根据companyId查询*      3.很多的对象中都具有companyId**/Specification<Department> spec = new Specification<Department>() {/*** 用户构造查询条件*      root   :包含了所有的对象数据*      cq     :一般不用*      cb     :构造查询条件*/public Predicate toPredicate(Root<Department> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {//根据企业id查询return cb.equal(root.get("companyId").as(String.class),companyId);}};return departmentDao.findAll(spec);}
}

(4)控制层

在ihrm_company工程的包com.zdw.ihrm.company.controller下面创建:DepartmentController

package com.zdw.ihrm.company.controller;import com.ihrm.common.entity.Result;
import com.ihrm.common.entity.ResultCode;
import com.zdw.ihrm.company.service.CompanyService;
import com.zdw.ihrm.company.service.DepartmentService;
import com.zdw.ihrm.domain.company.Company;
import com.zdw.ihrm.domain.company.Department;
import com.zdw.ihrm.domain.company.response.DeptListResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** Create By zdw on 2019/8/11*/
@CrossOrigin
@RestController
@RequestMapping("/company")
public class DepartmentController {@Autowiredprivate DepartmentService departmentService;@Autowiredprivate CompanyService companyService;/*** 添加部门*/@RequestMapping(value = "/departments", method = RequestMethod.POST)public Result add(@RequestBody Department department) throws Exception {department.setCompanyId("1");//先写死departmentService.save(department);return Result.SUCCESS();}/*** 修改部门信息*/@RequestMapping(value = "/departments/{id}", method = RequestMethod.PUT)public Result update(@PathVariable(name = "id") String id, @RequestBody Departmentdepartment) throws Exception {department.setCompanyId("1");//先写死department.setId(id);departmentService.update(department);return Result.SUCCESS();}/*** 删除部门*/@RequestMapping(value = "/departments/{id}", method = RequestMethod.DELETE)public Result delete(@PathVariable(name = "id") String id) throws Exception {departmentService.delete(id);return Result.SUCCESS();}/*** 根据id查询*/@RequestMapping(value = "/departments/{id}", method = RequestMethod.GET)public Result findById(@PathVariable(name = "id") String id) throws Exception {Department department = departmentService.findById(id);return new Result(ResultCode.SUCCESS,department);}/*** 组织架构列表*/@RequestMapping(value = "/departments", method = RequestMethod.GET)public Result findAll() throws Exception {Company company = companyService.findById("1");List<Department> list = departmentService.findAll("1");return new Result(ResultCode.SUCCESS,new DeptListResult(company,list));}
}

1.2.2 postman测试

1.2.3 抽取公共代码

(1)在模块ihrm_common的pom.xml引入下面的坐标:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency></dependencies>

(2) 公共controller

因为我们很多地方可能都要用到企业id和企业名称,后面甚至还会用到Resquest和Response对象,所以把这部分代码抽取出来,其他的类只要集成该基本的controller,自然就能获取到这些数据。
在ihrm_common模块下的com.ihrm.common.controller 包下添加公共BaseController

package com.ihrm.common.controller;import org.springframework.web.bind.annotation.ModelAttribute;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** Create By zdw on 2019/8/11*/
public class BaseController {protected HttpServletRequest request;protected HttpServletResponse response;@ModelAttribute//这个注解的作用:在实例化字类对象的时候,会先执行该方法public void setReqAndResp(HttpServletRequest request, HttpServletResponse response){this.request = request;this.response = response;}//企业id,(暂时使用1,以后会动态获取)public String parseCompanyId() {return "1";}public String parseCompanyName() {return "江苏教育股份有限公司";}
}

(3) 公共service

因为很多地方都需要根据企业id去查询企业信息,所以我们也可以抽取出来。
ihrm_common模块下的com.ihrm.common.service 包下添加公共BaseService

package com.ihrm.common.service;import org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;public class BaseService<T> {protected Specification<T> getSpec(String companyId) {Specification<T> spect = new Specification() {@Overridepublic Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder cb) {//根据企业id查询return cb.equal(root.get("companyId").as(String.class),companyId);}};return spect;}
}

1.2.4 修改之前的代码

修改DepartmentService,让其集成BaseService,修改findAll方法:

public class DepartmentService extends BaseService<Department> {/*** 获取部门列表*/public List<Department> findAll(String companyId) {/*** 用户构造查询条件*      1.只查询companyId*      2.很多的地方都需要根据companyId查询*      3.很多的对象中都具有companyId**/
//        Specification<Department> spec = new Specification<Department>() {
//            /**
//             * 用户构造查询条件
//             *      root   :包含了所有的对象数据
//             *      cq     :一般不用
//             *      cb     :构造查询条件
//             */
//            public Predicate toPredicate(Root<Department> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
//                //根据企业id查询
//                return cb.equal(root.get("companyId").as(String.class),companyId);
//            }
//        };Specification<Department> spec = getSpec(companyId);return departmentDao.findAll(spec);}
}
修改DepartmentController,让其集成BaseController,修改之后如下:
package com.zdw.ihrm.company.controller;import com.ihrm.common.controller.BaseController;
import com.ihrm.common.entity.Result;
import com.ihrm.common.entity.ResultCode;
import com.zdw.ihrm.company.service.CompanyService;
import com.zdw.ihrm.company.service.DepartmentService;
import com.zdw.ihrm.domain.company.Company;
import com.zdw.ihrm.domain.company.Department;
import com.zdw.ihrm.domain.company.response.DeptListResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** Create By zdw on 2019/8/11*/
@CrossOrigin
@RestController
@RequestMapping("/company")
public class DepartmentController extends BaseController {@Autowiredprivate DepartmentService departmentService;@Autowiredprivate CompanyService companyService;/*** 添加部门*/@RequestMapping(value = "/departments", method = RequestMethod.POST)public Result add(@RequestBody Department department) throws Exception {//department.setCompanyId("1");//先写死department.setCompanyId(parseCompanyId());//通过父类获取企业的iddepartmentService.save(department);return Result.SUCCESS();}/*** 修改部门信息*/@RequestMapping(value = "/departments/{id}", method = RequestMethod.PUT)public Result update(@PathVariable(name = "id") String id, @RequestBody Departmentdepartment) throws Exception {//department.setCompanyId("1");//先写死department.setCompanyId(parseCompanyId());//通过父类获取企业的iddepartment.setId(id);departmentService.update(department);return Result.SUCCESS();}/*** 删除部门*/@RequestMapping(value = "/departments/{id}", method = RequestMethod.DELETE)public Result delete(@PathVariable(name = "id") String id) throws Exception {departmentService.delete(id);return Result.SUCCESS();}/*** 根据id查询*/@RequestMapping(value = "/departments/{id}", method = RequestMethod.GET)public Result findById(@PathVariable(name = "id") String id) throws Exception {Department department = departmentService.findById(id);return new Result(ResultCode.SUCCESS,department);}/*** 组织架构列表*/@RequestMapping(value = "/departments", method = RequestMethod.GET)public Result findAll() throws Exception {String companyId = parseCompanyId();//通过父类获取企业的idCompany company = companyService.findById(companyId);List<Department> list = departmentService.findAll(companyId);return new Result(ResultCode.SUCCESS,new DeptListResult(company,list));}
}

1.3 组织机构前端实现

1.3.1 创建组织机构模块

在前端代码的目录(我的目录是:D:\IDEA\IDEAWorkspace\SaaS-HRM\UI_code\project-saas-hrm-vue-master\src\)下,创建组织机构模块:module-departments,在它的下面创建相关的子目录,具体结构如下:

其中的components目录是空的,pages目录放置的是我们的vue视图,router目录下面是路由规则文件index.js,store下面的app.js也是空的,index.js是跟demo目录里面的差不多的:

router目录下的index.js文件内容如下:

import Layout from '@/module-dashboard/pages/layout'
const _import = require('@/router/import_' + process.env.NODE_ENV)export default [{root: true,path: '/departments',component: Layout,redirect: 'noredirect',name: 'departments',meta: {title: '公司组织架构管理',icon: 'architecture'},children: [{path: 'index',component: _import('departments/pages/index'),name: 'organizations-index',meta: {title: '公司组织架构', icon: 'architecture', noCache: true}}]}
]

1.3.2 注册刚才的模块到项目中

在src/main.js中,注册刚才的模块:

import departments from '@/module-departments/' //刚新添加的 企业组织架构管理Vue.use(departments, store)  //注册  刚新添加的 企业组织架构管理

1.3.3 配置请求后台的API

在 /src/api/base/ 创建departments.js作为组织机构管理的API公共接口方法

import {createAPI, createFormAPI} from '@/utils/request'  //导入相关工具类,框架自己提供的//第一个参数/company是请求路径(路径可以是完全路径,也可以是部分路径,因为我们在config/dev.env.js下面有前缀配置),
//  BASE_API: '"http://localhost:9001/"'     第二参数是请求方式,第三个参数请求的参数数据
export const list = data => createAPI('/company/departments', 'get', data) //查询企业对应的所有组织机构export const save = data => createAPI('/company/departments', 'post', data) //保存export const update = data => createAPI('/company/departments/'+data.id, 'put', data) //修改export const deleteById = data => createAPI('/company/departments/'+data.id, 'delete', data) //删除export const findById = data => createAPI('/company/departments/'+data.id, 'get', data) //根据id查询export const saveOrUpdate = data => {return data.id?update(data):save(data)}  //新增或删除
// data代表请求的对象,${data.id}表示从请求的对象中取出id属性

1.3.4 完善index.vue视图

在index.vue视图中,构造企业的部门组织机构树结构,同时添加子部门对话框,实现子部门的增删改查操作,index.vue的完整代码如下:

<template><div class="dashboard-container"><div class="app-container"><el-card shadow="never"><div class='organization-index'><div class='organization-index-top'><div class='main-top-title'><el-tabs v-model="activeName"><el-tab-pane label="组织结构" name="first"></el-tab-pane><div class="el-tabs-report"><a class="el-button el-button--primary el-button--mini" title="导出" >导入</a><a class="el-button el-button--primary el-button--mini" title="导出" >导出</a></div></el-tabs></div></div><div style="overflow: scroll;white-space:nowrap"  class="treBox"><div class="treeCon clearfix"><span><i class="fa fa-university" aria-hidden="true"></i><span ><strong>{{departData.companyName}}</strong></span></span><div class="fr"><span class="treeRinfo"><div class="treeRinfo"><span>{{departData.companyManage}}</span><span>在职  <em class="colGreen" title="在职人数">---</em>&nbsp;&nbsp;(<em class="colGreen" title="正式员工">---</em>&nbsp;/&nbsp;<em class="colRed" title="非正式员工">---</em>)</span></div><div class="treeRinfo"><el-dropdown class="item"><span class="el-dropdown-link">操作<i class="el-icon-arrow-down el-icon--right"></i></span><el-dropdown-menu slot="dropdown"><el-dropdown-item><el-button type="text" @click="handlAdd('')">添加子部门</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handleList()">查看待分配员工</el-button></el-dropdown-item></el-dropdown-menu></el-dropdown></div></span>  </div></div><!-- 构造树形列表叶子 <i class="fa fa-male"></i>非叶子 展开 <i class="fa fa-minus-square-o">闭合 <i class="fa fa-plus-square-o"><div class="generalClass" slot-scope="{node,data}" style="width:99%">--><el-tree :props="{label:'name'}" :data="depts" node-key="id" default-expand-all><!--node : 是否展开,是否叶子节点data:部门对象   id,name--><div class="generalClass" slot-scope="{node,data}" style="width:99%"><span><i v-if="node.isLeaf" class="fa fa-male"></i><i v-else :class="node.expanded?'fa fa-minus-square-o':'fa fa-plus-square-o'"></i><span>{{ node.label }}</span></span><div class="fr"><span class="treeRinfo"><div class="treeRinfo"><span>{{departData.companyManage}}</span><span>在职  <em class="colGreen" title="在职人数">---</em>&nbsp;&nbsp;(<em class="colGreen" title="正式员工">---</em>&nbsp;/&nbsp;<em class="colRed" title="非正式员工">---</em>)</span></div><div class="treeRinfo"><el-dropdown class="item"><span class="el-dropdown-link">操作<i class="el-icon-arrow-down el-icon--right"></i></span><el-dropdown-menu slot="dropdown"><el-dropdown-item><el-button type="text" @click="handlAdd(data.id)">添加子部门</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handUpdate(data.id)">查看或修改部门</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handleList()">查看待分配员工</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handleDelete(data.id)">删除部门</el-button></el-dropdown-item></el-dropdown-menu></el-dropdown></div></span>  </div></div></el-tree></div></div>    </el-card></div><!--添加部门对话框--><el-dialog title="编辑部门" :visible.sync="dialogFormVisible"><!-- model : 数据模型 --><el-form :model="dept" label-width="120px"><el-form-item label="部门名称"><el-input v-model="dept.name" autocomplete="off"></el-input></el-form-item><el-form-item label="部门编码"><el-input v-model="dept.code" autocomplete="off"></el-input></el-form-item><el-form-item label="部门负责人"><el-input v-model="dept.manager" autocomplete="off"></el-input></el-form-item><el-form-item label="部门介绍"><el-input v-model="dept.introduce" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="saveDept">确 定</el-button></div></el-dialog>
</div>
</template><!-- 引入组件 -->
<script>
import {list,saveOrUpdate,findById,deleteById} from '@/api/base/dept'
import commonApi from '@/utils/common'
export default {data() {return {activeName: 'first', departData:{},   //部门对应的公司信息depts:[],   //部门列表dialogFormVisible:false,//默认不显示添加部门对话框parentId:'',//定义要添加的新部门的父iddept:{}  //定义添加的部门对象}},methods: {//查询部门树型结构getDeptList(){//调用API方法查询部门列表list().then(res => {console.log(res)this.departData = res.data.data//将普通的数据转化为父子结构this.depts = commonApi.transformTozTreeFormat(res.data.data.depts);})},//点击  添加子部门handlAdd(parentId){console.log(parentId)this.dialogFormVisible=true;//点击添加子部门,打开对话框this.parentId = parentId;},//添加子部门对话框的 确定  按钮saveDept(){this.dept.pid = this.parentId;//给新增部门赋 父id的值saveOrUpdate(this.dept).then(res => {this.$message({message: res.data.message,type: res.data.success?'success':'error'  //根据返回值来判断提示的是成功消息还是失败消息});setTimeout(function(){if(res.data.success){//如果成功,就重新加载页面location.reload();}},500)//延迟500毫秒,让客户可以看到提示消息});},//点击  查看部门  按钮handUpdate(id){//调用 根据id查询部门信息的 API 方法,{id:id} 这种写法是因为我们传的都是对象,所以要按对象封装findById({id:id}).then(res => {this.dialogFormVisible=true;//显示部门对话框this.dept = res.data.data;})},//点击 删除部门  按钮handleDelete(id){//提示客户是否确定要删除this.$confirm('是否删除此条记录?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {//then是点击确定要完成的操作//调用根据id删除部门的 api 方法deleteById({id:id}).then(res=> {this.$message({message: res.data.message,type: res.data.success?'success':'error'});setTimeout(function(){if(res.data.success) {//删除成功,重新加载页面location.reload();}},600)})})}},created: function() {//钩子方法中调用查询列表的方法this.getDeptList();},
}
</script>
<style rel="stylesheet/scss" lang="scss">
.el-dropdown {color: #000000
}
.el-tree-node__content>.el-tree-node__expand-icon {padding:0px;
}
.el-tree-node__expand-icon {color:#ffffff
}
.generalClassNode {padding-left: 20px;
}
.el-tree-node__content{font-size: 16px;line-height: 36px;height:36px;
}
.custom-tree-node{padding-left: 20px;
}
.objectTree {overflow: auto;z-index: 100;width: 300px;border: 1px solid #dcdfe6;margin-top: 5px;left: 70px;
}
.el-tabs__content {overflow: initial;
}
.boxpad {margin-left: -40px;
}
</style>
<style  rel="stylesheet/scss" lang="scss" scoped>
.el-tree-node__expand-icon{}
.el-icon-caret-right{}
.el-tree-node__content{font-size: 14px;line-height: 36px;
}
.generalClass {font-size: 14px;line-height: 36px;color:#000000
}
.all {position: relative;min-height: 100%;padding-bottom: 200px;
}
.organization-main:after,
.organization-index-top:after {display: block;clear: both;content: '';visibility: hidden;height: 0;
}
.organization-main {font-size: 14px;font-size: 14px;
}.organization-index {padding-bottom: 20px;margin-left: 20px;
}
.main-top-title {padding-left: 20px;padding-top: 20px;text-align: left;
}::-webkit-scrollbar-thumb {background-color: #018ee8;height: 50px;outline-offset: -2px;outline: 8px solid #fff;-webkit-border-radius: 4px;
}
::-webkit-scrollbar-track-piece {background-color: #fff;-webkit-border-radius: 0;
}
::-webkit-scrollbar {width: 8px;height: 8px;
}
::-webkit-scrollbar-thumb:hover {background-color: #fb4446;height: 50px;-webkit-border-radius: 4px;
}
.modal-total {width: 100%;height: 100%;position: fixed;top: 0;left: 0;background: #000;z-index: 90;opacity: 0.2;
}
.modal {width: 400px;height: 300px;background-color: #ffffff;z-index: 999;position: absolute;left: 45%;top: 20%;text-align: center;
}
.treBox {padding: 30px 120px 0;
}
.organization-index-top {position: relative;.el-tabs-report {position: absolute;top: -50px;right: 15px;}
}
.treeCon {border-bottom: 1px solid #cfcfcf;padding: 10px 0;margin-bottom: 10px;.el-dropdown {color: #333;}
}
.treeRinfo {display: inline-block;
}
.treeRinfo span {padding-left: 30px;
}
</style>

1.3.5 抽取组件

组件(Component)是Vue.js 最强大的功能。可以通过将不同的业务拆分为不同的组件进行开发,让代码更加优雅提供可读性。当然也可以封装可重用的代码,通过传入对象的不同,实现组件的复用。

(1)抽取新增/修改页面到 /module-departments/components/add.vue 中

<template><!--添加部门对话框--><el-dialog title="编辑部门" :visible.sync="dialogFormVisible"><!-- model : 数据模型 --><el-form :model="dept" label-width="120px"><el-form-item label="部门名称"><el-input v-model="dept.name" autocomplete="off"></el-input></el-form-item><el-form-item label="部门编码"><el-input v-model="dept.code" autocomplete="off"></el-input></el-form-item><el-form-item label="部门负责人"><el-input v-model="dept.manager" autocomplete="off"></el-input></el-form-item><el-form-item label="部门介绍"><el-input v-model="dept.introduce" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="saveDept">确 定</el-button></div></el-dialog>
</template>
<script>
import {saveOrUpdate} from '@/api/base/dept'  //引入api方法
export default {name:'deptAdd',data(){return{dialogFormVisible:false,//默认不显示添加部门对话框parentId:'',//定义要添加的新部门的父iddept:{}  //定义添加的部门对象}},methods:{//添加子部门对话框的 确定  按钮saveDept(){this.dept.pid = this.parentId;//给新增部门赋 父id的值saveOrUpdate(this.dept).then(res => {this.$message({message: res.data.message,type: res.data.success?'success':'error'  //根据返回值来判断提示的是成功消息还是失败消息});setTimeout(function(){if(res.data.success){//如果成功,就重新加载页面location.reload();}},500)//延迟500毫秒,让客户可以看到提示消息});}}
}
</script>

(2) 在 /module-departments/page/index.vue 中引用组件

导入组件:

import commonApi from '@/utils/common'//写好的公共组件
import deptAdd from './../components/add'  //导入自定义的添加子部门的组件
export default {components:{deptAdd},//声明组件data() {return {deptAdd:'deptAdd', //指定组件名称activeName: 'first', departData:{},   //部门对应的公司信息depts:[],   //部门列表// 。。。。}}

使用组件:

在之前书写添加子部门对话框的地方,使用组件标签引入组件:

<!-- 引入组件 addDept:指定组件//v-bind:is (绑定的组件名称)//ref : 引用子组件中内容的别名--><component v-bind:is="deptAdd" ref="addDept"></component>

改造新增修改方法:

因为现在是要通过父页面来操作组件中的变量,所以需要修改新增和修改子部门的方法:

//点击  添加子部门handlAdd(parentId){console.log(parentId)//this.dialogFormVisible=true;//点击添加子部门,打开对话框//this.parentId = parentId;//现在是父页面要控制子组件中的变量,通过this.$refs.addDept来操作,(父页面调用子组件中的内容)this.$refs.addDept.parentId = parentId;this.$refs.addDept.dialogFormVisible = true},//点击  查看部门  按钮handUpdate(id){//调用 根据id查询部门信息的 API 方法,{id:id} 这种写法是因为我们传的都是对象,所以要按对象封装findById({id:id}).then(res => {//this.dialogFormVisible=true;//显示部门对话框//this.dept = res.data.data;//现在是父页面要控制子组件中的变量,通过this.$refs.addDept来操作this.$refs.addDept.dept = res.data.data;this.$refs.addDept.dialogFormVisible = true})}

(3)抽取组件后,index.vue的完整代码

<template><div class="dashboard-container"><div class="app-container"><el-card shadow="never"><div class='organization-index'><div class='organization-index-top'><div class='main-top-title'><el-tabs v-model="activeName"><el-tab-pane label="组织结构" name="first"></el-tab-pane><div class="el-tabs-report"><a class="el-button el-button--primary el-button--mini" title="导出" >导入</a><a class="el-button el-button--primary el-button--mini" title="导出" >导出</a></div></el-tabs></div></div><div style="overflow: scroll;white-space:nowrap"  class="treBox"><div class="treeCon clearfix"><span><i class="fa fa-university" aria-hidden="true"></i><span ><strong>{{departData.companyName}}</strong></span></span><div class="fr"><span class="treeRinfo"><div class="treeRinfo"><span>{{departData.companyManage}}</span><span>在职  <em class="colGreen" title="在职人数">---</em>&nbsp;&nbsp;(<em class="colGreen" title="正式员工">---</em>&nbsp;/&nbsp;<em class="colRed" title="非正式员工">---</em>)</span></div><div class="treeRinfo"><el-dropdown class="item"><span class="el-dropdown-link">操作<i class="el-icon-arrow-down el-icon--right"></i></span><el-dropdown-menu slot="dropdown"><el-dropdown-item><el-button type="text" @click="handlAdd('')">添加子部门</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handleList()">查看待分配员工</el-button></el-dropdown-item></el-dropdown-menu></el-dropdown></div></span>  </div></div><!-- 构造树形列表叶子 <i class="fa fa-male"></i>非叶子 展开 <i class="fa fa-minus-square-o">闭合 <i class="fa fa-plus-square-o"><div class="generalClass" slot-scope="{node,data}" style="width:99%">--><el-tree :props="{label:'name'}" :data="depts" node-key="id" default-expand-all><!--node : 是否展开,是否叶子节点data:部门对象   id,name--><div class="generalClass" slot-scope="{node,data}" style="width:99%"><span><i v-if="node.isLeaf" class="fa fa-male"></i><i v-else :class="node.expanded?'fa fa-minus-square-o':'fa fa-plus-square-o'"></i><span>{{ node.label }}</span></span><div class="fr"><span class="treeRinfo"><div class="treeRinfo"><span>{{departData.companyManage}}</span><span>在职  <em class="colGreen" title="在职人数">---</em>&nbsp;&nbsp;(<em class="colGreen" title="正式员工">---</em>&nbsp;/&nbsp;<em class="colRed" title="非正式员工">---</em>)</span></div><div class="treeRinfo"><el-dropdown class="item"><span class="el-dropdown-link">操作<i class="el-icon-arrow-down el-icon--right"></i></span><el-dropdown-menu slot="dropdown"><el-dropdown-item><el-button type="text" @click="handlAdd(data.id)">添加子部门</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handUpdate(data.id)">查看或修改部门</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handleList()">查看待分配员工</el-button></el-dropdown-item><el-dropdown-item><el-button type="text" @click="handleDelete(data.id)">删除部门</el-button></el-dropdown-item></el-dropdown-menu></el-dropdown></div></span>  </div></div></el-tree></div></div>    </el-card></div><!--添加部门对话框,抽取成组件到components下面的add.vue--><!-- <el-dialog title="编辑部门" :visible.sync="dialogFormVisible"> --><!-- model : 数据模型 --><!--<el-form :model="dept" label-width="120px"><el-form-item label="部门名称"><el-input v-model="dept.name" autocomplete="off"></el-input></el-form-item><el-form-item label="部门编码"><el-input v-model="dept.code" autocomplete="off"></el-input></el-form-item><el-form-item label="部门负责人"><el-input v-model="dept.manager" autocomplete="off"></el-input></el-form-item><el-form-item label="部门介绍"><el-input v-model="dept.introduce" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="saveDept">确 定</el-button></div></el-dialog> --><!-- 引入组件 addDept:指定组件//v-bind:is (绑定的组件名称)//ref : 引用子组件中内容的别名--><component v-bind:is="deptAdd" ref="addDept"></component>
</div>
</template><script>
import {list,saveOrUpdate,findById,deleteById} from '@/api/base/dept'
import commonApi from '@/utils/common'//写好的公共组件
import deptAdd from './../components/add'  //导入自定义的添加子部门的组件
export default {components:{deptAdd},//声明组件data() {return {deptAdd:'deptAdd', //指定组件名称activeName: 'first', departData:{},   //部门对应的公司信息depts:[],   //部门列表//这三个跟添加子部门相关的三个参数提取到组件中去了,这里可以注释掉//dialogFormVisible:false,//默认不显示添加部门对话框//parentId:'',//定义要添加的新部门的父id//dept:{}  //定义添加的部门对象}},methods: {//查询部门树型结构getDeptList(){//调用API方法查询部门列表list().then(res => {console.log(res)this.departData = res.data.data//将普通的数据转化为父子结构this.depts = commonApi.transformTozTreeFormat(res.data.data.depts);})},//点击  添加子部门handlAdd(parentId){console.log(parentId)//this.dialogFormVisible=true;//点击添加子部门,打开对话框//this.parentId = parentId;//现在是父页面要控制子组件中的变量,通过this.$refs.addDept来操作,(父页面调用子组件中的内容)this.$refs.addDept.parentId = parentId;this.$refs.addDept.dialogFormVisible = true},//添加子部门对话框的 确定  按钮,这部门代码也抽取到了组件中/*saveDept(){this.dept.pid = this.parentId;//给新增部门赋 父id的值saveOrUpdate(this.dept).then(res => {this.$message({message: res.data.message,type: res.data.success?'success':'error'  //根据返回值来判断提示的是成功消息还是失败消息});setTimeout(function(){if(res.data.success){//如果成功,就重新加载页面location.reload();}},500)//延迟500毫秒,让客户可以看到提示消息});},*///点击  查看部门  按钮handUpdate(id){//调用 根据id查询部门信息的 API 方法,{id:id} 这种写法是因为我们传的都是对象,所以要按对象封装findById({id:id}).then(res => {//this.dialogFormVisible=true;//显示部门对话框//this.dept = res.data.data;//现在是父页面要控制子组件中的变量,通过this.$refs.addDept来操作this.$refs.addDept.dept = res.data.data;this.$refs.addDept.dialogFormVisible = true})},//点击 删除部门  按钮handleDelete(id){//提示客户是否确定要删除this.$confirm('是否删除此条记录?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {//then是点击确定要完成的操作//调用根据id删除部门的 api 方法deleteById({id:id}).then(res=> {this.$message({message: res.data.message,type: res.data.success?'success':'error'});setTimeout(function(){if(res.data.success) {//删除成功,重新加载页面location.reload();}},600)})})}},created: function() {//钩子方法中调用查询列表的方法this.getDeptList();},
}
</script>
<style rel="stylesheet/scss" lang="scss">
.el-dropdown {color: #000000
}
.el-tree-node__content>.el-tree-node__expand-icon {padding:0px;
}
.el-tree-node__expand-icon {color:#ffffff
}
.generalClassNode {padding-left: 20px;
}
.el-tree-node__content{font-size: 16px;line-height: 36px;height:36px;
}
.custom-tree-node{padding-left: 20px;
}
.objectTree {overflow: auto;z-index: 100;width: 300px;border: 1px solid #dcdfe6;margin-top: 5px;left: 70px;
}
.el-tabs__content {overflow: initial;
}
.boxpad {margin-left: -40px;
}
</style>
<style  rel="stylesheet/scss" lang="scss" scoped>
.el-tree-node__expand-icon{}
.el-icon-caret-right{}
.el-tree-node__content{font-size: 14px;line-height: 36px;
}
.generalClass {font-size: 14px;line-height: 36px;color:#000000
}
.all {position: relative;min-height: 100%;padding-bottom: 200px;
}
.organization-main:after,
.organization-index-top:after {display: block;clear: both;content: '';visibility: hidden;height: 0;
}
.organization-main {font-size: 14px;font-size: 14px;
}.organization-index {padding-bottom: 20px;margin-left: 20px;
}
.main-top-title {padding-left: 20px;padding-top: 20px;text-align: left;
}::-webkit-scrollbar-thumb {background-color: #018ee8;height: 50px;outline-offset: -2px;outline: 8px solid #fff;-webkit-border-radius: 4px;
}
::-webkit-scrollbar-track-piece {background-color: #fff;-webkit-border-radius: 0;
}
::-webkit-scrollbar {width: 8px;height: 8px;
}
::-webkit-scrollbar-thumb:hover {background-color: #fb4446;height: 50px;-webkit-border-radius: 4px;
}
.modal-total {width: 100%;height: 100%;position: fixed;top: 0;left: 0;background: #000;z-index: 90;opacity: 0.2;
}
.modal {width: 400px;height: 300px;background-color: #ffffff;z-index: 999;position: absolute;left: 45%;top: 20%;text-align: center;
}
.treBox {padding: 30px 120px 0;
}
.organization-index-top {position: relative;.el-tabs-report {position: absolute;top: -50px;right: 15px;}
}
.treeCon {border-bottom: 1px solid #cfcfcf;padding: 10px 0;margin-bottom: 10px;.el-dropdown {color: #333;}
}
.treeRinfo {display: inline-block;
}
.treeRinfo span {padding-left: 30px;
}
</style>

SaaS-HRM(3)企业部门管理前后台相关推荐

  1. Saas经销商业务管理系统/部门管理/职位管理/员工管理/仓库管理/商品管理/客户管理/价格管理/入库管理/采购管理/销售管理/行为管理/axure高保真经销商业务后台管理系统原型/ssas后台管理

    作品介绍:Saas经销商业务管理系统/部门管理/职位管理/员工管理/仓库管理/商品管理/客户管理/价格管理/入库管理/采购管理/销售管理/行为管理/axure高保真经销商业务后台管理系统原型/ssas ...

  2. 企业寄件分部门管理教程

    在某某大企业当行政的闺蜜又来抱怨工作量负荷了,我不解,行政不就管理管理公司一些简单的日常事务?怎么你就忙得跟陀螺似的??闺蜜一脸苦哈哈:在你们看来确实是沙子一般的琐事,当沙子多了堆积在一起的时候,就变 ...

  3. SaaS市场增长迅速 企业借CRM消灭管理黑洞

    本文讲的是SaaS市场增长迅速 企业借CRM消灭管理黑洞,[IT168 资讯]相对于ERP,CRM的市场需求更加广泛.只要存在和上下游的供需关系,就会有CRM的需求.日前,由计世资讯发布的<20 ...

  4. 计算机毕业设计ssm企业部门报销管理g9d62系统+程序+源码+lw+远程部署

    计算机毕业设计ssm企业部门报销管理g9d62系统+程序+源码+lw+远程部署 计算机毕业设计ssm企业部门报销管理g9d62系统+程序+源码+lw+远程部署 本源码技术栈: 项目架构:B/S架构 开 ...

  5. ssm毕设项目企业部门报销管理g9d62(java+VUE+Mybatis+Maven+Mysql+sprnig)

    ssm毕设项目企业部门报销管理g9d62(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HB ...

  6. 企业信息化管理:SaaS软件or传统软件如何选择?

    近几年,针对SaaS软件和传统软件之间的竞争,业内曾普遍持观望乃至唱衰的态度.尤其随着互联网在人们生活.工作.社会发展等各个方面的深度融入,一些传统软件企业发展减缓,逐渐影响波及到企业云软件领域.甚至 ...

  7. 汽配汽修行业SaaS供应商管理系统:精细化企业库存管理,提高供应链效率

    汽修汽配产业作为汽车工业的基础,是支撑汽车工业持续健康发展的必要因素.特别是当前汽车行业正在轰轰烈烈.如火如荼开展的自主开发与创新,更需要一个强大的零部件体系作支撑. 汽车汽配行业供应商管理是指在保证 ...

  8. 在企业里管理机器学习:来自银行和医疗行业的经验

    编者注:文中超链接如果不能访问可以点击"阅读原文"访问本文原页面:读者可查看"2020年3月15日至18日举办的Strata圣何塞数据大会"来获取更多相关内容. ...

  9. 打造国内专业企业研发管理解决方案,ONES完成华创资本领投A+轮600万美元融资

    近日,企业研发管理解决方案公司ONES宣布已经完成A+轮600万美元融资.本轮融资为华创资本领投,晨兴创投跟投.据悉,本轮融资将加速ONES产品研发和客户服务升级. ONES(深圳复临科技有限公司)成 ...

最新文章

  1. 第十二课.sklearn决策树实验
  2. POJ - 1741 Tree(点分治模板题)
  3. 独占一行 html_HTML基础-语义化标签
  4. 显卡测试软件毛毛虫,超龙超龙,与众不同,顶流配备,散热一流,3070Ti超龙旗舰版评测...
  5. windows内核情景分析---进程线程1
  6. 前端学习(810):webapi和js的关联性
  7. 解析应用结构,优化网络效能
  8. spring随笔(二) AOP
  9. 中的枚举属性函数_Java 枚举:有效应用
  10. 词性标注-隐马尔可夫模型
  11. LVDS 屏 format
  12. ROI是什么?电商ROI计算公式及理论及详解
  13. 通信专业能报国考的计算机类吗,通信工程专业可以报考计算机科学技术类公务员职位么...
  14. 【历史上的今天】4 月 28 日:人工智能理论之父出生;大众点评上线;苹果开设 iTunes 音乐商店
  15. 测试无线网网速软件,技术员教你解决怎么测试无线网络网速
  16. icloud有linux客户端吗,icloud drive:Windows 版 iCloud 客户端在哪下载
  17. C#List子类转List父类或者Obj对象转List
  18. imresize 函数用法
  19. c8815语言,华为C8815强刷教程(可救砖用)
  20. 升级android安全补丁,谷歌发布 2019 年 12 月的 Android 安全补丁

热门文章

  1. 张瑞申教授SSRN论文数据公开 | 公司层面气候变化暴露指数
  2. Qt使用QAudioInput、QAudioOutput实现局域网的音频通话
  3. 力扣 560. 和为 K 的子数组
  4. SQLSERVER 查询本周一至周日数据
  5. 根据当前时间获取当前周的周一到周日的日期
  6. leetcode | 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
  7. 合成孔径雷达地面运动目标检测技术研究——基于概率图(Matlab代码实现)
  8. 基于51单片机的蓄电池容量检测系统的设计(毕业设计资料)
  9. 看纷享销客如何布局连接型CRM
  10. python模型转PMML