Commit b305ec79 by 修福龙

刷脸开门系统

parent 8af95728
import React, {Component} from 'react';
import {Modal, View, Text, Image, FlatList, Dimensions} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import RtcEngine from 'react-native-agora';
// import {BoxShadow} from 'react-native-shadow';
import AsyncStorage from '@react-native-community/async-storage';
import ModalStyles from './Modal/styles';
import {font} from '../utils/common';
import Touch from './Touch';
import NP from '../utils/np';
import config from '../utils/config';
import phone from '../assets/Vertical/phone.png';
const screenWidth = Dimensions.get('window').width;
let pageSize = 7; // 分页大小
const mStyles = {
...ModalStyles,
......@@ -29,6 +26,7 @@ class OrderDetailsModal extends Component {
conatct: '',
storeName: '',
};
async componentWillMount() {
let contact = await AsyncStorage.getItem('CONTACT');
let storeName = await AsyncStorage.getItem('NAME');
......@@ -43,32 +41,56 @@ class OrderDetailsModal extends Component {
return String(index);
};
onCall = async () => {
const key = await AsyncStorage.getItem('KEY');
const channelName = 'face_' + key;
console.warn(channelName);
// const engine = await RtcEngine.create(appid);
// engine.joinChannel(token, channelName, null, 0);
// engine.joinChannel(token, 'face_001000010105', null, 0);
renderHeader = () => {
return (
<View style={{flex: 1, flexDirection: 'column'}}>
<View style={{backgroundColor: '#fff'}}>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
}}>
<View style={styles.firstThStyle}>
<Text style={styles.ThText}>商品名称</Text>
</View>
<View style={styles.ThStyle}>
<Text style={styles.ThText}>单价</Text>
</View>
<View style={styles.ThStyle}>
<Text style={styles.ThText}>数量</Text>
</View>
<View style={styles.ThStyle}>
<Text style={styles.ThText}>金额</Text>
</View>
</View>
</View>
<View style={styles.line} />
</View>
);
};
// 显示数据
renderCell = (item, index) => (
<View style={styles.cell}>
<View style={styles.TdStyle}>
{item.url ? (
<Image source={{uri: item.url}} style={styles.tdImg} />
) : (
''
)}
</View>
<View style={styles.nameTdStyle}>
<View style={index % 2 === 0 ? styles.oddCell : styles.evenCell}>
<View style={styles.firstTdStyle}>
<Text style={styles.TdText} numberOfLines={1}>
{item.name}
</Text>
</View>
<View style={styles.TdStyle}>
<Text style={styles.TdText}>x{NP.round(item.num, 0).toFixed(0)}</Text>
{item.price ? (
<Text style={styles.TdText}>
{NP.round(item.price, 2).toFixed(2)}
</Text>
) : (
<Text style={styles.TdText}>
{NP.round(item.prePrice, 2).toFixed(2)}
</Text>
)}
</View>
<View style={styles.TdStyle}>
<Text style={styles.TdText}> {NP.round(item.num, 0).toFixed(0)} </Text>
</View>
<View style={styles.TdStyle}>
{item.price ? (
......@@ -85,39 +107,43 @@ class OrderDetailsModal extends Component {
);
render() {
const {onClose, goodsArr, ...props} = this.props;
const {
onClose,
goodsArr,
talkCall,
onCall,
customerPhone,
current,
...props
} = this.props;
const {contact, storeName} = this.state;
const len = Math.ceil(screenWidth / 4);
const arr = [];
for (let i = 0; i < len / 3; i++) {
arr.push(i);
}
let totalCount = 0;
let totalPrice = 0;
goodsArr.map(v => {
v.url = config.imgUrl + v.barcode + config.watermark;
if (v.price) {
totalPrice += v.price * v.num;
totalCount += (v.prePrice - v.price) * v.num;
let goodsLength = Math.ceil(parseFloat(goodsArr.length / pageSize));
let gaTemp = goodsArr.slice((current - 1) * pageSize, current * pageSize);
let total = 0; // 总数量
let totalPrice = 0; // 总价
let totalCount = 0; // 总优惠
goodsArr.map(item => {
// item.url = config.imgUrl + item.barcode + config.watermark;
total += item.num;
if (item.price) {
totalPrice += item.price * item.num;
totalCount += (item.prePrice - item.price) * item.num;
} else {
totalPrice += v.prePrice * v.num;
totalPrice += item.prePrice * item.num;
}
});
// const shadowWidth = screenWidth * 0.8;
// const shadowOpt = {
// // width: 640, //包裹的子内容多宽这里必须多宽
// width: shadowWidth, //包裹的子内容多宽这里必须多宽
// height: 80, //同上
// // color: '#00CD66', //阴影颜色
// // color: '#90EE90',
// color: '#B4EEB4',
// border: 4, //阴影宽度
// radius: 8, //包裹的子元素圆角多少这里必须是多少
// opacity: 0.4, //透明度
// x: 0,
// y: 7,
// style: {marginVertical: 5},
// };
this.totalPrice = totalPrice;
this.totalCount = totalCount;
let phoneText = '';
if (customerPhone.length === 15) {
phoneText = '用户号:' + customerPhone;
} else {
phoneText =
'手机号:' +
customerPhone.substring(0, 3) +
'****' +
customerPhone.substring(customerPhone.length - 4, customerPhone.length);
}
return (
<Modal styles={mStyles} {...props}>
<View style={styles.modal}>
......@@ -128,52 +154,78 @@ class OrderDetailsModal extends Component {
source={require('../assets/logo2.png')}
style={styles.img}
/>
<Text style={styles.text}>订单详情</Text>
<Text style={styles.text}>{storeName}</Text>
</View>
<View style={styles.right}>
<Touch onPress={() => onClose()}>
<Icon name="md-close" color={'#FFFFFF'} size={50} />
</Touch>
<Text style={styles.number}>{contact}</Text>
<Text style={styles.text}>{contact}</Text>
<Image style={styles.phone} source={phone} />
</View>
</View>
<View style={styles.rod}>
<View style={styles.rodGradient} />
<View style={styles.headline}>
<Text style={styles.headTitle}>核对订单页面</Text>
</View>
<View style={styles.storeName}>
<Text style={styles.storeText}>{storeName}</Text>
<View style={styles.customerPhone}>
<Text style={styles.number}>{phoneText}</Text>
</View>
</View>
{goodsArr && goodsArr.length > 0 ? (
<View style={styles.container}>
<View style={styles.dottedTop} />
<View style={styles.dashLine}>
{arr.map((item, index) => (
<Text style={styles.dashItem} key={'dash' + index}>
-
</Text>
))}
</View>
<View style={styles.goods}>
<FlatList
style={styles.goodsStyle}
keyExtractor={this.keyExtractor}
horizontal={false}
data={goodsArr}
renderItem={({item, index}) => this.renderCell(item, index)}
/>
</View>
<View style={styles.dashLine}>
{arr.map((item, index) => (
<Text style={styles.dashItem} key={'dash' + index}>
-
</Text>
))}
<View style={{flexDirection: 'row', flex: 1}}>
<View style={{width: '90%'}}>
<FlatList
style={styles.goodsStyle}
ListHeaderComponent={this.renderHeader}
keyExtractor={this.keyExtractor}
horizontal={false}
data={gaTemp}
renderItem={({item, index}) => this.renderCell(item, index)}
/>
</View>
<View
style={{
width: '10%',
flexDirection: 'column',
}}>
<View style={{height: 81, backgroundColor: '#fff'}} />
<View style={{height: 8}} />
<View style={styles.pagination}>
<Touch
disabled={current <= 1}
onPress={() => this.props.dropUp()}>
<Image
source={
current > 1
? require('../assets/Vertical/arrowu01.png')
: require('../assets/Vertical/arrowu02.png')
}
style={styles.imgPagination}
/>
</Touch>
<Text style={styles.paginationText}>
{goodsLength === 0 ? 0 : current}/{goodsLength}
</Text>
<Touch
disabled={current >= goodsLength}
onPress={() => this.props.dropDown(goodsLength)}>
<Image
source={
current < goodsLength
? require('../assets/Vertical/arrowd01.png')
: require('../assets/Vertical/arrowd02.png')
}
style={styles.imgPagination}
/>
</Touch>
</View>
</View>
</View>
<View style={styles.line} />
<View style={styles.amount}>
<View style={styles.total}>
<Text style={styles.totalText}>商品总额</Text>
<Text style={styles.totalText}>合计</Text>
<Text style={styles.totalText}>
{' '}
{NP.round(
......@@ -183,11 +235,20 @@ class OrderDetailsModal extends Component {
</Text>
</View>
<View style={styles.total}>
<Text style={styles.totalText}>优惠金额</Text>
<Text style={styles.totalText}>数量</Text>
<Text style={styles.totalText}>
{NP.round(totalCount, 0).toFixed(0)}
</Text>
</View>
<View style={styles.total}>
<Text style={styles.totalText}>优惠</Text>
<Text style={styles.discount}>
- {NP.round(totalCount, 2).toFixed(2)}
</Text>
</View>
</View>
<View style={styles.line} />
<View style={styles.realPay}>
<View style={styles.total}>
<Text style={styles.totalText}>实付金额</Text>
<Text style={styles.totalText}>
......@@ -198,14 +259,6 @@ class OrderDetailsModal extends Component {
</View>
) : (
<View style={styles.container}>
<View style={styles.dottedTop} />
<View style={styles.dashLine}>
{arr.map((item, index) => (
<Text style={styles.dashItem} key={'dash' + index}>
-
</Text>
))}
</View>
<View style={styles.emptyContainer}>
<View style={styles.empty}>
<Image
......@@ -221,18 +274,43 @@ class OrderDetailsModal extends Component {
</View>
</View>
)}
<View style={styles.footer}>
{/*<BoxShadow setting={shadowOpt}>*/}
<View style={styles.service}>
<Touch onPress={() => this.onCall()} feddback={false}>
<View style={styles.call}>
<Icon name="md-call" color={'#fff'} size={45} />
<Text style={styles.callText}>呼叫客服</Text>
</View>
</Touch>
</View>
{/*</BoxShadow>*/}
<View style={styles.onCall}>
<Image
source={require('../assets/call.gif')}
style={styles.callGif}
/>
<Text style={styles.callText}>呼叫客服</Text>
</View>
{/*{talkCall === 1 ? (*/}
{/* <View style={styles.onCall}>*/}
{/* <Image*/}
{/* source={require('../assets/call.gif')}*/}
{/* style={styles.callGif}*/}
{/* />*/}
{/* <Text style={styles.onCallText}>正在语音通话中</Text>*/}
{/* </View>*/}
{/*) : talkCall === 0 ? (*/}
{/* <View style={styles.onCall}>*/}
{/* <Image*/}
{/* source={require('../assets/call.gif')}*/}
{/* style={styles.callGif}*/}
{/* />*/}
{/* <Text style={styles.onCallText}>正在接通中请稍候...</Text>*/}
{/* </View>*/}
{/*) : (*/}
{/* <Touch*/}
{/* onPress={() => onCall()}*/}
{/* style={styles.footer}*/}
{/* feedback={false}>*/}
{/* <View style={styles.call}>*/}
{/* <Image*/}
{/* source={require('../assets/call.gif')}*/}
{/* style={styles.callGif}*/}
{/* />*/}
{/* <Text style={styles.callText}>呼叫客服</Text>*/}
{/* </View>*/}
{/* </Touch>*/}
{/*)}*/}
</View>
</Modal>
);
......@@ -243,17 +321,15 @@ const styles = {
modal: {
height: '100%',
width: '100%',
// marginLeft: '5%',
// marginTop: '6%',
// borderRadius: 20,
backgroundColor: '#cccccc',
backgroundColor: '#fff',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
header: {
flex: 0.2,
backgroundColor: '#00CD66',
// backgroundColor: '#00CD66',
backgroundColor: 'rgb(0,205,102)',
width: '100%',
flexDirection: 'column',
borderTopRightRadius: 10,
......@@ -283,69 +359,40 @@ const styles = {
},
text: {
color: '#FFFFFF',
fontSize: 30,
fontSize: 35,
marginRight: 30,
},
rod: {
marginLeft: '3%',
marginRight: '3%',
marginTop: '2%',
borderRadius: 20,
backgroundColor: '#04BE02',
height: '12%',
},
rodGradient: {
marginLeft: '3.1%',
marginRight: '3.1%',
marginTop: '2%',
height: '50%',
// backgroundColor: '#F0FFF0',
// backgroundColor: '#C1FFC1',
backgroundColor: '#E0EEE0',
},
dashLine: {
headline: {
flexDirection: 'row',
marginLeft: '6%',
marginRight: '6%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
flex: 1,
},
dashItem: {
height: 3,
width: 5,
marginRight: 5,
backgroundColor: '#ddd',
fontSize: 20,
headTitle: {
fontSize: 60,
color: '#fff',
},
storeName: {
marginLeft: '6%',
marginRight: '6%',
backgroundColor: '#FFF',
flex: 1,
customerPhone: {
backgroundColor: '#3CB371',
flexDirection: 'row',
alignItems: 'flex-end',
},
storeText: {
fontSize: 40,
paddingLeft: 40,
justifyContent: 'center',
alignItems: 'center',
marginLeft: '5%',
marginRight: '5%',
marginBottom: '2%',
paddingTop: 10,
paddingBottom: 10,
elevation: 3,
},
container: {
flex: 0.7,
backgroundColor: '#F5F5F5',
flex: 0.6,
width: '100%',
flexDirection: 'column',
},
dottedTop: {
height: '3%',
marginLeft: '6%',
marginRight: '6%',
backgroundColor: '#FFF',
},
emptyContainer: {
flex: 1,
marginLeft: '6%',
marginRight: '6%',
marginLeft: '5%',
marginRight: '5%',
backgroundColor: '#fff',
flexDirection: 'column',
justifyContent: 'center',
......@@ -364,53 +411,81 @@ const styles = {
fontSize: 30,
color: '#8B8989',
},
goods: {
flex: 1,
marginLeft: '6%',
marginRight: '6%',
backgroundColor: '#FFF',
},
goodsStyle: {
width: '100%',
},
pagination: {
flex: 1,
backgroundColor: '#fff',
marginTop: '12%',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
paginationText: {
fontSize: 40,
},
imgPagination: {
width: 50,
height: 50,
},
cell: {
firstThStyle: {
width: '40%',
alignItems: 'flex-start',
paddingTop: 14,
paddingBottom: 14,
paddingLeft: 10,
paddingRight: 10,
marginLeft: '10%',
},
ThStyle: {
width: '20%',
alignItems: 'center',
paddingTop: 14,
paddingBottom: 14,
paddingLeft: 10,
paddingRight: 10,
},
ThText: {
fontSize: 30,
},
oddCell: {
flexDirection: 'row',
backgroundColor: '#fff',
},
nameTdStyle: {
evenCell: {
flexDirection: 'row',
backgroundColor: '#F0F0F0',
},
firstTdStyle: {
width: '40%',
justifyContent: 'center',
alignItems: 'flex-start',
paddingTop: 20,
paddingBottom: 20,
paddingTop: 14,
paddingBottom: 14,
paddingLeft: 10,
paddingRight: 10,
marginLeft: '5%',
},
TdStyle: {
flexDirection: 'row',
width: '20%',
alignItems: 'center',
justifyContent: 'center',
paddingTop: 20,
paddingBottom: 20,
paddingTop: 14,
paddingBottom: 14,
paddingLeft: 10,
paddingRight: 10,
},
tdImg: {
width: 60,
height: 60,
// marginRight: 10,
resizeMode: 'contain',
},
TdText: {
fontSize: 25,
fontSize: 20,
},
amount: {
flexDirection: 'column',
height: '25%',
backgroundColor: '#FFF',
marginLeft: '6%',
marginRight: '6%',
marginLeft: '2%',
marginRight: '2%',
},
total: {
flexDirection: 'row',
......@@ -427,15 +502,24 @@ const styles = {
fontSize: 30,
color: 'red',
},
footer: {
flex: 0.3,
line: {
width: '100%',
borderWidth: 1,
borderColor: '#ddd',
height: 1,
},
realPay: {
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5F5F5',
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
height: '10%',
backgroundColor: '#FFF',
marginLeft: '2%',
marginRight: '2%',
},
footer: {
flex: 0.2,
width: '100%',
// backgroundColor: '#44c571',
backgroundColor: 'rgb(0,205,102)',
},
phone: {
width: 40,
......@@ -448,25 +532,35 @@ const styles = {
fontSize: 30,
marginRight: 30,
},
service: {
// width: '98%',
width: '89%',
marginLeft: '1%',
marginRight: '1%',
},
call: {
felx: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 10,
padding: 15,
backgroundColor: '#00CD66',
borderRadius: 8,
},
callGif: {
width: 350,
height: 240,
marginLeft: -120,
},
callText: {
fontSize: 35,
fontSize: 70,
color: '#fff',
marginLeft: -50,
},
onCall: {
flex: 0.2,
width: '100%',
// backgroundColor: '#44c571',
backgroundColor: 'rgb(0,205,102)',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
onCallText: {
fontSize: 70,
color: '#fff',
marginLeft: 20,
marginLeft: -70,
},
};
......
......@@ -140,6 +140,14 @@ export default {
const {data} = yield call(api.verifysms, action);
return data;
},
*agora(action, {call}) {
const {data} = yield call(api.agora);
return data;
},
*talkCall(action, {call}) {
const {data} = yield call(api.talkCall);
return data;
},
},
};
......
import React, {Component} from 'react';
import {View, Text, Image, Dimensions, Animated, Easing} from 'react-native';
import {View, Text, Image, Dimensions} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
// import QRCode from 'react-native-qrcode-svg';
import {connect} from 'react-redux';
import RtcEngine from 'react-native-agora';
import Touch from '../components/Touch';
import PhoneModal from '../components/PhoneModal';
import VerifyCodeModal from '../components/VerifyCodeModal';
import OrderDetailsModal from '../components/OrderDetailsModal';
import NP from '../utils/np';
import delay from '../utils/delay';
import config from '../utils/config';
import Speech from '../utils/Speech';
import WxFacepay from '../utils/WxFacepay';
import phone from '../assets/Vertical/phone.png';
const {width, height} = Dimensions.get('screen');
const graph = {
temperature: [1, 1, 1, 1, 1, 1, 1, 1],
humidity: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
shock: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
trigger: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
offset: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
};
const graphItemWidth = (width - 60) * 0.12;
const graphItemHeight = height * 0.0135;
const graphSpaceHeight = height * 0.006;
let qrHost = config.qrHost;
const {width} = Dimensions.get('screen');
class FacePage extends Component {
state = {
tip: '',
tipBg: '#FC4000',
temperatureValue: new Animated.Value(0),
humidityValue: new Animated.Value(0),
shockValue: new Animated.Value(0),
triggerValue: new Animated.Value(0),
offsetValue: new Animated.Value(0),
phoneModal: false, // 显示输入电话号码弹窗
verifyCodeModal: false, // 显示输入验证码弹窗
orderDetailsModal: false, // 显示订单详情弹窗
goodsArr: [],
talkCall: 2, // 0请求通话,1通话中,2,已挂断通话
contact: '',
storeName: '',
customerPhone: '',
current: 1,
};
async componentWillMount() {
this.storeKey = await AsyncStorage.getItem('KEY');
let contact = await AsyncStorage.getItem('CONTACT');
let storeName = await AsyncStorage.getItem('NAME');
this.setState({
contact,
storeName,
});
if (!this.init) {
this.init = await WxFacepay.init();
}
......@@ -55,16 +42,6 @@ class FacePage extends Component {
async componentDidMount() {
this.listen();
clearInterval(this.noPersonInter);
this.noPersonInter = setInterval(async () => {
if (
(this.state.qrcode || this.state.scaleBusy) &&
(await this.noPerson())
) {
this.initScale();
this.setState({qrcode: null, tip: ''});
}
}, 5000);
}
onSubmit = async phone => {
......@@ -122,8 +99,10 @@ class FacePage extends Component {
};
handleOrderClose = () => {
// clearInterval(this.noTalkCall);
this.setState({
orderDetailsModal: false,
// talkCall: 2,
});
};
......@@ -139,6 +118,37 @@ class FacePage extends Component {
// 重力感应变化
window.socket.on('scale', this.handleScaleChange);
}
if (!window.socket.hasListeners('talkCall')) {
// 语音通话中
window.socket.on('talkCall', this.handleTalkCall);
// window.socket.on('talkCall', ({code, id, number, channel, device}) => {
// console.log(code, id, number, channel, device);
// if (code === 1) {
// this.setState({
// talkCall: 0,
// });
// } else if (code === 2) {
// this.setState({
// talkCall: 1,
// });
// }
// console.warn(code, id, number, channel, device);
// });
}
};
handleTalkCall = async () => {
// const {talkCall} = this.state;
// 加入语音通话
clearInterval(this.noTalkCall);
const {data} = await this.props.dispatch({
type: 'store/agora',
});
const engine = await RtcEngine.create(data.appid);
await engine.joinChannel(data.token, data.channel, null, 0);
this.setState({
talkCall: 1,
});
};
// 判断传感器上没人
......@@ -154,28 +164,20 @@ class FacePage extends Component {
if (count === -1) {
// 重力感应开始识别
this.wechatFace();
this.startScale();
} else if (count === 0) {
// 重力感应归零
this.initScale();
this.setState({qrcode: null, tip: ''});
this.setState({orderDetailsModal: false, current: 1});
}
};
handleDoorLogin = async ret => {
// console.warn(ret);
if (ret) {
const key = this.storeKey;
const prefix = `${qrHost}/#/store-${ret.action}-`;
if (ret.code < 0 || ret.code === 401) {
// 未授权,提示用户扫码验证
let tipText = ret.msg;
Speech.speak(tipText);
let qrcode = `${prefix}j${key}`;
if (ret.userId) {
qrcode += `-${ret.userId}`;
}
this.userId = ret.userId;
this.setState({qrcode, tip: tipText});
if (ret.code === 401) {
// 需要验证手机号
this.setState({phoneModal: true});
......@@ -186,89 +188,19 @@ class FacePage extends Component {
goodsArr.push(v2);
});
});
this.setState({orderDetailsModal: true, goodsArr});
}
} else if (ret.msg) {
let tipText = ret.msg.replace(/扫码/g, '人脸识别');
if (ret.code === 1) {
this.setState({qrcode: null});
} else if (ret.qrcode) {
this.setState({qrcode: `${prefix}j${key}`});
this.setState({
orderDetailsModal: true,
goodsArr,
customerPhone: ret.phone,
current: 1,
});
}
Speech.speak(tipText);
this.setState({tip: tipText});
}
} else {
Speech.speak('正在重新识别,请靠中间站稳');
}
};
startAnimation = () => {
let {ai} = this.props.store;
let duration = 1000;
let temperature =
(ai.temperature + 20) * 10 > 600 ? 600 : (ai.temperature + 20) * 10;
let humidity = ai.humidity > 100 ? 100 : ai.humidity;
let shock = ai.shock > 150 ? 150 : ai.shock;
let trigger = ai.trigger.data > 96 ? 96 : ai.trigger.data;
let offset = ai.offset > 50 ? 50 : ai.offset;
Animated.parallel([
Animated.spring(this.state.temperatureValue, {
toValue: temperature,
duration,
easing: Easing.linear,
}),
Animated.spring(this.state.humidityValue, {
toValue: humidity,
duration,
easing: Easing.linear,
}),
Animated.spring(this.state.shockValue, {
toValue: shock,
duration,
easing: Easing.linear,
}),
Animated.spring(this.state.triggerValue, {
toValue: trigger,
duration,
easing: Easing.linear,
}),
Animated.spring(this.state.offsetValue, {
toValue: offset,
duration,
easing: Easing.linear,
}),
]).start(() => {
this.state.temperatureValue.setValue(temperature);
this.state.humidityValue.setValue(humidity);
this.state.shockValue.setValue(shock);
this.state.triggerValue.setValue(trigger);
this.state.offsetValue.setValue(offset);
});
};
// 初始化重力感应
initScale = async () => {
this.setState({scaleBusy: false});
clearInterval(this.scaleInter);
await this.props.dispatch({
type: 'store/initScaleData',
});
this.startAnimation();
};
// 重力感应变化
startScale = () => {
this.setState({scaleBusy: true});
clearInterval(this.scaleInter);
this.scaleInter = setInterval(async () => {
await this.props.dispatch({
type: 'store/scaleData',
});
this.startAnimation();
}, 1000);
};
authinfo = async () => {
const rawdata = await WxFacepay.rawdata();
const {data} = await this.props.dispatch({
......@@ -280,9 +212,9 @@ class FacePage extends Component {
// 微信人脸身份识别
wechatFace = async () => {
if (this.state.qrcode) {
return;
} // 出现二维码,不做人脸识别
// if (this.state.qrcode) {
// return;
// } // 出现二维码,不做人脸识别
const tipText = '正在人脸识别,请看向屏幕,靠中间站稳';
Speech.speak(tipText);
this.setState({tip: tipText});
......@@ -328,30 +260,66 @@ class FacePage extends Component {
}
};
pressQrcode = async () => {
await this.setState({qrcode: null});
this.wechatFace();
// 语音通话请求
onCall = async () => {
// const {data} = await this.props.dispatch({
// type: 'store/agora',
// });
// const engine = await RtcEngine.create(data.appid);
// await engine.joinChannel(data.token, data.channel, null, 0);
// this.noTalkCall = setInterval(async () => {
// await this.props.dispatch({
// type: 'store/talkCall',
// });
// }, 10000);
Speech.speak('正在接通中请稍候');
this.talkCall();
clearInterval(this.noTalkCall);
this.noTalkCall = setInterval(() => this.talkCall(), 10000);
this.setState({
talkCall: 0,
});
};
talkCall = () => {
this.props.dispatch({
type: 'store/talkCall',
});
};
dropUp = () => {
let {current} = this.state;
if (current > 1) {
this.setState({
current: --current,
});
}
};
dropDown = goodsLength => {
let {current} = this.state;
if (current < goodsLength) {
this.setState({
current: ++current,
});
}
};
render() {
const {
scaleBusy,
tip,
tipBg,
verifyCodeModal,
temperatureValue,
humidityValue,
wakeup,
shockValue,
triggerValue,
offsetValue,
phoneModal,
orderDetailsModal,
goodsArr,
talkCall,
storeName,
contact,
customerPhone,
current,
} = this.state;
let {store} = this.props;
let {dispatch} = this.props;
return (
<View style={{flex: 1, alignItems: 'center', backgroundColor: '#333'}}>
<View style={styles.content}>
<PhoneModal
visible={phoneModal}
transparent
......@@ -374,499 +342,226 @@ class FacePage extends Component {
maskClosable
onClose={this.handleOrderClose}
onRequestClose={this.handleOrderClose}
onCall={this.onCall}
dropUp={this.dropUp}
dropDown={this.dropDown}
goodsArr={goodsArr}
dispatch={dispatch}
talkCall={talkCall}
customerPhone={customerPhone}
current={current}
/>
<View style={{alignItems: 'center', justifyContent: 'center', flex: 1}}>
<Touch onPress={this.pressQrcode} style={{flex: 1}}>
<Image
source={require('../assets/ai/face.gif')}
style={{flex: 1, width}}
/>
</Touch>
<Touch onPress={this.wechatFace}>
<View style={{...styles.tip, backgroundColor: tipBg}}>
<Text style={styles.tipText}>{tip}</Text>
<View style={styles.header}>
<View style={styles.title}>
<View style={styles.left}>
<Image
source={require('../assets/logo2.png')}
style={styles.img}
/>
<Text style={styles.text}>{storeName}</Text>
</View>
</Touch>
</View>
<View
style={{
flex: 1,
backgroundColor: scaleBusy || wakeup ? '#ffffff' : '#030303',
flexDirection: 'row',
}}>
<View style={{width: 30}} />
<View style={styles.aiItem}>
<View style={styles.graph}>
<View style={styles.graphView}>
<Text
style={[
styles.graphText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
{store.ai.temperature >= 0
? `+${store.ai.temperature}`
: store.ai.temperature}
</Text>
</View>
<View style={styles.graphMain}>
<View
style={{
zIndex: 999,
}}>
{graph.temperature.map((v, k) => {
return (
<View key={k}>
<View
style={[
styles.graphSpace,
{
backgroundColor:
scaleBusy || wakeup ? '#ffffff' : '#000000',
},
]}
/>
<View style={styles.graphItem} />
</View>
);
})}
</View>
<Animated.View
style={[
styles.graphData,
{
height: temperatureValue.interpolate({
inputRange: [0, 600],
outputRange: [
0,
(graphItemHeight + graphSpaceHeight) *
graph.temperature.length,
],
}),
backgroundColor: '#fff100',
},
]}
/>
<View
style={[
styles.graphBg,
{
height:
(graphItemHeight + graphSpaceHeight) *
graph.temperature.length,
},
]}
/>
</View>
<View style={styles.right}>
<Text style={styles.text}>{contact}</Text>
<Image style={styles.phone} source={phone} />
</View>
<Image
style={styles.aiIcon}
source={require('../assets/ai/temperature.png')}
/>
<Text
style={[
styles.aiText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
温度
</Text>
</View>
<View style={styles.aiItem}>
<View style={styles.graph}>
<View style={styles.graphView}>
<Text
style={[
styles.graphText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
{store.ai.humidity}%RH
</Text>
</View>
<View style={styles.graphMain}>
<View
style={{
zIndex: 999,
}}>
{graph.humidity.map((v, k) => {
return (
<View key={k}>
<View
style={[
styles.graphSpace,
{
backgroundColor:
scaleBusy || wakeup ? '#ffffff' : '#000000',
},
]}
/>
<View style={styles.graphItem} />
</View>
);
})}
</View>
<Animated.View
style={[
styles.graphData,
{
height: humidityValue.interpolate({
inputRange: [0, 100],
outputRange: [
0,
(graphItemHeight + graphSpaceHeight) *
graph.humidity.length,
],
}),
backgroundColor: '#7d4d76',
},
]}
/>
<View
style={[
styles.graphBg,
{
height:
(graphItemHeight + graphSpaceHeight) *
graph.humidity.length,
},
]}
/>
</View>
</View>
<Image
style={styles.aiIcon}
source={require('../assets/ai/humidity.png')}
/>
<Text
style={[
styles.aiText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
湿度
</Text>
<View style={styles.headline}>
<Text style={styles.headTitle}>刷脸开门系统</Text>
</View>
<View style={styles.aiItem}>
<View style={styles.graph}>
<View style={styles.graphView}>
<Text
style={[
styles.graphText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
{NP.round(store.ai.shock, 0).toFixed(0)}mm/s
</Text>
</View>
<View style={styles.graphMain}>
<View
style={{
zIndex: 999,
}}>
{graph.shock.map((v, k) => {
return (
<View key={k}>
<View
style={[
styles.graphSpace,
{
backgroundColor:
scaleBusy || wakeup ? '#ffffff' : '#000000',
},
]}
/>
<View style={styles.graphItem} />
</View>
);
})}
</View>
<Animated.View
style={[
styles.graphData,
{
height: shockValue.interpolate({
inputRange: [0, 150],
outputRange: [
0,
(graphItemHeight + graphSpaceHeight) *
graph.shock.length,
],
}),
backgroundColor: '#fc615e',
},
]}
/>
<View
style={[
styles.graphBg,
{
height:
(graphItemHeight + graphSpaceHeight) *
graph.shock.length,
},
]}
/>
</View>
</View>
<Image
style={styles.aiIcon}
source={require('../assets/ai/shock.png')}
/>
<Text
style={[
styles.aiText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
震动
</Text>
</View>
<View style={styles.aiItem}>
<View style={styles.graph}>
<View style={styles.graphView}>
<Text
style={[
styles.graphText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
{store.ai.trigger.text}G
</Text>
</View>
<View style={styles.graphMain}>
<View
style={{
zIndex: 999,
}}>
{graph.trigger.map((v, k) => {
return (
<View key={k}>
<View
style={[
styles.graphSpace,
{
backgroundColor:
scaleBusy || wakeup ? '#ffffff' : '#000000',
},
]}
/>
<View style={styles.graphItem} />
</View>
);
})}
</View>
<Animated.View
style={[
styles.graphData,
{
height: triggerValue.interpolate({
inputRange: [0, 96],
outputRange: [
0,
(graphItemHeight + graphSpaceHeight) *
graph.trigger.length,
],
}),
backgroundColor: '#8e8a7d',
},
]}
/>
<View
style={[
styles.graphBg,
{
height:
(graphItemHeight + graphSpaceHeight) *
graph.trigger.length,
},
]}
/>
</View>
</View>
</View>
<View style={styles.face}>
<Touch
onPress={this.wechatFace}
style={styles.faceGif}
feedback={false}>
<Image
style={styles.aiIcon}
source={require('../assets/ai/trigger.png')}
source={require('../assets/Vertical/face.gif')}
style={{flex: 1, width}}
/>
<Text
style={[
styles.aiText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
触点
</Text>
</View>
<View style={styles.aiItem}>
<View style={styles.graph}>
<View style={styles.graphView}>
<Text
style={[
styles.graphText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
±{NP.round(store.ai.offset, 0).toFixed(0)}G
</Text>
</View>
<View style={styles.graphMain}>
<View
style={{
zIndex: 999,
}}>
{graph.offset.map((v, k) => {
return (
<View key={k}>
<View
style={[
styles.graphSpace,
{
backgroundColor:
scaleBusy || wakeup ? '#ffffff' : '#000000',
},
]}
/>
<View style={styles.graphItem} />
</View>
);
})}
</View>
<Animated.View
style={[
styles.graphData,
{
height: offsetValue.interpolate({
inputRange: [0, 50],
outputRange: [
0,
(graphItemHeight + graphSpaceHeight) *
graph.offset.length,
],
}),
backgroundColor: '#69d6c5',
},
]}
/>
<View
style={[
styles.graphBg,
{
height:
(graphItemHeight + graphSpaceHeight) *
graph.offset.length,
},
]}
/>
</View>
</Touch>
<Touch
onPress={this.wechatFace}
style={styles.btnCome}
feedback={false}>
<View style={styles.click}>
<Image
source={require('../assets/wxpay.png')}
style={styles.wxpay}
/>
<Text style={styles.clickText}>点击进入</Text>
<Image source={require('../assets/up.png')} style={styles.up} />
<Text style={styles.clickText}>刷脸开门</Text>
</View>
<Image
style={styles.aiIcon}
source={require('../assets/ai/offset.png')}
/>
<Text
style={[
styles.aiText,
{color: scaleBusy || wakeup ? '#000000' : '#ffffff'},
]}>
误差
</Text>
</View>
<View style={{width: 30}} />
</Touch>
</View>
<View style={styles.onCall}>
<Image
source={require('../assets/call.gif')}
style={styles.callGif}
/>
<Text style={styles.callText}>呼叫客服</Text>
</View>
{/*{talkCall === 1 ? (*/}
{/* <View style={styles.onCall}>*/}
{/* <Image*/}
{/* source={require('../assets/call.gif')}*/}
{/* style={styles.callGif}*/}
{/* />*/}
{/* <Text style={styles.onCallText}>正在语音通话中</Text>*/}
{/* </View>*/}
{/*) : talkCall === 0 ? (*/}
{/* <View style={styles.onCall}>*/}
{/* <Image*/}
{/* source={require('../assets/call.gif')}*/}
{/* style={styles.callGif}*/}
{/* />*/}
{/* <Text style={styles.onCallText}>正在接通中请稍候...</Text>*/}
{/* </View>*/}
{/*) : (*/}
{/* <Touch onPress={this.onCall} style={styles.footer} feedback={false}>*/}
{/* <View style={styles.call}>*/}
{/* <Image*/}
{/* source={require('../assets/call.gif')}*/}
{/* style={styles.callGif}*/}
{/* />*/}
{/* <Text style={styles.callText}>呼叫客服</Text>*/}
{/* </View>*/}
{/* </Touch>*/}
{/*)}*/}
</View>
);
}
}
const styles = {
tip: {
width,
height: 60,
content: {
flex: 1,
alignItems: 'center',
backgroundColor: '#fff',
},
header: {
flex: 0.2,
// backgroundColor: '#00CD66',
backgroundColor: 'rgb(0,205,102)',
width: '100%',
flexDirection: 'column',
},
title: {
flexDirection: 'row',
justifyContent: 'space-between',
marginLeft: 30,
marginRight: 30,
marginTop: 10,
},
headline: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
flex: 1,
marginBottom: 20,
},
headTitle: {
fontSize: 60,
color: '#fff',
},
left: {
flexDirection: 'row',
alignItems: 'center',
},
right: {
flexDirection: 'row-reverse',
alignItems: 'center',
},
img: {
width: 60,
height: 60,
marginRight: 10,
resizeMode: 'contain',
},
tipText: {
color: 'white',
fontSize: 25,
text: {
color: '#FFFFFF',
fontSize: 40,
},
aiIcon: {
width: width * 0.08,
height: width * 0.08,
face: {
flex: 0.6,
width: '100%',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-around',
},
aiText: {
fontSize: 14,
color: '#000000',
fontWeight: 'bold',
marginVertical: 12,
faceGif: {
flex: 0.7,
},
aiTriangle: {
btnCome: {
flex: 0.15,
// backgroundColor: '#00CD66',
backgroundColor: 'rgb(0,205,102)',
width: '80%',
borderRadius: 30,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginTop: 18,
marginBottom: 26,
elevation: 2,
},
atLeft: {
width: 0,
height: 0,
marginTop: 1,
borderStyle: 'solid',
borderTopWidth: 13,
borderBottomWidth: 13,
borderRightWidth: (width - 60) * 0.1,
borderTopColor: '#fff',
borderLeftColor: '#fff',
borderBottomColor: '#fff',
click: {
flexDirection: 'row',
},
atRight: {
width: 0,
height: 0,
marginTop: 1,
borderStyle: 'solid',
borderTopWidth: 13,
borderBottomWidth: 13,
borderLeftWidth: (width - 60) * 0.1,
borderTopColor: '#fff',
borderBottomColor: '#fff',
borderRightColor: '#fff',
clickText: {
fontSize: 50,
color: '#fff',
marginTop: 25,
},
aiItem: {
flex: 1,
alignItems: 'center',
wxpay: {
width: 72,
height: 65,
marginTop: 30,
marginRight: 10,
},
graph: {
width: graphItemWidth,
flex: 1,
up: {
width: 100,
height: 120,
},
graphMain: {
position: 'relative',
marginBottom: 12,
phone: {
width: 40,
height: 40,
marginRight: 10,
resizeMode: 'contain',
},
graphItem: {
width: graphItemWidth,
height: graphItemHeight,
backgroundColor: 'transparent',
footer: {
flex: 0.2,
width: '100%',
// backgroundColor: '#44c571',
backgroundColor: 'rgb(68, 197, 114)',
},
graphSpace: {
width: graphItemWidth,
backgroundColor: '#ffffff',
height: graphSpaceHeight,
call: {
felx: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
graphBg: {
width: graphItemWidth,
position: 'absolute',
top: 0,
left: 0,
backgroundColor: '#d7d2bb',
callGif: {
width: 350,
height: 240,
marginLeft: -120,
},
graphData: {
width: graphItemWidth,
position: 'absolute',
bottom: -1,
left: 0,
zIndex: 9,
callText: {
fontSize: 70,
color: '#fff',
marginLeft: -50,
},
graphView: {
flex: 1,
onCall: {
flex: 0.2,
width: '100%',
// backgroundColor: '#44c571',
backgroundColor: 'rgb(68, 197, 114)',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
justifyContent: 'flex-end',
},
graphText: {
marginBottom: 5,
fontSize: 12,
color: '#000000',
onCallText: {
fontSize: 70,
color: '#fff',
marginLeft: -70,
},
};
......
......@@ -53,3 +53,11 @@ export function sendsms({phone}) {
export function verifysms({phone, code, userId}) {
return axios.post('/store/verifysms', qs.stringify({phone, code, userId}));
}
export function agora() {
return axios.post('/store/agora/token');
}
export function talkCall() {
return axios.post('/store/agora/call');
}
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