fix: Component awlays reset

This commit is contained in:
2025-05-17 17:32:16 +08:00
parent c7907b4253
commit 7aff4f3f02
7 changed files with 48 additions and 161 deletions

View File

@@ -44,11 +44,13 @@
</CollapsibleSection>
<CollapsibleSection title="组件功能" v-model:isExpanded="componentCapsExpanded" status="default" class="mt-4">
<div v-if="componentData && componentData.type">
<component v-if="capabilityComponent" :is="capabilityComponent" v-bind="componentData.attrs" />
<div v-else class="text-gray-400">该组件没有提供特殊功能</div>
<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>
<div v-else class="text-gray-400">选择元件以查看其功能</div>
</CollapsibleSection>
<!-- 未来可以在这里添加更多的分区 -->
@@ -71,9 +73,12 @@ 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, shallowRef, markRaw, h, createApp } from "vue"; // Vue核心API
import { isNull, isUndefined } from "lodash";
import type { JSX } from "vue/jsx-runtime";
import {
ref,
computed,
watch,
useTemplateRef,
} from "vue"; // Vue核心API
// 引脚接口定义
interface Pin {
@@ -95,6 +100,8 @@ const pinsSectionExpanded = ref(false); // 引脚配置区域默认折叠
const componentCapsExpanded = ref(true); // 组件功能区域默认展开
const wireSectionExpanded = ref(false); // 连线管理区域默认折叠
const componentCaps = useTemplateRef("ComponentCapabilities");
// DDS组件特殊属性的本地状态
const ddsProperties = ref({
frequency: 1000, // 频率默认1000Hz
@@ -207,129 +214,6 @@ function updateDDSProperties(newProperties: any) {
);
}
}
// 存储当前选中组件的能力组件
const capabilityComponent = shallowRef<JSX.Element>();
// 获取组件实例上暴露的方法
async function getExposedCapabilities(componentType: string) {
try {
// 动态导入组件
const module = await import(`./equipments/${componentType}.vue`);
const Component = module.default;
// 创建一个临时div作为挂载点
const tempDiv = document.createElement("div");
// 创建临时应用实例并挂载组件
let exposedMethods: any = null;
const app = createApp({
render() {
return h(Component, {
ref: (el: any) => {
if (el) {
// 获取组件实例暴露的方法
exposedMethods = el;
}
},
});
},
});
// 挂载应用
const vm = app.mount(tempDiv);
// 确保实例已创建并获取到暴露的方法
await new Promise((resolve) => setTimeout(resolve, 0));
// 检查是否有getCapabilities方法
if (
exposedMethods &&
typeof exposedMethods.getCapabilities === "function"
) {
// 获取能力组件定义
const CapabilityComponent = exposedMethods.getCapabilities();
// 卸载应用清理DOM
app.unmount();
tempDiv.remove();
return CapabilityComponent;
}
// 卸载应用清理DOM
app.unmount();
tempDiv.remove();
return null;
} catch (error) {
console.error(`获取${componentType}能力页面失败:`, error);
return null;
}
}
// 监听选中组件变化,动态加载能力组件
watch(
() => props.componentData,
async (newComponentData) => {
if (newComponentData && newComponentData.type) {
try {
// 首先尝试从实例中获取暴露的方法
let capsComponent = null;
if (!isUndefined( newComponentData.capsPage ) && !isNull(newComponentData.capsPage)) {
capsComponent = newComponentData.capsPage;
capabilityComponent.value = markRaw(capsComponent);
}
else
capsComponent = await getExposedCapabilities(newComponentData.type);
if (capsComponent) {
capabilityComponent.value = markRaw(capsComponent);
newComponentData.capsPage = capsComponent;
console.log(`已从实例加载${newComponentData.type}组件的能力页面`);
return;
}
// 如果实例方法获取失败,回退到模块导出方法
const module = await import(
`./equipments/${newComponentData.type}.vue`
);
if (
(module.default &&
typeof module.default.getCapabilities === "function") ||
typeof module.getCapabilities === "function"
) {
const getCapsFn =
typeof module.getCapabilities === "function"
? module.getCapabilities
: module.default.getCapabilities;
const moduleCapComponent = getCapsFn();
if (moduleCapComponent) {
capabilityComponent.value = markRaw(moduleCapComponent);
console.log(`已从模块加载${newComponentData.type}组件的能力页面`);
return;
}
}
capabilityComponent.value = null;
console.log(`组件${newComponentData.type}没有提供getCapabilities方法`);
} catch (error) {
console.error(`加载组件${newComponentData.type}能力页面失败:`, error);
capabilityComponent.value = null;
}
} else {
capabilityComponent.value = null;
}
},
{ immediate: true },
);
// 修改hasComponentCaps计算属性
const hasComponentCaps = computed(() => {
return capabilityComponent.value !== null;
});
</script>
<style scoped>