组织架构-树组件应用
树形组件-用层级结构展示信息,可展开或折叠。
属性设置
- data(绑定数据)
- props(设置属性)- children(设置子节点的字段名)/ label(设置显示内容的字段名)
- default-expand-all(默认展开所有节点)
组织架构-树组件自定义结构
显示右侧结构
节点结构设计
使用elementui的行和列结构
行
列
组织架构-节点作用域插槽
组织架构-递归转化树形结构
/**
* 列表型数据转化为数组结构
*/
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;//将子节点赋值给当前节点
}
})
}
组织架构-递归特点
- 一般来说是用来处理未知层级的数据
- 递归要有跳出条件
- 自身调用自身时参数不能重复
组织架构-添加子部门-新建弹层组件
1.注册事件
给每个选项添加command属性,方便我们定位到点击了那个菜单
2.封装组件
3.控制显示
组织架构-添加子部门-表单构造
<el-dialog title="新增部门" :visible="showDialog" @close="close">
<el-form label-width="120x">
<el-form-item label="部门名称">
<el-input placeholder="2-10字符" style="width: 80%" size="mini"/>
</el-form-item>
<el-form-item label="部门编码">
<el-input style="width: 80%" placeholder="2-10字符" size="mini"/>
</el-form-item>
<el-form-item label="部门负责人">
<el-select style="width: 80%" placeholder="2-10字符" size="mini"/>
</el-form-item>
<el-form-item label="部门介绍">
<el-input type="textarea" :row="4" style="width: 80%" placeholder="1-100字符" size="mini"/>
</el-form-item>
<el-form-item>
<el-row type="flex" justify="center">
<el-col :span="12" align="center">
<el-button type="primary" size="mini">确认</el-button>
<el-button size="mini">取消</el-button>
</el-col>
</el-row>
</el-form-item>
</el-form>
</el-dialog>
组织架构-添加子部门-表单校验
- 定义数据结构
- 绑定属性
- 定义规则
<template>
<el-dialog title="新增部门" :visible="showDialog" @close="close">
<el-form ref="addDept" :model="formData" :rules="rules" label-width="120x">
<el-form-item label="部门名称" prop="name">
<el-input v-model="formData.name" placeholder="2-10字符" style="width: 80%" size="mini"/>
</el-form-item>
<el-form-item label="部门编码" prop="code">
<el-input v-model="formData.code" style="width: 80%" placeholder="2-10字符" size="mini"/>
</el-form-item>
<el-form-item label="部门负责人" prop="managerId">
<el-select v-model="formData.managerId" style="width: 80%" placeholder="2-10字符" size="mini"/>
</el-form-item>
<el-form-item label="部门介绍" prop="introduce">
<el-input v-model="formData.introduce" type="textarea" :row="4" style="width: 80%" placeholder="1-100字符" size="mini"/>
</el-form-item>
<el-form-item>
<el-row type="flex" justify="center">
<el-col :span="12" align="center">
<el-button type="primary" size="mini">确认</el-button>
<el-button size="mini">取消</el-button>
</el-col>
</el-row>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script>
export default {
props:{
showDialog:{
type: Boolean,
default: false
}
},
data(){
return{
formData: {
code: '',
introduce: '',
managerId: '',
name: '',
pid: '',
},
rules: {
code: [
{ required: true, message: '部门编码不能为空', trigger: 'blur' },
{min: 2, max: 10, message: '部门编码的长度为2-10个字符', trigger: 'blur'}
],
introduce: [
{ required: true, message: '部门介绍不能为空', trigger: 'blur' },
{min: 1, max: 100, message: '部门介绍的长度为1-100个字符', trigger: 'blur'}
],
managerId: [
{ required: true, message: '部门负责人不能为空', trigger: 'blur' }
],
name: [
{ required: true, message: '部门名称不能为空', trigger: 'blur' },
{min: 2, max: 10, message: '部门名称的长度为2-10个字符', trigger: 'blur'}
],
}
}
},
methods:{
close(){
//修改父组件的值 子传父
this.$emit('update:showDialog',false)//自定义事件
}
}
}
</script>
组织架构-添加子部门-业务校验
- 非空校验
- 长度校验
- 业务校验
自定义校验器:validator(rule, value(输入的值), callback(返回的值))
数组.some(回调),判断数组是否存在某个值
rules: {
code: [
{ required: true, message: '部门编码不能为空', trigger: 'blur' },
{min: 2, max: 10, message: '部门编码的长度为2-10个字符', trigger: 'blur'},
{
trigger: 'blur',
// 自定义校验模式
validator: async(rule, value, callback) => {
// value就是输入的编码
let result = await getDepartment()
// 判断是否是编辑模式
if (this.formData.id) {
// 编辑场景
result = result.filter(item => item.id !== this.formData.id)
}
// result数组中是否存在 value值
//some判断数组是否存在某个值,里面是回调函数
if (result.some(item => item.code === value)) {
callback(new Error('部门中已经有该编码了'))
} else {
callback()
}
}
}
],
introduce: [
{ required: true, message: '部门介绍不能为空', trigger: 'blur' },
{min: 1, max: 100, message: '部门介绍的长度为1-100个字符', trigger: 'blur'}
],
managerId: [
{ required: true, message: '部门负责人不能为空', trigger: 'blur' }
],
name: [
{ required: true, message: '部门名称不能为空', trigger: 'blur' },
{min: 2, max: 10, message: '部门名称的长度为2-10个字符', trigger: 'blur'},
{
trigger: 'blur',
// 自定义校验模式
validator: async(rule, value, callback) => {
// value就是输入的编码
let result = await getDepartment()
// 判断是否是编辑模式
if (this.formData.id) {
// 编辑场景 排除自身
result = result.filter(item => item.id !== this.formData.id)
}
// result数组中是否存在 value值
//some判断数组是否存在某个值,里面是回调函数
if (result.some(item => item.name === value)) {
callback(new Error('部门中已经有该编码了'))
} else {
callback()
}
}
}
],
}
}
},
组织架构-添加子部门-负责人数据
1. 初始化调用负责人数据列表
created() {
this.getManagerList();
},
methods:{
async getManagerList(){
const result = await getManagerList();
this.managerList = result;
},
close(){
//修改父组件的值 子传父
this.$emit('update:showDialog',false)//自定义事件
}
}
2. 表单中循环渲染数据
<el-form-item label="部门负责人" prop="managerId">
<el-select v-model="formData.managerId" style="width: 80%" placeholder="2-10字符" size="mini">
<!-- 编写下来选项 循环负责人的数据 label表示显示的字段 value为存储字段-->
<el-option v-for="item in managerList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
组织架构-添加子部门-记录部门
1.点击菜单传输id
2.定义数据记录id
3.组件接受
组织架构-添加子部门-确认取消
1.封装新增api
/**
* 新增组织
* @param data
* @returns {AxiosPromise}
*/
export function addDepartment(data) {
return request({
method:'post',
url:'/company/department',
data
})
2.确实,和通知父组件更新
btnOK(){
//表单校验
//获取表单实例
this.$refs.addDept.validate(async isOK=>{
if (isOK){
await addDepartment({...this.formData,pid : this.currentNodeId})
//通知父组件去更新
this.$emit('updateDeptment')
//提示实现
this.$message.success('新增部门成功')
this.close()
}
})
},
3.父组件接收事件调研方法
<add-dept :current-node-id="currentNodeId" :show-dialog.sync="showDialog" @updateDeptment="getDepartment"/>
4.取消调用close方法
close(){
//重置表单
this.$refs.addDept.resetFields()
//修改父组件的值 子传父
this.$emit('update:showDialog',false)//自定义事件
}
小结代码
1.api/department.js
import request from '@/utils/request'
/**
* 获取组织架构
* @param params
* @returns {AxiosPromise}
*/
export function getDepartment() {
return request({
url: '/company/departmant',
})
}
/**
* 获取部门负责人数据
* @param params
* @returns {AxiosPromise}
*/
export function getManagerList() {
return request({
url: '/sys/user/simple',
})
}
/**
* 新增组织
* @param data
* @returns {AxiosPromise}
*/
export function addDepartment(data) {
return request({
method:'post',
url:'/company/department',
data
})
}
2.add-dept.vue
<template>
<el-dialog title="新增部门" :visible="showDialog" @close="close">
<el-form ref="addDept" :model="formData" :rules="rules" label-width="120x">
<el-form-item label="部门名称" prop="name">
<el-input v-model="formData.name" placeholder="2-10字符" style="width: 80%" size="mini"/>
</el-form-item>
<el-form-item label="部门编码" prop="code">
<el-input v-model="formData.code" style="width: 80%" placeholder="2-10字符" size="mini"/>
</el-form-item>
<el-form-item label="部门负责人" prop="managerId">
<el-select v-model="formData.managerId" style="width: 80%" placeholder="2-10字符" size="mini">
<!-- 编写下来选项 循环负责人的数据 label表示显示的字段 value为存储字段-->
<el-option v-for="item in managerList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="部门介绍" prop="introduce">
<el-input v-model="formData.introduce" type="textarea" :row="4" style="width: 80%" placeholder="1-100字符" size="mini"/>
</el-form-item>
<el-form-item>
<el-row type="flex" justify="center">
<el-col :span="12" align="center">
<el-button @click="btnOK" type="primary" size="mini">确认</el-button>
<el-button @click="close" size="mini">取消</el-button>
</el-col>
</el-row>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script>
import {getDepartment,getManagerList,addDepartment} from '@/api/department'
export default {
props:{
showDialog:{
type: Boolean,
default: false
},
currentNodeId:{
type: Number,
default: null
}
},
data(){
return{
managerList: [],//存储负责人列表
formData: {
code: '',
introduce: '',
managerId: '',
name: '',
pid: '',
},
rules: {
code: [
{ required: true, message: '部门编码不能为空', trigger: 'blur' },
{min: 2, max: 10, message: '部门编码的长度为2-10个字符', trigger: 'blur'},
{
trigger: 'blur',
// 自定义校验模式
validator: async(rule, value, callback) => {
// value就是输入的编码
let result = await getDepartment()
// 判断是否是编辑模式
if (this.formData.id) {
// 编辑场景
result = result.filter(item => item.id !== this.formData.id)
}
// result数组中是否存在 value值
//some判断数组是否存在某个值,里面是回调函数
if (result.some(item => item.code === value)) {
callback(new Error('部门中已经有该编码了'))
} else {
callback()
}
}
}
],
introduce: [
{ required: true, message: '部门介绍不能为空', trigger: 'blur' },
{min: 1, max: 100, message: '部门介绍的长度为1-100个字符', trigger: 'blur'}
],
managerId: [
{ required: true, message: '部门负责人不能为空', trigger: 'blur' }
],
name: [
{ required: true, message: '部门名称不能为空', trigger: 'blur' },
{min: 2, max: 10, message: '部门名称的长度为2-10个字符', trigger: 'blur'},
{
trigger: 'blur',
// 自定义校验模式
validator: async(rule, value, callback) => {
// value就是输入的编码
let result = await getDepartment()
// 判断是否是编辑模式
if (this.formData.id) {
// 编辑场景 排除自身
result = result.filter(item => item.id !== this.formData.id)
}
// result数组中是否存在 value值
//some判断数组是否存在某个值,里面是回调函数
if (result.some(item => item.name === value)) {
callback(new Error('部门中已经有该编码了'))
} else {
callback()
}
}
}
],
}
}
},
created() {
this.getManagerList();
},
methods:{
async getManagerList(){
const result = await getManagerList();
this.managerList = result;
},
close(){
//重置表单
this.$refs.addDept.resetFields()
//修改父组件的值 子传父
this.$emit('update:showDialog',false)//自定义事件
}
},
btnOK(){
//表单校验
//获取表单实例
this.$refs.addDept.validate(async isOK=>{
if (isOK){
await addDepartment({...this.formData,pid : this.currentNodeId})
//通知父组件去更新
this.$emit('updateDeptment')
//提示实现
this.$message.success('新增部门成功')
this.close()
}
})
},
}
</script>
3.index.vue
<template>
<div class="container">
<div class="app-container">
<!-- 展示树结构 -->
<el-tree :expand-on-click-node="false" :data="depts" :props="defaultProps" default-expand-all="true">
<!-- 节点结构-->
<!-- v-slot="{node,data}",只能作用在template标签里面-->
<template v-slot="{data}">
<el-row style="width:100%;height:40px" type="flex" justify="space-between" align="middle">
<el-col>{{data.label}}</el-col>
<el-col :span="4">
<span class="tree-manager">{{data.managerName}}</span>
<!-- $event 实参 表示类型-->
<el-dropdown @command="operateDept($event,data.id)">
<!-- 显示区域-->
<span class="el-dropdown-link">
下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<!-- 选项-->
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="add">添加子部门</el-dropdown-item>
<el-dropdown-item command="edit">编辑部门</el-dropdown-item>
<el-dropdown-item command="del">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-col>
</el-row>
</template>
</el-tree>
</div>
<!-- 3.组件放在最外层的里一层-->
<!-- 表示会接受子组件的事件和值 => 属性-->
<add-dept :current-node-id="currentNodeId" :show-dialog.sync="showDialog" @updateDeptment="getDepartment"/>
</div>
</template>
<script>
import {transListToTreeData} from "@/utils"
//1.导入组件
import AddDept from "./components/add-dept.vue"
export default {
name: 'Department',
//2.注册局部组件
components: {AddDept},
data() {
return {
currentNodeId:null,
showDialog: false,//控制弹层
depts: [{
label: '瑞德', managerName:'管理员',id:1,children: [
{label: '总裁办', managerName:'历史',id:2},{
label: '行政部', managerName:'五五',id:3
},
{
label: '人事部', managerName:'全球',id:4
}
]
}],//数据属性
defaultProps: {
label: 'label', //要显示字段的名字
children: 'children' //读取子节点的字段名
}
}
},
created() {
this.getDepartment()
},
methods:{
//封装好的方法
async getDepartment(){
// const result = await getDepartment()
// this.depts = transListToTreeData(result,0)
},
//操作部门的方法
operateDept(type,id){
if (type==="add"){
this.showDialog=true
this.currentNodeId=id
}
}
}
}
</script>
<!--scoped当前组件生效-->
<style scoped>
.app-container{
padding: 30px 140px;
font-size: 14px;
}
.tree-manager{
width: 50px;
display: inline-block;
margin: 10px;
}
</style>