Commit 54ef480e by zeven

基本代码重构完成

parent f07c3001
module.exports = {
root: true,
extends: '@react-native-community',
rules: {
"react-native/no-inline-styles": 0,
"no-eval": 0
}
};
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow strict-local
*/
import React from 'react';
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar,
} from 'react-native';
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
const App: () => React$Node = () => {
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<Header />
{global.HermesInternal == null ? null : (
<View style={styles.engine}>
<Text style={styles.footer}>Engine: Hermes</Text>
</View>
)}
<View style={styles.body}>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>Step One</Text>
<Text style={styles.sectionDescription}>
Edit <Text style={styles.highlight}>App.js</Text> to change this
screen and then come back to see your edits.
</Text>
</View>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>See Your Changes</Text>
<Text style={styles.sectionDescription}>
<ReloadInstructions />
</Text>
</View>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>Debug</Text>
<Text style={styles.sectionDescription}>
<DebugInstructions />
</Text>
</View>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>Learn More</Text>
<Text style={styles.sectionDescription}>
Read the docs to discover what to do next:
</Text>
</View>
<LearnMoreLinks />
</View>
</ScrollView>
</SafeAreaView>
</>
);
};
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,
},
engine: {
position: 'absolute',
right: 0,
},
body: {
backgroundColor: Colors.white,
},
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
color: Colors.black,
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
color: Colors.dark,
},
highlight: {
fontWeight: '700',
},
footer: {
color: Colors.dark,
fontSize: 12,
fontWeight: '600',
padding: 4,
paddingRight: 12,
textAlign: 'right',
},
});
export default App;
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
['@babel/plugin-proposal-decorators', {legacy: true}],
['import', {libraryName: 'antd-mobile'}],
],
};
......@@ -3,7 +3,12 @@
*/
import {AppRegistry} from 'react-native';
import App from './App';
import App from './src/App';
import {name as appName} from './app.json';
console.ignoredYellowBox = [
'Please update the following components: t',
'Require cycle: node_modules/redux-saga',
];
AppRegistry.registerComponent(appName, () => App);
{
"name": "ZmFaceCounter",
"name": "zm-face-counter",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
"lint": "eslint --ext .js index.js src",
"apk": "cd android && ./gradlew assembleRelease && cp ./app/build/outputs/apk/release/app-release.apk ../release.apk"
},
"pre-commit": [
"lint"
],
"dependencies": {
"@react-native-community/async-storage": "1.11.0",
"antd-mobile-rn": "^2.3.3",
"axios": "0.19.2",
"dva-core": "2.0.2",
"moment": "2.27.0",
"qs": "6.9.4",
"react": "16.11.0",
"react-native": "0.62.2"
"react-native": "0.62.2",
"react-native-keyevent": "0.2.8",
"react-native-qrcode-svg": "6.0.6",
"react-native-svg": "12.1.0",
"react-native-swiper": "1.6.0",
"react-native-vector-icons": "6.6.0",
"react-redux": "7.2.0",
"redux": "4.0.5",
"socket.io-client": "2.0.4",
"throttle-debounce": "2.2.1"
},
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/runtime": "^7.6.2",
"@react-native-community/eslint-config": "^0.0.5",
"babel-jest": "^24.9.0",
"eslint": "^6.5.1",
"jest": "^24.9.0",
"metro-react-native-babel-preset": "^0.58.0",
"@babel/core": "7.6.2",
"@babel/plugin-proposal-decorators": "7.10.3",
"@babel/runtime": "7.6.2",
"@react-native-community/eslint-config": "0.0.5",
"babel-jest": "24.9.0",
"babel-plugin-import": "1.13.0",
"babel-plugin-transform-decorators-legacy": "1.3.5",
"eslint": "6.5.1",
"jest": "24.9.0",
"metro-react-native-babel-preset": "0.58.0",
"pre-commit": "1.2.2",
"react-test-renderer": "16.11.0"
},
"jest": {
......
import React from 'react';
import {View, Dimensions} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import {connect} from 'react-redux';
import qs from 'qs';
import axios from 'axios';
import io from 'socket.io-client';
import Toast from './components/Toast';
import router from './router';
import models from './models';
import dva from './utils/dva';
import Restart from './utils/Restart';
import {counterInterval} from './utils/authInterval';
import {host} from './utils/config';
const {width: _width, height: _height} = Dimensions.get('window');
// axios.defaults.baseURL = host; // 配置接口地址
window.qs = qs;
window.axios = axios;
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded;charset=UTF-8';
axios.interceptors.request.use(config => {
// 请求拦截器,自动添加token
if (window.auth) {
// 门店Token
config.headers.common.Authorization = `Bearer ${window.auth.token}`;
}
return config;
});
axios.interceptors.response.use(res => {
// 请求拦截器,自动添加token
if (res.data.code < 0) {
Toast.fail(res.data.msg);
}
return res;
});
const dvaApp = dva({
models,
onError(e) {
console.warn(e);
},
});
const delay = t => new Promise(resolve => setTimeout(resolve, t));
window.retryTimeout = 15000; // 重试间隔时间
@connect()
class App extends React.Component {
state = {
ready: false,
curRoute: 'auth',
};
async UNSAFE_componentWillMount() {
window.dispatch = this.props.dispatch;
const HOST = await AsyncStorage.getItem('HOST');
axios.defaults.baseURL = HOST || host; // 配置接口地址
const auth = await AsyncStorage.getItem('auth');
this.device = await AsyncStorage.getItem('login'); // 设备类型
if (auth) {
await this.refresh();
} else {
window.socket =
window.socket ||
io(axios.defaults.baseURL, {query: {client: this.device}});
this.listen();
}
this.setState({ready: true});
}
listen = () => {
const {dispatch} = this.props;
window.socket.on('connect', () => {
window.socketDisconnected = false; // 重新连接
dispatch({type: 'admin/setSocket', socket: window.socket.id});
});
window.socket.on('disconnect', () => {
window.socket.connect();
});
if (!window.socket.hasListeners('restart')) {
window.socket.on('restart', Restart.restartApp);
}
if (!window.socket.hasListeners('version')) {
window.socket.on('version', () => {
dispatch({type: 'admin/version'});
});
}
};
refresh = async () => {
const {dispatch} = this.props;
const res = await dispatch({type: 'admin/auth'});
if (res && res.code === 1) {
// 门店助手授权登录成功
if (window.socket) {
window.socket.disconnect();
}
if (window.authInterval) {
clearInterval(window.authInterval);
}
if (window.socketInterval) {
clearInterval(window.socketInterval);
}
if (this.device === 'counter') {
// 收银设备
let curRoute = 'home';
if (_height > _width) {
curRoute = 'vertical';
}
await this.setState({curRoute});
dispatch({type: 'admin/version'});
dispatch({type: 'goods/getBags'});
} else if (this.device === 'face') {
// 人脸设备
await this.setState({curRoute: 'face'});
}
await counterInterval(dispatch, res.data.expiresIn);
this.listen();
} else {
await delay(window.retryTimeout);
await this.refresh();
}
};
render() {
const {ready, curRoute} = this.state;
const route = Object.keys(router).filter(name => curRoute === name)[0];
const Component = router[route];
return ready ? <Component route={curRoute} /> : <View />;
}
}
export default dvaApp.start(<App />);
import React from 'react';
import {View, Text} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import Touch from '../components/Touch';
import {colors} from '../utils/common';
import NP from '../utils/np';
const itemFontsize = 18;
export default class GoodsItem extends React.Component {
render() {
let {item, index, numRemove, numAdd, numChange, removeIndex} = this.props;
return (
<View
style={{flexDirection: 'row', alignItems: 'center', height: 55}}
key={index}>
<Text
style={{
width: 38,
fontSize: itemFontsize,
color: colors.textXSActive,
paddingLeft: 8,
}}>
{index + 1}
</Text>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
}}>
<Text
numberOfLines={1}
style={{
flex: 0.4,
fontSize: itemFontsize,
color: item.weight ? colors.textXSActive : '#FC4000',
}}>
{item.spec ? `${item.name}(${item.spec})` : item.name}
</Text>
{item.price ? (
<View
style={{
flex: 0.25,
justifyContent: 'flex-end',
alignItems: 'flex-end',
flexDirection: 'row',
}}>
<Text
style={{
fontSize: itemFontsize - 2,
textDecorationLine: 'line-through',
}}>
{NP.round(item.prePrice, 2).toFixed(2)}/
<Text
style={{
fontSize: itemFontsize - 2,
}}>
{item.unit}
</Text>
</Text>
<Text
style={{fontSize: itemFontsize, color: colors.textXSActive}}>
{NP.round(item.price, 2).toFixed(2)}/
<Text
style={{
fontSize: itemFontsize,
}}>
{item.unit}
</Text>
</Text>
</View>
) : (
<Text
style={{
flex: 0.25,
fontSize: itemFontsize,
textAlign: 'right',
color: colors.textXSActive,
}}>
{NP.round(item.prePrice, 2).toFixed(2)}/{item.unit}
</Text>
)}
<View
style={{
flex: 0.2,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
}}>
{item.numChange ? (
<Touch
style={{
height: 50,
justifyContent: 'center',
alignItems: 'center',
}}
onPress={() => numRemove(item.num, index)}>
<Icon
name="ios-remove-circle"
color={item.num === 1 ? '#909090' : '#00c670'}
size={30}
/>
</Touch>
) : (
<View style={{height: 50, width: 25}} />
)}
<Touch
style={{
width: 40,
height: 50,
justifyContent: 'center',
alignItems: 'center',
}}
onPress={() => item.numChange && numChange(index)}>
<Text
style={{
fontSize: itemFontsize,
minWidth: 30,
textAlign: 'center',
color: colors.textXSActive,
}}>
{item.num}
</Text>
</Touch>
{item.numChange ? (
<Touch
style={{
height: 50,
justifyContent: 'center',
alignItems: 'center',
}}
onPress={() => numAdd(item.num, index)}>
<Icon name="ios-add-circle" color="#00c670" size={30} />
</Touch>
) : (
<View style={{height: 50, width: 25}} />
)}
</View>
{item.price ? (
<Text
style={{
fontSize: itemFontsize,
flex: 0.15,
textAlign: 'right',
color: colors.textXSActive,
}}>
{NP.round(item.price * item.num, 2).toFixed(2)}
</Text>
) : (
<Text
style={{
fontSize: itemFontsize,
flex: 0.15,
textAlign: 'right',
color: colors.textXSActive,
}}>
{NP.round(item.prePrice * item.num, 2).toFixed(2)}
</Text>
)}
</View>
<Touch
onPress={() => removeIndex(index)}
style={{width: 50, alignItems: 'center'}}>
<View
style={{
height: 60,
width: 40,
justifyContent: 'center',
alignItems: 'center',
}}>
<Icon name="ios-close-circle" size={28} color={colors.bg} />
</View>
</Touch>
</View>
);
}
}
import React from 'react';
import {View, TextInput, Text} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import {colors, font} from '../utils/common';
import Touch from './Touch';
import Modal from './Modal';
import ModalStyles from './Modal/styles';
const mStyles = {
...ModalStyles,
innerContainer: {
...ModalStyles.innerContainer,
width: 777,
},
header: {
...ModalStyles.header,
fontSize: font.title,
},
};
const keyboard = [
{up: '1', down: '1'},
{up: '2', down: '2'},
{up: '3', down: '3'},
{up: '4', down: '4'},
{up: '5', down: '5'},
{up: '6', down: '6'},
{up: '7', down: '7'},
{up: '8', down: '8'},
{up: '9', down: '9'},
{up: '0', down: '0'},
{up: 'Q', down: 'q'},
{up: 'W', down: 'w'},
{up: 'E', down: 'e'},
{up: 'R', down: 'r'},
{up: 'T', down: 't'},
{up: 'Y', down: 'y'},
{up: 'U', down: 'u'},
{up: 'I', down: 'i'},
{up: 'O', down: 'o'},
{up: 'P', down: 'p'},
{up: 'A', down: 'a'},
{up: 'S', down: 's'},
{up: 'D', down: 'd'},
{up: 'F', down: 'f'},
{up: 'G', down: 'g'},
{up: 'H', down: 'h'},
{up: 'J', down: 'j'},
{up: 'K', down: 'k'},
{up: 'L', down: 'l'},
{up: 'tran', down: 'tran'},
{up: 'Z', down: 'z'},
{up: 'X', down: 'x'},
{up: 'C', down: 'c'},
{up: 'V', down: 'v'},
{up: 'B', down: 'b'},
{up: 'N', down: 'n'},
{up: 'M', down: 'm'},
{up: 'del', down: 'del'},
];
export default class KeyboardModal extends React.Component {
constructor(props) {
super(props);
this.state = {
caseUp: false,
value: '',
};
}
getKeyboard = () => {
let {caseUp} = this.state;
let keyboard1 = keyboard.slice(0, 10);
let keyboard2 = keyboard.slice(10, 20);
let keyboard3 = keyboard.slice(20, 29);
let keyboard4 = keyboard.slice(29, 38);
return (
<View style={{width: 667, marginLeft: 40}}>
<View style={styles.keyRow}>
{keyboard1.map((item, index) => (
<Touch
style={styles.keyTouch}
key={index}
onPress={() => this.pressKey(index)}>
<Text style={styles.keyUnit}>{item.up}</Text>
</Touch>
))}
</View>
<View style={styles.keyRow}>
{keyboard2.map((item, index) => (
<Touch
style={styles.keyTouch}
key={index}
onPress={() => this.pressKey(index + 10)}>
<Text style={styles.keyUnit}>{caseUp ? item.up : item.down}</Text>
</Touch>
))}
</View>
<View style={styles.keyRow}>
{keyboard3.map((item, index) => (
<Touch
style={styles.keyTouch}
key={index}
onPress={() => this.pressKey(index + 20)}>
<Text style={styles.keyUnit}>{caseUp ? item.up : item.down}</Text>
</Touch>
))}
</View>
<View style={styles.keyRow}>
{keyboard4.map((item, index) => {
if (index === 0) {
return (
<Touch
style={[styles.keyTouch, {width: 60, marginRight: 15}]}
key={index}
onPress={() => this.pressKey(index + 29)}>
<Icon
name={caseUp ? 'md-arrow-round-down' : 'md-arrow-round-up'}
size={30}
/>
</Touch>
);
} else if (index === 8) {
return (
<Touch
style={[styles.keyTouch, {width: 60, marginLeft: 15}]}
key={index}
onPress={() => this.pressKey(index + 29)}>
<Icon name="md-backspace" size={30} />
</Touch>
);
}
return (
<Touch
style={styles.keyTouch}
key={index}
onPress={() => this.pressKey(index + 29)}>
<Text style={styles.keyUnit}>
{caseUp ? item.up : item.down}
</Text>
</Touch>
);
})}
</View>
</View>
);
};
pressKey = index => {
let {value} = this.state;
if (index === 29) {
this.setState({
caseUp: !this.state.caseUp,
});
} else if (index === 37) {
value = value.substring(0, value.length - 1);
this.setState({value});
} else {
value += this.state.caseUp ? keyboard[index].up : keyboard[index].down;
this.setState({value});
}
};
render() {
const {title, visible, onSubmit, onClose} = this.props;
const {value} = this.state;
return (
<Modal
styles={mStyles}
visible={visible}
transparent
maskClosable
onClose={onClose}
title={title}>
<View
style={{
borderTopColor: '#cccccc',
borderTopWidth: 1,
paddingVertical: 20,
}}>
<View
style={{
width: 777,
height: 60,
justifyContent: 'center',
position: 'relative',
}}>
<TextInput
autoFocus
value={value}
style={{width: 667, fontSize: font.textActive, marginLeft: 40}}
onSubmitEditing={() => onSubmit(value)}
/>
<Touch
onPress={() => this.setState({value: ''})}
style={{position: 'absolute', right: 82}}>
<Icon name="ios-close" size={40} color="#D1D1D1" />
</Touch>
</View>
{this.getKeyboard()}
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
marginTop: 30,
}}>
<Touch
onPress={onClose}
style={{
width: 100,
height: 50,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: '#cccccc',
marginRight: 30,
borderRadius: 5,
}}>
<Text style={{color: '#2B2B2B', fontSize: font.textS}}>取消</Text>
</Touch>
<Touch
onPress={() => onSubmit(value)}
style={{
width: 100,
height: 50,
backgroundColor: '#E3430F',
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: '#E3430F',
borderRadius: 5,
}}>
<Text style={{color: '#ffffff', fontSize: font.textS}}>确定</Text>
</Touch>
</View>
</View>
</Modal>
);
}
}
const styles = {
keyRow: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: 15,
},
keyTouch: {
width: 60,
height: 60,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: '#cccccc',
borderRadius: 5,
marginHorizontal: 5,
},
keyUnit: {
fontSize: font.textActive,
color: colors.text,
},
};
import React from 'react';
import {Image, PanResponder, View, Text} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import {connect} from 'react-redux';
import moment from 'moment';
import {width} from '../utils/screen';
import {colors} from '../utils/common';
import Modal from './Modal';
import Toast from './Toast';
import Touch from './Touch';
import {counterInterval} from '../utils/authInterval';
import {switchQr, switchEnv} from '../utils/switchHost';
const weekdays = {
0: '周日',
1: '周一',
2: '周二',
3: '周三',
4: '周四',
5: '周五',
6: '周六',
};
@connect(({app}) => ({app}))
class Layout extends React.Component {
state = {
count: window.defaultCount,
contact: '',
maskVisible: true,
visibleActive: false,
dateInfo: `${moment().format('YYYY-M-D HH:mm')} ${
weekdays[Number(moment().day())]
}`,
};
async UNSAFE_componentWillMount() {
window.count = window.defaultCount;
window.login = this.counterLogin;
this.panResponder = PanResponder.create({
// 要求成为响应者:
onStartShouldSetPanResponder: this.handleStartShouldSetPanResponder,
});
let contact = await AsyncStorage.getItem('CONTACT');
let lock = await AsyncStorage.getItem('settingLock');
if (lock) {
this.props.dispatch({type: 'app/lock', lock});
}
this.setState({contact});
}
componentDidMount() {
this.timer = setInterval(() => {
this.setState({
dateInfo: `${moment().format('YYYY-M-D HH:mm')} ${
weekdays[Number(moment().day())]
}`,
});
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
handleStartShouldSetPanResponder = () => {
window.count = window.defaultCount;
};
showCounterLogin = async () => {
const key = await AsyncStorage.getItem('KEY');
Modal.prompt(
'门店授权',
'仲马购门店收银台授权认证',
[{text: '取消'}, {text: '登录', onPress: this.counterLogin}],
// (login, password) => console.log(`login: ${login}, password: ${password}`),
'login-password',
key,
['请填写门店标识', '请填写门店密钥'],
);
};
loginError = async msg => {
Toast.fail(msg, 1);
};
counterLogin = async (key, secret) => {
if (!key) {
await this.loginError('请输入门店标识');
return;
}
if (!secret) {
await this.loginError('请输入门店密钥');
return;
}
await Toast.loading('授权认证中');
const action = {type: 'admin/auth', key, secret, login: 'counter'};
const {dispatch} = this.props;
const res = await dispatch(action);
if (res.code === 1) {
Toast.success('授权认证成功,正在重启应用...', 2, async () => {
await counterInterval(dispatch, res.data.expiresIn, true);
});
}
};
stepOne = async () => {
await this.setState({
visibleActive: true,
});
setTimeout(() => {
this.setState({
visibleActive: false,
});
}, 3000);
};
stepTwo = () => {
let {visibleActive} = this.state;
if (visibleActive) {
this.setState({
maskVisible: false,
});
setTimeout(() => {
this.setState({
visibleActive: false,
maskVisible: true,
});
}, 5000);
}
};
render() {
const {children, app} = this.props;
let {contact, maskVisible, dateInfo, visibleActive} = this.state;
contact = contact || '未授权';
return (
<View
{...this.panResponder.panHandlers}
style={{flex: 1, backgroundColor: '#333'}}>
<View style={styles.navBar}>
<View style={{flex: 1, flexDirection: 'row', alignItems: 'center'}}>
<Image
source={require('../assets/zmgo_icon.png')}
style={styles.navLogo}
/>
<View
style={{
justifyContent: 'flex-end',
height: 80,
flex: 1,
alignItems: 'center',
}}>
<View
style={{
width: 200,
height: 40,
backgroundColor: '#000000',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 1,
}}>
<Text style={{color: '#ffffff', fontSize: 16}}>{dateInfo}</Text>
</View>
</View>
</View>
<Touch
onPress={!app.lock && this.showCounterLogin}
style={{alignItems: 'center'}}>
<Image
style={{width: 325, height: 36, resizeMode: 'contain'}}
source={require('../assets/zmgo_title.png')}
/>
</Touch>
<View style={styles.navRight}>
<Touch onPress={!app.lock && switchQr}>
<Image
source={require('../assets/phone_icon.png')}
style={{
width: 36,
height: 36,
marginRight: 5,
resizeMode: 'contain',
}}
/>
</Touch>
<Touch onPress={!app.lock && switchEnv}>
<Text
style={{
color: '#F5AB61',
fontSize: 32,
fontWeight: 'bold',
marginRight: 20,
}}>
{contact}
</Text>
</Touch>
</View>
</View>
{maskVisible ? (
<View style={styles.navMask}>
<Touch
onPress={() => this.stepOne()}
style={{
width: 150,
height: 80,
backgroundColor: visibleActive ? colors.bg : 'transparent',
}}>
<View />
</Touch>
<View style={{flex: 1, alignItems: 'center'}} />
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
}}>
<Touch
onPress={() => this.stepTwo()}
style={{width: 50, height: 80}}>
<View />
</Touch>
<View style={{opacity: 0}}>
<Text
style={{
color: '#F5AB61',
fontSize: 32,
fontWeight: 'bold',
marginRight: 20,
}}>
{contact}
</Text>
</View>
</View>
</View>
) : (
<View style={{display: 'none'}} />
)}
<View style={{flexDirection: 'row', flex: 1, zIndex: 9}}>
<View style={{flex: 1, margin: 10}}>{children}</View>
</View>
</View>
);
}
}
const styles = {
navMask: {
width,
height: 80,
position: 'absolute',
top: 0,
left: 0,
backgroundColor: 'transparent',
alignItems: 'center',
flexDirection: 'row',
},
navBar: {
width,
height: 80,
backgroundColor: colors.bg,
alignItems: 'center',
flexDirection: 'row',
},
navLogo: {
width: 81,
height: 35,
marginLeft: 15,
},
navTextL: {
color: '#ffffff',
marginLeft: 10,
fontSize: 28,
},
navRight: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
},
navTextR: {
color: '#ffffff',
marginRight: 20,
fontSize: 20,
},
footer: {
width: width - 20,
height: 50,
borderRadius: 3,
flexDirection: 'row',
backgroundColor: 'white',
margin: 10,
marginTop: 0,
},
contLine: {
width: 20,
backgroundColor: colors.bg,
},
navTime: {
fontSize: 16,
color: '#ffffff',
},
};
export default Layout;
import React from 'react';
import {Text, ScrollView} from 'react-native';
import Modal from 'antd-mobile-rn/lib/modal/Modal.native';
// import styles from './styles';
export type AlertButtonType = {
text: string,
onPress?: () => void,
style?: any,
};
export interface AlertContainerProps {
title: string;
content: any;
actions: Array<AlertButtonType>;
onAnimationEnd?: (visible: boolean) => void;
}
export default class AlertContainer extends React.Component<
AlertContainerProps,
any,
> {
constructor(props) {
super(props);
this.state = {
visible: true,
};
}
onClose = () => {
this.setState({
visible: false,
});
};
render() {
const {title, actions, content, onAnimationEnd} = this.props;
const footer = actions.map(button => {
const orginPress = button.onPress || function() {};
button.onPress = () => {
const res = orginPress();
if (res && res.then) {
res.then(() => {
this.onClose();
});
} else {
this.onClose();
}
};
return button;
});
return (
<Modal
// styles={styles}
bodyStyle={{alignItems: 'center'}}
transparent
title={title}
visible={this.state.visible}
footer={footer}
onAnimationEnd={onAnimationEnd}>
<ScrollView>
<Text>{content}</Text>
</ScrollView>
</Modal>
);
}
}
import React from 'react';
import Modal from 'antd-mobile-rn/lib/modal/Modal.native';
import modalStyle from 'antd-mobile-rn/lib/modal/style/index.native';
import styles from './styles';
const operationStyles = {
...styles,
innerContainer: {
...styles.innerContainer,
width: 600,
},
buttonText: {
...styles.buttonText,
alignSelf: 'center',
fontSize: 35,
},
};
export type OperationButtonType = {
text: string,
onPress?: () => void,
style?: any,
};
export interface OperationContainerProps {
actions: Array<OperationButtonType>;
onAnimationEnd?: (visible: boolean) => void;
}
export default class OperationContainer extends React.Component<
OperationContainerProps,
any,
> {
constructor(props) {
super(props);
this.state = {
visible: true,
};
}
onClose = () => {
this.setState({
visible: false,
});
};
render() {
const {actions, onAnimationEnd} = this.props;
const footer = actions.map(button => {
const orginPress = button.onPress || function() {};
button.onPress = () => {
const res = orginPress();
if (res && res.then) {
res.then(() => {
this.onClose();
});
} else {
this.onClose();
}
};
return button;
});
return (
<Modal
operation
transparent
maskClosable
styles={operationStyles}
visible={this.state.visible}
onClose={this.onClose}
onAnimationEnd={onAnimationEnd}
style={modalStyle.operationContainer}
bodyStyle={modalStyle.operationBody}
footer={footer}
/>
);
}
}
/* tslint:disable:jsx-no-multiline-js */
import React from 'react';
import {
View,
Text,
TextInput,
StyleSheet,
KeyboardAvoidingView,
} from 'react-native';
import Modal from 'antd-mobile-rn/lib/modal/Modal.native';
import promptStyle, {
IPromptStyle,
} from 'antd-mobile-rn/lib/modal/style/prompt.native';
import ModalStyles from './styles';
const styles = {
...promptStyle,
message: {
...promptStyle.message,
fontSize: 35,
marginBottom: 30,
},
input: {
...promptStyle.input,
paddingLeft: 50,
height: 80,
fontSize: 30,
},
inputLast: {
...promptStyle.inputLast,
marginBottom: 40,
},
};
export type ButtonType = {
text: string,
onPress?: () => void,
style?: any,
};
export interface PropmptContainerProps {
title: string;
type?: 'default' | 'login-password' | 'secure-text';
message?: string | null;
defaultValue?: string;
actions: Array<ButtonType>;
onAnimationEnd?: (visible: boolean) => void;
styles?: IPromptStyle;
placeholders?: string[];
}
const promptStyles = StyleSheet.create(styles);
export default class PropmptContainer extends React.Component<
PropmptContainerProps,
any,
> {
static defaultProps = {
type: 'default',
defaultValue: '',
styles: promptStyles,
};
constructor(props) {
super(props);
this.state = {
visible: true,
text: props.defaultValue,
password: props.type === 'secure-text' ? props.defaultValue : '',
};
}
onClose = () => {
this.setState({
visible: false,
});
};
onChangeText(type, value) {
this.setState({
[type]: value,
});
}
render() {
const {
title,
onAnimationEnd,
message,
type,
actions,
placeholders,
} = this.props;
// const styles = this.props.styles;
const {text, password} = this.state;
const getArgs = function(func) {
if (type === 'login-password') {
return func.apply(this, [text, password]);
} else if (type === 'secure-text') {
return func.apply(this, [password]);
}
return func.apply(this, [text]);
};
let callbacks;
if (typeof actions === 'function') {
callbacks = [
{text: '取消', style: 'cancel'},
{text: '确定', onPress: () => getArgs(actions)},
];
} else {
callbacks = actions.map(item => {
return {
text: item.text,
onPress: () => {
if (item.onPress) {
return getArgs(item.onPress);
}
},
style: item.style || {},
};
});
}
const footer = callbacks.map(button => {
const orginPress = button.onPress || function() {};
button.onPress = () => {
const res = orginPress();
if (res && res.then) {
res.then(() => {
this.onClose();
});
} else {
this.onClose();
}
};
return button;
});
const firstStyle = [styles.inputWrapper];
const lastStyle = [styles.inputWrapper];
if (type === 'login-password') {
firstStyle.push(styles.inputFirst);
lastStyle.push(styles.inputLast);
} else if (type === 'secure-text') {
lastStyle.push(styles.inputFirst);
lastStyle.push(styles.inputLast);
} else {
firstStyle.push(styles.inputFirst);
firstStyle.push(styles.inputLast);
}
return (
<Modal
styles={ModalStyles}
transparent
title={title}
visible={this.state.visible}
onClose={this.onClose}
footer={footer}
onAnimationEnd={onAnimationEnd}>
<KeyboardAvoidingView behavior="padding">
{message && message.length && (
<Text style={styles.message}>{message}</Text>
)}
<View style={styles.inputGroup}>
{type !== 'secure-text' && (
<View style={firstStyle}>
<TextInput
autoFocus
onChangeText={value => {
this.onChangeText('text', value);
}}
value={this.state.text}
style={styles.input}
underlineColorAndroid="transparent"
placeholder={placeholders[0]}
placeholderTextColor="#aaa"
/>
</View>
)}
{(type === 'secure-text' || type === 'login-password') && (
<View style={lastStyle}>
<TextInput
autoFocus
secureTextEntry
onChangeText={value => {
this.onChangeText('password', value);
}}
value={this.state.password}
style={styles.input}
underlineColorAndroid="transparent"
placeholder={placeholders[1]}
placeholderTextColor="#aaa"
/>
</View>
)}
</View>
</KeyboardAvoidingView>
</Modal>
);
}
}
import React from 'react';
import topView from 'rn-topview';
import AlertContainer from './AlertContainer';
import styles from './styles';
export default function a(title, content, actions = [{text: '确定'}]) {
const onAnimationEnd = visible => {
if (!visible) {
topView.remove();
}
};
topView.set(
<AlertContainer
styles={styles}
title={title}
content={content}
actions={actions}
onAnimationEnd={onAnimationEnd}
/>,
);
}
import React from 'react';
import Modal from 'antd-mobile-rn/lib/modal/Modal.native';
import styles from './styles';
import alert from './alert';
import prompt from './prompt';
import operation from './operation';
export default class ModalComp extends React.Component {
static alert = alert;
static prompt = prompt;
static operation = operation;
render() {
return <Modal styles={styles} {...this.props} />;
}
}
import React from 'react';
import topView from 'rn-topview';
import OperationContainer from './OperationContainer';
export default function a(...args) {
const actions = args[0] || [{text: '确定'}];
const onAnimationEnd = visible => {
if (!visible) {
topView.remove();
}
};
topView.set(
<OperationContainer actions={actions} onAnimationEnd={onAnimationEnd} />,
);
}
import React from 'react';
import topView from 'rn-topview';
import PromptContainer from './PromptContainer';
export default function prompt(
title,
message,
callbackOrActions,
type = 'default',
defaultValue = '',
placeholders = ['', ''],
) {
if (!callbackOrActions) {
console.error('Must specify callbackOrActions');
return;
}
const onAnimationEnd = visible => {
if (!visible) {
topView.remove();
}
};
topView.set(
<PromptContainer
title={title}
message={message}
actions={callbackOrActions}
type={type}
defaultValue={defaultValue}
onAnimationEnd={onAnimationEnd}
placeholders={placeholders}
/>,
);
}
import ModalStyle from 'antd-mobile-rn/lib/modal/style/index.native';
import {width} from '../../utils/screen';
const styles = {
...ModalStyle,
innerContainer: {
...ModalStyle.innerContainer,
width: width * 0.7,
},
header: {
...ModalStyle.header,
fontSize: 45,
marginBottom: 20,
},
buttonWrapV: {
...ModalStyle.buttonWrapV,
height: 80,
},
buttonWrapH: {
...ModalStyle.buttonWrapH,
height: 80,
},
buttonText: {
...ModalStyle.buttonText,
fontSize: 35,
},
};
export default styles;
import React from 'react';
import {View, Text} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import {colors, font} from '../utils/common';
import Touch from './Touch';
import Modal from './Modal';
import ModalStyles from './Modal/styles';
const mStyles = {
...ModalStyles,
innerContainer: {
...ModalStyles.innerContainer,
width: 580,
},
header: {
...ModalStyles.header,
fontSize: font.title,
},
};
export default class KeyboardModal extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
clickDot: true,
};
}
getKeyboard = () => {
const rows = [];
let items = [];
const {dot} = this.props;
for (let i = 1; i <= 12; i++) {
let unit;
if (i === 10 && !dot) {
unit = (
<Icon style={styles.keyUnit} name="ios-backspace-outline" size={60} />
);
} else if (i === 10 && dot) {
unit = <Text style={styles.keyUnit}>.</Text>;
} else if (i === 11) {
unit = <Text style={styles.keyUnit}>0</Text>;
} else if (i === 12) {
unit = <Icon style={styles.keyUnit} name="md-return-left" size={60} />;
} else {
unit = <Text style={styles.keyUnit}>{i}</Text>;
}
const item = (
<Touch style={styles.keyTouch} key={i} onPress={() => this.pressKey(i)}>
{unit}
</Touch>
);
items.push(item);
if (i % 3 === 0) {
rows.push(
<View style={styles.keyRow} key={i}>
{items}
</View>,
);
items = [];
}
}
return <View>{rows}</View>;
};
pressKey = index => {
let {value, clickDot} = this.state;
const {dot} = this.props;
if (index < 10) {
value += index;
} else if (index === 10 && !dot) {
value = value.substr(0, value.length - 1);
} else if (index === 10 && dot && clickDot) {
value += '.';
clickDot = false;
} else if (index === 11) {
value += 0;
} else if (index === 12) {
this.props.onSubmit(value);
this.handleClose();
return;
}
this.setState({value, clickDot});
};
handleClose = () => {
this.setState({value: '', clickDot: true});
this.props.onClose();
};
render() {
const {title, visible} = this.props;
const {value} = this.state;
return (
<Modal
styles={mStyles}
visible={visible}
transparent
maskClosable
onClose={this.handleClose}
title={title}>
<View
style={{
width: 550,
borderTopColor: '#cccccc',
borderTopWidth: 1,
paddingVertical: 20,
}}>
<Touch
style={{position: 'absolute', top: -70, right: -5}}
onPress={this.handleClose}
feedback={false}>
<Icon size={50} name="ios-close-circle-outline" />
</Touch>
<View
style={{
width: 550,
height: 70,
justifyContent: 'center',
position: 'relative',
}}>
<View
style={{
borderBottomWidth: 2,
borderBottomColor: '#ddd',
alignItems: 'center',
marginLeft: 20,
marginRight: 20,
}}>
<Text style={{color: 'gray', fontSize: 35, paddingBottom: 15}}>
{value || ' '}
</Text>
</View>
<Touch
onPress={() => this.setState({value: '', clickDot: true})}
style={{
position: 'absolute',
right: 30,
paddingLeft: 10,
paddingRight: 10,
}}>
<Icon name="ios-close" size={50} color="#D1D1D1" />
</Touch>
</View>
{this.getKeyboard()}
</View>
</Modal>
);
}
}
const styles = {
keyRow: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: 15,
},
keyTouch: {
width: 80,
height: 80,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: '#cccccc',
borderRadius: 5,
marginHorizontal: 15,
},
keyUnit: {
// fontSize: font.textActive,
fontSize: 25,
color: colors.text,
},
};
import React, {Component} from 'react';
import {Modal, View, Text, Image, TextInput} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import ModalStyles from './Modal/styles';
import {colors, font} from '../utils/common';
import Touch from './Touch';
const mStyles = {
...ModalStyles,
innerContainer: {
...ModalStyles.innerContainer,
// width: 380,
},
header: {
...ModalStyles.header,
fontSize: font.title,
},
};
class PhoneModal extends Component {
state = {
value: '',
};
getKeyboard = () => {
const rows = [];
let items = [];
for (let i = 1; i <= 9; i++) {
let unit;
unit = <Text style={styles.keyUnit}>{i}</Text>;
const item = (
<Touch style={styles.keyTouch} key={i} onPress={() => this.pressKey(i)}>
{unit}
</Touch>
);
items.push(item);
if (i % 3 === 0) {
rows.push(
<View style={styles.keyRow} key={i}>
{items}
</View>,
);
items = [];
}
}
return <View style={styles.NumberTop}>{rows}</View>;
};
pressKey = index => {
let {value} = this.state;
const {onSubmit} = this.props;
if (index < 10) {
value += index;
} else if (index === 11) {
value = value.substr(0, value.length - 1);
} else if (index === 12) {
this.setState({value: ''});
onSubmit(value);
return;
}
this.setState({value});
};
render() {
const {onClose, ...props} = this.props;
const {value} = this.state;
return (
<Modal styles={mStyles} {...props}>
<View style={styles.modal}>
<View style={styles.header}>
<View style={styles.title}>
<View style={styles.left}>
<Image
source={require('../assets/logo.png')}
style={styles.img}
/>
<Text style={styles.text}>安全验证手机号</Text>
</View>
<View style={styles.right}>
<Touch onPress={() => onClose()}>
<Icon name="md-close" color={'#FFFFFF'} size={50} />
</Touch>
</View>
</View>
<View style={styles.image}>
<Image
source={require('../assets/logo2.png')}
style={styles.logo}
/>
</View>
</View>
<View style={styles.container}>
<Text style={{color: 'red', fontSize: 45, marginBottom: 10}}>
请输入接收验证码的手机号
</Text>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<TextInput
style={{
fontSize: 35,
width: '80%',
textAlign: 'center',
padding: 30,
}}
placeholder="安全输入不留痕迹"
placeholderTextColor="lightgray"
editable={false}
value={value}
/>
<Touch
onPress={() => this.setState({value: ''})}
feddback={false}>
<Icon name="md-close" color={'#DCDCDC'} size={50} />
</Touch>
</View>
</View>
<View style={styles.footer}>
<View style={styles.footerLeft}>
{this.getKeyboard()}
<View style={styles.keyRowBottom}>
<Touch
style={styles.keyBottomTouch}
onPress={() => this.pressKey(0)}>
<Text style={styles.keyUnit}>0</Text>
</Touch>
</View>
</View>
<View style={styles.footerRight}>
<View style={styles.keyRowClose}>
<Touch
style={styles.keyTouchClose}
onPress={() => this.pressKey(11)}>
<Icon
style={styles.keyUnit}
name="ios-backspace-outline"
size={60}
/>
</Touch>
</View>
<View style={styles.keyRowSure}>
{/* <Touch style={styles.keyTouchSure} onPress={() => this.pressKey(12)}>*/}
{/* <Text style={styles.keyUnitClose}>确定</Text>*/}
{/* </Touch>*/}
{value.length < 1 ? (
<View style={styles.keyTouchSure}>
<Text style={styles.keyUnitClose}>确定</Text>
</View>
) : (
<Touch
style={styles.keyTouchOnSure}
onPress={() => this.pressKey(12)}>
<Text style={styles.keyUnitClose}>确定</Text>
</Touch>
)}
</View>
</View>
</View>
</View>
</Modal>
);
}
}
const styles = {
modal: {
height: '86%',
width: '90%',
marginLeft: '5%',
marginTop: '10%',
borderRadius: 20,
backgroundColor: '#cccccc',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
header: {
flex: 0.4,
backgroundColor: '#00CD66',
width: '100%',
flexDirection: 'column',
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
},
title: {
flexDirection: 'row',
justifyContent: 'space-between',
marginLeft: 30,
marginRight: 30,
marginTop: 10,
},
left: {
flexDirection: 'row',
alignItems: 'center',
},
right: {
flexDirection: 'row-reverse',
alignItems: 'center',
},
img: {
width: 80,
height: 80,
marginRight: 10,
resizeMode: 'contain',
},
image: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
logo: {
width: 150,
height: 150,
resizeMode: 'contain',
},
text: {
color: '#FFFFFF',
fontSize: 30,
},
container: {
flex: 0.2,
backgroundColor: '#FFFFFF',
width: '100%',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
footer: {
flex: 0.4,
width: '100%',
flexDirection: 'row',
backgroundColor: '#F5F5F5',
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
},
footerLeft: {
width: '75%',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
NumberTop: {
flex: 0.8,
},
keyRow: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
marginLeft: 20,
marginRight: 10,
flex: 0.33,
},
keyRowBottom: {
width: '100%',
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
marginLeft: 20,
marginRight: 10,
marginBottom: 10,
flex: 0.2,
},
keyBottomTouch: {
width: '100%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderRadius: 5,
marginHorizontal: 5,
},
keyTouch: {
width: '33%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderRadius: 5,
marginHorizontal: 5,
},
keyUnit: {
fontSize: 50,
color: colors.text,
},
footerRight: {
width: '25%',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
keyRowClose: {
flexDirection: 'row',
justifyContent: 'center',
marginLeft: 10,
marginTop: 10,
marginRight: 5,
flex: 0.25,
},
keyTouchClose: {
width: '90%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderRadius: 5,
marginHorizontal: 5,
},
keyRowSure: {
flexDirection: 'row',
justifyContent: 'center',
marginLeft: 10,
marginTop: 10,
marginBottom: 10,
marginRight: 5,
flex: 0.75,
},
keyTouchSure: {
width: '90%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#76EEC6',
borderRadius: 5,
marginHorizontal: 5,
},
keyTouchOnSure: {
width: '90%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#00CD66',
borderRadius: 5,
marginHorizontal: 5,
},
keyUnitClose: {
fontSize: 50,
color: '#FFFFFF',
},
};
export default PhoneModal;
import React from 'react';
import topView from 'rn-topview';
import ToastContainer from 'antd-mobile-rn/lib/toast/ToastContainer.native';
function notice(content, type, duration = 3, onClose, mask = true) {
topView.remove();
function animationEnd() {
topView.remove();
}
topView.set(
<ToastContainer
content={content}
duration={duration}
onClose={onClose}
type={type}
mask={mask}
onAnimationEnd={animationEnd}
/>,
);
}
export default {
SHORT: 3,
LONG: 8,
show(content: string, duration?: number, mask?: boolean) {
return notice(content, 'info', duration, () => {}, mask);
},
info(
content: string,
duration?: number,
onClose?: () => void,
mask?: boolean,
) {
return notice(content, 'info', duration, onClose, mask);
},
success(
content: string,
duration?: number,
onClose?: () => void,
mask?: boolean,
) {
return notice(content, 'success', duration, onClose, mask);
},
fail(
content: string,
duration?: number,
onClose?: () => void,
mask?: boolean,
) {
return notice(content, 'fail', duration, onClose, mask);
},
offline(
content: string,
duration?: number,
onClose?: () => void,
mask?: boolean,
) {
return notice(content, 'offline', duration, onClose, mask);
},
loading(
content: string,
duration?: number,
onClose?: () => void,
mask?: boolean,
) {
return notice(content, 'loading', duration, onClose, mask);
},
hide() {
topView.remove();
},
};
import React from 'react';
import {
Platform,
TouchableNativeFeedback,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native';
let TouchableComponent;
if (Platform.OS === 'android') {
TouchableComponent =
Platform.Version <= 20 ? TouchableOpacity : TouchableNativeFeedback;
} else {
TouchableComponent = TouchableOpacity;
}
if (TouchableComponent !== TouchableNativeFeedback) {
TouchableComponent.SelectableBackground = () => ({});
TouchableComponent.SelectableBackgroundBorderless = () => ({});
TouchableComponent.Ripple = () => ({});
TouchableComponent.canUseNativeForeground = () => false;
}
export default class PlatformTouchable extends React.Component {
static SelectableBackground = TouchableComponent.SelectableBackground;
static SelectableBackgroundBorderless =
TouchableComponent.SelectableBackgroundBorderless;
static Ripple = TouchableComponent.Ripple;
static canUseNativeForeground = TouchableComponent.canUseNativeForeground;
onPress = () => {
let {onPress} = this.props;
window.count = window.defaultCount;
if (onPress) {
onPress();
}
};
render() {
let {
children,
style,
foreground,
background,
useForeground,
feddback,
...props
} = this.props;
if (feddback === false) {
TouchableComponent = TouchableWithoutFeedback;
}
props.onPress = this.onPress;
// Even though it works for TouchableWithoutFeedback and
// TouchableNativeFeedback with this component, we want
// the API to be the same for all components so we require
// exactly one direct child for every touchable type.
children = React.Children.only(children);
if (TouchableComponent === TouchableNativeFeedback) {
useForeground =
foreground && TouchableNativeFeedback.canUseNativeForeground();
/* if (foreground && background) {
console.warn(
'Specified foreground and background for Touchable,' +
' only one can be used at a time. Defaulted to foreground.',
);
}*/
return (
<TouchableComponent
{...props}
useForeground={useForeground}
background={(useForeground && foreground) || background}>
<View style={style}>{children}</View>
</TouchableComponent>
);
} else if (TouchableComponent === TouchableWithoutFeedback) {
return (
<TouchableWithoutFeedback {...props}>
<View style={style}>{children}</View>
</TouchableWithoutFeedback>
);
} else {
const TouchableFallback = this.props.fallback || TouchableComponent;
return (
<TouchableFallback {...props} style={style}>
{children}
</TouchableFallback>
);
}
}
}
import React, {Component} from 'react';
import {Modal, View, Text, Image} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import ModalStyles from './Modal/styles';
import {colors, font} from '../utils/common';
import Touch from './Touch';
const mStyles = {
...ModalStyles,
innerContainer: {
...ModalStyles.innerContainer,
// width: 380,
},
header: {
...ModalStyles.header,
fontSize: font.title,
},
};
class VerifyCodeModal extends Component {
state = {
value: '',
};
getKeyboard = () => {
const rows = [];
let items = [];
for (let i = 1; i <= 9; i++) {
let unit;
unit = <Text style={styles.keyUnit}>{i}</Text>;
const item = (
<Touch style={styles.keyTouch} key={i} onPress={() => this.pressKey(i)}>
{unit}
</Touch>
);
items.push(item);
if (i % 3 === 0) {
rows.push(
<View style={styles.keyRow} key={i}>
{items}
</View>,
);
items = [];
}
}
return <View style={styles.NumberTop}>{rows}</View>;
};
pressKey = index => {
let {value} = this.state;
const {onSubmit} = this.props;
if (index < 10 && value.length < 4) {
value += index;
} else if (index === 11) {
value = value.substr(0, value.length - 1);
} else if (index === 12) {
this.setState({value: ''});
onSubmit(value);
return;
}
this.setState({value});
};
render() {
const {onClose, ...props} = this.props;
const {value} = this.state;
return (
<Modal styles={mStyles} {...props}>
<View style={styles.modal}>
<View style={styles.header}>
<View style={styles.title}>
<View style={styles.left}>
<Image
source={require('../assets/logo.png')}
style={styles.img}
/>
<Text style={styles.text}>安全验证手机号</Text>
</View>
<View style={styles.right}>
<Touch onPress={() => onClose()}>
<Icon name="md-close" color={'#FFFFFF'} size={50} />
</Touch>
</View>
</View>
<View style={styles.image}>
<Image
source={require('../assets/logo2.png')}
style={styles.logo}
/>
</View>
</View>
<View style={styles.container}>
<Text style={styles.tips}>请输入验证码</Text>
<View style={styles.codeView}>
<Text style={styles.code}>
{value && value.length >= 1 ? value.substr(0, 1) : ''}
</Text>
<Text style={styles.code}>
{value && value.length >= 2 ? value.substr(1, 1) : ''}
</Text>
<Text style={styles.code}>
{value && value.length >= 3 ? value.substr(2, 1) : ''}
</Text>
<Text style={styles.code}>
{value && value.length >= 4 ? value.substr(3, 1) : ''}
</Text>
</View>
</View>
<View style={styles.footer}>
<View style={styles.footerLeft}>
{this.getKeyboard()}
<View style={styles.keyRowBottom}>
<Touch
style={styles.keyBottomTouch}
onPress={() => this.pressKey(0)}>
<Text style={styles.keyUnit}>0</Text>
</Touch>
</View>
</View>
<View style={styles.footerRight}>
<View style={styles.keyRowClose}>
<Touch
style={styles.keyTouchClose}
onPress={() => this.pressKey(11)}>
<Icon
style={styles.keyUnit}
name="ios-backspace-outline"
size={60}
/>
</Touch>
</View>
<View style={styles.keyRowSure}>
{value.length < 4 ? (
<View style={styles.keyTouchSure}>
<Text style={styles.keyUnitClose}>确定</Text>
</View>
) : (
<Touch
style={styles.keyTouchOnSure}
onPress={() => this.pressKey(12)}>
<Text style={styles.keyUnitClose}>确定</Text>
</Touch>
)}
</View>
</View>
</View>
</View>
</Modal>
);
}
}
const styles = {
modal: {
height: '90%',
width: '90%',
marginLeft: '5%',
marginTop: '6%',
borderRadius: 20,
backgroundColor: '#cccccc',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
header: {
flex: 0.4,
backgroundColor: '#00CD66',
width: '100%',
flexDirection: 'column',
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
},
title: {
flexDirection: 'row',
justifyContent: 'space-between',
marginLeft: 30,
marginRight: 30,
marginTop: 10,
},
left: {
flexDirection: 'row',
alignItems: 'center',
},
right: {
flexDirection: 'row-reverse',
alignItems: 'center',
},
img: {
width: 80,
height: 80,
marginRight: 10,
resizeMode: 'contain',
},
image: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
logo: {
width: 150,
height: 150,
resizeMode: 'contain',
},
text: {
color: '#FFFFFF',
fontSize: 30,
},
container: {
flex: 0.3,
backgroundColor: '#FFFFFF',
width: '100%',
flexDirection: 'column',
justifyContent: 'center',
},
tips: {
color: 'red',
fontSize: 45,
marginBottom: 10,
textAlign: 'center',
},
codeView: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
flex: 0.5,
marginTop: 30,
},
code: {
height: '100%',
width: '15%',
borderWidth: 4,
borderColor: '#DCDCDC',
textAlign: 'center',
fontSize: 50,
textAlignVertical: 'center',
},
footer: {
flex: 0.4,
width: '100%',
flexDirection: 'row',
backgroundColor: '#F5F5F5',
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
},
footerLeft: {
width: '75%',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
NumberTop: {
flex: 0.8,
},
keyRow: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
marginLeft: 20,
marginRight: 10,
flex: 0.33,
},
keyRowBottom: {
width: '100%',
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
marginLeft: 20,
marginRight: 10,
marginBottom: 10,
flex: 0.2,
},
keyBottomTouch: {
width: '100%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderRadius: 5,
marginHorizontal: 5,
},
keyTouch: {
width: '33%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderRadius: 5,
marginHorizontal: 5,
},
keyUnit: {
fontSize: 50,
color: colors.text,
},
footerRight: {
width: '25%',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
keyRowClose: {
flexDirection: 'row',
justifyContent: 'center',
marginLeft: 10,
marginTop: 10,
marginRight: 5,
flex: 0.25,
},
keyTouchClose: {
width: '90%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderRadius: 5,
marginHorizontal: 5,
},
keyRowSure: {
flexDirection: 'row',
justifyContent: 'center',
marginLeft: 10,
marginTop: 10,
marginBottom: 10,
marginRight: 5,
flex: 0.75,
},
keyTouchSure: {
width: '90%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#76EEC6',
borderRadius: 5,
marginHorizontal: 5,
},
keyTouchOnSure: {
width: '90%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#00CD66',
borderRadius: 5,
marginHorizontal: 5,
},
keyUnitClose: {
fontSize: 50,
color: '#FFFFFF',
},
};
export default VerifyCodeModal;
import AsyncStorage from '@react-native-community/async-storage';
import * as api from '../services/admin';
export default {
namespace: 'admin',
state: {
auth: {},
socket: '',
},
reducers: {
setAuth(state, {id, auth, login}) {
state.id = id;
state.auth = auth;
window.auth = auth;
if (window.socket) {
window.socket.io.opts.query = {
token: auth.token,
};
}
AsyncStorage.setItem('auth', JSON.stringify(auth));
if (login) {
AsyncStorage.setItem('login', login);
}
return {...state};
},
setSocket(state, {socket}) {
state.socket = socket;
return {...state};
},
},
effects: {
*auth(action, {put, call}) {
let login = action.login;
action.device = login;
delete action.login;
const {data} = action.key
? yield call(api.token, action)
: yield call(api.refreshToken);
if (data && data.code === 1) {
if (data.data && data.data.contact) {
yield call(AsyncStorage.setItem, 'CONTACT', data.data.contact);
}
if (action.key) {
yield call(AsyncStorage.setItem, 'KEY', action.key);
}
yield put({type: 'setAuth', id: data.id, auth: data.data, login});
}
return data;
},
*logout(action, {put, call}) {
yield call(AsyncStorage.removeItem, 'auth');
yield put({type: 'app/replace', route: 'home'});
},
*version(action, {call}) {
yield call(api.version);
},
},
};
import * as api from '../services/alipay';
export default {
namespace: 'alipay',
state: {},
effects: {
*barcode(action, {call}) {
let {data} = yield call(api.barcode, action);
return data;
},
},
};
import * as api from '../services/goods';
export default {
namespace: 'goods',
state: {
orderInfo: [],
bags: [],
total: 0,
preTotal: 0,
status: -1,
},
reducers: {
setOrder(state, {data}) {
state.orderInfo = data.goods;
state.total = data.total;
state.preTotal = data.preTotal;
state.status = data.status;
return {...state};
},
setBags(state, {data}) {
state.bags = data;
return {...state};
},
},
effects: {
*getBags(action, {put, call}) {
let {data} = yield call(api.getBags);
if (data.code === 1) {
yield put({type: 'setBags', data: data.data});
}
},
*barcodepay(action, {call}) {
const err = {code: 500, msg: '付款失败,请扫屏幕二维码付款'};
try {
let {data} = yield call(api.barcodepay, action);
if (data.code === 500) {
return err;
}
return data;
} catch (e) {
return err;
}
},
*barcodeUser(action, {call}) {
try {
let {data} = yield call(api.barcodeUser, action);
return data;
} catch (e) {
return {code: -1};
}
},
*status(action, {call}) {
try {
let {data} = yield call(api.status, action);
return data;
} catch (e) {
return {code: -1};
}
},
*getGoods({barcode}, {call}) {
try {
return yield call(api.getGoods, barcode);
} catch (e) {
return {data: null};
}
},
*postOrder({ids, payType}, {call}) {
return yield call(api.postOrder, ids, payType);
},
*getOrder({id}, {put, call}) {
let {data} = yield call(api.getOrder, id);
if (data.code === 1) {
yield put({type: 'setOrder', data: data.data});
return data.data.status;
}
},
*canOrder({orderId}, {call}) {
return yield call(api.canOrder, orderId);
},
*faceinfo(action, {call}) {
return yield call(api.faceinfo, action);
},
*wxauthinfo(action, {call}) {
delete action.type;
return yield call(api.wxauthinfo, action);
},
},
};
import * as api from '../services/hkvs';
export default {
namespace: 'hkvs',
state: {
capture: {},
},
reducers: {
setDevices(state, {data}) {
state.device = data.device || true;
state.deviceIn = data.deviceIn;
state.deviceOut = data.deviceOut;
return {...state};
},
setCapture(state, {device, data}) {
const {capture} = state;
if (device === state.deviceIn) {
// if (!capture.in) capture.in = [];
capture.in = data;
} else if (device === state.deviceOut) {
// if (!capture.out) capture.out = [];
capture.out = data;
}
return {...state};
},
},
effects: {
*devices(action, {put, call}) {
const {data} = yield call(api.devices);
yield put({type: 'setDevices', data: data.data});
},
*capture({device}, {put, call}) {
let res = yield call(api.capture, device);
if (res.data.code !== 1) {
// 重试一遍
res = yield call(api.capture, device);
}
if (res.data.code !== 1) {
// 重试一遍
res = yield call(api.capture, device);
}
if (res.data.code === 1) {
yield put({type: 'setCapture', device, data: res.data.data});
return res.data.data;
}
return null;
},
},
};
import {Dimensions} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import admin from './admin';
import goods from './goods';
import alipay from './alipay';
import wxpay from './wxpay';
import order from './order';
import hkvs from './hkvs';
import user from './user';
import store from './store';
const {width: _width, height: _height} = Dimensions.get('window');
let curRoute = 'home';
if (_height > _width) {
curRoute = 'vertical';
}
const initRoute = {route: curRoute};
const app = {
namespace: 'app',
state: {
current: initRoute,
history: [initRoute],
step: 1,
lock: false,
},
reducers: {
replace(state, {route, params}) {
const current = {route, params};
state.current = current;
state.history[state.history.length - 1] = current;
return {...state};
},
push(state, {route, params}) {
const current = {route, params};
state.current = current;
state.history.push(current);
return {...state};
},
back(state, {params}) {
if (state.history.length === 1) {
return {...state};
}
state.history.pop();
state.current = state.history[state.history.length - 1];
state.current.params = params;
return {...state};
},
step(state, {step}) {
state.step = step;
return {...state};
},
lock(state, {lock}) {
state.lock = lock;
if (lock) {
AsyncStorage.setItem('settingLock', 'true');
} else {
AsyncStorage.removeItem('settingLock');
}
return {...state};
},
},
};
export default [app, admin, goods, alipay, wxpay, order, hkvs, user, store];
import * as api from '../services/order';
export default {
namespace: 'order',
state: {},
effects: {
*cardPay(action, {call}) {
let {data} = yield call(api.cardPay, action);
return data;
},
*status(action, {call}) {
try {
let {data} = yield call(api.status, action);
return data;
} catch (e) {
return {code: 1, data: 0};
}
},
},
};
import AsyncStorage from '@react-native-community/async-storage';
import * as api from '../services/store';
export default {
namespace: 'store',
state: {
auth: {},
socket: '',
ai: {
temperature: 0,
humidity: 0,
shock: 0,
trigger: {
text: 0,
data: 0,
},
offset: 0,
},
},
reducers: {
initScaleData(state) {
state.ai = {
...state.ai,
shock: 0,
trigger: {
text: 0,
data: 0,
},
offset: 0,
};
return {...state};
},
setAuth(state, {id, auth}) {
state.id = id;
state.auth = auth;
window.auth = auth;
if (window.socket) {
window.socket.io.opts.query = {
token: auth.token,
};
}
return {...state};
},
setScaleData(state, {data}) {
state.ai = data;
return {...state};
},
setSocket(state, {socket}) {
state.socket = socket;
return {...state};
},
},
effects: {
*auth(action, {put, call}) {
const {data} = action.key
? yield call(api.token, action)
: yield call(api.refreshToken);
if (data && data.code === 1) {
let set = [];
if (action.key) {
set = [
['KEY', action.key],
['SECRET', action.secret],
['DEVICE', action.device],
];
}
if (action.host) {
set.push(['HOST', action.host]);
}
if (data.data && data.data.contact) {
set.push(['CONTACT', data.data.contact]);
}
set.push(['auth', JSON.stringify(data.data)]);
yield call(AsyncStorage.multiSet, set);
// 缓存数据到内存,方便调用
const getValues = () =>
AsyncStorage.multiGet(['HOST', 'KEY', 'DEVICE', 'CONTACT']);
const values = yield call(getValues);
window.deviceInfo = {};
values.map(r => {
const k = r[0];
const v = r[1];
if (k && v) {
window.deviceInfo[k.toLowerCase()] = v;
}
});
yield put({type: 'setAuth', id: data.id, auth: data.data});
yield put({type: 'region'});
}
return data;
},
*logout(action, {put, call}) {
yield call(AsyncStorage.removeItem, 'auth');
yield put({type: 'app/replace', route: 'home'});
},
*version(action, {call}) {
yield call(api.version);
},
*region(action, {call}) {
const {data} = yield call(api.region);
if (data.code === 1) {
window.region = data.data;
window.regionArr = [];
['citycode', 'adcode', 'towncode'].map(k => {
const v = window.region[k];
if (v) {
window.regionArr.push(v);
}
});
window.regionArr.push(window.region.key);
window.regionArr = window.regionArr.reverse();
}
},
*door(action, {call}) {
const {data} = yield call(api.door, action);
if (data.code === 1) {
return data.data;
}
},
*wxdoor(action, {call}) {
const {data} = yield call(api.wxdoor, action);
if (data.code === 1) {
return data.data;
}
},
*scaleData(action, {put, call, select}) {
let {data} = yield call(api.scaleData);
if (data.code === 1 && data.data) {
let trigger = yield select(state => state.store.ai.trigger);
const dataTran = tranAIData(data.data, trigger);
yield put({type: 'setScaleData', data: dataTran});
return data.data;
}
},
*sendsms(action, {call}) {
const {data} = yield call(api.sendsms, action);
return data;
},
*verifysms(action, {call}) {
const {data} = yield call(api.verifysms, action);
return data;
},
},
};
const randomData = Math.random();
let tranAIData = (data, trigger) => {
let aiData = {
shock: 0,
trigger: {
text: 0,
data: 0,
},
offset: 0,
};
let max = 0;
let min = 500000;
let sum = 0;
data.weights.map(v => {
if (v > max) {
max = v;
}
if (v < min) {
min = v;
}
sum += v;
});
let ave = sum / 10;
if (max - min >= 600) {
aiData.shock = (100 + Math.random() * 80) * (ave / 75000);
} else {
aiData.shock = ((max - min) / 4) * (ave / 75000);
}
if (data.stableWeight && data.stableWeight > 0) {
aiData.trigger.data = 96;
aiData.trigger.text = data.stableWeight;
} else {
aiData.trigger.data = trigger.data + Math.random() * 30;
aiData.trigger.text = ave;
}
if (data.stableWeight && data.stableWeight > 0) {
aiData.offset = randomData * 30;
} else if (max - ave > 30 && ave - min > 30) {
aiData.offset = 30 + Math.random() * 30;
} else {
aiData.offset = max - ave > ave - min ? ave - min : max - ave;
}
if (
!data.weights ||
(Number(data.weights[0]) === 0 &&
Number(data.weights[data.weights.length - 1]) === 0)
) {
aiData = {
shock: 0,
trigger: {
text: 0,
data: 0,
},
offset: 0,
};
}
return {temperature: data.temperature, humidity: data.humidity, ...aiData};
};
import * as api from '../services/user';
export default {
namespace: 'user',
state: {},
effects: {
*sendSms({phone}, {call}) {
const {data} = yield call(api.sendsms, phone);
return data;
},
*signinup(action, {call}) {
delete action.type;
const {data} = yield call(api.signinup, action);
return data;
},
},
};
import * as api from '../services/wxpay';
export default {
namespace: 'wxpay',
state: {},
effects: {
*barcode(action, {call}) {
let {data} = yield call(api.barcode, action);
return data;
},
},
};
import React, {Component} from 'react';
import {View, Text, Image} from 'react-native';
import QRCode from 'react-native-qrcode-svg';
import io from 'socket.io-client';
import axios from 'axios';
import {counterLogin} from '../utils/authLogin';
import config from '../utils/config';
class AuthPage extends Component {
state = {};
async componentDidMount() {
this.socket = io(axios.defaults.baseURL);
this.socket.on('storeAuth', this.handleLogin);
this.socket.on('connect', () => {
this.setState({socket: this.socket.id});
});
this.socket.on('disconnect', () => {
this.socket.connect();
});
}
handleLogin = async values => {
this.setState({loading: true});
if (!values.host) {
values.host = config.host;
}
values.login = values.device;
await counterLogin(values);
};
render() {
const {socket} = this.state;
return (
<View style={styles.container}>
<View style={styles.title}>
<Image
style={styles.titleImg}
source={require('../assets/logo2.png')}
resizeMode="contain"
/>
<Image
style={{marginLeft: 20}}
source={require('../assets/Vertical/24h.png')}
/>
<Text style={styles.titleText}>仲马购人工智能</Text>
</View>
<View style={styles.qrcode}>
<QRCode
size={350}
logo={require('../assets/logo.png')}
logoBackgroundColor="#FC4000"
backgroundColor="white"
value={`${config.qrHost}/#/store-auth-${socket}`}
/>
</View>
</View>
);
}
}
const styles = {
title: {
top: 0,
paddingLeft: 30,
flexDirection: 'row',
height: 100,
width: '100%',
position: 'absolute',
backgroundColor: 'white',
alignItems: 'center',
elevation: 10,
},
titleImg: {
width: 80,
height: 80,
},
titleText: {
color: '#333',
fontSize: 40,
marginLeft: 30,
},
container: {
flex: 1,
backgroundColor: '#F5F5F5',
justifyContent: 'center',
alignItems: 'center',
},
qrcode: {
padding: 10,
backgroundColor: 'white',
elevation: 5,
},
};
export default AuthPage;
import React from 'react';
import {View, Text, DeviceEventEmitter} from 'react-native';
import {height, width} from '../../utils/screen';
import Scales from '../../utils/Scales';
import Touch from '../../components/Touch';
export default class ScalesPage extends React.Component {
state = {
data: '',
weight: '',
};
async componentDidMount() {
DeviceEventEmitter.addListener('onScalesChange', ({weight}) => {
this.setState({weight});
});
}
read = async () => {
const data = await Scales.read(0);
this.setState({data});
};
render() {
const style = {fontSize: 50, padding: 10};
const {data, weight} = this.state;
return (
<View
style={{
width,
height,
backgroundColor: 'rgba(255,255,255,.5)',
justifyContent: 'center',
alignItems: 'center',
}}>
<Touch onPress={this.read}>
<Text style={style}>{data || 'Read'}</Text>
</Touch>
<Text style={style}>{weight}</Text>
</View>
);
}
}
import React from 'react';
import io from 'socket.io-client';
import {View, Text} from 'react-native';
import Touch from '../../components/Touch';
import {height, width} from '../../utils/screen';
import {host} from '../../utils/config';
export default class SocketPage extends React.Component {
state = {
msg: '',
};
componentDidMount() {
this.socket = io(host);
this.socket.on('test', msg => {
this.setState({msg});
});
}
sayHello = () => {
this.socket.emit('test', 'Hello');
};
render() {
return (
<View
style={{
width,
height,
backgroundColor: 'rgba(255,255,255,.5)',
justifyContent: 'center',
alignItems: 'center',
}}>
<Touch onPress={this.sayHello}>
<Text style={{fontSize: 80}}>Click here to say hello.</Text>
</Touch>
<Text style={{fontSize: 60}}>
Receive from server: {this.state.msg}
</Text>
</View>
);
}
}
import HomePage from './pages/HomePage';
import VerticalPage from './pages/VerticalPage';
import AuthPage from './pages/AuthPage';
import FacePage from './pages/FacePage';
import ScalesPage from './pages/test/ScalesPage';
import SocketPage from './pages/test/SocketPage';
export default {
home: HomePage,
vertical: VerticalPage,
scales: ScalesPage,
socket: SocketPage,
auth: AuthPage,
face: FacePage,
};
import AsyncStorage from '@react-native-community/async-storage';
import axios from 'axios';
import qs from 'qs';
const pack = require('../../package.json');
export function token({key, secret, device}) {
return axios.post('/store/auth', qs.stringify({key, secret, device}));
}
export async function refreshToken() {
const auth = await AsyncStorage.getItem('auth');
if (auth) {
try {
const {refresh_token} = JSON.parse(auth);
return await axios.get('/auth/refresh', {
headers: {Authorization: `Bearer ${refresh_token}`},
});
} catch (e) {
return {data: null};
}
}
return {data: null};
}
export function version() {
return axios.put('/store/version', qs.stringify({version: pack.version}));
}
import axios from 'axios';
import qs from 'qs';
export function barcode({code, orderId}) {
return axios.post('/alipay/barcode', qs.stringify({code, orderId}));
}
import axios from 'axios';
import qs from 'qs';
export function getGoods(barcode) {
return axios.get(`/store/goods/${barcode}`);
}
export function getBags() {
return axios.get('/store/goods/bags');
}
export function barcodepay({ids, code, facepay}) {
return axios.post(
'/store/goods/barcodepay',
qs.stringify({ids, code, facepay}),
);
}
export function barcodeUser({userId, alipayUserId, orderId}) {
return axios.post(
'/store/goods/barcode/user',
qs.stringify({userId, alipayUserId, orderId}),
);
}
export function status({orderId}) {
return axios.post('/store/goods/status', qs.stringify({orderId}));
}
export function postOrder(ids, payType) {
payType = payType ? `/${payType}` : '';
return axios.post(`/api/orders${payType}`, qs.stringify({ids}));
}
export function getOrder(id) {
return axios.get(`/api/orders/${id}`);
}
export function canOrder(orderId) {
return axios.put('/api/orders/cancel', qs.stringify({orderId}));
}
export function faceinfo({rawdata}) {
return axios.post('/store/goods/faceinfo', qs.stringify({rawdata}));
}
export function wxauthinfo(action) {
return axios.post('/common/wxpay/faceAuth', action);
}
import axios from 'axios';
export function devices() {
return axios.get('/store/hkvs/devices');
}
export function capture(device) {
return axios.get(`/store/hkvs/capture/${device}`);
}
import axios from 'axios';
import qs from 'qs';
export function cardPay({code, orderId}) {
return axios.post('/api/orders/cardPay', qs.stringify({code, orderId}));
}
export function status({orderId, token}) {
return axios.get(`/api/orders/payStatus/${orderId}`, {
headers: {Authorization: `Bearer ${token}`},
});
}
import qs from 'qs';
import axios from 'axios';
import AsyncStorage from '@react-native-community/async-storage';
const pack = require('../../package.json');
export function token({host = '', key, secret, device}) {
return axios.post(`${host}/store/auth`, qs.stringify({key, secret, device}));
}
export async function refreshToken() {
const auth = await AsyncStorage.getItem('auth');
if (auth) {
try {
const {refresh_token} = JSON.parse(auth);
return await axios.get('/auth/refresh', {
headers: {Authorization: `Bearer ${refresh_token}`},
});
} catch (e) {
return {data: null};
}
}
return {data: null};
}
export function version() {
return axios.put('/store/version', qs.stringify({version: pack.version}));
}
export function region() {
return axios.get('/store/region');
}
export function door({userId}) {
return axios.post('/store/door', qs.stringify({userId}));
}
export function wxdoor({userId, openid, wxtoken, nickname}) {
return axios.post(
'/store/wxdoor',
qs.stringify({userId, openid, wxtoken, nickname}),
);
}
export function scaleData() {
return axios.get('/store/scaleData');
}
export function sendsms({phone}) {
return axios.post('/store/sendsms', qs.stringify({phone}));
}
export function verifysms({phone, code, userId}) {
return axios.post('/store/verifysms', qs.stringify({phone, code, userId}));
}
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment