OrganizationIdTree.vue 3.58 KB
<template>
  <div
    ref="tree"
    class="organization-tree flex relative items-center py-4"
    :class="foldFlag ? '' : 'pl-4'"
  >
    <div
      class="cursor-pointer flex py-4 fold-icon absolute rounded svg:fill-gray-400 hover:bg-gray-200"
      :class="foldFlag ? '' : '-right-4'"
      @click="handleFold"
    >
      <div>
        <CaretRightOutlined
          :class="[foldFlag ? '' : 'rotate-180']"
          class="transform fill-gray-100"
        />
      </div>
    </div>
    <div :style="{ width: foldFlag ? '0px' : '100%' }" class="bg-white mr-0 overflow-hidden h-full">
      <BasicTree v-bind="getBindData" />
    </div>
  </div>
</template>
<script lang="ts" setup name="OrganizationIdTree">
  import { computed, onMounted, ref, unref, useAttrs } from 'vue';
  import { BasicTree, TreeItem } from '/@/components/Tree';
  import { getOrganizationList } from '/@/api/system/system';
  import { CaretRightOutlined } from '@ant-design/icons-vue';
  import { getBoundingClientRect } from '/@/utils/domUtils';
  import { BasicTreePropsType, OrganizationTreeActionType } from './types';
  import { OrganizationTreePropsType } from './props';

  const props = defineProps<OrganizationTreePropsType>();

  const attrs = useAttrs();

  const tree = ref<Nullable<HTMLDivElement>>();
  const emit = defineEmits(['select', 'register']);
  const treeData = ref<TreeItem[]>([]);
  const selectedKeys = ref<string[]>();
  const treeExpandData = ref<string[]>([]);

  const innerProps = ref<OrganizationTreePropsType>({});

  //获取所有父级id
  function findForAllId(data: Recordable[] = [], arr: string[] = []) {
    for (const item of data) {
      arr.push(item.id);
    }
    return arr;
  }

  function handleSelect(keys: string[]) {
    selectedKeys.value = keys;
    emit('select', keys[0]);
  }
  function resetOrganization() {
    selectedKeys.value = [];
  }

  const foldFlag = ref(true);
  const handleFold = () => {
    foldFlag.value = !unref(foldFlag);
  };

  const setTreeHeight = () => {
    const rect = getBoundingClientRect(unref(tree)!);
    if (rect) {
      const { y } = rect as DOMRect;
      const clientHight = document.documentElement.clientHeight;
      const maxHeight = clientHight - y;
      if (unref(tree)) unref(tree)!.style.height = `${maxHeight}px`;
    }
  };

  onMounted(async () => {
    treeData.value = (await getOrganizationList()) as unknown as TreeItem[];
    const getAllIds = findForAllId(treeData.value as any, []);
    //设置要展开的id
    treeExpandData.value = getAllIds;

    setTreeHeight();
  });

  defineExpose({
    resetOrganization,
  });

  const getProps = computed<OrganizationTreePropsType>(() => ({ ...props, ...unref(innerProps) }));

  const getBindData = computed(() => {
    return {
      title: '组织列表',
      toolbar: true,
      search: true,
      clickRowToExpand: false,
      treeData: unref(treeData),
      expandedKeys: unref(treeExpandData),
      replaceFields: { key: 'id', title: 'name' },
      selectedKeys: unref(selectedKeys),
      ...attrs,
      ...unref(getProps),
      onSelect: (keys: string[]) => {
        handleSelect(keys);
      },
    } as BasicTreePropsType;
  });

  const setProps = (props: Partial<OrganizationTreePropsType>) => {
    innerProps.value = { ...(props || {}) };
  };

  emit('register', {
    clearSelected: resetOrganization,
    getSelectKey: () => unref(selectedKeys)?.[0],
    setProps,
  } as OrganizationTreeActionType);
</script>

<style scoped lang="less">
  .organization-tree {
    max-height: 100vh;

    .expand {
      opacity: 0;
    }

    &:hover {
      .expand {
        opacity: 1;
      }
    }
  }
</style>