// componentConfig.ts 提供通用的组件配置功能 import type { DiagramPart } from '../diagramManager'; // 属性配置接口 export interface PropertyConfig { name: string; type: string; label: string; default: any; options?: Array<{ value: any; label: string }>; // 添加 options 字段用于 select 类型 isDirectProp?: boolean; // 标记是否为直接属性 isReadOnly?: boolean; // 标记是否为只读属性 min?: number; // 用于数值类型的最小值 max?: number; // 用于数值类型的最大值 step?: number; // 用于数值类型的步长 isArrayType?: boolean; // 标记数组类型属性 } // 所有基础属性的标签映射 const basePropertyLabels: Record = { 0: 'ID', 1: '组件类型', 2: '水平坐标', 3: '垂直坐标', 4: '角度', 5: '分组', 6: '锁定位置', 7: '隐藏引脚', 8: '激活状态', 9: '层级' }; // 只读属性索引列表 const readOnlyPropertyIndexes = [0, 1]; // 移除了isOn对应的索引8 /** * 从组件数据中自动生成属性配置 * @param componentData 组件数据 * @returns 属性配置数组 */ export function generatePropertyConfigs(componentData: DiagramPart): PropertyConfig[] { const configs: PropertyConfig[] = []; // 获取基础属性(排除attrs) const directPropKeys = Object.keys(componentData).filter(key => key !== 'attrs'); // 为每个直接属性创建配置 directPropKeys.forEach((propName, index) => { let propValue: any = (componentData as any)[propName]; let propType = typeof propValue; // 对于undefined的属性,提供默认值 if (propValue === undefined) { if (propType === 'boolean') propValue = false; else if (propType === 'number') propValue = 0; else propValue = ''; } // 创建配置对象 const propConfig: PropertyConfig = { name: propName, label: basePropertyLabels[index] || propName, type: propType as 'string' | 'number' | 'boolean' | 'select', default: propValue, isDirectProp: true, isReadOnly: readOnlyPropertyIndexes.includes(index) }; // 数值类型的特殊设置 if (propType === 'number') { if (index === 9) { // 层级 propConfig.min = 0; propConfig.max = 100; } else if (index === 4) { // 角度 propConfig.min = 0; propConfig.max = 360; } propConfig.step = 1; } configs.push(propConfig); }); return configs; } /** * 从组件模块的getDefaultProps方法生成属性配置 * @param defaultProps 默认属性对象 * @returns 属性配置数组 */ export function generatePropsFromDefault(defaultProps: Record): PropertyConfig[] { const configs: PropertyConfig[] = []; for (const [propName, propValue] of Object.entries(defaultProps)) { // 特殊处理pins属性 if (propName === 'pins') { const propConfig: PropertyConfig = { name: propName, label: 'Pins', default: propValue, type: 'array', isArrayType: true }; configs.push(propConfig); continue; } // 根据属性类型创建配置 let propType = typeof propValue; let propConfig: PropertyConfig = { name: propName, label: propName.charAt(0).toUpperCase() + propName.slice(1), // 首字母大写作为标签 default: propValue, type: propType as 'string' | 'number' | 'boolean' | 'select' }; // 根据值类型设置表单控件类型 if (propType === 'string') { propConfig.type = 'string'; } else if (propType === 'number') { propConfig.type = 'number'; propConfig.min = 0; propConfig.max = 100; propConfig.step = 0.1; } else if (propType === 'boolean') { propConfig.type = 'boolean'; } else if (propType === 'object' && propValue !== null && propValue.hasOwnProperty('options')) { // 如果是含有options的对象,认为它是select类型 propConfig.type = 'select'; propConfig.options = (propValue as any).options; } configs.push(propConfig); } return configs; } /** * 从属性对象生成配置 * @param attrs 属性对象 * @returns 属性配置数组 */ export function generatePropsFromAttrs(attrs: Record): PropertyConfig[] { const configs: PropertyConfig[] = []; for (const [propName, propValue] of Object.entries(attrs)) { // 特殊处理pins属性 if (propName === 'pins') { const propConfig: PropertyConfig = { name: propName, label: 'Pins', default: propValue, type: 'array', isArrayType: true }; configs.push(propConfig); continue; } // 根据属性值类型创建配置 let propType = typeof propValue; let propConfig: PropertyConfig = { name: propName, label: propName.charAt(0).toUpperCase() + propName.slice(1), // 首字母大写作为标签 default: propValue || '', type: propType as 'string' | 'number' | 'boolean' | 'select' }; configs.push(propConfig); } return configs; } /** * 安全地从组件对象获取属性值 * @param component 组件对象 * @param propName 属性名 * @returns 属性值 */ export function getPropValue(component: DiagramPart, propName: string): any { if (!component) return undefined; return (component as any)[propName]; }