Refactor component configuration and diagram management
- Removed the component configuration from `componentConfig.ts` to streamline the codebase. - Introduced a new `diagram.json` file to define the initial structure for diagrams. - Created a `diagramManager.ts` to handle diagram data, including loading, saving, and validating diagram structures. - Updated `ProjectView.vue` to integrate the new diagram management system, including handling component selection and property updates. - Enhanced the component property management to support dynamic attributes and improved error handling. - Added functions for managing connections between components within the diagram.
This commit is contained in:
@@ -17,11 +17,11 @@
|
||||
<rect
|
||||
width="70"
|
||||
height="30"
|
||||
x="15"
|
||||
y="15"
|
||||
x="15"
|
||||
y="15"
|
||||
:fill="ledColor"
|
||||
:style="{ opacity: isOn ? 1 : 0.2 }"
|
||||
rx="15"
|
||||
rx="15"
|
||||
ry="15"
|
||||
class="interactive"
|
||||
/>
|
||||
@@ -39,13 +39,19 @@
|
||||
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"
|
||||
/> </svg>
|
||||
<!-- 渲染自定义引脚数组 -->
|
||||
<div v-for="pin in props.pins" :key="pin.pinId"
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
left: `${pin.x}px`,
|
||||
top: `${pin.y}px`,
|
||||
transform: 'translate(-50%, -50%)'
|
||||
}"> <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>
|
||||
@@ -57,34 +63,36 @@ import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
|
||||
import { getConstraintState, onConstraintStateChange } from '../../stores/constraints';
|
||||
import Pin from './Pin.vue';
|
||||
|
||||
// --- 关键:暴露getPinPosition,代理到内部Pin ---
|
||||
const pinRef = ref<any>(null);
|
||||
|
||||
// 从Pin组件继承属性
|
||||
interface PinProps {
|
||||
label?: string;
|
||||
constraint?: string;
|
||||
componentId?: string; // 添加componentId属性
|
||||
// 这些属性被预设为固定值,但仍然包含在类型中以便完整继承
|
||||
direction?: 'input' | 'output' | 'inout';
|
||||
type?: 'digital' | 'analog';
|
||||
}
|
||||
// 存储多个Pin引用
|
||||
const pinRefs = ref<Record<string, any>>({});
|
||||
|
||||
// LED特有属性
|
||||
interface LEDProps {
|
||||
size?: number;
|
||||
color?: string;
|
||||
initialOn?: boolean;
|
||||
brightness?: number;
|
||||
pins?: {
|
||||
pinId: string;
|
||||
constraint: string;
|
||||
x: number;
|
||||
y: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
// 组合两个接口
|
||||
interface Props extends PinProps, LEDProps {}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<LEDProps>(), {
|
||||
size: 1,
|
||||
color: 'red',
|
||||
constraint: '',
|
||||
label: 'LED',
|
||||
componentId: ''
|
||||
initialOn: false,
|
||||
brightness: 80,
|
||||
pins: () => [
|
||||
{
|
||||
pinId: 'LED',
|
||||
constraint: '',
|
||||
x: 50,
|
||||
y: 30
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const width = computed(() => 100 * props.size);
|
||||
@@ -106,18 +114,26 @@ const ledColor = computed(() => {
|
||||
return colorMap[props.color.toLowerCase()] || props.color;
|
||||
});
|
||||
|
||||
// 获取LED的constraint值
|
||||
const ledConstraint = computed(() => {
|
||||
if (props.pins && props.pins.length > 0) {
|
||||
return props.pins[0].constraint;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
// 监听约束状态变化
|
||||
let unsubscribe: (() => void) | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
if (props.constraint) {
|
||||
if (ledConstraint.value) {
|
||||
unsubscribe = onConstraintStateChange((constraint, level) => {
|
||||
if (constraint === props.constraint) {
|
||||
if (constraint === ledConstraint.value) {
|
||||
isOn.value = (level === 'high');
|
||||
}
|
||||
});
|
||||
// 初始化LED状态
|
||||
const currentState = getConstraintState(props.constraint);
|
||||
const currentState = getConstraintState(ledConstraint.value);
|
||||
isOn.value = (currentState === 'high');
|
||||
}
|
||||
});
|
||||
@@ -128,7 +144,7 @@ onUnmounted(() => {
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.constraint, (newConstraint) => {
|
||||
watch(() => ledConstraint.value, (newConstraint) => {
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
unsubscribe = null;
|
||||
@@ -149,20 +165,49 @@ defineExpose({
|
||||
getInfo: () => ({
|
||||
color: props.color,
|
||||
isOn: isOn.value,
|
||||
constraint: props.constraint,
|
||||
componentId: props.componentId,
|
||||
constraint: ledConstraint.value,
|
||||
direction: 'input',
|
||||
type: 'digital'
|
||||
}),
|
||||
getPinPosition: (componentId: string) => {
|
||||
if (pinRef.value && pinRef.value.getPinPosition) {
|
||||
return pinRef.value.getPinPosition(componentId);
|
||||
}
|
||||
return null;
|
||||
type: 'digital',
|
||||
pins: props.pins
|
||||
}), getPinPosition: (pinId: string) => {
|
||||
// 如果是自定义的引脚ID
|
||||
if (props.pins && props.pins.length > 0) {
|
||||
console.log('Pin ID:', pinId);
|
||||
const customPin = props.pins.find(p => p.pinId === pinId);
|
||||
console.log('Custom Pin:', customPin);
|
||||
console.log('Pin Refs:', pinRefs.value[pinId]);
|
||||
if (customPin) {
|
||||
// 调用对应Pin组件的getPinPosition方法
|
||||
return {
|
||||
x: customPin.x,
|
||||
y: customPin.y
|
||||
}
|
||||
} return null;
|
||||
} return null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
// 添加一个静态方法来获取默认props
|
||||
export function getDefaultProps() {
|
||||
return {
|
||||
size: 1,
|
||||
color: 'red',
|
||||
initialOn: false,
|
||||
brightness: 80,
|
||||
pins: [
|
||||
{
|
||||
pinId: 'LED',
|
||||
constraint: '',
|
||||
x: 50,
|
||||
y: 30
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.led-container {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user