add react版前端
This commit is contained in:
11
web-react/src/views/error/404.jsx
Normal file
11
web-react/src/views/error/404.jsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import React, { Component } from 'react'
|
||||
|
||||
export default class index extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
404
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
100
web-react/src/views/login/index.jsx
Normal file
100
web-react/src/views/login/index.jsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, Form, Input, message as Message } from 'antd'
|
||||
import Container from 'components/container'
|
||||
import { encryptByRSA } from 'util/rsa'
|
||||
import { RSA_PUBLIC_KEY } from 'util/global'
|
||||
import { api } from 'common/api'
|
||||
import { token } from 'common/token'
|
||||
import 'assets/style/login.less'
|
||||
|
||||
export default class index extends Component {
|
||||
|
||||
state = {
|
||||
loading: false,
|
||||
|
||||
focusUser: false,
|
||||
focusPassword: false
|
||||
}
|
||||
|
||||
backgroundImage = require(`assets/image/login-bg-0${Math.floor(Math.random() * 4)}.jpg`)
|
||||
|
||||
focus = {
|
||||
user: false,
|
||||
password: false
|
||||
}
|
||||
|
||||
form = React.createRef()
|
||||
|
||||
onLogin = (values) => {
|
||||
this.setState({
|
||||
loading: true
|
||||
})
|
||||
|
||||
let { account, password } = values
|
||||
password = encryptByRSA(password, RSA_PUBLIC_KEY)
|
||||
api.login({ account, password }).then(({ success, data, message }) => {
|
||||
if (success) {
|
||||
token.value = data
|
||||
Message.success('登录成功')
|
||||
this.props.history.replace('/')
|
||||
} else {
|
||||
Message.error(message)
|
||||
}
|
||||
}).catch(({ message }) => {
|
||||
if (typeof message === 'object' && message[0]) {
|
||||
Message.error(message[0].messages[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div className="yo-login">
|
||||
<img src={this.backgroundImage.default} alt="" />
|
||||
<div className="yo-login--placeholder">
|
||||
<Container mode="sm">
|
||||
<Form ref={this.form} layout="vertical" onFinish={this.onLogin}>
|
||||
<Form.Item
|
||||
name="account"
|
||||
className={!this.state.focusUser && 'yo-login--label'}
|
||||
colon={false}
|
||||
label="用户名"
|
||||
>
|
||||
<Input
|
||||
onBlur={() => { this.setState({ focusUser: !!this.form.current.getFieldValue('account') }); }}
|
||||
onFocus={() => { this.setState({ focusUser: true }) }}
|
||||
size="large"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
className={!this.state.focusPassword && 'yo-login--label'}
|
||||
colon={false}
|
||||
label="密码"
|
||||
>
|
||||
<Input.Password
|
||||
onBlur={() => { this.setState({ focusPassword: !!this.form.current.getFieldValue('password') }) }}
|
||||
onFocus={() => { this.setState({ focusPassword: true }) }}
|
||||
size="large"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item className="mt-lg">
|
||||
<Button
|
||||
disabled={this.form.user === '' || this.form.password === ''}
|
||||
loading={this.state.loading}
|
||||
block
|
||||
htmlType="submit"
|
||||
size="large"
|
||||
type="primary"
|
||||
>登录</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
138
web-react/src/views/main/_layout/content/index.jsx
Normal file
138
web-react/src/views/main/_layout/content/index.jsx
Normal file
@@ -0,0 +1,138 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Layout, Tabs, Menu, Dropdown } from 'antd'
|
||||
import NProgress from 'nprogress'
|
||||
import 'nprogress/nprogress.css'
|
||||
import AntIcon from 'components/ant-icon'
|
||||
|
||||
NProgress.configure({ parent: '.ant-layout-content > .yo-tab-external-mount > .yo-tab-external-mount-content' });
|
||||
|
||||
class ComponentDynamic extends Component {
|
||||
|
||||
state = {
|
||||
component: null
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
NProgress.start()
|
||||
|
||||
setTimeout(async () => {
|
||||
|
||||
let c;
|
||||
|
||||
try {
|
||||
c = await import(`../../../../pages${this.props.path}`)
|
||||
}
|
||||
catch {
|
||||
c = await import(`views/error/404`)
|
||||
}
|
||||
|
||||
this.setState({
|
||||
component: c.default
|
||||
}, () => {
|
||||
NProgress.done()
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (<>
|
||||
{
|
||||
this.state.component && <this.state.component {...this.props} />
|
||||
}
|
||||
</>)
|
||||
}
|
||||
}
|
||||
|
||||
export default class index extends Component {
|
||||
|
||||
state = {
|
||||
actived: ''
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props) {
|
||||
return {
|
||||
actived: props.actived
|
||||
}
|
||||
}
|
||||
|
||||
onChange = (activeKey) => {
|
||||
this.props.parent.setState({
|
||||
actived: activeKey
|
||||
})
|
||||
}
|
||||
|
||||
onClose = (targetKey, action) => {
|
||||
if (action === 'remove') {
|
||||
window.closeContentWindow(targetKey)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Layout.Content>
|
||||
<div className="yo-tab-external-mount">
|
||||
<Tabs
|
||||
type="editable-card"
|
||||
hideAdd
|
||||
activeKey={this.state.actived}
|
||||
onChange={this.onChange}
|
||||
onEdit={this.onClose}
|
||||
>
|
||||
{
|
||||
this.props.panes.map(pane => {
|
||||
return (
|
||||
<Tabs.TabPane
|
||||
closable={pane.closable}
|
||||
key={pane.key}
|
||||
tab={
|
||||
<Dropdown
|
||||
trigger={['contextMenu']}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item key="0">重新加载</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item key="1" onClick={() => window.closeContentWindow(pane.key)}>关闭</Menu.Item>
|
||||
<Menu.Item key="2" onClick={() => window.closeOtherContentWindow(pane.key)}>关闭其他标签页</Menu.Item>
|
||||
<Menu.Item key="3" onClick={() => window.closeRightContentWindow(pane.key)}>关闭右侧标签页</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<div>
|
||||
{pane.icon && <AntIcon type={pane.icon} />}
|
||||
{pane.title}
|
||||
</div>
|
||||
</Dropdown>
|
||||
}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Tabs>
|
||||
<div className="yo-tab-external-mount-content">
|
||||
{
|
||||
this.props.panes.map(pane => {
|
||||
return (
|
||||
<div
|
||||
key={pane.key}
|
||||
className={
|
||||
(pane.key === this.state.actived ? 'yo-tab-external-tabpane-active' : 'yo-tab-external-tabpane-inactive') + ' yo-tab-external-tabpane'
|
||||
}
|
||||
>
|
||||
<ComponentDynamic
|
||||
path={pane.path}
|
||||
id={pane.key}
|
||||
key={pane.key}
|
||||
param={pane.param}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Layout.Content>
|
||||
)
|
||||
}
|
||||
}
|
||||
36
web-react/src/views/main/_layout/header/index.jsx
Normal file
36
web-react/src/views/main/_layout/header/index.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Layout, Badge } from 'antd'
|
||||
import Components from 'components'
|
||||
import Logo from '../logo'
|
||||
import User from './user'
|
||||
|
||||
const { AntIcon, Container } = Components
|
||||
|
||||
export default class index extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Layout.Header>
|
||||
<Container mode="fluid">
|
||||
<div className="header-actions">
|
||||
<span className="header-action mr-md">
|
||||
<AntIcon type="menu" />
|
||||
</span>
|
||||
<Logo />
|
||||
{/* search */}
|
||||
</div>
|
||||
<div className="header-actions">
|
||||
<span className="header-action">
|
||||
<AntIcon type="reload" />
|
||||
</span>
|
||||
<span className="header-action">
|
||||
<Badge count="5">
|
||||
<AntIcon type="bell" />
|
||||
</Badge>
|
||||
</span>
|
||||
<User />
|
||||
</div>
|
||||
</Container>
|
||||
</Layout.Header>
|
||||
)
|
||||
}
|
||||
}
|
||||
121
web-react/src/views/main/_layout/header/user.jsx
Normal file
121
web-react/src/views/main/_layout/header/user.jsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import React, { Component } from 'react'
|
||||
import { withRouter } from 'react-router-dom'
|
||||
import { Modal, message as Message } from 'antd'
|
||||
import { isEqual } from 'lodash'
|
||||
import store from 'store'
|
||||
import { api } from 'common/api'
|
||||
import { token } from 'common/token'
|
||||
import Components from 'components'
|
||||
|
||||
const { getState, subscribe } = store
|
||||
|
||||
const { AntIcon, Image } = Components
|
||||
|
||||
const storePath = 'user'
|
||||
|
||||
let userOpenTimer, userCloseTimer
|
||||
let initDropdownHeight
|
||||
|
||||
class User extends Component {
|
||||
|
||||
state = {
|
||||
dropdownHeight: 0,
|
||||
user: getState(storePath)
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.unsubscribe = subscribe(storePath, () => {
|
||||
this.setState({
|
||||
user: getState(storePath)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// shouldComponentUpdate(props, state) {
|
||||
// return !isEqual(this.state, state)
|
||||
// }
|
||||
|
||||
componentDidMount() {
|
||||
initDropdownHeight = this.refs.dropdown.scrollHeight
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unsubscribe()
|
||||
}
|
||||
|
||||
onOpen = (e) => {
|
||||
clearTimeout(userCloseTimer)
|
||||
this.refs.container.classList.add('open')
|
||||
userOpenTimer = setTimeout(() => {
|
||||
this.refs.container.classList.add('drop')
|
||||
this.setState({
|
||||
dropdownHeight: initDropdownHeight
|
||||
})
|
||||
}, 300)
|
||||
}
|
||||
|
||||
onClose = (e) => {
|
||||
clearTimeout(userOpenTimer)
|
||||
this.refs.container.classList.remove('drop')
|
||||
this.setState({
|
||||
dropdownHeight: 0
|
||||
})
|
||||
userCloseTimer = setTimeout(() => {
|
||||
this.refs.container.classList.remove('open')
|
||||
}, 300)
|
||||
}
|
||||
|
||||
onAccountSetting = () => { }
|
||||
|
||||
onLogout = () => {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '是否确定退出登录',
|
||||
onOk: async () => {
|
||||
const { success, message } = await api.logout()
|
||||
if (success) {
|
||||
token.value = ''
|
||||
this.props.history.replace('/login')
|
||||
} else {
|
||||
Message.error(message)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className="user-container"
|
||||
onMouseEnter={(e) => { this.onOpen(e) }}
|
||||
onMouseLeave={(e) => { this.onClose(e) }}
|
||||
ref="container"
|
||||
>
|
||||
<div className="user-container-inner">
|
||||
<div className="user--base">
|
||||
<Image width="32" type="avatar" className="user--avatar" icon={<AntIcon type="user" />} id={this.state.user.avatar} />
|
||||
<span className="user--name">{this.state.user.nickName || this.state.user.name}</span>
|
||||
</div>
|
||||
<div className="user--dropdown" ref="dropdown" style={{ height: `${this.state.dropdownHeight}px` }}>
|
||||
<ul className="ant-dropdown-menu ant-dropdown-menu-vertical">
|
||||
<li className="ant-dropdown-menu-item" onClick={this.onAccountSetting}>
|
||||
<AntIcon type="user" />
|
||||
个人中心
|
||||
</li>
|
||||
<li className="ant-dropdown-menu-item-divider"></li>
|
||||
<li className="ant-dropdown-menu-item" onClick={this.onLogout}>
|
||||
<AntIcon type="logout" />
|
||||
退出登录
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default withRouter(User)
|
||||
14
web-react/src/views/main/_layout/logo.jsx
Normal file
14
web-react/src/views/main/_layout/logo.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React, { Component } from 'react'
|
||||
|
||||
export default class index extends Component {
|
||||
|
||||
logo = require('assets/image/logo-w.png')
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="logo">
|
||||
<img src={this.logo.default} alt="" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
69
web-react/src/views/main/_layout/sider/index.jsx
Normal file
69
web-react/src/views/main/_layout/sider/index.jsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Layout } from 'antd'
|
||||
import Swiper, { Mousewheel, Scrollbar } from 'swiper'
|
||||
import 'swiper/swiper-bundle.css'
|
||||
import Menu from './menu'
|
||||
|
||||
Swiper.use([Mousewheel, Scrollbar])
|
||||
|
||||
let timer,
|
||||
swiper
|
||||
|
||||
const siderSwiperOptions = {
|
||||
direction: 'vertical',
|
||||
slidesPerView: 'auto',
|
||||
freeMode: true,
|
||||
scrollbar: {
|
||||
el: '#layout--swiper-scrollbar',
|
||||
},
|
||||
mousewheel: true,
|
||||
}
|
||||
|
||||
const UpdateSwiper = () => {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
// 需要更新两次
|
||||
swiper.update()
|
||||
swiper.update()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
|
||||
export default class index extends Component {
|
||||
|
||||
state = {}
|
||||
|
||||
componentDidMount() {
|
||||
swiper = new Swiper('#layout--swiper-container', siderSwiperOptions)
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
UpdateSwiper()
|
||||
})
|
||||
}
|
||||
|
||||
updateSwiper() {
|
||||
UpdateSwiper()
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
UpdateSwiper()
|
||||
return null
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Layout.Sider className="yo-layout-sider" width="200" collapsed={false}>
|
||||
<div className="yo-sider-nav">
|
||||
<div className="swiper-container" id="layout--swiper-container">
|
||||
<div className="swiper-wrapper">
|
||||
<div className="swiper-slide">
|
||||
<Menu parent={this} menuStyle={{ height: '100%', borderRight: 0 }} nav={this.props.nav} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="swiper-scrollbar" id="layout--swiper-scrollbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout.Sider>
|
||||
)
|
||||
}
|
||||
}
|
||||
71
web-react/src/views/main/_layout/sider/menu.jsx
Normal file
71
web-react/src/views/main/_layout/sider/menu.jsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Menu } from 'antd'
|
||||
import AntIcon from 'components/ant-icon'
|
||||
|
||||
export default class index extends Component {
|
||||
|
||||
renderMenu = (menu) => {
|
||||
return menu.map((p) => {
|
||||
return p.children ? this.renderSubMenu(p) : this.renderMenuItem(p)
|
||||
})
|
||||
}
|
||||
|
||||
renderSubMenu = (menu) => {
|
||||
return (
|
||||
<Menu.SubMenu key={menu.id} title={menu.meta.title} icon={menu.meta.icon && <AntIcon type={menu.meta.icon} />}>
|
||||
{this.renderMenu(menu.children)}
|
||||
</Menu.SubMenu>
|
||||
)
|
||||
}
|
||||
|
||||
renderMenuItem = (menu) => {
|
||||
return (
|
||||
<Menu.Item key={menu.id} onClick={() => this.onOpenContentWindow(menu)}>
|
||||
{menu.meta.icon && <AntIcon type={menu.meta.icon} />}
|
||||
<span>{menu.meta.title}</span>
|
||||
</Menu.Item>
|
||||
)
|
||||
}
|
||||
|
||||
onOpenContentWindow = (menu) => {
|
||||
window.openContentWindow({
|
||||
key: menu.id,
|
||||
title: menu.meta.title,
|
||||
icon: menu.meta.icon,
|
||||
path: menu.component
|
||||
})
|
||||
}
|
||||
|
||||
onMenuOpenChange = () => {
|
||||
this.props.parent.updateSwiper()
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const props = {
|
||||
mode: 'inline',
|
||||
selectable: false,
|
||||
style: this.props.menuStyle,
|
||||
theme: 'light'
|
||||
}
|
||||
|
||||
const on = {
|
||||
onOpenChange: this.onMenuOpenChange,
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{
|
||||
this.props.nav.map((item, i) => {
|
||||
return (
|
||||
<section key={i}>
|
||||
<div className="yo-sider-nav--app">{item.app.name}</div>
|
||||
<Menu {...props} {...on}>{this.renderMenu(item.menu)}</Menu>
|
||||
</section>
|
||||
)
|
||||
})
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
245
web-react/src/views/main/index.jsx
Normal file
245
web-react/src/views/main/index.jsx
Normal file
@@ -0,0 +1,245 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Spin, Layout } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { api } from 'common/api'
|
||||
import { cloneDeep, groupBy, findIndex, last } from 'lodash'
|
||||
import store from 'store'
|
||||
import { EMPTY_ID } from 'util/global'
|
||||
|
||||
import Header from './_layout/header'
|
||||
import Sider from './_layout/sider'
|
||||
import Content from './_layout/content'
|
||||
|
||||
const { dispatch } = store
|
||||
|
||||
const serializeMenu = (menus) => {
|
||||
const menu = cloneDeep(menus)
|
||||
const children = groupBy(menu, 'pid')
|
||||
|
||||
const serialize = (m) => {
|
||||
m.forEach((p) => {
|
||||
if (children[p.id]) {
|
||||
p.children = serialize(children[p.id])
|
||||
}
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
return children[EMPTY_ID] ? serialize(children[EMPTY_ID]) : []
|
||||
}
|
||||
|
||||
const setNav = async (nav) => {
|
||||
const getNav = []
|
||||
nav.apps.forEach((app) => {
|
||||
getNav.push({
|
||||
app,
|
||||
})
|
||||
})
|
||||
|
||||
const menus = await api
|
||||
.$queue(getNav.map((p) => api.sysMenuChangeAwait({ application: p.app.code })))
|
||||
menus.forEach((menu, i) => {
|
||||
getNav[i].menu = serializeMenu(menu.data)
|
||||
})
|
||||
return getNav
|
||||
}
|
||||
|
||||
const getNewID = () => {
|
||||
return Math.random().toString(16).slice(2)
|
||||
}
|
||||
|
||||
export default class index extends Component {
|
||||
|
||||
state = {
|
||||
loading: true,
|
||||
nav: [],
|
||||
panes: [],
|
||||
actived: '',
|
||||
test: 0
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
window.openContentWindow = this.onOpenContentWindow
|
||||
window.closeContentWindow = this.onCloseContentWindow
|
||||
window.closeOtherContentWindow = this.onCloseOtherContentWindow
|
||||
window.closeRightContentWindow = this.onCloseRightContentWindow
|
||||
|
||||
api.getLoginUser().then(async ({ data }) => {
|
||||
const nav = await setNav(data)
|
||||
|
||||
dispatch({
|
||||
type: 'SET_USER_ACCOUNT',
|
||||
user: data
|
||||
})
|
||||
|
||||
this.setState({ loading: false, nav }, () => {
|
||||
this.onOpenContentWindow({
|
||||
title: '工作台',
|
||||
path: '/home',
|
||||
icon: 'home',
|
||||
closable: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开窗口
|
||||
* @param {*} settings
|
||||
* @returns
|
||||
*/
|
||||
onOpenContentWindow = (settings) => {
|
||||
if (settings.path) {
|
||||
const key = settings.key || getNewID();
|
||||
|
||||
/**
|
||||
* 如果当前标签页已打开,则只需要选中
|
||||
*/
|
||||
const pane = this.state.panes.find((p) => p.key === key);
|
||||
if (pane) {
|
||||
this.onChangeContentWindow(key);
|
||||
return;
|
||||
}
|
||||
|
||||
const path = settings.path.startsWith('/') ? settings.path : `/${settings.path}`;
|
||||
|
||||
/**
|
||||
* 向标签页队列中添加一个新的标签页
|
||||
*/
|
||||
const newPane = {
|
||||
key,
|
||||
closable: settings.closable === undefined ? true : settings.closable,
|
||||
icon: settings.icon,
|
||||
title: settings.title || '新建窗口',
|
||||
subTitle: settings.subTitle,
|
||||
component: null,
|
||||
path,
|
||||
param: settings.param,
|
||||
loaded: false,
|
||||
}
|
||||
this.setState({
|
||||
panes: [...this.state.panes, newPane]
|
||||
})
|
||||
|
||||
this.onChangeContentWindow(key);
|
||||
|
||||
//this.$refs.content.onLoadContentWindow(key);
|
||||
} else {
|
||||
console.warn('wrong component path');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭窗口
|
||||
* @param {*} key
|
||||
*/
|
||||
onCloseContentWindow = (key) => {
|
||||
key = key || this.state.actived
|
||||
const panes = this.state.panes
|
||||
const i = findIndex(panes, (p) => p.key === key)
|
||||
panes.splice(i, 1)
|
||||
|
||||
this.setState({
|
||||
panes
|
||||
}, () => {
|
||||
if (panes.length) {
|
||||
if (key === this.state.actived) {
|
||||
const pane = panes[i]
|
||||
if (pane) {
|
||||
this.onChangeContentWindow(pane.key)
|
||||
} else {
|
||||
this.onChangeContentWindow(panes[i - 1].key)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onCloseOtherContentWindow = (key) => {
|
||||
if (!key) return
|
||||
|
||||
const panes = this.state.panes
|
||||
let flag = false
|
||||
for (let i = panes.length - 1; i >= 0; i--) {
|
||||
const p = panes[i]
|
||||
if (p.key !== key && p.closable) {
|
||||
if (p.key === this.state.actived) {
|
||||
flag = true;
|
||||
}
|
||||
panes.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
panes
|
||||
}, () => {
|
||||
if (flag) {
|
||||
this.onChangeContentWindow(last(panes).key);
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
onCloseRightContentWindow = (key) => {
|
||||
if (!key) return
|
||||
|
||||
const panes = this.state.panes
|
||||
let flag = false
|
||||
for (let i = panes.length - 1; i >= 0; i--) {
|
||||
const p = panes[i]
|
||||
if (p.key !== key && p.closable) {
|
||||
if (p.key === this.tabActived) {
|
||||
flag = true
|
||||
}
|
||||
panes.splice(i, 1)
|
||||
} else if (p.key === key) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
panes
|
||||
}, () => {
|
||||
if (flag) {
|
||||
this.onChangeContentWindow(last(panes).key);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onReloadContentWindow = (key) => {
|
||||
if (!key) key = this.state.actived
|
||||
//this.$refs.content.onLoadContentWindow(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 选中窗口
|
||||
* @param {*} key
|
||||
*/
|
||||
onChangeContentWindow = (key) => {
|
||||
this.setState({
|
||||
actived: key
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />
|
||||
|
||||
return (
|
||||
<section className="yo-layout--spin">
|
||||
<Spin spinning={this.state.loading} indicator={antIcon}>
|
||||
<Layout className="yo-layout--top-nav--container-fluid yo-layout--top-nav">
|
||||
<Layout>
|
||||
<Header />
|
||||
<Layout className="yo-nav-theme--light">
|
||||
<Sider nav={this.state.nav} />
|
||||
<Content parent={this} panes={this.state.panes} actived={this.state.actived} />
|
||||
</Layout>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</Spin>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user