@mx-sose-front/mx-sose-graph 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,20 +22,27 @@
22
22
  :actionButtonShapeDataId="actionButtonShapeId" @edit-name="handleEditName"
23
23
  @update-shape="handleUpdateConnectShape" @diagramDoubleClick="handleDiagramDoubleClick"
24
24
  @connect-end="handleConnectEnd" @action-button-click="handleActionButtonClick"
25
+ @object-flow-connect-end="handleObjectFlowConnectEnd"
25
26
  @model-type-property-id-button-click="handleModelTypePropertyIdButtonClick" :lines="props.lines"
26
27
  :packages="props.packages" :diagram="props.diagram" :tagged-value-labels="props.taggedValueLabels"
27
28
  @action-button-add="handleActionButtonAdd" />
28
29
  </div>
29
-
30
+
31
+ <!-- 所在图表 -->
32
+ <DiagramListTooltip :visible="tooltipVisible" :x="tooltipX" :y="tooltipY" :current-diagram-id="currentDiagramId"
33
+ @close="tooltipVisible = false" :diagram-location-data="chartLocationData || []" />
34
+
30
35
  <!-- 缩放条 -->
31
- <div class="zoom-bar">
32
- <button @click="handleZoomOut" class="zoom-button zoom-out">-</button>
33
- <div class="zoom-slider">
34
- <input type="range" min="0.1" max="3" step="0.1" v-model="zoomValue" @input="handleZoomChange" />
35
- </div>
36
- <button @click="handleZoomIn" class="zoom-button zoom-in">+</button>
37
- <div class="zoom-level">{{ Math.round(currentScale * 100) }}%</div>
38
- </div>
36
+ <ZoomSlider
37
+ v-model="zoomValue"
38
+ :min="0.1"
39
+ :max="3"
40
+ :step="0.1"
41
+ @zoom-in="handleZoomIn"
42
+ @zoom-out="handleZoomOut"
43
+ @scale-change="handleScaleChange"
44
+ v-if="graphStore.canOperate"
45
+ />
39
46
  </div>
40
47
  </template>
41
48
 
@@ -43,7 +50,7 @@
43
50
  import { ref, onMounted, computed, watch, nextTick, onUnmounted } from 'vue'
44
51
  import normalizeWheel from 'normalize-wheel-es'
45
52
  import InteractionLayer from '../components/InteractionLayer.vue'
46
- import type { Shape } from '../types'
53
+ import type { locationChart, Shape } from '../types'
47
54
  import { useGraphStore } from '../store/graphStore'
48
55
  // 导入组件
49
56
  import StrategicTaxonomyDiagram from '../components/Diagram/StrategicTaxonomyDiagram.vue'
@@ -63,6 +70,9 @@ import { getShapeComponent, getShapeStyle } from "../render/shape-renderer";
63
70
  import { ShapeConfig } from '../utils/diagram'
64
71
  import { setCompartmentZones, buildZones, setTaggedValueLabelsCache, setPackageTypesCache } from '../utils/compartment'
65
72
  import { eventBus } from "../store";
73
+ import { guardOperate } from "../utils/license-guard"
74
+ import DiagramListTooltip from '../components/DiagramListTooltip/DiagramListTooltip.vue';
75
+ import ZoomSlider from '../components/ZoomSlider/ZoomSlider.vue'
66
76
 
67
77
  registerShapes({
68
78
  StrategicTaxonomyDiagram,
@@ -79,12 +89,19 @@ registerShapes({
79
89
  Port
80
90
  })
81
91
  const interactionLayerRef = ref<InstanceType<typeof InteractionLayer> | null>(null)
92
+
93
+ // 所在图表弹窗相关变量
94
+ const tooltipVisible = ref(false)
95
+ const tooltipX = ref(0)
96
+ const tooltipY = ref(0)
97
+ const currentDiagramId = ref<string>('')
98
+
82
99
  const props = defineProps<{
83
100
  addShapeData: Shape,
84
101
  connectShapeData: Shape,
85
- lines: String[],
102
+ lines: string[],
86
103
  packages: string[],
87
- diagram: String[],
104
+ diagram: string[],
88
105
  taggedValueLabels: string[],
89
106
  actionButtonShapeId?: string,
90
107
  classMetaTypes: string[],
@@ -92,12 +109,15 @@ const props = defineProps<{
92
109
  pins: string[],
93
110
  referentialAttributeModel: string[],
94
111
  ports: string[],
112
+ canOperate: boolean
113
+ chartLocationData?: locationChart[] | null,
95
114
  }>()
96
115
 
97
116
  const emit = defineEmits<{
98
117
  (e: 'shapes-property', value: { selectedShape: Shape, showPropertyPanel: boolean }): void
99
- (e: 'shapes-edit-name', value: { shape: Shape, newName: string }): void
118
+ (e: 'shapes-edit-name', value: { shape: Shape, newName: string, oldName: string }): void
100
119
  (e: 'connect-end', value: { sourceId: string, targetId: string, sourcePoint: { x: number, y: number }, targetPoint: { x: number, y: number }, waypoints: Array<{ x: number, y: number }> }): void
120
+ (e: 'object-flow-connect-end', value: { connectionData: { sourceId: string; targetId: string; sourcePoint: { x: number; y: number }; targetPoint: { x: number; y: number }; waypoints: Array<{ x: number; y: number }> }, outputPinBounds: { x: number; y: number; width: number; height: number }, inputPinBounds: { x: number; y: number; width: number; height: number } }): void
101
121
  (e: 'action-button-click', value: string, shape: Shape): void
102
122
  (e: 'diagramDoubleClick', data: any): void
103
123
  (e: 'model-type-property-id-button-click', value: string, shape: Shape): void
@@ -106,8 +126,6 @@ const emit = defineEmits<{
106
126
  }>()
107
127
 
108
128
  const graphStore = useGraphStore()
109
- const diagramContentRef = ref<HTMLElement | null>(null)
110
- const shapeComponents = ref<any[]>([]) // 用于获取子组件实例
111
129
  const resShape = ref<Shape>({} as Shape) // 用于存储通过 ref 获取的 shape 数据
112
130
 
113
131
  // 计算属性:获取当前画布的缩放比例
@@ -122,13 +140,14 @@ watch(currentScale, (newScale) => {
122
140
  })
123
141
 
124
142
  // 处理缩放滑块变化
125
- const handleZoomChange = () => {
126
- graphStore.setScale(zoomValue.value)
127
- emit('scale-changed', zoomValue.value)
143
+ const handleScaleChange = (scale: number) => {
144
+ graphStore.setScale(scale)
145
+ emit('scale-changed', scale)
128
146
  }
129
147
 
130
148
  // 处理放大按钮点击
131
149
  const handleZoomIn = () => {
150
+ // ZoomSlider组件已经处理了内部逻辑,这里只需要触发外部事件
132
151
  const newScale = Math.min(currentScale.value + 0.1, 3)
133
152
  graphStore.setScale(newScale)
134
153
  emit('scale-changed', newScale)
@@ -136,6 +155,7 @@ const handleZoomIn = () => {
136
155
 
137
156
  // 处理缩小按钮点击
138
157
  const handleZoomOut = () => {
158
+ // ZoomSlider组件已经处理了内部逻辑,这里只需要触发外部事件
139
159
  const newScale = Math.max(currentScale.value - 0.1, 0.1)
140
160
  graphStore.setScale(newScale)
141
161
  emit('scale-changed', newScale)
@@ -189,12 +209,14 @@ const handleNameClick = (shape: Shape, event: MouseEvent) => {
189
209
 
190
210
  // 处理图形点击事件
191
211
  const handleShapeClick = (shape: Shape, event: MouseEvent) => {
192
- graphStore.selectShape(shape)
212
+ return guardOperate(async () => {
213
+ graphStore.selectShape(shape)
214
+ })
193
215
  }
194
216
 
195
217
  // 处理编辑名称事件
196
- const handleEditName = (shape: Shape, newName: string) => {
197
- emit('shapes-edit-name', { shape, newName })
218
+ const handleEditName = (shape: Shape, newName: string, oldName: string) => {
219
+ emit('shapes-edit-name', { shape, newName, oldName })
198
220
  }
199
221
 
200
222
  // 处理连接点位置更新
@@ -211,6 +233,10 @@ const handleConnectEnd = (connectionData: { sourceId: string; targetId: string;
211
233
  console.log('连接结束事件已传递给父组件:', connectionData);
212
234
  }
213
235
 
236
+ const handleObjectFlowConnectEnd = (connectionData: { connectionData: { sourceId: string; targetId: string; sourcePoint: { x: number; y: number }; targetPoint: { x: number; y: number }; waypoints: Array<{ x: number; y: number }> }, outputPinBounds: { x: number; y: number; width: number; height: number }, inputPinBounds: { x: number; y: number; width: number; height: number } }) => {
237
+ emit('object-flow-connect-end', connectionData);
238
+ }
239
+
214
240
  // 处理双击图表事件
215
241
  const handleDiagramDoubleClick = (data: any) => {
216
242
  emit('diagramDoubleClick', data);
@@ -249,38 +275,48 @@ const handleEdgeClick = (shape: Shape, event: MouseEvent) => {
249
275
  interactionLayerRef.value.handleEdgeClick(edgeShape, event);
250
276
  }
251
277
  }
278
+
279
+ // 处理所在图表弹窗位置信息
280
+ const handleLocateChartPosition = (position: { x: number, y: number }) => {
281
+ tooltipX.value = position.x;
282
+ tooltipY.value = position.y;
283
+ tooltipVisible.value = true;
284
+ }
285
+
252
286
  const handleActionButtonAdd = (shape: Shape) => {
253
287
  emit('action-button-add', shape);
254
288
  }
255
289
 
256
290
  // 处理鼠标滚轮事件,实现缩放功能
257
291
  const handleWheel = (event: WheelEvent) => {
258
- // 只有按住Ctrl键时才执行缩放
259
- if (!event.ctrlKey && !event.metaKey) {
260
- // 不按住Ctrl键时,允许默认的滚轮行为(滚动)
261
- return;
262
- }
292
+ return guardOperate(async () => {
293
+ // 只有按住Ctrl键时才执行缩放
294
+ if (!event.ctrlKey && !event.metaKey) {
295
+ // 不按住Ctrl键时,允许默认的滚轮行为(滚动)
296
+ return;
297
+ }
263
298
 
264
- // 阻止默认行为,避免页面缩放
265
- event.preventDefault();
299
+ // 阻止默认行为,避免页面缩放
300
+ event.preventDefault();
266
301
 
267
- // 使用normalize-wheel-es标准化滚轮事件
268
- const normalized = normalizeWheel(event);
302
+ // 使用normalize-wheel-es标准化滚轮事件
303
+ const normalized = normalizeWheel(event);
269
304
 
270
- // 计算缩放比例增量
271
- const zoomFactor = 0.01;
272
- const delta = normalized.pixelY > 0 ? -zoomFactor : zoomFactor;
305
+ // 计算缩放比例增量
306
+ const zoomFactor = 0.01;
307
+ const delta = normalized.pixelY > 0 ? -zoomFactor : zoomFactor;
273
308
 
274
- // 获取当前缩放比例并计算新的缩放比例
275
- // getScale默认使用activeDiagramId
276
- const currentScale = graphStore.getScale();
277
- const newScale = currentScale + delta;
309
+ // 获取当前缩放比例并计算新的缩放比例
310
+ // getScale默认使用activeDiagramId
311
+ const currentScale = graphStore.getScale();
312
+ const newScale = currentScale + delta;
278
313
 
279
- // 设置新的缩放比例,默认使用activeDiagramId
280
- graphStore.setScale(newScale);
314
+ // 设置新的缩放比例,默认使用activeDiagramId
315
+ graphStore.setScale(newScale);
281
316
 
282
- // 通知父组件缩放变化
283
- emit('scale-changed', newScale);
317
+ // 通知父组件缩放变化
318
+ emit('scale-changed', newScale);
319
+ })
284
320
  }
285
321
 
286
322
  const updateShapes = (shapes: Shape[]) => {
@@ -378,17 +414,26 @@ watch(
378
414
  )
379
415
  // 把 referentialAttributeModel + pins 合并后存进 store
380
416
  watch(
381
- () => [props.referentialAttributeModel, props.pins,props.ports],
417
+ () => [props.referentialAttributeModel, props.pins, props.ports],
382
418
  ([referentialAttributeModel, pins]) => {
383
419
  const refArr = referentialAttributeModel ?? []
384
420
  const pinArr = pins ?? []
385
- const portArr = props.ports ?? []
421
+ const portArr = props.ports ?? []
386
422
  graphStore.pinsTypes = pinArr
387
423
  graphStore.portsTypes = portArr
388
- graphStore.ownerRequiredShapeKeys = [...refArr, ...pinArr,...portArr]
424
+ graphStore.ownerRequiredShapeKeys = [...refArr, ...pinArr, ...portArr]
389
425
  },
390
426
  { immediate: true }
391
427
  )
428
+ watch(
429
+ () => props.canOperate,
430
+ (val) => {
431
+ graphStore.canOperate = val ?? false
432
+ },
433
+ {
434
+ immediate: true,
435
+ }
436
+ )
392
437
  onMounted(() => {
393
438
  initShapes()
394
439
  document.addEventListener('keydown', (e) => {
@@ -398,6 +443,8 @@ onMounted(() => {
398
443
  }
399
444
  });
400
445
 
446
+ // 监听所在图表弹窗位置信息事件
447
+ eventBus.on('locate-chart-position', handleLocateChartPosition)
401
448
  })
402
449
 
403
450
  onUnmounted(() => {
@@ -407,6 +454,9 @@ onUnmounted(() => {
407
454
  graphStore.selectedIds = []
408
455
  }
409
456
  });
457
+
458
+ // 移除所在图表弹窗位置信息事件监听器
459
+ eventBus.off('locate-chart-position', handleLocateChartPosition)
410
460
  })
411
461
 
412
462
  defineExpose({
@@ -455,105 +505,21 @@ defineExpose({
455
505
  position: absolute;
456
506
  }
457
507
 
458
- /* 缩放条样式 */
459
- .zoom-bar {
460
- position: absolute;
461
- bottom: 0;
462
- right: 0;
463
- left: 0;
464
- width: 100%;
465
- height: 24px;
466
- display: flex;
467
- align-items: center;
468
- justify-content: flex-end;
469
- background: white;
470
- border-top: 1px solid #e0e0e0;
471
- box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
472
- z-index: 1000;
473
- gap: 6px;
474
- padding: 0 10px;
475
- }
476
-
508
+ /* 缩放百分比显示 */
477
509
  .zoom-level {
510
+ position: absolute;
511
+ bottom: 30px;
512
+ right: 15px;
478
513
  font-size: 10px;
479
514
  font-weight: 500;
480
515
  min-width: 35px;
481
516
  text-align: center;
482
517
  color: #333;
518
+ background: rgba(255, 255, 255, 0.9);
519
+ padding: 2px 6px;
520
+ border-radius: 3px;
521
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
483
522
  }
484
523
 
485
- .zoom-slider {
486
- width: 150px;
487
- height: 100%;
488
- display: flex;
489
- align-items: center;
490
- justify-content: center;
491
- }
492
-
493
- .zoom-slider input[type="range"] {
494
- width: 100%;
495
- height: 2px;
496
- border-radius: 1px;
497
- background: #e0e0e0;
498
- outline: none;
499
- -webkit-appearance: none;
500
- margin: 0;
501
- }
502
-
503
- .zoom-slider input[type="range"]::-webkit-slider-thumb {
504
- -webkit-appearance: none;
505
- appearance: none;
506
- width: 10px;
507
- height: 10px;
508
- border-radius: 50%;
509
- background: #1890ff;
510
- cursor: pointer;
511
- transition: all 0.2s;
512
- }
513
-
514
- .zoom-slider input[type="range"]::-webkit-slider-thumb:hover {
515
- background: #40a9ff;
516
- transform: scale(1.1);
517
- }
518
-
519
- .zoom-slider input[type="range"]::-moz-range-thumb {
520
- width: 10px;
521
- height: 10px;
522
- border-radius: 50%;
523
- background: #1890ff;
524
- cursor: pointer;
525
- border: none;
526
- transition: all 0.2s;
527
- }
528
-
529
- .zoom-slider input[type="range"]::-moz-range-thumb:hover {
530
- background: #40a9ff;
531
- transform: scale(1.1);
532
- }
533
-
534
- .zoom-button {
535
- width: 18px;
536
- height: 18px;
537
- display: flex;
538
- align-items: center;
539
- justify-content: center;
540
- border: 1px solid #e0e0e0;
541
- border-radius: 2px;
542
- background: white;
543
- cursor: pointer;
544
- font-size: 10px;
545
- font-weight: 600;
546
- color: #333;
547
- transition: all 0.2s;
548
- }
549
-
550
- .zoom-button:hover {
551
- background: #f5f5f5;
552
- border-color: #1890ff;
553
- color: #1890ff;
554
- }
555
524
 
556
- .zoom-button:active {
557
- background: #e6f7ff;
558
- }
559
525
  </style>
File without changes