vxe-pc-ui
Version:
A vue based PC component library
560 lines (559 loc) • 24.2 kB
JavaScript
import { ref, defineComponent, inject, h, createCommentVNode, TransitionGroup, computed, nextTick } from 'vue';
import { VxeUI, renderer, getIcon, getI18n } from '@vxe-ui/core';
import XEUtils from 'xe-utils';
import { hasFormDesignLayoutType } from '../src/util';
import { getSlotVNs } from '../../ui/src/vn';
import { useWidgetName } from '../../form-design/src/use';
import VxeFormItemComponent from '../../form/src/form-item';
import VxeButtonComponent from '../../button/src/button';
import VxeCheckboxComponent from '../../checkbox/src/checkbox';
const ViewSubItemComponent = defineComponent({
props: {
parentWidget: {
type: Object,
default: () => ({})
},
widget: {
type: Object,
default: () => ({})
},
childIndex: {
type: Number,
default: 0
}
},
emits: [],
setup(props) {
const $xeFormDesign = inject('$xeFormDesign', null);
const $xeFormView = inject('$xeFormView', null);
if (!$xeFormDesign) {
return () => [];
}
const { reactData: formDesignReactData } = $xeFormDesign;
const sortDragstartSubItemEvent = (evnt) => {
evnt.stopPropagation();
const divEl = evnt.currentTarget;
const dataTransfer = evnt.dataTransfer;
const widgetId = divEl.getAttribute('data-widget-id') || '';
const dragWidget = $xeFormDesign.getWidgetById(widgetId);
if (dataTransfer) {
dataTransfer.setData('text/plain', widgetId);
}
formDesignReactData.sortWidget = dragWidget;
formDesignReactData.dragWidget = null;
};
const sortDragenterSubItemEvent = (evnt) => {
const { parentWidget, childIndex } = props;
const { widgetObjList, sortWidget } = formDesignReactData;
const targetWidget = parentWidget.children[childIndex];
const formDesignInternalData = $xeFormDesign.internalData;
const { lastDragTime } = formDesignInternalData;
evnt.stopPropagation();
if (lastDragTime && lastDragTime > Date.now() - 300) {
evnt.preventDefault();
return;
}
if (sortWidget && targetWidget && parentWidget) {
if (sortWidget.id === parentWidget.id) {
return;
}
if (sortWidget.id === targetWidget.id) {
return;
}
if (hasFormDesignLayoutType(sortWidget)) {
return;
}
if (targetWidget && !hasFormDesignLayoutType(targetWidget)) {
const currRest = XEUtils.findTree(widgetObjList, item => item.id === sortWidget.id, { children: 'children' });
if (currRest) {
const { item, index, items, parent } = currRest;
// 如果是 subtable 内移动
if (parent && parent.id === parentWidget.id) {
parentWidget.children[childIndex] = item;
parentWidget.children[index] = targetWidget;
}
else {
parentWidget.children.splice(childIndex, 0, item);
items.splice(index, 1);
}
formDesignInternalData.lastDragTime = Date.now();
$xeFormDesign.dispatchEvent('drag-widget', { widget: item }, evnt);
}
}
}
};
return () => {
const { widget } = props;
const { dragWidget, activeWidget, sortWidget } = formDesignReactData;
const name = widget ? widget.name : '';
const compConf = renderer.get(name) || {};
const renderSubtableView = compConf.renderFormDesignWidgetSubtableEditView || compConf.renderFormDesignWidgetSubtableCellView || compConf.renderFormDesignWidgetSubtableDefaultView;
const renderWidgetDesignView = compConf.renderFormDesignWidgetEdit || compConf.renderFormDesignWidgetView;
const renderOpts = widget || { name };
const isEditMode = !!$xeFormDesign;
const defParams = { widget, readonly: false, disabled: false, isEditMode, isViewMode: !isEditMode, $formDesign: $xeFormDesign, $formView: $xeFormView };
const isActive = activeWidget && widget && activeWidget.id === widget.id;
const subOpts = { name };
const subParams = {
$table: null,
$grid: null,
seq: '',
column: {
field: widget.field,
title: widget.title
},
columnIndex: 0,
$columnIndex: 0,
_columnIndex: 0,
rowid: '',
row: {},
rowIndex: 0,
$rowIndex: 0,
_rowIndex: 0,
isEdit: false,
isHidden: false,
fixed: null,
type: '',
level: 1,
visibleData: [],
items: [],
data: [],
widget: widget
};
return h('div', {
class: ['vxe-form-design--widget-subtable-view-item', {
'is--active': isActive,
'is--sort': sortWidget && widget && sortWidget.id === widget.id,
'is--drag': dragWidget && widget && dragWidget.id === widget.id
}],
draggable: true,
'data-widget-id': widget.id,
onDragstart: sortDragstartSubItemEvent,
onDragenter: sortDragenterSubItemEvent,
onClick(evnt) {
if (widget) {
$xeFormDesign.handleClickWidget(evnt, widget);
}
}
}, [
h('div', {
class: 'vxe-form-design--widget-subtable-view-item-wrapper'
}, [
h('div', {
class: 'vxe-form-design--widget-subtable-view-item-box vxe-form--item-row'
}, renderSubtableView
? h(VxeFormItemComponent, {
class: ['vxe-form-design--widget-render-form-item'],
title: widget.title,
field: widget.field,
itemRender: {}
}, {
default() {
return getSlotVNs(renderSubtableView(subOpts, subParams));
}
})
: (renderWidgetDesignView
? getSlotVNs(renderWidgetDesignView(renderOpts, defParams))
: [])),
isActive
? h('div', {
class: 'vxe-form-design--preview-item-operate'
}, [
h(VxeButtonComponent, {
icon: getIcon().FORM_DESIGN_WIDGET_COPY,
status: 'primary',
size: 'mini',
circle: true,
onClick(params) {
$xeFormDesign.handleCopyWidget(params.$event, widget);
}
}),
h(VxeButtonComponent, {
icon: getIcon().FORM_DESIGN_WIDGET_DELETE,
status: 'danger',
size: 'mini',
circle: true,
onClick(params) {
$xeFormDesign.handleRemoveWidget(params.$event, widget);
}
})
])
: createCommentVNode()
])
]);
};
}
});
export const WidgetSubtableEditComponent = defineComponent({
props: {
renderOpts: {
type: Object,
default: () => ({})
},
renderParams: {
type: Object,
default: () => ({})
}
},
emits: [],
setup(props) {
const $xeFormDesign = inject('$xeFormDesign', null);
if (!$xeFormDesign) {
return () => [];
}
const { reactData: formDesignReactData } = $xeFormDesign;
const handleDragoverWrapperEvent = (evnt) => {
const { sortWidget, widgetObjList } = formDesignReactData;
const { renderParams } = props;
const { widget } = renderParams;
evnt.stopPropagation();
if (!sortWidget || !widget || widget.id === sortWidget.id) {
return;
}
if (hasFormDesignLayoutType(sortWidget)) {
if (VxeUI.modal) {
VxeUI.modal.message({
content: getI18n('vxe.formDesign.widgetProp.subtableProp.errSubDrag'),
status: 'error',
id: 'errSubDrag'
});
}
return;
}
// 如果控件不在当前子表中,则拖进去
if (widget.name && !widget.children.some(item => item.id === sortWidget.id)) {
const rest = XEUtils.findTree(widgetObjList, item => item.id === sortWidget.id, { children: 'children' });
if (rest) {
const { item, index, items } = rest;
formDesignReactData.sortWidget = null;
formDesignReactData.activeWidget = item;
widget.children.push(item);
items.splice(index, 1);
formDesignReactData.sortWidget = item;
}
}
};
const handleDragenterWrapperEvent = (evnt) => {
evnt.stopPropagation();
};
return () => {
const { renderParams } = props;
const { widget } = renderParams;
const { title, children, options } = widget;
const { showCheckbox } = options;
return h(VxeFormItemComponent, {
title,
className: 'vxe-form-design--widget-subtable-form-item'
}, {
default() {
return h('div', {
class: 'vxe-form-design--widget-subtable-view',
onDragenter: handleDragenterWrapperEvent,
onDragover: handleDragoverWrapperEvent
}, [
h('div', {
class: 'vxe-form-design--widget-subtable-view-left'
}, [
showCheckbox
? h('div', {
class: 'vxe-form-design--widget-subtable-col'
}, [
h('div', {
class: 'vxe-form-design--widget-subtable-head'
}, [
h(VxeCheckboxComponent)
]),
h('div', {
class: 'vxe-form-design--widget-subtable-body'
}, [
h(VxeCheckboxComponent)
])
])
: createCommentVNode(),
h('div', {
class: 'vxe-form-design--widget-subtable-col'
}, [
h('div', {
class: 'vxe-form-design--widget-subtable-head'
}, getI18n('vxe.formDesign.widgetProp.subtableProp.seqTitle')),
h('div', {
class: 'vxe-form-design--widget-subtable-body'
}, '1')
])
]),
h('div', {
class: 'vxe-form-design--widget-subtable-view-right'
}, [
h('div', {
class: 'vxe-form-design--widget-subtable-view-wrapper'
}, [
h(TransitionGroup, {
class: 'vxe-form-design--widget-subtable-view-list',
tag: 'div',
name: 'vxe-form-design--widget-subtable-view-list'
}, {
default: () => {
return children
? children.map((childWidget, childIndex) => {
return h(ViewSubItemComponent, {
key: childWidget.id,
parentWidget: widget,
widget: childWidget,
childIndex
});
})
: [];
}
}),
h('div', {
key: 'empty',
class: 'vxe-form-design--widget-subtable-view-empty'
}, getI18n('vxe.formDesign.widgetProp.subtableProp.colPlace'))
])
])
]);
}
});
};
}
});
export const WidgetSubtableViewComponent = defineComponent({
props: {
renderOpts: {
type: Object,
default: () => ({})
},
renderParams: {
type: Object,
default: () => ({})
}
},
emits: [],
setup(props) {
const VxeTableGridComponent = VxeUI.getComponent('VxeGrid');
const $xeFormView = inject('$xeFormView', null);
const { computeKebabCaseName } = useWidgetName(props);
const refGrid = ref();
const defaultDataList = ref([
{}
]);
const computeFormReadonly = computed(() => {
if ($xeFormView) {
return $xeFormView.props.readonly;
}
return false;
});
const computeSubtableColumns = computed(() => {
const { renderParams } = props;
const { widget } = renderParams;
const { children, options } = widget;
const formReadonly = computeFormReadonly.value;
const columns = [];
if (options.showCheckbox) {
columns.push({
type: 'checkbox',
width: 60,
fixed: 'left'
});
}
columns.push({
type: 'seq',
width: 60,
fixed: 'left'
});
if (children) {
children.forEach(childWidget => {
const { name } = childWidget;
const compConf = renderer.get(name) || {};
const parseSubtableColumn = compConf.parseFormDesignWidgetSubtableColumn;
let colConf = {
field: childWidget.field,
title: childWidget.title
};
if (parseSubtableColumn) {
colConf = Object.assign(colConf, parseSubtableColumn({
$formView: $xeFormView,
name: childWidget.name,
widget: childWidget,
readonly: !!formReadonly
}));
}
else {
if (formReadonly) {
colConf.cellRender = {
name: childWidget.name,
props: childWidget.options
};
}
else {
colConf.editRender = {
name: childWidget.name,
props: childWidget.options
};
}
}
const renderSubtableDefaultView = compConf.renderFormDesignWidgetSubtableDefaultView;
const renderSubtableCellView = compConf.renderFormDesignWidgetSubtableCellView || renderSubtableDefaultView;
const renderSubtableEditView = compConf.renderFormDesignWidgetSubtableEditView;
const colSlots = {};
if (renderSubtableDefaultView || renderSubtableCellView) {
colSlots.default = (slotParams) => {
const { isEdit, column } = slotParams;
const { editRender, cellRender } = column;
const params = Object.assign({ widget: childWidget }, slotParams);
if (isEdit && editRender) {
if (renderSubtableCellView) {
return getSlotVNs(renderSubtableCellView(editRender, params));
}
}
if (renderSubtableDefaultView) {
return getSlotVNs(renderSubtableDefaultView(cellRender || {}, params));
}
return [];
};
}
if (renderSubtableEditView) {
colSlots.edit = (slotParams) => {
const { column } = slotParams;
const { editRender } = column;
const params = Object.assign({ widget: childWidget }, slotParams);
return getSlotVNs(renderSubtableEditView(editRender, params));
};
}
colConf.slots = colSlots;
columns.push(colConf);
});
}
if (!formReadonly) {
columns.push({
field: 'action',
title: '操作',
fixed: 'right',
width: 80,
slots: {
default({ row }) {
return h(VxeButtonComponent, {
mode: 'text',
icon: 'vxe-icon-delete',
status: 'error',
onClick() {
removeSubRow(row);
}
});
}
}
});
}
return columns;
});
const computeGridOptions = computed(() => {
const { renderParams } = props;
const { widget, isEditMode } = renderParams;
const subtableColumns = computeSubtableColumns.value;
const formReadonly = computeFormReadonly.value;
const gridConf = {
border: true,
showOverflow: true,
height: 300,
columnConfig: {
resizable: true,
minWidth: 140
},
rowConfig: {
keyField: '_id'
},
data: isEditMode ? defaultDataList.value : $xeFormView ? $xeFormView.getItemValue(widget) : null,
columns: subtableColumns,
toolbarConfig: {
zoom: true,
custom: false,
slots: {
buttons: 'toolbarButtons'
}
}
};
if (!formReadonly) {
gridConf.keepSource = true;
gridConf.editConfig = {
mode: 'row',
trigger: 'click',
showStatus: true
};
}
return gridConf;
});
const getSubRecord = () => {
const { renderParams } = props;
const { widget } = renderParams;
const record = {
_id: Date.now()
};
XEUtils.each(widget.children, childWidget => {
record[childWidget.field] = null;
});
return record;
};
const addSubRowEvent = () => {
const { renderParams } = props;
const { widget } = renderParams;
if ($xeFormView) {
let list = $xeFormView.getItemValue(widget);
if (!XEUtils.isArray(list)) {
list = [];
}
const newRow = getSubRecord();
list.unshift(newRow);
$xeFormView.setItemValue(widget, list.slice(0)).then(() => {
return nextTick().then(() => {
const $grid = refGrid.value;
if ($grid) {
$grid.setEditRow(newRow);
}
});
});
}
};
const removeSubRow = (row) => {
const { renderParams } = props;
const { widget } = renderParams;
if ($xeFormView) {
const list = $xeFormView.getItemValue(widget);
if (list) {
$xeFormView.setItemValue(widget, list.filter(item => item._id !== row._id));
}
}
};
return () => {
const { renderParams } = props;
const { widget } = renderParams;
const kebabCaseName = computeKebabCaseName.value;
const gridOptions = computeGridOptions.value;
const formReadonly = computeFormReadonly.value;
return h(VxeFormItemComponent, {
class: ['vxe-form-design--widget-render-form-item', `widget-${kebabCaseName}`],
title: widget.title,
field: widget.field,
span: 24
}, {
default() {
return VxeTableGridComponent
? h(VxeTableGridComponent, Object.assign(Object.assign({}, gridOptions), { ref: refGrid }), {
toolbarButtons() {
return formReadonly
? []
: [
h(VxeButtonComponent, {
content: '新增',
icon: 'vxe-icon-add',
status: 'primary',
onClick: addSubRowEvent
})
];
}
})
: createCommentVNode();
}
});
};
}
});