✨ Upgrading components to typescript

This commit is contained in:
zuiidea
2021-04-05 22:54:36 +08:00
parent a0000d7371
commit 1dbeb05005
42 changed files with 377 additions and 475 deletions
+4 -7
View File
@@ -6,6 +6,9 @@ import routes from './routes'
import proxy from './proxy'
const isDevelopment = process.env.NODE_ENV === 'development'
const theme = lessToJs(
fs.readFileSync(path.join(__dirname, '../src/themes/default.less'), 'utf8')
)
const config: IConfig = {
// IMPORTANT! change next line to yours or delete. And hide in dev
@@ -14,20 +17,14 @@ const config: IConfig = {
ignoreMomentLocale: true,
targets: { ie: 9 },
dynamicImport: {},
theme,
proxy,
routes,
// a lower cost way to genereate sourcemap, default is cheap-module-source-map, could save 60% time in dev hotload
devtool: 'eval',
// umi3 comple node_modules by default, could be disable
nodeModulesTransform: {
type: 'none',
exclude: [],
},
// Theme for antd
// https://ant.design/docs/react/customize-theme
theme: lessToJs(
fs.readFileSync(path.join(__dirname, '../src/themes/default.less'), 'utf8')
),
extraBabelPresets: ['@lingui/babel-preset-react'],
extraBabelPlugins: [
'macros',
+8 -6
View File
@@ -1,10 +1,12 @@
import type { IRoute } from 'umi'
const routes: IRoute[] = [{
exact: false, path: '/', component: '@/layouts/index',
routes: [
{ exact: true, path: '/login', component: '@/pages/login' },
],
}]
const routes: IRoute[] = [
{
exact: false,
path: '/',
component: '@/layouts',
routes: [{ exact: true, path: '/login', component: '@/pages/login' }],
},
]
export default routes
+13 -14
View File
@@ -39,6 +39,8 @@
"@lingui/cli": "^3.8.2",
"@lingui/loader": "^3.8.2",
"@lingui/macro": "^3.8.2",
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"@umijs/preset-react": "^1.8.0",
"babel-eslint": "^10.0.0",
"babel-plugin-dev-expression": "^0.2.1",
@@ -71,15 +73,13 @@
"node": ">= 10.0.0"
},
"lint-staged": {
"src/**/*.js": [
"eslint --ext .js --fix",
"npm run prettier",
"git add"
"*.{ts,tsx,js,jsx}": [
"npm run eslint",
"npm run prettier"
],
"**/*.less": [
"stylelint --syntax less",
"npm run prettier",
"git add"
"*.less": [
"npm run stylelint",
"npm run prettier"
]
},
"lingui": {
@@ -110,14 +110,13 @@
]
},
"scripts": {
"analyze": "cross-env ANALYZE=1 umi build",
"start": "umi dev",
"build": "umi build",
"check:model": "umi dva list model",
"lint:js": "eslint --ext .js src",
"lint:style": "stylelint \"src/**/*.less\" --syntax less",
"start": "cross-env umi dev",
"test": "cross-env BABELRC=none umi test",
"prettier": "prettier --write 'src/**/*.{js,less}'",
"analyze": "cross-env ANALYZE=1 umi build",
"eslint": "eslint --fix 'src/**/*.{ts,tsx,js.jsx}'",
"stylelint": "stylelint src/**/*.less --syntax less",
"prettier": "prettier --write 'src/**/*.{ts,tsx,js.jsx,less}'",
"precommit": "lint-staged",
"add-locale": "lingui add-locale",
"extract": "lingui extract",
-35
View File
@@ -1,35 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { BarsOutlined, DownOutlined } from '@ant-design/icons'
import { Dropdown, Button, Menu } from 'antd'
const DropOption = ({
onMenuClick,
menuOptions = [],
buttonStyle,
dropdownProps,
}) => {
const menu = menuOptions.map(item => (
<Menu.Item key={item.key}>{item.name}</Menu.Item>
))
return (
<Dropdown
overlay={<Menu onClick={onMenuClick}>{menu}</Menu>}
{...dropdownProps}
>
<Button style={{ border: 'none', ...buttonStyle }}>
<BarsOutlined style={{ marginRight: 2 }} />
<DownOutlined />
</Button>
</Dropdown>
)
}
DropOption.propTypes = {
onMenuClick: PropTypes.func,
menuOptions: PropTypes.array.isRequired,
buttonStyle: PropTypes.object,
dropdownProps: PropTypes.object,
}
export default DropOption
-6
View File
@@ -1,6 +0,0 @@
{
"name": "DropOption",
"version": "0.0.0",
"private": true,
"main": "./DropOption.js"
}
+12 -12
View File
@@ -1,21 +1,21 @@
import React from 'react';
import { TooltipProps } from 'antd/lib/tooltip';
import React from 'react'
import { TooltipProps } from 'antd/lib/tooltip'
export interface EllipsisTooltipProps extends TooltipProps {
title?: undefined;
overlayStyle?: undefined;
title?: undefined
overlayStyle?: undefined
}
export interface EllipsisProps {
tooltip?: boolean | EllipsisTooltipProps;
length?: number;
lines?: number;
style?: React.CSSProperties;
className?: string;
fullWidthRecognition?: boolean;
tooltip?: boolean | EllipsisTooltipProps
length?: number
lines?: number
style?: React.CSSProperties
className?: string
fullWidthRecognition?: boolean
}
export function getStrFullLength(str: string): number;
export function cutStrByFullLength(str: string, maxLength: number): string;
export function getStrFullLength(str: string): number
export function cutStrByFullLength(str: string, maxLength: number): string
export default class Ellipsis extends React.Component<EllipsisProps, any> {}
+112 -98
View File
@@ -1,68 +1,79 @@
import React, { Component } from 'react';
import { Tooltip } from 'antd';
import classNames from 'classnames';
import styles from './index.less';
import React, { Component } from 'react'
import { Tooltip } from 'antd'
import classNames from 'classnames'
import styles from './index.less'
/* eslint react/no-did-mount-set-state: 0 */
/* eslint no-param-reassign: 0 */
const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined;
const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined
const TooltipOverlayStyle = {
overflowWrap: 'break-word',
wordWrap: 'break-word',
};
}
export const getStrFullLength = (str = '') =>
str.split('').reduce((pre, cur) => {
const charCode = cur.charCodeAt(0);
const charCode = cur.charCodeAt(0)
if (charCode >= 0 && charCode <= 128) {
return pre + 1;
return pre + 1
}
return pre + 2;
}, 0);
return pre + 2
}, 0)
export const cutStrByFullLength = (str = '', maxLength) => {
let showLength = 0;
let showLength = 0
return str.split('').reduce((pre, cur) => {
const charCode = cur.charCodeAt(0);
const charCode = cur.charCodeAt(0)
if (charCode >= 0 && charCode <= 128) {
showLength += 1;
showLength += 1
} else {
showLength += 2;
showLength += 2
}
if (showLength <= maxLength) {
return pre + cur;
return pre + cur
}
return pre;
}, '');
};
return pre
}, '')
}
const getTooltip = ({ tooltip, overlayStyle, title, children }) => {
if (tooltip) {
const props = tooltip === true ? { overlayStyle, title } : { ...tooltip, overlayStyle, title };
return <Tooltip {...props}>{children}</Tooltip>;
const props =
tooltip === true
? { overlayStyle, title }
: { ...tooltip, overlayStyle, title }
return <Tooltip {...props}>{children}</Tooltip>
}
return children;
};
return children
}
const EllipsisText = ({ text, length, tooltip, fullWidthRecognition, ...other }) => {
const EllipsisText = ({
text,
length,
tooltip,
fullWidthRecognition,
...other
}) => {
if (typeof text !== 'string') {
throw new Error('Ellipsis children must be string.');
throw new Error('Ellipsis children must be string.')
}
const textLength = fullWidthRecognition ? getStrFullLength(text) : text.length;
const textLength = fullWidthRecognition ? getStrFullLength(text) : text.length
if (textLength <= length || length < 0) {
return <span {...other}>{text}</span>;
return <span {...other}>{text}</span>
}
const tail = '...';
let displayText;
const tail = '...'
let displayText
if (length - tail.length <= 0) {
displayText = '';
displayText = ''
} else {
displayText = fullWidthRecognition ? cutStrByFullLength(text, length) : text.slice(0, length);
displayText = fullWidthRecognition
? cutStrByFullLength(text, length)
: text.slice(0, length)
}
const spanAttrs = tooltip ? {} : { ...other };
const spanAttrs = tooltip ? {} : { ...other }
return getTooltip({
tooltip,
overlayStyle: TooltipOverlayStyle,
@@ -73,116 +84,117 @@ const EllipsisText = ({ text, length, tooltip, fullWidthRecognition, ...other })
{tail}
</span>
),
});
};
})
}
export default class Ellipsis extends Component {
state = {
text: '',
targetCount: 0,
};
}
componentDidMount() {
if (this.node) {
this.computeLine();
this.computeLine()
}
}
componentDidUpdate(perProps) {
const { lines } = this.props;
const { lines } = this.props
if (lines !== perProps.lines) {
this.computeLine();
this.computeLine()
}
}
computeLine = () => {
const { lines } = this.props;
const { lines } = this.props
if (lines && !isSupportLineClamp) {
const text = this.shadowChildren.innerText || this.shadowChildren.textContent;
const lineHeight = parseInt(getComputedStyle(this.root).lineHeight, 10);
const targetHeight = lines * lineHeight;
this.content.style.height = `${targetHeight}px`;
const totalHeight = this.shadowChildren.offsetHeight;
const shadowNode = this.shadow.firstChild;
const text =
this.shadowChildren.innerText || this.shadowChildren.textContent
const lineHeight = parseInt(getComputedStyle(this.root).lineHeight, 10)
const targetHeight = lines * lineHeight
this.content.style.height = `${targetHeight}px`
const totalHeight = this.shadowChildren.offsetHeight
const shadowNode = this.shadow.firstChild
if (totalHeight <= targetHeight) {
this.setState({
text,
targetCount: text.length,
});
return;
})
return
}
// bisection
const len = text.length;
const mid = Math.ceil(len / 2);
const len = text.length
const mid = Math.ceil(len / 2)
const count = this.bisection(targetHeight, mid, 0, len, text, shadowNode);
const count = this.bisection(targetHeight, mid, 0, len, text, shadowNode)
this.setState({
text,
targetCount: count,
});
})
}
};
}
bisection = (th, m, b, e, text, shadowNode) => {
const suffix = '...';
let mid = m;
let end = e;
let begin = b;
shadowNode.innerHTML = text.substring(0, mid) + suffix;
let sh = shadowNode.offsetHeight;
const suffix = '...'
let mid = m
let end = e
let begin = b
shadowNode.innerHTML = text.substring(0, mid) + suffix
let sh = shadowNode.offsetHeight
if (sh <= th) {
shadowNode.innerHTML = text.substring(0, mid + 1) + suffix;
sh = shadowNode.offsetHeight;
shadowNode.innerHTML = text.substring(0, mid + 1) + suffix
sh = shadowNode.offsetHeight
if (sh > th || mid === begin) {
return mid;
return mid
}
begin = mid;
begin = mid
if (end - begin === 1) {
mid = 1 + begin;
mid = 1 + begin
} else {
mid = Math.floor((end - begin) / 2) + begin;
mid = Math.floor((end - begin) / 2) + begin
}
return this.bisection(th, mid, begin, end, text, shadowNode);
return this.bisection(th, mid, begin, end, text, shadowNode)
}
if (mid - 1 < 0) {
return mid;
return mid
}
shadowNode.innerHTML = text.substring(0, mid - 1) + suffix;
sh = shadowNode.offsetHeight;
shadowNode.innerHTML = text.substring(0, mid - 1) + suffix
sh = shadowNode.offsetHeight
if (sh <= th) {
return mid - 1;
return mid - 1
}
end = mid;
mid = Math.floor((end - begin) / 2) + begin;
return this.bisection(th, mid, begin, end, text, shadowNode);
};
end = mid
mid = Math.floor((end - begin) / 2) + begin
return this.bisection(th, mid, begin, end, text, shadowNode)
}
handleRoot = n => {
this.root = n;
};
handleRoot = (n) => {
this.root = n
}
handleContent = n => {
this.content = n;
};
handleContent = (n) => {
this.content = n
}
handleNode = n => {
this.node = n;
};
handleNode = (n) => {
this.node = n
}
handleShadow = n => {
this.shadow = n;
};
handleShadow = (n) => {
this.shadow = n
}
handleShadowChildren = n => {
this.shadowChildren = n;
};
handleShadowChildren = (n) => {
this.shadowChildren = n
}
render() {
const { text, targetCount } = this.state;
const { text, targetCount } = this.state
const {
children,
lines,
@@ -191,19 +203,19 @@ export default class Ellipsis extends Component {
tooltip,
fullWidthRecognition,
...restProps
} = this.props;
} = this.props
const cls = classNames(styles.ellipsis, className, {
[styles.lines]: lines && !isSupportLineClamp,
[styles.lineClamp]: lines && isSupportLineClamp,
});
})
if (!lines && !length) {
return (
<span className={cls} {...restProps}>
{children}
</span>
);
)
}
// length
@@ -217,28 +229,30 @@ export default class Ellipsis extends Component {
fullWidthRecognition={fullWidthRecognition}
{...restProps}
/>
);
)
}
const id = `antd-pro-ellipsis-${`${new Date().getTime()}${Math.floor(Math.random() * 100)}`}`;
const id = `antd-pro-ellipsis-${`${new Date().getTime()}${Math.floor(
Math.random() * 100
)}`}`
// support document.body.style.webkitLineClamp
if (isSupportLineClamp) {
const style = `#${id}{-webkit-line-clamp:${lines};-webkit-box-orient: vertical;}`;
const style = `#${id}{-webkit-line-clamp:${lines};-webkit-box-orient: vertical;}`
const node = (
<div id={id} className={cls} {...restProps}>
<style>{style}</style>
{children}
</div>
);
)
return getTooltip({
tooltip,
overlayStyle: TooltipOverlayStyle,
title: children,
children: node,
});
})
}
const childNode = (
@@ -246,7 +260,7 @@ export default class Ellipsis extends Component {
{targetCount > 0 && text.substring(0, targetCount)}
{targetCount > 0 && targetCount < text.length && '...'}
</span>
);
)
return (
<div {...restProps} ref={this.handleRoot} className={cls}>
@@ -265,6 +279,6 @@ export default class Ellipsis extends Component {
</div>
</div>
</div>
);
)
}
}
+8 -8
View File
@@ -1,13 +1,13 @@
import { getStrFullLength, cutStrByFullLength } from './index';
import { getStrFullLength, cutStrByFullLength } from './index'
describe('test calculateShowLength', () => {
it('get full length', () => {
expect(getStrFullLength('一二,a,')).toEqual(8);
});
expect(getStrFullLength('一二,a,')).toEqual(8)
})
it('cut str by full length', () => {
expect(cutStrByFullLength('一二,a,', 7)).toEqual('一二,a');
});
expect(cutStrByFullLength('一二,a,', 7)).toEqual('一二,a')
})
it('cut str when length small', () => {
expect(cutStrByFullLength('一22三', 5)).toEqual('一22');
});
});
expect(cutStrByFullLength('一22三', 5)).toEqual('一22')
})
})
@@ -1,8 +1,10 @@
import React from 'react'
import PropTypes from 'prop-types'
import styles from './FilterItem.less'
import styles from './index.less'
const FilterItem = ({ label = '', children }) => {
interface FilterItemProps {
label: string
}
const FilterItem: React.FC<FilterItemProps> = ({ label = '', children }) => {
const labelArray = label.split('')
return (
<div className={styles.filterItem}>
@@ -20,9 +22,4 @@ const FilterItem = ({ label = '', children }) => {
)
}
FilterItem.propTypes = {
label: PropTypes.string,
children: PropTypes.element.isRequired,
}
export default FilterItem
-6
View File
@@ -1,6 +0,0 @@
{
"name": "FilterItem",
"version": "0.0.0",
"private": true,
"main": "./FilterItem.js"
}
+1
View File
@@ -26,6 +26,7 @@ const GlobalFooter: React.FC<GlobalFooterProps> = ({
title={link.key}
target={link.blankTarget ? '_blank' : '_self'}
href={link.href}
rel="noreferrer"
>
{link.title}
</a>
+6 -8
View File
@@ -8,7 +8,7 @@ import {
MenuFoldOutlined,
MenuUnfoldOutlined,
} from '@ant-design/icons'
import { Trans } from "@lingui/macro"
import { Trans } from '@lingui/macro'
import { getLocale, setLocale } from 'utils'
import moment from 'moment'
import classnames from 'classnames'
@@ -18,7 +18,7 @@ import styles from './Header.less'
const { SubMenu } = Menu
class Header extends PureComponent {
handleClickMenu = e => {
handleClickMenu = (e) => {
e.key === 'SignOut' && this.props.onSignOut()
}
render() {
@@ -55,21 +55,19 @@ class Header extends PureComponent {
if (config.i18n) {
const { languages } = config.i18n
const language = getLocale()
const currentLanguage = languages.find(
item => item.key === language
)
const currentLanguage = languages.find((item) => item.key === language)
rightContent.unshift(
<Menu
key="language"
selectedKeys={[currentLanguage.key]}
onClick={data => {
onClick={(data) => {
setLocale(data.key)
}}
mode="horizontal"
>
<SubMenu title={<Avatar size="small" src={currentLanguage.flag} />}>
{languages.map(item => (
{languages.map((item) => (
<Menu.Item key={item.key}>
<Avatar
size="small"
@@ -99,7 +97,7 @@ class Header extends PureComponent {
locale={{
emptyText: <Trans>You have viewed all notifications.</Trans>,
}}
renderItem={item => (
renderItem={(item) => (
<List.Item className={styles.notificationItem}>
<List.Item.Meta
title={
+2 -2
View File
@@ -1,8 +1,8 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { Switch, Layout } from 'antd'
import { t } from "@lingui/macro"
import { Trans } from "@lingui/macro"
import { t } from '@lingui/macro'
import { Trans } from '@lingui/macro'
import { BulbOutlined } from '@ant-design/icons'
import ScrollBar from '../ScrollBar'
import { config } from 'utils'
@@ -1,67 +1,67 @@
.loader {
background-color: #fff;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
z-index: 100000;
display: flex;
justify-content: center;
align-items: center;
opacity: 1;
text-align: center;
&.fullScreen {
position: fixed;
}
.warpper {
width: 100px;
height: 100px;
display: inline-flex;
flex-direction: column;
justify-content: space-around;
}
.inner {
width: 40px;
height: 40px;
margin: 0 auto;
text-indent: -12345px;
border-top: 1px solid rgba(0, 0, 0, 0.08);
border-right: 1px solid rgba(0, 0, 0, 0.08);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
border-left: 1px solid rgba(0, 0, 0, 0.7);
border-radius: 50%;
z-index: 100001;
:local {
animation: spinner 600ms infinite linear;
}
}
.text {
width: 100px;
height: 20px;
text-align: center;
font-size: 12px;
letter-spacing: 4px;
color: #000;
}
&.hidden {
z-index: -1;
opacity: 0;
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s;
}
}
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loader {
background-color: #fff;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
z-index: 100000;
display: flex;
justify-content: center;
align-items: center;
opacity: 1;
text-align: center;
&.fullScreen {
position: fixed;
}
.warpper {
width: 100px;
height: 100px;
display: inline-flex;
flex-direction: column;
justify-content: space-around;
}
.inner {
width: 40px;
height: 40px;
margin: 0 auto;
text-indent: -12345px;
border-top: 1px solid rgba(0, 0, 0, 0.08);
border-right: 1px solid rgba(0, 0, 0, 0.08);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
border-left: 1px solid rgba(0, 0, 0, 0.7);
border-radius: 50%;
z-index: 100001;
:local {
animation: spinner 600ms infinite linear;
}
}
.text {
width: 100px;
height: 20px;
text-align: center;
font-size: 12px;
letter-spacing: 4px;
color: #000;
}
&.hidden {
z-index: -1;
opacity: 0;
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s;
}
}
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@@ -1,9 +1,13 @@
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import styles from './Loader.less'
import styles from './index.less'
const Loader = ({ spinning = false, fullScreen }) => {
interface LoaderProps {
spinning?: boolean
fullScreen?: boolean
}
const Loader: React.FC<LoaderProps> = ({ spinning = false, fullScreen }) => {
return (
<div
className={classNames(styles.loader, {
@@ -19,9 +23,4 @@ const Loader = ({ spinning = false, fullScreen }) => {
)
}
Loader.propTypes = {
spinning: PropTypes.bool,
fullScreen: PropTypes.bool,
}
export default Loader
-6
View File
@@ -1,6 +0,0 @@
{
"name": "Loader",
"version": "0.0.0",
"private": true,
"main": "./Loader.js"
}
+1 -2
View File
@@ -1,8 +1,7 @@
import FilterItem from './FilterItem'
import DropOption from './DropOption'
import Loader from './Loader'
import ScrollBar from './ScrollBar'
import GlobalFooter from './GlobalFooter'
import Ellipsis from './Ellipsis'
export { GlobalFooter, Ellipsis, FilterItem, DropOption, Loader, ScrollBar }
export { GlobalFooter, Ellipsis, FilterItem, Loader, ScrollBar }
+1 -1
View File
@@ -1,5 +1,5 @@
import { IConfig, ISupportedLocales } from '@/typings'
import { LOCALE_LANGUAGE } from '@/configs'
import { LOCALE_LANGUAGE } from '@/configs/constants'
import checkLanguage from '@/utils/checkLanguage'
import {
detect,
+28 -4
View File
@@ -1,10 +1,34 @@
import React from 'react'
import { HomeOutlined, AppstoreOutlined } from '@ant-design/icons'
import {
PayCircleOutlined,
ShoppingCartOutlined,
MessageOutlined,
TeamOutlined,
UserOutlined,
DashboardOutlined,
ApiOutlined,
CameraOutlined,
EditOutlined,
CodeOutlined,
LineOutlined,
BarChartOutlined,
AreaChartOutlined,
} from '@ant-design/icons'
import { IMenuIcon } from '@/typings'
const menuIcon: IMenuIcon = {
home: <HomeOutlined />,
other: <AppstoreOutlined />,
'pay-circle-o': <PayCircleOutlined />,
'shopping-cart': <ShoppingCartOutlined />,
'camera-o': <CameraOutlined />,
'line-chart': <LineOutlined />,
'code-o': <CodeOutlined />,
'area-chart': <AreaChartOutlined />,
'bar-chart': <BarChartOutlined />,
message: <MessageOutlined />,
team: <TeamOutlined />,
dashboard: <DashboardOutlined />,
user: <UserOutlined />,
api: <ApiOutlined />,
edit: <EditOutlined />,
}
export default menuIcon
+2 -29
View File
@@ -9,35 +9,8 @@ import { t } from '@lingui/macro'
const menus = [
{
path: '/',
name: t`主页`,
icon: 'home',
},
{
name: t`其他`,
key: '/other',
icon: 'other',
children: [
{
path: '/hello',
name: t`你好 (useRedux)`,
},
{
path: '/user',
name: t`用户 (useRequest)`,
},
{
path: '/i18n',
name: t`国际化 (useLingui)`,
},
{
path: '/simple',
name: t`国际化 (Elint插件)`,
},
{
path: '/simple2',
name: t`未定义页面`,
},
],
name: t`Dashboard`,
icon: 'dashboard',
},
]
+1 -1
View File
@@ -18,7 +18,7 @@ describe('Login', () => {
afterEach(() => page.close())
it('should login with failure', async () => {
await page.waitFor(selector => !!document.querySelector('#username'), {
await page.waitFor((selector) => !!document.querySelector('#username'), {
timeout: 3000,
})
await page.type('#username', 'wrong_user')
+1 -1
View File
@@ -12,7 +12,7 @@ const useIntlProvider = () => {
useEffect(() => {
const path = antdI18nMap[language]
import(`antd/lib/locale/${path}.js`).then(data => {
import(`antd/lib/locale/${path}.js`).then((data) => {
setLocale(data.default)
})
localStorage.setItem(LOCALE_LANGUAGE, language)
+1 -1
View File
@@ -11,7 +11,7 @@ const LayoutMap = {
public: PublicLayout,
}
const BaseLayout: React.FC = props => {
const BaseLayout: React.FC = (props) => {
const location = useLocation()
const Container = LayoutMap[queryLayout(config.layouts, location.pathname)]
return <Container>{props.children}</Container>
+15 -10
View File
@@ -11,12 +11,13 @@ import ProBasicLayout, {
SettingDrawerProps,
} from '@ant-design/pro-layout'
import { Link } from 'umi'
import { Dropdown, Menu } from 'antd'
import { Dropdown, Menu, Avatar } from 'antd'
import { useLocation } from '@/hooks'
import { ConfigContext } from '@/utils/context'
import { menus, menuIcon, language, languages, config } from '@/configs'
import defaultSettings from '@/defaultSettings'
import type { MenuProps } from 'antd/es/menu';
import { ISupportedLocales } from '@/typings'
import type { MenuProps } from 'antd/es/menu'
import styles from './index.less'
const renderMenuItem = (menus: MenuDataItem[]): MenuDataItem[] =>
@@ -26,7 +27,7 @@ const renderMenuItem = (menus: MenuDataItem[]): MenuDataItem[] =>
children: children && renderMenuItem(children),
}))
const PrimaryLayout: React.FC = props => {
const PrimaryLayout: React.FC = (props) => {
const location = useLocation()
const [settings] = useState<SettingDrawerProps['settings']>(defaultSettings)
const [openKeys, setOpenKeys] = useState<string[]>([])
@@ -54,7 +55,7 @@ const PrimaryLayout: React.FC = props => {
}, [])
const handleOnOpenChange = useCallback(
keys => setOpenKeys(keys as string[]),
(keys) => setOpenKeys(keys as string[]),
[]
)
@@ -70,10 +71,15 @@ const PrimaryLayout: React.FC = props => {
const rightContentRender = () => (
<Dropdown
overlay={
<Menu>
{languages.map(item => (
<Menu.Item key={item.key} onClick={() => setLanguage(item.key)}>
<span className={styles.headerFlag}>{item.flag}</span>
<Menu
selectedKeys={[currentLanguage.value]}
onClick={(data) => {
setLanguage(data.key as ISupportedLocales)
}}
>
{languages.map((item) => (
<Menu.Item key={item.key}>
<Avatar size="small" style={{ marginRight: 8 }} src={item.flag} />
{item.value}
</Menu.Item>
))}
@@ -81,8 +87,7 @@ const PrimaryLayout: React.FC = props => {
}
>
<div className={styles.headerButton}>
<span className={styles.headerFlag}>{currentLanguage.flag}</span>
{currentLanguage.value}
<Avatar size="small" src={currentLanguage.flag} />
</div>
</Dropdown>
)
+1 -1
View File
@@ -1,6 +1,6 @@
import React from 'react'
const PublicLayout: React.FC = props => {
const PublicLayout: React.FC = (props) => {
return <>{props.children}</>
}
+1 -2
View File
@@ -4,9 +4,8 @@ import { I18nProvider } from '@lingui/react'
import { useIntlProvider } from '@/hooks'
import { ConfigContext } from '@/utils/context'
import BaseLayout from './BaseLayout'
import PrimaryLayout from './PrimaryLayout'
const Layout: React.FC = props => {
const Layout: React.FC = (props) => {
const { language, setLanguage, i18n, locale } = useIntlProvider()
const globalConfig = {
language,
+6 -9
View File
@@ -1,15 +1,12 @@
import React from 'react'
import { FrownOutlined } from '@ant-design/icons'
import { Page } from 'components'
import styles from './404.less'
const Error = () => (
<Page inner>
<div className={styles.error}>
<FrownOutlined />
<h1>404 Not Found</h1>
</div>
</Page>
const NotFoundPage: React.FC = () => (
<div className={styles.error}>
<FrownOutlined />
<h1>404 Not Found</h1>
</div>
)
export default Error
export default NotFoundPage
+1
View File
@@ -23,6 +23,7 @@ const Login: React.FC = () => {
]
const handleFinish = (values) => {
// eslint-disable-next-line no-console
console.log(values)
}
-13
View File
@@ -1,13 +0,0 @@
import { message } from 'antd'
export default {
onError(e, a) {
e.preventDefault()
if (e.message) {
message.error(e.message)
} else {
/* eslint-disable */
console.error(e)
}
},
}
+3 -7
View File
@@ -3,7 +3,7 @@ import { apiPrefix } from 'utils/config'
import api from './api'
const gen = params => {
const gen = (params) => {
let url = apiPrefix + params
let method = 'GET'
@@ -13,7 +13,7 @@ const gen = params => {
url = apiPrefix + paramsArray[1]
}
return function(data) {
return function (data) {
return request({
url,
data,
@@ -27,7 +27,7 @@ for (const key in api) {
APIFunction[key] = gen(api[key])
}
APIFunction.queryWeather = params => {
APIFunction.queryWeather = (params) => {
params.key = 'i7sau1babuzwhycn'
return request({
url: `${apiPrefix}/weather/now.json`,
@@ -35,8 +35,4 @@ APIFunction.queryWeather = params => {
})
}
<<<<<<< HEAD
// module.exports = APIFunction
=======
export default APIFunction
>>>>>>> master
+15 -16
View File
@@ -1,16 +1,15 @@
// 本文件是对 ant-design:
// https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
// 相应变量值的覆盖
// 注意:只需写出要覆盖的变量即可(不需要覆盖的变量不要写)
@import '../../node_modules/antd/lib/style/themes/default.less';
@border-radius-base: 3px;
@border-radius-sm: 2px;
@shadow-color: rgba(0, 0, 0, 0.05);
@shadow-1-down: 4px 4px 40px @shadow-color;
@border-color-split: #f4f4f4;
@border-color-base: #e5e5e5;
@font-size-base: 13px;
@text-color: #666;
@hover-color: #f9f9fc;
/**
* Customize Ant Design theme, Ant design less variables could be found in:
* https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
*/
@import '../../node_modules/antd/lib/style/themes/default.less';
@border-radius-base: 3px;
@border-radius-sm: 2px;
@shadow-color: rgba(0, 0, 0, 0.05);
@shadow-1-down: 4px 4px 40px @shadow-color;
@border-color-split: #f4f4f4;
@border-color-base: #e5e5e5;
@font-size-base: 13px;
@text-color: #666;
@hover-color: #f9f9fc;
+1 -1
View File
@@ -56,8 +56,8 @@ body {
}
.ant-table-pagination {
display: table;
float: none !important;
display: table;
margin: 16px auto !important;
}
+7 -8
View File
@@ -1,12 +1,12 @@
@import '~@/themes/default';
@dark-half #494949;
@purple #d897eb;
@shadow-1 4px 4px 20px 0 rgba(0, 0, 0, 0.01);
@shadow-2 4px 4px 40px 0 rgba(0, 0, 0, 0.05);
@transition-ease-in all 0.3s ease-out;
@transition-ease-out all 0.3s ease-out;
@ease-in ease-in;
@dark-half: #494949;
@purple: #d897eb;
@shadow-1: 4px 4px 20px 0 rgba(0, 0, 0, 0.01);
@shadow-2: 4px 4px 40px 0 rgba(0, 0, 0, 0.05);
@transition-ease-in: all 0.3s ease-out;
@transition-ease-out: all 0.3s ease-out;
@ease-in: ease-in;
.text-overflow {
overflow: hidden;
@@ -28,7 +28,6 @@
}
.background-hover {
// transition: @transition-ease-in;
&:hover {
background-color: @hover-color;
}
-39
View File
@@ -1,39 +0,0 @@
export type ISupportedLocales = 'en' | 'zh'
export interface IConfigContext {
language: ISupportedLocales
setLanguage: (language: ISupportedLocales) => void
}
export interface ILanguageItem {
flag: string
value: string
}
export interface ILanguage {
[key: string]: ILanguageItem
}
export interface ILanguages {
key: string
flag: string
value: string
}
export interface IAntdI18nMap {
[key: string]: string
}
export interface ILayouItem {
name: string
include?: any[]
exlude?: any[]
}
export interface IConfig {
language: ISupportedLocales
title: string
logo: string
copyright: string
layouts: ILayouItem[]
}
+15 -1
View File
@@ -1,2 +1,16 @@
export * from './common'
import { ISupportedLocales } from '@/typings'
export * from './language'
export * from './menu'
export interface ILayouItem {
name: string
include?: any[]
exlude?: any[]
}
export interface IConfig {
language: ISupportedLocales
title: string
logo: string
copyright: string
layouts: ILayouItem[]
}
+20
View File
@@ -0,0 +1,20 @@
export type ISupportedLocales = 'en' | 'zh' | 'pt-br'
export interface ILanguageItem {
flag: string
value: string
}
export interface ILanguage {
[key: string]: ILanguageItem
}
export interface ILanguages {
key: ISupportedLocales
flag: string
value: string
}
export interface IAntdI18nMap {
[key: string]: string
}
+4 -4
View File
@@ -4020,11 +4020,11 @@ let DICT = {
990100: '海外',
}
const tree = list => {
const tree = (list) => {
let hashTable = Object.create(null)
list.forEach(aData => (hashTable[aData.id] = { ...aData, children: [] }))
list.forEach((aData) => (hashTable[aData.id] = { ...aData, children: [] }))
let dataTree = []
list.forEach(aData => {
list.forEach((aData) => {
if (aData.pid) {
if (hashTable[aData.pid])
hashTable[aData.pid].children.push(hashTable[aData.id])
@@ -4033,7 +4033,7 @@ const tree = list => {
return dataTree
}
let DICT_FIXED = (function() {
let DICT_FIXED = (function () {
let fixed = []
for (let id in DICT) {
if ({}.hasOwnProperty.call(DICT, id)) {
+7 -2
View File
@@ -1,8 +1,13 @@
import React from 'react'
import { config } from '@/configs'
import { IConfigContext } from '@/typings'
import { ISupportedLocales } from '@/typings'
interface IConfigContext {
language: ISupportedLocales
setLanguage: (language: ISupportedLocales) => void
}
export const ConfigContext = React.createContext<IConfigContext>({
language: config.language,
setLanguage: language => null,
setLanguage: (language) => null,
})
-31
View File
@@ -1,31 +0,0 @@
import {
PayCircleOutlined,
ShoppingCartOutlined,
MessageOutlined,
TeamOutlined,
UserOutlined,
DashboardOutlined,
ApiOutlined,
CameraOutlined,
EditOutlined,
CodeOutlined,
LineOutlined,
BarChartOutlined,
AreaChartOutlined,
} from '@ant-design/icons'
export default {
'pay-circle-o': <PayCircleOutlined />,
'shopping-cart': <ShoppingCartOutlined />,
'camera-o': <CameraOutlined />,
'line-chart': <LineOutlined />,
'code-o': <CodeOutlined />,
'area-chart': <AreaChartOutlined />,
'bar-chart': <BarChartOutlined />,
message: <MessageOutlined />,
team: <TeamOutlined />,
dashboard: <DashboardOutlined />,
user: <UserOutlined />,
api: <ApiOutlined />,
edit: <EditOutlined />,
}
+1 -1
View File
@@ -1,8 +1,8 @@
import axios from 'axios'
import { cloneDeep } from 'lodash'
const { parse, compile } = require('path-to-regexp')
import { message } from 'antd'
import { CANCEL_REQUEST_MESSAGE } from '@/utils/constant'
const { parse, compile } = require('path-to-regexp')
const { CancelToken } = axios
window.cancelRequest = new Map()