Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
ant-design-pro
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
duanledexianxianxian
ant-design-pro
Commits
6c519bb2
Commit
6c519bb2
authored
May 22, 2019
by
陈帅
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
commit
parent
0d5b157e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
237 additions
and
149 deletions
+237
-149
scripts/fetch-block.js
scripts/fetch-block.js
+49
-108
scripts/repalceRouter.js
scripts/repalceRouter.js
+77
-0
scripts/router.config.js
scripts/router.config.js
+13
-19
src/components/CopyBlock/index.less
src/components/CopyBlock/index.less
+25
-0
src/components/CopyBlock/index.tsx
src/components/CopyBlock/index.tsx
+41
-0
src/components/GlobalHeader/RightContent.tsx
src/components/GlobalHeader/RightContent.tsx
+18
-12
src/layouts/BasicLayout.tsx
src/layouts/BasicLayout.tsx
+14
-10
No files found.
scripts/fetch-block.js
View file @
6c519bb2
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
();
scripts/repalceRouter.js
0 → 100644
View file @
6c519bb2
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
;
scripts/router.config.js
View file @
6c519bb2
...
...
@@ -57,12 +57,12 @@ module.exports = [
{
path
:
'
/form/basic-form
'
,
name
:
'
basicform
'
,
component
:
'
./Form
s
/BasicForm
'
,
component
:
'
./Form/BasicForm
'
,
},
{
path
:
'
/form/step-form
'
,
name
:
'
stepform
'
,
component
:
'
./Form
s
/StepForm
'
,
component
:
'
./Form/StepForm
'
,
hideChildrenInMenu
:
true
,
// routes: [
// {
...
...
@@ -72,17 +72,17 @@ module.exports = [
// {
// path: '/form/step-form/info',
// name: 'info',
// component: './Form
s
/StepForm/Step1',
// component: './Form/StepForm/Step1',
// },
// {
// path: '/form/step-form/confirm',
// name: 'confirm',
// component: './Form
s
/StepForm/Step2',
// component: './Form/StepForm/Step2',
// },
// {
// path: '/form/step-form/result',
// name: 'result',
// component: './Form
s
/StepForm/Step3',
// component: './Form/StepForm/Step3',
// },
// ],
},
...
...
@@ -90,7 +90,7 @@ module.exports = [
path
:
'
/form/advanced-form
'
,
name
:
'
advancedform
'
,
authority
:
[
'
admin
'
],
component
:
'
./Form
s
/AdvancedForm
'
,
component
:
'
./Form/AdvancedForm
'
,
},
],
},
...
...
@@ -103,22 +103,22 @@ module.exports = [
{
path
:
'
/list/table-list
'
,
name
:
'
searchtable
'
,
component
:
'
./
List/TableL
ist
'
,
component
:
'
./
list/Tablel
ist
'
,
},
{
path
:
'
/list/basic-list
'
,
name
:
'
basiclist
'
,
component
:
'
./
List/BasicL
ist
'
,
component
:
'
./
list/Basicl
ist
'
,
},
{
path
:
'
/list/card-list
'
,
name
:
'
cardlist
'
,
component
:
'
./
List/CardL
ist
'
,
component
:
'
./
list/Cardl
ist
'
,
},
{
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
:
'
./
L
ist/Articles
'
,
component
:
'
./
l
ist/Articles
'
,
},
{
path
:
'
/list/search/projects
'
,
name
:
'
projects
'
,
component
:
'
./
L
ist/Projects
'
,
component
:
'
./
l
ist/Projects
'
,
},
{
path
:
'
/list/search/applications
'
,
name
:
'
applications
'
,
component
:
'
./
L
ist/Applications
'
,
component
:
'
./
l
ist/Applications
'
,
},
],
},
...
...
@@ -202,12 +202,6 @@ module.exports = [
name
:
'
server-error
'
,
component
:
'
./Exception/500
'
,
},
{
path
:
'
/exception/trigger
'
,
name
:
'
trigger
'
,
hideInMenu
:
true
,
component
:
'
./Exception/TriggerException
'
,
},
],
},
{
...
...
src/components/CopyBlock/index.less
0 → 100644
View file @
6c519bb2
.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;
}
src/components/CopyBlock/index.tsx
0 → 100644
View file @
6c519bb2
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
(
<
div
>
<
Typography
.
Paragraph
copyable
>
<
code
className
=
{
styles
[
'
copy-block-code
'
]
}
>
{
blockUrl
}
</
code
>
</
Typography
.
Paragraph
>
</
div
>
);
};
export
default
({
url
}:
{
url
:
string
})
=>
{
return
(
<
Tooltip
placement
=
"topLeft"
title
=
{
<
BlockCodeView
url
=
{
url
}
/>
}
trigger
=
"click"
>
<
div
className
=
{
styles
[
'
copy-block
'
]
}
>
<
Icon
type
=
"code"
/>
<
div
className
=
{
styles
[
'
copy-block-text
'
]
}
>
下载到
<
br
/>
项目中
</
div
>
</
div
>
</
Tooltip
>
);
};
src/components/GlobalHeader/RightContent.tsx
View file @
6c519bb2
...
...
@@ -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<GlobalHeaderRightProps> {
});
}
};
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
=
(
<
Menu
className
=
{
styles
.
menu
}
selectedKeys
=
{
[]
}
onClick
=
{
onMenuClick
}
>
<
Menu
.
Item
key
=
"
userC
enter"
>
<
Menu
className
=
{
styles
.
menu
}
selectedKeys
=
{
[]
}
onClick
=
{
this
.
onMenuClick
}
>
<
Menu
.
Item
key
=
"
c
enter"
>
<
Icon
type
=
"user"
/>
<
FormattedMessage
id
=
"menu.account.center"
defaultMessage
=
"account center"
/>
</
Menu
.
Item
>
<
Menu
.
Item
key
=
"
userinfo
"
>
<
Menu
.
Item
key
=
"
settings
"
>
<
Icon
type
=
"setting"
/>
<
FormattedMessage
id
=
"menu.account.settings"
defaultMessage
=
"account settings"
/>
</
Menu
.
Item
>
<
Menu
.
Item
key
=
"triggerError"
>
<
Icon
type
=
"close-circle"
/>
<
FormattedMessage
id
=
"menu.account.trigger"
defaultMessage
=
"Trigger Error"
/>
</
Menu
.
Item
>
<
Menu
.
Divider
/>
<
Menu
.
Item
key
=
"logout"
>
{
/* <Menu.Divider /> */
}
{
/* <Menu.Item key="logout">
<Icon type="logout" />
<FormattedMessage id="menu.account.logout" defaultMessage="logout" />
</
Menu
.
Item
>
</Menu.Item>
*/
}
</
Menu
>
);
const
noticeData
=
this
.
getNoticeData
();
...
...
src/layouts/BasicLayout.tsx
View file @
6c519bb2
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
<
BasicLayoutProps
>
=
props
=>
{
const
{
dispatch
,
children
,
settings
}
=
props
;
const
{
dispatch
,
children
,
settings
,
location
}
=
props
;
/**
* constructor
*/
...
...
@@ -73,15 +74,18 @@ const BasicLayout: React.FC<BasicLayoutProps> = props => {
>
{
children
}
</
BasicLayoutComponents
>
<
SettingDrawer
settings
=
{
settings
}
onSettingChange
=
{
config
=>
dispatch
!
({
type
:
'
settings/changeSetting
'
,
payload
:
config
,
})
}
/>
{
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION
===
'
site
'
&&
(
<
SettingDrawer
settings
=
{
settings
}
onSettingChange
=
{
config
=>
dispatch
!
({
type
:
'
settings/changeSetting
'
,
payload
:
config
,
})
}
/>
)
}
<
CopyBlock
url
=
{
location
.
pathname
}
/>
</>
);
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment