Explorar o código

新增 api tree 组件 (#1582)

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

* api-tree
ToQuery %!s(int64=3) %!d(string=hai) anos
pai
achega
67d514ad0e

+ 1 - 0
src/components/Form/index.ts

@@ -9,6 +9,7 @@ export { useForm } from './src/hooks/useForm';
 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';
 

+ 2 - 0
src/components/Form/src/componentMap.ts

@@ -24,6 +24,7 @@ import {
 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('AutoComplete', AutoComplete);
 
 componentMap.set('Select', Select);
 componentMap.set('ApiSelect', ApiSelect);
+componentMap.set('ApiTree', ApiTree);
 componentMap.set('TreeSelect', TreeSelect);
 componentMap.set('ApiTreeSelect', ApiTreeSelect);
 componentMap.set('ApiRadioGroup', ApiRadioGroup);

+ 86 - 0
src/components/Form/src/components/ApiTree.vue

@@ -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>

+ 1 - 0
src/components/Form/src/types/index.ts

@@ -91,6 +91,7 @@ export type ComponentType =
   | 'Select'
   | 'ApiSelect'
   | 'TreeSelect'
+  | 'ApiTree'
   | 'ApiTreeSelect'
   | 'ApiRadioGroup'
   | 'RadioButtonGroup'