做网站界面用的软件,国际新闻最新,什么是外网服务器,高端品牌女装iHRM人力资源 - 组织架构 文章目录 iHRM人力资源 - 组织架构一、展示数据-树形组件1.1 组件说明1.2 树组件自定义结构获取作用域数据1.2.1 说明1.2.2 页面代码1.2.3 获取组织架构数据-api 1.3 效果图1.4 修改树形结构bug 二、添加子部门2.1 表单弹层2.1.1 下拉菜单点击事件2.1.…iHRM人力资源 - 组织架构 文章目录 iHRM人力资源 - 组织架构一、展示数据-树形组件1.1 组件说明1.2 树组件自定义结构获取作用域数据1.2.1 说明1.2.2 页面代码1.2.3 获取组织架构数据-api 1.3 效果图1.4 修改树形结构bug 二、添加子部门2.1 表单弹层2.1.1 下拉菜单点击事件2.1.2 封装弹层组件 2.2 表单结构及校验2.3 部门负责人数据2.4 记录部门2.5 确认功能2.6 取消功能 一、展示数据-树形组件
树形组件用层级结构展示信息可展开或者折叠 使用element-ui组件 https://element.eleme.cn/#/zh-CN/component/tree 1.1 组件说明 template!--为什么这里写container和app-container 因为我们最初的时候导入过样式--div classcontainer!--在此容器上加了边距上下30px左右140px--div classapp-container组织架构!--展示树形结构--!--此处正好是标签的属性名叫props和vue框架中组件传递数据不是一个--!--default-expand-all属性表示默认将所有的树形结构打开完整写法是 :default-expand-all“true” (一定带冒号)--el-tree :datadepts :propsdefaultProps default-expand-all/el-tree/div/div
/templatescript
export default {name: Department,data() {return {// 数组属性depts: [{ name: 传智教育, children: [{ name: 总裁办 }, { name: 行政部 }, { name: 人事部 }] }],defaultProps: {// 当前层级数据在这里找此层级的显示数据label: name,// 子层级其实就是层级结构在这里找子节点children: children}}}
}
/scriptstyle scoped
.app-container {padding: 30px 140px;
}
/style
效果图 1.2 树组件自定义结构获取作用域数据
1.2.1 说明
我们其实要实现下面的这种树形结构在右侧还有操作地方但是我们在1.1中只展示了名称没有显示右侧
因为element-ui中树形结构默认只显示节点的名称如果我们想树形结构左边有内容右边也有内容的话就需要对树形结构进行自定义
我们这个地方需要再使用一个element-ui的行和列组件 如下图所示我们向实现这种结构 行 el-row 列 el-col 其实span默认是24份我们分配每列的空间的话分配span值即可 1.2.2 页面代码
我们代码要实现下面这种形式 template!--为什么这里写container和app-container 因为我们最初的时候导入过样式--div classcontainer!--在此容器上加了边距上下30px左右140px--div classapp-container组织架构!--展示树形结构--!--此处正好是标签的属性名叫props和vue框架中组件传递数据不是一个--!--default-expand-all属性表示默认将所有的树形结构打开完整写法是 :default-expand-all“true” (一定带冒号)--el-tree :datadepts :propsdefaultProps default-expand-all!--v-slot标签只能使用在template标签上--!--这个data数据其实是el-tree给的下面的template模板会不断的去循环有多少个节点就会循环多少次把每一个数据都塞到了data里面--template v-slot{data}!--节点结构。使用el-tree组件的插槽--!--会读取这个节点结构并循环渲染到页面上--!--我们如果把type布局模式设置为flex就可以用厚民安的两个属性justifyspace-between表示两头对其,alignmiddle表示垂直居中--el-row typeflex justifyspace-between alignmiddle stylewidth: 100%;height: 40px!--一行里面有两列,第一列是组织名称第二列是管理员和操作下拉菜单--el-col{{ data.name }}/el-col!--:span4一定带着冒号因为人家想要一个数字类型--el-col :span6span classtree-manager{{ data.managerName }}/span!--下拉菜单组件--el-dropdown!--显示区域内容--span classel-dropdown-link操作i classel-icon-arrow-down el-icon--right/i/span!--下拉菜单的选项--el-dropdown-menu slotdropdownel-dropdown-item添加子部门/el-dropdown-itemel-dropdown-item编辑部门/el-dropdown-itemel-dropdown-item删除/el-dropdown-item/el-dropdown-menu/el-dropdown/el-col/el-row/template/el-tree/div/div
/templatescript
import { getDepartment } from /api/department
import { transListToTreeData } from /utilsexport default {name: Department,data() {return {// 数组属性depts: [],defaultProps: {// 当前层级数据在这里找此层级的显示数据label: name,// 子层级其实就是层级结构在这里找子节点children: children}}},// 页面初始化的时候会调用这个函数created() {// 获取部门数据这个方法是下面methods里面的不是api里面的this.getDepartment()},methods: {async getDepartment() {// 下面这个方法是import导入的api请求方法const result await getDepartment()// 但是我们获取到的数据是列表的形式没有层级结构我们要使用递归的方式完成树形结构this.depts transListToTreeData(result, 0)}}
}
/scriptstyle scoped
.app-container {padding: 30px 140px;
}.tree-manager {width: 50px;display: inline-block;
//margin: 10px; margin-right: 50px;
}
/style
1.2.3 获取组织架构数据-api
封装获取组织架构的API
// 引入封装的axios工具
import request from /utils/request/*** 获取组织架构数据*/
export function getDepartment() {// request发送登录请求会得到一个promise结果并将其返回return request({// 请求地址url: /company/department,// 请求方式method: GET// 请求参数,但是这里没有请求参数// data: Data// 在ES6中上面data: Data可以简写为 data})
}初始化后调用 // 页面初始化的时候会调用这个函数created() {// 获取部门数据这个方法是下面methods里面的不是api里面的this.getDepartment()},methods: {async getDepartment() {// 下面这个方法是import导入的api请求方法const result await getDepartment()// 但是我们获取到的数据是列表的形式没有层级结构我们要使用递归的方式完成树形结构this.depts transListToTreeData(result, 0)}}赋值数据
这里我们要使用递归的方式将后端传输过来的列表数据变成树形结构
下图所示的情况 首先分析数据的关联管理 层级结构怎么通过数据体现出来的 如下图所示其实就是pid与id的关系
{success: true,code: 10000,data: [{id: 1,pid: 0,name: 传智教育,code: CZJY,managerId: 1,managerName: 管理员,introduce: 总部,createTime: 2022-10-26 09:13:37},{id: 2,pid: 1,name: 总裁办,code: ZCB,managerId: 1,managerName: 管理员,introduce: 公司战略部,createTime: 2022-10-26 09:13:37},{id: 3,pid: 1,name: 行政部,code: XZB,managerId: 4,managerName: 黑马文吉星,introduce: 行政部,createTime: 2022-10-26 09:13:39},......................],message: 获取组织架构数据成功
}封装递归函数根据关系转化层级结构 /*** 列表数据转树形数据* rootValue: 其实就是pid父id*/
export function transListToTreeData(list, rootValue) {const arr []list.forEach(item {if (item.pid rootValue) {// 找到了匹配的节点arr.push(item)// 当前节点的id和当前节点的字节点的pid相等// 下面的方法其实就是找当前节点的子节点const children transListToTreeData(list, item.id) // 找到的节点的子节点item.children children // 将子节点赋值给当前节点// 我们先push再赋值childern也没关系因为是一个对象地址是一样的}})return arr
}
1.3 效果图 1.4 修改树形结构bug
当我们点击“操作”的时候整个树形结构会关闭或者打开很不方便然后我们可以将expand-on-click-nod属性设置为false说明只有点击箭头图标的时候才会展开或者收缩节点 !--展示树形结构--
!--此处正好是标签的属性名叫props和vue框架中组件传递数据不是一个--
!--default-expand-all属性表示默认将所有的树形结构打开完整写法是 :default-expand-all“true” (一定带冒号)--
el-tree :datadepts :propsdefaultProps default-expand-all :expand-on-click-nodefalse二、添加子部门
2.1 表单弹层
我们可以将“添加”和“修改”功能公用同一个弹层也就是“添加”和“修改”的时候公用同一个组件
大体分为两步
注册添加子部门事件封装弹层组件控制弹层显示隐藏 在如下位置填写 2.1.1 下拉菜单点击事件 !--下拉菜单组件--!--command是下拉菜单的执行方法当点击下拉菜单中的某一项的时候就会执行operateDept方法--el-dropdown commandoperateDept!--显示区域内容--span classel-dropdown-link操作i classel-icon-arrow-down el-icon--right/i
/span!--下拉菜单的选项--el-dropdown-menu slotdropdownel-dropdown-item commandadd添加子部门/el-dropdown-itemel-dropdown-item commandedit编辑部门/el-dropdown-itemel-dropdown-item commanddel删除/el-dropdown-item/el-dropdown-menu/el-dropdown当点击某一个下拉框的时候就会将command的值传输到type
operateDept(type) {alert(type)
}效果为如下所示这样我们就能根据不同的按钮做出不同的功能了 2.1.2 封装弹层组件 template!--:visible用来控制显示和隐藏,由于我们是一个组件所以我们需要外部传入一个参数来控制显示还是隐藏--!--close用于监视关闭弹层点击右上角×号的时候就会执行此函数--el-dialog title新增部门 :visibleshowDialog closeclose!--放置弹层内容--/el-dialog
/templatescript
export default {// 接收外部传输过来的值props: {// 参数showDialog类型限制为Boolean默认值为falseshowDialog: { type: Boolean, default: false }},methods: {close() {// 修改父组件的值子传给父亲// this.$emit可以触发一个自定义事件父组件需要接收这个时间然后把false这个值传出去// this.$emit(false) 但是我们先不用这个方法// 这里我们使用了 sync修饰表示会接受子组件的事件也就是update:showDialog这个事件然后会把值赋值给showDialogthis.$emit(update:showDialog, false)}}
}
/script在index.vue组件中进行引用
template!--为什么这里写container和app-container 因为我们最初的时候导入过样式--div classcontainer!--在此容器上加了边距上下30px左右140px--div classapp-container组织架构!--展示树形结构--!--此处正好是标签的属性名叫props和vue框架中组件传递数据不是一个--!--default-expand-all属性表示默认将所有的树形结构打开完整写法是 :default-expand-all“true” (一定带冒号)--el-tree :datadepts :propsdefaultProps default-expand-all :expand-on-click-nodefalse!--v-slot标签只能使用在template标签上--!--这个data数据其实是el-tree给的下面的template模板会不断的去循环有多少个节点就会循环多少次把每一个数据都塞到了data里面--template v-slot{data}!--节点结构。使用el-tree组件的插槽--!--会读取这个节点结构并循环渲染到页面上--!--我们如果把type布局模式设置为flex就可以用厚民安的两个属性justifyspace-between表示两头对其,alignmiddle表示垂直居中--el-row typeflex justifyspace-between alignmiddle stylewidth: 100%;height: 40px!--一行里面有两列,第一列是组织名称第二列是管理员和操作下拉菜单--el-col{{ data.name }}/el-col!--:span4一定带着冒号因为人家想要一个数字类型--el-col :span6span classtree-manager{{ data.managerName }}/span!--下拉菜单组件--!--command是下拉菜单的执行方法当点击下拉菜单中的某一项的时候就会执行operateDept方法--el-dropdown commandoperateDept !--显示区域内容--span classel-dropdown-link操作i classel-icon-arrow-down el-icon--right/i/span!--下拉菜单的选项--el-dropdown-menu slotdropdownel-dropdown-item commandadd添加子部门/el-dropdown-itemel-dropdown-item commandedit编辑部门/el-dropdown-itemel-dropdown-item commanddel删除/el-dropdown-item/el-dropdown-menu/el-dropdown/el-col/el-row/template/el-tree/div!--放置弹层--!--:show-dialog 是我们在add-dept组件中定义的props--!--sync修饰表示会接受子组件的事件也就是update:showDialog这个事件然后会把值赋值给下面的showDialog--add-dept :show-dialog.syncshowDialog/add-dept/div
/templatescript
import { getDepartment } from /api/department
import { transListToTreeData } from /utils
// 引入封装的弹层组件
import AddDept from ./components/add-dept.vueexport default {name: Department,components: { AddDept },// 完成AddDept组件局部注册comments: { AddDept },data() {return {// 数组属性depts: [],defaultProps: {// 当前层级数据在这里找此层级的显示数据label: name,// 子层级其实就是层级结构在这里找子节点children: children},// 控制弹层的显示和隐藏showDialog: false}},// 页面初始化的时候会调用这个函数created() {// 获取部门数据这个方法是下面methods里面的不是api里面的this.getDepartment()},methods: {async getDepartment() {// 下面这个方法是import导入的api请求方法const result await getDepartment()// 但是我们获取到的数据是列表的形式没有层级结构我们要使用递归的方式完成树形结构this.depts transListToTreeData(result, 0)},operateDept(type) {if (type add) {// 添加子部门// 显示弹层组件this.showDialog true}}}
}
/scriptstyle scoped
.app-container {padding: 30px 140px;
}.tree-manager {width: 50px;display: inline-block;
//margin: 10px; margin-right: 50px;
}
/style2.2 表单结构及校验 下面是基本校验 也要完成业务校验
如
部门名称和已有部门不重复部门编码和已有编码不重复
如果不重复的话就实行添加功能
template!--:visible用来控制显示和隐藏,由于我们是一个组件所以我们需要外部传入一个参数来控制显示还是隐藏--!--close用于监视关闭弹层点击右上角×号的时候就会执行此函数--el-dialog title新增部门 :visibleshowDialog closeclose!--放置弹层内容--!--label-width设置文本的宽度这样文本框左边的字就能对其了--el-form :modelformDara :rulesrules refaddDept label-width120pxel-form-item propname label部门名称!--place-holder是文本提示信息--el-input v-modelformDara.name placeholder2-10个字符 stylewidth: 80% sizemini/el-input/el-form-itemel-form-item propcode label部门编码el-input v-modelformDara.code placeholder2-10个字符 stylewidth: 80% sizemini/el-input/el-form-itemel-form-item propmanagerId label部门负责人!--这个地方是一个下拉菜单--el-select v-modelformDara.managerId placeholder请选择负责人 stylewidth: 80% sizemini!--下拉选项循环managerList--!--label其实是下拉选项中所显示的字段名称v-model的值为当前被选中的el-option的value属性值--el-option v-foritem in managerList :keyitem.id :labelitem.username :valueitem.id/el-option/el-select/el-form-itemel-form-item propintroduce label部门介绍!--文本域,4行--el-input v-modelformDara.introduce typetextarea :rows4 placeholder1-100个字符 stylewidth: 80%sizemini/el-input/el-form-item!--按钮部分并且要实现居中--el-form-item!--我们可以使用行和列实现居中布局--!--justifycenter 水平方式居中--el-row typeflex justifycenterel-col :span12el-button typeprimary sizemini确定/el-buttonel-button sizemini取消/el-button/el-col/el-row/el-form-item/el-form/el-dialog
/templatescript
import { getDepartment } from /api/departmentexport default {// 接收外部传输过来的值props: {// 参数showDialog类型限制为Boolean默认值为falseshowDialog: { type: Boolean, default: false }},data() {return {formDara: {code: , // 部门编码introduce: , // 部门介绍managerId: , // 部门负责人idname: , // 部门名称,pid: // 父级部门的id},rules: {// 部门编码code: [{ required: true, message: 部门编码不能为空, trigger: blur },{ min: 2, max: 10, message: 部门编码的长度2-10个字符 },// 自定义业务校验部门编码不能重复{trigger: blur, validator: async(rule, value, callback) {// value值是输入的编码值const result await getDepartment()// result实际是一个数组然后查看数组中是否存在用户输入的value值// 我们可以使用some()方法如果存在就返回true不存在就返回falseif (result.some(item item.code value)) {// 校验失败时的错误对象callback(new Error(部门中已经有该编码))} else {// 校验成功时的对象callback()}}}],// 部门介绍introduce: [{ required: true, message: 部门介绍不能为空, trigger: blur },{ min: 2, max: 10, message: 部门名称的长度1-100个字符 }],// 部门负责人idmanagerId:[{ required: true, message: 部门负责人id不能为空, trigger: blur }],// 部门名称name:[{ required: true, message: 部门名称不能为空, trigger: blur },{ min: 2, max: 10, message: 部门名称的长度2-10个字符 },{trigger: blur, validator: async(rule, value, callback) {// value值是输入的编码值const result await getDepartment()// result实际是一个数组然后查看数组中是否存在用户输入的value值// 我们可以使用some()方法如果存在就返回true不存在就返回falseif (result.some(item item.name value)) {// 校验失败时的错误对象callback(new Error(部门中已经有该名称))} else {// 校验成功时的对象callback()}}}]// pid: // 父级部门的id}}},methods: {......}
}
/script2.3 部门负责人数据
如下图所示
实现步骤
获取负责人的列表绑定下拉组件 Api
/*** 获取部门负责人的数据*/
export function getManagerList() {return request({url: /sys/user/simple,// 请求方式method: GET})
}组件代码
data() {return {// 存储负责人的列表managerList: [],}
},
methods: {async getManagerList() {this.managerList await getManagerList()}
},
created() {this.getManagerList()
}, el-form-item propmanagerId label部门负责人!--这个地方是一个下拉菜单--el-select v-modelformDara.managerId placeholder请选择负责人 stylewidth: 80% sizemini!--下拉选项循环managerList--!--label其实是下拉选项中所显示的字段名称v-model的值为当前被选中的el-option的value属性值--el-option v-foritem in managerList :keyitem.id :labelitem.username :valueitem.id/el-option/el-select/el-form-item2.4 记录部门
我们要在PHP研发部下面添加其子部门这个时候我们要知道PHP研发部的id才可以
当我们点击PHP研发部的时候我们需要将其id传输给AddDept组件 我们可以先看一下父组件 template!--为什么这里写container和app-container 因为我们最初的时候导入过样式--div classcontainer!--在此容器上加了边距上下30px左右140px--div classapp-container组织架构!--展示树形结构--!--此处正好是标签的属性名叫props和vue框架中组件传递数据不是一个--!--default-expand-all属性表示默认将所有的树形结构打开完整写法是 :default-expand-all“true” (一定带冒号)--el-tree :datadepts :propsdefaultProps default-expand-all :expand-on-click-nodefalse!--v-slot标签只能使用在template标签上--!--这个data数据其实是el-tree给的下面的template模板会不断的去循环有多少个节点就会循环多少次把每一个数据都塞到了data里面--template v-slot{data}!--节点结构。使用el-tree组件的插槽--!--会读取这个节点结构并循环渲染到页面上--!--我们如果把type布局模式设置为flex就可以用厚民安的两个属性justifyspace-between表示两头对其,alignmiddle表示垂直居中--el-row typeflex justifyspace-between alignmiddle stylewidth: 100%;height: 40px!--一行里面有两列,第一列是组织名称第二列是管理员和操作下拉菜单--el-col{{ data.name }}/el-col!--:span4一定带着冒号因为人家想要一个数字类型--el-col :span6span classtree-manager{{ data.managerName }}/span!--下拉菜单组件--!--command是下拉菜单的执行方法当点击下拉菜单中的某一项的时候就会执行operateDept方法--!--$event实参表示类型也就是下面command中的值表示事件所携带的默认参数如果不传data.id的话默认传入的就是$event实参--el-dropdown commandoperateDept($event,data.id)!--显示区域内容--span classel-dropdown-link操作i classel-icon-arrow-down el-icon--right/i/span!--下拉菜单的选项--el-dropdown-menu slotdropdownel-dropdown-item commandadd添加子部门/el-dropdown-itemel-dropdown-item commandedit编辑部门/el-dropdown-itemel-dropdown-item commanddel删除/el-dropdown-item/el-dropdown-menu/el-dropdown/el-col/el-row/template/el-tree/div!--放置弹层--!--:show-dialog 是我们在add-dept组件中定义的props--!--sync修饰表示会接受子组件的事件也就是update:showDialog这个事件然后会把值赋值给下面的showDialog--add-dept :current-node-idcurrentNodeId :show-dialog.syncshowDialog/add-dept/div
/templatemethods: {operateDept($event, id) {if ($event add) {// 添加子部门// 显示弹层组件this.showDialog true// 当前点击节点的idthis.currentNodeId id}},.................
},data() {return {// 存储当前点击idcurrentNodeId: null,............// 控制弹层的显示和隐藏showDialog: false}}子组件进行接收 // 接收外部传输过来的值
props: {// 参数showDialog类型限制为Boolean默认值为falseshowDialog: { type: Boolean, default: false },currentNodeId: {type: Number,default: null}
}2.5 确认功能
点击“确认”时首先进行表单校验表单校验通过之后可以将数据提交到后端也就是调用新增接口如果调用接口成功我们就可以通知父组件更新组织架构列表要更新也要重置一下表单数据再点开后是空白的情况最后关闭弹层 按钮
el-button clickbtnOK typeprimary sizemini确定/el-buttonapi请求
/*** 新增组织接口*/
export function addDepartment(data) {return request({url: /company/department,// 请求方式method: POST,data: data})
}方法 methods: {close() {// 重置表单this.$refs.addDept.resetFields()// 修改父组件的值子传给父亲// this.$emit可以触发一个自定义事件父组件需要接收这个时间然后把false这个值传出去// this.$emit(false) 但是我们先不用这个方法// 这里我们使用了 sync修饰表示会接受子组件的事件也就是update:showDialog这个事件然后会把值赋值给showDialogthis.$emit(update:showDialog, false)},async getManagerList() {this.managerList await getManagerList()},// 点击确定时调用此方法btnOK() {this.$refs.addDept.validate(async isOK {if (isOK) {// 校验已经通过// ...this.formDara 表示相当于把formDara数据进行了拷贝考到了一个新对象里面// pid: this.currentNodeId表示将formDara中的pid赋值上currentNodeIdawait addDepartment({ ...this.formDara, pid: this.currentNodeId })// 此时可以通知父组件更新也就是子传父可以选择触发一个自定义事件(父组件要监听这个事件)this.$emit(updateDepartment)// 提示消息this.$message.success(新增部门成功)// 关闭this.close()}})}}父组件index.vue
子组件会触发自定义事件updateDepartment
!--放置弹层--
!--:show-dialog 是我们在add-dept组件中定义的props--
!--sync修饰表示会接受子组件的事件也就是update:showDialog这个事件然后会把值赋值给下面的showDialog--
!--自定义事件updateDepartment子组件触发父组件执行getDepartment方法刷新组织结构--
add-dept updateDepartmentgetDepartment :current-node-idcurrentNodeId :show-dialog.syncshowDialog
/add-dept2.6 取消功能
点击取消后重置表单关闭弹层即可 el-button clickclose sizemini取消/el-button