vue3封装组织架构人选组件封装

473 阅读2分钟

image.png

思路

  • 数据是个树状形结构,每一个层级有部门和人员组合,当勾选部门后,该部门都被选中,且无法点击下一级。当只选人时,那么该人员就会被选中。
  • 交互层面,选中的会被置灰,部门选中,置灰后不可进入下级。
  • 选中部门时,虽然已选区域显示的部门,但是实际上选择的还是该部门下的人,且选的是当时部门下的所有人
  • 当再次添加人员时,根据业务不同,有两种方式:
      1. 业务功能本身具有移除已选中的人。此时再次选人时,未选区域会回显出之前已经选中过的人,并且会置灰显示不可取消勾选;已选区域不会回显之前选中的人,而是每次进来只会显示当前已选的人或部门。
      1. 业务功能没有移除已选中的人。此时再次选人时,未选区域同样会回显之前已经选中过的人,但是不会置灰,可以取消勾选;已选区域会回显之前选中的人。

组件封装

主要利用两个概念理论:

  • 地址引用
  • 树状递归

第一步:接口数据格式分析:

image.png children中存储的是部门相关,stadds存储的是人员。

第二步:需求分析:

需求中需要实现勾选和半勾选、全选的状态,需要在树状数据结构中添加isChecked属性,用来标记选中状态。

代码实现

第一步:定义几个存储变量:

const membersDataObj = ref({children:[]}) // 存储所有数据
const membersDataQueryList = ref([]) // 只存储所有人员,用于搜索
const searchStaffs = ref([]) //通过搜索条件,模糊查询得出的结果
const currentMembersAndDepartments = ref({children:[],staffs:[]})
const levelDatas = ref([]) // 存储层级菜单面包屑
cosnt isCheckedItems = ref([]) // 存储已选中的对象

第二步:转换数据,加装属性isChecked,层级level

const switchOrganiseData = (obj, level) => {
  obj.level += 1;
  if (obj.staffs && obj.staffs.length > 0) {
    obj.staffs.forEach((staff) => {
      staff.isChecked = false;
    });
  }
  if (obj.children && obj.children.length > 0) {
    obj.children.forEach((child) => {
      child.isChecked = false;
      switchOrganiseData(child, obj.level);
    });
  }
};

第三步:递归获取所有成员,存储到membersDataQueryList变量数组中,用于模糊查询的数据

// 递归获取所有成员
const getStaffs = (arr, staffArr) => {
  arr.map((item) => {
    if (item.staffs && item.staffs.length > 0) {
      staffArr = staffArr.concat(item.staffs);
      if (item.children && item.children.length > 0) {
        staffArr = staffArr.concat(getStaffs(item.children, staffArr));
      }
    }
  });
  return staffArr;
};

部门下的成员,可能存在于多个部门下,需要去重,使用map函数

// 去重人员
const arrayNonRepeatfy = (staffArr) => {
  const map = new Map();
  staffArr.forEach((element) => {
    if (!map.has(element.idStaff)) {
      map.set(element.idStaff, element);
    }
  });
  return Array.from(map.values());
};