fix: 提供SimpleForm的选项式写法以便二开
This commit is contained in:
@ -119,7 +119,8 @@ tabStore.closeTab(currentRoute, router);
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SimpleForm from '/@/components/SimpleForm/src/SimpleForm.vue';
|
// 注意,这里继承的是SimpleFormSetup,使用sciprt setup写法的组件无法继承,必须使用特别的版本
|
||||||
|
import SimpleFormSetup from '/@/components/SimpleForm/src/SimpleFormSetup.vue';
|
||||||
import { Col, Form, Row } from 'ant-design-vue';
|
import { Col, Form, Row } from 'ant-design-vue';
|
||||||
import SimpleFormItem from '/@/components/SimpleForm/src/components/SimpleFormItem.vue';
|
import SimpleFormItem from '/@/components/SimpleForm/src/components/SimpleFormItem.vue';
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ const FormItem = Form.Item;
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { Form, Col, SimpleFormItem, Row, FormItem },
|
components: { Form, Col, SimpleFormItem, Row, FormItem },
|
||||||
mixins: [SimpleForm],
|
mixins: [SimpleFormSetup],
|
||||||
setup(props, ctx) {
|
setup(props, ctx) {
|
||||||
const ret = SimpleForm.setup(props, ctx);
|
const ret = SimpleForm.setup(props, ctx);
|
||||||
const schemaMap = {};
|
const schemaMap = {};
|
||||||
@ -218,7 +219,7 @@ export default {
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
setup(props, ctx) {
|
setup(props, ctx) {
|
||||||
const ret = SimpleForm.setup(props, ctx);
|
const ret = SimpleFormSetup.setup(props, ctx);
|
||||||
const schemaMap = {};
|
const schemaMap = {};
|
||||||
const cascadeData = ref([]);
|
const cascadeData = ref([]);
|
||||||
const cascadeValue = ref([]);
|
const cascadeValue = ref([]);
|
||||||
|
|||||||
696
src/components/SimpleForm/src/SimpleFormSetup.vue
Normal file
696
src/components/SimpleForm/src/SimpleFormSetup.vue
Normal file
@ -0,0 +1,696 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="formWrap">
|
||||||
|
<Form ref="formRef" :label-col="getProps?.labelCol" :labelAlign="getProps?.labelAlign" :layout="getProps?.layout" :model="formModel" :wrapper-col="getProps?.wrapperCol" @keypress.enter="handleEnterPress">
|
||||||
|
<Row v-bind="getRow">
|
||||||
|
<template v-for="schema in getSchemas" :key="schema.field">
|
||||||
|
<Col v-if="getIfShow(schema, formModel[schema.field])" v-show="getIsShow(schema, formModel[schema.field])" :span="getColWidth(schema)">
|
||||||
|
<div v-if="schema?.componentProps.respBreakLine" style="width: 100%; height: 1px"></div>
|
||||||
|
<template v-if="showComponent(schema) && schema.type !== 'slot'">
|
||||||
|
<SimpleFormItem v-model:value="formModel[schema.field]" :form-api="formApi" :isWorkFlow="isWorkFlow" :refreshFieldObj="refreshFieldObj" :schema="schema" />
|
||||||
|
</template>
|
||||||
|
<template v-if="schema.type === 'slot'">
|
||||||
|
<slot :formModel="formModel" :name="schema.slotName" :schema="schema"></slot>
|
||||||
|
</template>
|
||||||
|
</Col>
|
||||||
|
</template>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<div :style="{ textAlign: getProps.buttonLocation }">
|
||||||
|
<slot name="buttonBefore"></slot>
|
||||||
|
|
||||||
|
<a-button v-if="getProps.showSubmitButton" type="primary" @click="handleSubmit">
|
||||||
|
{{ t('提交') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button v-if="getProps.showResetButton" style="margin-left: 10px" @click="handleReset">
|
||||||
|
{{ t('重置') }}
|
||||||
|
</a-button>
|
||||||
|
<slot name="buttonAfter"></slot>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { Form, FormInstance, Row, Col, Modal, message } from 'ant-design-vue';
|
||||||
|
import { cloneDeep, isArray, isBoolean, isFunction, isObject, isString, uniqBy, isNil, debounce } from 'lodash-es';
|
||||||
|
import { computed, reactive, ref, provide, unref, nextTick, toRaw, createVNode, inject, onMounted, onUnmounted } from 'vue';
|
||||||
|
import { CardComponentProps, FormActionType, FormProps, FormSchema, GridComponentProps, TabComponentProps, regTestProps, requestProps } from '../../Form/src/types/form';
|
||||||
|
import SimpleFormItem from './components/SimpleFormItem.vue';
|
||||||
|
import { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
|
||||||
|
import { arrayValueComponents, defaultValueComponents, staticDataComponents, noFieldComponent, noDefaultValueComponents, noShowWorkFlowComponents, noShowGenerateComponents } from '../../Form/src/helper';
|
||||||
|
import { deepMerge } from '/@/utils';
|
||||||
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
|
import type { ModalFuncProps } from 'ant-design-vue/lib/modal/Modal';
|
||||||
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
import { needDicDefaultValue } from '../../Designer/src/types';
|
||||||
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
import { camelCaseString } from '/@/utils/event/design';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { notification } = useMessage();
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { Form, Row, Col, Modal, SimpleFormItem },
|
||||||
|
props: {
|
||||||
|
// 表单配置规则
|
||||||
|
formProps: {
|
||||||
|
type: Object as PropType<FormProps>
|
||||||
|
},
|
||||||
|
//表单数据
|
||||||
|
formModel: {
|
||||||
|
type: Object as PropType<Recordable>,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
//是否是工作流
|
||||||
|
isWorkFlow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
//是否系统表单需要转驼峰,兼容旧系统表单
|
||||||
|
isCamelCase: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 自定义监听 用于以编码开发的形式替代json配置中的change事件
|
||||||
|
watches: {
|
||||||
|
type: Array
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['submit'],
|
||||||
|
setup(props, { attrs, slots, emit, expose }) {
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const formWrap = ref<HTMLElement>();
|
||||||
|
const wrapWidth = ref(960);
|
||||||
|
const propsRef = ref<Partial<FormProps>>({});
|
||||||
|
const schemaRef = ref<Nullable<FormSchema[]>>(null);
|
||||||
|
|
||||||
|
const getSchemas = computed<FormSchema[]>(() => {
|
||||||
|
return (unref(getProps).schemas as any) || unref(schemaRef);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get the basic configuration of the form
|
||||||
|
const getProps = computed((): FormProps => {
|
||||||
|
return { ...(props.formProps as FormProps), ...unref(propsRef) } as FormProps;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get uniform row style and Row configuration for the entire form
|
||||||
|
const getRow = computed((): Recordable => {
|
||||||
|
const { baseRowStyle = {}, rowProps } = props.formProps!;
|
||||||
|
|
||||||
|
return {
|
||||||
|
style: baseRowStyle,
|
||||||
|
...rowProps
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function getWrapSize() {
|
||||||
|
const rect = formWrap.value?.getBoundingClientRect();
|
||||||
|
wrapWidth.value = rect?.width || 960;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColWidth(schema: any) {
|
||||||
|
const compProps = schema.componentProps;
|
||||||
|
if (compProps?.responsive) {
|
||||||
|
if (compProps.respNewRow) {
|
||||||
|
return 24; // 响应式布局下独立成行
|
||||||
|
} else {
|
||||||
|
const wrapValue = wrapWidth.value;
|
||||||
|
if (wrapValue > import.meta.env.VITE_RESP_LG_WIDTH) {
|
||||||
|
return 8;
|
||||||
|
} else if (wrapValue > import.meta.env.VITE_RESP_MD_WIDTH) {
|
||||||
|
return 12;
|
||||||
|
} else {
|
||||||
|
return 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return schema.colProps?.span;
|
||||||
|
}
|
||||||
|
|
||||||
|
const debGetWrapSize = debounce(getWrapSize, 300);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener('resize', debGetWrapSize);
|
||||||
|
getWrapSize();
|
||||||
|
nextTick(() => {
|
||||||
|
//添加隐藏组件
|
||||||
|
if (unref(getProps)?.hiddenComponent?.length) {
|
||||||
|
unref(getProps)?.hiddenComponent?.forEach((component) => {
|
||||||
|
formModel[component.bindField] = component.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', debGetWrapSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
function showComponent(schema) {
|
||||||
|
return props.isWorkFlow ? !noShowWorkFlowComponents.includes(schema.type) : !noShowGenerateComponents.includes(schema.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIsShow(schema: FormSchema, itemValue: any): boolean {
|
||||||
|
const { show } = schema;
|
||||||
|
const { showAdvancedButton } = getProps.value;
|
||||||
|
const itemIsAdvanced = showAdvancedButton ? (isBoolean(schema.isAdvanced) ? schema.isAdvanced : true) : true;
|
||||||
|
|
||||||
|
let isShow = true;
|
||||||
|
|
||||||
|
if (isBoolean(show)) {
|
||||||
|
isShow = show;
|
||||||
|
}
|
||||||
|
if (isFunction(show)) {
|
||||||
|
isShow = show({
|
||||||
|
values: itemValue,
|
||||||
|
model: formModel!,
|
||||||
|
schema: schema,
|
||||||
|
field: schema.field
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isShow = isShow && itemIsAdvanced;
|
||||||
|
return isShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIfShow(schema: FormSchema, itemValue: any): boolean {
|
||||||
|
const { ifShow } = schema;
|
||||||
|
|
||||||
|
let isIfShow = true;
|
||||||
|
|
||||||
|
if (isBoolean(ifShow)) {
|
||||||
|
isIfShow = ifShow;
|
||||||
|
}
|
||||||
|
if (isFunction(ifShow)) {
|
||||||
|
isIfShow = ifShow({
|
||||||
|
values: itemValue,
|
||||||
|
model: formModel!,
|
||||||
|
schema: schema,
|
||||||
|
field: schema.field
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return isIfShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formModel = reactive<Recordable>(props.formModel);
|
||||||
|
const isCustom = inject<boolean>('isCustomForm', false);
|
||||||
|
provide('formModel', formModel);
|
||||||
|
provide('formProps', getProps);
|
||||||
|
provide('isCustomForm', isCustom || props.isWorkFlow);
|
||||||
|
provide('isCamelCase', props.isCamelCase);
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
const { submitFunc } = unref(getProps);
|
||||||
|
if (submitFunc && isFunction(submitFunc)) {
|
||||||
|
await submitFunc();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await formRef.value!.validate();
|
||||||
|
emit('submit', res);
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshFieldObj = ref<object>({});
|
||||||
|
|
||||||
|
getComponent(getSchemas.value);
|
||||||
|
|
||||||
|
function getComponent(component) {
|
||||||
|
const layoutComponents = ['tab', 'grid', 'card'];
|
||||||
|
component?.map((info) => {
|
||||||
|
if (layoutComponents.includes(info.type!)) {
|
||||||
|
info.children?.map((childInfo) => {
|
||||||
|
childInfo.list.map((com) => {
|
||||||
|
if (layoutComponents.includes(com.type) || com.type === 'table-layout') {
|
||||||
|
getComponent(childInfo.list);
|
||||||
|
} else {
|
||||||
|
setComponentDefault(com);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (info.type === 'table-layout') {
|
||||||
|
info.children?.map((childInfo) => {
|
||||||
|
childInfo.list.map((com) => {
|
||||||
|
com.children.map((item) => {
|
||||||
|
if (layoutComponents.includes(item.type) || item.type === 'table-layout') {
|
||||||
|
getComponent(com.children);
|
||||||
|
} else {
|
||||||
|
setComponentDefault(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setComponentDefault(info);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setComponentDefault(item) {
|
||||||
|
if ((staticDataComponents.includes(item.component) && (item.componentProps as any)?.datasourceType === 'staticData') || (needDicDefaultValue.includes(item.type) && (item.componentProps as any)?.datasourceType === 'dic')) {
|
||||||
|
let { defaultSelect } = item.componentProps as any;
|
||||||
|
formModel[item.field] = defaultSelect;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let { defaultValue } = item;
|
||||||
|
if (!!item.field && !noDefaultValueComponents.includes(item.component)) {
|
||||||
|
if (item.component === 'OneForOne') {
|
||||||
|
if (item.componentProps.childSchemas?.length) {
|
||||||
|
const singleFormObj = {};
|
||||||
|
item.componentProps.childSchemas.map((singleCom) => {
|
||||||
|
if (
|
||||||
|
(staticDataComponents.includes(singleCom.component) && (singleCom.componentProps as any)?.datasourceType === 'staticData') ||
|
||||||
|
(needDicDefaultValue.includes(singleCom.type) && (singleCom.componentProps as any)?.datasourceType === 'dic')
|
||||||
|
) {
|
||||||
|
let { defaultSelect } = singleCom.componentProps as any;
|
||||||
|
singleFormObj[singleCom.field] = defaultSelect;
|
||||||
|
} else {
|
||||||
|
singleFormObj[singleCom.field] = singleCom.defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formModel[item.field] = [singleFormObj];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
formModel[item.field] = item.component === 'SubForm' ? [] : defaultValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回车提交表单
|
||||||
|
*/
|
||||||
|
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 validate = async (nameList?: NamePath[]): Promise<any> => formRef.value?.validate(nameList);
|
||||||
|
|
||||||
|
//清除表单验证
|
||||||
|
const clearValidate = async (name?: string | string[]): Promise<any> => formRef.value?.clearValidate(name);
|
||||||
|
|
||||||
|
//跳到某个字段
|
||||||
|
const scrollToField = async (name: NamePath, options?: ScrollOptions): Promise<any> => formRef.value?.scrollToField(name, options);
|
||||||
|
|
||||||
|
//验证某个字段
|
||||||
|
const validateFields = async (nameList?: NamePath[] | string, options?: ValidateOptions): Promise<any> => formRef.value?.validateFields(nameList, options);
|
||||||
|
|
||||||
|
const findSchema = (schemaArr, key) => {
|
||||||
|
let schema;
|
||||||
|
const formListComponent = ['tab', 'grid', 'card'];
|
||||||
|
schemaArr?.some((info) => {
|
||||||
|
if (formListComponent.includes(info.type!)) {
|
||||||
|
const hasComponent = info.children.some((childInfo) => {
|
||||||
|
schema = childInfo.list.find((com) => com.field === key);
|
||||||
|
if (!!schema) return true;
|
||||||
|
schema = findSchema(childInfo.list, key);
|
||||||
|
return !!schema;
|
||||||
|
});
|
||||||
|
return !!hasComponent;
|
||||||
|
} else if (info.type === 'table-layout') {
|
||||||
|
const hasComponent = info.children.some((childInfo) => {
|
||||||
|
return childInfo.list.some((chil) => {
|
||||||
|
schema = chil.children.find((com) => com.field === key);
|
||||||
|
if (!!schema) return true;
|
||||||
|
schema = findSchema(chil.children, key);
|
||||||
|
return !!schema;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return !!hasComponent;
|
||||||
|
} else {
|
||||||
|
schema = info.field === key ? info : null;
|
||||||
|
return !!schema;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setDefaultValue = async (): Promise<void> => {
|
||||||
|
getComponent(getSchemas.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置表单所有数据
|
||||||
|
const resetFields = async (): Promise<void> => {
|
||||||
|
Object.keys(formModel).forEach((key) => {
|
||||||
|
//没有绑定字段的组件不处理
|
||||||
|
if (!key) return;
|
||||||
|
const schema = findSchema(unref(getSchemas), key);
|
||||||
|
|
||||||
|
const isInput = schema?.component && defaultValueComponents.includes(schema.component);
|
||||||
|
const isSubForm = schema?.component && arrayValueComponents.includes(schema.component);
|
||||||
|
const isRange = schema?.component && schema?.component.includes('Range');
|
||||||
|
const isStatic = schema?.component && staticDataComponents.includes(schema.component) && schema?.componentProps.datasourceType === 'staticData';
|
||||||
|
const isDic = schema?.type && needDicDefaultValue.includes(schema.type) && schema?.componentProps.datasourceType === 'dic';
|
||||||
|
|
||||||
|
if (isSubForm) {
|
||||||
|
if (schema.component === 'OneForOne') {
|
||||||
|
if (schema.componentProps.childSchemas?.length) {
|
||||||
|
const singleFormObj = {};
|
||||||
|
schema.componentProps.childSchemas.map((singleCom) => {
|
||||||
|
if (
|
||||||
|
(staticDataComponents.includes(singleCom.component) && singleCom?.componentProps.datasourceType === 'staticData') ||
|
||||||
|
(needDicDefaultValue.includes(singleCom.type) && singleCom?.componentProps.datasourceType === 'dic')
|
||||||
|
) {
|
||||||
|
singleFormObj[singleCom.field] = singleCom?.componentProps.defaultSelect;
|
||||||
|
} else {
|
||||||
|
singleFormObj[singleCom.field] = singleCom.defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formModel[key] = [singleFormObj];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formModel[key] = [];
|
||||||
|
}
|
||||||
|
} else if (isInput) {
|
||||||
|
formModel[key] = schema?.defaultValue || '';
|
||||||
|
} else if (isRange) {
|
||||||
|
const startTimeKey = key.split(',')[0];
|
||||||
|
const endTimeKey = key.split(',')[1];
|
||||||
|
formModel[key] = schema?.defaultValue || [];
|
||||||
|
formModel[startTimeKey] = schema?.defaultValue && schema?.defaultValue.length > 0 && schema?.defaultValue[0];
|
||||||
|
formModel[endTimeKey] = schema?.defaultValue && schema?.defaultValue.length > 0 && schema?.defaultValue[1];
|
||||||
|
} else if (isStatic || isDic) {
|
||||||
|
formModel[key] = schema?.componentProps.defaultSelect;
|
||||||
|
} else {
|
||||||
|
formModel[key] = schema?.defaultValue || schema?.defaultValue === 0 ? schema?.defaultValue : '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
nextTick(() => clearValidate());
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更改formProps
|
||||||
|
const setProps = async (formProps: Partial<FormProps>): Promise<void> => {
|
||||||
|
propsRef.value = deepMerge(unref(propsRef) || {}, formProps);
|
||||||
|
};
|
||||||
|
|
||||||
|
//设定某个字段值 慎用 建议直接页面直接操作formModel数据
|
||||||
|
const setFieldsValue = async (values: Recordable): Promise<void> => {
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
if (!isNil(key)) {
|
||||||
|
formModel[key] = values[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
executeEvent(getSchemas.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行schema中 所有change事件
|
||||||
|
* 修改bug #5090
|
||||||
|
* 为了保证表单赋值触发所有组件的change事件
|
||||||
|
*/
|
||||||
|
const executeEvent = (allSchemas: FormSchema[]) => {
|
||||||
|
for (const schema of allSchemas) {
|
||||||
|
//如果是这几个组件 需要查询子级
|
||||||
|
if (['Card', 'Tab', 'Grid'].includes(schema.component)) {
|
||||||
|
if (schema.component === 'Tab') {
|
||||||
|
for (const child of schema.children as TabComponentProps[]) {
|
||||||
|
executeEvent(child.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema.component === 'Card') {
|
||||||
|
for (const child of schema.children as CardComponentProps[]) {
|
||||||
|
executeEvent(child.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema.component === 'Grid') {
|
||||||
|
for (const child of schema.children as GridComponentProps[]) {
|
||||||
|
executeEvent(child.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (schema.componentProps?.['events']) {
|
||||||
|
for (const eventKey in schema.componentProps['events']) {
|
||||||
|
if (eventKey !== 'change') return;
|
||||||
|
try {
|
||||||
|
const event = new Function('schema', 'formModel', 'formActionType', `${schema.componentProps['events'][eventKey]}`);
|
||||||
|
event(schema, formModel, formApi);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('error', error);
|
||||||
|
notification.error({
|
||||||
|
message: 'Tip',
|
||||||
|
description: '触发事件填写有误!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//获取表单值 慎用 建议直接页面直接操作formModel数据
|
||||||
|
const getFieldsValue = (): Recordable => {
|
||||||
|
return toRaw(unref(formModel));
|
||||||
|
};
|
||||||
|
|
||||||
|
//更新schema
|
||||||
|
const updateSchema = async (data: Partial<FormSchema> | Partial<FormSchema>[]): Promise<void> => {
|
||||||
|
let updateData: Partial<FormSchema>[] = [];
|
||||||
|
if (isObject(data)) {
|
||||||
|
updateData.push(data as FormSchema);
|
||||||
|
}
|
||||||
|
if (isArray(data)) {
|
||||||
|
updateData = [...data];
|
||||||
|
}
|
||||||
|
const hasField = updateData.every((item) => noFieldComponent.includes(item.component!) || (Reflect.has(item, 'field') && item.field));
|
||||||
|
if (!hasField) {
|
||||||
|
throw new Error('All children of the form Schema array that need to be updated must contain the `field` field');
|
||||||
|
}
|
||||||
|
const schema: FormSchema[] = [];
|
||||||
|
updateData.forEach((item: FormSchema) => {
|
||||||
|
unref(getSchemas).forEach((val: FormSchema) => {
|
||||||
|
//如果当前组件是布局组件 需要去child 里面更新
|
||||||
|
if (['Card', 'Tab', 'Grid'].includes(val.component)) {
|
||||||
|
deepEachChild(val.children!, item);
|
||||||
|
} else {
|
||||||
|
if (val.key && item.key && val.key === item.key) {
|
||||||
|
const newSchema = deepMerge(val, item);
|
||||||
|
schema.push(newSchema as FormSchema);
|
||||||
|
} else if (val.field === item.field) {
|
||||||
|
const newSchema = deepMerge(val, item);
|
||||||
|
schema.push(newSchema as FormSchema);
|
||||||
|
} else {
|
||||||
|
schema.push(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
schemaRef.value = uniqBy(schema, 'field');
|
||||||
|
};
|
||||||
|
const deepEachChild = (childs: GridComponentProps[] | TabComponentProps[] | CardComponentProps[], thisItem: FormSchema) => {
|
||||||
|
childs?.forEach((child: GridComponentProps | CardComponentProps | TabComponentProps) => {
|
||||||
|
child.list.forEach((it: FormSchema) => {
|
||||||
|
if (['Card', 'Tab', 'Grid'].includes(it.component)) {
|
||||||
|
deepEachChild(it.children!, thisItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisItem.key && it.key && thisItem.key === it.key) {
|
||||||
|
it = deepMerge(it, thisItem);
|
||||||
|
} else if (thisItem.field === it.field) {
|
||||||
|
it = deepMerge(it, thisItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//重置schema
|
||||||
|
const resetSchema = async (data: Partial<FormSchema> | Partial<FormSchema>[]): Promise<void> => {
|
||||||
|
let updateData: Partial<FormSchema>[] = [];
|
||||||
|
if (isObject(data)) {
|
||||||
|
updateData.push(data as FormSchema);
|
||||||
|
}
|
||||||
|
if (isArray(data)) {
|
||||||
|
updateData = [...data];
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasField = updateData.every((item) => noFieldComponent.includes(item.component!) || (Reflect.has(item, 'field') && item.field));
|
||||||
|
if (!hasField) {
|
||||||
|
throw new Error('All children of the form Schema array that need to be updated must contain the `field` field');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaRef.value = updateData as FormSchema[];
|
||||||
|
};
|
||||||
|
//移除schema
|
||||||
|
const removeSchemaByFiled = async (fields: string | string[]): Promise<void> => {
|
||||||
|
const schemaList: FormSchema[] = cloneDeep(unref(getSchemas));
|
||||||
|
if (!fields) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fieldList: string[] = isString(fields) ? [fields] : fields;
|
||||||
|
if (isString(fields)) {
|
||||||
|
fieldList = [fields];
|
||||||
|
}
|
||||||
|
for (const field of fieldList) {
|
||||||
|
if (isString(field)) {
|
||||||
|
const index = schemaList.findIndex((schema) => schema.field === field);
|
||||||
|
if (index !== -1) {
|
||||||
|
delete formModel[field];
|
||||||
|
schemaList.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schemaRef.value = schemaList;
|
||||||
|
};
|
||||||
|
//追加schema
|
||||||
|
const appendSchemaByField = async (schema: FormSchema, prefixField: string | undefined, first?: boolean | undefined): Promise<void> => {
|
||||||
|
const schemaList: FormSchema[] = cloneDeep(unref(getSchemas));
|
||||||
|
|
||||||
|
const index = schemaList.findIndex((schema) => schema.field === prefixField);
|
||||||
|
if (!prefixField || index === -1 || first) {
|
||||||
|
first ? schemaList.unshift(schema) : schemaList.push(schema);
|
||||||
|
schemaRef.value = schemaList;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (index !== -1) {
|
||||||
|
schemaList.splice(index + 1, 0, schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaRef.value = schemaList;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submit = async (e?: Event): Promise<void> => {
|
||||||
|
e && e.preventDefault();
|
||||||
|
const { submitFunc } = unref(getProps);
|
||||||
|
if (submitFunc && isFunction(submitFunc)) {
|
||||||
|
await submitFunc();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const formEl = unref(formRef);
|
||||||
|
if (!formEl) return;
|
||||||
|
try {
|
||||||
|
const values = await validate();
|
||||||
|
emit('submit', values);
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const showModal = async (modal: ModalFuncProps) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: modal.title,
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
content: createVNode('div', { style: 'color:red;' }, modal.content),
|
||||||
|
onOk: modal.onOk,
|
||||||
|
onCancel: modal.onCancel,
|
||||||
|
...modal
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const regTest = async (regular: regTestProps) => {
|
||||||
|
const regExpression = regular.regExpression;
|
||||||
|
const testRes = regExpression.test(regular.testValue);
|
||||||
|
testRes ? message.success(regular.successMessage) : message.error(regular.errorMessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const httpRequest = async (request: requestProps) => {
|
||||||
|
if (request.requestType.toLowerCase() === 'get') {
|
||||||
|
return defHttp[request.requestType](
|
||||||
|
{
|
||||||
|
url: request.requestUrl,
|
||||||
|
params: request.params
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorMessageMode: request.errorMessageMode || 'none'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return defHttp[request.requestType](
|
||||||
|
{
|
||||||
|
url: request.requestUrl,
|
||||||
|
data: request.params
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorMessageMode: request.errorMessageMode || 'none'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshAPI = (field: string) => {
|
||||||
|
if (!field) return;
|
||||||
|
if (!Object.keys(unref(refreshFieldObj)).includes(field)) {
|
||||||
|
unref(refreshFieldObj)[field] = 0;
|
||||||
|
}
|
||||||
|
unref(refreshFieldObj)[field]++;
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeStyle = (schema, style, field?) => {
|
||||||
|
if (field) {
|
||||||
|
const changeSchema = unref(getSchemas).filter((item) => {
|
||||||
|
if (props.isCamelCase) {
|
||||||
|
return camelCaseString(item.field) === field;
|
||||||
|
} else {
|
||||||
|
return item.field === field;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
schema = changeSchema[0];
|
||||||
|
}
|
||||||
|
schema.componentProps.style = { ...schema.componentProps.style, ...style };
|
||||||
|
};
|
||||||
|
|
||||||
|
const formApi: FormActionType = {
|
||||||
|
submit,
|
||||||
|
validate,
|
||||||
|
clearValidate,
|
||||||
|
scrollToField,
|
||||||
|
validateFields,
|
||||||
|
resetFields,
|
||||||
|
setProps,
|
||||||
|
updateSchema,
|
||||||
|
setFieldsValue,
|
||||||
|
getFieldsValue,
|
||||||
|
removeSchemaByFiled,
|
||||||
|
appendSchemaByField,
|
||||||
|
resetSchema,
|
||||||
|
showModal,
|
||||||
|
regTest,
|
||||||
|
httpRequest,
|
||||||
|
refreshAPI,
|
||||||
|
changeStyle,
|
||||||
|
setDefaultValue
|
||||||
|
};
|
||||||
|
|
||||||
|
//将表单方法 导出 给父组件使用。
|
||||||
|
expose({
|
||||||
|
...formApi
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
getRow,
|
||||||
|
getProps,
|
||||||
|
getSchemas,
|
||||||
|
getIfShow,
|
||||||
|
getIsShow,
|
||||||
|
getColWidth,
|
||||||
|
showComponent,
|
||||||
|
formApi,
|
||||||
|
refreshFieldObj,
|
||||||
|
handleSubmit,
|
||||||
|
t,
|
||||||
|
handleReset,
|
||||||
|
handleEnterPress,
|
||||||
|
formRef,
|
||||||
|
formWrap
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user