提交 a305e591 编写于 作者: V vben

fix(form): form validate error

上级 08df1987
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
- form: 新增`suffix`属性,用于配置后缀内容 - form: 新增`suffix`属性,用于配置后缀内容
- form: 新增远程下拉`ApiSelect`及示例 - form: 新增远程下拉`ApiSelect`及示例
- form: 新增`autoFocusFirstItem`配置。用于配置是否聚焦表单第一个输入框 - form: 新增`autoFocusFirstItem`配置。用于配置是否聚焦表单第一个输入框
- useForm: 支持动态改变参数。可以传入`Ref`类型与`Computed`类型进行动态更改
### ⚡ Performance Improvements ### ⚡ Performance Improvements
...@@ -18,7 +19,7 @@ ...@@ -18,7 +19,7 @@
### 🎫 Chores ### 🎫 Chores
- 升级`ant-design-vue``2.0.0-rc.6` - 升级`ant-design-vue``2.0.0-rc.7`
### 🐛 Bug Fixes ### 🐛 Bug Fixes
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"dependencies": { "dependencies": {
"@iconify/iconify": "^2.0.0-rc.4", "@iconify/iconify": "^2.0.0-rc.4",
"@vueuse/core": "^4.0.1", "@vueuse/core": "^4.0.1",
"ant-design-vue": "^2.0.0-rc.6", "ant-design-vue": "^2.0.0-rc.7",
"apexcharts": "^3.23.0", "apexcharts": "^3.23.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"crypto-es": "^1.2.6", "crypto-es": "^1.2.6",
......
...@@ -31,14 +31,24 @@ ...@@ -31,14 +31,24 @@
import type { AdvanceState } from './types/hooks'; import type { AdvanceState } from './types/hooks';
import type { CSSProperties, Ref, WatchStopHandle } from 'vue'; import type { CSSProperties, Ref, WatchStopHandle } from 'vue';
import { defineComponent, reactive, ref, computed, unref, onMounted, watch, toRefs } from 'vue'; import {
defineComponent,
reactive,
ref,
computed,
unref,
onMounted,
watch,
toRefs,
toRaw,
} from 'vue';
import { Form, Row } from 'ant-design-vue'; import { Form, Row } from 'ant-design-vue';
import FormItem from './components/FormItem'; import FormItem from './components/FormItem';
import FormAction from './components/FormAction.vue'; import FormAction from './components/FormAction.vue';
import { dateItemType } from './helper'; import { dateItemType } from './helper';
import moment from 'moment'; import moment from 'moment';
import { cloneDeep } from 'lodash-es'; // import { cloneDeep } from 'lodash-es';
import { deepMerge } from '/@/utils'; import { deepMerge } from '/@/utils';
import { useFormValues } from './hooks/useFormValues'; import { useFormValues } from './hooks/useFormValues';
...@@ -76,7 +86,7 @@ ...@@ -76,7 +86,7 @@
// Get the basic configuration of the form // Get the basic configuration of the form
const getProps = computed( const getProps = computed(
(): FormProps => { (): FormProps => {
return deepMerge(cloneDeep(props), unref(propsRef)); return { ...props, ...unref(propsRef) } as FormProps;
} }
); );
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
type: String as PropType<string>, type: String as PropType<string>,
}, },
api: { api: {
type: Function as PropType<(arg: Recordable) => Promise<OptionsItem[]>>, type: Function as PropType<(arg?: Recordable) => Promise<OptionsItem[]>>,
default: null, default: null,
}, },
params: { params: {
......
import { ref, onUnmounted, unref, nextTick } from 'vue'; import { ref, onUnmounted, unref, nextTick, watchEffect } from 'vue';
import { isInSetup } from '/@/utils/helper/vueHelper'; import { isInSetup } from '/@/utils/helper/vueHelper';
import { isProdMode } from '/@/utils/env'; import { isProdMode } from '/@/utils/env';
import { error } from '/@/utils/log'; import { error } from '/@/utils/log';
import { getDynamicProps } from '/@/utils';
import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form'; import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form';
import type { NamePath } from 'ant-design-vue/lib/form/interface'; import type { NamePath } from 'ant-design-vue/lib/form/interface';
import type { DynamicProps } from '/@/types/utils';
export declare type ValidateFields = (nameList?: NamePath[]) => Promise<Recordable>; export declare type ValidateFields = (nameList?: NamePath[]) => Promise<Recordable>;
export function useForm(props?: Partial<FormProps>): UseFormReturnType { type Props = Partial<DynamicProps<FormProps>>;
export function useForm(props?: Props): UseFormReturnType {
isInSetup(); isInSetup();
const formRef = ref<Nullable<FormActionType>>(null); const formRef = ref<Nullable<FormActionType>>(null);
...@@ -25,6 +29,7 @@ export function useForm(props?: Partial<FormProps>): UseFormReturnType { ...@@ -25,6 +29,7 @@ export function useForm(props?: Partial<FormProps>): UseFormReturnType {
await nextTick(); await nextTick();
return form as FormActionType; return form as FormActionType;
} }
function register(instance: FormActionType) { function register(instance: FormActionType) {
isProdMode() && isProdMode() &&
onUnmounted(() => { onUnmounted(() => {
...@@ -34,8 +39,12 @@ export function useForm(props?: Partial<FormProps>): UseFormReturnType { ...@@ -34,8 +39,12 @@ export function useForm(props?: Partial<FormProps>): UseFormReturnType {
if (unref(loadedRef) && isProdMode() && instance === unref(formRef)) return; if (unref(loadedRef) && isProdMode() && instance === unref(formRef)) return;
formRef.value = instance; formRef.value = instance;
props && instance.setProps(props);
loadedRef.value = true; loadedRef.value = true;
watchEffect(() => {
props && instance.setProps(getDynamicProps(props));
});
} }
const methods: FormActionType = { const methods: FormActionType = {
......
...@@ -178,12 +178,10 @@ export function useFormEvents({ ...@@ -178,12 +178,10 @@ export function useFormEvents({
} }
async function validateFields(nameList?: NamePath[] | undefined) { async function validateFields(nameList?: NamePath[] | undefined) {
const res = await unref(formElRef)?.validateFields(nameList || []); return unref(formElRef)?.validateFields(nameList);
return res;
} }
async function validate(nameList?: NamePath[] | undefined) { async function validate(nameList?: NamePath[] | undefined) {
return await unref(formElRef)?.validate(nameList || []); return await unref(formElRef)?.validate(nameList);
} }
async function clearValidate(name?: string | string[]) { async function clearValidate(name?: string | string[]) {
......
...@@ -18,6 +18,9 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref< ...@@ -18,6 +18,9 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
// If labelWidth is set globally, all items setting // If labelWidth is set globally, all items setting
if ((!globalLabelWidth && !labelWidth && !globalLabelCol) || disabledLabelWidth) { if ((!globalLabelWidth && !labelWidth && !globalLabelCol) || disabledLabelWidth) {
labelCol.style = {
textAlign: 'left',
};
return { labelCol, wrapperCol }; return { labelCol, wrapperCol };
} }
let width = labelWidth || globalLabelWidth; let width = labelWidth || globalLabelWidth;
...@@ -27,6 +30,7 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref< ...@@ -27,6 +30,7 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
if (width) { if (width) {
width = isNumber(width) ? `${width}px` : width; width = isNumber(width) ? `${width}px` : width;
} }
return { return {
labelCol: { style: { width }, ...col }, labelCol: { style: { width }, ...col },
wrapperCol: { style: { width: `calc(100% - ${width})` }, ...wrapCol }, wrapperCol: { style: { width: `calc(100% - ${width})` }, ...wrapCol },
......
...@@ -68,8 +68,9 @@ ...@@ -68,8 +68,9 @@
import { useEventListener } from '/@/hooks/event/useEventListener'; import { useEventListener } from '/@/hooks/event/useEventListener';
import { basicProps } from './props'; import { basicProps } from './props';
import { ROW_KEY } from './const'; import { ROW_KEY } from './const';
import './style/index.less';
import { useExpose } from '/@/hooks/core/useExpose'; import { useExpose } from '/@/hooks/core/useExpose';
import './style/index.less';
export default defineComponent({ export default defineComponent({
props: basicProps, props: basicProps,
components: { Table, BasicForm }, components: { Table, BasicForm },
...@@ -87,6 +88,12 @@ ...@@ -87,6 +88,12 @@
} as BasicTableProps; } as BasicTableProps;
}); });
// const getProps = computed(
// (): FormProps => {
// return deepMerge(toRaw(props), unref(innerPropsRef));
// }
// );
const { loadingRef } = useLoading(getMergeProps); const { loadingRef } = useLoading(getMergeProps);
const { getPaginationRef, setPagination } = usePagination(getMergeProps); const { getPaginationRef, setPagination } = usePagination(getMergeProps);
const { getColumnsRef, setColumns } = useColumns(getMergeProps, getPaginationRef); const { getColumnsRef, setColumns } = useColumns(getMergeProps, getPaginationRef);
...@@ -299,8 +306,8 @@ ...@@ -299,8 +306,8 @@
loadingRef.value = loading; loadingRef.value = loading;
}, },
setProps, setProps,
getSize: (): SizeType => { getSize: () => {
return unref(getBindValues).size; return unref(getBindValues).size as SizeType;
}, },
}; };
......
...@@ -16,6 +16,5 @@ ...@@ -16,6 +16,5 @@
default: '', default: '',
}, },
}, },
setup() {},
}); });
</script> </script>
...@@ -90,7 +90,6 @@ ...@@ -90,7 +90,6 @@
SettingOutlined, SettingOutlined,
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
import { useFullscreen } from '/@/hooks/web/useFullScreen'; import { useFullscreen } from '/@/hooks/web/useFullScreen';
import type { SizeType, TableSetting } from '../types/table'; import type { SizeType, TableSetting } from '../types/table';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
...@@ -150,6 +149,7 @@ ...@@ -150,6 +149,7 @@
init(); init();
} }
}); });
function init() { function init() {
let ret: Options[] = []; let ret: Options[] = [];
table.getColumns({ ignoreIndex: true, ignoreAction: true }).forEach((item) => { table.getColumns({ ignoreIndex: true, ignoreAction: true }).forEach((item) => {
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
components: { BasicTitle }, components: { BasicTitle },
props: { props: {
title: { title: {
type: [Function, String] as PropType<string | ((data: any) => string)>, type: [Function, String] as PropType<string | ((data: Recordable) => string)>,
}, },
getSelectRows: { getSelectRows: {
type: Function as PropType<() => any[]>, type: Function as PropType<() => Recordable[]>,
}, },
helpMessage: { helpMessage: {
type: [String, Array] as PropType<string | string[]>, type: [String, Array] as PropType<string | string[]>,
......
import { BasicArrow } from '/@/components/Basic'; import { BasicArrow } from '/@/components/Basic';
export default () => { export default () => {
return (props: any) => { return (props: Recordable) => {
return ( return (
<BasicArrow <BasicArrow
onClick={(e: Event) => { onClick={(e: Event) => {
......
import type { BasicTableProps, TableActionType, FetchParams, BasicColumn } from '../types/table'; import type { BasicTableProps, TableActionType, FetchParams, BasicColumn } from '../types/table';
import type { PaginationProps } from '../types/pagination'; import type { PaginationProps } from '../types/pagination';
import { ref, getCurrentInstance, onUnmounted, unref } from 'vue'; import { ref, onUnmounted, unref } from 'vue';
import { isProdMode } from '/@/utils/env'; import { isProdMode } from '/@/utils/env';
import { isInSetup } from '/@/utils/helper/vueHelper';
export function useTable( export function useTable(
tableProps?: Partial<BasicTableProps> tableProps?: Partial<BasicTableProps>
): [(instance: TableActionType) => void, TableActionType] { ): [(instance: TableActionType) => void, TableActionType] {
if (!getCurrentInstance()) { isInSetup();
throw new Error('Please put useTable function in the setup function!');
}
const tableRef = ref<TableActionType | null>(null); const tableRef = ref<Nullable<TableActionType>>(null);
const loadedRef = ref<boolean | null>(false); const loadedRef = ref<Nullable<boolean>>(false);
function register(instance: TableActionType) { function register(instance: TableActionType) {
onUnmounted(() => { onUnmounted(() => {
tableRef.value = null; tableRef.value = null;
loadedRef.value = null; loadedRef.value = null;
}); });
if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) { if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) {
return; return;
} }
......
...@@ -57,7 +57,7 @@ export default defineComponent({ ...@@ -57,7 +57,7 @@ export default defineComponent({
<p class={`${prefixCls}__header-name`}>{userStore.getUserInfoState.realName}</p> <p class={`${prefixCls}__header-name`}>{userStore.getUserInfoState.realName}</p>
</div> </div>
<BasicForm onRegister={registerForm} layout="vertical" /> <BasicForm onRegister={registerForm} />
<div class={`${prefixCls}__footer`}> <div class={`${prefixCls}__footer`}>
<Button type="primary" block class="mt-2" onClick={lock}> <Button type="primary" block class="mt-2" onClick={lock}>
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<p :class="`${prefixCls}__header-name`">{{ getRealName }}</p> <p :class="`${prefixCls}__header-name`">{{ getRealName }}</p>
</div> </div>
<BasicForm @register="registerForm" layout="vertical" /> <BasicForm @register="registerForm" />
<div :class="`${prefixCls}__footer`"> <div :class="`${prefixCls}__footer`">
<a-button type="primary" block class="mt-2" @click="handleLock"> <a-button type="primary" block class="mt-2" @click="handleLock">
......
import type { ComputedRef, Ref } from 'vue';
export type DynamicProps<T> = {
[P in keyof T]: Ref<T[P]> | T[P] | ComputedRef<T[P]>;
};
export const timestamp = () => +Date.now(); export const timestamp = () => +Date.now();
import { unref } from 'vue';
import { isObject } from '/@/utils/is'; import { isObject } from '/@/utils/is';
export const clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n)); export const clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n));
export const noop = () => {}; export const noop = () => {};
...@@ -76,3 +77,14 @@ export function openWindow( ...@@ -76,3 +77,14 @@ export function openWindow(
window.open(url, target, feature.join(',')); window.open(url, target, feature.join(','));
} }
// dynamic use hook props
export function getDynamicProps<T, U>(props: T): Partial<U> {
const ret: Recordable = {};
Object.keys(props).map((key) => {
ret[key] = unref((props as Recordable)[key]);
});
return ret as Partial<U>;
}
...@@ -162,6 +162,7 @@ ...@@ -162,6 +162,7 @@
components: { BasicForm, CollapseContainer }, components: { BasicForm, CollapseContainer },
setup() { setup() {
const { createMessage } = useMessage(); const { createMessage } = useMessage();
const [register, { setProps }] = useForm({ const [register, { setProps }] = useForm({
labelWidth: 120, labelWidth: 120,
schemas, schemas,
...@@ -172,7 +173,7 @@ ...@@ -172,7 +173,7 @@
return { return {
register, register,
schemas, schemas,
handleSubmit: (values: any) => { handleSubmit: (values: Recordable) => {
createMessage.success('click search,values:' + JSON.stringify(values)); createMessage.success('click search,values:' + JSON.stringify(values));
}, },
setProps, setProps,
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
<div class="m-5"> <div class="m-5">
<a-card title="仓库管理" :bordered="false"> <a-card title="仓库管理" :bordered="false">
<BasicForm @register="register" layout="vertical" /> <BasicForm @register="register" />
</a-card> </a-card>
<a-card title="任务管理" :bordered="false" class="mt-5"> <a-card title="任务管理" :bordered="false" class="mt-5">
<BasicForm @register="registerTask" layout="vertical" /> <BasicForm @register="registerTask" />
</a-card> </a-card>
<a-card title="成员管理" :bordered="false" class="mt-5"> <a-card title="成员管理" :bordered="false" class="mt-5">
<PersonTable ref="tableRef" /> <PersonTable ref="tableRef" />
......
...@@ -1956,10 +1956,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: ...@@ -1956,10 +1956,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies: dependencies:
color-convert "^2.0.1" color-convert "^2.0.1"
ant-design-vue@^2.0.0-rc.6: ant-design-vue@^2.0.0-rc.7:
version "2.0.0-rc.6" version "2.0.0-rc.7"
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0-rc.6.tgz#f25f61cde1c75c32a78b536751731c0b223b6590" resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0-rc.7.tgz#5d83a7f13275574ec1fc1ea8c1fe8d9aa6de067c"
integrity sha512-NRxzIC4CSM56MXYHdg3K2oTc+pkcSJd6BJtIBCxUsbFfbBGp+F7ei7C1bQDdHHos3o/Oe2iqGwzfrZ7+Ot2Uew== integrity sha512-QMStvwaLfV1Q3RaQ8D926aCkW6iqWBHXlNv7dBdTPvU8eeFXPaPKenLu1OTpSi+wpCncJqgumFOEcENPvh0nKw==
dependencies: dependencies:
"@ant-design-vue/use" "^0.0.1-0" "@ant-design-vue/use" "^0.0.1-0"
"@ant-design/icons-vue" "^5.1.7" "@ant-design/icons-vue" "^5.1.7"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册