feat: Enhance equipment components with pin functionality and constraint management
- Added pin support to MechanicalButton, enabling pin-click events and componentId handling. - Updated Pin component to manage constraint states and colors dynamically. - Integrated SMT_LED with pin functionality, allowing LED state to respond to constraints. - Enhanced Wire component to reflect constraint colors and manage wire states based on pin connections. - Introduced wireManager for managing wire states and constraints. - Implemented a constraints store for managing and notifying constraint state changes across components. - Updated component configuration to remove appearance options and clarify constraint descriptions. - Improved ProjectView to handle optional chaining for props and ensure robust data handling. - Initialized constraint communication in main application entry point.
This commit is contained in:
@@ -14,16 +14,15 @@
|
||||
<rect width="90" height="50" x="5" y="5" fill="#222" rx="3" ry="3" />
|
||||
|
||||
<!-- LED 发光部分 -->
|
||||
<rect
|
||||
<rect
|
||||
width="70"
|
||||
height="30"
|
||||
x="15"
|
||||
y="15"
|
||||
:fill="ledColor"
|
||||
:style="{ opacity: isOn ? brightness/100 : 0.2 }"
|
||||
:style="{ opacity: isOn ? 1 : 0.2 }"
|
||||
rx="15"
|
||||
ry="15"
|
||||
@click="toggleLed"
|
||||
class="interactive"
|
||||
/>
|
||||
|
||||
@@ -35,46 +34,64 @@
|
||||
x="12"
|
||||
y="12"
|
||||
:fill="ledColor"
|
||||
:style="{ opacity: brightness/100 * 0.3 }"
|
||||
:style="{ opacity: 0.3 }"
|
||||
rx="18"
|
||||
ry="18"
|
||||
filter="blur(5px)"
|
||||
class="glow"
|
||||
/>
|
||||
</svg>
|
||||
<!-- 新增:数字输入引脚Pin,放在LED左侧居中 -->
|
||||
<div style="position:absolute;left:-18px;top:50%;transform:translateY(-50%);">
|
||||
<Pin
|
||||
ref="pinRef"
|
||||
v-bind="props"
|
||||
@pin-click="$emit('pin-click', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
|
||||
import { getConstraintState, onConstraintStateChange } from '../../stores/constraints';
|
||||
import Pin from './Pin.vue';
|
||||
|
||||
// LED特有属性
|
||||
interface Props {
|
||||
size?: number;
|
||||
color?: string;
|
||||
initialOn?: boolean;
|
||||
brightness?: number;
|
||||
// --- 关键:暴露getPinPosition,代理到内部Pin ---
|
||||
const pinRef = ref<any>(null);
|
||||
|
||||
// 从Pin组件继承属性
|
||||
interface PinProps {
|
||||
label?: string;
|
||||
constraint?: string;
|
||||
componentId?: string; // 添加componentId属性
|
||||
// 这些属性被预设为固定值,但仍然包含在类型中以便完整继承
|
||||
direction?: 'input' | 'output' | 'inout';
|
||||
type?: 'digital' | 'analog';
|
||||
}
|
||||
|
||||
// 组件属性定义
|
||||
// LED特有属性
|
||||
interface LEDProps {
|
||||
size?: number;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
// 组合两个接口
|
||||
interface Props extends PinProps, LEDProps {}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
size: 1,
|
||||
color: 'red',
|
||||
initialOn: false,
|
||||
brightness: 80, // 亮度默认为80%
|
||||
constraint: ''
|
||||
constraint: '',
|
||||
label: 'LED',
|
||||
componentId: ''
|
||||
});
|
||||
|
||||
// 计算实际宽高
|
||||
const width = computed(() => 100 * props.size);
|
||||
const height = computed(() => 60 * props.size);
|
||||
|
||||
// 内部状态
|
||||
const isOn = ref(props.initialOn);
|
||||
const brightness = ref(props.brightness);
|
||||
const isOn = ref(false);
|
||||
|
||||
// LED 颜色映射表
|
||||
const colorMap: Record<string, string> = {
|
||||
'red': '#ff3333',
|
||||
'green': '#33ff33',
|
||||
@@ -85,70 +102,64 @@ const colorMap: Record<string, string> = {
|
||||
'purple': '#9933ff'
|
||||
};
|
||||
|
||||
// 计算实际LED颜色
|
||||
const ledColor = computed(() => {
|
||||
return colorMap[props.color.toLowerCase()] || props.color;
|
||||
});
|
||||
|
||||
// 定义组件发出的事件
|
||||
const emit = defineEmits([
|
||||
'toggle',
|
||||
'brightness-change',
|
||||
'value-change'
|
||||
]);
|
||||
// 监听约束状态变化
|
||||
let unsubscribe: (() => void) | null = null;
|
||||
|
||||
// 手动切换LED状态
|
||||
function toggleLed() {
|
||||
isOn.value = !isOn.value;
|
||||
emit('toggle', isOn.value);
|
||||
emit('value-change', {
|
||||
isOn: isOn.value,
|
||||
brightness: brightness.value
|
||||
});
|
||||
}
|
||||
|
||||
// 设置亮度
|
||||
function setBrightness(value: number) {
|
||||
// 限制亮度值在0-100范围内
|
||||
brightness.value = Math.max(0, Math.min(100, value));
|
||||
emit('brightness-change', brightness.value);
|
||||
emit('value-change', {
|
||||
isOn: isOn.value,
|
||||
brightness: brightness.value
|
||||
});
|
||||
}
|
||||
|
||||
// 手动设置LED开关状态
|
||||
function setLedState(on: boolean) {
|
||||
isOn.value = on;
|
||||
emit('toggle', isOn.value);
|
||||
emit('value-change', {
|
||||
isOn: isOn.value,
|
||||
brightness: brightness.value
|
||||
});
|
||||
}
|
||||
|
||||
// 监听props变化
|
||||
watch(() => props.brightness, (newVal) => {
|
||||
brightness.value = newVal;
|
||||
onMounted(() => {
|
||||
if (props.constraint) {
|
||||
unsubscribe = onConstraintStateChange((constraint, level) => {
|
||||
if (constraint === props.constraint) {
|
||||
isOn.value = (level === 'high');
|
||||
}
|
||||
});
|
||||
// 初始化LED状态
|
||||
const currentState = getConstraintState(props.constraint);
|
||||
isOn.value = (currentState === 'high');
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.initialOn, (newVal) => {
|
||||
isOn.value = newVal;
|
||||
onUnmounted(() => {
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.constraint, (newConstraint) => {
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
unsubscribe = null;
|
||||
}
|
||||
if (newConstraint) {
|
||||
unsubscribe = onConstraintStateChange((constraint, level) => {
|
||||
if (constraint === newConstraint) {
|
||||
isOn.value = (level === 'high');
|
||||
}
|
||||
});
|
||||
// 初始化LED状态
|
||||
const currentState = getConstraintState(newConstraint);
|
||||
isOn.value = (currentState === 'high');
|
||||
}
|
||||
});
|
||||
|
||||
// 向外暴露方法
|
||||
defineExpose({
|
||||
toggleLed,
|
||||
setBrightness,
|
||||
setLedState,
|
||||
getInfo: () => ({
|
||||
// LED特有属性
|
||||
color: props.color,
|
||||
isOn: isOn.value,
|
||||
brightness: brightness.value,
|
||||
constraint: props.constraint
|
||||
})
|
||||
constraint: props.constraint,
|
||||
componentId: props.componentId,
|
||||
direction: 'input',
|
||||
type: 'digital'
|
||||
}),
|
||||
getPinPosition: (componentId: string) => {
|
||||
if (pinRef.value && pinRef.value.getPinPosition) {
|
||||
return pinRef.value.getPinPosition(componentId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user