@truenewx/tnxvue3 3.0.0-alpha.33 → 3.0.0-alpha.35
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/package.json +4 -2
- package/src/element-plus/button/Button.vue +2 -0
- package/src/element-plus/dialog/Dialog.vue +5 -2
- package/src/element-plus/edit-table/EditTable.vue +212 -49
- package/src/element-plus/icon/Icon.vue +6 -0
- package/src/element-plus/input-number/InputNumber.vue +1 -1
- package/src/element-plus/tnxel.js +8 -3
- package/src/tnxvue.js +48 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truenewx/tnxvue3",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.35",
|
|
4
4
|
"description": "互联网技术解决方案:Vue3扩展支持",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"vue-router": "~4.4.0"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@truenewx/tnxcore": "3.0.0-alpha.
|
|
27
|
+
"@truenewx/tnxcore": "3.0.0-alpha.21",
|
|
28
28
|
"@element-plus/icons-vue": "2.3.1",
|
|
29
29
|
"async-validator": "4.2.5",
|
|
30
30
|
"mitt": "3.0.1"
|
|
@@ -64,6 +64,8 @@
|
|
|
64
64
|
],
|
|
65
65
|
"no-undef": "warn",
|
|
66
66
|
"no-useless-escape": "warn",
|
|
67
|
+
"no-empty": "off",
|
|
68
|
+
"vue/no-mutating-props": "warn",
|
|
67
69
|
"vue/no-v-model-argument": "off",
|
|
68
70
|
"vue/multi-word-component-names": "off"
|
|
69
71
|
}
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
:loading="loading"
|
|
31
31
|
:plain="plain"
|
|
32
32
|
:link="link"
|
|
33
|
+
:text="text"
|
|
33
34
|
:bg="bg"
|
|
34
35
|
:autofocus="autofocus"
|
|
35
36
|
:round="round"
|
|
@@ -75,6 +76,7 @@ export default {
|
|
|
75
76
|
loading: Boolean,
|
|
76
77
|
plain: Boolean,
|
|
77
78
|
link: Boolean,
|
|
79
|
+
text: Boolean,
|
|
78
80
|
bg: Boolean,
|
|
79
81
|
autofocus: Boolean,
|
|
80
82
|
round: Boolean,
|
|
@@ -42,7 +42,10 @@ export default {
|
|
|
42
42
|
'tnxel-dialog-content': DialogContent,
|
|
43
43
|
},
|
|
44
44
|
props: {
|
|
45
|
-
id:
|
|
45
|
+
id: {
|
|
46
|
+
type: String,
|
|
47
|
+
default: () => window.tnx.util.string.uuid32(),
|
|
48
|
+
},
|
|
46
49
|
modelValue: Boolean,
|
|
47
50
|
container: String,
|
|
48
51
|
title: String,
|
|
@@ -153,7 +156,7 @@ export default {
|
|
|
153
156
|
}
|
|
154
157
|
}
|
|
155
158
|
if (!$dialog || !$dialog.length) {
|
|
156
|
-
$dialog = $('.
|
|
159
|
+
$dialog = $('.tnxel-dialog[data-v-id="' + this.id + '"]');
|
|
157
160
|
}
|
|
158
161
|
if ($dialog.length) {
|
|
159
162
|
let top = window.tnx.util.dom.getTopVerticallyCenteredOnPage($dialog[0]);
|
|
@@ -3,37 +3,39 @@
|
|
|
3
3
|
<el-table ref="table"
|
|
4
4
|
class="tnxel-edit-table"
|
|
5
5
|
:class="{'padding-none': !padding}"
|
|
6
|
-
:data="
|
|
6
|
+
:data="tableDataList"
|
|
7
|
+
:row-key="rowKey"
|
|
8
|
+
:row-class-name="tableRowClassName"
|
|
7
9
|
:highlight-current-row="selectable"
|
|
8
10
|
border
|
|
9
11
|
@current-change="onSelectRow"
|
|
10
12
|
>
|
|
11
13
|
<slot></slot>
|
|
12
14
|
<el-table-column label="排序" align="center" width="60px" v-if="sortable">
|
|
13
|
-
<template #default="
|
|
15
|
+
<template #default="{row, $index}">
|
|
14
16
|
<tnxel-button
|
|
15
17
|
type="primary" link
|
|
16
18
|
icon="Top"
|
|
17
|
-
:class="{'text-transparent':
|
|
18
|
-
@click="sortUp(
|
|
19
|
+
:class="{'text-transparent': !isSortableRow(row, $index,true)}"
|
|
20
|
+
@click="sortUp(row, $index)"
|
|
19
21
|
/>
|
|
20
22
|
<tnxel-button
|
|
21
23
|
type="primary" link
|
|
22
24
|
icon="Bottom"
|
|
23
25
|
class="ms-0"
|
|
24
|
-
:class="{'text-transparent':
|
|
25
|
-
@click="sortDown(
|
|
26
|
+
:class="{'text-transparent': !isSortableRow(row, $index, false)}"
|
|
27
|
+
@click="sortDown(row, $index)"
|
|
26
28
|
/>
|
|
27
29
|
</template>
|
|
28
30
|
</el-table-column>
|
|
29
31
|
<el-table-column label="移除" align="center" width="60px" v-if="removable">
|
|
30
|
-
<template #default="
|
|
32
|
+
<template #default="{row, $index}">
|
|
31
33
|
<tnxel-button
|
|
32
34
|
type="primary" link
|
|
33
35
|
icon="CircleClose"
|
|
34
|
-
:tooltip="
|
|
35
|
-
@click="
|
|
36
|
-
|
|
36
|
+
:tooltip="row.removeTip"
|
|
37
|
+
@click="removeRow(row, $index)"
|
|
38
|
+
v-if="isRemovableRow(row, $index)"/>
|
|
37
39
|
</template>
|
|
38
40
|
</el-table-column>
|
|
39
41
|
</el-table>
|
|
@@ -61,7 +63,7 @@ export default {
|
|
|
61
63
|
default: true,
|
|
62
64
|
},
|
|
63
65
|
removable: {
|
|
64
|
-
type: Boolean,
|
|
66
|
+
type: [Boolean, Function],
|
|
65
67
|
default: true,
|
|
66
68
|
},
|
|
67
69
|
addText: {
|
|
@@ -76,9 +78,11 @@ export default {
|
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
},
|
|
81
|
+
rowKey: [Function, String],
|
|
82
|
+
rowClassName: [Function, String],
|
|
79
83
|
selectable: Boolean, // 可否选择行
|
|
80
84
|
padding: Boolean, // 单元格中是否有边距
|
|
81
|
-
sortable: Boolean, // 可否调整行的顺序
|
|
85
|
+
sortable: [Boolean, Function], // 可否调整行的顺序
|
|
82
86
|
rules: [String, Object], // 加载字段校验规则的URL地址,或规则集对象
|
|
83
87
|
rulesApp: { // 加载字段校验规则的应用名称
|
|
84
88
|
type: String,
|
|
@@ -86,13 +90,30 @@ export default {
|
|
|
86
90
|
},
|
|
87
91
|
rulesLoaded: Function, // 规则集加载后的附加处理函数,仅在rule为字符串类型的URL地址时有效
|
|
88
92
|
},
|
|
93
|
+
emits: ['sorted', 'removed'],
|
|
89
94
|
data() {
|
|
90
95
|
return {
|
|
91
96
|
id: window.tnx.util.string.uuid32(),
|
|
92
97
|
selectedRow: null,
|
|
93
98
|
validationRules: {},
|
|
99
|
+
indexes: {}, // 附加索引映射集,key:row,value:一级节点为单个索引下标,多级节点为其在各级节点中的索引下标集合
|
|
94
100
|
}
|
|
95
101
|
},
|
|
102
|
+
computed: {
|
|
103
|
+
tableDataList() {
|
|
104
|
+
for (let rowIndex = 0; rowIndex < this.data.length; rowIndex++) {
|
|
105
|
+
let row = this.data[rowIndex];
|
|
106
|
+
this.indexes[this.getRowKey(row, rowIndex)] = rowIndex;
|
|
107
|
+
if (this.rowKey && row.children) {
|
|
108
|
+
for (let j = 0; j < row.children.length; j++) {
|
|
109
|
+
let child = row.children[j];
|
|
110
|
+
this.indexes[this.getRowKey(child)] = [rowIndex, j];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return this.data;
|
|
115
|
+
},
|
|
116
|
+
},
|
|
96
117
|
watch: {
|
|
97
118
|
data(newData, oldData) {
|
|
98
119
|
if (!oldData) {
|
|
@@ -121,8 +142,11 @@ export default {
|
|
|
121
142
|
});
|
|
122
143
|
},
|
|
123
144
|
methods: {
|
|
145
|
+
getRowKey(row, rowIndex) {
|
|
146
|
+
return this.rowKey ? row[this.rowKey] : (rowIndex + '');
|
|
147
|
+
},
|
|
124
148
|
initElements() {
|
|
125
|
-
this.focusRowFirstInput(0);
|
|
149
|
+
this.focusRowFirstInput(this.tableDataList[0], 0);
|
|
126
150
|
// 为富文本输入框添加默认title
|
|
127
151
|
let table = this.$refs.table.$el;
|
|
128
152
|
let textareas = table.getElementsByTagName('textarea');
|
|
@@ -280,23 +304,39 @@ export default {
|
|
|
280
304
|
this.selectedRow = row;
|
|
281
305
|
}
|
|
282
306
|
},
|
|
283
|
-
|
|
284
|
-
let
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
307
|
+
tableRowClassName(data) {
|
|
308
|
+
let classNames = [this.getRowClassName(data.row, data.rowIndex)];
|
|
309
|
+
if (typeof this.rowClassName === 'function') {
|
|
310
|
+
classNames.push(this.rowClassName(data));
|
|
311
|
+
} else if (this.rowClassName) {
|
|
312
|
+
classNames.push(this.rowClassName);
|
|
313
|
+
}
|
|
314
|
+
return classNames.join(' ');
|
|
315
|
+
},
|
|
316
|
+
getRowClassName(row, rowIndex) {
|
|
317
|
+
let index = this.indexes[this.getRowKey(row, rowIndex)];
|
|
318
|
+
return 'tnxel-edit-table__row--' + (Array.isArray(index) ? index.join('_') : index);
|
|
319
|
+
},
|
|
320
|
+
focusRowFirstInput(row, rowIndex) {
|
|
321
|
+
if (row && this.$refs.table) {
|
|
322
|
+
let table = this.$refs.table.$el;
|
|
323
|
+
let rowClassName = this.getRowClassName(row, rowIndex);
|
|
324
|
+
let rowDoms = table.getElementsByClassName(rowClassName);
|
|
325
|
+
if (rowDoms.length) {
|
|
326
|
+
let rowDom = rowDoms[0];
|
|
327
|
+
if (rowDom) {
|
|
328
|
+
let cells = rowDom.getElementsByClassName('cell');
|
|
329
|
+
for (let cell of cells) {
|
|
330
|
+
let input = cell.querySelector('input:first-child');
|
|
331
|
+
if (input) {
|
|
332
|
+
input.focus();
|
|
299
333
|
return true;
|
|
334
|
+
} else {
|
|
335
|
+
let textarea = cell.querySelector('textarea:first-child');
|
|
336
|
+
if (textarea) {
|
|
337
|
+
textarea.focus();
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
300
340
|
}
|
|
301
341
|
}
|
|
302
342
|
}
|
|
@@ -306,33 +346,107 @@ export default {
|
|
|
306
346
|
},
|
|
307
347
|
toAddRow() {
|
|
308
348
|
let row = this.newRow();
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
this.
|
|
312
|
-
this.
|
|
313
|
-
|
|
349
|
+
if (row) {
|
|
350
|
+
let rowIndex = this.data.length;
|
|
351
|
+
this.indexes[this.getRowKey(row, rowIndex)] = rowIndex;
|
|
352
|
+
this.data.push(row);
|
|
353
|
+
this.$nextTick(() => {
|
|
354
|
+
setTimeout(() => {
|
|
355
|
+
this.bindElementRules();
|
|
356
|
+
this.focusRowFirstInput(row, rowIndex);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
}
|
|
314
360
|
},
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
this.focusRowFirstInput(index - 1);
|
|
361
|
+
isRemovableRow(row, rowIndex) {
|
|
362
|
+
if (typeof this.removable === 'function') {
|
|
363
|
+
let index = this.indexes[this.getRowKey(row, rowIndex)];
|
|
364
|
+
let removable = this.removable(row, index);
|
|
365
|
+
if (removable !== undefined) {
|
|
366
|
+
return removable;
|
|
322
367
|
}
|
|
368
|
+
// 自定义函数如果返回undefined,则使用默认判断逻辑
|
|
369
|
+
}
|
|
370
|
+
return !!this.removable;
|
|
371
|
+
},
|
|
372
|
+
removeRow(row, rowIndex) {
|
|
373
|
+
this.locateRow(row, rowIndex, (dataList, index) => {
|
|
374
|
+
delete this.indexes[this.getRowKey(row, rowIndex)];
|
|
375
|
+
dataList.splice(index, 1);
|
|
376
|
+
this.$emit('removed', row, rowIndex);
|
|
377
|
+
this.$nextTick(() => {
|
|
378
|
+
setTimeout(() => {
|
|
379
|
+
let next = dataList[index];
|
|
380
|
+
let nextIndex = rowIndex;
|
|
381
|
+
if (!next) {
|
|
382
|
+
next = dataList[index - 1];
|
|
383
|
+
nextIndex = rowIndex - 1;
|
|
384
|
+
}
|
|
385
|
+
this.focusRowFirstInput(next, nextIndex);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
323
388
|
});
|
|
324
389
|
},
|
|
325
|
-
|
|
326
|
-
if (
|
|
327
|
-
|
|
328
|
-
|
|
390
|
+
locateRow(row, rowIndex, func) {
|
|
391
|
+
if (typeof rowIndex === 'function') {
|
|
392
|
+
func = rowIndex;
|
|
393
|
+
rowIndex = undefined;
|
|
394
|
+
}
|
|
395
|
+
let indexes = this.indexes[this.getRowKey(row, rowIndex)];
|
|
396
|
+
if (!Array.isArray(indexes)) {
|
|
397
|
+
indexes = [indexes];
|
|
329
398
|
}
|
|
399
|
+
let dataList = this.tableDataList;
|
|
400
|
+
for (let i = 0; i < indexes.length - 1; i++) {
|
|
401
|
+
dataList = dataList[indexes[i]].children;
|
|
402
|
+
}
|
|
403
|
+
let index = indexes[indexes.length - 1];
|
|
404
|
+
return func(dataList, index);
|
|
330
405
|
},
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
let
|
|
334
|
-
this.
|
|
406
|
+
isSortableRow(row, rowIndex, up) {
|
|
407
|
+
if (typeof this.sortable === 'function') {
|
|
408
|
+
let index = this.indexes[this.getRowKey(row, rowIndex)];
|
|
409
|
+
let sortable = this.sortable(row, index, up);
|
|
410
|
+
if (sortable !== undefined) {
|
|
411
|
+
return sortable;
|
|
412
|
+
}
|
|
413
|
+
// 自定义函数如果返回undefined,则使用默认判断逻辑
|
|
414
|
+
}
|
|
415
|
+
if (this.sortable) {
|
|
416
|
+
if (up) {
|
|
417
|
+
let index = this.indexes[this.getRowKey(row, rowIndex)];
|
|
418
|
+
if (Array.isArray(index)) {
|
|
419
|
+
index = index[index.length - 1];
|
|
420
|
+
}
|
|
421
|
+
return index > 0;
|
|
422
|
+
} else {
|
|
423
|
+
return this.locateRow(row, rowIndex, (dataList, index) => {
|
|
424
|
+
return index < dataList.length - 1;
|
|
425
|
+
});
|
|
426
|
+
}
|
|
335
427
|
}
|
|
428
|
+
return false;
|
|
429
|
+
},
|
|
430
|
+
sortUp(row, rowIndex) {
|
|
431
|
+
this.locateRow(row, rowIndex, (dataList, index) => {
|
|
432
|
+
if (index > 0) {
|
|
433
|
+
let deleted = dataList.splice(index, 1);
|
|
434
|
+
dataList.splice(index - 1, 0, deleted[0]);
|
|
435
|
+
this.$emit('sorted', row, rowIndex, true);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
},
|
|
439
|
+
sortDown(row, rowIndex) {
|
|
440
|
+
this.locateRow(row, rowIndex, (dataList, index) => {
|
|
441
|
+
if (index < dataList.length - 1) {
|
|
442
|
+
let deleted = dataList.splice(index, 1);
|
|
443
|
+
dataList.splice(index + 1, 0, deleted[0]);
|
|
444
|
+
this.$emit('sorted', row, rowIndex, false);
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
},
|
|
448
|
+
toggleRowExpansion(row, expanded) {
|
|
449
|
+
this.$refs.table.toggleRowExpansion(row, expanded);
|
|
336
450
|
},
|
|
337
451
|
}
|
|
338
452
|
}
|
|
@@ -351,6 +465,16 @@ export default {
|
|
|
351
465
|
height: 32px;
|
|
352
466
|
}
|
|
353
467
|
|
|
468
|
+
.tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input-group__append,
|
|
469
|
+
.tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input-group__prepend {
|
|
470
|
+
border-radius: 0;
|
|
471
|
+
padding: 0 16px;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-button {
|
|
475
|
+
border-radius: 0;
|
|
476
|
+
}
|
|
477
|
+
|
|
354
478
|
.tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input--small .el-input__wrapper,
|
|
355
479
|
.tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input--small .el-select__wrapper {
|
|
356
480
|
height: 24px;
|
|
@@ -377,6 +501,45 @@ export default {
|
|
|
377
501
|
text-align: left;
|
|
378
502
|
}
|
|
379
503
|
|
|
504
|
+
.tnxel-edit-table-container .el-table .cell {
|
|
505
|
+
display: flex;
|
|
506
|
+
align-items: center;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.tnxel-edit-table-container .el-table .is-center .cell {
|
|
510
|
+
justify-content: center;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.tnxel-edit-table-container .el-table .el-table__placeholder {
|
|
514
|
+
width: 20px;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.tnxel-edit-table-container .el-table .el-table__indent + .el-table__placeholder {
|
|
518
|
+
width: 16px;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.tnxel-edit-table-container .el-table .is-center .el-table__placeholder {
|
|
522
|
+
width: 16px;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.tnxel-edit-table-container .el-table .is-center .el-table__indent + .el-table__placeholder {
|
|
526
|
+
width: 24px;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.tnxel-edit-table-container .el-table [class*=el-table__row--level] .el-table__expand-icon {
|
|
530
|
+
margin-left: 4px;
|
|
531
|
+
margin-right: 4px;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.tnxel-edit-table-container .el-table [class*=el-table__row--level] .is-center .el-table__expand-icon {
|
|
535
|
+
margin-left: 0;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.tnxel-edit-table-container .tnxel-edit-table .el-table__expand-icon + div {
|
|
539
|
+
width: auto;
|
|
540
|
+
flex-grow: 1;
|
|
541
|
+
}
|
|
542
|
+
|
|
380
543
|
.tnxel-edit-table-container .el-table .is-error {
|
|
381
544
|
box-shadow: 0 0 0 1px var(--el-color-danger) inset;
|
|
382
545
|
}
|
|
@@ -38,9 +38,11 @@
|
|
|
38
38
|
<Management v-else-if="value === 'Management'"/>
|
|
39
39
|
<Memo v-else-if="value === 'Memo'"/>
|
|
40
40
|
<Minus v-else-if="value === 'Minus'"/>
|
|
41
|
+
<More v-else-if="value === 'More'"/>
|
|
41
42
|
<MoreFilled v-else-if="value === 'MoreFilled'"/>
|
|
42
43
|
<Notebook v-else-if="value === 'Notebook'"/>
|
|
43
44
|
<OfficeBuilding v-else-if="value === 'OfficeBuilding'"/>
|
|
45
|
+
<Operation v-else-if="value === 'Operation'"/>
|
|
44
46
|
<Picture v-else-if="value === 'Picture'"/>
|
|
45
47
|
<PictureFilled v-else-if="value === 'PictureFilled'"/>
|
|
46
48
|
<Plus v-else-if="value === 'Plus'"/>
|
|
@@ -105,9 +107,11 @@ import {
|
|
|
105
107
|
Management,
|
|
106
108
|
Memo,
|
|
107
109
|
Minus,
|
|
110
|
+
More,
|
|
108
111
|
MoreFilled,
|
|
109
112
|
Notebook,
|
|
110
113
|
OfficeBuilding,
|
|
114
|
+
Operation,
|
|
111
115
|
Picture,
|
|
112
116
|
PictureFilled,
|
|
113
117
|
Plus,
|
|
@@ -169,10 +173,12 @@ const components = {
|
|
|
169
173
|
Management,
|
|
170
174
|
Memo,
|
|
171
175
|
Minus,
|
|
176
|
+
More,
|
|
172
177
|
MoreFilled,
|
|
173
178
|
Notebook,
|
|
174
179
|
Loading,
|
|
175
180
|
OfficeBuilding,
|
|
181
|
+
Operation,
|
|
176
182
|
Picture,
|
|
177
183
|
PictureFilled,
|
|
178
184
|
Plus,
|
|
@@ -350,9 +350,14 @@ export default build('tnxel', () => {
|
|
|
350
350
|
text: message,
|
|
351
351
|
});
|
|
352
352
|
this._closeMessage();
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
353
|
+
try {
|
|
354
|
+
window.tnx.loadingInstance = ElLoading.service(options);
|
|
355
|
+
this._handleZIndex('.el-loading-mask');
|
|
356
|
+
this.app.eventBus.emit('tnx.showLoading', options);
|
|
357
|
+
} catch (e) {
|
|
358
|
+
window.tnx.loadingInstance = null;
|
|
359
|
+
console.error(e);
|
|
360
|
+
}
|
|
356
361
|
return window.tnx.loadingInstance;
|
|
357
362
|
},
|
|
358
363
|
closeLoading() {
|
package/src/tnxvue.js
CHANGED
|
@@ -38,6 +38,53 @@ export default build('tnxvue', () => {
|
|
|
38
38
|
window.tnx.app.page.stopCache(router, from.path);
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
|
+
/**
|
|
42
|
+
* 深度监听指定对象,在created()中调用才能生效
|
|
43
|
+
* @param vm 页面vue实例
|
|
44
|
+
* @param target 要监听的对象
|
|
45
|
+
* @param handler 处理函数
|
|
46
|
+
*/
|
|
47
|
+
deepWatch(vm, target, handler) {
|
|
48
|
+
vm.$watch(() => {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.stringify(target);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.error(e);
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}, (newValue, oldValue) => {
|
|
56
|
+
try {
|
|
57
|
+
if (newValue !== oldValue) {
|
|
58
|
+
const newObject = JSON.parse(newValue);
|
|
59
|
+
const oldObject = JSON.parse(oldValue);
|
|
60
|
+
this.deepCompare(newObject, oldObject, '', handler);
|
|
61
|
+
}
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error(e);
|
|
64
|
+
}
|
|
65
|
+
}, {deep: true});
|
|
66
|
+
},
|
|
67
|
+
deepCompare(object1, object2, path = '', handler) {
|
|
68
|
+
if (object1) {
|
|
69
|
+
const keys = Object.keys(object1);
|
|
70
|
+
keys.forEach(key => {
|
|
71
|
+
const fullPath = path ? `${path}.${key}` : key;
|
|
72
|
+
if (object2) {
|
|
73
|
+
if (Array.isArray(object1[key]) && Array.isArray(object2[key])) {
|
|
74
|
+
object1[key].forEach((item, index) => {
|
|
75
|
+
this.deepCompare(item, object2[key][index], `${fullPath}[${index}]`, handler);
|
|
76
|
+
});
|
|
77
|
+
} else if (typeof object1[key] === 'object' && typeof object2[key] === 'object') {
|
|
78
|
+
this.deepCompare(object1[key], object2[key], fullPath, handler);
|
|
79
|
+
} else if (object1[key] !== object2[key]) {
|
|
80
|
+
handler(object1[key], object2[key], fullPath);
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
handler(object1[key], undefined, fullPath);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
},
|
|
41
88
|
createVueInstance(rootComponent, router, rootProps) {
|
|
42
89
|
let vm = Vue.createApp(rootComponent, rootProps);
|
|
43
90
|
vm.use(this);
|
|
@@ -49,7 +96,7 @@ export default build('tnxvue', () => {
|
|
|
49
96
|
vm.config.globalProperties.$router = window.tnx.router.instance;
|
|
50
97
|
}
|
|
51
98
|
// vm.config.unwrapInjectedRef = true;
|
|
52
|
-
window.tnx.app.eventBus = mitt();
|
|
99
|
+
window.tnx.app.eventBus = window.tnx.app.eventBus || mitt();
|
|
53
100
|
window.tnx.app.eventBus.once = function (name, handler) {
|
|
54
101
|
this.all.set(name, [handler]);
|
|
55
102
|
}
|