feat(BasicForm->Components): add beforeFetch & afterFetch to apicomp && perf the code (#3786)

* fix(apitree): fix the error way to use resultfield

* feat: add before & after Fetch fn in apiComp
This commit is contained in:
Electrolux 2024-04-24 18:00:13 +08:00 committed by GitHub
parent 2f655c2127
commit 7ae2ec03a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 134 additions and 49 deletions

View File

@ -69,6 +69,14 @@
displayRenderArray: { displayRenderArray: {
type: Array, type: Array,
}, },
beforeFetch: {
type: Function as PropType<Fn>,
default: null,
},
afterFetch: {
type: Function as PropType<Fn>,
default: null,
},
}); });
const emit = defineEmits(['change', 'defaultChange']); const emit = defineEmits(['change', 'defaultChange']);
@ -112,19 +120,25 @@
}, [] as Option[]); }, [] as Option[]);
} }
async function initialFetch() { async function fetch() {
const api = props.api; let { api, beforeFetch, initFetchParams, afterFetch, resultField } = props;
if (!api || !isFunction(api)) return; if (!api || !isFunction(api)) return;
apiData.value = []; apiData.value = [];
loading.value = true; loading.value = true;
try { try {
const res = await api(props.initFetchParams); if (beforeFetch && isFunction(beforeFetch)) {
initFetchParams = (await beforeFetch(initFetchParams)) || initFetchParams;
}
let res = await api(initFetchParams);
if (afterFetch && isFunction(afterFetch)) {
res = (await afterFetch(res)) || res;
}
if (Array.isArray(res)) { if (Array.isArray(res)) {
apiData.value = res; apiData.value = res;
return; return;
} }
if (props.resultField) { if (resultField) {
apiData.value = get(res, props.resultField) || []; apiData.value = get(res, resultField) || [];
} }
} catch (error) { } catch (error) {
console.warn(error); console.warn(error);
@ -136,20 +150,26 @@
const loadData: CascaderProps['loadData'] = async (selectedOptions) => { const loadData: CascaderProps['loadData'] = async (selectedOptions) => {
const targetOption = selectedOptions[selectedOptions.length - 1]; const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true; targetOption.loading = true;
let { api, beforeFetch, afterFetch, resultField, apiParamKey } = props;
const api = props.api;
if (!api || !isFunction(api)) return; if (!api || !isFunction(api)) return;
try { try {
const res = await api({ let param = {
[props.apiParamKey]: Reflect.get(targetOption, 'value'), [apiParamKey]: Reflect.get(targetOption, 'value'),
}); };
if (beforeFetch && isFunction(beforeFetch)) {
param = (await beforeFetch(param)) || param;
}
let res = await api(param);
if (afterFetch && isFunction(afterFetch)) {
res = (await afterFetch(res)) || res;
}
if (Array.isArray(res)) { if (Array.isArray(res)) {
const children = generatorOptions(res); const children = generatorOptions(res);
targetOption.children = children; targetOption.children = children;
return; return;
} }
if (props.resultField) { if (resultField) {
const children = generatorOptions(get(res, props.resultField) || []); const children = generatorOptions(get(res, resultField) || []);
targetOption.children = children; targetOption.children = children;
} }
} catch (e) { } catch (e) {
@ -162,7 +182,7 @@
watch( watch(
() => props.immediate, () => props.immediate,
() => { () => {
props.immediate && initialFetch(); props.immediate && fetch();
}, },
{ {
immediate: true, immediate: true,
@ -172,7 +192,7 @@
watch( watch(
() => props.initFetchParams, () => props.initFetchParams,
() => { () => {
!unref(isFirstLoad) && initialFetch(); !unref(isFirstLoad) && fetch();
}, },
{ deep: true }, { deep: true },
); );

View File

@ -57,6 +57,14 @@
labelField: propTypes.string.def('label'), labelField: propTypes.string.def('label'),
valueField: propTypes.string.def('value'), valueField: propTypes.string.def('value'),
immediate: propTypes.bool.def(true), immediate: propTypes.bool.def(true),
beforeFetch: {
type: Function as PropType<Fn>,
default: null,
},
afterFetch: {
type: Function as PropType<Fn>,
default: null,
},
}); });
const emit = defineEmits(['options-change', 'change', 'update:value']); const emit = defineEmits(['options-change', 'change', 'update:value']);
@ -95,19 +103,25 @@
); );
async function fetch() { async function fetch() {
const api = props.api; let { api, beforeFetch, afterFetch, params, resultField } = props;
if (!api || !isFunction(api)) return; if (!api || !isFunction(api)) return;
options.value = []; options.value = [];
try { try {
loading.value = true; loading.value = true;
const res = await api(props.params); if (beforeFetch && isFunction(beforeFetch)) {
params = (await beforeFetch(params)) || params;
}
let res = await api(params);
if (afterFetch && isFunction(afterFetch)) {
res = (await afterFetch(res)) || res;
}
if (Array.isArray(res)) { if (Array.isArray(res)) {
options.value = res; options.value = res;
emitChange(); emitChange();
return; return;
} }
if (props.resultField) { if (resultField) {
options.value = get(res, props.resultField) || []; options.value = get(res, resultField) || [];
} }
emitChange(); emitChange();
} catch (error) { } catch (error) {

View File

@ -54,6 +54,14 @@
type: Array<OptionsItem>, type: Array<OptionsItem>,
default: [], default: [],
}, },
beforeFetch: {
type: Function as PropType<Fn>,
default: null,
},
afterFetch: {
type: Function as PropType<Fn>,
default: null,
},
}); });
const emit = defineEmits(['options-change', 'change', 'update:value']); const emit = defineEmits(['options-change', 'change', 'update:value']);
@ -103,20 +111,26 @@
); );
async function fetch() { async function fetch() {
const api = props.api; let { api, beforeFetch, afterFetch, params, resultField } = props;
if (!api || !isFunction(api) || loading.value) return; if (!api || !isFunction(api) || loading.value) return;
optionsRef.value = []; optionsRef.value = [];
try { try {
loading.value = true; loading.value = true;
const res = await api(props.params); if (beforeFetch && isFunction(beforeFetch)) {
params = (await beforeFetch(params)) || params;
}
let res = await api(params);
if (afterFetch && isFunction(afterFetch)) {
res = (await afterFetch(res)) || res;
}
isFirstLoaded.value = true; isFirstLoaded.value = true;
if (Array.isArray(res)) { if (Array.isArray(res)) {
optionsRef.value = res; optionsRef.value = res;
emitChange(); emitChange();
return; return;
} }
if (props.resultField) { if (resultField) {
optionsRef.value = get(res, props.resultField) || []; optionsRef.value = get(res, resultField) || [];
} }
emitChange(); emitChange();
} catch (error) { } catch (error) {

View File

@ -32,7 +32,14 @@
dataSource: { type: Array as PropType<Array<TransferItem>> }, dataSource: { type: Array as PropType<Array<TransferItem>> },
immediate: propTypes.bool.def(true), immediate: propTypes.bool.def(true),
alwaysLoad: propTypes.bool.def(false), alwaysLoad: propTypes.bool.def(false),
afterFetch: { type: Function }, beforeFetch: {
type: Function as PropType<Fn>,
default: null,
},
afterFetch: {
type: Function as PropType<Fn>,
default: null,
},
resultField: propTypes.string.def(''), resultField: propTypes.string.def(''),
labelField: propTypes.string.def('title'), labelField: propTypes.string.def('title'),
valueField: propTypes.string.def('key'), valueField: propTypes.string.def('key'),
@ -98,23 +105,29 @@
); );
async function fetch() { async function fetch() {
const api = props.api; let { api, beforeFetch, afterFetch, params, resultField, dataSource } = props;
if (!api || !isFunction(api)) { if (!api || !isFunction(api)) {
if (Array.isArray(props.dataSource)) { if (Array.isArray(dataSource)) {
_dataSource.value = props.dataSource; _dataSource.value = dataSource;
} }
return; return;
} }
_dataSource.value = []; _dataSource.value = [];
try { try {
const res = await api(props.params); if (beforeFetch && isFunction(beforeFetch)) {
params = (await beforeFetch(params)) || params;
}
let res = await api(params);
if (afterFetch && isFunction(afterFetch)) {
res = (await afterFetch(res)) || res;
}
if (Array.isArray(res)) { if (Array.isArray(res)) {
_dataSource.value = res; _dataSource.value = res;
emitChange(); emitChange();
return; return;
} }
if (props.resultField) { if (resultField) {
_dataSource.value = get(res, props.resultField) || []; _dataSource.value = get(res, resultField) || [];
} }
emitChange(); emitChange();
} catch (error) { } catch (error) {

View File

@ -7,10 +7,10 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { type Recordable, type AnyFunction } from '@vben/types'; import { type Recordable } from '@vben/types';
import { type PropType, computed, watch, ref, onMounted, unref, useAttrs } from 'vue'; import { type PropType, computed, watch, ref, onMounted, unref, useAttrs } from 'vue';
import { Tree, TreeProps } from 'ant-design-vue'; import { Tree, TreeProps } from 'ant-design-vue';
import { isArray, isFunction } from '@/utils/is'; import { isFunction } from '@/utils/is';
import { get } from 'lodash-es'; import { get } from 'lodash-es';
import { DataNode } from 'ant-design-vue/es/tree'; import { DataNode } from 'ant-design-vue/es/tree';
import { useRuleFormItem } from '@/hooks/component/useFormItem'; import { useRuleFormItem } from '@/hooks/component/useFormItem';
@ -22,7 +22,14 @@
params: { type: Object }, params: { type: Object },
immediate: { type: Boolean, default: true }, immediate: { type: Boolean, default: true },
resultField: { type: String, default: '' }, resultField: { type: String, default: '' },
afterFetch: { type: Function as PropType<AnyFunction> }, beforeFetch: {
type: Function as PropType<Fn>,
default: null,
},
afterFetch: {
type: Function as PropType<Fn>,
default: null,
},
value: { value: {
type: Array as PropType<TreeProps['selectedKeys']>, type: Array as PropType<TreeProps['selectedKeys']>,
}, },
@ -72,25 +79,28 @@
}); });
async function fetch() { async function fetch() {
const { api, afterFetch } = props; let { api, beforeFetch, afterFetch, params, resultField } = props;
if (!api || !isFunction(api)) return; if (!api || !isFunction(api)) return;
loading.value = true; loading.value = true;
treeData.value = []; treeData.value = [];
let result; let res;
try { try {
result = await api(props.params); if (beforeFetch && isFunction(beforeFetch)) {
params = (await beforeFetch(params)) || params;
}
res = await api(params);
if (afterFetch && isFunction(afterFetch)) {
res = (await afterFetch(res)) || res;
}
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
if (afterFetch && isFunction(afterFetch)) {
result = afterFetch(result);
}
loading.value = false; loading.value = false;
if (!result) return; if (!res) return;
if (!isArray(result)) { if (resultField) {
result = get(result, props.resultField); res = get(res, resultField) || [];
} }
treeData.value = (result as (Recordable & { key: string | number })[]) || []; treeData.value = (res as (Recordable & { key: string | number })[]) || [];
isFirstLoaded.value = true; isFirstLoaded.value = true;
emit('options-change', treeData.value); emit('options-change', treeData.value);
} }

View File

@ -34,6 +34,14 @@
labelField: propTypes.string.def('title'), labelField: propTypes.string.def('title'),
valueField: propTypes.string.def('value'), valueField: propTypes.string.def('value'),
childrenField: propTypes.string.def('children'), childrenField: propTypes.string.def('children'),
beforeFetch: {
type: Function as PropType<Fn>,
default: null,
},
afterFetch: {
type: Function as PropType<Fn>,
default: null,
},
}); });
const emit = defineEmits(['options-change', 'change', 'load-data']); const emit = defineEmits(['options-change', 'change', 'load-data']);
@ -88,22 +96,28 @@
} }
async function fetch() { async function fetch() {
const { api } = props; let { api, beforeFetch, afterFetch, params, resultField } = props;
if (!api || !isFunction(api) || loading.value) return; if (!api || !isFunction(api) || loading.value) return;
loading.value = true; loading.value = true;
treeData.value = []; treeData.value = [];
let result; let res;
try { try {
result = await api(props.params); if (beforeFetch && isFunction(beforeFetch)) {
params = (await beforeFetch(params)) || params;
}
res = await api(params);
if (afterFetch && isFunction(afterFetch)) {
res = (await afterFetch(res)) || res;
}
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
loading.value = false; loading.value = false;
if (!result) return; if (!res) return;
if (!isArray(result)) { if (resultField) {
result = get(result, props.resultField); res = get(res, resultField) || [];
} }
treeData.value = (result as Recordable<any>[]) || []; treeData.value = (res as Recordable<any>[]) || [];
isFirstLoaded.value = true; isFirstLoaded.value = true;
emit('options-change', treeData.value); emit('options-change', treeData.value);
} }