├── .husky ├── .gitignore ├── pre-commit └── commit-msg ├── public ├── robots.txt ├── favicon.ico ├── static │ ├── banner.jpg │ ├── templet │ │ ├── bg.jpg │ │ ├── background-1.png │ │ ├── background-10.png │ │ ├── background-11.png │ │ ├── background-12.png │ │ ├── background-13.png │ │ ├── background-14.png │ │ ├── background-15.png │ │ ├── background-16.png │ │ ├── background-17.jpg │ │ ├── background-18.jpg │ │ ├── background-19.jpg │ │ ├── background-2.png │ │ ├── background-20.jpg │ │ ├── background-21.jpg │ │ ├── background-22.jpg │ │ ├── background-23.jpg │ │ ├── background-24.jpg │ │ ├── background-25.jpg │ │ ├── background-26.jpg │ │ ├── background-27.jpg │ │ ├── background-28.jpg │ │ ├── background-29.png │ │ ├── background-3.png │ │ ├── background-4.png │ │ ├── background-5.png │ │ ├── background-6.png │ │ ├── background-7.png │ │ ├── background-8.png │ │ └── background-9.png │ ├── banner-video.mp4 │ ├── component │ │ ├── bar.png │ │ ├── bg.jpg │ │ ├── line.png │ │ ├── pie.png │ │ ├── tab.png │ │ ├── banner.jpg │ │ ├── bubble.png │ │ ├── funnel.png │ │ ├── gauge.png │ │ ├── iframe.png │ │ ├── kline.png │ │ ├── radar.png │ │ ├── sankey.png │ │ ├── attrtable.png │ │ ├── bar-alien.png │ │ ├── bar-heap.png │ │ ├── barpolar.png │ │ ├── china-map.png │ │ ├── line-bar.png │ │ ├── pie-play.png │ │ ├── pie-rose.png │ │ ├── scatter.png │ │ ├── stack-ba.png │ │ ├── step-line.png │ │ ├── tableplay.png │ │ ├── bar-bothway.png │ │ ├── bar-series.png │ │ ├── border-box.png │ │ ├── earth-night.png │ │ ├── line-middle.png │ │ ├── liquid-fill.png │ │ ├── pie-nested.png │ │ ├── word-cloud.png │ │ ├── banner-video.mp4 │ │ ├── bar-contrast.png │ │ ├── bar-crosswise.png │ │ ├── map-province.png │ │ ├── calendar-heatmap.png │ │ ├── cartesian-heatmap.png │ │ ├── TB143rolQL0gK0jSZFxXXXWHVXa-160-116.png │ │ ├── TB19PPllUz1gK0jSZLeXXb9kVXa-332-144.png │ │ ├── TB1IhfqlUY1gK0jSZFCXXcwqXXa-334-144.png │ │ └── TB1cjHmlQP2gK0jSZPxXXacQpXa-332-144.png │ ├── login-bg.svg │ └── spreadsheet │ │ └── zh-cn.js ├── config.js └── index.html ├── src ├── components │ ├── split-panel │ │ ├── index.js │ │ ├── panel.js │ │ ├── resizer.js │ │ └── style.less │ ├── auto-loading │ │ ├── style.less │ │ └── index.js │ ├── auto-container │ │ └── style.less │ ├── vcharts │ │ └── index.js │ ├── iframe │ │ ├── style.less │ │ └── simple.js │ ├── iconfont │ │ └── index.js │ ├── typing │ │ ├── index.js │ │ └── core.js │ ├── index.js │ ├── scrollbar │ │ └── index.js │ ├── monaco-editor │ │ └── index.js │ ├── sketch-ruler │ │ └── line.js │ └── auto-breadcrumb │ │ └── index.js ├── packages │ ├── vcharts │ │ ├── index.js │ │ ├── util.js │ │ ├── options │ │ │ ├── index.js │ │ │ ├── radar.js │ │ │ ├── sankey.js │ │ │ ├── funnel.js │ │ │ ├── scatter.js │ │ │ ├── liquidfill.js │ │ │ ├── wordcloud.js │ │ │ ├── treemap.js │ │ │ ├── gauge.js │ │ │ └── heatmap.js │ │ └── src │ │ │ └── pie.js │ ├── dynamic-dialog │ │ ├── index.js │ │ ├── configuration-schema │ │ │ └── index.js │ │ └── modal.js │ ├── hoc.js │ ├── decoration │ │ ├── index.js │ │ └── src │ │ │ └── decoration3.js │ ├── iframe │ │ ├── style.less │ │ ├── index.js │ │ └── code.js │ ├── checkbox │ │ └── index.js │ ├── form │ │ ├── checkbox │ │ │ ├── index.js │ │ │ └── group.js │ │ ├── switch │ │ │ └── index.js │ │ ├── html │ │ │ └── index.js │ │ ├── container │ │ │ └── style.less │ │ ├── collapse │ │ │ └── index.js │ │ ├── radio │ │ │ └── index.js │ │ ├── number │ │ │ └── index.js │ │ ├── select │ │ │ ├── multiple.js │ │ │ └── index.js │ │ ├── date │ │ │ ├── range.js │ │ │ └── index.js │ │ ├── textarea │ │ │ └── index.js │ │ ├── input │ │ │ ├── size.js │ │ │ └── index.js │ │ ├── slider │ │ │ └── index.js │ │ ├── color │ │ │ └── index.js │ │ ├── upload │ │ │ └── index.js │ │ └── map │ │ │ └── index.js │ ├── switch │ │ └── index.js │ ├── html │ │ └── index.js │ ├── dynamic-actions │ │ ├── configuration-value │ │ │ ├── index.js │ │ │ ├── datav.js │ │ │ └── default.js │ │ └── index.js │ ├── border │ │ ├── index.js │ │ └── src │ │ │ ├── border6.js │ │ │ ├── border9.js │ │ │ ├── border3.js │ │ │ ├── border2.js │ │ │ └── border4.js │ ├── countdown │ │ └── index.js │ ├── checkbox-group │ │ └── index.js │ ├── tabs │ │ └── select.js │ ├── radio │ │ └── index.js │ ├── number │ │ └── index.js │ ├── select │ │ ├── multiple.js │ │ └── index.js │ ├── dependence │ │ └── index.js │ ├── date-picker │ │ ├── range.js │ │ └── index.js │ ├── textarea │ │ └── index.js │ ├── size │ │ └── index.js │ ├── slider │ │ └── index.js │ ├── input │ │ └── index.js │ ├── utils.js │ ├── upload │ │ └── index.js │ ├── color-picker │ │ └── index.js │ ├── indicator │ │ └── index.js │ └── map │ │ └── index.js ├── pages │ ├── designer │ │ ├── renderer │ │ │ ├── index.js │ │ │ ├── generator.js │ │ │ └── parser.js │ │ ├── configuration-schema │ │ │ └── index.js │ │ ├── configuration-value │ │ │ ├── index.js │ │ │ ├── default.js │ │ │ └── other.js │ │ ├── preview.js │ │ ├── configuration-panel │ │ │ └── index.js │ │ └── constants.js │ ├── 404.js │ ├── account │ │ ├── oauth.jsx │ │ └── styles.less │ └── dashboard │ │ ├── index.jsx │ │ └── feat.jsx ├── polyfills.js ├── hooks │ ├── useSet.js │ ├── useDesigner.js │ ├── useDocumentTitle.js │ ├── useDebounce.js │ └── useAutoResize.js ├── router │ ├── history.js │ ├── router-map.js │ └── index.js ├── store │ ├── modules │ │ ├── index.js │ │ ├── tab.js │ │ ├── form.js │ │ ├── app.js │ │ └── component.js │ └── index.js ├── form-render │ ├── transformField.js │ ├── index.js │ ├── getField.js │ ├── atom.less │ └── resolve.js ├── __mocks__ │ ├── modules │ │ ├── echarts.js │ │ └── user.js │ ├── _util.js │ └── index.js ├── styles │ ├── antd-design.less │ ├── account.less │ ├── var.less │ └── format.less ├── layouts │ ├── index.js │ ├── header.js │ └── content.js ├── App.js ├── api │ └── index.js ├── utils │ └── storage.js └── index.js ├── .env ├── .prettierrc ├── .editorconfig ├── .gitignore ├── .github └── workflows │ └── deploy-ci.yml ├── commitlint.config.js ├── README.md ├── package.json └── config-overrides.js /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn run lint-staged 5 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/static/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/banner.jpg -------------------------------------------------------------------------------- /src/components/split-panel/index.js: -------------------------------------------------------------------------------- 1 | import SplitPanel from "./split"; 2 | 3 | export default SplitPanel; 4 | -------------------------------------------------------------------------------- /public/static/templet/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/bg.jpg -------------------------------------------------------------------------------- /public/static/banner-video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/banner-video.mp4 -------------------------------------------------------------------------------- /public/static/component/bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bar.png -------------------------------------------------------------------------------- /public/static/component/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bg.jpg -------------------------------------------------------------------------------- /public/static/component/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/line.png -------------------------------------------------------------------------------- /public/static/component/pie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/pie.png -------------------------------------------------------------------------------- /public/static/component/tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/tab.png -------------------------------------------------------------------------------- /public/static/component/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/banner.jpg -------------------------------------------------------------------------------- /public/static/component/bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bubble.png -------------------------------------------------------------------------------- /public/static/component/funnel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/funnel.png -------------------------------------------------------------------------------- /public/static/component/gauge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/gauge.png -------------------------------------------------------------------------------- /public/static/component/iframe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/iframe.png -------------------------------------------------------------------------------- /public/static/component/kline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/kline.png -------------------------------------------------------------------------------- /public/static/component/radar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/radar.png -------------------------------------------------------------------------------- /public/static/component/sankey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/sankey.png -------------------------------------------------------------------------------- /public/static/component/attrtable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/attrtable.png -------------------------------------------------------------------------------- /public/static/component/bar-alien.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bar-alien.png -------------------------------------------------------------------------------- /public/static/component/bar-heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bar-heap.png -------------------------------------------------------------------------------- /public/static/component/barpolar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/barpolar.png -------------------------------------------------------------------------------- /public/static/component/china-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/china-map.png -------------------------------------------------------------------------------- /public/static/component/line-bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/line-bar.png -------------------------------------------------------------------------------- /public/static/component/pie-play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/pie-play.png -------------------------------------------------------------------------------- /public/static/component/pie-rose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/pie-rose.png -------------------------------------------------------------------------------- /public/static/component/scatter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/scatter.png -------------------------------------------------------------------------------- /public/static/component/stack-ba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/stack-ba.png -------------------------------------------------------------------------------- /public/static/component/step-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/step-line.png -------------------------------------------------------------------------------- /public/static/component/tableplay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/tableplay.png -------------------------------------------------------------------------------- /public/static/component/bar-bothway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bar-bothway.png -------------------------------------------------------------------------------- /public/static/component/bar-series.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bar-series.png -------------------------------------------------------------------------------- /public/static/component/border-box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/border-box.png -------------------------------------------------------------------------------- /public/static/component/earth-night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/earth-night.png -------------------------------------------------------------------------------- /public/static/component/line-middle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/line-middle.png -------------------------------------------------------------------------------- /public/static/component/liquid-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/liquid-fill.png -------------------------------------------------------------------------------- /public/static/component/pie-nested.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/pie-nested.png -------------------------------------------------------------------------------- /public/static/component/word-cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/word-cloud.png -------------------------------------------------------------------------------- /public/static/templet/background-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-1.png -------------------------------------------------------------------------------- /public/static/templet/background-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-10.png -------------------------------------------------------------------------------- /public/static/templet/background-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-11.png -------------------------------------------------------------------------------- /public/static/templet/background-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-12.png -------------------------------------------------------------------------------- /public/static/templet/background-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-13.png -------------------------------------------------------------------------------- /public/static/templet/background-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-14.png -------------------------------------------------------------------------------- /public/static/templet/background-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-15.png -------------------------------------------------------------------------------- /public/static/templet/background-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-16.png -------------------------------------------------------------------------------- /public/static/templet/background-17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-17.jpg -------------------------------------------------------------------------------- /public/static/templet/background-18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-18.jpg -------------------------------------------------------------------------------- /public/static/templet/background-19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-19.jpg -------------------------------------------------------------------------------- /public/static/templet/background-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-2.png -------------------------------------------------------------------------------- /public/static/templet/background-20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-20.jpg -------------------------------------------------------------------------------- /public/static/templet/background-21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-21.jpg -------------------------------------------------------------------------------- /public/static/templet/background-22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-22.jpg -------------------------------------------------------------------------------- /public/static/templet/background-23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-23.jpg -------------------------------------------------------------------------------- /public/static/templet/background-24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-24.jpg -------------------------------------------------------------------------------- /public/static/templet/background-25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-25.jpg -------------------------------------------------------------------------------- /public/static/templet/background-26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-26.jpg -------------------------------------------------------------------------------- /public/static/templet/background-27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-27.jpg -------------------------------------------------------------------------------- /public/static/templet/background-28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-28.jpg -------------------------------------------------------------------------------- /public/static/templet/background-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-29.png -------------------------------------------------------------------------------- /public/static/templet/background-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-3.png -------------------------------------------------------------------------------- /public/static/templet/background-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-4.png -------------------------------------------------------------------------------- /public/static/templet/background-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-5.png -------------------------------------------------------------------------------- /public/static/templet/background-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-6.png -------------------------------------------------------------------------------- /public/static/templet/background-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-7.png -------------------------------------------------------------------------------- /public/static/templet/background-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-8.png -------------------------------------------------------------------------------- /public/static/templet/background-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/templet/background-9.png -------------------------------------------------------------------------------- /public/static/component/banner-video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/banner-video.mp4 -------------------------------------------------------------------------------- /public/static/component/bar-contrast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bar-contrast.png -------------------------------------------------------------------------------- /public/static/component/bar-crosswise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/bar-crosswise.png -------------------------------------------------------------------------------- /public/static/component/map-province.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/map-province.png -------------------------------------------------------------------------------- /src/packages/vcharts/index.js: -------------------------------------------------------------------------------- 1 | export { default as GraphEffect } from "./src/generator"; 2 | 3 | export { default as Pie } from "./src/pie"; 4 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | ## 后端接口地址 2 | REACT_APP_API=https://www.mockjs.com/api 3 | 4 | ## 端口号 5 | PORT=9527 6 | 7 | # Whether to open mock 8 | REACT_APP_USE_MOCK=trued -------------------------------------------------------------------------------- /public/static/component/calendar-heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/calendar-heatmap.png -------------------------------------------------------------------------------- /src/pages/designer/renderer/index.js: -------------------------------------------------------------------------------- 1 | export { default as Designer } from "./core"; 2 | 3 | export { default as DesignerParser } from "./parser"; 4 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | echo '$ commit-msg' 5 | echo '$ yarn commitlint -e $1' 6 | yarn commitlint -e $1 7 | -------------------------------------------------------------------------------- /public/static/component/cartesian-heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/cartesian-heatmap.png -------------------------------------------------------------------------------- /src/packages/dynamic-dialog/index.js: -------------------------------------------------------------------------------- 1 | export { default as DynamicDialog } from "./modal"; 2 | 3 | export { default as DynamicContent } from "./component"; 4 | -------------------------------------------------------------------------------- /public/config.js: -------------------------------------------------------------------------------- 1 | window.appConfig = { 2 | // 后端接口地址 3 | APP_SERVER_API: "https://www.mock-api.com", 4 | VERSION: "1.2.0", 5 | TIMESTAMP: new Date().getTime() 6 | }; 7 | -------------------------------------------------------------------------------- /public/static/component/TB143rolQL0gK0jSZFxXXXWHVXa-160-116.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/TB143rolQL0gK0jSZFxXXXWHVXa-160-116.png -------------------------------------------------------------------------------- /public/static/component/TB19PPllUz1gK0jSZLeXXb9kVXa-332-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/TB19PPllUz1gK0jSZLeXXb9kVXa-332-144.png -------------------------------------------------------------------------------- /public/static/component/TB1IhfqlUY1gK0jSZFCXXcwqXXa-334-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/TB1IhfqlUY1gK0jSZFCXXcwqXXa-334-144.png -------------------------------------------------------------------------------- /public/static/component/TB1cjHmlQP2gK0jSZPxXXacQpXa-332-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aaron52077/react-visual-data/HEAD/public/static/component/TB1cjHmlQP2gK0jSZPxXXacQpXa-332-144.png -------------------------------------------------------------------------------- /src/components/auto-loading/style.less: -------------------------------------------------------------------------------- 1 | .loading-container { 2 | position: absolute; 3 | top: 50%; 4 | left: 50%; 5 | text-align: center; 6 | transform: translate(-50%, -50%); 7 | } 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "tabWidth": 2, 4 | "printWidth": 120, 5 | "singleQuote": false, 6 | "trailingComma": "none", 7 | "bracketSpacing": true, 8 | "semi": true 9 | } 10 | -------------------------------------------------------------------------------- /src/polyfills.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ie polyfill 3 | * yarn add react-app-polyfill core-js 4 | * create in 2020-08-12 by Aaron 5 | */ 6 | import "react-app-polyfill/ie11"; 7 | import "react-app-polyfill/stable"; 8 | -------------------------------------------------------------------------------- /src/hooks/useSet.js: -------------------------------------------------------------------------------- 1 | import { useReducer } from "react"; 2 | 3 | // 基于redux的实现,类似于class component的setState 适用于复杂对象模式 4 | export const useSet = (initState) => useReducer((state, action) => ({ ...state, ...action }), initState); 5 | -------------------------------------------------------------------------------- /src/router/history.js: -------------------------------------------------------------------------------- 1 | import { createHashHistory } from "history"; 2 | 3 | const env = process.env.NODE_ENV; // 环境参数 4 | let options = {}; 5 | 6 | if (env === "production") { 7 | options.basename = "/"; 8 | } 9 | 10 | export default createHashHistory(options); 11 | -------------------------------------------------------------------------------- /src/packages/hoc.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | // High order component 4 | export default function fetcher(FieldComponent) { 5 | return class extends React.Component { 6 | render() { 7 | return ; 8 | } 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/decoration/index.js: -------------------------------------------------------------------------------- 1 | export { default as Decoration1 } from "./src/decoration1"; 2 | 3 | export { default as Decoration2 } from "./src/decoration2"; 4 | 5 | export { default as Decoration3 } from "./src/decoration3"; 6 | 7 | export { default as Decoration4 } from "./src/decoration4"; 8 | -------------------------------------------------------------------------------- /src/packages/iframe/style.less: -------------------------------------------------------------------------------- 1 | .gc-iframe__html { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | bottom: 0; 6 | padding: 15px; 7 | width: 100%; 8 | height: 100%; 9 | .gc-iframe__container { 10 | position: relative; 11 | width: 100%; 12 | height: 100%; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Checkbox } from "antd"; 3 | 4 | export default (prop) => { 5 | const onChange = (e) => prop.onChange(prop.name, e.target.checked); 6 | 7 | return ; 8 | }; 9 | -------------------------------------------------------------------------------- /src/components/auto-loading/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Spin } from "antd"; 3 | import "./style.less"; 4 | 5 | function AutoLoading(props) { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | 13 | export default AutoLoading; 14 | -------------------------------------------------------------------------------- /src/store/modules/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from "redux"; 2 | 3 | import app from "./app"; 4 | import component from "./component"; 5 | import form from "./form"; 6 | import tab from "./tab"; 7 | 8 | const rootReducer = combineReducers({ 9 | app, 10 | component, 11 | form, 12 | tab 13 | }); 14 | 15 | export default rootReducer; 16 | -------------------------------------------------------------------------------- /src/router/router-map.js: -------------------------------------------------------------------------------- 1 | import { lazy } from "react"; 2 | 3 | const Dashboard = lazy(() => import("@/pages/dashboard")); 4 | const Error = lazy(() => import("@/pages/404")); 5 | 6 | export default [ 7 | { 8 | path: "/dashboard", 9 | component: Dashboard 10 | }, 11 | { 12 | path: "/error/404", 13 | component: Error 14 | } 15 | ]; 16 | -------------------------------------------------------------------------------- /src/packages/form/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from "react"; 2 | import { Checkbox } from "antd"; 3 | 4 | export default function VCheckbox(prop) { 5 | const onChange = useCallback((e) => prop.onChange(prop.name, e.target.checked), []); 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/auto-container/style.less: -------------------------------------------------------------------------------- 1 | #gc-designer-container { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | transform-origin: left top; 6 | background-repeat: no-repeat; 7 | overflow: hidden; 8 | ::-webkit-scrollbar, 9 | .preview-wrapper ::-webkit-scrollbar { 10 | width: 0; 11 | height: 0; 12 | color: transparent; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/hooks/useDesigner.js: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from "react"; 2 | 3 | const Ctx = createContext(() => {}); 4 | 5 | const StoreCtx = createContext({}); 6 | 7 | const useDesigner = () => { 8 | return useContext(Ctx); 9 | }; 10 | 11 | const useView = () => { 12 | return useContext(StoreCtx); 13 | }; 14 | 15 | export { Ctx, StoreCtx, useDesigner, useView }; 16 | -------------------------------------------------------------------------------- /src/hooks/useDocumentTitle.js: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from "react"; 2 | 3 | export function useDocumentTitle(title) { 4 | const prevTitleRef = useRef(title); 5 | 6 | useEffect(() => { 7 | document.title = title; 8 | return () => { 9 | // eslint-disable-next-line 10 | document.title = prevTitleRef.current; 11 | }; 12 | }, [title]); 13 | } 14 | -------------------------------------------------------------------------------- /src/packages/vcharts/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param [parma][数据] 3 | * @param [unit][单位] 4 | * @returns {*} 统一返回数据带单位 5 | */ 6 | export const tooltipFormatter = (parma, unit = "") => { 7 | let obj = parma[0].name + "
"; 8 | for (const item of parma) { 9 | obj = `${obj}${item.marker}${item.seriesName}: ${item.value}${unit}
`; 10 | } 11 | return obj; 12 | }; 13 | -------------------------------------------------------------------------------- /src/packages/switch/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Switch } from "antd"; 3 | 4 | const VSwitch = (p) => { 5 | return ( 6 | p.onChange(p.name, checked)} 11 | /> 12 | ); 13 | }; 14 | 15 | export default VSwitch; 16 | -------------------------------------------------------------------------------- /src/packages/form/switch/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Switch } from "antd"; 3 | 4 | const VSwitch = (p) => { 5 | return ( 6 | p.onChange(p.name, checked)} 11 | /> 12 | ); 13 | }; 14 | 15 | export default VSwitch; 16 | -------------------------------------------------------------------------------- /src/packages/html/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const VHtml = ({ value, defaultValue }) => { 4 | let __html = ""; 5 | try { 6 | __html = value ? value : defaultValue; 7 | if (typeof __html !== "string") { 8 | __html = ""; 9 | } 10 | } catch (error) {} 11 | return
; 12 | }; 13 | 14 | export default VHtml; 15 | -------------------------------------------------------------------------------- /src/packages/form/html/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const VHtml = ({ value, defaultValue }) => { 4 | let __html = ""; 5 | try { 6 | __html = value ? value : defaultValue; 7 | if (typeof __html !== "string") { 8 | __html = ""; 9 | } 10 | } catch (error) {} 11 | return
; 12 | }; 13 | 14 | export default VHtml; 15 | -------------------------------------------------------------------------------- /src/hooks/useDebounce.js: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from "react"; 2 | import { debounce } from "~utils"; 3 | 4 | export const useDebounce = (action, ms = 500) => { 5 | const debouncedAction = useRef(null); 6 | 7 | useEffect(() => { 8 | if (!debouncedAction.current) { 9 | debouncedAction.current = debounce(action, ms); 10 | } 11 | }, []); 12 | 13 | return debouncedAction.current; 14 | }; 15 | -------------------------------------------------------------------------------- /src/pages/designer/configuration-schema/index.js: -------------------------------------------------------------------------------- 1 | import BAR_SCHEMA from "./bar"; 2 | import LINE_SCHEMA from "./line"; 3 | import PIE_SCHEMA from "./pie"; 4 | import MAP_SCHEMA from "./map"; 5 | import DATAV_SCHEMA from "./datav"; 6 | import OTHER_SCHEMA from "./other"; 7 | 8 | // if you should all configs. 9 | export const screenToSchema = [BAR_SCHEMA, LINE_SCHEMA, PIE_SCHEMA, MAP_SCHEMA, OTHER_SCHEMA, DATAV_SCHEMA].flat(1); 10 | -------------------------------------------------------------------------------- /src/components/vcharts/index.js: -------------------------------------------------------------------------------- 1 | import echarts from "echarts"; 2 | import VEchartsCore from "./core"; 3 | import { DarkTheme } from "./theme"; 4 | 5 | // register theme object 6 | echarts.registerTheme("dark", DarkTheme); 7 | 8 | // export the Component the echarts Object. 9 | export default class VEcharts extends VEchartsCore { 10 | constructor(props) { 11 | super(props); 12 | this.echartsLib = echarts; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/dynamic-dialog/configuration-schema/index.js: -------------------------------------------------------------------------------- 1 | import BAR_SCHEMA from "./bar"; 2 | import LINE_SCHEMA from "./line"; 3 | import PIE_SCHEMA from "./pie"; 4 | import MAP_SCHEMA from "./map"; 5 | import DATAV_SCHEMA from "./datav"; 6 | import OTHER_SCHEMA from "./other"; 7 | 8 | // if you should all configs. 9 | export const subToSchema = [BAR_SCHEMA, LINE_SCHEMA, PIE_SCHEMA, MAP_SCHEMA, OTHER_SCHEMA, DATAV_SCHEMA].flat(1); 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 # 设置文件字符集为 utf-8 6 | indent_style = space # 缩进风格(tab | space) 7 | indent_size = 2 # 缩进大小 8 | end_of_line = lf # 控制换行类型(lf | cr | crlf) 9 | trim_trailing_whitespace = true # 去除行首的任意空白字符 10 | insert_final_newline = true # 始终在文件末尾插入一个新行 11 | 12 | [*.md] # 表示仅 md 文件适用以下规则 13 | insert_final_newline = false 14 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /src/packages/form/container/style.less: -------------------------------------------------------------------------------- 1 | .form-drag { 2 | position: absolute; 3 | left: -12px; 4 | top: -17px; 5 | bottom: 0; 6 | font-size: 20px; 7 | cursor: pointer; 8 | } 9 | 10 | .form-item__border { 11 | border-width: 1px; 12 | border-style: solid; 13 | border-color: transparent; 14 | &.is-active { 15 | border-color: #2681ff; 16 | } 17 | } 18 | 19 | .form-item { 20 | .field-flex { 21 | padding: 0 10px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/components/iframe/style.less: -------------------------------------------------------------------------------- 1 | .gc-iframe { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | bottom: 0; 6 | width: 100%; 7 | .ant-spin-container { 8 | width: 100%; 9 | height: 100%; 10 | } 11 | &__mask { 12 | position: absolute; 13 | top: 0; 14 | right: 0; 15 | bottom: 0; 16 | left: 0; 17 | border: 0; 18 | z-index: 1; 19 | } 20 | &__container { 21 | position: relative; 22 | width: 100%; 23 | height: 100%; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/form-render/transformField.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const transformField = 4 | ({ fieldCanRedefine: can, Field: SourceField = null, props = {} }) => 5 | (args) => { 6 | const { name, Field: RedefineField = null, ...others } = args; 7 | const Field = (can && RedefineField) || SourceField; 8 | if (Field) { 9 | return ; 10 | } 11 | return null; 12 | }; 13 | 14 | export default transformField; 15 | -------------------------------------------------------------------------------- /src/packages/dynamic-actions/configuration-value/index.js: -------------------------------------------------------------------------------- 1 | import BAR_CONF from "./bar"; 2 | import LINE_CONF from "./line"; 3 | import PIE_CONF from "./pie"; 4 | import MAP_CONF from "./map"; 5 | import DATAV_CONF from "./datav"; 6 | 7 | // if you should all configs. 8 | export const componentMarket = [BAR_CONF, LINE_CONF, PIE_CONF, MAP_CONF, DATAV_CONF].flat(1); 9 | 10 | export default { 11 | bar: BAR_CONF, 12 | line: LINE_CONF, 13 | pie: PIE_CONF, 14 | map: MAP_CONF, 15 | datav: DATAV_CONF 16 | }; 17 | -------------------------------------------------------------------------------- /src/__mocks__/modules/echarts.js: -------------------------------------------------------------------------------- 1 | import { resultSuccess } from "../_util"; 2 | 3 | export default [ 4 | { 5 | url: "/echart/bar", 6 | timeout: 200, 7 | method: "get", 8 | response: () => { 9 | return resultSuccess({ 10 | categories: ["苹果", "三星", "华为", "oppo", "vivo", "小米"], 11 | series: [ 12 | { 13 | name: "旺季", 14 | "data|7": ["@integer(10000, 25000)"] 15 | } 16 | ], 17 | unit: "台" 18 | }); 19 | } 20 | } 21 | ]; 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # production 7 | /dist 8 | /public/room 9 | /public/mansion 10 | /public/scene 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | # Editor directories and files 24 | .idea* 25 | .vscode 26 | *.suo 27 | *.ntvs* 28 | *.njsproj 29 | *.sln 30 | *.sw* -------------------------------------------------------------------------------- /src/store/modules/tab.js: -------------------------------------------------------------------------------- 1 | import { handleActions } from "redux-actions"; 2 | 3 | /** 4 | * tab项组件状态 5 | * @param {*} tabStore 列表项 6 | * @param {*} bind 依赖关系id集合 7 | */ 8 | const initState = { 9 | tabStore: [], 10 | tabBind: [] 11 | }; 12 | 13 | export default handleActions( 14 | { 15 | "tab/tabStore": (state, action) => ({ ...state, tabStore: action.data }), 16 | "tab/tabBind": (state, action) => ({ ...state, tabBind: action.data }), 17 | "tab/resetState": () => { 18 | return initState; 19 | } 20 | }, 21 | initState 22 | ); 23 | -------------------------------------------------------------------------------- /src/pages/designer/configuration-value/index.js: -------------------------------------------------------------------------------- 1 | import BAR_CONF from "./bar"; 2 | import LINE_CONF from "./line"; 3 | import PIE_CONF from "./pie"; 4 | import MAP_CONF from "./map"; 5 | import DATAV_CONF from "./datav"; 6 | import OTHER_CONF from "./other"; 7 | 8 | // if you should all configs. 9 | export const componentMarket = [BAR_CONF, LINE_CONF, PIE_CONF, MAP_CONF, OTHER_CONF, DATAV_CONF].flat(1); 10 | 11 | export default { 12 | bar: BAR_CONF, 13 | line: LINE_CONF, 14 | pie: PIE_CONF, 15 | map: MAP_CONF, 16 | datav: DATAV_CONF, 17 | other: OTHER_CONF 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/iconfont/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { createFromIconfontCN } from "@ant-design/icons"; 3 | 4 | const Iconfont = (props) => { 5 | const { antd = false, type, ...rest } = props; 6 | const IconFonts = createFromIconfontCN({ 7 | scriptUrl: ["//at.alicdn.com/t/font_908589_jybcb6d47pq.js"] 8 | }); 9 | if (antd) { 10 | const Icons = require("@ant-design/icons")[type]; 11 | return ; 12 | } else { 13 | return ; 14 | } 15 | }; 16 | 17 | export default Iconfont; 18 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Button, Result } from "antd"; 3 | import { withRouter } from "react-router-dom"; 4 | 5 | const notFound = (props) => { 6 | const { history } = props; 7 | return ( 8 | history.replace("/dashboard")}> 14 | 返回首页 15 | 16 | } 17 | /> 18 | ); 19 | }; 20 | 21 | export default withRouter(notFound); 22 | -------------------------------------------------------------------------------- /src/packages/border/index.js: -------------------------------------------------------------------------------- 1 | export { default as BorderBox1 } from "./src/border1"; 2 | 3 | export { default as BorderBox2 } from "./src/border2"; 4 | 5 | export { default as BorderBox3 } from "./src/border3"; 6 | 7 | export { default as BorderBox4 } from "./src/border4"; 8 | 9 | export { default as BorderBox5 } from "./src/border5"; 10 | 11 | export { default as BorderBox6 } from "./src/border6"; 12 | 13 | export { default as BorderBox7 } from "./src/border7"; 14 | 15 | export { default as BorderBox8 } from "./src/border8"; 16 | 17 | export { default as BorderBox9 } from "./src/border9"; 18 | -------------------------------------------------------------------------------- /src/packages/dynamic-actions/configuration-value/datav.js: -------------------------------------------------------------------------------- 1 | import { BASE_DATA_CONF } from "./default.js"; 2 | 3 | export default [ 4 | { 5 | name: "iframe", 6 | icon: "iframe", 7 | type: "iframe", 8 | data: { 9 | title: "iframe", 10 | width: 450, 11 | height: 450, 12 | left: 15, 13 | top: 15, 14 | background: "", 15 | isLock: false, 16 | isHidden: false, 17 | dataConfig: { 18 | ...BASE_DATA_CONF, 19 | data: { 20 | src: "https://www.baidu.com" 21 | } 22 | } 23 | } 24 | } 25 | ]; 26 | -------------------------------------------------------------------------------- /src/form-render/index.js: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from "react"; 2 | import FieldFactory from "./factory"; 3 | import { mapping as defaultMapping, widgets as defaultWidgets } from "~packages"; 4 | import "./atom.less"; 5 | 6 | const SchemaRender = forwardRef(({ mapping = {}, widgets = {}, ...rest }, ref) => { 7 | return ( 8 | 20 | ); 21 | }); 22 | 23 | export default SchemaRender; 24 | -------------------------------------------------------------------------------- /src/styles/antd-design.less: -------------------------------------------------------------------------------- 1 | .ant-layout-footer { 2 | padding: 15px 50px 24px; 3 | } 4 | 5 | .ant-tree-list { 6 | font-size: 13px; 7 | } 8 | 9 | .silder-tree { 10 | .ant-tree .ant-tree-treenode { 11 | padding: 5px 0 7px 5px; 12 | } 13 | } 14 | 15 | .gc-design__hd--setting { 16 | .ant-space { 17 | justify-content: flex-end; 18 | } 19 | } 20 | 21 | .gc-design__setting { 22 | .ant-tabs .ant-tabs-nav .ant-tabs-nav-wrap { 23 | width: 50px; 24 | white-space: initial; 25 | } 26 | } 27 | 28 | .field-flex__control { 29 | .ant-radio-group .ant-radio-wrapper { 30 | display: block; 31 | padding: 3px 0; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/packages/form/collapse/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { Collapse } from "antd"; 3 | 4 | const { Panel } = Collapse; 5 | 6 | export default ({ name, value, schema, onChange }) => { 7 | const callback = (key) => { 8 | onChange(name, key.length > 0 ? true : false); 9 | }; 10 | 11 | useEffect(() => { 12 | onChange(name, value || false); 13 | }, [value]); 14 | 15 | return ( 16 |
17 | 18 | 19 | 20 |
21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /src/pages/designer/renderer/generator.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Empty } from "antd"; 3 | 4 | import "./datav.less"; 5 | import "./renderer.less"; 6 | 7 | const FieldGenerator = 8 | ({ fieldCanRedefine: can, Field: SourceField = null, props = {} }) => 9 | (args) => { 10 | const { Field: RedefineField = null, ...rest } = args; 11 | const Field = (can && RedefineField) || SourceField; 12 | if (Field) { 13 | return ; 14 | } 15 | 16 | return ( 17 |
18 | 19 |
20 | ); 21 | }; 22 | 23 | export default FieldGenerator; 24 | -------------------------------------------------------------------------------- /src/components/typing/index.js: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from "react"; 2 | import Typing from "./core"; 3 | 4 | const TypingPrint = (props) => { 5 | const { source, delay = 30 } = props; 6 | 7 | const sourceEl = useRef(); 8 | const outputEl = useRef(); 9 | 10 | useEffect(() => { 11 | const typing = new Typing({ 12 | source: sourceEl.current, 13 | output: outputEl.current, 14 | delay: delay 15 | }); 16 | typing.start(); 17 | }, [delay]); 18 | 19 | return ( 20 | <> 21 |
22 |
23 | 24 | ); 25 | }; 26 | 27 | export default TypingPrint; 28 | -------------------------------------------------------------------------------- /src/layouts/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { BackTop, Layout } from "antd"; 3 | import LayoutHeader from "./header"; 4 | import LayoutSider from "./sider"; 5 | import LayoutContent from "./content"; 6 | 7 | import "../styles/layout.less"; 8 | 9 | function BaseLayout() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | document.querySelector("#g-layout")} /> 17 | DataV Pro ©2020 Created by Aaron 18 | 19 | 20 | ); 21 | } 22 | 23 | export default BaseLayout; 24 | -------------------------------------------------------------------------------- /src/packages/vcharts/options/index.js: -------------------------------------------------------------------------------- 1 | import barOpt from "./bar"; 2 | import lineOpt from "./line"; 3 | import pieOpt from "./pie"; 4 | import mapOpt from "./map"; 5 | import mapcityOpt from "./mapcity"; 6 | 7 | /** 8 | * 组件类型和配置项类型统一管理 9 | */ 10 | export default { 11 | bar: barOpt, 12 | "bar-crosswise": barOpt, 13 | "bar-series": barOpt, 14 | "bar-heap": barOpt, 15 | "bar-contrast": barOpt, 16 | "bar-bothway": barOpt, 17 | "bar-alien": barOpt, 18 | line: lineOpt, 19 | "step-line": lineOpt, 20 | "line-middle": lineOpt, 21 | "line-bar": lineOpt, 22 | pie: pieOpt, 23 | "pie-nested": pieOpt, 24 | "pie-rose": pieOpt, 25 | "pie-double": pieOpt, 26 | "pie-play": pieOpt, 27 | "china-map": mapOpt, 28 | "map-city": mapcityOpt 29 | }; 30 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react"; 2 | import { ConfigProvider } from "antd"; 3 | import zhCN from "antd/es/locale/zh_CN"; 4 | import { Provider } from "react-redux"; 5 | import { PersistGate } from "redux-persist/es/integration/react"; 6 | import store, { persistor } from "./store"; 7 | import Router from "./router"; 8 | 9 | import "./styles/format.less"; 10 | 11 | class App extends PureComponent { 12 | render() { 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | } 23 | } 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /src/store/modules/form.js: -------------------------------------------------------------------------------- 1 | import { handleActions } from "redux-actions"; 2 | 3 | /** 4 | * 筛选组件状态 5 | * @param {*} valid 表单必填项验证 6 | * @param {*} dependencies 表单依赖关系id集合 7 | * @param {*} conditions 表单筛选条件列表 8 | * @param {*} parmas 表单筛选条件查询参数 9 | */ 10 | const initState = { 11 | dependencies: [], 12 | parmas: [], 13 | conditions: [] 14 | }; 15 | 16 | export default handleActions( 17 | { 18 | "form/dependencies": (state, action) => ({ ...state, dependencies: action.data }), 19 | "form/conditions": (state, action) => ({ ...state, conditions: action.data }), 20 | "form/parmas": (state, action) => ({ ...state, parmas: action.data }), 21 | "form/resetState": () => { 22 | return initState; 23 | } 24 | }, 25 | initState 26 | ); 27 | -------------------------------------------------------------------------------- /.github/workflows/deploy-ci.yml: -------------------------------------------------------------------------------- 1 | name: Develop CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - src/** 9 | - ".github/workflows/*" 10 | 11 | jobs: 12 | deploy: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | 19 | - name: Install and Build 20 | run: yarn && yarn build 21 | 22 | - name: Deploy 23 | uses: JamesIves/github-pages-deploy-action@3.7.1 24 | with: 25 | GITHUB_TOKEN: ${{ secrets.DEADV_TOKEN }} 26 | BRANCH: gh-pages 27 | FOLDER: dist 28 | GIT_CONFIG_NAME: Aaron52077 29 | GIT_CONFIG_EMAIL: chao_code520@163.com 30 | COMMIT_MESSAGE: gh-pages deploy 31 | -------------------------------------------------------------------------------- /src/packages/iframe/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "react-redux"; 3 | import { withRouter } from "react-router-dom"; 4 | import { IFrameSimple } from "~components"; 5 | 6 | const IframeTpl = ({ value, mode, location }) => { 7 | const { data } = value.dataConfig; 8 | if (!data) return "请输入iframe的地址"; 9 | 10 | if (mode === "development") { 11 | return ( 12 |
13 | 14 | {!location.pathname.includes("/preview/") ?
: null} 15 |
16 | ); 17 | } 18 | 19 | return ; 20 | }; 21 | 22 | export default connect((state) => ({ 23 | mode: state.component.mode 24 | }))(withRouter(IframeTpl)); 25 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, combineReducers } from "redux"; 2 | import thunkMiddleware from "redux-thunk"; 3 | import reducer from "./modules"; 4 | 5 | // 引入redux-persist插件进行持久化存储状态 6 | // defaults to localStorage for web. eg: session => import storage from "redux-persist/es/storage/session"; 7 | import { persistStore, persistReducer } from "redux-persist"; 8 | import storage from "redux-persist/es/storage"; 9 | 10 | // 首先定义一个对 11 | const persistConfig = { 12 | key: "root", 13 | storage, 14 | whitelist: ["app"] 15 | }; 16 | 17 | // 使用redux-persist合并 18 | const rootReducer = persistReducer(persistConfig, reducer); 19 | 20 | const store = createStore(rootReducer, applyMiddleware(thunkMiddleware)); 21 | // 应用redux-persist完成数据持久化 22 | export const persistor = persistStore(store); 23 | 24 | export default store; 25 | -------------------------------------------------------------------------------- /src/packages/dynamic-actions/configuration-value/default.js: -------------------------------------------------------------------------------- 1 | // 下钻公共基础配置项抽离 2 | const BASE_CONF = { 3 | width: 8, 4 | height: 250, 5 | link: "", 6 | titleColor: "", 7 | background: "", 8 | remark: "", 9 | isCenter: false, 10 | chartCustomStyle: false, 11 | borderColor: "", 12 | chartBorderRadius: "", 13 | borderWidth: "", 14 | chartBorderStyle: "", 15 | shadowWidth: "", 16 | shadowOffset: "", 17 | chartShadowColor: "", 18 | transition: "", 19 | transitionTime: 3, 20 | animateTime: "", 21 | animateRepeat: "", 22 | drillDownOpen: false, 23 | drillDown: [], 24 | dependenceOpen: false, 25 | dependences: [] 26 | }; 27 | 28 | // 公共数据配置项抽离 29 | const BASE_DATA_CONF = { 30 | dataType: "json", 31 | dataSqlId: "", 32 | dataModals: {}, 33 | dataApiId: "" 34 | }; 35 | 36 | export { BASE_CONF, BASE_DATA_CONF }; 37 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | // https://commitlint.js.org/#/reference-rules 2 | module.exports = { 3 | extends: ["@commitlint/config-conventional"], 4 | rules: { 5 | "type-enum": [2, "always", ["feat", "fix", "docs", "style", "refactor", "perf", "test", "ci", "chore", "revert"]], 6 | "type-case": [2, "always", "lower-case"], 7 | "type-empty": [2, "never"], 8 | "scope-enum": [2, "always", ["core", "style", "docs", "dev", "util", "store", "suspense"]], 9 | "scope-case": [2, "always", "lower-case"], 10 | "subject-case": [2, "never", ["sentence-case", "start-case", "pascal-case", "upper-case"]], 11 | "subject-empty": [2, "never"], 12 | "subject-full-stop": [2, "never", "."], 13 | "header-min-length": [2, "always", 3], 14 | "header-max-length": [2, "always", 72], 15 | "body-leading-blank": [2, "always"] 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/components/split-panel/panel.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react"; 2 | 3 | class Panel extends PureComponent { 4 | render() { 5 | const { children, className, mode, style: styleProps, size, eleRef } = this.props; 6 | 7 | let style = { 8 | flex: 1, 9 | position: "relative", 10 | outline: "none" 11 | }; 12 | 13 | if (size !== undefined) { 14 | if (mode === "vertical") { 15 | style.width = size; 16 | } else { 17 | style.height = size; 18 | style.display = "flex"; 19 | } 20 | style.flex = "none"; 21 | } 22 | 23 | style = Object.assign({}, style, styleProps || {}); 24 | 25 | return ( 26 |
27 | {children} 28 |
29 | ); 30 | } 31 | } 32 | 33 | export default Panel; 34 | -------------------------------------------------------------------------------- /src/pages/designer/configuration-value/default.js: -------------------------------------------------------------------------------- 1 | // 公共基础配置项抽离 2 | const BASE_CONF = { 3 | width: 400, 4 | height: 250, 5 | left: 15, 6 | top: 15, 7 | background: "", 8 | isLock: false, 9 | isHidden: false, 10 | remark: "", 11 | isCustomStyle: false, 12 | borderRadius: "", 13 | borderColor: "", 14 | borderWidth: "", 15 | borderStyle: "solid", 16 | shadowOffset: 0, 17 | shadowColor: "", 18 | shadowWidth: 0, 19 | animateType: "", 20 | animateTime: "", 21 | animateSpeed: "", 22 | animateRepeat: "", 23 | drillDownOpen: false, 24 | drillDown: [], 25 | dependenceOpen: false, 26 | dependence: [], 27 | isRefresh: false, 28 | refreshTime: 1800 29 | }; 30 | 31 | // 公共数据配置项抽离 32 | const BASE_DATA_CONF = { 33 | dataType: "json", 34 | dataSqlId: "", 35 | dataModals: {}, 36 | dataApiId: "" 37 | }; 38 | 39 | export { BASE_CONF, BASE_DATA_CONF }; 40 | -------------------------------------------------------------------------------- /src/packages/countdown/index.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { Statistic } from "antd"; 3 | 4 | const { Countdown } = Statistic; 5 | const deadline = Date.now() + 1000 * 60 * 60 * 24 * 2 + 1000 * 30; // Moment is also OK 6 | 7 | export default ({ options, schema }) => { 8 | const { 9 | prefix = "", 10 | suffix = "", 11 | name = "", 12 | fontFamily = "Microsoft Yahei", 13 | fontSize = 16, 14 | color = "", 15 | precision = 0, 16 | format = "HH:mm:ss" 17 | } = options; 18 | const { data } = schema; 19 | 20 | let option = useMemo(() => { 21 | return { 22 | title: name, 23 | prefix, 24 | suffix, 25 | precision, 26 | format, 27 | valueStyle: { fontFamily, fontSize, color }, 28 | value: data.value || deadline 29 | }; 30 | }, [options]); 31 | 32 | return ; 33 | }; 34 | -------------------------------------------------------------------------------- /src/packages/checkbox-group/index.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { Checkbox } from "antd"; 3 | 4 | export default (prop) => { 5 | const { enum: enums, enumNames } = prop.schema || {}; 6 | 7 | const rootValue = useMemo(() => { 8 | return prop.value && Array.isArray(prop.value) ? prop.value : []; 9 | }, [prop.value]); 10 | 11 | const onChange = (values) => prop.onChange(prop.name, values); 12 | 13 | return ( 14 | 15 | {enums.map((val, index) => ( 16 | 17 | 23 | 24 | ))} 25 | 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /src/packages/tabs/select.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Select } from "antd"; 3 | 4 | const VTabToSelect = ({ name, value, onChange, formData }) => { 5 | let { tabToChart } = formData.config; 6 | 7 | const onTabChange = (val) => { 8 | onChange(name, val); 9 | }; 10 | 11 | return ( 12 | 30 | ); 31 | }; 32 | 33 | export default VTabToSelect; 34 | -------------------------------------------------------------------------------- /src/packages/vcharts/src/pie.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { connect } from "react-redux"; 3 | import { Vcharts } from "~components"; 4 | import getOption from "../options/pie"; 5 | import { isEmpty } from "~utils/helper"; 6 | 7 | const GeneratorPie = ({ value, options }) => { 8 | if (isEmpty(value.dataConfig.data)) return null; 9 | const { dataConfig, isRefresh } = value; 10 | 11 | let currentOption = getOption(options, dataConfig.data); 12 | 13 | return ( 14 | { 18 | currentOption.callback && currentOption.callback(echart); 19 | }} 20 | theme="dark" 21 | style={{ width: "100%", height: "100%" }} 22 | /> 23 | ); 24 | }; 25 | 26 | export default connect((state) => ({ 27 | mode: state.component.mode, 28 | dependencies: state.component.dependencies 29 | }))(GeneratorPie); 30 | -------------------------------------------------------------------------------- /src/packages/form/checkbox/group.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo, useCallback } from "react"; 2 | import { Checkbox } from "antd"; 3 | 4 | export default function VCheckboxes(prop) { 5 | const { enum: enums, enumNames } = prop.schema || {}; 6 | 7 | const rootValue = useMemo(() => { 8 | return prop.value && Array.isArray(prop.value) ? prop.value : []; 9 | }, [prop.value]); 10 | 11 | const onChange = useCallback((values) => prop.onChange(prop.name, values), []); 12 | 13 | return ( 14 | 15 | {enums.map((val, index) => ( 16 | 17 | 23 | 24 | ))} 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/__mocks__/modules/user.js: -------------------------------------------------------------------------------- 1 | import { resultSuccess } from "../_util"; 2 | 3 | export default [ 4 | { 5 | url: "/user/login", 6 | timeout: 200, 7 | method: "post", 8 | response: () => { 9 | return resultSuccess({ 10 | role: "admin", 11 | access_token: "@guid", 12 | refresh_token: "@guid", 13 | avatar: "@image('80x80', '#2d8cf0', '#FFF', 'admin')", 14 | name: "admin" 15 | }); 16 | } 17 | }, 18 | { 19 | url: "/menu/list", 20 | timeout: 200, 21 | method: "post", 22 | response: () => { 23 | return resultSuccess([ 24 | { 25 | icon: "wp-hot", 26 | path: "/dashboard", 27 | title: "可视化设计器", 28 | roles: ["admin", "editor", "guest"] 29 | } 30 | ]); 31 | } 32 | }, 33 | { 34 | url: "/user/logout", 35 | timeout: 200, 36 | method: "get", 37 | response: () => { 38 | return resultSuccess("退出成功"); 39 | } 40 | } 41 | ]; 42 | -------------------------------------------------------------------------------- /src/api/index.js: -------------------------------------------------------------------------------- 1 | import fetch from "~utils/http"; 2 | 3 | /** 4 | * @description 账户登录 5 | */ 6 | export function accountIn(param) { 7 | return fetch({ 8 | url: "/user/login", 9 | method: "post", 10 | data: param 11 | }); 12 | } 13 | 14 | export function getMeunList() { 15 | return fetch({ 16 | url: "/menu/list", 17 | method: "post" 18 | }); 19 | } 20 | 21 | export function echartBarAPI() { 22 | return fetch({ 23 | url: "/echart/bar", 24 | method: "get" 25 | }); 26 | } 27 | 28 | export function dataVScreen() { 29 | return fetch({ 30 | url: "/datav/screen", 31 | method: "post" 32 | }); 33 | } 34 | 35 | export function dataVGrid() { 36 | return fetch({ 37 | url: "/datav/grid", 38 | method: "post" 39 | }); 40 | } 41 | 42 | export function dataVApiList() { 43 | return fetch({ 44 | url: "/datav/api", 45 | method: "get" 46 | }); 47 | } 48 | 49 | export function dataVOpenApi() { 50 | return fetch({ 51 | url: "/datav/openapi", 52 | method: "get" 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /src/store/modules/app.js: -------------------------------------------------------------------------------- 1 | import { handleActions } from "redux-actions"; 2 | 3 | /** 4 | * 用户信息、路由信息 5 | */ 6 | const initState = { 7 | accessToken: "", 8 | refreshToken: "", 9 | userInfo: {}, 10 | routes: [], 11 | routerPath: "", 12 | layouts: {}, 13 | sidebarOpened: true 14 | }; 15 | 16 | export default handleActions( 17 | { 18 | "app/accessToken": (state, action) => ({ ...state, accessToken: action.data }), 19 | "app/refreshToken": (state, action) => ({ ...state, refreshToken: action.data }), 20 | "app/routes": (state, action) => ({ ...state, routes: action.data }), 21 | "app/userInfo": (state, action) => ({ ...state, userInfo: action.data }), 22 | "app/routerPath": (state, action) => ({ ...state, routerPath: action.data }), 23 | "app/layouts": (state, action) => ({ ...state, layouts: action.data }), 24 | "app/sidebarOpened": (state) => ({ ...state, sidebarOpened: !state.sidebarOpened }), 25 | "app/resetState": () => { 26 | return initState; 27 | } 28 | }, 29 | initState 30 | ); 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # data-visual-platform 2 | 3 | #### 介绍 4 | 5 | 🎉 基于 reactjs 开发的可视化大屏设计器项目 [react版本](https://wuli-admin.gitee.io/react-visual-data/#/dashboard) [vue3版本](https://wuli-admin.gitee.io/vite-vue-pro/#/) 6 | 7 | #### 参与贡献 8 | 9 | 此项目为作者闲暇时间`学习计划`的一部分,项目中可能会出现实验性的功能,所以在完成第一个可用版本之前只接受 `fixbug PR`,不接受 `feature PR`。还望大家理解。 10 | 最近在研究微前端相关领域 [react-mat-pro](https://wuli-admin.gitee.io/react-mat-pro/#/dashboard) 11 | 12 | 1. Fork 本仓库 13 | 2. 新建 Feat_xxx 分支 14 | 3. 提交代码 15 | 4. 新建 Pull Request 16 | 17 | **目录结构:** 18 | 19 | ``` 20 | ├── config-overrides.js 21 | ├── yarn-lock.json 22 | ├── package.json 23 | ├── public 24 | │ ├── config.js 25 | │ ├── favicon.ico 26 | │ ├── index.html 27 | │ ├── robots.txt 28 | │ └── static 29 | ├── README.md 30 | ├── src 31 | │ ├── __mocks__ 32 | │ ├── api 33 | │ ├── components 34 | │ ├── form-render 35 | │ ├── hooks 36 | │ ├── layouts 37 | │ ├── packages 38 | │ ├── pages 39 | │ ├── router 40 | │ ├── store 41 | │ ├── styles 42 | │ ├── utils 43 | │ └── index.js // main入口 44 | ``` 45 | -------------------------------------------------------------------------------- /src/packages/vcharts/options/radar.js: -------------------------------------------------------------------------------- 1 | import { DEFAULT_COLORS } from "~packages/constants"; 2 | 3 | export default (option, data) => { 4 | const { indicators, series } = data; 5 | const { stack = false, legendShow = false } = option; 6 | 7 | return { 8 | color: DEFAULT_COLORS, 9 | tooltip: { 10 | trigger: "item" 11 | }, 12 | legend: { 13 | show: legendShow, 14 | type: "scroll", 15 | bottom: 15, 16 | data: series.map((item) => item.name) 17 | }, 18 | radar: { 19 | radius: "60%", 20 | indicator: indicators 21 | }, 22 | series: [ 23 | { 24 | type: "radar", 25 | areaStyle: stack 26 | ? { 27 | normal: { 28 | shadowBlur: 13, 29 | shadowColor: "rgba(0,0,0,.2)", 30 | shadowOffsetX: 0, 31 | shadowOffsetY: 10, 32 | opacity: 1 33 | } 34 | } 35 | : undefined, 36 | data: series 37 | } 38 | ] 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /src/styles/account.less: -------------------------------------------------------------------------------- 1 | .gc-login { 2 | width: 100%; 3 | min-height: 100vh; 4 | background-repeat: no-repeat; 5 | background-color: var(--datav-panel-title-bg); 6 | background-position: center; 7 | overflow: hidden; 8 | &__bd { 9 | position: relative; 10 | width: 360px; 11 | max-width: 100%; 12 | padding: 180px 35px 0; 13 | margin: 0 auto; 14 | overflow: hidden; 15 | } 16 | &__title { 17 | padding: 15px 0; 18 | font-size: 20px; 19 | color: #fff; 20 | text-align: center; 21 | } 22 | &__footer { 23 | position: absolute; 24 | left: 0; 25 | right: 0; 26 | bottom: 0; 27 | padding: 1em 0; 28 | &--copyright { 29 | margin-bottom: 10px; 30 | font-size: 12px; 31 | line-height: 12px; 32 | text-align: center; 33 | color: #fff; 34 | } 35 | &--options { 36 | font-size: 12px; 37 | line-height: 12px; 38 | text-align: center; 39 | } 40 | } 41 | .ant-input-affix-wrapper { 42 | border-color: rgba(0, 199, 255, 0.4); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/__mocks__/_util.js: -------------------------------------------------------------------------------- 1 | // Interface data format used to return a unified format 2 | export function resultSuccess(result, { message = "ok" } = {}) { 3 | return { 4 | code: 0, 5 | data: result, 6 | message, 7 | type: "success" 8 | }; 9 | } 10 | 11 | export function resultPageSuccess(page, pageSize, list, { message = "ok" } = {}) { 12 | const pageData = pagination(page, pageSize, list); 13 | 14 | return { 15 | ...resultSuccess({ 16 | items: pageData, 17 | total: list.length 18 | }), 19 | message 20 | }; 21 | } 22 | 23 | export function resultError(message = "Request failed", { code = 1, result = null } = {}) { 24 | return { 25 | code, 26 | data: result, 27 | message, 28 | type: "error" 29 | }; 30 | } 31 | 32 | export function pagination(current, pageSize, array) { 33 | const offset = (current - 1) * Number(pageSize); 34 | const ret = 35 | offset + Number(pageSize) >= array.length 36 | ? array.slice(offset, array.length) 37 | : array.slice(offset, offset + Number(pageSize)); 38 | return ret; 39 | } 40 | -------------------------------------------------------------------------------- /src/packages/radio/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Radio } from "antd"; 3 | 4 | const radioHoc = (props, onChange, RadioComponent) => { 5 | const { enum: enums, enumNames } = props.schema || {}; 6 | 7 | return ( 8 | 9 | {(enums || [true, false]).map((val, index) => ( 10 | 11 | 17 | 18 | ))} 19 | 20 | ); 21 | }; 22 | 23 | const VRadio = (p) => { 24 | const { optionType = "default" } = p.options; 25 | const onChange = (e) => p.onChange(p.name, e.target.value); 26 | const RadioComponent = optionType === "button" ? Radio.Button : Radio; 27 | return radioHoc(p, onChange, RadioComponent); 28 | }; 29 | 30 | export default VRadio; 31 | -------------------------------------------------------------------------------- /src/packages/form/radio/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Radio } from "antd"; 3 | 4 | const radioHoc = (props, onChange, RadioComponent) => { 5 | const { enum: enums, enumNames } = props.schema || {}; 6 | 7 | return ( 8 | 9 | {(enums || [true, false]).map((val, index) => ( 10 | 11 | 17 | 18 | ))} 19 | 20 | ); 21 | }; 22 | 23 | const VRadio = (p) => { 24 | const { optionType = "default" } = p.options; 25 | const onChange = (e) => p.onChange(p.name, e.target.value); 26 | const RadioComponent = optionType === "button" ? Radio.Button : Radio; 27 | return radioHoc(p, onChange, RadioComponent); 28 | }; 29 | 30 | export default VRadio; 31 | -------------------------------------------------------------------------------- /src/packages/border/src/border6.js: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from "react"; 2 | import { useAutoResize } from "~hooks/useAutoResize"; 3 | 4 | export default forwardRef(({ children, style, backgroundColor = "transparent" }, ref) => { 5 | const { width, height, domRef } = useAutoResize(ref); 6 | 7 | return ( 8 |
9 | 10 | 17 | 18 | 19 | {["left-top", "right-top", "left-bottom", "right-bottom"].map((name) => ( 20 | 21 | 22 | 23 | ))} 24 |
{children}
25 |
26 | ); 27 | }); 28 | -------------------------------------------------------------------------------- /src/pages/designer/configuration-value/other.js: -------------------------------------------------------------------------------- 1 | import { BASE_CONF, BASE_DATA_CONF } from "./default.js"; 2 | 3 | export default [ 4 | { 5 | name: "词云图", 6 | icon: "word-cloud", 7 | type: "wordCloud", 8 | data: { 9 | title: "词云图", 10 | ...BASE_CONF, 11 | config: { 12 | unit: "", 13 | backgroundColor: "#E3F7FF", 14 | fontPadding: 8, 15 | fontRotate: true, 16 | minFontSize: 12, 17 | maxFontSize: 35, 18 | shape: "circle", 19 | gridSize: 5, 20 | rotationStep: true 21 | }, 22 | dataConfig: { 23 | ...BASE_DATA_CONF, 24 | data: { 25 | series: [ 26 | { name: "龙头镇", value: "111" }, 27 | { name: "大埔镇", value: "222" }, 28 | { name: "太平镇", value: "458" }, 29 | { name: "沙埔镇", value: "445" }, 30 | { name: "东泉镇", value: "456" }, 31 | { name: "凤山镇", value: "647" }, 32 | { name: "六塘镇", value: "189" }, 33 | { name: "冲脉镇", value: "864" }, 34 | { name: "寨隆镇", value: "652" } 35 | ] 36 | } 37 | } 38 | } 39 | } 40 | ]; 41 | -------------------------------------------------------------------------------- /src/packages/number/index.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { InputNumber } from "antd"; 3 | import fetcher from "~packages/hoc"; 4 | import { isEmpty } from "~utils/helper"; 5 | 6 | const NumberComponent = (props) => { 7 | const style = props.invalid ? { borderColor: "#f5222d" } : {}; 8 | const { max, min, step } = props.schema; 9 | let obj = { 10 | placeholder: "请输入数字" 11 | }; 12 | if (max || max === 0) { 13 | obj = { max }; 14 | } 15 | 16 | if (min || min === 0) { 17 | obj = { ...obj, min }; 18 | } 19 | 20 | if (step) { 21 | obj = { ...obj, step }; 22 | } 23 | 24 | const rootValue = useMemo(() => { 25 | return !isEmpty(props.value) ? props.value : min || 0; 26 | }, [props.value]); 27 | 28 | const onChange = (value) => { 29 | props.onChange(props.name, value); 30 | }; 31 | 32 | return ( 33 | 41 | ); 42 | }; 43 | 44 | export default fetcher(NumberComponent); 45 | -------------------------------------------------------------------------------- /src/packages/form/number/index.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { InputNumber } from "antd"; 3 | import fetcher from "~packages/hoc"; 4 | import { isEmpty } from "~utils/helper"; 5 | 6 | const NumberComponent = (props) => { 7 | const style = props.invalid ? { borderColor: "#f5222d" } : {}; 8 | const { max, min, step } = props.schema; 9 | let obj = { 10 | placeholder: "请输入数字" 11 | }; 12 | if (max || max === 0) { 13 | obj = { max }; 14 | } 15 | 16 | if (min || min === 0) { 17 | obj = { ...obj, min }; 18 | } 19 | 20 | if (step) { 21 | obj = { ...obj, step }; 22 | } 23 | 24 | const rootValue = useMemo(() => { 25 | return !isEmpty(props.value) ? props.value : min || 0; 26 | }, [props.value]); 27 | 28 | const onChange = (value) => { 29 | props.onChange(props.name, value); 30 | }; 31 | 32 | return ( 33 | 41 | ); 42 | }; 43 | 44 | export default fetcher(NumberComponent); 45 | -------------------------------------------------------------------------------- /src/packages/vcharts/options/sankey.js: -------------------------------------------------------------------------------- 1 | import { DEFAULT_COLORS } from "~packages/constants"; 2 | 3 | export default (option, data) => { 4 | const { series } = data; 5 | const { sortType, textColor = "#19d4ae", textSize = 14, curveness, unit = "" } = option; 6 | 7 | return { 8 | color: DEFAULT_COLORS, 9 | tooltip: { 10 | trigger: "item", 11 | formatter: function (params) { 12 | if (params.data.name) { 13 | return [params.marker + "节点:" + params.data.name + "(" + (params.data.value || 0) + unit + ")"].join(""); 14 | } else { 15 | return [params.data.source + " vs " + params.data.target + "(" + (params.data.value || 0) + unit + ")"].join( 16 | "" 17 | ); 18 | } 19 | } 20 | }, 21 | series: [ 22 | { 23 | type: "sankey", 24 | bottom: "10%", 25 | data: series.data, 26 | links: series.links, 27 | orient: sortType, 28 | label: { 29 | color: textColor, 30 | fontSize: textSize 31 | }, 32 | lineStyle: { 33 | color: "source", 34 | curveness: curveness * 0.1 35 | } 36 | } 37 | ] 38 | }; 39 | }; 40 | -------------------------------------------------------------------------------- /src/packages/vcharts/options/funnel.js: -------------------------------------------------------------------------------- 1 | import { DEFAULT_COLORS } from "~packages/constants"; 2 | 3 | export default (option, data) => { 4 | const { series = [] } = data; 5 | const { sortType = "descending", funnelWidth = "100%", unit = "" } = option; 6 | 7 | return { 8 | color: DEFAULT_COLORS, 9 | tooltip: { 10 | trigger: "item", 11 | formatter: function (params) { 12 | return [params.marker + params.name + " " + (params.value || 0) + unit + "(" + params.percent + "%" + ")"].join( 13 | "" 14 | ); 15 | } 16 | }, 17 | series: [ 18 | { 19 | type: "funnel", 20 | x: 0, 21 | y: 60, 22 | y2: 60, 23 | top: 15, 24 | bottom: 20, 25 | width: "100%", 26 | min: 0, 27 | max: 100, 28 | minSize: "0%", 29 | maxSize: funnelWidth, 30 | sort: sortType, 31 | gap: 0, 32 | data: series, 33 | roseType: true, 34 | label: { 35 | normal: { 36 | formatter: function (params) { 37 | return params.name + ": " + params.value; 38 | }, 39 | position: "center" 40 | } 41 | } 42 | } 43 | ] 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /src/packages/select/multiple.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { Select } from "antd"; 3 | import fetcher from "~packages/hoc"; 4 | 5 | const MultiSelectComponent = (props) => { 6 | const style = props.invalid ? { borderColor: "#f5222d" } : {}; 7 | const { enum: enums, enumNames } = props.schema || {}; 8 | 9 | const rootValue = useMemo(() => { 10 | return props.value && Array.isArray(props.value) ? props.value : []; 11 | }, [props.value]); 12 | 13 | const onChange = (value) => props.onChange(props.name, value); 14 | 15 | return ( 16 | 35 | ); 36 | }; 37 | 38 | export default fetcher(MultiSelectComponent); 39 | -------------------------------------------------------------------------------- /src/packages/dependence/index.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { connect } from "react-redux"; 3 | import { Select } from "antd"; 4 | import fetcher from "~packages/hoc"; 5 | import { useDesigner } from "~hooks/useDesigner"; 6 | 7 | function SelectComponent({ name, value, onChange, selected }) { 8 | const { state } = useDesigner(); 9 | const options = useMemo(() => { 10 | return state.components.filter((v) => v.uniqueId !== selected && v.data.dependence); 11 | }, [selected]); 12 | 13 | // TODO: 联动参数处理 14 | const onDependenceChange = (value) => { 15 | onChange(name, value); 16 | }; 17 | 18 | return ( 19 | 36 | ); 37 | } 38 | 39 | export default connect((state) => ({ 40 | selected: state.component.selected 41 | }))(fetcher(SelectComponent)); 42 | -------------------------------------------------------------------------------- /src/packages/form/select/multiple.js: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { Select } from "antd"; 3 | import fetcher from "~packages/hoc"; 4 | 5 | const MultiSelectComponent = (props) => { 6 | const style = props.invalid ? { borderColor: "#f5222d" } : {}; 7 | const { enum: enums, enumNames } = props.schema || {}; 8 | 9 | const rootValue = useMemo(() => { 10 | return props.value && Array.isArray(props.value) ? props.value : []; 11 | }, [props.value]); 12 | 13 | const onChange = (value) => props.onChange(props.name, value); 14 | 15 | return ( 16 | 35 | ); 36 | }; 37 | 38 | export default fetcher(MultiSelectComponent); 39 | -------------------------------------------------------------------------------- /src/packages/date-picker/range.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { DatePicker } from "antd"; 3 | import locale from "antd/es/date-picker/locale/zh_CN"; 4 | import moment from "moment"; 5 | import "moment/locale/zh-cn"; 6 | moment.locale("zh-cn"); 7 | import { getFormat } from "@/form-render/utils"; 8 | 9 | function rangeHoc(props, onChange, RangeComponent) { 10 | const { value } = props; 11 | const { format = "dateTime" } = props.schema; 12 | const dateFormat = getFormat(format); 13 | 14 | let defaultObj = {}; 15 | if (value && Array.isArray(value) && value[0] && value[1]) { 16 | defaultObj = { 17 | defaultValue: [moment(props.value[0], dateFormat), moment(props.value[1], dateFormat)] 18 | }; 19 | } 20 | 21 | const dateParms = { 22 | ...props.options, 23 | ...defaultObj, 24 | style: { width: "100%" }, 25 | showTime: format === "dateTime", 26 | disabled: props.disabled, 27 | onChange 28 | }; 29 | 30 | return ; 31 | } 32 | 33 | const { RangePicker } = DatePicker; 34 | 35 | const VdateRange = (props) => { 36 | const onChange = (value, string) => props.onChange(props.name, string); 37 | return rangeHoc(props, onChange, RangePicker); 38 | }; 39 | 40 | export default VdateRange; 41 | -------------------------------------------------------------------------------- /src/packages/dynamic-dialog/modal.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Button, Modal } from "antd"; 4 | 5 | function DynamicDialog({ container = null, title, content, onCancel }) { 6 | const node = document.createElement("div"); 7 | 8 | if (container && typeof container === "string") { 9 | document.querySelector(container).appendChild(node); 10 | } else { 11 | document.body.appendChild(node); 12 | } 13 | 14 | const close = () => { 15 | onCancel && onCancel(); 16 | 17 | if (container && typeof container === "string") { 18 | document.querySelector(container).removeChild(node); 19 | } else { 20 | document.body.removeChild(node); 21 | } 22 | 23 | ReactDOM.unmountComponentAtNode(node); 24 | node.remove(); 25 | }; 26 | 27 | ReactDOM.render( 28 | 36 | 确定 37 | 38 | } 39 | width={1000} 40 | > 41 | {content} 42 | , 43 | node 44 | ); 45 | } 46 | 47 | export default DynamicDialog; 48 | -------------------------------------------------------------------------------- /src/packages/form/date/range.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { DatePicker } from "antd"; 3 | import locale from "antd/es/date-picker/locale/zh_CN"; 4 | import moment from "moment"; 5 | import "moment/locale/zh-cn"; 6 | moment.locale("zh-cn"); 7 | import { getFormat } from "@/form-render/utils"; 8 | 9 | function rangeHoc(props, onChange, RangeComponent) { 10 | const { value } = props; 11 | const { format = "dateTime" } = props.schema; 12 | const dateFormat = getFormat(format); 13 | 14 | let defaultObj = {}; 15 | if (value && Array.isArray(value) && value[0] && value[1]) { 16 | defaultObj = { 17 | defaultValue: [moment(props.value[0], dateFormat), moment(props.value[1], dateFormat)] 18 | }; 19 | } 20 | 21 | const dateParms = { 22 | ...props.options, 23 | ...defaultObj, 24 | style: { width: "100%" }, 25 | showTime: format === "dateTime", 26 | disabled: props.disabled, 27 | onChange 28 | }; 29 | 30 | return ; 31 | } 32 | 33 | const { RangePicker } = DatePicker; 34 | 35 | const VdateRange = (props) => { 36 | const onChange = (value, string) => props.onChange(props.name, string); 37 | return rangeHoc(props, onChange, RangePicker); 38 | }; 39 | 40 | export default VdateRange; 41 | -------------------------------------------------------------------------------- /src/packages/textarea/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Input } from "antd"; 3 | 4 | const { TextArea } = Input; 5 | 6 | const VTextArea = (p) => { 7 | const { options, invalid, schema = {} } = p; 8 | const { maxLength } = schema; 9 | const style = invalid ? { borderColor: "#ff4d4f", boxShadow: "0 0 0 2px rgba(255,77,79,.2)" } : {}; 10 | const defaultUi = { rows: 3 }; 11 | const ui = { ...defaultUi, ...options }; 12 | const onChange = (e) => p.onChange(p.name, e.target.value); 13 | 14 | const _value = p.value || ""; 15 | return ( 16 |
17 |