Commit 67d514ad0e27083328c853e010a8eee9ed7f0408

Authored by ToQuery
Committed by GitHub
1 parent 929141be

新增 api tree 组件 (#1582)

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

* api-tree
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'