Commit 67d514ad0e27083328c853e010a8eee9ed7f0408
Committed by
GitHub
1 parent
929141be
新增 api tree 组件 (#1582)
* tsconfig 增加 types , 解决webstorm提示错误 * api-tree
Showing
4 changed files
with
90 additions
and
0 deletions
src/components/Form/index.ts
@@ -9,6 +9,7 @@ export { useForm } from './src/hooks/useForm'; | @@ -9,6 +9,7 @@ export { useForm } from './src/hooks/useForm'; | ||
9 | export { default as ApiSelect } from './src/components/ApiSelect.vue'; | 9 | export { default as ApiSelect } from './src/components/ApiSelect.vue'; |
10 | export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; | 10 | export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; |
11 | export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; | 11 | export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; |
12 | +export { default as ApiTree } from './src/components/ApiTree.vue'; | ||
12 | export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; | 13 | export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; |
13 | export { default as ApiCascader } from './src/components/ApiCascader.vue'; | 14 | export { default as ApiCascader } from './src/components/ApiCascader.vue'; |
14 | 15 |
src/components/Form/src/componentMap.ts
@@ -24,6 +24,7 @@ import { | @@ -24,6 +24,7 @@ import { | ||
24 | import ApiRadioGroup from './components/ApiRadioGroup.vue'; | 24 | import ApiRadioGroup from './components/ApiRadioGroup.vue'; |
25 | import RadioButtonGroup from './components/RadioButtonGroup.vue'; | 25 | import RadioButtonGroup from './components/RadioButtonGroup.vue'; |
26 | import ApiSelect from './components/ApiSelect.vue'; | 26 | import ApiSelect from './components/ApiSelect.vue'; |
27 | +import ApiTree from './components/ApiTree.vue'; | ||
27 | import ApiTreeSelect from './components/ApiTreeSelect.vue'; | 28 | import ApiTreeSelect from './components/ApiTreeSelect.vue'; |
28 | import ApiCascader from './components/ApiCascader.vue'; | 29 | import ApiCascader from './components/ApiCascader.vue'; |
29 | import { BasicUpload } from '/@/components/Upload'; | 30 | import { BasicUpload } from '/@/components/Upload'; |
@@ -43,6 +44,7 @@ componentMap.set('AutoComplete', AutoComplete); | @@ -43,6 +44,7 @@ componentMap.set('AutoComplete', AutoComplete); | ||
43 | 44 | ||
44 | componentMap.set('Select', Select); | 45 | componentMap.set('Select', Select); |
45 | componentMap.set('ApiSelect', ApiSelect); | 46 | componentMap.set('ApiSelect', ApiSelect); |
47 | +componentMap.set('ApiTree', ApiTree); | ||
46 | componentMap.set('TreeSelect', TreeSelect); | 48 | componentMap.set('TreeSelect', TreeSelect); |
47 | componentMap.set('ApiTreeSelect', ApiTreeSelect); | 49 | componentMap.set('ApiTreeSelect', ApiTreeSelect); |
48 | componentMap.set('ApiRadioGroup', ApiRadioGroup); | 50 | componentMap.set('ApiRadioGroup', ApiRadioGroup); |
src/components/Form/src/components/ApiTree.vue
0 → 100644
1 | +<template> | ||
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 | + <template #suffixIcon v-if="loading"> | ||
7 | + <LoadingOutlined spin /> | ||
8 | + </template> | ||
9 | + </a-tree> | ||
10 | +</template> | ||
11 | + | ||
12 | +<script lang="ts"> | ||
13 | + import { computed, defineComponent, watch, ref, onMounted, unref } from 'vue'; | ||
14 | + import { Tree } from 'ant-design-vue'; | ||
15 | + import { isArray, isFunction } from '/@/utils/is'; | ||
16 | + import { get } from 'lodash-es'; | ||
17 | + import { propTypes } from '/@/utils/propTypes'; | ||
18 | + import { LoadingOutlined } from '@ant-design/icons-vue'; | ||
19 | + export default defineComponent({ | ||
20 | + name: 'ApiTree', | ||
21 | + components: { ATree: Tree, LoadingOutlined }, | ||
22 | + props: { | ||
23 | + api: { type: Function as PropType<(arg?: Recordable) => Promise<Recordable>> }, | ||
24 | + params: { type: Object }, | ||
25 | + immediate: { type: Boolean, default: true }, | ||
26 | + resultField: propTypes.string.def(''), | ||
27 | + }, | ||
28 | + emits: ['options-change', 'change'], | ||
29 | + setup(props, { attrs, emit }) { | ||
30 | + const treeData = ref<Recordable[]>([]); | ||
31 | + const isFirstLoaded = ref<Boolean>(false); | ||
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() { | ||
64 | + const { api } = props; | ||
65 | + if (!api || !isFunction(api)) return; | ||
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 | + } | ||
74 | + loading.value = false; | ||
75 | + if (!result) return; | ||
76 | + if (!isArray(result)) { | ||
77 | + result = get(result, props.resultField); | ||
78 | + } | ||
79 | + treeData.value = (result as Recordable[]) || []; | ||
80 | + isFirstLoaded.value = true; | ||
81 | + emit('options-change', treeData.value); | ||
82 | + } | ||
83 | + return { getAttrs, loading, handleChange }; | ||
84 | + }, | ||
85 | + }); | ||
86 | +</script> |
src/components/Form/src/types/index.ts
@@ -91,6 +91,7 @@ export type ComponentType = | @@ -91,6 +91,7 @@ export type ComponentType = | ||
91 | | 'Select' | 91 | | 'Select' |
92 | | 'ApiSelect' | 92 | | 'ApiSelect' |
93 | | 'TreeSelect' | 93 | | 'TreeSelect' |
94 | + | 'ApiTree' | ||
94 | | 'ApiTreeSelect' | 95 | | 'ApiTreeSelect' |
95 | | 'ApiRadioGroup' | 96 | | 'ApiRadioGroup' |
96 | | 'RadioButtonGroup' | 97 | | 'RadioButtonGroup' |