refactor: separation page code

add socket.io test

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2019-07-31 18:38:00 +08:00
parent d66c64fdff
commit 1e8601d148
18 changed files with 754 additions and 306 deletions

View File

@ -9,7 +9,7 @@
"css": "sass" "css": "sass"
}, },
"scripts": { "scripts": {
"build:weapp": "taro build --type weapp", "build:wx": "taro build --type weapp",
"build:swan": "taro build --type swan", "build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay", "build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt", "build:tt": "taro build --type tt",
@ -17,7 +17,7 @@
"build:rn": "taro build --type rn", "build:rn": "taro build --type rn",
"build:qq": "taro build --type qq", "build:qq": "taro build --type qq",
"build:quickapp": "taro build --type quickapp", "build:quickapp": "taro build --type quickapp",
"dev:weapp": "npm run build:weapp -- --watch", "dev:wx": "npm run build:weapp -- --watch",
"dev:swan": "npm run build:swan -- --watch", "dev:swan": "npm run build:swan -- --watch",
"dev:alipay": "npm run build:alipay -- --watch", "dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch", "dev:tt": "npm run build:tt -- --watch",
@ -29,33 +29,39 @@
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tarojs/async-await": "^1.3.10", "@tarojs/async-await": "^1.3.11",
"@tarojs/components": "1.3.10", "@tarojs/components": "1.3.11",
"@tarojs/redux": "^1.3.10", "@tarojs/redux": "^1.3.11",
"@tarojs/redux-h5": "^1.3.10", "@tarojs/redux-h5": "^1.3.11",
"@tarojs/router": "1.3.10", "@tarojs/router": "1.3.11",
"@tarojs/taro": "1.3.10", "@tarojs/taro": "1.3.11",
"@tarojs/taro-alipay": "1.3.10", "@tarojs/taro-alipay": "1.3.11",
"@tarojs/taro-h5": "1.3.10", "@tarojs/taro-h5": "1.3.11",
"@tarojs/taro-qq": "1.3.10", "@tarojs/taro-qq": "1.3.11",
"@tarojs/taro-quickapp": "1.3.10", "@tarojs/taro-quickapp": "1.3.11",
"@tarojs/taro-swan": "1.3.10", "@tarojs/taro-swan": "1.3.11",
"@tarojs/taro-tt": "1.3.10", "@tarojs/taro-tt": "1.3.11",
"@tarojs/taro-weapp": "1.3.10", "@tarojs/taro-weapp": "1.3.11",
"bufferutil": "^4.0.1",
"dva-core": "^1.4.0", "dva-core": "^1.4.0",
"dva-loading": "^3.0.12", "dva-loading": "^3.0.12",
"nerv-devtools": "^1.4.0", "nerv-devtools": "^1.4.0",
"nervjs": "^1.4.0", "nervjs": "^1.4.0",
"taro-ui": "^2.2.1" "socket.io-client": "^2.2.0",
"supports-color": "^7.0.0",
"taro-ui": "^2.2.1",
"utf-8-validate": "^5.0.2",
"weapp.socket.io": "^2.0.1"
}, },
"devDependencies": { "devDependencies": {
"@tarojs/cli": "^1.3.10", "@tarojs/cli": "^1.3.11",
"@tarojs/plugin-babel": "1.3.10", "@tarojs/plugin-babel": "1.3.11",
"@tarojs/plugin-csso": "1.3.10", "@tarojs/plugin-csso": "1.3.11",
"@tarojs/plugin-sass": "1.3.10", "@tarojs/plugin-sass": "^1.3.11",
"@tarojs/plugin-uglifyjs": "1.3.10", "@tarojs/plugin-uglifyjs": "^1.3.11",
"@tarojs/webpack-runner": "1.3.10", "@tarojs/webpack-runner": "1.3.11",
"@types/react": "^16.4.6", "@types/react": "^16.4.6",
"@types/socket.io-client": "^1.4.32",
"@types/webpack-env": "^1.13.6", "@types/webpack-env": "^1.13.6",
"@typescript-eslint/parser": "^1.6.0", "@typescript-eslint/parser": "^1.6.0",
"babel-eslint": "^8.2.3", "babel-eslint": "^8.2.3",
@ -72,6 +78,6 @@
"stylelint": "9.3.0", "stylelint": "9.3.0",
"stylelint-config-taro-rn": "1.3.10", "stylelint-config-taro-rn": "1.3.10",
"stylelint-taro-rn": "1.3.10", "stylelint-taro-rn": "1.3.10",
"typescript": "^3.0.1" "typescript": "^3.5.3"
} }
} }

13
project.weapp.json Normal file
View File

@ -0,0 +1,13 @@
{
"miniprogramRoot": "./dist",
"projectname": "TeraWallet",
"description": "泰瑞管理工具",
"appid": "wx243ba1a5ae302a75",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}

View File

@ -11,6 +11,7 @@ export type Dispatch = <P = any, C = (payload: P) => void>(action: {
export interface DefaultProps { export interface DefaultProps {
dispatch: Dispatch dispatch: Dispatch
[key: string]: Function
} }
export interface DefaultModel<T> { export interface DefaultModel<T> {

View File

@ -1,5 +1,21 @@
let mapDefaultProps = (obj: any) => ((def) => ({ ...def[obj.name.toLowerCase()] })) import { Dispatch } from "./types";
let mapModelProps = (name: string) => ((def: { [x: string]: any; }) => ({ ...def[name] }))
let mapModelActions = (name: string, actions: { [key: string]: string }) => ((dispatch: Dispatch) => {
let acts = Object.keys(actions).map(action => {
return {
[action]: function __run(args: any) {
dispatch({
type: `${name}/${action}`,
payload: args
})
}
}
}).reduce((p, n) => ({ ...p, ...n }))
return { ...acts, dispatch }
})
export { export {
mapDefaultProps mapModelProps,
mapModelActions
} }

View File

@ -0,0 +1,13 @@
import { AtCard } from "taro-ui";
import { View } from "@tarojs/components";
export default ({ info }) => (
<AtCard className='base-info' title='基本信息'>
<View>: {info.version}</View>
<View>: {info.block}</View>
<View>: {info.supply}</View>
<View> : {info.percent}</View>
<View>: {info.lastNumber}</View>
<View> : {info.lastMiner} {info.lastName}</View>
</AtCard>
)

View File

@ -1,15 +1,21 @@
import { connect } from '@tarojs/redux'; import { connect } from '@tarojs/redux';
import { AtCard, AtNoticebar } from 'taro-ui'; import { AtNoticebar } from 'taro-ui';
import { View, Image } from '@tarojs/components'; import { View, Image } from '@tarojs/components';
import Taro, { Component, Config } from '@tarojs/taro'; import Taro, { Component, Config } from '@tarojs/taro';
import logoImg from '../../assets/images/logo.png'; import logoImg from '../../assets/images/logo.png';
import { mapDefaultProps } from '../../models/utils'; import { mapModelProps, mapModelActions } from '../../models/utils';
import './index.scss'; import './index.scss';
import { Actions } from './model';
import BaseInfo from './components/base-info'
import { IndexProps, IndexState } from './type'; import { IndexProps, IndexState } from './type';
@connect(mapDefaultProps(Index)) // import WsClient from '../../rpc/socket'
const PAGE_NAME = 'index'
@connect(mapModelProps(PAGE_NAME), mapModelActions(PAGE_NAME, Actions))
class Index extends Component<IndexProps, IndexState> { class Index extends Component<IndexProps, IndexState> {
config: Config = { config: Config = {
navigationBarTitleText: '首页', navigationBarTitleText: '首页',
@ -19,38 +25,33 @@ class Index extends Component<IndexProps, IndexState> {
notify: '通知: 钱包目前处于测试阶段 如果发现BUG 请及时反馈!' notify: '通知: 钱包目前处于测试阶段 如果发现BUG 请及时反馈!'
} }
switchWs() {
// if (WsClient.connected) {
// WsClient.disconnect();
// } else {
// WsClient.connect();
// }
}
componentDidMount() { componentDidMount() {
Taro.startPullDownRefresh(); Taro.startPullDownRefresh();
} }
async onPullDownRefresh() { onPullDownRefresh() {
await this.props.dispatch({ this.props[Actions.getCurrentInfo]();
type: 'index/getCurrentInfo'
})
} }
render() { render() {
const data = this.props
const info = (
<AtCard className='base-info' title='基本信息'>
<View>: {data.version}</View>
<View>: {data.block}</View>
<View>: {data.supply}</View>
<View> : {data.percent}</View>
<View>: {data.lastNumber}</View>
<View> : {data.lastMiner} {data.lastName}</View>
</AtCard>
)
return ( return (
<View className='page page-index'> <View className='page page-index'>
<AtNoticebar close marquee icon='volume-plus'> <AtNoticebar close marquee icon='volume-plus'>
{this.state.notify} {this.state.notify}
</AtNoticebar> </AtNoticebar>
<View className='logo'> <View className='logo' onClick={() => this.switchWs()}>
<Image src={logoImg} className='img' mode='scaleToFill' /> <Image src={logoImg} className='img' mode='scaleToFill' />
</View> </View>
<View className='page-title'></View> <View className='page-title'></View>
{info} <BaseInfo info={this.props} />
</View> </View>
) )
} }

View File

@ -3,6 +3,10 @@ import { DefaultModel } from '../../models/types';
import { getInfo } from './service'; import { getInfo } from './service';
import { IndexModel } from './type'; import { IndexModel } from './type';
let Actions = {
getCurrentInfo: 'getCurrentInfo'
}
export default { export default {
namespace: 'index', namespace: 'index',
state: { state: {
@ -28,3 +32,5 @@ export default {
} }
} }
} as DefaultModel<IndexModel> } as DefaultModel<IndexModel>
export { Actions }

View File

@ -0,0 +1,24 @@
import { AtList, AtListItem } from "taro-ui";
const AccountHeader = () => (
<AtList hasBorder={false}>
<AtListItem
hasBorder={false}
title='创建/绑定私钥'
iconInfo={{
size: 20,
color: 'red',
value: 'lock',
}} />
<AtListItem
hasBorder={false}
title='创建账户'
iconInfo={{
size: 20,
color: 'green',
value: 'credit-card',
}} />
</AtList>
)
export default AccountHeader

View File

@ -0,0 +1,33 @@
import { AtList, AtListItem } from "taro-ui";
import coinKit from "../../../utils/coin-kit";
import { Account } from '../../../rpc/types';
const AccountList = ({ accounts, defaultImage }) => (
<AtList >
<AtListItem
hasBorder={false}
title='账户列表'
iconInfo={{
size: 20,
color: 'blue',
value: 'numbered-list',
}} />
{(accounts || []).map((a: Account) => {
return <AtListItem
key={a.Num}
hasBorder={false}
title={`${a.Num}(${a.Name})`}
note={`${coinKit.toNumber(a.Value)}`}
iconInfo={{
size: 20,
color: 'green',
value: 'credit-card',
}}
extraThumb={defaultImage}
/>
})}
</AtList>
)
export default AccountList

View File

@ -0,0 +1,44 @@
.flex-wrp{
display: flex;
justify-content: center;
align-items: center;
}
.flex-item{
flex-grow: 1;
text-align: center;
}
.user {
width: 725px;
background: #ffffff;
padding: 30px 25px 30px 0;
margin: 15rpx 0 0 0;
border-top: 1px solid #eee;
border-bottom: 1px solid #dcdcdc;
box-shadow: 0 2px 5px #eeeeee;
.userinfo-avatar{
margin-top: 30px;
flex: 1;
display: inline-block;
width: 100px!important;
height: 100px!important;
border-radius: 80px;
}
.user-info{
flex: 5;
text-align: left;
text,div,span{
display: block;
}
.userinfo-nickname{
padding: 8px 0 10px 0;
font-size: 30px;
color: #818A8F;
}
.edit{
font-size: 30px;
color: #bababa;
line-height: 34px;
}
}
}

View File

@ -0,0 +1,9 @@
import UserInfo from './user-info'
import AccountHeader from './account-header'
import AccountList from './account-list'
export {
UserInfo,
AccountHeader,
AccountList
}

View File

@ -0,0 +1,15 @@
import { View, Text, Image } from '@tarojs/components';
import './components.scss'
export default ({ avatarUrl, nickName }) => (
<View className='user flex-wrp'>
<View className='avatar flex-item'>
<Image className='userinfo-avatar' src={avatarUrl}></Image>
</View>
<View className='user-info flex-item'>
<Text className='userinfo-nickname'>{nickName}</Text>
<Text className='edit'></Text>
</View>
</View>
)

View File

@ -1,38 +1,3 @@
.user {
width: 725px;
background: #ffffff;
padding: 30px 25px 30px 0;
margin: 15rpx 0 0 0;
border-top: 1px solid #eee;
border-bottom: 1px solid #dcdcdc;
box-shadow: 0 2px 5px #eeeeee;
.userinfo-avatar{
margin-top: 30px;
flex: 1;
display: inline-block;
width: 100px!important;
height: 100px!important;
border-radius: 80px;
}
.user-info{
flex: 5;
text-align: left;
text,div,span{
display: block;
}
.userinfo-nickname{
padding: 8px 0 10px 0;
font-size: 30px;
color: #818A8F;
}
.edit{
font-size: 30px;
color: #bababa;
line-height: 34px;
}
}
}
.my { .my {
padding: 30px; padding: 30px;
} }

View File

@ -1,16 +1,18 @@
import { connect } from '@tarojs/redux'; import { connect } from '@tarojs/redux';
import { AtList, AtListItem } from 'taro-ui';
import Taro, { Component, Config } from '@tarojs/taro'; import Taro, { Component, Config } from '@tarojs/taro';
import { View, Text, Image } from '@tarojs/components'; import { View } from '@tarojs/components';
import coinKit from '../../utils/coin-kit';
import { mapDefaultProps } from '../../models/utils';
import defaultImage from '../../assets/images/logo.png'; import defaultImage from '../../assets/images/logo.png';
import { mapModelProps, mapModelActions } from '../../models/utils';
import './index.scss'; import './index.scss';
import { Actions } from './model';
import { MyIndexProps, MyState } from './type'; import { MyIndexProps, MyState } from './type';
import { UserInfo, AccountHeader, AccountList } from './components'
@connect(mapDefaultProps(My)) const PAGE_NAME = 'my'
@connect(mapModelProps(PAGE_NAME), mapModelActions(PAGE_NAME, Actions))
class My extends Component<MyIndexProps, MyState> { class My extends Component<MyIndexProps, MyState> {
config: Config = { config: Config = {
navigationBarTitleText: '个人中心', navigationBarTitleText: '个人中心',
@ -19,16 +21,14 @@ class My extends Component<MyIndexProps, MyState> {
state = { state = {
nickName: 'MiaoWoo', nickName: 'MiaoWoo',
avatarUrl: defaultImage, avatarUrl: defaultImage,
publicKey: '191864'
}
defaultProps = {
accounts: []
} }
onPullDownRefresh() { onPullDownRefresh() {
const { dispatch } = this.props; this.props[Actions.getAccounts](this.state.publicKey)
if (dispatch) {
dispatch({
type: 'my/getAccounts',
playload: '02078AC7F16BAF88F9A6F8FA05D5C9F697596402D9EB774A36C74E52A3470EA85B'
})
}
} }
componentDidMount() { componentDidMount() {
@ -40,63 +40,13 @@ class My extends Component<MyIndexProps, MyState> {
nickName, nickName,
avatarUrl avatarUrl
} = this.state; } = this.state;
const accounts = this.props.accounts.map(a => {
return <AtListItem
key={a.Num}
hasBorder={false}
title={`${a.Num}(${a.Name})`}
note={`${coinKit.toNumber(a.Value)}`}
iconInfo={{
size: 20,
color: 'green',
value: 'credit-card',
}}
extraThumb={defaultImage}
/>
})
return ( return (
<View className='page'> <View className='page'>
<View className='user flex-wrp'> <UserInfo nickName={nickName} avatarUrl={avatarUrl} />
<View className='avatar flex-item'>
<Image className='userinfo-avatar' src={avatarUrl}></Image>
</View>
<View className='user-info flex-item'>
<Text className='userinfo-nickname'>{nickName}</Text>
<Text className='edit'></Text>
</View>
</View>
<View className='my'> <View className='my'>
<AtList hasBorder={false}> <AccountHeader />
<AtListItem <View className='account' />
hasBorder={false} <AccountList accounts={this.props.accounts} defaultImage={defaultImage} />
title='创建/绑定私钥'
iconInfo={{
size: 20,
color: 'red',
value: 'lock',
}} />
<AtListItem
hasBorder={false}
title='创建账户'
iconInfo={{
size: 20,
color: 'green',
value: 'credit-card',
}} />
</AtList>
<View className='account'>
<AtList >
<AtListItem
hasBorder={false}
title='账户列表'
iconInfo={{
size: 20,
color: 'blue',
value: 'numbered-list',
}} />
{accounts}
</AtList>
</View>
</View> </View>
</View> </View>
) )

View File

@ -3,22 +3,29 @@ import { DefaultModel } from '../../models/types';
import { getAccounts } from './service'; import { getAccounts } from './service';
import { MyProps } from './type'; import { MyProps } from './type';
let Actions = {
getAccounts: 'getAccounts'
}
export default { export default {
namespace: 'my', namespace: 'my',
state: { state: {
accounts: [] accounts: []
}, },
effects: { effects: {
*['getAccounts']({ playload }, { call, put }) { *[Actions.getAccounts]({ payload }, { call, put }) {
let accounts = yield call(getAccounts, playload); let accounts = yield call(getAccounts, payload);
yield put({ yield put({
type: "setState", playload: accounts type: "setState",
payload: accounts
}); });
} }
}, },
reducers: { reducers: {
setState(state: MyProps, { playload }) { setState(state: MyProps, { payload }) {
return { ...state, ...playload } return { ...state, ...payload }
} }
} }
} as DefaultModel<MyProps> } as DefaultModel<MyProps>
export { Actions }

View File

@ -1,15 +1,24 @@
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import { getAccountListByKey } from '../../rpc/tera'; import { getAccountListByKey, getAccount } from '../../rpc/tera';
async function getAccounts(key: string) { async function getAccounts(key: string) {
console.log(key)
try {
if (!key) { return { accounts: [] } }
Taro.showLoading({ Taro.showLoading({
title: '加载中...' title: '加载中...'
}) })
if (/[0-9]*/.test(key)) {
let account = await getAccount(Number(key));
key = account.PubKeyStr;
}
let result = await getAccountListByKey(key); let result = await getAccountListByKey(key);
Taro.hideLoading()
Taro.stopPullDownRefresh()
return { accounts: result }; return { accounts: result };
} finally {
Taro.hideLoading();
Taro.stopPullDownRefresh();
}
} }
export { getAccounts } export { getAccounts }

17
src/rpc/socket.ts Normal file
View File

@ -0,0 +1,17 @@
import io from 'weapp.socket.io'
const client = io('https://tera-ws.miaowoo.cc/web', {
path: '/ws',
transports: ['websocket'],
autoConnect: false
})
client.on('connect', () => {
console.log('connect')
})
client.on('message', (msg) => {
console.log(msg)
})
export default client

613
yarn.lock

File diff suppressed because it is too large Load Diff