@mx-sose-front/mx-sose-graph 1.1.7 → 1.1.9
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/assets/edgeWorker-b57ca007.js +2 -0
- package/dist/assets/edgeWorker-b57ca007.js.map +1 -0
- package/dist/index.d.ts +633 -30
- package/dist/index.esm.js +8728 -4734
- 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/Common/Tree.vue +451 -0
- package/src/components/Common/index.ts +2 -0
- package/src/components/DiagramListTooltip/DiagramListTooltip.vue +1 -2
- package/src/components/Edge/Edge.vue +172 -169
- package/src/components/Gantt/Gantt.vue +1544 -0
- package/src/components/GanttContextMenu/GanttContextMenu.vue +304 -0
- package/src/components/InteractionLayer.vue +343 -147
- package/src/components/Matrix/Matrix.vue +828 -0
- package/src/components/Matrix/index.ts +168 -0
- package/src/components/Shape/ConceptualRole.vue +2 -34
- package/src/components/Table/Table.vue +970 -0
- package/src/constants/edgeShapeKeys.ts +8 -5
- package/src/constants/index.ts +259 -45
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useChartRowSelection.ts +456 -0
- package/src/hooks/useResize.ts +2 -2
- package/src/hooks/useVirtualScroll.ts +258 -0
- package/src/index.ts +1 -1
- package/src/render/shape-renderer.ts +62 -2
- package/src/statics/icons/childIcons//345/221/275/344/273/244@3x.png +0 -0
- package/src/statics/icons/childIcons//346/210/230/347/225/245/346/246/202/345/277/265/350/241/250@3x.png +0 -0
- package/src/statics/icons/childIcons//346/216/247/345/210/266@3x.png +0 -0
- package/src/statics/icons/createMenu/down.png +0 -0
- package/src/statics/icons/createMenu/remove.png +0 -0
- package/src/statics/icons/createMenu/up.png +0 -0
- package/src/store/graphStore.ts +217 -44
- package/src/types/index.ts +86 -4
- package/src/utils/batchAutoExpand.ts +9 -10
- package/src/utils/containers.ts +72 -17
- package/src/utils/contextMenuUtils.ts +7 -7
- package/src/utils/dateUtils.ts +160 -0
- package/src/utils/diagram.ts +10 -8
- package/src/utils/drag.ts +6 -5
- package/src/utils/edgeUtils.ts +344 -427
- package/src/utils/edgeWorker.ts +471 -0
- package/src/utils/hittest.ts +37 -38
- package/src/utils/index.ts +3 -0
- package/src/utils/keyboardUtils.ts +5 -5
- package/src/utils/packageOutline.ts +96 -0
- package/src/utils/rafThrottle.ts +162 -0
- package/src/utils/workerManager.ts +335 -0
- package/src/view/graph.vue +47 -33
- /package/src/statics/icons/childIcons//346/210/230/347/225/{245@3x.png" → 245/345/261/202@3x.png"} +0 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<teleport to="body">
|
|
3
|
+
<div
|
|
4
|
+
v-if="visible"
|
|
5
|
+
class="gantt-context-menu px-[6px]"
|
|
6
|
+
:style="dynamicMenuStyle"
|
|
7
|
+
@contextmenu.prevent
|
|
8
|
+
@click.stop
|
|
9
|
+
ref="menuRef"
|
|
10
|
+
>
|
|
11
|
+
<!-- 属性配置 -->
|
|
12
|
+
<div class="menu-item" @click="handlePropertyConfig">
|
|
13
|
+
<div class="flex items-center box-border border-b-[1px] border-solid border-[#DCDFE6]">
|
|
14
|
+
<img :src="getIcon('createMenu', 'config')" class="w-[18px] h-[18px] mr-[10px] ml-[2px]" alt="属性配置" />
|
|
15
|
+
<span>属性配置</span>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<!-- 树上高亮 -->
|
|
20
|
+
<div class="menu-item" @click="handleTreeHighlight">
|
|
21
|
+
<div class="flex items-center box-border border-b-[1px] border-solid border-[#DCDFE6]">
|
|
22
|
+
<img :src="getIcon('createMenu', 'tree')" class="w-[18px] h-[18px] mr-[10px] ml-[2px]" alt="树上高亮" />
|
|
23
|
+
<span>树上高亮</span>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<!-- 上移 -->
|
|
28
|
+
<div class="menu-item" :class="{ 'menu-disabled': !canMoveUp }" @click="handleMoveUp">
|
|
29
|
+
<div class="flex items-center box-border border-b-[1px] border-solid border-[#DCDFE6]">
|
|
30
|
+
<img :src="getIcon('createMenu', 'up')" class="w-[18px] h-[18px] mr-[10px] ml-[2px]" alt="上移" />
|
|
31
|
+
<span>上移</span>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<!-- 下移 -->
|
|
36
|
+
<div class="menu-item" :class="{ 'menu-disabled': !canMoveDown }" @click="handleMoveDown">
|
|
37
|
+
<div class="flex items-center box-border border-b-[1px] border-solid border-[#DCDFE6]">
|
|
38
|
+
<img :src="getIcon('createMenu', 'down')" class="w-[18px] h-[18px] mr-[10px] ml-[2px]" alt="下移" />
|
|
39
|
+
<span>下移</span>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<!-- 删除 -->
|
|
44
|
+
<div class="menu-item" @click="handleDelete">
|
|
45
|
+
<div class="flex items-center box-border border-b-[1px] border-solid border-[#DCDFE6]">
|
|
46
|
+
<img :src="getIcon('createMenu', 'delete')" class="w-[18px] h-[18px] mr-[10px] ml-[2px]" alt="删除" />
|
|
47
|
+
<span>删除</span>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<!-- 移除 -->
|
|
52
|
+
<div class="menu-item" @click="handleRemove">
|
|
53
|
+
<div class="flex items-center">
|
|
54
|
+
<img :src="getIcon('createMenu', 'remove')" class="w-[18px] h-[18px] mr-[10px] ml-[2px]" alt="移除" />
|
|
55
|
+
<span>移除</span>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</teleport>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<script setup lang="ts">
|
|
63
|
+
import { ref, watch, onMounted, onUnmounted, type CSSProperties } from 'vue'
|
|
64
|
+
import { getIcon } from '../../utils/iconLoader'
|
|
65
|
+
|
|
66
|
+
interface Props {
|
|
67
|
+
visible: boolean
|
|
68
|
+
position: {
|
|
69
|
+
x: number
|
|
70
|
+
y: number
|
|
71
|
+
}
|
|
72
|
+
canMoveUp: boolean
|
|
73
|
+
canMoveDown: boolean
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const props = defineProps<Props>()
|
|
77
|
+
|
|
78
|
+
const emit = defineEmits<{
|
|
79
|
+
(e: 'update:visible', value: boolean): void
|
|
80
|
+
(e: 'property-config'): void
|
|
81
|
+
(e: 'tree-highlight'): void
|
|
82
|
+
(e: 'move-up'): void
|
|
83
|
+
(e: 'move-down'): void
|
|
84
|
+
(e: 'delete'): void
|
|
85
|
+
(e: 'remove'): void
|
|
86
|
+
}>()
|
|
87
|
+
|
|
88
|
+
const menuRef = ref<HTMLElement | null>(null)
|
|
89
|
+
|
|
90
|
+
// 菜单尺寸常量
|
|
91
|
+
const MENU_WIDTH = 180
|
|
92
|
+
const MENU_HEIGHT = 240 // 估算菜单高度
|
|
93
|
+
const SAFE_MARGIN = 10
|
|
94
|
+
|
|
95
|
+
// 动态菜单样式
|
|
96
|
+
const dynamicMenuStyle = ref<CSSProperties>({
|
|
97
|
+
left: '0px',
|
|
98
|
+
top: '0px',
|
|
99
|
+
display: 'none',
|
|
100
|
+
position: 'fixed',
|
|
101
|
+
zIndex: '9999',
|
|
102
|
+
minWidth: `${MENU_WIDTH}px`,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// 计算并更新菜单位置
|
|
106
|
+
const updateMenuPosition = () => {
|
|
107
|
+
if (!props.visible) {
|
|
108
|
+
dynamicMenuStyle.value = { ...dynamicMenuStyle.value, display: 'none' }
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 获取视口尺寸
|
|
113
|
+
const viewportWidth = window.innerWidth
|
|
114
|
+
const viewportHeight = window.innerHeight
|
|
115
|
+
|
|
116
|
+
// 初始位置
|
|
117
|
+
let left = props.position.x
|
|
118
|
+
let top = props.position.y
|
|
119
|
+
|
|
120
|
+
// 水平方向调整 - 确保不超出右侧边界
|
|
121
|
+
if (left + MENU_WIDTH > viewportWidth) {
|
|
122
|
+
left = viewportWidth - MENU_WIDTH - SAFE_MARGIN
|
|
123
|
+
}
|
|
124
|
+
// 确保不小于左侧边界
|
|
125
|
+
left = Math.max(SAFE_MARGIN, left)
|
|
126
|
+
|
|
127
|
+
// 垂直方向调整 - 确保不超出底部边界
|
|
128
|
+
if (top + MENU_HEIGHT > viewportHeight) {
|
|
129
|
+
top = viewportHeight - MENU_HEIGHT - SAFE_MARGIN
|
|
130
|
+
}
|
|
131
|
+
// 确保不小于顶部边界
|
|
132
|
+
top = Math.max(SAFE_MARGIN, top)
|
|
133
|
+
|
|
134
|
+
dynamicMenuStyle.value = {
|
|
135
|
+
left: `${left}px`,
|
|
136
|
+
top: `${top}px`,
|
|
137
|
+
display: 'block',
|
|
138
|
+
position: 'fixed',
|
|
139
|
+
zIndex: '9999',
|
|
140
|
+
minWidth: `${MENU_WIDTH}px`,
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 关闭菜单
|
|
145
|
+
const closeMenu = () => {
|
|
146
|
+
emit('update:visible', false)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 处理点击外部关闭菜单
|
|
150
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
151
|
+
if (!props.visible || !menuRef.value) return
|
|
152
|
+
|
|
153
|
+
if (!menuRef.value.contains(event.target as Node)) {
|
|
154
|
+
closeMenu()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 监听 props 变化
|
|
159
|
+
watch(
|
|
160
|
+
() => [props.visible, props.position],
|
|
161
|
+
() => {
|
|
162
|
+
updateMenuPosition()
|
|
163
|
+
|
|
164
|
+
// 当菜单显示时,延迟添加点击外部关闭的监听
|
|
165
|
+
if (props.visible) {
|
|
166
|
+
// 使用 setTimeout 确保当前的右键点击事件已经完成
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
document.addEventListener('click', handleClickOutside, { capture: true })
|
|
169
|
+
}, 0)
|
|
170
|
+
} else {
|
|
171
|
+
// 菜单隐藏时移除监听
|
|
172
|
+
document.removeEventListener('click', handleClickOutside, { capture: true })
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{ immediate: true }
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
// 菜单项处理函数
|
|
179
|
+
const handlePropertyConfig = () => {
|
|
180
|
+
emit('property-config')
|
|
181
|
+
closeMenu()
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const handleTreeHighlight = () => {
|
|
185
|
+
emit('tree-highlight')
|
|
186
|
+
closeMenu()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const handleMoveUp = () => {
|
|
190
|
+
if (!props.canMoveUp) return
|
|
191
|
+
emit('move-up')
|
|
192
|
+
closeMenu()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const handleMoveDown = () => {
|
|
196
|
+
if (!props.canMoveDown) return
|
|
197
|
+
emit('move-down')
|
|
198
|
+
closeMenu()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const handleDelete = () => {
|
|
202
|
+
emit('delete')
|
|
203
|
+
closeMenu()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const handleRemove = () => {
|
|
207
|
+
emit('remove')
|
|
208
|
+
closeMenu()
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 处理窗口大小变化
|
|
212
|
+
const handleWindowResize = () => {
|
|
213
|
+
if (props.visible) {
|
|
214
|
+
updateMenuPosition()
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 组件挂载时添加事件监听
|
|
219
|
+
onMounted(() => {
|
|
220
|
+
window.addEventListener('resize', handleWindowResize)
|
|
221
|
+
updateMenuPosition()
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
// 组件卸载时移除事件监听
|
|
225
|
+
onUnmounted(() => {
|
|
226
|
+
document.removeEventListener('click', handleClickOutside, { capture: true })
|
|
227
|
+
window.removeEventListener('resize', handleWindowResize)
|
|
228
|
+
})
|
|
229
|
+
</script>
|
|
230
|
+
|
|
231
|
+
<style scoped lang="scss">
|
|
232
|
+
.gantt-context-menu {
|
|
233
|
+
background-color: #fff;
|
|
234
|
+
border: 1px solid #ebeef5;
|
|
235
|
+
border-radius: 6px;
|
|
236
|
+
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
237
|
+
padding: 6px 0;
|
|
238
|
+
overflow-y: auto;
|
|
239
|
+
box-sizing: border-box;
|
|
240
|
+
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
241
|
+
transform-origin: top left;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.gantt-context-menu[style*='display: block'] {
|
|
245
|
+
animation: fadeIn 0.2s ease forwards;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@keyframes fadeIn {
|
|
249
|
+
from {
|
|
250
|
+
opacity: 0;
|
|
251
|
+
transform: scale(0.95);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
to {
|
|
255
|
+
opacity: 1;
|
|
256
|
+
transform: scale(1);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* 滚动条优化 */
|
|
261
|
+
.gantt-context-menu::-webkit-scrollbar {
|
|
262
|
+
width: 6px;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.gantt-context-menu::-webkit-scrollbar-thumb {
|
|
266
|
+
background-color: #ddd;
|
|
267
|
+
border-radius: 3px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.gantt-context-menu::-webkit-scrollbar-track {
|
|
271
|
+
background-color: #f5f5f5;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.menu-item {
|
|
275
|
+
padding: 0 15px;
|
|
276
|
+
cursor: pointer;
|
|
277
|
+
font-size: 14px;
|
|
278
|
+
color: #606266;
|
|
279
|
+
border-radius: 4px;
|
|
280
|
+
height: 36px;
|
|
281
|
+
line-height: 36px;
|
|
282
|
+
box-sizing: border-box;
|
|
283
|
+
|
|
284
|
+
&:hover:not(.menu-disabled) {
|
|
285
|
+
background-color: #f5f7fa;
|
|
286
|
+
color: #303133;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* 置灰样式 */
|
|
291
|
+
.menu-disabled {
|
|
292
|
+
color: #c0c4cc !important;
|
|
293
|
+
cursor: not-allowed !important;
|
|
294
|
+
pointer-events: none;
|
|
295
|
+
|
|
296
|
+
&:hover {
|
|
297
|
+
background-color: transparent !important;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
img {
|
|
301
|
+
opacity: 0.5;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
</style>
|