实训台:加 ADAM-4150 DO1 照明灯的卡片(项目 7 用);滑块松开后等服务器回传同样的值再换回,键盘方向键连按不再丢步
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b3d6e1f88f
commit
b7e7f77fb0
1 file changed
+32
-1
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// 虚拟实训台:按教材实训台布局图(顶棚 → LED 屏 → 传感器 → 采集模块)排列。
|
// 虚拟实训台:按教材实训台布局图(顶棚 → LED 屏 → 传感器 → 采集模块)排列。
|
||||||
// 传感器卡片上的滑块和开关调节环境(经服务器推给学生程序),灯和继电器的状态由学生程序控制。
|
// 传感器卡片上的滑块和开关调节环境(经服务器推给学生程序),灯和继电器的状态由学生程序控制。
|
||||||
import { computed, onBeforeUnmount, ref } from 'vue'
|
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
||||||
import { ANALOG_INFO, clockWall, type AnalogKey, type BoardState, type ClientMessage, type DigitalKey } from '@iot/shared'
|
import { ANALOG_INFO, clockWall, type AnalogKey, type BoardState, type ClientMessage, type DigitalKey } from '@iot/shared'
|
||||||
|
|
||||||
type BoardInput = Omit<Extract<ClientMessage, { type: 'boardInput' }>, 'type'>
|
type BoardInput = Omit<Extract<ClientMessage, { type: 'boardInput' }>, 'type'>
|
||||||
@@ -63,12 +63,34 @@ function flush() {
|
|||||||
pending = {}
|
pending = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 松开后继续显示本地值,等服务器回传了这个值再用服务器的:键盘方向键连按时每按一下都会触发 change,
|
||||||
|
// 立刻换回服务器的旧值,下一下就从旧值开始加,看起来像丢了几步。服务器没回传同样的值(比如被截到范围内)时 1 秒后放弃
|
||||||
|
const releasing = new Map<AnalogKey, ReturnType<typeof setTimeout>>()
|
||||||
|
|
||||||
function release(key: AnalogKey) {
|
function release(key: AnalogKey) {
|
||||||
flush()
|
flush()
|
||||||
|
clearTimeout(releasing.get(key))
|
||||||
|
releasing.set(
|
||||||
|
key,
|
||||||
|
setTimeout(() => drop(key), 1000),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function drop(key: AnalogKey) {
|
||||||
|
clearTimeout(releasing.get(key))
|
||||||
|
releasing.delete(key)
|
||||||
const { [key]: _, ...rest } = dragging.value
|
const { [key]: _, ...rest } = dragging.value
|
||||||
dragging.value = rest
|
dragging.value = rest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.board?.analog,
|
||||||
|
(values) => {
|
||||||
|
for (const key of [...releasing.keys()]) if (values?.[key] === dragging.value[key]) drop(key)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
onBeforeUnmount(() => releasing.forEach((timer) => clearTimeout(timer)))
|
||||||
|
|
||||||
function toggle(key: DigitalKey) {
|
function toggle(key: DigitalKey) {
|
||||||
if (props.board) emit('set', { digital: { [key]: !props.board.digital[key] } })
|
if (props.board) emit('set', { digital: { [key]: !props.board.digital[key] } })
|
||||||
}
|
}
|
||||||
@@ -77,6 +99,8 @@ const digital = computed(() => props.board?.digital ?? { bodyInfrared: false, fi
|
|||||||
const relays = computed(() => props.board?.relays ?? [])
|
const relays = computed(() => props.board?.relays ?? [])
|
||||||
const streetLampOn = computed(() => props.board?.zigbee[1] === true)
|
const streetLampOn = computed(() => props.board?.zigbee[1] === true)
|
||||||
const alarmOn = computed(() => relays.value[0] === true)
|
const alarmOn = computed(() => relays.value[0] === true)
|
||||||
|
/** ADAM-4150 DO1 接的照明灯(教材项目 7 的智慧教室、寝室、会议室用它) */
|
||||||
|
const roomLampOn = computed(() => relays.value[1] === true)
|
||||||
const ledText = computed(() => props.board?.ledText ?? '')
|
const ledText = computed(() => props.board?.ledText ?? '')
|
||||||
const camera = computed(() => props.board?.camera ?? { on: false, x: 3, y: 1 })
|
const camera = computed(() => props.board?.camera ?? { on: false, x: 3, y: 1 })
|
||||||
// ---------- 虚拟时钟:显示学生程序看到的时间,可以拨时间、调倍速 ----------
|
// ---------- 虚拟时钟:显示学生程序看到的时间,可以拨时间、调倍速 ----------
|
||||||
@@ -122,6 +146,7 @@ const cameraTitle = computed(() =>
|
|||||||
<span class="board-name">虚拟实训台</span>
|
<span class="board-name">虚拟实训台</span>
|
||||||
<span class="io out warn" :class="{ lit: alarmOn }"><i />警示灯</span>
|
<span class="io out warn" :class="{ lit: alarmOn }"><i />警示灯</span>
|
||||||
<span class="io out" :class="{ lit: streetLampOn }"><i />照明灯 1</span>
|
<span class="io out" :class="{ lit: streetLampOn }"><i />照明灯 1</span>
|
||||||
|
<span class="io out" :class="{ lit: roomLampOn }"><i />照明灯 2</span>
|
||||||
<span class="summary-readings">
|
<span class="summary-readings">
|
||||||
<span v-for="key in ['temperature', 'humidity', 'light'] as AnalogKey[]" :key="key">
|
<span v-for="key in ['temperature', 'humidity', 'light'] as AnalogKey[]" :key="key">
|
||||||
{{ ANALOG_INFO[key].label }} <b>{{ analog(key) }}{{ ANALOG_INFO[key].unit }}</b>
|
{{ ANALOG_INFO[key].label }} <b>{{ analog(key) }}{{ ANALOG_INFO[key].unit }}</b>
|
||||||
@@ -251,6 +276,12 @@ const cameraTitle = computed(() =>
|
|||||||
<div class="card-title">火焰传感器</div>
|
<div class="card-title">火焰传感器</div>
|
||||||
<div class="card-note">{{ digital.fire ? '有火焰' : '正常' }}</div>
|
<div class="card-note">{{ digital.fire ? '有火焰' : '正常' }}</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div class="card" title="照明灯 2:由 ADAM-4150 的 DO1 控制(教材项目 7 的教室、寝室、会议室照明)">
|
||||||
|
<div class="bulb" :class="{ on: roomLampOn }" />
|
||||||
|
<div class="card-title">照明灯 2</div>
|
||||||
|
<div class="card-note">ADAM-4150 DO1</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 采集模块与串口 -->
|
<!-- 采集模块与串口 -->
|
||||||
|
|||||||
Reference in new issue
Block a user