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

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.
@@ -0,0 +1,212 @@
1
+ <template>
2
+ <!-- 名称虚线框(选中时显示) -->
3
+ <div
4
+ v-if="
5
+ selectedShape &&
6
+ selectedShape.nameBounds &&
7
+ !isEditingName &&
8
+ selectedShape.shapeKey !== 'ConceptRole'
9
+ "
10
+ class="name-text-box-container"
11
+ :style="computedNameTextBoxContainerStyle"
12
+ >
13
+ <div
14
+ class="name-text-box"
15
+ :style="computedNameTextBoxStyle"
16
+ title="点击编辑名称"
17
+ @click="handleNameTextBoxClick"
18
+ ></div>
19
+ </div>
20
+
21
+ <!-- 名称编辑输入框 -->
22
+ <div
23
+ v-if="
24
+ isEditingName &&
25
+ selectedShape &&
26
+ selectedShape.shapeKey !== 'ConceptRole'
27
+ "
28
+ class="name-editor-container"
29
+ :style="computedNameEditorContainerStyle"
30
+ >
31
+ <input
32
+ ref="nameInput"
33
+ v-model="localEditingName"
34
+ class="name-input"
35
+ :style="computedNameInputStyle"
36
+ @blur="handleBlur"
37
+ @keyup.enter="handleKeyUp($event)"
38
+ @keyup.escape="handleKeyUp($event)"
39
+ />
40
+ </div>
41
+ </template>
42
+
43
+ <script setup lang="ts">
44
+ import { ref, watch, computed, nextTick, type CSSProperties } from 'vue';
45
+ import type { Shape } from '../types';
46
+ import { nameTextBoxContainerStyle, nameTextBoxStyle, nameEditorContainerStyle, nameInputStyle } from '../utils/diagram';
47
+ import type { NameEditManager } from '../utils/nameEditUtils';
48
+
49
+ // 定义组件的props
50
+ interface NameEditorProps {
51
+ selectedShape: Shape | null;
52
+ canEdit: boolean;
53
+ isEditingName: boolean;
54
+ editingName: string;
55
+ nameEditManager: NameEditManager;
56
+ }
57
+
58
+ // 定义组件的事件
59
+ const emit = defineEmits<{
60
+ (e: 'editName', shape: Shape, newName: string, oldName: string): void;
61
+ }>();
62
+
63
+ // 获取props
64
+ const props = defineProps<NameEditorProps>();
65
+
66
+ // 名称输入框引用
67
+ const nameInput = ref<HTMLInputElement | null>(null);
68
+
69
+ // 创建本地ref存储输入值
70
+ const localEditingName = ref(props.editingName);
71
+
72
+ // 监听props.editingName的变化,同步到本地ref
73
+ watch(() => props.editingName, (newValue) => {
74
+ localEditingName.value = newValue;
75
+ });
76
+
77
+ // 监听nameInput ref变化,将其传递给NameEditManager
78
+ watch(() => nameInput.value, (newValue) => {
79
+ if (newValue) {
80
+ props.nameEditManager.setNameInput(newValue);
81
+ }
82
+ });
83
+
84
+ // 监听本地输入值的变化,同步到nameEditManager
85
+ watch(() => localEditingName.value, (newValue) => {
86
+ // 更新NameEditManager中的editingName状态
87
+ (props.nameEditManager as any).editingName.value = newValue;
88
+ });
89
+
90
+ // 监听selectedShape变化,如果编辑中的形状不是当前选中的形状,取消编辑
91
+ watch(() => props.selectedShape, (newShape) => {
92
+ if (props.isEditingName && (!newShape || newShape.id !== props.selectedShape?.id)) {
93
+ props.nameEditManager.cancelEdit();
94
+ }
95
+ });
96
+
97
+ // 计算名称虚线框容器样式
98
+ const computedNameTextBoxContainerStyle = computed<CSSProperties>(() => {
99
+ if (!props.selectedShape) return {};
100
+ return nameTextBoxContainerStyle(props.selectedShape.id);
101
+ });
102
+
103
+ // 计算名称虚线框样式
104
+ const computedNameTextBoxStyle = computed<CSSProperties>(() => {
105
+ if (!props.selectedShape) return {};
106
+ return nameTextBoxStyle(props.selectedShape);
107
+ });
108
+
109
+ // 计算名称编辑器容器样式
110
+ const computedNameEditorContainerStyle = computed<CSSProperties>(() => {
111
+ if (!props.selectedShape) return {};
112
+ return nameEditorContainerStyle(props.selectedShape);
113
+ });
114
+
115
+ // 计算名称输入框样式
116
+ const computedNameInputStyle = computed<CSSProperties>(() => {
117
+ if (!props.selectedShape) return {};
118
+ return nameInputStyle(props.selectedShape);
119
+ });
120
+
121
+ // 处理名称虚线框点击事件
122
+ const handleNameTextBoxClick = () => {
123
+ if (props.canEdit && props.nameEditManager.canEdit(props.selectedShape)) {
124
+ startEditName();
125
+ }
126
+ };
127
+
128
+ // 开始编辑名称
129
+ const startEditName = async () => {
130
+ await props.nameEditManager.startEdit(props.selectedShape);
131
+ };
132
+
133
+ // 处理失焦事件
134
+ const handleBlur = () => {
135
+ props.nameEditManager.handleBlur(props.selectedShape);
136
+ };
137
+
138
+ // 处理键盘事件
139
+ const handleKeyUp = (event: KeyboardEvent) => {
140
+ props.nameEditManager.handleKeyUp(event, props.selectedShape);
141
+ };
142
+
143
+ // 暴露方法给父组件
144
+ defineExpose({
145
+ startEditName,
146
+ canEdit: (shape: Shape | null) => props.nameEditManager.canEdit(shape),
147
+ cancelEdit: () => props.nameEditManager.cancelEdit(),
148
+ });
149
+ </script>
150
+
151
+ <style scoped>
152
+ /* 名称虚线框容器 */
153
+ .name-text-box-container {
154
+ position: absolute;
155
+ z-index: 1001;
156
+ pointer-events: all;
157
+ }
158
+
159
+ /* 名称虚线框 */
160
+ .name-text-box {
161
+ border: 1px dashed #007bff;
162
+ background: rgba(255, 255, 255, 0.2);
163
+ cursor: pointer;
164
+ pointer-events: all;
165
+ transition: all 0.2s ease;
166
+ border-radius: 4px;
167
+ box-shadow: 0 0 0 1px rgba(0, 123, 255, 0.1);
168
+ height: 100%;
169
+ display: flex;
170
+ align-items: center;
171
+ justify-content: center;
172
+ }
173
+
174
+ .name-text-box:hover {
175
+ border-color: #0056b3;
176
+ background: rgba(0, 123, 255, 0.05);
177
+ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.2);
178
+ transform: scale(1.02);
179
+ }
180
+
181
+ /* 名称编辑器容器 */
182
+ .name-editor-container {
183
+ position: absolute;
184
+ z-index: 1002;
185
+ display: flex;
186
+ justify-content: center;
187
+ align-items: center;
188
+ pointer-events: all;
189
+ }
190
+
191
+ /* 名称输入框 */
192
+ .name-input {
193
+ width: calc(100% - 20px);
194
+ padding: 2px 4px;
195
+ border: 2px solid #007bff;
196
+ border-radius: 6px;
197
+ font-size: 12px;
198
+ font-weight: 600;
199
+ background: #fff;
200
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
201
+ outline: none;
202
+ text-align: center;
203
+ font-family: inherit;
204
+ resize: none;
205
+ overflow: hidden;
206
+ }
207
+
208
+ .name-input:focus {
209
+ border-color: #0056b3;
210
+ box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
211
+ }
212
+ </style>
@@ -0,0 +1,189 @@
1
+ <template>
2
+ <div class="selection-box" :style="getSelectionBoxStyle(shape)">
3
+ <!-- 只有当shapeType不是edge且不是conceptualRole时才渲染四个角手柄 -->
4
+ <div class="resize-handles" v-show="!isBusy && shape.shapeType !== 'edge'">
5
+ <div
6
+ v-for="h in resizeHandles"
7
+ :key="h.position"
8
+ class="resize-handle"
9
+ :class="[`resize-${h.position}`, { 'is-disabled': isMultiSelected }]"
10
+ :style="getHandleStyle(h, shape)"
11
+ @mousedown.stop.prevent="onHandleMouseDown($event, h.position)"
12
+ />
13
+ </div>
14
+ <div
15
+ class="action-buttons"
16
+ v-show="shouldShowActionButtons"
17
+ :style="actionButtonsStyle(shape)"
18
+ >
19
+ <div v-show="shape.modelTypePropertyId" class="border-btn">
20
+ <button
21
+ class="action-btn edit-btn"
22
+ @mousedown.stop.prevent="onModelTypePropertyIdClick"
23
+ title="设置类型"
24
+ >
25
+ <img src="../statics/icons/childIcons/设置类型.png" alt="设置类型" />
26
+ </button>
27
+ </div>
28
+ <button
29
+ v-for="value in shape.scenarioMenus"
30
+ :key="value.code"
31
+ class="action-btn edit-btn"
32
+ @mousedown.stop.prevent="onActionButtonClick(value.code)"
33
+ @click.stop.prevent
34
+ :title="value.name"
35
+ >
36
+ <img :src="getIcon('childIcons', value.icon || '')" />
37
+ </button>
38
+ </div>
39
+ </div>
40
+ </template>
41
+
42
+ <script setup lang="ts">
43
+ import { computed } from "vue";
44
+ import type { Shape } from "../types";
45
+ import { resizeHandles } from "../constants/index";
46
+ import {
47
+ selectionBoxStyle,
48
+ handleStyle,
49
+ actionButtonsStyle,
50
+ ShapeConfig,
51
+ } from "../utils/diagram";
52
+ import { getIcon } from "../utils/iconLoader";
53
+
54
+ // Props
55
+ const props = defineProps<{
56
+ shape: Shape;
57
+ isBusy: boolean;
58
+ isMultiSelected: boolean;
59
+ }>();
60
+
61
+ // 计算属性:是否显示操作按钮
62
+ const shouldShowActionButtons = computed(() => {
63
+ return !props.isMultiSelected &&
64
+ props.shape.scenarioMenus &&
65
+ props.shape.scenarioMenus.length > 0 &&
66
+ props.shape.shapeType != ShapeConfig.SHAPE_TYPE;
67
+ });
68
+
69
+ // Emits
70
+ const emit = defineEmits<{
71
+ (
72
+ e: "resize-start",
73
+ event: MouseEvent,
74
+ position: "nw" | "ne" | "sw" | "se",
75
+ shape: Shape
76
+ ): void;
77
+ (e: "action-button-click", code: string, shape: Shape): void;
78
+ (e: "model-type-property-id-click", value: string, shape: Shape): void;
79
+ }>();
80
+
81
+ // Methods
82
+ const getSelectionBoxStyle = (shape: Shape) => selectionBoxStyle(shape);
83
+ const getHandleStyle = (h: any, shape: Shape) => handleStyle(h.position, shape);
84
+
85
+ // Event handlers
86
+ const onHandleMouseDown = (
87
+ event: MouseEvent,
88
+ position: "nw" | "ne" | "sw" | "se"
89
+ ) => {
90
+ emit("resize-start", event, position, props.shape);
91
+ };
92
+
93
+ const onActionButtonClick = (code: string) => {
94
+ emit("action-button-click", code, props.shape);
95
+ };
96
+
97
+ const onModelTypePropertyIdClick = () => {
98
+ if (props.shape.modelTypePropertyId) {
99
+ emit(
100
+ "model-type-property-id-click",
101
+ props.shape.modelTypePropertyId,
102
+ props.shape
103
+ );
104
+ }
105
+ };
106
+ </script>
107
+
108
+ <style scoped>
109
+ .selection-box {
110
+ pointer-events: none;
111
+ background: transparent;
112
+ }
113
+
114
+ .resize-handles {
115
+ position: relative;
116
+ width: 100%;
117
+ height: 100%;
118
+ }
119
+
120
+ .resize-handle {
121
+ position: absolute;
122
+ width: 10px;
123
+ height: 10px;
124
+ background-color: #007bff;
125
+ border: 2px solid #fff;
126
+ border-radius: 50%;
127
+ pointer-events: all;
128
+ transition: all 0.2s ease;
129
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
130
+ z-index: 999;
131
+ }
132
+
133
+ .resize-handle.is-disabled {
134
+ cursor: default !important;
135
+ }
136
+
137
+ .resize-handle:hover {
138
+ background-color: #0056b3;
139
+ transform: scale(1.2);
140
+ }
141
+
142
+ .action-buttons {
143
+ display: flex;
144
+ flex-direction: column;
145
+ gap: 4px;
146
+ pointer-events: all;
147
+ background: rgba(255, 255, 255, 0.95);
148
+ padding: 6px;
149
+ border-radius: 4px;
150
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
151
+ border: 1px solid #e0e0e0;
152
+ backdrop-filter: blur(2px);
153
+ }
154
+
155
+ .action-btn {
156
+ width: 28px;
157
+ height: 28px;
158
+ border: 1px solid #d0d0d0;
159
+ border-radius: 3px;
160
+ background: linear-gradient(to bottom, #f8f9fa, #e9ecef);
161
+ cursor: pointer;
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: center;
165
+ font-size: 12px;
166
+ font-weight: bold;
167
+ font-family: "Arial", sans-serif;
168
+ color: #495057;
169
+ transition: all 0.2s ease;
170
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
171
+ }
172
+
173
+ .action-btn:hover {
174
+ background: linear-gradient(to bottom, #e3f2fd, #bbdefb);
175
+ border-color: #90caf9;
176
+ transform: translateY(-1px);
177
+ box-shadow: 0 2px 4px rgba(33, 150, 243, 0.3);
178
+ color: #1976d2;
179
+ }
180
+
181
+ .edit-btn:hover {
182
+ background: #e3f2fd;
183
+ }
184
+
185
+ .border-btn {
186
+ padding-bottom: 4px;
187
+ border-bottom: 1px solid #e0e0e0;
188
+ }
189
+ </style>
@@ -228,7 +228,9 @@ export const BlockKeyMap = {
228
228
  'ArbitraryRelationship':'Edge',//任意关系
229
229
  'DirectedRelationship':'Edge',//定向关系
230
230
  'OperationalControlFlow':'Edge',//业务控制流
231
+ 'OperationalObjectFlow':'Edge',//业务对象流
231
232
  'FunctionControlFlow':'Edge',//功能控制流
233
+ 'FunctionObjectFlow': 'Edge', // 功能对象流
232
234
  'ServiceConnector':'Edge',//服务连接器
233
235
  'ServiceControlFlow':'Edge',//服务控制流
234
236
  "ServiceObjectFlow": 'Edge', // 服务对象流
@@ -1,5 +1,7 @@
1
1
  import { ref, type Ref } from 'vue';
2
2
  import { eventBus } from '../store';
3
+ import _ from 'lodash';
4
+ import { getUuid } from '../utils/index';
3
5
 
4
6
  // 菜单位置接口
5
7
  export interface MenuPosition {
@@ -40,6 +42,9 @@ const DEFAULT_MENU_CONFIG: Required<MenuConfig> = {
40
42
 
41
43
  // 右键菜单工具函数
42
44
  export class ContextMenuUtils {
45
+ // 用于存储复制的图元
46
+ private static copiedShapes: any[] = [];
47
+
43
48
  /**
44
49
  * 处理右键菜单点击事件
45
50
  * @param event 鼠标事件
@@ -73,7 +78,7 @@ export class ContextMenuUtils {
73
78
  // 使用命中测试找到点击的图元
74
79
  const hit = pickTarget(shapes, point);
75
80
 
76
- if (hit.kind === "shape" && hit.shape) {
81
+ if ((hit.kind === "shape" || hit.kind === "pin") && hit.shape) {
77
82
  // 选中图元
78
83
  if (selectShape) {
79
84
  selectShape(hit.shape);
@@ -174,11 +179,27 @@ export class ContextMenuUtils {
174
179
  }
175
180
  }
176
181
 
182
+ /**
183
+ * 设置复制的图元
184
+ */
185
+ static setCopiedShapes(shapes: any[]) {
186
+ this.copiedShapes = _.cloneDeep(shapes);
187
+ console.log('已复制的图元:', this.copiedShapes);
188
+ }
189
+
190
+ /**
191
+ * 获取复制的图元
192
+ */
193
+ static getCopiedShapes(): any[] {
194
+ return this.copiedShapes;
195
+ }
196
+
177
197
  /**
178
198
  * 处理复制
179
199
  */
180
200
  static handleCopy(target: any) {
181
201
  if (target) {
202
+ this.setCopiedShapes([target]);
182
203
  eventBus.emit('copy-shape', target);
183
204
  }
184
205
  }
@@ -187,9 +208,40 @@ export class ContextMenuUtils {
187
208
  * 处理粘贴
188
209
  */
189
210
  static handlePaste(target: any) {
190
- if (target) {
191
- eventBus.emit('paste-shape', target);
211
+ if (this.copiedShapes.length === 0) {
212
+ return;
192
213
  }
214
+
215
+ // 设置粘贴位置(画布左上角50像素处)
216
+ const pasteX = 50;
217
+ const pasteY = 50;
218
+
219
+ // 为每个复制的图元创建新的副本
220
+ const pastedShapes: any[] = [];
221
+
222
+ this.copiedShapes.forEach(shape => {
223
+ // 深拷贝图元
224
+ const newShape = _.cloneDeep(shape);
225
+
226
+ // 生成新的ID
227
+ newShape.id = getUuid();
228
+
229
+ // 更新位置到画布左上角50像素处
230
+ if (newShape.bounds) {
231
+ newShape.bounds.x = pasteX;
232
+ newShape.bounds.y = pasteY;
233
+ }
234
+
235
+ pastedShapes.push(newShape);
236
+ });
237
+
238
+ // 通过事件总线通知添加图元
239
+ eventBus.emit('paste-shapes', pastedShapes);
240
+
241
+ // 通过事件总线通知选中新粘贴的图元
242
+ eventBus.emit('select-shapes', pastedShapes.map(s => s.id));
243
+
244
+ console.log('已粘贴的图元:', pastedShapes);
193
245
  }
194
246
 
195
247
  /**
@@ -259,6 +311,11 @@ export const defaultMenuItems: MenuItemConfig[] = [
259
311
  ];
260
312
 
261
313
  // 标准右键菜单配置
262
- export const standardContextMenuConfig: MenuConfig = {
263
- items: defaultMenuItems
264
- };
314
+ // export const standardContextMenuConfig: MenuConfig = {
315
+ // items: defaultMenuItems.map(item => {
316
+ // if (item.id === 'copy' || item.id === 'paste') {
317
+ // return { ...item, disabled: false };
318
+ // }
319
+ // return item;
320
+ // })
321
+ // };
@@ -375,13 +375,17 @@ export const nameInputStyle = (shape: Shape): Record<string, string> => {
375
375
  * 名称编辑容器样式 - 确保在父组件内水平居中
376
376
  */
377
377
  export const nameEditorContainerStyle = (shape: Shape): Record<string, string> => {
378
- const b = shape.bounds ?? {} as any
379
- const nb = (shape as any).nameBounds ?? {} as any
380
- const ns = (shape as any).nameStyle ?? {} as any
378
+ // 使用shape.id重新从store获取最新的图元信息,确保位置是最新的
379
+ const graphStore = useGraphStore();
380
+ const latestShape = graphStore.shapes.find(s => s.id === shape.id) || shape;
381
+
382
+ const b = latestShape.bounds ?? {} as any
383
+ const nb = (latestShape as any).nameBounds ?? {} as any
384
+ const ns = (latestShape as any).nameStyle ?? {} as any
381
385
 
382
- if ((shape as any).shapeType === 'pin' && (nb.x != null) && (nb.y != null)) {
386
+ if ((latestShape as any).shapeType === 'pin' && (nb.x != null) && (nb.y != null)) {
383
387
  const fontSize = Number(ns.fontSize || nb.height || 12)
384
- const textLen = (shape.name?.length || 0)
388
+ const textLen = (latestShape.name?.length || 0)
385
389
  const textWidth = Math.max(10, textLen * fontSize * 0.6)
386
390
  const boxW = Math.min(300, Math.max(40, textWidth + 14))
387
391
  const boxH = Math.max(22, fontSize + 10)
@@ -403,18 +407,18 @@ export const nameEditorContainerStyle = (shape: Shape): Record<string, string> =
403
407
  else top = yAbs - fontSize
404
408
 
405
409
  return {
406
- position: 'absolute',
407
- left: `${Math.round(left)}px`,
408
- top: `${Math.round(top)}px`,
409
- width: `${Math.round(boxW)}px`,
410
- height: `${Math.round(boxH)}px`,
411
- display: 'block',
412
- zIndex: '1001',
413
- }
410
+ position: 'absolute',
411
+ left: `${Math.round(left)}px`,
412
+ top: `${Math.round(top)}px`,
413
+ width: `${Math.round(boxW)}px`,
414
+ height: `${Math.round(boxH)}px`,
415
+ display: 'block',
416
+ zIndex: '1001',
414
417
  }
418
+ }
415
419
 
416
- const shapeBounds = shape.bounds ?? {};
417
- const nameBounds = shape.nameBounds ?? {};
420
+ const shapeBounds = latestShape.bounds ?? {};
421
+ const nameBounds = latestShape.nameBounds ?? {};
418
422
 
419
423
  // 计算text name在画布中的绝对位置
420
424
  const absoluteY = (shapeBounds.y ?? 0) + (nameBounds.y ?? 0);
@@ -10,6 +10,8 @@ interface KeyboardConfig {
10
10
  onCancelConnection?: () => void;
11
11
  onShapesRemove?: (items: Array<{ modelId: string; shapeId: string; shapeType: string; isRemoveModelTree: boolean }>) => void;
12
12
  isEditingName?: () => boolean;
13
+ onCopy?: () => void;
14
+ onPaste?: () => void;
13
15
  }
14
16
 
15
17
  /**
@@ -124,6 +126,32 @@ export const createKeyboardHandler = (config: KeyboardConfig): KeyboardEventHand
124
126
  }
125
127
  }
126
128
 
129
+ // 按下Ctrl+C时复制选中的图元
130
+ if ((e.ctrlKey || e.metaKey) && e.key === 'c' && graphStore.museInGraphView && !isInputElement) {
131
+ // 如果正在编辑名称,不执行复制功能
132
+ if (config.isEditingName && config.isEditingName()) {
133
+ return;
134
+ }
135
+
136
+ e.preventDefault();
137
+ if (config.onCopy) {
138
+ config.onCopy();
139
+ }
140
+ }
141
+
142
+ // 按下Ctrl+V时粘贴选中的图元
143
+ if ((e.ctrlKey || e.metaKey) && e.key === 'v' && graphStore.museInGraphView && !isInputElement) {
144
+ // 如果正在编辑名称,不执行粘贴功能
145
+ if (config.isEditingName && config.isEditingName()) {
146
+ return;
147
+ }
148
+
149
+ e.preventDefault();
150
+ if (config.onPaste) {
151
+ config.onPaste();
152
+ }
153
+ }
154
+
127
155
  // 按下方向键时移动选中的图元(不在输入框或文本域中时)
128
156
  if ((e.key === 'ArrowUp' || e.key === 'ArrowDown' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') && graphStore.museInGraphView && !isInputElement) {
129
157
  // 如果正在编辑名称,不执行移动功能
@@ -11,7 +11,7 @@ export interface NameEditOptions {
11
11
  export class NameEditManager {
12
12
  private isEditing: Ref<boolean>;
13
13
  private editingName: Ref<string>;
14
- private nameInput: Ref<HTMLInputElement | undefined>;
14
+ private nameInput: Ref<HTMLInputElement | undefined | null>;
15
15
  private options: NameEditOptions;
16
16
 
17
17
  constructor(options: NameEditOptions = {}) {
@@ -30,6 +30,11 @@ export class NameEditManager {
30
30
  };
31
31
  }
32
32
 
33
+ // 设置名称输入框引用
34
+ setNameInput(input: HTMLInputElement | null) {
35
+ this.nameInput.value = input;
36
+ }
37
+
33
38
  // 开始编辑名称
34
39
  async startEdit(shape: Shape | null): Promise<void> {
35
40
  if (!shape || this.isEditing.value) return;
@@ -1 +0,0 @@
1
- export const packageMap = ['Strategic']