You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2152 lines
67 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import Taro from "@tarojs/taro";
import dayjs from "dayjs";
import classnames from "classnames";
// 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 } from "@/utils/traoAPI";
import { InstrumentInfo } from "@/utils/Interface";
import "./iotCarePlan.less";
import UpdateIotWL200 from "@/components/bluetoot/update-wl200/index";
// import log from "@/utils/log";
// log.info("123456info", 123456, { sdfasdf: 123 });
import {
notifyBLECharacteristicValueChange,
sendCommand,
} from "@/utils/bluetoothWXAPI";
import {
deviceCommandSamples,
bleCommandSamples,
} from "@/components/bluetoot/connection/test";
import { Progress } from "@antmjs/vantui";
import {
s_to_s,
s_to_m,
minSecToS,
s_to_ms,
s_to_hms,
sleep,
} from "@/utils/util";
import { DeviceToolKit as DeviceToolKitWE100 } from "@flossom-npm/iot-translater-we100";
import commandMap from "@/utils/commandMap";
const deviceToolKitInstanceWL200 = new DeviceToolKitWE100("WL200", "WL200");
let currentTimeTimer: any = null; // 当前项目时间定时器
let CountdownTimer: any = null;
let timer: any = null;
let checkVersionTimeout: any = null;
let showTipsTimer: any = null;
let loadingTipsTimer: any = null; // 蓝牙连接提示
let switchModeStatus = "free"; // 用于标记是否在切换模式中, free: 空闲, switching: 切换中
// 设备运行时间校准频率,每多少秒校准一次
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 = deviceToolKitInstanceWL200;
class IotCarePlan extends Component<any, any> {
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, // 是否展示过支架断开提示
popupType: "", // enoughTimePopup: 时间达标提示, endPopup: 结束弹窗
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: false,
};
}
// 不涉及渲染的页面变量
isRuning: any = false; // 设备是否运行中
jsonStatus: any = {}; // 同步设备返回数据,用于结束
tempModeCurrent: any = {}; // 临时保存的当前模式
elapsedTime: any = 0; // 设备已运行时间
workStatus: any = ""; // 工作状态
WL200NursingHistory: any = null; // 护理缓存历史
hadCheckReport = false; // 是否已检查仪器护理记录
hadGotInstrumentHistoryData = false; // 是否已缓存仪器历史数据
hadLoadedPage = false; // 判断是否首次进入页面
async onLoad() {
// 保持屏幕常亮
Taro.setKeepScreenOn({
keepScreenOn: true,
});
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 objStr = getStorageSync("instrument_detail");
if (objStr) {
let info = JSON.parse(objStr);
this.setState({
currentDevice: info,
});
await this.GetModeList(info.id);
console.log("info");
// 如果不存在设备模式值,则判断为首次进入,弹窗提示
let isFirstTipShow = getStorageSync("first_instrument_" + info.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]);
});
} else {
this.setState({ ModeList: res.data.data });
}
}
};
/**
* 倒计时弹窗
* 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;
this.footerIsDisabled();
if (!isNotCheck) {
let isReturn = this.modeRuningChange();
if (isReturn) return;
}
let { isStandStatus, isShowNurse } = this.state;
// let isCabinMode = data.isCabinMode === 1;
// if (isStandStatus === isCabinMode) {
// this.setState({ isCanClick: true }); // 是否舱体一致时,可以点击
// } else {
// this.setState({ isCanClick: false });
// }
let currentServiceData = {
startSource: "",
stopSource: "",
};
if (data.serviceData.length) {
currentServiceData = data.serviceData[0];
}
let currentTime = data.modeTimeStr;
this.setState({
ActiveModeItem: data,
activeModeID: data.id,
ModeID: "mode_" + data.id,
currentServiceData,
ModeStepIndex: 0,
currentTime,
});
setTimeout(() => {
// 设置时间组合
if (data.serviceData.length > 0) {
this.setServiceTimeData();
}
// 存在组合模式时,设置组合模式
if (data.combineData.length > 0) {
this.setCustomMaskData();
}
});
// 如果是正在运行中切换,则直接准备运行
if (isShowNurse) {
this.onStartNurse();
setTimeout(() => {
this.onNursingTap();
}, 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, ActiveModeItem, isStandStatus } = this.state;
let modeArray = ["all", "visor", "cabin", "yimeish"];
// 切换护理模式时,需判断舱体和面罩是否切换
// if (SwitchActiveModeItem.isCabinMode !== ActiveModeItem.isCabinMode) {
// if (SwitchActiveModeItem.isCabinMode === 1) {
// // 判断舱体是否连接成功
// if (!isStandStatus) {
// console.log(
// "检测到面罩与舱体未连接成功,请确认面罩是否和舱体连接并接通舱体电源"
// );
// this.showTips(
// "检测到面罩与舱体未连接成功,请确认面罩是否和舱体连接并接通舱体电源"
// );
// // this.openErrorTipsText(
// // "检测到面罩与舱体未连接成功,请确认面罩是否和舱体连接并接通舱体电源"
// // );
// // return;
// }
// } else {
// // 判断舱体是否断开连接
// if (isStandStatus) {
// console.log("检测到面罩与舱体仍在连接中,该模式需要分离面罩和舱体");
// this.showTips("检测到面罩与舱体仍在连接中,该模式需要分离面罩和舱体");
// // this.openErrorTipsText(
// // "检测到面罩与舱体仍在连接中,该模式需要分离面罩和舱体"
// // );
// // return;
// }
// }
// }
this.setState({
ModeType: modeArray[SwitchActiveModeItem.modeClass],
});
setTimeout(() => {
this.modeCurrentFun(SwitchActiveModeItem);
this.cancelModeSwitchBtn();
}, 100);
};
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();
return;
}
// 如果检查失败,则报错
this.onEmitErrorTips();
};
/**
* @name 不可切换光照提示
* @description isCabinMode是否舱体模式。 0.检测面罩与舱体是否仍在连接中,需要分离 1.检测是否连接失败,需要重新连接
*/
onEmitErrorTips = async () => {
let { isStandStatus, ActiveModeItem } = this.state;
if (isStandStatus) {
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,
});
};
closeStepTips = (data) => {
if (data.isLocal) {
setStorageSync("isFirstEntry_" + 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,
});
}
break;
default:
console.log("监听到到设备连接状态改变 this.footerIsDisabled()");
this.footerIsDisabled(); // 判断底部运行按钮是否可点击
break;
}
break;
//小程序主动问主机,现在链接了哪些附属设备,这时候主机给小程序的回复消息
case "QueryMatchStatus":
console.log("QueryMatchStatus 设备回复小程序", jsonStatus);
const isStandDevice = jsonStatus?.subDeviceList?.includes("Stand");
deviceToolKitInstance = deviceToolKitInstanceWL200;
console.log("支架是否链接", isStandDevice);
this.setState({
isStandStatus: isStandDevice,
});
// 连上面罩后, 获取仪器记录, 与缓存信息对比
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);
break;
case "DeviceControl":
console.log("打印小程序控制设备,给设备发送的指令", jsonStatus);
// setTimeout(() => {
// console.log("currentTime", this.state.currentTime);
// });
break;
//设备主动上报给小程序的指令 一般是工作状态改变
case "DeviceStatusSync":
console.log(
"设备主动上报给小程序的指令 一般是工作状态改变",
jsonStatus
);
this.workStatus = jsonStatus.workStatus;
this.setState({
Electricity: jsonStatus.battery,
// fr200Electricity: jsonStatus.battery,
matrixElectricity: jsonStatus.matrixBattery,
});
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 "customModeSet":
console.log(">>>>>>>>>>>>>>>设置自定义模式>>>>>>>>>>>>>>>");
console.log(
"InfoQuery customModeSet responseStatus=====>",
jsonStatus
);
if (jsonStatus.responseStatus == "OK") {
console.log("设置成功自定义模式");
this.setState({
isCombineSuccess: true,
});
}
break;
// 自定义模式信息
case "customModeInfo":
console.log(">>>>>>>>>>>>>>>查询自定义模式信息>>>>>>>>>>>>>>>");
console.log(
"InfoQuery customModeInfo responseStatus=====>",
jsonStatus
);
break;
case "versionInfo":
break;
// 当前报告
case "currentMaskReportInfo":
// 每次切换模式并开始运行后生成一个新的自增ID
// commandType: "InfoQuery"
// createDate: ""
// gear: 0
// id: 73
// infoQueryType: "currentMaskReportInfo"
// neededTotalSeconds: 900
// totalSeconds: 0
// workMode: "BrightenStand"
console.log("当前面罩报告 currentMaskReportInfo", jsonStatus);
if (!this.hadCheckReport) {
this.hadCheckReport = true;
this.checkInstrumentRecord(jsonStatus);
} else {
this.setWL200NursingHistory(jsonStatus);
}
break;
default:
break;
}
break;
// default:
// break;
}
});
/**
* 延迟500毫秒获取附属设备状态
*/
const querySubDeviceArrayBuffer = deviceToolKitInstance.toBleCommand({
...bleCommandSamples.querySubDevice,
queryType: "WL200",
} as any);
setTimeout(() => {
console.log("发送查询指令");
sendCommand({
value: querySubDeviceArrayBuffer,
});
}, 500);
/**
* 延迟500毫秒获取设备电量
*/
const queryDeviceArrayBuffer = deviceToolKitInstance.toBleCommand(
bleCommandSamples.queryDeviceStatus as any
);
setTimeout(() => {
console.log("发送查询设备指令");
sendCommand({
value: queryDeviceArrayBuffer,
});
}, 500);
});
};
/** 同步设备运行信息:运行时间 */
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 = 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);
}
},
};
// 仪器开始倒计时
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;
const statusF = {
sleep: () => {
this.setState({
isShowCountdown: false,
});
},
standby: () => {
this.setState({
isShowCountdown: false,
});
if (nowModeItem?.isCabinMode && step == 2) {
opts.currentTime = nowModeItem.modeTimeStr;
} 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 = nowModeItem.modeTimeStr;
}
// 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 = minSecToS(ActiveModeItem.modeTimeStr);
// 现在的倒计时剩余时间:同步时检查是否断开重连,如果是,则使用断开的剩余时长,进行倒计时计算
let currentSeconds = ActiveModeItem?.breakTimeStr
? minSecToS(ActiveModeItem.breakTimeStr)
: minSecToS(currentTime);
let checkTime = totalSeconds - currentSeconds;
this.elapsedTime = checkTime;
// 完成重连同步则删除重连时间字段
if (ActiveModeItem?.breakTimeStr) {
delete ActiveModeItem?.breakTimeStr;
this.setState({ ActiveModeItem });
}
// 判断剩余时间是否大于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.updateWL200NursingHistory(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
);
});
};
/**
* 点击开始护理
*/
onNursingTap() {
// 如果已禁止运行,则停止执行后续逻辑
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 === 1 && ActiveModeItem.isCabinMode === 0) {
console.log("已连接舱体,只可选择舱体模式");
return;
}
if (isStandStatus === 0 && 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;
}
let downNum = CountDownTime[ActiveModeItem.modeType] || 3;
console.log("downNum", downNum);
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) => {
let { currentDevice, ActiveModeItem, ModeList } = this.state;
if (jsonStatus) {
}
// 1.判断是否存在工作状态:如果不存在,则等待两秒用于连接设备与赋值,再执行后面的代码
if (!this.workStatus) {
await sleep(2);
}
// 2.判断是否已存在缓存的护理记录:如果没有历史,则缓存
let workStatus = this.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.id;
});
if (!WL200NursingHistory || !recordModeItem) {
console.log("仪器有数据, 但是缓存没有数据, 忽略");
return;
}
let sceneTime = minSecToS(ActiveModeItem.modeTimeStr);
// 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 neededTotalSeconds = jsonStatus.neededTotalSeconds; // 从仪器上获取的使用时间
console.log(
"从仪器上获取的使用时间 totalSeconds: %d neededTotalSeconds: %d",
totalSeconds,
neededTotalSeconds
);
let nursingTimeStr = currentDevice?.nursingTimeStr;
let nursingTime = nursingTimeStr ? minSecToS(nursingTimeStr) : 60; // 设备生成护理记录至少需要运行时间
if (totalSeconds < nursingTime) {
console.log("护理时间不足,弹出提示");
// todo
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,
};
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",
};
let res: any = await this.PostNursingLogClock(params);
console.log("res", res);
this.rmWL200NursingHistory(WL200NursingHistory);
}
} else {
// 5.判断设备状态-运行中 正常逻辑,这里不做处理,如果用户操作,则按正常流程判断
console.log("同步异常,但设备运行中");
console.log("同步异常,但设备运行中");
console.log("同步异常,但设备运行中");
}
};
/** 获取小程序本地缓存的历史记录 */
getWL200NursingHistory() {
this.WL200NursingHistory = Taro.getStorageSync("WL200NursingHistory");
}
/** 设置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,
};
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");
}
};
/** 删除WL200护理历史 */
rmWL200NursingHistory = (WL200NursingHistory, hard = false) => {
const nowWL200NursingHistory = Taro.getStorageSync("WL200NursingHistory");
if (nowWL200NursingHistory.id == WL200NursingHistory.id) {
Taro.removeStorageSync("WL200NursingHistory");
} else if (hard) {
Taro.removeStorageSync("WL200NursingHistory");
}
};
/** 提交护理记录 */
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) {
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.switchTab({
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,
});
};
connectionClose = () => {
this.setState({
isConnectShow: false,
});
};
// 手动护理模式切换:提示是否保存护理
closeTipsSave = () => {
this.setState({
isShowTipsSave: false,
});
this.modeCurrentFun(this.tempModeCurrent, true); // 不进行校验
};
confirmTipsSave = async () => {
this.setState({
isShowTipsSave: false,
});
// isShowTipsSave
this.PostNursingLogClock(null, false);
this.modeCurrentFun(this.tempModeCurrent, true); // 不进行校验
};
/** 初次护理信息弹窗 */
firstNurseInfo = async () => {
let { currentDevice } = this.state;
let res = await InstrumentInfo.firstNurseInfo({
instrumentId: currentDevice.id,
});
if (res.data.code === 200) {
let isFirstTipShow = getStorageSync(
"first_instrument_" + currentDevice.id
);
if (!isFirstTipShow) {
// 首次进入页面:自动打开打卡介绍弹窗
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 = !(isStandStatus === isCanClick);
this.setState({
isFooterBtnDisabled: isFooterBtnDisabled,
});
return isFooterBtnDisabled; // 数据更新有延迟,返回用于判断
};
render() {
let {
name,
title,
isConnectShow,
isShowStepTips,
isCanClick,
isShowNurse,
isStopNurse,
ModeList,
ModeType,
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,
} = this.state;
return (
<Block>
<Navbar titleSlot={title} isBack />
<View catchMove>
<PopupInstrumentUploadTips
isShow={isFirstTipShow}
title="打卡介绍"
data={nurseInfo}
close={this.onTipShowClose}
confirm={this.onTipShowClose}
/>
<PopupCountdown isShow={isShowCountdown} countdown={countdown} />
<PopupConfirm
isLarge
isClose
isShow={isEndCarePlan}
title="提示"
content="是否结束护理"
textAlgin="center"
cancelButtonText="取消"
confirmButtonText="确定"
close={this.cancelEndBtn}
confirm={this.confirmEndBtn}
/>
<PopupConfirm
isLarge
isClose
isShow={isSwitchActiveMode}
title="护理模式切换"
content={
<ModeListView
ModeID={ModeID}
activeModeID={activeModeID}
isPop
isShowNurse={isShowNurse}
ModeList={ModeList}
ModeType={ModeType}
ActiveModeItem={SwitchActiveModeItem}
onEmit={this.switchModeCurrentFun}
onEmitShowAll={this.openModeSwitch}
/>
}
textAlgin="center"
cancelButtonText="取消"
confirmButtonText="确定"
close={this.cancelModeSwitchBtn}
confirm={this.confirmModeSwitchBtn}
/>
{ActiveModeItem.openSourceData && (
<PopupStepTips
isShow={isShowStepTips}
isLarge
isFirstEntry
confirmButtonText="知道了"
data={ActiveModeItem.openSourceData}
close={this.closeStepTips}
/>
)}
<PopupAlert
isShow={isNotEnoughTime}
isClose
title="提示"
content="您的本次护理时间不足,请重新护理"
confirmButtonText="确认"
textAlgin="center"
close={this.closeNotEnoughTime}
confirm={this.closeNotEnoughTime}
/>
<PopupAlert
isShow={isShowErrorTipsText}
isClose
zIndex={10020}
myClassName="level-up"
title="提示"
content={errorTipsText}
confirmButtonText="知道了"
textAlgin="center"
close={this.closeErrorTipsText}
confirm={this.closeErrorTipsText}
/>
<PopupConfirm
isShow={isShowTipsSave}
isClose
zIndex={10020}
myClassName="level-up"
title="提示"
content={
<Block>
<View></View>
<View></View>
</Block>
}
cancelButtonText="取消"
confirmButtonText="确认"
textAlgin="center"
close={this.closeTipsSave}
confirm={this.confirmTipsSave}
/>
<PopupConfirm
isShow={isShowReReadRecordSave}
isClose
zIndex={10020}
myClassName="level-up"
title="提示"
content={
<Block>
<View></View>
<View></View>
</Block>
}
cancelButtonText="取消"
confirmButtonText="确认"
textAlgin="center"
close={this.closeTipsSave}
confirm={this.confirmTipsSave}
/>
<PopupStatus
isShow={isShowNursingSuccess}
isClose
title="您已结束本次护理"
type="success"
content="正在上传护理记录……"
confirmButtonText="知道了"
textAlgin="center"
close={() => {
/*不需要做处理*/
}}
/>
{isConnectShow && (
<ConnectionBluetoot
deviceInfo={currentDevice}
close={this.connectionClose}
isDisconnect={!isConnectionBlutoot}
offlineChange={() => {}}
pairingChange={this.pairingChange}
upgradeFun={() => {}}
/>
)}
</View>
<View>
<View className="iot-main">
<View className="banner-box">
<View>
{!isShowNurse && (
<Video
className="video-or-image"
src={ActiveModeItem.modeVideo}
/>
)}
{isShowNurse && (
<Block>
{isStopNurse ? (
<Image
className="video-or-image"
src={currentServiceData.stopSource}
/>
) : (
<Image
className="video-or-image"
src={currentServiceData.startSource}
/>
)}
</Block>
)}
{errorTips && (
<Block>
<View className="msg-tips">
<Image
className="msg-tips-img"
src={require("../../img/tips.png")}
/>
<View className="msg-tips-content">{errorTips}</View>
</View>
</Block>
)}
</View>
<View className="iot-device">
<View className="item">
<Text className="device-time">
<Text className="time">{currentTime}</Text>
</Text>
</View>
<View className="line" />
<ElectricityView
Electricity={Electricity}
matrixElectricity={matrixElectricity}
facialMaskConnectStatus={facialMaskConnectStatus}
/>
</View>
</View>
{ModeList.length > 0 && (
<ModeListView
isPop={false}
isShowNurse={isShowNurse}
ModeList={ModeList}
ModeType={ModeType}
ModeID={ModeID}
activeModeID={activeModeID}
ActiveModeItem={ActiveModeItem}
onEmit={this.modeCurrentFun}
onEmitShowAll={this.openModeSwitch}
/>
)}
<ModeContent
isShowNurse={isShowNurse}
ActiveModeItem={ActiveModeItem}
/>
{/* <Echarts></Echarts> */}
</View>
<Footer
isDisabled={isFooterBtnDisabled}
isShowNurse={isShowNurse}
isStopNurse={isStopNurse}
onEmitStartNurse={this.onStartNurse}
onEmitSwitchChange={this.onSwitchChange}
onEmitEndPlan={this.onEndPlan}
onEmitErrorTips={this.onEmitErrorTips}
/>
</View>
</Block>
);
}
}
const mapStateToProps = (state) => ({
bluetoothInfo: state.deviceInfo.bluetoothInfo,
});
const mapDispatchToProps = (dispatch) => ({
// userRefresh(data) {
// dispatch(userRefresh(data));
// },
});
export default connect(mapStateToProps, mapDispatchToProps)(IotCarePlan);
// isCharging