deptTree.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <script setup lang="ts">
  2. import { onMounted, ref, defineEmits, watch, nextTick } from "vue";
  3. import { getSystemRoleDeptTree } from "@/api/system/role";
  4. import { type CheckboxValueType } from "element-plus";
  5. onMounted(() => {
  6. getDeptList();
  7. console.log(model.value);
  8. });
  9. const emit = defineEmits(["update:modelValue"]);
  10. const deptList = ref([]);
  11. const getDeptList = async () => {
  12. let res = await getSystemRoleDeptTree("2");
  13. deptList.value = res.depts;
  14. };
  15. const model = defineModel();
  16. watch(
  17. model,
  18. (value: number[]) => {
  19. nextTick(() => {
  20. setCheckedKeys(value, true);
  21. const allKeys = getAllKeys(deptList.value);
  22. menuNodeAll.value = value.length === allKeys.length;
  23. isIndeterminate.value = value.length > 0 && value.length < allKeys.length;
  24. });
  25. },
  26. { immediate: true, deep: true }
  27. );
  28. const menuRef = ref(null);
  29. const menuCheckStrictly = ref(true);
  30. const menuNodeAll = ref(false);
  31. const menuExpand = ref(false);
  32. const isIndeterminate = ref(false);
  33. const handleCheckedTreeExpand = (value: CheckboxValueType) => {
  34. // 递归展开
  35. for (let i = 0; i < deptList.value.length; i++) {
  36. menuRef.value.store.nodesMap[deptList.value[i].id].expanded = value;
  37. }
  38. };
  39. const handleCheckedTreeNodeAll = (value: CheckboxValueType) => {
  40. menuRef.value.setCheckedNodes(value ? deptList.value : []);
  41. isIndeterminate.value = false;
  42. const allKeys = getAllKeys(deptList.value);
  43. model.value = value ? allKeys : [];
  44. console.log(model.value);
  45. console.log(menuNodeAll.value);
  46. };
  47. const handleTreeCheck = (_: any, checkedState: any) => {
  48. const allKeys = getAllKeys(deptList.value);
  49. const checkedCount = checkedState.checkedKeys.length;
  50. menuNodeAll.value = checkedCount === allKeys.length;
  51. isIndeterminate.value = checkedCount > 0 && checkedCount < allKeys.length;
  52. model.value = checkedState.checkedKeys;
  53. emit("update:modelValue", checkedState.checkedKeys);
  54. };
  55. // 递归获取所有节点key
  56. const getAllKeys = (data: any) => {
  57. return data.reduce((keys: any, node: any) => {
  58. keys.push(node.id);
  59. if (node.children && menuCheckStrictly) {
  60. keys.push(...getAllKeys(node.children));
  61. }
  62. return keys;
  63. }, []);
  64. };
  65. const setCheckedKeys = (keys: number[], leafOnly: boolean) => {
  66. return menuRef.value.setCheckedKeys(keys, leafOnly);
  67. };
  68. </script>
  69. <template>
  70. <div style="width: 100%">
  71. <el-row type="flex" justify="space-between" align="middle">
  72. <el-col :span="4">
  73. <el-checkbox
  74. v-model="menuExpand"
  75. @change="handleCheckedTreeExpand($event)"
  76. >全部展开/折叠
  77. </el-checkbox>
  78. </el-col>
  79. <el-col :span="4">
  80. <el-checkbox
  81. v-model="menuNodeAll"
  82. :indeterminate="isIndeterminate"
  83. @change="handleCheckedTreeNodeAll($event)"
  84. >全选/全不选
  85. </el-checkbox>
  86. </el-col>
  87. <el-col :span="4">
  88. <el-checkbox v-model="menuCheckStrictly">级联下级 </el-checkbox>
  89. </el-col>
  90. </el-row>
  91. <el-tree
  92. ref="menuRef"
  93. class="tree-border"
  94. :data="deptList"
  95. show-checkbox
  96. node-key="id"
  97. empty-text="加载中,请稍后"
  98. :check-strictly="!menuCheckStrictly"
  99. @check="handleTreeCheck"
  100. />
  101. </div>
  102. </template>
  103. <style scoped lang="scss">
  104. /* tree border */
  105. .tree-border {
  106. width: 100%;
  107. margin-top: 5px;
  108. border: 1px solid #e5e6e7;
  109. background: #ffffff none;
  110. border-radius: 4px;
  111. }
  112. </style>