fineui是帆软报表和BI产品线所使用的前端框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

345 lines
11 KiB

import {
VTapeLayout,
RightVerticalAdaptLayout,
HTapeLayout,
AbsoluteLayout,
VerticalLayout,
Widget,
shortcut,
clamp,
isPlainObject,
extend,
isNotNull,
MouseMoveTracker,
i18nText,
SIZE_CONSANTS
} from "@/core";
import { Label, IconButton, Button } from "../single";
import { Resizers } from "../0.base";
import { getOuterBody } from "@/core/utils/dom";
/**
* Popover弹出层,
* @class Popover
* @extends Widget
*/
@shortcut()
export class Popover extends Widget {
_constant = {
SIZE: {
SMALL: "small",
NORMAL: "normal",
BIG: "big",
},
MAX_HEIGHT: 600,
};
props() {
return {
baseCls: "bi-popover bi-card bi-border-radius",
size: "normal", // small, normal, big
logic: {
dynamic: false,
},
header: null,
headerHeight: 40,
body: null,
footer: null,
footerHeight: 44,
footerButtonHeight: 28,
closable: true, // BI-40839 是否显示右上角的关闭按钮
bodyHgap: SIZE_CONSANTS.H_GAP_SIZE,
bodyTgap: SIZE_CONSANTS.V_GAP_SIZE,
};
}
static xtype = "bi.popover";
static EVENT_CLOSE = "EVENT_CLOSE";
static EVENT_OPEN = "EVENT_OPEN";
static EVENT_CANCEL = "EVENT_CANCEL";
static EVENT_CONFIRM = "EVENT_CONFIRM";
render() {
// var self = this;
const { header, headerHeight, closable, logic, footer, footerHeight, body, bodyTgap, bodyHgap } = this.options;
const c = this._constant;
const size = this._calculateSize();
const items = [
{
el: {
type: HTapeLayout.xtype,
cls: "bi-message-title bi-header-background",
items: [
{
el: {
type: AbsoluteLayout.xtype,
ref: _ref => {
this.dragger = _ref;
},
items: [
{
el: isPlainObject(header)
? extend({}, header, {
extraCls: "bi-font-bold",
})
: {
type: Label.xtype,
cls: "bi-font-bold",
height: headerHeight,
text: header,
title: header,
textAlign: "left",
},
top: 0,
bottom: 0,
left: SIZE_CONSANTS.H_GAP_SIZE,
right: closable ? 0 : SIZE_CONSANTS.H_GAP_SIZE,
}
],
},
},
closable
? {
el: {
type: IconButton.xtype,
cls: "bi-message-close close-font",
height: headerHeight,
handler: () => {
this.close();
},
},
width: 56,
}
: null
],
height: headerHeight,
},
height: headerHeight,
},
logic.dynamic
? {
el: {
type: VerticalLayout.xtype,
scrolly: true,
cls: "popover-body",
ref: _ref => {
this.body = _ref;
},
css: {
"max-height": this._getSuitableBodyHeight(
c.MAX_HEIGHT - headerHeight - (footer ? footerHeight : 0) - bodyTgap
),
"min-height": this._getSuitableBodyHeight(
size.height - headerHeight - (footer ? footerHeight : 0) - bodyTgap
),
},
items: [
{
el: body,
}
],
hgap: bodyHgap,
tgap: bodyTgap,
},
}
: {
el: {
type: AbsoluteLayout.xtype,
items: [
{
el: body,
left: bodyHgap,
top: bodyTgap,
right: bodyHgap,
bottom: 0,
}
],
},
}
];
if (footer) {
items.push({
el: {
type: AbsoluteLayout.xtype,
items: [
{
el: footer,
left: SIZE_CONSANTS.H_GAP_SIZE,
top: 0,
right: SIZE_CONSANTS.H_GAP_SIZE,
bottom: 0,
}
],
height: footerHeight,
},
height: footerHeight,
});
}
return extend(
{
items,
width: this._getSuitableWidth(size.width),
},
logic.dynamic
? {
type: VerticalLayout.xtype,
scrolly: false,
}
: {
type: VTapeLayout.xtype,
height: this._getSuitableHeight(size.height),
}
);
}
// mounted之后绑定事件
mounted() {
this.startX = 0;
this.startY = 0;
this.tracker = new MouseMoveTracker(
(deltaX, deltaY) => {
const el = Widget._renderEngine.createElement(getOuterBody())[0];
const W = el.clientWidth;
const H = el.clientHeight;
this.startX += deltaX;
this.startY += deltaY;
this.element.css({
left: `${clamp(this.startX, 0, W - this.element.width())}px`,
top: `${clamp(this.startY, 0, H - this.element.height())}px`,
});
// BI-12134 没有什么特别好的方法
Resizers._resize({
target: this.element[0],
});
},
() => {
this.tracker.releaseMouseMoves();
},
_global
);
this.dragger?.element.mousedown(e => {
if (this.options.draggable !== false) {
this.startX = this.element[0].offsetLeft;
this.startY = this.element[0].offsetTop;
this.tracker.captureMouseMoves(e);
}
});
}
_getSuitableBodyHeight(height) {
const { headerHeight, footer, footerHeight, bodyTgap } = this.options;
const bodyDom = getOuterBody();
return clamp(
height,
0,
Widget._renderEngine.createElement(bodyDom)[0].clientHeight -
headerHeight -
(footer ? footerHeight : 0) -
bodyTgap
);
}
_getSuitableHeight(height) {
return clamp(height, 0, Widget._renderEngine.createElement(getOuterBody())[0].clientHeight);
}
_getSuitableWidth(width) {
return clamp(width, 0, Widget._renderEngine.createElement(getOuterBody())[0].clientWidth);
}
_calculateSize() {
const { size, width, height } = this.options;
const sizeValue = {};
if (isNotNull(size)) {
switch (size) {
case this._constant.SIZE.SMALL:
sizeValue.width = 450;
sizeValue.height = 200;
sizeValue.type = "small";
break;
case this._constant.SIZE.BIG:
sizeValue.width = 900;
sizeValue.height = 500;
sizeValue.type = "big";
break;
default:
sizeValue.width = 550;
sizeValue.height = 500;
sizeValue.type = "default";
}
}
return {
width: width || sizeValue.width,
height: height || sizeValue.height,
type: sizeValue.type || "default",
};
}
setDraggable(b) {
this.options.draggable = b;
}
hide() {
}
open() {
this.show();
this.fireEvent(Popover.EVENT_OPEN, arguments);
}
close() {
this.hide();
this.fireEvent(Popover.EVENT_CLOSE, arguments);
}
setZindex(zindex) {
this.element.css({ "z-index": zindex });
}
}
@shortcut()
export class BarPopover extends Popover {
static xtype = "bi.bar_popover";
_defaultConfig() {
return extend(super._defaultConfig(...arguments), {
btns: [i18nText("BI-Basic_OK"), i18nText("BI-Basic_Cancel")],
});
}
beforeCreate() {
const { footer, warningTitle, footerButtonHeight } = this.options;
footer ||
(this.options.footer = {
type: RightVerticalAdaptLayout.xtype,
lgap: 10,
items: [
{
type: Button.xtype,
height: footerButtonHeight,
text: this.options.btns[1],
value: 1,
light: true,
handler: v => {
this.fireEvent(Popover.EVENT_CANCEL, v);
this.close(v);
},
},
{
type: Button.xtype,
height: footerButtonHeight,
text: this.options.btns[0],
warningTitle,
value: 0,
handler: v => {
this.fireEvent(Popover.EVENT_CONFIRM, v);
this.close(v);
},
}
],
});
}
}