Compare commits

..

No commits in common. "46621fdb40732db8e9bcc833a9c12bb1a4eac85b" and "3883cd8304b2cd888818ff4c25eb2d8149e99cb9" have entirely different histories.

2 changed files with 71 additions and 58 deletions

View File

@ -1,8 +1,7 @@
<template> <template>
<div class="flex-1 h-full w-full bg-base-200 relative overflow-hidden diagram-container" ref="canvasContainer" <div class="flex-1 h-full w-full bg-base-200 relative overflow-hidden diagram-container" ref="canvasContainer"
@mousedown="handleCanvasMouseDown" @mousedown.middle.prevent="startMiddleDrag" @wheel.prevent="onZoom" @mousedown="handleCanvasMouseDown" @mousedown.middle.prevent="startMiddleDrag" @wheel.prevent="onZoom"
@contextmenu.prevent="handleContextMenu"> @contextmenu.prevent="handleContextMenu"> <!-- 工具栏 -->
<!-- 工具栏 -->
<div class="absolute top-2 right-2 flex gap-2 z-30"> <div class="absolute top-2 right-2 flex gap-2 z-30">
<button class="btn btn-sm btn-primary" @click="openDiagramFileSelector"> <button class="btn btn-sm btn-primary" @click="openDiagramFileSelector">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24"
@ -33,7 +32,7 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /> d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg> </svg>
{{ props.showDocPanel ? "属性面板" : "文档" }} {{ props.showDocPanel ? '属性面板' : '文档' }}
</button> </button>
</div> </div>
@ -65,23 +64,16 @@
'component-disabled': !component.isOn, 'component-disabled': !component.isOn,
'component-hidepins': component.hidepins, 'component-hidepins': component.hidepins,
}" :style="{ }" :style="{
top: component.y + 'px', top: component.y + 'px',
left: component.x + 'px', left: component.x + 'px',
zIndex: component.index ?? 0, zIndex: component.index ?? 0,
transform: component.rotate transform: component.rotate
? `rotate(${component.rotate}deg)` ? `rotate(${component.rotate}deg)`
: 'none', : 'none',
opacity: component.isOn ? 1 : 0.6, opacity: component.isOn ? 1 : 0.6,
display: 'block', display: 'block',
}" @mousedown.left.stop="startComponentDrag($event, component)" @mouseover=" }" @mousedown.left.stop="startComponentDrag($event, component)" @mouseover="hoveredComponent = component.id"
(event) => { @mouseleave="hoveredComponent = null">
hoveredComponent = component.id;
}
" @mouseleave="
(event) => {
hoveredComponent = null;
}
">
<!-- 动态渲染组件 --> <!-- 动态渲染组件 -->
<component :is="getComponentDefinition(component.type)" v-if="props.componentModules[component.type]" <component :is="getComponentDefinition(component.type)" v-if="props.componentModules[component.type]"
v-bind="prepareComponentProps(component.attrs || {}, component.id)" @update:bindKey=" v-bind="prepareComponentProps(component.attrs || {}, component.id)" @update:bindKey="
@ -106,10 +98,10 @@
<!-- 通知组件 --> <!-- 通知组件 -->
<div v-if="showNotification" class="toast toast-top toast-center z-50 w-fit-content"> <div v-if="showNotification" class="toast toast-top toast-center z-50 w-fit-content">
<div :class="`alert ${notificationType === 'success' <div :class="`alert ${notificationType === 'success'
? 'alert-success' ? 'alert-success'
: notificationType === 'error' : notificationType === 'error'
? 'alert-error' ? 'alert-error'
: 'alert-info' : 'alert-info'
}`"> }`">
<span>{{ notificationMessage }}</span> <span>{{ notificationMessage }}</span>
</div> </div>
@ -181,7 +173,7 @@ const emit = defineEmits([
// //
const props = defineProps<{ const props = defineProps<{
componentModules: Record<string, any>; componentModules: Record<string, any>;
showDocPanel?: boolean; // showDocPanel?: boolean; //
}>(); }>();
// --- --- // --- ---

View File

@ -2,34 +2,60 @@
<div class="h-screen flex flex-col overflow-hidden"> <div class="h-screen flex flex-col overflow-hidden">
<div class="flex flex-1 overflow-hidden relative"> <div class="flex flex-1 overflow-hidden relative">
<!-- 左侧图形化区域 --> <!-- 左侧图形化区域 -->
<div class="relative bg-base-200 overflow-hidden h-full" :style="{ width: leftPanelWidth + '%' }"> <div
<DiagramCanvas ref="diagramCanvas" :componentModules="componentModules" :showDocPanel="showDocPanel" class="relative bg-base-200 overflow-hidden h-full"
@component-selected="handleComponentSelected" @component-moved="handleComponentMoved" :style="{ width: leftPanelWidth + '%' }"
@component-delete="handleComponentDelete" @wire-created="handleWireCreated" @wire-deleted="handleWireDeleted" >
@diagram-updated="handleDiagramUpdated" @open-components="openComponentsMenu" <DiagramCanvas
@load-component-module="handleLoadComponentModule" @toggle-doc-panel="toggleDocPanel" /> ref="diagramCanvas"
:componentModules="componentModules"
:showDocPanel="showDocPanel"
@component-selected="handleComponentSelected"
@component-moved="handleComponentMoved"
@component-delete="handleComponentDelete"
@wire-created="handleWireCreated"
@wire-deleted="handleWireDeleted"
@diagram-updated="handleDiagramUpdated"
@open-components="openComponentsMenu"
@load-component-module="handleLoadComponentModule"
@toggle-doc-panel="toggleDocPanel"
/>
</div> </div>
<!-- 拖拽分割线 --> <!-- 拖拽分割线 -->
<div <div
class="resizer bg-base-100 hover:bg-primary hover:opacity-70 active:bg-primary active:opacity-90 transition-colors" class="resizer bg-base-100 hover:bg-primary hover:opacity-70 active:bg-primary active:opacity-90 transition-colors"
@mousedown="startResize"></div> @mousedown="startResize"
<!-- 右侧编辑区域 --> ></div> <!-- 右侧编辑区域 -->
<div class="bg-base-200 h-full overflow-hidden flex flex-col" :style="{ width: 100 - leftPanelWidth + '%' }"> <div
class="bg-base-200 h-full overflow-hidden flex flex-col"
:style="{ width: 100 - leftPanelWidth + '%' }"
>
<div class="overflow-y-auto flex-1"> <div class="overflow-y-auto flex-1">
<!-- 使用条件渲染显示不同的面板 --> <!-- 使用条件渲染显示不同的面板 -->
<PropertyPanel v-show="!showDocPanel" :componentData="selectedComponentData" <PropertyPanel
:componentConfig="selectedComponentConfig" @updateProp="updateComponentProp" v-if="!showDocPanel"
@updateDirectProp="updateComponentDirectProp" /> :componentData="selectedComponentData"
<div v-show="showDocPanel" class="doc-panel overflow-y-auto h-full"> :componentConfig="selectedComponentConfig"
@updateProp="updateComponentProp"
@updateDirectProp="updateComponentDirectProp"
/> <div
v-else
class="doc-panel overflow-y-auto h-full"
>
<MarkdownRenderer :content="documentContent" /> <MarkdownRenderer :content="documentContent" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- 元器件选择组件 --> <!-- 元器件选择组件 -->
<ComponentSelector :open="showComponentsMenu" @update:open="showComponentsMenu = $event" <ComponentSelector
@add-component="handleAddComponent" @add-template="handleAddTemplate" @close="showComponentsMenu = false" /> :open="showComponentsMenu"
@update:open="showComponentsMenu = $event"
@add-component="handleAddComponent"
@add-template="handleAddTemplate"
@close="showComponentsMenu = false"
/>
</div> </div>
</template> </template>
@ -54,7 +80,7 @@ const showDocPanel = ref(false);
const documentContent = ref(""); const documentContent = ref("");
// //
import { useRoute } from "vue-router"; import { useRoute } from 'vue-router';
const route = useRoute(); const route = useRoute();
// //
@ -71,14 +97,14 @@ async function toggleDocPanel() {
async function loadDocumentContent() { async function loadDocumentContent() {
try { try {
// ID // ID
const tutorialId = (route.query.tutorial as string) || "02"; // 02 const tutorialId = route.query.tutorial as string || '02'; // 02
// //
let docPath = `/doc/${tutorialId}/doc.md`; let docPath = `/doc/${tutorialId}/doc.md`;
// 线 02_key // 线 02_key
// 使 // 使
if (!tutorialId.includes("_")) { if (!tutorialId.includes('_')) {
docPath = `/doc/${tutorialId}/doc.md`; docPath = `/doc/${tutorialId}/doc.md`;
} }
@ -89,14 +115,11 @@ async function loadDocumentContent() {
} }
// //
documentContent.value = (await response.text()).replace( documentContent.value = (await response.text())
/.\/images/gi, .replace(/.\/images/gi, `/doc/${tutorialId}/images`);
`/doc/${tutorialId}/images`,
);
} catch (error) { } catch (error) {
console.error("加载文档失败:", error); console.error('加载文档失败:', error);
documentContent.value = "# 文档加载失败\n\n无法加载请求的文档。"; documentContent.value = '# 文档加载失败\n\n无法加载请求的文档。'; }
}
} }
// //
@ -820,10 +843,8 @@ body {
padding: 1.5rem; padding: 1.5rem;
max-width: 100%; max-width: 100%;
margin: 0; margin: 0;
background-color: transparent; background-color: transparent; /* 使用透明背景 */
/* 使用透明背景 */ border: none; /* 确保没有边框 */
border: none;
/* 确保没有边框 */
} }
/* 文档切换按钮样式 */ /* 文档切换按钮样式 */