diff --git a/src/components/equipments/SevenSegmentDisplay.vue b/src/components/equipments/SevenSegmentDisplay.vue index 4e80e3b..4e90edf 100644 --- a/src/components/equipments/SevenSegmentDisplay.vue +++ b/src/components/equipments/SevenSegmentDisplay.vue @@ -78,7 +78,8 @@ const pinRefs = ref>({}); interface SevenSegmentDisplayProps { size?: number; color?: string; - AFTERGLOW_DURATION?: number; // 余晖持续时间,单位毫秒 + AFTERGLOW_BUFFER_SIZE?: number; // 余晖存储槽大小 + AFTERGLOW_UPDATE_INTERVAL?: number; // 余晖更新间隔,单位毫秒 pins?: { pinId: string; constraint: string; @@ -91,6 +92,8 @@ interface SevenSegmentDisplayProps { const props = withDefaults(defineProps(), { size: 1, color: "red", + AFTERGLOW_BUFFER_SIZE: 1, // 默认存储槽大小为100 + AFTERGLOW_UPDATE_INTERVAL: 1, // 默认更新间隔为2毫秒 cathodeType: "common", // 默认为共阴极 pins: () => [ { pinId: "a", constraint: "", x: 10, y: 170 }, // a段 @@ -122,7 +125,7 @@ watch( { deep: true }, ); -// 段引脚状态 +// 段引脚的当前状态 const segmentStates = ref({ a: false, b: false, @@ -134,26 +137,26 @@ const segmentStates = ref({ dp: false, }); -// 余晖状态 -const afterglowStates = ref({ - a: false, - b: false, - c: false, - d: false, - e: false, - f: false, - g: false, - dp: false, +// 余晖存储槽 - 每个段有一个存储槽数组,存储历史状态 +const afterglowBuffers = ref>({ + a: [], + b: [], + c: [], + d: [], + e: [], + f: [], + g: [], + dp: [], }); -// 余晖定时器 -const afterglowTimers = ref>({}); +// 更新间隔计时器 +let updateIntervalTimer: number | null = null; -// 判断段是否激活 +// 判断段是否激活 - 如果当前状态或任一历史状态为true,则视为激活 function isSegmentActive( segment: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "dp", ): boolean { - return segmentStates.value[segment] || afterglowStates.value[segment]; + return segmentStates.value[segment] || afterglowBuffers.value[segment].some(state => state); } // 更新引脚状态的函数 @@ -170,17 +173,16 @@ function updateSegmentStates() { // 可扩展其他模式 } + // 如果COM口激活,更新所有段的状态到存储槽 + if (comActive) { + updateAfterglowBuffers(); + } + for (const pin of props.pins) { if (["a", "b", "c", "d", "e", "f", "g", "dp"].includes(pin.pinId)) { - // 如果COM未激活,段直接进入熄灭(带余晖效果) - if (!comActive) { - handleSegmentStateChange(pin.pinId, false); - continue; - } - // 如果constraint为空,则默认为未激活状态 if (!pin.constraint) { - handleSegmentStateChange(pin.pinId, false); + segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = false; continue; } @@ -193,63 +195,69 @@ function updateSegmentStates() { // 共阳极: 低电平激活段 newState = pinState === "low"; } - handleSegmentStateChange(pin.pinId, newState); + + // 更新当前状态 + segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState && comActive; } } } -// 处理段状态变化 -function handleSegmentStateChange(segmentId: string, newState: boolean) { - const typedSegmentId = segmentId as keyof typeof segmentStates.value; - const currentState = segmentStates.value[typedSegmentId]; - - // 更新实际状态 - segmentStates.value[typedSegmentId] = newState; - - // 处理余晖效果 - if (currentState && !newState) { - // 从激活变为非激活,启动余晖 - if (afterglowTimers.value[segmentId]) { - window.clearTimeout(afterglowTimers.value[segmentId]); +// 更新余晖存储槽 - 将当前段状态添加到存储槽中 +function updateAfterglowBuffers() { + for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) { + const typedSegmentId = segmentId as keyof typeof segmentStates.value; + const currentState = segmentStates.value[typedSegmentId]; + + // 将当前状态添加到存储槽的开头 + afterglowBuffers.value[segmentId].unshift(currentState); + + // 如果存储槽超过了最大容量,移除最旧的状态 + if (afterglowBuffers.value[segmentId].length > props.AFTERGLOW_BUFFER_SIZE) { + afterglowBuffers.value[segmentId].pop(); } - afterglowStates.value[typedSegmentId] = true; - afterglowTimers.value[segmentId] = window.setTimeout(() => { - afterglowStates.value[typedSegmentId] = false; - delete afterglowTimers.value[segmentId]; - }, props.AFTERGLOW_DURATION ?? 700); - } else if (newState) { - // 重新激活,清除余晖 - if (afterglowTimers.value[segmentId]) { - window.clearTimeout(afterglowTimers.value[segmentId]); - delete afterglowTimers.value[segmentId]; - } - afterglowStates.value[typedSegmentId] = false; + } +} + +// 开始余晖更新间隔 +function startAfterglowUpdates() { + if (updateIntervalTimer) return; + + updateIntervalTimer = window.setInterval(() => { + updateSegmentStates(); + }, props.AFTERGLOW_UPDATE_INTERVAL); +} + +// 停止余晖更新间隔 +function stopAfterglowUpdates() { + if (updateIntervalTimer) { + window.clearInterval(updateIntervalTimer); + updateIntervalTimer = null; } } // 监听约束状态变化 function onConstraintChange(constraint: string, level: string) { const affectedPin = props.pins.find((pin) => pin.constraint === constraint); - if ( - affectedPin && - ["a", "b", "c", "d", "e", "f", "g", "dp"].includes(affectedPin.pinId) - ) { + if (affectedPin) { updateSegmentStates(); } } // 生命周期钩子 onMounted(() => { + // 初始化余晖存储槽 + for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) { + afterglowBuffers.value[segmentId] = Array(props.AFTERGLOW_BUFFER_SIZE).fill(false); + } + updateSegmentStates(); onConstraintStateChange(onConstraintChange); + startAfterglowUpdates(); }); onUnmounted(() => { // 清理约束状态监听 - // 清理所有余晖定时器 - Object.values(afterglowTimers.value).forEach(timerId => { - if (timerId) window.clearTimeout(timerId); - }); + stopAfterglowUpdates(); }); // 暴露属性和方法