feat: frontend add boundary scan
This commit is contained in:
@@ -1,106 +1,75 @@
|
||||
<template>
|
||||
<div class="seven-segment-display" :style="{ width: width + 'px', height: height + 'px', position: 'relative' }"> <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
:width="width"
|
||||
:height="height"
|
||||
viewBox="0 0 120 220"
|
||||
class="display"
|
||||
>
|
||||
<div class="seven-segment-display" :style="{
|
||||
width: width + 'px',
|
||||
height: height + 'px',
|
||||
position: 'relative',
|
||||
}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" :width="width" :height="height" viewBox="0 0 120 220" class="display">
|
||||
<!-- 数码管基座 -->
|
||||
<rect width="120" height="180" x="0" y="0" fill="#222" rx="10" ry="10" />
|
||||
<rect width="110" height="170" x="5" y="5" fill="#333" rx="5" ry="5" />
|
||||
<!-- 7段 + 小数点,每个段由多边形表示,重新设计点位置使其更接近实际数码管 -->
|
||||
<!-- 7段 + 小数点,每个段由多边形表示,重新设计点位置使其更接近实际数码管 -->
|
||||
<!-- a段 (顶部横线) -->
|
||||
<polygon
|
||||
:points="'30,20 90,20 98,28 82,36 38,36 22,28'"
|
||||
:fill="isSegmentActive('a') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('a') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/>
|
||||
|
||||
<polygon :points="'30,20 90,20 98,28 82,36 38,36 22,28'"
|
||||
:fill="isSegmentActive('a') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('a') ? 1 : 0.15 }" class="segment" />
|
||||
|
||||
<!-- b段 (右上竖线) -->
|
||||
<polygon
|
||||
:points="'100,30 108,38 108,82 100,90 92,82 92,38'"
|
||||
:fill="isSegmentActive('b') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('b') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/>
|
||||
|
||||
<polygon :points="'100,30 108,38 108,82 100,90 92,82 92,38'"
|
||||
:fill="isSegmentActive('b') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('b') ? 1 : 0.15 }" class="segment" />
|
||||
|
||||
<!-- c段 (右下竖线) -->
|
||||
<polygon
|
||||
:points="'100,90 108,98 108,142 100,150 92,142 92,98'"
|
||||
:fill="isSegmentActive('c') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('c') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/>
|
||||
|
||||
<polygon :points="'100,90 108,98 108,142 100,150 92,142 92,98'"
|
||||
:fill="isSegmentActive('c') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('c') ? 1 : 0.15 }" class="segment" />
|
||||
|
||||
<!-- d段 (底部横线) -->
|
||||
<polygon
|
||||
:points="'30,160 90,160 98,152 82,144 38,144 22,152'"
|
||||
:fill="isSegmentActive('d') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('d') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/>
|
||||
|
||||
<polygon :points="'30,160 90,160 98,152 82,144 38,144 22,152'"
|
||||
:fill="isSegmentActive('d') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('d') ? 1 : 0.15 }" class="segment" />
|
||||
|
||||
<!-- e段 (左下竖线) -->
|
||||
<polygon
|
||||
:points="'20,90 28,98 28,142 20,150 12,142 12,98'"
|
||||
:fill="isSegmentActive('e') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('e') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/>
|
||||
|
||||
<polygon :points="'20,90 28,98 28,142 20,150 12,142 12,98'"
|
||||
:fill="isSegmentActive('e') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('e') ? 1 : 0.15 }" class="segment" />
|
||||
|
||||
<!-- f段 (左上竖线) -->
|
||||
<polygon
|
||||
:points="'20,30 28,38 28,82 20,90 12,82 12,38'"
|
||||
:fill="isSegmentActive('f') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('f') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/>
|
||||
|
||||
<polygon :points="'20,30 28,38 28,82 20,90 12,82 12,38'"
|
||||
:fill="isSegmentActive('f') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('f') ? 1 : 0.15 }" class="segment" />
|
||||
|
||||
<!-- g段 (中间横线) -->
|
||||
<polygon
|
||||
:points="'30,90 38,82 82,82 90,90 82,98 38,98'"
|
||||
:fill="isSegmentActive('g') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('g') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/> <!-- dp段 (小数点) -->
|
||||
<circle
|
||||
cx="108"
|
||||
cy="154"
|
||||
r="6"
|
||||
:fill="isSegmentActive('dp') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('dp') ? 1 : 0.15 }"
|
||||
class="segment"
|
||||
/>
|
||||
<polygon :points="'30,90 38,82 82,82 90,90 82,98 38,98'"
|
||||
:fill="isSegmentActive('g') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('g') ? 1 : 0.15 }" class="segment" />
|
||||
<!-- dp段 (小数点) -->
|
||||
<circle cx="108" cy="154" r="6" :fill="isSegmentActive('dp') ? segmentColor : inactiveColor"
|
||||
:style="{ opacity: isSegmentActive('dp') ? 1 : 0.15 }" class="segment" />
|
||||
</svg>
|
||||
|
||||
|
||||
<!-- 引脚 -->
|
||||
<div v-for="pin in pins" :key="pin.pinId"
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
left: `${pin.x * props.size}px`,
|
||||
top: `${pin.y * props.size}px`,
|
||||
transform: 'translate(-50%, -50%)'
|
||||
}"
|
||||
:data-pin-wrapper="`${pin.pinId}`"
|
||||
:data-pin-x="`${pin.x * props.size}`"
|
||||
:data-pin-y="`${pin.y * props.size}`">
|
||||
<Pin
|
||||
:ref="el => { if(el) pinRefs[pin.pinId] = el }"
|
||||
:label="pin.pinId"
|
||||
:constraint="pin.constraint"
|
||||
:pinId="pin.pinId"
|
||||
@pin-click="$emit('pin-click', $event)"
|
||||
/>
|
||||
<div v-for="pin in pins" :key="pin.pinId" :style="{
|
||||
position: 'absolute',
|
||||
left: `${pin.x * props.size}px`,
|
||||
top: `${pin.y * props.size}px`,
|
||||
transform: 'translate(-50%, -50%)',
|
||||
}" :data-pin-wrapper="`${pin.pinId}`" :data-pin-x="`${pin.x * props.size}`"
|
||||
:data-pin-y="`${pin.y * props.size}`">
|
||||
<Pin :ref="(el) => {
|
||||
if (el) pinRefs[pin.pinId] = el;
|
||||
}
|
||||
" :label="pin.pinId" :constraint="pin.constraint" :pinId="pin.pinId" @pin-click="$emit('pin-click', $event)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
|
||||
import { getConstraintState, onConstraintStateChange } from '../../stores/constraints';
|
||||
import Pin from './Pin.vue';
|
||||
import { ref, computed, watch, onMounted, onUnmounted } from "vue";
|
||||
import { useConstraintsStore } from "../../stores/constraints";
|
||||
import Pin from "./Pin.vue";
|
||||
|
||||
const { getConstraintState, onConstraintStateChange } = useConstraintsStore();
|
||||
|
||||
// 存储Pin引用
|
||||
const pinRefs = ref<Record<string, any>>({});
|
||||
@@ -115,41 +84,41 @@ interface SevenSegmentDisplayProps {
|
||||
x: number;
|
||||
y: number;
|
||||
}[];
|
||||
cathodeType?: 'common' | 'anode'; // 共阴极或共阳极
|
||||
cathodeType?: "common" | "anode"; // 共阴极或共阳极
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<SevenSegmentDisplayProps>(), {
|
||||
size: 1,
|
||||
color: 'red',
|
||||
cathodeType: 'common', // 默认为共阴极
|
||||
color: "red",
|
||||
cathodeType: "common", // 默认为共阴极
|
||||
pins: () => [
|
||||
{ pinId: 'a', constraint: '', x: 10 , y: 170 }, // a段
|
||||
{ pinId: 'b', constraint: '', x: 25-1 , y: 170 }, // b段
|
||||
{ pinId: 'c', constraint: '', x: 40-2 , y: 170 }, // c段
|
||||
{ pinId: 'd', constraint: '', x: 55-3 , y: 170 }, // d段
|
||||
{ pinId: 'e', constraint: '', x: 70-4 , y: 170 }, // e段
|
||||
{ pinId: 'f', constraint: '', x: 85-5 , y: 170 }, // f段
|
||||
{ pinId: 'g', constraint: '', x: 100-6, y: 170 }, // g段
|
||||
{ pinId: 'dp', constraint: '', x: 115-7, y: 170 }, // 小数点
|
||||
{ pinId: 'COM', constraint: '', x: 60 , y: 10 } // 公共端,稍微低一点
|
||||
]
|
||||
{ pinId: "a", constraint: "", x: 10, y: 170 }, // a段
|
||||
{ pinId: "b", constraint: "", x: 25 - 1, y: 170 }, // b段
|
||||
{ pinId: "c", constraint: "", x: 40 - 2, y: 170 }, // c段
|
||||
{ pinId: "d", constraint: "", x: 55 - 3, y: 170 }, // d段
|
||||
{ pinId: "e", constraint: "", x: 70 - 4, y: 170 }, // e段
|
||||
{ pinId: "f", constraint: "", x: 85 - 5, y: 170 }, // f段
|
||||
{ pinId: "g", constraint: "", x: 100 - 6, y: 170 }, // g段
|
||||
{ pinId: "dp", constraint: "", x: 115 - 7, y: 170 }, // 小数点
|
||||
{ pinId: "COM", constraint: "", x: 60, y: 10 }, // 公共端,稍微低一点
|
||||
],
|
||||
});
|
||||
|
||||
const width = computed(() => 120 * props.size);
|
||||
const height = computed(() => 220 * props.size);
|
||||
|
||||
// 计算段颜色和非激活状态颜色
|
||||
const segmentColor = computed(() => props.color || 'red');
|
||||
const inactiveColor = computed(() => '#FFFFFF');
|
||||
const segmentColor = computed(() => props.color || "red");
|
||||
const inactiveColor = computed(() => "#FFFFFF");
|
||||
|
||||
// 监听props变化
|
||||
watch(
|
||||
() => props,
|
||||
(newProps) => {
|
||||
console.log('SevenSegmentDisplay props changed:', newProps);
|
||||
console.log("SevenSegmentDisplay props changed:", newProps);
|
||||
updateSegmentStates();
|
||||
},
|
||||
{ deep: true }
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
// 段引脚状态
|
||||
@@ -165,29 +134,34 @@ const segmentStates = ref({
|
||||
});
|
||||
|
||||
// 判断段是否激活
|
||||
function isSegmentActive(segment: 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'dp'): boolean {
|
||||
function isSegmentActive(
|
||||
segment: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "dp",
|
||||
): boolean {
|
||||
return segmentStates.value[segment];
|
||||
}
|
||||
|
||||
// 更新引脚状态的函数
|
||||
function updateSegmentStates() {
|
||||
for (const pin of props.pins) {
|
||||
if (['a', 'b', 'c', 'd', 'e', 'f', 'g', 'dp'].includes(pin.pinId)) {
|
||||
if (["a", "b", "c", "d", "e", "f", "g", "dp"].includes(pin.pinId)) {
|
||||
// 如果constraint为空,则默认为未激活状态
|
||||
if (!pin.constraint) {
|
||||
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = false;
|
||||
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] =
|
||||
false;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const pinState = getConstraintState(pin.constraint);
|
||||
|
||||
|
||||
// 根据阴极/阳极类型反转逻辑
|
||||
if (props.cathodeType === 'common') {
|
||||
if (props.cathodeType === "common") {
|
||||
// 共阴极: 高电平激活段
|
||||
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = pinState === 'high';
|
||||
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] =
|
||||
pinState === "high";
|
||||
} else {
|
||||
// 共阳极: 低电平激活段
|
||||
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = pinState === 'low';
|
||||
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] =
|
||||
pinState === "low";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,8 +169,11 @@ function updateSegmentStates() {
|
||||
|
||||
// 监听约束状态变化
|
||||
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)) {
|
||||
const affectedPin = props.pins.find((pin) => pin.constraint === constraint);
|
||||
if (
|
||||
affectedPin &&
|
||||
["a", "b", "c", "d", "e", "f", "g", "dp"].includes(affectedPin.pinId)
|
||||
) {
|
||||
updateSegmentStates();
|
||||
}
|
||||
}
|
||||
@@ -213,7 +190,7 @@ onUnmounted(() => {
|
||||
|
||||
// 暴露属性和方法
|
||||
defineExpose({
|
||||
updateSegmentStates
|
||||
updateSegmentStates,
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -224,7 +201,9 @@ defineExpose({
|
||||
}
|
||||
|
||||
.segment {
|
||||
transition: opacity 0.2s, fill 0.2s;
|
||||
transition:
|
||||
opacity 0.2s,
|
||||
fill 0.2s;
|
||||
}
|
||||
|
||||
/* 数码管发光效果 */
|
||||
@@ -238,19 +217,19 @@ defineExpose({
|
||||
export function getDefaultProps() {
|
||||
return {
|
||||
size: 1,
|
||||
color: 'red',
|
||||
cathodeType: 'common',
|
||||
color: "red",
|
||||
cathodeType: "common",
|
||||
pins: [
|
||||
{ pinId: 'a', constraint: '', x: 10 , y: 170 },
|
||||
{ pinId: 'b', constraint: '', x: 25-1 , y: 170 },
|
||||
{ pinId: 'c', constraint: '', x: 40-2 , y: 170 },
|
||||
{ pinId: 'd', constraint: '', x: 55-3 , y: 170 },
|
||||
{ pinId: 'e', constraint: '', x: 70-4 , y: 170 },
|
||||
{ pinId: 'f', constraint: '', x: 85-5 , y: 170 },
|
||||
{ pinId: 'g', constraint: '', x: 100-6, y: 170 },
|
||||
{ pinId: 'dp', constraint: '', x: 115-7, y: 170 },
|
||||
{ pinId: 'COM', constraint: '', x: 60 , y: 10 }
|
||||
]
|
||||
{ pinId: "a", constraint: "", x: 10, y: 170 },
|
||||
{ pinId: "b", constraint: "", x: 25 - 1, y: 170 },
|
||||
{ pinId: "c", constraint: "", x: 40 - 2, y: 170 },
|
||||
{ pinId: "d", constraint: "", x: 55 - 3, y: 170 },
|
||||
{ pinId: "e", constraint: "", x: 70 - 4, y: 170 },
|
||||
{ pinId: "f", constraint: "", x: 85 - 5, y: 170 },
|
||||
{ pinId: "g", constraint: "", x: 100 - 6, y: 170 },
|
||||
{ pinId: "dp", constraint: "", x: 115 - 7, y: 170 },
|
||||
{ pinId: "COM", constraint: "", x: 60, y: 10 },
|
||||
],
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user