🎉 1.0.0.RELEASE
This commit is contained in:
parent
5ae64b104d
commit
5c84131762
|
|
@ -1,7 +1,5 @@
|
|||
**/*.md
|
||||
**/*.svg
|
||||
**/*.ejs
|
||||
**/*.html
|
||||
package.json
|
||||
.umi
|
||||
.umi-production
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Alipay.inc
|
||||
Copyright (c) 2019 bladex.vip
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
74
azure-pipelines.yml
Normal file
74
azure-pipelines.yml
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Node.js
|
||||
# Build a general Node.js project with npm.
|
||||
# Add steps that analyze code, save build artifacts, deploy, and more:
|
||||
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript
|
||||
name: ant design pro
|
||||
|
||||
trigger:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
- job: lintAndBuild
|
||||
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: false
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run lint
|
||||
displayName: lint
|
||||
- script: npm run build
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: build
|
||||
|
||||
- job: test
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
|
||||
container:
|
||||
image: circleci/node:latest-browsers
|
||||
options: '-u root'
|
||||
|
||||
steps:
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run test:all
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: test
|
||||
|
||||
- job: Windows
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '11.x'
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run lint
|
||||
displayName: lint
|
||||
- script: npm run build
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: build
|
||||
|
||||
- job: MacOS
|
||||
pool:
|
||||
vmImage: 'macOS-10.13'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '11.x'
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run lint
|
||||
displayName: lint
|
||||
- script: npm run
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: build
|
||||
|
|
@ -5,6 +5,8 @@ import webpackPlugin from './plugin.config';
|
|||
import defaultSettings from '../src/defaultSettings';
|
||||
import slash from 'slash2';
|
||||
|
||||
const { pwa, primaryColor } = defaultSettings;
|
||||
|
||||
const plugins = [
|
||||
[
|
||||
'umi-plugin-react',
|
||||
|
|
@ -22,12 +24,14 @@ const plugins = [
|
|||
loadingComponent: './components/PageLoading/index',
|
||||
webpackChunkName: true,
|
||||
},
|
||||
pwa: {
|
||||
workboxPluginMode: 'InjectManifest',
|
||||
workboxOptions: {
|
||||
importWorkboxFrom: 'local',
|
||||
},
|
||||
},
|
||||
pwa: pwa
|
||||
? {
|
||||
workboxPluginMode: 'InjectManifest',
|
||||
workboxOptions: {
|
||||
importWorkboxFrom: 'local',
|
||||
},
|
||||
}
|
||||
: {},
|
||||
...(!process.env.TEST && os.platform() === 'darwin'
|
||||
? {
|
||||
dll: {
|
||||
|
|
@ -68,7 +72,7 @@ export default {
|
|||
// Theme for antd
|
||||
// https://ant.design/docs/react/customize-theme-cn
|
||||
theme: {
|
||||
'primary-color': defaultSettings.primaryColor,
|
||||
'primary-color': primaryColor,
|
||||
},
|
||||
externals: {
|
||||
'@antv/data-set': 'DataSet',
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
"firebase-functions": "^2.1.0",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"moment": "^2.22.2",
|
||||
"path-to-regexp": "^2.2.1"
|
||||
"path-to-regexp": "^3.0.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
// ps https://github.com/GoogleChrome/puppeteer/issues/3120
|
||||
module.exports = {
|
||||
launch: {
|
||||
headless: true,
|
||||
args: [
|
||||
'--disable-gpu',
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-setuid-sandbox',
|
||||
'--no-first-run',
|
||||
'--no-sandbox',
|
||||
'--no-zygote',
|
||||
],
|
||||
},
|
||||
|
|
|
|||
91
package.json
91
package.json
|
|
@ -31,78 +31,76 @@
|
|||
"docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/data-set": "^0.10.0",
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"antd": "^3.11.6",
|
||||
"bizcharts": "^3.4.2",
|
||||
"@antv/data-set": "^0.10.1",
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"antd": "^3.13.0",
|
||||
"bizcharts": "^3.4.3",
|
||||
"bizcharts-plugin-slider": "^2.1.1-beta.1",
|
||||
"chalk": "^2.4.2",
|
||||
"classnames": "^2.2.6",
|
||||
"dva": "^2.4.0",
|
||||
"dva": "^2.4.1",
|
||||
"enquire-js": "^0.2.1",
|
||||
"hash.js": "^1.1.5",
|
||||
"lodash": "^4.17.10",
|
||||
"lodash-decorators": "^6.0.0",
|
||||
"hash.js": "^1.1.7",
|
||||
"lodash": "^4.17.11",
|
||||
"lodash-decorators": "^6.0.1",
|
||||
"memoize-one": "^5.0.0",
|
||||
"moment": "^2.22.2",
|
||||
"moment": "^2.24.0",
|
||||
"numeral": "^2.0.6",
|
||||
"nzh": "^1.0.3",
|
||||
"nzh": "^1.0.4",
|
||||
"omit.js": "^1.0.0",
|
||||
"path-to-regexp": "^2.4.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"path-to-regexp": "^3.0.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"qs": "^6.6.0",
|
||||
"rc-animate": "^2.4.4",
|
||||
"react": "^16.6.3",
|
||||
"rc-animate": "^2.6.0",
|
||||
"react": "^16.7.0",
|
||||
"react-container-query": "^0.11.0",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
"react-document-title": "^2.0.3",
|
||||
"react-dom": "^16.6.3",
|
||||
"react-dom": "^16.7.0",
|
||||
"react-fittext": "^1.0.0",
|
||||
"react-media": "^1.8.0",
|
||||
"react-media": "^1.9.2",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"roadhog-api-doc": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.7.7",
|
||||
"@types/react-dom": "^16.0.10",
|
||||
"@types/react": "^16.8.1",
|
||||
"@types/react-dom": "^16.0.11",
|
||||
"antd-pro-merge-less": "^1.0.0",
|
||||
"antd-theme-webpack-plugin": "^1.1.8",
|
||||
"antd-theme-webpack-plugin": "^1.2.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"check-prettier": "^1.0.1",
|
||||
"cross-env": "^5.1.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"cross-port-killer": "^1.0.1",
|
||||
"enzyme": "3.7.0",
|
||||
"eslint": "^5.4.0",
|
||||
"eslint-config-airbnb": "^17.0.0",
|
||||
"eslint-config-prettier": "^3.0.1",
|
||||
"enzyme": "3.8.0",
|
||||
"eslint": "^5.13.0",
|
||||
"eslint-config-airbnb": "^17.1.0",
|
||||
"eslint-config-prettier": "^4.0.0",
|
||||
"eslint-plugin-babel": "^5.3.0",
|
||||
"eslint-plugin-compat": "^2.6.2",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.1.2",
|
||||
"eslint-plugin-markdown": "^1.0.0-beta.6",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"eslint-plugin-compat": "^2.6.3",
|
||||
"eslint-plugin-import": "^2.16.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.0",
|
||||
"eslint-plugin-markdown": "^1.0.0",
|
||||
"eslint-plugin-react": "^7.12.4",
|
||||
"gh-pages": "^2.0.1",
|
||||
"husky": "^1.2.0",
|
||||
"jest-puppeteer": "^3.5.1",
|
||||
"jest-puppeteer": "^3.9.0",
|
||||
"less": "^3.9.0",
|
||||
"lint-staged": "^8.1.0",
|
||||
"merge-umi-mock-data": "^0.0.3",
|
||||
"lint-staged": "^8.1.1",
|
||||
"merge-umi-mock-data": "^1.0.4",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"prettier": "1.15.2",
|
||||
"pro-download": "^1.0.1",
|
||||
"prettier": "1.16.3",
|
||||
"slash2": "^2.0.0",
|
||||
"stylelint": "^9.8.0",
|
||||
"stylelint": "^9.10.1",
|
||||
"stylelint-config-prettier": "^4.0.0",
|
||||
"stylelint-config-standard": "^18.0.0",
|
||||
"tslint": "^5.10.0",
|
||||
"tslint-config-prettier": "^1.10.0",
|
||||
"stylelint-config-standard": "^18.2.0",
|
||||
"tslint": "^5.12.1",
|
||||
"tslint-config-prettier": "^1.17.0",
|
||||
"tslint-react": "^3.6.0",
|
||||
"umi": "^2.4.2",
|
||||
"umi": "^2.4.4",
|
||||
"umi-plugin-ga": "^1.1.3",
|
||||
"umi-plugin-react": "^1.3.4"
|
||||
"umi-plugin-react": "^1.4.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"puppeteer": "^1.10.0"
|
||||
"puppeteer": "^1.12.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.{js,ts,tsx,json,jsx,less}": [
|
||||
|
|
@ -126,10 +124,5 @@
|
|||
"src/**/*.less",
|
||||
"config/**/*.js*",
|
||||
"scripts/**/*.js"
|
||||
],
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm run lint-staged"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,18 +152,21 @@ ReactDOM.render(
|
|||
>
|
||||
<NoticeIcon.Tab
|
||||
list={noticeData['通知']}
|
||||
name="通知"
|
||||
title="通知"
|
||||
emptyText="你已查看所有通知"
|
||||
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
|
||||
/>
|
||||
<NoticeIcon.Tab
|
||||
list={noticeData['消息']}
|
||||
name="消息"
|
||||
title="消息"
|
||||
emptyText="您已读完所有消息"
|
||||
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
|
||||
/>
|
||||
<NoticeIcon.Tab
|
||||
list={noticeData['待办']}
|
||||
name="待办"
|
||||
title="待办"
|
||||
emptyText="你已完成所有待办"
|
||||
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/HsIsxMZiWKrNUavQUXqx.svg"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
.popover {
|
||||
width: 336px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.noticeButton {
|
||||
|
|
@ -9,9 +10,13 @@
|
|||
display: inline-block;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.icon {
|
||||
padding: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
|
|
|
|||
|
|
@ -100,18 +100,20 @@ export default class BreadcrumbView extends PureComponent {
|
|||
</Breadcrumb.Item>
|
||||
) : null;
|
||||
});
|
||||
// Add home breadcrumbs to your head
|
||||
extraBreadcrumbItems.unshift(
|
||||
<Breadcrumb.Item key="home">
|
||||
{createElement(
|
||||
linkElement,
|
||||
{
|
||||
[linkElement === 'a' ? 'href' : 'to']: '/',
|
||||
},
|
||||
home || 'Home'
|
||||
)}
|
||||
</Breadcrumb.Item>
|
||||
);
|
||||
// Add home breadcrumbs to your head if defined
|
||||
if (home) {
|
||||
extraBreadcrumbItems.unshift(
|
||||
<Breadcrumb.Item key="home">
|
||||
{createElement(
|
||||
linkElement,
|
||||
{
|
||||
[linkElement === 'a' ? 'href' : 'to']: '/',
|
||||
},
|
||||
home
|
||||
)}
|
||||
</Breadcrumb.Item>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Breadcrumb className={styles.breadcrumb} separator={breadcrumbSeparator}>
|
||||
{extraBreadcrumbItems}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
vertical-align: top;
|
||||
line-height: @layout-header-height;
|
||||
> i {
|
||||
font-size: 14px !important;
|
||||
font-size: 16px !important;
|
||||
transform: none !important;
|
||||
svg {
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const { SubMenu } = Menu;
|
|||
// icon: <Icon type="setting" />,
|
||||
const getIcon = icon => {
|
||||
if (typeof icon === 'string' && isUrl(icon)) {
|
||||
return <img src={icon} alt="icon" className={styles.icon} />;
|
||||
return <Icon component={() => <img src={icon} alt="icon" className={styles.icon} />} />;
|
||||
}
|
||||
if (typeof icon === 'string') {
|
||||
return <Icon type={icon} />;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import { getDefaultCollapsedSubMenus } from './SiderMenuUtils';
|
|||
const BaseMenu = React.lazy(() => import('./BaseMenu'));
|
||||
const { Sider } = Layout;
|
||||
|
||||
let firstMount = true;
|
||||
|
||||
export default class SiderMenu extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -17,11 +19,16 @@ export default class SiderMenu extends PureComponent {
|
|||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
firstMount = false;
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
const { pathname } = state;
|
||||
if (props.location.pathname !== pathname) {
|
||||
const { pathname, flatMenuKeysLen } = state;
|
||||
if (props.location.pathname !== pathname || props.flatMenuKeys.length !== flatMenuKeysLen) {
|
||||
return {
|
||||
pathname: props.location.pathname,
|
||||
flatMenuKeysLen: props.flatMenuKeys.length,
|
||||
openKeys: getDefaultCollapsedSubMenus(props),
|
||||
};
|
||||
}
|
||||
|
|
@ -46,12 +53,12 @@ export default class SiderMenu extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { logo, collapsed, onCollapse, fixSiderbar, theme } = this.props;
|
||||
const { logo, collapsed, onCollapse, fixSiderbar, theme, isMobile } = this.props;
|
||||
const { openKeys } = this.state;
|
||||
const defaultProps = collapsed ? {} : { openKeys };
|
||||
|
||||
const siderClassName = classNames(styles.sider, {
|
||||
[styles.fixSiderbar]: fixSiderbar,
|
||||
[styles.fixSiderBar]: fixSiderbar,
|
||||
[styles.light]: theme === 'light',
|
||||
});
|
||||
return (
|
||||
|
|
@ -60,7 +67,11 @@ export default class SiderMenu extends PureComponent {
|
|||
collapsible
|
||||
collapsed={collapsed}
|
||||
breakpoint="lg"
|
||||
onCollapse={onCollapse}
|
||||
onCollapse={collapse => {
|
||||
if (firstMount || !isMobile) {
|
||||
onCollapse(collapse);
|
||||
}
|
||||
}}
|
||||
width={256}
|
||||
theme={theme}
|
||||
className={siderClassName}
|
||||
|
|
|
|||
|
|
@ -35,5 +35,6 @@ export const getDefaultCollapsedSubMenus = props => {
|
|||
} = props;
|
||||
return urlToList(pathname)
|
||||
.map(item => getMenuMatches(flatMenuKeys, item)[0])
|
||||
.filter(item => item);
|
||||
.filter(item => item)
|
||||
.reduce((acc, curr) => [...acc, curr], ['/']);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,19 +25,28 @@
|
|||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.sider {
|
||||
min-height: 100vh;
|
||||
box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
&.fixSiderbar {
|
||||
&.fixSiderBar {
|
||||
box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
:global(.ant-menu-root) {
|
||||
overflow-y: auto;
|
||||
height: ~'calc(100vh - @{nav-header-height})';
|
||||
:global {
|
||||
.ant-menu-root {
|
||||
overflow-y: auto;
|
||||
height: ~'calc(100vh - @{nav-header-height})';
|
||||
}
|
||||
.ant-menu-inline {
|
||||
border-right: 0;
|
||||
.ant-menu-item,
|
||||
.ant-menu-submenu-title {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.light {
|
||||
|
|
@ -57,8 +66,8 @@
|
|||
}
|
||||
|
||||
.icon {
|
||||
vertical-align: baseline;
|
||||
width: 14px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
:global {
|
||||
|
|
|
|||
1
src/components/TagSelect/index.d.ts
vendored
1
src/components/TagSelect/index.d.ts
vendored
|
|
@ -7,6 +7,7 @@ export interface ITagSelectProps {
|
|||
value?: string[] | number[];
|
||||
style?: React.CSSProperties;
|
||||
hideCheckAll?: boolean;
|
||||
actionsText?: { expandText?: string; collapseText?: string; selectAllText?: string };
|
||||
}
|
||||
|
||||
export default class TagSelect extends React.Component<ITagSelectProps, any> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { Tag, Icon } from 'antd';
|
||||
|
||||
|
|
@ -15,8 +16,18 @@ const TagSelectOption = ({ children, checked, onChange, value }) => (
|
|||
TagSelectOption.isTagSelectOption = true;
|
||||
|
||||
class TagSelect extends Component {
|
||||
static propTypes = {
|
||||
actionsText: PropTypes.object,
|
||||
hideCheckAll: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
hideCheckAll: false,
|
||||
actionsText: {
|
||||
expandText: 'Expand',
|
||||
collapseText: 'Collapse',
|
||||
selectAllText: 'All',
|
||||
},
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -88,19 +99,21 @@ class TagSelect extends Component {
|
|||
|
||||
render() {
|
||||
const { value, expand } = this.state;
|
||||
const { children, hideCheckAll, className, style, expandable } = this.props;
|
||||
|
||||
const { children, hideCheckAll, className, style, expandable, actionsText } = this.props;
|
||||
const checkedAll = this.getAllTags().length === value.length;
|
||||
const { expandText = 'Expand', collapseText = 'Collapse', selectAllText = 'All' } =
|
||||
actionsText === null ? {} : actionsText;
|
||||
|
||||
const cls = classNames(styles.tagSelect, className, {
|
||||
[styles.hasExpandTag]: expandable,
|
||||
[styles.expanded]: expand,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={cls} style={style}>
|
||||
{hideCheckAll ? null : (
|
||||
<CheckableTag checked={checkedAll} key="tag-select-__all__" onChange={this.onSelectAll}>
|
||||
全部
|
||||
{selectAllText}
|
||||
</CheckableTag>
|
||||
)}
|
||||
{value &&
|
||||
|
|
@ -117,7 +130,7 @@ class TagSelect extends Component {
|
|||
})}
|
||||
{expandable && (
|
||||
<a className={styles.trigger} onClick={this.handleExpand}>
|
||||
{expand ? '收起' : '展开'} <Icon type={expand ? 'up' : 'down'} />
|
||||
{expand ? collapseText : expandText} <Icon type={expand ? 'up' : 'down'} />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ module.exports = {
|
|||
autoHideHeader: false, // auto hide header
|
||||
fixSiderbar: true, // sticky siderbar
|
||||
collapse: true,
|
||||
title: 'Sword企业级开发平台',
|
||||
menu: {
|
||||
disableLocal: false,
|
||||
},
|
||||
title: 'Sword企业级开发平台',
|
||||
pwa: true,
|
||||
};
|
||||
|
|
|
|||
103
src/global.js
103
src/global.js
|
|
@ -1,54 +1,59 @@
|
|||
import React from 'react';
|
||||
import { notification, Button, message } from 'antd';
|
||||
import { formatMessage } from 'umi/locale';
|
||||
import defaultSettings from './defaultSettings';
|
||||
|
||||
// Notify user if offline now
|
||||
window.addEventListener('sw.offline', () => {
|
||||
message.warning(formatMessage({ id: 'app.pwa.offline' }));
|
||||
});
|
||||
|
||||
// Pop up a prompt on the page asking the user if they want to use the latest version
|
||||
window.addEventListener('sw.updated', e => {
|
||||
const reloadSW = async () => {
|
||||
// Check if there is sw whose state is waiting in ServiceWorkerRegistration
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
|
||||
const worker = e.detail && e.detail.waiting;
|
||||
if (!worker) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
// Send skip-waiting event to waiting SW with MessageChannel
|
||||
await new Promise((resolve, reject) => {
|
||||
const channel = new MessageChannel();
|
||||
channel.port1.onmessage = event => {
|
||||
if (event.data.error) {
|
||||
reject(event.data.error);
|
||||
} else {
|
||||
resolve(event.data);
|
||||
}
|
||||
};
|
||||
worker.postMessage({ type: 'skip-waiting' }, [channel.port2]);
|
||||
});
|
||||
// Refresh current page to use the updated HTML and other assets after SW has skiped waiting
|
||||
window.location.reload(true);
|
||||
return true;
|
||||
};
|
||||
const key = `open${Date.now()}`;
|
||||
const btn = (
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
notification.close(key);
|
||||
reloadSW();
|
||||
}}
|
||||
>
|
||||
{formatMessage({ id: 'app.pwa.serviceworker.updated.ok' })}
|
||||
</Button>
|
||||
);
|
||||
notification.open({
|
||||
message: formatMessage({ id: 'app.pwa.serviceworker.updated' }),
|
||||
description: formatMessage({ id: 'app.pwa.serviceworker.updated.hint' }),
|
||||
btn,
|
||||
key,
|
||||
onClose: async () => {},
|
||||
const { pwa } = defaultSettings;
|
||||
// if pwa is true
|
||||
if (pwa) {
|
||||
// Notify user if offline now
|
||||
window.addEventListener('sw.offline', () => {
|
||||
message.warning(formatMessage({ id: 'app.pwa.offline' }));
|
||||
});
|
||||
});
|
||||
|
||||
// Pop up a prompt on the page asking the user if they want to use the latest version
|
||||
window.addEventListener('sw.updated', e => {
|
||||
const reloadSW = async () => {
|
||||
// Check if there is sw whose state is waiting in ServiceWorkerRegistration
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
|
||||
const worker = e.detail && e.detail.waiting;
|
||||
if (!worker) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
// Send skip-waiting event to waiting SW with MessageChannel
|
||||
await new Promise((resolve, reject) => {
|
||||
const channel = new MessageChannel();
|
||||
channel.port1.onmessage = event => {
|
||||
if (event.data.error) {
|
||||
reject(event.data.error);
|
||||
} else {
|
||||
resolve(event.data);
|
||||
}
|
||||
};
|
||||
worker.postMessage({ type: 'skip-waiting' }, [channel.port2]);
|
||||
});
|
||||
// Refresh current page to use the updated HTML and other assets after SW has skiped waiting
|
||||
window.location.reload(true);
|
||||
return true;
|
||||
};
|
||||
const key = `open${Date.now()}`;
|
||||
const btn = (
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
notification.close(key);
|
||||
reloadSW();
|
||||
}}
|
||||
>
|
||||
{formatMessage({ id: 'app.pwa.serviceworker.updated.ok' })}
|
||||
</Button>
|
||||
);
|
||||
notification.open({
|
||||
message: formatMessage({ id: 'app.pwa.serviceworker.updated' }),
|
||||
description: formatMessage({ id: 'app.pwa.serviceworker.updated.hint' }),
|
||||
btn,
|
||||
key,
|
||||
onClose: async () => {},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@import '~antd/lib/style/themes/default.less';
|
||||
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
|
|
@ -31,3 +33,20 @@ ul,
|
|||
ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs) {
|
||||
.ant-table {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
&-thead > tr,
|
||||
&-tbody > tr {
|
||||
> th,
|
||||
> td {
|
||||
white-space: pre;
|
||||
> span {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ const query = {
|
|||
},
|
||||
};
|
||||
|
||||
class BasicLayout extends React.PureComponent {
|
||||
class BasicLayout extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.getPageTitle = memoizeOne(this.getPageTitle);
|
||||
|
|
@ -76,15 +76,6 @@ class BasicLayout extends React.PureComponent {
|
|||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(preProps) {
|
||||
// After changing to phone mode,
|
||||
// if collapsed is true, you need to click twice to display
|
||||
const { collapsed, isMobile } = this.props;
|
||||
if (isMobile && !preProps.isMobile && !collapsed) {
|
||||
this.handleMenuCollapse(false);
|
||||
}
|
||||
}
|
||||
|
||||
getContext() {
|
||||
const { location, breadcrumbNameMap } = this.props;
|
||||
return {
|
||||
|
|
@ -98,20 +89,28 @@ class BasicLayout extends React.PureComponent {
|
|||
return breadcrumbNameMap[pathKey];
|
||||
};
|
||||
|
||||
getRouterAuthority = (pathname, routeData) => {
|
||||
let routeAuthority = ['noAuthority'];
|
||||
const getAuthority = (key, routes) => {
|
||||
routes.forEach(route => {
|
||||
if (route.path && pathToRegexp(route.path).test(key)) {
|
||||
routeAuthority = route.authority;
|
||||
} else if (route.routes) {
|
||||
routeAuthority = getAuthority(key, route.routes);
|
||||
getRouteAuthority = (pathname, routeData) => {
|
||||
const routes = routeData.slice(); // clone
|
||||
let authorities;
|
||||
|
||||
while (routes.length > 0) {
|
||||
const route = routes.shift();
|
||||
// check partial route
|
||||
if (pathToRegexp(`${route.path}(.*)`).test(pathname)) {
|
||||
if (route.authority) {
|
||||
authorities = route.authority;
|
||||
}
|
||||
return route;
|
||||
});
|
||||
return routeAuthority;
|
||||
};
|
||||
return getAuthority(pathname, routeData);
|
||||
// is exact route?
|
||||
if (pathToRegexp(route.path).test(pathname)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (route.routes) {
|
||||
route.routes.forEach(r => routes.push(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
return authorities;
|
||||
};
|
||||
|
||||
getPageTitle = (pathname, breadcrumbNameMap) => {
|
||||
|
|
@ -172,7 +171,7 @@ class BasicLayout extends React.PureComponent {
|
|||
} = this.props;
|
||||
|
||||
const isTop = PropsLayout === 'topmenu';
|
||||
const routerConfig = this.getRouterAuthority(pathname, routes);
|
||||
const routerConfig = this.getRouteAuthority(pathname, routes);
|
||||
const contentStyle = !fixedHeader ? { paddingTop: 0 } : {};
|
||||
const layout = (
|
||||
<Layout>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
import React from 'react';
|
||||
import { formatMessage } from 'umi/locale';
|
||||
import { Layout, message, Modal } from 'antd';
|
||||
import Animate from 'rc-animate';
|
||||
|
|
@ -10,7 +10,7 @@ import styles from './Header.less';
|
|||
|
||||
const { Header } = Layout;
|
||||
|
||||
class HeaderView extends PureComponent {
|
||||
class HeaderView extends React.Component {
|
||||
state = {
|
||||
visible: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,44 +40,26 @@ const copyright = (
|
|||
</Fragment>
|
||||
);
|
||||
|
||||
class UserLayout extends React.PureComponent {
|
||||
// @TODO title
|
||||
// getPageTitle() {
|
||||
// const { routerData, location } = this.props;
|
||||
// const { pathname } = location;
|
||||
// let title = 'Ant Design Pro';
|
||||
// if (routerData[pathname] && routerData[pathname].name) {
|
||||
// title = `${routerData[pathname].name} - Ant Design Pro`;
|
||||
// }
|
||||
// return title;
|
||||
// }
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
return (
|
||||
// @TODO <DocumentTitle title={this.getPageTitle()}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.lang}>
|
||||
<SelectLang />
|
||||
const UserLayout = ({ children }) => (
|
||||
// @TODO <DocumentTitle title={this.getPageTitle()}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.lang}>
|
||||
<SelectLang />
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.top}>
|
||||
<div className={styles.header}>
|
||||
<Link to="/">
|
||||
<img alt="logo" className={styles.logo} src={logo} />
|
||||
<span className={styles.title}>Ant Design</span>
|
||||
</Link>
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.top}>
|
||||
<div className={styles.header}>
|
||||
<Link to="/">
|
||||
<img alt="logo" className={styles.logo} src={logo} />
|
||||
<span className={styles.title}>Sword 企业级开发平台</span>
|
||||
</Link>
|
||||
</div>
|
||||
<div className={styles.desc}>
|
||||
Sword是SpringBlade前端UI项目,基于react 、ant design、umi、dva等流行技术栈。
|
||||
</div>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
<GlobalFooter links={links} copyright={copyright} />
|
||||
<div className={styles.desc}>Ant Design 是西湖区最具影响力的 Web 设计规范</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
{children}
|
||||
</div>
|
||||
<GlobalFooter links={links} copyright={copyright} />
|
||||
</div>
|
||||
);
|
||||
|
||||
export default UserLayout;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import result from './en-US/result';
|
|||
import settingDrawer from './en-US/settingDrawer';
|
||||
import settings from './en-US/settings';
|
||||
import pwa from './en-US/pwa';
|
||||
import component from './en-US/component';
|
||||
|
||||
export default {
|
||||
'navBar.lang': 'Languages',
|
||||
|
|
@ -34,4 +35,5 @@ export default {
|
|||
...settingDrawer,
|
||||
...settings,
|
||||
...pwa,
|
||||
...component,
|
||||
};
|
||||
|
|
|
|||
5
src/locales/en-US/component.js
Normal file
5
src/locales/en-US/component.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
'component.tagSelect.expand': 'Expand',
|
||||
'component.tagSelect.collapse': 'Collapse',
|
||||
'component.tagSelect.all': 'All',
|
||||
};
|
||||
|
|
@ -25,14 +25,14 @@ export default {
|
|||
'app.settings.security.medium': 'Medium',
|
||||
'app.settings.security.weak': 'Weak',
|
||||
'app.settings.security.password': 'Account Password',
|
||||
'app.settings.security.password-description': 'Current password strength:',
|
||||
'app.settings.security.password-description': 'Current password strength',
|
||||
'app.settings.security.phone': 'Security Phone',
|
||||
'app.settings.security.phone-description': 'Bound phone:',
|
||||
'app.settings.security.phone-description': 'Bound phone',
|
||||
'app.settings.security.question': 'Security Question',
|
||||
'app.settings.security.question-description':
|
||||
'The security question is not set, and the security policy can effectively protect the account security',
|
||||
'app.settings.security.email': 'Backup Email',
|
||||
'app.settings.security.email-description': 'Bound Email:',
|
||||
'app.settings.security.email-description': 'Bound Email',
|
||||
'app.settings.security.mfa': 'MFA Device',
|
||||
'app.settings.security.mfa-description':
|
||||
'Unbound MFA device, after binding, can be confirmed twice',
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import result from './zh-CN/result';
|
|||
import settingDrawer from './zh-CN/settingDrawer';
|
||||
import settings from './zh-CN/settings';
|
||||
import pwa from './zh-CN/pwa';
|
||||
import component from './zh-CN/component';
|
||||
|
||||
export default {
|
||||
'navBar.lang': '语言',
|
||||
|
|
@ -34,4 +35,5 @@ export default {
|
|||
...settingDrawer,
|
||||
...settings,
|
||||
...pwa,
|
||||
...component,
|
||||
};
|
||||
|
|
|
|||
5
src/locales/zh-CN/component.js
Normal file
5
src/locales/zh-CN/component.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
'component.tagSelect.expand': '展开',
|
||||
'component.tagSelect.collapse': '收起',
|
||||
'component.tagSelect.all': '全部',
|
||||
};
|
||||
|
|
@ -25,13 +25,13 @@ export default {
|
|||
'app.settings.security.medium': '中',
|
||||
'app.settings.security.weak': '弱',
|
||||
'app.settings.security.password': '账户密码',
|
||||
'app.settings.security.password-description': '当前密码强度:',
|
||||
'app.settings.security.password-description': '当前密码强度',
|
||||
'app.settings.security.phone': '密保手机',
|
||||
'app.settings.security.phone-description': '已绑定手机:',
|
||||
'app.settings.security.phone-description': '已绑定手机',
|
||||
'app.settings.security.question': '密保问题',
|
||||
'app.settings.security.question-description': '未设置密保问题,密保问题可有效保护账户安全',
|
||||
'app.settings.security.email': '备用邮箱',
|
||||
'app.settings.security.email-description': '已绑定邮箱:',
|
||||
'app.settings.security.email-description': '已绑定邮箱',
|
||||
'app.settings.security.mfa': 'MFA 设备',
|
||||
'app.settings.security.mfa-description': '未绑定 MFA 设备,绑定后,可以进行二次确认',
|
||||
'app.settings.security.modify': '修改',
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import result from './zh-TW/result';
|
|||
import settingDrawer from './zh-TW/settingDrawer';
|
||||
import settings from './zh-TW/settings';
|
||||
import pwa from './zh-TW/pwa';
|
||||
import component from './zh-TW/component';
|
||||
|
||||
export default {
|
||||
'navBar.lang': '語言',
|
||||
|
|
@ -34,4 +35,5 @@ export default {
|
|||
...settingDrawer,
|
||||
...settings,
|
||||
...pwa,
|
||||
...component,
|
||||
};
|
||||
|
|
|
|||
5
src/locales/zh-TW/component.js
Normal file
5
src/locales/zh-TW/component.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
'component.tagSelect.expand': '展開',
|
||||
'component.tagSelect.collapse': '收起',
|
||||
'component.tagSelect.all': '全部',
|
||||
};
|
||||
|
|
@ -3,7 +3,7 @@ export default {
|
|||
'component.globalHeader.search.example1': '搜索提示壹',
|
||||
'component.globalHeader.search.example2': '搜索提示二',
|
||||
'component.globalHeader.search.example3': '搜索提示三',
|
||||
'component.globalHeader.help': '使用文檔',
|
||||
'component.globalHeader.help': '使用手冊',
|
||||
'component.globalHeader.notification': '通知',
|
||||
'component.globalHeader.notification.empty': '妳已查看所有通知',
|
||||
'component.globalHeader.message': '消息',
|
||||
|
|
@ -12,7 +12,7 @@ export default {
|
|||
'component.globalHeader.event.empty': '妳已完成所有待辦',
|
||||
'component.noticeIcon.clear': '清空',
|
||||
'component.noticeIcon.cleared': '清空了',
|
||||
'component.noticeIcon.empty': '暫無數據',
|
||||
'component.noticeIcon.empty': '暫無資料',
|
||||
'component.noticeIcon.loaded': '加載完畢',
|
||||
'component.noticeIcon.loading-more': '加載更多',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ export default {
|
|||
'app.settings.security.medium': '中',
|
||||
'app.settings.security.weak': '弱',
|
||||
'app.settings.security.password': '賬戶密碼',
|
||||
'app.settings.security.password-description': '當前密碼強度:',
|
||||
'app.settings.security.password-description': '當前密碼強度',
|
||||
'app.settings.security.phone': '密保手機',
|
||||
'app.settings.security.phone-description': '已綁定手機:',
|
||||
'app.settings.security.phone-description': '已綁定手機',
|
||||
'app.settings.security.question': '密保問題',
|
||||
'app.settings.security.question-description': '未設置密保問題,密保問題可有效保護賬戶安全',
|
||||
'app.settings.security.email': '備用郵箱',
|
||||
'app.settings.security.email-description': '已綁定郵箱:',
|
||||
'app.settings.security.email-description': '已綁定郵箱',
|
||||
'app.settings.security.mfa': 'MFA 設備',
|
||||
'app.settings.security.mfa-description': '未綁定 MFA 設備,綁定後,可以進行二次確認',
|
||||
'app.settings.security.modify': '修改',
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ class Workplace extends PureComponent {
|
|||
<span>
|
||||
<a className={styles.username}>SpringBlade 企业版系列 </a>
|
||||
<span className={styles.event}>
|
||||
已通过长时间生产环境的考验,现将其拆分出基础模块进行开源,当前版本为:2.0.0-RC3。
|
||||
已通过长时间生产环境的考验,现将其拆分出基础模块进行开源,当前版本为:2.0.0。
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;">
|
||||
<title>Sword企业级开发平台</title>
|
||||
<link rel="icon" href="/favicon.png" type="image/x-icon">
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
||||
/>
|
||||
<title>Ant Design Pro</title>
|
||||
<link rel="icon" href="/favicon.png" type="image/x-icon" />
|
||||
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.data-set-0.9.6/dist/data-set.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>Sorry, we need js to run correctly!</noscript>
|
||||
<div id="root"></div>
|
||||
<noscript>Sorry, we need js to run correctly!</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user