diff --git a/src/components/bluetoot/update-fr200/index.less b/src/components/bluetoot/update-fr200/index.less new file mode 100644 index 0000000..5bb8f2a --- /dev/null +++ b/src/components/bluetoot/update-fr200/index.less @@ -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; +} diff --git a/src/components/bluetoot/update-fr200/index.tsx b/src/components/bluetoot/update-fr200/index.tsx new file mode 100644 index 0000000..2a0f1a2 --- /dev/null +++ b/src/components/bluetoot/update-fr200/index.tsx @@ -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 { + 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 ( + + + + + + 设备升级中 + + + + + + {progressbar}% + + 注意事项: + 1.保持设备开机状态 + 2.请勿切出该页面 + + + + + + ); + } +} + +const mapStateToProps = (state) => ({ + bluetoothInfo: state.deviceInfo.bluetoothInfo, +}); +const mapDispatchToProps = (dispatch) => ({}); +export default connect(mapStateToProps, mapDispatchToProps)(UpdateIotFR200); diff --git a/src/components/popup/popup-countdown.less b/src/components/popup/popup-countdown.less index 5b33adf..624f3ee 100644 --- a/src/components/popup/popup-countdown.less +++ b/src/components/popup/popup-countdown.less @@ -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); + } } } diff --git a/src/moduleIOT/pages/iotCarePlan/FR200.tsx b/src/moduleIOT/pages/iotCarePlan/FR200.tsx index c5dfdd4..85b9012 100644 --- a/src/moduleIOT/pages/iotCarePlan/FR200.tsx +++ b/src/moduleIOT/pages/iotCarePlan/FR200.tsx @@ -183,14 +183,15 @@ class IotCarePlanFR200 extends Component { 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 { MaskModeBuzzingIndex: 0, // 面膜蜂鸣 MaskModeVibrateIndex: 0, // 面膜震动 - currentServiceData: { - // 当前展示的开启暂停GIF: 因为时间判断不方便,所以单独领出来 - startSource: "", - stopSource: "", - }, - // 倒计时 isShowCountdown: false, // 倒计时弹窗 countdown: 3, @@ -386,7 +381,7 @@ class IotCarePlanFR200 extends Component { "intelligence", ]; - /** 基础版:脸部/眼部/PRO 设备使用时,会自动开启暂停 */ + /** 基础版:脸部/眼部/PRO 设备使用时,会自动开启,不能暂停 */ BaseModeType: string[] = [ "face", "eyes", @@ -524,19 +519,25 @@ class IotCarePlanFR200 extends Component { }); 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 { 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 { 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 { 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 { } // 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 { isStopNurse, ModeList, ModeType, - ModeStepIndex, ActiveModeItem, currentWorkModeType, isSwitchActiveMode, @@ -2371,14 +2371,19 @@ class IotCarePlanFR200 extends Component { showEcharts, echartsData, isShowReReadRecordConnect, - currentServiceData, series, isFullScreen, } = this.state; return ( - + { + isFullScreen && + } + { + !isFullScreen && + } + { confirm={this.confirmModeSwitchBtn} /> + {ActiveModeItem.openSourceData.length > 0 && ( + + )} + + + + + + + 当前模式已护理部分时间 + 是否保存护理记录 + + } + cancelButtonText="取消" + confirmButtonText="确认" + textAlgin="center" + close={this.closeTipsSave} + cancel={this.cancelTipsSave} + confirm={this.confirmTipsSave} + /> + + { + /*不需要做处理*/ + }} + /> + + {isConnectShow && ( + { }} + pairingChange={this.pairingChange} + upgradeFun={() => { }} + /> + )} + { } - {ModeList.length > 0 && isFullScreen&&( + {ModeList.length > 0 && isFullScreen && ( { {(ActiveModeItem?.modeType === "maskPenetration" || - ActiveModeItem?.modeType === "essence") &&isFullScreen&&( + ActiveModeItem?.modeType === "essence") && isFullScreen && ( { > )} - {ActiveModeItem?.modeType === "moistureTest" && isFullScreen&&( + {ActiveModeItem?.modeType === "moistureTest" && isFullScreen && ( { // 如果检查失败,则报错 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 { 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 { 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 { }, 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((resolve) => { - setTimeout(() => { - waterStepList[waterStepIndex].schedule = 100; - that.setState({ - waterStepList, - }); - - resolve(); - }, 3000); - }).then(() => { - return new Promise((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 { 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 ); diff --git a/src/moduleIOT/pages/iotCarePlan/WL200.tsx b/src/moduleIOT/pages/iotCarePlan/WL200.tsx index e9f56c2..32cc37f 100644 --- a/src/moduleIOT/pages/iotCarePlan/WL200.tsx +++ b/src/moduleIOT/pages/iotCarePlan/WL200.tsx @@ -272,7 +272,12 @@ class IotCarePlanWL200 extends Component { 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 { 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 + ); }; // 完成配对 diff --git a/src/moduleIOT/pages/iotCarePlan/components/Echart/index.less b/src/moduleIOT/pages/iotCarePlan/components/Echart/index.less index 8e475ac..2c746aa 100644 --- a/src/moduleIOT/pages/iotCarePlan/components/Echart/index.less +++ b/src/moduleIOT/pages/iotCarePlan/components/Echart/index.less @@ -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; + } } } diff --git a/src/moduleIOT/pages/iotCarePlan/components/Echart/index.tsx b/src/moduleIOT/pages/iotCarePlan/components/Echart/index.tsx index c535cc2..24a6c54 100644 --- a/src/moduleIOT/pages/iotCarePlan/components/Echart/index.tsx +++ b/src/moduleIOT/pages/iotCarePlan/components/Echart/index.tsx @@ -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(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 ( - + - - - 实时能量 + + + 实时能量 {level.map((item) => ( - - {item} - + + {item} + ))} - - 1 + + 1 - 时间 + 时间 - + ); } diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index 323425a..da4558b 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -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 { 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 { // 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 { isShowVersionUpgradFinish: false, }); }; + UpgradeFinishFun = () => { + let { connectInstrument } = this.state; + console.log("connectInstrument", connectInstrument); + let content = connectInstrument.iotVersionUpgrade; + let nodes = decodeURIComponent(content || ""); + nodes = nodes.replace(/\ { return ( - {/* */} - {/* */} + {/* */} { confirm={this.confirmUpdateVersionTip} /> {isShowVersionUpgrading && ( - + + {connectInstrument.model === "WL200" && ( + + )} + + {connectInstrument.model === "FR200" && ( + + )} + )} { 你已绑定所有设备 - + 膜布选择 - {MembraneClothList.map((item, index) => { - return ( - - {item.name} - - - ); - })} + {MembraneClothList.map((item, index) => { + return ( + + + {item.name} + + + ); + })} - - 确认 - + 确认 - - - - {/* - + {/* */} + {/*