<template><div class="department-container"><div class="app-container"><el-card><!-- 用一个行列布局 --><el-row type="flex" justify="space-between" align="middle" style="height: 40px"><el-col :span="20"><span>江苏传智播客教育科技股份有限公司</span></el-col><el-col :span="4"><el-row type="flex" justify="end"><!-- 两个内容 --><el-col>负责人</el-col><el-col>操作</el-col></el-row></el-col></el-row></el-card></div></div></template>
结构树
页面内需要用到一个新的组件<el-tree>结构树
:data="结构数组"data绑定结构数组:props=""重新定义结构数组里面的key:default-expand-all="true"展开所有子节点 ```vue
<a name="PWc1R"></a>#### 自定义结构> 自定义结构 模板 -> 插槽 ->data是当前行的数据( 一个对象 )```vue<template #default="{ data }"><el-rowtype="flex"justify="space-between"align="middle"style="height: 40px; width: 100%;"><el-col :span="20"><span>{{ data.name }}</span></el-col><el-col :span="4"><el-row type="flex" justify="end"><!-- 两个内容 --><el-col>{{ data.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>
import request from '@/utils/request'export const getDepartmentsApi = () => {return request({url: '/company/department'})}
<script>function totree(arr) {const newArr = []const map = {}arr.forEach(item => {if (!item.children) item.children = []map[item.id] = item // 添加对应的映射关系})arr.forEach(item => {if (map[item.pid]) {map[item.pid].children.push(item)} else {newArr.push(item)}})// 处理之后的tree数组return newArr}import { getDepartmentsApi } from '@/api/departments'export default {data() {return {list: [],defaultProps: {label: 'name'}}},mounted () {this.getDepartments()},methods: {async getDepartments() {const { data } = await getDepartmentsApi()// console.log(data)this.list = totree(data.depts)}}}</script>
数据处理 -> 平铺转树形
核心逻辑:平铺转树形 寻找父节点的过程 这里就是通过pid去匹配id的过程 实施流程:
- 遍历数组,以数组中的每一项的id作为key 每一项本身作为value形成一个对象map (方便查找)- 遍历数组 通过pid去匹配id 如果匹配上了 就把当前项目添加道匹配项的children属性中,如果没有发生匹配则代表当前项目本身就是最外层的节点 它没有父节点 直接把它push到treeList中匹配: === 这里使用的是一个小技巧 对象取值 如果取到了就是匹配上了
// 数据处理 => 结构树transTree(arr) {// 传入数组const map = {}const treeList = []arr.forEach(item => {// map空对象 添加键值对 key为item.id 值为itemmap[item.id] = item// 给每一项都加上一个children 空数组map[item.id].children = []})arr.forEach(item => {// 取数组的pid 与map的每一项对比 返回true说明对比成功(item.pid === map.id)// 给匹配当的这一项的 children数组下面 添加 作为子级列表数据if (map[item.pid]) {map[item.pid].children.push(item)} else {// 返回false 没有pid 说明是第一层的数据不需要匹配treeList.push(item)}})return treeList},
操作功能
添加子部门
流程:
- 实现一个弹框打开关闭的交互效果
- 实现的是一个表单 校验 单个校验 + 兜底校验
- 收集表单数据 确定提交接口
- 提交成功之后的后续逻辑 提示用户 更新列表 重置数据 重置校验痕迹
点击添加子部门 打开弹层
native修饰符:某个组件的根元素上绑定原生js事件需要 不加默认是自定义事件
<template><div class="department-container">native修饰符:某个组件的根元素上绑定原生js事件需要 不加默认是自定义事件<el-dropdown-item @click.native="addDepaart">添加子部门</el-dropdown-item><!-- 弹层 --><el-dialogtitle="提示":visible="showDialog"width="30%"@close="closeDialog"><span>内容</span><span slot="footer"><el-button @click="showDialog = false">取消</el-button><el-button type="primary">确定</el-button></span></el-dialog></div></template><script>export default {data() {return {showDialog: false}},methods: {// 新增部门addDepaart () {this.showDialog = true},// 关闭弹层closeDialog () {this.showDialog = false}}}</script><style lang="scss" scoped></style>
// 下拉框数据export function getEmployeeSimpleApi() {return request({url: '/sys/user/simple'})}
@open事件的时候获取下拉框列表数据
<template><div class="department-container"><!-- 弹层 --><el-dialogtitle="提示":visible="showDialog"width="30%"@close="closeDialog"@open="getEmployeeSimple"><span><el-form label-width="120px" :model="form" :rules="rules"><el-form-item label="部门名称" prop="name"><el-input v-model="form.name" style="width:80%" placeholder="1-50个字符" /></el-form-item><el-form-item label="部门编码" prop="code"><el-input v-model="form.code" style="width:80%" placeholder="1-50个字符" /></el-form-item><el-form-item label="部门负责人" prop="manager"><el-select v-model="form.manager" style="width:80%" placeholder="请选择"><el-option v-for="item in managerList" :key="item.id" :label="item.username" :value="item.id" /></el-select></el-form-item><el-form-item label="部门介绍" prop="introduce"><el-input v-model="form.introduce" style="width:80%" placeholder="1-300个字符" type="textarea" /></el-form-item></el-form></span><span slot="footer"><el-button @click="showDialog = false">取消</el-button><el-button type="primary">确定</el-button></span></el-dialog></div></template><script>import { getDepartmentsApi, getEmployeeSimpleApi } from '@/api/departments'export default {data() {return {// 弹层显隐showDialog: false,// 表单数据form: {name: '',code: '',manager: '',introduce: ''},// 校验规则rules: {name: [{ required: true, message: '部门名称不能为空', trigger: ['blur', 'change'] },{ min: 1, max: 50, message: '部门名称要求1-50个字符', trigger: ['blur', 'change'] }],code: [{ required: true, message: '部门编码不能为空', trigger: ['blur', 'change'] },{ min: 1, max: 50, message: '部门编码要求1-50个字符', trigger: ['blur', 'change'] }],manager: [{ required: true, message: '部门负责人不能为空', trigger: ['blur', 'change'] }],introduce: [{ required: true, message: '部门介绍不能为空', trigger: ['blur', 'change'] },{ min: 1, max: 300, message: '部门介绍要求1-300个字符', trigger: ['blur', 'change'] }]},// 下拉框数据managerList: []}},mounted () {this.getDepartments()},methods: {// 下拉框数据async getEmployeeSimple() {const { data } = await getEmployeeSimpleApi()console.log(data)this.managerList = data},// 获取组织架构async getDepartments() {const { data } = await getDepartmentsApi()// console.log(data)this.list = totree(data.depts)},// 新增部门addDepaart () {this.showDialog = true},// 关闭弹层closeDialog () {this.showDialog = false}}}</script><style lang="scss" scoped></style>
收集数据处理
接口需要pid 表单无法提供,data代表的是当前行的数据,在点击操作时获取到当前行的 pid
<template>绑定事件(传参 id)<el-dropdown-item @click.native="addDepaart(data.id)">添加子部门</el-dropdown-item></template><script>export default {data() {return {// 当前行idcurrId: null}},methods: {// 新增部门addDepaart (id) {this.currId = idthis.showDialog = true}}}</script><style lang="scss" scoped></style>
clickSubmit () {this.$refs.formRef.validate(async (value) => {if (value) {await addDepartApi({ ...this.form, pid: this.currId })// 关闭弹层this.showDialog = false// 重新获取列表this.getDepartments()// 提示成功this.$message.success('添加部门成功')// 清空表单&校验规则this.resetFields()}})},
// 关闭弹层closeDialog () {this.showDialog = false// 清空表单this.form = {name: '',code: '',manager: '',introduce: ''}// 清空校验规则this.$refs.formRef.resetFields()}
编辑功能
流程:
- 1.打开弹层(复用新增时的弹框)
- 获取数据完成回填(回填完毕之后 多一个id值)
- 3.进行具体的表单编辑调用更新接口(根据是否有di作为是否变的判断依据)
/*** 获取当前数据* @param {*} id 部门id* @returns*/export const editDepartApi = (id) => request.get(`/company/department/${id}`)/**** @param {*} data 修改的数据* @returns*/export function updateDepartments(data) {return request({url: `/company/department/${data.id}`,method: 'put',data})}
数据回填
点编辑时传入 部门id 根据id获取当前点击的这一行的数据进行回填
// 编辑async editDepart(id) {this.showDialog = true// 获取数据const { data } = await editDepartApi(id)// 数据回填this.form = data},
修改数据
与提交公用一个弹层 用form里面是否获取到id来进行判断时提交还是修改
clickSubmit () {this.$refs.formRef.validate(async (value) => {if (value) {if (this.form.id) {await updateDepartments(this.form)} else {await addDepartApi({ ...this.form, pid: this.currId })}this.showDialog = false// 重新获取列表this.getDepartments()// 提示成功this.$message.success(`${this.form.id ? '更新' : '新增'} 部门成功 `)}})
删除部门
/*** 删除部门* @param {*} id 部门id* @returns*/export const delDepartApi = (id) => request.delete(`/company/department/${id}`)
delDepaart(id) {this.currId = id// 确定是否删除this.$confirm('确定删除吗?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消' }).then(() => {}).then(async() => {// 点击确定执行的代码try {await delDepartApi(id)// 提示删除成功this.$message.success('删除部门成功')// 重新获取列表this.getDepartments()} catch (error) {this.$message.error(error)}}).catch(() => {// 点击取消执行的代码})},
