vxe-table-demonic
Version:
一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...
446 lines (445 loc) • 15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _vue = require("vue");
var _xeUtils = _interopRequireDefault(require("xe-utils"));
var _conf = _interopRequireDefault(require("../../v-x-e-table/src/conf"));
var _size = require("../../hooks/size");
var _dom = require("../../tools/dom");
var _utils = require("../../tools/utils");
var _event = require("../../tools/event");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _vue.defineComponent)({
name: 'VxeButton',
props: {
/**
* 按钮类型
*/
type: String,
className: [String, Function],
popupClassName: [String, Function],
/**
* 按钮尺寸
*/
size: {
type: String,
default: function () {
return _conf.default.button.size || _conf.default.size;
}
},
/**
* 用来标识这一项
*/
name: [String, Number],
/**
* 按钮内容
*/
content: String,
/**
* 固定显示下拉面板的方向
*/
placement: String,
/**
* 按钮状态
*/
status: String,
/**
* 按钮的图标
*/
icon: String,
/**
* 圆角边框
*/
round: Boolean,
/**
* 圆角按钮
*/
circle: Boolean,
/**
* 是否禁用
*/
disabled: Boolean,
/**
* 是否加载中
*/
loading: Boolean,
/**
* 在下拉面板关闭时销毁内容
*/
destroyOnClose: Boolean,
/**
* 是否将弹框容器插入于 body 内
*/
transfer: {
type: Boolean,
default: function () {
return _conf.default.button.transfer;
}
},
layer: {
type: [HTMLElement, String, Function]
}
},
emits: ['click', 'dropdown-click'],
setup: function (props, context) {
var slots = context.slots,
emit = context.emit;
var xID = _xeUtils.default.uniqueId();
var computeSize = (0, _size.useSize)(props);
var reactData = (0, _vue.reactive)({
inited: false,
showPanel: false,
animatVisible: false,
panelIndex: 0,
panelStyle: {},
panelPlacement: ''
});
var internalData = {
showTime: null
};
var refElem = (0, _vue.ref)();
var refButton = (0, _vue.ref)();
var refBtnPanel = (0, _vue.ref)();
var refMaps = {
refElem: refElem
};
var $xebutton = {
xID: xID,
props: props,
context: context,
reactData: reactData,
internalData: internalData,
getRefMaps: function () {
return refMaps;
}
};
var buttonMethods = {};
var computeIsFormBtn = (0, _vue.computed)(function () {
var type = props.type;
if (type) {
return ['submit', 'reset', 'button'].indexOf(type) > -1;
}
return false;
});
var computeBtnType = (0, _vue.computed)(function () {
var type = props.type;
return type && type === 'text' ? type : 'button';
});
var updateZindex = function () {
if (reactData.panelIndex < (0, _utils.getLastZIndex)()) {
reactData.panelIndex = (0, _utils.nextZIndex)();
}
};
var updatePlacement = function () {
return (0, _vue.nextTick)().then(function () {
var transfer = props.transfer,
placement = props.placement,
layer = props.layer;
var panelIndex = reactData.panelIndex;
var targetElem = refButton.value;
var panelElem = refBtnPanel.value;
if (panelElem && targetElem) {
var targetHeight = targetElem.offsetHeight;
var targetWidth = targetElem.offsetWidth;
var panelHeight = panelElem.offsetHeight;
var panelWidth = panelElem.offsetWidth;
var marginSize = 5;
var panelStyle = {
zIndex: panelIndex
};
var _a = (0, _dom.getAbsolutePos)(targetElem),
top_1 = _a.top,
left = _a.left,
boundingTop = _a.boundingTop,
boundingBottom = _a.boundingBottom,
visibleHeight = _a.visibleHeight,
visibleWidth = _a.visibleWidth;
var panelPlacement = 'bottom';
if (transfer) {
// todo 会员管理页btnTop计算错误 超出视距
var btnLeft = left + targetWidth - panelWidth;
var btnTop = top_1 + targetHeight;
if (placement === 'top') {
panelPlacement = 'top';
btnTop = top_1 - panelHeight;
} else if (!placement) {
// 如果下面不够放,则向上
if (boundingTop + targetHeight + panelHeight + marginSize > visibleHeight) {
panelPlacement = 'top';
btnTop = top_1 - panelHeight;
}
// 如果上面不够放,则向下(优先)
if (btnTop < marginSize) {
panelPlacement = 'bottom';
btnTop = top_1 + targetHeight;
}
}
// 如果溢出右边
if (btnLeft + panelWidth + marginSize > visibleWidth) {
btnLeft -= btnLeft + panelWidth + marginSize - visibleWidth;
}
// 如果溢出左边
if (btnLeft < marginSize) {
btnLeft = marginSize;
}
Object.assign(panelStyle, {
left: "".concat(btnLeft, "px"),
right: 'auto',
top: "".concat(btnTop, "px"),
minWidth: "".concat(targetWidth, "px")
});
} else {
var layerEle = layer ? _xeUtils.default.isFunction(layer) ? layer(targetElem) : _xeUtils.default.isString(layer) ? document.querySelector(layer) : layer : undefined;
if (placement === 'top') {
panelPlacement = 'top';
panelStyle.bottom = "".concat(targetHeight, "px");
} else if (!placement) {
if (layerEle) {
var _b = layerEle.getBoundingClientRect(),
layerBottom = _b.bottom,
layerTop = _b.top;
// 如果下面不够放,上面够放,则向上
if (boundingBottom + targetHeight + panelHeight > layerBottom && boundingTop - targetHeight - panelHeight > layerTop) {
panelPlacement = 'top';
panelStyle.bottom = "".concat(targetHeight, "px");
}
} else {
// 如果下面不够放,则向上
if (boundingTop + targetHeight + panelHeight > visibleHeight) {
// 如果上面不够放,则向下(优先)
if (boundingTop - targetHeight - panelHeight > marginSize) {
panelPlacement = 'top';
panelStyle.bottom = "".concat(targetHeight, "px");
}
}
}
}
}
reactData.panelStyle = panelStyle;
reactData.panelPlacement = panelPlacement;
return (0, _vue.nextTick)();
}
});
};
var clickEvent = function (evnt) {
buttonMethods.dispatchEvent('click', {
$event: evnt
}, evnt);
};
var mousedownDropdownEvent = function (evnt) {
var isLeftBtn = evnt.button === 0;
if (isLeftBtn) {
evnt.stopPropagation();
}
};
var clickDropdownEvent = function (evnt) {
var dropdownElem = evnt.currentTarget;
var panelElem = refBtnPanel.value;
var _a = (0, _dom.getEventTargetNode)(evnt, dropdownElem, 'vxe-button'),
flag = _a.flag,
targetElem = _a.targetElem;
if (flag) {
if (panelElem) {
panelElem.dataset.active = 'N';
}
reactData.showPanel = false;
setTimeout(function () {
if (!panelElem || panelElem.dataset.active !== 'Y') {
reactData.animatVisible = false;
}
}, 350);
buttonMethods.dispatchEvent('dropdown-click', {
name: targetElem.getAttribute('name'),
$event: evnt
}, evnt);
}
};
var mouseenterEvent = function () {
var panelElem = refBtnPanel.value;
if (panelElem) {
panelElem.dataset.active = 'Y';
reactData.animatVisible = true;
setTimeout(function () {
if (panelElem.dataset.active === 'Y') {
reactData.showPanel = true;
updateZindex();
updatePlacement();
setTimeout(function () {
if (reactData.showPanel) {
updatePlacement();
}
}, 50);
}
}, 20);
}
};
var mouseenterTargetEvent = function () {
var panelElem = refBtnPanel.value;
if (panelElem) {
panelElem.dataset.active = 'Y';
if (!reactData.inited) {
reactData.inited = true;
}
internalData.showTime = setTimeout(function () {
if (panelElem.dataset.active === 'Y') {
mouseenterEvent();
} else {
reactData.animatVisible = false;
}
}, 250);
}
};
var closePanel = function () {
var panelElem = refBtnPanel.value;
clearTimeout(internalData.showTime);
if (panelElem) {
panelElem.dataset.active = 'N';
setTimeout(function () {
if (panelElem.dataset.active !== 'Y') {
reactData.showPanel = false;
setTimeout(function () {
if (panelElem.dataset.active !== 'Y') {
reactData.animatVisible = false;
}
}, 350);
}
}, 100);
} else {
reactData.animatVisible = false;
reactData.showPanel = false;
}
};
var mouseleaveEvent = function () {
closePanel();
};
var renderContent = function () {
var content = props.content,
icon = props.icon,
loading = props.loading;
var contVNs = [];
if (loading) {
contVNs.push((0, _vue.h)('i', {
class: ['vxe-button--loading-icon', _conf.default.icon.BUTTON_LOADING]
}));
} else if (slots.icon) {
contVNs.push((0, _vue.h)('span', {
class: 'vxe-button--custom-icon'
}, slots.icon({})));
} else if (icon) {
contVNs.push((0, _vue.h)('i', {
class: ['vxe-button--icon', icon]
}));
}
if (slots.default) {
contVNs.push((0, _vue.h)('span', {
class: 'vxe-button--content'
}, slots.default({})));
} else if (content) {
contVNs.push((0, _vue.h)('span', {
class: 'vxe-button--content'
}, (0, _utils.getFuncText)(content)));
}
return contVNs;
};
buttonMethods = {
dispatchEvent: function (type, params, evnt) {
emit(type, Object.assign({
$button: $xebutton,
$event: evnt
}, params));
},
focus: function () {
var btnElem = refButton.value;
btnElem.focus();
return (0, _vue.nextTick)();
},
blur: function () {
var btnElem = refButton.value;
btnElem.blur();
return (0, _vue.nextTick)();
}
};
Object.assign($xebutton, buttonMethods);
(0, _vue.onMounted)(function () {
_event.GlobalEvent.on($xebutton, 'mousewheel', function (evnt) {
var panelElem = refBtnPanel.value;
if (reactData.showPanel && !(0, _dom.getEventTargetNode)(evnt, panelElem).flag) {
closePanel();
}
});
});
(0, _vue.onUnmounted)(function () {
_event.GlobalEvent.off($xebutton, 'mousewheel');
});
var renderVN = function () {
var _a, _b, _c, _d;
var className = props.className,
popupClassName = props.popupClassName,
transfer = props.transfer,
type = props.type,
round = props.round,
circle = props.circle,
destroyOnClose = props.destroyOnClose,
status = props.status,
name = props.name,
disabled = props.disabled,
loading = props.loading;
var inited = reactData.inited,
showPanel = reactData.showPanel;
var isFormBtn = computeIsFormBtn.value;
var btnType = computeBtnType.value;
var vSize = computeSize.value;
if (slots.dropdowns) {
return (0, _vue.h)('div', {
ref: refElem,
class: ['vxe-button--dropdown', className ? _xeUtils.default.isFunction(className) ? className({
$button: $xebutton
}) : className : '', (_a = {}, _a["size--".concat(vSize)] = vSize, _a['is--active'] = showPanel, _a)]
}, [(0, _vue.h)('button', {
ref: refButton,
class: ['vxe-button', "type--".concat(btnType), (_b = {}, _b["size--".concat(vSize)] = vSize, _b["theme--".concat(status)] = status, _b['is--round'] = round, _b['is--circle'] = circle, _b['is--disabled'] = disabled || loading, _b['is--loading'] = loading, _b)],
name: name,
type: isFormBtn ? type : 'button',
disabled: disabled || loading,
onMouseenter: mouseenterTargetEvent,
onMouseleave: mouseleaveEvent,
onClick: clickEvent
}, renderContent().concat([(0, _vue.h)('i', {
class: "vxe-button--dropdown-arrow ".concat(_conf.default.icon.BUTTON_DROPDOWN)
})])), (0, _vue.h)(_vue.Teleport, {
to: 'body',
disabled: transfer ? !inited : true
}, [(0, _vue.h)('div', {
ref: refBtnPanel,
class: ['vxe-button--dropdown-panel', popupClassName ? _xeUtils.default.isFunction(popupClassName) ? popupClassName({
$button: $xebutton
}) : popupClassName : '', (_c = {}, _c["size--".concat(vSize)] = vSize, _c['animat--leave'] = reactData.animatVisible, _c['animat--enter'] = showPanel, _c)],
placement: reactData.panelPlacement,
style: reactData.panelStyle
}, inited ? [(0, _vue.h)('div', {
class: 'vxe-button--dropdown-wrapper',
onMousedown: mousedownDropdownEvent,
onClick: clickDropdownEvent,
onMouseenter: mouseenterEvent,
onMouseleave: mouseleaveEvent
}, destroyOnClose && !showPanel ? [] : slots.dropdowns({}))] : [])])]);
}
return (0, _vue.h)('button', {
ref: refButton,
class: ['vxe-button', "type--".concat(btnType), (_d = {}, _d["size--".concat(vSize)] = vSize, _d["theme--".concat(status)] = status, _d['is--round'] = round, _d['is--circle'] = circle, _d['is--disabled'] = disabled || loading, _d['is--loading'] = loading, _d)],
name: name,
type: isFormBtn ? type : 'button',
disabled: disabled || loading,
onClick: clickEvent
}, renderContent());
};
$xebutton.renderVN = renderVN;
return $xebutton;
},
render: function () {
return this.renderVN();
}
});
exports.default = _default;