Commit 1e4f33b9 by 姜雷

Merge branch 'test'

parents cb285263 79c03d98
......@@ -19,6 +19,9 @@ type Params = {
smaproPrepayConfigId: number;
// 预付配置id
smaproPrepayConfigIds?: number[];
// 预付配置id集合,serviceId为30或者31时才需传
areaId: number;
// 区域id
......
......@@ -54,9 +54,18 @@ type SmaproPrepayConfig = {
id: number;
// 会员id
isMajor: number;
// 是否主要功能 1:主要功能;2:附加功能
isOpen: number;
// 是否开启
isShowRate: number;
// 是否显示费率 0:否;1:是。默认1
name: string;
// 名称
operateId: number;
// 运营商id
......@@ -77,6 +86,8 @@ type SmaproPrepayConfig = {
updateAt: string;
// 更新时间
duration: number;
};
type ResponseData = {
deviceInfoResponse: DeviceInfoResponse;
......
......@@ -35,6 +35,9 @@ class App extends Component {
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black',
},
networkTimeout: {
connectSocket: 600000,
},
};
// 在 App 类中的 render() 函数没有实际作用
......
......@@ -4,4 +4,4 @@ export const NotRegisterCode = 1005;
export const BASE_SERVER_URL = 'https://dcxy-smapro-app.dcrym.com';
export const SOCKET_URL = 'wss://shower-wss1.dcrym.com:9443/ws';
export const DRY_SOCKET_URL = 'wss://share-device-manager.dcrym.com:9443';
export const DRY_SOCKET_URL = 'wss://share-device-wss1.dcrym.com:9443';
.Connect {
.state {
height: 0;
overflow: hidden;
}
.Connect-title {
font-size: 34rpx;
height: 102rpx;
line-height: 102rpx;
text-align: center;
border-bottom: 1rpx dotted #f8f8f8;
}
.Connect-Pay {
border-top: 20rpx solid #f8f8f8;
padding: 0 35rpx;
.Connect-Pay-title {
padding: 40rpx 0 30rpx;
font-size: 34rpx;
border-bottom: 1rpx solid #e8e8e8;
}
.Connect-Pay-titleTip {
color: #999;
}
.Connect-Pay-content {
padding: 10rpx 0;
}
.Connect-Pay-item {
display: flex;
align-items: center;
height: 80rpx;
font-size: 28rpx;
.Connect-Pay-itemName {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.Connect-Pay-itemTime {
width: 170rpx;
text-align: right;
color: #999;
}
.Connect-Pay-itemPrice {
width: 175rpx;
text-align: right;
}
.Connect-Pay-itemSelect {
margin-left: 50rpx;
width: 40rpx;
height: 40rpx;
.Connect-Pay-itemSelecticon {
width: 40rpx;
height: 40rpx;
}
}
}
}
.Connect-info {
padding: 40px 32px;
font-size: 28px;
......@@ -47,6 +103,11 @@
border-radius: 30px;
vertical-align: middle;
}
.Connect-tip3 {
padding: 26rpx 48rpx;
font-size: 26rpx;
color: #ff4b4b;
}
.Connect-money {
display: flex;
flex-wrap: wrap;
......@@ -54,6 +115,7 @@
margin: 0 auto;
.Connect-money-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
......@@ -64,6 +126,12 @@
border: 1px solid #ccc;
margin-bottom: 16px;
margin-right: 16px;
.time {
font-size: 30px;
}
.money {
font-size: 36px;
}
&.seleted {
border-color: #6180f4;
color: #6180f4;
......
import Taro, { Component, Config } from '@tarojs/taro';
import { ComponentClass } from 'react';
import { View, Text, Button, ScrollView } from '@tarojs/components';
import { View, Text, Button, ScrollView, Image } from '@tarojs/components';
import { getPayOrder } from '../../api/Order/pay';
import { connect } from '@tarojs/redux';
import {
......@@ -18,6 +18,10 @@ import PaddingPkcs7 from 'crypto-js/pad-pkcs7';
import './connect.scss';
import { str2ab, ab2str } from '@/utils/arrayBuffer';
import { DRY_SOCKET_URL } from '@/constants';
import selectIcon from '../../images/select_icon1@2x.png';
import selectedIcon from '../../images/selected_icon1@2x.png';
import select2Icon from '../../images/select_icon2@2x.png';
import selected2Icon from '../../images/selected_icon2@2x.png';
enum ContorlCode {
using = '1',
......@@ -61,6 +65,7 @@ type DeviceInfo = {
type PageStateProps = {
device: Device;
prepayConfig: PrepayConfig[];
addprepayConfig: PrepayConfig[];
userinfo: Customer;
};
......@@ -68,6 +73,8 @@ type PageDispatchProps = {};
type PageState = {
payId: undefined | number;
payIds: number[];
payMoney: number;
bluetoothState: boolean;
deviceInfo: DeviceInfo;
sockedDone: boolean;
......@@ -90,10 +97,18 @@ const StopCode = 1000;
let timer: NodeJS.Timeout | null = null;
let reConnectting: boolean = false;
let socketTask: Taro.SocketTask | null = null;
let liveTimer: NodeJS.Timeout | null = null;
let msgList: Message[] = [];
let msgindex: number = 0;
let currentThis: Connect | null = null;
@connect(({ device, prepayConfig, userinfo }) => ({
device,
prepayConfig,
// prepayConfig: prepayConfig,
prepayConfig: prepayConfig.filter((item: PrepayConfig) => item.isMajor === 1),
addprepayConfig: prepayConfig.filter(
(item: PrepayConfig) => item.isMajor === 2
),
userinfo,
}))
class Connect extends Component {
......@@ -104,8 +119,10 @@ class Connect extends Component {
super(props);
this.state = {
payId: undefined,
payIds: [],
payMoney: 0,
bluetoothState: false,
sockedDone: false,
sockedDone: socketTask ? true : false,
deviceDone: false,
showerState: false,
deviceInfo: {
......@@ -121,36 +138,68 @@ class Connect extends Component {
lastMessage: '',
canPay: false,
};
this.checkBluetoothAndWs();
}
componentWillMount() {
const { prepayConfig } = this.props;
if (prepayConfig.length) {
this.setState({
this.setState(
{
payId: prepayConfig[0].id,
});
},
() => {
this.getPayMoney();
}
);
}
this.checkBluetoothAndWs();
currentThis = this;
}
componentWillUnmount() {
// this.closeBluetooth();
// this.closeDeviceSocket();
msgList = [];
msgindex = 0;
currentThis = null;
}
connectDeviceSocket() {
this.addMessageItem({
type: MessageType.info,
text: '服务器连接中...',
});
Taro.connectSocket({ url: DRY_SOCKET_URL }).then(task => {
const { device } = this.props;
const { canPay } = this.state;
// if (socketTask) return;
// this.addMessageItem({
// type: MessageType.info,
// text: '服务器连接中...',
// });
if (msgindex) return;
// Taro.closeSocket()
// .catch(err => {
// console.log(err);
// })
// .then(() => {
// })
let connectHandle;
if (socketTask) {
connectHandle = new Promise(resolve => resolve(socketTask));
} else {
connectHandle = Taro.connectSocket({
url: DRY_SOCKET_URL,
timeout: 1200000,
}).then(task => {
socketTask = task;
task.onOpen(() => {
this.addMessageItem({
type: MessageType.success,
text: '服务器连接成功',
});
this.addConnectMsg();
liveTimer = setInterval(() => {
task.send({ data: str2ab('{}') });
}, 20000);
console.log('onOpen');
if (reConnectting) {
this.reConnectDeviceSocket(true);
......@@ -162,12 +211,9 @@ class Connect extends Component {
this.sendDeviceCode();
});
task.onMessage(res => {
this.addMessageItem({
type: MessageType.info,
text: '正在与设备通信...',
});
const msg: string = ab2str(res.data);
console.log('获取socket消息: ', msg);
console.log('状态: ', canPay, device.isOnlyBluetooth);
const msgObj: UploadMessage = JSON.parse(msg);
if (msgObj.type === 1) {
if (msgObj.data.length > 20) {
......@@ -194,9 +240,8 @@ class Connect extends Component {
content: '设备已损坏',
});
} else if (msgObj.contorlCode === ContorlCode.usable) {
this.setState({
canPay: true,
});
console.log('in setState', currentThis.canPay);
currentThis && currentThis.setState({ canPay: true });
} else if (msgObj.contorlCode === ContorlCode.opened) {
Taro.showModal({
title: '提示',
......@@ -208,15 +253,19 @@ class Connect extends Component {
}
});
task.onClose(e => {
if (msgindex !== 0) {
this.addMessageItem({
type: MessageType.error,
text: '服务器连接失败,请稍后扫码重试',
});
}
console.log('socked关闭', e, reConnectting, timer);
this.setState({
sockedDone: false,
});
liveTimer && clearInterval(liveTimer);
socketTask = null;
liveTimer = null;
if (e.code === StopCode) {
console.log('正确结束socket连接');
} else {
......@@ -226,6 +275,23 @@ class Connect extends Component {
});
});
}
connectHandle.then(() => {
console.log('socket done');
});
}
addConnectMsg() {
const { sockedDone, deviceDone } = this.state;
if (sockedDone && deviceDone) {
if (msgindex === 0) {
this.addMessageItem({
type: MessageType.info,
text: '正在与设备通信...',
});
}
msgindex++;
}
}
reConnectDeviceSocket(cancel: boolean) {
if (cancel) {
......@@ -259,22 +325,22 @@ class Connect extends Component {
sendDeviceCode() {
const { sockedDone, deviceDone } = this.state;
const { device } = this.props;
// const { device } = this.props;
console.log('socket状态:', sockedDone, '蓝牙状态:', deviceDone);
if (sockedDone && socketTask && deviceDone) {
let deviceData = '{<' + device.code + '>}';
console.log('<---发送设备编号:', deviceData);
socketTask.send({
data: str2ab(deviceData),
success: msg => {
console.log('发送设备编号:', msg, '--->');
},
fail: err => {
console.log('发送设备编号:', err, '--->');
},
});
}
// if (sockedDone && socketTask && deviceDone) {
// let deviceData = '{<' + device.code + '>}';
// console.log('<---发送设备编号:', deviceData);
// socketTask.send({
// data: str2ab(deviceData),
// success: msg => {
// console.log('发送设备编号:', msg, '--->');
// },
// fail: err => {
// console.log('发送设备编号:', err, '--->');
// },
// });
// }
}
closeDeviceSocket() {
......@@ -383,7 +449,9 @@ class Connect extends Component {
console.log('in startDevicesDiscovery', this.checkBluetoothState());
if (this.checkBluetoothState()) {
return Taro.startBluetoothDevicesDiscovery()
return Taro.startBluetoothDevicesDiscovery({
// services: ['00001103-0000-1000-8000-00805f9b34fb'],
})
.then(() => {
const {
code,
......@@ -455,7 +523,7 @@ class Connect extends Component {
}
createConnection(deviceId: string) {
const { userinfo } = this.props;
const { userinfo, device } = this.props;
console.log(deviceId);
return new Promise((resolve, reject) => {
Taro.createBLEConnection({
......@@ -476,19 +544,21 @@ class Connect extends Component {
this.closeBluetoothConnection();
} else {
if (
datastr.substring(0, 1) === '{' &&
datastr.substring(datastr.length - 1, datastr.length) === '}'
(datastr.substring(0, 1) === '{' &&
datastr.substring(datastr.length - 1, datastr.length) === '}') ||
(datastr.substring(0, 1) === '<' &&
datastr.substring(datastr.length - 1, datastr.length) === '>')
) {
console.log('<---发送完整数据: ', datastr);
if (socketTask) {
let sendData: UploadMessage = {
deviceCode: deviceId,
deviceCode: device.code,
userId: userinfo.customerId.toString(),
type: 1,
data: datastr,
};
socketTask.send({
data: JSON.stringify(sendData),
data: str2ab(JSON.stringify(sendData)),
success: msg => {
console.log('发送完整数据:', msg, '--->');
},
......@@ -497,23 +567,28 @@ class Connect extends Component {
},
});
}
} else if (datastr.substring(0, 1) === '{') {
} else if (
datastr.substring(0, 1) === '{' ||
datastr.substring(0, 1) === '<'
) {
abStr = datastr;
} else if (
abStr.length &&
datastr.substring(datastr.length - 1, datastr.length) === '}'
(abStr.length &&
datastr.substring(datastr.length - 1, datastr.length) === '}') ||
(abStr.length &&
datastr.substring(datastr.length - 1, datastr.length) === '>')
) {
abStr += datastr;
console.log('<---发送完整数据: ', abStr);
let sendData: UploadMessage = {
deviceCode: deviceId,
deviceCode: device.code,
userId: userinfo.customerId.toString(),
type: 1,
data: abStr,
};
if (socketTask) {
socketTask.send({
data: JSON.stringify(sendData),
data: str2ab(JSON.stringify(sendData)),
success: msg => {
console.log('发送完整数据:', msg, '--->');
},
......@@ -523,8 +598,9 @@ class Connect extends Component {
});
}
abStr = '';
} else {
console.log('弃掉数据:', datastr);
} else if (abStr.length) {
console.log('追加数据:', datastr);
abStr += datastr;
}
}
});
......@@ -589,6 +665,7 @@ class Connect extends Component {
deviceId: string;
serviceId: string;
}) {
console.log(deviceId, serviceId);
return Taro.getBLEDeviceCharacteristics({
deviceId,
serviceId,
......@@ -604,7 +681,7 @@ class Connect extends Component {
if (charc.properties.write) {
writeId = charc.uuid;
}
if (charc.properties.write) {
if (charc.properties.read) {
readId = charc.uuid;
}
}
......@@ -617,6 +694,7 @@ class Connect extends Component {
}
openNotify({ notifyId, writeId, readId }) {
console.log(notifyId, writeId, readId);
this.setState(({ deviceInfo }: PageState) => ({
deviceInfo: {
...deviceInfo,
......@@ -697,6 +775,7 @@ class Connect extends Component {
type: MessageType.success,
text: '蓝牙连接成功',
});
this.addConnectMsg();
this.sendDeviceCode();
// if (!reConnect) {
// setTimeout(() => {
......@@ -740,11 +819,60 @@ class Connect extends Component {
}
selectPayConfig(id: number) {
this.setState({
if (id === this.state.payId) return;
this.setState(
{
payId: id,
},
() => {
this.getPayMoney();
}
);
}
getPayMoney() {
let money = 0;
if (this.state.payId) {
let payConfig = this.props.prepayConfig.find(
payConfig => payConfig.id === this.state.payId
);
money += payConfig ? payConfig.prepayMoney : 0;
}
if (this.state.payIds.length) {
this.props.addprepayConfig
.filter(payConfig => this.state.payIds.includes(payConfig.id))
.map(payConfig => {
money += payConfig.prepayMoney;
return payConfig;
});
}
this.setState({
payMoney: money,
});
}
checkAddPayConfig(id: number) {
let index = this.state.payIds.findIndex(payId => payId === id);
let payIds: number[] = [];
if (index === -1) {
payIds = [...this.state.payIds, id];
} else {
payIds = [
...this.state.payIds.slice(0, index),
...this.state.payIds.slice(index + 1),
];
}
this.setState(
{
payIds,
},
() => {
this.getPayMoney();
}
);
}
showerPayHandle() {
this.closeBluetooth();
return Taro.showModal({
......@@ -762,7 +890,7 @@ class Connect extends Component {
device,
userinfo: { customerId },
} = this.props;
const { payId, deviceDone, sockedDone } = this.state;
const { payId, payIds, deviceDone, sockedDone } = this.state;
if (payId) {
if (device.isOnlyBluetooth && device.isOnlyBluetooth === 1) {
console.log(deviceDone, sockedDone);
......@@ -777,6 +905,7 @@ class Connect extends Component {
serviceId: device.serviceId,
smaproCustomerId: customerId,
smaproPrepayConfigId: payId,
smaproPrepayConfigIds: [...payIds, payId],
areaId: device.areaId,
areaName: device.areaName,
};
......@@ -839,25 +968,32 @@ class Connect extends Component {
}
}
gobackHandle() {
if (this.checkIsShower()) {
setTimeout(() => {
Taro.navigateTo({
url: '/pages/index/index?', // 需要问号不然回到首页可以取到业务参数
changePageState(state: boolean) {
if (state) {
Taro.setNavigationBarTitle({
title: '设备使用',
});
}, 2000);
setTimeout(() => {
this.closeBluetooth();
this.closeDeviceSocket();
}, 10000);
} else {
Taro.setNavigationBarTitle({
title: '设备连接',
});
}
this.setState({
canPay: state,
});
}
gobackHandle() {
msgList = [];
setTimeout(() => {
Taro.navigateTo({
this.setState({
canPay: false,
});
Taro.redirectTo({
url: '/pages/index/index?', // 需要问号不然回到首页可以取到业务参数
});
}, 2000);
}
}
getPhoneHandle(e) {
console.log(e);
......@@ -872,17 +1008,120 @@ class Connect extends Component {
}
addMessageItem(msg: Message) {
msgList.push(msg);
this.setState({
messageQueue: [...this.state.messageQueue, msg],
lastMessage: 'Connect-Message-item' + this.state.messageQueue.length,
messageQueue: [...msgList],
lastMessage: 'Connect-Message-item' + msgList.length,
});
}
render() {
const { device, prepayConfig, userinfo } = this.props;
const { payId, messageQueue, lastMessage, canPay } = this.state;
return device.isOnlyBluetooth && !canPay ? (
const { device, prepayConfig, addprepayConfig, userinfo } = this.props;
const {
payId,
payIds,
messageQueue,
lastMessage,
canPay,
payMoney,
} = this.state;
console.log(canPay, device.isOnlyBluetooth);
return (
<View className="Connect">
<View className="state">{canPay}</View>
{/* <Button onClick={() => currentThis.gobackHandle()}>重载</Button> */}
{device.isOnlyBluetooth && canPay ? (
<View>
<View className="Connect-title">{`${
device.serviceName ? device.serviceName : ''
} ${device.code ? device.code : ''}(${device.position})`}</View>
<View className="Connect-tip3">
说明:请在1分钟内选择功能并进行支付;支付后30秒内设备没有正常启动,重新扫码后无需支付可自动开启设备。
</View>
<View className="Connect-Pay">
<View className="Connect-Pay-title">
请选择主功能
<Text className="Connect-Pay-titleTip">(只能选择一个)</Text>
</View>
<View className="Connect-Pay-content">
{prepayConfig &&
prepayConfig.length &&
prepayConfig.map(payConfig => (
<View
className="Connect-Pay-item"
key="id"
onClick={() => this.selectPayConfig(payConfig.id)}>
<View className="Connect-Pay-itemName">
{payConfig.name}
</View>
<View className="Connect-Pay-itemTime">
{payConfig.duration}分钟
</View>
<View className="Connect-Pay-itemPrice">
{payConfig.prepayMoney.toFixed(2)}
</View>
<View className="Connect-Pay-itemSelect">
{payId === payConfig.id ? (
<Image
className="Connect-Pay-itemSelecticon"
src={selectedIcon}></Image>
) : (
<Image
className="Connect-Pay-itemSelecticon"
src={selectIcon}></Image>
)}
</View>
</View>
))}
</View>
</View>
<View className="Connect-Pay">
<View className="Connect-Pay-title">请选择附加功能</View>
<View className="Connect-Pay-content">
{addprepayConfig &&
addprepayConfig.length &&
addprepayConfig.map(payConfig => (
<View
className="Connect-Pay-item"
key="id"
onClick={() => this.checkAddPayConfig(payConfig.id)}>
<View className="Connect-Pay-itemName">
{payConfig.name}
</View>
<View className="Connect-Pay-itemPrice">
{payConfig.prepayMoney.toFixed(2)}
</View>
<View className="Connect-Pay-itemSelect">
{payIds.find(id => id === payConfig.id) ? (
<Image
className="Connect-Pay-itemSelecticon"
src={selected2Icon}></Image>
) : (
<Image
className="Connect-Pay-itemSelecticon"
src={select2Icon}></Image>
)}
</View>
</View>
))}
</View>
</View>
{userinfo.isAuth ? (
<Button className="Connect-btn" onClick={this.payHandle}>
确定支付 共{payMoney.toFixed(2)}
</Button>
) : (
<Button
className="Connect-btn"
open-type="getPhoneNumber"
onGetphonenumber={this.getPhoneHandle}>
确定支付 共{payMoney.toFixed(2)}
</Button>
)}
</View>
) : (
<View>
<View className="Connect-info">
<View className="Connect-info-item">
<Text>服务类型</Text>
......@@ -911,78 +1150,11 @@ class Connect extends Component {
))}
</ScrollView>
<View className="Connect-tip2">
{device.refundMode === DeviceRefundMode.notRefund
? '说明:设备成功开启后,未使用金额将不会退换!'
: '说明:如本次预付款未全部使用,系统将在使用结束后半小时内自动退还剩余金额,请留意查收!'}
</View>
</View>
) : (
<View className="Connect">
<View className="Connect-info">
<View className="Connect-info-item">
<Text>服务类型</Text>
<Text>{device.serviceName ? device.serviceName : ''}</Text>
</View>
<View className="Connect-info-item">
<Text>设备编号</Text>
<Text>{device.code ? device.code : ''}</Text>
</View>
<View className="Connect-info-item">
<Text>设备位置</Text>
<Text className="Connect-info-position">{device.position}</Text>
</View>
{device.rates.length && (
<View className="Connect-info-item">
<Text>适用费率</Text>
<View className="Connect-info-rate">
{device.rates.map(item => (
<View key="name" className="Connect-info-rate-item">
<Text className="Connect-info-rate-name">
{item.duration}分钟
</Text>
<Text className="Connect-info-rate-mark">
{item.money}
</Text>
</View>
))}
说明:如果在1分钟内没有跳转到支付页面,请开启手机蓝牙后再次微信扫码。
</View>
</View>
)}
</View>
<View className="Connect-tip">
{device.refundMode === DeviceRefundMode.notRefund
? '温馨提示:设备成功开启后,未使用金额将不会退换!'
: '温馨提示:如本次预付款未全部使用,系统将在使用结束后半小时内自动退还剩余金额,请留意查收!'}
</View>
<View className="Connect-money">
{prepayConfig &&
prepayConfig.length &&
prepayConfig.map(payConfig => (
<View
key="id"
className={`Connect-money-item ${
payConfig.id == payId ? 'seleted' : ''
}`}
onClick={() => this.selectPayConfig(payConfig.id)}>
{payConfig.prepayMoney}
</View>
))}
</View>
{userinfo.isAuth ? (
<Button className="Connect-btn" onClick={this.payHandle}>
确定支付
</Button>
) : (
<Button
className="Connect-btn"
open-type="getPhoneNumber"
onGetphonenumber={this.getPhoneHandle}>
确定支付
</Button>
)}
<ad unit-id="adunit-8d48f17389f7e2aa"></ad>
</View>
);
}
}
......
......@@ -5,9 +5,18 @@ export type PrepayConfig = {
id: number;
// 会员id
isMajor: number;
// 是否主要功能 1:主要功能;2:附加功能
isOpen: number;
// 是否开启
isShowRate: number;
// 是否显示费率 0:否;1:是。默认1
name: string;
// 名称
operateId: number;
// 运营商id
......@@ -28,6 +37,8 @@ export type PrepayConfig = {
updateAt: string;
// 更新时间
duration: number;
};
export default PrepayConfig;
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