UNPKG

@riil-frontend/component-page-config

Version:

page config components,include components list,component attribute panel and page canvas

865 lines (720 loc) 28.1 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports["default"] = void 0; var _button = _interopRequireDefault(require("@alifd/next/lib/button")); var _icon = _interopRequireDefault(require("@alifd/next/lib/icon")); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _dialog = _interopRequireDefault(require("@alifd/next/lib/dialog")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _react = _interopRequireWildcard(require("react")); var _reactGridLayout = _interopRequireWildcard(require("react-grid-layout")); var _lodash = _interopRequireDefault(require("lodash")); var _propTypes = _interopRequireDefault(require("prop-types")); var _util = require("../util"); require("./index.scss"); var _utils = require("@riil-frontend/utils"); var _constant = require("../constant"); var ReactGridLayout = (0, _reactGridLayout.WidthProvider)(_reactGridLayout["default"]); /** */ var DragLayoutCanvas = /*#__PURE__*/function (_Component) { (0, _inheritsLoose2["default"])(DragLayoutCanvas, _Component); function DragLayoutCanvas(props) { var _this; _this = _Component.call(this, props) || this; _this.onResize = function (e) { if (_this.props.pageConfig && _this.props.pageConfig.layoutConfig && _this.props.pageConfig.layoutConfig.isFitHeight && !_this.props.isEdit) { _this.setState({ pageConfig: (0, _util.fitHeight)(_this.props.pageConfig, _this.props.parentDOM) }); } //浏览器改变大小,需保持全屏组件的样式 _this.keepFull(); }; _this.setPageState = function (obj, callback) { var pageState = _this.state.pageState; if (obj) { _this.setState({ pageState: Object.assign(pageState, obj) }, callback); } }; _this.removePageState = function (keys) { _this.setState(function (prevState, props) { keys.forEach(function (item) { if (item in prevState.pageState) { delete prevState.pageState[item]; } }); return prevState; }); }; _this.setWidgetsState = function (id, obj, callback) { if (!obj || !id) return; obj.id = id; var _w = _lodash["default"].cloneDeep(_this.state.widgetsState); var hasState = false; _w = _w.map(function (item) { if (item.id === id) { hasState = true; item = Object.assign(item, obj); } return item; }); if (hasState) { _this.setState({ widgetsState: _w }, callback); } else { _w.push(obj); _this.setState({ widgetsState: _w }, callback); } }; _this.setConfigVisible = function (b) { if (_this.newElementId !== "") { var widgets = _this.state.pageConfig.widgets; var _widgets = widgets.filter(function (item) { return item.id !== _this.newElementId; }); _this.props.onChange && _this.props.onChange(_widgets); _this.newElementId = ""; } else { _this.setState({ attrDrawerId: "" }); } }; _this.generateDOM = function () { var widgets = _this.state.pageConfig.widgets.filter(function (ele) { return !_this.props.hideComList.includes(ele.type); }); var comDict = _this.props.comDict; return _lodash["default"].map(widgets, function (ele, i) { var item = (0, _util.fixWidget)(ele); var Com = _this.props.ExpCom ? _this.props.ExpCom : (0, _util.getComRequire)(item.type, comDict, _this.props.customGetComRequire); var layouts = item.layouts; if (layouts.y === null) { layouts.y = 0; } var editClassName = _this.props.isEdit ? " edit" : ""; var selectClassName = _this.props.selectedId === item.id && _this.props.isEdit ? " selected" : ""; var _style = item.comContainerAttributes ? item.comContainerAttributes : (0, _util.getBaseAttributes)(); //标记属性面板是否打开 var configVisible = _this.state.attrDrawerId === item.id; return /*#__PURE__*/_react["default"].createElement("div", { onClick: function onClick(e) { e.stopPropagation(); _this.props.isEdit && _this.props.onSelect && _this.props.onSelect(item.id); }, className: "drag-item-custom" + editClassName + selectClassName, key: layouts.i, style: _style, id: item.id }, /*#__PURE__*/_react["default"].createElement(DragItem, { config: item, setPageState: _this.setPageState.bind((0, _assertThisInitialized2["default"])(_this)), removePageState: _this.removePageState.bind((0, _assertThisInitialized2["default"])(_this)), pageProps: _this.state.pageState, isEdit: _this.props.isEdit, onRemoveItem: _this.onRemoveItem.bind((0, _assertThisInitialized2["default"])(_this), i, item) //快速点击,用以区分拖拽和点击事件 , onQuickClick: function onQuickClick() { _this.setState({ attrDrawerId: item.id }); }, render: /*#__PURE__*/_react["default"].createElement(Com, { isEdit: _this.props.isEdit, config: item, pageProps: _this.state.pageState, widgetsProps: _this.state.widgetsState, setPageState: _this.setPageState.bind((0, _assertThisInitialized2["default"])(_this)), removePageState: _this.removePageState.bind((0, _assertThisInitialized2["default"])(_this)), setWidgetsState: _this.setWidgetsState.bind((0, _assertThisInitialized2["default"])(_this)), request: _this.props.request, jumpto: _this.props.jumpto, onConfigChange: _this.onComConfigChange.bind((0, _assertThisInitialized2["default"])(_this)), toggleFullScreen: function toggleFullScreen(id) { return _this.toggleFullScreen(id || item.id); }, getFullScreenState: function getFullScreenState() { return !!_this.fullScreenItem[item.id]; }, getComRequire: _util.getComRequire, customGetComRequire: _this.props.customGetComRequire, getBaseAttributes: _util.getBaseAttributes, onSelect: function onSelect(id) { _this.props.onSelect(id); }, selectedId: item.type === _constant.CONTAINER_COM_TYPE ? _this.props.selectedId : null, allWidgets: widgets, onAllWidgetsChangeByCom: _this.onAllWidgetsChangeByCom.bind((0, _assertThisInitialized2["default"])(_this)), dragPanelIsDroppable: _this.props.layoutProps.isDroppable, hideComList: _this.props.hideComList, comDict: comDict, setConfigVisible: _this.setConfigVisible.bind((0, _assertThisInitialized2["default"])(_this)) //组件属性面板是否打开 , configVisible: configVisible //组件透传面板状态 , dragPanelState: _this.state //组件透传修改面板状态方法 , setDragPanelState: function setDragPanelState(v) { _this.setState(v); }, appConfig: _this.props.appConfig, pageConfig: _this.state.pageConfig }) })); }); }; _this.generateLayouts = function () { var widgets = _this.state.pageConfig.widgets; return _lodash["default"].map(widgets, function (l, i) { var layouts = l.layouts; if (layouts.y === null) { layouts.y = 0; } return layouts; }); }; _this.onComConfigChange = function (comWidget, callback, isUpdateService) { if (isUpdateService === void 0) { isUpdateService = true; } _this.newElementId = ""; var widgets = _this.state.pageConfig.widgets; var _widgets = widgets.map(function (i) { if (comWidget.id === i.id) { return comWidget; } return i; }); _this.props.onChange && _this.props.onChange(_widgets, callback, isUpdateService); }; _this.onAllWidgetsChangeByCom = function (allWidgets, callback, isUpdateService) { if (isUpdateService === void 0) { isUpdateService = true; } _this.props.onChange && _this.props.onChange(allWidgets, callback, isUpdateService); }; _this.toggleFullScreen = function (widgetId) { if (_this.fullScreenItem[widgetId]) { var fullItem = document.getElementById(widgetId); if (fullItem) { _this.escFullScreen(fullItem, widgetId); return false; } else { _this.fullScreenItem[widgetId] = null; _this.fullScreen(widgetId); return true; } } else { _this.fullScreen(widgetId); return true; } }; _this.escFullScreen = function (fullItem, widgetId) { var _this$mainRef, _this$mainRef$element; var canvas = (_this$mainRef = _this.mainRef) === null || _this$mainRef === void 0 ? void 0 : (_this$mainRef$element = _this$mainRef.elementRef) === null || _this$mainRef$element === void 0 ? void 0 : _this$mainRef$element.current; if (!canvas) { return; } var parentNode = canvas.parentNode; var childNodes = canvas.childNodes; parentNode.style.overflow = ""; if (_this.fullScreenItem[widgetId].fullItemParentNode) { _this.fullScreenItem[widgetId].fullItemParentNode.appendChild(fullItem); fullItem.style.width = _this.fullScreenItem[widgetId].oldStyle.width; fullItem.style.height = _this.fullScreenItem[widgetId].oldStyle.height; fullItem.style.margin = _this.fullScreenItem[widgetId].oldStyle.margin; fullItem.style.padding = 0; } else { fullItem.style.width = _this.fullScreenItem[widgetId].oldStyle.width; fullItem.style.height = _this.fullScreenItem[widgetId].oldStyle.height; fullItem.style.transform = _this.fullScreenItem[widgetId].oldStyle.transform; fullItem.style.zIndex = ""; } childNodes.forEach(function (ele) { ele.style.display = ""; }); _this.fullScreenItem[widgetId] = null; (0, _util.dispatchResizeEvent)(0); }; _this.fullScreen = function (widgetId) { var _this$mainRef2, _this$mainRef2$elemen; var canvas = (_this$mainRef2 = _this.mainRef) === null || _this$mainRef2 === void 0 ? void 0 : (_this$mainRef2$elemen = _this$mainRef2.elementRef) === null || _this$mainRef2$elemen === void 0 ? void 0 : _this$mainRef2$elemen.current; if (!canvas) { return; } var fullItem = document.getElementById(widgetId); var isContent = !fullItem.className.includes("react-grid-item"); var fullItemParentNode = fullItem.parentNode; var parentNode = canvas.parentNode; var childNodes = canvas.childNodes; childNodes.forEach(function (ele) { ele.style.display = "none"; }); parentNode.style.overflow = "hidden"; parentNode.scrollTop = 0; if (isContent) { canvas.appendChild(fullItem); _this.fullScreenItem[widgetId] = { oldStyle: { width: fullItem.style.width, height: fullItem.style.height, margin: fullItem.style.margin, padding: 0 }, fullItemParentNode: fullItemParentNode }; fullItem.style.width = "100%"; fullItem.style.height = parentNode.clientHeight + "px"; fullItem.style.padding = fullItem.style.margin; fullItem.style.margin = 0; } else { _this.fullScreenItem[widgetId] = { oldStyle: { width: fullItem.style.width, height: fullItem.style.height, transform: fullItem.style.transform } }; fullItem.style.display = ""; fullItem.style.width = "100%"; fullItem.style.height = parentNode.clientHeight + "px"; fullItem.style.transform = "translate(0px, 0px)"; fullItem.style.zIndex = 1; } }; _this.keepFull = function () { if (_this.fullScreenItem) { var _this$mainRef3, _this$mainRef3$elemen; var canvas = (_this$mainRef3 = _this.mainRef) === null || _this$mainRef3 === void 0 ? void 0 : (_this$mainRef3$elemen = _this$mainRef3.elementRef) === null || _this$mainRef3$elemen === void 0 ? void 0 : _this$mainRef3$elemen.current; if (!canvas) { return; } var parentNode = canvas.parentNode; var childNodes = canvas.childNodes; var fullItem = null; for (var key in _this.fullScreenItem) { if (Object.hasOwnProperty.call(_this.fullScreenItem, key)) { var element = document.getElementById(key); if (element && _this.fullScreenItem[key]) { fullItem = element; } } } if (fullItem) { setTimeout(function () { childNodes.forEach(function (ele) { ele.style.display = "none"; }); fullItem.style.display = ""; fullItem.style.width = "100%"; fullItem.style.height = parentNode.clientHeight + "px"; fullItem.style.transform = "translate(0px, 0px)"; fullItem.style.zIndex = 1; }, 0); } } }; _this.onDrop = function (layout, wd, e) { var item = JSON.parse(e.dataTransfer.getData("text")); if (!item.importFrom || item.type === _constant.COMLIST_TEMPLATE_TYPE) { if (_this.state.pageConfig.widgets.length === 0) { var newTemplate = (0, _util.templateReId)(item.template, _this.state.pageConfig.pageId); _this.props.allPageOnChange && _this.props.allPageOnChange(newTemplate); } else { _dialog["default"].confirm({ title: "清空", content: "更换布局会清空当前编辑区的内容,是否继续?", messageProps: { type: "warning" }, onOk: function onOk() { var newTemplate = (0, _util.templateReId)(item.template, _this.state.pageConfig.pageId); _this.props.allPageOnChange && _this.props.allPageOnChange(newTemplate); } }); _this.props.onChange && _this.props.onChange(_this.state.pageConfig.widgets); } } else { var widgets = _this.state.pageConfig.widgets; var layoutObj = {}; layout.forEach(function (litem) { if (litem.i) { layoutObj[litem.i] = litem; } }); item.layouts = wd; item.layouts.isDraggable = undefined; item.layouts.i = item.id = (0, _utils.getUUID)(); item = (0, _util.fixWidget)(item); var _widgets = _lodash["default"].cloneDeep(widgets); _widgets = _widgets.map(function (i) { if (layoutObj[i.id]) { i.layouts = layoutObj[i.id]; } return i; }); var __widgets = _widgets.concat((0, _extends2["default"])({}, item)); _this.newElementId = item.id; _this.props.onChange && _this.props.onChange(__widgets); //当组件拖拽到画布后,立即选中该组件 _this.props.onSelect && _this.props.onSelect(item.id); //设置打开当前新建组件属性抽屉 if (item.type !== _constant.CONTAINER_COM_TYPE) { _this.setState({ attrDrawerId: item.id }); } } }; _this.fullScreenItem = {}; //标记是否可以执行onLayoutChange内事件 _this.candoLayoutChange = false; _this.state = { pageState: (0, _extends2["default"])({}, props.pageProps), widgetsState: [], pageConfig: (0, _util.fitHeight)(props.pageConfig, props.parentDOM, props.isEdit), minHeight: "100%", attrDrawerId: "" //属性面板改为内置后,以此来记录当前打开属性面板的组件id。无打开为空 }; _this.newElementId = ""; window.addEventListener("resize", _this.onResize); return _this; } var _proto = DragLayoutCanvas.prototype; _proto.componentWillUnmount = function componentWillUnmount() { window.removeEventListener("resize", this.onResize); }; _proto.componentDidUpdate = function componentDidUpdate() { //配置项变化时,需保持全屏组件的样式 this.keepFull(); // const resizables = document.getElementsByClassName('react-resizable-handle'); // resizables.forEach((item) => { // item.addEventListener('click', (e) => { // e.stopPropagation(); // }); // }); // console.log(resizables); }; DragLayoutCanvas.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) { var configObj = {}; var pagePropsObj = {}; if ("pageConfig" in nextProps) { configObj = { pageConfig: (0, _util.fitHeight)(nextProps.pageConfig, nextProps.parentDOM, nextProps.isEdit) }; } if ("pageProps" in nextProps) { pagePropsObj = { pageState: nextProps.pageProps }; } return (0, _extends2["default"])({}, configObj, pagePropsObj); }; _proto.onRemoveItem = function onRemoveItem(i, ele) { var _this2 = this; _dialog["default"].confirm({ title: "删除", content: ele.type === _constant.CONTAINER_COM_TYPE ? "删除容器会同时删除内部组件,是否继续?" : "是否删除所选组件?", messageProps: { type: "warning" }, onOk: function onOk() { var widgets = _this2.state.pageConfig.widgets; var _widgets = widgets.filter(function (item, index) { return index !== i; }); _this2.props.onChange && _this2.props.onChange(_widgets); } }); }; _proto.layoutToWidget = function layoutToWidget(layout) { var widgets = this.state.pageConfig.widgets; var _widgets = _lodash["default"].cloneDeep(widgets); layout.forEach(function (item, index) { if (_widgets[index]) { _widgets[index].layouts = item; } }); return _widgets; } //拖拽事件会允许执行onLayoutChange ; _proto.onDragStop = function onDragStop() { this.candoLayoutChange = true; } //形状变化允许执行onLayoutChange ; _proto.onResizeStop = function onResizeStop() { this.candoLayoutChange = true; } //布局变更触发外部onChange,并立即将candoLayoutChange标记为不允许 ; _proto.onLayoutChange = function onLayoutChange(layout) { var _this3 = this; //动态设置最小高度,保证编辑模式下,留白半个屏幕的空间 if (this.props.isEdit) { var parentClassName = "creater-canvas" + (this.props.tabKey ? " " + this.props.tabKey : ""); var canvasDom = document.getElementsByClassName(parentClassName)[0]; if (!(0, _util.checkVisibility)(canvasDom)) { this.setState({ minHeight: "100%" }); } else { var minHeight = canvasDom.clientHeight; var wedgetHeights = [0]; layout.forEach(function (ele) { wedgetHeights.push((ele.h + ele.y) * _this3.state.pageConfig.layoutConfig.rowHeight); }); var wedgetMinHeight = Math.max.apply(Math, wedgetHeights.concat([minHeight])); this.setState({ minHeight: wedgetMinHeight + minHeight / 2 }); } } else { this.setState({ minHeight: "100%" }); } if (this.candoLayoutChange) { var widgets = this.layoutToWidget(layout); this.props.onChange && this.props.onChange(widgets); this.candoLayoutChange = false; } }; _proto.render = function render() { var _this4 = this; var _this$props = this.props, layoutProps = _this$props.layoutProps, isEdit = _this$props.isEdit; var pageConfig = this.state.pageConfig; var layouts = this.generateLayouts(); return /*#__PURE__*/_react["default"].createElement(ReactGridLayout, (0, _extends2["default"])({ resizeHandle: /*#__PURE__*/_react["default"].createElement("span", { onClick: function onClick(e) { e.stopPropagation(); }, className: "react-resizable-handle react-resizable-handle-se" }), style: (0, _extends2["default"])({}, this.props.style, { minHeight: this.state.minHeight }), ref: function ref(node) { _this4.mainRef = node; }, onDrop: this.onDrop.bind(this), isDraggable: isEdit, isResizable: isEdit }, layoutProps, pageConfig.layoutConfig, { layout: layouts, onResizeStop: this.onResizeStop.bind(this), onDragStop: this.onDragStop.bind(this), onLayoutChange: this.onLayoutChange.bind(this) }), this.generateDOM()); }; return DragLayoutCanvas; }(_react.Component); DragLayoutCanvas.propTypes = { /** * ResponsiveReactGridLayout组件属性 */ layoutProps: _propTypes["default"].object, /** * 当前选中项id */ selectedId: _propTypes["default"].string, /** * 子组件选中回调(id)=>{} */ onSelect: _propTypes["default"].func, /** * 是否是编辑模式 */ isEdit: _propTypes["default"].bool, /** *(widgets)=>{}切换布局,增加组件,删除组件回调,将组件配置数据传出 */ onChange: _propTypes["default"].func, /** *(pageConfig)=>{}装载布局回调,将页面配置数据传出 */ allPageOnChange: _propTypes["default"].func, /** * 页面顶级参数,例如业务详情页面的业务appId将放在此属性中,供组件以及页面使用 */ pageProps: _propTypes["default"].object, /** * 在开发npm包组件时需用到此属性。面板使用者无需使用此属性 */ ExpCom: _propTypes["default"].any, /** * 应用框架级数据请求方法,用来实现数据请求,参考 {request} from 'ice' */ request: _propTypes["default"].any, /** * (path)=>{}页面跳转操作 */ jumpto: _propTypes["default"].func, /** * 画布要展示内容的配置数据 */ pageConfig: _propTypes["default"].object, /** *画布外层dom对象,用来实现自动适配高度的功能 */ parentDOM: _propTypes["default"].any, /** * 自定义导入组件类方法,请参考util.js中的getComRequire实现此方法 * (comName, importFrom)=>component Class */ customGetComRequire: _propTypes["default"].func, /** * 隐藏不显示的组件列表 * 数组内放置组件type */ hideComList: _propTypes["default"].array }; DragLayoutCanvas.defaultProps = { layoutProps: { droppingItem: { i: "drop", w: 12, h: 5 }, //拖拽到画布上的组件预显示区域 className: "layout" //类名,固定值 }, selectedId: undefined, isEdit: true, ExpCom: undefined, hideComList: [], pageConfig: { pageId: "", pageName: "", widgets: [], layoutConfig: { cols: 24, //默认栅格为24格 rowHeight: 40, //高度比为40倍 margin: [0, 0], //默认间隔 measureBeforeMount: true, //如果为true,画布将在装入组件之前测量容器宽度。 isFitHeight: false, //浏览模式是否一屏显示 isShowGrid: true //编辑模式是否显示网格 } } }; var DragItem = /*#__PURE__*/function (_Component2) { (0, _inheritsLoose2["default"])(DragItem, _Component2); function DragItem(props) { var _this5; _this5 = _Component2.call(this, props) || this; //快速点击时间戳 _this5.quickClickTime = 0; var config = props.config, setPageState = props.setPageState; if (config && config.publishProps) { config.publishProps.forEach(function (item) { var _setPageState; setPageState((_setPageState = {}, _setPageState[item.key] = item.defaultValue, _setPageState)); }); } return _this5; } var _proto2 = DragItem.prototype; _proto2.componentWillUnmount = function componentWillUnmount() { var _this$props2 = this.props, config = _this$props2.config, removePageState = _this$props2.removePageState; if (config && config.publishProps) { removePageState(config.publishProps.map(function (item) { return item.key; })); } }; _proto2.render = function render() { var _this$props3 = this.props, children = _this$props3.children, config = _this$props3.config, pageProps = _this$props3.pageProps, isEdit = _this$props3.isEdit, onRemoveItem = _this$props3.onRemoveItem, render = _this$props3.render, onQuickClick = _this$props3.onQuickClick; var isHideConfig = config === null || config === void 0 ? void 0 : config.isHideConfig; var lackInfoElements = []; var removeElement = isEdit ? /*#__PURE__*/_react["default"].createElement(_button["default"].Group, { className: "option-group" }, /*#__PURE__*/_react["default"].createElement(_button["default"], { className: "option-children ", onMouseDown: function onMouseDown(e) { e.stopPropagation(); }, onClick: function onClick(e) { e.stopPropagation(); onRemoveItem(); }, title: "\u5220\u9664\u7EC4\u4EF6", text: true, style: { color: "white" } }, /*#__PURE__*/_react["default"].createElement(_icon["default"], { type: "ashbin" })), isHideConfig ? null : /*#__PURE__*/_react["default"].createElement(_button["default"], { className: "option-children ", onMouseDown: function onMouseDown(e) { e.stopPropagation(); }, onClick: function onClick(e) { e.stopPropagation(); onQuickClick(); }, title: "\u8BBE\u7F6E", text: true, style: { color: "white" } }, /*#__PURE__*/_react["default"].createElement(_icon["default"], { type: "set" }))) : null; //只有在浏览模式下(!isEdit),缺少等级属性,才会显示为lackInfoElements if (!isEdit && config && config.dependentProps) { config.dependentProps.forEach(function (item) { if (!(item.key in pageProps)) { lackInfoElements.push( /*#__PURE__*/_react["default"].createElement("div", { key: item.key }, item.info)); } }); } return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, lackInfoElements.length > 0 ? /*#__PURE__*/_react["default"].createElement("div", { style: { width: "100%", height: "100%", border: "1px solid #e9e9e9", background: "white" } }, lackInfoElements) : render, isEdit && config.type !== _constant.CONTAINER_COM_TYPE ? /*#__PURE__*/ //在遮罩面板上增加快速点击事件,实现弹出组件抽屉的行为 _react["default"].createElement("div", { // onMouseDown={() => { // this.quickClickTime = new Date().getTime(); // }} // onMouseUp={() => { // if (this.quickClickTime) { // this.quickClickTime = new Date().getTime() - this.quickClickTime; // if (this.quickClickTime < quickClickInterval) { // onQuickClick(); // } // this.quickClickTime = 0; // } // }} className: "edit-item-mask" }) : null, removeElement, children); }; return DragItem; }(_react.Component); var _default = DragLayoutCanvas; exports["default"] = _default;