使用element-UI组件布局组织架构的基本布局

认识组织架构

组织架构产品prd

一个企业的组织架构是该企业的灵魂,组织架构多常采用树形金字塔式结构,本章节,我们布局出页面的基本结构

实现组织架构的头部内容

首先实现头部的结构,采用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>

树形组件认识

接下来,实现树形的结构,采用element的tree组件, 如图效果

树形组件属性

参数 说明 类型 可选值 默认值
default-expand-all 是否默认展开所有节点 boolean
data 展示数据 array
node-key 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的 String
props 配置选项,具体看下表 object

props属性

参数 说明 类型 可选值 默认值
label 指定节点标签为节点对象的某个属性值 string, function(data, node)
children 指定子树为节点对象的某个属性值 string
disabled 指定节点选择框是否禁用为节点对象的某个属性值 boolean, function(data, node)
isLeaf 指定节点是否为叶子节点,仅在指定了 lazy 属性的情况下生效 boolean, function(data, node)

data是组成树形数据的关键,如下的数据便能构建树形数据

[{
          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>

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

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

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

在钩子函数中调用接口

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, '')

删除部门功能实现

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

在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 {
        //  删除操作
      }
    }

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

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

// 操作节点调用的方法
    operateDepts(type) {
      if (type === 'add') {
        // 添加子部门的操作
      } else if (type === 'edit') {
        //  编辑部门的操作
      } else {
        //  删除操作
        this.$confirm('确定要删除该部门吗').then(() => {
          // 如果点击了确定就会进入then
          return delDepartments(this.treeNode.id) // 返回promise对象
        }).then(() => {
          //  如果删除成功了  就会进入这里
        })
      }
    }

通过自定义事件this.$emit的方式来进行

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

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

<tree-tools slot-scope="obj" :tree-node="obj.data" @delDepts="getDepartments" />

新增部门功能-建立组件

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

我们需要构建一个新增部门的窗体组件 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
    }

完成新增部门的规则校验

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

部门名称(name):必填 1-50个字符 / 同级部门中禁止出现重复部门

部门编码(code):必填 1-50个字符 / 部门编码在整个模块中都不允许重复

部门负责人(manager):必填

部门介绍 ( introduce):必填 1-300个字符

定义数据结构

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个字符' }
        ]
      }
    }
  }

部门名称和部门编码的自定义校验

部门名称和部门编码的规则 有两条我们需要通过自定义校验函数validator来实现

在校验名称和编码时,要获取最新的组织架构,这也是我们这里trigger采用blur的原因,因为change对于访问的频率过高,我们需要控制访问频率

部门名称不能和同级别的重复,这里注意,我们需要找到所有同级别的数据,进行校验,所以还需要另一个参数pid

props: {
    //   用来控制窗体是否显示或者隐藏
    showDialog: {
      type: Boolean,
      default: false
    },
    // 当前操作的节点
    treeNode: {
      type: Object,
      default: null
    }
  },
  <add-dept :show-dialog="showDialog" :tree-node="node" />

根据当前部门id,找到所有子部门相关的数据,判断是否重复

// 现在定义一个函数 这个函数的目的是 去找 同级部门下 是否有重复的部门名称
    const checkNameRepeat = async(rule, value, callback) => {
      // 先要获取最新的组织架构数据
      const { depts } = await getDepartments()
      // depts是所有的部门数据
      // 如何去找技术部所有的子节点
      const isRepeat = depts.filter(item => item.pid === this.treeNode.id).some(item => item.name === value)
      isRepeat ? callback(new Error(`同级部门下已经有${value}的部门了`)) : callback()
    }

检查部门编码的过程同理

// 检查编码重复
    const checkCodeRepeat = async(rule, value, callback) => {
      // 先要获取最新的组织架构数据
      const { depts } = await getDepartments()
      const isRepeat = depts.some(item => item.code === value && value) // 这里加一个 value不为空 因为我们的部门有可能没有code
      isRepeat ? callback(new Error(`组织架构中已经有部门使用${value}编码`)) : callback()
    }

在规则中定义

// 定义校验规则
      rules: {
        name: [
          { required: true, message: '部门名称不能为空', trigger: 'blur' },
          { min: 1, max: 50, message: '部门名称要求1-50个字符', trigger: 'blur' },
          // 自定义函数的形式校验
          {trigger: 'blur',validator: checkNameRepeat }
        ],
        code: [
          { required: true, message: '部门编码不能为空', trigger: 'blur' },
          { min: 1, max: 50, message: '部门编码要求1-50个字符', trigger: 'blur' }, 
          { trigger: 'blur',validator: checkCodeRepeat}
        ],
        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: '' }
 }

人资项目day06-组织架构树形结构布局相关推荐

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

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

  2. 组织架构树形结构布局

    实现组织架构的头部内容 首先实现头部的结构,采用element的行列布局 <!-- 实现页面的基本布局 --> <el-card class="tree-card" ...

  3. 普元云计算-云计算平台项目团队组织架构与缘起

    转载本文需注明出处:EAII企业架构创新研究院,违者必究.如需加入微信群参与微课堂.架构设计与讨论直播请直接回复公众号:"EAII企业架构创新研究院".(微信号:eaworld) ...

  4. 云计算平台项目团队组织架构与缘起

    转载本文需注明出处:EAII企业架构创新研究院,违者必究.如需加入微信群参与微课堂.架构设计与讨论直播请直接回复公众号:"EAII企业架构创新研究院".(微信号:eaworld) ...

  5. PMP组织架构分类(强矩阵弱矩阵等)及项目经理权力与职能经理对比,一看必懂

    PMP组织架构中一般分类 :职能型,项目型,矩阵型(包括弱矩阵型.强矩阵型.平衡型矩阵). 先重点来说说弱/强 矩阵型: 矩阵型组织架构 : 大家在各部门呆着好好的.我因为有特殊项目,到各个部门挑个同 ...

  6. 组织架构分类 :职能型、项目型、弱矩阵型、强矩阵型

    1.职能型组织架构 每个职能部门都有自己的职能经理,员工干自己部门的事务. 2.项目型组织架构 每个项目都有自己的项目经理,员工干这个项目的事务. 3.弱/强 矩阵型组织架构 矩阵型简述 : 大家在各 ...

  7. SAP-MM-PA精解分析系列之基本介绍(02) -组织架构

    MM基本知识(02)--组织架构讲解        采购业务下的组织架构讲解 在SAP系统中,不同的组织架构代表着企业的不同法律或者组织单位.在每一次项目实施中,确定企业的组织架构是一件非常重要的事情 ...

  8. 打造高效研发团队 (1) —— 组织架构篇

    原文:https://my.oschina.net/huangyong/blog/1812037 2015 年,我加入特赞,带领了一支小规模研发团队.那时公司还在天使轮,团队最大的目标是能让产品上线, ...

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

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

最新文章

  1. 图解:电商支付架构设计
  2. linux+bash+参数脚本名,linux – Bash中的脚本参数
  3. Ubuntu自带pdf查看器不能显示中文解决问题
  4. 技术盘点:2022年云原生架构趋势解读
  5. plsql 使用技巧 及 语句集锦(二)经典update
  6. 【转】AngularJs 弹出框 model(模态框)
  7. 一天学完spark的Scala基础语法教程十、类和对象(idea版本)
  8. Mac 系统引导过程概述 BootCamp 的秘密
  9. Django——Model
  10. 用友政务知识管理平台_云创数字政务大数据平台,助力政务工作高效管理
  11. seajs的模块化开发--实践笔记
  12. Linux DNS 服务配置 (非常详细)
  13. Flex走出低谷的关键: 打破Flex固有的定义
  14. Reza Zafarani经典教材-《社交媒体挖掘》PDF+随书课件打包分享
  15. 如何读写8bit rgb彩色png图像
  16. 短短十言,把人生说透了.
  17. karaf学习 (2)
  18. 【面试题笔记-Java】MySQL数据库、索引、MVCC等知识点(自己整理)
  19. 《内网安全攻防:渗透测试实战指南》读书笔记(二):内网信息收集
  20. 华为云配置nodejs环境

热门文章

  1. 实验五:Romberg算法
  2. 全网最详细的Hadoop大数据集群搭建并进行项目分析(基于完全分布式)---终结篇
  3. 中国水溶性肥料市场趋势报告、技术动态创新及市场预测
  4. 微笑小程序的相关知识
  5. oracle中的样本差怎么计算-----样本标准差和全数据标准差两种
  6. html拖拽不能放下,HTML拖拽时Drop偶尔不激发的问题
  7. 六.随机神经网络Boltzmann(玻尔兹曼机)
  8. PHP请求天气api获取多个城市天气预报数据
  9. c语言bitmap,bitmap C语言实现
  10. 系统计算机如何使用记录,Win7如何查看电脑使用记录?