UNPKG

vxe-pc-ui

Version:
329 lines (328 loc) 13.7 kB
import { defineComponent, ref, h, reactive, nextTick, inject, provide, watch, createCommentVNode } from 'vue'; import XEUtils from 'xe-utils'; import { getConfig, renderer, useSize, createEvent } from '../../ui'; import { getSlotVNs } from '../../ui/src/vn'; import { createDefaultFormViewPCFormConfig } from './default-setting-data'; import VxeFormComponent from '../../form/src/form'; import VxeFormGroupComponent from '../../form/src/form-group'; import VxeFormItemComponent from '../../form/src/form-item'; import { configToWidget } from './widget-info'; import { warnLog } from '../../ui/src/log'; export default defineComponent({ name: 'VxeFormView', props: { modelValue: Object, config: Object, readonly: Boolean, disabled: Boolean, viewRender: Object, formOptions: Object, createFormConfig: Function, size: { type: String, default: () => getConfig().formView.size || getConfig().size } }, emits: [ 'update:modelValue', 'submit', 'reset' ], setup(props, context) { const { emit, slots } = context; const xID = XEUtils.uniqueId(); const refElem = ref(); const formRef = ref(); const { computeSize } = useSize(props); const $xeFormDesignLayoutStyle = inject('$xeFormDesignLayoutStyle', null); const reactData = reactive({ formConfig: {}, formRules: {}, widgetObjList: [] }); const refMaps = { refElem }; const computeMaps = { computeSize }; const $xeFormView = { xID, props, context, reactData, getRefMaps: () => refMaps, getComputeMaps: () => computeMaps }; const clearConfig = () => { return loadConfig({ formConfig: {}, widgetData: [] }); }; const loadConfig = (config) => { if (config) { const { formConfig, widgetData } = config; loadFormConfig(formConfig || {}); loadWidgetData(widgetData || []); } return nextTick(); }; const parseConfig = (config) => { const { formConfig, widgetData } = config || {}; const widgetObjList = parseWidgetData(widgetData || []); return Object.assign(Object.assign({}, parseForm(widgetObjList)), { formConfig: parseFormConfig(formConfig || {}), widgetData: widgetObjList }); }; const parseFormConfig = (formConfig) => { const { viewRender, createFormConfig, formOptions } = props; const params = { viewRender, formConfig }; if (createFormConfig) { return createFormConfig(params); } const { name } = viewRender || {}; const compConf = renderer.get(name) || {}; const createPCFormConfig = compConf ? compConf.createFormViewFormConfig : null; return Object.assign({}, createPCFormConfig ? createPCFormConfig(params) : createDefaultFormViewPCFormConfig(params), formOptions); }; const loadFormConfig = (formConfig) => { reactData.formConfig = parseFormConfig(formConfig); return nextTick(); }; const parseForm = (widgetObjList) => { const formData = {}; const formRules = {}; XEUtils.eachTree(widgetObjList, widget => { const { name, field, required } = widget; const compConf = renderer.get(name) || {}; const createWidgetFieldValue = compConf.createFormDesignWidgetFieldValue; const createWidgetFieldRules = compConf.createFormDesignWidgetFieldRules; formData[field] = createWidgetFieldValue ? createWidgetFieldValue({ widget, $formView: $xeFormView }) : getWidgetDefaultValue(widget); if (createWidgetFieldRules) { const rules = createWidgetFieldRules({ widget, $formView: $xeFormView }); if (rules && rules.length) { formRules[field] = rules; } } else if (required) { formRules[field] = getWidgetDefaultRule(); } }, { children: 'children' }); return { formData, formRules }; }; const parseWidgetData = (widgetData) => { return (widgetData || []).map(item => configToWidget(item)); }; const loadWidgetData = (widgetData) => { const widgetObjList = parseWidgetData(widgetData); reactData.widgetObjList = widgetObjList; const { formData, formRules } = parseForm(widgetObjList); reactData.formRules = formRules; emit('update:modelValue', Object.assign(formData, props.modelValue)); return nextTick(); }; const getWidgetDefaultValue = (widget) => { switch (widget.name) { case 'subtable': return []; } return null; }; const getWidgetDefaultRule = () => { return [ { required: true, content: '该填写该字段!' } ]; }; const updateWidgetStatus = (widget, value) => { const { field } = widget; const $form = formRef.value; if ($form) { $form.updateStatus({ field }, value); } return nextTick(); }; const setItemValue = (widget, value) => { const { modelValue } = props; const { field } = widget; const $form = formRef.value; if (modelValue) { modelValue[field] = value; } if ($form) { $form.updateStatus({ field }, value); } return nextTick(); }; const getItemValue = (widget) => { const { modelValue } = props; if (modelValue) { return modelValue[widget.field]; } return null; }; const dispatchEvent = (type, params, evnt) => { emit(type, createEvent(evnt, { $formView: $xeFormView }, params)); }; const toWidgetFields = (widget) => { if (widget) { if (XEUtils.isArray(widget)) { return widget.map(item => item.name); } else { return [widget.name]; } } return null; }; const formViewMethods = { dispatchEvent, clearConfig, loadConfig, parseConfig, loadFormConfig, loadWidgetData, updateWidgetStatus, setItemValue, getItemValue, validate() { const $form = formRef.value; if ($form) { return $form.validate(); } return nextTick(); }, validateWidget(widget) { const $form = formRef.value; if ($form) { return $form.validateField(toWidgetFields(widget)); } return nextTick(); }, clearValidate(widget) { const $form = formRef.value; if ($form) { return $form.clearValidate(toWidgetFields(widget)); } return nextTick(); }, reset() { const { widgetObjList } = reactData; const { formData } = parseForm(widgetObjList); emit('update:modelValue', Object.assign({}, formData)); return nextTick(); }, /** * 已废弃 * @deprecated */ updateItemStatus(widget, value) { if (process.env.NODE_ENV === 'development') { warnLog('vxe.error.delFunc', ['updateItemStatus', 'updateWidgetStatus']); } return updateWidgetStatus(widget, value); } }; const handleSubmit = (params) => { dispatchEvent('submit', params, params.$event); }; const handleReset = (params) => { dispatchEvent('reset', params, params.$event); }; const formViewPrivateMethods = {}; Object.assign($xeFormView, formViewMethods, formViewPrivateMethods); const renderVN = () => { const { readonly, disabled, modelValue } = props; const { formConfig, formRules, widgetObjList } = reactData; const vSize = computeSize.value; const topSlot = slots.top; const bottomSlot = slots.bottom; const headerSlot = slots.header; const footerSlot = slots.footer; return h('div', { ref: refElem, class: ['vxe-form-view', { [`size--${vSize}`]: vSize }] }, [ topSlot ? h('div', { class: 'vxe-form-view--top' }, getSlotVNs(topSlot({ $formView: $xeFormView }))) : createCommentVNode(), h(VxeFormComponent, Object.assign(Object.assign({ ref: formRef }, formConfig), { data: modelValue, customLayout: true, readonly, disabled, span: 24, rules: formRules, onSubmit: handleSubmit, onReset: handleReset }), { default() { const { readonly, disabled } = props; return [ headerSlot ? h(VxeFormItemComponent, {}, { default() { return headerSlot({}); } }) : createCommentVNode(), ...widgetObjList.map(widget => { const { name } = widget; const compConf = renderer.get(name) || {}; const renderWidgetDesignView = compConf.renderFormDesignWidgetView; const renderWidgetDesignPreview = compConf.renderFormDesignWidgetPreview; const renderWidgetDesignMobilePreview = compConf.renderFormDesignWidgetMobilePreview; const isEditMode = !!$xeFormDesignLayoutStyle; const renderOpts = widget; const params = { widget, readonly: !!readonly, disabled: !!disabled, isEditMode, isViewMode: !isEditMode, $formDesign: null, $formView: $xeFormView }; return h(VxeFormGroupComponent, { key: widget.id }, { default() { // 如果处于表单设计器-样式设置-预览模式下 if ($xeFormDesignLayoutStyle) { if ($xeFormDesignLayoutStyle.reactData.activeTab === 2) { if (renderWidgetDesignMobilePreview) { return getSlotVNs(renderWidgetDesignMobilePreview(renderOpts, params)); } } else { if (renderWidgetDesignPreview) { return getSlotVNs(renderWidgetDesignPreview(renderOpts, params)); } } } return renderWidgetDesignView ? getSlotVNs(renderWidgetDesignView(renderOpts, params)) : []; } }); }), footerSlot ? h(VxeFormGroupComponent, { span: 24 }, { default() { return footerSlot({}); } }) : createCommentVNode() ]; } }), bottomSlot ? h('div', { class: 'vxe-form-view--bottom' }, getSlotVNs(bottomSlot({ $formView: $xeFormView }))) : createCommentVNode() ]); }; $xeFormView.renderVN = renderVN; watch(() => props.config, (value) => { loadConfig(value || {}); }); if (props.config) { loadConfig(props.config); } provide('$xeFormView', $xeFormView); return $xeFormView; }, render() { return this.renderVN(); } });