mirror of
https://github.com/SunnyQjm/sunny-blog.git
synced 2026-10-05 01:15:39 +08:00
init
This commit is contained in:
1 parent
f36828501a
commit
7bf538b041
26 files changed
+509
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,7 @@
|
||||
import mockjs from "mockjs";
|
||||
|
||||
export default {
|
||||
'GET /api/img': mockjs.mock({
|
||||
'list|10': [{ src: '@image' }],
|
||||
})
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "umi dev",
|
||||
"build": "umi build",
|
||||
"test": "umi test",
|
||||
"lint:es": "eslint --ext .js src mock tests",
|
||||
"lint:ts": "tslint \"src/**/*.ts\" \"src/**/*.tsx\"",
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/react-transition-group": "^4.2.3",
|
||||
"antd": "^3.19.5",
|
||||
"dva": "^2.6.0-beta.6",
|
||||
"mockjs": "^1.1.0",
|
||||
"node-sass": "^4.13.0",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-transition-group": "^4.3.0",
|
||||
"sass-loader": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^23.3.12",
|
||||
"@types/mockjs": "^1.0.2",
|
||||
"@types/react": "^16.7.18",
|
||||
"@types/react-dom": "^16.0.11",
|
||||
"@types/react-test-renderer": "^16.0.3",
|
||||
"babel-eslint": "^9.0.0",
|
||||
"eslint": "^5.4.0",
|
||||
"eslint-config-umi": "^1.4.0",
|
||||
"eslint-plugin-flowtype": "^2.50.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "^5.1.1",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"husky": "^0.14.3",
|
||||
"lint-staged": "^7.2.2",
|
||||
"react-test-renderer": "^16.7.0",
|
||||
"tslint": "^5.12.0",
|
||||
"tslint-eslint-rules": "^5.4.0",
|
||||
"tslint-react": "^3.6.0",
|
||||
"umi": "^2.9.0",
|
||||
"umi-plugin-react": "^1.8.0",
|
||||
"umi-types": "^0.3.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": [
|
||||
"tslint --fix",
|
||||
"git add"
|
||||
],
|
||||
"*.{js,jsx}": [
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export const dva = {
|
||||
config: {
|
||||
onError(err: ErrorEvent) {
|
||||
err.preventDefault();
|
||||
console.error(err.message);
|
||||
},
|
||||
},
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
@@ -0,0 +1,5 @@
|
||||
import NavBarComponent from "@/components/nav-bar";
|
||||
|
||||
export {
|
||||
NavBarComponent
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
@import "../../scss/animation";
|
||||
|
||||
.nav-bar-component {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px 20%;
|
||||
background: #f5f5f5;
|
||||
|
||||
&__title {
|
||||
position: relative;
|
||||
margin-right: 30px;
|
||||
&::before {
|
||||
content: '';
|
||||
background: #222;
|
||||
height: 2px;
|
||||
width: 80%;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: 10%;
|
||||
animation: width-show 1s;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
background: #222;
|
||||
height: 2px;
|
||||
width: 80%;
|
||||
position: absolute;
|
||||
bottom: -5px;
|
||||
left: 10%;
|
||||
animation: width-show 1s;
|
||||
}
|
||||
font-size: 22px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
animation: fadeInDown 1s;
|
||||
}
|
||||
|
||||
&__menu {
|
||||
font-size: 13px;
|
||||
color: #555;
|
||||
&-item {
|
||||
&:hover {
|
||||
background: #e1e1e1;
|
||||
}
|
||||
&--active {
|
||||
background: #e1e1e1;
|
||||
}
|
||||
padding: 3px 10px;
|
||||
border-radius: 2px;
|
||||
outline: none;
|
||||
color: #555;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
transition-property: border-color;
|
||||
transition-duration: 0.2s;
|
||||
transition-delay: 0s;
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import React from "react";
|
||||
import './index.scss';
|
||||
import Link from 'umi/link';
|
||||
import {
|
||||
Icon
|
||||
} from 'antd';
|
||||
import RouterTypes from "umi/routerTypes";
|
||||
import withRouter from 'umi/withRouter';
|
||||
|
||||
|
||||
interface NavBarComponentProps extends RouterTypes{
|
||||
title: string,
|
||||
menu: {
|
||||
url: string,
|
||||
icon: string,
|
||||
value: string,
|
||||
}[],
|
||||
}
|
||||
|
||||
interface NavBarComponentState {
|
||||
|
||||
}
|
||||
|
||||
class NavBarComponent extends React.Component<NavBarComponentProps, NavBarComponentState> {
|
||||
static defaultProps = {
|
||||
title: 'Website title',
|
||||
menu: []
|
||||
};
|
||||
|
||||
constructor(props: NavBarComponentProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render(): React.ReactElement<any, string | React.JSXElementConstructor<any>> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined {
|
||||
const {
|
||||
title,
|
||||
menu,
|
||||
location
|
||||
} = this.props;
|
||||
const menus = menu.map(item => {
|
||||
return (
|
||||
<Link to={item.url} className={`nav-bar-component__menu-item ${(location && location.pathname == item.url) ? 'nav-bar-component__menu-item--active' : ''}`} key={item.url + item.value}>
|
||||
<Icon type={item.icon} theme='filled' style={{marginRight: '5px'}}/>
|
||||
{item.value}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
return (
|
||||
<div className='nav-bar-component'>
|
||||
<span className='nav-bar-component__title'>
|
||||
{title}
|
||||
</span>
|
||||
|
||||
<div className='nav-bar-component__menu'>
|
||||
{menus}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(NavBarComponent);
|
||||
@@ -0,0 +1,28 @@
|
||||
html, body, #root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.item-enter {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
}
|
||||
.item-enter-active {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
.item-exit {
|
||||
opacity: 1;
|
||||
}
|
||||
.item-exit-active {
|
||||
opacity: 0;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'jest';
|
||||
import BasicLayout from '..';
|
||||
import React from 'react';
|
||||
import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
|
||||
|
||||
describe('Layout: BasicLayout', () => {
|
||||
it('Render correctly', () => {
|
||||
const wrapper: ReactTestRenderer = renderer.create(<BasicLayout />);
|
||||
expect(wrapper.root.children.length).toBe(1);
|
||||
const outerLayer = wrapper.root.children[0] as ReactTestInstance;
|
||||
expect(outerLayer.type).toBe('div');
|
||||
const title = outerLayer.children[0] as ReactTestInstance;
|
||||
expect(title.type).toBe('h1');
|
||||
expect(title.children[0]).toBe('Yay! Welcome to umi!');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
.page_layout {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&__header {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&__content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import './index.scss'
|
||||
import {
|
||||
NavBarComponent
|
||||
} from '../components';
|
||||
|
||||
const menu = [
|
||||
{
|
||||
icon: 'home',
|
||||
value: '首页',
|
||||
url: '/'
|
||||
},
|
||||
{
|
||||
icon: 'fire',
|
||||
value: '关于',
|
||||
url: '/about'
|
||||
},
|
||||
{
|
||||
icon: 'tags',
|
||||
value: '标签',
|
||||
url: '/tags'
|
||||
}
|
||||
];
|
||||
|
||||
const BasicLayout: React.FC = props => {
|
||||
return (
|
||||
<div className='page_layout'>
|
||||
<div className='page_layout__header'>
|
||||
<NavBarComponent title='建明 | Ming.J' menu={menu}/>
|
||||
</div>
|
||||
<div className='page_layout__content'>
|
||||
{props.children}
|
||||
</div>
|
||||
<div className='page_layout__footer'>
|
||||
footer
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BasicLayout;
|
||||
Whitespace-only changes.
@@ -0,0 +1,16 @@
|
||||
import 'jest';
|
||||
import Index from '..';
|
||||
import React from 'react';
|
||||
import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
|
||||
|
||||
|
||||
describe('Page: index', () => {
|
||||
it('Render correctly', () => {
|
||||
const wrapper: ReactTestRenderer = renderer.create(<Index />);
|
||||
expect(wrapper.root.children.length).toBe(1);
|
||||
const outerLayer = wrapper.root.children[0] as ReactTestInstance;
|
||||
expect(outerLayer.type).toBe('div');
|
||||
expect(outerLayer.children.length).toBe(2);
|
||||
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import Link from 'umi/link';
|
||||
import withRouter from 'umi/withRouter';
|
||||
import {TransitionGroup, CSSTransition} from "react-transition-group";
|
||||
import React from "react";
|
||||
|
||||
export default withRouter(
|
||||
({location, match, children}) =>
|
||||
(
|
||||
<>
|
||||
<h1>/animated-transitions</h1>
|
||||
<ul>
|
||||
<li><Link to={`${match.url}/red`}>red</Link></li>
|
||||
<li><Link to={`${match.url}/blue`}>blue</Link></li>
|
||||
<li><Link to={`${match.url}/green`}>green</Link></li>
|
||||
{JSON.stringify(location)}
|
||||
</ul>
|
||||
<hr />
|
||||
<div style={{ height: 100, background: 'brown', position: 'relative' }}>
|
||||
<TransitionGroup>
|
||||
<CSSTransition key={location.pathname} classNames="item" timeout={300}>
|
||||
{children}
|
||||
</CSSTransition>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
.block {
|
||||
height: 100px;
|
||||
width: 80%;
|
||||
position: absolute;
|
||||
color: white;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import styles from './block.css'
|
||||
import React from "react";
|
||||
|
||||
export default () =>
|
||||
(
|
||||
<h2
|
||||
className={styles.block}
|
||||
style={{background: 'blue'}}
|
||||
>
|
||||
blue
|
||||
</h2>
|
||||
);
|
||||
@@ -0,0 +1,12 @@
|
||||
import styles from './block.css'
|
||||
import React from "react";
|
||||
|
||||
export default () =>
|
||||
(
|
||||
<h2
|
||||
className={styles.block}
|
||||
style={{background: 'green'}}
|
||||
>
|
||||
green
|
||||
</h2>
|
||||
);
|
||||
@@ -0,0 +1,12 @@
|
||||
import styles from './block.css';
|
||||
import React from "react";
|
||||
|
||||
export default () =>
|
||||
(
|
||||
<h2
|
||||
className={styles.block}
|
||||
style={{background: 'red'}}
|
||||
>
|
||||
red
|
||||
</h2>
|
||||
);
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
.welcome {
|
||||
height: 328px;
|
||||
background: url(../assets/yay.jpg) no-repeat center 0;
|
||||
background-size: 388px 328px;
|
||||
}
|
||||
|
||||
.list {
|
||||
font-size: 1.2em;
|
||||
margin-top: 1.8em;
|
||||
list-style: none;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.list code {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import Link from 'umi/link';
|
||||
import styles from './index.css';
|
||||
|
||||
export default function () {
|
||||
return (
|
||||
<div className={styles.normal}>
|
||||
<div className={styles.welcome}/>
|
||||
<ul className={styles.list}>
|
||||
<li>To get started, edit <code>src/pages/index.js</code> and save to reload.</li>
|
||||
<Link to='/test'>go to /test</Link>
|
||||
<li>
|
||||
<a href="https://umijs.org/guide/getting-started.html">
|
||||
Getting Started
|
||||
</a>
|
||||
</li>
|
||||
<li><Link to="/animated-transitions">/animated-transitions</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from "react";
|
||||
|
||||
interface TestPageProps {
|
||||
|
||||
}
|
||||
|
||||
interface TestPageState {
|
||||
|
||||
}
|
||||
|
||||
class TestPage extends React.Component<TestPageProps, TestPageState> {
|
||||
constructor(props: TestPageProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render(): React.ReactElement<any, string | React.JSXElementConstructor<any>> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined {
|
||||
return (
|
||||
<div>
|
||||
test
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default TestPage;
|
||||
@@ -0,0 +1,21 @@
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-1);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes width-show {
|
||||
from {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"allowSyntheticDefaultImports": true
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
defaultSeverity: error
|
||||
extends:
|
||||
- tslint-react
|
||||
- tslint-eslint-rules
|
||||
rules:
|
||||
eofline: true
|
||||
# no-console: true
|
||||
no-construct: true
|
||||
no-debugger: true
|
||||
no-reference: true
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
declare module '*.css';
|
||||
declare module "*.png";
|
||||
Reference in new issue
Block a user