diff --git a/spug_web/config-overrides.js b/spug_web/config-overrides.js index 6382497..34a4ab5 100644 --- a/spug_web/config-overrides.js +++ b/spug_web/config-overrides.js @@ -3,13 +3,9 @@ * Copyright (c) * Released under the AGPL-3.0 License. */ -const {override, fixBabelImports, addDecoratorsLegacy} = require('customize-cra'); +const {override, addDecoratorsLegacy, addLessLoader} = require('customize-cra'); module.exports = override( addDecoratorsLegacy(), - fixBabelImports('import', { - libraryName: 'antd', - libraryDirectory: 'es', - style: true, - }) + addLessLoader(), ); diff --git a/spug_web/package.json b/spug_web/package.json index 90abee2..77c71f4 100644 --- a/spug_web/package.json +++ b/spug_web/package.json @@ -1,24 +1,23 @@ { "name": "spug_web", - "version": "0.1.0", + "version": "3.0.0", "private": true, "dependencies": { - "@antv/data-set": "^0.10.2", + "@ant-design/icons": "^4.3.0", "ace-builds": "^1.4.7", - "antd": "^3.25.0", - "axios": "^0.19.0", + "antd": "^4.8.5", + "axios": "^0.20.0", "bizcharts": "^3.5.6", "history": "^4.10.1", - "http-proxy-middleware": "^0.20.0", "lodash": "^4.17.19", - "mobx": "^5.15.0", - "mobx-react": "^6.1.4", + "mobx": "^5.15.6", + "mobx-react": "^6.3.0", "moment": "^2.24.0", - "react": "^16.11.0", + "react": "^16.13.1", "react-ace": "^8.0.0", - "react-dom": "^16.11.0", - "react-router-dom": "^5.1.2", - "react-scripts": "3.2.0", + "react-dom": "^16.13.1", + "react-router-dom": "^5.2.0", + "react-scripts": "3.4.3", "xterm": "^4.6.0", "xterm-addon-fit": "^0.4.0" }, @@ -44,9 +43,10 @@ ] }, "devDependencies": { - "@babel/plugin-proposal-decorators": "^7.7.0", - "babel-plugin-import": "^1.12.2", - "customize-cra": "^0.8.0", - "react-app-rewired": "^2.1.5" + "@babel/plugin-proposal-decorators": "^7.10.5", + "customize-cra": "^1.0.0", + "less": "^3.12.2", + "less-loader": "^7.1.0", + "react-app-rewired": "^2.1.6" } } diff --git a/spug_web/src/layout/Footer.js b/spug_web/src/layout/Footer.js index eb0b517..1960384 100644 --- a/spug_web/src/layout/Footer.js +++ b/spug_web/src/layout/Footer.js @@ -4,8 +4,9 @@ * Released under the AGPL-3.0 License. */ import React from 'react'; -import { Layout, Icon } from 'antd'; -import styles from './layout.module.css'; +import { Layout } from 'antd'; +import { CopyrightOutlined, GithubOutlined } from '@ant-design/icons'; +import styles from './layout.module.less'; export default class extends React.Component { @@ -14,15 +15,15 @@ export default class extends React.Component {
- 官网 - - + 文档
- Copyright 2020 By OpenSpug + Copyright 2020 By OpenSpug
diff --git a/spug_web/src/layout/Header.js b/spug_web/src/layout/Header.js index 0f0017e..00378e9 100644 --- a/spug_web/src/layout/Header.js +++ b/spug_web/src/layout/Header.js @@ -5,8 +5,16 @@ */ import React from 'react'; import { Link } from 'react-router-dom'; -import { Layout, Dropdown, Menu, List, Icon, Badge, Avatar } from 'antd'; -import styles from './layout.module.css'; +import { Layout, Dropdown, Menu, List, Badge, Avatar } from 'antd'; +import { + CheckOutlined, + MenuFoldOutlined, + MenuUnfoldOutlined, + UserOutlined, + LogoutOutlined, + NotificationOutlined +} from '@ant-design/icons'; +import styles from './layout.module.less'; import http from '../libs/http'; import history from '../libs/history'; import avatar from './avatar.png'; @@ -62,12 +70,12 @@ export default class extends React.Component { - 个人中心 + 个人中心 - 退出登录 + 退出登录 ); @@ -84,7 +92,7 @@ export default class extends React.Component { this.handleRead(e, item)}> } + avatar={} title={{item.title}} description={[
{item.content}
, @@ -105,7 +113,7 @@ export default class extends React.Component {
- + {this.props.collapsed ? : }
@@ -119,7 +127,7 @@ export default class extends React.Component { - + diff --git a/spug_web/src/layout/Sider.js b/spug_web/src/layout/Sider.js index 643a1e7..a5b7677 100644 --- a/spug_web/src/layout/Sider.js +++ b/spug_web/src/layout/Sider.js @@ -1,98 +1,64 @@ -/** - * Copyright (c) OpenSpug Organization. https://github.com/openspug/spug - * Copyright (c) - * Released under the AGPL-3.0 License. - */ import React from 'react'; -import { withRouter } from 'react-router-dom'; -import { Layout, Menu, Icon } from 'antd'; -import { hasPermission } from "../libs/functools"; -import history from '../libs/history'; +import { Layout, Menu } from 'antd'; +import { hasPermission, history } from 'libs'; import styles from './layout.module.css'; -import lodash from 'lodash'; -import menus from '../menus'; +import menus from '../routes'; import logo from './logo-spug.png'; import logoText from './logo-text.png'; - -class Sider extends React.Component { - constructor(props) { - super(props); - this._init(props); - this.state = { - selectedKeys: [], - openKeys: [lodash.get(this.keysMap, props.location.pathname)], - }; - } - - _init() { - this.keysMap = {}; - for (let item of menus.filter(x => x.child)) { - for (let m of item.child) { - this.keysMap[m.path] = item.title +const initPath = window.location.pathname; +let openKeys = []; +loop: + for (let item of menus.filter(x => x.child)) { + for (let sub of item.child) { + if (sub.path === initPath) { + openKeys = [item.title] + break loop } } } - UNSAFE_componentWillReceiveProps(nextProps, nextContext) { - if (nextProps.collapsed && !this.props.collapsed) { - this.setState({openKeys: []}) - } +export default function Sider(props) { + function makeMenu(menu) { + if (menu.auth && !hasPermission(menu.auth)) return null; + if (!menu.title) return null; + return menu.child ? _makeSubMenu(menu) : _makeItem(menu) } - makeMenu = (menu) => { - if (menu.auth !== undefined && !hasPermission(menu.auth)) return null; - return (menu.child) ? this.makeSubMenu(menu) : this.makeItem(menu) - }; + function _makeSubMenu(menu) { + return ( + {menu.icon}{menu.title}}> + {menu.child.map(menu => makeMenu(menu))} + + ) + } - makeItem = (menu) => { + function _makeItem(menu) { return ( - {menu.icon && } + {menu.icon} {menu.title} ) - }; + } - makeSubMenu = (subMenu) => { - return ( - {subMenu.title}}> - {subMenu.child.map(menu => this.makeMenu(menu))} - - ) - }; - - handleSelect = ({key}) => { - history.push(key) - }; - - handleClick = ({key}) => { - if (key === this.state.selectedKeys[0] && key !== this.props.location.pathname) { - this.props.history.push(key) - } - }; - - render() { - return ( - -
- Logo - logo-text -
+ return ( + +
+ Logo + logo-text +
+
this.setState({openKeys})} - > - {menus.map(menu => this.makeMenu(menu))} + className={styles.menus} + defaultSelectedKeys={[initPath]} + defaultOpenKeys={openKeys} + onSelect={menu => history.push(menu.key)}> + {menus.map(menu => makeMenu(menu))} - - ) - } -} - -export default withRouter(Sider) +
+
+ ) +} \ No newline at end of file diff --git a/spug_web/src/layout/layout.module.css b/spug_web/src/layout/layout.module.css deleted file mode 100644 index 651b7c4..0000000 --- a/spug_web/src/layout/layout.module.css +++ /dev/null @@ -1,108 +0,0 @@ -.header { - height: 64px; - padding: 0 12px 0 0; - background: #fff; - box-shadow: 2px 2px 2px rgba(0, 21, 41, 0.08); - position: relative; - z-index: 2; -} - -.header .icon { - margin-right: 10px; -} - -.content { - display: flex; - flex-direction: column; - justify-content: space-between; - padding: 24px 24px 0; - overflow-y: scroll; -} - -.trigger { - font-size: 20px; - line-height: 64px; - cursor: pointer; - transition: all 0.3s, padding 0s; - padding: 0 24px; - float: left; -} - -.trigger:hover { - background: rgb(233, 247, 254); -} - -.logo { - height: 64px; - line-height: 64px; - padding-left: 15px; - overflow: hidden; -} - -.logo h1 { - display: inline-block; - vertical-align: middle; - color: #ffffff; - font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; - font-size: 20px; - margin: 0 0 0 12px; - font-weight: 600; -} - -.logo img { - width: 50px; -} - -.right { - float: right; - height: 100%; -} - -.action { - cursor: pointer; - padding: 0 12px; - display: inline-block; - transition: all 0.3s; - height: 100%; -} - -.action:hover { - background: rgb(233, 247, 254); -} -.notify { - width: 350px; - padding: 0; -} -.notify :global(.ant-dropdown-menu-item:hover) { - background-color: #fff; -} -.notifyItem { - align-items: center; - cursor: pointer; - padding: 12px 24px; -} -.notifyItem:hover { - background-color: rgb(233, 247, 254); -} -.notifyFooter { - line-height: 46px; - text-align: center; - cursor: pointer; - border-top: 1px solid #e8e8e8; -} - -.footerZone { - width: 100%; - padding: 20px; - font-size: 14px; - text-align: center; - display: flex; - flex-direction: column; -} - -.footerZone .linksZone { - margin-bottom: 7px; -} -.footerZone .links{ - margin-right: 40px; -} diff --git a/spug_web/src/layout/layout.module.less b/spug_web/src/layout/layout.module.less new file mode 100644 index 0000000..bddd7ce --- /dev/null +++ b/spug_web/src/layout/layout.module.less @@ -0,0 +1,124 @@ +.header { + display: flex; + flex-direction: row; + padding: 0 12px 0 0;; + height: 48px; + line-height: 48px; + background: #fff; + box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); + z-index: 2; + + .left { + flex: 1; + + .trigger { + font-size: 20px; + line-height: 48px; + cursor: pointer; + transition: all 0.3s, padding 0s; + padding: 0 24px; + float: left; + } + + .trigger:hover { + background: rgba(0, 0, 0, 0.025); + } + } + + .right { + .action { + cursor: pointer; + padding: 0 12px; + display: inline-block; + transition: all 0.3s; + height: 100%; + } + + .action:hover { + background: rgba(0, 0, 0, 0.025); + } + } +} + +.content { + padding: 24px 24px 0; + overflow-y: scroll; +} + +.sider { + height: 100%; + width: 208px; + min-height: 100vh; + box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05); + overflow: hidden; + + .menus { + overflow: auto; + + } + + .logo { + height: 64px; + line-height: 64px; + padding-left: 24px; + background-color: #002140; + overflow: hidden; + } + + .logo h1 { + display: inline-block; + vertical-align: middle; + color: #ffffff; + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; + font-size: 20px; + margin: 0 0 0 12px; + font-weight: 600; + } + + .logo img { + height: 32px; + } +} + +.footer { + margin: 48px 0 24px; + text-align: center; + color: rgba(0, 0, 0, .45); +} + +.router { + display: flex; + height: 80%; + align-items: center; + + .imgBlock { + flex: 0 0 62.5%; + width: 62.5%; + zoom: 1; + padding-right: 88px; + + .img { + float: right; + height: 360px; + width: 100%; + max-width: 430px; + background-size: contain; + background: url('./404.svg') no-repeat 50% 50%; + } + } + + .title { + color: #434e59; + font-size: 72px; + font-weight: 600; + line-height: 72px; + margin-bottom: 24px; + } + + .desc { + color: rgba(0, 0, 0, .45); + font-size: 20px; + line-height: 28px; + margin-bottom: 16px; + } +} \ No newline at end of file diff --git a/spug_web/src/pages/config/setting/index.js b/spug_web/src/pages/config/setting/index.js index 7d64c68..0008eb3 100644 --- a/spug_web/src/pages/config/setting/index.js +++ b/spug_web/src/pages/config/setting/index.js @@ -5,7 +5,8 @@ */ import React from 'react'; import { observer } from 'mobx-react'; -import { Menu, Input, Button, Select, PageHeader, Icon, Modal } from 'antd'; +import { Menu, Input, Button, Select, PageHeader, Modal } from 'antd'; +import { TableOutlined, UnorderedListOutlined, NumberOutlined } from '@ant-design/icons'; import envStore from '../environment/store'; import styles from './index.module.css'; import history from 'libs/history'; @@ -84,9 +85,9 @@ class Index extends React.Component { diff --git a/spug_web/src/pages/login/index.js b/spug_web/src/pages/login/index.js index dae3565..8b7dd29 100644 --- a/spug_web/src/pages/login/index.js +++ b/spug_web/src/pages/login/index.js @@ -4,7 +4,8 @@ * Released under the AGPL-3.0 License. */ import React from 'react'; -import { Form, Input, Icon, Button, Tabs, Modal } from 'antd'; +import { Form, Input, Button, Tabs, Modal } from 'antd'; +import { UserOutlined, LockOutlined } from '@ant-design/icons'; import styles from './login.module.css'; import history from 'libs/history'; import { http, updatePermissions } from 'libs'; @@ -94,7 +95,7 @@ class LoginIndex extends React.Component { size="large" autoComplete="off" placeholder="请输入账户" - prefix={}/> + prefix={}/> )} @@ -105,7 +106,7 @@ class LoginIndex extends React.Component { autoComplete="off" placeholder="请输入密码" onPressEnter={this.handleSubmit} - prefix={}/> + prefix={}/> )} diff --git a/spug_web/src/pages/ssh/FileManager.js b/spug_web/src/pages/ssh/FileManager.js index 71454d6..878fff2 100644 --- a/spug_web/src/pages/ssh/FileManager.js +++ b/spug_web/src/pages/ssh/FileManager.js @@ -4,7 +4,8 @@ * Released under the AGPL-3.0 License. */ import React from 'react'; -import { Drawer, Breadcrumb, Table, Icon, Divider, Switch, Button, Progress, Modal, message } from 'antd'; +import { Drawer, Breadcrumb, Table, Divider, Switch, Button, Progress, Modal, message } from 'antd'; +import { DownloadOutlined, FileOutlined, FolderOutlined, DeleteOutlined, HomeOutlined } from '@ant-design/icons'; import { http, uniqueId, X_TOKEN } from 'libs'; import lds from 'lodash'; import styles from './index.module.css' @@ -31,12 +32,12 @@ class FileManager extends React.Component { key: 'name', render: info => info.kind === 'd' ? (
this.handleChdir(info.name, '1')} style={{cursor: 'pointer'}}> - + {info.name}
) : ( - + {info.name} ), @@ -63,9 +64,9 @@ class FileManager extends React.Component { key: 'action', render: info => info.kind === '-' ? ( - this.handleDownload(info.name)}/> + this.handleDownload(info.name)}/> - this.handleDelete(info.name)}/> + this.handleDelete(info.name)}/> ) : null }]; @@ -188,7 +189,7 @@ class FileManager extends React.Component {
this.handleChdir('', '0')}> - + {this.state.pwd.map(item => ( this.handleChdir(item, '2')}>