diff --git a/scripts/fetch-block.js b/scripts/fetch-block.js index b6414fa8732c4aa03923cf2a62b858f9dfdc98aa..4f770426ce69923fd6cc62a211c0797717fbe42e 100644 --- a/scripts/fetch-block.js +++ b/scripts/fetch-block.js @@ -1,101 +1,12 @@ -const parser = require('@babel/parser'); -const traverse = require('@babel/traverse'); -const generate = require('@babel/generator'); -const t = require('@babel/types'); const path = require('path'); const fs = require('fs'); +const fetch = require('node-fetch'); const exec = require('child_process').exec; - -const prettier = require('prettier'); - +const getNewRouteCode = require('./repalceRouter'); const router = require('./router.config'); -const getNewRouteCode = (configPath, newRoute, absSrcPath) => { - const ast = parser.parse(fs.readFileSync(configPath, 'utf-8'), { - sourceType: 'module', - plugins: ['typescript'], - }); - let routesNode = null; - const importModules = []; - // 查询当前配置文件是否导出 routes 属性 - traverse.default(ast, { - Program({ node }) { - // find import - const { body } = node; - body.forEach(item => { - if (t.isImportDeclaration(item)) { - const { specifiers } = item; - const defaultEpecifier = specifiers.find(s => { - return t.isImportDefaultSpecifier(s) && t.isIdentifier(s.local); - }); - if (defaultEpecifier && t.isStringLiteral(item.source)) { - importModules.push({ - identifierName: defaultEpecifier.local.name, - modulePath: item.source.value, - }); - } - } - }); - }, - ObjectExpression({ node, parent }) { - // find routes on object, like { routes: [] } - if (t.isArrayExpression(parent)) { - // children routes - return; - } - const { properties } = node; - properties.forEach(p => { - const { key, value } = p; - if (t.isObjectProperty(p) && t.isIdentifier(key) && key.name === 'routes') { - if (value) { - // find json file program expression - (p.value = parser.parse(JSON.stringify(newRoute)).program.body[0].expression), - (routesNode = value); - } - } - }); - }, - }); - if (routesNode) { - const code = generateCode(ast); - return { code, routesPath: configPath }; - } else { - throw new Error('route array config not found.'); - } -}; - -/** - * 生成代码 - * @param {*} ast - */ -function generateCode(ast) { - const newCode = generate.default(ast, {}).code; - return prettier.format(newCode, { - // format same as ant-design-pro - singleQuote: true, - trailingComma: 'es5', - printWidth: 100, - parser: 'typescript', - }); -} - const relativePath = path.join(__dirname, '../config/config.ts'); -const filterParentRouter = router => { - return [...router] - .map(item => { - if (item.routes) { - return { ...item, routes: filterParentRouter(item.routes) }; - } - return null; - }) - .filter(item => item); -}; -const parentRouter = filterParentRouter(router); -const { routesPath, code } = getNewRouteCode(relativePath, parentRouter); -// write ParentRouter -fs.writeFileSync(routesPath, code); - const findAllInstallRouter = router => { let routers = []; router.forEach(item => { @@ -116,8 +27,16 @@ const findAllInstallRouter = router => { return routers; }; -const installRouters = findAllInstallRouter(router); -let i = 0; +const filterParentRouter = router => { + return [...router] + .map(item => { + if (item.routes) { + return { ...item, routes: filterParentRouter(item.routes) }; + } + return null; + }) + .filter(item => item); +}; const firstUpperCase = pathString => { return pathString .replace('.', '') @@ -126,22 +45,44 @@ const firstUpperCase = pathString => { .filter(s => s) .join(''); }; -const installBlock = () => { - const item = installRouters[i]; - if (!item || !item.path) { - return; - } - console.log('install ' + item.name + ' to: ' + item.component); - const cmd = `umi block add https://github.com/ant-design/pro-blocks/tree/master/${firstUpperCase( - item.path, - )} --npm-client=cnpm --path=${item.path}`; - console.log(cmd); - exec(cmd, { encoding: 'utf8' }, (error, statusbar) => { - if (error) console.log(error); - console.log(statusbar); - i += 1; - installBlock(); +const execCmd = shell => { + return new Promise((resolve, reject) => { + exec(shell, { encoding: 'utf8' }, (error, statusbar) => { + if (error) { + console.log(error); + return reject(error); + } + console.log(statusbar); + resolve(); + }); }); }; + +// replace router config +const parentRouter = filterParentRouter(router); +const { routesPath, code } = getNewRouteCode(relativePath, parentRouter); +// write ParentRouter +fs.writeFileSync(routesPath, code); + +const installBlock = () => { + const installRouters = findAllInstallRouter(router); + const installBlockIteration = async i => { + const item = installRouters[i]; + + if (!item || !item.path) { + return; + } + console.log('install ' + item.name + ' to: ' + item.component); + const cmd = `umi block add https://github.com/ant-design/pro-blocks/tree/master/${firstUpperCase( + item.path, + )} --npm-client=cnpm --path=${item.path}`; + const data = await fetch( + ` https://github.com/ant-design/pro-blocks/tree/master/${firstUpperCase(item.path)}`, + ); + await execCmd(cmd); + installBlockIteration(i + 1); + }; + installBlockIteration(0); +}; installBlock(); diff --git a/scripts/repalceRouter.js b/scripts/repalceRouter.js new file mode 100644 index 0000000000000000000000000000000000000000..4910d3b343a2b4e71dab4c022da60c9c0da937e4 --- /dev/null +++ b/scripts/repalceRouter.js @@ -0,0 +1,77 @@ +const parser = require('@babel/parser'); +const traverse = require('@babel/traverse'); +const generate = require('@babel/generator'); +const t = require('@babel/types'); +const fs = require('fs'); +const prettier = require('prettier'); + +const getNewRouteCode = (configPath, newRoute, absSrcPath) => { + const ast = parser.parse(fs.readFileSync(configPath, 'utf-8'), { + sourceType: 'module', + plugins: ['typescript'], + }); + let routesNode = null; + const importModules = []; + // 查询当前配置文件是否导出 routes 属性 + traverse.default(ast, { + Program({ node }) { + // find import + const { body } = node; + body.forEach(item => { + if (t.isImportDeclaration(item)) { + const { specifiers } = item; + const defaultEpecifier = specifiers.find(s => { + return t.isImportDefaultSpecifier(s) && t.isIdentifier(s.local); + }); + if (defaultEpecifier && t.isStringLiteral(item.source)) { + importModules.push({ + identifierName: defaultEpecifier.local.name, + modulePath: item.source.value, + }); + } + } + }); + }, + ObjectExpression({ node, parent }) { + // find routes on object, like { routes: [] } + if (t.isArrayExpression(parent)) { + // children routes + return; + } + const { properties } = node; + properties.forEach(p => { + const { key, value } = p; + if (t.isObjectProperty(p) && t.isIdentifier(key) && key.name === 'routes') { + if (value) { + // find json file program expression + (p.value = parser.parse(JSON.stringify(newRoute)).program.body[0].expression), + (routesNode = value); + } + } + }); + }, + }); + if (routesNode) { + const code = generateCode(ast); + return { code, routesPath: configPath }; + } else { + throw new Error('route array config not found.'); + } +}; + +/** + * 生成代码 + * @param {*} ast + */ +function generateCode(ast) { + const newCode = generate.default(ast, {}).code; + return prettier.format(newCode, { + // format same as ant-design-pro + singleQuote: true, + trailingComma: 'es5', + printWidth: 100, + parser: 'typescript', + }); +} + +module.exports = getNewRouteCode; diff --git a/scripts/router.config.js b/scripts/router.config.js index eb280bc054d5ebefeaf8798e8fe0b6863cf38e32..5de93dffd8223f51009dee05e0b25e3d562e9664 100644 --- a/scripts/router.config.js +++ b/scripts/router.config.js @@ -57,12 +57,12 @@ module.exports = [ { path: '/form/basic-form', name: 'basicform', - component: './Forms/BasicForm', + component: './Form/BasicForm', }, { path: '/form/step-form', name: 'stepform', - component: './Forms/StepForm', + component: './Form/StepForm', hideChildrenInMenu: true, // routes: [ // { @@ -72,17 +72,17 @@ module.exports = [ // { // path: '/form/step-form/info', // name: 'info', - // component: './Forms/StepForm/Step1', + // component: './Form/StepForm/Step1', // }, // { // path: '/form/step-form/confirm', // name: 'confirm', - // component: './Forms/StepForm/Step2', + // component: './Form/StepForm/Step2', // }, // { // path: '/form/step-form/result', // name: 'result', - // component: './Forms/StepForm/Step3', + // component: './Form/StepForm/Step3', // }, // ], }, @@ -90,7 +90,7 @@ module.exports = [ path: '/form/advanced-form', name: 'advancedform', authority: ['admin'], - component: './Forms/AdvancedForm', + component: './Form/AdvancedForm', }, ], }, @@ -103,22 +103,22 @@ module.exports = [ { path: '/list/table-list', name: 'searchtable', - component: './List/TableList', + component: './list/Tablelist', }, { path: '/list/basic-list', name: 'basiclist', - component: './List/BasicList', + component: './list/Basiclist', }, { path: '/list/card-list', name: 'cardlist', - component: './List/CardList', + component: './list/Cardlist', }, { path: '/list/search', name: 'search-list', - component: './List/List', + component: './list/search', routes: [ { path: '/list/search', @@ -127,17 +127,17 @@ module.exports = [ { path: '/list/search/articles', name: 'articles', - component: './List/Articles', + component: './list/Articles', }, { path: '/list/search/projects', name: 'projects', - component: './List/Projects', + component: './list/Projects', }, { path: '/list/search/applications', name: 'applications', - component: './List/Applications', + component: './list/Applications', }, ], }, @@ -202,12 +202,6 @@ module.exports = [ name: 'server-error', component: './Exception/500', }, - { - path: '/exception/trigger', - name: 'trigger', - hideInMenu: true, - component: './Exception/TriggerException', - }, ], }, { diff --git a/src/components/CopyBlock/index.less b/src/components/CopyBlock/index.less new file mode 100644 index 0000000000000000000000000000000000000000..48e6c7e28ac6b2a4235e150ee1a7b034d59707c6 --- /dev/null +++ b/src/components/CopyBlock/index.less @@ -0,0 +1,25 @@ +.copy-block { + position: absolute; + right: 80px; + bottom: 40px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 80px; + height: 80px; + font-size: 20px; + background: #fff; + border-radius: 40px; + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), + 0 1px 10px 0 rgba(0, 0, 0, 0.12); + cursor: pointer; + + .copy-block-text { + font-size: 12px; + } +} +.copy-block-code { + color: #fff; + background: #000; +} diff --git a/src/components/CopyBlock/index.tsx b/src/components/CopyBlock/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..68590253ce01fbb72e25597a9e6413825ecf2721 --- /dev/null +++ b/src/components/CopyBlock/index.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { Icon, Typography, Tooltip } from 'antd'; +import styles from './index.less'; +const firstUpperCase = (pathString: string) => { + return pathString + .replace('.', '') + .split(/\/|\-/) + .map(s => s.toLowerCase().replace(/( |^)[a-z]/g, L => L.toUpperCase())) + .filter(s => s) + .join(''); +}; +const BlockCodeView: React.SFC<{ + url: string; +}> = ({ url }) => { + console.log(url); + const blockUrl = `umi block add https://github.com/ant-design/pro-blocks/tree/master/${firstUpperCase( + url, + )} --npm-client=cnpm --path=${url}`; + return ( +
+ + {blockUrl} + +
+ ); +}; + +export default ({ url }: { url: string }) => { + return ( + } trigger="click"> +
+ +
+ 下载到 +
+ 项目中 +
+
+
+ ); +}; diff --git a/src/components/GlobalHeader/RightContent.tsx b/src/components/GlobalHeader/RightContent.tsx index f2ca00f9f82dbe557896b0fac52ae0d086631614..880b8a41ae31c8780dc318ca84c665b11c57a585 100644 --- a/src/components/GlobalHeader/RightContent.tsx +++ b/src/components/GlobalHeader/RightContent.tsx @@ -3,7 +3,7 @@ import { NoticeItem } from '@/models/global'; import { CurrentUser } from '@/models/user'; import React, { Component } from 'react'; import { Spin, Tag, Menu, Icon, Avatar, Tooltip, message } from 'antd'; -import { ClickParam } from 'antd/es/menu'; +import { ClickParam } from 'antd/lib/menu'; import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale'; import moment from 'moment'; import groupBy from 'lodash/groupBy'; @@ -13,6 +13,7 @@ import HeaderDropdown from '../HeaderDropdown'; import SelectLang from '../SelectLang'; import styles from './index.less'; import { connect } from 'dva'; +import router from 'umi/router'; export type SiderTheme = 'light' | 'dark'; @@ -95,27 +96,32 @@ class GlobalHeaderRight extends Component { }); } }; + onMenuClick = (event: ClickParam) => { + const { onMenuClick } = this.props; + if (onMenuClick) { + onMenuClick(event); + return; + } + const { key } = event; + router.push(`/account/${key}`); + }; render() { - const { currentUser, fetchingNotices, onNoticeVisibleChange, onMenuClick, theme } = this.props; + const { currentUser, fetchingNotices, onNoticeVisibleChange, theme } = this.props; const menu = ( - - + + - + - - - - - - + {/* */} + {/* - + */} ); const noticeData = this.getNoticeData(); diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index f4a4bce90cb3cdc71ce5e315548aa69751b7e2dc..8ce2d93a0eafad9802c5008f2f835d1177adefb3 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -1,5 +1,6 @@ import { ConnectState, ConnectProps } from '@/models/connect'; import RightContent from '@/components/GlobalHeader/RightContent'; +import CopyBlock from '@/components/CopyBlock'; import { connect } from 'dva'; import React, { useState } from 'react'; import logo from '../assets/logo.svg'; @@ -42,7 +43,7 @@ const filterMenuData = (menuList: MenuDataItem[], locale: boolean): MenuDataItem }; const BasicLayout: React.FC = props => { - const { dispatch, children, settings } = props; + const { dispatch, children, settings, location } = props; /** * constructor */ @@ -73,15 +74,18 @@ const BasicLayout: React.FC = props => { > {children} - - dispatch!({ - type: 'settings/changeSetting', - payload: config, - }) - } - /> + {ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' && ( + + dispatch!({ + type: 'settings/changeSetting', + payload: config, + }) + } + /> + )} + ); };