refactor: try to rewrite component manager

This commit is contained in:
2025-07-02 21:16:18 +08:00
parent d18cf82813
commit 14d8499f77
13 changed files with 4093 additions and 79 deletions

View File

@@ -0,0 +1,316 @@
// LabCanvas组件管理系统 - 统一导出
// 基于VueUse重构的Konva组件管理系统
// 类型定义
export type {
KonvaComponent,
KonvaComponentBase,
ComponentTemplate,
ComponentProps,
ComponentGroup,
SelectionState,
HistoryRecord,
ComponentEvents,
CanvasConfig,
ProjectData
} from './types/KonvaComponent'
// 核心管理器
export { useKonvaComponentManager } from './composables/useKonvaComponentManager'
export type { UseKonvaComponentManagerOptions } from './composables/useKonvaComponentManager'
// 模板管理器
export { useKonvaTemplateManager } from './composables/useKonvaTemplateManager'
export type {
TemplateData,
UseKonvaTemplateManagerOptions
} from './composables/useKonvaTemplateManager'
// 渲染器
export { useKonvaRenderer } from './composables/useKonvaRenderer'
export type { UseKonvaRendererOptions } from './composables/useKonvaRenderer'
// 组件
export { default as LabCanvasNew } from './LabCanvasNew.vue'
export { default as LabComponentsDrawerNew } from './LabComponentsDrawerNew.vue'
export { default as ExampleUsage } from '../../views/TestView.vue'
// 导入需要的类型
import type { ProjectData, ComponentTemplate, CanvasConfig } from './types/KonvaComponent'
// 工具函数
export const KonvaLabUtils = {
/**
* 生成唯一ID
*/
generateId: (): string => {
return `component-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
},
/**
* 计算矩形的边界框(考虑旋转和缩放)
*/
calculateBoundingBox: (
width: number,
height: number,
rotation: number = 0,
scaleX: number = 1,
scaleY: number = 1,
padding: number = 0
) => {
const scaledWidth = width * scaleX
const scaledHeight = height * scaleY
const radians = (rotation * Math.PI) / 180
const cos = Math.cos(radians)
const sin = Math.sin(radians)
const corners = [
{ x: 0, y: 0 },
{ x: scaledWidth, y: 0 },
{ x: scaledWidth, y: scaledHeight },
{ x: 0, y: scaledHeight },
].map((point) => ({
x: point.x * cos - point.y * sin,
y: point.x * sin + point.y * cos,
}))
const minX = Math.min(...corners.map((p) => p.x))
const maxX = Math.max(...corners.map((p) => p.x))
const minY = Math.min(...corners.map((p) => p.y))
const maxY = Math.max(...corners.map((p) => p.y))
return {
x: minX - padding,
y: minY - padding,
width: maxX - minX + padding * 2,
height: maxY - minY + padding * 2,
}
},
/**
* 检查两个矩形是否相交
*/
rectsIntersect: (
rect1: { x: number; y: number; width: number; height: number },
rect2: { x: number; y: number; width: number; height: number }
): boolean => {
return (
rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.y + rect1.height > rect2.y
)
},
/**
* 计算两点之间的距离
*/
distance: (
point1: { x: number; y: number },
point2: { x: number; y: number }
): number => {
const dx = point2.x - point1.x
const dy = point2.y - point1.y
return Math.sqrt(dx * dx + dy * dy)
},
/**
* 格式化项目数据用于导出
*/
formatProjectForExport: (projectData: ProjectData) => {
return {
...projectData,
exportedAt: new Date().toISOString(),
components: projectData.components.map((comp: any) => ({
...comp,
// 移除运行时状态
isSelected: false,
isHovered: false,
konvaNodeId: undefined
}))
}
},
/**
* 验证项目数据格式
*/
validateProjectData: (data: any): { isValid: boolean; errors: string[] } => {
const errors: string[] = []
if (!data.version) errors.push('缺少版本信息')
if (!data.canvas) errors.push('缺少画布配置')
if (!Array.isArray(data.components)) errors.push('组件数据格式错误')
// 验证组件
if (Array.isArray(data.components)) {
data.components.forEach((comp: any, index: number) => {
if (!comp.id) errors.push(`组件 ${index} 缺少ID`)
if (!comp.type) errors.push(`组件 ${index} 缺少类型`)
if (typeof comp.x !== 'number') errors.push(`组件 ${index} X坐标无效`)
if (typeof comp.y !== 'number') errors.push(`组件 ${index} Y坐标无效`)
})
}
return {
isValid: errors.length === 0,
errors
}
}
}
// 预定义的组件模板
export const PredefinedTemplates: ComponentTemplate[] = [
{
type: "MechanicalButton",
name: "机械按钮",
category: "basic",
defaultProps: {
size: "medium",
color: "blue",
pressed: false
},
previewSize: 0.4
},
{
type: "Switch",
name: "开关",
category: "basic",
defaultProps: {
state: false,
style: "toggle"
},
previewSize: 0.35
},
{
type: "Pin",
name: "引脚",
category: "basic",
defaultProps: {
type: "input",
label: "Pin"
},
previewSize: 0.8
},
{
type: "SMT_LED",
name: "贴片LED",
category: "basic",
defaultProps: {
color: "red",
state: false,
brightness: 1
},
previewSize: 0.7
},
{
type: "SevenSegmentDisplay",
name: "数码管",
category: "advanced",
defaultProps: {
digits: 4,
value: "0000",
color: "red"
},
previewSize: 0.4
},
{
type: "HDMI",
name: "HDMI接口",
category: "advanced",
defaultProps: {
version: "2.0",
connected: false
},
previewSize: 0.5
},
{
type: "DDR",
name: "DDR内存",
category: "advanced",
defaultProps: {
type: "DDR4",
capacity: "8GB",
speed: "3200MHz"
},
previewSize: 0.5
},
{
type: "ETH",
name: "以太网接口",
category: "advanced",
defaultProps: {
speed: "1000Mbps",
connected: false
},
previewSize: 0.5
},
{
type: "SD",
name: "SD卡插槽",
category: "basic",
defaultProps: {
cardInserted: false,
type: "microSD"
},
previewSize: 0.6
},
{
type: "SFP",
name: "SFP光纤模块",
category: "advanced",
defaultProps: {
type: "SFP+",
speed: "10Gbps",
connected: false
},
previewSize: 0.4
},
{
type: "SMA",
name: "SMA连接器",
category: "basic",
defaultProps: {
type: "female",
impedance: "50ohm"
},
previewSize: 0.7
},
{
type: "MotherBoard",
name: "主板",
category: "template",
defaultProps: {
model: "Generic",
size: "ATX"
},
previewSize: 0.13
},
{
type: "DDS",
name: "信号发生器",
category: "virtual",
defaultProps: {
frequency: 1000,
amplitude: 1.0,
waveform: "sine",
enabled: false
},
previewSize: 0.3
}
]
// 默认配置
export const DefaultCanvasConfig: CanvasConfig = {
width: window.innerWidth,
height: window.innerHeight,
scale: 1,
offsetX: 0,
offsetY: 0,
gridSize: 20,
showGrid: true,
snapToGrid: false
}
// 版本信息
export const VERSION = '1.0.0'