29 changed files with 937 additions and 242 deletions
@ -0,0 +1,45 @@ |
|||
import React from 'react'; |
|||
import NavSate from './navState'; |
|||
|
|||
const LayoutSetting = ({ value, onChange }) => { |
|||
return ( |
|||
<div |
|||
style={{ |
|||
margin: 5, |
|||
display: 'flex', |
|||
}} |
|||
> |
|||
{['sidemenu', 'topmenu'].map(layout => ( |
|||
<div |
|||
onClick={() => onChange && onChange(layout)} |
|||
key={layout} |
|||
style={{ |
|||
width: 70, |
|||
height: 44, |
|||
textAlign: 'center', |
|||
margin: 8, |
|||
}} |
|||
> |
|||
<NavSate |
|||
type={layout} |
|||
state={value === layout ? 'active' : 'default'} |
|||
alt={layout} |
|||
/> |
|||
</div> |
|||
))} |
|||
<div |
|||
key="topside" |
|||
style={{ |
|||
width: 70, |
|||
height: 44, |
|||
textAlign: 'center', |
|||
margin: 8, |
|||
}} |
|||
> |
|||
<NavSate type="topside" state="disable" alt="topside" /> |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default LayoutSetting; |
|||
@ -0,0 +1,55 @@ |
|||
import React from 'react'; |
|||
import styles from './ThemeColor.less'; |
|||
|
|||
const Tag = ({ color, ...rest }) => { |
|||
return ( |
|||
<div |
|||
{...rest} |
|||
style={{ |
|||
backgroundColor: color, |
|||
}} |
|||
/> |
|||
); |
|||
}; |
|||
|
|||
const ThemeColor = ({ colors, value, onChange }) => { |
|||
let colorList = colors; |
|||
if (!colors) { |
|||
colorList = [ |
|||
'#F5222D', |
|||
'#FA541C', |
|||
'#FA8C16', |
|||
'#FAAD14', |
|||
'#FADB14', |
|||
'#A0D911', |
|||
'#52C41A', |
|||
'#13C2C2', |
|||
'#1890FF', |
|||
'#2F54EB', |
|||
'#722ED1', |
|||
'#EB2F96', |
|||
]; |
|||
} |
|||
|
|||
return ( |
|||
<div className={styles.themeColor}> |
|||
<h3 className={styles.title}>主题颜色</h3> |
|||
{colorList.map((color) => { |
|||
const classname = |
|||
value === color |
|||
? `${styles.colorBlock} ${styles.active}` |
|||
: styles.colorBlock; |
|||
return ( |
|||
<Tag |
|||
className={classname} |
|||
key={color} |
|||
color={color} |
|||
onClick={() => onChange && onChange(color)} |
|||
/> |
|||
); |
|||
})} |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default ThemeColor; |
|||
@ -0,0 +1,26 @@ |
|||
.themeColor { |
|||
overflow: hidden; |
|||
margin-top: 15px; |
|||
margin-left: -5px; |
|||
margin-right: -5px; |
|||
.title { |
|||
font-size: 14px; |
|||
color: rgba(0, 0, 0, 0.65); |
|||
line-height: 22px; |
|||
margin-bottom: 5px; |
|||
} |
|||
.colorBlock { |
|||
width: 16px; |
|||
height: 16px; |
|||
border-radius: 2px; |
|||
float: left; |
|||
margin: 5px; |
|||
&.active { |
|||
width: 18px; |
|||
height: 18px; |
|||
margin: 4px; |
|||
border: 2px solid hsl(90, 100%, 50%); |
|||
box-shadow: 0 0 4px 0 hsl(90, 100%, 50%); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,218 @@ |
|||
import React, { PureComponent, Fragment } from 'react'; |
|||
import { Select, List, Switch, Divider, Radio } from 'antd'; |
|||
import styles from './index.less'; |
|||
import ThemeColor from './ThemeColor'; |
|||
import LayoutSeting from './LayoutSetting'; |
|||
|
|||
const RadioGroup = Radio.Group; |
|||
|
|||
const ColorBlock = ({ color, title }) => ( |
|||
<Fragment> |
|||
<div |
|||
className={styles.color_block} |
|||
style={{ |
|||
backgroundColor: color, |
|||
}} |
|||
/> |
|||
<div className={styles.color_block_title}>{title}</div> |
|||
</Fragment> |
|||
); |
|||
|
|||
const Body = ({ children, title, style }) => ( |
|||
<div |
|||
style={{ |
|||
padding: 15, |
|||
...style, |
|||
}} |
|||
> |
|||
<h3 className={styles.bodyTitle}>{title}</h3> |
|||
{children} |
|||
</div> |
|||
); |
|||
|
|||
class Sidebar extends PureComponent { |
|||
constructor(props) { |
|||
super(props); |
|||
this.defaultstate = { |
|||
collapse: false, |
|||
silderTheme: 'dark', |
|||
themeColor: '#1890FF', |
|||
layout: 'sidemenu', |
|||
grid: 'Fluid', |
|||
fixedHeader: false, |
|||
autoHideHeader: false, |
|||
fixSiderbar: false, |
|||
colorWeak: 'close', |
|||
}; |
|||
const propsState = this.propsToState(props); |
|||
this.state = { ...this.defaultstate, ...propsState }; |
|||
} |
|||
componentWillReceiveProps(props) { |
|||
this.setState(this.propsToState(props)); |
|||
} |
|||
getLayOutSetting = () => { |
|||
const { layout } = this.state; |
|||
return [ |
|||
{ |
|||
title: '栅格模式', |
|||
isShow: true, |
|||
action: [ |
|||
<Select |
|||
value={this.state.grid} |
|||
onSelect={value => this.changeSetting('grid', value)} |
|||
style={{ width: 120 }} |
|||
> |
|||
<Select.Option value="Wide">Wide</Select.Option> |
|||
<Select.Option value="Fluid">Fluid</Select.Option> |
|||
</Select>, |
|||
], |
|||
}, |
|||
{ |
|||
title: 'Fixed Header', |
|||
isShow: true, |
|||
action: [ |
|||
<Switch |
|||
checked={!!this.state.fixedHeader} |
|||
onChange={checked => this.changeSetting('fixedHeader', checked)} |
|||
/>, |
|||
], |
|||
}, |
|||
{ |
|||
title: '↳ 下滑时隐藏 Header', |
|||
isShow: true, |
|||
action: [ |
|||
<Switch |
|||
checked={!!this.state.autoHideHeader} |
|||
onChange={checked => this.changeSetting('autoHideHeader', checked)} |
|||
/>, |
|||
], |
|||
}, |
|||
{ |
|||
title: 'Fix Siderbar', |
|||
isShow: layout === 'sidemenu', |
|||
action: [ |
|||
<Switch |
|||
checked={!!this.state.fixSiderbar} |
|||
onChange={this.fixSiderbar} |
|||
/>, |
|||
], |
|||
}, |
|||
].filter(item => item.isShow); |
|||
}; |
|||
fixSiderbar = (checked) => { |
|||
this.changeSetting('fixSiderbar', checked); |
|||
}; |
|||
changeSetting = (key, value) => { |
|||
const nextState = {}; |
|||
nextState[key] = value; |
|||
if (key === 'layout') { |
|||
if (value === 'topmenu') { |
|||
nextState.grid = 'Wide'; |
|||
} else { |
|||
nextState.grid = 'Fluid'; |
|||
} |
|||
} |
|||
this.setState(nextState, () => { |
|||
if (this.props.onChange) { |
|||
this.props.onChange(this.state); |
|||
} |
|||
}); |
|||
}; |
|||
propsToState = (props) => { |
|||
const nextState = {}; |
|||
Object.keys(props).forEach((key) => { |
|||
if (props[key] && this.defaultstate[key] !== undefined) { |
|||
nextState[key] = props[key]; |
|||
} |
|||
}); |
|||
return nextState; |
|||
}; |
|||
togglerContent = () => { |
|||
this.changeSetting('collapse', !this.state.collapse); |
|||
}; |
|||
render() { |
|||
const radioStyle = { |
|||
display: 'block', |
|||
}; |
|||
return ( |
|||
<div |
|||
className={`${styles.sidebar} ${ |
|||
this.state.collapse ? styles.show : '' |
|||
}`}
|
|||
> |
|||
<div className={styles.mini_bar} onClick={this.togglerContent}> |
|||
<img |
|||
alt="logo" |
|||
src="https://gw.alipayobjects.com/zos/rmsportal/ApQgLmeZDNJMomKNvavq.svg" |
|||
/> |
|||
</div> |
|||
<div className={styles.content}> |
|||
<Body |
|||
title="整体风格设置" |
|||
style={{ |
|||
paddingBottom: 10, |
|||
}} |
|||
> |
|||
<RadioGroup |
|||
onChange={({ target }) => |
|||
this.changeSetting('silderTheme', target.value) |
|||
} |
|||
value={this.state.silderTheme} |
|||
> |
|||
<Radio style={radioStyle} value="dark"> |
|||
<ColorBlock color="#002140" title="深色导航" /> |
|||
</Radio> |
|||
<Radio style={radioStyle} value="ligth"> |
|||
<ColorBlock color="#E9E9E9" title="浅色导航" /> |
|||
</Radio> |
|||
</RadioGroup> |
|||
<ThemeColor |
|||
value={this.state.themeColor} |
|||
onChange={color => this.changeSetting('themeColor', color)} |
|||
/> |
|||
</Body> |
|||
<Divider style={{ margin: 0 }} /> |
|||
<Body title="导航设置 "> |
|||
<LayoutSeting |
|||
value={this.state.layout} |
|||
onChange={layout => this.changeSetting('layout', layout)} |
|||
/> |
|||
<List |
|||
split={false} |
|||
dataSource={this.getLayOutSetting()} |
|||
renderItem={item => ( |
|||
<List.Item actions={item.action}>{item.title}</List.Item> |
|||
)} |
|||
/> |
|||
</Body> |
|||
<Divider style={{ margin: 0 }} /> |
|||
<Body title="其他设置"> |
|||
<List |
|||
split={false} |
|||
dataSource={[ |
|||
{ |
|||
title: '色弱模式', |
|||
action: [ |
|||
<Select |
|||
value={this.state.colorWeak} |
|||
onSelect={value => this.changeSetting('colorWeak', value)} |
|||
style={{ width: 120 }} |
|||
> |
|||
<Select.Option value="open">打开</Select.Option> |
|||
<Select.Option value="colse">关闭</Select.Option> |
|||
</Select>, |
|||
], |
|||
}, |
|||
]} |
|||
renderItem={item => ( |
|||
<List.Item actions={item.action}>{item.title}</List.Item> |
|||
)} |
|||
/> |
|||
</Body> |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default Sidebar; |
|||
@ -0,0 +1,62 @@ |
|||
.sidebar { |
|||
position: fixed; |
|||
right: -336px; |
|||
top: 150px; |
|||
transition: 0.3s; |
|||
display: flex; |
|||
z-index: 9; |
|||
&.show { |
|||
right: 0; |
|||
} |
|||
.mini_bar { |
|||
width: 50px; |
|||
height: 45px; |
|||
border-top-left-radius: 28px; |
|||
border-bottom-left-radius: 28px; |
|||
text-align: center; |
|||
font-size: 24px; |
|||
background: white; |
|||
box-shadow: 0 0 6px 0 rgba(0, 21, 41, 0.35); |
|||
img { |
|||
width: 28px; |
|||
height: 28px; |
|||
} |
|||
} |
|||
.content { |
|||
width: 336px; |
|||
background: white; |
|||
box-shadow: 0 0 6px 0 rgba(0, 21, 41, 0.35); |
|||
box-shadow: -3px 0 10px 3px rgba(183, 183, 183, 0.3); |
|||
:global { |
|||
.ant-switch-checked { |
|||
background-color: #87d068; |
|||
} |
|||
.ant-list-item { |
|||
padding-top: 7px; |
|||
padding-bottom: 7px; |
|||
} |
|||
} |
|||
} |
|||
.color_block { |
|||
width: 38px; |
|||
height: 22px; |
|||
margin: 4px; |
|||
margin-right: 12px; |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
background: #002140; |
|||
border-radius: 2px; |
|||
} |
|||
.color_block_title { |
|||
display: inline-block; |
|||
font-size: 14px; |
|||
color: rgba(0, 0, 0, 0.65); |
|||
line-height: 22px; |
|||
} |
|||
.bodyTitle { |
|||
font-size: 14px; |
|||
color: rgba(0, 0, 0, 0.85); |
|||
line-height: 22px; |
|||
margin-bottom: 10px; |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
import React from 'react'; |
|||
|
|||
const UrlMap = { |
|||
sidemenu: { |
|||
active: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/YcoRFFREHxmXebXryzhC.svg', |
|||
default: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/FUcluUxklaHEgbCfosWO.svg', |
|||
disable: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/nnbGSviuREntXtWJEquJ.svg', |
|||
}, |
|||
topside: { |
|||
active: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/cRVYqCCkknDizjyHpjgR.svg', |
|||
default: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/ygeNiTUuhrHuNMjkVQkv.svg', |
|||
disable: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/KtcgueNbQdMSbxGDigdT.svg', |
|||
}, |
|||
topmenu: { |
|||
active: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/RCtKLhlMLWYKaWDzLsBC.svg', |
|||
default: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/pMRBYBPSKXgEGrglJsdl.svg', |
|||
disable: |
|||
'http://alipay-os.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/PvQhRIcAGTKewuOfJOSn.svg', |
|||
}, |
|||
}; |
|||
|
|||
const navState = ({ alt, type, state }) => { |
|||
const url = UrlMap[type][state]; |
|||
return <img src={url} alt={alt} />; |
|||
}; |
|||
|
|||
export default navState; |
|||
@ -1,31 +1,53 @@ |
|||
.main { |
|||
display: flex; |
|||
.head { |
|||
width: 100%; |
|||
transition: background 0.3s, width 0.2s; |
|||
height: 64px; |
|||
margin: auto; |
|||
max-width: 1200px; |
|||
.left { |
|||
flex: 1; |
|||
padding: 0 12px 0 0; |
|||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); |
|||
position: relative; |
|||
&.ligth { |
|||
background-color: #fff; |
|||
} |
|||
.main { |
|||
display: flex; |
|||
.logo { |
|||
width: 160px; |
|||
height: 64px; |
|||
position: relative; |
|||
line-height: 64px; |
|||
transition: all 0.3s; |
|||
overflow: hidden; |
|||
img { |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
height: 32px; |
|||
} |
|||
h1 { |
|||
color: #fff; |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
font-size: 16px; |
|||
margin: 0 0 0 12px; |
|||
font-weight: 400; |
|||
} |
|||
height: 64px; |
|||
padding-left: 24px; |
|||
&.wide { |
|||
max-width: 1200px; |
|||
margin: auto; |
|||
padding-left: 4px; |
|||
} |
|||
.left { |
|||
flex: 1; |
|||
display: flex; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.logo { |
|||
width: 160px; |
|||
height: 64px; |
|||
position: relative; |
|||
line-height: 64px; |
|||
transition: all 0.3s; |
|||
overflow: hidden; |
|||
img { |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
height: 32px; |
|||
} |
|||
h1 { |
|||
color: #fff; |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
font-size: 16px; |
|||
margin: 0 0 0 12px; |
|||
font-weight: 400; |
|||
} |
|||
} |
|||
|
|||
.ligth { |
|||
h1 { |
|||
color: #002140; |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,38 @@ |
|||
|
|||
import React, { Fragment } from 'react'; |
|||
import { Layout, Icon } from 'antd'; |
|||
import GlobalFooter from '../components/GlobalFooter'; |
|||
|
|||
const { Footer } = Layout; |
|||
const FooterView = () => ( |
|||
<Footer style={{ padding: 0 }}> |
|||
<GlobalFooter |
|||
links={[ |
|||
{ |
|||
key: 'Pro 首页', |
|||
title: 'Pro 首页', |
|||
href: 'http://pro.ant.design', |
|||
blankTarget: true, |
|||
}, |
|||
{ |
|||
key: 'github', |
|||
title: <Icon type="github" />, |
|||
href: 'https://github.com/ant-design/ant-design-pro', |
|||
blankTarget: true, |
|||
}, |
|||
{ |
|||
key: 'Ant Design', |
|||
title: 'Ant Design', |
|||
href: 'http://ant.design', |
|||
blankTarget: true, |
|||
}, |
|||
]} |
|||
copyright={ |
|||
<Fragment> |
|||
Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品 |
|||
</Fragment> |
|||
} |
|||
/> |
|||
</Footer> |
|||
); |
|||
export default FooterView; |
|||
@ -0,0 +1,153 @@ |
|||
import React, { PureComponent } from 'react'; |
|||
import { Layout, message } from 'antd'; |
|||
import Animate from 'rc-animate'; |
|||
import { connect } from 'dva'; |
|||
import { routerRedux } from 'dva/router'; |
|||
import GlobalHeader from '../components/GlobalHeader'; |
|||
import TopNavHeader from '../components/TopNavHeader'; |
|||
import styles from './Header.less'; |
|||
import Authorized from '../utils/Authorized'; |
|||
|
|||
const { Header } = Layout; |
|||
|
|||
class HeaderView extends PureComponent { |
|||
state = { |
|||
visible: true, |
|||
}; |
|||
componentDidMount() { |
|||
document.getElementById('root').addEventListener('scroll', this.handScroll); |
|||
} |
|||
componentWillUnmount() { |
|||
document |
|||
.getElementById('root') |
|||
.removeEventListener('scroll', this.handScroll); |
|||
} |
|||
getHeadWidth = () => { |
|||
if ( |
|||
!this.props.fixedHeader || |
|||
this.props.layout === 'topmenu' || |
|||
this.props.fixSiderbar |
|||
) { |
|||
return '100%'; |
|||
} |
|||
if (!this.props.collapsed) { |
|||
return 'calc(100% - 256px)'; |
|||
} |
|||
if (this.props.collapsed) { |
|||
return 'calc(100% - 80px)'; |
|||
} |
|||
}; |
|||
handleNoticeClear = (type) => { |
|||
message.success(`清空了${type}`); |
|||
this.props.dispatch({ |
|||
type: 'global/clearNotices', |
|||
payload: type, |
|||
}); |
|||
}; |
|||
handleMenuClick = ({ key }) => { |
|||
if (key === 'userCenter') { |
|||
this.props.dispatch(routerRedux.push('/user-profile/user-center')); |
|||
return; |
|||
} |
|||
if (key === 'triggerError') { |
|||
this.props.dispatch(routerRedux.push('/exception/trigger')); |
|||
return; |
|||
} |
|||
if (key === 'userinfo') { |
|||
this.props.dispatch(routerRedux.push('/user-profile/userinfo/base')); |
|||
return; |
|||
} |
|||
if (key === 'logout') { |
|||
this.props.dispatch({ |
|||
type: 'login/logout', |
|||
}); |
|||
} |
|||
}; |
|||
handleNoticeVisibleChange = (visible) => { |
|||
if (visible) { |
|||
this.props.dispatch({ |
|||
type: 'global/fetchNotices', |
|||
}); |
|||
} |
|||
}; |
|||
handScroll = () => { |
|||
if (!this.props.autoHideHeader) { |
|||
return; |
|||
} |
|||
const { scrollTop } = document.getElementById('root'); |
|||
if (!this.ticking) { |
|||
this.ticking = false; |
|||
requestAnimationFrame(() => { |
|||
if (scrollTop > 400 && this.state.visible) { |
|||
this.setState({ |
|||
visible: false, |
|||
}); |
|||
} |
|||
if (scrollTop < 400 && !this.state.visible) { |
|||
this.setState({ |
|||
visible: true, |
|||
}); |
|||
} |
|||
this.ticking = false; |
|||
}); |
|||
} |
|||
}; |
|||
render() { |
|||
const { |
|||
logo, |
|||
isMobile, |
|||
handleMenuCollapse, |
|||
silderTheme, |
|||
layout, |
|||
fixedHeader, |
|||
} = this.props; |
|||
const isTop = layout === 'topmenu'; |
|||
const HeaderDom = this.state.visible ? ( |
|||
<Header |
|||
style={{ padding: 0, width: this.getHeadWidth() }} |
|||
className={fixedHeader ? styles.fixedHeader : ''} |
|||
> |
|||
{isTop && !isMobile ? ( |
|||
<TopNavHeader |
|||
logo={logo} |
|||
theme={silderTheme} |
|||
mode="horizontal" |
|||
Authorized={Authorized} |
|||
isMobile={isMobile} |
|||
onNoticeClear={this.handleNoticeClear} |
|||
onCollapse={handleMenuCollapse} |
|||
onMenuClick={this.handleMenuClick} |
|||
onNoticeVisibleChange={this.handleNoticeVisibleChange} |
|||
{...this.props} |
|||
/> |
|||
) : ( |
|||
<GlobalHeader |
|||
logo={logo} |
|||
onNoticeClear={this.handleNoticeClear} |
|||
onCollapse={handleMenuCollapse} |
|||
onMenuClick={this.handleMenuClick} |
|||
onNoticeVisibleChange={this.handleNoticeVisibleChange} |
|||
{...this.props} |
|||
/> |
|||
)} |
|||
</Header> |
|||
) : null; |
|||
return ( |
|||
<Animate component="" transitionName="fade"> |
|||
{HeaderDom} |
|||
</Animate> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default connect(({ user, global, setting, loading }) => ({ |
|||
currentUser: user.currentUser, |
|||
collapsed: global.collapsed, |
|||
fetchingNotices: loading.effects['global/fetchNotices'], |
|||
notices: global.notices, |
|||
layout: setting.layout, |
|||
silderTheme: setting.silderTheme, |
|||
fixedHeader: setting.fixedHeader, |
|||
fixSiderbar: setting.fixSiderbar, |
|||
autoHideHeader: setting.autoHideHeader, |
|||
}))(HeaderView); |
|||
@ -0,0 +1,6 @@ |
|||
.fixedHeader { |
|||
position: fixed; |
|||
top: 0; |
|||
width: 100%; |
|||
z-index: 9; |
|||
} |
|||
@ -0,0 +1,94 @@ |
|||
import React, { PureComponent } from 'react'; |
|||
import { Spin } from 'antd'; |
|||
import { enquireScreen } from 'enquire-js'; |
|||
import { connect } from 'dva'; |
|||
import BasicLayout from './BasicLayout'; |
|||
import { getMenuData } from '../common/menu'; |
|||
|
|||
/** |
|||
* 根据菜单取得重定向地址. |
|||
*/ |
|||
|
|||
const MenuData = getMenuData(); |
|||
const getRedirectData = () => { |
|||
const redirectData = []; |
|||
const getRedirect = (item) => { |
|||
if (item && item.children) { |
|||
if (item.children[0] && item.children[0].path) { |
|||
redirectData.push({ |
|||
from: `${item.path}`, |
|||
to: `${item.children[0].path}`, |
|||
}); |
|||
item.children.forEach((children) => { |
|||
getRedirect(children); |
|||
}); |
|||
} |
|||
} |
|||
}; |
|||
MenuData.forEach(getRedirect); |
|||
return redirectData; |
|||
}; |
|||
const redirectData = getRedirectData(); |
|||
|
|||
class LodingPage extends PureComponent { |
|||
state = { |
|||
loading: true, |
|||
isMobile: false, |
|||
}; |
|||
componentDidMount() { |
|||
enquireScreen((mobile) => { |
|||
this.setState({ |
|||
isMobile: mobile, |
|||
}); |
|||
}); |
|||
this.props.dispatch({ |
|||
type: 'user/fetchCurrent', |
|||
}); |
|||
const urlParams = new URL(window.location.href); |
|||
const settingString = urlParams.searchParams.get('setting'); |
|||
if (settingString) { |
|||
const setting = {}; |
|||
settingString.split(';').forEach((keyValue) => { |
|||
const [key, value] = keyValue.split(':'); |
|||
setting[key] = value; |
|||
}); |
|||
this.props.dispatch({ |
|||
type: 'setting/changeSetting', |
|||
payload: setting, |
|||
}); |
|||
} |
|||
this.hideLoading(); |
|||
} |
|||
hideLoading() { |
|||
this.setState({ |
|||
loading: false, |
|||
}); |
|||
} |
|||
render() { |
|||
if (this.state.loading) { |
|||
return ( |
|||
<div |
|||
style={{ |
|||
width: '100%', |
|||
height: '100%', |
|||
margin: 'auto', |
|||
paddingTop: 50, |
|||
textAlign: 'center', |
|||
}} |
|||
> |
|||
<Spin size="large" /> |
|||
</div> |
|||
); |
|||
} |
|||
return ( |
|||
<BasicLayout |
|||
isMobile={this.state.isMobile} |
|||
menuData={MenuData} |
|||
redirectData={redirectData} |
|||
{...this.props} |
|||
/> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default connect()(LodingPage); |
|||
@ -0,0 +1,32 @@ |
|||
export default { |
|||
namespace: 'setting', |
|||
|
|||
state: { |
|||
collapse: false, |
|||
silderTheme: 'dark', |
|||
themeColor: '#1890FF', |
|||
layout: 'sidemenu', |
|||
grid: 'Fluid', |
|||
fixedHeader: false, |
|||
autoHideHeader: false, |
|||
fixSiderbar: false, |
|||
colorWeak: 'close', |
|||
}, |
|||
reducers: { |
|||
changeSetting(state, { payload }) { |
|||
const urlParams = new URL(window.location.href); |
|||
let urlParamsString = ''; |
|||
Object.keys(payload).forEach((key) => { |
|||
if (payload[key] && state[key] !== undefined && key !== 'collapse') { |
|||
urlParamsString += `${key}:${payload[key]};`; |
|||
} |
|||
}); |
|||
urlParams.searchParams.set('setting', urlParamsString); |
|||
window.history.replaceState(null, 'setting', urlParams.href); |
|||
return { |
|||
...state, |
|||
...payload, |
|||
}; |
|||
}, |
|||
}, |
|||
}; |
|||
Loading…
Reference in new issue