@uyun/grid-layout-screen
portal拖拽布局
Last updated 6 years ago by chengdiao .
ISC · Repository ·
$ cnpm install @uyun/grid-layout-screen 
Private package

@uyun/grid-layout-screen

portal 拖拽布局

示例

import {
  Screen, // 屏整体布局组件
  GridLayout, // 拖拽部分
  GridLayoutHeader, // 布局头部标题和按钮
  Widget // widget渲染部分
} from "@uyun/grid-layout-screen";

Screen

页面整体布局部分,用于放置 GridLayout

API

i18n = {
  loadingText: "加载中..."
};
参数 类型 说明
loading boolean 是否显示加载效果
i18n object 多语言内容
children JSX.Element 子元素

GridLayout

拖拽部分主体部分

API

type MaterialType = {
  title: string,
  disabled?: boolean
  // ...可携带其他任意属性
};
type Data = {
  jsUrl: string, // js文件地址
  cssUrl: string, // css文件地址
  title: string // widget标题
};
type LayoutItem = {
  i: string, // 布局元素的唯一标识
  x: number, // 布局元素的位置信息
  y: number,
  w: number,
  h: number,
  minW?: number, // 最小宽度
  minH?: number, // 最小高度
  maxW?: number, // 最大宽度
  maxH?: number, // 最小宽度
  static?: boolean, // 是否是静态的元素,即不永远不变化位置
  isDraggable?: ?boolean, // 是否可拖拽
  isResizable?: ?boolean, // 是否可调整大小
  data: Data // 拖拽元素对应的widget信息
};
i18n = {
  materialsTitle: "部件列表",
  materialsDesc: "选择所需部件,并拖至相应位置",
  materialsEmpty: "没有可用部件"
};
参数 类型 说明
i18n object 多语言内容
cols number 布局列数
rowHeight number 布局每一个单位的高度
margin number[] 布局元素间的 x 方向和 y 方向的距离
layout LayoutItem[] 布局数据
materials MaterialType[] widget 列表
isEditable boolean 是否处于可编辑状态
onLayoutChange (layout: LayoutItem[]) => void 布局改变之后的回调,回调参数为新的布局数组
header JSX.Element 头部的屏标题和操作按钮
children (layoutItem: LayoutItem) => JSX.Element 布局中的每一项的渲染函数

GridLayoutHeader

布局头部样式

API

type ButtonItem = {
  icon: JSX.Element, // 按钮图标
  text: string, // 按钮文字
  disabled: false, // 是否禁用
  onClick: () => void // 点击回调
};
i18n = {
  cancel: "取消",
  ok: "保存"
};
参数 类型 说明
i18n object 多语言内容
isEditable boolean 是否处于可编辑状态
title string 头部标题
buttons ButtonItem[] 头部的屏标题和操作按钮
onCancel () => void 取消按钮点击回调
onOk () => void 确定按钮点击回调
onTitleChange (e: Event) => void 标题输入改变事件

Widget

type Data = {
  jsUrl: string, // js文件地址
  cssUrl: string, // css文件地址
  title: string // widget标题
};
i18n = {
  deleteTips: "确定删除部件吗?",
  loadingText: "加载中...",
  loadError: "部件加载失败!",
  renderError: "部件内部出错无法显示!"
};
参数 类型 说明
i18n object 多语言内容
i string 部件的唯一 id,与 layout 中的 i 相同
isEditable boolean 是否处于可编辑状态
data Data 部件渲染相关的数据,与LayoutItem中的 data 是一致的
onDelete (i:string, data: Data) => void 删除部件事件回调
onChange (i:string, data: Data) => void widget 改变事件回调,如标题等

使用示例

import React from "react";
import {
  Screen,
  GridLayout,
  GridLayoutHeader,
  Widget
} from "@uyun/grid-layout-screen";
import request from "@/utils/request";
import { Icon } from "@uyun/components";
import cloneDeep from "lodash/cloneDeep";

export default class extends React.Component {
  state = {
    title: "",
    loading: true,
    widgets: [],
    layout: [],
    isEditable: false,
    data: {}
  };

  buttons = [
    {
      action: "edit",
      icon: <Icon type="edit" />,
      text: "编辑",
      disabled: false,
      onClick: () => {
        this.setState({
          isEditable: true,
          data: {
            layout: cloneDeep(this.state.layout),
            title: this.state.title
          }
        });
      }
    },
    {
      action: "copy",
      icon: <Icon type="copy" />,
      text: "复制",
      disabled: false
    },
    {
      action: "add",
      icon: <Icon type="plus" />,
      text: "添加屏",
      disabled: false
    },
    {
      action: "authorize",
      icon: <Icon type="user-switch" />,
      text: "授权",
      disabled: false
    },
    {
      action: "delete",
      icon: <Icon type="delete" />,
      text: "删除",
      disabled: false
    },
    {
      action: "home",
      icon: <Icon type="home" />,
      text: "设为主屏",
      disabled: false
    }
  ];

  componentDidMount() {
    Promise.all([
      request.get("/portal/frontapi/v1/widget/getOriginalWidget"),
      request.get("/portal/frontapi/v1/screen/getScreenWidget?id=165")
    ]).then(([widgets, screen]) => {
      this.setState({
        title: screen.data.name,
        layout: screen.data.widgets.map((item, index) => {
          const { width, height, minHeight, ...layout } = item.layout;
          return {
            ...layout,
            i: `${item.id}-${index}`,
            w: Math.round(width),
            h: Math.round(height / 60),
            minH: Math.round(minHeight / 60),
            data: item
          };
        }),
        widgets: widgets.data.map(item => {
          if (item.config.repeat === 0) {
            if (screen.data.widgets.find(it => it.name === item.name)) {
              item.disabled = true;
            }
          }
          if (!item.authorized) {
            item.disabled = true;
          }
          return item;
        }),
        loading: false
      });
    });
  }

  onLayoutChange = items => {
    this.setState({
      layout: items
    });
  };

  onDrop = widget => {
    const { widgets } = this.state;
    const index = widgets.findIndex(
      item => item.insertWidgetId === widget.insertWidgetId
    );
    if (index === -1) return;
    if (widget.config.repeat === 0) {
      widgets[index].disabled = true;
    }
    console.log(index);
    this.setState({
      widgets
    });
  };

  onWidgetChange = (i, data) => {
    const { layout } = this.state;
    const index = layout.findIndex(item => item.i === i);
    if (index === -1) return;
    layout[index].data = data;
    this.setState({
      layout
    });
  };

  onWidgetDelete = (i, data) => {
    const { layout, widgets } = this.state;
    const index = layout.findIndex(item => item.i === i);
    if (index === -1) return;
    layout.splice(index, 1);
    const idx = widgets.findIndex(({ name }) => data.name === name);
    if (idx === -1) return;
    const widget = widgets[idx];
    if (widget.config.repeat === 0) {
      widgets[idx].disabled = false;
    }
    console.log(idx);
    this.setState({
      layout,
      widgets
    });
  };

  screenHeaderChange = e => {
    this.setState({
      title: e.target.value
    });
  };

  exitEdit = () => {
    const { layout = [], title = "" } = this.state.data;

    this.setState({
      isEditable: false,
      layout,
      title
    });
  };

  save = () => {
    this.setState({
      isEditable: false
    });
  };

  render() {
    return (
      <Screen
        loading={this.state.loading}
        i18n={{
          loadingText: "加载中..."
        }}
      >
        <GridLayout
          i18n={{
            materialsTitle: "部件列表",
            materialsDesc: "选择所需部件,并拖至相应位置"
          }}
          cols={6}
          rowHeight={50}
          margin={[15, 10]}
          layout={this.state.layout}
          materials={this.state.widgets}
          isEditable={this.state.isEditable}
          onDrop={this.onDrop}
          onLayoutChange={this.onLayoutChange}
          header={
            <GridLayoutHeader
              i18n={{
                cancel: "取消",
                ok: "保存"
              }}
              isEditable={this.state.isEditable}
              buttons={this.buttons}
              title={this.state.title}
              onTitleChange={this.screenHeaderChange}
              onCancel={this.exitEdit}
              onOk={this.save}
            />
          }
        >
          {item => {
            return (
              <Widget
                {...item}
                i18n={{
                  deleteTips: "确定删除部件吗?",
                  loadingText: "加载中...",
                  loadError: "部件加载失败!",
                  renderError: "部件内部出错无法显示!"
                }}
                isEditable={this.state.isEditable}
                onChange={this.onWidgetChange}
                onDelete={this.onWidgetDelete}
              />
            );
          }}
        </GridLayout>
      </Screen>
    );
  }
}

Current Tags

  • 0.0.3                                ...           latest (6 years ago)

3 Versions

  • 0.0.1                                ...           6 years ago
  • 0.0.2                                ...           6 years ago
  • 0.0.3                                ...           6 years ago
Maintainers (1)
Downloads
Today 0
This Week 0
This Month 0
Last Day 0
Last Week 0
Last Month 0
Dependencies (6)
Dependents (0)
None

Copyright 2013 - present © cnpmjs.org