@mx-sose-front/mx-sose-graph 1.2.1 → 1.2.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.
- package/dist/index.esm.js +1525 -1157
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/Gantt/Gantt.vue +2 -0
- package/src/components/Matrix/Matrix.vue +87 -12
- package/src/components/MatrixContextMenu/MatrixContextMenu.vue +235 -0
- package/src/components/Shape/DividingLine.vue +80 -64
- package/src/components/Table/Table.vue +2 -0
- package/src/constants/edgeShapeKeys.ts +4 -2
- package/src/constants/index.ts +18 -10
- package/src/hooks/useChartRowSelection.ts +37 -6
- package/src/statics/icons/childIcons/DIV-3/347/211/251/347/220/206/346/225/260/346/215/256/346/250/241/345/236/213/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SV-3/347/263/273/347/273/237/342/200/224/347/263/273/347/273/237/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-10c/346/234/215/345/212/241/344/272/213/344/273/266/342/200/224/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-2 /346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/345/206/205/351/203/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-3a/347/263/273/347/273/237/342/200/224/346/234/215/345/212/241/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-3b /346/234/215/345/212/241 -/346/234/215/345/212/241/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-3b/346/234/215/345/212/241/342/200/224/346/234/215/345/212/241/347/237/251/351/230/265/345/214/205@3x.png +0 -0
- package/src/statics/icons/childIcons/SvcV-5 /346/234/215/345/212/241/345/210/260/344/270/232/345/212/241/346/264/273/345/212/250/345/217/257/350/277/275/346/272/257/346/200/247/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons/set@3x.png +0 -0
- package/src/statics/icons/childIcons//344/270/232/345/212/241/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//344/270/232/345/212/241/346/211/247/350/241/214/350/200/205/344/270/216/350/203/275/345/212/233/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons//344/270/232/345/212/241/347/273/223/346/236/204/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons//344/270/232/345/212/241/347/274/223/350/247/243/346/216/252/346/226/275@3x.png +0 -0
- package/src/statics/icons/childIcons//344/272/272/345/221/230/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//344/272/272/345/221/230/347/272/246/346/235/237/345/256/232/344/271/211/345/233/276@3x.png +0 -0
- package/src/statics/icons/childIcons//345/256/211/345/205/250/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//345/256/236/351/231/205/346/210/230/347/225/245/351/230/266/346/256/265/344/270/216/350/203/275/345/212/233/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons//345/256/236/351/231/205/350/265/204/346/272/220/345/205/263/347/263/273@3x.png +0 -0
- package/src/statics/icons/childIcons//345/256/236/351/231/205/350/265/204/346/272/220/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//346/210/230/347/225/245/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//346/234/215/345/212/241/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//346/234/215/345/212/241/350/277/236/351/200/232/347/237/251/351/230/265@3x.png +0 -0
- package/src/statics/icons/childIcons//346/234/215/345/212/241/350/277/236/351/200/232/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons//346/240/207/345/207/206/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//346/240/207/345/207/206/350/267/257/347/272/277/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons//346/240/207/345/207/206/350/277/275/346/272/257/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons//347/212/266/346/200/201/346/214/207/346/240/207@3x.png +0 -0
- package/src/statics/icons/childIcons//350/265/204/346/272/220/345/261/202@3x.png +0 -0
- package/src/statics/icons/childIcons//351/200/202/347/224/250/350/203/275/345/212/233@3x.png +0 -0
- package/src/statics/icons/childIcons//351/241/271/347/233/256/345/261/202@3x.png +0 -0
- package/src/utils/keyboardUtils.ts +13 -0
- /package/src/statics/icons/childIcons/{role@3x.png → Role@3x.png} +0 -0
- /package/src/statics/icons/childIcons/SV-10c/347/263/273/347/273/237/344/272/213/344/273/{266- → 266/342/200/224}/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png" +0 -0
- /package/src/statics/icons/childIcons/{SV-3/347/263/273/347/273/237-/347/263/273/347/273/237/347/237/251/351/230/265 → SV-10c/347/263/273/347/273/237/344/272/213/344/273/266/344/270/200/350/277/275/350/270/252/346/217/217/350/277/260}/345/214/205@3x.png" +0 -0
- /package/src/statics/icons/childIcons//347/233/270/346/257/{224@3x (1).png" → 224@3x.png"} +0 -0
|
@@ -198,6 +198,8 @@ const headerHeight = computed(() => {
|
|
|
198
198
|
|
|
199
199
|
// 响应式状态管理
|
|
200
200
|
const actualContentHeight = ref<number>(0); // 实际内容高度
|
|
201
|
+
// 实际内容宽度
|
|
202
|
+
const actualContentWidth = ref<number>(0)
|
|
201
203
|
const contentRef = ref<HTMLElement | null>(null);
|
|
202
204
|
|
|
203
205
|
// 内容区域高度计算
|
|
@@ -278,73 +280,90 @@ const reportMetrics = () => {
|
|
|
278
280
|
});
|
|
279
281
|
}
|
|
280
282
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
283
|
+
/**
|
|
284
|
+
* 测量内容真实宽高
|
|
285
|
+
*/
|
|
286
|
+
const measureContentSize = () => {
|
|
287
|
+
if (!contentRef.value) return
|
|
288
|
+
|
|
289
|
+
// 先重置,保证测量的是内容自然撑开的尺寸
|
|
290
|
+
contentRef.value.style.width = 'auto'
|
|
291
|
+
contentRef.value.style.height = 'auto'
|
|
292
|
+
contentRef.value.style.maxWidth = 'none'
|
|
293
|
+
|
|
294
|
+
// 真实内容尺寸
|
|
295
|
+
const realWidth = contentRef.value.scrollWidth
|
|
296
|
+
const realHeight = contentRef.value.scrollHeight
|
|
297
|
+
|
|
298
|
+
let changed = false
|
|
299
|
+
|
|
300
|
+
if (realWidth !== actualContentWidth.value) {
|
|
301
|
+
actualContentWidth.value = realWidth
|
|
302
|
+
changed = true
|
|
303
|
+
}
|
|
284
304
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
305
|
+
if (realHeight !== actualContentHeight.value) {
|
|
306
|
+
actualContentHeight.value = realHeight
|
|
307
|
+
changed = true
|
|
308
|
+
}
|
|
288
309
|
|
|
289
|
-
|
|
290
|
-
const actualHeight = contentRef.value.scrollHeight;
|
|
291
|
-
if (actualHeight !== actualContentHeight.value) {
|
|
292
|
-
actualContentHeight.value = actualHeight;
|
|
310
|
+
if (changed) {
|
|
293
311
|
nextTick(() => {
|
|
294
312
|
updateShapeBounds()
|
|
295
313
|
debouncedReportMetrics()
|
|
296
314
|
})
|
|
297
|
-
|
|
298
315
|
}
|
|
299
|
-
}
|
|
316
|
+
}
|
|
300
317
|
|
|
301
318
|
// 更新组件宽度和高度
|
|
319
|
+
/**
|
|
320
|
+
* 更新组件宽高
|
|
321
|
+
*/
|
|
302
322
|
const updateShapeBounds = () => {
|
|
303
|
-
//
|
|
304
|
-
const
|
|
323
|
+
// 内容区左右 padding:foreignObject x=12,左右一共约 24
|
|
324
|
+
const contentRequiredWidth = actualContentWidth.value > 0
|
|
325
|
+
? actualContentWidth.value + 24
|
|
326
|
+
: 0
|
|
327
|
+
|
|
328
|
+
// 标题区和内容区,取最大值
|
|
329
|
+
const requiredWidth = Math.max(
|
|
330
|
+
estimatedTextWidth.value,
|
|
331
|
+
contentRequiredWidth,
|
|
332
|
+
150
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
// 计算最小总高度
|
|
336
|
+
const minTotalHeight = headerHeight.value + 15 + contentHeight.value + 10
|
|
305
337
|
|
|
306
|
-
// 设置一个基于字体大小的最小高度,确保字体较大时组件也能正常显示
|
|
307
338
|
const fontSizeBasedMinHeight = Math.max(
|
|
308
339
|
(keywordsStyle.value.fontSize || 12) * 3,
|
|
309
340
|
(nameStyle.value.fontSize || 12) * 3
|
|
310
|
-
) + 50
|
|
311
|
-
|
|
312
|
-
// 设置一个明确的最小高度限制,确保组件不会太小
|
|
313
|
-
const explicitMinHeight = 110; // 明确的最小高度值,不小于100
|
|
314
|
-
const effectiveMinHeight = Math.max(minTotalHeight, fontSizeBasedMinHeight, explicitMinHeight);
|
|
341
|
+
) + 50
|
|
315
342
|
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
343
|
+
const explicitMinHeight = 110
|
|
344
|
+
const effectiveMinHeight = Math.max(
|
|
345
|
+
minTotalHeight,
|
|
346
|
+
fontSizeBasedMinHeight,
|
|
347
|
+
explicitMinHeight
|
|
348
|
+
)
|
|
319
349
|
|
|
320
|
-
|
|
321
|
-
const
|
|
350
|
+
const currentWidth = props.shape.bounds?.width || 0
|
|
351
|
+
const currentHeight = props.shape.bounds?.height || 0
|
|
322
352
|
|
|
323
|
-
|
|
324
|
-
const
|
|
353
|
+
const nextWidth = Math.max(currentWidth, requiredWidth)
|
|
354
|
+
const nextHeight = Math.max(currentHeight, effectiveMinHeight)
|
|
325
355
|
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
if (currentHeight < effectiveMinHeight) {
|
|
329
|
-
updates.height = effectiveMinHeight;
|
|
330
|
-
}
|
|
356
|
+
// 宽高没变就不更新,避免死循环
|
|
357
|
+
if (nextWidth === currentWidth && nextHeight === currentHeight) return
|
|
331
358
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
graphStore.updateShape(props.shape.id, {
|
|
341
|
-
bounds: {
|
|
342
|
-
...props.shape.bounds,
|
|
343
|
-
...updates
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
};
|
|
359
|
+
graphStore.updateShape(props.shape.id, {
|
|
360
|
+
bounds: {
|
|
361
|
+
...props.shape.bounds,
|
|
362
|
+
width: nextWidth,
|
|
363
|
+
height: nextHeight
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
}
|
|
348
367
|
|
|
349
368
|
// 添加额外的尺寸保护,在拖拽结束后强制检查最小尺寸
|
|
350
369
|
const enforceMinSizeOnResizeEnd = () => {
|
|
@@ -389,7 +408,7 @@ const debouncedUpdateShapeBounds = debounce(updateShapeBounds, 100);
|
|
|
389
408
|
|
|
390
409
|
// 监听尺寸变化,更新compartment区域
|
|
391
410
|
const debouncedReportMetrics = debounce(reportMetrics, 100);
|
|
392
|
-
const
|
|
411
|
+
const debouncedMeasureContentSize = debounce(measureContentSize, 100)
|
|
393
412
|
|
|
394
413
|
// 监听拖拽缩放事件
|
|
395
414
|
const handleDragStart = () => {
|
|
@@ -407,7 +426,7 @@ onMounted(() => {
|
|
|
407
426
|
nextTick(() => {
|
|
408
427
|
reportMetrics();
|
|
409
428
|
// 初始测量内容高度
|
|
410
|
-
setTimeout(
|
|
429
|
+
setTimeout(measureContentSize, 0)
|
|
411
430
|
// 初始更新图元尺寸
|
|
412
431
|
updateShapeBounds();
|
|
413
432
|
});
|
|
@@ -419,7 +438,7 @@ onMounted(() => {
|
|
|
419
438
|
eventBus.on('shape-resize-end', enforceMinSizeOnResizeEnd);
|
|
420
439
|
|
|
421
440
|
// 监听内容变化相关的事件
|
|
422
|
-
window.addEventListener('resize',
|
|
441
|
+
window.addEventListener('resize', debouncedMeasureContentSize)
|
|
423
442
|
});
|
|
424
443
|
|
|
425
444
|
// 监听shape变化,重新计算尺寸
|
|
@@ -428,7 +447,7 @@ watch(() => [props.shape.name, props.shape.keywords, props.shape.bounds?.width,
|
|
|
428
447
|
nextTick(() => {
|
|
429
448
|
reportMetrics();
|
|
430
449
|
// 当内容或宽度变化时重新测量高度
|
|
431
|
-
|
|
450
|
+
debouncedMeasureContentSize()
|
|
432
451
|
});
|
|
433
452
|
}
|
|
434
453
|
}, { deep: true }); // 启用深度监听以捕获样式对象的变化
|
|
@@ -487,8 +506,7 @@ watch(
|
|
|
487
506
|
() => {
|
|
488
507
|
if (!isResizing.value) {
|
|
489
508
|
nextTick(() => {
|
|
490
|
-
|
|
491
|
-
debouncedMeasureContentHeight()
|
|
509
|
+
debouncedMeasureContentSize()
|
|
492
510
|
})
|
|
493
511
|
}
|
|
494
512
|
},
|
|
@@ -499,7 +517,7 @@ onBeforeUnmount(() => {
|
|
|
499
517
|
eventBus.off('shape-drag-end', handleDragEnd);
|
|
500
518
|
eventBus.off('shape-resize-start', handleDragStart);
|
|
501
519
|
eventBus.off('shape-resize-end', enforceMinSizeOnResizeEnd);
|
|
502
|
-
window.removeEventListener('resize',
|
|
520
|
+
window.removeEventListener('resize', debouncedMeasureContentSize)
|
|
503
521
|
});
|
|
504
522
|
// ================== 监听 bounds 宽高变化 ==================
|
|
505
523
|
|
|
@@ -521,24 +539,22 @@ const lastBounds = ref({
|
|
|
521
539
|
watch(
|
|
522
540
|
() => [props.shape.bounds.width, props.shape.bounds.height],
|
|
523
541
|
([newW, newH]) => {
|
|
524
|
-
|
|
525
|
-
|
|
542
|
+
// 只有真实图元变化时,才通知父元素扩容
|
|
543
|
+
if (isGhost.value) return
|
|
544
|
+
|
|
526
545
|
const width = newW ?? DEFAULT_WIDTH
|
|
527
546
|
const height = newH ?? DEFAULT_HEIGHT
|
|
528
547
|
|
|
529
|
-
// 如果和上一次一致,直接返回,避免重复触发
|
|
530
548
|
if (
|
|
531
|
-
width
|
|
532
|
-
height
|
|
549
|
+
width === lastBounds.value.width &&
|
|
550
|
+
height === lastBounds.value.height
|
|
533
551
|
) {
|
|
534
552
|
return
|
|
535
553
|
}
|
|
536
554
|
|
|
537
|
-
// 更新“上一次”的记录
|
|
538
555
|
lastBounds.value = { width, height }
|
|
539
|
-
|
|
540
|
-
if (
|
|
541
|
-
width !== DEFAULT_WIDTH || height !== DEFAULT_HEIGHT) {
|
|
556
|
+
|
|
557
|
+
if (width !== DEFAULT_WIDTH || height !== DEFAULT_HEIGHT) {
|
|
542
558
|
graphStore.expandParentAndEmitSizeUpdateByChild(props.shape)
|
|
543
559
|
}
|
|
544
560
|
}
|
|
@@ -55,7 +55,8 @@ export const DASHED_EDGE_SHAPES = [
|
|
|
55
55
|
'Protects',
|
|
56
56
|
'MapsToCapability',
|
|
57
57
|
'ActualResourceRelationship',
|
|
58
|
-
'ProjectSequence'
|
|
58
|
+
'ProjectSequence',
|
|
59
|
+
'Supports'
|
|
59
60
|
];
|
|
60
61
|
|
|
61
62
|
/**
|
|
@@ -92,7 +93,8 @@ export const EDGES_WITH_KEYWORDS = [
|
|
|
92
93
|
'Protects',
|
|
93
94
|
'MapsToCapability',
|
|
94
95
|
'ActualResourceRelationship',
|
|
95
|
-
'ProjectSequence'
|
|
96
|
+
'ProjectSequence',
|
|
97
|
+
'Supports'
|
|
96
98
|
];
|
|
97
99
|
|
|
98
100
|
/**
|
package/src/constants/index.ts
CHANGED
|
@@ -74,6 +74,7 @@ export const EdgeKeyMap = {
|
|
|
74
74
|
'ResourceConnector': 'Edge',//资源连接器
|
|
75
75
|
'CompetenceToConduct': 'Edge',//开展工作能力
|
|
76
76
|
'ResponsibleFor': 'Edge',//负责
|
|
77
|
+
'Supports': 'Edge',//支持
|
|
77
78
|
} as const
|
|
78
79
|
|
|
79
80
|
// Diagram 类型 (shapeType: 'diagram') - 用于组件渲染映射
|
|
@@ -169,11 +170,9 @@ export const DiagramKeyMap = {
|
|
|
169
170
|
'ProjectsProcessesDiagram': 'StrategicTaxonomyDiagram', //项目流程图
|
|
170
171
|
'ProjectsProcessesFlowDiagram': 'StrategicTaxonomyDiagram', //项目内部流程图
|
|
171
172
|
'ActualProjectMilestoneSummaryTable': 'StrategicTaxonomyDiagram', //实际项目里程碑摘要表
|
|
172
|
-
'ActualProjectsToCapabilitiesMappingMatrix': 'StrategicTaxonomyDiagram', //实际项目与能力映射矩阵
|
|
173
173
|
'ActualResponsibleResourcesToActualProjectsMappingMatrix': 'StrategicTaxonomyDiagram', //实际负责资源与实际项目映射矩阵
|
|
174
174
|
'ProjectActivitiesToCapabilitiesMappingMatrix': 'StrategicTaxonomyDiagram', //项目活动到能力映射矩阵
|
|
175
175
|
'StandardsTaxonomyDiagram': 'StrategicTaxonomyDiagram', //标准概念图
|
|
176
|
-
'StandardsTaxonomyTable': 'StrategicTaxonomyDiagram', //标准概念表
|
|
177
176
|
'StandardsStructureDiagram': 'StrategicTaxonomyDiagram', //标准结构图
|
|
178
177
|
'StandardsTraceabilityDiagram': 'StrategicTaxonomyDiagram', //标准可追溯图
|
|
179
178
|
'ActualResourcesTaxonomyMatrix': 'StrategicTaxonomyDiagram', //实际资源概念矩阵
|
|
@@ -231,6 +230,7 @@ export const GanttKeyMap = {
|
|
|
231
230
|
'SV8SystemsEvolutionDescriptionDiagram': 'Gantt', //SV-8 系统演进描述甘特图
|
|
232
231
|
'PV2ProjectTimelinesChart': 'Gantt', //PV-2项目时间进度甘特图
|
|
233
232
|
} as const
|
|
233
|
+
|
|
234
234
|
//Table 类型 (shapeType: 'table') - 表格组件渲染映射
|
|
235
235
|
export const TableKeyMap = {
|
|
236
236
|
'StrategicTaxonomyTable': 'Table', //战略概念表
|
|
@@ -244,15 +244,18 @@ export const TableKeyMap = {
|
|
|
244
244
|
'ProjectsTaxonomyTable': 'Table', //项目概念表
|
|
245
245
|
'ActualProjectMilestoneSummaryTable': 'Table', //实际项目里程碑汇总表
|
|
246
246
|
'StandardsTraceabilityTable': 'Table', //标准追溯表
|
|
247
|
+
'ResourcesConnectivityTable': 'Table', //资源连通表
|
|
248
|
+
'StandardsTaxonomyTable': 'Table', //标准概念表
|
|
247
249
|
|
|
248
250
|
// dodaf
|
|
249
251
|
'AV2IntegratedDictionaryTable': 'Table', //AV-2集成字典表
|
|
250
252
|
'SvcV9ServicesTechnologyandSkillsForecastTable': 'Table', //SvcV-9 服务技术与技能预测表
|
|
251
253
|
'StdV1StandardsProfileTable': 'Table', //StdV-1 标准配置表
|
|
252
254
|
'StdV2StandardsForecastTable': 'Table', //StdV-2 标准预测表
|
|
253
|
-
'
|
|
255
|
+
'SV9SystemsTechologyAndSkillsForecastTable': 'Table', //SV-9 系统技术与技能预测表
|
|
254
256
|
'SV10aSystemsRulesModelTable': 'Table', //SV-10a 系统规则模型表
|
|
255
257
|
} as const
|
|
258
|
+
|
|
256
259
|
//Matrix 类型 (shapeType: 'matrix') - 矩阵组件渲染映射
|
|
257
260
|
export const MatrixKeyMap = {
|
|
258
261
|
'StrategicConnectivityMatrix': 'Matrix', //战略概念矩阵
|
|
@@ -266,7 +269,8 @@ export const MatrixKeyMap = {
|
|
|
266
269
|
'RisksToAssetsMappingMatrix': 'Matrix', //风险到资产映射矩阵
|
|
267
270
|
'SecurityControlsToRisksMappingMatrix': 'Matrix', //安全控制到风险映射矩阵
|
|
268
271
|
'ProjectActivitiesToCapabilitiesMappingMatrix': 'Matrix', //项目活动到能力映射矩阵
|
|
269
|
-
|
|
272
|
+
'ActualProjectsToCapabilitiesMappingMatrix': 'Matrix', //实际项目与能力的映射矩阵
|
|
273
|
+
'ActualStrategicPhasesToCapabilitiesMappingMatrix': 'Matrix', //实际战略阶段与能力映射矩阵
|
|
270
274
|
// dodaf
|
|
271
275
|
'CV5CapabilityToOrganizationDeploymentMapping': 'Matrix', //CV-5能力到组织的映射矩阵
|
|
272
276
|
'CV6CapabilityToOperationalActivitiesMappingMatrix': 'Matrix', //CV-6能力到业务活动映射矩阵
|
|
@@ -280,7 +284,7 @@ export const MatrixKeyMap = {
|
|
|
280
284
|
'SvcV6ServicesResourceFlowMatrix': 'Matrix', //SvcV-6 服务资源流矩阵
|
|
281
285
|
'SvcV7ServicesTypicalMeasuresMatrix': 'Matrix', //SvcV-7 服务典型度量矩阵
|
|
282
286
|
'SV3SystemsSystemsMatrix': 'Matrix', //SV-3 系统 - 系统矩阵
|
|
283
|
-
'
|
|
287
|
+
'SV5aOperationalActivityToSystemsFunctionMatrix': 'Matrix', //SV-5a 业务活动到系统功能的可追溯性矩阵
|
|
284
288
|
'SV5bOperationalActivityToSystemsTarceabilityMatrix': 'Matrix', //SV-5b 业务活动到系统的可追溯性矩阵
|
|
285
289
|
'SV6SystemsResourceFlowMatrix': 'Matrix', //SV-6 系统资源流动矩阵
|
|
286
290
|
'SV7SystemsActualMeasuresMatrix': 'Matrix', //SV-7 系统实际度量矩阵
|
|
@@ -504,6 +508,10 @@ export const ShapeKeyMap = {
|
|
|
504
508
|
'ResourceParameter': 'Block', //资源参数
|
|
505
509
|
'ResourceRole': 'Block', //资源角色
|
|
506
510
|
'ResourceSignal': 'Block', //资源信号
|
|
511
|
+
'Standard': 'Block', //标准
|
|
512
|
+
'Protocol': 'Block', //协议
|
|
513
|
+
'ProtocolStack': 'Block', //协议栈
|
|
514
|
+
'ProtocolLayer': 'Block', //协议层
|
|
507
515
|
|
|
508
516
|
// DividingLine 类型
|
|
509
517
|
'EnterpriseGoal': 'DividingLine', //企业目标
|
|
@@ -551,7 +559,6 @@ export const ShapeKeyMap = {
|
|
|
551
559
|
'StrategicActualStrategicPhaseTaxonomyTable': 'Diagram', //战略实际战略阶段分类表
|
|
552
560
|
'StrategicActualDeploymentDiagram': 'Diagram', //战略实际部署图
|
|
553
561
|
'StrategicConnectivityMatrixTable': 'Diagram', //战略连通矩阵表
|
|
554
|
-
'ActualStrategicPhasesToCapabilitiesMappingMatrix': 'Diagram', //实际战略阶段与能力映射矩阵
|
|
555
562
|
'OperationalConnectivityTable': 'Diagram', //业务连通表
|
|
556
563
|
'OperationalActivitiesToCapabilitiesMappingMatrix': 'Diagram', //业务活动与能力映射矩阵
|
|
557
564
|
'OperationalPerformersToCapabilitiesMappingMatrix': 'Diagram', //业务执行者与能力映射矩阵
|
|
@@ -587,7 +594,6 @@ export const ShapeKeyMap = {
|
|
|
587
594
|
'ResourcesTaxonomyTable': 'Diagram', //资源概念表
|
|
588
595
|
'ResourcesStructureDiagram': 'Diagram', //资源结构图
|
|
589
596
|
'ResourcesConnectivityDiagram': 'Diagram', //资源连通图
|
|
590
|
-
'ResourcesConnectivityTable': 'Diagram', //资源连通表
|
|
591
597
|
'ResourcesInternalConnectivityDiagram': 'Diagram', //资源内部连通图
|
|
592
598
|
'ResourcesProcessesDiagram': 'Diagram', //资源流程图
|
|
593
599
|
'ResourcesProcessesFlowDiagram': 'Diagram', //资源内部流程图
|
|
@@ -615,17 +621,19 @@ export const ShapeKeyMap = {
|
|
|
615
621
|
'ProjectsProcessesDiagram': 'Diagram', //项目流程图
|
|
616
622
|
'ProjectsProcessesFlowDiagram': 'Diagram', //项目内部流程图
|
|
617
623
|
'ActualProjectMilestoneSummaryTable': 'Diagram', //实际项目里程碑汇总表
|
|
618
|
-
'ActualProjectsToCapabilitiesMappingMatrix': 'Diagram', //实际项目与能力映射矩阵
|
|
619
624
|
'ActualResponsibleResourcesToActualProjectsMappingMatrix': 'Diagram', //实际资源与实际项目对应关系矩阵
|
|
620
625
|
'ProjectActivitiesToCapabilitiesMappingMatrix': 'Diagram', //项目活动与能力映射矩阵
|
|
621
626
|
'StandardsTaxonomyDiagram': 'Diagram', //标准概念图
|
|
622
|
-
'StandardsTaxonomyTable': 'Diagram', //标准概念表
|
|
623
627
|
'StandardsStructureDiagram': 'Diagram', //标准结构图
|
|
624
628
|
'StandardsTraceabilityDiagram': 'Diagram', //标准追溯图
|
|
625
629
|
'ActualResourcesTaxonomyMatrix': 'Diagram', //实际资源概念矩阵
|
|
626
630
|
'ActualResourcesStructureDiagram': 'Diagram', //实际资源结构图
|
|
627
631
|
'ActualResourcesConnectivityDiagram': 'Diagram', //实际资源连通图
|
|
628
632
|
'ActualStrategicPhasesGanttChart': 'Diagram', //实际战略阶段甘特图
|
|
633
|
+
'OperationalTaxonomyTable': 'Diagram', //业务概念表
|
|
634
|
+
'StandardsTaxonomyTable': 'Diagram', //标准概念表
|
|
635
|
+
'ServicesTaxonomyTable': 'Diagram', //服务概念表
|
|
636
|
+
'StandardsRoadmapTable': 'Diagram', //标准路线图
|
|
629
637
|
|
|
630
638
|
// DODAF Diagram 类型
|
|
631
639
|
'AV1OverviewAndSummaryInformationDiagram': 'Diagram', //AV-1概述摘要图
|
|
@@ -682,7 +690,7 @@ export const ShapeKeyMap = {
|
|
|
682
690
|
'StdV1StandardsProfileTable': 'Diagram', //StdV-1 标准配置表
|
|
683
691
|
'StdV2StandardsForecastTable': 'Diagram', //StdV-2 标准预测表
|
|
684
692
|
'SV3SystemsSystemsMatrix': 'Diagram', //SV-3 系统 - 系统矩阵
|
|
685
|
-
'
|
|
693
|
+
'SV5aOperationalActivityToSystemsFunctionMatrix': 'Diagram', //SV-5a 业务活动到系统功能的可追溯性矩阵
|
|
686
694
|
'SV5bOperationalActivityToSystemsTarceabilityMatrix': 'Diagram', //SV-5b 业务活动到系统的可追溯性矩阵
|
|
687
695
|
'SV6SystemsResourceFlowMatrix': 'Diagram', //SV-6 系统资源流动矩阵
|
|
688
696
|
'SV7SystemsActualMeasuresMatrix': 'Diagram', //SV-7 系统实际度量矩阵
|
|
@@ -21,6 +21,10 @@ interface RemoveContext {
|
|
|
21
21
|
selectedIndices: number[]
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
interface AddSuccessContext {
|
|
25
|
+
modelId?: string | null
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
/**
|
|
25
29
|
* 行选择 Hook 配置项
|
|
26
30
|
*/
|
|
@@ -82,6 +86,7 @@ export function useChartRowSelection<T extends ChartRowItem>({
|
|
|
82
86
|
const showContextMenu = ref(false)
|
|
83
87
|
const contextMenuPosition = ref({ x: 0, y: 0 })
|
|
84
88
|
const contextMenuTargetItem = ref<T | null>(null)
|
|
89
|
+
const pendingAddSelection = ref<AddSuccessContext | null>(null)
|
|
85
90
|
|
|
86
91
|
/**
|
|
87
92
|
* 缓存本次“移除”的上下文
|
|
@@ -393,19 +398,45 @@ export function useChartRowSelection<T extends ChartRowItem>({
|
|
|
393
398
|
* 选中最后一行
|
|
394
399
|
* 用于新增成功后的默认回选
|
|
395
400
|
*/
|
|
396
|
-
function selectLastRow() {
|
|
401
|
+
function selectLastRow(payload?: AddSuccessContext | string) {
|
|
397
402
|
const list = items.value
|
|
398
403
|
if (!list.length) {
|
|
399
|
-
|
|
400
|
-
|
|
404
|
+
pendingAddSelection.value =
|
|
405
|
+
typeof payload === 'string' ? { modelId: payload } : payload ?? null
|
|
401
406
|
return
|
|
402
407
|
}
|
|
403
408
|
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
409
|
+
const targetModelId =
|
|
410
|
+
typeof payload === 'string'
|
|
411
|
+
? payload
|
|
412
|
+
: payload?.modelId || null
|
|
413
|
+
|
|
414
|
+
const targetItem = targetModelId
|
|
415
|
+
? list.find(item => item.modelId === targetModelId)
|
|
416
|
+
: null
|
|
417
|
+
|
|
418
|
+
if (targetModelId && !targetItem) {
|
|
419
|
+
pendingAddSelection.value =
|
|
420
|
+
typeof payload === 'string' ? { modelId: payload } : payload ?? null
|
|
421
|
+
return
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
pendingAddSelection.value = null
|
|
425
|
+
const nextSelected = targetItem || list[list.length - 1]
|
|
426
|
+
selectedRowIds.value = new Set([nextSelected.id])
|
|
427
|
+
lastSelectedId.value = nextSelected.id
|
|
428
|
+
// 默认选中新建行时,同步触发行点击链路,确保属性面板也刷新到当前行。
|
|
429
|
+
eventBus.emit('chart-row-click', nextSelected)
|
|
407
430
|
}
|
|
408
431
|
|
|
432
|
+
watch(
|
|
433
|
+
() => items.value.map(item => `${item.id}:${item.modelId}`).join('|'),
|
|
434
|
+
() => {
|
|
435
|
+
if (!pendingAddSelection.value) return
|
|
436
|
+
selectLastRow(pendingAddSelection.value)
|
|
437
|
+
}
|
|
438
|
+
)
|
|
439
|
+
|
|
409
440
|
/**
|
|
410
441
|
* 同步“单行选中”状态
|
|
411
442
|
* 供属性面板等只关心单选对象的模块使用
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,6 +3,7 @@ import { eventBus } from '../store';
|
|
|
3
3
|
import _ from 'lodash';
|
|
4
4
|
import { guardOperate } from './license-guard';
|
|
5
5
|
import { ContextMenuUtils } from './contextMenuUtils';
|
|
6
|
+
import { adjustCanvasToFitAllShapes } from './diagram';
|
|
6
7
|
|
|
7
8
|
// 定义快捷键处理函数类型
|
|
8
9
|
type KeyboardEventHandler = (e: KeyboardEvent) => void;
|
|
@@ -303,6 +304,7 @@ export const createKeyboardHandler = (config: KeyboardConfig): KeyboardEventHand
|
|
|
303
304
|
const selectedShapes = graphStore.selectedIds
|
|
304
305
|
.map(id => graphStore.shapeMap.get(id))
|
|
305
306
|
.filter((shape): shape is NonNullable<typeof shape> => shape != null);
|
|
307
|
+
const hasNestedSelection = selectedShapes.some(shape => Boolean(shape.parenShapeId));
|
|
306
308
|
|
|
307
309
|
// ==================== 防抖机制:记录初始状态 ====================
|
|
308
310
|
// 在第一次移动时记录初始bounds
|
|
@@ -407,6 +409,17 @@ export const createKeyboardHandler = (config: KeyboardConfig): KeyboardEventHand
|
|
|
407
409
|
|
|
408
410
|
// ==================== 防抖机制:重置定时器 ====================
|
|
409
411
|
// 清除之前的定时器
|
|
412
|
+
// 键盘移动嵌套图元后,也要同步扩展父图元,保持与鼠标拖拽行为一致。
|
|
413
|
+
if (hasNestedSelection) {
|
|
414
|
+
selectedShapes.forEach(shape => {
|
|
415
|
+
const currentShape = graphStore.shapeMap.get(shape.id);
|
|
416
|
+
if (currentShape?.parenShapeId) {
|
|
417
|
+
graphStore.expandParentAndEmitSizeUpdateByChild(currentShape);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
adjustCanvasToFitAllShapes();
|
|
421
|
+
}
|
|
422
|
+
|
|
410
423
|
if (keyboardMoveTimer !== null) {
|
|
411
424
|
window.clearTimeout(keyboardMoveTimer);
|
|
412
425
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|