@zhangqingcq/vgce 0.1.3 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/style.css +1 -1
- package/dist/vgce.js +22660 -19299
- package/dist/vgce.umd.cjs +34 -33
- package/package.json +2 -2
- package/src/components/svg-editor/left-panel.vue +11 -1
- package/src/components/svg-editor/right-panel/dynamic-el-form-item.vue +45 -17
- package/src/components/svg-viewer.vue +1 -1
- package/src/config/types.ts +1 -0
- package/src/utils/mqtt-net.ts +16 -6
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@zhangqingcq/vgce",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.5",
|
4
4
|
"description": "Vector graphics configure editor. svg组态编辑器。基于vue3.3+ts+element-plus+vite",
|
5
5
|
"publishConfig": {
|
6
6
|
"access": "public"
|
@@ -60,7 +60,7 @@
|
|
60
60
|
"echarts": "^5.4.1",
|
61
61
|
"element-plus": "^2.3.8",
|
62
62
|
"lodash-es": "^4.17.21",
|
63
|
-
"mqtt": "^
|
63
|
+
"mqtt": "^5.1.3",
|
64
64
|
"pinia": "^2.1.3",
|
65
65
|
"vue": "^3.3.4",
|
66
66
|
"vue-echarts": "^6.5.1",
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<!--左侧工具栏-->
|
2
2
|
<script lang="ts" setup>
|
3
|
+
import { isEmpty } from 'lodash-es'
|
3
4
|
import { ElCollapse, ElCollapseItem, ElIcon, ElMessage } from 'element-plus'
|
4
5
|
import type { IConfig, IConfigItem } from '@/config/types'
|
5
6
|
import { pinia } from '@/hooks'
|
@@ -23,7 +24,16 @@
|
|
23
24
|
'echarts'
|
24
25
|
])
|
25
26
|
const createBegin = (svg_item: IConfigItem) => {
|
26
|
-
globalStore.setCreateInfo(svg_item)
|
27
|
+
globalStore.setCreateInfo(sortProps(svg_item))
|
28
|
+
}
|
29
|
+
|
30
|
+
const sortProps = (svg_item: IConfigItem): IConfigItem => {
|
31
|
+
if (svg_item?.props && !isEmpty(svg_item.props)) {
|
32
|
+
Object.keys(svg_item.props).forEach((k, i) => {
|
33
|
+
svg_item.props[k].sort = String(i)
|
34
|
+
})
|
35
|
+
}
|
36
|
+
return svg_item
|
27
37
|
}
|
28
38
|
const dragEndEvent = (e: DragEvent) => {
|
29
39
|
//拖动时记录拖动的svg信息
|
@@ -21,6 +21,38 @@
|
|
21
21
|
code: false
|
22
22
|
})
|
23
23
|
|
24
|
+
const _objInfo = computed(() => {
|
25
|
+
const keys: Record<string, any> = {}
|
26
|
+
let l = 0
|
27
|
+
let t = []
|
28
|
+
for (let k of Object.keys(props.objInfo)) {
|
29
|
+
const s = props.objInfo[k]?.sort
|
30
|
+
if (s) {
|
31
|
+
const _s = Number(s)
|
32
|
+
if (_s > l) {
|
33
|
+
l = _s
|
34
|
+
}
|
35
|
+
}
|
36
|
+
if (s) {
|
37
|
+
keys[s] = k
|
38
|
+
} else {
|
39
|
+
return Object.keys(props.objInfo).map((k) => ({
|
40
|
+
...props.objInfo[k],
|
41
|
+
_key: k
|
42
|
+
}))
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
for (let i = 0; i < l + 1; i++) {
|
47
|
+
const _i = String(i)
|
48
|
+
t.push({
|
49
|
+
...props.objInfo[keys[_i]],
|
50
|
+
_key: keys[_i]
|
51
|
+
})
|
52
|
+
}
|
53
|
+
return t
|
54
|
+
})
|
55
|
+
|
24
56
|
function propsChangeHandle(e: any) {
|
25
57
|
let t: any = window.setTimeout(function () {
|
26
58
|
emit('change', e)
|
@@ -31,19 +63,19 @@
|
|
31
63
|
</script>
|
32
64
|
|
33
65
|
<template>
|
34
|
-
<div v-for="
|
66
|
+
<div v-for="attr_item in _objInfo" :key="attr_item._key">
|
35
67
|
<!--表单项上显示的灰色值-->
|
36
68
|
<el-form-item v-if="props.code" class="props-row" size="small">
|
37
69
|
<template #label>
|
38
70
|
<el-tooltip
|
39
|
-
:content="String(
|
40
|
-
v-if="getStringWidth(String(
|
71
|
+
:content="String(attr_item._key)"
|
72
|
+
v-if="getStringWidth(String(attr_item._key)) > 78"
|
41
73
|
placement="left"
|
42
74
|
popper-class="props-popper"
|
43
75
|
>
|
44
|
-
<div class="one-row-txt" style="width: 78px">{{
|
76
|
+
<div class="one-row-txt" style="width: 78px">{{ attr_item._key }}</div>
|
45
77
|
</el-tooltip>
|
46
|
-
<span v-else>{{
|
78
|
+
<span v-else>{{ attr_item._key }}</span>
|
47
79
|
</template>
|
48
80
|
<el-tooltip
|
49
81
|
:content="JSON.stringify(attr_item.val)"
|
@@ -56,10 +88,10 @@
|
|
56
88
|
<span v-else>{{ attr_item.val }}</span>
|
57
89
|
</el-form-item>
|
58
90
|
<!--props-->
|
59
|
-
<el-form-item :label="attr_item.title" size="small" v-if="props.hide.indexOf(String(
|
91
|
+
<el-form-item :label="attr_item.title" size="small" v-if="props.hide.indexOf(String(attr_item._key)) < 0">
|
60
92
|
<el-select
|
61
93
|
v-if="attr_item.type === EConfigItemPropsType.Select"
|
62
|
-
v-model="attr_item.val"
|
94
|
+
v-model="props.objInfo[attr_item._key].val"
|
63
95
|
placeholder="Select"
|
64
96
|
size="small"
|
65
97
|
:disabled="Boolean(attr_item?.disabled)"
|
@@ -69,19 +101,19 @@
|
|
69
101
|
</el-select>
|
70
102
|
<el-input-number
|
71
103
|
v-else-if="attr_item.type === EConfigItemPropsType.InputNumber"
|
72
|
-
v-model="attr_item.val"
|
104
|
+
v-model="props.objInfo[attr_item._key].val"
|
73
105
|
:disabled="Boolean(attr_item?.disabled)"
|
74
106
|
@change="propsChangeHandle"
|
75
107
|
/>
|
76
108
|
<el-input
|
77
109
|
v-else-if="attr_item.type === EConfigItemPropsType.Input"
|
78
|
-
v-model="attr_item.val"
|
110
|
+
v-model="props.objInfo[attr_item._key].val"
|
79
111
|
:disabled="Boolean(attr_item?.disabled)"
|
80
112
|
@change="propsChangeHandle"
|
81
113
|
/>
|
82
114
|
<el-input
|
83
115
|
v-else-if="attr_item.type === EConfigItemPropsType.Textarea"
|
84
|
-
v-model="attr_item.val"
|
116
|
+
v-model="props.objInfo[attr_item._key].val"
|
85
117
|
autosize
|
86
118
|
type="textarea"
|
87
119
|
:disabled="Boolean(attr_item?.disabled)"
|
@@ -89,19 +121,19 @@
|
|
89
121
|
/>
|
90
122
|
<el-color-picker
|
91
123
|
v-else-if="attr_item.type === EConfigItemPropsType.Color"
|
92
|
-
v-model="attr_item.val"
|
124
|
+
v-model="props.objInfo[attr_item._key].val"
|
93
125
|
:disabled="Boolean(attr_item?.disabled)"
|
94
126
|
@change="propsChangeHandle"
|
95
127
|
/>
|
96
128
|
<el-switch
|
97
129
|
v-else-if="attr_item.type === EConfigItemPropsType.Switch"
|
98
|
-
v-model="attr_item.val"
|
130
|
+
v-model="props.objInfo[attr_item._key].val"
|
99
131
|
:disabled="Boolean(attr_item?.disabled)"
|
100
132
|
@change="propsChangeHandle"
|
101
133
|
/>
|
102
134
|
<code-edit-modal
|
103
135
|
v-else-if="attr_item.type === EConfigItemPropsType.JsonEdit"
|
104
|
-
v-model="attr_item.val"
|
136
|
+
v-model="props.objInfo[attr_item._key].val"
|
105
137
|
:disabled="Boolean(attr_item?.disabled)"
|
106
138
|
@close="propsChangeHandle"
|
107
139
|
/>
|
@@ -119,8 +151,4 @@
|
|
119
151
|
.props-popper {
|
120
152
|
max-width: 350px;
|
121
153
|
}
|
122
|
-
sdf {
|
123
|
-
color: rgb(245, 247, 250);
|
124
|
-
background-color: rgb(92, 184, 122);
|
125
|
-
}
|
126
154
|
</style>
|
@@ -240,7 +240,7 @@
|
|
240
240
|
1.用你的项目里前后端约定的svg组件唯一标识符替换掉编辑器生成的id(必须保证唯一),然后调用setNodeAttrByID改变组件属性。
|
241
241
|
2.如果不想改动id(避免因不能保证手动改过的id唯一性导致编辑器功能异常),可以在config里给想要改变的组件的配置文件的props里增加一个字段,
|
242
242
|
如deviceCode(svg-text的配置文件里有被注释的例子),然后在编辑组态时,给对应组件填上对应的deviceCode(这样deviceCode就和组件id实现
|
243
|
-
了映射关系),并保存,后台给前台推MQTT消息时带上指定的deviceCode,前台预览时,在收到MQTT消息后,凭借消息里的deviceCode
|
243
|
+
了映射关系),并保存,后台给前台推MQTT消息时带上指定的deviceCode,前台预览时,在收到MQTT消息后,凭借消息里的deviceCode在done_json
|
244
244
|
找到组件的id(可以用vue的computed计算一份deviceCode和id的映射关系存到一个对象里,这样在需要id时可直接在计算出的对象凭借deviceCode
|
245
245
|
直接取到),即可用setNodeAttrByID改变组件属性*/
|
246
246
|
emit('onMessage', {
|
package/src/config/types.ts
CHANGED
package/src/utils/mqtt-net.ts
CHANGED
@@ -4,9 +4,14 @@ import type { MqttClient, PacketCallback } from 'mqtt'
|
|
4
4
|
let client: MqttClient
|
5
5
|
|
6
6
|
export const sub = (url: string, user: string, pwd: string, topics: string, callback: Function) => {
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
const _url = url.trim()
|
8
|
+
if (!/^wss?:\/\/.*$/.test(_url)) {
|
9
|
+
console.error('编辑器MQTT通信只支持ws协议 (url必须以"ws://"开头)')
|
10
|
+
return
|
11
|
+
}
|
12
|
+
client = connect(_url, {
|
13
|
+
username: user.trim(),
|
14
|
+
password: pwd.trim(),
|
10
15
|
reconnectPeriod: 600000 /*如果连不上,10分钟后重试*/
|
11
16
|
})
|
12
17
|
|
@@ -20,9 +25,14 @@ export const sub = (url: string, user: string, pwd: string, topics: string, call
|
|
20
25
|
}
|
21
26
|
|
22
27
|
export const pub = (url: string, user: string, pwd: string, topics: string, data: any, callback: PacketCallback) => {
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
const _url = url.trim()
|
29
|
+
if (!/^wss?:\/\/.*$/.test(_url)) {
|
30
|
+
console.error('编辑器MQTT通信只支持ws协议 (url必须以"ws://"开头)')
|
31
|
+
return
|
32
|
+
}
|
33
|
+
client = connect(_url, {
|
34
|
+
username: user.trim(),
|
35
|
+
password: pwd.trim()
|
26
36
|
})
|
27
37
|
|
28
38
|
client.on('connect', () => {
|