|
|
@ -1,8 +1,18 @@ |
|
|
|
<template> |
|
|
|
<div class="device-management"> |
|
|
|
<div class="setting-item"> |
|
|
|
<span class="label">日期</span> |
|
|
|
<span class="value">{{ formattedDate }}</span> |
|
|
|
<span class="label">日期与时间</span> |
|
|
|
<el-date-picker |
|
|
|
class="date-input" |
|
|
|
v-model="time" |
|
|
|
type="datetime" |
|
|
|
placeholder="修改日期与时间" |
|
|
|
format="YYYY-MM-DD HH:mm:ss" |
|
|
|
value-format="YYYY-MM-DD HH:mm:ss" |
|
|
|
@change="(val) => updateSetting('date', val)" |
|
|
|
@focus="pauseTimer" |
|
|
|
@blur="resumeTimer" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- <div class="setting-item"> |
|
|
@ -24,20 +34,55 @@ |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="setting-item"> |
|
|
|
<span class="label">孵育温度</span> |
|
|
|
<div class="options"> |
|
|
|
<button |
|
|
|
v-for="t in temperatures" |
|
|
|
:key="t" |
|
|
|
:class="{ active: settings.temperature === t }" |
|
|
|
@click="updateSetting('temperature', t)" |
|
|
|
> |
|
|
|
{{ t }} |
|
|
|
</button> |
|
|
|
<div class="setting-item-box"> |
|
|
|
<div class="setting-item setting-item-no-border"> |
|
|
|
<span class="label">整体温度控制</span> |
|
|
|
<div class="options"> |
|
|
|
<input |
|
|
|
style="width: 150px" |
|
|
|
v-model="settings.allTemperature" |
|
|
|
type="number" |
|
|
|
@focus="showKeyboard('number', 1)" |
|
|
|
readonly |
|
|
|
/> |
|
|
|
<button @click="updateSetting('allTemperature', settings.allTemperature)"> |
|
|
|
设置 |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="setting-item setting-item-no-border"> |
|
|
|
<span class="label">孵育盘温度</span> |
|
|
|
<div class="options"> |
|
|
|
<input |
|
|
|
style="width: 150px" |
|
|
|
v-model="settings.incubateBoxTemperature" |
|
|
|
type="number" |
|
|
|
@focus="showKeyboard('number',2)" |
|
|
|
readonly |
|
|
|
/> |
|
|
|
<button @click="updateSetting('incubateBoxTemperature', settings.incubateBoxTemperature)"> |
|
|
|
设置 |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="setting-item setting-item-no-border"> |
|
|
|
<span class="label">板夹区温度</span> |
|
|
|
<div class="options"> |
|
|
|
<input |
|
|
|
style="width: 150px" |
|
|
|
v-model="settings.plateBoxTemperature" |
|
|
|
type="number" |
|
|
|
@focus="showKeyboard('number',3)" |
|
|
|
readonly |
|
|
|
/> |
|
|
|
<button @click="updateSetting('plateBoxTemperature', settings.plateBoxTemperature)"> |
|
|
|
设置 |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="setting-item"> |
|
|
|
|
|
|
|
<div class="setting-item" style="border-radius: 0"> |
|
|
|
<span class="label">DHCP</span> |
|
|
|
<div class="options"> |
|
|
|
<button |
|
|
@ -65,7 +110,7 @@ |
|
|
|
style="min-width: 250px" |
|
|
|
v-model="settings.localIp" |
|
|
|
type="text" |
|
|
|
@focus="showKeyboard()" |
|
|
|
@focus="showKeyboard(undefined, 4)" |
|
|
|
readonly |
|
|
|
/> |
|
|
|
<button @click="updateSetting('localIP', settings.localIp)"> |
|
|
@ -126,6 +171,7 @@ |
|
|
|
<div class="keyboard" v-if="keyboardVisible"> |
|
|
|
<SimpleKeyboard |
|
|
|
:input="currentInputValue" |
|
|
|
:layout |
|
|
|
@onChange="handleKeyboardInput" |
|
|
|
@onKeyPress="handleKeyPress" |
|
|
|
/> |
|
|
@ -142,20 +188,32 @@ import { |
|
|
|
setAutoPrint, |
|
|
|
setAutoLogout, |
|
|
|
getTemperatureRange, |
|
|
|
setTemperature, |
|
|
|
setDHCP, |
|
|
|
setLocalIP, |
|
|
|
setAutoLogoutTime, |
|
|
|
} from '../../../services/Index/settings/settings' |
|
|
|
setAutoLogoutTime, setAllTemperature, setIncubateBoxTemperature, setPlateBoxTemperature, setDateAndTime |
|
|
|
} from '@/services' |
|
|
|
import { eMessage, isValidIPv4 } from '../utils' |
|
|
|
|
|
|
|
const layout = ref() |
|
|
|
|
|
|
|
const numericLayout = { |
|
|
|
default: [ |
|
|
|
'1 2 3', |
|
|
|
'4 5 6', |
|
|
|
'7 8 9', |
|
|
|
'{bksp} 0 {enter}' // 包含删除和确认键 |
|
|
|
], |
|
|
|
} |
|
|
|
|
|
|
|
// 系统设置状态 |
|
|
|
interface Settings { |
|
|
|
language: string |
|
|
|
autoPrint: boolean |
|
|
|
autoLogout: boolean |
|
|
|
autoLogoutTimeout: number |
|
|
|
temperature: number |
|
|
|
allTemperature: number | undefined |
|
|
|
incubateBoxTemperature:number |
|
|
|
plateBoxTemperature: number |
|
|
|
DHCP: boolean |
|
|
|
localIp: string |
|
|
|
} |
|
|
@ -165,7 +223,9 @@ const settings = ref<Settings>({ |
|
|
|
autoPrint: true, |
|
|
|
autoLogout: false, |
|
|
|
autoLogoutTimeout: 10, |
|
|
|
temperature: 0, |
|
|
|
allTemperature: 20, |
|
|
|
incubateBoxTemperature:20, |
|
|
|
plateBoxTemperature: 20, |
|
|
|
DHCP: true, |
|
|
|
localIp: '', |
|
|
|
}) |
|
|
@ -210,17 +270,33 @@ const fetchSettings = async () => { |
|
|
|
const res = await getSystemSettings() |
|
|
|
if (res.success) { |
|
|
|
settings.value = res.data |
|
|
|
if (res.data.incubateBoxTemperature === res.data.plateBoxTemperature) { |
|
|
|
settings.value.allTemperature = res.data.incubateBoxTemperature |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
eMessage.error('获取系统设置失败') |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function isIntegerInRange(str: string): boolean { |
|
|
|
// 匹配 20-40 的整数 |
|
|
|
const regex = /^(2[0-9]|3[0-9]|40)$/; |
|
|
|
return regex.test(str); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新设置 |
|
|
|
const updateSetting = async (key: string, value: any) => { |
|
|
|
try { |
|
|
|
let res |
|
|
|
switch (key) { |
|
|
|
case 'date': |
|
|
|
// 暂停定时器 |
|
|
|
clearInterval(intervalId.value) |
|
|
|
res = await setDateAndTime(value) |
|
|
|
// 恢复定时器 |
|
|
|
startTimer() |
|
|
|
break |
|
|
|
case 'language': |
|
|
|
res = await setLanguage(value) |
|
|
|
break |
|
|
@ -233,8 +309,26 @@ const updateSetting = async (key: string, value: any) => { |
|
|
|
case 'autoLogoutTimeout': |
|
|
|
res = await setAutoLogoutTime(value) |
|
|
|
break |
|
|
|
case 'temperature': |
|
|
|
res = await setTemperature(value) |
|
|
|
case 'allTemperature': |
|
|
|
if (!isIntegerInRange(value)) { |
|
|
|
eMessage.error('输入有误, 温度范围为20℃-40℃') |
|
|
|
return |
|
|
|
} |
|
|
|
res = await setAllTemperature(value) |
|
|
|
break |
|
|
|
case 'incubateBoxTemperature': |
|
|
|
if (!isIntegerInRange(value)) { |
|
|
|
eMessage.error('输入有误, 温度范围为20℃-40℃') |
|
|
|
return |
|
|
|
} |
|
|
|
res = await setIncubateBoxTemperature(value) |
|
|
|
break |
|
|
|
case 'plateBoxTemperature': |
|
|
|
if (!isIntegerInRange(value)) { |
|
|
|
eMessage.error('输入有误, 温度范围为20℃-40℃') |
|
|
|
return |
|
|
|
} |
|
|
|
res = await setPlateBoxTemperature(value) |
|
|
|
break |
|
|
|
case 'DHCP': |
|
|
|
res = await setDHCP(value) |
|
|
@ -252,24 +346,42 @@ const updateSetting = async (key: string, value: any) => { |
|
|
|
|
|
|
|
if (res?.success) { |
|
|
|
settings.value = { ...settings.value, [key]: value } |
|
|
|
|
|
|
|
if (key === 'allTemperature') { |
|
|
|
settings.value.incubateBoxTemperature = settings.value.plateBoxTemperature = value |
|
|
|
} |
|
|
|
if (settings.value.incubateBoxTemperature === settings.value.plateBoxTemperature) { |
|
|
|
settings.value.allTemperature = settings.value.incubateBoxTemperature |
|
|
|
} else { |
|
|
|
settings.value.allTemperature = undefined |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.log(error) |
|
|
|
eMessage.error('设置更新失败') |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 定时器相关 |
|
|
|
const intervalId = ref<number | null>(null) |
|
|
|
|
|
|
|
// 启动定时器 |
|
|
|
const startTimer = () => { |
|
|
|
intervalId.value = setInterval(() => { |
|
|
|
const now = new Date() |
|
|
|
currentDate.value = now |
|
|
|
time.value = format(now, 'yyyy.MM.dd HH:mm:ss'); |
|
|
|
}, 1000) |
|
|
|
} |
|
|
|
|
|
|
|
const temperatures = ref<number[]>([]) |
|
|
|
|
|
|
|
// 初始化 |
|
|
|
onMounted(async () => { |
|
|
|
await fetchSettings() |
|
|
|
|
|
|
|
// 更新时间显示 |
|
|
|
setInterval(() => { |
|
|
|
const now = new Date() |
|
|
|
currentDate.value = now |
|
|
|
time.value = now.toLocaleTimeString() |
|
|
|
}, 1000) |
|
|
|
// 启动定时器 |
|
|
|
startTimer() |
|
|
|
|
|
|
|
const res = await getTemperatureRange() |
|
|
|
if (res && res.success) { |
|
|
@ -279,22 +391,49 @@ onMounted(async () => { |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
// 在组件卸载时清理定时器 |
|
|
|
onUnmounted(() => { |
|
|
|
if (intervalId.value) { |
|
|
|
clearInterval(intervalId.value) |
|
|
|
} |
|
|
|
hideKeyboard() |
|
|
|
}) |
|
|
|
|
|
|
|
// 键盘相关状态 |
|
|
|
const keyboardVisible = ref(false) |
|
|
|
const currentInputValue = ref('') |
|
|
|
|
|
|
|
// 显示键盘 |
|
|
|
const showKeyboard = () => { |
|
|
|
const showKeyboard = (KeyboardType: string | undefined, type: number) => { |
|
|
|
inputNumberType.value = type |
|
|
|
if (KeyboardType) { |
|
|
|
layout.value = numericLayout |
|
|
|
}else{ |
|
|
|
layout.value = undefined |
|
|
|
} |
|
|
|
keyboardVisible.value = false |
|
|
|
setTimeout(() => { |
|
|
|
keyboardVisible.value = true |
|
|
|
}, 200) |
|
|
|
// 清空当前输入值,避免累加 |
|
|
|
currentInputValue.value = settings.value.localIp |
|
|
|
keyboardVisible.value = true |
|
|
|
currentInputValue.value = settings.value[inputType[type]] |
|
|
|
} |
|
|
|
|
|
|
|
const inputNumberType = ref(0) |
|
|
|
|
|
|
|
const inputType = { |
|
|
|
1:'allTemperature', |
|
|
|
2:'incubateBoxTemperature', |
|
|
|
3:'plateBoxTemperature', |
|
|
|
4:'localIp', |
|
|
|
} |
|
|
|
|
|
|
|
// 处理键盘输入 |
|
|
|
const handleKeyboardInput = (value: string) => { |
|
|
|
|
|
|
|
// 更新当前输入值 |
|
|
|
currentInputValue.value = value |
|
|
|
settings.value.localIp = value |
|
|
|
settings.value[inputType[inputNumberType.value]] = value |
|
|
|
} |
|
|
|
|
|
|
|
// 处理键盘按键 |
|
|
@ -321,6 +460,23 @@ const hideKeyboard = () => { |
|
|
|
onUnmounted(() => { |
|
|
|
hideKeyboard() |
|
|
|
}) |
|
|
|
|
|
|
|
// 暂停定时器 |
|
|
|
const pauseTimer = () => { |
|
|
|
if (intervalId.value) { |
|
|
|
console.log(111) |
|
|
|
clearInterval(intervalId.value); |
|
|
|
intervalId.value = null; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 恢复定时器 |
|
|
|
const resumeTimer = () => { |
|
|
|
if (!intervalId.value) { |
|
|
|
startTimer(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped lang="less"> |
|
|
@ -333,7 +489,15 @@ onUnmounted(() => { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
gap: 20px; |
|
|
|
.setting-item-box > :nth-child(2) { |
|
|
|
border-top: 1px solid #ddd; |
|
|
|
border-bottom: 1px solid #ddd; |
|
|
|
} |
|
|
|
|
|
|
|
.setting-item-no-border { |
|
|
|
border-radius: 0 !important; |
|
|
|
box-shadow: none !important; |
|
|
|
} |
|
|
|
.setting-item { |
|
|
|
background-color: #fff; |
|
|
|
border-radius: 12px; |
|
|
@ -414,4 +578,14 @@ onUnmounted(() => { |
|
|
|
.slide-up-leave-to { |
|
|
|
transform: translateY(100%); |
|
|
|
} |
|
|
|
:deep(.date-input) { |
|
|
|
width: 250px; |
|
|
|
margin-right: 30px; |
|
|
|
.el-input__wrapper { |
|
|
|
height: 40px; |
|
|
|
} |
|
|
|
.el-input__inner { |
|
|
|
font-size: 18px; |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |