Skip to content
This repository was archived by the owner on Aug 4, 2022. It is now read-only.

Commit ff47cb8

Browse files
committed
first commit
0 parents  commit ff47cb8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1481
-0
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.build
2+
build
3+
web_modules
4+
node_modules
5+
6+
.history/

.prettierignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.history
2+
build
3+
4+
**/*.md
5+
**/*.svg
6+
**/*.html
7+
8+
package.json

.prettierrc

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"semi": false,
3+
"singleQuote": true,
4+
"trailingComma": "all",
5+
"jsxBracketSameLine": true,
6+
"printWidth": 120,
7+
"overrides": [
8+
{
9+
"files": ".prettierrc",
10+
"options": { "parser": "json" }
11+
}
12+
]
13+
}

.vscode/extensions.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"recommendations": [
3+
"streetsidesoftware.code-spell-checker",
4+
"eamodio.gitlens",
5+
"xyz.local-history",
6+
"editorconfig.editorconfig",
7+
"christian-kohler.npm-intellisense",
8+
"axetroy.vscode-npm-import-package-version"
9+
]
10+
}

.vscode/settings.json

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"telemetry.enableCrashReporter": false,
3+
"telemetry.enableTelemetry": false,
4+
"grunt.autoDetect": "off",
5+
"gulp.autoDetect": "off",
6+
"jake.autoDetect": "off",
7+
"search.followSymlinks": false,
8+
"search.exclude": {
9+
"**/.tsbuildinfo": true,
10+
"**/.tsbuildinfo.*": true,
11+
"**/.history": true,
12+
"**/build/**": true
13+
},
14+
"files.autoSave": "afterDelay",
15+
"files.autoSaveDelay": 1500,
16+
"files.insertFinalNewline": true,
17+
"files.trimTrailingWhitespace": true,
18+
"files.eol": "\n",
19+
"files.exclude": {
20+
"**/.DS_Store": true,
21+
"**/.history": true
22+
},
23+
"files.watcherExclude": {
24+
"**/.history/**": true,
25+
"**/build/**": true
26+
},
27+
"editor.minimap.enabled": false,
28+
"cSpell.words": ["devtools"],
29+
"cSpell.ignoreWords": ["tslib"],
30+
"cSpell.ignorePaths": [".history", ".vscode", "build", "package-lock.json", "yarn.lock"]
31+
}

README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# react-app
2+
3+
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
4+
5+
## 目录结构
6+
7+
```text
8+
Project/
9+
├── README.md
10+
├── package.json
11+
├── tsconfig.json
12+
├── babel.config.json
13+
├── snowpack.config.js
14+
├── public/
15+
└── src/
16+
├── components/
17+
├── hooks/
18+
├── lib/
19+
├── mocks/
20+
├── models/
21+
├── services/
22+
├── store/
23+
├── styles/
24+
├── views/
25+
├── App.tsx
26+
├── index.tsx
27+
└── router.tsx
28+
```
29+
30+
## 开发步骤
31+
32+
你需要安装 Node.js 的版本为 6+.
33+
34+
克隆此仓库后运行:
35+
36+
```bash
37+
# 安装依赖
38+
$ npm install
39+
40+
# 本地开发
41+
$ npm run dev
42+
43+
# 构建代码
44+
$ npm run build
45+
```
46+
47+
在 package.json 文件的 scripts 部分还有一些其他脚本可用.
48+
49+
## 运行单元测试
50+
51+
```bash
52+
# 单元测试
53+
$ npm test
54+
```

babel.config.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "@snowpack/app-scripts-react/babel.config.json"
3+
}

jest.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const baseConfig = require('@snowpack/app-scripts-react/jest.config.js')()
2+
3+
module.exports = {
4+
...baseConfig,
5+
}

jest.setup.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// jest-dom adds custom jest matchers for asserting on DOM nodes.
2+
// allows you to do things like:
3+
// expect(element).toHaveTextContent(/react/i)
4+
// learn more: https://github.com/testing-library/jest-dom
5+
import '@testing-library/jest-dom/extend-expect'

package.json

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "snowpack-react-app",
3+
"private": true,
4+
"version": "0.1.0",
5+
"scripts": {
6+
"dev": "snowpack dev",
7+
"build": "snowpack build",
8+
"test": "jest",
9+
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json}\"",
10+
"lint": "prettier --check \"**/*.{js,jsx,ts,tsx,json}\""
11+
},
12+
"gitHooks": {
13+
"pre-commit": "lint-staged"
14+
},
15+
"lint-staged": {
16+
"*.{js,jsx,ts,tsx}": [
17+
"prettier --write",
18+
"git add"
19+
]
20+
},
21+
"dependencies": {
22+
"axios": "^0.19.2",
23+
"lodash-es": "^4.17.15",
24+
"react": "^16.13.0",
25+
"react-dom": "^16.13.0",
26+
"react-redux": "^7.2.0",
27+
"react-router-config": "^5.1.1",
28+
"react-router-dom": "^5.2.0",
29+
"redux": "^4.0.5",
30+
"tslib": "^2.0.0"
31+
},
32+
"devDependencies": {
33+
"@snowpack/app-scripts-react": "^1.2.0",
34+
"@testing-library/jest-dom": "^5.5.0",
35+
"@testing-library/react": "^10.0.3",
36+
"@types/lodash-es": "^4.17.3",
37+
"@types/react": "^16.9.35",
38+
"@types/react-dom": "^16.9.8",
39+
"@types/react-redux": "^7.1.9",
40+
"@types/react-router-config": "^5.0.1",
41+
"@types/react-router-dom": "^5.1.5",
42+
"babel-plugin-transform-async-to-promises": "^0.8.15",
43+
"better-mock": "^0.2.5",
44+
"jest": "^25.4.0",
45+
"lint-staged": "^10.2.11",
46+
"node-sass": "^4.14.1",
47+
"prettier": "^2.0.0",
48+
"snowpack": "^2.5.0",
49+
"typescript": "^3.8.0",
50+
"yorkie": "^2.0.0"
51+
},
52+
"author": "zhengxs2018 <[email protected]>",
53+
"license": "MIT"
54+
}

public/favicon.ico

3.08 KB
Binary file not shown.

public/index.html

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="description" content="" />
8+
<title>React web app</title>
9+
10+
<script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
11+
<script>
12+
if ('addEventListener' in document) {
13+
document.addEventListener('DOMContentLoaded', function() {
14+
FastClick.attach(document.body);
15+
}, false);
16+
}
17+
if(!window.Promise) {
18+
document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>');
19+
}
20+
</script>
21+
</head>
22+
<body>
23+
<noscript>You need to enable JavaScript to run this app.</noscript>
24+
<div id="root"></div>
25+
<script type="module" src="/_dist_/index.js"></script>
26+
</body>
27+
</html>

public/robots.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://www.robotstxt.org/robotstxt.html
2+
User-agent: *
3+
Disallow:

snowpack.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
extends: '@snowpack/app-scripts-react',
3+
scripts: {},
4+
plugins: [],
5+
}

src/App.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React, { FC } from 'react'
2+
import { Provider } from 'react-redux'
3+
4+
import store from './store/index'
5+
import { RouterView } from './router'
6+
7+
export type AppState = {}
8+
9+
const App: FC = () => (
10+
<Provider store={store}>
11+
<RouterView />
12+
</Provider>
13+
)
14+
15+
export default App
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { FC } from 'react'
2+
3+
import { connect } from 'react-redux'
4+
5+
import type { RootState } from 'src/store/types'
6+
import { Categories, loadAllCategories } from 'src/store/actions/app'
7+
8+
import UISelect from 'src/components/ui-select'
9+
10+
export type BizCategorySelectState = {
11+
categories: Categories
12+
}
13+
14+
export type BizCategorySelectProps = {
15+
value?: string | ReadonlyArray<string> | number
16+
onInput?: (value: string) => void
17+
}
18+
19+
const BizCategorySelect: FC<BizCategorySelectState & BizCategorySelectProps> = ({ value, categories, onInput }) => {
20+
const onProxyChange = (e: React.FormEvent<HTMLSelectElement>) => {
21+
onInput && onInput(((e.target as unknown) as { value: string }).value)
22+
}
23+
24+
return (
25+
<UISelect
26+
{...categories}
27+
value={value}
28+
valueKey="id"
29+
labelKey="name"
30+
onChange={onProxyChange}
31+
onRefresh={loadAllCategories}
32+
/>
33+
)
34+
}
35+
36+
function mapStateToProps(state: RootState): BizCategorySelectState {
37+
return { categories: state.app.categories }
38+
}
39+
40+
export default connect<BizCategorySelectState, {}, BizCategorySelectProps, RootState>(mapStateToProps)(
41+
BizCategorySelect,
42+
)

src/biz/components/biz-me.tsx

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React, { FC } from 'react'
2+
3+
import { connect } from 'react-redux'
4+
5+
import type { RootState } from 'src/store/types'
6+
7+
import type { User } from 'src/biz/models/user'
8+
import { AuthStatus, UserStatus } from 'src/store/enums'
9+
10+
export type BizMeState = {
11+
info?: User
12+
message?: string | null
13+
authStatus: AuthStatus
14+
userStatus: UserStatus
15+
}
16+
17+
const BizMe: FC<BizMeState> = ({ authStatus, info, userStatus, message }) => {
18+
if (authStatus === AuthStatus.LOADING) {
19+
return <div>正在查询登录状态</div>
20+
} else if (authStatus === AuthStatus.NOT_AUTHORIZED) {
21+
return <div>正在注销登录状态</div>
22+
} else if (authStatus === AuthStatus.UNKNOWN) {
23+
return <div>用户未登录,请先登录</div>
24+
} else if (authStatus === AuthStatus.CONNECTED) {
25+
if (userStatus === UserStatus.LOADING) {
26+
return <div>正在加载用户信息</div>
27+
} else if (userStatus === UserStatus.ERROR) {
28+
return <div>加载用户失败:{message}</div>
29+
} else if (userStatus === UserStatus.UNKNOWN) {
30+
return <div>匿名用户</div>
31+
} else if (userStatus === UserStatus.CONNECTED) {
32+
return <div>{info?.nickname ?? info?.username}</div>
33+
}
34+
}
35+
36+
return <div>未知错误</div>
37+
}
38+
39+
function mapStateToProps(state: RootState): BizMeState {
40+
return {
41+
info: state.me.info,
42+
message: state.me.message,
43+
authStatus: state.app.authStatus,
44+
userStatus: state.me.status,
45+
}
46+
}
47+
48+
export default connect<BizMeState, {}, {}, RootState>(mapStateToProps)(BizMe)

src/biz/models/access.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface Permission {
2+
id: number
3+
code: string
4+
}

src/biz/models/bill.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface Bill {
2+
type: number
3+
time: number
4+
category: string
5+
amount: number
6+
}

src/biz/models/category.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface Category {
2+
id: string
3+
type: number
4+
name: string
5+
}

src/biz/models/user.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface User {
2+
id: number
3+
username: string
4+
avatar: string
5+
nickname: string
6+
}

src/biz/services/bill.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { Bill } from 'src/biz/models/bill'
2+
3+
import { usePaginated } from 'src/hooks/usePaginated'
4+
5+
/**
6+
* 账单列表查询
7+
*/
8+
export const useBillListByPagination = usePaginated<Bill>('/api/bill/list')

0 commit comments

Comments
 (0)