5 changed files with 287 additions and 0 deletions
@ -0,0 +1,146 @@ |
|||||
|
<template> |
||||
|
<div ref="containerRef" style="width: 100%"></div> |
||||
|
</template> |
||||
|
<script setup lang="ts"> |
||||
|
import { ref, onMounted } from 'vue'; |
||||
|
import { InternalEvent, Graph, Geometry, Cell } from '@maxgraph/core'; |
||||
|
import type { VertexParameterType } from './types/VertexParameterType'; |
||||
|
|
||||
|
const containerRef = ref(); |
||||
|
let graph: Graph | null = null; |
||||
|
let parent: Cell | null = null; |
||||
|
let entries: VertexParameterType[] = []; |
||||
|
const cellTitleMap = {}; |
||||
|
|
||||
|
class ComponentsGraph extends Graph { |
||||
|
getTooltipForCell(cell) { |
||||
|
return cellTitleMap[cell.id]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
InternalEvent.disableContextMenu(containerRef.value); |
||||
|
graph = new ComponentsGraph(containerRef.value); |
||||
|
graph.setPanning(true); |
||||
|
graph.setHtmlLabels(true); |
||||
|
graph.setTooltips(true); |
||||
|
parent = graph.getDefaultParent(); |
||||
|
addEntry({ |
||||
|
id: 'start', |
||||
|
title: '开始', |
||||
|
value: `<div class="w-full h-full align-middle text-center" style="width:47px">开始</div>`, |
||||
|
width: 50, |
||||
|
height: 50, |
||||
|
style: { shape: 'ellipse' }, |
||||
|
}); |
||||
|
addEntry({ |
||||
|
id: 'decide', |
||||
|
title: '条件判断', |
||||
|
value: `<div class="w-full h-full align-middle text-center" style="width:97px">条件判断</div>`, |
||||
|
width: 100, |
||||
|
height: 50, |
||||
|
style: { shape: 'rhombus' }, |
||||
|
}); |
||||
|
addEntry({ |
||||
|
id: 'commandSet', |
||||
|
title: '指令集', |
||||
|
value: `<div class="w-full h-full align-middle text-center" style="width:47px">指令集</div>`, |
||||
|
width: 50, |
||||
|
height: 50, |
||||
|
style: { shape: 'rectangle' }, |
||||
|
}); |
||||
|
addEntry({ |
||||
|
id: 'resource', |
||||
|
title: '资源', |
||||
|
value: `<div class="w-full h-full align-middle text-center" style="width:47px">资源</div>`, |
||||
|
width: 50, |
||||
|
height: 50, |
||||
|
style: { shape: 'rectangle' }, |
||||
|
}); |
||||
|
|
||||
|
addEntry({ |
||||
|
id: 'resource', |
||||
|
title: '指令资源', |
||||
|
value: `<div class="w-full h-full align-middle text-center" style="width:47px">指令资源</div>`, |
||||
|
width: 50, |
||||
|
height: 50, |
||||
|
style: { shape: 'rectangle' }, |
||||
|
}); |
||||
|
|
||||
|
addEntry({ |
||||
|
id: 'subModel', |
||||
|
title: '子模型', |
||||
|
value: `<div class="w-full h-full align-middle text-center" style="width:47px">子模型</div>`, |
||||
|
width: 50, |
||||
|
height: 50, |
||||
|
style: { shape: 'rectangle' }, |
||||
|
}); |
||||
|
|
||||
|
refresh(); |
||||
|
}); |
||||
|
|
||||
|
const addVertexWithDefaultStyle = (parameter: VertexParameterType): Cell | undefined => { |
||||
|
addVertex({ |
||||
|
id: parameter.id, |
||||
|
title: parameter.title, |
||||
|
value: parameter.value, |
||||
|
geometry: parameter.geometry, |
||||
|
style: { |
||||
|
//'rectangle' | 'ellipse' | 'doubleEllipse' | 'rhombus' | 'line' | 'image' | 'arrow' | 'arrowConnector' | 'label' | 'cylinder' | 'swimlane' | 'connector' | 'actor' | 'cloud' | 'triangle' | 'hexagon'; |
||||
|
shape: parameter.style?.shape, |
||||
|
verticalAlign: parameter.style?.verticalAlign || 'middle', |
||||
|
verticalLabelPosition: parameter.style?.verticalLabelPosition || 'middle', |
||||
|
align: parameter.style?.align || 'left', |
||||
|
fontSize: parameter.style?.fontSize || 12, |
||||
|
rounded: parameter.style?.rounded || true, |
||||
|
whiteSpace: parameter.style?.whiteSpace || 'wrap', |
||||
|
fillColor: parameter.style?.fillColor || '#F7F2E0', |
||||
|
strokeColor: parameter.style?.strokeColor || 'black', |
||||
|
}, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const addVertex = (parameter: VertexParameterType): Cell | undefined => { |
||||
|
const vertex = graph?.insertVertex({ |
||||
|
id: parameter.id, |
||||
|
parent: parent, |
||||
|
position: [parameter.geometry?.x || 0, parameter.geometry?.y || 0], |
||||
|
size: [parameter.geometry?.width || 10, parameter.geometry?.height || 10], |
||||
|
style: parameter.style, |
||||
|
value: parameter.value, |
||||
|
}); |
||||
|
cellTitleMap[parameter.id] = parameter.title; |
||||
|
return vertex; |
||||
|
}; |
||||
|
|
||||
|
const addEntry = (entry: VertexParameterType) => { |
||||
|
entry.geometry = new Geometry(0, 0, entry.width, entry.height); |
||||
|
entries.push(entry); |
||||
|
}; |
||||
|
|
||||
|
const refresh = () => { |
||||
|
let availableWidth = containerRef.value.clientWidth; |
||||
|
let currentWidth = 0; |
||||
|
for (const entry of entries) { |
||||
|
if (currentWidth + entry.width > availableWidth) { |
||||
|
entry.geometry.x = 0; |
||||
|
} else { |
||||
|
entry.geometry.x = currentWidth; |
||||
|
} |
||||
|
currentWidth += entry.width; |
||||
|
} |
||||
|
|
||||
|
graph.batchUpdate(() => { |
||||
|
for (const entry of entries) { |
||||
|
entry.geometry = new Geometry(70, 80, entry.width, entry.height); |
||||
|
} |
||||
|
for (const entry of entries) { |
||||
|
addVertexWithDefaultStyle(entry); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
defineExpose({ |
||||
|
addEntry, |
||||
|
}); |
||||
|
</script> |
@ -0,0 +1,53 @@ |
|||||
|
<template> |
||||
|
<div ref="containerRef"></div> |
||||
|
</template> |
||||
|
<script setup lang="ts"> |
||||
|
import { ref, onMounted } from 'vue'; |
||||
|
import { type CellStyle, Graph, InternalEvent } from '@maxgraph/core'; |
||||
|
|
||||
|
const containerRef = ref(); |
||||
|
|
||||
|
onMounted(() => { |
||||
|
//const container = <HTMLElement>document.getElementById('graph-container'); |
||||
|
// Disables the built-in context menu |
||||
|
InternalEvent.disableContextMenu(containerRef.value); |
||||
|
|
||||
|
const graph = new Graph(containerRef.value); |
||||
|
graph.setPanning(true); // Use mouse right button for panning |
||||
|
// Gets the default parent for inserting new cells. This |
||||
|
// is normally the first child of the root (ie. layer 0). |
||||
|
const parent = graph.getDefaultParent(); |
||||
|
|
||||
|
// Adds cells to the model in a single step |
||||
|
graph.batchUpdate(() => { |
||||
|
const vertex01 = graph.insertVertex({ |
||||
|
parent, |
||||
|
position: [10, 10], |
||||
|
size: [100, 100], |
||||
|
value: 'rectangle', |
||||
|
}); |
||||
|
const vertex02 = graph.insertVertex({ |
||||
|
parent, |
||||
|
position: [350, 90], |
||||
|
size: [50, 50], |
||||
|
style: { |
||||
|
fillColor: 'orange', |
||||
|
shape: 'ellipse', |
||||
|
verticalAlign: 'top', |
||||
|
verticalLabelPosition: 'bottom', |
||||
|
}, |
||||
|
value: 'ellipse', |
||||
|
}); |
||||
|
graph.insertEdge({ |
||||
|
parent, |
||||
|
source: vertex01, |
||||
|
target: vertex02, |
||||
|
value: 'edge', |
||||
|
style: { |
||||
|
edgeStyle: 'orthogonalEdgeStyle', |
||||
|
rounded: true, |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
</script> |
@ -0,0 +1,22 @@ |
|||||
|
<template> |
||||
|
<div style="height: 100%" class="px-1"> |
||||
|
<q-tabs model-value="currentSelectedTabRef" align="left" dense inline-label shrink outside-arrows mobile-arrows :breakpoint="0" no-caps> |
||||
|
<q-tab name="setting" label="设置" /> |
||||
|
<q-tab name="style" label="样式" /> |
||||
|
<q-tab name="text" label="文本" /> |
||||
|
<q-tab name="arrange" label="排列" /> |
||||
|
</q-tabs> |
||||
|
|
||||
|
<q-tab-panels v-model="currentSelectedTabRef" animated swipeable keep-alive style="height: calc(100% - 48px)"> |
||||
|
<q-tab-panel name="setting" class="px-0 pb-0" style="height: 100%"> </q-tab-panel> |
||||
|
<q-tab-panel name="style" class="px-0 pb-0" style="height: 100%"> </q-tab-panel> |
||||
|
<q-tab-panel name="text" class="px-0 pb-0" style="height: 100%"> </q-tab-panel> |
||||
|
<q-tab-panel name="arrange" class="px-0 pb-0" style="height: 100%"> </q-tab-panel> |
||||
|
</q-tab-panels> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script setup lang="ts"> |
||||
|
import { ref } from 'vue'; |
||||
|
|
||||
|
const currentSelectedTabRef = ref('style'); |
||||
|
</script> |
@ -0,0 +1,19 @@ |
|||||
|
<template> |
||||
|
<q-list class="rounded-borders"> |
||||
|
<q-expansion-item label="可用组件" default-opened switch-toggle-side header-style="padding-left:8px;padding-right:8px; " expand-icon-class="px-0"> |
||||
|
<Components></Components> |
||||
|
</q-expansion-item> |
||||
|
<q-expansion-item label="Account settings" switch-toggle-side header-style="padding-left:8px;padding-right:8px; " expand-icon-class="px-0"> |
||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quidem, eius reprehenderit eos corrupti commodi magni quaerat ex numquam, dolorum officiis modi |
||||
|
facere maiores architecto suscipit iste eveniet doloribus ullam aliquid. |
||||
|
</q-expansion-item> |
||||
|
</q-list> |
||||
|
</template> |
||||
|
<script setup lang="ts"> |
||||
|
import Components from './Components.vue'; |
||||
|
</script> |
||||
|
<style> |
||||
|
.q-item__section--avatar { |
||||
|
min-width: 36px !important; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,47 @@ |
|||||
|
<template> |
||||
|
<q-toolbar class="w-full border-b rounded-sm gap-x-1"> |
||||
|
<q-btn outline icon="bi-floppy" /> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn-dropdown label="100%" outline> |
||||
|
<q-list> |
||||
|
<q-item v-close-popup clickable> |
||||
|
<q-item-section> |
||||
|
<q-item-label>Reset View</q-item-label> |
||||
|
</q-item-section> |
||||
|
</q-item> |
||||
|
|
||||
|
<q-separator vertical /> |
||||
|
|
||||
|
<q-item v-close-popup clickable> |
||||
|
<q-item-section> |
||||
|
<q-item-label>25%</q-item-label> |
||||
|
</q-item-section> |
||||
|
</q-item> |
||||
|
|
||||
|
<q-item v-close-popup clickable> |
||||
|
<q-item-section> |
||||
|
<q-item-label>50%</q-item-label> |
||||
|
</q-item-section> |
||||
|
</q-item> |
||||
|
</q-list> |
||||
|
</q-btn-dropdown> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn outline icon="bi-zoom-in" /> |
||||
|
<q-btn outline icon="bi-zoom-out" /> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn outline icon="undo" /> |
||||
|
<q-btn outline icon="redo" /> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn outline icon="bi-trash" /> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn outline icon="bi-layers" /> |
||||
|
<q-btn outline icon="bi-layers-half" /> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn outline icon="bi-paint-bucket" /> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn outline icon="bi-palette" /> |
||||
|
<q-separator vertical /> |
||||
|
<q-btn outline icon="bi-bezier2" /> |
||||
|
</q-toolbar> |
||||
|
</template> |
||||
|
<script setup lang="ts"></script> |
Loading…
Reference in new issue