@zhangqingcq/vgce 0.0.13 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +16 -2
- package/dist/style.css +1 -1
- package/dist/vgce.js +28 -34
- package/dist/vgce.umd.cjs +5 -5
- package/package.json +3 -2
- package/src/App.vue +11 -0
- package/src/assets/base.less +49 -0
- package/src/assets/icons/add.svg +1 -0
- package/src/assets/icons/delete.svg +12 -0
- package/src/assets/icons/export.svg +1 -0
- package/src/assets/icons/group.svg +13 -0
- package/src/assets/icons/import.svg +1 -0
- package/src/assets/icons/lock.svg +7 -0
- package/src/assets/icons/menu-fold.svg +9 -0
- package/src/assets/icons/menu-unfold.svg +9 -0
- package/src/assets/icons/preview.svg +6 -0
- package/src/assets/icons/redo.svg +8 -0
- package/src/assets/icons/return.svg +8 -0
- package/src/assets/icons/rotate.svg +1 -0
- package/src/assets/icons/save.svg +9 -0
- package/src/assets/icons/setting.svg +6 -0
- package/src/assets/icons/undo.svg +7 -0
- package/src/assets/icons/ungroup.svg +16 -0
- package/src/assets/icons/unlock.svg +7 -0
- package/src/assets/main.less +6 -0
- package/src/assets/svgs/alternator.svg +8 -0
- package/src/assets/svgs/bot-12.svg +1 -0
- package/src/assets/svgs/bot-2.svg +1 -0
- package/src/assets/svgs/bot-3.svg +1 -0
- package/src/assets/svgs/bot-7.svg +1 -0
- package/src/assets/svgs/bot-9.svg +94 -0
- package/src/assets/svgs/car.svg +1 -0
- package/src/assets/svgs/circuit-breaker.svg +11 -0
- package/src/assets/svgs/clock-a.svg +23 -0
- package/src/assets/svgs/common-table.svg +7 -0
- package/src/assets/svgs/el-button.svg +10 -0
- package/src/assets/svgs/el-tag.svg +13 -0
- package/src/assets/svgs/hospital.svg +1 -0
- package/src/assets/svgs/house.svg +1 -0
- package/src/assets/svgs/light.svg +24 -0
- package/src/assets/svgs/now-time.svg +9 -0
- package/src/assets/svgs/package.svg +1 -0
- package/src/assets/svgs/pie-charts.svg +10 -0
- package/src/assets/svgs/progress-a.svg +1 -0
- package/src/assets/svgs/reservoir.svg +10 -0
- package/src/assets/svgs/svg-text.svg +5 -0
- package/src/assets/svgs/switch-a.svg +5 -0
- package/src/assets/svgs/traction-transformer.svg +11 -0
- package/src/components/ace-edit/index.ts +27 -0
- package/src/components/config/index.ts +450 -0
- package/src/components/config/types.ts +25 -0
- package/src/components/svg-analysis/index.vue +11 -0
- package/src/components/svg-editor/center-panel/index.vue +867 -0
- package/src/components/svg-editor/center-panel/types.ts +11 -0
- package/src/components/svg-editor/component-tree/index.vue +33 -0
- package/src/components/svg-editor/connection-line/index.vue +125 -0
- package/src/components/svg-editor/connection-panel/index.vue +198 -0
- package/src/components/svg-editor/export-json/index.vue +37 -0
- package/src/components/svg-editor/handle-panel/index.vue +342 -0
- package/src/components/svg-editor/import-json/index.vue +37 -0
- package/src/components/svg-editor/index.vue +280 -0
- package/src/components/svg-editor/left-panel/index.vue +83 -0
- package/src/components/svg-editor/right-panel/code-edit-modal.vue +50 -0
- package/src/components/svg-editor/right-panel/common-animate.vue +96 -0
- package/src/components/svg-editor/right-panel/condition.vue +101 -0
- package/src/components/svg-editor/right-panel/dynamic-el-form-item.vue +97 -0
- package/src/components/svg-editor/right-panel/index.vue +304 -0
- package/src/components/svg-editor/right-panel/list.vue +86 -0
- package/src/components/svg-editor/top-panel/index.vue +139 -0
- package/src/components/svg-editor/types.ts +22 -0
- package/src/components/svg-viewer/index.vue +340 -0
- package/src/components/vue3-ruler-tool/index.vue +506 -0
- package/src/config/files/clock-a.vue +66 -0
- package/src/config/files/common-table.vue +49 -0
- package/src/config/files/light-a.vue +72 -0
- package/src/config/files/now-time.vue +53 -0
- package/src/config/files/pie-charts.vue +72 -0
- package/src/config/files/progress.vue +40 -0
- package/src/config/files/svg-text.vue +39 -0
- package/src/config/files/switch-a.vue +45 -0
- package/src/config/index.ts +28 -0
- package/src/config/svg/animation/index.ts +8 -0
- package/src/config/svg/animation/reservoir.ts +32 -0
- package/src/config/svg/custom/clock-a.ts +23 -0
- package/src/config/svg/custom/index.ts +11 -0
- package/src/config/svg/custom/light.ts +29 -0
- package/src/config/svg/custom/svg-text.ts +54 -0
- package/src/config/svg/custom/switch-a.ts +29 -0
- package/src/config/svg/index.ts +12 -0
- package/src/config/svg/stateful/circuit-breaker.ts +38 -0
- package/src/config/svg/stateful/index.ts +8 -0
- package/src/config/svg/stateless/alternator.ts +28 -0
- package/src/config/svg/stateless/bot-12.ts +22 -0
- package/src/config/svg/stateless/bot-2.ts +22 -0
- package/src/config/svg/stateless/bot-3.ts +22 -0
- package/src/config/svg/stateless/bot-7.ts +22 -0
- package/src/config/svg/stateless/bot-9.ts +22 -0
- package/src/config/svg/stateless/car.ts +22 -0
- package/src/config/svg/stateless/hospital.ts +22 -0
- package/src/config/svg/stateless/house.ts +22 -0
- package/src/config/svg/stateless/index.ts +30 -0
- package/src/config/svg/stateless/package.ts +22 -0
- package/src/config/svg/stateless/traction-transformer.ts +28 -0
- package/src/config/types.ts +126 -0
- package/src/config/vue/component/button.ts +57 -0
- package/src/config/vue/component/common-table.ts +124 -0
- package/src/config/vue/component/index.ts +13 -0
- package/src/config/vue/component/now-time.ts +29 -0
- package/src/config/vue/component/progress.ts +29 -0
- package/src/config/vue/component/tag.ts +46 -0
- package/src/config/vue/echarts/index.ts +8 -0
- package/src/config/vue/echarts/pie-charts.ts +60 -0
- package/src/config/vue/index.ts +5 -0
- package/src/hooks.ts +47 -0
- package/src/index.ts +14 -0
- package/src/main.ts +15 -0
- package/src/router.ts +24 -0
- package/src/stores/config/index.ts +44 -0
- package/src/stores/config/types.ts +27 -0
- package/src/stores/global/index.ts +109 -0
- package/src/stores/global/types.ts +115 -0
- package/src/stores/main.ts +10 -0
- package/src/stores/svg-edit-layout/index.ts +17 -0
- package/src/stores/svg-edit-layout/types.ts +8 -0
- package/src/stores/system/index.ts +174 -0
- package/src/stores/system/types.ts +43 -0
- package/src/utils/fetch.ts +351 -0
- package/src/utils/file-read-write.ts +26 -0
- package/src/utils/index.ts +397 -0
- package/src/utils/mqtt-net.ts +48 -0
- package/src/utils/proxy.ts +7 -0
- package/src/utils/scale-core.ts +214 -0
- package/src/utils/types.ts +13 -0
- package/src/views/EditorS.vue +18 -0
- package/src/views/Preview.vue +12 -0
@@ -0,0 +1,342 @@
|
|
1
|
+
<!-- 旋转缩放组件 -->
|
2
|
+
<script lang="ts" setup>
|
3
|
+
import { pinia } from '@/hooks'
|
4
|
+
import { useSvgEditLayoutStore } from '@/stores/svg-edit-layout'
|
5
|
+
import { ref } from 'vue'
|
6
|
+
import { useGlobalStore } from '@/stores/global'
|
7
|
+
import { EGlobalStoreIntention, EMouseInfoState, EScaleInfoType } from '@/stores/global/types'
|
8
|
+
import type { IDoneJson } from '@/stores/global/types'
|
9
|
+
import { getCoordinateOffset } from '@/utils'
|
10
|
+
|
11
|
+
const props = defineProps<{ itemInfo: IDoneJson }>()
|
12
|
+
const globalStore = useGlobalStore(pinia)
|
13
|
+
const svgEditLayoutStore = useSvgEditLayoutStore(pinia)
|
14
|
+
const offset = ref(4)
|
15
|
+
const fill = ref('#4F80FF')
|
16
|
+
const angle_to_cursor = [
|
17
|
+
{
|
18
|
+
start: 338,
|
19
|
+
end: 23,
|
20
|
+
cursor: 'nw',
|
21
|
+
type: EScaleInfoType.TopLeft
|
22
|
+
},
|
23
|
+
{
|
24
|
+
start: 23,
|
25
|
+
end: 68,
|
26
|
+
cursor: 'n',
|
27
|
+
type: EScaleInfoType.TopCenter
|
28
|
+
},
|
29
|
+
{
|
30
|
+
start: 68,
|
31
|
+
end: 113,
|
32
|
+
cursor: 'ne',
|
33
|
+
type: EScaleInfoType.TopRight
|
34
|
+
},
|
35
|
+
{
|
36
|
+
start: 293,
|
37
|
+
end: 338,
|
38
|
+
cursor: 'w',
|
39
|
+
type: EScaleInfoType.Left
|
40
|
+
},
|
41
|
+
{
|
42
|
+
start: 113,
|
43
|
+
end: 158,
|
44
|
+
cursor: 'e',
|
45
|
+
type: EScaleInfoType.Right
|
46
|
+
},
|
47
|
+
{
|
48
|
+
start: 248,
|
49
|
+
end: 293,
|
50
|
+
cursor: 'sw',
|
51
|
+
type: EScaleInfoType.BottomLeft
|
52
|
+
},
|
53
|
+
{
|
54
|
+
start: 203,
|
55
|
+
end: 248,
|
56
|
+
cursor: 's',
|
57
|
+
type: EScaleInfoType.BottomCenter
|
58
|
+
},
|
59
|
+
{
|
60
|
+
start: 158,
|
61
|
+
end: 203,
|
62
|
+
cursor: 'se',
|
63
|
+
type: EScaleInfoType.BottomRight
|
64
|
+
}
|
65
|
+
]
|
66
|
+
const onHandleMouseDown = (type: EScaleInfoType, e: MouseEvent) => {
|
67
|
+
console.log('onHandleMouseDown', e)
|
68
|
+
const { clientX, clientY } = e
|
69
|
+
e.stopPropagation()
|
70
|
+
globalStore.intention = EGlobalStoreIntention.Zoom
|
71
|
+
globalStore.setMouseInfo({
|
72
|
+
state: EMouseInfoState.Down,
|
73
|
+
position_x: clientX - svgEditLayoutStore.center_offset.x,
|
74
|
+
position_y: clientY - svgEditLayoutStore.center_offset.y,
|
75
|
+
now_position_x: clientX - svgEditLayoutStore.center_offset.x,
|
76
|
+
now_position_y: clientY - svgEditLayoutStore.center_offset.y,
|
77
|
+
new_position_x: 0,
|
78
|
+
new_position_y: 0
|
79
|
+
})
|
80
|
+
globalStore.setScaleInfo({
|
81
|
+
type: type,
|
82
|
+
scale_times: {
|
83
|
+
x: props.itemInfo.scale_x,
|
84
|
+
y: props.itemInfo.scale_y
|
85
|
+
},
|
86
|
+
scale_item_info: {
|
87
|
+
x: props.itemInfo.x,
|
88
|
+
y: props.itemInfo.y
|
89
|
+
},
|
90
|
+
symmetric_point: {
|
91
|
+
x:
|
92
|
+
props.itemInfo.client.x +
|
93
|
+
Math.abs(clientX - svgEditLayoutStore.center_offset.x - props.itemInfo.client.x) *
|
94
|
+
(clientX - svgEditLayoutStore.center_offset.x < props.itemInfo.client.x ? 1 : -1),
|
95
|
+
y:
|
96
|
+
props.itemInfo.client.y +
|
97
|
+
Math.abs(clientY - svgEditLayoutStore.center_offset.y - props.itemInfo.client.y) *
|
98
|
+
(clientY - svgEditLayoutStore.center_offset.y < props.itemInfo.client.y ? 1 : -1)
|
99
|
+
}
|
100
|
+
})
|
101
|
+
}
|
102
|
+
const onRotateCircleMouseDown = (e: MouseEvent) => {
|
103
|
+
const { clientX, clientY } = e
|
104
|
+
e.stopPropagation()
|
105
|
+
globalStore.intention = EGlobalStoreIntention.Rotate
|
106
|
+
globalStore.rotate_info = {
|
107
|
+
angle: props.itemInfo.rotate
|
108
|
+
}
|
109
|
+
globalStore.setMouseInfo({
|
110
|
+
state: EMouseInfoState.Down,
|
111
|
+
position_x: clientX - svgEditLayoutStore.center_offset.x,
|
112
|
+
position_y: clientY - svgEditLayoutStore.center_offset.y,
|
113
|
+
now_position_x: clientX - svgEditLayoutStore.center_offset.x,
|
114
|
+
now_position_y: clientY - svgEditLayoutStore.center_offset.y,
|
115
|
+
new_position_x: 0,
|
116
|
+
new_position_y: 0
|
117
|
+
})
|
118
|
+
}
|
119
|
+
/**
|
120
|
+
* 获取旋转之后的光标样式
|
121
|
+
* @param init_angle 初始角度 360/8=45
|
122
|
+
*/
|
123
|
+
const getCursor = (init_angle: number) => {
|
124
|
+
const now_init_angle = (init_angle + props.itemInfo.rotate) % 360
|
125
|
+
const find_cursor = angle_to_cursor.find((f) => f.start <= now_init_angle && f.end > now_init_angle)
|
126
|
+
if (!find_cursor) {
|
127
|
+
return {
|
128
|
+
cursor: 'nw-resize',
|
129
|
+
type: EScaleInfoType.TopLeft
|
130
|
+
}
|
131
|
+
}
|
132
|
+
return {
|
133
|
+
cursor: find_cursor.cursor + '-resize',
|
134
|
+
type: find_cursor.type
|
135
|
+
}
|
136
|
+
}
|
137
|
+
</script>
|
138
|
+
|
139
|
+
<template>
|
140
|
+
<g style="vector-effect: non-scaling-stroke">
|
141
|
+
<rect
|
142
|
+
id="resize_tl"
|
143
|
+
width="8"
|
144
|
+
height="8"
|
145
|
+
:fill="fill"
|
146
|
+
:style="{ cursor: getCursor(0).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
147
|
+
pointer-events="all"
|
148
|
+
:x="
|
149
|
+
props.itemInfo.actual_bound.x -
|
150
|
+
offset -
|
151
|
+
getCoordinateOffset(props.itemInfo.actual_bound.width, props.itemInfo.scale_x)
|
152
|
+
"
|
153
|
+
:y="
|
154
|
+
props.itemInfo.actual_bound.y -
|
155
|
+
offset -
|
156
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
157
|
+
"
|
158
|
+
stroke="rgba(0,0,0,0)"
|
159
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.TopLeft, $event)"
|
160
|
+
>
|
161
|
+
</rect>
|
162
|
+
<circle
|
163
|
+
:cx="props.itemInfo.actual_bound.x + props.itemInfo.actual_bound.width / 2"
|
164
|
+
:cy="
|
165
|
+
props.itemInfo.actual_bound.y -
|
166
|
+
offset -
|
167
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y) -
|
168
|
+
24
|
169
|
+
"
|
170
|
+
:r="4"
|
171
|
+
class="rotate-circle"
|
172
|
+
@mousedown="onRotateCircleMouseDown"
|
173
|
+
/>
|
174
|
+
<line
|
175
|
+
:x1="props.itemInfo.actual_bound.x + props.itemInfo.actual_bound.width / 2"
|
176
|
+
:y1="
|
177
|
+
props.itemInfo.actual_bound.y -
|
178
|
+
offset -
|
179
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
180
|
+
"
|
181
|
+
:x2="props.itemInfo.actual_bound.x + props.itemInfo.actual_bound.width / 2"
|
182
|
+
:y2="
|
183
|
+
props.itemInfo.actual_bound.y -
|
184
|
+
offset -
|
185
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y) -
|
186
|
+
20
|
187
|
+
"
|
188
|
+
:style="{ stroke: fill, 'stroke-width': 2 }"
|
189
|
+
/>
|
190
|
+
<rect
|
191
|
+
id="resize_tc"
|
192
|
+
width="8"
|
193
|
+
height="8"
|
194
|
+
:fill="fill"
|
195
|
+
:style="{ cursor: getCursor(45).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
196
|
+
pointer-events="all"
|
197
|
+
:x="props.itemInfo.actual_bound.x + props.itemInfo.actual_bound.width / 2 - offset"
|
198
|
+
:y="
|
199
|
+
props.itemInfo.actual_bound.y -
|
200
|
+
offset -
|
201
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
202
|
+
"
|
203
|
+
stroke="rgba(0,0,0,0)"
|
204
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.TopCenter, $event)"
|
205
|
+
></rect>
|
206
|
+
<rect
|
207
|
+
id="resize_tr"
|
208
|
+
width="8"
|
209
|
+
height="8"
|
210
|
+
:fill="fill"
|
211
|
+
:style="{ cursor: getCursor(90).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
212
|
+
pointer-events="all"
|
213
|
+
:x="
|
214
|
+
props.itemInfo.actual_bound.x +
|
215
|
+
props.itemInfo.actual_bound.width -
|
216
|
+
offset +
|
217
|
+
getCoordinateOffset(props.itemInfo.actual_bound.width, props.itemInfo.scale_x)
|
218
|
+
"
|
219
|
+
:y="
|
220
|
+
props.itemInfo.actual_bound.y -
|
221
|
+
offset -
|
222
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
223
|
+
"
|
224
|
+
stroke="rgba(0,0,0,0)"
|
225
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.TopRight, $event)"
|
226
|
+
></rect>
|
227
|
+
<rect
|
228
|
+
id="resize_l"
|
229
|
+
width="8"
|
230
|
+
height="8"
|
231
|
+
:fill="fill"
|
232
|
+
:style="{ cursor: getCursor(315).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
233
|
+
pointer-events="all"
|
234
|
+
:x="
|
235
|
+
props.itemInfo.actual_bound.x -
|
236
|
+
offset -
|
237
|
+
getCoordinateOffset(props.itemInfo.actual_bound.width, props.itemInfo.scale_x)
|
238
|
+
"
|
239
|
+
:y="
|
240
|
+
props.itemInfo.actual_bound.y -
|
241
|
+
offset +
|
242
|
+
(props.itemInfo.actual_bound.height * props.itemInfo.scale_y) / 2 -
|
243
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
244
|
+
"
|
245
|
+
stroke="rgba(0,0,0,0)"
|
246
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.Left, $event)"
|
247
|
+
></rect>
|
248
|
+
<rect
|
249
|
+
id="resize_r"
|
250
|
+
width="8"
|
251
|
+
height="8"
|
252
|
+
:fill="fill"
|
253
|
+
:style="{ cursor: getCursor(135).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
254
|
+
pointer-events="all"
|
255
|
+
:x="
|
256
|
+
props.itemInfo.actual_bound.x -
|
257
|
+
offset +
|
258
|
+
props.itemInfo.actual_bound.width +
|
259
|
+
getCoordinateOffset(props.itemInfo.actual_bound.width, props.itemInfo.scale_x)
|
260
|
+
"
|
261
|
+
:y="
|
262
|
+
props.itemInfo.actual_bound.y -
|
263
|
+
offset +
|
264
|
+
(props.itemInfo.actual_bound.height * props.itemInfo.scale_y) / 2 -
|
265
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
266
|
+
"
|
267
|
+
stroke="rgba(0,0,0,0)"
|
268
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.Right, $event)"
|
269
|
+
></rect>
|
270
|
+
<rect
|
271
|
+
id="resize_bl"
|
272
|
+
width="8"
|
273
|
+
height="8"
|
274
|
+
:fill="fill"
|
275
|
+
:style="{ cursor: getCursor(270).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
276
|
+
pointer-events="all"
|
277
|
+
:x="
|
278
|
+
props.itemInfo.actual_bound.x -
|
279
|
+
offset -
|
280
|
+
getCoordinateOffset(props.itemInfo.actual_bound.width, props.itemInfo.scale_x)
|
281
|
+
"
|
282
|
+
:y="
|
283
|
+
props.itemInfo.actual_bound.y -
|
284
|
+
offset +
|
285
|
+
props.itemInfo.actual_bound.height * props.itemInfo.scale_y -
|
286
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
287
|
+
"
|
288
|
+
stroke="rgba(0,0,0,0)"
|
289
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.BottomLeft, $event)"
|
290
|
+
></rect>
|
291
|
+
<rect
|
292
|
+
id="resize_bc"
|
293
|
+
width="8"
|
294
|
+
height="8"
|
295
|
+
:fill="fill"
|
296
|
+
:style="{ cursor: getCursor(225).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
297
|
+
pointer-events="all"
|
298
|
+
:x="props.itemInfo.actual_bound.x - offset + props.itemInfo.actual_bound.width / 2"
|
299
|
+
:y="
|
300
|
+
props.itemInfo.actual_bound.y -
|
301
|
+
offset +
|
302
|
+
props.itemInfo.actual_bound.height +
|
303
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
304
|
+
"
|
305
|
+
stroke="rgba(0,0,0,0)"
|
306
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.BottomCenter, $event)"
|
307
|
+
></rect>
|
308
|
+
<rect
|
309
|
+
id="resize_br"
|
310
|
+
width="8"
|
311
|
+
height="8"
|
312
|
+
:fill="fill"
|
313
|
+
:style="{ cursor: getCursor(180).cursor, 'vector-effect': 'non-scaling-stroke' }"
|
314
|
+
pointer-events="all"
|
315
|
+
:x="
|
316
|
+
props.itemInfo.actual_bound.x -
|
317
|
+
offset +
|
318
|
+
props.itemInfo.actual_bound.width +
|
319
|
+
getCoordinateOffset(props.itemInfo.actual_bound.width, props.itemInfo.scale_x)
|
320
|
+
"
|
321
|
+
:y="
|
322
|
+
props.itemInfo.actual_bound.y -
|
323
|
+
offset +
|
324
|
+
props.itemInfo.actual_bound.height +
|
325
|
+
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y)
|
326
|
+
"
|
327
|
+
stroke="rgba(0,0,0,0)"
|
328
|
+
@mousedown="onHandleMouseDown(EScaleInfoType.BottomRight, $event)"
|
329
|
+
></rect>
|
330
|
+
</g>
|
331
|
+
</template>
|
332
|
+
|
333
|
+
<style scoped>
|
334
|
+
.rotate-circle {
|
335
|
+
stroke: v-bind('fill');
|
336
|
+
stroke-width: 1;
|
337
|
+
fill-opacity: 0;
|
338
|
+
cursor:
|
339
|
+
url('@/assets/icons/rotate.svg') 12 12,
|
340
|
+
auto;
|
341
|
+
}
|
342
|
+
</style>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { ref } from 'vue'
|
3
|
+
import { VAceEditor } from 'vue3-ace-editor'
|
4
|
+
import '@/components/ace-edit'
|
5
|
+
|
6
|
+
import { useImportDataModel } from '@/hooks'
|
7
|
+
import { ElMessage } from 'element-plus'
|
8
|
+
const content = ref<string>('')
|
9
|
+
|
10
|
+
const setVal = (d: any) => {
|
11
|
+
content.value = d
|
12
|
+
}
|
13
|
+
const onImportJson = () => {
|
14
|
+
if (useImportDataModel(content.value)) {
|
15
|
+
ElMessage.success('导入成功')
|
16
|
+
}
|
17
|
+
}
|
18
|
+
defineExpose({
|
19
|
+
setVal,
|
20
|
+
onImportJson
|
21
|
+
})
|
22
|
+
</script>
|
23
|
+
|
24
|
+
<template>
|
25
|
+
<v-ace-editor
|
26
|
+
v-model:value="content"
|
27
|
+
lang="json"
|
28
|
+
theme="kr_theme"
|
29
|
+
style="height: 400px"
|
30
|
+
:options="{
|
31
|
+
useWorker: true,
|
32
|
+
enableBasicAutocompletion: true,
|
33
|
+
enableSnippets: true,
|
34
|
+
enableLiveAutocompletion: true
|
35
|
+
}"
|
36
|
+
/>
|
37
|
+
</template>
|
@@ -0,0 +1,280 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { getCurrentInstance, onMounted, reactive, ref } from 'vue'
|
3
|
+
import {
|
4
|
+
ElContainer,
|
5
|
+
ElHeader,
|
6
|
+
ElAside,
|
7
|
+
ElMain,
|
8
|
+
ElScrollbar,
|
9
|
+
ElDialog,
|
10
|
+
ElButton,
|
11
|
+
ElUpload,
|
12
|
+
ElMessage,
|
13
|
+
ElMessageBox
|
14
|
+
} from 'element-plus'
|
15
|
+
import 'element-plus/dist/index.css'
|
16
|
+
import 'animate.css'
|
17
|
+
import TopPanel from '@/components/svg-editor/top-panel/index.vue'
|
18
|
+
import LeftPanel from '@/components/svg-editor/left-panel/index.vue'
|
19
|
+
import CenterPanel from '@/components/svg-editor/center-panel/index.vue'
|
20
|
+
import RightPanel from '@/components/svg-editor/right-panel/index.vue'
|
21
|
+
import ExportJson from '@/components/svg-editor/export-json/index.vue'
|
22
|
+
import ImportJson from '@/components/svg-editor/import-json/index.vue'
|
23
|
+
import Vue3RulerTool from '@/components/vue3-ruler-tool/index.vue'
|
24
|
+
import { EVisibleConfKey } from '@/components/svg-editor/types'
|
25
|
+
import type { IVisibleConf, IDataModel } from '@/components/svg-editor/types'
|
26
|
+
import type { IConfig } from '@/config/types'
|
27
|
+
import { EGlobalStoreIntention } from '@/stores/global/types'
|
28
|
+
import type { IDoneJson } from '@/stores/global/types'
|
29
|
+
import { pinia } from '@/hooks'
|
30
|
+
import { useSvgEditLayoutStore } from '@/stores/svg-edit-layout'
|
31
|
+
import { useImportDataModel } from '@/hooks'
|
32
|
+
import { useGlobalStore } from '@/stores/global'
|
33
|
+
import { useConfigStore } from '@/stores/config'
|
34
|
+
import { fileRead, fileWrite } from '@/utils/file-read-write'
|
35
|
+
|
36
|
+
const props = withDefaults(defineProps<{ customToolbar?: IConfig; data?: string; saveFile?: boolean }>(), {
|
37
|
+
saveFile: false
|
38
|
+
})
|
39
|
+
const presetLine = ref([])
|
40
|
+
const input = (list: any) => {
|
41
|
+
presetLine.value = list
|
42
|
+
}
|
43
|
+
const globalStore = useGlobalStore(pinia)
|
44
|
+
const svgEditLayoutStore = useSvgEditLayoutStore(pinia)
|
45
|
+
const configStore = useConfigStore(pinia)
|
46
|
+
const importJsonRef = ref<InstanceType<typeof ImportJson>>()
|
47
|
+
const visible_conf: IVisibleConf = reactive({
|
48
|
+
[EVisibleConfKey.ExportJson]: false,
|
49
|
+
[EVisibleConfKey.ImportJson]: false,
|
50
|
+
[EVisibleConfKey.ImportFile]: false
|
51
|
+
})
|
52
|
+
const emits = defineEmits(['onReturn', 'onPreview', 'onSave'])
|
53
|
+
const changeVisible = (key: EVisibleConfKey, val: boolean) => {
|
54
|
+
visible_conf[key] = val
|
55
|
+
}
|
56
|
+
|
57
|
+
const onImportJson = ref()
|
58
|
+
onImportJson.value = () => {
|
59
|
+
importJsonRef.value!.onImportJson()
|
60
|
+
changeVisible(EVisibleConfKey.ImportJson, false)
|
61
|
+
}
|
62
|
+
|
63
|
+
const onImportFile = (f: File) => {
|
64
|
+
if (['text/plain', 'application/json'].indexOf(f.type) < 0) {
|
65
|
+
ElMessage.error('仅支持的格式:txt、json')
|
66
|
+
return false
|
67
|
+
}
|
68
|
+
fileRead(f).then((r) => {
|
69
|
+
importJsonRef.value!.setVal(r)
|
70
|
+
ElMessage.success('文件读取成功!')
|
71
|
+
})
|
72
|
+
return false
|
73
|
+
}
|
74
|
+
const setGraphNodeJson = (done_json: IDoneJson[]) => {
|
75
|
+
globalStore.setDoneJson(done_json)
|
76
|
+
}
|
77
|
+
onMounted(() => {
|
78
|
+
if (props.data) {
|
79
|
+
useImportDataModel(props.data)
|
80
|
+
} else {
|
81
|
+
globalStore.setDoneJson([])
|
82
|
+
}
|
83
|
+
globalStore.intention = EGlobalStoreIntention.None
|
84
|
+
})
|
85
|
+
defineExpose({
|
86
|
+
setGraphNodeJson
|
87
|
+
})
|
88
|
+
|
89
|
+
const { appContext } = getCurrentInstance()!
|
90
|
+
|
91
|
+
function save(d: IDataModel) {
|
92
|
+
if (props.saveFile) {
|
93
|
+
ElMessageBox.prompt('请输入文件名', '保存', { cancelButtonText: '取消', confirmButtonText: '保存' }, appContext)
|
94
|
+
.then((r: any) => {
|
95
|
+
fileWrite(d, r.value.trim())
|
96
|
+
emits('onSave', d)
|
97
|
+
})
|
98
|
+
.catch((e: any) => {
|
99
|
+
console.log(e)
|
100
|
+
})
|
101
|
+
} else {
|
102
|
+
emits('onSave', d)
|
103
|
+
}
|
104
|
+
}
|
105
|
+
</script>
|
106
|
+
<template>
|
107
|
+
<div>
|
108
|
+
<el-container>
|
109
|
+
<el-header class="top-el-header">
|
110
|
+
<top-panel
|
111
|
+
@change-visible="changeVisible"
|
112
|
+
@on-return="emits('onReturn')"
|
113
|
+
@on-preview="(val: IDataModel) => emits('onPreview', val)"
|
114
|
+
@on-save="save"
|
115
|
+
></top-panel>
|
116
|
+
</el-header>
|
117
|
+
<el-container class="middle">
|
118
|
+
<el-aside class="side-nav" :class="svgEditLayoutStore.left_nav ? 'show-nav' : 'hide-nav'">
|
119
|
+
<el-scrollbar class="el-scroll-pc">
|
120
|
+
<left-panel class="content-left" :custom-toolbar="props.customToolbar" />
|
121
|
+
</el-scrollbar>
|
122
|
+
</el-aside>
|
123
|
+
<el-main class="middle main">
|
124
|
+
<div class="canvas-main-pc">
|
125
|
+
<Vue3RulerTool
|
126
|
+
class="canvas-main-pc"
|
127
|
+
:value="presetLine"
|
128
|
+
:step-length="50"
|
129
|
+
:parent="true"
|
130
|
+
:is-scale-revise="false"
|
131
|
+
v-model:visible="configStore.svg.ruler"
|
132
|
+
@input="input"
|
133
|
+
>
|
134
|
+
<center-panel></center-panel>
|
135
|
+
</Vue3RulerTool>
|
136
|
+
</div>
|
137
|
+
</el-main>
|
138
|
+
<el-aside class="side-nav" :class="svgEditLayoutStore.right_nav ? 'show-nav' : 'hide-nav'">
|
139
|
+
<el-scrollbar class="el-scroll-pc">
|
140
|
+
<right-panel></right-panel>
|
141
|
+
</el-scrollbar>
|
142
|
+
</el-aside>
|
143
|
+
</el-container>
|
144
|
+
</el-container>
|
145
|
+
<el-dialog class="modal-full" v-model="visible_conf.ImportJson" title="导入数据" width="60%" destroy-on-close>
|
146
|
+
<import-json ref="importJsonRef"></import-json>
|
147
|
+
<template #footer>
|
148
|
+
<el-upload
|
149
|
+
:beforeUpload="onImportFile"
|
150
|
+
style="display: inline-flex; margin-right: 12px"
|
151
|
+
:multiple="false"
|
152
|
+
:show-file-list="false"
|
153
|
+
:limit="1"
|
154
|
+
>
|
155
|
+
<el-button @click="changeVisible(EVisibleConfKey.ImportFile, true)">读取文件</el-button>
|
156
|
+
</el-upload>
|
157
|
+
<el-button type="primary" @click="onImportJson">导入数据</el-button>
|
158
|
+
</template>
|
159
|
+
</el-dialog>
|
160
|
+
<el-dialog class="modal-full" v-model="visible_conf.ExportJson" title="导出" width="60%" destroy-on-close>
|
161
|
+
<export-json></export-json>
|
162
|
+
</el-dialog>
|
163
|
+
</div>
|
164
|
+
</template>
|
165
|
+
<style scoped lang="less">
|
166
|
+
@headerHeight: 45px;
|
167
|
+
.el-scroll-pc {
|
168
|
+
height: calc(100vh - @headerHeight - 1px);
|
169
|
+
}
|
170
|
+
|
171
|
+
.canvas-main-pc {
|
172
|
+
width: 100%;
|
173
|
+
height: 100%;
|
174
|
+
margin: 0 auto;
|
175
|
+
}
|
176
|
+
|
177
|
+
.middle {
|
178
|
+
height: calc(100vh - @headerHeight - 1px);
|
179
|
+
|
180
|
+
&.main {
|
181
|
+
margin: 0 5px;
|
182
|
+
background-color: #ffffff;
|
183
|
+
padding: 0 2px;
|
184
|
+
}
|
185
|
+
|
186
|
+
.side-nav {
|
187
|
+
@showLeftNavWidth: 260px;
|
188
|
+
@hideLeftNavWidth: 0;
|
189
|
+
position: relative;
|
190
|
+
overflow: inherit;
|
191
|
+
transition: all 0.5s;
|
192
|
+
// background-color: rgb(250, 251, 253);
|
193
|
+
box-shadow: 0 0 2px #dfcfcf;
|
194
|
+
|
195
|
+
.content-left {
|
196
|
+
overflow: hidden;
|
197
|
+
margin: 0 1vh;
|
198
|
+
}
|
199
|
+
|
200
|
+
&.show-nav {
|
201
|
+
flex: 0 0 @showLeftNavWidth;
|
202
|
+
min-width: @showLeftNavWidth;
|
203
|
+
max-width: @showLeftNavWidth;
|
204
|
+
}
|
205
|
+
|
206
|
+
&.hide-nav {
|
207
|
+
flex: 0 0 @hideLeftNavWidth;
|
208
|
+
min-width: @hideLeftNavWidth;
|
209
|
+
max-width: @hideLeftNavWidth;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
.top-el-header {
|
215
|
+
display: flex;
|
216
|
+
flex-direction: row;
|
217
|
+
align-items: center;
|
218
|
+
box-shadow: 0 0 2px #dfcfcf;
|
219
|
+
margin-bottom: 1px;
|
220
|
+
height: @headerHeight;
|
221
|
+
}
|
222
|
+
|
223
|
+
.bottom-el-footer {
|
224
|
+
box-shadow: 0 -1px 0 0 #dfcfcf;
|
225
|
+
margin-top: 10px;
|
226
|
+
}
|
227
|
+
|
228
|
+
.contextMenu {
|
229
|
+
position: absolute;
|
230
|
+
z-index: 99999;
|
231
|
+
background: #ffffff;
|
232
|
+
padding: 5px 0;
|
233
|
+
margin: 0;
|
234
|
+
display: block;
|
235
|
+
border-radius: 5px;
|
236
|
+
box-shadow: 2px 5px 10px rgba(0, 0, 0, 0.3);
|
237
|
+
|
238
|
+
li {
|
239
|
+
list-style: none;
|
240
|
+
padding: 0;
|
241
|
+
margin: 0;
|
242
|
+
}
|
243
|
+
|
244
|
+
.shortcut {
|
245
|
+
width: 115px;
|
246
|
+
text-align: right;
|
247
|
+
float: right;
|
248
|
+
}
|
249
|
+
|
250
|
+
p {
|
251
|
+
text-decoration: none;
|
252
|
+
display: block;
|
253
|
+
padding: 0 15px 1px 20px;
|
254
|
+
margin: 0;
|
255
|
+
user-select: none;
|
256
|
+
-webkit-user-select: none;
|
257
|
+
}
|
258
|
+
|
259
|
+
p:hover {
|
260
|
+
background-color: #0cf;
|
261
|
+
color: #ffffff;
|
262
|
+
cursor: default;
|
263
|
+
}
|
264
|
+
|
265
|
+
.disabled {
|
266
|
+
color: #999;
|
267
|
+
}
|
268
|
+
|
269
|
+
.disabled:hover {
|
270
|
+
color: #999;
|
271
|
+
background-color: transparent;
|
272
|
+
}
|
273
|
+
|
274
|
+
li.separator {
|
275
|
+
border-top: solid 1px #e3e3e3;
|
276
|
+
padding-top: 5px;
|
277
|
+
margin-top: 5px;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
</style>
|