From 9dfa701454d6a94690bad39dbb0e38f2a0b31489 Mon Sep 17 00:00:00 2001 From: Ben Lin <maobin001@msn.com> Date: 星期二, 18 六月 2024 18:08:47 +0800 Subject: [PATCH] build --- src/components/Form/src/components/ApiTreeSelect.vue | 176 +++++++++++++++++++++++++++++++++++----------------------- 1 files changed, 106 insertions(+), 70 deletions(-) diff --git a/src/components/Form/src/components/ApiTreeSelect.vue b/src/components/Form/src/components/ApiTreeSelect.vue index 1e8b04c..5a46128 100644 --- a/src/components/Form/src/components/ApiTreeSelect.vue +++ b/src/components/Form/src/components/ApiTreeSelect.vue @@ -1,88 +1,124 @@ <template> - <a-tree-select v-bind="getAttrs" @change="handleChange"> + <TreeSelect + v-bind="getAttrs" + @change="handleChange" + :field-names="fieldNames" + :load-data="async ? onLoadData : undefined" + > <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-select> + </TreeSelect> </template> -<script lang="ts"> +<script lang="ts" setup> import { type Recordable } from '@vben/types'; - import { type PropType, computed, defineComponent, watch, ref, onMounted, unref } from 'vue'; + import { type PropType, computed, watch, ref, onMounted, unref, useAttrs } from 'vue'; import { TreeSelect } from 'ant-design-vue'; - import { isArray, isFunction } from '/@/utils/is'; + import { isArray, isFunction } from '@/utils/is'; import { get } from 'lodash-es'; - import { propTypes } from '/@/utils/propTypes'; + import { propTypes } from '@/utils/propTypes'; import { LoadingOutlined } from '@ant-design/icons-vue'; - export default defineComponent({ - name: 'ApiTreeSelect', - components: { ATreeSelect: TreeSelect, LoadingOutlined }, - props: { - api: { type: Function as PropType<(arg?: Recordable<any>) => Promise<Recordable<any>>> }, - params: { type: Object }, - immediate: { type: Boolean, default: true }, - resultField: propTypes.string.def(''), + defineOptions({ name: 'ApiTreeSelect' }); + + const props = defineProps({ + api: { type: Function as PropType<(arg?: any) => Promise<Recordable<any>>> }, + params: { type: Object }, + immediate: { type: Boolean, default: true }, + async: { type: Boolean, default: false }, + resultField: propTypes.string.def(''), + labelField: propTypes.string.def('title'), + valueField: propTypes.string.def('value'), + childrenField: propTypes.string.def('children'), + beforeFetch: { + type: Function as PropType<Fn>, + default: null, }, - emits: ['options-change', 'change'], - setup(props, { attrs, emit }) { - const treeData = ref<Recordable<any>[]>([]); - 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<any>[]) || []; - isFirstLoaded.value = true; - emit('options-change', treeData.value); - } - return { getAttrs, loading, handleChange }; + afterFetch: { + type: Function as PropType<Fn>, + default: null, }, }); + + const emit = defineEmits(['options-change', 'change', 'load-data']); + + const attrs = useAttrs(); + const treeData = ref<Recordable<any>[]>([]); + const isFirstLoaded = ref<Boolean>(false); + const loading = ref(false); + const getAttrs = computed(() => { + return { + ...(props.api ? { treeData: unref(treeData) } : {}), + ...attrs, + }; + }); + const fieldNames = { + children: props.childrenField, + value: props.valueField, + label: props.labelField, + }; + + 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(); + }); + + function onLoadData(treeNode) { + return new Promise((resolve: (value?: unknown) => void) => { + if (isArray(treeNode.children) && treeNode.children.length > 0) { + resolve(); + return; + } + emit('load-data', { treeData, treeNode, resolve }); + }); + } + + async function fetch() { + let { api, beforeFetch, afterFetch, params, resultField } = props; + if (!api || !isFunction(api) || loading.value) return; + loading.value = true; + treeData.value = []; + let res; + try { + if (beforeFetch && isFunction(beforeFetch)) { + params = (await beforeFetch(params)) || params; + } + res = await api(params); + if (afterFetch && isFunction(afterFetch)) { + res = (await afterFetch(res)) || res; + } + } catch (e) { + console.error(e); + } + loading.value = false; + if (!res) return; + if (resultField) { + res = get(res, resultField) || []; + } + treeData.value = (res as Recordable<any>[]) || []; + isFirstLoaded.value = true; + emit('options-change', treeData.value); + } </script> -- Gitblit v1.9.3