vxe-pc-ui
Version:
A vue based PC component library
329 lines (328 loc) • 13.7 kB
JavaScript
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();
}
});