qsj 2 years ago
commit 62901485e0

@ -0,0 +1,36 @@
.common-progress-box {
padding: 50rpx;
}
.progress {
display: flex;
margin-top: 10rpx;
font-size: 24rpx;
font-family: PingFang SC;
font-weight: 500;
color: #999999;
align-items: center;
.van-progress {
width: 440rpx;
.van-progress__portion {
background: linear-gradient(90deg, #ffe9c7, #eecda1);
border-radius: 6rpx;
height: 12rpx;
.van-progress__pivot {
display: none;
}
}
}
.percent {
margin-left: 52rpx;
}
}
.progress-tips {
font-family: PingFang SC;
font-weight: 500;
font-size: 26rpx;
color: #666666;
line-height: 60rpx;
}

@ -0,0 +1,471 @@
import Taro from "@tarojs/taro";
import classnames from "classnames";
import { Component, PropsWithChildren, useEffect, useState } from "react";
import { Block, View, Text, PageMeta } from "@tarojs/components";
import { Popup, Progress } from "@antmjs/vantui";
import { connect } from "react-redux";
import {
msg,
back,
showModal,
go,
loading,
getStorageSync,
} from "@/utils/traoAPI";
import { InstrumentInfo } from "@/utils/Interface";
import {
notifyBLECharacteristicValueChange,
writeBLECharacteristicValue,
sendCommand,
} from "@/utils/bluetoothWXAPI";
import {
ab2hex,
ccrc8,
filterBleData,
hex2int,
string2buffer,
} from "@/utils/util";
import {
Stringkit,
TResponseFromDevice,
} from "@flossom-npm/iot-translater-we100";
// 通过设备类型判断给 deviceToolKitInstance 赋值
import { DeviceToolKit as DeviceToolKitWE100 } from "@flossom-npm/iot-translater-we100";
import { DeviceToolKit as DeviceToolKitFR200 } from "@flossom-npm/iot-translater";
import OtaDeviceTypeEnum from "../OtaDeviceTypeEnum";
// 临时替代
var log = console;
let deviceToolKitInstance: any = null;
const deviceToolKitInstanceFR200 = new DeviceToolKitFR200("FR200");
deviceToolKitInstanceFR200.setDebug(true);
import "./index.less";
class UpdateIotFR200 extends Component<any, any> {
constructor(props) {
super(props);
this.state = {
name: "UpdateIotFR200",
progressbar: 1, // 进度条
currentDevice: {},
hadStartOta: false, // 是否开始ota
};
}
$instance = Taro.getCurrentInstance();
$checkTimer: any = null;
// 与页面渲染无关的数据
$otaDataGroup: any = {
// 包大小面罩设置为100主机设置为240
packageSize: 240, //每个包的大小上限(单位是字节)
otaBin: null, //固件包buffer形式从16进制字符串转换成
otaHexString: "", //固件包的16进制字符串从后端接口返回
packageLength: 0, //升级包的总长度(单位是字节)
packageCount: 0, //分包后的总包数
otaData: [], //分包数组
packageCrc8: "", //总包的校验码
versionNo: "", //包的版本号
otaCurrentPackageIndex: 0, //现在正在传输的分包索引
countDown: 7,
};
async onLoad() {
if (this.$checkTimer) clearInterval(this.$checkTimer);
}
componentDidMount() {
console.log("componentDidMount");
this.initData();
}
componentDidHide() {
console.log("componentDidHide");
this.errorFun();
}
async initData() {
console.log("UpdateIotWL200");
deviceToolKitInstance = deviceToolKitInstanceFR200;
let objStr = getStorageSync("instrument_detail");
if (objStr) {
this.setState({
currentDevice: objStr,
});
}
setTimeout(() => {
this.notifyBLECharacteristicValueChange();
this.getDeviceUpgrade();
});
}
/**
*
*/
async getUpgradeData() {
//解析获取升级包更新数据
const { otaHexString, packageSize } = this.$otaDataGroup;
if (!otaHexString?.length) {
return [];
}
let arr: any = [];
for (let i = 0, len = otaHexString.length; i < len; i += packageSize * 2) {
let index = i + packageSize * 2;
let value = otaHexString.slice(i, index);
arr.push(value);
}
return arr;
}
/**
* OTA
*/
resetOta() {
this.$otaDataGroup = {
...this.$otaDataGroup,
otaCurrentPackageIndex: 0,
otaData: [],
};
}
/**
* ota
*/
startOTA() {
this.resetOta();
let jsoncmd = {
commandType: "OTAStart",
otaDeviceType: "FR200",
versionNo: this.$otaDataGroup.versionNo,
};
console.log("startOTA jsoncmd", jsoncmd);
//@ts-ignore
const value = deviceToolKitInstance.toBleCommand(jsoncmd as any);
console.log(jsoncmd);
sendCommand({ value }).then((res) => {
this.setState({
hadStartOta: true,
});
this.createTimer();
});
}
/**
* ota
*/
preOTA() {
const { packageCount, packageLength, packageCrc8, versionNo } =
this.$otaDataGroup;
let jsoncmd = {
commandType: "OTAPrepare",
packageCount,
packageLength,
packageCrc8,
versionNo,
};
console.info("OTAPrepare json => ", jsoncmd);
//@ts-ignore
const value = deviceToolKitInstance.toBleCommand(jsoncmd as any);
sendCommand({ value });
}
/**
* ota
*/
processOTA(i, data) {
const { packageCount, packageLength } = this.$otaDataGroup;
if (!packageLength) {
this.quitOTA();
}
let jsoncmd = {
commandType: "OTAUpdating",
packageCount,
packageLength,
currentPackageNo: i + 1,
currentPackageLength: data.length / 2,
currentPackageContent: data,
};
console.info("OTAUpdating json => ", jsoncmd);
//@ts-ignore
const value = deviceToolKitInstance.toBleCommand(jsoncmd as any);
sendCommand({ value });
}
/**
* ota
*/
async finishedOTA() {
let jsoncmd = {
commandType: "OTAUpdateFinish",
versionNo: this.$otaDataGroup.versionNo,
};
clearInterval(this.$checkTimer);
log.info("ota成功日志, 清除计时器");
//@ts-ignore
const value = deviceToolKitInstance.toBleCommand(jsoncmd as any);
sendCommand({ value }).then((res) => {
this.resetOta();
});
}
/**
* ota退
*/
quitOTA(errorString = "") {
// log.info('ota失败日志', errorString);
console.log("ota失败日志", errorString);
const errorMap = {
packageError: "总包错误",
packageNumError: "包号错误",
checkedError: "校验错误",
dataLengthError: "数据总长度错误",
dataCRCError: "数据总数CRC错误",
updateTimeOut: "数据更新超时",
};
let jsoncmd = {
commandType: "OTAQuit",
};
//@ts-ignore
const value = deviceToolKitInstance.toBleCommand(jsoncmd as any);
sendCommand({ value })
.then((res) => {
this.resetOta();
// this.showError(errorMap[errorString] || tipMap[errorString] || '发生错误')
})
.catch((err) => {
if (!this.state.hadShowError) {
this.setState({
hadShowError: true,
});
// log.info('ota失败日志', '发送日志OTAQuit失败', err);
console.info("ota失败日志", "发送日志OTAQuit失败", err);
if (err.errCode === 10000) {
let isDisconnect = getStorageSync("isDisconnectUpdate");
if (isDisconnect) {
if (this.$checkTimer) clearInterval(this.$checkTimer);
}
}
}
});
setTimeout(() => {
this.errorFun();
}, 1000);
}
/**
* OTA
*/
async parseData(json) {
console.log("parseData json.commandType", json.commandType);
if (!json || !json.commandType) return;
switch (json.commandType) {
case "OTAStart":
if (json.responseStatus == "OK") {
const otaData = await this.getUpgradeData();
this.$otaDataGroup = {
...this.$otaDataGroup,
otaData,
};
this.$otaDataGroup.otaCurrentPackageIndex = 0;
this.preOTA();
} else {
this.quitOTA(json.responseStatus);
}
break;
case "OTAPrepare":
if (json.responseStatus == "OK") {
this.processOTA(0, this.$otaDataGroup.otaData[0]);
} else {
this.quitOTA(json.responseStatus);
}
break;
case "OTAUpdating":
if (json.responseStatus == "OK") {
let ota = this.$otaDataGroup;
let progressbar =
(ota.otaCurrentPackageIndex / ota.packageCount) * 100;
this.setState({
progressbar: (progressbar <= 1 ? 1 : progressbar).toFixed(0),
});
if (!json.currentPackageNo) {
return;
}
if (json.currentPackageNo < this.$otaDataGroup.packageCount) {
this.$otaDataGroup.otaCurrentPackageIndex++;
this.processOTA(
this.$otaDataGroup.otaCurrentPackageIndex,
this.$otaDataGroup.otaData[
this.$otaDataGroup.otaCurrentPackageIndex
]
);
} else {
this.finishedOTA();
}
} else {
this.quitOTA(json.responseStatus);
}
break;
case "OTAUpdateFinish":
console.log("完成OTA传输");
this.setState({
progressbar: 100,
});
this.finishFun();
// quitOTA()
break;
default:
break;
}
}
/**
* ota
*/
getDeviceUpgrade = async () => {
let res: any = await InstrumentInfo.getUpgrade({
instrumentId: this.state.currentDevice.id,
isWe200: false,
});
if (res.data.data == "解析失败") {
// this.showError('文件解析失败');
return;
}
if (res.data.code !== 200) {
return;
}
const otaHexString = res.data.data;
const otaBin = string2buffer(res.data.data);
const packageLength = otaBin?.byteLength || 0;
const packageSize = this.$otaDataGroup.packageSize;
const packageCrc8 = Stringkit.getCrc8CodeByString(otaHexString);
const packageCount = Math.ceil(packageLength / packageSize);
let { iotVersion: versionNo } = this.state.currentDevice;
this.$otaDataGroup = {
...this.$otaDataGroup,
otaHexString,
otaBin,
packageLength,
packageSize,
packageCrc8,
packageCount,
versionNo,
};
console.log("this.$otaDataGroup ", this.$otaDataGroup);
};
notifyBLECharacteristicValueChange = () => {
const bluetoothInfo = this.props.bluetoothInfo;
notifyBLECharacteristicValueChange({
deviceId: bluetoothInfo.deviceId,
servicesuuid: bluetoothInfo.servicesuuid,
characteristicsuuid1: bluetoothInfo.characteristicsuuid1,
characteristicsuuid0: bluetoothInfo.characteristicsuuid0,
}).then((res) => {
Taro.onBLECharacteristicValueChange((value) => {
// let str = ab2hex(value.value); //转为16进制字符串
// console.log('返回',str)
const jsonStatus: any = deviceToolKitInstance.toJsonStatus(value.value);
log.info("OTA页面设备响应数据打印==》", JSON.stringify(jsonStatus));
console.info("onBLECharacteristicValueChange json => ", jsonStatus);
this.$otaDataGroup.currentPackageNo = jsonStatus.currentPackageNo;
this.$otaDataGroup.countDown = 7;
this.parseData(jsonStatus);
});
setTimeout(() => {
this.startOTA();
}, 500);
});
};
createTimer() {
log.info("设备ota计时器创建成功");
this.$checkTimer = setInterval(() => {
// 超过7s没有回包, 直接断开
if (this.$otaDataGroup.countDown <= 0 && this.state.hadStartOta) {
this.quitOTA("shutDownMaskTip");
} else {
this.$otaDataGroup.countDown--;
}
console.log(this.$otaDataGroup.countDown);
}, 1000);
}
//升级销毁页面时关闭小程序蓝牙
onUnload() {
console.log("onUnload");
if (this.$checkTimer) clearInterval(this.$checkTimer);
Taro.closeBluetoothAdapter();
}
onPullDownRefresh() {
Taro.stopPullDownRefresh();
}
onClickStop = (e) => {
e.stopPropagation();
};
// 错误关闭回调
errorFun = () => {
this.resetOta();
this.props.errorFun();
};
// 升级完成回调
finishFun = () => {
this.props.finishFun();
};
render() {
let { isShow } = this.props;
let { progressbar } = this.state;
return (
<Block>
<PageMeta pageStyle={isShow ? "overflow: hidden;" : ""} />
<Popup
show={isShow}
closeOnClickOverlay={false}
round
overlayStyle="width: 100vw;padding: 0;"
onClick={this.onClickStop}
>
<View
className={classnames(
"common-box",
"common-progress-box",
"common-large"
)}
catchMove
>
<View className={classnames("common-popup-title", "margin-samll")}>
</View>
<View className="common-popup-content-box">
<View className={classnames("common-popup-content", "text-left")}>
<View className="progress">
<Progress
percentage={progressbar}
strokeWidth="12"
color="linearGradient(to right, #eecda1, #ffe9c7) !important"
/>
<View className="percent"> {progressbar}%</View>
</View>
<View className="progress-tips"></View>
<View className="progress-tips">1.</View>
<View className="progress-tips">2.</View>
</View>
</View>
</View>
</Popup>
</Block>
);
}
}
const mapStateToProps = (state) => ({
bluetoothInfo: state.deviceInfo.bluetoothInfo,
});
const mapDispatchToProps = (dispatch) => ({});
export default connect(mapStateToProps, mapDispatchToProps)(UpdateIotFR200);

@ -15,65 +15,65 @@
display: flex;
justify-content: center;
}
}
.countdown-popup-loading {
position: relative;
}
.countdown-popup-loading-time {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
margin: auto;
font-size: 54rpx;
text-align: center;
color: #ecf0f3;
font-weight: bold;
}
.countdown-popup-loading {
position: relative;
}
.ui-loading__bg {
position: relative;
width: 160rpx;
height: 160rpx;
border-radius: 50%;
background-color: #ecf0f3;
/* background-image: conic-gradient(#3CACFF 100%,#000 0%); */
}
.ui-loading__bg::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 140rpx;
height: 140rpx;
border-radius: 50%;
background-color: #fff;
}
.countdown-popup-loading-time {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
margin: auto;
font-size: 54rpx;
text-align: center;
color: #ecf0f3;
font-weight: bold;
}
.ui-loading {
position: absolute;
width: 160rpx;
height: 160rpx;
border-radius: 50%;
background: transparent;
box-sizing: border-box;
border: 10rpx solid #3cacff;
clip-path: polygon(0% 0%, 25% 0%, 50% 50%, 0% 25%);
animation: rotate 1s linear infinite;
}
.ui-loading__bg {
position: relative;
width: 160rpx;
height: 160rpx;
border-radius: 50%;
background-color: #ecf0f3;
/* background-image: conic-gradient(#3CACFF 100%,#000 0%); */
}
.ui-loading__bg::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 140rpx;
height: 140rpx;
border-radius: 50%;
background-color: #fff;
}
@keyframes rotate {
from {
transform: rotateZ(0deg);
.ui-loading {
position: absolute;
width: 160rpx;
height: 160rpx;
border-radius: 50%;
background: transparent;
box-sizing: border-box;
border: 10rpx solid #3cacff;
clip-path: polygon(0% 0%, 25% 0%, 50% 50%, 0% 25%);
animation: countdownRotate 1s linear infinite;
}
to {
transform: rotateZ(360deg);
@keyframes countdownRotate {
from {
transform: rotateZ(0deg);
}
to {
transform: rotateZ(360deg);
}
}
}

@ -183,14 +183,15 @@ class IotCarePlanFR200 extends Component<any, any> {
ModeList: [],
ModeType: "all", // all 1基础护理 2专区护理 3专研促渗 4敏期护理 5智能测肤
ActiveModeItem: {
modeType: "",
openSourceData: [],
modeType:""
modeType: ""
}, // 当前选中模式
SwitchActiveModeItem: {}, // 切换选中模式
SwitchActiveModeItem: {
modeType: "",
}, // 切换选中模式
ModeID: "mode_", // 模式KEY
activeModeID: "", // 当前选中模式ID:用于高亮
ModeStepIndex: 0, // 当前护理功效步骤:每个步骤时间不定,所以时间另外计算,根据步骤显示
ModeStepTimeArray: [], // 护理功效时间步骤用于切换显示GIF
// TestModeStepIndex: 0, // 水分测试步骤
EssenceStepIndex: 0, // 精华促渗步骤
@ -201,12 +202,6 @@ class IotCarePlanFR200 extends Component<any, any> {
MaskModeBuzzingIndex: 0, // 面膜蜂鸣
MaskModeVibrateIndex: 0, // 面膜震动
currentServiceData: {
// 当前展示的开启暂停GIF: 因为时间判断不方便,所以单独领出来
startSource: "",
stopSource: "",
},
// 倒计时
isShowCountdown: false, // 倒计时弹窗
countdown: 3,
@ -386,7 +381,7 @@ class IotCarePlanFR200 extends Component<any, any> {
"intelligence",
];
/** 基础版:脸部/眼部/PRO 设备使用时,会自动开启暂停 */
/** 基础版:脸部/眼部/PRO 设备使用时,会自动开启,不能暂停 */
BaseModeType: string[] = [
"face",
"eyes",
@ -524,19 +519,25 @@ class IotCarePlanFR200 extends Component<any, any> {
});
if (this.state.activeModeID != "") {
let res1 = res.data.data.find((e) => e?.id == this.state.activeModeID);
setTimeout(() => {
this.modeCurrentFun(res1);
}, 100);
let res1 = res.data.data.find(
(e) => e?.id == this.state.activeModeID
);
if (res1) {
setTimeout(() => {
this.modeCurrentFun(res1);
}, 100);
}
} else {
setTimeout(() => {
this.modeCurrentFun(res.data.data[0]);
}, 100);
}
let res1 = res.data.data.find((e) => e?.id == this.state.activeModeID);
setTimeout(() => {
this.modeCurrentFun(res1);
}, 100);
if (res1) {
setTimeout(() => {
this.modeCurrentFun(res1);
}, 100);
}
} else {
this.setState({ ModeList: [] });
}
@ -611,7 +612,6 @@ class IotCarePlanFR200 extends Component<any, any> {
ActiveModeItem: data,
activeModeID: data?.id,
ModeID: "mode_" + data?.id,
ModeStepIndex: 0,
waterStepIndex: 0, // 水分测试步骤
EssenceStepIndex: 0, // 精华促渗步骤
MaskModeStepIndex: 0, // 面膜促渗步骤
@ -627,9 +627,10 @@ class IotCarePlanFR200 extends Component<any, any> {
this.changeItemUpdateFR200NursingHistory();
this.stepNext(); // 仅切换模式,不执行开始逻辑
// FR200水分测试不可自动运行,需手动点击开始测试,手动启动检测
// FR200 水分测试和促渗不可自动运行,需手动点击开始测试,手动启动检测
// 其他模式可以自动运行
if (data?.modeType !== "moistureTest") {
let notStartArr = ["moistureTest", "maskPenetration", "essence"];
if (!notStartArr.includes(data?.modeType)) {
setTimeout(() => {
this.onNursingTap("switch");
}, 800);
@ -739,7 +740,7 @@ class IotCarePlanFR200 extends Component<any, any> {
setTimeout(() => {
this.onNursingTap();
// // 倒计时弹窗: 倒计时完成后,自动开始,并判断弹窗
// let downNum = CountDownTime[this.state.ActiveModeItem.modeType] || 3;
// let downNum = CountDownTime[this.state.ActiveModeItem?.modeType] || 3;
// this.showCountdownFun(downNum, () => {});
}, 500);
@ -905,8 +906,8 @@ class IotCarePlanFR200 extends Component<any, any> {
}
// return 'landscape'
this.setState({ isFullScreen: !this.state.isFullScreen });
console.log(this.state.textscreen,1111);
console.log(this.state.textscreen, 1111);
}
/** 切换光照 */
@ -2340,7 +2341,6 @@ class IotCarePlanFR200 extends Component<any, any> {
isStopNurse,
ModeList,
ModeType,
ModeStepIndex,
ActiveModeItem,
currentWorkModeType,
isSwitchActiveMode,
@ -2371,14 +2371,19 @@ class IotCarePlanFR200 extends Component<any, any> {
showEcharts,
echartsData,
isShowReReadRecordConnect,
currentServiceData,
series,
isFullScreen,
} = this.state;
return (
<Block>
<PageMeta pageOrientation={textscreen}></PageMeta>
{
isFullScreen && <PageMeta pageOrientation='portrait'></PageMeta>
}
{
!isFullScreen && <PageMeta pageOrientation='landscape'></PageMeta>
}
<Block>
<Navbar
@ -2450,6 +2455,85 @@ class IotCarePlanFR200 extends Component<any, any> {
confirm={this.confirmModeSwitchBtn}
/>
{ActiveModeItem.openSourceData.length > 0 && (
<PopupStepTips
isShow={isShowStepTips}
isLarge
isFirstEntry={false}
confirmButtonText="知道了"
data={ActiveModeItem.openSourceData}
close={this.closeStepTips}
/>
)}
<PopupAlert
isShow={isNotEnoughTime}
isClose
title="提示"
content="您的本次护理时间不足,请重新护理"
confirmButtonText="确认"
textAlgin="center"
close={this.closeNotEnoughTime}
confirm={this.closeNotEnoughTime}
/>
<PopupAlert
isShow={isShowErrorTipsText}
isClose
zIndex={10020}
myClassName="level-up"
title="提示"
content={errorTipsText}
confirmButtonText="知道了"
textAlgin="center"
close={this.closeErrorTipsText}
confirm={this.closeErrorTipsText}
/>
<PopupConfirm
isShow={isShowTipsSave}
isClose
zIndex={10020}
myClassName="level-up"
title="提示"
content={
<Block>
<View></View>
<View></View>
</Block>
}
cancelButtonText="取消"
confirmButtonText="确认"
textAlgin="center"
close={this.closeTipsSave}
cancel={this.cancelTipsSave}
confirm={this.confirmTipsSave}
/>
<PopupStatus
isShow={isShowNursingSuccess}
isClose
title="您已结束本次护理"
type="success"
content="正在上传护理记录……"
confirmButtonText="知道了"
textAlgin="center"
close={() => {
/*不需要做处理*/
}}
/>
{isConnectShow && (
<ConnectionBluetoot
deviceInfo={currentDevice}
close={this.connectionClose}
isDisconnect={!isConnectionBlutoot}
offlineChange={() => { }}
pairingChange={this.pairingChange}
upgradeFun={() => { }}
/>
)}
<Popup
show={isShowHistoryMsg}
className="custom-popup"
@ -2508,7 +2592,7 @@ class IotCarePlanFR200 extends Component<any, any> {
</View>
}
{ModeList.length > 0 && isFullScreen&&(
{ModeList.length > 0 && isFullScreen && (
<ModeListView
isPop={false}
isShowNurse={isShowNurse}
@ -2530,7 +2614,7 @@ class IotCarePlanFR200 extends Component<any, any> {
{(ActiveModeItem?.modeType === "maskPenetration" ||
ActiveModeItem?.modeType === "essence") &&isFullScreen&&(
ActiveModeItem?.modeType === "essence") && isFullScreen && (
<Gears
onEmitMinus={this.handleMinus}
onEmitAdd={this.handleAdd}
@ -2538,7 +2622,7 @@ class IotCarePlanFR200 extends Component<any, any> {
></Gears>
)}
{ActiveModeItem?.modeType === "moistureTest" && isFullScreen&&(
{ActiveModeItem?.modeType === "moistureTest" && isFullScreen && (
<WaterTest
isRuningTest={isRuningTest}
stepList={waterStepList}

@ -738,107 +738,6 @@ class IotCarePlanWE200 extends Component<any, any> {
// 如果检查失败,则报错
this.onEmitErrorTips();
};
/** 完成护理,跳转到水分 */
onsuccess = async () => {
let waterStepList = this.state.waterStepList;
this.setState({
isShowNursingSuccess: true,
});
// return;
let { currentDevice, ActiveModeItem } = this.state;
let params: any = {};
params = {
instrumentId: currentDevice.id,
instrumentName: currentDevice.name,
modeId: ActiveModeItem.id,
modeName: ActiveModeItem.modeName,
nursingTime: s_to_hms(this.elapsedTime),
nursingData: JSON.stringify({
GearData: [...waterStepList],
}),
};
// params = { ...params, ...nursingData };
let res: any = await InstrumentInfo.apiNursingLog.addLog(
JSON.stringify(params)
);
setTimeout(async () => {
this.setState({
isShowNursingSuccess: false,
});
let date = new Date();
let year = date.getFullYear();
let month = (date.getMonth() + 1).toString().padStart(2, "0");
let day = date.getDate().toString().padStart(2, "0");
let formattedDate = `${year}.${month}.${day}`;
this.moistureTest(
params.nursingData,
formattedDate,
ActiveModeItem.id,
currentDevice.id
);
}, 2000);
};
async moistureTest(
nursingData,
formattedDate,
ActiveModeItemId,
currentDeviceId
) {
let data = {
queryDate: formattedDate,
instrumentId: currentDeviceId,
};
let res = await InstrumentInfo.fr200.moistureTest(data);
let echartsData = res.data.rows;
for (let i = 0; i < echartsData.length; i++) {
for (let j = i + 1; j < echartsData.length; j++) {
if (
echartsData[i].createTime.split(" ")[0] ==
echartsData[j].createTime.split(" ")[0]
) {
let result =
Date.parse(echartsData[i].createTime) -
Date.parse(echartsData[j].createTime);
if (result < 0) {
echartsData.splice(i, 1);
} else {
echartsData.splice(j, 1);
}
}
}
}
let gears: any = [];
let eDate: any = [];
echartsData?.map((item) => {
const result = item.createTime.split(" ")[0].substring(5);
eDate.push(result);
item.nursingData = JSON.parse(item.nursingData);
let level: any = 0;
item.nursingData?.GearData?.map((gear) => {
level = level + gear.forehead;
});
level = Math.floor(level / 3);
gears.push(level);
});
echartsData = {
gears,
eDate,
};
setStorageSync("moistureEachtsData", JSON.stringify(echartsData));
let report = true;
// go(`/recoding/pages/moisture_test_report/moisture_test_report?data=${allData.nursingData}&date=${allData.createTime}&modeId=${allData.modeId}&id=${allData.instrumentId}&echartsData=${JSON.stringify(echartsData)}`);
go(
`/recoding/pages/moisture_test_report/moisture_test_report?data=${nursingData}&date=${formattedDate}&modeId=${ActiveModeItemId}&id=${currentDeviceId}&echartsData=${JSON.stringify(
echartsData
)}&report=${report}`
);
}
/**
* @name
@ -852,41 +751,6 @@ class IotCarePlanWE200 extends Component<any, any> {
this.showTips("检测到您的设备没有紧贴肌肤,请紧贴肌肤后重新尝试");
});
};
updata() {
let that = this;
let stop = 0;
let time = setInterval(function () {
stop++;
let series = JSON.parse(JSON.stringify(that.state.series));
let num = Math.floor(Math.random() * 9);
let count = 0;
series.map((item) => {
if (item.type === "line") {
item.data.splice(0, 1);
item.data.push(num);
}
if (item.type === "bar") {
count++;
item.data.splice(0, 1);
if (count <= num) {
item.data.push(1);
} else {
item.data.push(0);
}
}
});
// 更新图表数据
that.setState({ series });
if (stop >= 20) {
clearInterval(time);
}
}, 1000);
}
full() {
this.setState({ isFullScreen: !this.state.isFullScreen });
}
/** 切换光照 */
onSwitchChange = async () => {
@ -911,37 +775,6 @@ class IotCarePlanWE200 extends Component<any, any> {
isStopNurse: !isStopNurse,
});
};
/** LED切换模式 */
onSwitchChangeLED = () => {
let { isStopNurse } = this.state;
if (isStopNurse) {
// 开始光照逻辑
this.onNursingTap();
this.switchVideoPlay(); // 开始
} else {
// 暂停光照逻辑
let sendParams: any = {
...deviceCommandSamples.pause,
workMode: "led", // 使用模式
workStatus: "standby",
};
const pauseArrayBuffer = deviceToolKitInstance.toBleCommand(
sendParams as any
);
sendCommand({
value: pauseArrayBuffer,
}).then(() => {
this.workStatus = "pause";
this.resetTimer();
console.info(`发送暂停指令成功 参数为 =>`, sendParams);
});
// this.handleWorkStatus(false, MODE_WORKING_ENUM.PAUSE);
this.switchVideoPause(); // 暂停
}
this.setState({
isStopNurse: !isStopNurse,
});
};
/**
* @name
@ -1235,265 +1068,11 @@ class IotCarePlanWE200 extends Component<any, any> {
}, 1000);
};
/**
* @name
* @description +1
*/
waterTestNext(index) {
let ActiveModeItem = this.state.ActiveModeItem;
if (index === 0 && ActiveModeItem.stepOneVideo) {
this.VideoSrcLoad(ActiveModeItem.stepOneVideo);
} else if (index === 1 && ActiveModeItem.stepTwoVideo) {
this.VideoSrcLoad(ActiveModeItem.stepTwoVideo);
} else if (index === 2 && ActiveModeItem.stepThreeVideo) {
this.VideoSrcLoad(ActiveModeItem.stepThreeVideo);
}
}
/**
* @name ,
* @description 1. 2./
* */
maskPenetrationNext() {
let {
MaskModeStepIndex,
MaskModeBuzzingIndex,
MaskModeVibrateIndex,
ActiveModeItem,
} = this.state;
// 模式多个步骤节点切换
// 已运行时间达到下一节点时,切换
let GearLength = ActiveModeItem.modeGear.length;
if (GearLength && MaskModeStepIndex < GearLength) {
let GearTime = minSecToS(ActiveModeItem.modeGear[MaskModeStepIndex].time);
if (this.elapsedTime > GearTime) {
// 已运行时间达到下一节点,且存在下一节点,步骤切换时更新
if (MaskModeStepIndex < GearLength) {
let index = MaskModeStepIndex + 1; // 提前步骤+1
this.setState({
MaskModeStepIndex: index,
});
this.FR200AutoChangeGear(index);
}
}
}
let BuzzingLength = ActiveModeItem.modeBuzzing.length;
if (BuzzingLength && MaskModeStepIndex < GearLength) {
let BuzzingTime = minSecToS(
ActiveModeItem.modeBuzzing[MaskModeStepIndex].time
);
if (this.elapsedTime > BuzzingTime) {
if (MaskModeBuzzingIndex < BuzzingLength) {
let index = MaskModeBuzzingIndex + 1; // 提前步骤+1
this.setState({
MaskModeBuzzingIndex: index,
});
this.FR200Buzzing();
}
}
}
let VibrateLength = ActiveModeItem.modeVibrate.length;
if (VibrateLength && MaskModeStepIndex < VibrateLength) {
let VibrateTime = minSecToS(
ActiveModeItem.modeVibrate[MaskModeStepIndex].time
);
if (this.elapsedTime > VibrateTime) {
if (MaskModeVibrateIndex < VibrateLength) {
let index = MaskModeVibrateIndex + 1; // 提前步骤+1
this.setState({
MaskModeVibrateIndex: index,
});
this.FR200Vibrate();
}
}
}
}
/** @name 精华促渗下一步,根据时间自动调用 */
essencePenetrationNext() {
let {
EssenceStepIndex,
EssenceBuzzingIndex,
EssenceVibrateIndex,
ActiveModeItem,
} = this.state;
// 模式多个步骤节点切换
// 已运行时间达到下一节点时,切换
let GearLength = ActiveModeItem.modeGear.length;
if (GearLength && EssenceBuzzingIndex < GearLength) {
let GearTime = minSecToS(
ActiveModeItem.modeGear[EssenceBuzzingIndex].time
);
if (this.elapsedTime > GearTime) {
// 已运行时间达到下一节点,且存在下一节点,步骤切换时更新
if (EssenceStepIndex < GearLength) {
let index = EssenceStepIndex + 1; // 提前步骤+1
this.setState({
EssenceStepIndex: index,
});
this.FR200AutoChangeGear(index);
}
}
}
let BuzzingLength = ActiveModeItem.modeBuzzing.length;
if (BuzzingLength && EssenceBuzzingIndex < BuzzingLength) {
let BuzzingTime = minSecToS(
ActiveModeItem.modeBuzzing[EssenceBuzzingIndex].time
);
if (this.elapsedTime > BuzzingTime) {
if (EssenceBuzzingIndex < BuzzingLength) {
let index = EssenceBuzzingIndex + 1; // 提前步骤+1
this.setState({
EssenceBuzzingIndex: index,
});
this.FR200Buzzing();
}
}
}
let VibrateLength = ActiveModeItem.modeVibrate.length;
if (VibrateLength && EssenceBuzzingIndex < VibrateLength) {
let VibrateTime = minSecToS(
ActiveModeItem.modeBuzzing[EssenceBuzzingIndex].time
);
if (this.elapsedTime > VibrateTime) {
if (EssenceVibrateIndex < VibrateLength) {
let index = EssenceVibrateIndex + 1; // 提前步骤+1
this.setState({
EssenceVibrateIndex: index,
});
this.FR200Vibrate();
}
}
}
}
/**切换挡位发起蜂鸣:可以切换到现在的挡位?*/
FR200Buzzing = () => {
console.log("FR200Buzzing 蜂鸣", this.elapsedTime);
const { ActiveModeItem, currentGear } = this.state;
let sendParams: any = {
...deviceCommandSamples.pause,
workMode: ActiveModeItem.modeType, // 使用模式
workStatus: "working",
gear: currentGear,
};
if (currentGear > 1) {
sendParams.gear = currentGear - 1;
let pauseArrayBuffer = deviceToolKitInstance.toBleCommand(
sendParams as any
);
sendCommand({
value: pauseArrayBuffer,
});
} else {
sendParams.gear = currentGear + 1;
let pauseArrayBuffer = deviceToolKitInstance.toBleCommand(
sendParams as any
);
sendCommand({
value: pauseArrayBuffer,
});
}
setTimeout(() => {
sendParams.gear = currentGear;
let pauseArrayBuffer = deviceToolKitInstance.toBleCommand(
sendParams as any
);
sendCommand({
value: pauseArrayBuffer,
});
}, 300);
};
/**
* @name FR200
* @description
*/
FR200AutoChangeGear = (index: number = 0) => {
console.log("FR200AutoChangeGear 切换挡位", this.elapsedTime);
const { ActiveModeItem, GearData } = this.state;
let gear = GearData[index].forehead;
// 同步挡位
this.setState({
currentGear: gear,
});
let sendParams: any = {
...deviceCommandSamples.pause,
workMode: ActiveModeItem.modeType, // 使用模式
workStatus: "working",
gear: gear,
};
const pauseArrayBuffer = deviceToolKitInstance.toBleCommand(
sendParams as any
);
sendCommand({
value: pauseArrayBuffer,
}).then(() => {
this.workStatus = "working";
this.resetTimer();
});
};
/**
* @name FR200
* @description
*/
FR200Vibrate = () => {
console.log("FR200Vibrate FR200震动", this.elapsedTime);
const { ActiveModeItem, currentGear } = this.state;
let sendParams: any = {
...deviceCommandSamples.pause,
workMode: ActiveModeItem.modeType, // 使用模式
workStatus: "working",
gear: currentGear,
};
const pauseArrayBuffer = deviceToolKitInstance.toBleCommand(
sendParams as any
);
sendCommand({
value: pauseArrayBuffer,
});
};
executePromises = async () => {
let waterStepList = this.state.waterStepList;
let waterStepIndex = this.state.waterStepIndex;
let that = this;
await new Promise<void>((resolve) => {
setTimeout(() => {
waterStepList[waterStepIndex].schedule = 100;
that.setState({
waterStepList,
});
resolve();
}, 3000);
}).then(() => {
return new Promise<void>((resolve) => {
setTimeout(() => {
waterStepList[waterStepIndex].finish = true;
that.setState({
waterStepList,
});
resolve();
}, 2000);
});
});
};
// 检测并控制工作状态
handleWorkStatus = async (isBtnClick: boolean, workStatus) => {
const { DeviceConnectStatus, ActiveModeItem } = this.state;
// 如果没有指定工作状态,则切换工作状态
let newWorkStatus =
workStatus ||
(this.workStatus == MODE_WORKING_ENUM.WORKING ? "pause" : "working");
@ -1504,33 +1083,8 @@ class IotCarePlanWE200 extends Component<any, any> {
workStatus: newWorkStatus,
};
// 水分测试需要特殊处理
// 水分测试准备 水分测试工作 水分测试启动
if (ActiveModeItem.modeType === "moistureTest") {
let that = this;
sendParams.testStatus = "standby"; // 切换为准备
// 3秒定时器逻辑3秒把进度条弄成100再加2秒获取最后结果
if (isBtnClick) {
that.setState({
isRuningTest: 2,
});
this.executePromises();
sendParams.testStatus = "start"; // 点击开始再开始
console.log("点击开始", isBtnClick);
}
}
// 面膜促渗和精华促渗
if (
ActiveModeItem.modeType === "maskPenetration" ||
ActiveModeItem.modeType === "essence"
) {
sendParams.gear = this.state.currentGear; // 点击开始再开始
}
console.log("准备发送自定义或工作指令", ActiveModeItem, sendParams);
const pauseArrayBuffer = deviceToolKitInstance.toBleCommand(
sendParams as any
);

@ -272,7 +272,12 @@ class IotCarePlanWL200 extends Component<any, any> {
title: obj.name,
});
Taro.showLoading({
title: "请求中...",
mask: true,
});
await this.GetModeList(obj.id);
Taro.hideLoading();
// 如果不存在设备模式值,则判断为首次进入,弹窗提示
let isFirstTipShow = getStorageSync("first_instrument_" + obj.id);
@ -1928,7 +1933,10 @@ class IotCarePlanWL200 extends Component<any, any> {
goFaceReport = () => {
// 跳转前置空定时器,防止重复提交
if (currentTimeTimer) clearInterval(currentTimeTimer);
go("/recording/pages/face_report/face_report?id=" + this.state.currentDevice.id);
go(
"/recording/pages/face_report/face_report?id=" +
this.state.currentDevice.id
);
};
// 完成配对

@ -1,4 +1,4 @@
.box {
.echart-component {
width: 690rpx;
height: 320rpx;
margin: 28rpx auto 150rpx;
@ -8,94 +8,84 @@
box-sizing: border-box;
position: relative;
// writing-mode: vertical-lr;
// text-orientation: upright;
// white-space: nowrap;
// font-size: 18px;
// font-weight: bold;
// background-color: #c2e5f3;
// color: #fff;
// width: 100%;
}
.fullscreen {
position: fixed;
top: 450rpx;
left: -450rpx;
right: 0;
bottom: 0;
width: 100vh;
height: 100vw;
z-index: 9999;
background-color: rgba(0, 0, 0, 0.5); /* 背景色 */
transform: rotate(90deg);
// animation: rotate 0s linear;
}
@keyframes rotate {
from {
width: 690rpx;
height: 320rpx;
transform: rotate(0deg);
}
to {
.fullscreen {
position: fixed;
top: 450rpx;
left: -450rpx;
right: 0;
bottom: 0;
width: 100vh;
height: 100vw;
transform: rotate(0deg);
z-index: 9999;
background-color: rgba(0, 0, 0, 0.5); /* 背景色 */
transform: rotate(90deg);
// animation: rotate 0s linear;
}
}
.box_background {
position: absolute;
top: 0;
left: 0;
width: 690rpx;
height: 320rpx;
border-radius: 30rpx;
background-color: #fff;
.power {
margin: 34rpx 0 28rpx 28rpx;
font-family: PingFang-SC;
font-weight: 500;
font-size: 18rpx;
color: #cccccc;
@keyframes echartRotate {
from {
width: 690rpx;
height: 320rpx;
transform: rotate(0deg);
}
to {
width: 100vh;
height: 100vw;
transform: rotate(0deg);
}
}
.full {
width: 24rpx;
height: 24rpx;
.box_background {
position: absolute;
top: 32rpx;
right: 26rpx;
z-index: 2;
}
.line {
margin: 0 0 6rpx 35rpx;
font-family: PingFang-SC;
font-size: 14rpx;
color: #cccccc;
display: flex;
position: relative;
height: 18rpx;
.bottom_line {
// border-bottom: 1rpx #ccc dashed;
width: 550rpx;
margin-left: 20rpx;
top: 0;
left: 0;
width: 690rpx;
height: 320rpx;
border-radius: 30rpx;
background-color: #fff;
.power {
margin: 34rpx 0 28rpx 28rpx;
font-family: PingFang-SC;
font-weight: 500;
font-size: 18rpx;
color: #cccccc;
}
.full {
width: 24rpx;
height: 24rpx;
position: absolute;
bottom: -6rpx;
right: 74rpx;
height: 4rpx;
color: #fff;
top: 32rpx;
right: 26rpx;
z-index: 2;
}
.line {
margin: 0 0 6rpx 35rpx;
font-family: PingFang-SC;
font-size: 14rpx;
color: #cccccc;
display: flex;
position: relative;
height: 18rpx;
.bottom_line {
// border-bottom: 1rpx #ccc dashed;
width: 550rpx;
margin-left: 20rpx;
position: absolute;
bottom: -6rpx;
right: 74rpx;
height: 4rpx;
color: #fff;
}
}
}
.time {
position: absolute;
bottom: 22rpx;
right: 24rpx;
font-family: PingFang-SC;
font-size: 18rpx;
color: #cccccc;
.time {
position: absolute;
bottom: 22rpx;
right: 24rpx;
font-family: PingFang-SC;
font-size: 18rpx;
color: #cccccc;
}
}
}

@ -9,13 +9,11 @@ import echarts from "@/utils/echarts.min.js";
import "./index.less";
interface Props {
series: any,
full:any
series: any;
full: any;
}
function Index({ series ,full}: Props) {
function Index({ series, full }: Props) {
const echartsRef = useRef<EchartsHandle>(null);
const [options, setOptions] = useState({
animation: false,
@ -145,40 +143,36 @@ function Index({ series ,full}: Props) {
color: "#ff8410",
},
},
series: []
})
series: [],
});
const level = [8, 7, 6, 5, 4, 3, 2];
const [newOptions, setNewOptions] = useState(options)
const [newOptions, setNewOptions] = useState(options);
const updata = useCallback((res) => {
let option = JSON.parse(JSON.stringify(options))
option.series = JSON.parse(JSON.stringify(res))
let option = JSON.parse(JSON.stringify(options));
option.series = JSON.parse(JSON.stringify(res));
// 更新图表数据
setNewOptions(option)
}, [])
setNewOptions(option);
}, []);
const cancelFull = useCallback((res) => {
full()
}, [])
full();
}, []);
useEffect(() => {
setOptions(newOptions)
setOptions(newOptions);
}, [newOptions]);
useEffect(() => {
updata(series)
}, [series])
updata(series);
}, [series]);
return (
<Block>
<View id='box' className='box'>
<View id="box" className="echart-component">
<Echarts
force-use-old-canvas='false'
force-use-old-canvas="false"
echarts={echarts}
option={options}
ref={echartsRef}
@ -186,22 +180,26 @@ function Index({ series ,full}: Props) {
// style自定义设置echarts宽高
style={{ width: "630rpx", height: "260rpx", zIndex: 1 }}
/>
<View className='box_background'>
<Image className='full' src={require("@/img/full-scran.png")} onClick={cancelFull}></Image>
<View className='power'></View>
<View className="box_background">
<Image
className="full"
src={require("@/img/full-scran.png")}
onClick={cancelFull}
></Image>
<View className="power"></View>
{level.map((item) => (
<View className='line' key={item}>
<View className='number'>{item}</View>
<View className='bottom_line'></View>
<View className="line" key={item}>
<View className="number">{item}</View>
<View className="bottom_line"></View>
</View>
))}
<View className='line'>
<View className='number'>1</View>
<View className="line">
<View className="number">1</View>
</View>
<View className='time'></View>
<View className="time"></View>
</View>
</View>
</Block >
</Block>
);
}

@ -13,7 +13,7 @@ import {
RichText,
PageMeta,
} from "@tarojs/components";
import { Popup,Radio } from "@antmjs/vantui";
import { Popup, Radio } from "@antmjs/vantui";
/*** redux ***/
import { connect } from "react-redux";
import { userRefresh, tokenRefresh } from "@/store/features/userInfo";
@ -39,6 +39,7 @@ import Navbar from "@/components/navbar/navbar";
import ConnectionBluetoot from "@/components/bluetoot/connection";
import UpdateIotWL200 from "@/components/bluetoot/update-wl200/index";
import UpdateIotFR200 from "@/components/bluetoot/update-fr200/index";
/** 自定义组件 **/
import {
@ -84,23 +85,25 @@ class Index extends Component<any, any> {
mobile: Taro.getStorageSync("mobile"),
},
// 膜布列表
MembraneClothList:[ {
name:'mox名字'
},
{
name:'mox名字'
},
{
name:'mox名字'
}, {
name:'mox名字'
}, {
name:'mox名字'
},],
checkedMembraneCloth:'',
list: [
MembraneClothList: [
{
name: "mox名字",
},
{
name: "mox名字",
},
{
name: "mox名字",
},
{
name: "mox名字",
},
{
name: "mox名字",
},
],
checkedMembraneCloth: "",
list: [],
params: "",
messageCount: Taro.getStorageSync("messageCount") || 0,
offlineDialogType: 1, //1离线弹窗 2升级弹窗
@ -872,7 +875,9 @@ class Index extends Component<any, any> {
// return;
if (platform === "devtools") {
setStorageSync("instrument_detail", item);
this.setState({ connectInstrument: item });
this.setState({
connectInstrument: item,
});
if (item.type === 1) {
//非IOT
setTimeout(() => {
@ -1043,6 +1048,26 @@ class Index extends Component<any, any> {
isShowVersionUpgradFinish: false,
});
};
UpgradeFinishFun = () => {
let { connectInstrument } = this.state;
console.log("connectInstrument", connectInstrument);
let content = connectInstrument.iotVersionUpgrade;
let nodes = decodeURIComponent(content || "");
nodes = nodes.replace(/\<img/gi, '<img style="width:100%;height:auto" ');
nodes = nodes.replace(
/\<table/gi,
'<table style="border-spacing: 0;border-collapse: collapse;border: 1px solid #000" '
);
nodes = nodes.replace(
/\<td/gi,
'<td style="border: 1px solid #000;text-align:center" '
);
this.setState({
isShowVersionUpgrading: false,
isShowVersionUpgradFinish: true, // 升级介绍
versionUpgradFinishNodes: nodes,
});
};
/** iot版本升级 END */
/**
@ -1149,8 +1174,7 @@ class Index extends Component<any, any> {
return (
<Block>
{/* <PageMeta pageOrientation="landscape"> </PageMeta> */}
{/* <View> */}
{/* <PageMeta pageOrientation="landscape"></PageMeta> */}
<View catchMove>
<PopupAlert
isShow={isCommonError}
@ -1324,11 +1348,23 @@ class Index extends Component<any, any> {
confirm={this.confirmUpdateVersionTip}
/>
{isShowVersionUpgrading && (
<UpdateIotWL200
isShow={isShowVersionUpgrading}
finishFun={this.wl200UpgradeFinishFun}
errorFun={this.wl200UpgradeErrorFun}
/>
<Block>
{connectInstrument.model === "WL200" && (
<UpdateIotWL200
isShow={isShowVersionUpgrading}
finishFun={this.wl200UpgradeFinishFun}
errorFun={this.wl200UpgradeErrorFun}
/>
)}
{connectInstrument.model === "FR200" && (
<UpdateIotFR200
isShow={isShowVersionUpgrading}
finishFun={this.UpgradeFinishFun}
errorFun={this.wl200UpgradeErrorFun}
/>
)}
</Block>
)}
<PopupAlert
isShow={isShowVersionUpgradFinish}
@ -1476,33 +1512,27 @@ class Index extends Component<any, any> {
<View className="popBox"></View>
</Popup>
<Popup show={false} >
<Popup show={false}>
<View className="MembraneCloth">
<View className="title"></View>
<View className="center">
{MembraneClothList.map((item, index) => {
return (
<View
key={index}
className="list"
>
<Radio name="1" v-model={this.state.checkedMembraneCloth}>{item.name}</Radio>
</View>
);
})}
{MembraneClothList.map((item, index) => {
return (
<View key={index} className="list">
<Radio name="1" v-model={this.state.checkedMembraneCloth}>
{item.name}
</Radio>
</View>
);
})}
</View>
<View className="popbtnbox flex aitems jcenter">
<View className="btn1" >
</View>
<View className="btn1"></View>
</View>
</View>
</Popup>
{/* </View>
<View
</Popup>
{/* </PageMeta> */}
{/* <View
style="position:fixed;width:100vw;height:100vh"
onClick={this.goTest}
>

Loading…
Cancel
Save