From 08abfcfea8247c394b2034cad59734846b403dd9 Mon Sep 17 00:00:00 2001 From: Ben Lin <maobin001@msn.com> Date: 星期一, 28 十月 2024 22:22:58 +0800 Subject: [PATCH] 计划任务优化 --- src/components/Form/src/BasicForm.vue | 511 +++++++++++++++++++++++++++++++------------------------- 1 files changed, 279 insertions(+), 232 deletions(-) diff --git a/src/components/Form/src/BasicForm.vue b/src/components/Form/src/BasicForm.vue index f561a9a..63e942c 100644 --- a/src/components/Form/src/BasicForm.vue +++ b/src/components/Form/src/BasicForm.vue @@ -37,269 +37,311 @@ </Row> </Form> </template> -<script lang="ts"> - import type { FormActionType, FormProps, FormSchema } from './types/form'; +<script lang="ts" setup> + import type { FormActionType, FormProps, FormSchemaInner as FormSchema } from './types/form'; import type { AdvanceState } from './types/hooks'; import type { Ref } from 'vue'; - import { defineComponent, reactive, ref, computed, unref, onMounted, watch, nextTick } from 'vue'; - import { Form, Row } from 'ant-design-vue'; + import { reactive, ref, computed, unref, onMounted, watch, nextTick, useAttrs } from 'vue'; + import { Form, Row, type FormProps as AntFormProps } from 'ant-design-vue'; import FormItem from './components/FormItem.vue'; import FormAction from './components/FormAction.vue'; - import { dateItemType } from './helper'; - import { dateUtil } from '/@/utils/dateUtil'; + import { dateItemType, isIncludeSimpleComponents } from './helper'; + import { dateUtil } from '@/utils/dateUtil'; - // import { cloneDeep } from 'lodash-es'; - import { deepMerge } from '/@/utils'; + import { deepMerge } from '@/utils'; import { useFormValues } from './hooks/useFormValues'; import useAdvanced from './hooks/useAdvanced'; - import { useFormEvents } from './hooks/useFormEvents'; + import { itemIsUploadComponent, useFormEvents } from './hooks/useFormEvents'; import { createFormContext } from './hooks/useFormContext'; import { useAutoFocus } from './hooks/useAutoFocus'; - import { useModalContext } from '/@/components/Modal'; + import { useModalContext } from '@/components/Modal'; import { useDebounceFn } from '@vueuse/core'; import { basicProps } from './props'; - import { useDesign } from '/@/hooks/web/useDesign'; + import { useDesign } from '@/hooks/web/useDesign'; import { cloneDeep } from 'lodash-es'; + import { TableActionType } from '@/components/Table'; + import { isArray, isFunction } from '@/utils/is'; - export default defineComponent({ - name: 'BasicForm', - components: { FormItem, Form, Row, FormAction }, - props: basicProps, - emits: ['advanced-change', 'reset', 'submit', 'register', 'field-value-change'], - setup(props, { emit, attrs }) { - const formModel = reactive({}); - const modalFn = useModalContext(); + defineOptions({ name: 'BasicForm' }); - const advanceState = reactive<AdvanceState>({ - isAdvanced: true, - hideAdvanceBtn: false, - isLoad: false, - actionSpan: 6, - }); + const props = defineProps(basicProps); - const defaultValueRef = ref({}); - const isInitedDefaultRef = ref(false); - const propsRef = ref<Partial<FormProps>>({}); - const schemaRef = ref<FormSchema[] | null>(null); - const formElRef = ref<FormActionType | null>(null); + const emit = defineEmits([ + 'advanced-change', + 'reset', + 'submit', + 'register', + 'field-value-change', + ]); - const { prefixCls } = useDesign('basic-form'); + const attrs = useAttrs(); - // Get the basic configuration of the form - const getProps = computed((): FormProps => { - return { ...props, ...unref(propsRef) }; - }); + const formModel = reactive({}); + const modalFn = useModalContext(); - const getFormClass = computed(() => { - return [ - prefixCls, - { - [`${prefixCls}--compact`]: unref(getProps).compact, - }, - ]; - }); + const advanceState = reactive<AdvanceState>({ + isAdvanced: true, + hideAdvanceBtn: false, + isLoad: false, + actionSpan: 6, + }); - // Get uniform row style and Row configuration for the entire form - const getRow = computed(() => { - const { baseRowStyle = {}, rowProps } = unref(getProps); - return { - style: baseRowStyle, - ...rowProps, - }; - }); + const defaultValueRef = ref({}); + const isInitedDefaultRef = ref(false); + const propsRef = ref<Partial<FormProps>>(); + const schemaRef = ref<FormSchema[] | null>(null); + const formElRef = ref<FormActionType | null>(null); - const getBindValue = computed(() => ({ ...attrs, ...props, ...unref(getProps) })); + const { prefixCls } = useDesign('basic-form'); - const getSchema = computed((): FormSchema[] => { - const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any); - for (const schema of schemas) { - const { defaultValue, component, isHandleDateDefaultValue = true } = schema; - // handle date type - if (isHandleDateDefaultValue && defaultValue && dateItemType.includes(component)) { - if (!Array.isArray(defaultValue)) { - schema.defaultValue = dateUtil(defaultValue); - } else { - const def: any[] = []; - defaultValue.forEach((item) => { - def.push(dateUtil(item)); - }); - schema.defaultValue = def; - } - } - } - if (unref(getProps).showAdvancedButton) { - return cloneDeep( - schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[], - ); - } else { - return cloneDeep(schemas as FormSchema[]); - } - }); + // Get the basic configuration of the form + const getProps = computed(() => { + return { ...props, ...unref(propsRef) } as FormProps; + }); - const { handleToggleAdvanced, fieldsIsAdvancedMap } = useAdvanced({ - advanceState, - emit, - getProps, - getSchema, - formModel, - defaultValueRef, - }); + const getFormClass = computed(() => { + return [ + prefixCls, + { + [`${prefixCls}--compact`]: unref(getProps).compact, + }, + ]; + }); - const { handleFormValues, initDefault } = useFormValues({ - getProps, - defaultValueRef, - getSchema, - formModel, - }); + // Get uniform row style and Row configuration for the entire form + const getRow = computed(() => { + const { baseRowStyle = {}, rowProps } = unref(getProps); + return { + style: baseRowStyle, + ...rowProps, + }; + }); - useAutoFocus({ - getSchema, - getProps, - isInitedDefault: isInitedDefaultRef, - formElRef: formElRef as Ref<FormActionType>, - }); + const getBindValue = computed(() => ({ ...attrs, ...props, ...unref(getProps) }) as AntFormProps); + const getSchema = computed((): FormSchema[] => { + const schemas: FormSchema[] = cloneDeep(unref(schemaRef) || (unref(getProps).schemas as any)); + for (const schema of schemas) { const { - handleSubmit, - setFieldsValue, - clearValidate, - validate, - validateFields, - getFieldsValue, - updateSchema, - resetSchema, - appendSchemaByField, - removeSchemaByField, - resetFields, - scrollToField, - } = useFormEvents({ - emit, - getProps, - formModel, - getSchema, - defaultValueRef, - formElRef: formElRef as Ref<FormActionType>, - schemaRef: schemaRef as Ref<FormSchema[]>, - handleFormValues, - }); - - createFormContext({ - resetAction: resetFields, - submitAction: handleSubmit, - }); - - watch( - () => unref(getProps).model, - () => { - const { model } = unref(getProps); - if (!model) return; - setFieldsValue(model); - }, - { - immediate: true, - }, - ); - - watch( - () => unref(getProps).schemas, - (schemas) => { - resetSchema(schemas ?? []); - }, - ); - - watch( - () => getSchema.value, - (schema) => { - nextTick(() => { - // Solve the problem of modal adaptive height calculation when the form is placed in the modal - modalFn?.redoModalHeight?.(); + defaultValue, + component, + componentProps = {}, + isHandleDateDefaultValue = true, + field, + isHandleDefaultValue = true, + valueFormat, + } = schema; + // handle date type + if ( + isHandleDateDefaultValue && + defaultValue && + component && + dateItemType.includes(component) + ) { + const opt = { + schema, + tableAction: props.tableAction ?? ({} as TableActionType), + formModel, + formActionType: {} as FormActionType, + }; + const valueFormat = componentProps + ? typeof componentProps === 'function' + ? componentProps(opt)['valueFormat'] + : componentProps['valueFormat'] + : null; + if (!Array.isArray(defaultValue)) { + schema.defaultValue = valueFormat + ? dateUtil(defaultValue).format(valueFormat) + : dateUtil(defaultValue); + } else { + const def: any[] = []; + defaultValue.forEach((item) => { + def.push(valueFormat ? dateUtil(item).format(valueFormat) : dateUtil(item)); }); - if (unref(isInitedDefaultRef)) { - return; - } - if (schema?.length) { - initDefault(); - isInitedDefaultRef.value = true; - } - }, - ); - - watch( - () => formModel, - useDebounceFn(() => { - unref(getProps).submitOnChange && handleSubmit(); - }, 300), - { deep: true }, - ); - - async function setProps(formProps: Partial<FormProps>): Promise<void> { - propsRef.value = deepMerge(unref(propsRef) || {}, formProps); + schema.defaultValue = def; + } } - - function setFormModel(key: string, value: any, schema: FormSchema) { - formModel[key] = value; - emit('field-value-change', key, value); - // TODO 浼樺寲楠岃瘉锛岃繖閲屽鏋滄槸autoLink=false鎵嬪姩鍏宠仈鐨勬儏鍐典笅鎵嶄細鍐嶆瑙﹀彂姝ゅ嚱鏁� - if (schema && schema.itemProps && !schema.itemProps.autoLink) { - validateFields([key]).catch((_) => {}); + // handle upload type + if (defaultValue && itemIsUploadComponent(schema?.component)) { + if (isArray(defaultValue)) { + schema.defaultValue = defaultValue; + } else if (typeof defaultValue == 'string') { + schema.defaultValue = [defaultValue]; } } - function handleEnterPress(e: KeyboardEvent) { - const { autoSubmitOnEnter } = unref(getProps); - if (!autoSubmitOnEnter) return; - if (e.key === 'Enter' && e.target && e.target instanceof HTMLElement) { - const target: HTMLElement = e.target as HTMLElement; - if (target && target.tagName && target.tagName.toUpperCase() == 'INPUT') { - handleSubmit(); - } - } + // handle schema.valueFormat + if (isHandleDefaultValue && defaultValue && component && isFunction(valueFormat)) { + schema.defaultValue = valueFormat({ + value: defaultValue, + schema, + model: formModel, + field, + }); } + } + if (unref(getProps).showAdvancedButton) { + return schemas.filter( + (schema) => !isIncludeSimpleComponents(schema.component), + ) as FormSchema[]; + } else { + return schemas as FormSchema[]; + } + }); - const formActionType: Partial<FormActionType> = { - getFieldsValue, - setFieldsValue, - resetFields, - updateSchema, - resetSchema, - setProps, - removeSchemaByField, - appendSchemaByField, - clearValidate, - validateFields, - validate, - submit: handleSubmit, - scrollToField: scrollToField, - }; + const { handleToggleAdvanced, fieldsIsAdvancedMap } = useAdvanced({ + advanceState, + emit, + getProps, + getSchema, + formModel, + defaultValueRef, + }); - onMounted(() => { - initDefault(); - emit('register', formActionType); - }); + const { handleFormValues, initDefault } = useFormValues({ + getProps, + defaultValueRef, + getSchema, + formModel, + }); - return { - getBindValue, - handleToggleAdvanced, - handleEnterPress, - formModel, - defaultValueRef, - advanceState, - getRow, - getProps, - formElRef, - getSchema, - formActionType: formActionType as any, - setFormModel, - getFormClass, - getFormActionBindProps: computed(() => ({ ...getProps.value, ...advanceState })), - fieldsIsAdvancedMap, - ...formActionType, - }; + useAutoFocus({ + getSchema, + getProps, + isInitedDefault: isInitedDefaultRef, + formElRef: formElRef as Ref<FormActionType>, + }); + + const { + handleSubmit, + setFieldsValue, + clearValidate, + validate, + validateFields, + getFieldsValue, + updateSchema, + resetSchema, + appendSchemaByField, + removeSchemaByField, + resetFields, + scrollToField, + resetDefaultField, + } = useFormEvents({ + emit, + getProps, + formModel, + getSchema, + defaultValueRef, + formElRef: formElRef as Ref<FormActionType>, + schemaRef: schemaRef as Ref<FormSchema[]>, + handleFormValues, + }); + + createFormContext({ + resetAction: resetFields, + submitAction: handleSubmit, + }); + + watch( + () => unref(getProps).model, + () => { + const { model } = unref(getProps); + if (!model) return; + setFieldsValue(model); }, + { + immediate: true, + }, + ); + + watch( + () => props.schemas, + (schemas) => { + resetSchema(schemas ?? []); + }, + ); + + watch( + () => getSchema.value, + (schema) => { + nextTick(() => { + // Solve the problem of modal adaptive height calculation when the form is placed in the modal + modalFn?.redoModalHeight?.(); + }); + if (unref(isInitedDefaultRef)) { + return; + } + if (schema?.length) { + initDefault(); + isInitedDefaultRef.value = true; + } + }, + ); + + watch( + () => formModel, + useDebounceFn(() => { + unref(getProps).submitOnChange && handleSubmit(); + }, 300), + { deep: true }, + ); + + async function setProps(formProps: Partial<FormProps>): Promise<void> { + propsRef.value = deepMerge(unref(propsRef) || {}, formProps); + } + + function setFormModel(key: string, value: any, schema: FormSchema) { + formModel[key] = value; + emit('field-value-change', key, value); + // TODO 浼樺寲楠岃瘉锛岃繖閲屽鏋滄槸autoLink=false鎵嬪姩鍏宠仈鐨勬儏鍐典笅鎵嶄細鍐嶆瑙﹀彂姝ゅ嚱鏁� + if (schema && schema.itemProps && !schema.itemProps.autoLink) { + validateFields([key]).catch((_) => {}); + } + } + + function handleEnterPress(e: KeyboardEvent) { + const { autoSubmitOnEnter } = unref(getProps); + if (!autoSubmitOnEnter) return; + if (e.key === 'Enter' && e.target && e.target instanceof HTMLElement) { + const target: HTMLElement = e.target as HTMLElement; + if (target && target.tagName && target.tagName.toUpperCase() === 'INPUT') { + handleSubmit(); + } + } + } + + const formActionType = { + getFieldsValue, + setFieldsValue, + resetFields, + updateSchema, + resetSchema, + setProps, + removeSchemaByField, + appendSchemaByField, + clearValidate, + validateFields, + validate, + submit: handleSubmit, + scrollToField: scrollToField, + resetDefaultField, + }; + + const getFormActionBindProps = computed( + () => ({ ...getProps.value, ...advanceState }) as InstanceType<typeof FormAction>['$props'], + ); + + defineExpose({ + ...formActionType, + }); + + onMounted(() => { + initDefault(); + emit('register', formActionType); }); </script> <style lang="less"> @@ -311,21 +353,26 @@ margin: 0 6px 0 2px; } - &-with-help { - margin-bottom: 0; - } + // &-with-help { + // margin-bottom: 0; + // } - &:not(.ant-form-item-with-help) { - margin-bottom: 20px; - } + // &:not(.ant-form-item-with-help) { + // margin-bottom: 20px; + // } - &.suffix-item { + &.suffix-item, + &.prefix-item { .ant-form-item-children { display: flex; } - .ant-form-item-control { - margin-top: 4px; + .prefix { + display: inline-flex; + align-items: center; + margin-top: 1px; + padding-right: 6px; + line-height: 1; } .suffix { -- Gitblit v1.9.3