【VUE】封装用户树形选择和部门树形选择控件

news/2024/10/18 23:25:23/

用vue实现封装用户树形选择和部门树形选择控件,采用el-tree。方便各个功能模块的使用和以后的开发。

一、封装用户树形选择控件(userTree.vue)

<template><div  style="padding: 10px;"><!-- 选择人员对话框 --><el-input placeholder="输入关键字进行过滤" v-model="filterText"></el-input><div v-loading="loading" style="padding:0px 20px;overflow-y: auto;height: 50vh;margin-top: 10px;"><el-tree class="filter-tree" :data="treeData" show-checkbox :props="defaultProps":filter-node-method="filterNode" :default-checked-keys="checkedKeys" :check-strictly="singleSelection":default-expanded-keys="checkedKeys" @check="handleCheckChange" ref="tree" node-key="id"></el-tree><!--  --></div><div slot="footer" class="dialog-footer" style="text-align: right;padding-top: 20px;"><el-button class="border_buttom" size="small" plain @click="cancel">关 闭</el-button><el-button class="press_button" size="small" @click="handleAddDept">确 定</el-button></div></div>
</template><script>javascript">
import {allListUser
} from "@/api/system/user";
import {listDept
} from "@/api/system/dept";
export default {name: "userTree",props: {//选中数据回显checkedKeys: {type: Array,default: () => {return [];}},//是否开启单选singleSelection: {type: Boolean,default: () => {return false;}},},data() {return {loading:true,//是否已勾选判断checkIf:false,services: [],//选人弹窗open: false,//选人过滤filterText: '',//树控件数据treeData: null,defaultProps: {children: 'children',label: 'label'},selectedMumberList: [],}},inject: ["selectUser", "closeUserTree"],watch: {filterText(val) {this.$refs.tree.filter(val);}},created() {this.getUserTree();},methods: {cancel() {this.closeUserTree()this.$refs.tree.setCheckedKeys([]);},filterNode(value, data) {if (!value) return true;return data.label.indexOf(value) !== -1;},handleCheckChange(node, list) {if (this.singleSelection) {if (node.uid != null) {this.checkIf=truethis.selectedMumberList = [];//选中事件在选中后执行,当lis中有两个选中时,使用setCheckedKeys方法,选中一个节点if (list.checkedKeys.length == 2) {this.$refs.tree.setCheckedKeys([node.id]);}this.selectedMumberList.push({uid: node.id,label: node.label,phonenumber:node.phonenumber})} else {this.$message({message: '请选择用户数据',type: 'warning'});}} else {// 获取选中的子节点列表this.checkIf=truethis.selectedMumberList = this.$refs.tree.getCheckedNodes(true, false);this.selectedMumberList = this.selectedMumberList.filter(obj => {return obj.uid != null})}},/** 确定选择人员 */handleAddUser() {let arr = []let userIds = []let phonenumbers = []let form = {userNames: null,userIds: null,phonenumbers:null,}if(this.checkIf){this.selectedMumberList.forEach((obj) => {arr.push(obj.label);userIds.push(obj.uid.replace('u_', ''));phonenumbers.push(obj.phonenumber)})form.userNames = arr.toString()form.userIds = userIds.toString()form.phonenumbers = phonenumbers.toString()this.checkIf=falsethis.selectUser(form)this.$refs.tree.setCheckedKeys([])}else{this.checkIf=falsethis.closeUserTree()}},/** 构建树形数据结构 */getUserTree() {this.loading=true//获取所有部门的数据接口listDept().then(res => {let deptTree = res.data//获取所有用户数据allListUser().then((res) => {this.userList = []for (let i in res.rows) {const obj = {pid: null,id: null,uid: null,label: null,phonenumber:null,}if (res.rows[i].deptId == null || res.rows[i].deptId == "") {obj.pid = -1} else {obj.pid = res.rows[i].deptId}//加‘u_’是为了区分部门id和用户idobj.id = "u_" + res.rows[i].userIdobj.uid = "u_" + res.rows[i].userIdobj.label = res.rows[i].userName//可以按需求补充其他字段,如一下为补充电话号码obj.phonenumber= res.rows[i].phonenumber||'-'this.userList.push(obj)}this.mapTree(deptTree)this.treeData = deptTreethis.loading=false});})},mapTree(data) {data.forEach(ditem => { //遍历树 拼入相应的userif (this.singleSelection && !ditem.uid) {ditem['disabled'] = true}this.userList.forEach(uitem => {if (ditem.id == uitem.pid && ditem.uid == null) {if (!ditem.children) {ditem.children = []}ditem.children.push(uitem)}})if (ditem.children) {this.mapTree(ditem.children)}})},}};
</script><style>
</style>

二、封装部门选择控件(deptTree.vue)

<template><div style="padding: 10px;"><!-- 选择部门对话框 --><el-input placeholder="输入关键字进行过滤" v-model="filterText"> </el-input><div  v-loading="loading"  style="padding:0px 20px;overflow-y: auto;height: 50vh;margin-top: 10px;"><el-tree class="filter-tree" :data="treeData" show-checkbox :props="defaultProps":filter-node-method="filterNode" :default-checked-keys="checkedDeptKeys"  default-expand-all:check-strictly="singleSelection" :default-expanded-keys="checkedDeptKeys" @check="handleCheckChange"ref="tree" node-key="id"></el-tree></div><div slot="footer" class="dialog-footer" style="text-align: right;padding-top: 20px;"><el-button class="border_buttom" size="small"  plain @click="cancel">关 闭</el-button><el-button class="press_button" size="small" @click="handleAddDept">确 定</el-button></div></div>
</template><script>javascript">
import {listDept
} from "@/api/system/dept";
export default {name: "deptTree",props: {//选中回显checkedDeptKeys: {type: Array,default: () => {return [];}},//是否单选singleSelection: {type: Boolean,default: () => {return false;}},},data() {return {loading:true,services: [],//选人弹窗open: false,//选人过滤filterText: '',//树控件数据treeData: null,defaultProps: {children: 'children',label: 'label'},selectedMumberList: [],//是否有选择checkIf:false,}},inject: ["selectDept", "closeDeptTree"],watch: {filterText(val) {this.$refs.tree.filter(val);}},created() {this.getDeptTree();},methods: {cancel() {this.closeDeptTree()this.$refs.tree.setCheckedKeys([]);},filterNode(value, data) {if (!value) return true;return data.label.indexOf(value) !== -1;},handleCheckChange(node, list) {if (this.singleSelection) {this.checkIf=truethis.selectedMumberList = [];//node 该节点所对应的对象、list 树目前的选中状态对象//选中事件在选中后执行,当lis中有两个选中时,使用setCheckedKeys方法,选中一个节点if (list.checkedKeys.length == 2) {//单选实现this.$refs.tree.setCheckedKeys([node.id]);}this.selectedMumberList.push({id: node.id,label: node.label})} else {this.checkIf=true// 获取选中的子节点列表this.selectedMumberList = this.$refs.tree.getCheckedNodes(true, false);}},/** 选择部门 */handleAddDept() {let arr = []let deptIds = []this.selectedMumberList.forEach((obj) => {arr.push(obj.label);deptIds.push(obj.id);})let form = {deptNames: null,deptIds: null}if(this.checkIf){form.deptNames = arr.toString()form.deptIds = deptIds.toString()this.checkIf=falsethis.selectDept(form)this.$refs.tree.setCheckedKeys([]);}else{this.checkIf=falsethis.closeDeptTree()}},/** 构建树形数据结构 */getDeptTree() {this.loading=truelistDept().then(res => {this.treeData = res.datathis.loading=false})},}};
</script><style>
</style>

三、控件使用

<template><div><div><el-form ref="form" :model="form" :rules="rules" label-width="90px"><el-row :gutter="24"><el-col :span="12"><el-form-item label="用户1" prop="u1"><el-input v-model="form.u1Name" readonly @click.native="handleUser(1)" placeholder="请选择用户1"><template slot="append"><span class="inco"><i class="el-icon-user"></i></span></template></el-input></el-form-item></el-col><el-col :span="12"><el-form-item label="部门1" prop="d1Name"><el-input v-model="form.d1Name" readonly @click.native="handleDept(1)" placeholder="请输入部门1"><template slot="append"><span class="inco"><i class="el-icon-user"></i></span></template></el-input></el-form-item></el-col></el-row><el-row :gutter="24"><el-col :span="12"><el-form-item label="用户2" prop="u2"><el-input v-model="form.u2Name" readonly @click.native="handleUser(2)" placeholder="请选择用户2"><template slot="append"><span class="inco"><i class="el-icon-user"></i></span></template></el-input></el-form-item></el-col></el-row><el-row :gutter="24"><el-col :span="24"><el-form-item label="用户3" prop="u3"><el-input v-model="form.u3Name" readonly @click.native="handleUser(3)" type="text"placeholder="请选择用户3"><template slot="append"><span class="inco"><i class="el-icon-user"></i></span></template></el-input></el-form-item></el-col></el-row><el-row :gutter="24"><el-col :span="24"><el-form-item label="用户4" prop="u4"><el-input v-model="form.u4Name" readonly @click.native="handleUser(4)" placeholder="请选择用户4"><template slot="append"><span class="inco"><i class="el-icon-user"></i></span></template></el-input></el-form-item></el-col></el-row></el-form></div><el-dialog title="选择人员" :visible.sync="openUserTree" width="500px" append-to-body><userTree v-if="openUserTree" :singleSelection="singleSelection" :checkedKeys="checkedKeys"></userTree></el-dialog><el-dialog title="选择部门" :visible.sync="openDeptTree" width="500px" append-to-body><deptTree :singleSelection="true" :checkedDeptKeys="checkedDeptKeys"></deptTree></el-dialog></div>
</template><script>javascript">//引用用户选择和部门选择树形控件import userTree from "/src/components/deptUserTree/userTree.vue"import deptTree from "/src/components/deptUserTree/deptTree.vue"export default {name: "myPage",components: {userTree,deptTree,},data() {return {//用户tree打开openUserTree: false,//部门tree打开openDeptTree: false,//用户tree数据回显checkedKeys: [],//部门tree数据回显checkedDeptKeys: [],// 表单参数form: {},//选人控件是否单选singleSelection: false,};},created() {},//父子组件方法触发的关键provide() {return {selectUser: this.selectUser,closeUserTree: this.closeUserTree,selectDept: this.selectDept,closeDeptTree: this.closeDeptTree,};},methods: {//点击选人输入框,通过i区分不同的字段的处理handleUser(i) {this.userFlag = ithis.checkedKeys = []this.singleSelection = falseif (this.userFlag == 1) {this.singleSelection = trueif (this.form.u1Name != null) {this.checkedKeys = this.form.u1.split(',')}} else if (this.userFlag == 2) {this.singleSelection = trueif (this.form.u2Name != null) {this.checkedKeys = this.form.u2.split(',')}} else if (this.userFlag == 3) {if (this.form.u3Name != null) {this.checkedKeys = this.form.u3.split(',')}} else if (this.userFlag == 4) {if (this.form.u4Name != null) {this.checkedKeys = this.form.u4.split(',')}}//处理数据回显赋值if (this.checkedKeys != []) {this.checkedKeys.forEach((item, index) => {this.checkedKeys[index] = "u_" + this.checkedKeys[index]})}this.openUserTree = true},//选人确定赋值selectUser(e) {if (this.userFlag == 1) {this.form.u1 = e.userIdsthis.form.u1Name = e.userNames} else if (this.userFlag == 2) {this.form.u2 = e.userIdsthis.form.u2Name = e.userNames//赋值联系方式this.form.u2Way = e.phonenumbers} else if (this.userFlag == 3) {this.form.u3 = e.userIdsthis.form.u3Name = e.userNames} else if (this.userFlag == 4) {this.form.u4 = e.userIdsthis.form.u4Name = e.userNames}this.openUserTree = false},//关闭组件closeUserTree() {this.openUserTree = false},//点击选部门输入框handleDept(i) {this.deptFlag = ithis.checkedDeptKeys = []if (this.deptFlag == 1) {if (this.form.d1Name != null) {//处理部门回显选中的到控件里this.checkedDeptKeys = this.form.d1.split(',')}}this.openDeptTree = true},//选择部门selectDept(e) {if (this.deptFlag == 1) {this.form.d1 = e.deptIdsthis.form.d1Name = e.deptNames}this.openDeptTree = false},//关闭部门选择组件closeDeptTree() {this.openDeptTree = false},// 表单重置reset() {this.form = {u1: null,u1Name: null,u2: null,u2Name: null,u3: null,u3Name: null,u4: null,u4Name: null,d1: null,d1Name: null,};this.resetForm("form");},}};
</script><style scoped lang="scss"></style>

三、代码分析

自己看代码的注释吧,重点主要是
1、数据结构的构建,获取用户数据和部门数据接口时按照自己的相关字段调整,还有一些数据权限问题按自己需求规避。
2、父子组件方法的调用,因为会存在各种前端标签包裹问题,目前代码只是简单样例,因此采用了provide()来处理。
3、其他应该没有技术难点。


http://www.ppmy.cn/news/1540117.html

相关文章

中科星图(GVE)——使用随机森林方法进行土地分类

目录 简介 函数 gve.Classifier.smileRandomForest(numberOfTrees,variablesPerSplit,minLeafPopulation,bagFraction,maxNodes,seed) 代码 结果 简介 使用随机森林方法进行土地分类的步骤如下&#xff1a; 数据准备&#xff1a;收集所需的土地分类数据&#xff0c;并对数…

如何分离人声和背景音乐?精准音频分离,提升你的作品质量

在音频编辑和处理的领域中&#xff0c;分离人声和背景音乐是一项颇具挑战的任务&#xff0c;但也是众多音频爱好者和专业人士经常面临的需求。无论是为了制作卡拉OK伴奏、提升视频制作质量&#xff0c;还是进行音乐分析和研究&#xff0c;掌握人声与背景音乐的分离技术都显得至…

大数据治理

在大数据时代&#xff0c;数据治理已成为确保数据质量、安全性和可用性的关键。然而&#xff0c;许多组织在实施大数据治理时往往忽视了一些高效但不太为人所知的策略。本文将揭示5个可能被忽视但极具价值的大数据治理技巧&#xff0c;帮助你更好地管理和利用数据资产。 1. 利…

LeetCode 1884.鸡蛋掉落-两枚鸡蛋:动态规划

【LetMeFly】1884.鸡蛋掉落-两枚鸡蛋&#xff1a;动态规划 力扣题目链接&#xff1a;https://leetcode.cn/problems/egg-drop-with-2-eggs-and-n-floors/ 给你 2 枚相同 的鸡蛋&#xff0c;和一栋从第 1 层到第 n 层共有 n 层楼的建筑。 已知存在楼层 f &#xff0c;满足 0 …

FFMPEG录屏(18)--- 枚举Windows下的窗口列表并获取进程图标、标题、缩略图等

在Windows中获取可进行屏幕共享捕获的窗口列表及其图标、缩略图 在Windows系统中&#xff0c;获取可进行屏幕共享捕获的窗口列表以及它们的图标和缩略图是一个复杂但有趣的过程。本文将详细介绍如何实现这一功能&#xff0c;涉及到的主要技术包括Windows API、C编程和一些第三…

如何正确并优雅的使用Java中的临时文件目录

场景需求 在一些需要进行文件数据处理的开发场景中&#xff0c;我们可能会想到将文件存储在一个临时的目录中&#xff0c;当数据处理完成后&#xff0c;把临时文件删除即可。 下面就为大家介绍如何正确并优雅的使用Java中的临时文件目录 正文内容 其实在 Java SDK 中已经提…

Vue 上传图片前 裁剪图片

一. 使用的技术 vue-cropper 文档&#xff1a;vue-cropper | A simple picture clipping plugin for vue 二. 安装 npm install vue-cropper 或 yarn add vue-cropper 三. 引入 在使用页面中引用 import { VueCropper } from vue-cropper; 四. 使用 配置项&#xff1…

Linux云计算 |【第四阶段】RDBMS2-DAY5

主要内容&#xff1a; PXC概述、部署PXC&#xff08;自动故障恢复测试&#xff09;、存储引擎、读锁/写锁、表锁/行锁、常用的存储引擎介绍 一、PXC概述 PXC&#xff08;Percona XtraDB Cluster&#xff0c;简称PXC集群&#xff09;&#xff0c;是基于Galera的MySQL高可用集群…