ToQuery
2022-01-18 67d514ad0e27083328c853e010a8eee9ed7f0408
新增 api tree 组件 (#1582)

* tsconfig 增加 types , 解决webstorm提示错误

* api-tree
1个文件已添加
3个文件已修改
90 ■■■■■ 已修改文件
src/components/Form/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/componentMap.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/components/ApiTree.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/types/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/index.ts
@@ -9,6 +9,7 @@
export { default as ApiSelect } from './src/components/ApiSelect.vue';
export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue';
export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue';
export { default as ApiTree } from './src/components/ApiTree.vue';
export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue';
export { default as ApiCascader } from './src/components/ApiCascader.vue';
src/components/Form/src/componentMap.ts
@@ -24,6 +24,7 @@
import ApiRadioGroup from './components/ApiRadioGroup.vue';
import RadioButtonGroup from './components/RadioButtonGroup.vue';
import ApiSelect from './components/ApiSelect.vue';
import ApiTree from './components/ApiTree.vue';
import ApiTreeSelect from './components/ApiTreeSelect.vue';
import ApiCascader from './components/ApiCascader.vue';
import { BasicUpload } from '/@/components/Upload';
@@ -43,6 +44,7 @@
componentMap.set('Select', Select);
componentMap.set('ApiSelect', ApiSelect);
componentMap.set('ApiTree', ApiTree);
componentMap.set('TreeSelect', TreeSelect);
componentMap.set('ApiTreeSelect', ApiTreeSelect);
componentMap.set('ApiRadioGroup', ApiRadioGroup);
src/components/Form/src/components/ApiTree.vue
New file
@@ -0,0 +1,86 @@
<template>
  <a-tree v-bind="getAttrs" @change="handleChange">
    <template #[item]="data" v-for="item in Object.keys($slots)">
      <slot :name="item" v-bind="data || {}"></slot>
    </template>
    <template #suffixIcon v-if="loading">
      <LoadingOutlined spin />
    </template>
  </a-tree>
</template>
<script lang="ts">
  import { computed, defineComponent, watch, ref, onMounted, unref } from 'vue';
  import { Tree } from 'ant-design-vue';
  import { isArray, isFunction } from '/@/utils/is';
  import { get } from 'lodash-es';
  import { propTypes } from '/@/utils/propTypes';
  import { LoadingOutlined } from '@ant-design/icons-vue';
  export default defineComponent({
    name: 'ApiTree',
    components: { ATree: Tree, LoadingOutlined },
    props: {
      api: { type: Function as PropType<(arg?: Recordable) => Promise<Recordable>> },
      params: { type: Object },
      immediate: { type: Boolean, default: true },
      resultField: propTypes.string.def(''),
    },
    emits: ['options-change', 'change'],
    setup(props, { attrs, emit }) {
      const treeData = ref<Recordable[]>([]);
      const isFirstLoaded = ref<Boolean>(false);
      const loading = ref(false);
      const getAttrs = computed(() => {
        return {
          ...(props.api ? { treeData: unref(treeData) } : {}),
          ...attrs,
        };
      });
      function handleChange(...args) {
        emit('change', ...args);
      }
      watch(
        () => props.params,
        () => {
          !unref(isFirstLoaded) && fetch();
        },
        { deep: true },
      );
      watch(
        () => props.immediate,
        (v) => {
          v && !isFirstLoaded.value && fetch();
        },
      );
      onMounted(() => {
        props.immediate && fetch();
      });
      async function fetch() {
        const { api } = props;
        if (!api || !isFunction(api)) return;
        loading.value = true;
        treeData.value = [];
        let result;
        try {
          result = await api(props.params);
        } catch (e) {
          console.error(e);
        }
        loading.value = false;
        if (!result) return;
        if (!isArray(result)) {
          result = get(result, props.resultField);
        }
        treeData.value = (result as Recordable[]) || [];
        isFirstLoaded.value = true;
        emit('options-change', treeData.value);
      }
      return { getAttrs, loading, handleChange };
    },
  });
</script>
src/components/Form/src/types/index.ts
@@ -91,6 +91,7 @@
  | 'Select'
  | 'ApiSelect'
  | 'TreeSelect'
  | 'ApiTree'
  | 'ApiTreeSelect'
  | 'ApiRadioGroup'
  | 'RadioButtonGroup'