组织架构路由
import layout from '@/layout'
export default {
path: '/department',
component: layout, // 一级路由
children: [{
path: '', // 二级路由地址为空 表示/department 显示一级路由+二级路由
component: () => import('@/views/department'),
name: '', // 可以用来跳转,也可以用来标记路由
meta: {
// 路由元信息,存储数据的
icon: 'tree', // 存菜单图标
title: '组织'// 存菜单标题
}
}]
}
创建好后,在router/index里引入
分析左侧菜单怎么生成的
logo大小调整
树形组件应用
<el-tree :data="depts" :props="defaultProps" default-expand-all />
<template>
<div class="container">
<div class="app-container">
<!--展示树形结构-->
<!--default-expand-all默认展开-->
<el-tree :data="depts" :props="defaultProps" default-expand-all />
</div>
</div>
</template>
<script>
export default {
name: 'Department',
data() {
return {
depts: [{ name: '充值教育', children: [{ name: '总裁办' }, { name: '行政部' }, { name: '人事部' }] }], // 数据属性
defaultProps: {
label: 'name', // 要显示的字段的名称
children: 'children'// 读取子节点的字段名
}
}
}
}
</script>
增加样式
<style scoped>
.app-container{
padding: 30px 140px;
font-size: 14px;
}
</style>
用插槽显示节点数据
<div class="app-container">
<!-- 展示树形结构 -->
<el-tree :expand-on-click-node="false" default-expand-all :data="depts" :props="defaultProps">
<!-- 节点结构 -->
<!-- 作用域插槽 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.name }}</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" />
</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>
封装接口获取数据
1.api下新建department.js用来专门管理组织架构的接口
import request from '@/utils/request'
// 导出获取组织信息的函数
export function getDepartment() {
return request({
url: '/company/department'
})
}
2.调用方法
methods: {
async getDepartment() {
const result = await getDepartment()
this.depts = result
}
}
递归转化树形结构
index.js
/**
* 列表型转换为树型
*/
export function transListToTreeData(list, rootValue) {
const arr = []
list.forEach(item => {
if (item.pid === rootValue) {
arr.push()
const children = transListToTreeData(list, item.id)
list.children = children
}
})
return arr
}
添加子部门弹框
封装的弹框
<template>
<el-dialog title="新增" :visible="showDialog" @close="close" />
</template>
<script>
export default {
props: {
// 接收外部过来的showDialog,是一个promise
showDialog: {
type: Boolean,
default: false
}
}, method: {
close() {
// 修改父组件的值,子传父
this.$emit('update:showDialog', false)
}
}
}
</script>
表单结构
<el-dialog title="新增" :visible="showDialog" @close="close">
<el-form label-width="120px">
<el-form-item label="部门名称">
<el-input placeholder="2-10个字符" style="width:80%" size="mini" />
</el-form-item>
<el-form-item label="部门编码">
<el-input placeholder="2-10个字符" style="width:80%" size="mini" />
</el-form-item><el-form-item label="部门负责人">
<el-select placeholder="选择负责人" style="width:80%" size="mini" />
</el-form-item><el-form-item label="部门介绍">
<el-input placeholder="2-10个字符" type="textarea" size="mini" :rows="4" style="width:80%" />
</el-form-item>
<el-from-item>
<el-row type="flex" justify="center">
<el-col :span="12">
<el-button type="primary" size="mini">确定</el-button>
<el-button type="primary" size="mini">取消</el-button></el-col>
</el-row>
</el-from-item>
</el-form>
</el-dialog>
基础校验
rules: {
code: [{ required: true, message: '不能空' }, { min: 2, max: 10, message: '长度2-10' }],
introduce: [{ required: true, message: '不能空' }, { min: 1, max: 100, message: '长度1-100' }],
managerId: [{ required: true, message: '不能空' }, { min: 2, max: 10, message: '长度2-10' }],
name: [{ required: true, message: '不能空' }, { min: 2, max: 10, message: '长度2-10' }]
// pid: [] pid不需要校验
}
部门名称不重复的自定义校验
name: [{ required: true, message: '不能空', trigger: 'blur' }, { min: 2, max: 10, message: '长度2-10', trigger: 'blur' }, { trigger: 'blur', validtaor: async(rules, value, callback) => {
// value就是输入的编码
const result = await getDepartment()
if (result.some(item => item.name === value)) {
callback(new Error('已经有了'))
} else {
callback()
}
} }]
总结
获取负责人数据
<el-select v-model="formData.managerId" placeholder="选择负责人" style="width:80%" size="mini">
<!--下拉选项 循环 显示负责人数据 label表示显示的字段 value表示存储字段-->
<el-option v-for="item in manageList" :key="item.id" :value="item.id" :label="item.username" />
</el-select>
created() {
// 一开始就调用,以获取信息
// 在methods里封装方法以调用接口
// 在这里调用封装好的方法
this.getManageList()
},
methods: {
close() {
// 修改父组件的值,子传父
this.$emit('update:showDialog', false)
},
// 有await必须有async
async getManageList() {
// 调用封装好的接口,用await接收返回的数据
const result = await getManageList()
// 把获取的数据赋值给data里设定的变量
this.manageList = result
}
}
先声明变量,在created中调用方法,方法中调用API。好处:以后想调用方法可以直接调用
label是显示值,value是存储值
export function getManageList() {
return request({
url: '/sys/user/simple'
})
}
记录当前部门的id,传给组件
<!-- $event 实参 表示类型 -->
<el-dropdown @command="operateDept($event,data.id)">
<!--:current-node-id="currentNodeId" 前面是属性名(自己取的),后面是变量名(data里定义好的)-->
<add-dept :current-node-id="currentNodeId" :show-dialog.sync="showDialog" @updateDepartment="getDepartment" />
</div>
operateDept(type, id) {
// type是上面绑定的command的值,不同选线绑定了不同的值
if (type === 'add') {
this.showDialog = true// 显示弹层
this.currentNodeId = id// 记录当前节点定义的id,传给弹层
}
组件接收
props: {
// 接收外部过来的showDialog,是一个promise
showDialog: {
type: Boolean,
default: false
},
currentNodeId: {
type: Number,
default: null
}
},
数据提交,确认与取消
子组件
btnOk() {
this.$refs.addDept.validate(async(isOk) => {
if (isOk) {
// formData里的前四个都有值,最后一个没有,所以把currentNodeId 的值赋给pid
// 调用接口一定要记得加await和async
await addDepartment({ ...this.formData, pid: this.currentNodeId })
// 完成await之后,通知父组件更新
this.$emit('updateDepartment')
// 提示消息
this.$message.success('新增部门成功')
// 提示消息
// 调用close方法,重置和关闭表单
this.close()
}
})
}
methods: {
close() {
// 重置表单
this.$refs.addDept.resetFields()
// 修改父组件的值,子传父
this.$emit('update:showDialog', false)
},
父组件
<!--:current-node-id="currentNodeId" 前面是属性名(自己取的),后面是变量名(data里定义好的)-->
<!--@updateDepartment="getDepartment"监听子组件的updateDepartment事件,这个事件一触发,就调用getDepartment方法,重新获取数据-->
<add-dept :current-node-id="currentNodeId" :show-dialog.sync="showDialog" @updateDepartment="getDepartment" />
</div>