FPGA_WebLab/src/components/PropertyPanel.vue

234 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="property-panel">
<CollapsibleSection title="基本属性" v-model:isExpanded="propertySectionExpanded" status="default">
<PropertyEditor :componentData="componentData" :componentConfig="componentConfig" @updateProp="
(componentId, propName, value) =>
$emit('updateProp', componentId, propName, value)
" @updateDirectProp="
(componentId, propName, value) =>
$emit('updateDirectProp', componentId, propName, value)
" />
</CollapsibleSection>
<!-- 信号发生器DDS特殊属性编辑器 -->
<div v-if="isDDSComponent">
<DDSPropertyEditor v-model="ddsProperties" @update:modelValue="updateDDSProperties" />
</div>
<!-- 如果选中的组件有pins属性则显示引脚配置区域 -->
<CollapsibleSection v-if="hasPinsProperty" title="引脚配置" v-model:isExpanded="pinsSectionExpanded" status="default">
<div class="space-y-4 p-2">
<!-- 显示现有的pins -->
<div v-for="(pin, index) in componentPins" :key="index" class="pin-item p-2 border rounded-md bg-base-200">
<div class="font-medium mb-2">引脚 #{{ index + 1 }}</div>
<div class="grid grid-cols-2 gap-2">
<div class="form-control">
<label class="label">
<span class="label-text text-xs">ID</span>
</label>
<input type="text" v-model="componentPins[index].pinId" class="input input-bordered input-sm w-full"
placeholder="引脚ID" @change="updatePins" />
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-xs">约束条件</span>
</label>
<input type="text" v-model="componentPins[index].constraint" class="input input-bordered input-sm w-full"
placeholder="约束条件" @change="updatePins" />
</div>
</div>
</div>
</div>
</CollapsibleSection>
<CollapsibleSection title="组件功能" v-model:isExpanded="componentCapsExpanded" status="default" class="mt-4">
<div id="ComponentCapabilities" ref="ComponentCapabilities"></div>
<div v-if="!(componentData && componentData.type)" class="text-gray-400">
选择元件以查看其功能
</div>
<div v-else-if="!componentCaps?.hasChildNodes()" class="text-gray-400">
该组件没有提供特殊功能
</div>
</CollapsibleSection>
<!-- 未来可以在这里添加更多的分区 -->
<!-- 例如:
<CollapsibleSection
title="连线管理"
v-model:isExpanded="wireSectionExpanded"
status="default"
>
<div>连线管理内容</div>
</CollapsibleSection>
-->
</div>
</template>
<script setup lang="ts">
// 导入所需的类型和组件
import { type DiagramPart } from "@/components/LabCanvas/diagramManager"; // 图表部件类型定义
import { type PropertyConfig } from "@/components/equipments/componentConfig"; // 属性配置类型定义
import CollapsibleSection from "./CollapsibleSection.vue"; // 可折叠区域组件
import PropertyEditor from "./PropertyEditor.vue"; // 属性编辑器组件
import DDSPropertyEditor from "./equipments/DDSPropertyEditor.vue"; // DDS专用属性编辑器组件
import {
ref,
computed,
watch,
useTemplateRef,
} from "vue"; // Vue核心API
// 引脚接口定义
interface Pin {
pinId: string; // 引脚ID
constraint: string; // 引脚约束条件
x: number; // 引脚X坐标位置
y: number; // 引脚Y坐标位置
}
// 定义组件的输入属性
const props = defineProps<{
componentData: DiagramPart | null; // 当前选中的组件数据
componentConfig: { props: PropertyConfig[] } | null; // 组件的配置信息
}>();
// 控制各个属性分区的展开状态
const propertySectionExpanded = ref(false); // 基本属性区域默认展开
const pinsSectionExpanded = ref(false); // 引脚配置区域默认折叠
const componentCapsExpanded = ref(true); // 组件功能区域默认展开
const wireSectionExpanded = ref(false); // 连线管理区域默认折叠
const componentCaps = useTemplateRef("ComponentCapabilities");
// DDS组件特殊属性的本地状态
const ddsProperties = ref({
frequency: 1000, // 频率默认1000Hz
phase: 0, // 相位默认0度
waveform: "sine", // 波形类型,默认正弦波
customWaveformPoints: [], // 自定义波形点数据,默认空数组
});
// 本地维护一个pins数组副本用于编辑操作
const componentPins = ref<Pin[]>([]);
// 监听组件pins属性变化更新本地pins数据
watch(
() => props.componentData?.attrs?.pins,
(newPins) => {
if (newPins) {
// 深拷贝以避免直接修改原始数据
componentPins.value = JSON.parse(JSON.stringify(newPins));
} else {
componentPins.value = [];
}
},
{ deep: true, immediate: true }, // 深度监听并立即执行
);
// 监听DDS组件数据变化更新特殊属性
watch(
() => props.componentData?.attrs,
(newAttrs) => {
if (newAttrs && isDDSComponent.value) {
// 从组件属性中提取DDS特有属性
ddsProperties.value = {
frequency: newAttrs.frequency || 1000,
phase: newAttrs.phase || 0,
waveform: newAttrs.waveform || "sine",
customWaveformPoints: newAttrs.customWaveformPoints || [],
};
}
},
{ deep: true, immediate: true }, // 深度监听并立即执行
);
// 计算属性检查组件是否有pins属性
const hasPinsProperty = computed(() => {
if (!props.componentData || !props.componentData.attrs) {
return false;
}
// 方法1检查配置中是否有pins属性
if (props.componentConfig && props.componentConfig.props) {
return props.componentConfig.props.some(
(prop) => prop.name === "pins" && prop.isArrayType,
);
}
// 方法2直接检查attrs中是否有pins属性
return "pins" in props.componentData.attrs;
});
// 计算属性检查组件是否为DDS组件
const isDDSComponent = computed(() => {
return props.componentData?.type === "DDS";
});
// 定义向父组件发送的事件
const emit = defineEmits<{
// 更新嵌套属性(如数组或对象中的属性)
(e: "updateProp", componentId: string, propName: string, value: any): void;
// 更新直接属性
(
e: "updateDirectProp",
componentId: string,
propName: string,
value: any,
): void;
}>();
// 更新pins属性的函数
function updatePins() {
if (props.componentData && props.componentData.id) {
// 将编辑后的pins数据发送给父组件
emit("updateProp", props.componentData.id, "pins", componentPins.value);
}
}
// 更新DDS特殊属性的函数
function updateDDSProperties(newProperties: any) {
// 更新本地状态
ddsProperties.value = newProperties;
if (props.componentData && props.componentData.id) {
// 将各个属性单独更新,而不是作为一个整体更新
emit(
"updateProp",
props.componentData.id,
"frequency",
newProperties.frequency,
);
emit("updateProp", props.componentData.id, "phase", newProperties.phase);
emit(
"updateProp",
props.componentData.id,
"waveform",
newProperties.waveform,
);
emit(
"updateProp",
props.componentData.id,
"customWaveformPoints",
newProperties.customWaveformPoints,
);
}
}
</script>
<style scoped>
.property-panel {
width: 100%;
height: 100%;
overflow-y: auto;
}
.pin-item {
transition: all 0.2s ease;
}
.pin-item:hover {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
</style>