├── .changeset ├── config.json ├── flat-bags-roll.md ├── great-cycles-matter.md ├── grumpy-worms-design.md ├── large-cups-fix.md ├── slow-dolls-share.md ├── spicy-eels-compare.md └── thirty-hairs-occur.md ├── .dumi └── global.less ├── .dumirc.ts ├── .eslintrc-auto-import.json ├── .gitignore ├── .husky └── commit-msg ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .stylelintignore ├── .stylelintrc.js ├── .vscode ├── extensions.json ├── settings.json └── vis-react.code-workspace ├── README.md ├── auto-import.d.ts ├── commitlint.config.js ├── config ├── api.tsx ├── auto-import │ ├── ahooks-present.ts │ ├── antd-icons-present.ts │ ├── antd-present.ts │ ├── antdpro-present.ts │ ├── index.ts │ ├── lodash-present.ts │ └── umi-presents.ts ├── config.dev.ts ├── config.prod.ts ├── config.ts ├── plugins │ └── cssVarible.ts ├── routes.jsx └── theme │ ├── component.ts │ └── tokens.ts ├── docs ├── changelog │ ├── charts.md │ ├── common.md │ ├── components.md │ ├── test.md │ └── utils.md ├── cli │ ├── ide.md │ └── index.md ├── components │ └── index.md ├── demos │ ├── customization-value-type.tsx │ └── valueType.tsx ├── guide │ ├── deploy.md │ ├── getting-started.md │ ├── index.md │ ├── publish.md │ ├── subapp.md │ └── test.md ├── index.md └── playground │ └── curd.playground.md ├── jest.config.js ├── mock └── index.ts ├── package.json ├── packages ├── charts │ ├── .fatherrc.ts │ ├── README.md │ ├── package.json │ ├── src │ │ ├── BasicColumn │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── BasicLine │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── BasicPie │ │ │ ├── README.md │ │ │ └── index.tsx │ │ ├── BasicRingPie │ │ │ ├── README.md │ │ │ └── index.tsx │ │ ├── Describe │ │ │ ├── README.md │ │ │ └── index.tsx │ │ ├── ProgressLine │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── WordCloud │ │ │ ├── README.md │ │ │ ├── Setting.tsx │ │ │ ├── api.tsx │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ ├── word-cloud.d.ts │ │ │ └── word-cloud.js │ │ ├── charts.md │ │ └── index.tsx │ └── tsconfig.json ├── common │ ├── .fatherrc.ts │ ├── README.md │ ├── package.json │ ├── src │ │ ├── Unit │ │ │ ├── README.md │ │ │ └── index.tsx │ │ ├── VisCrud │ │ │ ├── README.md │ │ │ └── index.tsx │ │ ├── VisHeader │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── Workspace │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── common.md │ │ ├── index.tsx │ │ └── interceptors │ │ │ └── index.ts │ └── tsconfig.json ├── components │ ├── .fatherrc.ts │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── Condition │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── ContextMenu │ │ │ ├── Item.tsx │ │ │ ├── README.md │ │ │ ├── SubMenu.tsx │ │ │ ├── helper.ts │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── useContextMenu.tsx │ │ ├── DragLayoutResize │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── Marquee │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── audio │ │ │ ├── index.tsx │ │ │ └── useAudio.tsx │ │ ├── components.md │ │ └── index.tsx │ └── tsconfig.json ├── decorator │ ├── .fatherrc.ts │ ├── README.md │ ├── package.json │ ├── src │ │ ├── Background │ │ │ ├── demos │ │ │ │ ├── index.tsx │ │ │ │ └── small-deer.svg │ │ │ └── index.tsx │ │ ├── BorderBox │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── BorderBox1 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox10 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox11 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox12 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox2 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox3 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox4 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox5 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox6 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox7 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox8 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── BorderBox9 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration1 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration10 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration11 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration12 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration2 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration3 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration4 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration5 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration6 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration7 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration8 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── Decoration9 │ │ │ ├── index.tsx │ │ │ └── style.less │ │ ├── decorator.md │ │ └── index.tsx │ └── tsconfig.json ├── test │ ├── .fatherrc.ts │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.module.less │ │ ├── index.tsx │ │ └── test.md │ └── tsconfig.json └── utils │ ├── .fatherrc.ts │ ├── README.md │ ├── package.json │ ├── src │ ├── SnowFlake │ │ └── index.ts │ ├── aes │ │ └── index.ts │ ├── dataTransform │ │ └── index.ts │ ├── dateArrayFormatter │ │ └── index.tsx │ ├── genCopyable │ │ └── index.tsx │ ├── index.tsx │ ├── isBrowser │ │ └── index.ts │ ├── isDeepEqualReact │ │ └── index.ts │ ├── isImg │ │ └── index.ts │ ├── isUrl │ │ └── index.ts │ ├── matchString │ │ └── index.tsx │ ├── nanoid │ │ └── index.ts │ ├── observerDomResize │ │ └── index.tsx │ ├── parseValueToMoment │ │ └── index.ts │ ├── rsa │ │ └── index.ts │ ├── runFunction │ │ └── index.ts │ ├── stringLikely │ │ └── index.ts │ ├── typing.ts │ ├── unit │ │ └── index.ts │ ├── useAutoResize │ │ └── index.tsx │ └── utils.md │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── projects └── template │ ├── .eslintignore │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc │ ├── .stylelintignore │ ├── .umirc.ts │ ├── README.md │ ├── mock │ └── index.ts │ ├── package.json │ ├── public │ └── icon │ │ └── iconfont.js │ ├── src │ ├── apis │ │ └── dashboard.ts │ ├── app.tsx │ ├── components │ │ └── Error │ │ │ └── ErrorBoundary.tsx │ ├── constants │ │ └── other.ts │ ├── global.less │ ├── layouts │ │ └── main.tsx │ ├── pages │ │ ├── index │ │ │ ├── Space1.tsx │ │ │ ├── Space2.tsx │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ └── test │ │ │ └── index.tsx │ ├── routes.ts │ ├── types │ │ └── framework.ts │ └── typings.d.ts │ └── tsconfig.json ├── public └── cdn │ └── lodash.min.js ├── scripts ├── bootstrap.js ├── buildAdapt.js ├── buildPackage.js ├── checkDeps.js ├── checkEnv.js ├── clearMfsu.js ├── createRelease.js ├── devPackage.js ├── devProject.js ├── gen_less_entry.js ├── gen_version.js ├── generateSizeLimit.js ├── preDeploy.js ├── preinstall.js ├── releasePackage.js ├── replaceLib.js └── utils │ ├── exec.js │ ├── file.js │ ├── genAlias.js │ ├── getPackages.js │ └── getProject.js ├── src ├── access.ts ├── app.tsx ├── components │ └── Guide │ │ ├── Guide.less │ │ ├── Guide.tsx │ │ └── index.ts ├── constants │ └── index.ts ├── global.less ├── layouts │ ├── base │ │ ├── AvatarDropDown.tsx │ │ ├── ContentSearch.tsx │ │ ├── NotificatTab.tsx │ │ ├── index.module.less │ │ ├── index.tsx │ │ └── layoutHelper.tsx │ └── login │ │ └── index.tsx ├── models │ ├── global.ts │ └── memoHistory.ts ├── pages │ ├── Access │ │ └── index.tsx │ ├── Dash │ │ └── index.tsx │ ├── Home │ │ ├── Space1.tsx │ │ ├── Space2.tsx │ │ ├── index.module.less │ │ └── index.tsx │ ├── MicroApp │ │ ├── dash.tsx │ │ └── index.tsx │ ├── Table │ │ └── index.tsx │ └── Test │ │ ├── Test1.tsx │ │ ├── index.module.less │ │ └── index.tsx ├── services │ └── demo │ │ ├── UserController.ts │ │ ├── index.ts │ │ └── typings.d.ts ├── typings.d.ts ├── utils │ └── format.ts └── vis.less ├── tests ├── charts │ └── WordCloud.test.tsx ├── jsTransformer.js ├── setupTests.js └── util.ts ├── tsconfig.json ├── unocss.config.ts └── webpack.config.js /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [["@vis/*"]], 6 | "access": "restricted", 7 | "baseBranch": "master", 8 | "fetch-depth": 0, 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["@vis/dashboard"], 11 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 12 | "onlyUpdatePeerDependentsWhenOutOfRange": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.changeset/flat-bags-roll.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@vis/common': patch 3 | --- 4 | 5 | common 包增加通用 request 拦截器 6 | -------------------------------------------------------------------------------- /.changeset/great-cycles-matter.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@vis/components': patch 3 | --- 4 | 5 | 封装通用性组件 Workspace 组件,增加文档 6 | -------------------------------------------------------------------------------- /.changeset/grumpy-worms-design.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@vis/decorator': major 3 | '@vis/utils': minor 4 | --- 5 | 6 | 增加装饰包,添加边框组件 12 个 7 | -------------------------------------------------------------------------------- /.changeset/large-cups-fix.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@vis/charts': patch 3 | --- 4 | 5 | basiceLine 组件自动生成文档 6 | -------------------------------------------------------------------------------- /.changeset/slow-dolls-share.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@vis/decorator': patch 3 | --- 4 | 5 | feat(decorator): 增加背景特效插件,文档,优化 readme 6 | -------------------------------------------------------------------------------- /.changeset/spicy-eels-compare.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@vis/components': patch 3 | --- 4 | 5 | feat(components): 增加 Condition 条件筛选组件 6 | -------------------------------------------------------------------------------- /.changeset/thirty-hairs-occur.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@vis/decorator': major 3 | --- 4 | 5 | feat(decoratot): 增加背景装饰 12 个以及相关文档 6 | -------------------------------------------------------------------------------- /.dumi/global.less: -------------------------------------------------------------------------------- 1 | .dumi-default-features { 2 | display: flex; 3 | flex-wrap: wrap; 4 | } 5 | .markdown { 6 | h1, 7 | h2, 8 | h3, 9 | h4, 10 | h5 { 11 | color: inherit; 12 | } 13 | } 14 | 15 | h1.dumi-default-hero-title { 16 | padding: 0 40px; 17 | // box-shadow: 0px 14px 9px #6964647a; 18 | > span { 19 | // text-shadow: 0 3px 6px rgb(22 119 255); 20 | text-shadow: none; 21 | color: transparent; 22 | text-transform: uppercase; 23 | font-family: 'Open Sans Pro', sans-serif; 24 | background: url(https://wimg.588ku.com/gif620/20/06/07/fbce6f1ceefb606f5b594ca282ec72bc.gif) 25 | center 285px; 26 | background-size: cover; 27 | -webkit-background-clip: text; 28 | -webkit-text-fill-color: transparent; 29 | } 30 | } 31 | 32 | @keyframes shining { 33 | from { 34 | background-position: -500%; 35 | } 36 | to { 37 | background-position: 500%; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | .dumi/tmp 17 | .dumi/tmp-test 18 | .dumi/tmp-production 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # TypeScript v1 declaration files 46 | typings/ 47 | 48 | # Optional npm cache directory 49 | .npm 50 | 51 | # Optional eslint cache 52 | .eslintcache 53 | 54 | # Optional REPL history 55 | .node_repl_history 56 | 57 | # Output of 'npm pack' 58 | *.tgz 59 | 60 | # Yarn Integrity file 61 | .yarn-integrity 62 | 63 | # dotenv environment variables file 64 | .env 65 | 66 | # parcel-bundler cache (https://parceljs.org/) 67 | .cache 68 | 69 | # next.js build output 70 | .next 71 | 72 | # nuxt.js build output 73 | .nuxt 74 | 75 | 76 | # vuepress build output 77 | .vuepress/dist 78 | 79 | # Serverless directories 80 | .serverless 81 | 82 | # IDE / Editor 83 | .idea 84 | 85 | # Service worker 86 | sw.* 87 | 88 | # Mac OSX 89 | .DS_Store 90 | 91 | # Vim swap files 92 | *.swp 93 | yarn.lock 94 | web 95 | .ice 96 | index.module.scss.d.ts 97 | *.dia~ 98 | 99 | # production 100 | build/ 101 | dist/ 102 | tmp/ 103 | /packages/*/lib/ 104 | .happypack 105 | /build-doc/* 106 | 107 | 108 | # production 109 | **/dist 110 | **/**/es/** 111 | # misc 112 | .DS_Store 113 | 114 | /coverage 115 | .idea 116 | package-lock.json 117 | *bak 118 | 119 | # visual studio code 120 | .history 121 | *.log 122 | 123 | functions/mock 124 | .temp/** 125 | 126 | # umi 127 | .umi 128 | .umi-production 129 | 130 | # screenshot 131 | screenshot 132 | .firebase 133 | .eslintcache 134 | .changelogs 135 | .changelog.md 136 | .temp 137 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit 5 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | engine-strict = true 3 | strict-peer-dependencies=false 4 | node-options=--max_old_space_size=8192 5 | engine-strict = true 6 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build/ 2 | tests/ 3 | demo/ 4 | .ice/ 5 | coverage/ 6 | **/*-min.js 7 | **/*.min.js 8 | package-lock.json 9 | yarn.lock 10 | .umi 11 | .umi-production 12 | **/dist 13 | **/lib 14 | **/es 15 | **\__snapshots__\** 16 | assets/ 17 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "proseWrap": "never", 6 | "overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }] 7 | } 8 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | # 忽略目录 2 | build/ 3 | tests/ 4 | demo/ 5 | 6 | # node 覆盖率文件 7 | coverage/ 8 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: require.resolve('@umijs/max/stylelint'), 3 | }; 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "esbenp.prettier-vscode", 4 | "folke.vscode-monorepo-workspace", 5 | "antfu.unocss" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/vis-react.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "name": "✨ youname", 5 | "path": ".." 6 | }, 7 | { 8 | "name": "📈@vis/charts", 9 | "path": "../packages/charts" 10 | }, 11 | { 12 | "name": "💡@vis/common", 13 | "path": "../packages/common" 14 | }, 15 | { 16 | "name": "🤔@vis/components", 17 | "path": "../packages/components" 18 | }, 19 | { 20 | "name": "💄@vis/decorator", 21 | "path": "../packages/decorator" 22 | }, 23 | { 24 | "name": "🎯@vis/test", 25 | "path": "../packages/test" 26 | }, 27 | { 28 | "name": "🤸‍♀️@vis/utils", 29 | "path": "../packages/utils" 30 | }, 31 | { 32 | "name": "🌘@vis/template", 33 | "path": "../projects/template" 34 | } 35 | ], 36 | "settings": {} 37 | } 38 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {extends: ['@commitlint/config-conventional']} 2 | -------------------------------------------------------------------------------- /config/api.tsx: -------------------------------------------------------------------------------- 1 | import React, { type FC } from 'react'; 2 | -------------------------------------------------------------------------------- /config/auto-import/ahooks-present.ts: -------------------------------------------------------------------------------- 1 | import * as ahooks from 'ahooks'; 2 | 3 | export const AhooksPresent = Object.keys(ahooks).map((i) => { 4 | return [i, `_${i}`]; 5 | }); 6 | -------------------------------------------------------------------------------- /config/auto-import/antd-icons-present.ts: -------------------------------------------------------------------------------- 1 | import * as antd from '@ant-design/icons' 2 | 3 | // https://github.com/antfu/unplugin-vue-components/blob/main/src/core/resolvers/antdv.ts 4 | // console.log('all',all); 5 | export const antdIconPresent = Object.keys(antd) 6 | .filter((k) => k !== 'default') 7 | .map((i) => { 8 | return [i, i] 9 | // return [i, `Icon${i}`]; 10 | }) 11 | // console.log(Object.keys(antd).filter((k) => k !== 'default')) 12 | -------------------------------------------------------------------------------- /config/auto-import/antd-present.ts: -------------------------------------------------------------------------------- 1 | import * as antd from 'antd' 2 | 3 | // https://github.com/antfu/unplugin-vue-components/blob/main/src/core/resolvers/antdv.ts 4 | // console.log('all', antd) 5 | export const antdPresent = Object.keys(antd).map((i) => { 6 | if (/^[a-z][A-Za-z]*$/.test(i)) { 7 | return [i, `_${i}`] 8 | } 9 | if (i === 'Image') { 10 | return [i, 'AImage'] 11 | } 12 | return [i, i] 13 | }) 14 | -------------------------------------------------------------------------------- /config/auto-import/index.ts: -------------------------------------------------------------------------------- 1 | import { AhooksPresent } from './ahooks-present'; 2 | import { antdIconPresent } from './antd-icons-present'; 3 | import { antdPresent } from './antd-present'; 4 | // import { lodashPresent } from './lodash-present'; 5 | import { umiPresent } from './umi-presents'; 6 | import { antdProPresent } from './antdpro-present'; 7 | const IconsResolver = require('unplugin-icons/resolver'); 8 | 9 | export const autoImportPlugin = () => 10 | require('unplugin-auto-import/webpack')({ 11 | dts: './auto-import.d.ts', 12 | include: [ 13 | /\.[t]sx?$/, // .ts, .tsx, 14 | ], 15 | imports: [ 16 | 'react', 17 | { 18 | 'antd/es': antdPresent, 19 | // 'lodash-es': lodashPresent, 20 | ahooks: AhooksPresent, 21 | '@ant-design/icons': antdIconPresent, 22 | '@umijs/max': umiPresent, 23 | '@ant-design/pro-components': antdProPresent, 24 | }, 25 | ], 26 | vueTemplate: false, 27 | 28 | // Auto import for all module exports under directories 29 | // when using in file names mostly use prefixes _ and $ to avoid conflicts 30 | dirs: [ 31 | // './xx/**', // all nested modules 32 | ], 33 | resolvers: [ 34 | IconsResolver({ 35 | componentPrefix: 'Icon', 36 | extension: 'jsx', 37 | }), 38 | ], 39 | eslintrc: { 40 | enabled: true, // Default `false` 41 | filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json` 42 | globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable') 43 | }, 44 | }); 45 | -------------------------------------------------------------------------------- /config/auto-import/lodash-present.ts: -------------------------------------------------------------------------------- 1 | import * as lodash from 'lodash'; 2 | // console.log( 3 | // 'all', 4 | // Object.keys(all).map((i) => { 5 | // return [i, `__${i}`]; 6 | // }), 7 | // ); 8 | export const lodashPresent = Object.keys(lodash).map((i) => { 9 | return [i, `__${i}`] 10 | }) 11 | -------------------------------------------------------------------------------- /config/auto-import/umi-presents.ts: -------------------------------------------------------------------------------- 1 | // import * as umi from '@umijs/max'; 2 | 3 | // const umiPresent = Object.keys(umi).map((i) => { 4 | // if (/^[a-z][A-Za-z]*$/.test(i)) { 5 | // return [i, `$${i}`]; 6 | // } 7 | // return [i, `U${i}`]; 8 | // }); 9 | // import * as umi from 'umi'; 10 | 11 | // console.log('umiPresent',umiPresent); 12 | 13 | export const umiPresent = [ 14 | ['Access', 'Access'], 15 | ['ApplyPluginsType', 'ApplyPluginsType'], 16 | 'Link', 17 | 'NavLink', 18 | 'Navigate', 19 | 'Outlet', 20 | 'PluginManager', 21 | 'Provider', 22 | 'UseRequestProvider', 23 | ['__getRoot', '__getRoot'], 24 | ['__useFetcher', '__useFetcher'], 25 | ['createBrowserHistory', '$createBrowserHistory'], 26 | ['createHashHistory', '$createHashHistory'], 27 | ['createHistory', '$createHistory'], 28 | ['createMemoryHistory', '$createMemoryHistory'], 29 | ['createSearchParams', '$createSearchParams'], 30 | ['defineApp', '$defineApp'], 31 | ['generatePath', '$generatePath'], 32 | ['getRequestInstance', '$getRequestInstance'], 33 | ['history', '$history'], 34 | ['matchPath', '$matchPath'], 35 | ['matchRoutes', '$matchRoutes'], 36 | ['renderClient', '$renderClient'], 37 | ['request', '$request'], 38 | ['resolvePath', '$resolvePath'], 39 | ['terminal', '$terminal'], 40 | ['useAccess', 'useAccess'], 41 | ['useAccessMarkedRoutes', 'useAccessMarkedRoutes'], 42 | ['useAppData', 'useAppData'], 43 | ['useClientLoaderData', 'useClientLoaderData'], 44 | ['useLocation', 'useLocation'], 45 | ['useMatch', 'useMatch'], 46 | ['useModel', 'useModel'], 47 | ['useNavigate', 'useNavigate'], 48 | ['useOutlet', 'useOutlet'], 49 | ['useOutletContext', 'useOutletContext'], 50 | ['useParams', 'useParams'], 51 | ['useRequest', 'useRequest'], 52 | ['useResolvedPath', 'useResolvedPath'], 53 | ['useRouteData', 'useRouteData'], 54 | ['useRoutes', 'useRoutes'], 55 | ['useSearchParams', 'useSearchParams'], 56 | ['useServerLoaderData', 'useServerLoaderData'], 57 | ['withRouter', '$withRouter'], 58 | ['history', '_history'], 59 | ]; 60 | -------------------------------------------------------------------------------- /config/config.dev.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@umijs/max'; 2 | 3 | console.log('config.dev is working 😊'); 4 | 5 | export default defineConfig({ 6 | devtool: 'source-map', 7 | clickToComponent: {}, 8 | monorepoRedirect: { 9 | // 优化 子包的热更新,目前没用,走的是alias 10 | exclude: [/^@vis\/.+/], 11 | }, 12 | // externals: { 13 | // react: 'React', 14 | // 'react-dom/client': 'ReactDOM', 15 | // }, 16 | // headScripts: ['/cdn/react.dev.js', '/cdn/react-dom.dev.js'], 17 | proxy: { 18 | '/vis': { 19 | // target: 'http://xxx.xxx.xx.xxx:8089/', 20 | }, 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /config/config.prod.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@umijs/max'; 2 | 3 | console.log('config.prod is working 😊'); 4 | 5 | // 注: dev模式下的externals配置后增加相关development.js在开启mfsu的前提下优化效果可能不是很大,所以没做 6 | // const moduleFederationName = '__vis'; 7 | // const shared = { // 使用mf共享模块 8 | // react: { 9 | // singleton: true, 10 | // eager: true, 11 | // }, 12 | // 'react-dom': { 13 | // singleton: true, 14 | // eager: true, 15 | // }, 16 | // 'antd': { 17 | // singleton: true, 18 | // eager: true, 19 | // } 20 | // } 21 | export default defineConfig({ 22 | // deadCode: { 23 | // failOnHint: true, // will force a error message and exit immediately 24 | // exclude some folder or directory 25 | // exclude: ['pages/unused/**'], 26 | // }, 27 | // mf: { 28 | // name: moduleFederationName, 29 | // library: { type: "window", name: "__vis" }, 30 | // shared 31 | // }, 32 | // mfsu: { 33 | // // strategy: 'eager', 34 | // mfName:`mf_${moduleFederationName}`, 35 | // remoteName: moduleFederationName, 36 | // shared 37 | // }, 38 | publicPath: '/main/', 39 | mfsu: { 40 | esbuild: true, 41 | }, 42 | jsMinifier: 'esbuild', 43 | jsMinifierOptions: { 44 | minifyWhitespace: true, 45 | minifyIdentifiers: true, 46 | minifySyntax: true, 47 | drop: ['console'], 48 | }, 49 | cssMinifierOptions: { 50 | minifyWhitespace: true, 51 | minifySyntax: true, 52 | }, 53 | codeSplitting: { 54 | // granularChunks as testing in lighthouse it get 1% better performance 55 | jsStrategy: 'granularChunks', 56 | jsStrategyOptions: {}, 57 | cssStrategyOptions: {}, 58 | }, 59 | }); 60 | -------------------------------------------------------------------------------- /config/plugins/cssVarible.ts: -------------------------------------------------------------------------------- 1 | import { IApi } from 'umi'; 2 | import { theme } from 'antd'; 3 | import { antdTheme } from '../theme/tokens'; 4 | const { defaultAlgorithm } = theme; 5 | const mapToken = defaultAlgorithm(antdTheme); 6 | let _hack_varible: Record = {}; 7 | for (const key in mapToken) { 8 | if (Object.prototype.hasOwnProperty.call(mapToken, key)) { 9 | const element = mapToken[key as 'red']; 10 | _hack_varible[`--${key}`] = element; 11 | } 12 | } 13 | 14 | const cssVarible = `:root ${JSON.stringify(_hack_varible) 15 | .replaceAll(',', ';') 16 | .replaceAll('"', '')}`; 17 | 18 | export default (api: IApi) => { 19 | api.addHTMLStyles(() => cssVarible); 20 | }; 21 | -------------------------------------------------------------------------------- /config/routes.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | BarChartOutlined, 3 | BorderInnerOutlined, 4 | GithubOutlined, 5 | IdcardOutlined, 6 | RocketOutlined, 7 | SubnodeOutlined, 8 | } from '@ant-design/icons'; 9 | import React from 'react'; 10 | 11 | export default [ 12 | { path: '/', redirect: '/dash' }, 13 | { 14 | name: '首页', 15 | path: '/', 16 | component: '@/layouts/base', 17 | meta: { 18 | desc: '首页的描述', 19 | }, 20 | routes: [ 21 | { 22 | name: '首页', 23 | path: '/dash', 24 | component: './Dash', 25 | meta: { 26 | desc: '数据分析', 27 | keepAlive: false, 28 | }, 29 | icon: , 30 | }, 31 | { 32 | name: '工作区Demo', 33 | path: '/home', 34 | component: './Home', 35 | meta: { 36 | desc: '初始化demo,用来展示workSpace的基本用法,后续添加面包屑功能', 37 | }, 38 | icon: , 39 | }, 40 | { 41 | name: '权限演示', 42 | path: '/access', 43 | component: './Access', 44 | meta: { 45 | desc: '演示权限', 46 | keepAlive: false, 47 | }, 48 | icon: , 49 | }, 50 | { 51 | name: 'CRUD 示例', 52 | path: '/table', 53 | component: './Table', 54 | meta: { 55 | desc: '基础的CRUD模型DEMO', 56 | }, 57 | icon: , 58 | }, 59 | { 60 | name: '测试', 61 | path: '/test', 62 | icon: , 63 | routes: [ 64 | { 65 | name: '测试主页', 66 | path: '/test/index', 67 | component: './Test', 68 | meta: { 69 | desc: '测试主页的描述', 70 | }, 71 | }, 72 | { 73 | name: '测试1', 74 | path: '/test/test1', 75 | component: './Test/Test1', 76 | meta: { 77 | desc: '测试1的描述', 78 | }, 79 | }, 80 | ], 81 | }, 82 | { 83 | name: '微前端', 84 | path: '/subApp', 85 | icon: , 86 | routes: [ 87 | { 88 | name: '模版', 89 | path: '/subApp/template/*', 90 | // component: './MicroApp/dash' 91 | microApp: 'template', 92 | meta: { 93 | desc: '可视化页面配置', 94 | }, 95 | }, 96 | ], 97 | }, 98 | ], 99 | }, 100 | { 101 | name: '登录', 102 | path: '/login', 103 | component: '@/layouts/login', 104 | meta: { 105 | desc: '登录页面', 106 | }, 107 | }, 108 | ]; 109 | -------------------------------------------------------------------------------- /config/theme/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | Button: { 3 | // 某个组件的具体token, 权重会大于全局配置 4 | // colorPrimary: '#00b96b', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /docs/changelog/charts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: vis/charts - 更新日志 3 | order: 1 4 | nav: 更新日志 5 | --- 6 | 7 | # Change Log 8 | 9 | ## 3.1.0 10 | 11 | ### Patch Changes 12 | 13 | - 96fdc5c: docs: 优化文档 14 | 15 | ## 2.0.0 16 | 17 | ### Major Changes 18 | 19 | - ed7b0d2: test 20 | - test2 21 | - 3a4de15: 测试 22 | - test333 23 | 24 | All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 25 | 26 | # [1.3.0](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/compare/@vis/charts@1.2.0...@vis/charts@1.3.0) (2022-07-19) 27 | 28 | ### Features 29 | 30 | - 增加独立发布脚本,增加发布相关文档说明 ([cb009b5](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/cb009b5bc5837dedab851d9d38dae1b046a406c5)) 31 | 32 | # [1.2.0](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/compare/@vis/charts@1.1.0...@vis/charts@1.2.0) (2022-07-18) 33 | 34 | ### Features 35 | 36 | - 日志跳转详情对接 gitlab ([bd62a9f](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/bd62a9f6fba5b5aab7704236c06a3663ae84e16a)) 37 | 38 | ### Performance Improvements 39 | 40 | - 增加词云图组件,增加词云图文档,优化主页文档。 ([129aa35](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/129aa3546ac4a7c114aec3fecfd4626ef1adacec)) 41 | 42 | # 1.1.0 (2022-07-15) 43 | 44 | ### Features 45 | 46 | - 增加 chart,common 包,增加基础结构代码和文档,增加 DragLayoutResize 组件 ([ef2c8eb](http://xxx.xxx.xxx.xxx:xxxx/-/web/detail/@vis/components/commits/ef2c8eb2613650fa23ae38b340d882ace57fe14e)) 47 | -------------------------------------------------------------------------------- /docs/changelog/components.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: vis/components - 更新日志 3 | nav: 更新日志 4 | 5 | --- 6 | 7 | # Change Log 8 | 9 | ## 3.1.0 10 | 11 | ### Patch Changes 12 | 13 | - 96fdc5c: docs: 优化文档 14 | 15 | ## 2.0.0 16 | 17 | ### Major Changes 18 | 19 | - ed7b0d2: test 20 | - test2 21 | - 3a4de15: 测试 22 | - test333 23 | 24 | All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 25 | 26 | # [1.2.0](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/compare/@vis/common@1.1.0...@vis/common@1.2.0) (2022-07-18) 27 | 28 | ### Features 29 | 30 | - 日志跳转详情对接 gitlab ([bd62a9f](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/bd62a9f6fba5b5aab7704236c06a3663ae84e16a)) 31 | 32 | # 1.1.0 (2022-07-15) 33 | 34 | ### Features 35 | 36 | - 增加 chart,common 包,增加基础结构代码和文档,增加 DragLayoutResize 组件 ([ef2c8eb](http://xxx.xxx.xxx.xxx:xxxx/-/web/detail/@vis/components/commits/ef2c8eb2613650fa23ae38b340d882ace57fe14e)) 37 | -------------------------------------------------------------------------------- /docs/changelog/test.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: vis/test - 更新日志 3 | nav: 更新日志 4 | --- 5 | 6 | # Change Log 7 | 8 | ## 4.0.0 9 | 10 | ### Patch Changes 11 | 12 | - Updated dependencies [f30f284] 13 | - @vis/utils@4.0.0 14 | 15 | ## 3.2.0 16 | 17 | ### Minor Changes 18 | 19 | - 3ac5a36: test 20 | 21 | ## 3.1.0 22 | 23 | ### Minor Changes 24 | 25 | - 96fdc5c: docs: 优化文档 26 | 27 | ### Patch Changes 28 | 29 | - Updated dependencies [96fdc5c] 30 | - @vis/utils@3.1.0 31 | 32 | ## 3.0.0 33 | 34 | ### Major Changes 35 | 36 | - f91a3ce: 测试打包日志 37 | 38 | ## 2.0.0 39 | 40 | ### Major Changes 41 | 42 | - ed7b0d2: test 43 | - test2 44 | - 3a4de15: 测试 45 | - test333 46 | 47 | ### Patch Changes 48 | 49 | - Updated dependencies [ed7b0d2] 50 | - Updated dependencies 51 | - Updated dependencies [3a4de15] 52 | - @vis/utils@2.0.0 53 | 54 | All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 55 | 56 | # [1.2.0](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/compare/@vis/test@1.1.0...@vis/test@1.2.0) (2022-07-18) 57 | 58 | ### Features 59 | 60 | - 打包后自动重新生成相关库变动后的更新内容 ([45013da](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/45013da8d06b8804fd806c09c6f8530989663e29)) 61 | - 日志跳转详情对接 gitlab ([bd62a9f](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/bd62a9f6fba5b5aab7704236c06a3663ae84e16a)) 62 | - 适配自动生成版本发包日志并渲染日志记录文档 ([91acb09](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/91acb09cf81c19dc3aed5eaac666c6fa8ec879e9)) 63 | - 增加 chart,common 包,增加基础结构代码和文档,增加 DragLayoutResize 组件 ([ef2c8eb](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/ef2c8eb2613650fa23ae38b340d882ace57fe14e)) 64 | - 自动发包,根据 commit 类型自动生成 features 文档,提示本次发包的内容, ([8ed8abd](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/8ed8abd8cb589b233fb601939e31f46fd8367ed5)) 65 | 66 | # 1.1.0 (2022-07-14) 67 | 68 | ### Features 69 | 70 | - 修改打包配置, 修改文档相关配置,增加测试组件和 utils 组件 ([444b8f3](https://github.com/ant-design/pro-components/commit/444b8f34295bd35dac4c1b86de7d4b629e4279c8)) 71 | - update flag, 这是一次测试提交 ([87b579b](https://github.com/ant-design/pro-components/commit/87b579bf065aea5bbb0735907c0c4bd0e21cce1f)) 72 | -------------------------------------------------------------------------------- /docs/changelog/utils.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: vis/utils - 更新日志 3 | nav: 更新日志 4 | --- 5 | 6 | # Change Log 7 | 8 | ## 4.0.0 9 | 10 | ### Major Changes 11 | 12 | - f30f284: test: 测试 utils 变动下的 test 引用 13 | 14 | ## 3.1.0 15 | 16 | ### Patch Changes 17 | 18 | - 96fdc5c: docs: 优化文档 19 | 20 | ## 2.0.0 21 | 22 | ### Major Changes 23 | 24 | - ed7b0d2: test 25 | - test2 26 | - 3a4de15: 测试 27 | 28 | All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 29 | 30 | # [1.45.0](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/compare/@vis/utils@1.44.0...@vis/utils@1.45.0) (2022-07-18) 31 | 32 | ### Features 33 | 34 | - 打包后自动重新生成相关库变动后的更新内容 ([45013da](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/45013da8d06b8804fd806c09c6f8530989663e29)) 35 | - 日志跳转详情对接 gitlab ([bd62a9f](http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/commits/bd62a9f6fba5b5aab7704236c06a3663ae84e16a)) 36 | 37 | # [1.44.0](https://github.com/ant-design/pro-components/compare/@vis/utils@1.43.0...@vis/utils@1.44.0) (2022-07-14) 38 | 39 | ### Features 40 | 41 | - 适配自动生成版本发包日志并渲染日志记录文档 ([91acb09](https://github.com/ant-design/pro-components/commit/91acb09cf81c19dc3aed5eaac666c6fa8ec879e9)) 42 | - 自动发包,根据 commit 类型自动生成 features 文档,提示本次发包的内容, ([8ed8abd](https://github.com/ant-design/pro-components/commit/8ed8abd8cb589b233fb601939e31f46fd8367ed5)) 43 | 44 | # 1.43.0 (2022-07-14) 45 | 46 | ### Features 47 | 48 | - 修改打包配置, 修改文档相关配置,增加测试组件和 utils 组件 ([444b8f3](https://github.com/ant-design/pro-components/commit/444b8f34295bd35dac4c1b86de7d4b629e4279c8)) 49 | -------------------------------------------------------------------------------- /docs/components/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 通用配置 3 | order: 2 4 | group: 5 | path: / 6 | nav: 7 | title: 组件 8 | path: /components 9 | --- 10 | 11 | ## 通用 12 | 13 | 每个组件下的`README.md`就是我们当前组件的文档描述。用来描述组件的用法和常用 api 配置 demo 等。
我们推荐使用 TypeScript 去写组件代码,这样在主应用或者其他项目中使用我们的包时会有代码类型校验和错误提示,且能规避很多不易发现的基本错误,更好的适配 dumi 自动生成 api 文档,不需要再单独去 md 文档写当前组件的 api 参数等。 14 | 15 | ## api 自动生成 16 | 17 |

18 | ⚠️警告:目前dumi2.x版本API自动生成正在研发中,配置先暂时关闭 19 |

20 | 21 | `还是建议使用完整的ts类型来写你的组件`,在每个类型上可以规范添加对应的内容描述,前面的事情清晰的做好后后面文档你会发现几乎不需要太多时间,你的组件文档就写完了,差不多只要写几个 demo 示例,后面的所有 api 都可以自动导出 api 来自定生成。 22 | 23 | - 我们建议在每个组件下定义一个`api.tsx`, 导出到处当前文档的类型。基于[react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript)语法,更多功能可以参考该语法。 24 |
25 | 切记:每个导出的类型需要变成组件参数,然后导出组件,不可🙅直接导出类型 26 |
27 | 28 | ```js 29 | import React from 'react'; 30 | const Api: React.FC<{ 31 | /** 32 | * @description 这是props1的描述 33 | * @default 支持定义默认值 34 | * 35 | */ 36 | props1: string 37 | }> = () => <>; 38 | const Api2: React.FC<{ 39 | /** 这是props1简写的描述 */ 40 | props1: string 41 | }> = () => <>; 42 | export default Api; 43 | export const Api2; 44 | ``` 45 | 46 | 配置完之后我们就可以去当前组件下的 README.md 文件引入该组件 api 了 47 | 48 | ```js 49 | // 不展示api头部,渲染导出的Api2的表格api格式 50 | // 展示api头部,渲染导出的Api的表格api格式 51 | ``` 52 | 53 | 最终效果: 54 | 55 | | 属性 | 描述 | 类型 | 默认值 | 56 | | ------ | ---------------------- | ------ | ------ | 57 | | props1 | 这是 props1 简写的描述 | string | - | 58 | 59 | ## api 60 | 61 | | 属性 | 描述 | 类型 | 默认值 | 62 | | ------ | ---------------------- | ------ | -------------- | 63 | | props1 | 这是 props1 简写的描述 | string | 支持定义默认值 | 64 | 65 | ## 资产元数据 66 | 67 | 该功能提供一套可视化的组件区块拖拽后代码生成功能,但是目前仅兼容了 umi3,没适配其他脚手架依赖,接入可能需要很大的成本,暂不考虑接入。 68 | 69 | 70 | 71 | 关于[构建资产](https://d.umijs.org/zh-CN/guide/advanced#ui-%E8%B5%84%E4%BA%A7%E6%95%B0%E6%8D%AE%E5%8C%96),可以看这里的文档,如何对接 umi3 项目 72 | -------------------------------------------------------------------------------- /docs/demos/valueType.tsx: -------------------------------------------------------------------------------- 1 | export default () => { 2 | return

ValueType.tsx

; 3 | }; 4 | -------------------------------------------------------------------------------- /docs/guide/deploy.md: -------------------------------------------------------------------------------- 1 | --- 2 | nav: 3 | title: 指南 4 | order: -1 5 | title: 部署 6 | order: 6 7 | group: 8 | path: / 9 | --- 10 | 11 | ## 部署 12 | 13 | ### 路由规则 14 | 15 | 为了很好的区分应用和对应的路由,我们建议所有子应用使用 hash 路由开发,这样就能统一路由风格,增加路由的可读性,且能减少很多不必要的 nginx 配置 😊 16 | 17 | 地址拆分解析: 18 | 19 | `http://xxx.xxx.xxx.xx:8088/dash/#/list?type=dashboard` 20 | 21 | - `http://xxx.xxx.xxx.xx:8088` - 主机地址 22 | - `/dash` - 路由的 history 用来区分子应用 23 | - `/#/list` - hash 路由参数为子应用自己的路由 24 | - `?type=dashboard` - 传参 25 | 26 | ### 全量更新 27 | 28 | 进入[部署地址](http://10.28.184.220:8888/job/yourname/)后点击`Build Now` 即可, 包含:仪表板,主应用,画布,文档, 数据模型... 29 | 30 | ### 构建环境文件结构 31 | 32 | ```bash 33 | - main/ * 主应用入口 34 | - visual/ * 画布入口 35 | - dash/ * 仪表板 36 | - build-docs/ * 文档 37 | - dataModel/ * 数据模型 38 | 39 | ``` 40 | 41 | ### 增量更新 42 | 43 | 为了优化构建速度,我们建议在构建时尽可能的对指定的模块更新即可,这样原本几十分钟的全量构建过程仅仅只要几分钟就好了。 44 | 45 | - 进入[仪表板增量更新](http://10.28.184.220:8888/job/vis-dash/)后点击`Build Now`即可 46 | - 进入[文档增量更新](http://10.28.184.220:8888/job/vis-docs/)后点击`Build Now`即可 47 | - 进入[画布增量更新](http://10.28.184.220:8888/job/vis-visual/)后点击`Build Now`即可 48 | - 进入[主应用增量更新](http://10.28.184.220:8888/job/vis-main/)后点击`Build Now`即可 49 | - 进入[数据模型增量更新](http://10.28.184.220:8888/job/vis-dataModel/)后点击`Build Now`即可 50 | 51 | ### 访问地址: 52 | 53 | - [主应用](http://xxx.xxx.xxx.xx:8088/#/) 54 | - [仪表板](http://xxx.xxx.xxx.xx:8088/dash/#/list) 55 | - [文档](http://xxx.xxx.xxx.xx:8088/docs/#/) 56 | - [画布](http://xxx.xxx.xxx.xx:8088/visual#/) 57 | - [数据模型](http://xxx.xxx.xxx.xx:8088/dataModel#/) 58 | -------------------------------------------------------------------------------- /docs/guide/publish.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: commit & 发布 3 | order: 5 4 | group: 5 | path: / 6 | --- 7 | 8 | ## 提交代码 9 | 10 | ### commit 规范 11 | 12 | 为了帮助我们更好的生成 changelog,我们希望你严格按照目前统一的[commit 规范](https://www.conventionalcommits.org/zh-hans/v1.0.0/)来规范化你的提交,这更有利于编写自动化工具。 通过在提交信息中描述功能、修复和破坏性变更,使其他部门或者人员更好的知道我们对于当前版本都做了什么。 13 | 14 | ### 开发人员 15 | 16 | 当我们单独修改某一个包后, 当你觉得此次的修改需要记录在发布日志的 change-log 时,这时候需要用我们提供的工具去按照规范提交对应代码并生成 patch 文件后提交即可, 仅将你的修改提交到暂存区,切记不要先 commit,然后执行`npm run commit`,这时候会提示你做相应的自动化界面,你只需要根据他的提示一步一步操作即可,后续统一发版的时候就会生成你之前的记录。 17 | 18 | ## 发布 19 | 20 | ### 统一发包 21 | 22 | 当我们需要统一发包的时候,该操作比较适合当前整体应用的管理者来操作,管理者需要对整体项目有一个大概,直接运行`npm run release`即可。 23 | 24 | 发包流程如下: 25 | 26 | ```jsx 27 | import { SmileOutlined } from '@ant-design/icons'; 28 | import { Timeline } from 'antd'; 29 | import React from 'react'; 30 | export default () => { 31 | const arr = [ 32 | '打包构建', 33 | '跑测试用例', 34 | '选择发包(多个)', 35 | '选择升级的主版本包', 36 | '自动升级其他相关有依赖的包(升级版本)', 37 | '打版本tag', 38 | '生成日志change-log', 39 | '写入到dumi文档', 40 | '发布npm', 41 | ]; 42 | return ( 43 | 44 | {arr.map((i) => ( 45 | {i} 46 | ))} 47 | 48 | ); 49 | }; 50 | ``` 51 | 52 | 所以在我们确认完开发内容,提交 PR 之前,执行 `npm run release`, 这是自动化工具会将上述流程自动跑完,我们要做的就是在执行过程中输入相关内容来表示此次更新的意图(版本大小,改动情况)这些都是为了使项目后期看起来更具有历史性和意义。 53 | 54 | ### 操作流程 55 | 56 | 以上构建流程中,选择发包 => 选择升级的主版本包 => 自动升级其他相关有依赖的包 需要我们手动干预,需要做如下操作: 57 | 58 | - 选择自己修改的包。 59 | 60 | ``` 61 | 🦋 Which packages would you like to include? 空格选择 62 | ``` 63 | 64 | - 选择是不是大版本修改 65 | 如果不确定,以下两个问题都不选,直接回车。 66 | 67 | ``` 68 | 🦋 Which packages should have a major bump? · No items were selected 69 | 🦋 Which packages should have a minor bump? · No items were selected 70 | ``` 71 | 72 | - 输入修改内容说明 73 | 命令行写起来麻烦,可以随便写一下。在下一步里面详细写明。 74 | 75 | ``` 76 | 🦋 Please enter a summary for this change (this will be in the changelogs). Submit empty line to open external editor 77 | 🦋 Summary : ... 78 | ``` 79 | 80 | - 如果已在命令行中写明 changelog,这一步可以跳过 81 | 82 | 执行完前三步,会在 `.changeset` 目录下面,随机生成一个文件。双击打开编辑里面的 changelog 就可以。 83 | 84 | - 将生成的文件,与本次的所有修改,提交到云端即可。再发版本的时候,这些文件会被自动消耗。 85 | 86 | 建议: `所有核心的功能和组件相关都写几个测试用例,这样能防止发包后主应用出现一些非常低级的问题,也能快速定位到对应的问题去解决它` 87 | 88 | ### 手动发布 89 | 90 | 当修改完对应的包内容和版本后,直接运行命令行`npm run release:only`, changeset 会自动检查你的包版本是否已发布,没有发布自动帮你发布。(适合版本统一管理的项目, 目前 umi 的做法也是如此,所有的子包版本都跟随主应用走,不用繁琐的记录某个包具体的版本,直接统一,坏处是新版刚发布版本就已经是很高的版本的,无法知道版本更新迭代的时间顺序) 91 | 92 | ## 错误和警告 93 | -------------------------------------------------------------------------------- /docs/guide/test.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 自动化测试 3 | order: 4 4 | group: 5 | path: / 6 | --- 7 | 8 | ## 测试 9 | 10 | ### 简述 11 | 12 | 基于 monorepo 架构下,我们能很好的统一跑测试用例,生成测试覆盖率文件等,因为相对于 jest,他们仅仅都是在同一个项目中,所以我们推荐,当你写完一个组件和某些核心功能时,都可以去 tests 文件夹适当的添加一些测试用例,防止以后有其他人不小心修改了相关代码或者增加新功能时,无法适配旧的代码功能等异常情况能够提前检查到并快速定位到对应的问题进行调整修改。 13 | 14 | 我们基于[react-testing-library](https://testing-library.com/docs/react-testing-library/intro)来测试我们的组件。基于 DOM Testing Library 的基础上添加一些 API,主要用于测试 React 组件。如果是其它的技术栈,可以选择对应的 Testing Library 库。该库在使用过程并不关注组件的内部实现,而是更关注测试。该库基于 react-dom 和 react-dom/test-utils,是以上两者的轻量实现。 15 | 16 | ## 功能测试 17 | 18 | ### api 19 | 20 | 更多详情看这里[api](https://testing-library.com/docs/react-testing-library/api) 21 | 22 | ### dom 相关 23 | 24 | ```ts 25 | import { render } from '@testing-library/react'; 26 | import { WordCloud } from '@vis/charts' 27 | const html = render(WordCloud) 28 | //render 的结果, 与浏览器domApi一致 29 | { 30 | ...queries, //选择器,例如(get/query/find)By(Text/Label/...) 31 | container: HTMLDivElement,//自动创建一个div,并插入到body中 32 | baseElement: HTMLBodyElement, //相当于document.body 33 | debug: Function, //打印当前document.body 34 | rerender: Function, //重新渲染组件 35 | unmount: Function, //组件卸载,此时container.innerHTML === '' 36 | asFragment:Function //记录某个时刻的dom 37 | } 38 | ``` 39 | 40 | ### hooks 41 | 42 | ```ts 43 | import { renderHook } from '@testing-library/react'; 44 | 45 | const { result } = renderHook(() => { 46 | const [name, setName] = useState(''); 47 | React.useEffect(() => { 48 | setName('Alice'); 49 | }, []); 50 | 51 | return name; 52 | }); 53 | expect(result.current).toBe('Alice'); 54 | ``` 55 | 56 | ### 事件 57 | 58 | ```ts 59 | import React, { useState } from 'react'; 60 | import { render, fireEvent } from '@testing-library/react'; 61 | 62 | const TestComponent = () => { 63 | const [count, setCounter] = useState(0); 64 | 65 | return ( 66 | 69 | ); 70 | }; 71 | 72 | const { getByText, asFragment } = render(); 73 | const firstRender = asFragment(); 74 | 75 | fireEvent.click(getByText(/Click to increase/)); 76 | 77 | // This will snapshot only the difference between the first render, and the 78 | // state of the DOM after the click event. 79 | // See https://github.com/jest-community/snapshot-diff 80 | expect(firstRender).toMatchDiffSnapshot(asFragment()); // 对比Dom快照,可以简单理解为dom字符串 81 | ``` 82 | -------------------------------------------------------------------------------- /docs/playground/curd.playground.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CRUD 3 | nav: 4 | title: Playground 5 | path: /playground 6 | group: 7 | path: / 8 | --- 9 | 10 | # CRUD 11 | ```tsx 12 | import React from 'react' 13 | export default () => { 14 | return
123
15 | } 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | const getPackages = require('./scripts/utils/getPackages'); 3 | 4 | const pkgList = getPackages(); 5 | 6 | const moduleNameMapper = { 7 | '\\.(css|less|sass|scss)$': require.resolve('identity-obj-proxy'), 8 | }; 9 | 10 | pkgList.forEach((shortName) => { 11 | const name = `@vis/${shortName}`; 12 | moduleNameMapper[name] = join(__dirname, `./packages/${shortName}/src`); 13 | }); 14 | 15 | module.exports = { 16 | collectCoverageFrom: [ 17 | 'packages/**/src/**/*.{ts,tsx}', 18 | ], 19 | testEnvironment: 'jsdom', 20 | moduleNameMapper, 21 | transform: { 22 | '\\.(t|j)sx?$': require.resolve('./tests/jsTransformer'), 23 | }, 24 | unmockedModulePathPatterns: ['node_modules/react/'], 25 | testURL: 'http://localhost', 26 | verbose: true, 27 | setupFiles: ['./tests/setupTests.js'], 28 | globals: { 29 | VIS_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: false, 30 | }, 31 | testPathIgnorePatterns: ["/node_modules/", '/packages/', '/src/'] 32 | }; 33 | -------------------------------------------------------------------------------- /mock/index.ts: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /packages/charts/.fatherrc.ts: -------------------------------------------------------------------------------- 1 | 2 | const type = process.env.BUILD_TYPE; 3 | 4 | let config = {}; 5 | 6 | if (type === 'lib') { 7 | config = { 8 | cjs: { type: 'babel', lazy: true }, 9 | esm: false, 10 | runtimeHelpers: true, 11 | extraBabelPlugins: [ 12 | [ 13 | 'babel-plugin-import', 14 | { libraryName: 'antd', libraryDirectory: 'lib', style: true }, 15 | 'antd', 16 | ], 17 | ], 18 | }; 19 | } 20 | 21 | if (type === 'es') { 22 | config = { 23 | cjs: false, 24 | esm: { 25 | type: 'babel', 26 | }, 27 | runtimeHelpers: true, 28 | extraBabelPlugins: [ 29 | [require('./../../scripts/replaceLib')], 30 | ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'antd'], 31 | ], 32 | }; 33 | } 34 | 35 | export default config; 36 | -------------------------------------------------------------------------------- /packages/charts/README.md: -------------------------------------------------------------------------------- 1 | # @vis/charts 2 | 3 | > @vis/charts. 4 | 5 | See our website [@vis/charts](https://umijs.org/plugins/charts) for more information. 6 | 7 | ## Install 8 | 9 | Using npm: 10 | 11 | ```bash 12 | $ npm install --save @vis/charts --registry http://xxx.xxx.xxx.xxx:xxxx/ 13 | ``` 14 | 15 | or using yarn: 16 | 17 | ```bash 18 | $ yarn add @vis/charts --registry http://xxx.xxx.xxx.xxx:xxxx/ 19 | ``` 20 | -------------------------------------------------------------------------------- /packages/charts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis/charts", 3 | "version": "0.0.0", 4 | "description": "@vis/charts", 5 | "keywords": [ 6 | "antd", 7 | "admin", 8 | "ant-design", 9 | "ant-design-pro" 10 | ], 11 | "homepage": "http://xxx.xxx.xxx.xxx:xxxx/-/web/detail/@vis/components", 12 | "repository": { 13 | "type": "git", 14 | "url": "http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/" 15 | }, 16 | "license": "MIT", 17 | "main": "dist/index.js", 18 | "module": "es/index.js", 19 | "types": "es/index.d.ts", 20 | "files": [ 21 | "lib", 22 | "src", 23 | "dist", 24 | "es" 25 | ], 26 | "scripts": { 27 | "build": "cross-env BUILD_TYPE=es father-build" 28 | }, 29 | "browserslist": [ 30 | "last 2 versions", 31 | "Firefox ESR", 32 | "> 1%", 33 | "ie >= 11" 34 | ], 35 | "dependencies": { 36 | "@ant-design/plots": "^1.0.9", 37 | "@babel/runtime": "^7.16.3", 38 | "@vis/utils": "workspace:^*" 39 | }, 40 | "peerDependencies": { 41 | "react": ">=16.9.0", 42 | "react-dom": ">=16.9.0" 43 | }, 44 | "publishConfig": { 45 | "access": "public", 46 | "registry": "http://xxx.xxx.xxx.xxx:xxxx/" 47 | }, 48 | "authors": [ 49 | "chenjie " 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /packages/charts/src/BasicColumn/README.md: -------------------------------------------------------------------------------- 1 | ## 基础柱状图 2 | 3 | ```jsx 4 | import React from 'react'; 5 | import { BasicColumn } from '@vis/charts'; 6 | export default () => { 7 | const data = [ 8 | { 9 | name: '类型一', 10 | value: 23, 11 | }, 12 | { 13 | name: '类型二', 14 | value: 31, 15 | }, 16 | { 17 | name: '类型三', 18 | value: 15, 19 | }, 20 | { 21 | name: '类型四', 22 | value: 62, 23 | }, 24 | ]; 25 | const config = { 26 | xField: 'name', 27 | yField: 'value', 28 | meta: { 29 | name: { 30 | alias: '类别', 31 | }, 32 | value: { 33 | alias: '数量', 34 | }, 35 | }, 36 | }; 37 | return ; 38 | }; 39 | ``` 40 | 41 | 42 | 43 | ## 默认配置 44 | 45 | ```ts 46 | defaultConfig = { 47 | data: renderData, 48 | xField: 'type', 49 | yField: 'sales', 50 | label: { 51 | // 可手动配置 label 数据标签位置 52 | position: 'middle', 53 | // 'top', 'bottom', 'middle', 54 | // 配置样式 55 | style: { 56 | fill: '#FFFFFF', 57 | opacity: 0.6, 58 | }, 59 | }, 60 | xAxis: { 61 | label: { 62 | autoHide: true, 63 | autoRotate: false, 64 | }, 65 | }, 66 | meta: { 67 | type: { 68 | alias: '类别', 69 | }, 70 | sales: { 71 | alias: '销售额', 72 | }, 73 | }, 74 | }; 75 | ``` 76 | -------------------------------------------------------------------------------- /packages/charts/src/BasicColumn/index.less: -------------------------------------------------------------------------------- 1 | .basic-column { 2 | color: #e3e3e3; 3 | } -------------------------------------------------------------------------------- /packages/charts/src/BasicColumn/index.tsx: -------------------------------------------------------------------------------- 1 | import { Column, ColumnConfig as _ColumnConfig } from '@ant-design/plots'; 2 | import React from 'react'; 3 | import './index.less'; 4 | 5 | interface BasicColumnProps { 6 | config?: _ColumnConfig; 7 | data?: Array<{ type: string; sales: number }>; 8 | } 9 | 10 | export const ColumnConfig: React.FC<_ColumnConfig> = ({}) => <>; 11 | 12 | export default (props: BasicColumnProps) => { 13 | const { config, data } = props; 14 | 15 | const tempData = [ 16 | { 17 | type: '家具家电', 18 | sales: 38, 19 | }, 20 | { 21 | type: '粮油副食', 22 | sales: 52, 23 | }, 24 | { 25 | type: '生鲜水果', 26 | sales: 61, 27 | }, 28 | { 29 | type: '美容洗护', 30 | sales: 145, 31 | }, 32 | { 33 | type: '母婴用品', 34 | sales: 48, 35 | }, 36 | { 37 | type: '进口食品', 38 | sales: 38, 39 | }, 40 | { 41 | type: '食品饮料', 42 | sales: 38, 43 | }, 44 | { 45 | type: '家庭清洁', 46 | sales: 38, 47 | }, 48 | ]; 49 | 50 | const renderData = data || tempData; 51 | 52 | const renderConfig: _ColumnConfig = { 53 | data: renderData, 54 | xField: 'type', 55 | yField: 'sales', 56 | label: { 57 | // 可手动配置 label 数据标签位置 58 | position: 'middle', 59 | // 'top', 'bottom', 'middle', 60 | // 配置样式 61 | style: { 62 | fill: '#FFFFFF', 63 | opacity: 0.6, 64 | }, 65 | }, 66 | xAxis: { 67 | label: { 68 | autoHide: true, 69 | autoRotate: false, 70 | }, 71 | }, 72 | meta: { 73 | type: { 74 | alias: '类别', 75 | }, 76 | sales: { 77 | alias: '销售额', 78 | }, 79 | }, 80 | ...config, 81 | }; 82 | return ; 83 | }; 84 | -------------------------------------------------------------------------------- /packages/charts/src/BasicLine/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: BasicLine 基础折线图 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | ## 基础折线图 11 | 12 | ```jsx 13 | import React from 'react'; 14 | import { BasicLine } from '@vis/charts'; 15 | export default () => { 16 | const data = [ 17 | { 18 | type: '家具家电', 19 | sales: 38, 20 | }, 21 | { 22 | type: '粮油副食', 23 | sales: 52, 24 | }, 25 | { 26 | type: '生鲜水果', 27 | sales: 61, 28 | }, 29 | { 30 | type: '家具家电1', 31 | sales: 145, 32 | }, 33 | { 34 | type: '粮油副食1', 35 | sales: 61, 36 | }, 37 | { 38 | type: '生鲜水果1', 39 | sales: 145, 40 | }, 41 | ]; 42 | const config = { 43 | xField: 'type', 44 | yField: 'sales', 45 | seriesField: 'series', 46 | colorField: 'type', 47 | }; 48 | return ; 49 | }; 50 | ``` 51 | 52 | 53 | 54 | ## 默认配置 55 | 56 | ```ts 57 | defaultConfig = { 58 | autoFit: true, 59 | padding: 'auto', 60 | renderer: 'canvas', 61 | limitInPlot: false, 62 | data: renderData, 63 | xField: 'name', 64 | yField: 'value', 65 | xAxis: { 66 | tickCount: 5, 67 | }, 68 | smooth: true, 69 | connectNulls: true, 70 | isStack: false, 71 | }; 72 | ``` 73 | -------------------------------------------------------------------------------- /packages/charts/src/BasicLine/index.less: -------------------------------------------------------------------------------- 1 | .basic-line { 2 | color: #e3e3e3; 3 | } -------------------------------------------------------------------------------- /packages/charts/src/BasicLine/index.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import { Line, LineConfig as _LineConfig } from '@ant-design/plots'; 3 | import React from 'react'; 4 | interface BasicLineProps { 5 | config?: _LineConfig; 6 | data?: Array<{ name: string; value: number }>; 7 | } 8 | export const LineConfig: React.FC<_LineConfig> = () => <>; 9 | 10 | export default (props: BasicLineProps) => { 11 | const { config, data } = props; 12 | const tempData = [ 13 | { 14 | name: '分类一', 15 | value: 27, 16 | category: '1', 17 | }, 18 | { 19 | name: '分类二', 20 | value: 25, 21 | category: '1', 22 | }, 23 | { 24 | name: '分类三', 25 | value: 18, 26 | category: '1', 27 | }, 28 | { 29 | name: '分类一', 30 | value: 15, 31 | category: '2', 32 | }, 33 | { 34 | name: '分类二', 35 | value: 10, 36 | category: '2', 37 | }, 38 | { 39 | name: '分类三', 40 | value: 5, 41 | category: '2', 42 | }, 43 | ]; 44 | 45 | const renderData = data || tempData; 46 | 47 | const renderConfig: _LineConfig = { 48 | // 图表容器 49 | autoFit: true, 50 | padding: 'auto', 51 | renderer: 'canvas', 52 | limitInPlot: false, 53 | // 数据映射 54 | data: renderData, 55 | xField: 'name', 56 | yField: 'value', 57 | xAxis: { 58 | tickCount: 5, 59 | }, 60 | // 图形样式 61 | smooth: true, 62 | connectNulls: true, 63 | isStack: false, 64 | color: 'pink', 65 | seriesField: 'category', 66 | lineStyle: { 67 | // style: { 68 | // fill: 'red', 69 | // fillOpacity: 0.5, 70 | // stroke: 'black', 71 | // lineWidth: 1, 72 | // lineDash: [4, 5], 73 | // strokeOpacity: 0.7, 74 | // shadowColor: 'black', 75 | // shadowBlur: 10, 76 | // shadowOffsetX: 5, 77 | // shadowOffsetY: 5, 78 | // cursor: 'pointer' 79 | // } 80 | }, 81 | ...config, 82 | }; 83 | 84 | // 折线图单系列、多系列时颜色配置处理 85 | renderConfig.color = 86 | renderData[0][renderConfig.seriesField] !== undefined && 87 | renderConfig.seriesField !== undefined 88 | ? ['red', 'yellow'] 89 | : 'blue'; 90 | renderConfig.seriesField && 91 | !renderData[0][renderConfig.seriesField] && 92 | delete renderConfig.seriesField; 93 | 94 | return ; 95 | }; 96 | -------------------------------------------------------------------------------- /packages/charts/src/BasicPie/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: BasicPie 基础饼图 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | ## 基础饼图 11 | 12 | ```jsx 13 | import React from 'react'; 14 | import { BasicPie } from '@vis/charts'; 15 | export default () => { 16 | const pieData = [ 17 | { 18 | name: 'www', 19 | value: 20, 20 | }, 21 | { 22 | name: 'eee', 23 | value: 30, 24 | }, 25 | ]; 26 | const config = { 27 | angleField: 'value', 28 | colorField: 'name', 29 | }; 30 | 31 | return ; 32 | }; 33 | ``` 34 | 35 | 36 | 37 | ## 默认配置 38 | 39 | ```ts 40 | defaultConfig = { 41 | color: ['#4f8cbf', '#2ecc71', '#0065ba', '#FF0000', '#FFFF00 ', '#FF00FF '], 42 | appendPadding: 10, 43 | angleField: 'value', 44 | colorField: 'type', 45 | radius: 0.8, 46 | label: { 47 | type: 'outer', 48 | content: '{name} {percentage}', 49 | }, 50 | interactions: [ 51 | { 52 | type: 'pie-legend-active', 53 | }, 54 | { 55 | type: 'element-active', 56 | }, 57 | ], 58 | }; 59 | ``` 60 | -------------------------------------------------------------------------------- /packages/charts/src/BasicPie/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Pie, PieConfig as _PieConfig } from '@ant-design/plots'; 3 | 4 | interface BasicPieConfig { 5 | config?: _PieConfig, 6 | data?: Array<{name: string, value: number}> 7 | } 8 | 9 | export const PieConfig: React.FC<_PieConfig> = () => <>; 10 | 11 | export default (props: BasicPieConfig) => { 12 | const { config, data } = props 13 | const tempData = [ 14 | { 15 | type: '分类一', 16 | value: 27, 17 | }, 18 | { 19 | type: '分类二', 20 | value: 25, 21 | }, 22 | { 23 | type: '分类三', 24 | value: 18, 25 | }, 26 | { 27 | type: '分类四', 28 | value: 15, 29 | }, 30 | { 31 | type: '分类五', 32 | value: 10, 33 | }, 34 | { 35 | type: '其他', 36 | value: 5, 37 | }, 38 | ]; 39 | const renderData = data || tempData 40 | const renderConfig: _PieConfig = { 41 | color: ["#4f8cbf", "#2ecc71", "#0065ba", "#FF0000", "#FFFF00 ", "#FF00FF "], 42 | appendPadding: 10, 43 | data: renderData, 44 | angleField: 'value', 45 | colorField: 'type', 46 | radius: 0.8, 47 | label: { 48 | type: 'outer', 49 | content: '{name} {percentage}', 50 | }, 51 | interactions: [ 52 | { 53 | type: 'pie-legend-active', 54 | }, 55 | { 56 | type: 'element-active', 57 | }, 58 | ], 59 | ...config 60 | }; 61 | return ; 62 | } -------------------------------------------------------------------------------- /packages/charts/src/Describe/README.md: -------------------------------------------------------------------------------- 1 | ## describe 2 | 3 | ```tsx 4 | import React from 'react'; 5 | import { Describe } from '@vis/charts'; 6 | export default () => { 7 | return ; 8 | }; 9 | ``` 10 | -------------------------------------------------------------------------------- /packages/charts/src/ProgressLine/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ProgressLine-条形进度条 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | ## 条形进度条 11 | 12 | ```tsx 13 | import React from 'react'; 14 | import { ProgressLine } from '@vis/charts'; 15 | export default () => { 16 | return ; 17 | }; 18 | ``` 19 | -------------------------------------------------------------------------------- /packages/charts/src/ProgressLine/index.less: -------------------------------------------------------------------------------- 1 | @vis-progressLine-prefix-cls: ~'vis-progress-line-'; 2 | 3 | .@{vis-progressLine-prefix-cls}progress-box { 4 | width: 100%; 5 | padding-left: 0px; 6 | position: relative; 7 | list-style: none; 8 | .@{vis-progressLine-prefix-cls}progress { 9 | text-align: left; 10 | margin-top: 5px; 11 | } 12 | .@{vis-progressLine-prefix-cls}line { 13 | display: flex; 14 | justify-content: space-between; 15 | align-items: flex-end; 16 | } 17 | .@{vis-progressLine-prefix-cls}number { 18 | display: inline-block; 19 | } 20 | .@{vis-progressLine-prefix-cls}img-province { 21 | width: 40px; 22 | height: 28px; 23 | // background: url("/images/smartPortal/progress/local-bg.png"); 24 | font-size: 13px; 25 | line-height: 30px; 26 | color: #ffffff; 27 | padding-left: 8px; 28 | margin-right: 11px; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/charts/src/WordCloud/Setting.tsx: -------------------------------------------------------------------------------- 1 | export default () => { 2 | return
Setting
; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/charts/src/WordCloud/api.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { Options } from './word-cloud'; 3 | const Api: React.FC = () => <>; 4 | export default Api; 5 | export const Tooltip : React.FC = () => <>; 6 | -------------------------------------------------------------------------------- /packages/charts/src/WordCloud/index.less: -------------------------------------------------------------------------------- 1 | @vis-worldCloud-prefix-cls: ~'vis-word-cloud'; 2 | 3 | .@{vis-worldCloud-prefix-cls} { 4 | height: 100%; 5 | // font-size: @font-size-base; 6 | position: relative; 7 | } 8 | -------------------------------------------------------------------------------- /packages/charts/src/WordCloud/index.tsx: -------------------------------------------------------------------------------- 1 | import type { LegacyRef } from 'react'; 2 | import { useLayoutEffect, useRef } from 'react'; 3 | import './index.less'; 4 | import type { Options } from './word-cloud'; 5 | import { COLOR_MODE, init, RENDER_MODE, TEXT_ORIENTATION } from './word-cloud.js'; 6 | const prefix = 'vis-word-cloud'; 7 | 8 | function WordCloud({ config, data }: { 9 | /** 渲染的所有配置,参考高级配置 */ 10 | config: Options['config']; 11 | /** 渲染源数据 */ 12 | data: Array<{ name: string; value: number }> }) { 13 | const elRef = useRef(); 14 | useLayoutEffect(() => { 15 | init({ 16 | el: elRef.current as HTMLElement, 17 | data, 18 | config, 19 | }); 20 | }, [config]); 21 | return
| undefined} className={prefix} />; 22 | } 23 | 24 | WordCloud.RENDER_MODE = RENDER_MODE; 25 | WordCloud.TEXT_ORIENTATION = TEXT_ORIENTATION; 26 | WordCloud.COLOR_MODE = COLOR_MODE; 27 | export default WordCloud; 28 | -------------------------------------------------------------------------------- /packages/charts/src/charts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: charts-图表总览 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | # 总览 11 | 12 | ## Install 13 | 14 | Using npm: 15 | 16 | ```bash 17 | $ npm install --save @vis/charts --registry http://xxx.xxx.xxx.xxx:xxxx/ 18 | ``` 19 | 20 | or using yarn: 21 | 22 | ```bash 23 | $ yarn add @vis/charts --registry http://xxx.xxx.xxx.xxx:xxxx/ 24 | ``` 25 | 26 | ## 词云图 27 | 28 | 大致与官方开源的一致,增加了滚动模式,超出可视化区域不会忽略词条 [详情](/components/word-cloud) 29 | 30 | ```jsx 31 | import React from 'react'; 32 | // import { WordCloud } from '@vis/components' 33 | import { WordCloud } from '@vis/charts'; 34 | 35 | const temp = []; 36 | const words = [ 37 | '这根本就不好玩', 38 | '再见', 39 | 'MDML在线测试', 40 | '深入浅出CSS3', 41 | 'React测试', 42 | '这就是个文字内容', 43 | '高刷屏', 44 | '默认触发间隔', 45 | '假如我说假如', 46 | '发现越来越多的美好', 47 | '小惊喜', 48 | '不会只有我', 49 | '哦次打次', 50 | '客气客气', 51 | ]; 52 | for (let index = 0; index < words.length; index++) { 53 | const item = words[index]; 54 | temp.push({ 55 | value: Math.floor(Math.random() * 1000), 56 | name: item || `test-${index}`, 57 | }); 58 | } 59 | export default () => { 60 | const { RENDER_MODE, TEXT_ORIENTATION } = WordCloud; 61 | const config = { 62 | mode: RENDER_MODE.SCROLL, 63 | animate: true, 64 | }; 65 | return ( 66 |
67 |
68 | 69 |
70 |
71 | 72 |
73 |
74 | ); 75 | }; 76 | ``` 77 | 78 | ## 条形进度条 79 | -------------------------------------------------------------------------------- /packages/charts/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ProgressLine, { 2 | progressLineDefaultConfig, 3 | progressLineDefaultData, 4 | } from './ProgressLine'; 5 | import WordCloud from './WordCloud'; 6 | import BasicLine from './BasicLine'; 7 | import BasicColumn from './BasicColumn/index'; 8 | import BasicRingPie from './BasicRingPie/index'; 9 | import BasicPie from './BasicPie/index'; 10 | import Describe, { describeDefaultConfig, describeDefaultData } from './Describe'; 11 | export { 12 | ProgressLine, 13 | WordCloud, 14 | BasicLine, 15 | BasicColumn, 16 | BasicRingPie, 17 | BasicPie, 18 | progressLineDefaultConfig, 19 | progressLineDefaultData, 20 | Describe, 21 | describeDefaultConfig, 22 | describeDefaultData 23 | }; 24 | -------------------------------------------------------------------------------- /packages/charts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "esnext", 5 | "lib": ["dom", "esnext"], 6 | "skipLibCheck": true, 7 | "importHelpers": true, 8 | "declaration": true, 9 | "sourceMap": true, 10 | "rootDir": "./", 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "baseUrl": "./", 24 | "paths": { 25 | "*": ["src/*", "node_modules/*"] 26 | }, 27 | "jsx": "react-jsx", 28 | "esModuleInterop": true 29 | }, 30 | "include": [ 31 | "src", 32 | ], 33 | "exclude": [ 34 | "node_modules", 35 | "public", 36 | "lib" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /packages/common/.fatherrc.ts: -------------------------------------------------------------------------------- 1 | 2 | const type = process.env.BUILD_TYPE; 3 | 4 | let config = {}; 5 | 6 | if (type === 'lib') { 7 | config = { 8 | cjs: { type: 'babel', lazy: true }, 9 | esm: false, 10 | runtimeHelpers: true, 11 | extraBabelPlugins: [ 12 | [ 13 | 'babel-plugin-import', 14 | { libraryName: 'antd', libraryDirectory: 'lib', style: true }, 15 | 'antd', 16 | ], 17 | ], 18 | }; 19 | } 20 | 21 | if (type === 'es') { 22 | config = { 23 | 24 | cjs: false, 25 | esm: { 26 | type: 'babel', 27 | }, 28 | runtimeHelpers: true, 29 | extraBabelPlugins: [ 30 | [require('./../../scripts/replaceLib')], 31 | ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'antd'], 32 | ], 33 | }; 34 | } 35 | 36 | export default config; 37 | -------------------------------------------------------------------------------- /packages/common/README.md: -------------------------------------------------------------------------------- 1 | # @vis/components 2 | 3 | > @vis/components. 4 | 5 | See our website [@vis/components](https://umijs.org/plugins/components) for more information. 6 | 7 | ## Install 8 | 9 | Using npm: 10 | 11 | ```bash 12 | $ npm install --save @vis/components 13 | ``` 14 | 15 | or using yarn: 16 | 17 | ```bash 18 | $ yarn add @vis/components 19 | ``` 20 | -------------------------------------------------------------------------------- /packages/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis/common", 3 | "version": "0.0.0", 4 | "description": "@vis/common", 5 | "keywords": [ 6 | "antd", 7 | "admin", 8 | "ant-design", 9 | "ant-design-pro", 10 | "ant-design/pro-components" 11 | ], 12 | "homepage": "http://xxx.xxx.xxx.xxx:xxxx/-/web/detail/vis", 13 | "bugs": "http://github.com/umijs/plugins/issues", 14 | "repository": { 15 | "type": "git", 16 | "url": "http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/" 17 | }, 18 | "scripts": { 19 | "build": "cross-env BUILD_TYPE=es father-build" 20 | }, 21 | "license": "MIT", 22 | "main": "dist/index.js", 23 | "module": "es/index.js", 24 | "types": "es/index.d.ts", 25 | "files": [ 26 | "lib", 27 | "src", 28 | "dist", 29 | "es" 30 | ], 31 | "browserslist": [ 32 | "last 2 versions", 33 | "Firefox ESR", 34 | "> 1%", 35 | "ie >= 11" 36 | ], 37 | "dependencies": { 38 | "@babel/runtime": "^7.16.3", 39 | "@vis/utils": "workspace:*" 40 | }, 41 | "peerDependencies": { 42 | "react": ">=16.9.0", 43 | "react-dom": ">=16.9.0" 44 | }, 45 | "publishConfig": { 46 | "access": "public", 47 | "registry": "http://xxx.xxx.xxx.xxx:xxxx/" 48 | }, 49 | "authors": [ 50 | "chenjie " 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /packages/common/src/Unit/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Unit-单位组件 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | ## 单位转换 11 | 12 | ```tsx 13 | import React from 'react'; 14 | import { Unit } from '@vis/common'; 15 | export default () => { 16 | return ; 17 | }; 18 | ``` 19 | -------------------------------------------------------------------------------- /packages/common/src/Unit/index.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import { isNumber, numberFormat, unitConvert } from '@vis/utils'; 3 | import { CSSProperties } from 'react'; 4 | 5 | declare interface UnitType { 6 | data: number | string; 7 | show?: boolean; 8 | numberConversion?: boolean; 9 | useGrouping?: boolean; 10 | pointLength?: number; 11 | numStyle?: CSSProperties; 12 | unitStyle?: CSSProperties; 13 | } 14 | 15 | function Unit({ 16 | data, 17 | show, 18 | numberConversion, 19 | pointLength, 20 | useGrouping = false, 21 | numStyle, 22 | unitStyle, 23 | }: UnitType) { 24 | let numberDom = {numberFormat(data, useGrouping)}; 25 | if (numberConversion && isNumber(data)) { 26 | const transed = unitConvert(data as number, pointLength); 27 | const num = transed?.num; 28 | const unit = transed?.unit; 29 | const formatNum = numberFormat(num, useGrouping); 30 | numberDom = ( 31 | <> 32 | {formatNum} 33 | {unit} 34 | 35 | ); 36 | } 37 | const dom =
{numberDom}
; 38 | return show ? dom : null; 39 | } 40 | 41 | export default Unit; 42 | -------------------------------------------------------------------------------- /packages/common/src/VisHeader/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: VisHeader-统一头部 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | ## VisHeader 组件描述 11 | 12 | VisHeader 大部分 API 与 WorkSpace 保持一致,很多地方他们都有一定的相似性,但又有一些差异。 13 | 14 | ## 单个 tab 15 | 16 | ```jsx 17 | import React from 'react'; 18 | import { VisHeader } from '@vis/common'; 19 | export default () => { 20 | return ( 21 | SQL View, 27 | }, 28 | ]} 29 | /> 30 | ); 31 | }; 32 | ``` 33 | 34 | ## 多个 tab 35 | 36 | ```jsx 37 | import React from 'react'; 38 | import { VisHeader } from '@vis/common'; 39 | export default () => { 40 | return ( 41 | Table View, 47 | }, 48 | { 49 | title: 'SQL视图', 50 | key: '2', 51 | content:

SQL View

, 52 | }, 53 | ]} 54 | /> 55 | ); 56 | }; 57 | ``` 58 | 59 | ## 右侧自定义渲染 60 | 61 | ```jsx 62 | import React from 'react'; 63 | import { VisHeader } from '@vis/common'; 64 | export default () => { 65 | return ( 66 | +表单,或者图标
} 68 | tabs={[ 69 | { 70 | title: '表视图', 71 | key: '1', 72 | content:

Table View

, 73 | }, 74 | { 75 | title: 'SQL视图', 76 | key: '2', 77 | content:

SQL View

, 78 | }, 79 | ]} 80 | /> 81 | ); 82 | }; 83 | ``` 84 | 85 | ## 自定义布局 86 | 87 | ```jsx 88 | import React from 'react'; 89 | import { VisHeader } from '@vis/common'; 90 | export default () => { 91 | return ( 92 | Table View, 98 | }, 99 | { 100 | title: 'SQL视图', 101 | key: '2', 102 | content:

SQL View

, 103 | }, 104 | ]} 105 | > 106 | {(item) => { 107 | return
{item.content}
; 108 | }} 109 |
110 | ); 111 | }; 112 | ``` 113 | 114 | 115 | -------------------------------------------------------------------------------- /packages/common/src/VisHeader/index.less: -------------------------------------------------------------------------------- 1 | @comp-cls: ~'vis-comp-header'; 2 | 3 | 4 | 5 | .@{comp-cls}-wrap{ 6 | display: flex; 7 | flex-direction: column; 8 | width: 100%; 9 | height: 100%; 10 | h1{ 11 | margin-bottom: 0; 12 | } 13 | .ant-tabs-top.@{comp-cls}-tabs > .ant-tabs-nav::before{ 14 | border-bottom-width: 0; 15 | } 16 | .ant-tabs-large > .ant-tabs-nav .ant-tabs-tab{ 17 | padding: 5px 0; 18 | } 19 | .@{comp-cls}-content-wrap{ 20 | flex: 1; 21 | overflow: scroll; 22 | } 23 | .@{comp-cls}-header{ 24 | background-color: white; 25 | // padding: 16px 14px 16px 24px; 26 | border-bottom: solid 1px #ecf0f6; 27 | min-height: 40px; 28 | position: relative; 29 | display: flex; 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 0 10px; 33 | &.tabs{ 34 | display: block; 35 | } 36 | 37 | .@{comp-cls}-desc{ 38 | font-size: 12px; 39 | line-height: 12px; 40 | color: #666; 41 | } 42 | .@{comp-cls}-label{ 43 | color: #333; 44 | line-height: 16px; 45 | font-weight: 700; 46 | font-size: 14px; 47 | } 48 | .@{comp-cls}-title{ 49 | .ant-tabs-top > .ant-tabs-nav{ 50 | margin-bottom: 0; 51 | } 52 | .@{comp-cls}-item{ 53 | font-weight: 700; 54 | line-height: 16px; 55 | margin-right: 23px; 56 | cursor: pointer; 57 | padding-bottom: 10px; 58 | &.cur{ 59 | border-bottom: 4px solid var(--colorPrimary); 60 | } 61 | } 62 | } 63 | .@{comp-cls}-desc{ 64 | margin-top: 10px; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/common/src/Workspace/index.less: -------------------------------------------------------------------------------- 1 | @comp-cls: ~'vis-comp-wrokspace'; 2 | 3 | 4 | 5 | .@{comp-cls}-wrap{ 6 | background-color: #ecf0f6; 7 | height: 100%; 8 | display: flex; 9 | flex-direction: column; 10 | width: 100%; 11 | overflow: auto; 12 | .ant-tabs-top.@{comp-cls}-tabs > .ant-tabs-nav::before{ 13 | border-bottom-width: 0; 14 | } 15 | h1{ 16 | margin-bottom: 0; 17 | } 18 | .ant-tabs-large > .ant-tabs-nav .ant-tabs-tab{ 19 | padding: 5px 0; 20 | } 21 | .@{comp-cls}-content-wrap{ 22 | padding: 10px; 23 | flex: 1; 24 | overflow: auto; 25 | } 26 | .@{comp-cls}-content-footer{ 27 | padding: 10px 0; 28 | text-align: center; 29 | background-color: white; 30 | } 31 | .@{comp-cls}-header{ 32 | font-size: 16px; 33 | padding: 16px 24px; 34 | background-color: white; 35 | box-shadow: 1px 1px 8px rgb(221, 220, 220); 36 | position: relative; 37 | .@{comp-cls}-form{ 38 | position: absolute; 39 | right: 20px; 40 | top: 20px; 41 | } 42 | .@{comp-cls}-desc{ 43 | font-size: 12px; 44 | line-height: 12px; 45 | color: #666; 46 | margin-top: 4px; 47 | } 48 | .@{comp-cls}-label{ 49 | color: #333; 50 | padding-left: 8px; 51 | border-left: 4px solid var(--colorPrimary); 52 | line-height: 16px; 53 | font-weight: 700; 54 | margin-bottom: 10px; 55 | } 56 | .@{comp-cls}-title{ 57 | >.ant-tabs-small > .ant-tabs-nav .ant-tabs-tab { 58 | padding: 4px 0; 59 | } 60 | .@{comp-cls}-item{ 61 | font-weight: 700; 62 | line-height: 16px; 63 | margin-right: 23px; 64 | cursor: pointer; 65 | padding-bottom: 10px; 66 | &.cur{ 67 | border-bottom: 4px solid var(--colorPrimary); 68 | } 69 | } 70 | } 71 | .@{comp-cls}-desc{ 72 | // margin-top: 10px; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /packages/common/src/common.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: common 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | # 总览 11 | 12 | ## Install 13 | 14 | Using npm: 15 | 16 | ```bash 17 | $ npm install --save @vis/common --registry http://xxx.xxx.xxx.xxx:xxxx/ 18 | ``` 19 | 20 | or using yarn: 21 | 22 | ```bash 23 | $ yarn add @vis/common --registry http://xxx.xxx.xxx.xxx:xxxx/ 24 | ``` 25 | 26 | ## 业务组件 27 | -------------------------------------------------------------------------------- /packages/common/src/index.tsx: -------------------------------------------------------------------------------- 1 | import Workspace from './Workspace'; 2 | import VisHeader from './VisHeader'; 3 | import VisCRUD from './VisCrud'; 4 | import Unit from './Unit'; 5 | 6 | export { VisCRUD, VisHeader, Workspace, Unit }; 7 | -------------------------------------------------------------------------------- /packages/common/src/interceptors/index.ts: -------------------------------------------------------------------------------- 1 | import { notification } from 'antd' 2 | 3 | declare type RequestConfig = { 4 | headers?: Record; 5 | [other: string]: any; 6 | } 7 | declare type ResponseType = { 8 | code?: 200 | 404 | 500 | 302; 9 | data?: any; 10 | message?: string; 11 | } 12 | export const handleResponseData = (response: ResponseType = {}) => { 13 | const { code, msg } = response.data 14 | if (code === 200) { 15 | return response.data; 16 | } 17 | if (code === 424) { // token过期判断 18 | history.pushState('', '', '/user/login'); 19 | return 20 | } 21 | 22 | const message = msg || '请求失败' 23 | 24 | notification.error({ 25 | message, 26 | }); 27 | 28 | throw new Error(message) 29 | }; 30 | 31 | export default { 32 | request: { 33 | onConfig: (config: RequestConfig = {}) => { 34 | // 发送请求前:可以对 RequestConfig 做一些统一处理 35 | const accessToken = localStorage.getItem('token'); 36 | if (accessToken) { 37 | config.headers = { Authorization: `Bearer ${accessToken}` } 38 | } 39 | return config; 40 | }, 41 | onError: (error: Error) => { 42 | return Promise.reject(error); 43 | }, 44 | }, 45 | response: { 46 | onConfig: (response: ResponseType) => { 47 | console.log('===response', response); 48 | // 请求成功:可以做全局的 toast 展示,或者对 response 做一些格式化 49 | return handleResponseData(response); 50 | }, 51 | onError: (error: Error) => { 52 | // 请求出错:服务端返回错误状态码 53 | console.error(error); 54 | return Promise.reject(error); 55 | }, 56 | }, 57 | }; 58 | -------------------------------------------------------------------------------- /packages/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "esnext", 5 | "skipLibCheck": true, 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | "declaration": true, 9 | "sourceMap": true, 10 | "rootDir": "./", 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "baseUrl": "./", 24 | "paths": { 25 | "*": ["src/*", "node_modules/*"] 26 | }, 27 | "jsx": "react-jsx", 28 | "esModuleInterop": true 29 | }, 30 | "include": [ 31 | "src", 32 | ], 33 | "exclude": [ 34 | "node_modules", 35 | "build", 36 | "public", 37 | "lib" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /packages/components/.fatherrc.ts: -------------------------------------------------------------------------------- 1 | 2 | const type = process.env.BUILD_TYPE; 3 | 4 | let config = {}; 5 | 6 | if (type === 'lib') { 7 | config = { 8 | cjs: { type: 'babel', lazy: true }, 9 | esm: false, 10 | runtimeHelpers: true, 11 | extraBabelPlugins: [ 12 | [ 13 | 'babel-plugin-import', 14 | { libraryName: 'antd', libraryDirectory: 'lib', style: true }, 15 | 'antd', 16 | ], 17 | ], 18 | }; 19 | } 20 | 21 | if (type === 'es') { 22 | config = { 23 | cjs: false, 24 | esm: { 25 | type: 'babel', 26 | }, 27 | runtimeHelpers: true, 28 | extraBabelPlugins: [ 29 | [require('./../../scripts/replaceLib')], 30 | ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'antd'], 31 | ], 32 | }; 33 | } 34 | 35 | export default config; 36 | -------------------------------------------------------------------------------- /packages/components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis/components", 3 | "version": "0.0.0", 4 | "description": "@vis/components", 5 | "keywords": [ 6 | "antd", 7 | "admin", 8 | "ant-design", 9 | "ant-design-pro" 10 | ], 11 | "homepage": "http://xxx.xxx.xxx.xxx:xxxx/-/web/detail/@vis/components", 12 | "repository": { 13 | "type": "git", 14 | "url": "http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/" 15 | }, 16 | "scripts": { 17 | "build": "cross-env BUILD_TYPE=es father-build" 18 | }, 19 | "license": "MIT", 20 | "main": "dist/index.js", 21 | "module": "es/index.js", 22 | "types": "es/index.d.ts", 23 | "files": [ 24 | "lib", 25 | "src", 26 | "dist", 27 | "es" 28 | ], 29 | "browserslist": [ 30 | "last 2 versions", 31 | "Firefox ESR", 32 | "> 1%", 33 | "ie >= 11" 34 | ], 35 | "peerDependencies": { 36 | "react": ">=16.9.0", 37 | "react-dom": ">=16.9.0" 38 | }, 39 | "publishConfig": { 40 | "access": "public", 41 | "registry": "http://xxx.xxx.xxx.xxx:xxxx/" 42 | }, 43 | "authors": [ 44 | "chenjie " 45 | ], 46 | "dependencies": { 47 | "@babel/runtime": "^7.16.3", 48 | "@ahooksjs/use-url-state": "3.5.1" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/components/readme.md: -------------------------------------------------------------------------------- 1 | # @vis/components 2 | 3 | > @vis/components. 4 | 5 | See our website [@vis/common](https://umijs.org/plugins/common) for more information. 6 | 7 | ## Install 8 | 9 | Using npm: 10 | 11 | ```bash 12 | $ npm install --save @vis/components --registry http://xxx.xxx.xxx.xxx:xxxx/ 13 | ``` 14 | 15 | or using yarn: 16 | 17 | ```bash 18 | $ yarn add @vis/components --registry http://xxx.xxx.xxx.xxx:xxxx/ 19 | ``` 20 | -------------------------------------------------------------------------------- /packages/components/src/Condition/index.less: -------------------------------------------------------------------------------- 1 | @comp-cls: ~'vis-comp-condition'; 2 | 3 | .@{comp-cls}-tip{ 4 | color: red; 5 | font-size: 12px; 6 | position: absolute; 7 | left: 40px; 8 | } 9 | .@{comp-cls}-header-filter{ 10 | position: relative; 11 | 12 | >.@{comp-cls}-icon-close{ 13 | position: absolute; 14 | right: 0; 15 | cursor: pointer; 16 | display: inline-block; 17 | } 18 | .@{comp-cls}-rg-btn-wrap{ 19 | position: absolute; 20 | right: 20px; 21 | } 22 | } 23 | .@{comp-cls}-body-filter { 24 | &:last-child { 25 | >div.@{comp-cls}-sub-item{ 26 | &:after{ 27 | height: 30px; 28 | } 29 | } 30 | } 31 | } 32 | .@{comp-cls}-item-wrap-child{ 33 | margin-left: 90px; 34 | position: relative; 35 | margin-top: 20px; 36 | border: solid 1px #dae3ee; 37 | padding: 14px; 38 | &:last-child{ 39 | &::after{ 40 | height: 35px; 41 | } 42 | } 43 | &::before{ 44 | content: ''; 45 | display: inline-block; 46 | width: 54px; 47 | height: 15px; 48 | position: absolute; 49 | left: -54px; 50 | top: -3px; 51 | border-bottom: solid 2px #eceef1; 52 | } 53 | &::after{ 54 | content: ''; 55 | display: inline-block; 56 | width: 30px; 57 | height: calc( 100% + 45px ); 58 | position: absolute; 59 | left: -54px; 60 | top: -22px; 61 | border-left: solid 2px #eceef1; 62 | } 63 | } 64 | .@{comp-cls}-sub-item{ 65 | position: relative; 66 | margin-left: 90px; 67 | white-space: nowrap; 68 | margin-top: 14px; 69 | display: flex; 70 | align-items: flex-start; 71 | > div { 72 | flex: 1; 73 | } 74 | .ant-form-item { 75 | margin-bottom: var(--vis-size); 76 | } 77 | &::before{ 78 | content: ''; 79 | display: inline-block; 80 | width: 53px; 81 | height: 13px; 82 | position: absolute; 83 | left: -53px; 84 | top: 5px; 85 | border-bottom: solid 2px #eceef1; 86 | } 87 | &::after{ 88 | content: ''; 89 | display: inline-block; 90 | width: 53px; 91 | height: calc( 100% + 14px ); 92 | position: absolute; 93 | left: -53px; 94 | top: -14px; 95 | border-left: solid 2px #eceef1; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /packages/components/src/ContextMenu/SubMenu.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children, createRef, useLayoutEffect, useState } from "react"; 2 | import { compareShapeLocation } from "./helper"; 3 | import { prefixCls } from "./index"; 4 | 5 | declare type SubMenuProps = { 6 | children: React.ReactNode; 7 | depth: number; 8 | prevRects: Array<() => HTMLUListElement>; 9 | } 10 | 11 | /** 12 | * 13 | * @param SubMenuProps 14 | * @description 负责根据渲染路径计算布局冲突, 进行位置调和 15 | */ 16 | 17 | export default function (props : SubMenuProps) { 18 | const { children, prevRects, depth } = props 19 | const [_layout, setLayout] = useState({ position: 'absolute', left: '100%', top: '0', zIndex: depth }) 20 | const rectRef = createRef() 21 | prevRects[depth] = () => rectRef.current as HTMLUListElement 22 | useLayoutEffect(() => { 23 | const rect = rectRef.current?.getBoundingClientRect() 24 | // 是否需要解决冲突 25 | const res = rect && compareShapeLocation(rect) 26 | let layout: React.CSSProperties = { transform : ''} 27 | if(res?.right) { // 右侧无法展示, 移到最左侧展示 28 | let moveX = 0 29 | if(depth <= 1) { // 如果当前第二层以前,更好的效果我们渲染到最左边去 30 | prevRects.forEach((i, idx) => { 31 | if(idx !== prevRects.length -1 ) { 32 | moveX += (i?.()?.getBoundingClientRect().width) || 0 33 | } 34 | }) 35 | layout.transform += `translateX(calc( -100% - ${moveX}px ))` 36 | }else{ // 否则直接基于上一次的出来的做累加 37 | layout.left = 10 38 | } 39 | } 40 | if(res?.bottom) { 41 | layout.transform += `translateY(-${res.bottom as number + depth * 10}px )` 42 | } 43 | (res?.right || res?.bottom ) && setLayout({..._layout, ...layout}) 44 | }, []) 45 | return ( 46 |
    51 | { 52 | Children.map(children, (child) => React.cloneElement(child as any, { prevRects })) 53 | } 54 |
55 | ) 56 | } 57 | -------------------------------------------------------------------------------- /packages/components/src/ContextMenu/helper.ts: -------------------------------------------------------------------------------- 1 | export const compareShapeLocation = function (b: DOMRect) { 2 | let ret: Record = { 3 | left: false, 4 | top: false, 5 | bottom: false, 6 | right: false 7 | } 8 | 0 > b.left && (ret.left = true) 9 | 0 > b.top && (ret.top = true) 10 | window.innerWidth < b.right && (ret.right = b.right - window.innerWidth) 11 | window.innerHeight < (b.bottom ) && (ret.bottom = (b.bottom) - window.innerHeight) 12 | return ret 13 | } 14 | 15 | export const reconcileLocation = function () { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /packages/components/src/ContextMenu/index.less: -------------------------------------------------------------------------------- 1 | @comp-cls: ~'vis-comp-context-menu'; 2 | 3 | .@{comp-cls}-wrap{ 4 | min-width: 100px; 5 | background: white; 6 | border: 1px solid #e4e7ed; 7 | border-radius: 4px; 8 | padding: 8px 0; 9 | >li{ 10 | list-style: none; 11 | line-height: 32px; 12 | margin: 0; 13 | font-size: 13px; 14 | height: 32px; 15 | cursor: pointer; 16 | position: relative; 17 | white-space: nowrap; 18 | color: #333; 19 | .@{comp-cls}-sitem{ 20 | position: relative; 21 | padding: 0 22px 0 16px; 22 | } 23 | .@{comp-cls}-icon { 24 | display: inline-block; 25 | margin-right: 8px; 26 | vertical-align: middle; 27 | font-size: 12px; 28 | } 29 | .@{comp-cls}-arrow{ 30 | position: absolute; 31 | right: 2px; 32 | top: calc( 50% - 6px ); 33 | font-size: 12px; 34 | } 35 | &:hover{ 36 | background: #ecf5ff; 37 | } 38 | &.@{comp-cls}-disabled{ 39 | cursor: not-allowed; 40 | color: gray; 41 | &:hover{ 42 | background: none; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/components/src/ContextMenu/index.tsx: -------------------------------------------------------------------------------- 1 | import { MouseEvent, useMemo } from 'react'; 2 | import './index.less'; 3 | import Item from './Item'; 4 | import SubMenu from './SubMenu'; 5 | export type ContextMenuItem = { 6 | /** 唯一值 */ 7 | value: string; 8 | /** 展示的名称或者自定义jsx */ 9 | label: React.ReactNode; 10 | /** 子节点加载方法或者子节点数组 */ 11 | children?: 12 | | ContextMenuItem[] 13 | | ((item: ContextMenuItem, data: any) => ContextMenuItem[]); 14 | /** 图表 */ 15 | icon?: React.ReactNode; 16 | /** 是否禁用,禁用后不会处罚单击函数 */ 17 | disabled?: boolean; 18 | /** 自定义渲染 */ 19 | render?: (_: ContextMenuItem) => React.ReactNode; 20 | /** 自定义加载图表 */ 21 | loadding?: React.ReactNode; 22 | /** 自定义单独处理函数 */ 23 | onClick?: (e: MouseEvent, item: ContextMenuItem, data: any) => void; 24 | [key: string]: any; 25 | }; 26 | 27 | export type HandleClick = ( 28 | e: MouseEvent, 29 | item: any, 30 | menu: ContextMenuItem, 31 | ) => void; 32 | 33 | export type ContextMenuProps = { 34 | /** 菜单数据 */ 35 | menus: Array; 36 | /** 点击处理函数,传递e, 当前数据项, menu 菜单项 */ 37 | onClick: HandleClick; 38 | /** 当前Trigger触发的数据项 */ 39 | curItem: React.MutableRefObject; 40 | /** 递归深度 */ 41 | depth?: number; 42 | /** 43 | * Save the parameter layout of each item, 44 | * When rendering to the next layer, check whether it can be expanded 45 | * */ 46 | prevRects?: Array<() => HTMLUListElement>; 47 | /** 自定义加载图表 */ 48 | loadding?: React.ReactNode; 49 | /** 设置菜单显示隐藏 */ 50 | setMenuVisible: (visible: boolean) => void; 51 | }; 52 | 53 | export const prefixCls = 'vis-comp-context-menu-'; 54 | 55 | const ContextMenu = function (props: ContextMenuProps) { 56 | const { 57 | onClick, 58 | menus, 59 | curItem, 60 | prevRects = [], 61 | depth = 0, 62 | loadding, 63 | setMenuVisible, 64 | } = props; 65 | return useMemo( 66 | () => ( 67 | 68 | {menus.map((i) => ( 69 | 79 | ))} 80 | 81 | ), 82 | [onClick, menus, loadding], 83 | ); 84 | }; 85 | 86 | ContextMenu.Item = Item; 87 | 88 | export default ContextMenu; 89 | -------------------------------------------------------------------------------- /packages/components/src/DragLayoutResize/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: DragLayoutResize-拖拽布局 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | ## DragLayoutResize 组件描述 11 | 12 | 拖拽布局(布局切割),最初版本,后期添加拖拽样式自定义渲染等功能,基于 flex 布局实现,故在使用时记得外层包一个 flex 代码的包裹层 13 | 14 | ### 横向 15 | 16 | ```jsx 17 | import React from 'react'; 18 | import { DragLayoutResize } from '@vis/components'; 19 | export default () => { 20 | const { DRAG_DIRECTION } = DragLayoutResize; 21 | return ( 22 |
23 |
24 | 28 |

点我旁边拖拽

29 |
30 |
31 | ); 32 | }; 33 | ``` 34 | 35 | ### 竖向 36 | 37 | ```jsx 38 | import React from 'react'; 39 | import { DragLayoutResize } from '@vis/components'; 40 | const { DRAG_DIRECTION } = DragLayoutResize; 41 | 42 | export default () => { 43 | return ( 44 |
45 | 49 |

点我下方拖拽

50 |
51 |
52 |
53 | ); 54 | }; 55 | ``` 56 | 57 | ### 布局切割 58 | 59 | ```jsx 60 | import React from 'react'; 61 | import { DragLayoutResize } from '@vis/components'; 62 | export default () => { 63 | const { DRAG_DIRECTION } = DragLayoutResize; 64 | return ( 65 |
66 |
67 | 75 |
82 | 86 |

点我下方拖拽

87 |
88 |
89 |
90 |
91 |
92 | ); 93 | }; 94 | ``` 95 | 96 | 97 | -------------------------------------------------------------------------------- /packages/components/src/DragLayoutResize/index.less: -------------------------------------------------------------------------------- 1 | @vis-dragLayoutResize-prefix-cls: ~'ant-vis-drag-layout-resize'; 2 | .@{vis-dragLayoutResize-prefix-cls}-drag-line { 3 | position: absolute; 4 | z-index: 999; 5 | // border: solid 1px var(--colorPrimary); 6 | opacity: 0.3; 7 | &:hover { 8 | background-color: var(--colorPrimary); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/components/src/Marquee/index.less: -------------------------------------------------------------------------------- 1 | @comp-cls: ~'vis-comp-word-view'; 2 | 3 | 4 | 5 | // .@{comp-cls}-wrap{ 6 | // overflow: hidden; 7 | .@{comp-cls}-marquee-container { 8 | overflow-x: hidden !important; 9 | display: flex !important; 10 | flex-direction: row !important; 11 | position: relative; 12 | width: 100%; 13 | 14 | &:hover div { 15 | animation-play-state: var(--pause-on-hover); 16 | } 17 | 18 | &:active div { 19 | animation-play-state: var(--pause-on-click); 20 | } 21 | } 22 | 23 | .@{comp-cls}-overlay { 24 | position: absolute; 25 | width: 100%; 26 | height: 100%; 27 | background: linear-gradient(to right, var(--gradient-color)); 28 | &::before, 29 | &::after { 30 | content: ""; 31 | height: 100%; 32 | position: absolute; 33 | width: var(--gradient-width); 34 | z-index: 2; 35 | } 36 | 37 | &::after { 38 | right: 0; 39 | top: 0; 40 | transform: rotateZ(180deg); 41 | } 42 | 43 | &::before { 44 | left: 0; 45 | top: 0; 46 | } 47 | } 48 | 49 | .@{comp-cls}-marquee { 50 | flex: 0 0 auto; 51 | min-width: 100%; 52 | z-index: 1; 53 | display: flex; 54 | flex-direction: row; 55 | align-items: center; 56 | animation: scroll var(--duration) linear var(--delay) var(--iteration-count); 57 | animation-play-state: var(--play); 58 | animation-delay: var(--delay); 59 | animation-direction: var(--direction); 60 | 61 | @keyframes scroll { 62 | 0% { 63 | transform: translateX(0%); 64 | } 65 | 100% { 66 | transform: translateX(-100%); 67 | } 68 | } 69 | } 70 | 71 | // .@{comp-cls}-marquee-wrap { 72 | // width: 100%; 73 | // background-color: var(--color); 74 | // } 75 | // .@{comp-cls}-marquee-content { 76 | 77 | // &.scroll{ 78 | // float: left; 79 | // white-space: nowrap; 80 | // animation: marquee-content 4s infinite linear; 81 | // } 82 | // } 83 | // } 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /packages/components/src/audio/useAudio.tsx: -------------------------------------------------------------------------------- 1 | import React, { useLayoutEffect } from "react" 2 | import audio, {PlayerProps} from './index' 3 | export default (audioRef: React.RefObject, config?: PlayerProps) => { 4 | useLayoutEffect(() => { 5 | config && audioRef.current && audio.bind(audioRef.current, config) 6 | return () => { 7 | config && audioRef.current && audio.unbind(audioRef.current) 8 | } 9 | }, [config]) 10 | } 11 | 12 | export const AudioProps = (_: PlayerProps) =>
13 | -------------------------------------------------------------------------------- /packages/components/src/components.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: components-功能组件总览 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | # 总览 11 | 12 | ## Install 13 | 14 | Using npm: 15 | 16 | ```bash 17 | $ npm install --save @vis/components --registry http://xxx.xxx.xxx.xxx:xxxx/ 18 | ``` 19 | 20 | or using yarn: 21 | 22 | ```bash 23 | $ yarn add @vis/components --registry http://xxx.xxx.xxx.xxx:xxxx/ 24 | ``` 25 | 26 | ## DragLayoutResize 拖拽改变宽高 27 | 28 | ```jsx 29 | import React from 'react'; 30 | import { DragLayoutResize } from '@vis/components'; 31 | const { DRAG_DIRECTION } = DragLayoutResize 32 | export default () => { 33 | return ( 34 |
35 |
36 | 40 |

点我旁边拖拽

41 |
42 |
43 | ); 44 | }; 45 | ``` 46 | -------------------------------------------------------------------------------- /packages/components/src/index.tsx: -------------------------------------------------------------------------------- 1 | import DragLayoutResize from './DragLayoutResize'; 2 | import Marquee from './Marquee'; 3 | import Condition from './Condition'; 4 | import useContextMenu from './ContextMenu/useContextMenu'; 5 | import ContextMenu, { ContextMenuItem } from './ContextMenu'; 6 | 7 | import type { CondRef } from './Condition'; 8 | import useAudio from './audio/useAudio'; 9 | export { DragLayoutResize, Marquee, Condition, useContextMenu, ContextMenu, useAudio }; 10 | export type { ContextMenuItem, CondRef }; 11 | -------------------------------------------------------------------------------- /packages/components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "esnext", 5 | "skipLibCheck": true, 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | "declaration": true, 9 | "sourceMap": true, 10 | "rootDir": "./", 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "baseUrl": "./", 24 | "paths": { 25 | "*": ["src/*", "node_modules/*"] 26 | }, 27 | "jsx": "react-jsx", 28 | "esModuleInterop": true 29 | }, 30 | "include": [ 31 | "src", 32 | ], 33 | "exclude": [ 34 | "node_modules", 35 | "build", 36 | "public", 37 | "lib" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /packages/decorator/.fatherrc.ts: -------------------------------------------------------------------------------- 1 | 2 | const type = process.env.BUILD_TYPE; 3 | let config = {}; 4 | 5 | if (type === 'lib') { 6 | config = { 7 | cjs: { type: 'babel', lazy: true }, 8 | esm: false, 9 | runtimeHelpers: true, 10 | extraBabelPlugins: [ 11 | [ 12 | 'babel-plugin-import', 13 | { libraryName: 'antd', libraryDirectory: 'lib', style: true }, 14 | 'antd', 15 | ], 16 | ], 17 | }; 18 | } 19 | 20 | if (type === 'es') { 21 | config = { 22 | cjs: false, 23 | esm: { 24 | type: 'babel', 25 | }, 26 | runtimeHelpers: true, 27 | extraBabelPlugins: [ 28 | [require('./../../scripts/replaceLib')], 29 | ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'antd'], 30 | ], 31 | }; 32 | } 33 | 34 | export default config; 35 | 36 | -------------------------------------------------------------------------------- /packages/decorator/README.md: -------------------------------------------------------------------------------- 1 | # @vis/decorator 2 | 3 | > @vis/decorator. 4 | 5 | ## Install 6 | 7 | Using npm: 8 | 9 | ```bash 10 | $ npm install --save @vis/decorator --registry http://xxx.xxx.xxx.xxx:xxxx/ 11 | ``` 12 | 13 | or using yarn: 14 | 15 | ```bash 16 | $ yarn add @vis/decorator --registry http://xxx.xxx.xxx.xxx:xxxx/ 17 | ``` 18 | -------------------------------------------------------------------------------- /packages/decorator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis/decorator", 3 | "version": "1.0.0", 4 | "description": "@vis/decorator", 5 | "files": [ 6 | "lib", 7 | "src", 8 | "dist", 9 | "es" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "https://10.28.184.132/ssa-vis/vis-components/Index/" 14 | }, 15 | "dependencies": { 16 | "@babel/runtime": "^7.16.3", 17 | "lodash": "^4.17.21", 18 | "@vis/utils": "workspace:^*", 19 | "react-particles-js": "2.4.2", 20 | "pathseg": "^1.2.0" 21 | }, 22 | "devDependencies": { 23 | "@types/lodash": "^4.14.182" 24 | }, 25 | "scripts": { 26 | "build": "cross-env BUILD_TYPE=es father-build" 27 | }, 28 | "browserslist": [ 29 | "last 2 versions", 30 | "Firefox ESR", 31 | "> 1%", 32 | "ie >= 11" 33 | ], 34 | "authors": [ 35 | "chenjie " 36 | ], 37 | "license": "MIT", 38 | "peerDependencies": { 39 | "antd": ">=4.20.0", 40 | "react": ">=16.9.0", 41 | "react-dom": ">=16.9.0" 42 | }, 43 | "main": "dist/index.js", 44 | "module": "es/index.js", 45 | "types": "es/index.d.ts", 46 | "publishConfig": { 47 | "access": "public", 48 | "registry": "http://xxx.xxx.xxx.xxx:xxxx/" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/decorator/src/Background/index.tsx: -------------------------------------------------------------------------------- 1 | import Particles, { ParticlesProps } from 'react-particles-js'; 2 | import "pathseg"; 3 | 4 | export default (props: ParticlesProps) => 5 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox1/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-1 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .border { 7 | position: absolute; 8 | display: block; 9 | } 10 | 11 | .right-top { 12 | right: 0px; 13 | transform: rotateY(180deg); 14 | } 15 | 16 | .left-bottom { 17 | bottom: 0px; 18 | transform: rotateX(180deg); 19 | } 20 | 21 | .right-bottom { 22 | right: 0px; 23 | bottom: 0px; 24 | transform: rotateX(180deg) rotateY(180deg); 25 | } 26 | 27 | .border-box-content { 28 | position: relative; 29 | width: 100%; 30 | height: 100%; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox10/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-11 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | width: 100%; 9 | height: 100%; 10 | top: 0px; 11 | left: 0px; 12 | 13 | & > polyline { 14 | fill: none; 15 | stroke-width: 1; 16 | } 17 | } 18 | 19 | .border-box-content { 20 | position: relative; 21 | width: 100%; 22 | height: 100%; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox11/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo, forwardRef, CSSProperties } from 'react'; 2 | 3 | 4 | import classnames from 'classnames'; 5 | 6 | import cloneDeep from 'lodash/cloneDeep'; 7 | import merge from 'lodash/merge'; 8 | import { useAutoResize } from '@vis/utils'; 9 | import './style.less'; 10 | 11 | const defaultColor = ['#6586ec', '#2cf7fe']; 12 | 13 | 14 | const BorderBox = forwardRef(({ children, className, style, color = [], backgroundColor = 'transparent' }: { 15 | /** 子节点 */ 16 | children: React.ReactNode; 17 | /** 自定义类名 */ 18 | className: string; 19 | /** 自定义css属性 */ 20 | style: CSSProperties; 21 | /** */ 22 | color: string[]; 23 | backgroundColor: string; 24 | }, ref) => { 25 | const { width, height, domRef } = useAutoResize(ref); 26 | 27 | const mergedColor = useMemo(() => merge(cloneDeep(defaultColor), color || []), [color]); 28 | 29 | const classNames = useMemo(() => classnames('dv-border-box-13', className), [ 30 | className, 31 | ]); 32 | 33 | 34 | return ( 35 |
36 | 37 | 47 | 48 | 56 | 57 | 62 | 63 | 68 | 69 |
70 | {children} 71 |
72 |
73 | ); 74 | }); 75 | 76 | export default BorderBox; 77 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox11/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-12 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | width: 100%; 9 | height: 100%; 10 | top: 0px; 11 | left: 0px; 12 | } 13 | 14 | .border-box-content { 15 | position: relative; 16 | width: 100%; 17 | height: 100%; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox12/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-13 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | width: 100%; 9 | height: 100%; 10 | top: 0px; 11 | left: 0px; 12 | } 13 | 14 | .border-box-content { 15 | position: relative; 16 | width: 100%; 17 | height: 100%; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox2/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo, forwardRef, CSSProperties } from 'react'; 2 | 3 | import cloneDeep from 'lodash/cloneDeep'; 4 | import merge from 'lodash/merge'; 5 | import { useAutoResize } from '@vis/utils'; 6 | 7 | 8 | import './style.less'; 9 | import classnames from 'classnames'; 10 | 11 | const defaultColor = ['#fff', 'rgba(255, 255, 255, 0.6)']; 12 | 13 | interface PropsTypes { 14 | children: React.ReactNode; 15 | className: string; 16 | style: CSSProperties; 17 | color: string[]; 18 | backgroundColor: string; 19 | } 20 | 21 | const BorderBox = forwardRef(({ children, className, style, color = [], backgroundColor = 'transparent' }: PropsTypes, ref) => { 22 | const { width, height, domRef } = useAutoResize(ref); 23 | 24 | const mergedColor = useMemo(() => merge(cloneDeep(defaultColor), color || []), [color]); 25 | 26 | const classNames = useMemo(() => classnames('dv-border-box-2', className), [ 27 | className, 28 | ]); 29 | 30 | return ( 31 |
32 | 33 | 39 | 44 | 49 | 50 | 51 | 52 | 53 | 54 |
{children}
55 |
56 | ); 57 | }); 58 | 59 | 60 | export default BorderBox; 61 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox2/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-2 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | width: 100%; 9 | height: 100%; 10 | top: 0px; 11 | left: 0px; 12 | 13 | & > polyline { 14 | fill: none; 15 | stroke-width: 1; 16 | } 17 | } 18 | 19 | .border-box-content { 20 | position: relative; 21 | width: 100%; 22 | height: 100%; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox3/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-4 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-reverse { 7 | transform: rotate(180deg); 8 | } 9 | 10 | .dv-border-svg-container { 11 | position: absolute; 12 | width: 100%; 13 | height: 100%; 14 | top: 0px; 15 | left: 0px; 16 | 17 | & > polyline { 18 | fill: none; 19 | } 20 | } 21 | 22 | .sw1 { 23 | stroke-width: 1; 24 | } 25 | 26 | .sw3 { 27 | stroke-width: 3px; 28 | stroke-linecap: round; 29 | } 30 | 31 | .dv-bb4-line-1 { 32 | .sw1; 33 | } 34 | 35 | .dv-bb4-line-2 { 36 | .sw1; 37 | } 38 | 39 | .dv-bb4-line-3 { 40 | .sw3; 41 | } 42 | 43 | .dv-bb4-line-4 { 44 | .sw3; 45 | } 46 | 47 | .dv-bb4-line-5 { 48 | .sw1; 49 | } 50 | 51 | .dv-bb4-line-6 { 52 | .sw1; 53 | } 54 | 55 | .dv-bb4-line-7 { 56 | .sw1; 57 | } 58 | 59 | .dv-bb4-line-8 { 60 | .sw3; 61 | } 62 | 63 | .dv-bb4-line-9 { 64 | .sw3; 65 | stroke-dasharray: 100 250; 66 | } 67 | 68 | .dv-bb4-line-10 { 69 | .sw1; 70 | stroke-dasharray: 80 270; 71 | } 72 | 73 | .border-box-content { 74 | position: relative; 75 | width: 100%; 76 | height: 100%; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox4/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-5 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-reverse { 7 | transform: rotate(180deg); 8 | } 9 | 10 | .dv-border-svg-container { 11 | position: absolute; 12 | top: 0px; 13 | left: 0px; 14 | width: 100%; 15 | height: 100%; 16 | 17 | & > polyline { 18 | fill: none; 19 | } 20 | } 21 | 22 | .dv-bb5-line-1, .dv-bb5-line-2 { 23 | stroke-width: 1; 24 | } 25 | 26 | .dv-bb5-line-3, .dv-bb5-line-6 { 27 | stroke-width: 5; 28 | } 29 | 30 | .dv-bb5-line-4, .dv-bb5-line-5 { 31 | stroke-width: 2; 32 | } 33 | 34 | .border-box-content { 35 | position: relative; 36 | width: 100%; 37 | height: 100%; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox5/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-6 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | top: 0px; 9 | left: 0px; 10 | width: 100%; 11 | height: 100%; 12 | 13 | & > polyline { 14 | fill: none; 15 | stroke-width: 1; 16 | } 17 | } 18 | 19 | .border-box-content { 20 | position: relative; 21 | width: 100%; 22 | height: 100%; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox6/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-7 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | top: 0px; 9 | left: 0px; 10 | width: 100%; 11 | height: 100%; 12 | 13 | & > polyline { 14 | fill: none; 15 | stroke-linecap: round; 16 | } 17 | } 18 | 19 | .dv-bb7-line-width-2 { 20 | stroke-width: 2; 21 | } 22 | 23 | .dv-bb7-line-width-5 { 24 | stroke-width: 5; 25 | } 26 | 27 | .border-box-content { 28 | position: relative; 29 | width: 100%; 30 | height: 100%; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox7/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-8 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | width: 100%; 9 | height: 100%; 10 | left: 0px; 11 | top: 0px; 12 | } 13 | 14 | .border-box-content { 15 | position: relative; 16 | width: 100%; 17 | height: 100%; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox8/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-9 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | 6 | .dv-border-svg-container { 7 | position: absolute; 8 | width: 100%; 9 | height: 100%; 10 | left: 0px; 11 | top: 0px; 12 | } 13 | 14 | .border-box-content { 15 | position: relative; 16 | width: 100%; 17 | height: 100%; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox9/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo, forwardRef, CSSProperties } from 'react'; 2 | 3 | 4 | import classnames from 'classnames'; 5 | 6 | import cloneDeep from 'lodash/cloneDeep'; 7 | import merge from 'lodash/merge'; 8 | import { useAutoResize } from '@vis/utils'; 9 | import './style.less'; 10 | 11 | const defaultColor = ['#235fa7', '#4fd2dd']; 12 | 13 | interface PropsTypes { 14 | children: React.ReactNode; 15 | className: string; 16 | style: CSSProperties; 17 | color: string[]; 18 | backgroundColor: string; 19 | } 20 | const border = ['left-top', 'right-top', 'left-bottom', 'right-bottom']; 21 | 22 | const BorderBox = forwardRef(({ children, className, style, color = [], backgroundColor = 'transparent' }: PropsTypes, ref) => { 23 | const { width, height, domRef } = useAutoResize(ref); 24 | 25 | const mergedColor = useMemo(() => merge(cloneDeep(defaultColor), color || []), [color]); 26 | 27 | const classNames = useMemo(() => classnames('dv-border-box-10', className), [ 28 | className, 29 | ]); 30 | 31 | const styles = useMemo(() => ({ 32 | boxShadow: `inset 0 0 25px 3px ${mergedColor[0]}`, 33 | ...style, 34 | }), [style, mergedColor]); 35 | 36 | 37 | return ( 38 |
39 | 40 | 47 | 48 | 49 | {border.map((borderName) => ( 50 | 56 | 60 | 61 | ))} 62 |
{children}
63 |
64 | ); 65 | }); 66 | 67 | export default BorderBox; 68 | -------------------------------------------------------------------------------- /packages/decorator/src/BorderBox9/style.less: -------------------------------------------------------------------------------- 1 | .dv-border-box-10 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | border-radius: 6px; 6 | 7 | .dv-border-svg-container { 8 | position: absolute; 9 | display: block; 10 | } 11 | 12 | .right-top { 13 | right: 0px; 14 | transform: rotateY(180deg); 15 | } 16 | 17 | .left-bottom { 18 | bottom: 0px; 19 | transform: rotateX(180deg); 20 | } 21 | 22 | .right-bottom { 23 | right: 0px; 24 | bottom: 0px; 25 | transform: rotateX(180deg) rotateY(180deg); 26 | } 27 | 28 | .border-box-content { 29 | position: relative; 30 | width: 100%; 31 | height: 100%; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration1/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-1 { 2 | width: 100%; 3 | height: 100%; 4 | 5 | svg { 6 | transform-origin: left top; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration10/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-11 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | display: flex; 6 | 7 | .decoration-content { 8 | position: absolute; 9 | top: 0px; 10 | left: 0px; 11 | width: 100%; 12 | height: 100%; 13 | display: flex; 14 | align-items: center; 15 | justify-content: center; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration11/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-11 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | display: flex; 6 | 7 | .decoration-content { 8 | position: absolute; 9 | top: 0px; 10 | left: 0px; 11 | width: 100%; 12 | height: 100%; 13 | display: flex; 14 | align-items: center; 15 | justify-content: center; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration12/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './style.less'; 3 | 4 | export default ({ color = ['white'], children }: { 5 | color: [string]; 6 | // styles: React.CSSProperties; 7 | children: React.ReactNode; 8 | }) => { 9 | console.log(color); 10 | return ( 11 |
12 | { children } 13 |
); 14 | }; 15 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration12/style.less: -------------------------------------------------------------------------------- 1 | 2 | .vis-decoration-area { 3 | text-align: center; 4 | font-size: 6.5em; 5 | color: #fff; 6 | letter-spacing: -7px; 7 | font-weight: 700; 8 | text-transform: uppercase; 9 | animation: blur .75s ease-out infinite; 10 | text-shadow: 0px 0px 5px #fff, 0px 0px 7px #fff; 11 | } 12 | 13 | @keyframes blur { 14 | from { 15 | text-shadow:0px 0px 10px #fff, 16 | 0px 0px 10px #fff, 17 | 0px 0px 25px #fff, 18 | 0px 0px 25px #fff, 19 | 0px 0px 25px #fff, 20 | 0px 0px 25px #fff, 21 | 0px 0px 25px #fff, 22 | 0px 0px 25px #fff, 23 | 0px 0px 50px #fff, 24 | 0px 0px 50px #fff, 25 | 0px 0px 50px #7B96B8, 26 | 0px 0px 150px #7B96B8, 27 | 0px 10px 100px #7B96B8, 28 | 0px 10px 100px #7B96B8, 29 | 0px 10px 100px #7B96B8, 30 | 0px 10px 100px #7B96B8, 31 | 0px -10px 100px #7B96B8, 32 | 0px -10px 100px #7B96B8; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration2/index.tsx: -------------------------------------------------------------------------------- 1 | import { useMemo, forwardRef, CSSProperties } from 'react'; 2 | 3 | 4 | import classnames from 'classnames'; 5 | 6 | import cloneDeep from 'lodash/cloneDeep'; 7 | import merge from 'lodash/merge'; 8 | import { useAutoResize } from '@vis/utils'; 9 | import './style.less'; 10 | 11 | const defaultColor = ['#3faacb', '#fff']; 12 | 13 | 14 | const Decoration = forwardRef(({ reverse = false, dur = 6, className, style, color = [] }: { 15 | /** 自定义类名 */ 16 | className: string; 17 | /** 自定义css属性 */ 18 | style: CSSProperties; 19 | /** 颜色 */ 20 | color: string[]; 21 | /** 是否反向 */ 22 | reverse: boolean; 23 | /** 动画执行周期 */ 24 | dur: number; 25 | 26 | }, ref) => { 27 | const { width, height, domRef } = useAutoResize(ref); 28 | 29 | function calcSVGData() { 30 | return reverse 31 | ? { w: 1, h: height, x: width / 2, y: 0 } 32 | : { w: width, h: 1, x: 0, y: height / 2 }; 33 | } 34 | 35 | const mergedColor = useMemo(() => merge(cloneDeep(defaultColor), color || []), [color]); 36 | 37 | const { x, y, w, h } = useMemo(calcSVGData, [reverse, width, height]); 38 | 39 | const classNames = useMemo(() => classnames('dv-decoration-2', className), [ 40 | className, 41 | ]); 42 | 43 | return ( 44 |
45 | 46 | 47 | 57 | 58 | 59 | 60 | 70 | 71 | 72 |
73 | ); 74 | }); 75 | 76 | export default Decoration; 77 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration2/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-2 { 2 | display: flex; 3 | width: 100%; 4 | height: 100%; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration3/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-3 { 2 | width: 100%; 3 | height: 100%; 4 | 5 | svg { 6 | transform-origin: left top; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration4/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-5 { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration5/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-6 { 2 | width: 100%; 3 | height: 100%; 4 | 5 | svg { 6 | transform-origin: left top; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration6/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo, CSSProperties } from 'react'; 2 | 3 | 4 | import classnames from 'classnames'; 5 | 6 | import cloneDeep from 'lodash/cloneDeep'; 7 | import merge from 'lodash/merge'; 8 | import './style.less'; 9 | 10 | const defaultColor = ['#1dc1f5', '#1dc1f5']; 11 | 12 | 13 | const Decoration = ({ children, className, style, color = [] }: { 14 | /** 自定义类名 */ 15 | className: string; 16 | /** 自定义css属性 */ 17 | style: CSSProperties; 18 | /** 颜色 */ 19 | color: string[]; 20 | /** */ 21 | children: React.ReactNode; 22 | }) => { 23 | const mergedColor = useMemo(() => merge(cloneDeep(defaultColor), color || []), [color]); 24 | 25 | 26 | const classNames = useMemo(() => classnames('dv-decoration-6', className), [ 27 | [className], 28 | ]); 29 | 30 | return ( 31 |
32 | 33 | 39 | 45 | 46 | {children} 47 | 48 | 54 | 60 | 61 |
62 | ); 63 | }; 64 | 65 | export default Decoration; 66 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration6/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-7 { 2 | display: flex; 3 | width: 100%; 4 | height: 100%; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration7/index.tsx: -------------------------------------------------------------------------------- 1 | import { useMemo, forwardRef, CSSProperties } from 'react'; 2 | 3 | 4 | import classnames from 'classnames'; 5 | import { useAutoResize } from '@vis/utils'; 6 | import cloneDeep from 'lodash/cloneDeep'; 7 | import merge from 'lodash/merge'; 8 | import './style.less'; 9 | 10 | const defaultColor = ['#1dc1f5', '#1dc1f5']; 11 | 12 | 13 | const Decoration = forwardRef(({ reverse = false, className, style, color = [] }: { 14 | /** 自定义类名 */ 15 | className: string; 16 | /** 自定义css属性 */ 17 | style: CSSProperties; 18 | /** 颜色 */ 19 | color: string[]; 20 | /** 方向 */ 21 | reverse: boolean; 22 | }, ref) => { 23 | const { width, height, domRef } = useAutoResize(ref); 24 | 25 | const xPos = (pos: any) => (!reverse ? pos : width - pos); 26 | 27 | const mergedColor = useMemo(() => merge(cloneDeep(defaultColor), color || []), [color]); 28 | 29 | const [pointsOne, pointsTwo, pointsThree] = useMemo( 30 | () => [ 31 | `${xPos(0)}, 0 ${xPos(30)}, ${height / 2}`, 32 | `${xPos(20)}, 0 ${xPos(50)}, ${height / 2} ${xPos(width)}, ${height / 2}`, 33 | `${xPos(0)}, ${height - 3}, ${xPos(200)}, ${height - 3}`, 34 | ], 35 | [reverse, width, height], 36 | ); 37 | 38 | const classNames = useMemo(() => classnames('dv-decoration-8', className), [ 39 | className, 40 | ]); 41 | 42 | return ( 43 |
44 | 45 | 51 | 52 | 58 | 59 | 65 | 66 |
67 | ); 68 | }); 69 | 70 | export default Decoration; 71 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration7/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-8 { 2 | display: flex; 3 | width: 100%; 4 | height: 100%; 5 | } 6 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration8/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-9 { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | display: flex; 6 | align-items: center; 7 | justify-content: center; 8 | 9 | svg { 10 | position: absolute; 11 | left: 0px; 12 | top: 0px; 13 | transform-origin: left top; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/decorator/src/Decoration9/style.less: -------------------------------------------------------------------------------- 1 | .dv-decoration-10 { 2 | width: 100%; 3 | height: 100%; 4 | display: flex; 5 | } 6 | -------------------------------------------------------------------------------- /packages/decorator/src/index.tsx: -------------------------------------------------------------------------------- 1 | import BorderBox from './BorderBox'; 2 | import BorderBox1 from './BorderBox1'; 3 | import BorderBox2 from './BorderBox2'; 4 | import BorderBox3 from './BorderBox3'; 5 | import BorderBox4 from './BorderBox4'; 6 | import BorderBox5 from './BorderBox5'; 7 | import BorderBox6 from './BorderBox6'; 8 | import BorderBox7 from './BorderBox7'; 9 | import BorderBox8 from './BorderBox8'; 10 | import BorderBox9 from './BorderBox9'; 11 | import BorderBox10 from './BorderBox10'; 12 | import BorderBox11 from './BorderBox11'; 13 | import BorderBox12 from './BorderBox12'; 14 | 15 | import Decoration1 from './Decoration1'; 16 | import Decoration2 from './Decoration2'; 17 | import Decoration3 from './Decoration3'; 18 | import Decoration4 from './Decoration4'; 19 | import Decoration5 from './Decoration5'; 20 | import Decoration6 from './Decoration6'; 21 | import Decoration7 from './Decoration7'; 22 | import Decoration8 from './Decoration8'; 23 | import Decoration9 from './Decoration9'; 24 | import Decoration10 from './Decoration10'; 25 | import Decoration11 from './Decoration11'; 26 | import Background from './Background'; 27 | 28 | export { 29 | BorderBox, 30 | BorderBox1, 31 | BorderBox2, 32 | BorderBox3, 33 | BorderBox4, 34 | BorderBox5, 35 | BorderBox6, 36 | BorderBox7, 37 | BorderBox8, 38 | BorderBox9, 39 | BorderBox10, 40 | BorderBox11, 41 | BorderBox12, 42 | Decoration1, 43 | Decoration2, 44 | Decoration3, 45 | Decoration4, 46 | Decoration5, 47 | Decoration6, 48 | Decoration7, 49 | Decoration8, 50 | Decoration9, 51 | Decoration10, 52 | Decoration11, 53 | Background, 54 | }; 55 | -------------------------------------------------------------------------------- /packages/decorator/tsconfig.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "skipLibCheck": true, 4 | "compilerOptions": { 5 | "target": "es6", 6 | "module": "esnext", 7 | "lib": ["dom", "esnext"], 8 | "importHelpers": true, 9 | "declaration": true, 10 | "sourceMap": true, 11 | "skipLibCheck": true, 12 | "rootDir": "./", 13 | "strict": true, 14 | "noImplicitAny": true, 15 | "strictNullChecks": true, 16 | "strictFunctionTypes": true, 17 | "strictPropertyInitialization": true, 18 | "noImplicitThis": true, 19 | "alwaysStrict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noImplicitReturns": true, 23 | "noFallthroughCasesInSwitch": true, 24 | "moduleResolution": "node", 25 | "baseUrl": "./", 26 | "paths": { 27 | "*": ["src/*", "node_modules/*"] 28 | }, 29 | "jsx": "react-jsx", 30 | "esModuleInterop": true 31 | }, 32 | "include": [ 33 | "src", 34 | ], 35 | "exclude": [ 36 | "node_modules", 37 | "build", 38 | "public", 39 | "lib" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /packages/test/.fatherrc.ts: -------------------------------------------------------------------------------- 1 | 2 | const type = process.env.BUILD_TYPE; 3 | 4 | let config = {}; 5 | 6 | if (type === 'lib') { 7 | config = { 8 | cjs: { type: 'babel', lazy: true }, 9 | esm: false, 10 | runtimeHelpers: true, 11 | extraBabelPlugins: [ 12 | [ 13 | 'babel-plugin-import', 14 | { libraryName: 'antd', libraryDirectory: 'lib', style: true }, 15 | 'antd', 16 | ], 17 | ], 18 | }; 19 | } 20 | 21 | if (type === 'es') { 22 | config = { 23 | cjs: false, 24 | esm: { 25 | type: 'babel', 26 | }, 27 | runtimeHelpers: true, 28 | extraBabelPlugins: [ 29 | [require('./../../scripts/replaceLib')], 30 | ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'antd'], 31 | ], 32 | }; 33 | } 34 | 35 | export default config; 36 | -------------------------------------------------------------------------------- /packages/test/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: test-测试组件 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | # @vis/test 11 | 12 | > @vis/test. 13 | 14 | See our website [@vis/test](https://umijs.org/plugins/test) for more information. 15 | 16 | ## Install 17 | 18 | Using npm: 19 | 20 | ```bash 21 | $ npm install --save @vis/test --registry http://xxx.xxx.xxx.xxx:xxxx/ 22 | ``` 23 | 24 | or using yarn: 25 | 26 | ```bash 27 | $ yarn add @vis/test --registry http://xxx.xxx.xxx.xxx:xxxx/ 28 | ``` 29 | 30 | 测试组件描述 31 | 32 | ```jsx 33 | import React from 'react'; 34 | import { Test } from '@vis/test'; 35 | export default () => { 36 | return ( 37 |

38 | 自定义渲染代码块 39 | 40 |

41 | ); 42 | }; 43 | ``` 44 | -------------------------------------------------------------------------------- /packages/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis/test", 3 | "version": "0.0.0", 4 | "description": "@vis/test", 5 | "keywords": [ 6 | "antd", 7 | "admin", 8 | "ant-design", 9 | "ant-design-pro" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/" 14 | }, 15 | "license": "MIT", 16 | "main": "dist/index.js", 17 | "module": "es/index.js", 18 | "types": "es/index.d.ts", 19 | "files": [ 20 | "lib", 21 | "src", 22 | "dist", 23 | "es" 24 | ], 25 | "scripts": { 26 | "build": "cross-env BUILD_TYPE=es father-build" 27 | }, 28 | "browserslist": [ 29 | "last 2 versions", 30 | "Firefox ESR", 31 | "> 1%", 32 | "ie >= 11" 33 | ], 34 | "dependencies": { 35 | "@babel/runtime": "^7.16.3", 36 | "@vis/charts": "workspace:*", 37 | "@vis/utils": "workspace:*" 38 | }, 39 | "peerDependencies": { 40 | "antd": ">=4.20.0", 41 | "react": ">=16.9.0", 42 | "react-dom": ">=16.9.0" 43 | }, 44 | "publishConfig": { 45 | "access": "public", 46 | "registry": "http://xxx.xxx.xxx.xxx:xxxx/" 47 | }, 48 | "authors": [] 49 | } 50 | -------------------------------------------------------------------------------- /packages/test/src/index.module.less: -------------------------------------------------------------------------------- 1 | @vis-test-prefix-cls: ~'vis-test'; 2 | 3 | .@{vis-test-prefix-cls} { 4 | } 5 | -------------------------------------------------------------------------------- /packages/test/src/index.tsx: -------------------------------------------------------------------------------- 1 | import { ProForm, ProFormText } from '@ant-design/pro-components'; 2 | import { isBrowser, nanoid } from '@vis/utils'; 3 | import { ConfigProvider } from 'antd'; 4 | import { useContext } from 'react'; 5 | import './index.module.less'; 6 | import { BasicRingPie } from '@vis/charts' 7 | 8 | export const Test = () => { 9 | console.log(isBrowser()); 10 | const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); 11 | const prefix = getPrefixCls('vis-test'); 12 | 13 | // 测试环形饼图配置 14 | const pieData = [ 15 | { 16 | name: 'www', 17 | value: 20 18 | },{ 19 | name: 'eee', 20 | value: 30 21 | } 22 | ] 23 | const pieConfig = { 24 | data: pieData 25 | } 26 | 27 | return ( 28 |

29 | {nanoid()}--testComp 30 | 31 | 32 | 33 | {/* 环形饼图 */} 34 | 35 |

36 | ); 37 | }; 38 | export default Test; 39 | -------------------------------------------------------------------------------- /packages/test/src/test.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: test-测试组件 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | # @vis/test 11 | 12 | > @vis/test. 13 | 14 | See our website [@vis/test](https://umijs.org/plugins/test) for more information. 15 | 16 | ## Install 17 | 18 | Using npm: 19 | 20 | ```bash 21 | $ npm install --save @vis/test --registry http://xxx.xxx.xxx.xxx:xxxx/ 22 | ``` 23 | 24 | or using yarn: 25 | 26 | ```bash 27 | $ yarn add @vis/test --registry http://xxx.xxx.xxx.xxx:xxxx/ 28 | ``` 29 | 30 | 测试组件描述 31 | 32 | ```jsx 33 | import React from 'react'; 34 | import { Test } from '@vis/test'; 35 | export default () => { 36 | return ( 37 |

38 | 自定义渲染代码块update 39 | 40 |

41 | ); 42 | }; 43 | ``` 44 | -------------------------------------------------------------------------------- /packages/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "esnext", 5 | "lib": ["dom", "esnext"], 6 | "importHelpers": true, 7 | "declaration": true, 8 | "sourceMap": true, 9 | "skipLibCheck": true, 10 | "rootDir": "./", 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "baseUrl": "./", 24 | "paths": { 25 | "*": ["src/*", "node_modules/*"] 26 | }, 27 | "jsx": "react-jsx", 28 | "esModuleInterop": true 29 | }, 30 | "include": [ 31 | "src", 32 | ], 33 | "exclude": [ 34 | "node_modules", 35 | "build", 36 | "public", 37 | "lib" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /packages/utils/.fatherrc.ts: -------------------------------------------------------------------------------- 1 | 2 | const type = process.env.BUILD_TYPE; 3 | 4 | let config = {}; 5 | 6 | if (type === 'lib') { 7 | config = { 8 | cjs: { type: 'babel', lazy: true }, 9 | esm: false, 10 | runtimeHelpers: true, 11 | extraBabelPlugins: [ 12 | [ 13 | 'babel-plugin-import', 14 | { libraryName: 'antd', libraryDirectory: 'lib', style: true }, 15 | 'antd', 16 | ], 17 | ], 18 | }; 19 | } 20 | 21 | if (type === 'es') { 22 | config = { 23 | 24 | cjs: false, 25 | esm: { 26 | type: 'babel', 27 | }, 28 | runtimeHelpers: true, 29 | extraBabelPlugins: [ 30 | [require('./../../scripts/replaceLib')], 31 | ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'antd'], 32 | ], 33 | }; 34 | } 35 | 36 | export default config; 37 | -------------------------------------------------------------------------------- /packages/utils/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: utils-工具函数库 3 | group: 4 | path: / 5 | nav: 6 | title: 7 | path: /components 8 | --- 9 | 10 | # @vis/utils 11 | 12 | > @vis/utils. 13 | 14 | See our website [@ant-design/pro-utils](https://procomponent.ant.design/) for more information. 15 | 16 | ## Install 17 | 18 | Using npm: 19 | 20 | ```bash 21 | $ npm install --save @vis/utils --registry http://xxx.xxx.xxx.xxx:xxxx/ 22 | ``` 23 | 24 | or using yarn: 25 | 26 | ```bash 27 | $ yarn add @vis/utils --registry http://xxx.xxx.xxx.xxx:xxxx/ 28 | ``` 29 | 30 | ## nanoid 31 | 32 | 用来生成唯一不重复 ID 33 | 34 | ```jsx 35 | import { nanoid } from '@vis/utils'; 36 | import { Button } from 'antd'; 37 | import React from 'react'; 38 | export default () => { 39 | return ( 40 | 47 | ); 48 | }; 49 | ``` 50 | -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis/utils", 3 | "version": "0.0.0", 4 | "description": "@vis/utils", 5 | "keywords": [ 6 | "antd", 7 | "admin", 8 | "ant-design", 9 | "ant-design-pro" 10 | ], 11 | "homepage": "https://github.com/ant-design/pro-components/tree/master/packages/utils#readme", 12 | "bugs": "http://github.com/umijs/plugins/issues", 13 | "repository": { 14 | "type": "git", 15 | "url": "http://xxx.xxx.xxx.xx/ssa-vis/vis-components/Index/" 16 | }, 17 | "license": "MIT", 18 | "sideEffects": [ 19 | "*.less" 20 | ], 21 | "scripts": { 22 | "build": "cross-env BUILD_TYPE=es father-build" 23 | }, 24 | "main": "dist/index.js", 25 | "module": "es/index.js", 26 | "types": "es/index.d.ts", 27 | "files": [ 28 | "lib", 29 | "dist", 30 | "es" 31 | ], 32 | "browserslist": [ 33 | "last 2 versions", 34 | "Firefox ESR", 35 | "> 1%", 36 | "ie >= 11" 37 | ], 38 | "dependencies": { 39 | "@babel/runtime": "^7.18.0", 40 | "lodash": "^4.17.21" 41 | }, 42 | "devDependencies": { 43 | "@types/crypto-js": "^4.1.1", 44 | "@types/lodash": "^4.14.182" 45 | }, 46 | "peerDependencies": { 47 | "react": ">=16.9.0", 48 | "react-dom": ">=16.9.0" 49 | }, 50 | "publishConfig": { 51 | "access": "public", 52 | "registry": "http://xxx.xxx.xxx.xxx:xxxx/" 53 | }, 54 | "authors": [] 55 | } 56 | -------------------------------------------------------------------------------- /packages/utils/src/SnowFlake/index.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | export default function Snowflake (_workerId, _dataCenterId, _sequence) { 3 | this.twepoch = 1288834974657n 4 | // this.twepoch = 0n; 5 | this.workerIdBits = 5n 6 | this.dataCenterIdBits = 5n 7 | this.maxWrokerId = -1n ^ (-1n << this.workerIdBits) // 值为:31 8 | this.maxDataCenterId = -1n ^ (-1n << this.dataCenterIdBits) // 值为:31 9 | this.sequenceBits = 12n 10 | this.workerIdShift = this.sequenceBits // 值为:12 11 | this.dataCenterIdShift = this.sequenceBits + this.workerIdBits // 值为:17 12 | this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits // 值为:22 13 | this.sequenceMask = -1n ^ (-1n << this.sequenceBits) // 值为:4095 14 | this.lastTimestamp = -1n 15 | // 设置默认值,从环境变量取 16 | this.workerId = 1n 17 | this.dataCenterId = 1n 18 | this.sequence = 0n 19 | if (this.workerId > this.maxWrokerId || this.workerId < 0) { 20 | throw new Error('_workerId must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']') 21 | } 22 | if (this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) { 23 | throw new Error('_dataCenterId must max than 0 and small than maxDataCenterId-[' + this.maxDataCenterId + ']') 24 | } 25 | 26 | this.workerId = window.BigInt(_workerId) 27 | this.dataCenterId = window.BigInt(_dataCenterId) 28 | this.sequence = window.BigInt(_sequence) 29 | } 30 | Snowflake.prototype.tilNextMillis = function (lastTimestamp) { 31 | let timestamp = this.timeGen() 32 | while (timestamp <= lastTimestamp) { 33 | timestamp = this.timeGen() 34 | } 35 | return window.BigInt(timestamp) 36 | } 37 | Snowflake.prototype.timeGen = function () { 38 | return window.BigInt(Date.now()) 39 | } 40 | Snowflake.prototype.nextId = function () { 41 | let timestamp = this.timeGen() 42 | if (timestamp < this.lastTimestamp) { 43 | throw new Error('Clock moved backwards. Refusing to generate id for ' + 44 | (this.lastTimestamp - timestamp)) 45 | } 46 | if (this.lastTimestamp === timestamp) { 47 | this.sequence = (this.sequence + 1n) & this.sequenceMask 48 | if (this.sequence === 0n) { 49 | timestamp = this.tilNextMillis(this.lastTimestamp) 50 | } 51 | } else { 52 | this.sequence = 0n 53 | } 54 | this.lastTimestamp = timestamp 55 | return ((timestamp - this.twepoch) << this.timestampLeftShift) | 56 | (this.dataCenterId << this.dataCenterIdShift) | 57 | (this.workerId << this.workerIdShift) | 58 | this.sequence 59 | } 60 | 61 | -------------------------------------------------------------------------------- /packages/utils/src/aes/index.ts: -------------------------------------------------------------------------------- 1 | import Crypto from 'crypto-js' 2 | 3 | const SECRET_PASSHARASE = Crypto.enc.Utf8.parse('xB0K5MBLChA+cYgTJB6FtAbf1Y5uh6nZ') 4 | const AES_PARAMS = { mode: Crypto.mode.ECB, padding: Crypto.pad.Pkcs7 } 5 | 6 | export function encryptMsg (msg: string) { 7 | const encrypted = Crypto.AES.encrypt(Crypto.enc.Utf8.parse(msg), SECRET_PASSHARASE, AES_PARAMS) 8 | return encrypted.toString() 9 | } 10 | 11 | export function decryptContext (context: string) { 12 | const decryptResult = Crypto.AES.decrypt(context, SECRET_PASSHARASE, AES_PARAMS) 13 | return decryptResult.toString(Crypto.enc.Utf8).toString() 14 | } 15 | 16 | -------------------------------------------------------------------------------- /packages/utils/src/dataTransform/index.ts: -------------------------------------------------------------------------------- 1 | export type StandardDataType = { 2 | columnList: Array<{ 3 | alias: string; 4 | name: string; 5 | }>; 6 | data: any[][]; 7 | }; 8 | 9 | export const transformList2Standard = ( 10 | standardData: StandardDataType, 11 | ): Array> => { 12 | const { columnList, data } = standardData; 13 | const ret: Array> = []; 14 | console.log(data); 15 | data?.forEach((i) => { 16 | const temp: any = {}; 17 | i.forEach((j, jdx) => { 18 | temp[columnList[jdx].alias] = j; 19 | }); 20 | ret.push(temp); 21 | }); 22 | return ret; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/utils/src/dateArrayFormatter/index.tsx: -------------------------------------------------------------------------------- 1 | import type { Dayjs } from 'dayjs'; 2 | import dayjs from 'dayjs'; 3 | 4 | type FormatType = ((dayjs: Dayjs) => string) | string; 5 | 6 | const formatString = (endText: any, format: FormatType) => { 7 | if (typeof format === 'function') { 8 | return format(dayjs(endText)); 9 | } 10 | return dayjs(endText).format(format); 11 | }; 12 | 13 | /** 14 | * 格式化区域日期 15 | * 16 | * @param value 17 | */ 18 | const dateArrayFormatter = ( 19 | value: any[], 20 | format: FormatType | FormatType[], 21 | ) => { 22 | const [startText, endText] = Array.isArray(value) ? value : []; 23 | 24 | let formatFirst: FormatType; 25 | let formatEnd: FormatType; 26 | 27 | if (Array.isArray(format)) { 28 | formatFirst = format[0]; 29 | formatEnd = format[1]; 30 | } else { 31 | formatFirst = format; 32 | formatEnd = format; 33 | } 34 | 35 | // activePickerIndex for https://github.com/ant-design/ant-design/issues/22158 36 | const parsedStartText: string = startText 37 | ? formatString(startText, formatFirst) 38 | : ''; 39 | const parsedEndText: string = endText ? formatString(endText, formatEnd) : ''; 40 | const valueStr: string = 41 | parsedStartText && parsedEndText 42 | ? `${parsedStartText} ~ ${parsedEndText}` 43 | : ''; 44 | 45 | return valueStr; 46 | }; 47 | 48 | export default dateArrayFormatter; 49 | -------------------------------------------------------------------------------- /packages/utils/src/genCopyable/index.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from 'antd'; 2 | import React from 'react'; 3 | 4 | const isNeedTranText = (item: any): boolean => { 5 | if (item?.valueType?.toString().startsWith('date')) { 6 | return true; 7 | } 8 | if (item?.valueType === 'select' || item?.valueEnum) { 9 | return true; 10 | } 11 | return false; 12 | }; 13 | 14 | /** 15 | * 生成 Copyable 或 Ellipsis 的 dom 16 | * 17 | * @param dom 18 | * @param item 19 | * @param text 20 | */ 21 | export const genCopyable = (dom: React.ReactNode, item: any, text: string) => { 22 | if (item.copyable || item.ellipsis) { 23 | const copyable = 24 | item.copyable && text 25 | ? { 26 | text, 27 | tooltips: ['', ''], 28 | } 29 | : undefined; 30 | 31 | /** 有些 valueType 需要设置copy的为string */ 32 | const needTranText = isNeedTranText(item); 33 | 34 | const ellipsis = 35 | item.ellipsis && text 36 | ? { 37 | tooltip: needTranText ?
{dom}
: text, 38 | } 39 | : false; 40 | return ( 41 | 51 | {dom} 52 | 53 | ); 54 | } 55 | return dom; 56 | }; 57 | -------------------------------------------------------------------------------- /packages/utils/src/index.tsx: -------------------------------------------------------------------------------- 1 | import dateArrayFormatter from './dateArrayFormatter'; 2 | import { genCopyable } from './genCopyable'; 3 | import isBrowser from './isBrowser'; 4 | import isDeepEqualReact from './isDeepEqualReact'; 5 | import isImg from './isImg'; 6 | import isUrl from './isUrl'; 7 | import { nanoid } from './nanoid'; 8 | import parseValueToMoment from './parseValueToMoment'; 9 | import { runFunction } from './runFunction'; 10 | import { observerDomResize } from './observerDomResize'; 11 | import useAutoResize from './useAutoResize'; 12 | import rsa, { 13 | DEFAULT_PUBLIC_KEY, 14 | PASSWORD_PUBLIC_KEY, 15 | JWT_PUBLIC_KEY, 16 | } from './rsa'; 17 | import { matchString } from './matchString'; 18 | import SnowFlake from './SnowFlake'; 19 | import { encryptMsg, decryptContext } from './aes'; 20 | import { transformList2Standard, StandardDataType } from './dataTransform'; 21 | import { stringLikely, similarity } from "./stringLikely"; 22 | /** Type */ 23 | import type { 24 | ProFieldProps, 25 | ProFieldRequestData, 26 | ProFieldTextType, 27 | ProFieldValueEnumType, 28 | ProFieldValueObjectType, 29 | ProSchemaValueEnumMap, 30 | ProSchemaValueEnumObj, 31 | ProTableEditableFnType, 32 | RequestOptionsType, 33 | SearchConvertKeyFn, 34 | SearchTransformKeyFn, 35 | } from './typing'; 36 | 37 | import { isNumber, numberFormat, unitConvert } from './unit'; 38 | 39 | export type { 40 | SearchConvertKeyFn, 41 | RequestOptionsType, 42 | ProSchemaValueEnumMap, 43 | ProSchemaValueEnumObj, 44 | SearchTransformKeyFn, 45 | ProTableEditableFnType, 46 | ProFieldRequestData, 47 | ProFieldTextType, 48 | ProFieldValueEnumType, 49 | ProFieldValueObjectType, 50 | ProFieldProps, 51 | StandardDataType, 52 | }; 53 | export { 54 | SnowFlake, 55 | isDeepEqualReact, 56 | parseValueToMoment, 57 | genCopyable, 58 | isImg, 59 | matchString, 60 | isUrl, 61 | isBrowser, 62 | runFunction, 63 | dateArrayFormatter, 64 | nanoid, 65 | observerDomResize, 66 | useAutoResize, 67 | stringLikely, 68 | rsa, 69 | DEFAULT_PUBLIC_KEY, 70 | PASSWORD_PUBLIC_KEY, 71 | JWT_PUBLIC_KEY, 72 | encryptMsg, 73 | decryptContext, 74 | transformList2Standard, 75 | unitConvert, 76 | isNumber, 77 | numberFormat, 78 | similarity 79 | }; 80 | -------------------------------------------------------------------------------- /packages/utils/src/isBrowser/index.ts: -------------------------------------------------------------------------------- 1 | const isNode = 2 | typeof process !== 'undefined' && process.versions != null && process.versions.node != null; 3 | 4 | const isBrowser = () => { 5 | if (process.env.NODE_ENV === 'TEST') { 6 | return true; 7 | } 8 | return ( 9 | typeof window !== 'undefined' && 10 | typeof window.document !== 'undefined' && 11 | typeof window.matchMedia !== 'undefined' && 12 | !isNode 13 | ); 14 | }; 15 | 16 | export default isBrowser; 17 | -------------------------------------------------------------------------------- /packages/utils/src/isImg/index.ts: -------------------------------------------------------------------------------- 1 | /** 判断是否是图片链接 */ 2 | function isImg(path: string): boolean { 3 | return /\w.(png|jpg|jpeg|svg|webp|gif|bmp)$/i.test(path); 4 | } 5 | 6 | export default isImg; 7 | -------------------------------------------------------------------------------- /packages/utils/src/isUrl/index.ts: -------------------------------------------------------------------------------- 1 | const isUrl = (path: string | undefined): boolean => { 2 | if (!path) return false; 3 | if (!path.startsWith('http')) { 4 | return false; 5 | } 6 | try { 7 | const url = new URL(path); 8 | return !!url; 9 | } catch (error) { 10 | return false; 11 | } 12 | }; 13 | 14 | export default isUrl; 15 | -------------------------------------------------------------------------------- /packages/utils/src/matchString/index.tsx: -------------------------------------------------------------------------------- 1 | 2 | export const matchString = function (s: string, p: string) { 3 | // 构造 dp 函数 4 | let dp = [] 5 | for (let i = 0; i <= s.length; i++) { 6 | let child = [] 7 | for (let j = 0; j <= p.length; j++) { 8 | child.push(false) 9 | } 10 | dp.push(child) 11 | } 12 | dp[s.length][p.length] = true 13 | // 执行 14 | for (let i = p.length - 1; i >= 0; i--) { 15 | if (p[i] != "*") break 16 | else dp[s.length][i] = true 17 | } 18 | 19 | for (let i = s.length - 1; i >= 0; i--) { 20 | for (let j = p.length - 1; j >= 0; j--) { 21 | if (s[i] == p[j] || p[j] == "?") { 22 | dp[i][j] = dp[i + 1][j + 1] 23 | } else if (p[j] == "*") { 24 | dp[i][j] = dp[i + 1][j] || dp[i][j + 1] 25 | } else { 26 | dp[i][j] = false 27 | } 28 | } 29 | } 30 | return dp[0][0] 31 | } 32 | -------------------------------------------------------------------------------- /packages/utils/src/nanoid/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-nested-ternary */ 2 | /* eslint-disable prefer-const */ 3 | 4 | let index = 0; 5 | let genNanoid = (t = 21) => { 6 | if (!window.crypto) { 7 | index++; 8 | return index.toFixed(0); 9 | } 10 | let e = ''; 11 | let r = crypto.getRandomValues(new Uint8Array(t)); 12 | // eslint-disable-next-line no-param-reassign 13 | for (; t--;) { 14 | let n = 63 & r[t]; 15 | e += 16 | n < 36 ? n.toString(36) : n < 62 ? (n - 26).toString(36).toUpperCase() : n < 63 ? '_' : '-'; 17 | } 18 | return e; 19 | }; 20 | 21 | /** 22 | * 生成uuid,如果不支持 randomUUID,就用 genNanoid 23 | * 24 | * @returns 25 | */ 26 | export const nanoid = (): string => { 27 | if (typeof window === 'undefined') return genNanoid(); 28 | // @ts-ignore 29 | if (window.crypto && window.crypto.randomUUID && typeof crypto.randomUUID === 'function') { 30 | // @ts-ignore 31 | return crypto.randomUUID(); 32 | } 33 | return genNanoid(); 34 | }; 35 | -------------------------------------------------------------------------------- /packages/utils/src/observerDomResize/index.tsx: -------------------------------------------------------------------------------- 1 | export function observerDomResize(dom: HTMLElement, callback: any) { 2 | const MutationObserver = window.MutationObserver 3 | 4 | const observer = new MutationObserver(callback) 5 | 6 | observer.observe(dom, { 7 | attributes: true, 8 | attributeFilter: ['style'], 9 | attributeOldValue: true 10 | }) 11 | 12 | return observer 13 | } 14 | -------------------------------------------------------------------------------- /packages/utils/src/parseValueToMoment/index.ts: -------------------------------------------------------------------------------- 1 | import dayjs, { Dayjs } from 'dayjs'; 2 | 3 | type DateValue = Dayjs | Dayjs[] | string | string[] | number | number[]; 4 | 5 | const parseValueToMoment = ( 6 | value: DateValue, 7 | formatter?: string, 8 | ): Dayjs | Dayjs[] | null | undefined => { 9 | if (Array.isArray(value)) { 10 | return (value as any[]).map( 11 | (v) => parseValueToMoment(v, formatter) as Dayjs, 12 | ); 13 | } 14 | if (typeof value === 'number') return dayjs(value); 15 | return dayjs(value, formatter); 16 | }; 17 | 18 | export default parseValueToMoment; 19 | -------------------------------------------------------------------------------- /packages/utils/src/rsa/index.ts: -------------------------------------------------------------------------------- 1 | import JSEncrypt from 'jsencrypt' 2 | const publicKey = 3 | 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCGBBujBtavj/ZyaUo207utO/D15NA0zjJnlCTrxmRFZvcN126vwfPgdDVFTcKg79YnwWHpFHki0zLTPSjw6BB+7DixpKVGayzSiD1riVFlmCqxQWXTueK/F6M5SZ/5weU2JwmBb8YEP93AIrsOOUnnteBGWc1JqNuLCCqG121QSQIDAQAB' 4 | const pwdkey = 5 | 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChDnCJSDnLdKrK5QBv7hb+QNIWiC2slLOeWYUQ' + 6 | 'hA7DKYKp7f6aKmWFE7mDRnA/LUoo26yxEJcfT9Wt2CzMmrjnRQDT3BmJxlWBHul90Hv1dMVdkrDn' + 7 | '+dP7uXLLeiT4NFwbhLRMVYrMaXSdRDaRAG6g6oDIJfPM24XvBVZf3a/J7wIDAQAB' 8 | 9 | export const encrypt = { 10 | encrypt(str: string, key = publicKey): string | false { 11 | const jsEncrypt = new JSEncrypt(); 12 | jsEncrypt.setPublicKey(key); 13 | return jsEncrypt.encrypt(str); 14 | }, 15 | encryptByPwdkey(str: string) { 16 | const jsEncrypt = new JSEncrypt(); 17 | jsEncrypt.setPublicKey(pwdkey); 18 | const encrypted = jsEncrypt.encrypt(str); 19 | return encrypted; 20 | }, 21 | } 22 | 23 | export default encrypt 24 | export const DEFAULT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCGBBujBtavj/ZyaUo207utO/D15NA0zjJnlCTrxmRFZvcN126vwfPgdDVFTcKg79YnwWHpFHki0zLTPSjw6BB+7DixpKVGayzSiD1riVFlmCqxQWXTueK/F6M5SZ/5weU2JwmBb8YEP93AIrsOOUnnteBGWc1JqNuLCCqG121QSQIDAQAB"; 25 | export const JWT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCNS+vq/8w8OVqpHTeYBZZBIFrEw/2C67jUCuUYj4zzgh670o99SWjkHmhN0bNwKylj4UpGMTmlOijUYl5yM7EFcr8ID7//r8xVZCtANa9nHtBKdQux7yP2HYnJ6zQtM4tmAXqwXN3iK/xb+b/gMUNg4bzf/VPO0QZuMaBmuU2DhQIDAQAB"; 26 | export const PASSWORD_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhYnRwe8HIQQ3uvZYSVfJx5DyEMQITHFnwkagbh32Sosjf3xmh5oOVxZeihUzzH3wLAGUwAjYj7OOmKfmNYSIf1UTRttzgamSiRVUn8vFgt4VTVoOluVIawzYeCu4tODgwJDqajR3T0Hx3bv87YFHE5ZX28VIhEP0eQHXlkzf0TQIDAQAB"; 27 | -------------------------------------------------------------------------------- /packages/utils/src/runFunction/index.ts: -------------------------------------------------------------------------------- 1 | /** 如果是个方法执行一下它 */ 2 | export function runFunction(valueEnum: any, ...rest: T) { 3 | if (typeof valueEnum === 'function') { 4 | return valueEnum(...rest); 5 | } 6 | return valueEnum; 7 | } 8 | -------------------------------------------------------------------------------- /packages/utils/src/stringLikely/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | export function stringLikely(s1: string, s2: string) { 3 | s1 = s1.toLowerCase(); 4 | s2 = s2.toLowerCase(); 5 | 6 | let costs = []; 7 | for (let i = 0; i <= s1.length; i++) { 8 | let lastValue = i; 9 | for (let j = 0; j <= s2.length; j++) { 10 | if (i === 0) 11 | costs[j] = j; 12 | else { 13 | if (j > 0) { 14 | let newValue = costs[j - 1]; 15 | if (s1.charAt(i - 1) !== s2.charAt(j - 1)) 16 | newValue = Math.min(Math.min(newValue, lastValue), 17 | costs[j]) + 1; 18 | costs[j - 1] = lastValue; 19 | lastValue = newValue; 20 | } 21 | } 22 | } 23 | if (i > 0) 24 | costs[s2.length] = lastValue; 25 | } 26 | return costs[s2.length]; 27 | } 28 | export function similarity(s1: string, s2: string) { 29 | let longer: string = s1; 30 | let shorter: string = s2; 31 | if (s1.length < s2.length) { 32 | longer = s2; 33 | shorter = s1; 34 | } 35 | const longerLength = longer.length; 36 | if (longerLength === 0) { 37 | return 1.0; 38 | } 39 | return (longerLength - stringLikely(longer, shorter)) / parseFloat(String(longerLength)); 40 | } 41 | -------------------------------------------------------------------------------- /packages/utils/src/typing.ts: -------------------------------------------------------------------------------- 1 | import type { NamePath } from 'antd/lib/form/interface'; 2 | import type { ReactNode } from 'react'; 3 | 4 | export type PageInfo = { 5 | pageSize: number; 6 | total: number; 7 | current: number; 8 | }; 9 | 10 | export type RequestOptionsType = { 11 | label?: React.ReactNode; 12 | value?: React.ReactText; 13 | /** 渲染的节点类型 */ 14 | optionType?: 'optGroup' | 'option'; 15 | options?: Omit[]; 16 | [key: string]: any; 17 | }; 18 | 19 | export type ProFieldRequestData = (params: U, props: any) => Promise; 20 | 21 | export type ProFieldValueEnumType = ProSchemaValueEnumMap | ProSchemaValueEnumObj; 22 | 23 | export type ProFieldValueObjectType = { 24 | type: 'progress' | 'money' | 'percent' | 'image'; 25 | status?: 'normal' | 'active' | 'success' | 'exception' | undefined; 26 | locale?: string; 27 | /** Percent */ 28 | showSymbol?: ((value: any) => boolean) | boolean; 29 | showColor?: boolean; 30 | precision?: number; 31 | moneySymbol?: boolean; 32 | request?: ProFieldRequestData; 33 | /** Image */ 34 | width?: number; 35 | }; 36 | 37 | export type ProSchemaValueEnumType = { 38 | /** @name 演示的文案 */ 39 | text: ReactNode; 40 | 41 | /** @name 预定的颜色 */ 42 | status?: string; 43 | /** @name 自定义的颜色 */ 44 | color?: string; 45 | /** @name 是否禁用 */ 46 | disabled?: boolean; 47 | }; 48 | 49 | /** 50 | * 支持 Map 和 Record 51 | * 52 | * @name ValueEnum 的类型 53 | */ 54 | export type ProSchemaValueEnumMap = Map; 55 | 56 | export type ProSchemaValueEnumObj = Record; 57 | 58 | export type ProFieldTextType = 59 | | React.ReactNode 60 | | React.ReactNode[] 61 | | Record 62 | | Record[]; 63 | 64 | export type SearchTransformKeyFn = ( 65 | value: any, 66 | namePath: string, 67 | allValues: any, 68 | ) => string | Record; 69 | export type SearchConvertKeyFn = (value: any, field: NamePath) => string | Record; 70 | 71 | export type ProTableEditableFnType = (value: any, record: T, index: number) => boolean; 72 | 73 | // 支持的变形,还未完全支持完毕 74 | /** 支持的变形,还未完全支持完毕 */ 75 | export type ProSchemaComponentTypes = 76 | | 'form' 77 | | 'list' 78 | | 'descriptions' 79 | | 'table' 80 | | 'cardList' 81 | | undefined; 82 | 83 | export interface ProFieldProps { 84 | light?: boolean; 85 | emptyText?: ReactNode; 86 | label?: React.ReactNode; 87 | mode?: 'read' | 'edit'; 88 | /** 这个属性可以设置useSwr的key */ 89 | proFieldKey?: string; 90 | render?: any; 91 | readonly?: boolean; 92 | } 93 | -------------------------------------------------------------------------------- /packages/utils/src/unit/index.ts: -------------------------------------------------------------------------------- 1 | export const strNumSize = (tempNum: string | number) => { 2 | const stringNum = tempNum.toString(); 3 | const index = stringNum.indexOf('.'); 4 | let newNum = stringNum; 5 | if (index !== -1) { 6 | newNum = stringNum.substring(0, index); 7 | } 8 | return newNum.length; 9 | }; 10 | export const isToFixedFun = (currentNum: number, dividend: number) => { 11 | const numStr = String(currentNum); 12 | return currentNum < dividend && !numStr.includes('.'); 13 | }; 14 | // 数字转化为带单位 15 | export const unitConvert = (num: number, length = 0) => { 16 | if (num !== undefined) { 17 | const moneyUnits = ['', '万', '亿', '万亿']; 18 | const dividend = 10000; 19 | let currentNum = Number(num); 20 | const isToFixed = isToFixedFun(currentNum, dividend); // 小于10000不带小数点的数字 不转换小数点 21 | if (isNaN(currentNum)) { 22 | return { num: '', unit: '' }; 23 | } 24 | // 转换数字 25 | let currentUnit = moneyUnits[0]; 26 | // 转换单位 27 | for (let i = 0; i < 4; i++) { 28 | currentUnit = moneyUnits[i]; 29 | if (strNumSize(currentNum) < 5) { 30 | break; 31 | } 32 | currentNum /= dividend; 33 | } 34 | return { 35 | // eslint-disable-next-line no-nested-ternary 36 | num: 37 | num === 0 38 | ? currentNum 39 | : isToFixed 40 | ? currentNum 41 | : currentNum.toFixed(length), 42 | unit: currentUnit, 43 | }; 44 | } 45 | return false; 46 | }; 47 | export const isNumber = (val: any) => { 48 | return typeof val !== 'boolean' && typeof +val === 'number' && !isNaN(val); 49 | }; 50 | // 数字格式化处理 51 | export const numberFormat = (num: string | undefined, useGrouping = true) => { 52 | let formatNum = num; 53 | if (num && isNumber(num) && useGrouping) { 54 | const splitNum = num.toString().split('.'); 55 | // 整数每3位加","处理 56 | if (splitNum) { 57 | const integer = splitNum[0] 58 | ?.split('') 59 | ?.reverse() 60 | ?.join('') 61 | ?.match(/(\d{1,3})/g) 62 | ?.join(',') 63 | ?.split('') 64 | ?.reverse() 65 | ?.join(''); 66 | formatNum = splitNum[1] ? `${integer}.${splitNum[1]}` : integer; 67 | } 68 | } 69 | return formatNum; 70 | }; 71 | -------------------------------------------------------------------------------- /packages/utils/src/useAutoResize/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback, useEffect, useRef, useImperativeHandle } from 'react' 2 | import debounce from 'lodash/debounce' 3 | import { observerDomResize } from './../observerDomResize' 4 | export default function useAutoResize(ref: React.Ref) { 5 | const [state, setState] = useState({ width: 0, height: 0 }) 6 | 7 | const domRef = useRef(null) 8 | 9 | const setWH = useCallback(() => { 10 | const { clientWidth, clientHeight } = domRef.current || { clientWidth: 0, clientHeight: 0 } 11 | 12 | setState({ width: clientWidth, height: clientHeight }) 13 | 14 | if (!domRef.current) { 15 | console.warn('DataV: Failed to get dom node, component rendering may be abnormal!') 16 | } else if (!clientWidth || !clientHeight) { 17 | console.warn('DataV: Component width or height is 0px, rendering abnormality may occur!') 18 | } 19 | }, []) 20 | 21 | useImperativeHandle(ref, () => ({ setWH }), []) 22 | 23 | useEffect(() => { 24 | const debounceSetWHFun = debounce(setWH, 100) 25 | 26 | debounceSetWHFun() 27 | if(!domRef.current) return 28 | const domObserver = observerDomResize(domRef.current, debounceSetWHFun) 29 | 30 | window.addEventListener('resize', debounceSetWHFun) 31 | 32 | return () => { 33 | window.removeEventListener('resize', debounceSetWHFun) 34 | 35 | if (!domObserver) { 36 | return 37 | } 38 | 39 | domObserver.disconnect() 40 | domObserver.takeRecords() 41 | } 42 | }, []) 43 | 44 | return { ...state, domRef, setWH } 45 | } 46 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "skipLibCheck": true, 4 | "compilerOptions": { 5 | "target": "es6", 6 | "module": "esnext", 7 | "lib": ["dom", "esnext"], 8 | "importHelpers": true, 9 | "declaration": true, 10 | "sourceMap": true, 11 | "skipLibCheck": true, 12 | "rootDir": "./", 13 | "strict": true, 14 | "noImplicitAny": true, 15 | "strictNullChecks": true, 16 | "strictFunctionTypes": true, 17 | "strictPropertyInitialization": true, 18 | "noImplicitThis": true, 19 | "alwaysStrict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noImplicitReturns": true, 23 | "noFallthroughCasesInSwitch": true, 24 | "moduleResolution": "node", 25 | "baseUrl": "./", 26 | "paths": { 27 | "*": ["src/*", "node_modules/*"] 28 | }, 29 | "jsx": "react-jsx", 30 | "esModuleInterop": true 31 | }, 32 | "include": [ 33 | "src", 34 | ], 35 | "exclude": [ 36 | "node_modules", 37 | "build", 38 | "public", 39 | "lib" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - 'features/*' 4 | - 'projects/*' 5 | 6 | -------------------------------------------------------------------------------- /projects/template/.eslintignore: -------------------------------------------------------------------------------- 1 | # 忽略目录 2 | build/ 3 | tests/ 4 | demo/ 5 | 6 | # node 覆盖率文件 7 | coverage/ 8 | 9 | # 忽略文件 10 | **/*-min.js 11 | **/*.min.js 12 | -------------------------------------------------------------------------------- /projects/template/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # production 7 | /build 8 | /dist 9 | 10 | # misc 11 | .idea/ 12 | .happypack 13 | .DS_Store 14 | .ice 15 | .vscode 16 | .yalc/ 17 | npm-debug.log* 18 | yarn-debug.log* 19 | yarn-error.log* 20 | -------------------------------------------------------------------------------- /projects/template/.prettierignore: -------------------------------------------------------------------------------- 1 | build/ 2 | tests/ 3 | demo/ 4 | .ice/ 5 | coverage/ 6 | **/*-min.js 7 | **/*.min.js 8 | package-lock.json 9 | yarn.lock -------------------------------------------------------------------------------- /projects/template/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "proseWrap": "never", 6 | "overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }] 7 | } 8 | -------------------------------------------------------------------------------- /projects/template/.stylelintignore: -------------------------------------------------------------------------------- 1 | # 忽略目录 2 | build/ 3 | tests/ 4 | demo/ 5 | 6 | # node 覆盖率文件 7 | coverage/ 8 | -------------------------------------------------------------------------------- /projects/template/.umirc.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import { defineConfig } from '@umijs/max'; 3 | import routes from './src/routes'; 4 | const genAlias = require('../../scripts/utils/genAlias'); 5 | import { antdTheme } from './../../config/theme/tokens'; 6 | import componentTheme from './../../config/theme/component'; 7 | const isDev = process.env.NODE_ENV === 'development'; 8 | export default defineConfig({ 9 | antd: { 10 | import: false, 11 | theme: { 12 | token: antdTheme, 13 | components: componentTheme, 14 | }, 15 | }, 16 | hash: true, 17 | history: { 18 | type: 'hash', 19 | }, 20 | access: {}, 21 | model: {}, 22 | initialState: {}, 23 | mfsu: { 24 | shared: { 25 | react: { 26 | singleton: true, 27 | }, 28 | 'react-router': { 29 | singleton: true, 30 | }, 31 | 'react-router-dom': { 32 | singleton: true, 33 | }, 34 | '@ant-design/pro-components': { 35 | singleton: true, 36 | }, 37 | antd: { 38 | singleton: true, 39 | }, 40 | }, 41 | }, 42 | request: {}, 43 | routes, 44 | npmClient: 'pnpm', 45 | publicPath: isDev ? '/' : '/template/', 46 | plugins: [ 47 | require.resolve('@umijs/plugins/dist/unocss'), 48 | require.resolve('../../config/plugins/cssVarible'), 49 | ], 50 | unocss: { 51 | watch: [ 52 | 'src/**/**.tsx', 53 | 'src/**.tsx', 54 | 'src/**/**/**.tsx', 55 | 'src/**/**/**/**.tsx', 56 | ], 57 | }, 58 | qiankun: { 59 | slave: {}, 60 | }, 61 | proxy: {}, 62 | alias: genAlias(), 63 | }); 64 | -------------------------------------------------------------------------------- /projects/template/README.md: -------------------------------------------------------------------------------- 1 | # umi sub app 2 | 3 | ## 使用 4 | 5 | - 启动调试服务: `npm start` 6 | - 构建 dist: `npm run build` 7 | 8 | ## 目录结构 9 | 10 | - 应用配置: `src/app.js` 11 | - 路由配置: `src/routes.js` 12 | - 布局文件: `src/layouts` 13 | - 通用组件: `src/components` 14 | - 页面文件: `src/pages` 15 | 16 | 17 | -------------------------------------------------------------------------------- /projects/template/mock/index.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | // 同时支持 GET 和 POST 3 | '/api/users/1': { data: {} }, 4 | '/api/foo/bar': { data: {} }, 5 | 6 | // 支持标准 HTTP 7 | 'POST /api/table': { 8 | code: 200, 9 | total: 20, 10 | data: { 11 | columnList: [ 12 | { 13 | alias: 'name', 14 | name: 'name', 15 | }, 16 | { 17 | alias: 'value', 18 | name: 'value', 19 | }, 20 | ], 21 | data: [ 22 | [ 23 | 'CPU异常', 24 | 15, 25 | ], 26 | [ 27 | '磁盘异常', 28 | 3, 29 | ], 30 | [ 31 | '内存异常', 32 | 5, 33 | ], 34 | [ 35 | '磁盘', 36 | 3, 37 | ], 38 | [ 39 | '内存', 40 | 5, 41 | ], 42 | ], 43 | }, 44 | size: 10, 45 | }, 46 | 'POST /api/data': { 47 | code: 200, 48 | data: { 49 | columnList: [ 50 | { 51 | alias: 'name', 52 | name: 'name', 53 | }, 54 | { 55 | alias: 'value', 56 | name: 'value', 57 | }, 58 | ], 59 | data: [ 60 | [ 61 | 'CPU异常', 62 | 15, 63 | ], 64 | [ 65 | '磁盘异常', 66 | 3, 67 | ], 68 | [ 69 | '内存异常', 70 | 5, 71 | ], 72 | [ 73 | '磁盘', 74 | 3, 75 | ], 76 | [ 77 | '内存', 78 | 5, 79 | ], 80 | ], 81 | }, 82 | }, 83 | 'DELETE /api/users': { users: [1, 2] }, 84 | 85 | }; 86 | -------------------------------------------------------------------------------- /projects/template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis/template", 3 | "version": "0.1.0", 4 | "description": "微前端 + 部署 + package热更新 方案 的子应用模板,用于快速初始化微应用", 5 | "dependencies": {}, 6 | "devDependencies": { 7 | "@unocss/cli": "^0.48.4" 8 | }, 9 | "resolutions": { 10 | "react": ">=18.2.0", 11 | "react-dom": ">=18.2.0", 12 | "@types/react": ">=18.0.25", 13 | "@types/react-dom": ">=18.0.9", 14 | "antd": ">=5.1.4" 15 | }, 16 | "peerDependencies": {}, 17 | "scripts": { 18 | "dev": " cross-env SOCKET_SERVER=http://localhost:7779/ PORT=7779 max dev", 19 | "build": "max build", 20 | "format": "prettier --cache --write src/*" 21 | }, 22 | "repository": { 23 | "type": "git" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /projects/template/src/apis/dashboard.ts: -------------------------------------------------------------------------------- 1 | // 仪表板管理 2 | export const UPDATE = '/vis/dashboard/update'; 3 | export const FIND_ONE_BY_ID = '/vis/dashboard/query/detail'; 4 | export const PAGE_LIST = '/vis/dashboard/query/page'; 5 | export const PUBLISH = '/vis/dashboard/publish'; 6 | export const DELETE_MUTI = '/vis/dashboard/delete'; 7 | export const ADD_ITEM = '/vis/dashboard/add'; 8 | 9 | // 仪表板区块管理 10 | export const BLOCK_ADD = '/vis/dashboard/block/add'; 11 | export const BLOCK_DELETE = '/vis/dashboard/block/delete'; 12 | export const BLOCK_QUERY_ITEM = '/vis/dashboard/block/query/detail'; 13 | export const BLOCK_PAGE = '/vis/dashboard/block/query/page'; 14 | export const BLOCK_UPDATEE = '/vis/dashboard/block/update'; 15 | export const BLOCK_FIND_CATE_LIST = '/vis/dashboard/block/query/page'; 16 | export const BLOCK_COPY = '/vis/dashboard/copy'; 17 | 18 | // 仪表板区块分类管理 19 | export const ADD_CATE_BLOCK = '/vis/dashboard/block/babel/add'; 20 | export const DELETE_CATE_BLOCK = '/vis/dashboard/block/babel/delete'; 21 | export const LIST_CATE_BLOCK = '/vis/dashboard/block/babel/query/list'; 22 | export const UPDATE_CATE_BLOCK = '/vis/dashboard/block/babel/update'; 23 | -------------------------------------------------------------------------------- /projects/template/src/app.tsx: -------------------------------------------------------------------------------- 1 | import { RequestConfig } from '@umijs/max'; 2 | import { notification } from 'antd'; 3 | 4 | // 更多信息见文档:https://next.umijs.org/docs/api/runtime-config#getinitialstate 5 | export async function getInitialState(): Promise { 6 | // 获取用户信息, 权限 7 | return { name: '@umijs/max', username: 'Chencc' }; 8 | } 9 | export const request: RequestConfig = { 10 | timeout: 1000, 11 | requestInterceptors: [], 12 | responseInterceptors: [ 13 | (response) => { 14 | const { data = {} as any } = response; 15 | if (data.code === 200) { 16 | return data; 17 | } 18 | notification.error({ 19 | message: data.message || '请求失败', 20 | }); 21 | return data; 22 | }, 23 | ], 24 | }; 25 | -------------------------------------------------------------------------------- /projects/template/src/components/Error/ErrorBoundary.tsx: -------------------------------------------------------------------------------- 1 | import { Alert } from 'antd'; 2 | import Paragraph from 'antd/lib/typography/Paragraph'; 3 | import React from 'react'; 4 | 5 | class ErrorBoundary extends React.Component< 6 | { children: React.ReactNode; FallBack?: React.ReactNode }, 7 | { 8 | hasError: boolean; 9 | error: { 10 | code: string; 11 | message: string; 12 | }; 13 | } 14 | > { 15 | constructor(props) { 16 | super(props); 17 | this.state = { hasError: false, error: { code: '', message: '' } }; 18 | } 19 | 20 | static getDerivedStateFromError(error) { 21 | // 更新 state 使下一次渲染能够显示降级后的 UI 22 | return { hasError: true, error }; 23 | } 24 | 25 | componentDidCatch(error, errorInfo) { 26 | // 你同样可以将错误日志上报给服务器 27 | } 28 | 29 | render() { 30 | if (this.state.hasError) { 31 | const normalError = ( 32 | {`${this.state.error.code}:${this.state.error.message}`} 38 | } 39 | type="error" 40 | showIcon 41 | /> 42 | ); 43 | if (this.state.error.code === 'MODULE_NOT_FOUND') { 44 | // module no found 优先选择组件穿参降级, 兜底方案使用Alert提示 45 | return this.props.FallBack || normalError; 46 | } else { 47 | return normalError; 48 | } 49 | } 50 | return this.props.children; 51 | } 52 | } 53 | export default ErrorBoundary; 54 | -------------------------------------------------------------------------------- /projects/template/src/constants/other.ts: -------------------------------------------------------------------------------- 1 | export const DRAG_DIRECTION = { 2 | LEFT_RIGHT: 'LEFT_RIGHT', 3 | TOP_BUTTOM: 'TOP_BUTTOM', 4 | RIGHT_LEFT: 'RIGHT_LEFT', 5 | BUTTOM_TOP: 'BUTTOM_TOP', 6 | }; 7 | -------------------------------------------------------------------------------- /projects/template/src/global.less: -------------------------------------------------------------------------------- 1 | #root { 2 | height: 100%; 3 | } 4 | div:has(#root) { 5 | // 包含root的父元素给一个高度 6 | height: 100%; 7 | } 8 | body { 9 | -webkit-font-smoothing: antialiased; 10 | margin: 0; 11 | } 12 | -------------------------------------------------------------------------------- /projects/template/src/layouts/main.tsx: -------------------------------------------------------------------------------- 1 | import { useOutlet } from '@umijs/max'; 2 | export default () => { 3 | const outlet = useOutlet(); 4 | console.log(outlet); 5 | return
{outlet}
; 6 | }; 7 | -------------------------------------------------------------------------------- /projects/template/src/pages/index/Space1.tsx: -------------------------------------------------------------------------------- 1 | import { VisHeader } from '@vis/common'; 2 | import React from 'react'; 3 | import { history } from '@umijs/max'; 4 | 5 | function Space1() { 6 | return ( 7 |
8 |
, 15 | }, 16 | ]} 17 | /> 18 | 25 |
Table View
26 | 27 | ), 28 | }, 29 | { 30 | title: 'SQL视图', 31 | key: '2', 32 | content: ( 33 |
34 |
SQL View
35 |
36 | ), 37 | }, 38 | ]} 39 | tabBarExtraContent={ 40 | history.push('/test')}>🫱点我跳转 41 | } 42 | > 43 | {(item) => { 44 | return
{item?.content}
; 45 | }} 46 |
47 | 48 | ); 49 | } 50 | 51 | export default Space1; 52 | -------------------------------------------------------------------------------- /projects/template/src/pages/index/Space2.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Space2() { 4 | return ( 5 |
6 | Space2 7 |
8 | ); 9 | } 10 | 11 | export default Space2; 12 | -------------------------------------------------------------------------------- /projects/template/src/pages/index/index.module.less: -------------------------------------------------------------------------------- 1 | .container { 2 | height: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /projects/template/src/pages/index/index.tsx: -------------------------------------------------------------------------------- 1 | import styles from './index.module.less'; 2 | import { Workspace } from '@vis/common'; 3 | import { Button } from 'antd'; 4 | import Space1 from './Space1'; 5 | import Space2 from './Space2'; 6 | const HomePage: React.FC = (props) => { 7 | return ( 8 |
9 | 14 | 17 | 18 | 19 | } 20 | breadcrumb={{ 21 | routes: [{ path: '/', breadcrumbName: '子应用', children: [] }], 22 | }} 23 | desc="初始化demo,用来展示workSpace的基本用法, 面包屑只在多层开启,单层需要手动配置" 24 | formProps={{ 25 | size: 'small', 26 | }} 27 | formColumns={[ 28 | { 29 | title: '标题', 30 | dataIndex: 'title', 31 | formItemProps: { 32 | rules: [ 33 | { 34 | required: true, 35 | message: '此项为必填项', 36 | }, 37 | ], 38 | }, 39 | width: 's', 40 | colProps: { 41 | xs: 24, 42 | md: 12, 43 | }, 44 | }, 45 | { 46 | title: '状态', 47 | dataIndex: 'state', 48 | valueType: 'select', 49 | valueEnum: { a: 1, b: 2 }, 50 | width: 's', 51 | colProps: { 52 | xs: 24, 53 | md: 12, 54 | }, 55 | }, 56 | ]} 57 | tabs={[ 58 | { 59 | key: '1', 60 | title: '工作区1', 61 | content: , 62 | }, 63 | { 64 | key: '2', 65 | title: '工作区2', 66 | content: , 67 | }, 68 | ]} 69 | /> 70 |
71 | ); 72 | }; 73 | 74 | export default HomePage; 75 | -------------------------------------------------------------------------------- /projects/template/src/pages/test/index.tsx: -------------------------------------------------------------------------------- 1 | export default () => { 2 | return
Test page
; 3 | }; 4 | -------------------------------------------------------------------------------- /projects/template/src/routes.ts: -------------------------------------------------------------------------------- 1 | const routerConfig = [ 2 | { 3 | path: '/', 4 | name: 'layout', 5 | component: '@/layouts/main', 6 | routes: [ 7 | { 8 | path: '/', 9 | component: './index', 10 | name: 'index', 11 | }, 12 | { 13 | path: '/test', 14 | component: './test', 15 | name: 'test', 16 | }, 17 | ], 18 | }, 19 | ]; 20 | 21 | export default routerConfig; 22 | -------------------------------------------------------------------------------- /projects/template/src/types/framework.ts: -------------------------------------------------------------------------------- 1 | declare interface FrameWorkProps { 2 | count: number; 3 | onChange?: (state: any) => void; 4 | } 5 | -------------------------------------------------------------------------------- /projects/template/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.scss' { 2 | const classes: { [key: string]: string }; 3 | export default classes; 4 | } 5 | 6 | declare module '*.module.less' { 7 | const classes: { [key: string]: string }; 8 | export default classes; 9 | } 10 | 11 | declare module '*.module.css' { 12 | const classes: { [key: string]: string }; 13 | export default classes; 14 | } 15 | declare module '@vis/*' { 16 | const classes: { [key: string]: string }; 17 | export default classes; 18 | } 19 | -------------------------------------------------------------------------------- /projects/template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./src/.umi/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /scripts/buildAdapt.js: -------------------------------------------------------------------------------- 1 | const execa = require('./utils/exec'); 2 | const os = require('os'); 3 | 4 | const path = require('path'); 5 | execa( 6 | `pnpm`, 7 | [ 8 | '--filter', 9 | os.type() === 'Darwin' ? `'./packages/**'` : `./packages/**`, 10 | 'build', 11 | ], 12 | { 13 | cwd: path.resolve(__dirname, `../`), 14 | stdio: 'inherit', 15 | }, 16 | ); 17 | -------------------------------------------------------------------------------- /scripts/buildPackage.js: -------------------------------------------------------------------------------- 1 | const execa = require('./utils/exec'); 2 | const chalk = require('chalk') 3 | const inquirer = require('inquirer'); 4 | const getPackages = require('./utils/getPackages'); 5 | const package = getPackages() 6 | const path = require('path') 7 | inquirer 8 | .prompt([ 9 | { 10 | type: 'checkbox', 11 | message: '😊:请选择需要单独打包的package', 12 | name: 'names', 13 | choices: [ 14 | new inquirer.Separator('----- 我是分割线 -----'), 15 | ...package.map(i => ({ name: i })) 16 | ], 17 | validate(answer) { 18 | if (answer.length < 1) { 19 | return '🙅:你必须选择一个包!'; 20 | } 21 | return true; 22 | }, 23 | }, 24 | ]) 25 | .then(async(answers) => { 26 | answers.names.forEach(pkgName => { 27 | console.log(chalk.greenBright(`开始打包${pkgName},请稍后...`)); 28 | execa('npm',['run', 'build'], { 29 | cwd: path.resolve(__dirname, `../packages/${pkgName}/`), 30 | stdio: 'inherit', 31 | }) 32 | }) 33 | }); 34 | -------------------------------------------------------------------------------- /scripts/checkEnv.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | 3 | async function exec () { 4 | const ver = process.version 5 | const version = Number(ver.split('.')[0].slice(1, 3)); 6 | let errorStr = '' 7 | if(version <= 15) { 8 | const err = `🙅 当前node版本不匹配, 需要16+, 您当前版本:${ver},请升级后重试 9 | ` 10 | errorStr += err 11 | console.log(chalk.redBright(err)); 12 | } 13 | if(errorStr) { 14 | process.exit(1) 15 | } 16 | } 17 | exec() 18 | -------------------------------------------------------------------------------- /scripts/clearMfsu.js: -------------------------------------------------------------------------------- 1 | const getProjects = require('./utils/getProject'); 2 | const { join } = require('path'); 3 | const fs = require('fs') 4 | const { removeDir } = require('./utils/file') 5 | const chalk = require('chalk') 6 | async function exec () {// 删除umi的mfsu缓存,不然组件无法更新 7 | const pkgs = getProjects() 8 | try { 9 | const mainMfsuFolder = join(__dirname, '../node_modules/.cache/mfsu/') 10 | fs.existsSync(mainMfsuFolder) && removeDir(mainMfsuFolder); 11 | } catch (error) { 12 | console.log(chalk.greenBright(`😣 主应用未找到mfsu文件夹,删除失败!!!`), error); 13 | } 14 | pkgs.forEach(i => { 15 | try { 16 | const folderPath = join(__dirname, `../projects/${i}/node_modules/.cache/mfsu`) 17 | const isExist = fs.existsSync(folderPath) 18 | isExist && removeDir(folderPath); 19 | } catch (error) { 20 | console.log(chalk.greenBright(`😣 子应用${i}mfsu缓存文件夹删除失败!!!`), error); 21 | } 22 | }) 23 | } 24 | exec() 25 | -------------------------------------------------------------------------------- /scripts/createRelease.js: -------------------------------------------------------------------------------- 1 | const exec = require('child_process').execSync; 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | // 创建当前版本历史更新日志,自动写入文档 5 | const getChangelog = (content, version) => { 6 | const lines = content.split('\n'); 7 | const changeLog = []; 8 | const startPattern = new RegExp(`^## ${version}`); 9 | const stopPattern = /^## /; // 前一个版本 10 | const skipPattern = /^`/; // 日期 11 | let begin = false; 12 | for (let i = 0; i < lines.length; i += 1) { 13 | const line = lines[i]; 14 | if (begin && stopPattern.test(line)) { 15 | break; 16 | } 17 | if (begin && line && !skipPattern.test(line)) { 18 | changeLog.push(line); 19 | } 20 | if (!begin) { 21 | begin = startPattern.test(line); 22 | } 23 | } 24 | return changeLog.join('\n'); 25 | }; 26 | 27 | const getMds = async (allVersion = false) => { 28 | const docDir = path.join(__dirname, '..', 'docs'); 29 | const mdFils = fs.readdirSync(docDir).filter((name) => name.includes('changelog.md')); 30 | mdFils.map((mdFile) => { 31 | const pkg = mdFile.replace('.changelog.md', ''); 32 | const content = fs 33 | .readFileSync(path.join(__dirname, '..', `/packages/${pkg}/CHANGELOG.md`)) 34 | .toString(); 35 | // dumi路由相关信息 36 | const _content = `--- 37 | title: vis/${pkg} - 更新日志 38 | nav: 39 | title: Changelog 40 | path: /changelog 41 | group: 42 | path: / 43 | ---`; 44 | // let versions = [ 45 | // require(path.join(path.join(__dirname, '..', 'packages', pkg, 'package.json'))).version, 46 | // ]; 47 | const filePath = path.join(__dirname, '..', `docs/${pkg}.changelog.md`); 48 | fs.unlinkSync(filePath); 49 | fs.writeFileSync( 50 | filePath, 51 | `${_content} 52 | 53 | ${content} 54 | `, 55 | ); 56 | // if (allVersion) { 57 | // versions = exec('git tag') 58 | // .toString() 59 | // .split('\n') 60 | // .filter((tag) => tag.includes(pkg)) 61 | // .map((tag) => tag.split('@').pop()); 62 | // } 63 | // versions.map(async (version) => { 64 | // const versionPkg = `@vis/${pkg}@${version}`; 65 | // const changeLog = getChangelog(content, versionPkg); 66 | // if (!changeLog) { 67 | // return; 68 | // } 69 | // }); 70 | }); 71 | }; 72 | 73 | getMds(); 74 | -------------------------------------------------------------------------------- /scripts/devPackage.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const execa = require('./utils/exec'); 4 | const chalk = require('chalk') 5 | const inquirer = require('inquirer'); 6 | const getPackages = require('./utils/getPackages'); 7 | const _ = require('lodash') 8 | async function execHandler () { 9 | const tailPkgs = getPackages() 10 | // const res = await inquirer.prompt([ 11 | // { 12 | // type: 'input', 13 | // name: 'package', 14 | // message: '请输入需要热更新的包名', 15 | // }, 16 | // ]); 17 | inquirer 18 | .prompt([ 19 | { 20 | type: 'checkbox', 21 | message: '😊:请选择需要开启热更新的package', 22 | name: 'name', 23 | choices: [ 24 | new inquirer.Separator('----- 我是分割线 -----'), 25 | ...tailPkgs.map(i => ({ name: i })) 26 | ], 27 | validate(answer) { 28 | if (answer.length !== 1) { 29 | return '🙅:你只能选择一个包!'; 30 | } 31 | return true; 32 | }, 33 | }, 34 | ]) 35 | .then(async(answers) => { 36 | package = answers.name[0]; 37 | if(!package || !tailPkgs.includes(package)) { 38 | throw new Error('未找到对应包名,请重试!') 39 | } 40 | console.log(chalk.greenBright('😄热更新开启成功!')); 41 | const reloadDir = path.resolve(__dirname, `../packages/${package}/src/`) 42 | const handle = _.debounce(function(filename) { 43 | console.log(`${chalk.greenBright(`visTip: libName: ${package} >> save:`)} ${chalk.magenta.bold(filename)}, 正在热更新中...`); 44 | execa('npm',['run', 'build'], { 45 | cwd: path.resolve(reloadDir, '../'), 46 | stdio: 'inherit', 47 | }) 48 | }, 500) 49 | fs.watch(reloadDir, { recursive: true },(event, filename) => { 50 | handle(filename) 51 | }); 52 | }); 53 | } 54 | 55 | execHandler() 56 | -------------------------------------------------------------------------------- /scripts/devProject.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const execa = require('./utils/exec'); 4 | const chalk = require('chalk'); 5 | const inquirer = require('inquirer'); 6 | const getProjects = require('./utils//getProject'); 7 | const _ = require('lodash') 8 | async function execHandler () { 9 | const tailPkgs = getProjects() 10 | inquirer 11 | .prompt([ 12 | { 13 | type: 'checkbox', 14 | message: '😊:请选择dev的project', 15 | name: 'name', 16 | choices: [ 17 | new inquirer.Separator('----- 我是分割线 -----'), 18 | ...tailPkgs.map(i => ({ name: i })) 19 | ], 20 | validate(answer) { 21 | if (answer.length !== 1) { 22 | return '🙅:你只能选择一个项目!'; 23 | } 24 | return true; 25 | }, 26 | }, 27 | ]) 28 | .then(async(answers) => { 29 | package = answers.name[0]; 30 | if(!package || !tailPkgs.includes(package)) { 31 | throw new Error('未找到对应项目,请重试!') 32 | } 33 | console.log(chalk.greenBright('😄开启成功!')); 34 | const reloadDir = path.resolve(__dirname, `../projects/${package}/src/`) 35 | execa('npm',['run', 'dev'], { 36 | cwd: path.resolve(reloadDir, '../'), 37 | stdio: 'inherit', 38 | }) 39 | }); 40 | } 41 | 42 | execHandler() 43 | -------------------------------------------------------------------------------- /scripts/gen_less_entry.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { join } = require('path'); 3 | const fg = require('fast-glob'); 4 | const slash = require('slash'); 5 | const getPkgs = require('./utils/getPackages'); 6 | 7 | const pkgList = getPkgs() 8 | 9 | 10 | pkgList.map(async (path) => { 11 | const baseUrl = slash(`${join(__dirname, '../', 'packages')}/${path}/src`); 12 | const lessFiles = await fg(`${baseUrl}/**/*.less`, { 13 | ignore: ['**/demos/**'], 14 | deep: 5, 15 | }); 16 | 17 | const importFiles = lessFiles.map((lessPath) => { 18 | return `@import "../es${lessPath.replace(baseUrl, '')}";`; 19 | }); 20 | 21 | const distPath = slash(`${join(__dirname, '../', 'packages', path, 'dist', `${path}.less`)}`); 22 | fs.writeFileSync(distPath, importFiles.join('\n')); 23 | }); 24 | -------------------------------------------------------------------------------- /scripts/gen_version.js: -------------------------------------------------------------------------------- 1 | const { readdirSync, existsSync, fstat, writeFileSync } = require('fs'); 2 | const { join } = require('path'); 3 | const prettier = require('prettier'); 4 | 5 | // utils must build before core 6 | // runtime must build before renderer-react 7 | const packagesPath = join(__dirname, '../packages'); 8 | const pkgList = readdirSync(packagesPath) 9 | .filter((pkg) => pkg.charAt(0) !== '.') 10 | .map((pkg) => { 11 | const package_path = join(packagesPath, pkg); 12 | if (!existsSync(join(package_path, 'package.json'))) return; 13 | const json = require(join(package_path, 'package.json')); 14 | return { 15 | name: json.name, 16 | version: json.version, 17 | }; 18 | }); 19 | 20 | const file_content = ` 21 | 22 | export const version = { 23 | ${pkgList 24 | .map((pak) => { 25 | return `"${pak.name}": '${pak.version}'`; 26 | }) 27 | .join(',\n ')} 28 | } 29 | `; 30 | 31 | writeFileSync( 32 | join(packagesPath, 'common', '/src/version.ts'), 33 | prettier.format(file_content, { parser: 'typescript' }).toString(), 34 | ); 35 | -------------------------------------------------------------------------------- /scripts/generateSizeLimit.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const writePkg = require('write-pkg'); 4 | 5 | const cwd = process.cwd(); 6 | const ignoreDirPath = ['.DS_Store']; 7 | 8 | const filePath = path.resolve(cwd, 'package.json'); 9 | const packagesDir = path.resolve(cwd, 'packages'); 10 | const json = JSON.parse(fs.readFileSync(filePath, 'utf8')); 11 | 12 | delete json['size-limit']; 13 | 14 | let componentsNames = fs.readdirSync(packagesDir); 15 | 16 | componentsNames = componentsNames.filter((dir) => ignoreDirPath.indexOf(dir) === -1); 17 | 18 | (async () => { 19 | const sizeLimitConfig = []; 20 | componentsNames.forEach((component) => { 21 | sizeLimitConfig.push({ 22 | path: `packages/${component}/lib/**/*.js`, 23 | limit: '2 s', 24 | webpack: false, 25 | running: false, 26 | }); 27 | sizeLimitConfig.push({ 28 | path: `packages/${component}/es/**/*.js`, 29 | limit: '2 s', 30 | webpack: false, 31 | running: false, 32 | }); 33 | }); 34 | 35 | await writePkg(cwd, { ...json, 'size-limit': sizeLimitConfig }); 36 | })(); 37 | -------------------------------------------------------------------------------- /scripts/preDeploy.js: -------------------------------------------------------------------------------- 1 | const { existsSync, readdirSync } = require('fs'); 2 | const { join } = require('path'); 3 | const getPkgs = require('./utils/getPackages'); 4 | 5 | (async () => { 6 | const pkgs = getPkgs() 7 | 8 | pkgs.forEach((shortName) => { 9 | const distPath = join(__dirname, '..', 'packages', shortName, 'dist'); 10 | const distExists = existsSync(distPath); 11 | if (!distExists || !existsSync(join(__dirname, '..', 'packages', shortName, 'es'))) { 12 | console.error('Please execute "npm build-lib && npm build-dist" first!'); 13 | process.exit(1); 14 | } 15 | }); 16 | })(); 17 | -------------------------------------------------------------------------------- /scripts/preinstall.js: -------------------------------------------------------------------------------- 1 | 2 | if (!/pnpm/.test(process.env.npm_execpath || '')) { 3 | console.warn( 4 | `\u001b[33mThis repository requires using pnpm as the package manager ` + 5 | ` for scripts to work properly.\u001b[39m\n` 6 | ) 7 | process.exit(1) 8 | } 9 | -------------------------------------------------------------------------------- /scripts/releasePackage.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const execa = require('./utils/exec'); 4 | const chalk = require('chalk') 5 | 6 | // 增加版本号,在这之前我们已经单独打包过了 7 | const filePath = path.resolve(__dirname, '../', '.temp'); 8 | try { 9 | let packageName = fs.readFileSync(filePath).toString(); 10 | if (packageName) { 11 | const packagePath = path.resolve(__dirname, '../', `packages/${packageName}/package.json`); 12 | const packageStr = fs.readFileSync(packagePath).toString(); 13 | const packageJson = JSON.parse(packageStr); 14 | const curVersion = packageJson.version; 15 | const nums = curVersion.split('.').map((i) => Number(i)); 16 | nums[nums.length - 1]++; 17 | const nextVersion = nums.join('.'); 18 | fs.unlinkSync(packagePath); 19 | fs.writeFileSync(packagePath, packageStr.replace(curVersion, nextVersion)); 20 | execa('npm', ['publish'], { 21 | // 执行发布 22 | cwd: path.resolve(__dirname, '../', `packages/${packageName}`), 23 | }); 24 | fs.unlinkSync(filePath); 25 | } else { 26 | console.log(`${chalk.red('>> 未读取到单独打包的包名:')} }`); 27 | } 28 | } catch (error) {} 29 | -------------------------------------------------------------------------------- /scripts/replaceLib.js: -------------------------------------------------------------------------------- 1 | const { join, dirname } = require('path'); 2 | const fs = require('fs'); 3 | 4 | const cwd = process.cwd(); 5 | 6 | function replacePath(path) { 7 | if (path.node.source && /\/lib\//.test(path.node.source.value)) { 8 | const esModule = path.node.source.value.replace('/lib/', '/es/'); 9 | const esPath = dirname(join(cwd, `node_modules/${esModule}`)); 10 | if (fs.existsSync(esPath)) { 11 | console.log(`[es build] replace ${path.node.source.value} with ${esModule}`); 12 | path.node.source.value = esModule; 13 | } 14 | } 15 | } 16 | 17 | function replaceLib() { 18 | return { 19 | visitor: { 20 | ImportDeclaration: replacePath, 21 | ExportNamedDeclaration: replacePath, 22 | }, 23 | }; 24 | } 25 | module.exports = replaceLib; 26 | -------------------------------------------------------------------------------- /scripts/utils/exec.js: -------------------------------------------------------------------------------- 1 | const { spawn } = require('child_process'); 2 | 3 | module.exports = function exec(command, args, opts) { 4 | return new Promise((resolve, reject) => { 5 | const child = spawn(command, args, { 6 | shell: true, 7 | stdio: 'inherit', 8 | env: process.env, 9 | ...opts, 10 | }); 11 | child.once('error', (err) => { 12 | console.log(err); 13 | reject(err); 14 | }); 15 | child.once('close', (code) => { 16 | if (code === 1) { 17 | process.exit(1); 18 | } else { 19 | resolve(); 20 | } 21 | }); 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /scripts/utils/file.js: -------------------------------------------------------------------------------- 1 | let fs = require('fs'); 2 | let path = require('path'); 3 | function removeDir(dir) { 4 | let files = fs.readdirSync(dir) 5 | for(var i=0;i { 4 | const pkgs = getPackages() 5 | let alias = {} 6 | pkgs.forEach(i => { 7 | alias[`@vis/${i}`] = path.resolve(__dirname, `../../packages/${i}/src`) 8 | }) 9 | return alias 10 | } 11 | -------------------------------------------------------------------------------- /scripts/utils/getPackages.js: -------------------------------------------------------------------------------- 1 | const { readdirSync } = require('fs'); 2 | const { join } = require('path'); 3 | 4 | module.exports = function getPackages() { 5 | return readdirSync(join(__dirname, '../../packages')); 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /scripts/utils/getProject.js: -------------------------------------------------------------------------------- 1 | const { readdirSync } = require('fs'); 2 | const { join } = require('path'); 3 | 4 | module.exports = function getPackages() { 5 | return readdirSync(join(__dirname, '../../projects')); 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /src/access.ts: -------------------------------------------------------------------------------- 1 | export default (initialState: API.UserInfo) => { 2 | // 在这里按照初始化数据定义项目中的权限,统一管理 3 | // 参考文档 https://next.umijs.org/docs/max/access 4 | const canSeeAdmin = !!( 5 | initialState && initialState.name !== 'dontHaveAccess' 6 | ); 7 | return { 8 | canSeeAdmin, 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /src/app.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | // 更多信息见文档:https://next.umijs.org/docs/api/runtime-config#getinitialstate 4 | export async function getInitialState(): Promise { 5 | // 获取用户信息, 权限 6 | return { name: '@umijs/max', username: 'Chencc' }; 7 | } 8 | 9 | export function useQiankunStateForSlave() { 10 | const [globalState, setGlobalState] = useState({ 11 | slogan: 'Hello MicroFrontend', 12 | isMicroApp: true, 13 | }); 14 | 15 | return { 16 | globalState, 17 | setGlobalState, 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /src/components/Guide/Guide.less: -------------------------------------------------------------------------------- 1 | .title { 2 | margin: 0 auto; 3 | font-weight: 200; 4 | } 5 | -------------------------------------------------------------------------------- /src/components/Guide/Guide.tsx: -------------------------------------------------------------------------------- 1 | import { Layout, Row, Typography } from 'antd'; 2 | import React from 'react'; 3 | import styles from './Guide.less'; 4 | 5 | interface Props { 6 | name: string; 7 | } 8 | 9 | // 脚手架示例组件 10 | const Guide: React.FC = (props) => { 11 | const { name } = props; 12 | return ( 13 | 14 | 15 | 16 | 欢迎使用 {name} ! 17 | 18 | 19 | 20 | ); 21 | }; 22 | 23 | export default Guide; 24 | -------------------------------------------------------------------------------- /src/components/Guide/index.ts: -------------------------------------------------------------------------------- 1 | import Guide from './Guide'; 2 | export default Guide; 3 | -------------------------------------------------------------------------------- /src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_NAME = 'Umi Max'; 2 | -------------------------------------------------------------------------------- /src/global.less: -------------------------------------------------------------------------------- 1 | @import url(./vis.less); 2 | .header-icon-wrap { 3 | cursor: pointer; 4 | display: inline-block; 5 | padding: 0 10px; 6 | &:hover { 7 | background-color: rgba(0, 0, 0, 0.2); 8 | } 9 | .anticon { 10 | margin: 0 10px; 11 | } 12 | } 13 | .vis__fadeIn { 14 | animation: fadeIn 1s; 15 | height: 100%; 16 | @keyframes fadeIn { 17 | 0% { 18 | opacity: 0; 19 | } 20 | 100% { 21 | opacity: 1; 22 | } 23 | } 24 | } 25 | 26 | .ant-layout { 27 | // tab相关给100%高度撑开 28 | height: 100vh; 29 | .ant-layout-content { 30 | padding-block: 10px !important; 31 | padding-inline: 10px !important; 32 | > .ant-tabs { 33 | height: 100%; 34 | .ant-tabs-content, 35 | .ant-tabs-tabpane { 36 | height: 100%; 37 | } 38 | } 39 | } 40 | 41 | .ant-tabs-card > .ant-tabs-nav .ant-tabs-tab { 42 | padding: 4px 8px; 43 | } 44 | } 45 | .ant-tabs-top > div.ant-tabs-nav { 46 | margin: 0; 47 | } 48 | -------------------------------------------------------------------------------- /src/layouts/base/AvatarDropDown.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, Dropdown } from 'antd'; 2 | 3 | export default () => { 4 | return ( 5 | <> 6 | 我的部门, 11 | key: '0', 12 | }, 13 | { 14 | label: 个人信息, 15 | key: '0', 16 | }, 17 | { 18 | label: 设置, 19 | key: '1', 20 | }, 21 | { 22 | type: 'divider', 23 | }, 24 | { 25 | label: '退出', 26 | key: '3', 27 | }, 28 | ], 29 | }} 30 | trigger={['hover']} 31 | > 32 | 33 | {'Chencc'} 34 | 35 | 36 | 37 | 38 | ); 39 | }; 40 | -------------------------------------------------------------------------------- /src/layouts/base/NotificatTab.tsx: -------------------------------------------------------------------------------- 1 | export default () => { 2 | const TabsContent = ( 3 |
4 | 10 | 通知 11 | 12 | ), 13 | value: '通知', 14 | }, 15 | '私信', 16 | '订单', 17 | ]} 18 | /> 19 | 24 |
25 | ); 26 | return ( 27 | 33 |
34 | 35 | 36 | 37 |
38 |
39 | ); 40 | }; 41 | -------------------------------------------------------------------------------- /src/layouts/base/index.module.less: -------------------------------------------------------------------------------- 1 | .base-layout-wrap { 2 | :global { 3 | } 4 | } 5 | 6 | .menu-item { 7 | padding: 5px; 8 | cursor: pointer; 9 | color: black; 10 | &:hover { 11 | color: white; 12 | background-color: var(--colorPrimaryBgHover); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/models/global.ts: -------------------------------------------------------------------------------- 1 | // 全局共享数据示例 2 | import { DEFAULT_NAME } from '@/constants'; 3 | import { useState } from 'react'; 4 | 5 | const useUser = () => { 6 | const [name, setName] = useState(DEFAULT_NAME); 7 | return { 8 | name, 9 | setName, 10 | }; 11 | }; 12 | 13 | export default useUser; 14 | -------------------------------------------------------------------------------- /src/models/memoHistory.ts: -------------------------------------------------------------------------------- 1 | import { RoutersType } from '@/layouts/base'; 2 | import { useState } from 'react'; 3 | 4 | const memoHistory = () => { 5 | const [memoHistory, setMemoHistory] = useState([]); 6 | return { 7 | memoHistory, 8 | setMemoHistory, 9 | remove(key: string) { 10 | const idx = memoHistory.findIndex((i) => i.key === key); 11 | idx >= 0 && 12 | setMemoHistory([...(memoHistory.splice(idx, 1) && memoHistory)]); 13 | }, 14 | push(item: RoutersType) { 15 | const isExist = memoHistory.find((i) => i.key === item.key); 16 | if (!isExist) { 17 | if (memoHistory.length >= 20) { 18 | // 超过20退出最开始的一个 19 | setMemoHistory([...(memoHistory.shift(), memoHistory)]); 20 | } else { 21 | setMemoHistory(memoHistory.concat(item)); 22 | } 23 | } 24 | }, 25 | }; 26 | }; 27 | 28 | export default memoHistory; 29 | -------------------------------------------------------------------------------- /src/pages/Access/index.tsx: -------------------------------------------------------------------------------- 1 | import { PageContainer } from '@ant-design/pro-components'; 2 | import { Access, useAccess } from '@umijs/max'; 3 | import { Button } from 'antd'; 4 | import { useState } from 'react'; 5 | 6 | const AccessPage: React.FC = () => { 7 | const access = useAccess(); 8 | const [count, setCount] = useState(0) 9 | return ( 10 | 11 | 14 | 15 | ); 16 | }; 17 | 18 | export default AccessPage; 19 | -------------------------------------------------------------------------------- /src/pages/Home/Space1.tsx: -------------------------------------------------------------------------------- 1 | import { VisHeader } from '@vis/common'; 2 | import React from 'react'; 3 | 4 | function Space1() { 5 | return ( 6 |
7 |
, 14 | }, 15 | ]} 16 | /> 17 | 24 |
Table View
25 | 26 | ), 27 | }, 28 | { 29 | title: 'SQL视图', 30 | key: '2', 31 | content: ( 32 |
33 |
SQL View
34 |
35 | ), 36 | }, 37 | ]} 38 | tabBarExtraContent={🫱} 39 | > 40 | {(item) => { 41 | return
{item?.content}
; 42 | }} 43 |
44 | 45 | ); 46 | } 47 | 48 | export default Space1; 49 | -------------------------------------------------------------------------------- /src/pages/Home/Space2.tsx: -------------------------------------------------------------------------------- 1 | function Space2() { 2 | return ( 3 |
4 | 5 | 6 | {'{"key": "value"}'} 7 | 8 | 9 |
10 | ); 11 | } 12 | 13 | export default Space2; 14 | -------------------------------------------------------------------------------- /src/pages/Home/index.module.less: -------------------------------------------------------------------------------- 1 | .container { 2 | height: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import { Workspace } from '@vis/common'; 2 | import { Button } from 'antd'; 3 | import styles from './index.module.less'; 4 | import Space1 from './Space1'; 5 | import Space2 from './Space2'; 6 | const HomePage: React.FC = (props) => { 7 | return ( 8 |
9 | 15 | 18 | 19 | 20 | } 21 | breadcrumb={{ 22 | routes: [ 23 | { path: '/home', breadcrumbName: '主页面包屑', children: [] }, 24 | ], 25 | }} 26 | desc="初始化demo,用来展示workSpace的基本用法, 面包屑只在多层开启,单层需要手动配置" 27 | formProps={{ 28 | size: 'small', 29 | }} 30 | formColumns={[ 31 | { 32 | title: '标题', 33 | dataIndex: 'title', 34 | formItemProps: { 35 | rules: [ 36 | { 37 | required: true, 38 | message: '此项为必填项', 39 | }, 40 | ], 41 | }, 42 | width: 's', 43 | colProps: { 44 | xs: 24, 45 | md: 12, 46 | }, 47 | }, 48 | { 49 | title: '状态', 50 | dataIndex: 'state', 51 | valueType: 'select', 52 | valueEnum: { a: 1, b: 2 }, 53 | width: 's', 54 | colProps: { 55 | xs: 24, 56 | md: 12, 57 | }, 58 | }, 59 | ]} 60 | tabs={[ 61 | { 62 | key: '1', 63 | title: '工作区1', 64 | content: , 65 | }, 66 | { 67 | key: '2', 68 | title: '工作区2', 69 | content: , 70 | }, 71 | ]} 72 | /> 73 |
74 | ); 75 | }; 76 | 77 | export default HomePage; 78 | -------------------------------------------------------------------------------- /src/pages/MicroApp/dash.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import {MicroApp} from '@umijs/max'; 3 | 4 | function Dash() { 5 | const microAppRef = useRef(); 6 | 7 | // 执行此方法时,更新子应用 8 | const updateMicroApp = () => { 9 | microAppRef?.current?.update(); 10 | }; 11 | return ( 12 |
13 | 14 |
15 | ); 16 | } 17 | 18 | export default Dash; 19 | -------------------------------------------------------------------------------- /src/pages/MicroApp/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function MicroApp() { 4 | return ( 5 |
6 | MicroApp 7 |
8 | ); 9 | } 10 | 11 | export default MicroApp; 12 | -------------------------------------------------------------------------------- /src/pages/Test/Test1.tsx: -------------------------------------------------------------------------------- 1 | import { Workspace } from '@vis/common'; 2 | 3 | const HomePage: React.FC = () => { 4 | return ( 5 |
6 | 工作区1, 48 | }, 49 | { 50 | key: '工作区22', 51 | title: '工作区2', 52 | content:

工作区2

, 53 | }, 54 | ]} 55 | /> 56 |
57 | ); 58 | }; 59 | 60 | export default HomePage; 61 | -------------------------------------------------------------------------------- /src/pages/Test/index.module.less: -------------------------------------------------------------------------------- 1 | .test { 2 | margin: 0 auto; 3 | border: solid 1px var(--colorErrorBorder); 4 | } 5 | .test2 { 6 | border: solid 1px red; 7 | } 8 | -------------------------------------------------------------------------------- /src/pages/Test/index.tsx: -------------------------------------------------------------------------------- 1 | import styles from './index.module.less'; 2 | 3 | declare global { 4 | const env: { 5 | version: string; 6 | isDev: boolean; 7 | }; 8 | } 9 | function Table() { 10 | const [a] = useState(1); 11 | console.log(process.env.version, process.env.isDev); 12 | return ( 13 |
14 | 123:{a} 15 | 16 |

子节点, 测试unocss打包

17 | 18 |

19 | 子节点1 20 |

21 |

22 | 子节点, 使用unocss 预定义的css变量 23 |

24 |
28 | test 29 |
30 |
31 | ); 32 | } 33 | 34 | export default Table; 35 | -------------------------------------------------------------------------------- /src/services/demo/UserController.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // 该文件由 OneAPI 自动生成,请勿手动修改! 3 | import { request } from '@umijs/max'; 4 | 5 | /** 此处后端没有提供注释 GET /api/v1/queryUserList */ 6 | export async function queryUserList( 7 | params: { 8 | // query 9 | /** keyword */ 10 | keyword?: string; 11 | /** current */ 12 | current?: number; 13 | /** pageSize */ 14 | pageSize?: number; 15 | }, 16 | options?: { [key: string]: any }, 17 | ) { 18 | return request('/api/v1/queryUserList', { 19 | method: 'GET', 20 | params: { 21 | ...params, 22 | }, 23 | ...(options || {}), 24 | }); 25 | } 26 | 27 | /** 此处后端没有提供注释 POST /api/v1/user */ 28 | export async function addUser( 29 | body?: API.UserInfoVO, 30 | options?: { [key: string]: any }, 31 | ) { 32 | return request('/api/v1/user', { 33 | method: 'POST', 34 | headers: { 35 | 'Content-Type': 'application/json', 36 | }, 37 | data: body, 38 | ...(options || {}), 39 | }); 40 | } 41 | 42 | /** 此处后端没有提供注释 GET /api/v1/user/${param0} */ 43 | export async function getUserDetail( 44 | params: { 45 | // path 46 | /** userId */ 47 | userId?: string; 48 | }, 49 | options?: { [key: string]: any }, 50 | ) { 51 | const { userId: param0 } = params; 52 | return request(`/api/v1/user/${param0}`, { 53 | method: 'GET', 54 | params: { ...params }, 55 | ...(options || {}), 56 | }); 57 | } 58 | 59 | /** 此处后端没有提供注释 PUT /api/v1/user/${param0} */ 60 | export async function modifyUser( 61 | params: { 62 | // path 63 | /** userId */ 64 | userId?: string; 65 | }, 66 | body?: API.UserInfoVO, 67 | options?: { [key: string]: any }, 68 | ) { 69 | const { userId: param0 } = params; 70 | return request(`/api/v1/user/${param0}`, { 71 | method: 'PUT', 72 | headers: { 73 | 'Content-Type': 'application/json', 74 | }, 75 | params: { ...params }, 76 | data: body, 77 | ...(options || {}), 78 | }); 79 | } 80 | 81 | /** 此处后端没有提供注释 DELETE /api/v1/user/${param0} */ 82 | export async function deleteUser( 83 | params: { 84 | // path 85 | /** userId */ 86 | userId?: string; 87 | }, 88 | options?: { [key: string]: any }, 89 | ) { 90 | const { userId: param0 } = params; 91 | return request(`/api/v1/user/${param0}`, { 92 | method: 'DELETE', 93 | params: { ...params }, 94 | ...(options || {}), 95 | }); 96 | } 97 | -------------------------------------------------------------------------------- /src/services/demo/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // 该文件由 OneAPI 自动生成,请勿手动修改! 3 | 4 | import * as UserController from './UserController'; 5 | export default { 6 | UserController, 7 | }; 8 | -------------------------------------------------------------------------------- /src/services/demo/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // 该文件由 OneAPI 自动生成,请勿手动修改! 3 | 4 | declare namespace API { 5 | interface PageInfo { 6 | /** 7 | 1 */ 8 | current?: number; 9 | pageSize?: number; 10 | total?: number; 11 | list?: Array>; 12 | } 13 | 14 | interface PageInfo_UserInfo_ { 15 | /** 16 | 1 */ 17 | current?: number; 18 | pageSize?: number; 19 | total?: number; 20 | list?: Array; 21 | } 22 | 23 | interface Result { 24 | success?: boolean; 25 | errorMessage?: string; 26 | data?: Record; 27 | } 28 | 29 | interface Result_PageInfo_UserInfo__ { 30 | success?: boolean; 31 | errorMessage?: string; 32 | data?: PageInfo_UserInfo_; 33 | } 34 | 35 | interface Result_UserInfo_ { 36 | success?: boolean; 37 | errorMessage?: string; 38 | data?: UserInfo; 39 | } 40 | 41 | interface Result_string_ { 42 | success?: boolean; 43 | errorMessage?: string; 44 | data?: string; 45 | } 46 | 47 | type UserGenderEnum = 'MALE' | 'FEMALE'; 48 | 49 | interface UserInfo { 50 | id?: string; 51 | name?: string; 52 | /** nick */ 53 | nickName?: string; 54 | /** email */ 55 | email?: string; 56 | gender?: UserGenderEnum; 57 | } 58 | 59 | interface UserInfoVO { 60 | name?: string; 61 | /** nick */ 62 | nickName?: string; 63 | /** email */ 64 | email?: string; 65 | } 66 | 67 | type definitions_0 = null; 68 | } 69 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.scss' { 2 | const classes: { [key: string]: string }; 3 | export default classes; 4 | } 5 | 6 | declare module '*.module.less' { 7 | const classes: { [key: string]: string }; 8 | export default classes; 9 | } 10 | 11 | declare module '*.module.css' { 12 | const classes: { [key: string]: string }; 13 | export default classes; 14 | } 15 | declare module '@vis/*' { 16 | const classes: { [key: string]: string }; 17 | export default classes; 18 | } 19 | -------------------------------------------------------------------------------- /src/utils/format.ts: -------------------------------------------------------------------------------- 1 | // 示例方法,没有实际意义 2 | export function trim(str: string) { 3 | return str.trim(); 4 | } 5 | -------------------------------------------------------------------------------- /src/vis.less: -------------------------------------------------------------------------------- 1 | .vis-dialog { 2 | div.ant-modal-body { 3 | padding: 0; 4 | .ant-modal-confirm-title { 5 | padding: 16px 24px; 6 | color: #000000d9; 7 | background: #fff; 8 | border-bottom: 1px solid rgba(0, 0, 0, 0.06); 9 | border-radius: 2px 2px 0 0; 10 | } 11 | .ant-modal-confirm-content { 12 | overflow: scroll; 13 | max-height: 70vh; 14 | padding: 24px; 15 | font-size: 14px; 16 | line-height: 1.5715; 17 | word-wrap: break-word; 18 | } 19 | .ant-modal-confirm-btns { 20 | padding: 10px 16px; 21 | text-align: right; 22 | background: 0 0; 23 | border-top: 1px solid rgba(0, 0, 0, 0.06); 24 | border-radius: 0 0 2px 2px; 25 | } 26 | } 27 | } 28 | 29 | .ant-pro-table div.ant-pro-table-search { 30 | margin-bottom: 10px; 31 | } 32 | 33 | body, 34 | html { 35 | margin: 0; 36 | padding: 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/charts/WordCloud.test.tsx: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | import { render as reactRender, fireEvent } from '@testing-library/react'; 3 | import { WordCloud } from '@vis/charts'; 4 | import React, { useRef } from 'react'; 5 | import { waitForComponentToPaint, waitTime } from '../util'; 6 | describe('wordcloud test', () => { 7 | it('wordcloud items number should fllower the data length & onClick & textContent', async () => { 8 | const { RENDER_MODE, TEXT_ORIENTATION } = WordCloud; 9 | let _temp = 1 10 | const config = { 11 | mode: RENDER_MODE.NORMAL, 12 | animate: true, 13 | events: { 14 | click(){ 15 | _temp++ 16 | } 17 | } 18 | }; 19 | const data = [{ 20 | name: 'test1', 21 | value: 20 22 | }, 23 | { 24 | name: 'test2', 25 | value: 100 26 | } 27 | ] 28 | const html = reactRender(
29 | 32 |
); 33 | await waitForComponentToPaint(html, 200); 34 | fireEvent.click(html.getByText(/test1/)); // 模拟点击,触发事件 35 | expect(html.baseElement.querySelectorAll('#wordcloud .word-cloud-item-chencc')?.length).toBe(data.length); 36 | expect(html.asFragment().textContent).toBe(data.map(i => i.name).join('')); 37 | expect(_temp).toBe(2); 38 | }) 39 | }) 40 | 41 | 42 | -------------------------------------------------------------------------------- /tests/jsTransformer.js: -------------------------------------------------------------------------------- 1 | const babel = require('babel-jest'); 2 | 3 | module.exports = babel.default.createTransformer({ 4 | presets: [ 5 | require.resolve('@babel/preset-typescript'), 6 | '@babel/preset-react', 7 | ['@babel/preset-env', { targets: { node: 'current' } }], 8 | ], 9 | }); 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./src/.umi/tsconfig.json", 3 | "exclude": [ 4 | "node_modules", 5 | "build", 6 | "public", 7 | "packages", 8 | "projects", 9 | "tests", 10 | "scripts" 11 | ], 12 | "compilerOptions": { 13 | "baseUrl": ".", 14 | "jsx": "react-jsx", 15 | "types": ["unplugin-icons/types/react"] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /unocss.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, presetIcons, presetUno } from 'unocss'; 2 | import { antdUnoColor } from './config/theme/tokens'; 3 | 4 | export function createConfig({ dev = true } = {}) { 5 | return defineConfig({ 6 | envMode: dev ? 'dev' : 'build', 7 | shortcuts: { 8 | border: 'border-1 border-solid border-red', 9 | center: 'height-width-100 color-red flex-center border', 10 | 'center-2': 'height-width-100 color-red flex items-center justify-center', 11 | }, 12 | presets: [ 13 | presetUno(), 14 | presetIcons({ 15 | prefix: '', 16 | }), 17 | ], 18 | theme: { 19 | colors: { 20 | demoColor: '#0000ff', // class="text-demo-color", 21 | ...(antdUnoColor() || {}), 22 | }, 23 | }, 24 | }); 25 | } 26 | 27 | export default createConfig(); 28 | --------------------------------------------------------------------------------