实现组织架构的头部内容

首先实现头部的结构,采用element的行列布局

   <!-- 实现页面的基本布局 -->    <el-card class="tree-card"><!-- 用了一个行列布局 --><el-row type="flex" justify="space-between" align="middle" style="height: 40px"><el-col><span>江苏传智播客教育科技股份有限公司</span></el-col><el-col :span="4"><el-row type="flex" justify="end"><!-- 两个内容 --><el-col>负责人</el-col><el-col><!-- 下拉菜单 element --><el-dropdown><span>操作<i class="el-icon-arrow-down" /></span><!-- 下拉菜单 --><el-dropdown-menu slot="dropdown"><el-dropdown-item>添加子部门</el-dropdown-item></el-dropdown-menu></el-dropdown></el-col></el-row></el-col></el-row><!-- 下面就是树形控件内容了 --></el-card>

样式

<style scoped>
.tree-card {padding: 30px  140px;font-size:14px;
}
</style>
​

树形组件认识

 [{label: '一级 1',children: [{label: '二级 1-1',children: [{label: '三级 1-1-1'}]}]}, {label: '一级 2',children: [{label: '二级 2-1',children: [{label: '三级 2-1-1'}]}, {label: '二级 2-2',children: [{label: '三级 2-2-1'}]}]}, {label: '一级 3',children: [{label: '二级 3-1',children: [{label: '三级 3-1-1'}]}, {label: '二级 3-2',children: [{label: '三级 3-2-1'}]}]}]

实现树形的静态组织架构

由此,我们首先实现静态数据的组织架构

 <!--放置一个属性   这里的props和我们之前学习的父传子 的props没关系--><el-tree :data="departs" :props="defaultProps" />
export default {data() {return {defaultProps: {label: 'name'},departs: [{ name: '总裁办', children: [{ name: '董事会' }] },{ name: '行政部' },{ name: '人事部' }]}}
}

接下来,对每个层级节点增加显示内容,此时需要用到tree的插槽

<template><div class="dashboard-container"><div class="app-container"><!-- 实现页面的基本布局 --><el-card><!--省略了头部内容--> <!--放置一个属性   这里的props和我们之前学习的父传子 的props没关系--><el-tree :data="departs" :props="defaultProps" :default-expand-all="true"><!-- 传入内容 插槽内容 会循环多次 有多少节点 就循环多少次 --><!-- 作用域插槽 slot-scope="obj" 接收传递给插槽的数据   data 每个节点的数据对象--><el-row slot-scope="{data}" type="flex" justify="space-between" align="middle" style="width:100%;height:40px;"><!-- 左侧内容 --><el-col><span>{{ data.name }}</span></el-col><!-- 右侧内容 --><el-col :span="4"><el-row type="flex" justify="end"><el-col>{{ data.manager }}</el-col><el-col><!-- 放置下拉菜单 --><el-dropdown><!-- 内容 --><span>操作 <i class="el-icon-arrow-down" /> </span><!-- 具名插槽 --><el-dropdown-menu slot="dropdown"><el-dropdown-item>添加子部门</el-dropdown-item><el-dropdown-item>编辑部门</el-dropdown-item><el-dropdown-item>删除部门</el-dropdown-item></el-dropdown-menu></el-dropdown></el-col></el-row></el-col></el-row></el-tree></el-card> </div></div>
</template>
​
<script>
export default {name: 'Departments',data() {return {defaultProps: {label: 'name'},departs: [{ name: '总裁办', manager: '曹操', children: [{ name: '董事会', manager: '曹丕' }] },{ name: '行政部', manager: '刘备' },{ name: '人事部', manager: '孙权' }]}}
}
</script>
​
<style>
​
</style>

最终形成静态结构效果

将树形的操作内容单独抽提成组件

目标: 将树形的操作内容单独抽提成组件

封装单独的树操作栏组件

组件 src/views/departments/components/tree-tools.vue

<template><el-row type="flex" justify="space-between" align="middle" style="height: 40px;width: 100%"><el-col><!-- 名称应该变成 对应的节点中的name --><span>{{ treeNode.name }}</span></el-col><el-col :span="4"><el-row type="flex" justify="end"><!-- 两个内容 --><el-col>{{ treeNode.manager }}</el-col><el-col><!-- 下拉菜单 element --><el-dropdown><span>操作<i class="el-icon-arrow-down" /></span><!-- 下拉菜单 --><el-dropdown-menu slot="dropdown"><el-dropdown-item>添加子部门</el-dropdown-item><el-dropdown-item>编辑部门</el-dropdown-item><el-dropdown-item>删除部门</el-dropdown-item></el-dropdown-menu></el-dropdown></el-col></el-row></el-col></el-row>
</template>
​
<script>
// 该组件需要对外开放属性 外部需要提供一个对象 对象里需要有name  manager
export default {// props可以用数组来接收数据 也可以用对象来接收// props: {   props属性: {  配置选项 }  }props: {//   定义一个props属性treeNode: {type: Object, // 对象类型required: true // 要求对方使用您的组件的时候 必须传treeNode属性 如果不传 就会报错}}
}
</script>
​
​

在组织架构中应用操作栏组件

接下来,在src/views/departments/index.vue进行代码的简化

<template><div class="dashboard-container"><div class="app-container"><!-- 实现页面的基本布局 --><el-card class="tree-card"><!-- 用了一个行列布局 --><!-- 缺少treeNode --><tree-tools :tree-node="company" /><!--放置一个属性   这里的props和我们之前学习的父传子 的props没关系--><el-tree :data="departs" :props="defaultProps" default-expand-all><!-- 说明el-tree里面的这个内容 就是插槽内容 => 填坑内容  => 有多少个节点循环多少次 --><!-- scope-scope 是 tree组件传给每个节点的插槽的内容的数据 --><!-- 顺序一定是 执行slot-scope的赋值 才去执行 props的传值 --><tree-tools slot-scope="{ data }" :tree-node="data" /></el-tree></el-card></div></div>
</template>
​

同时,由于在两个位置都使用了该组件,但是放置在最上层的组件是不需要显示 删除部门编辑部门

所以,增加一个新的属性 isRoot(是否根节点)进行控制

 props: {treeNode: {required: true, // 设置当前数据为必填type: Object // 类型是Object},isRoot: {type: Boolean,default: false}}<tree-tools :tree-node="company" :is-root="true" />

组件中, 根据isRoot判断显示

     <!-- 编辑部门和删除部门只会在子节点上显示 --><el-dropdown-item v-if="!isRoot">编辑部门</el-dropdown-item><el-dropdown-item v-if="!isRoot">删除部门</el-dropdown-item>

获取组织架构数据,并进行树形处理

目标获取真实的组织架构数据,并将其转化成树形数据显示在页面上

封装API接口,获取组织架构数据

现在基本的静态结构已经形成,接下来需要获取真实的数据

首先,封装获取组织架构的请求 src/api/departments.js

/** *** 获取组织架构数据* **/
export function getDepartments() {return request({url: '/company/department'})
}
​

在钩子函数中调用接口

import TreeTools from './components/tree-tools'
import { getDepartments } from '@/api/departments'
export default {components: {TreeTools},data() {return {company: { }, // 就是头部的数据结构departs: [],defaultProps: {label: 'name' // 表示 从这个属性显示内容}}},created() {this.getDepartments() // 调用自身的方法},methods: {async getDepartments() {const result = await getDepartments()this.company = { name: result.companyName, manager: '负责人' }this.departs = result.depts // 需要将其转化成树形结构console.log(result)}}
}

将数组数据转化成树形结构

然后,我们需要将列表型的数据,转化成树形数据,这里需要用到递归算法

封装一个工具方法,src/utils/index.js

/** ***  将列表型的数据转化成树形数据 => 递归算法 => 自身调用自身 => 一定条件不能一样, 否则就会死循环*  遍历树形 有一个重点 要先找一个头儿* ***/
export function tranListToTreeData(list, rootValue) {var arr = []list.forEach(item => {if (item.pid === rootValue) {// 找到之后 就要去找 item 下面有没有子节点const children = tranListToTreeData(list, item.id)if (children.length) {// 如果children的长度大于0 说明找到了子节点item.children = children}arr.push(item) // 将内容加入到数组中}})return arr
}

调用转化方法,转化树形结构

  this.company = { name: result.companyName, manager: '负责人' } // 这里定义一个空串  因为 它是根 所有的子节点的数据pid 都是 ""this.departs = tranListToTreeData(result.depts, '')

这样一来,树形数据就有了,下一章节,就可以针对部门进行操作

删除部门功能实现

目标实现操作功能的删除功能

封装删除接口,注册下拉菜单事件

首先,封装删除功能模块 src/api/departments.js

/** **  根据id根据部门  接口是根据restful的规则设计的   删除 delete  新增 post  修改put 获取 get* **/
export function delDepartments(id) {return request({url: `/company/department/${id}`,method: 'delete'})
}

然后,在tree-tools组件中,监听下拉菜单的点击事件 src/views/departments/index.vue

          <el-dropdown @command="operateDepts"><span>操作<i class="el-icon-arrow-down" /></span><!-- 下拉菜单 --><el-dropdown-menu slot="dropdown"><el-dropdown-item command="add">添加子部门</el-dropdown-item><!-- 编辑部门和删除部门只会在子节点上显示 --><el-dropdown-item v-if="!isRoot" command="edit">编辑部门</el-dropdown-item><el-dropdown-item v-if="!isRoot" command="del">删除部门</el-dropdown-item></el-dropdown-menu></el-dropdown>

dropdown下拉菜单的监听事件command

    // 操作节点调用的方法operateDepts(type) {if (type === 'add') {// 添加子部门的操作} else if (type === 'edit') {//  编辑部门的操作} else {//  删除操作}}

调用删除接口,通知父组件更新数据

删除之前,提示用户是否删除,然后调用删除接口

在前面的课程中,我们已经学习过可以通过自定义事件this.$emit的方式来进行

         //  如果删除成功了  就会进入这里this.$emit('delDepts') // 触发自定义事件this.$message.success('删除部门成功')

父组件监听事件 src/views/department/index.vue

新增部门功能-建立组件

目标:实现新增部门功能的组件建立

封装新增接口,新建组件中的弹层结构

首先, 封装新增部门的api模块 src/api/departments.js

/***  新增部门接口** ****/
export function addDepartments(data) {return request({url: '/company/department',method: 'post',data})
}
​

然后,我们需要构建一个新增部门的窗体组件 src/views/department/components/add-dept.vue

<template><!-- 新增部门的弹层 --><el-dialog title="新增部门"><!-- 表单组件  el-form   label-width设置label的宽度   --><!-- 匿名插槽 --><el-form label-width="120px"><el-form-item label="部门名称"><el-input style="width:80%" placeholder="1-50个字符" /></el-form-item><el-form-item label="部门编码"><el-input style="width:80%" placeholder="1-50个字符" /></el-form-item><el-form-item label="部门负责人"><el-select style="width:80%" placeholder="请选择" /></el-form-item><el-form-item label="部门介绍"><el-input style="width:80%" placeholder="1-300个字符" type="textarea" :rows="3" /></el-form-item></el-form><!-- el-dialog有专门放置底部操作栏的 插槽  具名插槽 --><el-row slot="footer" type="flex" justify="center"><!-- 列被分为24 --><el-col :span="6"><el-button type="primary" size="small">确定</el-button><el-button size="small">取消</el-button></el-col></el-row></el-dialog>
</template>

点击新增子部门显示弹层组件

然后,我们需要用属性控制组件的显示或者隐藏

  // 需要传入一个props变量来控制 显示或者隐藏props: {showDialog: {type: Boolean,default: false}}
<el-dialog title="新增部门" :visible="showDialog">

departments/index.vue 中引入该组件

import AddDept from './components/add-dept' // 引入新增部门组件
export default {components: { AddDept }
}

定义控制窗体显示的变量showDialog

 data() {return {showDialog: false // 显示窗体}},<!-- 放置新增弹层组件  --><add-dept :show-dialog="showDialog" />

当点击新增部门时,弹出组件

子组件触发新增事件· src/views/departments/tree-tools.vue

  if (type === 'add') {// 添加子部门的操作// 告诉父组件 显示弹层this.$emit('addDepts', this.treeNode) // 为何传出treeNode 因为是添加子部门 需要当前部门的数据}

父组件监听事件

2处添加
<tree-tools slot-scope="{data}" :tree-node="data" @delDepts="getDepartments" @addDepts="addDepts" />
<tree-tools :tree-node="company" :is-root="true" @delDepts="getDepartments" @addDepts="addDepts" />

方法中弹出层,记录在哪个节点下添加子部门

 addDepts(node) {this.showDialog = true // 显示弹层// 因为node是当前的点击的部门, 此时这个部门应该记录下来,this.node = node}

完成新增部门的规则校验

目标 完成新增部门功能的规则校验和数据提交部分

完成新增表单的基本校验条件

  formData: {name: '', // 部门名称code: '', // 部门编码manager: '', // 部门管理者introduce: '' // 部门介绍},
  • el-form配置model和rules属性

  • el-form-item配置prop属性

  • 表单进行v-model双向绑定

配置新增表单的基本校验规则

  data() {return {// 定义表单数据formData: {name: '', // 部门名称code: '', // 部门编码manager: '', // 部门管理者introduce: '' // 部门介绍},// 定义校验规则rules: {name: [{ required: true, message: '部门名称不能为空', trigger: 'blur' },{ min: 1, max: 50, message: '部门名称要求1-50个字符', trigger: 'blur' }],code: [{ required: true, message: '部门编码不能为空', trigger: 'blur' },{ min: 1, max: 50, message: '部门编码要求1-50个字符', trigger: 'blur' }],manager: [{ required: true, message: '部门负责人不能为空', trigger: 'blur' }],introduce: [{ required: true, message: '部门介绍不能为空', trigger: 'blur' },{ trigger: 'blur', min: 1, max: 300, message: '部门介绍要求1-50个字符' }]}}}

处理首部内容的pid数据

需要注意:在最根级的tree-tools组件中,由于treenode属性中没有id,id便是undefined,但是通过undefined进行等值判断是寻找不到对应的根节点的, 所以在传值时,我们将id属性设置为 “”

src/views/departments/index.vue

 async getDepartments() {const result = await getDepartments()this.departs = tranListToTreeData(result.depts, '')this.company = { name: result.companyName, manager: '负责人', id: '' }},

新增部门功能-部门负责人数据

目标:获取新增表单中的部门负责人下拉数据

在上节的表单中,部门负责人是下拉数据,我们应该从员工接口中获取该数据

首先,封装获取简单员工列表的模块 src/api/employees.js

import request from '@/utils/request'
​
/***  获取员工的简单列表* **/
export function getEmployeeSimple() {return request({url: '/sys/user/simple'})
}
​

然后,在add-dept.vue中的select聚焦事件focus中调用该接口,因为我们要获取实时的最新数据

<el-select v-model="formData.manager" style="width:80%" placeholder="请选择" @focus="getEmployeeSimple"><!-- 需要循环生成选项   这里做一下简单的处理 显示的是用户名 存的也是用户名--><el-option v-for="item in peoples" :key="item.id" :label="item.username" :value="item.username" />
</el-select>

获取员工列表

import  { getEmployeeSimple }   from '@/api/employees'
methods: {// 获取员工简单列表数据async  getEmployeeSimple() {this.peoples = await getEmployeeSimple()}
}
data:{peoples: [] // 接收获取的员工简单列表的数据
}
​

提交代码

本节任务:新增部门功能-部门负责人数据

新增功能-提交-取消-关闭

目标: 完成新增模块的提交-取消-关闭等功能

校验通过,调用新增接口

首先,在点击确定时,校验表单

给el-form定义一个ref属性

    <el-form ref="deptForm" :model="formData" :rules="rules" label-width="120px">
    // 点击确定时触发btnOK() {this.$refs.deptForm.validate(isOK => {if (isOK) {// 表示可以提交了}})}

然后,在校验通过时,调用新增接口

    // 点击确定时触发btnOK() {this.$refs.deptForm.validate(async isOK => {if (isOK) {// 表示可以提交了await addDepartments({ ...this.formData, pid: this.treeNode.id }) // 调用新增接口 添加父部门的id}})}

同样,在新增成功之后,调用告诉父组件,重新拉取数据

 this.$emit('addDepts')

父组件

 <add-dept :show-dialog="showDialog" :tree-node="node" @addDepts="getDepartments" />
​

本节注意:同学们可能会疑惑,我们tree-tools.vueadd-dept.vue两个组件都触发了addDepts事件,不冲突吗?

这里,我们触发的自定义事件都是组件自身的,他们之间没有任何关系,只是名字相同而已,大家不要混淆

利用sync修饰符关闭新增弹层

这里我们学习一个新的技巧,sync修饰符

按照常规,想要让父组件更新showDialog的话,需要这样做

// 子组件
this.$emit('changedialog', false) //触发事件
// 父组件
<child @changedialog="method" :showDialog="showDialog" />
// JS 里面method(value) {this.showDialog = value
}

// 子组件 update:固定写法 (update:props名称, 值) this.$emit('update:showDialog', false) //触发事件 // 父组件 sync修饰符 <child :showDialog.sync="showDialog" /> ​

只要用sync修饰,就可以省略父组件的监听和方法,直接将值赋值给showDialog

取消按钮和关闭

// 点击确定时触发btnOK() {this.$refs.deptForm.validate(async isOK => {if (isOK) {// 表示可以提交了await addDepartments({ ...this.formData, pid: this.treeNode.id }) // 调用新增接口 添加父部门的idthis.$emit('addDepts') // 告诉父组件 新增数据成功 重新拉取数据// update:props名称this.$emit('update:showDialog', false)}})}

取消时重置数据和校验

btnCancel() {this.$refs.deptForm.resetFields() // 重置校验字段this.$emit('update:showDialog', false) // 关闭
}

需要在el-dialog中监听其close事件

  <el-dialog title="新增部门" :visible="showDialog" @close="btnCancel">

本节任务 新增功能-提交-取消-关闭

computed: {showTitle() {return this.formData.id ? '编辑部门' : '新增子部门'}},

同时发现,el-form中的resetFields不能重置非表单中的数据,所以在取消的位置需要强制加上 重置数据

    btnCancel() {// 重置数据  因为resetFields 只能重置 表单上的数据 非表单上的 比如 编辑中id 不能重置this.formData = {name: '',code: '',manager: '',introduce: ''}// 关闭弹层this.$emit('update:showDialog', false)// 清除之前的校验  可以重置数据 只能重置 定义在data中的数据this.$refs.deptForm.resetFields()}

组织架构树形结构布局相关推荐

  1. Vue人资中台--公司组织架构(树形结构)

    组织架构树形结构布局 目标:使用element-UI组件布局组织架构的基本布局 认识组织架构 组织架构产品prd 一个企业的组织架构是该企业的灵魂,组织架构多常采用树形金字塔式结构,本章节,我们布局出 ...

  2. 人资项目day06-组织架构树形结构布局

    使用element-UI组件布局组织架构的基本布局 认识组织架构 组织架构产品prd 一个企业的组织架构是该企业的灵魂,组织架构多常采用树形金字塔式结构,本章节,我们布局出页面的基本结构 实现组织架构 ...

  3. jQuery table组织架构图表插件

    jQuery table组织架构图表插件 jQuery.orgchart分支节点组织结构图插件,绘制分级模块的组织架构图表分析布局代码. 演示地址 下载地址

  4. 企业微信组织架构递归展示

    业务场景:获取企业微信员工列表,然后按照组织架构的结构展示出来. // 人员分组处理,补充管理员身份标示public function personTree($user, $admin_list){$ ...

  5. rtx 加密机制_rtx腾讯通组织架构(结构)不显示的解决办法

    rtx腾讯通组织架构(结构)不显示了? 在公司,刚来的新同事的rtx腾讯通组织架构(结构)不显示,这些都是电脑上以前没有上过rtx的原因,其实很简单就可以完美的解决这一个问题. 1.首先,我以前用的方 ...

  6. 【每日随笔】西游记相关随笔 ( 天庭的结构以及人事关系 | 天庭组织架构 | 佛门组织架构 | 天庭的盘根错节 | 西游记中的人情世故 )

    文章目录 一.天庭组织架构 二.佛门组织架构 三.天庭的盘根错节 四.西游记中的人情世故 西游记 和 红楼梦 每一个细节都 蕴含了 大智慧 , 值的每个人都去精读 , 是中国古代智慧的集大成者 ; 西 ...

  7. php 获取所有的下级组织,树形结构 查找上下级

    现有树形结构如下    若给出cat_id 9  如何查处 9 的所有上级  和  所有下级 array ( 1 =>array ( 'cat_id' => '1', 'cat_name' ...

  8. 使用Echars实现水滴状、环形图、分割图、堆叠、组织架构图、地图轮廓等图表

    百度Echarts 水滴状图表 横向柱形图 分割块柱形图 曲线面积图 横向堆叠柱形图 环形进度图 饼状图 饼状图多个标题 组织架构图 省市轮廓地图 新疆省地图 全国地图 折线图阴影效果 柱形折线混合图 ...

  9. Vue 人资 实战篇七 员工管理上 封装通用的组件、formatter属性、过滤器的使用、树形结构、建立公共导入的页面路由、excel的导入和导出、

    1.0 封装一个通用的工具栏 目标:封装一个通用的工具栏供大家使用 1.1 通用工具栏的组件结构 在后续的业务开发中,经常会用到一个类似下图的工具栏,作为公共组件,进行一下封装 组件 src/comp ...

最新文章

  1. InnoDB memcached插件部署
  2. IntelliTest(5) - The IntelliTest Reference Manual[译]
  3. Xamarin.Forms中使用LiteDB分页
  4. ubuntu命令模式中文乱码
  5. 【英语学习】【English L06】U02 Food L3 Peking roast duck
  6. 业界分享 | 美团到店综合知识图谱的构建与应用
  7. 如何自学成为设计师_如何成为平面设计师?平面设计师平时做什么?教你做好平面设计...
  8. 离开APM的弹性云还是真弹性吗
  9. 梦的解析 —— 梦知道答案
  10. 判断一个整数是不是回文
  11. 2014年计算机求职总结--准备篇
  12. 栈和队列的基础算法学习(EPI)
  13. 基于与非门和多路开关结构的一位全加器实现方法
  14. 易语言PHP自动更新,易语言自动更新源码
  15. 可以插卡的ipad_平板电脑可以插手机卡吗,终于能插卡了!苹果iPad 2018蜂窝网络版上架国内官网...
  16. pytorch制作数据集
  17. android实现微信网页浏览、QQ下拉效果SlidingLayout
  18. C语言练习题(n个自然数的立方和)
  19. 步进电机S(SigMoid)曲线加减速【查表法】
  20. ERP_课程论文(hunnu)

热门文章

  1. Revit开发柱附着和分离
  2. 基于樽海鞘算法的极限学习机(ELM)回归预测-附代码
  3. 分屏视频怎么剪?手把手教你剪辑
  4. DLPC-PEG-阳离子聚合物/聚酚胺/聚(N-异丙基丙烯酰胺/聚丙烯酸酯/聚甲基丙烯酸甲酯
  5. [BZOJ2246][SDOI2011]迷宫探险(状压概率DP)
  6. .net Entity Framework
  7. 面试题---框架阶段
  8. 编程中常见的代码词汇汇总
  9. 安装Fedora 36 Server
  10. 中国十大“勾魂”美景-雪山