feat: add project view

This commit is contained in:
alivender
2025-04-25 16:11:53 +08:00
parent 4465091db3
commit cfd8769e9b
6 changed files with 589 additions and 3 deletions

137
src/views/ProjectView.vue Normal file
View File

@@ -0,0 +1,137 @@
<template>
<div class="h-screen w-screen flex flex-col">
<!-- 顶部工具栏 -->
<div class="flex items-center p-2 border-b border-base-300 bg-base-100">
<h2 class="text-xl font-bold mr-auto">FPGA 工程界面</h2>
<button class="btn btn-circle btn-primary" @click="openComponentsMenu">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div>
<div class="flex flex-1 overflow-hidden">
<!-- 左侧图形化区域 -->
<DiagramCanvas
ref="diagramCanvas"
:initialComponents="components"
@component-selected="handleComponentSelected"
@component-moved="handleComponentMoved"
/>
<!-- 右侧编辑区域 -->
<div class="w-[40%] bg-base-100 border-l flex flex-col p-4">
<h3 class="text-lg font-bold mb-4">属性编辑器</h3>
<div v-if="!selectedComponent" class="text-gray-400">选择元器件以编辑属性</div>
<div v-else>
<div class="mb-2">编辑元器件: {{ getComponentName(selectedComponent) }}</div>
<!-- 这里可以添加元器件的属性编辑表单 -->
</div>
</div>
</div>
<!-- 元器件选择菜单 -->
<div v-if="showComponentsMenu" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50" @click.self="showComponentsMenu = false">
<div class="bg-base-100 p-4 rounded-lg shadow-xl max-w-3xl max-h-[80vh] overflow-auto">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">选择元器件</h3>
<button class="btn btn-ghost btn-sm" @click="showComponentsMenu = false">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div class="grid grid-cols-2 md:grid-cols-3 gap-4">
<div v-for="(component, index) in availableComponents" :key="index"
class="border p-4 rounded-lg flex flex-col items-center hover:bg-base-200 cursor-pointer"
@click="addComponent(component)">
<div class="flex-1 flex items-center justify-center p-2">
<component :is="component.type" style="transform: scale(0.5);"></component>
</div>
<div class="mt-2 text-center">{{ component.name }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
// 引入wokwi-elements和组件
import "@wokwi/elements";
import { ref, reactive } from 'vue';
import DiagramCanvas from '@/components/DiagramCanvas.vue';
// 元器件管理
const showComponentsMenu = ref(false);
interface ComponentItem {
id: string;
type: string;
name: string;
x: number;
y: number;
}
const components = ref<ComponentItem[]>([]);
const selectedComponent = ref<string | null>(null);
const selectedComponentData = ref<ComponentItem | null>(null);
const diagramCanvas = ref(null);
// 可用元器件列表
const availableComponents = [
{ type: 'wokwi-led', name: 'LED灯' },
{ type: 'wokwi-resistor', name: '电阻' },
{ type: 'wokwi-pushbutton', name: '按钮' },
{ type: 'wokwi-7segment', name: '7段数码管' },
{ type: 'wokwi-arduino-uno', name: 'Arduino Uno' },
{ type: 'wokwi-servo', name: '舵机' },
{ type: 'wokwi-lcd1602', name: 'LCD显示屏' },
{ type: 'wokwi-dht22', name: '温湿度传感器' },
{ type: 'wokwi-buzzer', name: '蜂鸣器' }
];
// 打开元器件选择菜单
function openComponentsMenu() {
showComponentsMenu.value = true;
}
// 添加新元器件
function addComponent(componentTemplate) {
const newComponent = {
id: `component-${Date.now()}`,
type: componentTemplate.type,
name: componentTemplate.name,
x: 100,
y: 100
};
components.value.push(newComponent);
// 由于我们使用的是响应式数据绑定,不需要再次调用 diagramCanvas 的 addComponent
// DiagramCanvas 组件通过 :initialComponents="components" 已经接收到更新
showComponentsMenu.value = false;
}
// 处理组件选中事件
function handleComponentSelected(component) {
selectedComponent.value = component ? component.id : null;
selectedComponentData.value = component;
}
// 处理组件移动事件
function handleComponentMoved(moveData) {
const component = components.value.find(c => c.id === moveData.id);
if (component) {
component.x = moveData.x;
component.y = moveData.y;
}
}
// 获取组件名称
function getComponentName(componentId) {
const component = components.value.find(c => c.id === componentId);
return component ? component.name : '';
}
</script>