wms-antdvue/.svn/pristine/21/21b9e454f3bd1656dd029a36b13766029a325999.svn-base
2024-11-07 16:33:03 +08:00

359 lines
9.7 KiB
Plaintext

<template>
<a-form v-bind="getBindValue" :model="formModel" ref="formElRef">
<a-row v-bind="getRow">
<a-col
v-bind="!schema.colProps ? getCol : schema.colProps"
v-for="schema in getSchema"
:key="schema.name"
>
<a-form-item
:label="schema.labelMessage ? null : schema.label"
:name="schema.name"
v-if="!getHidden(schema)"
>
<!--标签名右侧温馨提示-->
<template #label v-if="schema.labelMessage">
{{ schema.label }}
<a-tooltip trigger="hover" :style="schema.labelMessageStyle">
<span class="text-gray-400 cursor-pointer mx-1">
<QuestionCircleOutlined />
</span>
<template #title>{{ schema.labelMessage }}</template>
</a-tooltip>
</template>
<!--判断插槽-->
<template v-if="schema.slot">
<slot
:name="schema.slot"
:model="formModel"
:field="schema.name"
:value="formModel[schema.name]"
></slot>
</template>
<!--Checkbox-->
<template v-else-if="schema.component === 'Checkbox'">
<a-checkbox-group
v-bind="getSpecComponentProps(schema)"
v-model:value="formModel[schema.name]"
>
<a-space>
<a-checkbox
v-for="item in schema.componentProps?.options"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</a-space>
</a-checkbox-group>
</template>
<!--RadioGroup-->
<template v-else-if="schema.component === 'RadioGroup'">
<a-radio-group
v-bind="getSpecComponentProps(schema)"
v-model:value="formModel[schema.name]"
>
<a-space>
<a-radio
v-for="item in schema.componentProps?.options"
:key="item.value"
:value="item.value"
>
{{ item.label }}
</a-radio>
</a-space>
</a-radio-group>
</template>
<!--BasicSelect-->
<template v-else-if="schema.component === 'BasicSelect'">
<BasicSelect v-model:value="formModel[schema.name]" v-bind="schema.componentProps" />
</template>
<!--动态渲染表单组件-->
<component
v-else
v-bind="getComponentProps(schema)"
:is="`a-${schema.component}`"
v-model:value="formModel[schema.name]"
:class="{ isFull: schema.isFull != false && getProps.isFull }"
/>
<!--组件后面的内容-->
<template v-if="schema.suffix">
<slot
:name="schema.suffix"
:model="formModel"
:field="schema.name"
:value="formModel[schema.name]"
></slot>
</template>
</a-form-item>
</a-col>
<!--提交 重置 展开收起 后期实现 -->
<a-col
v-bind="getActionCol"
:style="getProps.actionStyle"
v-if="getProps.showActionButtonGroup"
class="pl-0 pr-0"
>
<a-button
v-if="getProps.showSubmitButton"
v-bind="getSubmitBtnOptions"
@click="handleSubmit"
:loading="loadingSub"
class="mr-2"
>
<template #icon>
<SearchOutlined />
</template>
{{ getProps.submitButtonText }}</a-button
>
<a-button
v-if="getProps.showResetButton"
v-bind="getResetBtnOptions"
@click="resetFields"
>{{ getProps.resetButtonText }}</a-button
>
</a-col>
</a-row>
</a-form>
</template>
<script lang="ts" setup>
import { reactive, ref, useAttrs, computed, unref, onMounted, watch } from 'vue';
import { createPlaceholderMessage } from './helper';
import { useFormEvents } from './hooks/useFormEvents';
import { useFormValues } from './hooks/useFormValues';
import { BasicSelect } from '@/components/Select';
import { basicProps } from './props';
import { QuestionCircleOutlined,SearchOutlined } from '@ant-design/icons-vue';
import type { Ref } from 'vue';
import type { FormSchema, FormProps, FormActionType } from './types/form';
import { isArray, isBoolean, isFunction } from '@/utils/is/index';
import { deepMerge } from '@/utils';
import { Form } from 'ant-design-vue';
const useForm = Form.useForm;
const props = defineProps({ ...basicProps });
const emit = defineEmits(['reset', 'submit', 'register', 'advanced']);
const attrs = useAttrs();
const defaultFormModel = ref<Recordable>({});
const formModel = reactive<Recordable>({});
const propsRef = ref<Partial<FormProps>>({});
const schemaRef = ref<Nullable<FormSchema[]>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const loadingSub = ref(false);
const isUpdateDefaultRef = ref(false);
const getSubmitBtnOptions = computed(() => {
return Object.assign(
{
size: props.size,
type: 'primary',
},
props.submitButtonOptions,
);
});
const getResetBtnOptions = computed(() => {
return Object.assign(
{
size: props.size,
type: 'default',
},
props.resetButtonOptions,
);
});
function getComponentProps(schema) {
const compProps = schema.componentProps ?? {};
const component = schema.component;
return {
clearable: true,
placeholder: createPlaceholderMessage(unref(component)),
...compProps,
};
}
function getHidden(schema): boolean {
const hidden = schema.hidden;
const field = schema.field;
if (isBoolean(hidden)) return hidden;
if (isFunction(hidden)) {
const values = getFieldsValue();
const status = hidden({ schema, values, model: formModel, field });
return status;
}
return false;
}
function getSpecComponentProps(schema) {
const compProps = schema.componentProps ?? {};
return {
...compProps,
};
}
const getProps = computed((): FormProps => {
const formProps = { ...props, ...unref(propsRef) } as FormProps;
const rulesObj: any = {
rules: {},
};
const schemas: any = formProps.schemas || [];
schemas.forEach((item) => {
if (item.rules && isArray(item.rules)) {
rulesObj.rules[item.name] = item.rules;
}
});
return { ...formProps, ...unref(rulesObj) };
});
const isVertical = computed(() => {
const { layout } = unref(getProps);
return layout === 'vertical';
});
const getActionCol = computed(() => {
let colObj = {};
const { labelCol, actInheritLabelCol, colProps } = unref(getProps);
if (!actInheritLabelCol) {
colObj = {
...colProps,
};
} else {
if (labelCol && !unref(isVertical)) {
let leftSpan: any = labelCol?.span || 0;
colObj = {
span: 24 - leftSpan,
offset: labelCol?.span,
};
}
}
return colObj;
});
const getRow = computed(() => {
const { rowProps } = unref(getProps);
return {
...rowProps,
};
});
const getCol = computed(() => {
const { colProps } = unref(getProps);
return {
...colProps,
};
});
const getBindValue = computed(() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable));
const getSchema = computed((): FormSchema[] => {
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any);
for (const schema of schemas) {
const { defaultValue } = schema;
// handle date type
// dateItemType.includes(component as string)
if (defaultValue) {
schema.defaultValue = defaultValue;
}
}
return schemas as FormSchema[];
});
const getFormRules = computed(() => {
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any);
const rulesObj = {};
for (const schema of schemas) {
if (schema.rules) {
rulesObj[schema.name] = schema.rules;
}
}
return rulesObj;
});
const formRules = reactive<Recordable>(getFormRules.value);
const { handleFormValues, initDefault } = useFormValues({
defaultFormModel,
getSchema,
formModel,
});
const { handleSubmit, validate, resetFields, getFieldsValue, clearValidate, setFieldsValue } =
useFormEvents({
emit,
getProps,
formModel,
getSchema,
formElRef: formElRef as Ref<FormActionType>,
defaultFormModel,
loadingSub,
handleFormValues,
});
async function setProps(formProps: Partial<FormProps>): Promise<void> {
propsRef.value = deepMerge(unref(propsRef) || {}, formProps);
}
async function setSchema(schemaProps: FormSchema[]): Promise<void> {
schemaRef.value = schemaProps;
}
const { validateInfos, mergeValidateInfo } = useForm(formModel, formRules);
const formActionType: Partial<FormActionType> = {
validateInfos,
mergeValidateInfo,
getFieldsValue,
setFieldsValue,
resetFields,
validate,
clearValidate,
setProps,
setSchema,
submit: handleSubmit,
};
watch(
() => getSchema.value,
(schema) => {
if (unref(isUpdateDefaultRef)) {
return;
}
if (schema?.length) {
initDefault();
isUpdateDefaultRef.value = true;
}
},
);
defineExpose({
...formActionType,
});
onMounted(() => {
initDefault();
emit('register', formActionType);
});
</script>
<style lang="less" scoped>
.isFull {
width: 100%;
justify-content: flex-start;
}
.unfold-icon {
margin-left: 5px;
}
</style>