bowen
2023-10-10 30b3ee5c89c31cb5794faab40e800c36507d258a
提交 | 用户 | age
67d514 1 <template>
T 2   <a-tree v-bind="getAttrs" @change="handleChange">
3     <template #[item]="data" v-for="item in Object.keys($slots)">
4       <slot :name="item" v-bind="data || {}"></slot>
5     </template>
6   </a-tree>
7 </template>
8
9 <script lang="ts">
553ee9 10   import { type Recordable, type AnyFunction } from '@vben/types';
V 11   import { type PropType, computed, defineComponent, watch, ref, onMounted, unref } from 'vue';
67d514 12   import { Tree } from 'ant-design-vue';
T 13   import { isArray, isFunction } from '/@/utils/is';
14   import { get } from 'lodash-es';
15   import { propTypes } from '/@/utils/propTypes';
b3b2ca 16   import { DataNode } from 'ant-design-vue/es/tree';
746931 17
67d514 18   export default defineComponent({
T 19     name: 'ApiTree',
b78f06 20     components: { ATree: Tree },
67d514 21     props: {
553ee9 22       api: { type: Function as PropType<(arg?: Recordable<any>) => Promise<Recordable<any>>> },
67d514 23       params: { type: Object },
T 24       immediate: { type: Boolean, default: true },
25       resultField: propTypes.string.def(''),
553ee9 26       afterFetch: { type: Function as PropType<AnyFunction> },
67d514 27     },
T 28     emits: ['options-change', 'change'],
29     setup(props, { attrs, emit }) {
b3b2ca 30       const treeData = ref<DataNode[]>([]);
67d514 31       const isFirstLoaded = ref<Boolean>(false);
T 32       const loading = ref(false);
33       const getAttrs = computed(() => {
34         return {
35           ...(props.api ? { treeData: unref(treeData) } : {}),
36           ...attrs,
37         };
38       });
39
40       function handleChange(...args) {
41         emit('change', ...args);
42       }
43
44       watch(
45         () => props.params,
46         () => {
47           !unref(isFirstLoaded) && fetch();
48         },
49         { deep: true },
50       );
51
52       watch(
53         () => props.immediate,
54         (v) => {
55           v && !isFirstLoaded.value && fetch();
56         },
57       );
58
59       onMounted(() => {
60         props.immediate && fetch();
61       });
62
63       async function fetch() {
3b8643 64         const { api, afterFetch } = props;
67d514 65         if (!api || !isFunction(api)) return;
T 66         loading.value = true;
67         treeData.value = [];
68         let result;
69         try {
70           result = await api(props.params);
71         } catch (e) {
72           console.error(e);
73         }
3b8643 74         if (afterFetch && isFunction(afterFetch)) {
J 75           result = afterFetch(result);
76         }
67d514 77         loading.value = false;
T 78         if (!result) return;
79         if (!isArray(result)) {
80           result = get(result, props.resultField);
81         }
30b3ee 82         treeData.value = (result as (Recordable & { key: string | number })[]) || [];
67d514 83         isFirstLoaded.value = true;
T 84         emit('options-change', treeData.value);
85       }
86       return { getAttrs, loading, handleChange };
87     },
88   });
89 </script>