¶Ô±ÈÐÂÎļþ |
| | |
| | | // import { ElInput } from "element-plus"; |
| | | import { |
| | | defineComponent, |
| | | PropType, |
| | | ref, |
| | | Ref, |
| | | SetupContext, |
| | | computed, |
| | | unref, |
| | | markRaw, |
| | | DefineComponent, |
| | | } from 'vue' |
| | | import styles from './DyForm.module.scss' |
| | | import ElInput from 'element-plus/es/components/input/index' |
| | | import Option from '@/components/Select/Option' |
| | | import Select from '@/components/Select/Select' |
| | | import SelectInput from '@/components/SelectInput/SelectInput' |
| | | import type { FormInstance } from 'element-plus' |
| | | import Icon from '../Icon/Icon' |
| | | import { |
| | | FormPropsType, |
| | | FormItemPropType, |
| | | PropsType, |
| | | OptionItemType, |
| | | } from './DyForm.d' |
| | | import Variable from '../Variable/Variable' |
| | | import Title from '../Title/Title' |
| | | import TextareaFlow from '../Flow/Flow' |
| | | import get from 'lodash/get' |
| | | import set from 'lodash/set' |
| | | |
| | | const formItemElementMap = markRaw<Record<string, any>>({ |
| | | input: ElInput, |
| | | select: Select, |
| | | selectInput: SelectInput, |
| | | variable: Variable, |
| | | textareaFlow: TextareaFlow, |
| | | }) |
| | | |
| | | const Type: Record<string, any> = { |
| | | select: 'select', |
| | | } |
| | | export default defineComponent<FormPropsType>({ |
| | | //@ts-ignore |
| | | name: 'å¨æè¡¨å', |
| | | props: { |
| | | labelWidth: { |
| | | type: String, |
| | | default: '100px', |
| | | }, |
| | | labelPosition: { |
| | | type: String, |
| | | default: 'left', |
| | | }, |
| | | formData: { |
| | | type: Object as PropType<{ [key: string]: any }>, |
| | | default: () => ({}), |
| | | }, |
| | | formItemProps: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | inLine: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | setup(props: PropsType, { attrs, emit, expose }: SetupContext) { |
| | | const formRef = ref<FormInstance>() |
| | | const form: any = computed({ |
| | | get() { |
| | | return props.formData |
| | | }, |
| | | set(v) { |
| | | emit('update:formData', v) |
| | | }, |
| | | }) |
| | | |
| | | const currentWidgetModel = computed(() => { |
| | | return (path: string) => { |
| | | return get(form.value, path) |
| | | } |
| | | }) |
| | | |
| | | const validate = () => { |
| | | if (!formRef.value) return false |
| | | return new Promise((resolve, reject) => { |
| | | formRef.value?.validate((valid: boolean) => { |
| | | if (valid) { |
| | | resolve(true) |
| | | } else { |
| | | reject(false) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | const resetForm = () => { |
| | | if (!formRef.value) return false |
| | | formRef.value.resetFields() |
| | | } |
| | | |
| | | const formItemProps = computed(() => { |
| | | return props.formItemProps || [] |
| | | }) |
| | | |
| | | expose({ validate, resetForm }) |
| | | |
| | | const FormRender: any = ($props: any) => { |
| | | const item: FormItemPropType = $props.item |
| | | const options = $props.item.options || [] |
| | | if (item.el && Type[item.el as string]) { |
| | | return options.map((el: OptionItemType) => ( |
| | | <Option |
| | | label={el.label || el.description || el.name} |
| | | value={el.value} |
| | | ></Option> |
| | | )) |
| | | } |
| | | return null |
| | | } |
| | | |
| | | const onUpdateModelValue = (v: string | number, prop: string) => { |
| | | set(form.value, prop, v) |
| | | } |
| | | |
| | | return () => { |
| | | return ( |
| | | <div class={styles.formStyle}> |
| | | <el-form |
| | | labelPosition={props.labelPosition} |
| | | labelWidth={props.labelWidth} |
| | | model={form.value} |
| | | ref={formRef} |
| | | inline={props.inLine} |
| | | > |
| | | {formItemProps.value.map( |
| | | (item: FormItemPropType, index: number) => { |
| | | if (item.isTitle) { |
| | | if (typeof item.title === 'string') { |
| | | return ( |
| | | <Title style="margin-bottom: 10px">{item.title}</Title> |
| | | ) |
| | | } |
| | | return item.title |
| | | } |
| | | |
| | | const itemProps: FormItemPropType = {} |
| | | Object.entries(item).forEach(([key, value]) => { |
| | | itemProps[key] = unref(value) |
| | | }) |
| | | |
| | | const el = |
| | | typeof itemProps.el === 'string' |
| | | ? formItemElementMap[itemProps.el] |
| | | : itemProps.el || null |
| | | const Component = el |
| | | return Component && !item.isHide ? ( |
| | | <el-form-item |
| | | label={itemProps.label} |
| | | prop={itemProps.prop} |
| | | rules={itemProps.rules} |
| | | key={itemProps.prop} |
| | | vSlots={ |
| | | itemProps.labelIcon |
| | | ? { |
| | | label: () => ( |
| | | <label class={styles.formitemPropsLabel}> |
| | | {itemProps.label} |
| | | <Icon icon={itemProps.labelIcon} /> |
| | | </label> |
| | | ), |
| | | } |
| | | : null |
| | | } |
| | | > |
| | | <Component |
| | | style={{ |
| | | width: itemProps.width, |
| | | height: itemProps.height, |
| | | }} |
| | | {...itemProps} |
| | | // v-model={form.value[itemProps.prop as keyof any]} |
| | | modelValue={currentWidgetModel.value(itemProps.prop)} |
| | | onUpdate:modelValue={(val: string | number) => |
| | | onUpdateModelValue(val, itemProps.prop) |
| | | } |
| | | > |
| | | <FormRender item={itemProps} /> |
| | | </Component> |
| | | </el-form-item> |
| | | ) : null |
| | | } |
| | | )} |
| | | </el-form> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |