Commit cb285263 by 姜雷

Merge branch 'test'

parents 28674a32 5426891e
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": true,
"arrowParens": "avoid",
"requirePragma": false,
"proseWrap": "preserve"
}
{
"name": "wx-school-app-public",
"version": "1.0.11",
"version": "1.0.12",
"private": true,
"description": "",
"scripts": {
......
......@@ -24,6 +24,8 @@ type Params = {
areaName: string;
// 区域名称
duration?: number;
};
type ResponseData = {
outTradeNo: string;
......@@ -33,7 +35,7 @@ type ResponseData = {
// 微信小程序端支付信息
};
export const getPayOrder = (
entity: Params,
entity: Params
): Promise<ResponseDataEntity<ResponseData>> =>
baseFetch({
url: '/smapro/prepay/order/wx/apply/pay',
......
import { baseFetch, ResponseDataEntity } from '.';
import { Rate } from '../types/Device/Device';
export enum ScanTrigger {
false = 0,
true = 1,
}
type Params = {
customerId: number;
equipmentNum: string;
serviceId: number;
isScanTrigger: ScanTrigger;
};
type DeviceInfoResponse = {
code: string;
......@@ -29,7 +36,7 @@ type DeviceInfoResponse = {
positionId: string;
// 位置id
rates: RateInfoResponse[];
rates: Rate[];
// 是否纯蓝牙设备 1:是,0:否
isOnlyBluetooth: number;
......@@ -40,13 +47,6 @@ type DeviceInfoResponse = {
// 区域名称
areaName: string;
};
type RateInfoResponse = {
mark: string;
// 费率描述
name: string;
// 费率名称
};
type SmaproPrepayConfig = {
createAt: string;
// 创建时间
......@@ -84,7 +84,7 @@ type ResponseData = {
};
export const getDeviceConfig = (
entity: Params,
entity: Params
): Promise<ResponseDataEntity<ResponseData>> =>
baseFetch({
url: '/smapro/prepay/config/wxmini',
......
......@@ -27,6 +27,7 @@ class App extends Component {
'pages/scanEnter/scanEnter',
'pages/index/index',
'pages/pay/pay',
'pages/connect/connect',
],
window: {
backgroundTextStyle: 'light',
......
......@@ -4,3 +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';
.Connect {
.Connect-info {
padding: 40px 32px;
font-size: 28px;
color: #333;
padding-bottom: 30px;
border-bottom: 1px dotted #e1e1e1;
.Connect-info-item {
line-height: 60px;
display: flex;
justify-content: space-between;
.Connect-info-rate {
line-height: 40px;
.Connect-info-rate-item {
display: flex;
}
.Connect-info-rate-name {
margin-right: 5px;
}
.Connect-info-rate-mark {
width: 250px;
text-align: right;
}
}
.Connect-info-position {
text-align: right;
width: 500px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.Connect-tip {
margin: 38px 32px 30px;
color: #ff4b4b;
font-size: 24px;
line-height: 34px;
}
.Connect-tip2 {
padding: 36px 22px;
margin: 38px 32px 30px;
color: #999;
font-size: 24px;
line-height: 30px;
border: 1px solid #a4a4a4;
border-radius: 30px;
vertical-align: middle;
}
.Connect-money {
display: flex;
flex-wrap: wrap;
width: 714px;
margin: 0 auto;
.Connect-money-item {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
width: 218px;
height: 110px;
font-size: 28px;
border-radius: 24px;
border: 1px solid #ccc;
margin-bottom: 16px;
margin-right: 16px;
&.seleted {
border-color: #6180f4;
color: #6180f4;
}
}
}
.Connect-btn {
margin: 20px 32px 80px;
}
.Connect-Message {
box-sizing: border-box;
width: 100%;
padding: 50px 42px;
font-size: 26px;
height: 440px;
overflow-y: auto;
.Connect-Message-item {
margin-bottom: 28px;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.info {
color: #1596e0;
}
.success {
color: #15e0ae;
}
.error {
color: #ec2929;
}
}
}
import Taro, { Component, Config } from '@tarojs/taro';
import { ComponentClass } from 'react';
import { View, Text, Button, ScrollView } from '@tarojs/components';
import { getPayOrder } from '../../api/Order/pay';
import { connect } from '@tarojs/redux';
import {
Device,
DeviceRefundMode,
OnlyBluetooth,
} from '../../types/Device/Device';
import PrepayConfig from '../../types/Order/Order';
import { Customer } from '../../types/Customer/Customer';
import AES from 'crypto-js/aes';
import Utf8 from 'crypto-js/enc-utf8';
import ECBmode from 'crypto-js/mode-ecb';
import PaddingPkcs7 from 'crypto-js/pad-pkcs7';
// import { paySuccess } from '../../api/Order/paySuccess';
import './connect.scss';
import { str2ab, ab2str } from '@/utils/arrayBuffer';
import { DRY_SOCKET_URL } from '@/constants';
enum ContorlCode {
using = '1',
broken = '2',
usable = '3',
opened = '4',
}
type UploadMessage = {
deviceCode: string;
userId: string;
type: number;
contorlCode?: ContorlCode;
data: string;
};
enum MessageType {
info = 'info',
success = 'success',
error = 'error',
}
type Message = {
type: MessageType;
text: string;
};
enum BlueToothError {
BlueToothNotOpen = 'BlueToothNotOpen',
DeviceNotFound = 'DeviceNotFound',
}
type DeviceInfo = {
deviceId: string;
uuid: string;
isPrimary: boolean;
serviceId: string;
notifyId: string;
writeId: string;
readId: string;
};
type PageStateProps = {
device: Device;
prepayConfig: PrepayConfig[];
userinfo: Customer;
};
type PageDispatchProps = {};
type PageState = {
payId: undefined | number;
bluetoothState: boolean;
deviceInfo: DeviceInfo;
sockedDone: boolean;
deviceDone: boolean;
showerState: boolean;
messageQueue: Message[];
lastMessage: string;
canPay: boolean;
};
type PageOwnProps = {};
type Iprop = PageStateProps & PageDispatchProps & PageOwnProps;
interface Connect {
props: Iprop;
state: PageState;
}
const StopCode = 1000;
let timer: NodeJS.Timeout | null = null;
let reConnectting: boolean = false;
let socketTask: Taro.SocketTask | null = null;
@connect(({ device, prepayConfig, userinfo }) => ({
device,
prepayConfig,
userinfo,
}))
class Connect extends Component {
config: Config = {
navigationBarTitleText: '设备链接',
};
constructor(props) {
super(props);
this.state = {
payId: undefined,
bluetoothState: false,
sockedDone: false,
deviceDone: false,
showerState: false,
deviceInfo: {
deviceId: '',
uuid: '',
isPrimary: false,
serviceId: '',
notifyId: '',
writeId: '',
readId: '',
},
messageQueue: [],
lastMessage: '',
canPay: false,
};
this.checkBluetoothAndWs();
}
componentWillMount() {
const { prepayConfig } = this.props;
if (prepayConfig.length) {
this.setState({
payId: prepayConfig[0].id,
});
}
}
componentWillUnmount() {
// this.closeBluetooth();
// this.closeDeviceSocket();
}
connectDeviceSocket() {
this.addMessageItem({
type: MessageType.info,
text: '服务器连接中...',
});
Taro.connectSocket({ url: DRY_SOCKET_URL }).then(task => {
socketTask = task;
task.onOpen(() => {
this.addMessageItem({
type: MessageType.success,
text: '服务器连接成功',
});
console.log('onOpen');
if (reConnectting) {
this.reConnectDeviceSocket(true);
}
this.setState({
sockedDone: true,
});
task.send({ data: str2ab('{}') });
this.sendDeviceCode();
});
task.onMessage(res => {
this.addMessageItem({
type: MessageType.info,
text: '正在与设备通信...',
});
const msg: string = ab2str(res.data);
console.log('获取socket消息: ', msg);
const msgObj: UploadMessage = JSON.parse(msg);
if (msgObj.type === 1) {
if (msgObj.data.length > 20) {
for (
let index = 0;
index <= Math.floor(msgObj.data.length / 20);
index++
) {
let str = msgObj.data.substring(index * 20, (index + 1) * 20);
this.sendMessageToDevice(str);
}
} else {
this.sendMessageToDevice(msgObj.data);
}
} else if (msgObj.type === 0) {
if (msgObj.contorlCode === ContorlCode.using) {
Taro.showModal({
title: '提示',
content: '设备正在使用',
});
} else if (msgObj.contorlCode === ContorlCode.broken) {
Taro.showModal({
title: '提示',
content: '设备已损坏',
});
} else if (msgObj.contorlCode === ContorlCode.usable) {
this.setState({
canPay: true,
});
} else if (msgObj.contorlCode === ContorlCode.opened) {
Taro.showModal({
title: '提示',
content: '设备已启动',
});
} else {
}
} else {
}
});
task.onClose(e => {
this.addMessageItem({
type: MessageType.error,
text: '服务器连接失败,请稍后扫码重试',
});
console.log('socked关闭', e, reConnectting, timer);
this.setState({
sockedDone: false,
});
socketTask = null;
if (e.code === StopCode) {
console.log('正确结束socket连接');
} else {
console.log('开始重连socket');
this.reConnectDeviceSocket(false);
}
});
});
}
reConnectDeviceSocket(cancel: boolean) {
if (cancel) {
timer && clearTimeout(timer);
timer = null;
reConnectting = false;
return;
}
console.log(reConnectting, timer);
if (reConnectting) {
this.connectDeviceSocket();
} else if (timer) {
clearTimeout(timer);
reConnectting = false;
timer = null;
console.log('请保证网络正常');
Taro.showModal({
title: '警告',
content: '请保持网络畅通正常',
});
} else {
timer = setTimeout(() => {
reConnectting = false;
}, 10000);
reConnectting = true;
console.log(reConnectting, timer);
this.connectDeviceSocket();
}
}
sendDeviceCode() {
const { sockedDone, deviceDone } = this.state;
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, '--->');
},
});
}
}
closeDeviceSocket() {
console.log('in close', socketTask, timer);
if (socketTask) {
socketTask.close({
code: StopCode,
complete: () => {
socketTask = null;
},
});
}
if (timer) {
clearTimeout(timer);
}
}
checkBluetoothAndWs() {
this.closeBluetooth()
.then(() => {
console.log('打开蓝牙和WebSocket');
this.openBluetooth();
this.connectDeviceSocket();
})
.catch(err => {
console.log(err);
console.log(err, '打开蓝牙和WebSocket');
this.openBluetooth();
this.connectDeviceSocket();
});
}
openBluetooth() {
this.addMessageItem({
type: MessageType.info,
text: '蓝牙链接中...',
});
Taro.openBluetoothAdapter()
.then(res => {
console.log(res);
this.setState(
{
bluetoothState: true,
},
() => {
this.startConnectDevice();
}
);
})
.catch(err => {
this.addMessageItem({
type: MessageType.error,
text: '蓝牙连接失败,请稍后扫码重试',
});
Taro.showModal({
title: '温馨提示',
content: '为了更好的体验本次服务,请打开手机蓝牙!',
});
console.error(err);
Taro.onBluetoothAdapterStateChange(res => {
console.log('adapterState changed, now is', res);
if (res.available) {
this.setState({
bluetoothState: true,
});
}
});
});
}
checkBluetoothState() {
const { bluetoothState } = this.state;
return bluetoothState;
}
closeBluetoothConnection() {
const { deviceInfo } = this.state;
this.setState({
showerState: false,
});
Taro.closeBLEConnection({
deviceId: deviceInfo.deviceId,
})
.then(() => {
this.setState({
deviceDone: false,
});
})
.catch(err => {
console.log('断开蓝牙连接失败!');
console.error(err);
});
}
closeBluetooth() {
return Taro.closeBluetoothAdapter();
}
warnBluetoothOpen() {
return Taro.showModal({
title: '警告',
content: '为保障正常使用,请打开蓝牙功能',
});
}
startDevicesDiscovery() {
console.log('in startDevicesDiscovery', this.checkBluetoothState());
if (this.checkBluetoothState()) {
return Taro.startBluetoothDevicesDiscovery()
.then(() => {
const {
code,
// isOnlyBluetooth
} = this.props.device;
let timer: NodeJS.Timeout | null = null;
return new Promise((resolve, reject) => {
// if (isOnlyBluetooth) {
// timer = setTimeout(() => {
// reject({ msg: BlueToothError.DeviceNotFound });
// }, 10000);
// } else {
timer = setTimeout(() => {
reject({ msg: BlueToothError.DeviceNotFound });
}, 5000);
// }
Taro.onBluetoothDeviceFound(res => {
const devices = res.devices;
if (devices[0].name === code) {
let deviceId = devices[0].deviceId;
Taro.stopBluetoothDevicesDiscovery();
this.setState({
deviceId,
});
if (timer) {
clearInterval(timer);
}
resolve(deviceId);
}
});
});
})
.catch(err => {
// Taro.stopBluetoothDevicesDiscovery();
if (timer) {
clearInterval(timer);
}
Taro.hideLoading();
console.error('startBluetoothDevicesDiscovery: ', err);
// if (err.msg === BlueToothError.DeviceNotFound) {
Taro.stopBluetoothDevicesDiscovery();
// this.sendStartShower();
throw err;
// } else {
// return this.warnBluetoothOpen();
// }
});
} else {
Taro.hideLoading();
return this.warnBluetoothOpen().then(res => {
if (res.confirm) {
// const { isOnlyBluetooth } = this.props.bluetoothDevice;
// if (!isOnlyBluetooth) {
// Taro.showLoading({
// title: '开启中',
// mask: true,
// });
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// this.sendStartShower();
// reject();
// }, 5000);
// });
// }
}
throw BlueToothError.BlueToothNotOpen;
});
}
}
createConnection(deviceId: string) {
const { userinfo } = this.props;
console.log(deviceId);
return new Promise((resolve, reject) => {
Taro.createBLEConnection({
deviceId,
});
let abStr = '';
Taro.onBLECharacteristicValueChange(res => {
console.log(
`characteristic ${res.characteristicId} has changed, now is ${res.value}`
);
console.log(res.value);
let datastr = ab2str(res.value);
console.log('获取bluetooth消息: ', datastr);
if (datastr === '<>') {
console.log('结束蓝牙以及socket: ', datastr);
// this.closeDeviceSocket();
this.closeBluetoothConnection();
} else {
if (
datastr.substring(0, 1) === '{' &&
datastr.substring(datastr.length - 1, datastr.length) === '}'
) {
console.log('<---发送完整数据: ', datastr);
if (socketTask) {
let sendData: UploadMessage = {
deviceCode: deviceId,
userId: userinfo.customerId.toString(),
type: 1,
data: datastr,
};
socketTask.send({
data: JSON.stringify(sendData),
success: msg => {
console.log('发送完整数据:', msg, '--->');
},
fail: err => {
console.log('发送完整数据:', err, '--->');
},
});
}
} else if (datastr.substring(0, 1) === '{') {
abStr = datastr;
} else if (
abStr.length &&
datastr.substring(datastr.length - 1, datastr.length) === '}'
) {
abStr += datastr;
console.log('<---发送完整数据: ', abStr);
let sendData: UploadMessage = {
deviceCode: deviceId,
userId: userinfo.customerId.toString(),
type: 1,
data: abStr,
};
if (socketTask) {
socketTask.send({
data: JSON.stringify(sendData),
success: msg => {
console.log('发送完整数据:', msg, '--->');
},
fail: err => {
console.log('发送完整数据:', err, '--->');
},
});
}
abStr = '';
} else {
console.log('弃掉数据:', datastr);
}
}
});
Taro.onBLEConnectionStateChange(res => {
// const { showerState } = this.state;
console.log(
`device ${res.deviceId} state has changed, connected: ${res.connected}`
);
if (res.connected) {
this.setState({
deviceDone: true,
showerState: true,
});
resolve(res.deviceId);
} else {
console.log(res);
this.setState({
deviceDone: false,
});
// if (showerState) {
this.reConnectDeviceBluetooth(); // 只要断了就重连
// }
reject('蓝牙未成功连接');
}
});
});
}
sendMessageToDevice(msg: string) {
const { deviceInfo } = this.state;
console.log(msg, str2ab(msg).byteLength);
if (deviceInfo.writeId) {
Taro.writeBLECharacteristicValue({
deviceId: deviceInfo.deviceId,
serviceId: deviceInfo.serviceId,
characteristicId: deviceInfo.writeId,
value: str2ab(msg),
});
}
}
reConnectDeviceBluetooth() {
if (this.checkBluetoothState()) {
const { deviceInfo } = this.state;
this.createConnection(deviceInfo.deviceId);
}
}
getDeviceServices(deviceId: string) {
return Taro.getBLEDeviceServices({
deviceId: deviceId,
}).then(services => {
return { deviceId: deviceId, services: services.services };
});
}
getDeviceCharacter({
deviceId,
serviceId,
}: {
deviceId: string;
serviceId: string;
}) {
return Taro.getBLEDeviceCharacteristics({
deviceId,
serviceId,
}).then(res => {
let notifyId = '',
writeId = '',
readId = '';
for (let i = 0; i < res.characteristics.length; i++) {
let charc = res.characteristics[i];
if (charc.properties.notify) {
notifyId = charc.uuid;
}
if (charc.properties.write) {
writeId = charc.uuid;
}
if (charc.properties.write) {
readId = charc.uuid;
}
}
return {
notifyId,
writeId,
readId,
};
});
}
openNotify({ notifyId, writeId, readId }) {
this.setState(({ deviceInfo }: PageState) => ({
deviceInfo: {
...deviceInfo,
notifyId,
writeId,
readId,
},
}));
const { deviceInfo } = this.state;
return Taro.notifyBLECharacteristicValueChange({
deviceId: deviceInfo.deviceId,
serviceId: deviceInfo.serviceId,
characteristicId: notifyId,
state: true,
});
}
userWarnningHandle(thresholdPrompt, money, beanAmount) {
Taro.hideLoading();
console.log('in userWarnningHandle');
let arr = [money, beanAmount];
let i = -1;
return Taro.showModal({
title: '提示',
content: thresholdPrompt.replace(/(\{.*?\})/g, () => {
i++;
return arr[i];
}),
}).then(res => {
if (res.confirm) {
Taro.showLoading({
title: '开启中',
mask: true,
});
return Promise.resolve();
} else {
return Promise.reject();
}
});
}
startConnectDevice() {
const { sockedDone } = this.state;
if (!sockedDone) {
this.connectDeviceSocket();
}
this.startDevicesDiscovery()
.then((deviceId: string) => this.createConnection(deviceId))
.then(this.getDeviceServices)
.then(res => {
const deviceId = res.deviceId;
const services = res.services;
let service = services.find(
item =>
item.uuid.toLocaleLowerCase() ===
'6e401103-b5a3-f393-e0a9-e50e24dcca9e'
);
if (!service) {
service = services[0];
}
console.log('获取全部services: ', services, '. serviceId: ', service);
const serviceId = service.uuid;
this.setState(({ deviceInfo }: PageState) => ({
deviceInfo: {
...deviceInfo,
deviceId,
serviceId,
},
}));
return this.getDeviceCharacter({
deviceId,
serviceId,
});
})
.then(res => this.openNotify(res))
.then(() => {
this.addMessageItem({
type: MessageType.success,
text: '蓝牙连接成功',
});
this.sendDeviceCode();
// if (!reConnect) {
// setTimeout(() => {
// this.sendStartShower();
// }, 2000);
// }
})
.catch(err => {
console.error(err);
Taro.hideLoading();
});
}
sendStartShower() {
console.log('开启洗浴');
// const { code } = this.props.device;
// const { userinfo } = this.props;
// startShowerEquipment({
// deviceCode: code,
// customerId: userinfo.customerId.toString(),
// customerName: userinfo.customerName,
// customerPhone: userinfo.customerPhone,
// })
// .then(res => {
// console.log(res);
// Taro.showToast({
// title: '开启成功!',
// });
// this.setState({
// showerState: true,
// });
// })
// .catch(err => {
// console.error(err);
// Taro.showToast({
// title: err.msg || '开启失败!',
// icon: 'none',
// });
// this.closeBluetoothConnection();
// });
}
selectPayConfig(id: number) {
this.setState({
payId: id,
});
}
showerPayHandle() {
this.closeBluetooth();
return Taro.showModal({
title: '提示',
content: '设备蓝牙或网络连接失败...请稍后再试',
showCancel: false,
}).then(res => {
console.log(res);
this.openBluetooth();
});
}
payHandle(phoneData) {
const {
device,
userinfo: { customerId },
} = this.props;
const { payId, deviceDone, sockedDone } = this.state;
if (payId) {
if (device.isOnlyBluetooth && device.isOnlyBluetooth === 1) {
console.log(deviceDone, sockedDone);
if (!deviceDone || !sockedDone) {
return this.showerPayHandle();
}
}
let entity = {
equipmentNum: device.originCode,
equipmentPos: device.position,
payType: '2',
serviceId: device.serviceId,
smaproCustomerId: customerId,
smaproPrepayConfigId: payId,
areaId: device.areaId,
areaName: device.areaName,
};
if (device.rates[0]) {
entity.duration = device.rates[0].duration;
}
if (phoneData) {
entity = { ...entity, ...phoneData };
}
getPayOrder(entity)
.then(res => {
console.log('res: ', res);
const { payStr } = res;
let key = customerId.toString();
while (key.length < 16) {
key = key + '0';
}
const payData = JSON.parse(
AES.decrypt(payStr, Utf8.parse(key), {
mode: ECBmode,
padding: PaddingPkcs7,
}).toString(Utf8)
);
console.log('payData:', payData);
Taro.requestPayment({
timeStamp: payData.msg.timeStamp.toString(),
nonceStr: payData.msg.nonceStr,
package: payData.msg.package,
signType: payData.msg.signType,
paySign: payData.msg.paySign,
}).then(res => {
console.log(res);
// paySuccess({ orderId: outTradeNo });
// Taro.showLoading({
// title: '设备连接中',
// mask: true,
// });
Taro.showToast({
title: '支付成功!',
icon: 'success',
mask: true,
});
this.gobackHandle();
});
})
.catch(err => {
Taro.showToast({
title: '发起支付失败!',
icon: 'none',
});
console.error(err);
});
} else {
Taro.showToast({
title: '请选择预付金额',
icon: 'none',
});
}
}
gobackHandle() {
if (this.checkIsShower()) {
setTimeout(() => {
Taro.navigateTo({
url: '/pages/index/index?', // 需要问号不然回到首页可以取到业务参数
});
}, 2000);
setTimeout(() => {
this.closeBluetooth();
this.closeDeviceSocket();
}, 10000);
} else {
setTimeout(() => {
Taro.navigateTo({
url: '/pages/index/index?', // 需要问号不然回到首页可以取到业务参数
});
}, 2000);
}
}
getPhoneHandle(e) {
console.log(e);
const { encryptedData, iv } = e.detail;
if (encryptedData && iv) {
console.log('获得手机权限');
this.payHandle({
encryptedData,
iv,
});
}
}
addMessageItem(msg: Message) {
this.setState({
messageQueue: [...this.state.messageQueue, msg],
lastMessage: 'Connect-Message-item' + this.state.messageQueue.length,
});
}
render() {
const { device, prepayConfig, userinfo } = this.props;
const { payId, messageQueue, lastMessage, canPay } = this.state;
return device.isOnlyBluetooth && !canPay ? (
<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>
</View>
<ScrollView
scroll-y
scroll-into-view={lastMessage}
className="Connect-Message">
{messageQueue.map((item, index) => (
<View
key={'Connect-Message-item' + index}
id={'Connect-Message-item' + index}
className={'Connect-Message-item ' + item.type}>
{item.text}
</View>
))}
</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>
))}
</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>
);
}
}
export default Connect as ComponentClass<Iprop, PageState>;
......@@ -2,11 +2,9 @@ import { ComponentClass } from 'react';
import Taro, { Component, Config } from '@tarojs/taro';
import { View, Image } from '@tarojs/components';
import scanIcon from '../../images/icon_s@2x.png';
import './index.scss';
import { registerAndLogin } from '../../api/customer';
import { getDeviceConfig } from '../../api/device';
import { getDeviceConfig, ScanTrigger } from '../../api/device';
import { UserState, updateUserInfo } from '../../store/rootReducers/userinfo';
import { connect } from '@tarojs/redux';
import { Customer } from '../../types/Customer/Customer';
......@@ -17,6 +15,7 @@ import {
} from '../../store/rootReducers/device';
import PrepayConfig from '../../types/Order/Order';
import { updatePayData } from '../../store/rootReducers/prepayConfig';
import { getPathParams } from '@/utils/path';
type DeviceEntity = {
serviceId: number;
......@@ -64,7 +63,7 @@ interface Index {
resetDeviceData() {
dispatch(resetDeviceData());
},
}),
})
)
class Index extends Component {
config: Config = {
......@@ -80,13 +79,26 @@ class Index extends Component {
componentWillMount() {
this.loginHandle().then(() => {
let codeStr = this.$router.params.q;
let queryArr = Object.keys(this.$router.params);
console.log(this.$router.params);
let scene: string = queryArr.length > 0 ? queryArr[0] : '';
console.log('scene:', scene);
if (scene) {
if (codeStr) {
// Taro.showLoading();
let params = getPathParams(codeStr);
console.log('code', params);
if (params['code']) {
let entity = this.getDeviceEntity(params['code']);
if (entity) {
this.getDeviceConfigHandle(entity);
}
} else {
this.scanErrorWeQRcode();
}
} else if (scene) {
Taro.showLoading();
let entity = this.getDeviceEntity(scene);
if (entity) {
......@@ -171,6 +183,7 @@ class Index extends Component {
customerId: userinfo.customerId,
equipmentNum: equipmentNum,
serviceId: serviceId,
isScanTrigger: ScanTrigger.false,
})
.then(res => {
Taro.hideLoading();
......@@ -191,9 +204,7 @@ class Index extends Component {
} else {
updatePayData([]);
}
Taro.redirectTo({
url: '/pages/pay/pay',
});
this.goNextPage(serviceId);
})
.catch(err => {
console.error(err);
......@@ -219,10 +230,32 @@ class Index extends Component {
this.scanHandle();
}
scanErrorWeQRcode() {
Taro.showToast({
title: '请扫描正确的小程序',
icon: 'none',
});
this.setState({
errorText: '请扫描正确的小程序',
});
}
goNextPage(serviceId: number) {
if (serviceId === 30 || serviceId === 31) {
Taro.redirectTo({
url: '/pages/connect/connect',
});
} else {
Taro.redirectTo({
url: '/pages/pay/pay',
});
}
}
render() {
const { errorText } = this.state;
return (
<View className='index'>
<View className="index">
{errorText}
{/* <Button
className='scan-icon'
......
......@@ -857,7 +857,7 @@ class Pay extends Component {
<Text>适用费率</Text>
<View className='Pay-info-rate'>
{device.rates.map(item => (
<View key={item.name} className='Pay-info-rate-item'>
<View key='name' className='Pay-info-rate-item'>
<Text className='Pay-info-rate-name'>{item.name}</Text>
<Text className='Pay-info-rate-mark'>{item.mark}</Text>
</View>
......@@ -884,7 +884,7 @@ class Pay extends Component {
prepayConfig.length &&
prepayConfig.map(payConfig => (
<View
key={payConfig.id}
key='id'
className={`Pay-money-item ${
payConfig.id == payId ? 'seleted' : ''
}`}
......
......@@ -6,7 +6,7 @@ import scanIcon from '../../images/icon_s@2x.png';
import './scanEnter.scss';
import { registerAndLogin } from '../../api/customer';
import { getDeviceConfig } from '../../api/device';
import { getDeviceConfig, ScanTrigger } from '../../api/device';
import { UserState, updateUserInfo } from '../../store/rootReducers/userinfo';
import { connect } from '@tarojs/redux';
import { Customer } from '../../types/Customer/Customer';
......@@ -17,6 +17,7 @@ import {
} from '../../store/rootReducers/device';
import PrepayConfig from '../../types/Order/Order';
import { updatePayData } from '../../store/rootReducers/prepayConfig';
import { getPathParams } from '@/utils/path';
type DeviceEntity = {
serviceId: number;
......@@ -61,7 +62,7 @@ interface ScanEnter {
resetDeviceData() {
dispatch(resetDeviceData());
},
}),
})
)
class ScanEnter extends Component {
config: Config = {
......@@ -121,12 +122,17 @@ class ScanEnter extends Component {
.then(res => {
console.log(res);
const { path, result } = res;
let param = getPathParams(result);
if (path) {
let queryArr = path.split('?');
let queryStr = queryArr.length >= 2 ? queryArr[1] : '';
console.log(result, queryArr, queryStr);
const entity = this.getDeviceEntity(queryStr);
this.getDeviceConfigHandle(entity);
} else if (param['code']) {
console.log(param['code']);
const entity = this.getDeviceEntity(param['code']);
this.getDeviceConfigHandle(entity);
} else {
Taro.showToast({
title: '请扫描正确的小程序',
......@@ -151,6 +157,7 @@ class ScanEnter extends Component {
customerId: userinfo.customerId,
equipmentNum: equipmentNum,
serviceId: serviceId,
isScanTrigger: ScanTrigger.true,
})
.then(res => {
Taro.hideLoading();
......@@ -171,9 +178,7 @@ class ScanEnter extends Component {
} else {
updatePayData([]);
}
Taro.navigateTo({
url: '/pages/pay/pay',
});
this.goNextPage(serviceId);
})
.catch(err => {
console.error(err);
......@@ -196,20 +201,32 @@ class ScanEnter extends Component {
this.scanHandle();
}
goNextPage(serviceId: number) {
if (serviceId === 30 || serviceId === 31) {
Taro.redirectTo({
url: '/pages/connect/connect',
});
} else {
Taro.redirectTo({
url: '/pages/pay/pay',
});
}
}
render() {
return (
<View className='ScanEnter'>
<View className="ScanEnter">
{/* <Button
className='scan-icon'
onGetUserInfo={this.getUserInfoHandle}
open-type='getUserInfo'>
<Image src={scanIcon} />
</Button> */}
<View className='scan-icon' onClick={this.clickHandle}>
<View className="scan-icon" onClick={this.clickHandle}>
<Image src={scanIcon} />
</View>
<View className='scan-text'>马上扫一扫</View>
<View className='scan-text'>使用多彩自助服务</View>
<View className="scan-text">马上扫一扫</View>
<View className="scan-text">使用多彩自助服务</View>
</View>
);
}
......
......@@ -2,10 +2,25 @@ export enum DeviceRefundMode {
needRefund = 1,
notRefund = 2,
}
export enum OnlyBluetooth {
false = 0,
true = 1,
}
export type Rate = {
mark: string;
// 费率描述
name: string;
// 费率名称
duration: number;
// 消费时长,单位分钟
money: number;
// 费率金额
};
export type Device = {
refundMode: DeviceRefundMode;
originCode: string;
......@@ -20,7 +35,7 @@ export type Device = {
rates: Rate[];
serviceId: number;
serviceName: string;
isOnlyBluetooth: number;
isOnlyBluetooth: OnlyBluetooth;
areaId: number;
areaName: string;
};
export const getPathParams = (path: string) => {
let paramsArr = decodeURIComponent(path).split("?");
if (paramsArr.length > 1) {
let params = {};
paramsArr = paramsArr[1].split("&");
for (let index = 0; index < paramsArr.length; index++) {
const element = paramsArr[index].split("=");
if (element.length) {
params[element[0]] = element[1];
}
}
return params;
} else {
return {};
}
};
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