diff --git a/src/components/bluetoot/connection/fr200.js b/src/components/bluetoot/connection/fr200.js new file mode 100644 index 0000000..80a01fd --- /dev/null +++ b/src/components/bluetoot/connection/fr200.js @@ -0,0 +1,90 @@ +/**蓝牙命令合集*/ +export const fr200BleCommand = { + /**发送配对码*/ + match: { + commandType: "BleMatch", + bleCommandType: "SendMatchCode", + }, + + InfoQuery: { + /**查询版本指令*/ + versionInfo: { + commandType: "InfoQuery", + infoQueryType: "versionInfo", + otaDeviceType: "FR200", + }, + /**时间同步*/ + timeSync: { + commandType: "InfoQuery", + infoQueryType: "timeSync", + date: new Date(), + }, + /**查询离线记录概要*/ + clockSummary: { + commandType: "InfoQuery", + infoQueryType: "offlineClockInInfo", + dataType: "summary", + }, + /**查询离线明细第一条*/ + clockDetail: { + commandType: "InfoQuery", + infoQueryType: "offlineClockInInfo", + dataType: "detail", + dataIndex: 0, + }, + }, +}; + +/**控制设备命令合集*/ +export const fr200DeviceControlCommand = { + /**查询设备状态指令*/ + queryDeviceStatus: { + commandType: "DeviceStatusSync", + deviceSyncCommandType: "onlySyncStatusToDevice", + }, + /**控制设备暂停 pause暂停 working启动 end关闭*/ + pause: { + commandType: "DeviceControl", + workStatus: "pause", + }, + standby: { + commandType: "DeviceControl", + workStatus: "standby", + }, + end: { + commandType: "DeviceControl", + workStatus: "end", + }, + + /** + * '脸部' = 'workFace', + * '眼部' = 'workEye', + * '颈纹' = 'workNeck', + * '进入水分测试模式' = 'switchTestMode', + * '启动水分测试模式' = 'startTestMode', + * face + * eyes + * neck + * moistureTest + */ + // 普通工作模式 + work: { + commandType: "DeviceControl", + workStatus: "working", + workMode: "face", + }, + // 切换/进入水分测试 + switchTestMode: { + commandType: "DeviceControl", + workStatus: "working", + workMode: "moistureTest", + testStatus: "standby", + }, + // 启动水分测试 + startTestMode: { + commandType: "DeviceControl", + workStatus: "working", + workMode: "moistureTest", + testStatus: "start", + }, +}; diff --git a/src/components/bluetoot/connection/index.tsx b/src/components/bluetoot/connection/index.tsx index 8ac11a8..4a06de4 100644 --- a/src/components/bluetoot/connection/index.tsx +++ b/src/components/bluetoot/connection/index.tsx @@ -37,17 +37,19 @@ import { // const log = require("@/utils/log"); import commandMap from "@/utils/commandMap"; import { bleCommandSamples } from "./wl200"; +import { fr200BleCommand, fr200DeviceControlCommand } from "./fr200"; import { DeviceToolKit as DeviceToolKitWE100 } from "@flossom-npm/iot-translater-we100"; +import { DeviceToolKit as DeviceToolKitFR200 } from "@flossom-npm/iot-translater"; + const deviceToolKitInstanceWL200 = new DeviceToolKitWE100("WL200", "WL200"); deviceToolKitInstanceWL200.setDebug(true); - const deviceToolKitInstanceM01 = new DeviceToolKitWE100("WE100", "M01"); deviceToolKitInstanceM01.setDebug(true); const deviceToolKitInstanceFR200 = new DeviceToolKitFR200("FR200"); +deviceToolKitInstanceFR200.setDebug(true); -import { DeviceToolKit as DeviceToolKitFR200 } from "@flossom-npm/iot-translater"; import { showModal, msg, @@ -113,13 +115,13 @@ class ConnectionBluetoot extends Component { versionInfo: {}, //版本号 offlineDataList: [], //离线数据 - prefix: "12CAA", // WL200蓝牙搜索前缀 // WL200匹配 tranType: [ "WE100", // 发箍 "WE200", // 发箍 "WL200", // 面罩 "12CAA", // 面罩前缀名 + "FR200", // FR200 ], currentDeviceType: "", // 现在的设备类型: WE200 WL200 @@ -422,6 +424,40 @@ class ConnectionBluetoot extends Component { }); } + /**获取附属设备信息与设置当前设备名字*/ + getQueryMatchStatusAndSetName(value) { + const { deviceInfo } = this.props; + let querySubDeviceArrayBuffer: any = null; + let jsonStatus: any = null; + if (deviceInfo.model == "WL200") { + if (this.isWL200()) { + this.setState({ currentDeviceType: "WL200" }); + jsonStatus = deviceToolKitInstanceWL200.toJsonStatus(value); + querySubDeviceArrayBuffer = deviceToolKitInstanceWL200.toBleCommand( + bleCommandSamples.querySubDevice as any + ); + } else { + this.setState({ currentDeviceType: "WE200" }); + jsonStatus = deviceToolKitInstanceM01.toJsonStatus(value); + querySubDeviceArrayBuffer = deviceToolKitInstanceM01.toBleCommand( + bleCommandSamples.querySubDevice as any + ); + } + } else if (deviceInfo.model == "M01") { + this.setState({ currentDeviceType: "M01" }); + jsonStatus = deviceToolKitInstanceM01.toJsonStatus(value.value); + querySubDeviceArrayBuffer = deviceToolKitInstanceM01.toBleCommand( + bleCommandSamples.querySubDevice as any + ); + } else if (deviceInfo.model === "FR200") { + // FR200 不需要查询子设备 + jsonStatus = deviceToolKitInstanceFR200.toJsonStatus(value.value); + this.setState({ currentDeviceType: "FR200" }); + } + // if (querySubDeviceArrayBuffer) this.sendQuerySubDevice(querySubDeviceArrayBuffer) + return jsonStatus; + } + /** 7.通知BLE特征值更改 */ notifyBLECharacteristicValueChange() { console.log("7.通知BLE特征值更改"); @@ -443,39 +479,13 @@ class ConnectionBluetoot extends Component { let str = ab2hex(value.value); //转为16进制字符串 console.log("转为16进制字符串 str", str); - let jsonStatus: any = null; - let querySubDeviceArrayBuffer; - - if (deviceInfo.model == "WL200") { - if (this.isWL200()) { - this.setState({ currentDeviceType: "WL200" }); - jsonStatus = deviceToolKitInstanceWL200.toJsonStatus( - value.value - ); - querySubDeviceArrayBuffer = - deviceToolKitInstanceWL200.toBleCommand( - bleCommandSamples.querySubDevice as any - ); - } else { - this.setState({ currentDeviceType: "WE200" }); - jsonStatus = deviceToolKitInstanceM01.toJsonStatus(value.value); - querySubDeviceArrayBuffer = - deviceToolKitInstanceM01.toBleCommand( - bleCommandSamples.querySubDevice as any - ); - } - } else if (deviceInfo.model == "M01") { - this.setState({ currentDeviceType: "M01" }); - jsonStatus = deviceToolKitInstanceM01.toJsonStatus(value.value); - querySubDeviceArrayBuffer = deviceToolKitInstanceM01.toBleCommand( - bleCommandSamples.querySubDevice as any - ); - } + let jsonStatus = this.getQueryMatchStatusAndSetName(value.value); console.log( commandMap.reciviedBLECommand, `仪器模式: ${deviceInfo.model}`, jsonStatus ); + console.log("jsonStatus", jsonStatus); if (jsonStatus?.commandType === "BleMatch") { switch (jsonStatus?.bleCommandType) { @@ -489,17 +499,9 @@ class ConnectionBluetoot extends Component { islian: true, // 不需要离线记录,但暂未完全删除这部分逻辑,所以直接设为true }); - // this.pairingChange(this.state); // 临时添加,用于跳转 this.detectVersionUpdate(); // 获取升级信息 // todo 连接成功需删除离线记录,暂时未缓存离线记录 if (this.state.connectionSuccess) return; - // 暂时不需要查询是否连接子设备, 直接进入查询版本信息 - // this.detectVersionUpdate(); - /*if(deviceInfo.type == instrumentTypeEnum.M01) { - this.detectVersionUpdate() - } else { - this.sendQuerySubDevice(querySubDeviceArrayBuffer) - }*/ } break; case "BleStatusSync": // 设备连接状态 @@ -519,6 +521,10 @@ class ConnectionBluetoot extends Component { console.log("面罩连上了 value => ", jsonStatus); this.detectVersionUpdate(); break; + case "FR200": + console.log("FR200连上了 value => ", jsonStatus); + this.detectVersionUpdate(); + break; default: break; } @@ -526,7 +532,10 @@ class ConnectionBluetoot extends Component { console.log("BleStatusSync value => ", jsonStatus); break; case "QueryMatchStatus": - console.log("QueryMatchStatus value => ", jsonStatus); + console.log( + "查询附属设备QueryMatchStatus value => ", + jsonStatus + ); break; default: break; @@ -536,16 +545,6 @@ class ConnectionBluetoot extends Component { console.log("当前设备:", jsonStatus.otaDeviceType); console.log("当前设备版本号:", jsonStatus.versionNo); - if ( - jsonStatus.otaDeviceType === "WE100" || - jsonStatus.otaDeviceType === "WE200" - ) { - console.log("closeBLEConnection"); - setTimeout(() => { - this.againConnection(); - }, 1000); - } - switch (jsonStatus.infoQueryType) { case "versionInfo": if (this.state.hasVersionInfo) return; @@ -560,7 +559,7 @@ class ConnectionBluetoot extends Component { let currentDevicesName = getStorageSync("currentDevicesName"); let deviceVersionNo = jsonStatus.versionNo; let latestVersionNo = deviceInfo.iotVersion; - if (currentDevicesName.indexOf("12CAA") === -1) { + if (currentDevicesName.indexOf("WE") > -1) { latestVersionNo = deviceInfo.we200IotVersion; } // 判断版本号是否需要升级 @@ -573,6 +572,16 @@ class ConnectionBluetoot extends Component { // 版本号需要更新: 告诉父级页面,关闭连接弹窗,显示更新弹窗 this.props.upgradeFun(); } else { + if ( + currentDevicesName === "WE100" || + currentDevicesName === "WE200" + ) { + console.log("closeBLEConnection"); + setTimeout(() => { + this.againConnection(); + }, 1000); + return; + } console.log("不需要升级,跳转进入仪器详情页"); // 不需要升级,跳转进入仪器详情页 if (isGetVersionTimer) clearTimeout(isGetVersionTimer); @@ -615,7 +624,6 @@ class ConnectionBluetoot extends Component { } else if (deviceInfo.model == "WL200" || deviceInfo.model == "M01") { if (sendPairingTimer) clearInterval(sendPairingTimer); sendPairingTimer = setInterval(() => { - console.log("test WL200"); this.sendPairingSignal(); }, 1000); } else if ( @@ -661,44 +669,54 @@ class ConnectionBluetoot extends Component { } } + const isWEorWL = ["WL200", "WE200", "WE100"].includes(model); const isFRDevice = ["FR200", "FR380", "FR390"].includes(model); - console.log(commandMap.sendVersionCommand, `仪器:${model}`); if (isFRDevice) { - writeBLECharacteristicValue({ - //发送获取仪器版本号 - deviceId: this.props.bluetoothInfo.deviceId, - servicesuuid: this.props.bluetoothInfo.servicesuuid, - characteristicsuuid1: this.props.bluetoothInfo.characteristicsuuid1, - characteristicsuuid0: this.props.bluetoothInfo.characteristicsuuid0, - value: `dbf0a00300${ccrc8("dbf0a00300")}de`, - }); - } else { - const otaDeviceType = this.isWL200() - ? OtaDeviceTypeEnum.WL200 - : OtaDeviceTypeEnum.WE100; + if (model === "FR200") { + const value = deviceToolKitInstanceFR200.toBleCommand( + fr200BleCommand.InfoQuery.versionInfo as any + ); + sendCommand({ value }); + } else { + writeBLECharacteristicValue({ + //发送获取仪器版本号 + deviceId: this.props.bluetoothInfo.deviceId, + servicesuuid: this.props.bluetoothInfo.servicesuuid, + characteristicsuuid1: this.props.bluetoothInfo.characteristicsuuid1, + characteristicsuuid0: this.props.bluetoothInfo.characteristicsuuid0, + value: `dbf0a00300${ccrc8("dbf0a00300")}de`, + }); + } + } else if (isWEorWL) { const versionCommand = { commandType: "InfoQuery", infoQueryType: "versionInfo", - otaDeviceType, + otaDeviceType: "", }; - console.log("versionCommand", versionCommand); - - // 区分WL200 和 发箍 - const value = this.isWL200() - ? deviceToolKitInstanceWL200.toBleCommand(versionCommand as any) - : deviceToolKitInstanceM01.toBleCommand(versionCommand as any); - - console.log(otaDeviceType, " value", value); - sendCommand({ value }); + if (this.isWL200()) { + // WL200 + const otaDeviceType = OtaDeviceTypeEnum.WL200; + versionCommand.otaDeviceType = otaDeviceType; + const value = deviceToolKitInstanceWL200.toBleCommand( + versionCommand as any + ); + sendCommand({ value }); + } else { + // WE200 WE100 + const otaDeviceType = OtaDeviceTypeEnum.WE100; + versionCommand.otaDeviceType = otaDeviceType; + const value = deviceToolKitInstanceM01.toBleCommand( + versionCommand as any + ); + sendCommand({ value }); + } } } /** 获取离线记录 */ sendofflist() { - // log.info() if (this.state.offlineDataindex == this.state.offlineDataList.length) { console.log("离线记录获取完成", this.state); - // log.info(commandMap.finishOfflineData, this.state.offlineDataList); /**** * 发送同步时间 * ****/ @@ -711,51 +729,65 @@ class ConnectionBluetoot extends Component { return false; } console.log("发送获取离线记录(细)指令"); - // log.info(commandMap.finishOfflineData, "发送获取离线记录(细)指令"); - writeBLECharacteristicValue({ - //发送获取离线记录 - deviceId: this.props.bluetoothInfo.deviceId, - servicesuuid: this.props.bluetoothInfo.servicesuuid, - characteristicsuuid1: this.props.bluetoothInfo.characteristicsuuid1, - characteristicsuuid0: this.props.bluetoothInfo.characteristicsuuid0, - value: this.state.offlineData[this.state.offlineDataList.length], - }); + const { deviceInfo } = this.props; + let model = deviceInfo.model; + if (model === "FR200") { + let matchArrayBuffer = deviceToolKitInstanceFR200.toBleCommand( + fr200BleCommand.InfoQuery.clockDetail as any + ); + sendCommand({ value: matchArrayBuffer }); + } else { + writeBLECharacteristicValue({ + //发送获取离线记录 + deviceId: this.props.bluetoothInfo.deviceId, + servicesuuid: this.props.bluetoothInfo.servicesuuid, + characteristicsuuid1: this.props.bluetoothInfo.characteristicsuuid1, + characteristicsuuid0: this.props.bluetoothInfo.characteristicsuuid0, + value: this.state.offlineData[this.state.offlineDataList.length], + }); + } } /** 获取离线记录(汇总) */ sendofflistSummary() { let str = "DBF0A00200"; console.log("发送离线记录汇总指令 ==》", str); this.setState({ offlineDataList: [] }); // 置空重查离线记录 - // log.info(commandMap.finishOfflineData, `发送获取离线记录(总)指令`); - writeBLECharacteristicValue({ - //发送获取离线记录 - deviceId: this.props.bluetoothInfo.deviceId, - servicesuuid: this.props.bluetoothInfo.servicesuuid, - characteristicsuuid1: this.props.bluetoothInfo.characteristicsuuid1, - characteristicsuuid0: this.props.bluetoothInfo.characteristicsuuid0, - value: `${str}${ccrc8(str)}DE`, - }); + + const { deviceInfo } = this.props; + let model = deviceInfo.model; + if (model === "FR200") { + let matchArrayBuffer = deviceToolKitInstanceFR200.toBleCommand( + fr200BleCommand.InfoQuery.clockSummary as any + ); + sendCommand({ value: matchArrayBuffer }); + } else { + writeBLECharacteristicValue({ + //发送获取离线记录 + deviceId: this.props.bluetoothInfo.deviceId, + servicesuuid: this.props.bluetoothInfo.servicesuuid, + characteristicsuuid1: this.props.bluetoothInfo.characteristicsuuid1, + characteristicsuuid0: this.props.bluetoothInfo.characteristicsuuid0, + value: `${str}${ccrc8(str)}DE`, + }); + } } /** 9.发送配对码 */ sendPairingSignal() { console.log("9.发送配对码 sendPairingSignal"); const { deviceInfo } = this.props; - // log.info(commandMap.sendMatchCode, `仪器:${deviceInfo.model}发送匹配码`); console.log(commandMap.sendMatchCode, `仪器:${deviceInfo.model}发送匹配码`); let matchArrayBuffer: any = null; switch (deviceInfo.model) { case InstrumentTypeEnum.FR200: matchArrayBuffer = deviceToolKitInstanceFR200.toBleCommand( - bleCommandSamples.match as any + fr200BleCommand.match as any ); break; case InstrumentTypeEnum.WL200: - console.log("正在发送WL200", bleCommandSamples.match); let currentDevicesName = getStorageSync("currentDevicesName"); // 区分面罩和发箍 if (currentDevicesName.indexOf("12CAA") > -1) { - console.log("12CAA"); matchArrayBuffer = deviceToolKitInstanceWL200.toBleCommand( bleCommandSamples.match as any ); @@ -945,6 +977,8 @@ class ConnectionBluetoot extends Component { errorText, }); } + + /**发送消息获取子设备*/ sendQuerySubDevice(value) { isGetSubDeviceTimer = setInterval(() => { sendCommand({ value }); @@ -995,14 +1029,35 @@ class ConnectionBluetoot extends Component { /** 发送同步记录 */ sendSyncRecording() { - const versionCommand = { + const clockSummaryCommand = { commandType: "InfoQuery", infoQueryType: "offlineClockSummary", }; - const value = this.isWL200() - ? deviceToolKitInstanceWL200.toBleCommand(versionCommand as any) - : deviceToolKitInstanceM01.toBleCommand(versionCommand as any); - sendCommand({ value }).then(); + + const { deviceInfo } = this.props; + let model = deviceInfo.model; + if (model === "WL200") { + if (!this.isWL200()) { + model = "WE200"; + } + } + + const isWEorWL = ["WL200", "WE200", "WE100"].includes(model); + const isFRDevice = ["FR200", "FR380", "FR390"].includes(model); + if (isFRDevice) { + if (model === "FR200") { + let value = deviceToolKitInstanceFR200.toBleCommand( + fr200BleCommand.InfoQuery.clockSummary as any + ); + sendCommand({ value }).then(); + } + } else if (isWEorWL) { + const value = this.isWL200() + ? deviceToolKitInstanceWL200.toBleCommand(clockSummaryCommand as any) + : deviceToolKitInstanceM01.toBleCommand(clockSummaryCommand as any); + sendCommand({ value }).then(); + } + if (isGetSyncRecordingTimer) clearTimeout(isGetSyncRecordingTimer); isGetSyncRecordingTimer = setTimeout(() => { if (this.state.hasSyncRecord) { diff --git a/src/moduleIOT/pages/iotCarePlan/FR200.tsx b/src/moduleIOT/pages/iotCarePlan/FR200.tsx index e69de29..439cd85 100644 --- a/src/moduleIOT/pages/iotCarePlan/FR200.tsx +++ b/src/moduleIOT/pages/iotCarePlan/FR200.tsx @@ -0,0 +1,2306 @@ +import Taro from "@tarojs/taro"; +import dayjs from "dayjs"; +import classnames from "classnames"; +import { debounce } from "lodash"; +// eslint-disable-next-line import/no-named-as-default +import React, { + Component, + PropsWithChildren, + useEffect, + useState, +} from "react"; + +// import Echarts from "./components/Echart/index"; +import { + Block, + View, + Text, + Image, + Video, + Input, + Button, +} from "@tarojs/components"; + +/*** redux ***/ +import { connect } from "react-redux"; +/*** redux end ***/ + +/* 公共组件 */ +import Navbar from "@/components/navbar/navbar"; +import PopupCountdown from "@/components/popup/popup-countdown"; +import PopupStepTips from "@/components/popup/popup-step-tips"; +import PopupConfirm from "@/components/popup/popup-confirm"; +import PopupAlert from "@/components/popup/popup-alert"; +import PopupStatus from "@/components/popup/popup-status"; +import PopupInstrumentUploadTips from "@/components/popup/popup-instrument-upload-tips"; +import ConnectionBluetoot from "@/components/bluetoot/connection"; +/* 公共组件 END */ + +/* 本页组件 */ +import ElectricityView from "./components/ElectricityView/index"; +import ModeListView from "./components/ModeList/index"; +import ModeContent from "./components/ModeContent/index"; +import Footer from "./components/Footer"; +/* 本页组件 END */ + +import { go, getStorageSync, setStorageSync, msg } from "@/utils/traoAPI"; +import { InstrumentInfo } from "@/utils/Interface"; +import "./iotCarePlan.less"; + +import { + notifyBLECharacteristicValueChange, + sendCommand, +} from "@/utils/bluetoothWXAPI"; +import { + deviceCommandSamples, + bleCommandSamples, +} from "@/components/bluetoot/connection/wl200"; + +import { minSecToS, s_to_ms, s_to_hms, sleep, s_to_s } from "@/utils/util"; +// import { DeviceToolKit as DeviceToolKitWE100 } from "@flossom-npm/iot-translater-we100"; +import { + DeviceToolKit as DeviceToolKitWM, + TResponseFromDevice as TResponseFromDeviceWM, +} from "@flossom-npm/iot-translater"; +import commandMap from "@/utils/commandMap"; +import { Popup } from "@antmjs/vantui"; + +const deviceToolKitInstanceFR200 = new DeviceToolKitWM("FR200"); + +let currentTimeTimer: any = null; // 当前项目时间定时器 +let CountdownTimer: any = null; +let timer: any = null; +let showTipsTimer: any = null; +let loadingTipsTimer: any = null; // 蓝牙连接提示 +// 设备运行时间校准频率,每多少秒校准一次 +const TIME_CALIBRATION_FREQUENCY = 5; + +// 组合模式:分别对应的是哪几个模式类型 +// 黄光590nm +// 红光630nm +// 近红外光830nm + +// 模式类型中文名 +const WORK_MODE_Chinese_NAME = { + 强效舒缓: "powerfulSoothing", + 维稳修复: "Stability", // 黄光?近红外光? + 均色提亮: "Brighten", // 黄光?近红外光? + 紧致淡纹: "FirmSkin", // 黄光?近红外光? + 自定义: "MaskCustom", + 均色提亮Pro: "BrightenStand", + 紧致淡纹Pro: "FirmSkinStand", + 痘肌舒缓Pro: "SmallpoxSoothingPro", + 痘肌舒缓: "SmallpoxSoothing", + 混合Pro: "MixNursePro", + 混合: "MixNurse", + 头皮护理: "ScalpCare", +}; + +const MODE_WORKING_ENUM = { + STANDBY: "standby", // 待命 + WORKING: "working", // 工作 + PAUSE: "pause", + END: "end", +}; + +// 不同模式启动前的倒计时时间 +let CountDownTime = { + powerfulSoothing: 6, + Stability: 3, + Brighten: 3, + FirmSkin: 3, + MaskCustom: 6, + BrightenStand: 6, + FirmSkinStand: 6, + SmallpoxSoothingPro: 6, + SmallpoxSoothing: 4, + MixNursePro: 6, + MixNurse: 4, + ScalpCare: 6, +}; + +let DeviceSyncData = { + totalWorkingMinutes: 0, + totalWorkingSeconds: 0, +}; +let deviceToolKitInstance = deviceToolKitInstanceFR200; + +class IotCareWR200 extends Component { + constructor(props) { + super(props); + this.state = { + name: "iotCarePlan", + title: "美容仪名字", // 页面标题 + // 当前设备 + currentDevice: { + name: "", + model: "", + }, + + /** 连接设备 */ + hasVersion: false, // 是否已查询到版本号 + basicModeList: [], //模式列表 + modelActiveIndex: 0, //模式下标 + sliderProgress: 22, + facialMaskConnectStatus: 1, // 面罩连接状态 0未连接 1已连接 + Electricity: 4, // WL200电量 + matrixElectricity: 4, // WE200发箍电量 + + workMode: "", //当前模式 + + gear: { gear: 1 }, + currentShowDialog: "", + step: 1, // 1:选择模式并播放视频, 2:护理中 + showVideoPlayBtn: true, // 视频播放按钮 + duration: 0, // 视频总时长 + hadShowBreakTips: false, // 是否展示过支架断开提示 + + isConnectShow: false, // 是否弹出连蓝牙弹窗:在蓝牙断开时弹出 + /** 连接设备 End */ + + /** 护理过程 */ + isStandStatus: false, // 当前模式是否舱体/支架模式 + isShowStepTips: false, // 是否显示介绍步骤弹窗 + isConnectionBlutoot: true, // 是否已连接蓝牙 + isShowNurse: false, // 是否开始并显示护理 + isStopNurse: false, // 是否暂停护理 + isEndNurse: false, // 是否结束护理 + errorTips: "", // 错误提示 + /** 护理过程 END*/ + + // 模式列表 + isSwitchActiveMode: false, // 是否显示弹窗切换模式 + ModeList: [], + ModeType: "all", // all visor面罩 cabin舱体 yimeish医美 + modeClass: "", // 1面罩 2舱体 3医美 + ActiveModeItem: {}, // 当前选中模式 + SwitchActiveModeItem: {}, // 切换选中模式 + ModeID: "mode_", // 模式KEY + activeModeID: "", // 当前选中模式ID:用于高亮 + ModeStepIndex: 0, // 当前护理功效步骤:每个步骤时间不定,所以时间另外计算,根据步骤显示 + ModeStepTimeArray: [], // 护理功效时间步骤,用于切换显示GIF + currentServiceData: { + // 当前展示的开启暂停GIF: 因为时间判断不方便,所以单独领出来 + startSource: "", + stopSource: "", + }, + + // 模式组合 + isCombineSuccess: false, // 组合模式是否设置成功 + // 倒计时 + isShowCountdown: false, // 倒计时弹窗 + countdown: 3, + // 是否结束护理 + isEndCarePlan: false, + currentTime: "01:00", + + // 护理时间不够 + isNotEnoughTime: false, + // 通用错误提示 + isShowErrorTipsText: false, // 护理模式切换错误弹窗 + errorTipsText: "", // 护理模式切换错误提示 + + isShowNursingSuccess: false, // 护理成功弹窗 + isShowTipsSave: false, // 切换模式时,提示是否保存部分护理记录 + + // 初次护理弹窗 + isFirstTipShow: false, + nurseInfo: [], + + // 上一次护理记录未生成,是否继续连接设备 + isShowReReadRecordConnect: false, + + // 按钮是否不可运行 + isFooterBtnDisabled: true, + // isFirstEntryMode: false, // 模式首次打开 + + isShowHistoryMsg: false, // 是否显示正在同步历史 + }; + } + + // 不涉及渲染的页面变量 + isRuning: any = false; // 设备是否运行中 + jsonStatus: any = {}; // 同步设备返回数据,用于结束 + workJsonStatus: any = {}; // 同步工作中的仪器 + tempModeCurrent: any = {}; // 临时保存的当前模式 + elapsedTime: any = 0; // 设备已运行时间 + workStatus: any = ""; // 工作状态 + WL200NursingHistory: any = null; // 护理缓存历史 + hadCheckReport = false; // 是否已检查仪器护理记录 + hadGotInstrumentHistoryData = false; // 是否已缓存仪器历史数据 + hadLoadedPage = false; // 判断是否首次进入页面 + + async onLoad() { + // 保持屏幕常亮 + Taro.setKeepScreenOn({ + keepScreenOn: true, + }); + this.getWL200NursingHistory(); + this.initData(); + } + componentDidMount() {} + + componentWillUnmount() {} + + componentDidShow() { + console.log("页面显示了"); + + if (!this.hadLoadedPage) { + this.hadLoadedPage = true; // 二次进入页面(非首次进入) + return; + } + + this.getWL200NursingHistory(); + // 重置初始值,每次进入页面重新检查面罩护理记录 + this.hadCheckReport = false; + this.hadGotInstrumentHistoryData = false; + } + + componentDidHide() { + console.log("Hide"); + // 页面隐藏后,下次显示需要重新检查记录 + this.hadCheckReport = false; + } + + async initData() { + let obj = getStorageSync("instrument_detail"); + if (obj) { + this.setState({ + currentDevice: obj, + title: obj.name, + }); + + await this.GetModeList(obj.id); + + // 如果不存在设备模式值,则判断为首次进入,弹窗提示 + let isFirstTipShow = getStorageSync("first_instrument_" + obj.id); + if (!isFirstTipShow) { + this.firstNurseInfo(); + } + } + + // 开发者工具 + const platform = Taro.getSystemInfoSync().platform; + if (platform !== "devtools") { + // 仅手机端初始化蓝牙 + this.init(); + } + + // 初始化蓝牙 + // this.init(); + } + + getOption() { + const option = { + grid: { top: 8, right: 8, bottom: 24, left: 36 }, + xAxis: { + type: "category", + data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + }, + yAxis: { + type: "value", + }, + series: [ + { + data: [820, 932, 901, 934, 1290, 1330, 1320], + type: "line", + smooth: true, + }, + ], + tooltip: { + trigger: "axis", + }, + // title: { + // text: 'ECharts 示例' + // }, + // tooltip: {}, + // xAxis: { + // data: ['A', 'B', 'C', 'D', 'E'] + // }, + // yAxis: {}, + // series: [{ + // name: '数量', + // type: 'bar', + // data: [5, 20, 36, 10, 10] + // }] + }; + return option; + } + + async init() { + // 查询自定义设备指令 + const queryInstructionParams = { + commandType: "InfoQuery", + infoQueryType: "customModeInfo", + }; + let commandBuffer = deviceToolKitInstance.toBleCommand( + queryInstructionParams as any + ); + sendCommand({ value: commandBuffer }).then((res) => { + console.log( + "查询自定义组合模式指令发送成功 参数为=>", + queryInstructionParams + ); + }); + + // 监听蓝牙连接状态改变 + Taro.onBLEConnectionStateChange(this.listener); + await this.notifyBLECharacteristicValueChange(); + + // this.handleWorkStatus(false, MODE_WORKING_ENUM.STANDBY); + } + listener = (res) => { + console.log("listener res", res); + if (res?.connected) return; + // 蓝牙未连接才执行下面逻辑 + Taro.offBLECharacteristicValueChange((res) => { + console.log("offBLECharacteristicValueChange", res); + }); + clearTimeout(loadingTipsTimer); + console.log(commandMap.WL200Command, "监听到蓝牙断开, 打开断开提示"); + + this.workStatus = ""; + // 显示蓝牙断开弹窗 + this.setState({ + isConnectShow: true, // 打开蓝牙链接弹窗 + isConnectionBlutoot: false, // 断开蓝牙 + isShowCountdown: false, // 关闭倒计时,防止倒计时还在运行 + }); + this.footerIsDisabled(); + }; + + GetModeList = async (id) => { + let params = { + instrumentId: id, + }; + let res = await InstrumentInfo.modeInfoList(params); + if (res.data.code === 200) { + if (res.data.data.length > 0) { + this.setState({ + ActiveModeItem: res.data.data[0], + ModeList: res.data.data, + }); + + // setTimeout(() => { + // this.modeCurrentFun(res.data.data[0]); + // }, 100); + } else { + this.setState({ ModeList: [] }); + } + } + }; + + /** + * 倒计时弹窗 + * param 重置倒计时 + * callback 回调函数 + */ + showCountdownFun(count = 3, callback: any = null) { + this.setState({ + countdown: count, + }); + setTimeout(() => { + clearInterval(CountdownTimer); + this.setState({ + isShowCountdown: true, + }); + CountdownTimer = setInterval(() => { + if (this.state.countdown === 0) { + clearInterval(CountdownTimer); + this.setState({ + isShowCountdown: false, + }); + if (callback) callback(); + } else { + this.setState({ + countdown: this.state.countdown - 1, + }); + } + }, 1000); + }, 0); + } + + /** 选中护理模式 */ + modeCurrentFun = async (data, isNotCheck = false) => { + // 护理检查改变模式,是否提示切换护理模式 + // isNotCheck为真时,不进行校验,直接切换 + this.tempModeCurrent = data; + + // 仅在未开始护理前,切换模式的时候提示模式弹窗 + if (!this.state.isShowNurse) { + this.openStepTips(); + } + + // 如果按钮不可点击则报错,内部自带检查底部按钮函数 + this.onEmitErrorTips(); + if (!isNotCheck) { + let isReturn = this.modeRuningChange(); + if (isReturn) return; + } + + let { isShowNurse } = this.state; + let currentServiceData = { + startSource: "", + stopSource: "", + }; + if (data.serviceData.length) { + currentServiceData = data.serviceData[0]; + } + + let currentTime = data.modeTimeStr; + let modeArray = ["all", "visor", "cabin", "yimeish"]; + this.setState({ + ActiveModeItem: data, + activeModeID: data.id, + ModeID: "mode_" + data.id, + currentServiceData, + ModeStepIndex: 0, + currentTime, + ModeType: modeArray[data.modeClass], + }); + + setTimeout(() => { + // 设置时间组合 + if (data.serviceData.length > 0) { + this.setServiceTimeData(); + } + // 存在组合模式时,设置组合模式 + if (data.combineData.length > 0) { + this.setCustomMaskData(); + } + }); + + // 如果是正在运行中切换,则直接准备运行 + if (isShowNurse) { + if (!this.footerIsDisabled()) { + this.stepNext(); // 如果切换模式,则不执行开始逻辑 + setTimeout(() => { + this.onNursingTap("switch"); + }, 800); + } + } + }; + /** 设备运行中切换模式 */ + modeRuningChange() { + // 运行中切换模式逻辑 + if ( + this.workStatus === MODE_WORKING_ENUM.PAUSE || + this.workStatus === MODE_WORKING_ENUM.WORKING + ) { + const { totalWorkingMinutes, totalWorkingSeconds } = DeviceSyncData; + const totalTime = totalWorkingMinutes * 60 + totalWorkingSeconds; // 设备时间 + let { ActiveModeItem } = this.state; + if (!ActiveModeItem || totalTime === 0) { + return false; + } + + if (this.state.step == 2 && this.state.facialMaskConnectStatus == 1) { + // 提示切换护理模式 + if (this.isCheckNurseTime()) { + // 满足时间条件,提示是否保存部分护理记录 + this.judgementWorkStatus( + MODE_WORKING_ENUM.PAUSE, + this.state.ActiveModeItem?.modeType + ); + this.setState({ + isShowTipsSave: true, + }); + } + return true; + } + } + return false; + } + + /** 切换护理模式 */ + switchModeCurrentFun = async (data) => { + this.setState({ + SwitchActiveModeItem: data, + activeModeID: data.id, + ModeID: "mode_" + data.id, + }); + }; + // 打开模式切换弹窗 + openModeSwitch = () => { + console.log("openModeSwitch"); + this.setState({ + isSwitchActiveMode: true, + }); + }; + // 取消并关闭切换护理模式弹窗 + cancelModeSwitchBtn = () => { + this.setState({ + isSwitchActiveMode: false, + }); + }; + // 弹窗确定切换护理模式 + confirmModeSwitchBtn = () => { + let { SwitchActiveModeItem } = this.state; + this.cancelModeSwitchBtn(); + this.modeCurrentFun(SwitchActiveModeItem); + + let modeArray = ["all", "visor", "cabin", "yimeish"]; + this.setState({ + ModeType: modeArray[SwitchActiveModeItem.modeClass], + }); + }; + + stepNext = () => { + // //0未定义(全部) 1面罩模式 2舱体模式 3医美术后 + let modeArray = ["all", "visor", "cabin", "yimeish"]; + let modeClass = this.state.ActiveModeItem.modeClass; + this.workStatus = "pause"; + this.setState({ + ModeType: modeArray[modeClass], + isShowNurse: true, + isStopNurse: true, + step: 2, + }); + + setTimeout(() => { + this.handleWorkStatus(false, MODE_WORKING_ENUM.STANDBY); + }); + }; + /** 开始护理按钮:点击开始,页面进行到下一步 */ + onStartNurse = async () => { + // 如果检查通过,可运行,则执行下一步 + if (!this.footerIsDisabled()) { + this.stepNext(); + + setTimeout(() => { + this.onNursingTap(); + // 倒计时弹窗: 倒计时完成后,自动开始,并判断弹窗 + let downNum = CountDownTime[this.state.ActiveModeItem.modeType] || 3; + this.showCountdownFun(downNum, () => {}); + }, 500); + + return; + } + // 如果检查失败,则报错 + this.onEmitErrorTips(); + }; + + /** + * @name 不可切换光照提示 + * @description isCabinMode是否舱体模式。 0.检测面罩与舱体是否仍在连接中,需要分离 1.检测是否连接失败,需要重新连接 + */ + onEmitErrorTips = async () => { + setTimeout(() => { + let { ActiveModeItem } = this.state; + + // 按钮不可点击时,提示报错 + let isDisabled = this.footerIsDisabled(); + if (isDisabled) { + if (ActiveModeItem.isCabinMode === 0) { + this.showTips("检测到面罩与舱体仍在连接中,该模式需要分离面罩和舱体"); + } else { + this.showTips( + "检测到面罩与舱体未连接成功,请确认面罩是否和舱体连接并接通舱体电源" + ); + } + } + }); + }; + + // 绘制能量图 + drawProwerPicture() {} + + /** 切换光照 */ + onSwitchChange = async () => { + // todo + let { isStopNurse } = this.state; + if (isStopNurse) { + // 开始光照逻辑 + this.onNursingTap(); + } else { + // 暂停光照逻辑 + this.handleWorkStatus(false, MODE_WORKING_ENUM.PAUSE); + } + this.setState({ + isStopNurse: !isStopNurse, + }); + }; + + /** + * @name 每次进入设备运行页,打开首个模式的介绍弹窗 + */ + openStepTips = () => { + let isFirstEntryModeNot = getStorageSync( + "isFirstEntryMode_" + this.state.currentDevice.id + ); + // 1.如果没有持久化不再提示,每次进入都会弹窗提示 + if (!isFirstEntryModeNot) { + // 2.必须要有数据才弹窗 + if (this.state.ActiveModeItem.openSourceData.length > 0) { + this.setState({ isShowStepTips: true }); + } + } + }; + closeStepTips = (data) => { + if (data.isLocal) { + setStorageSync("isFirstEntryMode_" + this.state.currentDevice.id, true); // 关闭首次进入弹窗 + } + this.setState({ isShowStepTips: false }); + }; + + /** 蓝牙相关 */ + switchBLEMatch = (jsonStatus: any) => { + console.log("蓝牙相关", jsonStatus); + let { ActiveModeItem } = this.state; + + switch (jsonStatus.bleCommandType) { + // 如果设备配对链接发送配对码的时候,设备应答小程序配对码是否正确。 + case "SendMatchCode": + if (jsonStatus.matchedSuccess) { + console.log("设备配对成功"); + this.setState({ + facialMaskConnectStatus: 1, + }); + } + break; + + // 设备状态主动上报,这种指令是主机主动上报某个附属设备断开或者连上了 + case "BleStatusSync": + console.log("BleStatusSync 附属设备状态主动上报", jsonStatus); + switch (jsonStatus.connectMessage?.deviceName) { + case "WL200": + if (jsonStatus.connectMessage?.connectType == "CONNECTED") { + } else { + this.setState({ + facialMaskConnectStatus: 0, // 蓝牙断开 + isFooterBtnDisabled: false, // 蓝牙断开所以不可点击 + }); + // 断开连接直接暂停:会自动暂停定时器 + this.judgementWorkStatus( + MODE_WORKING_ENUM.PAUSE, + ActiveModeItem?.modeType + ); + // 设备断开时,给定一个断开时间 + ActiveModeItem.breakTimeStr = this.state.currentTime; + } + break; + // 附属设备是否连接支架 + case "Stand": + if (jsonStatus.connectMessage?.connectType == "CONNECTED") { + console.log("舱体支架连接"); + this.setState({ + isStandStatus: true, + }); + if (!this.state.isStandStatus && this.isRuning) { + // 断开连接直接暂停 + this.judgementWorkStatus( + MODE_WORKING_ENUM.PAUSE, + ActiveModeItem?.modeType + ); + } + } else { + console.log("舱体支架断开连接"); + + if (this.state.isStandStatus && this.isRuning) { + // 断开连接直接暂停 + this.judgementWorkStatus( + MODE_WORKING_ENUM.PAUSE, + ActiveModeItem?.modeType + ); + } + + // 设备断开时,给定一个断开时间 + ActiveModeItem.breakTimeStr = this.state.currentTime; + + this.setState({ + isStandStatus: false, + isStopNurse: true, + ActiveModeItem, + }); + + setTimeout(() => { + this.onEmitErrorTips(); + }, 500); + } + setTimeout(() => { + this.footerIsDisabled(); + }, 100); + break; + default: + console.log("监听到到设备连接状态改变 this.footerIsDisabled()"); + this.footerIsDisabled(); // 判断底部运行按钮是否可点击 + break; + } + break; + + //小程序主动问主机,现在链接了哪些附属设备,这时候主机给小程序的回复消息 + case "QueryMatchStatus": + console.log("QueryMatchStatus 设备回复小程序", jsonStatus); + + const isStandDevice = jsonStatus?.subDeviceList?.includes("Stand"); + deviceToolKitInstance = deviceToolKitInstanceFR200; + console.log("支架是否链接", isStandDevice); + this.setState({ + isStandStatus: isStandDevice, + }); + setTimeout(() => { + this.footerIsDisabled(); + }); + + // 连上面罩后, 获取仪器记录, 与缓存信息对比 + if (!this.hadGotInstrumentHistoryData) { + // 查询护理记录 + this.getInstrumentHistoryData(); + + // 查询仪器状态 + const queryDeviceArrayBuffer = deviceToolKitInstance.toBleCommand( + bleCommandSamples.queryDeviceStatus as any + ); + console.log("发送查询设备指令 获取仪器状态"); + sendCommand({ + value: queryDeviceArrayBuffer, + }); + } + } + }; + + // 蓝牙特征更改 + notifyBLECharacteristicValueChange = () => { + console.log("notifyBLECharacteristicValueChange deviceInfo 参数为=>"); + const bluetoothInfo = this.props.bluetoothInfo; + notifyBLECharacteristicValueChange({ + deviceId: bluetoothInfo.deviceId, + servicesuuid: bluetoothInfo.servicesuuid, + characteristicsuuid1: bluetoothInfo.characteristicsuuid1, + characteristicsuuid0: bluetoothInfo.characteristicsuuid0, + }).then((res) => { + Taro.onBLECharacteristicValueChange((value) => { + const jsonStatus: any = deviceToolKitInstance.toJsonStatus(value.value); + console.log( + "onBLECharacteristicValueChange jsonStatus => ", + jsonStatus + ); + if (!jsonStatus || jsonStatus == null) { + return; + } + this.workStatus = jsonStatus.workStatus; // 记录工作状态 + // end 和 endWork 都是护理结束, endWork不关机, end 关机, 对小程序而言处理流程都一样 + if (jsonStatus.workStatus && jsonStatus.workStatus == "endWork") { + jsonStatus.workStatus = "end"; + console.log(jsonStatus.workStatus, "护理结束"); + } + + switch (jsonStatus?.commandType) { + //设备配对和连接的返回 + case "BleMatch": + // 蓝牙相关指令 + this.switchBLEMatch(jsonStatus); + // switch (jsonStatus.bleCommandType) { + // case 'SendMatchCode': + // if(jsonStatus.matchedSuccess){ + // //设备返回了蓝牙配对成功 + // }else{ + + // } + // break; + // default: + // break; + // } + + break; + //设备状态同步 + case "DeviceStatusSync": + console.log("设备状态同步", jsonStatus); + switch (jsonStatus.workStatus) { + case "standby": + //设备的待机状态 可能workMode字段为空 + break; + case "pause": + //设备的暂停状态 + break; + case "working": + //设备的运行中状态 + break; + default: + break; + } + + break; + //设备对控制指令的响应 + case "DeviceControl": + console.log("设备控制响应", jsonStatus); + // if (jsonStatus.responseStatus == "OK") { + // console.log("发送控制指令成功"); + // this.workJsonStatus = jsonStatus; + // this.workStatus = jsonStatus.workStatus; + + // setTimeout(() => console.log("this.workStatus", this.workStatus)); + // this.setState({ + // Electricity: jsonStatus.battery, + // // fr200Electricity: jsonStatus.battery, + // matrixElectricity: jsonStatus.matrixBattery, + // }); + + // // 判断设备主动上报的关机事件 + // if (jsonStatus.workStatus === MODE_WORKING_ENUM.END) { + // // 判断id是否一致, 一致的话则生成护理报表, 并提示 + // if (jsonStatus.id == this.WL200NursingHistory.id) { + // debounce( + // this.checkInstrumentRecord.bind(this, jsonStatus), + // 500 + // ); + // } + // return; + // } + + // if (jsonStatus?.workMode === this.state.ActiveModeItem.modeType) { + // this.setState({ + // workMode: jsonStatus?.workMode, // 仅当设备上报模式与小程序一致时,才允许改变小程序变量缓存 + // }); + + // // 判断是否在step == 2(护理中) + // // 仅当设备模式与小程序是否一致,才允许更改设备运行时间 + // if ( + // this.state.facialMaskConnectStatus === 1 && + // this.state.step == 2 && + // jsonStatus.workStatus !== MODE_WORKING_ENUM.END + // ) { + // this.updateDeviceSyncData( + // { + // totalWorkingMinutes: jsonStatus.totalWorkingMinutes, + // totalWorkingSeconds: jsonStatus.totalWorkingSeconds, + // }, + // jsonStatus + // ); + // } + // } + + // if ( + // jsonStatus.workMode === MODE_WORKING_ENUM.WORKING && + // this.state.step == 2 + // ) { + // const { ActiveModeItem } = this.state; + // const item = ActiveModeItem; + // if (jsonStatus.workMode !== item.modeType) { + // clearTimeout(loadingTipsTimer); + // this.setState({ + // isShowCountdown: false, + // }); + // } + // } + // } + break; + //设备对信息查询指令的响应 + case "InfoQuery": + switch (jsonStatus.infoQueryType) { + // 离线记录 + case "offlineClockInInfo": + console.log("离线记录", jsonStatus); + break; + // 版本信息 + case "versionInfo": + console.log("版本信息", jsonStatus); + break; + // 时间同步 + case "timeSync": + console.log("时间同步", jsonStatus); + break; + default: + break; + } + break; + default: + break; + } + }); + + /** + * 延迟600毫秒获取附属设备状态 + */ + const querySubDeviceArrayBuffer = deviceToolKitInstance.toBleCommand({ + ...bleCommandSamples.querySubDevice, + queryType: "WL200", + } as any); + setTimeout(() => { + console.log("发送查询附属设备指令 querySubDeviceArrayBuffer"); + sendCommand({ + value: querySubDeviceArrayBuffer, + }); + }, 600); + + /** + * 延迟500毫秒获取设备电量 + */ + const queryDeviceArrayBuffer = deviceToolKitInstance.toBleCommand( + bleCommandSamples.queryDeviceStatus as any + ); + setTimeout(() => { + console.log("发送查询设备电量指令"); + sendCommand({ + value: queryDeviceArrayBuffer, + }); + }, 500); + }); + }; + + /**监听关机事件*/ + onEndDevice = () => { + this.rmWL200NursingHistory(this.WL200NursingHistory, true); + // 判断护理时间,如果不足,则提示不足 + if (!this.isCheckNurseTime()) { + this.setState({ isNotEnoughTime: true }); + } else { + this.endNurseFun(); + } + }; + + /** 同步设备运行信息:运行时间 */ + updateDeviceSyncData = (newData, jsonStatus) => { + DeviceSyncData = { + ...DeviceSyncData, + ...newData, + }; + if (newData.hasOwnProperty("totalWorkingSeconds")) { + this.renderDeviceStatus.renderWorkTime(jsonStatus); + } + }; + + // 页面同步护理剩余时间 + renderDeviceStatus = { + renderWorkTime: (jsonStatus) => { + const { totalWorkingMinutes, totalWorkingSeconds } = DeviceSyncData; + let { ActiveModeItem, currentTime } = this.state; + const totalTime = totalWorkingMinutes * 60 + totalWorkingSeconds; + console.log("仪器上报的已经运行的总秒数", totalTime); + console.log("时间校准频率,默认5秒一次", TIME_CALIBRATION_FREQUENCY); + //对比仪器上报运行的总秒数 和小程序页面运行的已经运行的总秒数,如果不一致就进行校准 + const currentScene = ActiveModeItem; // 获取当前的场景 + let sceneTime = ActiveModeItem?.breakTimeStr + ? minSecToS(ActiveModeItem.breakTimeStr) + : minSecToS(currentScene.modeTimeStr); // 场景时间 + + console.log("场景时间 sceneTime", sceneTime); + console.log("当前显示时间 currentTime", currentTime); + console.log("设备运行时间 totalTime", totalTime); + + // 更新界面倒计时 + this.resetTimer(); + + if ( + sceneTime > totalTime && + this.state.step == 2 && + this.state.facialMaskConnectStatus == 1 + ) { + // 界面倒计时同步设备时间 + const t = sceneTime - totalTime; // 场景时间 - 已运行时间 = 剩余时间 + this.setState({ + currentTime: s_to_ms(t), + }); + } else { + this.setState({ + currentTime: "00:00", + }); + this.judgementWorkStatus(MODE_WORKING_ENUM.END, jsonStatus.workMode); + } + + // 每次同步后,更新历史缓存 + setTimeout(() => { + this.updateWL200NursingHistory(); + }, 100); + }, + }; + + // 仪器开始倒计时 + setLoadingTips(time) { + this.setState({ + countdown: time, + }); + if (time >= 0) { + loadingTipsTimer = setTimeout(() => { + this.setLoadingTips(--time); + }, 1000); + } else { + // 停止倒计时 + // that.data.startSettingCountDown = false; + this.setState({ + isShowCountdown: false, + }); + } + } + + /** + * 设备上报不同状态 + * params 工作状态 工作模式 响应状态 + */ + judgementWorkStatus(nWorkStatus, nWorkMode) { + const { step, workMode, ActiveModeItem, ModeList } = this.state; + const opts: any = {}; + // ActiveModeItem + let nowModeItem; + if (nWorkMode) { + nowModeItem = ModeList.find((item) => { + return item.modeType === nWorkMode; + }); + } + opts.workStatus = nWorkStatus; + + let nowCurrentTime = ActiveModeItem.modeTimeStr; + // 完成重连同步则删除重连时间字段 + if (ActiveModeItem?.breakTimeStr) { + nowCurrentTime = ActiveModeItem?.breakTimeStr; + } + + const statusF = { + sleep: () => { + this.setState({ + isShowCountdown: false, + }); + }, + standby: () => { + this.setState({ + isShowCountdown: false, + }); + if (nowModeItem?.isCabinMode && step == 2) { + opts.currentTime = nowCurrentTime; + } else if (!nowModeItem?.isCabinMode && step == 2) { + // fix: 启动非支架模式倒计时时,连上支架,仪器的状态变为standby + opts.step = 1; + } + }, + setting: () => { + // that.data.hadShowBreakTips = false; + this.setState({ + hadShowBreakTips: false, + }); + if (step != 2 && !ActiveModeItem.isCabinMode) { + opts.step = 2; + this.setState({ + title: "正在护理", + isStopNurse: false, + }); + } else if (step != 2 && ActiveModeItem.isCabinMode) { + opts.step = 2; + // this.setState({ + // title: "正在护理", + // }); + this.setState({ + title: "正在护理", + isStopNurse: false, + }); + } + if (nowModeItem) { + opts.currentTime = nowCurrentTime; + } + // startSettingCountDown 用于标记打开了倒计时loading + if (!this.state.isShowCountdown) { + this.setState({ + isShowCountdown: true, + }); + this.setLoadingTips(CountDownTime[workMode] || 6); + } + }, + working: () => { + if (this.state.facialMaskConnectStatus != 1) { + opts.workStatus = MODE_WORKING_ENUM.STANDBY; + opts.step = 1; + } else if (step != 2) { + opts.step = 2; + this.setState({ + title: "正在护理", + isStopNurse: false, + }); + } + + this.setState({ + isShowCountdown: false, + hadShowBreakTips: false, + }); + }, + pause: () => { + clearInterval(currentTimeTimer); + this.setState({ + isShowCountdown: false, + }); + if (ActiveModeItem.isCabinMode) { + this.setState({ + title: "暂停护理", + isStopNurse: true, + }); + } + }, + end: () => { + // 已进入了报告阶段, 防止重复进入, 主要防止在手动点击结束护理接收到仪器消息 + console.log("END 护理结束"); + clearInterval(currentTimeTimer); + + this.endnursing(true); + }, + }; + statusF[nWorkStatus] && statusF[nWorkStatus](); + if (Object.keys(opts).length) { + this.setState(opts); + } + } + + /** + * 保存护理报告 + * 1.是否跳转 2.数据 + * */ + saveNurseReport = async (isJump = true, from) => { + this.endNurseFun(); + }; + + /** + * 结束护理 + * param isAuto 是否仪器自动结束 + */ + endnursing = (isAuto) => { + if (isAuto == true) { + // 仪器自动上报完成, 直接上报并跳转报告页 + clearInterval(currentTimeTimer); + const isEnough = this.isCheckNurseTime(); + if (isEnough) { + this.saveNurseReport(true, "endnursing"); + } + } else { + // 手动点击结束, 弹出弹窗, 看看是否需要结束 + this.onEndPlan(); + } + }; + + // 重置并同步计时器 + resetTimer = () => { + // 切换模式后, 需要重新设置计时器, 以防进行中的计时器 + currentTimeTimer && clearInterval(currentTimeTimer); + currentTimeTimer = setInterval(() => { + let { + step, + facialMaskConnectStatus, + currentTime, + ModeStepTimeArray, + ModeStepIndex, + ActiveModeItem, + } = this.state; + if ( + this.workStatus == MODE_WORKING_ENUM.WORKING && + step == 2 && + facialMaskConnectStatus == 1 + ) { + let totalSeconds = ActiveModeItem?.breakTimeStr + ? minSecToS(ActiveModeItem.breakTimeStr) + : minSecToS(ActiveModeItem.modeTimeStr); + // 现在的倒计时剩余时间:同步时检查是否断开重连,如果是,则使用断开的剩余时长,进行倒计时计算 + let currentSeconds = minSecToS(currentTime); + let checkTime = totalSeconds - currentSeconds; + + // 缓存经过的时间:用于接口提交 + this.elapsedTime = checkTime; + // 如果存在中断时间,则要加上间隔的时间 + if (ActiveModeItem?.breakTimeStr) { + let intervalTime = + minSecToS(ActiveModeItem.modeTimeStr) - + minSecToS(ActiveModeItem.breakTimeStr); + this.elapsedTime += intervalTime; + } + + // 判断剩余时间是否大于1 + if (currentSeconds >= 1) { + // 小程序显示倒计时 + this.setState({ + currentTime: s_to_ms(--currentSeconds), + }); + + let length = ModeStepTimeArray.length; + if (length) { + // 模式多个步骤节点切换 + // 已运行时间达到下一节点时,切换 + if (checkTime > ModeStepTimeArray[ModeStepIndex]) { + // 已运行时间达到下一节点,且存在下一节点,步骤切换时更新 + if (ModeStepIndex < length - 1) { + let index = ModeStepIndex + 1; // 提前步骤+1 + let currentServiceData = { + startSource: "", + stopSource: "", + }; + let serviceLength = ActiveModeItem.serviceData.length; + if (serviceLength > index) { + currentServiceData = ActiveModeItem.serviceData[index]; + } + + console.log("********************"); + console.log("********************"); + console.log( + "仅在时间达到下一步,步骤切换时更新currentServiceData", + currentServiceData + ); + this.setState({ + ModeStepIndex: index, + currentServiceData, + }); + } + } + } + } else { + clearInterval(currentTimeTimer); + this.setState({ + currentTime: "00:00", + ModeStepIndex: 0, + }); + this.saveNurseReport(true, "setTimer"); // 保存护理计划,并且结束 + } + } + }, 1000); + }; + + // 检测并控制工作状态 + handleWorkStatus = (isBtnClick: boolean, workStatus) => { + const { facialMaskConnectStatus, isStandStatus, ActiveModeItem } = + this.state; + let newWorkStatus = + workStatus || + (this.workStatus == MODE_WORKING_ENUM.WORKING ? "pause" : "working"); + if (isBtnClick && newWorkStatus == "working") { + // 舱体模式 + if (ActiveModeItem.isCabinMode === 1 && !isStandStatus) { + this.showTips( + `检测到舱体未连接成功,请确认面罩开机后与舱体连接,并接通舱体电源` + ); + return; + } + // 非舱体模式 + if (!ActiveModeItem.isCabinMode && facialMaskConnectStatus != 1) { + console.log("facialMaskConnectStatus", facialMaskConnectStatus); + this.showTips("检测到面罩未连接成功,请确认面罩开机并佩戴"); + return; + } + } + + const sendParams = { + ...deviceCommandSamples.pause, + workMode: ActiveModeItem.modeType, // 使用模式 + workStatus: newWorkStatus, + }; + console.log("准备发送自定义或工作指令", ActiveModeItem, sendParams); + const pauseArrayBuffer = deviceToolKitInstance.toBleCommand( + sendParams as any + ); + sendCommand({ + value: pauseArrayBuffer, + }).then(() => { + this.workStatus = newWorkStatus; + this.resetTimer(); + console.info( + `handleWorkStatus 发送${newWorkStatus}指令成功 参数为 =>`, + sendParams + ); + }); + }; + + /** + * @name 点击开始护理 + * @params type 传值 switch 则用于区分是否切换模式的启动 + */ + onNursingTap(type = "") { + // 如果已禁止运行,则停止执行后续逻辑 + if (this.state.isFooterBtnDisabled) return; + // 防止多次点击 + if (this.state.hadClickStart) return; + this.setState({ + hadClickStart: true, + }); + setTimeout(() => { + this.setState({ + hadClickStart: false, + }); + }, 500); + + const { ActiveModeItem, isStandStatus, facialMaskConnectStatus } = + this.state; + + if (isStandStatus === true && ActiveModeItem.isCabinMode === 0) { + console.log("已连接舱体,只可选择舱体模式"); + return; + } + if (isStandStatus === false && ActiveModeItem.isCabinMode === 1) { + console.log("未连接舱体!"); + return; + } + + console.info( + commandMap.WL200Command, + "点击开始护理按钮", + `当前模式: ${ActiveModeItem.modeType}`, + `当前面罩状态:${facialMaskConnectStatus}`, + `当前仪器模式:${this.workStatus}` + ); + console.log(ActiveModeItem); + console.log("isStandStatus:" + isStandStatus); + + if (facialMaskConnectStatus != 1) { + console.log("facialMaskConnectStatus 开始处", facialMaskConnectStatus); + this.showTips("检测到面罩未连接成功,请确认面罩开机并佩戴"); + return; + } + // 如果是强效舒缓,需要判断是否连接支架 + if (ActiveModeItem.isCabinMode && !isStandStatus) { + this.showTips( + `检测到舱体未连接成功,请确认面罩开机后与舱体连接,并接通舱体电源` + ); + return; + } else if (!ActiveModeItem.isCabinMode && isStandStatus) { + this.showTips(`检测到面罩仍和舱体连接中,请分离后切换`); + return; + } + if ( + ActiveModeItem.modeType === "MaskCustom" && + !this.state.isCombineSuccess + ) { + this.showTips(`${ActiveModeItem.modeName}模式设置失败,请联系小助手`); + return; + } + + // 仅在切换模式的时候,弹窗倒计时. + if (type === "switch") { + let downNum = CountDownTime[ActiveModeItem.modeType] || 3; + this.showCountdownFun(downNum, () => {}); // 倒计时弹窗 + } + + // 开始执行护理 + this.workStatus = MODE_WORKING_ENUM.WORKING; // 不管当前什么状态,直接设为工作状态 + this.handleWorkStatus(true, MODE_WORKING_ENUM.WORKING); + this.setState({ + isStopNurse: false, + }); + } + + // 结束护理 + endNurseFun() { + this.handleWorkStatus(false, "end"); + if (this.isCheckNurseTime()) { + this.PostNursingLogClock(); + } else { + // 时间不满足,回到主页 + this.handleWorkStatus(false, "end"); + this.setState({ + isEndCarePlan: false, + isNotEnoughTime: true, + }); + } + } + + /** 检查时间是否达标仪器最低护理时间 */ + isCheckNurseTime() { + const { currentDevice, ActiveModeItem } = this.state; + const currentScene = ActiveModeItem; + let sceneTime = minSecToS(currentScene.modeTimeStr); + const timeRemaining = sceneTime - minSecToS(this.state.currentTime); // 当前模式已运行时间 + + let nursingTimeStr = currentDevice?.nursingTimeStr; + let nursingTime = nursingTimeStr ? minSecToS(nursingTimeStr) : 60; // 设备生成护理记录至少需要运行时间 + + console.log("检查已运行时间", timeRemaining, nursingTime); + if (timeRemaining >= nursingTime) { + return true; + } else { + return false; + } + } + /*** 护理记录 START ***/ + /** 小程序查询护理记录 */ + getInstrumentHistoryData() { + this.hadGotInstrumentHistoryData = true; + console.log("发送指令currentMaskReportInfo 获取设备护理记录"); + setTimeout(() => { + const queryCurrentMaskReportInfoBuffer = + deviceToolKitInstance.toBleCommand({ + ...(bleCommandSamples.queryCurrentMaskReportInfo as any), + }); + sendCommand({ + value: queryCurrentMaskReportInfoBuffer, + }); + }, 3000); + } + /** + * @title 检查护理记录 + * @description + * 1.判断是否存在工作状态:如果不存在,则等待两秒用于连接设备与赋值,再执行后面的代码 + * + * 2.判断是否已存在缓存的护理记录:如果没有历史,则缓存 + * + * 3.判断是否当天(如果不是当天,则删除记录) + * + * 4.判断设备状态-未运行/已完成/待机 + * 4-1.已有缓存护理记录,判断ID一致,同步时间。若主动结束,需判断时间是否满足仪器最低护理时间,满足直接跳转护理报告页;不满足需提示不满足,回到首页 + * 4-2.已有缓存护理记录,判断ID不一致(同步异常)。直接提交,固定设置为一分钟。 + * + * 5.判断设备状态-运行中 + * 正常执行逻辑 + * + * */ + checkInstrumentRecord = async (jsonStatus: any) => { + console.log("检查护理记录"); + let { currentDevice, ActiveModeItem, ModeList } = this.state; + + await sleep(2); + + let isSyncHistory = Taro.getStorageSync("isSyncHistory"); + if (isSyncHistory) { + this.setState({ isShowHistoryMsg: false }); + Taro.removeStorageSync("isSyncHistory"); + } + console.log( + "this.workJsonStatus", + this.workJsonStatus, + this.workJsonStatus.workMode + ); + + this.setState({ + isFooterBtnDisabled: false, + }); + if (this.workJsonStatus.workMode) { + console.log("this.workJsonStatus.workMode", this.workJsonStatus.workMode); + if (this.workJsonStatus.workMode.indexOf("Stand") > -1) { + console.log( + "this.workJsonStatus.workMode", + this.workJsonStatus.workMode + ); + this.setState({ + isStandStatus: true, + }); + setTimeout(() => this.footerIsDisabled(), 100); + } + } + + // 2.判断是否已存在缓存的护理记录:如果没有历史,则缓存 + let workStatus = this.workJsonStatus.workStatus; + let WL200NursingHistory = this.WL200NursingHistory; + if (!this.WL200NursingHistory) { + console.log("小程序缓存没有数据, 忽略"); + if ( + workStatus == MODE_WORKING_ENUM.WORKING || + workStatus == MODE_WORKING_ENUM.PAUSE + ) { + // 缓存没有数据, 要存缓存 + this.setWL200NursingHistory(jsonStatus); + } + return; + } + + // 3.判断是否当天(如果不是当天,则删除记录) + if (!dayjs().isSame(WL200NursingHistory?.createDate, "day")) { + console.log("小程序缓存有数据,但是不是当天数据,忽略"); + this.rmWL200NursingHistory(WL200NursingHistory); + return; + } + + // 仪器缓存模式,判断是否存在于现有模式中 + let recordModeItem = ModeList.find((item) => { + return item.id == WL200NursingHistory.currentServiceData.modeId; + }); + if (!WL200NursingHistory || !recordModeItem) { + console.log("仪器有数据, 但是缓存没有数据, 忽略"); + return; + } + + console.log("workStatus", workStatus); + console.log("jsonStatus", jsonStatus, this.workJsonStatus); + console.log("currentTime", WL200NursingHistory.currentTime); + console.log("isStandStatus", this.state.isStandStatus); + + let historyElapsedTime = + minSecToS(recordModeItem.modeTimeStr) - + minSecToS(WL200NursingHistory.currentTime); + + this.elapsedTime = + this.elapsedTime > historyElapsedTime + ? this.elapsedTime + : historyElapsedTime; + // 4.判断设备状态-未运行/已完成/待机 + if ( + workStatus == MODE_WORKING_ENUM.STANDBY || + workStatus == MODE_WORKING_ENUM.END || + !workStatus + ) { + // 判断id是否一致, 一致的话则生成护理报表 + if (jsonStatus.id == WL200NursingHistory.id) { + console.log("id一致, 设备没有运行/已完成/待机"); + let totalSeconds = jsonStatus.totalSeconds; // 从仪器上获取的使用时间 + + let nursingTimeStr = currentDevice?.nursingTimeStr; + let nursingTime = nursingTimeStr ? minSecToS(nursingTimeStr) : 60; // 设备生成护理记录至少需要运行时间 + + if (totalSeconds < nursingTime) { + // 护理时间不足 + this.setState({ isNotEnoughTime: true }); + this.rmWL200NursingHistory(WL200NursingHistory); + return; + } + + // 小程序时间和设备时间,谁大用谁 + let timeValue = + totalSeconds > this.elapsedTime + ? s_to_hms(totalSeconds) + : s_to_hms(this.elapsedTime); + + let params = { + instrumentId: currentDevice.id, + instrumentName: currentDevice.name, + modeId: ActiveModeItem.id, + modeName: ActiveModeItem.modeName, + nursingTime: timeValue, + }; + this.handleWorkStatus(false, "end"); + let res: any = await this.PostNursingLogClock(params); + console.log("res", res); + this.rmWL200NursingHistory(WL200NursingHistory); + } else { + // ID不一致,同步异常,统一提交一分钟 + let params = { + instrumentId: currentDevice.id, + instrumentName: currentDevice.name, + modeId: ActiveModeItem.id, + modeName: ActiveModeItem.modeName, + nursingTime: "00:01:00", + }; + this.handleWorkStatus(false, "end"); + let res: any = await this.PostNursingLogClock(params); + console.log("res", res); + this.rmWL200NursingHistory(WL200NursingHistory); + } + } else { + console.log("id一致, 设备运行中或暂停"); + // 5.判断设备状态-运行中 + // 同步时间 + if (jsonStatus.id == WL200NursingHistory.id) { + if (WL200NursingHistory.currentTime) { + this.setState({ + step: 2, + }); + this.resetTimer(); + } + } + } + }; + + /** 获取小程序本地缓存的历史记录 */ + getWL200NursingHistory() { + this.WL200NursingHistory = Taro.getStorageSync("WL200NursingHistory"); + + // 是否同步历史记录 + let isSyncHistory = Taro.getStorageSync("isSyncHistory"); + if (isSyncHistory) { + let ActiveModeItem = this.WL200NursingHistory.ActiveModeItem; + // 直接进入开始护理状态 + this.setState({ + isShowNurse: true, + isShowHistoryMsg: true, + currentServiceData: this.WL200NursingHistory.currentServiceData, + tempModeCurrent: ActiveModeItem, + ActiveModeItem: ActiveModeItem, + activeModeID: ActiveModeItem.id, + ModeID: "mode_" + ActiveModeItem.id, + currentTime: this.WL200NursingHistory.currentTime, + }); + setTimeout(() => { + // 设置时间组合 + if (ActiveModeItem.serviceData.length > 0) { + this.setServiceTimeData(); + } + // 存在组合模式时,设置组合模式 + if (ActiveModeItem.combineData.length > 0) { + this.setCustomMaskData(); + } + }); + } + } + /** 设置WL200护理历史 */ + setWL200NursingHistory = (jsonStatus: any) => { + let { currentDevice, ActiveModeItem, ModeList } = this.state; + const params = { + createDate: dayjs().format("YYYY-MM-DD"), + workMode: jsonStatus.workMode, + instrumentId: currentDevice.id, + instrumentName: currentDevice.name, + modeId: ActiveModeItem.id, + modeName: ActiveModeItem.modeName, + id: jsonStatus.id, + neededTotalSeconds: jsonStatus.neededTotalSeconds, + jsonStatus, + ActiveModeItem: this.state.ActiveModeItem, + }; + this.WL200NursingHistory = JSON.parse(JSON.stringify(params)); + Taro.setStorageSync("WL200NursingHistory", params); + console.log("保存setWL200NursingHistory"); + }; + /** 更新WL200护理历史运行时间 */ + updateWL200NursingHistory = (data: any = null) => { + this.WL200NursingHistory = Taro.getStorageSync("WL200NursingHistory"); + + if (this.WL200NursingHistory) { + let params: any = this.WL200NursingHistory; + + // 设置当前时间 + params.currentTime = this.state.currentTime; + + // 设置正确封面 + if (data) { + params.currentServiceData = data; + } else { + let currentServiceData = { + startSource: "", + stopSource: "", + }; + let serviceLength = this.state.ActiveModeItem.serviceData.length; + if (serviceLength > 0) { + currentServiceData = this.state.ActiveModeItem.serviceData[0]; + } + params.currentServiceData = currentServiceData; + } + Taro.setStorageSync("WL200NursingHistory", params); + console.log("更新updateWL200NursingHistory"); + } + }; + /** + * @name 删除WL200护理历史 + * @description 参数1 护理历史 参数2 强制删除 + * 如果传入护理历史ID与现有ID相等,则删除。 + * 如果参数二为真,则强制删除 + */ + rmWL200NursingHistory = (WL200NursingHistory, hard = false) => { + const nowWL200NursingHistory = Taro.getStorageSync("WL200NursingHistory"); + if (nowWL200NursingHistory.id == WL200NursingHistory.id) { + Taro.removeStorageSync("WL200NursingHistory"); + this.WL200NursingHistory.id = ""; + } else if (hard) { + Taro.removeStorageSync("WL200NursingHistory"); + this.WL200NursingHistory.id = ""; + } + }; + + /** 提交护理记录 */ + PostNursingLogClock = async (data: any = null, isJump = true) => { + let { currentDevice, ActiveModeItem } = this.state; + + let params = {}; + if (data) { + params = data; + } else { + params = { + instrumentId: currentDevice.id, + instrumentName: currentDevice.name, + modeId: ActiveModeItem.id, + modeName: ActiveModeItem.modeName, + nursingTime: s_to_hms(this.elapsedTime), + }; + } + + let res: any = await InstrumentInfo.apiNursingLog.addLog(params); + console.log("PostNursingLogClock", res); + + if (res.data.code === 200) { + let params = { + instrumentId: currentDevice.id, + }; + // 上传护理完成的仪器ID + let res = await InstrumentInfo.apiClock.addClockInstrument(params); + console.log(res, "护理完成"); + + this.rmWL200NursingHistory(this.WL200NursingHistory); // 护理完成,删除记录 + if (isJump) { + this.setState({ + isShowNursingSuccess: true, + }); + setTimeout(() => { + this.setState({ + isShowNursingSuccess: false, + }); + this.goFaceReport(); + }, 2000); + } + } + }; + /*** 护理记录 END ***/ + + //蓝牙断开连接处理 + bluetoothDisconnectProcessing() { + clearInterval(timer); + Taro.offBLEConnectionStateChange(this.listener); // 需传入与监听时同一个的函数对象 + Taro.offBLECharacteristicValueChange((res) => { + console.log("offBLECharacteristicValueChange", res); + }); + if (!this.state.isToOTA) { + Taro.closeBluetoothAdapter(); + } + } + + /** 获取护理时间组合 */ + getServiceTimeData() { + const { ActiveModeItem } = this.state; + let serviceData = ActiveModeItem.serviceData.map((item) => { + let totalWorkingMinutes = parseInt( + item.serviceStartTimeStr.split(":")[0] + ); // 仅分钟数 + let totalWorkingSeconds = parseInt(item.serviceEndTimeStr.split(":")[1]); // 仅秒数 + // let totalWorkingMinutes = 1; // 仅分钟数 + // let totalWorkingSeconds = 0; // 仅秒数 + return { + totalWorkingMinutes, + totalWorkingSeconds, + }; + }); + return serviceData; + } + /** 设置护理时间组合 */ + setServiceTimeData() { + let ServiceTimeData = this.getServiceTimeData(); + + // 组合时间 + let ModeStepTimeArray: any = []; + ServiceTimeData.reduce((old, cur) => { + let curTime = cur.totalWorkingMinutes * 60 + cur.totalWorkingSeconds; + let newTotalWorkingMinutes = cur.totalWorkingMinutes; + let newTotalWorkingSeconds = cur.totalWorkingSeconds; + if (old) { + newTotalWorkingMinutes += old.totalWorkingMinutes; + newTotalWorkingSeconds += old.totalWorkingSeconds; + + let oldTime = old.totalWorkingMinutes * 60 + old.totalWorkingSeconds; + let value = oldTime + curTime; + ModeStepTimeArray.push(value); + return { + totalWorkingMinutes: newTotalWorkingMinutes, + totalWorkingSeconds: newTotalWorkingSeconds, + }; + } + ModeStepTimeArray.push(curTime); + return { + totalWorkingMinutes: newTotalWorkingMinutes, + totalWorkingSeconds: newTotalWorkingSeconds, + }; + }, null); + this.setState({ + ModeStepTimeArray: ModeStepTimeArray, + ModeStepIndex: 0, // 每次切换组合模式,重置组合步骤 + }); + console.log("组合时间ModeStepTimeArray", ModeStepTimeArray); + } + + /* 组合模式 */ + /** 获取自定义组合模式数组 */ + getCustomModesArray = () => { + const { ModeList, ActiveModeItem } = this.state; + const combineIds = ActiveModeItem.combineData.map( + (item) => item.combineModeId + ); + let modesArray = ModeList.filter((item) => + combineIds.includes(item.id) + ).map((item) => { + let totalWorkingMinutes = parseInt(item.modeTimeStr.split(":")[0]); // 仅分钟数 + let totalWorkingSeconds = parseInt(item.modeTimeStr.split(":")[1]); // 仅秒数 + return { + workMode: item.modeType, + totalWorkingMinutes, + totalWorkingSeconds, + }; + }); + return modesArray; + }; + setCustomMaskData() { + console.log("================"); + console.log("setCustomMaskData"); + console.log("================"); + + // modesArray 发送组合模式数组指令到设备存储 + let modesArray = this.getCustomModesArray(); + console.log("组合模式modesArray", modesArray); + + let customModeSetCommand = { + commandType: "InfoQuery", + infoQueryType: "customModeSet", + modesArray, + }; + let commandBuffer = deviceToolKitInstance.toBleCommand( + customModeSetCommand as any + ); + sendCommand({ + value: commandBuffer, + }).then((res) => { + console.info("发送切换组合模式指令成功", res); + }); + } + // 发送启动组合模式指令 + startCombinationMode() { + const jsonCommand = { + commandType: "DeviceControl", + workStatus: "working", + workMode: "MaskCustom", + }; + let commandBuffer = deviceToolKitInstance.toBleCommand(jsonCommand as any); + sendCommand({ + value: commandBuffer, + }).then(() => { + console.info("发送启动组合模式指令成功 参数为 =>", jsonCommand); + }); + } + + // 护理的错误提示 + showTips(ctx) { + if (!ctx) return; + if (showTipsTimer) clearTimeout(showTipsTimer); + this.setState({ + errorTips: ctx, + }); + showTipsTimer = setTimeout(() => { + this.setState({ + errorTips: "", + }); + }, 2000); + } + + /** 结束护理弹窗 */ + onEndPlan = async () => { + this.setState({ + isEndCarePlan: true, + }); + }; + confirmEndBtn = () => { + console.log("confirmEndBtn", this.isCheckNurseTime()); + if (this.isCheckNurseTime()) { + this.endNurseFun(); + this.cancelEndBtn(); + } else { + this.handleWorkStatus(false, "end"); + this.setState({ + isEndCarePlan: false, + isNotEnoughTime: true, + }); + } + }; + cancelEndBtn = () => { + this.setState({ + isEndCarePlan: false, + }); + }; + /** 弹窗 END*/ + + // 打开通用错误弹窗 + openErrorTipsText = (str) => { + this.setState({ + isShowErrorTipsText: true, + errorTipsText: str, + }); + }; + // 关闭通用错误弹窗 + closeErrorTipsText = () => { + this.setState({ + isShowErrorTipsText: false, + }); + }; + + closeNotEnoughTime = () => { + this.setState({ + isNotEnoughTime: false, + }); + Taro.reLaunch({ + url: "/pages/index/index", + }); + }; + + /** 完成护理提交:跳转护理报告页 */ + goFaceReport = () => { + // 跳转前置空定时器,防止重复提交 + if (currentTimeTimer) clearInterval(currentTimeTimer); + go("/pages/face_report/face_report?id=" + this.state.currentDevice.id); + }; + + // 完成配对 + pairingChange = () => { + this.setState({ + isConnectShow: false, + isShowNurse: true, + }); + setTimeout(() => { + this.onNursingTap("switch"); + }); + }; + connectionClose = () => { + this.setState({ + isConnectShow: false, + }); + Taro.reLaunch({ url: "/pages/index/index" }); + }; + + // 手动护理模式切换:提示是否保存护理 + /**仅关闭*/ + closeTipsSave = () => { + this.setState({ + isShowTipsSave: false, + }); + }; + /**关闭+切换*/ + cancelTipsSave = () => { + this.setState({ + isShowTipsSave: false, + }); + this.modeCurrentFun(this.tempModeCurrent, true); // 不提交护理记录,也不进行校验 + }; + /**关闭+提交+切换*/ + confirmTipsSave = async () => { + this.setState({ + isShowTipsSave: false, + }); + this.PostNursingLogClock(null, false); // 先提交护理记录 + this.modeCurrentFun(this.tempModeCurrent, true); // 不进行校验 + }; + + /** 初次护理信息弹窗 */ + firstNurseInfo = async () => { + let { currentDevice } = this.state; + let res = await InstrumentInfo.firstNurseInfo({ + instrumentId: currentDevice.id, + }); + console.log(res, "接口"); + + if (res.data.code === 200) { + let isFirstTipShow = getStorageSync( + "first_instrument_" + currentDevice.id + ); + console.log(isFirstTipShow, "查看返回值"); + + if (!isFirstTipShow) { + if (res.data.data.length !== 0) { + // 首次进入页面:自动打开打卡介绍弹窗 + this.setState({ nurseInfo: res.data.data, isFirstTipShow: true }); + } + + setStorageSync("first_instrument_" + currentDevice.id, true); + } else { + this.setState({ nurseInfo: res.data.data }); + } + } + }; + onTipShowOpen = async () => { + this.setState({ isFirstTipShow: true }); + }; + onTipShowClose = async () => { + setStorageSync("first_instrument_" + this.state.currentDevice.id, true); + this.setState({ isFirstTipShow: false }); + }; + /** 初次护理信息弹窗 END */ + + /** + * @name 设备运行开关按钮是否禁用 + * @description 判断所选模式与设备连接状态是否一致 + * @returns 返回true则禁用 + */ + footerIsDisabled = () => { + let { isStandStatus } = this.state; + let isCanClick = isStandStatus + ? this.tempModeCurrent?.isCabinMode === 1 + : this.tempModeCurrent?.isCabinMode === 0; + // 如果舱体状态和模式类型不相等,则禁用 + let isFooterBtnDisabled = false; + + if (!isCanClick) { + isFooterBtnDisabled = true; + } + console.log("isCanClick", isCanClick); + console.log("isFooterBtnDisabled", isFooterBtnDisabled); + // 仅在值变化时更新state + // if (isFooterBtnDisabled !== this.state.isFooterBtnDisabled) { + this.setState({ + isFooterBtnDisabled: isFooterBtnDisabled, + }); + // } + + return isFooterBtnDisabled; // 数据更新有延迟,返回用于判断 + }; + + customBack = () => { + Taro.reLaunch({ url: "/pages/index/index" }); + }; + + render() { + let { + title, + isConnectShow, + isShowStepTips, + isShowNurse, + isStopNurse, + ModeList, + ModeType, + ModeStepIndex, + currentServiceData, + ActiveModeItem, + SwitchActiveModeItem, + isSwitchActiveMode, + ModeID, + activeModeID, + isShowCountdown, + countdown, + Electricity, + matrixElectricity, + errorTips, + isEndCarePlan, + currentTime, + facialMaskConnectStatus, + isShowErrorTipsText, + errorTipsText, + isNotEnoughTime, + isShowNursingSuccess, + currentDevice, + isConnectionBlutoot, + isShowTipsSave, + isFirstTipShow, + nurseInfo, + isShowReReadRecordSave, + isFooterBtnDisabled, + isShowHistoryMsg, + stepIndex, + } = this.state; + + return ( + + + + + + + + + + + } + textAlgin="center" + cancelButtonText="取消" + confirmButtonText="确定" + close={this.cancelModeSwitchBtn} + confirm={this.confirmModeSwitchBtn} + /> + + {ActiveModeItem.openSourceData && ( + + )} + + + + + + + 当前模式已护理部分时间 + 是否保存护理记录 + + } + cancelButtonText="取消" + confirmButtonText="确认" + textAlgin="center" + close={this.closeTipsSave} + cancel={this.cancelTipsSave} + confirm={this.confirmTipsSave} + /> + + { + /*不需要做处理*/ + }} + /> + + {isConnectShow && ( + {}} + pairingChange={this.pairingChange} + upgradeFun={() => {}} + /> + )} + + + 正在同步护理记录... + + + + + + + + {!isShowNurse && ( + + + + + + 护理时间: + {currentTime} + + + + + + + + {ModeList.length > 0 && ( + + )} + + {ActiveModeItem.combineData && ( + + )} + + {/* */} + + +