Files
2026-06-02 15:18:26 +08:00

1039 lines
35 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="bg">
<view class="status_bar">
<view class="top_view"></view>
</view>
<view class="title" @click="debug">
智能内镜储存柜
<p class="sub-title">
INTELLIGENT ENDOSCOPE STORAGE CABINET
</p>
</view>
<view class="btn">
<view class="ant-btn ant-btn-lg" @click="toIndex">
<uni-icons type="gear-filled" size="30"></uni-icons>
进入
</view>
</view>
<uni-popup ref="popup" type="bottom" :mask-click="false">
<view class="debug-btn-group">
<view class="ant-btn ant-btn-lg" @click="toModbus">
modbus调试
</view>
<view class="ant-btn ant-btn-lg" @click="toSqlite">
sqlite调试
</view>
<view class="ant-btn ant-btn-lg" @click="cleanStorage">
清除缓存
</view>
<uni-icons @click="closePop" class="close-debug" type="close" size="40" color="#fff"></uni-icons>
</view>
</uni-popup>
<input-num-pop ref="inputPop" @submit="inputModalSubmit" />
</view>
</template>
<script>
// #ifdef APP
import * as db from '@/db/sqlite.js'
// #endif
import storage from '@/utils/storage.js'
import InputNumPop from '@/components/InputNumPop.vue';
import cmd from '@/utils/cmd.js'
import { formatDateTime, delay, getTimeDifference } from "@/utils/common.js"
import * as Api from '@/api/index.js'
import beeper from '@/utils/beeper.js';
import { compareTimes } from '../utils/common';
import store from '../store';
export default {
components: { InputNumPop },
data() {
return {
clickTimes: 0,
RS485: undefined,
RS232: undefined,
timer: null, // 定时器读取485接口数据
taskTimer: null,
last485DataTime: null, // 上次收到485数据的时间戳
heartbeatTimer: null, // 心跳检测定时器
reconnectCount: 0, // 重连次数计数器
maxReconnect: 5, // 最大重连次数
}
},
computed: {
cleanMode() {
// 清洗状态
return this.$store.state.clean
},
autoDisinfect() {
// 自动消毒状态
return this.$store.state.autoDisinfect
},
disinfectMode() {
// 消毒状态
return this.$store.state.relay.disinfect
},
windMode() {
// 风机状态
return this.$store.state.relay.wind
},
vacuumMode() {
// 真空泵状态
return this.$store.state.relay.vacuum
},
doorStatus() {
// 门状态
return this.$store.state.relay.door
},
doorAlert() {
// 门报警
return this.$store.state.timer.doorAlert
},
humi() {
// 当前湿度
return this.$store.state.sensor.humi
},
temp() {
// 当前温度
return this.$store.state.sensor.temp
},
},
onLoad() {
this.RS485 = getApp().globalData.RS485
this.RS232 = getApp().globalData.RS232
this.init()
uni.$on('addLog', (data) => {
this.addLog(data.name, data.action)
})
// 监听内镜存入事件
uni.$on('storeEndoscope', (data) => {
this.addLog(data.ic, '内镜存入')
})
// 监听内镜取出事件
uni.$on('takeEndoscope', (data) => {
this.addLog(data.ic, '内镜取出')
})
uni.$on('closeDoor', async (data) => {
try {
await cmd.LeftDoor(false)
await delay(200)
await cmd.RightDoor(false)
this.addLog('门', '触摸屏关门')
// 触发关门事件
this.closeDoorEvent()
} catch (error) {
this.addLog('手动关门错误', error)
}
})
},
onShow() {
// 监听日志记录事件
},
onBackPress() {
// 禁用返回按键
return true;
},
onHide() {
// 移除事件监听
// uni.$off('addLog')
// uni.$off('storeEndoscope')
// uni.$off('takeEndoscope')
},
onUnload() {
// 记录日志
this.addLog('485通信', '页面销毁,已停止所有定时器')
// 清理心跳定时器
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer)
this.heartbeatTimer = null
}
// 清理485轮询定时器
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
// 清理任务定时器
if (this.taskTimer) {
clearInterval(this.taskTimer)
this.taskTimer = null
}
},
methods: {
init() {
// 初始化串口
this.initSerialport()
// 初始化本地存储
this.initStorage()
// 初始化网络时间
this.initTime()
// 监听运行状态
this.initWatch()
// 初始化本地数据库
this.initDB()
},
initSerialport() {
try {
this.startRS485()
this.startRS232()
} catch (e) {
uni.showToast({
title: '初始化串口失败',
icon: 'error'
})
}
},
initTime() {
// 初始化本地时间
this.$store.state.time = formatDateTime()
if (this.$store.state.apiUrl != '') {
// 同步网络时间
Api.time().then(res => {
// console.log('time', res)
if (res && Date.parse(res) != NaN) {
this.$store.state.time = res
this.$store.state.connect = true
}
})
}
},
// 初始化监听器
initWatch() {
// 监听消毒状态
this.$watch('disinfectMode', (newVal, oldVal) => {
if (newVal == true) {
// 消毒开启事件,记录时间
this.$store.state.timer.disinfect = formatDateTime()
}
if (newVal == false) {
// 消毒停止事件
let timer = this.$store.state.timer.disinfect
if (timer != '' && timer != null) {
// 获取时间间隔
let diff = getTimeDifference(timer, formatDateTime())
let local = storage.get('disinfectRun') ? storage.get('disinfectRun') : 0
storage.set('disinfectRun', diff.minutes + local)
}
}
})
// 风机状态
this.$watch('windMode', (newVal, oldVal) => {
if (newVal == true && oldVal == false) {
// 分机开启事件,记录时间
this.$store.state.timer.wind = formatDateTime()
}
if (newVal == false) {
// 停止事件
let timer = this.$store.state.timer.wind
if (timer != '' && timer != null) {
// 获取时间间隔
let diff = getTimeDifference(timer, formatDateTime())
let local = storage.get('windRun') ? storage.get('windRun') : 0
// 存储风机总运行时间
storage.set('windRun', diff.minutes + local)
}
}
})
// 监听温度高,启动风机
this.$watch('humi', (newVal, oldVal) => {
// 湿度高启动风机,关闭状态,自动模式
if (newVal > this.$store.state.run.humi && this.windMode == false) {
// 启动风机
cmd.Wind(true)
}
})
this.$watch('temp', (newVal, oldVal) => {
// 湿度高启动风机,关闭状态,自动模式
if (newVal > this.$store.state.run.temp && this.windMode == false) {
// 启动风机
cmd.Wind(true)
}
})
// 监听开门
this.$watch('doorStatus', (newVal, oldVal) => {
// 监听门状态
if (newVal == true) {
// 触发门打开事件,记录开门时间
this.openDoorEvent()
this.$store.state.timer.door = formatDateTime()
}
if (newVal == false) {
// 触发门关闭事件
this.closeDoorEvent()
// 记录关门日志(手动关门)
this.addLog('门', '手动关门')
this.$store.state.timer.door = ''
this.$store.state.timer.doorAlert = false
}
})
// 监听开门报警事件
this.$watch('doorAlert', (newVal, oldVal) => {
// 监听门报警
if (newVal == true) {
// 触发门报警事件
beeper.play()
}
if (newVal == false) {
// 停止报警
beeper.stop()
}
})
this.$watch('vacuumMode', (newVal, oldVal) => {
// 监听真空泵状态
if (newVal == true) {
this.$store.state.timer.vacuumStart = formatDateTime()
}
if (newVal == false) {
this.$store.state.timer.vacuumEnd = formatDateTime()
}
})
},
initStorage() {
// 初始化本地配置存储
let runStorage = storage.get('run')
if (runStorage) {
this.$store.commit('SET_RUN', { ...runStorage })
}
let baseStorage = storage.get('base')
if (baseStorage) {
this.$store.commit('SET_BASE', { ...baseStorage })
}
let config = storage.get('config')
if (config) {
this.$store.state.apiUrl = 'http://' + config.ip + ':' + config.port
}
},
async initDB() {
await db.isTable('user').then(res => {
if (!res) {
db.addUserTable()
}
})
await db.isTable('log').then(res => {
if (!res) {
db.addLogTable()
}
})
await db.isTable('endo').then(res => {
if (!res) {
db.addEndoTable()
}
})
let scope = await db.isTable('scope')
if (!scope) {
await db.addScopeTable()
for (let i = 0; i < 16; i++) {
await db.addTabItem('scope', {
name: '', ic: '', key: i,
})
}
}
},
startRS485() {
// 获取本地串口存储端口
let rs485Conf = storage.get('rs485')
if (rs485Conf) {
// 设置串口和波特率
} else {
rs485Conf = {
path: '/dev/ttyUSB2',
baudrate: 9600
}
}
this.RS485.setPath(rs485Conf.path)
this.RS485.setBaudrate(rs485Conf.baudrate)
// 打开串口
const state = this.RS485.open();
if (state) {
uni.showToast({
title: '485已打开',
icon: 'none'
})
this.RS485.startAutoReadData((res) =>{
try {
// console.log('485 data', res)
// 转换成十六进制字符串
let hex = this.RS485.byte2HexString(res)
this.handle485HexData(hex)
} catch (e) {
// console.error('[RS485回调异常]', e)
this.addLog('485回调异常', e.message || e)
}
})
// 读取数据
clearInterval(this.timer)
this.readData()
// 启动心跳检测
this.startHeartbeat()
// 串口打开成功后,重置重连计数器和时间戳
this.reconnectCount = 0
this.last485DataTime = Date.now()
// 记录通信恢复日志
// this.addLog('485通信', '通信已恢复(重连成功)')
} else {
// 确保心跳是关闭的
this.stopHeartbeatIfNeeded()
uni.showToast({
title: '485打开失败',
icon: 'error'
})
}
},
async startRS232() {
// 获取本地串口存储端口
let rs232Conf = storage.get('rs232')
if (rs232Conf) {
// 设置串口和波特率
} else {
rs232Conf = {
path: '/dev/ttyUSB1',
baudrate: 115200
}
}
this.RS232.setPath(rs232Conf.path)
this.RS232.setBaudrate(rs232Conf.baudrate)
// 打开串口
const state = this.RS232.open();
if (state) {
uni.showToast({
title: '232已打开',
icon: 'none'
})
this.RS232.startAutoReadData((res) =>{
try {
// 转换成十六进制字符串
let hex = this.RS232.byte2HexString(res)
this.handle232HexData(hex)
} catch (e) {
// console.error('[RS232回调异常]', e)
this.addLog('232回调异常', e.message || e)
}
})
this.startAutoTask()
}
},
stopRS485() {
// 停止心跳检测
this.stopHeartbeatIfNeeded()
this.addLog('485通信', '串口关闭')
this.RS485.stopReadPortData()
this.RS485.close()
},
stopRS232() {
this.RS232.stopReadPortData()
this.RS232.close()
},
// 启动心跳检测定时器
startHeartbeat() {
// 清除已有的心跳定时器
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer)
this.heartbeatTimer = null
}
// 记录日志
this.addLog('485通信', '心跳检测已启动')
// 每10秒检查一次485数据是否正常上报
this.heartbeatTimer = setInterval(() => {
this.check485Heartbeat()
}, 10000)
},
// 停止心跳检测(安全方法,如果没运行也不会报错)
stopHeartbeatIfNeeded() {
if (!this.heartbeatTimer) {
// 心跳未运行
return
}
clearInterval(this.heartbeatTimer)
this.heartbeatTimer = null
this.addLog('485通信', '心跳检测已停止')
},
// 检测485数据心跳,如果超时则触发重连
check485Heartbeat() {
// 如果还没有收到过数据,跳过检查(等待初始化完成)
if (!this.last485DataTime) {
return
}
const now = Date.now()
const timeout = 10000 // 10秒超时阈值
// 判断距离上次数据是否超过30秒
if (now - this.last485DataTime > timeout) {
// 检查重连次数是否超限
if (this.reconnectCount >= this.maxReconnect) {
this.addLog('485通信', '重连' + this.maxReconnect + '次失败,请检查硬件')
uni.showToast({
title: '485通信中断,请检查硬件连接',
icon: 'none',
duration: 3000
})
return
}
// 记录日志
this.addLog('485通信', '数据中断(第' + (this.reconnectCount + 1) + '次重连)')
uni.showToast({
title: '485通信中断,正在恢复...',
icon: 'none',
duration: 2000
})
// 统一重置双串口
this.resetSerialPorts()
}
},
/**
* 统一双串口重连入口
* 执行顺序: 停定时器 → 停双串口 → 清空485队列 → 等待释放 → 重启485 → 延迟→ 重启232
* 失败处理: 指数退避重试 / 耗尽则 plus.runtime.restart()
*/
async resetSerialPorts() {
try {
this.reconnectCount++
// ===== Step 1: 停止所有定时器(必须最先执行!)=====
// T1: 心跳检测定时器
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null
}
// T2: 485轮询定时器
if (this.timer) {
clearInterval(this.timer);
this.timer = null
}
// T3: 业务任务定时器(关键!原resetRS485遗漏此项)
if (this.taskTimer) {
clearInterval(this.taskTimer);
this.taskTimer = null
}
// ===== Step 2: 停止两个串口 =====
if (this.RS485) {
this.RS485.stopReadPortData();
this.RS485.close()
}
if (this.RS232) {
this.RS232.stopReadPortData();
this.RS232.close()
}
// ===== Step 3: 清空RS485消息队列(RS232无队列,无需清理)=====
cmd.clearRS485Queue()
// ===== Step 4: 等待端口释放(指数退避,最少2500ms)=====
const backoff = Math.min(1000 * Math.pow(2, this.reconnectCount - 1), 30000)
const waitTime = Math.max(backoff, 2500)
console.log(`[重连] 第${this.reconnectCount}次, 等待${waitTime}ms...`)
await delay(waitTime)
// ===== Step 5: 重置时间戳 =====
this.last485DataTime = null
// ===== Step 6: 依次重启两个串口 =====
// 先启动RS485(会自动重建T1心跳 + T2轮询)
this.startRS485()
// 错开启动时间,避免同时打开端口竞争
await delay(500)
// 再启动RS232(会自动重建T3 taskTimer
this.startRS232()
this.addLog('串口通信', `双串口重连完成(第${this.reconnectCount}次)`)
} catch (error) {
this.addLog('串口通信错误', error.message || '重置失败')
// 失败后延迟重试
await delay(5000)
if (this.reconnectCount < this.maxReconnect) {
this.resetSerialPorts()
} else {
// 重连次数耗尽,自动重启应用
this.addLog('串口通信', `重连${this.maxReconnect}次均失败,即将自动重启应用`)
uni.showToast({
title: '通信异常,3秒后重启',
icon: 'none',
duration: 3000
})
setTimeout(() => {
// #ifdef APP-PLUS
plus.runtime.restart()
// #endif
}, 3000)
}
}
},
readData() {
this.timer = setInterval(async () => {
await cmd.getTemp()
await delay(1000)
await cmd.getPressure()
}, 5000)
},
handle485HexData(hex) {
// 更新最后收到数据的时间戳
this.last485DataTime = Date.now()
// 处理485接口上报的数据
// 温湿度temp, humi, 压差pressure, 门状态door
let data = cmd.parse485Data(hex)
// 将获取的数据赋值到状态
if (data.hasOwnProperty('temp')) {
this.$store.state.sensor.temp = data.temp
}
if (data.hasOwnProperty('humi')) {
this.$store.state.sensor.humi = data.humi
}
if (data.hasOwnProperty('pressure')) {
let pressure = parseFloat(data.pressure) + parseInt(this.$store.state.run.pressureCom)
this.$store.state.sensor.pressure = pressure
}
// 处理门状态上报(功能码04,中盛IO控制器DI状态变化上报)
// 注意: 门状态的修改统一由cmd.js的LeftDoor/RightDoor方法管理
// 这里只处理收到上报后的自动逻辑,不修改门状态
if (data.action == 'LeftDoor' && data.status == 'closed') {
// 左门触点触发(关门)
// 调用cmd.LeftDoor(false)来更新门状态
cmd.LeftDoor(false)
uni.showToast({
title: '左门已关闭',
icon: 'none'
})
this.addLog('左门触点触发', '左门已关闭')
}
if (data.action == 'RightDoor' && data.status == 'closed') {
// 右门触点触发(关门)
// 调用cmd.RightDoor(false)来更新门状态
cmd.RightDoor(false)
uni.showToast({
title: '右门已关闭',
icon: 'none'
})
this.addLog('右门触点触发', '右门已关闭')
}
if (data.action == 'door' && data.status == 'closed') {
try {
cmd.LeftDoor(false)
cmd.RightDoor(false)
// 触发关门事件,不需要重复触发,监听器触发
// this.closeDoorEvent()
uni.showToast({
title: '两门已关闭',
icon: 'none'
})
} catch (error) {
this.addLog('门关闭错误', error.message || error)
}
}
},
handle232HexData(hex) {
// 处理232接口上报的卡片数据
// 数据格式说明:
// - 卡存入: 20 01 00 08 04 00 00 00 [卡号4字节] [校验] 03 (14字节)
// - 卡离开: 20 01 00 01 02 [校验] 03 (7字节)
// - 卡号位置: 倒数4-8字节(字节位置6-9)
// - 所有卡片通过同一通道读取,通过数据库比对判断卡片类型
let data = cmd.parse232dData(hex)
if (data == {}) return
if (data.hasOwnProperty('number')) {
// 收到卡号数据,发送卡号事件
uni.$emit('ic', data.number)
// 判断当前门状态
if (store.state.relay.door == false) {
// 门关闭状态: 验证是否为人员卡
// 人员卡验证通过后弹窗选择开左门/开右门
this.checkPersonCard(data.number).then(res => {
if (res) {
// 验证通过,是人员卡
// 发送弹窗选择事件,让index页面弹窗选择开左门/开右门
uni.$emit('showDoorSelect', data.number)
} else {
// 验证失败,不是人员卡
// 继续验证是否为内镜卡
this.checkEndoCard(data.number).then(res => {
if (res) {
// 是内镜卡,门关闭状态下不允许操作
uni.showToast({
title: '请先开门',
icon: 'none'
})
} else {
// 既不是人员卡也不是内镜卡
uni.showToast({
title: '无效卡片',
icon: 'none'
})
}
})
}
})
} else {
// 门打开状态: 验证是否为人员卡或内镜卡
// 人员卡验证通过后弹窗选择开左门/开右门
// 内镜卡验证通过后弹窗选择存入/取出
this.checkPersonCard(data.number).then(res => {
if (res) {
// 验证通过,是人员卡
// 发送弹窗选择事件,让index页面弹窗选择开左门/开右门
uni.$emit('showDoorSelect', data.number)
} else {
// 验证失败,不是人员卡
// 继续验证是否为内镜卡
this.checkEndoCard(data.number).then(res => {
if (res) {
// 是内镜卡,门打开状态只能存入
uni.$emit('showActionSelect', data.number)
} else {
// 既不是人员卡也不是内镜卡
uni.showToast({
title: '无效卡片',
icon: 'none'
})
}
})
}
})
}
}
},
// 密码框提交
inputModalSubmit(val) {
let password = this.$store.state.base.screenPw
this.$refs.inputPop.close()
if (val == password) {
uni.showToast({
title: '验证通过',
icon: 'none'
})
setTimeout(() => {
uni.navigateTo({
url: '/pages/index',
animationType: 'fade-in',
})
}, 300)
} else {
uni.showToast({
title: '密码错误',
icon: 'none',
})
}
},
toIndex() {
let screenPw = this.$store.state.base.screenPw
if(screenPw) {
this.$refs.inputPop.show()
} else {
uni.navigateTo({
url: '/pages/index',
animationType: 'fade-in',
})
}
},
toModbus() {
try {
this.stopRS485()
this.stopRS232()
} catch (error) {
// console.log(error)
}
this.closePop()
uni.navigateTo({
url: '/pages/modbus/modbus'
})
},
toSqlite() {
this.closePop()
uni.navigateTo({
url: '/pages/database/database'
})
},
cleanStorage() {
storage.clear()
uni.showToast({
title: '已清空缓存,重启应用生效',
icon: 'none'
})
},
// 调试弹窗
debug() {
this.clickTimes++
if (this.clickTimes == 5) {
this.clickTimes = 0
this.$refs.popup.open()
}
setTimeout(() => {
this.clickTimes = 0
}, 3000)
},
closePop() {
this.$refs.popup.close()
},
// send485Data(cmd) {
// this.RS485.sendDataString(cmd);
// },
// async send232Data(cmd) {
// await this.RS232.sendDataString(cmd);
// },
// 开门事件
async openDoorEvent() {
// 关闭真空泵和消毒,打开照明,打开门锁,打开风机
cmd.Light(true)
await delay(500)
cmd.Vacuum(false)
await delay(500)
cmd.Wind(true)
},
// 关门事件
async closeDoorEvent() {
// 关闭照明,打开真空泵、消毒
await delay(500)
await cmd.Light(false) // 照明关闭指令
await delay(500)
await cmd.Vacuum(true) //真空泵开启指令
await delay(500)
await cmd.Wind(true)
},
// 验证人员卡是否可以开门
async checkPersonCard(ic) {
let res1 = await db.selectDataList('user', {'ic': ic})
if (res1.length > 0) {
return true
}
let res2 = await db.selectDataList('user', {'ic2': ic})
if (res2.length > 0) {
return true
}
return false
},
// 验证内镜卡是否可以
async checkEndoCard(ic) {
let res1 = await db.selectDataList('endo', {'ic': ic})
if (res1.length > 0) {
return true
}
let res2 = await db.selectDataList('endo', {'ic2': ic})
if (res2.length > 0) {
return true
}
return false
},
// /***
// * 更新内镜数据
// * @param {*} key 内镜位置编号 起始0
// * @param {*} action 操作类型 enter:进入 leave:离开
// * @param {*} sn 内镜编号
// * */
// async updateScope(key, action, ic) {
// let data = {
// name: action,
// ic: ic,
// time: formatDateTime(),
// }
// try {
// await db.updateSQL('scope', data, 'key', key)
// } catch (error) {
// console.log(error)
// }
// },
// 添加日志数据
async addLog(name, action) {
try {
// 本地存储
await db.addTabItem('log', {
name: name,
action: action,
})
// 网络同步
// Api.logsync()
} catch (error) {
// console.log(error)
}
},
/**
* 任务
* */
startAutoTask() {
// clearInterval(this.taskTimer)
this.taskTimer = setInterval(() => {
// 检查开门时长
this.checkDoorOpenTimer()
// 真空泵运行任务
this.vacuumTask()
// 自动消毒任务
this.disinfectTask()
// 风机停止任务
this.windCloseTask()
}, 2000)
},
// 消毒任务
async disinfectTask() {
// 启动自动触发任务
let group = this.$store.state.run.group
let now = formatDateTime()
let nowTime = now.split(' ')[1]
let time = nowTime.substring(0, nowTime.length - 3)
let isStart = false
for (let i = 0; i < group.length; i++) {
if (group[i].status) {
let start = group[i].start.h + ':' + group[i].start.m
let end = group[i].end.h + ':' + group[i].end.m
// 开始时间
if (compareTimes(start, time) == 1 && compareTimes(time, end) == 1) {
isStart = true
break;
}
}
}
if (this.disinfectMode == false && isStart == true) {
// 启动消毒
cmd.Disinfect(true)
await delay(100)
cmd.Wind(true)
}
if (this.disinfectMode == true && isStart == false && this.autoDisinfect == true) {
// 停止消毒
cmd.Disinfect(false)
}
},
// 真空泵任务
async vacuumTask() {
let start = this.$store.state.timer.vacuumStart
if (start != '') {
// 开始启动到当前时间
let startM = getTimeDifference(start, formatDateTime())
// 真空泵运行时长
let runTime = this.$store.state.run.vacuumRunTime
// 分钟单位
if (startM.minutes >= runTime) {
// 关闭真空泵
this.$store.state.timer.vacuumStart = ''
// 超过阈值 关闭
cmd.Vacuum(false)
}
}
let end = this.$store.state.timer.vacuumEnd
if (end != '') {
let endH = getTimeDifference(end, formatDateTime())
// 间隔时长
let perHour = this.$store.state.run.vacuumPerHour
// 小时单位
if (endH.hour >= perHour) {
// 启动真空泵
this.$store.state.timer.vacuumEnd = ''
// 启动真空泵
cmd.Vacuum(true)
await delay(100)
cmd.Wind(true)
}
}
},
async windCloseTask() {
await delay(100)
let { light, vacuum, disinfect, door } = this.$store.state.relay
if (light || vacuum || disinfect || door ) {
return;
}
if (this.$store.state.sensor.temp > this.$store.state.run.temp) {
return;
}
if (this.$store.state.sensor.humi > this.$store.state.run.humi) {
return;
}
cmd.Wind(false)
},
checkDoorOpenTimer() {
let openTime = this.$store.state.timer.door
// 记录开门时间并且不是清洗模式
if (openTime != '' && this.cleanMode == false) {
let diff = getTimeDifference(formatDateTime(openTime), formatDateTime())
if (diff.minutes > 3) {
this.$store.state.timer.doorAlert = true
uni.$emit('notice', { title: '未关门', content: '请及时关闭'})
}
}
},
}
}
</script>
<style scoped>
.bg{
position: relative;
width: 100%;
height: 100%;
background-image: url("@/assets/bg.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
.title{
position: absolute;
top: 40%;
left: 0;
right: 0;
margin: auto;
height: 60px;
font-size: 56px;
color: #fff;
}
.sub-title{
font-size: 14px;
color: #777D90;
}
.btn{
position: absolute;
bottom: 125px;
left: 0;
right: 0;
margin: auto;
width: 200px;
}
.ant-btn.ant-btn-lg{
font-size: 28px;
height: 60px;
/* line-height: 50px; */
border-radius: 50px;
width: 180px;
}
.debug-btn-group{
margin-bottom: 40rpx;
position: relative;
}
.debug-btn-group .ant-btn{
margin: 0 10rpx;
font-size: 20px;
line-height: 40px;
width:auto;
}
.close-debug{
position: absolute;
right: 10px;
}
</style>