只需简单几步即可拥有动态仪表板功能
解决的是"千人千面"的 B 端几乎都要用到的 Dashboard + Widget 客制化需求。
https://github.com/yuanguandong/react-dashboard-pro
https://yuanguandong.github.io/react-dashboard-pro/
npm i react-dashboard-pro -S
git clone https://github.com/yuanguandong/react-widgets
import React, { useState } from 'react';
import type { LayoutsIF } from 'react-dashboard-pro';
import Dashboard from 'react-dashboard-pro';
import allWidgets from '../widgets';
export default () => {
const [layout, setLayout] = useState<LayoutsIF>([]);
const onLayoutChange = (layout: LayoutsIF) => {
setLayout(layout);
};
return (
<Dashboard
widgets={allWidgets}
onLayoutChange={onLayoutChange}
layout={layout}
/>
);
};
property | description | type | defaultValue | required |
---|---|---|---|---|
widgets | 可选的小程序对象集合 | { [key: string]:widget} | true | |
editMode | 是否编辑状态 | boolean | false | false |
defaultLayout | 默认布局 | layoutItem[] | [] | false |
widgetWrapClassName | widget 容器类名 | string | false | |
widgetWrapStyle | widget 容器样式 | React.CSSProperties | false | |
layout | 布局数据 | layoutItem[] | null | false |
minHeight | 最小高度 | number | 300 | false |
maxWidgetLength | 当前仪表板最大可添加的 widget 数量 | number | 20 | false |
toolbar | 是否显示默认工具栏 | {type: 'left' | 'right' | 'top' | 'bottom'; speed: number;} | true | false |
storageKey | 本地存储唯一标识 | boolean | 'default' | false |
onLayoutChange | 布局改变的回调 | (layout: LayoutsIF) => void | false | |
onReset | 清空按钮的回调 | (dirtyCurrentLayout: LayoutsIF, currentLayout: LayoutItem) => void | false | |
onRemoveWidget | 删除小程序的回调 | (widget: widgetIF,dirtyCurrentLayout: LayoutsIF,currentLayout: LayoutsIF) => void | false | |
onAddWidget | 添加小程序的回调 | (widget: widgetIF,dirtyCurrentLayout: LayoutsIF,currentLayout: LayoutsIF) => void | false | |
onReload | 刷新按钮的回调 | (currentLayout: LayoutsIF) => void | false | |
onCancelEdit | 取消编辑的回调 | (dirtyCurrentLayout: LayoutsIF,currentLayout: LayoutItem) => void | false | |
onEdit | 进入编辑的回调 | (currentLayout: LayoutsIF) => void | false | |
onSave | 保存按钮的回调 | (currentLayout: LayoutsIF) => void | false | |
onRevert | 恢复按钮的回调 | (dirtyCurrentLayout: LayoutsIF, currentLayout: LayoutItem) => void | false |
widget 可以是开放式的任何内容,可以自由扩展,入口文件需要导出一个对象来描述这个 widget, 对象格式如下,更多 widget 可以看这里
预设的 widget 基本都依赖了 antd,使用了 less, 注意依赖的安装
property | description | type | defaultValue | required |
---|---|---|---|---|
name | 小程序名称 | string | true | |
description | 小程序描述 | string | true | |
tags | 标签,被用作小程序选择器分类依据 | string[] | true | |
component | 小程序组件 | ReactElement | true | |
configComponent | 小程序对应的配置组件 | ReactElement | true | |
maxLength | 该小程序在当前仪表板最大可添加数量 | number | true | |
snapShot | 小程序快照图片,用于小程序选择器显示 | ImageBitmapSource | true | |
icon | 小程序图标,用于小程序选择器显示 | ReactElement | true | |
iconBackground | 小程序图标背景,用于小程序选择器显示 | string | true | |
size | 小程序尺寸信息 | {defaultWidth: number;defaultHeight: number;maxWidth: number;maxHeight: number;minWidth: number;minHeight: number} | true |
// todo/index.tsx
import { CalendarOutlined } from '@ant-design/icons';
import Panel from './component';
import snapShot from './snapshot.png';
export default {
name: 'Todo',
description: 'todo list',
tags: ['all','list'],
component: Panel,
configComponent: null,
maxLength: 2,
snapShot,
icon: <CalendarOutlined />,
iconBackground: 'linear-gradient(-20deg, #b721ff 0%, #21d4fd 100%)',
size: {
defaultWidth: 3,
defaultHeight: 11,
maxWidth: 12,
maxHeight: 16,
minWidth: 2,
minHeight: 4,
},
}
// **/**.index ……
// widgets/index.tsx
import Clock from './clock';
import Column from './column';
import Guide from './guide';
import Popular from './popular';
import Ring from './ring';
import Todo from './todo';
export default{ Clock,Guide,Popular,Todo,Column,Ring };
布局信息一般情况下不需要太关注,只需要序列化的以字符串方式存储下来即可,若想实时获取仪表板布局数据(比如要设置默认布局时),可以聚焦(鼠标点击)到对应的仪表板,按快捷键 <Text keyboard>Ctrl</Text>+<Text keyboard>Shift</Text>+<Text keyboard>C</Text> 复制布局数据到剪切板,同时 console 面板也会打印出来布局数据
property | description | type | defaultValue | required |
---|---|---|---|---|
i | 唯一标识, 以小程序的唯一标识加中划线开头,如 'widgetKey-1234567' | string | true | |
w | 宽度份数,总共 12 份 | number | true | |
h | 高度份数,1 份大概 30px | number | true | |
x | 横向位置,总共 12 份 | number | true | |
y | 纵向位置,1 份大概 30px | number | true | |
minW | 最小宽度 | number | true | |
maxW | 最大宽度 | number | true | |
minH | 最小高度 | number | true | |
maxH | 最大高度 | number | true |
export default [
{
w: 3,
h: 16,
x: 0,
y: 0,
i: 'Popular-81735522335293475546087951289435',
},
{
w: 3,
h: 11,
x: 3,
y: 5,
i: 'Todo-53084247679600442035440807237732',
}
]
可通过 ref 获取组件实例,实例对象上挂载了一些方法和 dom 对象,可以方便拓展自定义的 Toolbar 和 WidgetSelector
property | description | type |
---|---|---|
dom | DOM 对象 | HTMLDivElement |
addWidget | 添加小程序 | (widget)=>void |
removeWidget | 删除小程序 | (i:widgetKey)=>void |
reload | 刷新 | ()=>void |
edit | 进入编辑 | ()=>void |
cancelEdit | 取消编辑 | ()=>void |
revert | 重置 | ()=>void |
save | 保存 | ()=>void |
import React,{useRef} from 'react';
import Dashboard from 'react-dashboard-pro';
import allWidgets from '../widgets';
export default () => {
const ref = useRef()
const addWidget = ()=>{
ref.current.addWidget('Todo-1234567')
}
return (<>
<Dashboard
ref={ref}
widgets={allWidgets}
/>
<button onClick={addWidget}>新增</button>
</>
);
};
✅ configPanel
☑️ gap
☑️ modern theme
☑️ dark theme
☑️ more widget
☑️ widget-cli
☑️ 国际化
觉得有用的话点个 star 吧 🙊,支持一下吧!
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.