feat: Refactor code structure for improved readability and maintainability

This commit is contained in:
alivender
2025-05-09 19:28:43 +08:00
parent d4b34bd6d4
commit 6a786c1519
17 changed files with 2913 additions and 583 deletions

View File

@@ -0,0 +1,195 @@
<template>
<div class="property-editor">
<div v-if="!componentData" class="text-gray-400">选择元器件以编辑属性</div>
<div v-else>
<div class="mb-4 pb-4 border-b border-base-300">
<h4 class="font-semibold text-lg mb-1">{{ componentData?.type }}</h4>
<p class="text-xs text-base-content opacity-70">ID: {{ componentData?.id }}</p>
<p class="text-xs text-base-content opacity-70">类型: {{ componentData?.type }}</p>
</div>
<!-- 通用属性部分 -->
<CollapsibleSection
title="通用属性"
v-model:isExpanded="generalPropsExpanded"
status="default"
>
<div class="space-y-4">
<div v-for="prop in getGeneralProps()" :key="prop.name" class="form-control">
<label class="label">
<span class="label-text">{{ prop.label || prop.name }}</span>
</label>
<!-- 根据 prop 类型选择输入控件 -->
<input
v-if="prop.type === 'number'"
type="number"
:placeholder="prop.label || prop.name"
class="input input-bordered input-sm w-full"
:value="getPropValue(componentData, prop.name)"
:disabled="prop.isReadOnly"
:min="prop.min"
:max="prop.max"
:step="prop.step"
@input="updateDirectProp(componentData.id, prop.name, parseFloat(($event.target as HTMLInputElement).value) || prop.default)"
/>
<input
v-else-if="prop.type === 'string'"
type="text"
:placeholder="prop.label || prop.name"
class="input input-bordered input-sm w-full"
:value="getPropValue(componentData, prop.name)"
:disabled="prop.isReadOnly"
@input="updateDirectProp(componentData.id, prop.name, ($event.target as HTMLInputElement).value)"
/>
<div v-else-if="prop.type === 'boolean'" class="flex items-center">
<input
type="checkbox"
class="checkbox checkbox-sm mr-2"
:checked="getPropValue(componentData, prop.name)"
:disabled="prop.isReadOnly"
@change="updateDirectProp(componentData.id, prop.name, ($event.target as HTMLInputElement).checked)"
/>
<span>{{ prop.label || prop.name }}</span>
</div>
</div>
</div>
</CollapsibleSection>
<!-- 组件特有属性部分 -->
<CollapsibleSection
title="组件特有属性"
v-model:isExpanded="componentPropsExpanded"
status="default"
class="mt-4"
>
<div v-if="componentConfig && componentConfig.props" class="space-y-4">
<div v-for="prop in getComponentProps()" :key="prop.name" class="form-control">
<label class="label">
<span class="label-text">{{ prop.label || prop.name }}</span>
</label>
<!-- 根据 prop 类型选择输入控件 -->
<input
v-if="prop.type === 'string'"
type="text"
:placeholder="prop.label || prop.name"
class="input input-bordered input-sm w-full"
:value="componentData?.attrs?.[prop.name]"
:disabled="prop.isReadOnly"
@input="updateProp(componentData.id, prop.name, ($event.target as HTMLInputElement).value)"
/>
<input
v-else-if="prop.type === 'number'"
type="number"
:placeholder="prop.label || prop.name"
class="input input-bordered input-sm w-full"
:value="componentData?.attrs?.[prop.name]"
:disabled="prop.isReadOnly"
:min="prop.min"
:max="prop.max"
:step="prop.step"
@input="updateProp(componentData.id, prop.name, parseFloat(($event.target as HTMLInputElement).value) || prop.default)"
/>
<div v-else-if="prop.type === 'boolean'" class="flex items-center">
<input
type="checkbox"
class="checkbox checkbox-sm mr-2"
:checked="componentData?.attrs?.[prop.name]"
:disabled="prop.isReadOnly"
@change="updateProp(componentData.id, prop.name, ($event.target as HTMLInputElement).checked)"
/>
<span>{{ prop.label || prop.name }}</span>
</div>
<select
v-else-if="prop.type === 'select' && prop.options"
class="select select-bordered select-sm w-full"
:value="componentData?.attrs?.[prop.name]"
:disabled="prop.isReadOnly"
@change="(event) => {
const selectElement = event.target as HTMLSelectElement;
const value = selectElement.value;
if (componentData) {
updateProp(componentData.id, prop.name, value);
}
}"
>
<option v-for="option in prop.options" :key="option.value" :value="option.value">
{{ option.label }}
</option>
</select>
<p v-else class="text-xs text-warning">不支持的属性类型: {{ prop.type }}</p>
</div>
</div>
<div v-else-if="componentData && !componentConfig" class="text-base-content opacity-70 text-sm">
正在加载组件配置...
</div>
<div v-else-if="componentData && componentConfig && getComponentProps().length === 0" class="text-base-content opacity-70 text-sm">
此组件没有特有属性可配置
</div>
</CollapsibleSection>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import CollapsibleSection from './CollapsibleSection.vue';
import { type DiagramPart } from '@/components/diagramManager';
import {
type PropertyConfig,
getPropValue
} from '@/components/equipments/componentConfig';
// 定义属性
const props = defineProps<{
componentData: DiagramPart | null;
componentConfig: { props: PropertyConfig[] } | null;
}>();
// 定义事件
const emit = defineEmits<{
(e: 'updateProp', componentId: string, propName: string, value: any): void;
(e: 'updateDirectProp', componentId: string, propName: string, value: any): void;
}>();
// 控制折叠面板状态
const generalPropsExpanded = ref(true);
const componentPropsExpanded = ref(true);
// 更新组件属性方法
function updateProp(componentId: string, propName: string, value: any) {
emit('updateProp', componentId, propName, value);
}
// 更新组件的直接属性
function updateDirectProp(componentId: string, propName: string, value: any) {
emit('updateDirectProp', componentId, propName, value);
}
// 获取通用属性(直接属性)
function getGeneralProps(): PropertyConfig[] {
return props.componentConfig?.props.filter(p => p.isDirectProp && p.name !== 'pins') || [];
}
// 获取组件特有属性(非直接属性)
function getComponentProps(): PropertyConfig[] {
return props.componentConfig?.props.filter(p => !p.isDirectProp && p.name !== 'pins') || [];
}
</script>
<style scoped>
.property-editor {
width: 100%;
}
/* 添加一些垂直间距 */
.form-control {
margin-bottom: 0.5rem;
}
/* 针对黑暗模式的文本颜色调整 */
:deep(.label-text) {
color: hsl(var(--bc));
opacity: 0.9;
}
</style>