Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
This commit is contained in:
@@ -62,7 +62,7 @@ async function handleReset(e: Event) {
|
||||
e?.stopPropagation();
|
||||
const props = unref(rootProps);
|
||||
|
||||
const values = toRaw(props.formApi?.getValues());
|
||||
const values = toRaw(await props.formApi?.getValues());
|
||||
|
||||
if (isFunction(props.handleReset)) {
|
||||
await props.handleReset?.(values);
|
||||
|
@@ -378,7 +378,10 @@ export interface VbenFormProps<
|
||||
/**
|
||||
* 表单值变化回调
|
||||
*/
|
||||
handleValuesChange?: (values: Record<string, any>) => void;
|
||||
handleValuesChange?: (
|
||||
values: Record<string, any>,
|
||||
fieldsChanged: string[],
|
||||
) => void;
|
||||
/**
|
||||
* 重置按钮参数
|
||||
*/
|
||||
|
@@ -1,12 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type { Recordable } from '@vben-core/typings';
|
||||
|
||||
import type { ExtendedFormApi, VbenFormProps } from './types';
|
||||
|
||||
// import { toRaw, watch } from 'vue';
|
||||
import { nextTick, onMounted, watch } from 'vue';
|
||||
// import { isFunction } from '@vben-core/shared/utils';
|
||||
|
||||
import { useForwardPriorityValues } from '@vben-core/composables';
|
||||
import { cloneDeep } from '@vben-core/shared/utils';
|
||||
import { cloneDeep, get, isEqual, set } from '@vben-core/shared/utils';
|
||||
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
|
||||
@@ -61,16 +62,46 @@ function handleKeyDownEnter(event: KeyboardEvent) {
|
||||
}
|
||||
|
||||
const handleValuesChangeDebounced = useDebounceFn(async () => {
|
||||
forward.value.handleValuesChange?.(
|
||||
cloneDeep(await forward.value.formApi.getValues()),
|
||||
);
|
||||
state.value.submitOnChange && forward.value.formApi?.validateAndSubmitForm();
|
||||
}, 300);
|
||||
|
||||
const valuesCache: Recordable<any> = {};
|
||||
|
||||
onMounted(async () => {
|
||||
// 只在挂载后开始监听,form.values会有一个初始化的过程
|
||||
await nextTick();
|
||||
watch(() => form.values, handleValuesChangeDebounced, { deep: true });
|
||||
watch(
|
||||
() => form.values,
|
||||
async (newVal) => {
|
||||
if (forward.value.handleValuesChange) {
|
||||
const fields = state.value.schema?.map((item) => {
|
||||
return item.fieldName;
|
||||
});
|
||||
|
||||
if (fields && fields.length > 0) {
|
||||
const changedFields: string[] = [];
|
||||
fields.forEach((field) => {
|
||||
const newFieldValue = get(newVal, field);
|
||||
const oldFieldValue = get(valuesCache, field);
|
||||
if (!isEqual(newFieldValue, oldFieldValue)) {
|
||||
changedFields.push(field);
|
||||
set(valuesCache, field, newFieldValue);
|
||||
}
|
||||
});
|
||||
|
||||
if (changedFields.length > 0) {
|
||||
// 调用handleValuesChange回调,传入所有表单值的深拷贝和变更的字段列表
|
||||
forward.value.handleValuesChange(
|
||||
cloneDeep(await forward.value.formApi.getValues()),
|
||||
changedFields,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
handleValuesChangeDebounced();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@@ -9,7 +9,11 @@ vi.mock('@vben-core/shared/store', () => {
|
||||
return {
|
||||
isFunction: (fn: any) => typeof fn === 'function',
|
||||
Store: class {
|
||||
get state() {
|
||||
return this._state;
|
||||
}
|
||||
private _state: DrawerState;
|
||||
|
||||
private options: any;
|
||||
|
||||
constructor(initialState: DrawerState, options: any) {
|
||||
@@ -25,10 +29,6 @@ vi.mock('@vben-core/shared/store', () => {
|
||||
this._state = fn(this._state);
|
||||
this.options.onUpdate();
|
||||
}
|
||||
|
||||
get state() {
|
||||
return this._state;
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -54,7 +54,6 @@ describe('drawerApi', () => {
|
||||
});
|
||||
|
||||
it('should close the drawer if onBeforeClose allows it', () => {
|
||||
drawerApi.open();
|
||||
drawerApi.close();
|
||||
expect(drawerApi.store.state.isOpen).toBe(false);
|
||||
});
|
||||
|
@@ -86,7 +86,8 @@ export class DrawerApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭弹窗
|
||||
* 关闭抽屉
|
||||
* @description 关闭抽屉时会调用 onBeforeClose 钩子函数,如果 onBeforeClose 返回 false,则不关闭弹窗
|
||||
*/
|
||||
async close() {
|
||||
// 通过 onBeforeClose 钩子函数来判断是否允许关闭弹窗
|
||||
|
@@ -186,7 +186,7 @@ const getAppendTo = computed(() => {
|
||||
});
|
||||
|
||||
const getForceMount = computed(() => {
|
||||
return !unref(destroyOnClose);
|
||||
return !unref(destroyOnClose) && unref(firstOpened);
|
||||
});
|
||||
|
||||
function handleClosed() {
|
||||
|
Reference in New Issue
Block a user