@truenewx/tnxvue3 3.0.0-alpha.27 → 3.0.0-alpha.29

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truenewx/tnxvue3",
3
- "version": "3.0.0-alpha.27",
3
+ "version": "3.0.0-alpha.29",
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.15",
27
+ "@truenewx/tnxcore": "3.0.0-alpha.16",
28
28
  "@element-plus/icons-vue": "2.3.1",
29
29
  "async-validator": "4.2.5",
30
30
  "mitt": "3.0.1"
@@ -1,7 +1,9 @@
1
1
  <template>
2
- <el-tooltip :content="tooltipContent" :placement="tooltipPlacement" :disabled="disabled || !tooltipContent"
3
- v-if="disabled === false || disabledTip !== false">
4
- <el-dropdown split-button :type="type" :class="className" :disabled="disabled" :title="title" :size="size"
2
+ <el-tooltip
3
+ :content="tooltipContent"
4
+ :placement="tooltipPlacement"
5
+ :disabled="finalDisabled || !tooltipContent">
6
+ <el-dropdown split-button :type="type" :class="className" :disabled="finalDisabled" :title="title" :size="size"
5
7
  :style="$attrs.style" @click="clickButton" @command="clickItem" v-if="dropdownItems.length">
6
8
  <i :class="icon" style="margin-right: 0.5rem;" v-if="icon"></i>
7
9
  <template v-if="!hiddenCaption">
@@ -19,10 +21,21 @@
19
21
  </el-dropdown-menu>
20
22
  </template>
21
23
  </el-dropdown>
22
- <el-button :type="type" :class="className" :disabled="disabled" :title="title" @click="clickButton" :size="size"
23
- :loading="loading" :plain="plain" :link="link" :bg="bg" :autofocus="autofocus"
24
+ <el-button :type="type"
25
+ :class="className"
26
+ :disabled="finalDisabled"
27
+ :title="title"
28
+ @click="clickButton"
29
+ :size="size"
30
+ :loading="loading"
31
+ :plain="plain"
32
+ :link="link"
33
+ :bg="bg"
34
+ :autofocus="autofocus"
24
35
  :round="round"
25
- :circle="circle" :style="$attrs.style" v-else>
36
+ :circle="circle"
37
+ :style="$attrs.style"
38
+ v-else>
26
39
  <tnxel-icon :value="icon" v-if="icon"/>
27
40
  <span v-if="!hiddenCaption && ($slots.default || menuItem)">
28
41
  <slot>{{ menuItem ? menuItem.caption : '' }}</slot>
@@ -52,7 +65,13 @@ export default {
52
65
  },
53
66
  type: String,
54
67
  icon: String,
55
- size: String,
68
+ size: {
69
+ type: String,
70
+ validator: value => {
71
+ return ['small', 'default', 'large'].includes(value);
72
+ },
73
+ default: 'default',
74
+ },
56
75
  loading: Boolean,
57
76
  plain: Boolean,
58
77
  link: Boolean,
@@ -68,6 +87,10 @@ export default {
68
87
  type: String,
69
88
  default: 'top',
70
89
  },
90
+ disabled: {
91
+ type: Boolean,
92
+ default: false,
93
+ },
71
94
  disabledTip: {
72
95
  type: [String, Boolean],
73
96
  default: '没有操作权限',
@@ -83,7 +106,7 @@ export default {
83
106
  }
84
107
  return {
85
108
  menuItem: menuItem,
86
- disabled: null,
109
+ finalDisabled: this.disabled,
87
110
  dropdownItems: [],
88
111
  }
89
112
  },
@@ -105,7 +128,13 @@ export default {
105
128
  return undefined;
106
129
  },
107
130
  title() {
108
- return this.disabled ? this.disabledTip : this.$attrs.title;
131
+ if (this.finalDisabled) {
132
+ if (this.disabledTip === false) {
133
+ return undefined;
134
+ }
135
+ return this.disabledTip;
136
+ }
137
+ return this.$attrs.title;
109
138
  }
110
139
  },
111
140
  created() {
@@ -122,11 +151,11 @@ export default {
122
151
  methods: {
123
152
  init() {
124
153
  if (this.granted !== null) {
125
- this.disabled = !this.granted;
154
+ this.finalDisabled = this.disabled || !this.granted;
126
155
  } else if (this.menu && this.path) {
127
156
  let vm = this;
128
157
  this.menu.loadGrantedItems(function () {
129
- vm.disabled = !vm.menu.isGranted(vm.path);
158
+ vm.finalDisabled = this.disabled || !vm.menu.isGranted(vm.path);
130
159
  vm.buildDropdownItems();
131
160
  });
132
161
  }
@@ -40,15 +40,18 @@
40
40
  <div class="tnxel-edit-table-footer" v-if="addable">
41
41
  <tnxel-button type="primary" link icon="Plus" @click="toAddRow">{{ addText }}</tnxel-button>
42
42
  </div>
43
+ <tnxel-icon class="d-none icon-warning" value="WarningFilled"/>
43
44
  </div>
44
45
  </template>
45
46
 
46
47
  <script>
47
48
  import Button from '../button/Button.vue';
49
+ import Icon from '../icon/Icon.vue';
48
50
 
49
51
  export default {
50
52
  components: {
51
53
  'tnxel-button': Button,
54
+ 'tnxel-icon': Icon,
52
55
  },
53
56
  name: 'TnxelEditTable',
54
57
  props: {
@@ -192,15 +195,7 @@ export default {
192
195
  });
193
196
  },
194
197
  bindRules() {
195
- this.loopValidatableElements((fieldName, element) => {
196
- element.addEventListener('blur', event => {
197
- let element = event.target;
198
- this.validateElement(fieldName, element);
199
- });
200
- element.addEventListener('focus', event => {
201
- this.removeErrorIcon(event.target);
202
- });
203
- });
198
+ this.bindElementRules();
204
199
  this.loopColumns((fieldName, columnName) => {
205
200
  let rules = this.validationRules[fieldName];
206
201
  if (rules) {
@@ -216,6 +211,20 @@ export default {
216
211
  }
217
212
  });
218
213
  },
214
+ bindElementRules() {
215
+ this.loopValidatableElements((fieldName, element) => {
216
+ let blurEventHandler = event => {
217
+ this.validateElement(fieldName, event.target);
218
+ };
219
+ element.removeEventListener('blur', blurEventHandler);
220
+ element.addEventListener('blur', blurEventHandler);
221
+ let focusEventHandler = event => {
222
+ this.removeErrorIcon(event.target);
223
+ };
224
+ element.removeEventListener('focus', focusEventHandler);
225
+ element.addEventListener('focus', focusEventHandler);
226
+ });
227
+ },
219
228
  validateElement(fieldName, element) {
220
229
  this.removeErrorIcon(element);
221
230
  element.parentElement.classList.remove('is-error');
@@ -234,9 +243,13 @@ export default {
234
243
  }
235
244
  message = message.trim();
236
245
  element.parentElement.classList.add('is-error');
237
- let icon = document.createElement('i');
246
+
247
+ let container = document.getElementById(this.id);
248
+ let icon = container.getElementsByClassName('icon-warning')[0];
249
+ icon = icon.cloneNode(true);
250
+ icon.classList.remove('d-none');
251
+ icon.classList.remove('icon-warning');
238
252
  icon.classList.add('error-icon');
239
- icon.classList.add('el-icon'); // TODO
240
253
  icon.classList.add('text-danger');
241
254
  icon.title = message;
242
255
  icon.style.top = (element.parentElement.offsetHeight - 16) / 2 + 'px';
@@ -295,6 +308,7 @@ export default {
295
308
  let row = this.newRow();
296
309
  this.data.push(row);
297
310
  this.$nextTick(() => {
311
+ this.bindElementRules();
298
312
  this.focusRowFirstInput(this.data.length - 1);
299
313
  });
300
314
  },
@@ -337,11 +351,20 @@ export default {
337
351
  height: 32px;
338
352
  }
339
353
 
354
+ .tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input--small .el-input__wrapper,
355
+ .tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input--small .el-select__wrapper {
356
+ height: 24px;
357
+ }
358
+
340
359
  .tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-textarea__wrapper {
341
360
  border-radius: 0;
342
361
  height: 40px;
343
362
  }
344
363
 
364
+ .tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input--small .el-textarea__wrapper {
365
+ height: 32px;
366
+ }
367
+
345
368
  .tnxel-edit-table-container .tnxel-edit-table .is-center .el-input__inner {
346
369
  text-align: center;
347
370
  }
@@ -354,14 +377,8 @@ export default {
354
377
  text-align: left;
355
378
  }
356
379
 
357
- .tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-input__inner:focus,
358
- .tnxel-edit-table-container .el-table.padding-none .el-table__body-wrapper .el-textarea__inner:focus {
359
- border-color: var(--el-color-primary);
360
- }
361
-
362
- .tnxel-edit-table-container .el-table .is-error .el-input__inner,
363
- .tnxel-edit-table-container .el-table .is-error .el-textarea__inner {
364
- border-color: var(--el-color-danger);
380
+ .tnxel-edit-table-container .el-table .is-error {
381
+ box-shadow: 0 0 0 1px var(--el-color-danger) inset;
365
382
  }
366
383
 
367
384
  .tnxel-edit-table-container .el-table th.is-required:not(.is-no-asterisk) .cell:after {
@@ -375,6 +392,7 @@ export default {
375
392
  top: 12px;
376
393
  right: 10px;
377
394
  font-size: 16px;
395
+ cursor: default;
378
396
  }
379
397
 
380
398
  .tnxel-edit-table-container .el-table .el-input__inner:focus + .error-icon,
@@ -391,9 +409,9 @@ export default {
391
409
  }
392
410
 
393
411
  .tnxel-edit-table-container .tnxel-edit-table-footer {
394
- border-left: 1px solid var(--el-border-color);
395
- border-right: 1px solid var(--el-border-color);
396
- border-bottom: 1px solid var(--el-border-color);
412
+ border-left: 1px solid var(--el-border-color-lighter);
413
+ border-right: 1px solid var(--el-border-color-lighter);
414
+ border-bottom: 1px solid var(--el-border-color-lighter);
397
415
  height: 32px;
398
416
  display: flex;
399
417
  align-items: center;
@@ -14,6 +14,7 @@
14
14
  <CircleCheckFilled v-else-if="value === 'CircleCheckFilled'"/>
15
15
  <CircleClose v-else-if="value === 'CircleClose'"/>
16
16
  <CircleCloseFilled v-else-if="value === 'CircleCloseFilled'"/>
17
+ <CirclePlus v-else-if="value === 'CirclePlus'"/>
17
18
  <Close v-else-if="value === 'Close'"/>
18
19
  <CloseBold v-else-if="value === 'CloseBold'"/>
19
20
  <CopyDocument v-else-if="value === 'CopyDocument'"/>
@@ -27,10 +28,13 @@
27
28
  <Files v-else-if="value === 'Files'"/>
28
29
  <Finished v-else-if="value === 'Finished'"/>
29
30
  <Folder v-else-if="value === 'Folder'"/>
31
+ <FolderOpened v-else-if="value === 'FolderOpened'"/>
32
+ <Grid v-else-if="value === 'Grid'"/>
30
33
  <Histogram v-else-if="value === 'Histogram'"/>
31
34
  <HomeFilled v-else-if="value === 'HomeFilled'"/>
32
35
  <InfoFilled v-else-if="value === 'InfoFilled'"/>
33
36
  <List v-else-if="value === 'List'"/>
37
+ <Management v-else-if="value === 'Management'"/>
34
38
  <Memo v-else-if="value === 'Memo'"/>
35
39
  <Minus v-else-if="value === 'Minus'"/>
36
40
  <MoreFilled v-else-if="value === 'MoreFilled'"/>
@@ -76,6 +80,7 @@ import {
76
80
  CircleCheckFilled,
77
81
  CircleClose,
78
82
  CircleCloseFilled,
83
+ CirclePlus,
79
84
  Close,
80
85
  CloseBold,
81
86
  CopyDocument,
@@ -89,11 +94,14 @@ import {
89
94
  Files,
90
95
  Finished,
91
96
  Folder,
97
+ FolderOpened,
98
+ Grid,
92
99
  Histogram,
93
100
  HomeFilled,
94
101
  InfoFilled,
95
102
  List,
96
103
  Loading,
104
+ Management,
97
105
  Memo,
98
106
  Minus,
99
107
  MoreFilled,
@@ -137,6 +145,7 @@ const components = {
137
145
  CircleCheckFilled,
138
146
  CircleClose,
139
147
  CircleCloseFilled,
148
+ CirclePlus,
140
149
  Close,
141
150
  CloseBold,
142
151
  CopyDocument,
@@ -150,10 +159,13 @@ const components = {
150
159
  Files,
151
160
  Finished,
152
161
  Folder,
162
+ FolderOpened,
163
+ Grid,
153
164
  Histogram,
154
165
  HomeFilled,
155
166
  InfoFilled,
156
167
  List,
168
+ Management,
157
169
  Memo,
158
170
  Minus,
159
171
  MoreFilled,
@@ -142,8 +142,8 @@
142
142
  {{ emptyText }}
143
143
  </el-option>
144
144
  <template v-for="item in items">
145
- <el-option :key="item[valueName]" :value="item[valueName]" :data-value="item[valueName]"
146
- :disabled="item.disabled === true || typeof item.disabled === 'string'"
145
+ <el-option :key="item[valueName]" :value="item[valueName]" :label="item[textName]"
146
+ :data-value="item[valueName]" :disabled="item.disabled === true || typeof item.disabled === 'string'"
147
147
  :title="typeof item.disabled === 'string' ? item.disabled : item.title"
148
148
  v-if="!hiddenValues.contains(item[valueName])">
149
149
  <slot name="option" :item="item" v-if="$slots.option"></slot>
@@ -321,6 +321,17 @@ export default {
321
321
  if (!Array.isArray(model)) {
322
322
  model = [model];
323
323
  }
324
+ if (items && items.length) {
325
+ // 多选时,如果model中有值不在items中,则去掉
326
+ for (let i = model.length - 1; i >= 0; i--) {
327
+ let item = this.getItem(model[i]);
328
+ if (!item) {
329
+ model.splice(i, 1);
330
+ }
331
+ }
332
+ } else {
333
+ model = [];
334
+ }
324
335
  return model;
325
336
  }
326
337
  if (util.object.isNull(model)) {
@@ -247,6 +247,7 @@ export default build('tnxel', () => {
247
247
  type: 'warning',
248
248
  confirmButtonText: '确定',
249
249
  }, options);
250
+ this.closeLoading();
250
251
  ElMessageBox.alert(message, title, options).then(callback);
251
252
  this._handleZIndex('.el-message-box__wrapper:last');
252
253
  this.app.eventBus.emit('tnx.alert', options);
@@ -258,6 +259,7 @@ export default build('tnxel', () => {
258
259
  type: 'success',
259
260
  confirmButtonText: '确定',
260
261
  });
262
+ this.closeLoading();
261
263
  ElMessageBox.alert(message, '成功', options).then(callback);
262
264
  this._handleZIndex('.el-message-box__wrapper:last');
263
265
  this.app.eventBus.emit('tnx.success', options);
@@ -269,6 +271,7 @@ export default build('tnxel', () => {
269
271
  type: 'error',
270
272
  confirmButtonText: '确定',
271
273
  });
274
+ this.closeLoading();
272
275
  ElMessageBox.alert(message, '错误', options).then(callback);
273
276
  this._handleZIndex('.el-message-box__wrapper:last');
274
277
  this.app.eventBus.emit('tnx.error', options);
@@ -308,6 +311,7 @@ export default build('tnxel', () => {
308
311
  callback(yes);
309
312
  }
310
313
  }
314
+ this.closeLoading();
311
315
  ElMessageBox.confirm(message, title, options);
312
316
  this._handleZIndex('.el-message-box__wrapper:last');
313
317
  this.app.eventBus.emit('tnx.confirm', options);
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 工具栏项
3
+ */
4
+ export default class ToolBarItem {
5
+
6
+ icon = '';
7
+ caption = '';
8
+ disabled = false;
9
+ click = null;
10
+
11
+ static from(object) {
12
+ return Object.assign(new ToolBarItem(), object);
13
+ }
14
+
15
+ }
@@ -0,0 +1,43 @@
1
+ <template>
2
+ <Button type="default" link
3
+ :icon="item.icon"
4
+ :tooltip="item.caption" tooltip-placement="bottom"
5
+ :disabled="item.disabled"
6
+ :key="item.disabled"
7
+ :disabled-tip="false"
8
+ :size="size"
9
+ @click="item.click"/>
10
+ </template>
11
+
12
+ <script>
13
+ import ToolBarItem from './ToolBarItem.js';
14
+ import Button from '../button/Button.vue';
15
+
16
+ export default {
17
+ name: 'TnxelToolBarItem',
18
+ components: {Button},
19
+ props: {
20
+ item: {
21
+ type: ToolBarItem,
22
+ required: true,
23
+ },
24
+ size: {
25
+ type: String,
26
+ validator: value => {
27
+ return ['small', 'default', 'large'].includes(value);
28
+ },
29
+ default: 'default',
30
+ },
31
+ },
32
+ data() {
33
+ return {
34
+ model: {},
35
+ };
36
+ },
37
+ methods: {}
38
+ }
39
+ </script>
40
+
41
+ <style>
42
+
43
+ </style>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <div class="tnxel-toolbar">
3
+ <div class="flex-v-center">
4
+ <template v-for="(item, index) of leftItems" :key="index">
5
+ <el-divider direction="vertical" v-if="item === '|'"/>
6
+ <ToolBarItem
7
+ :item="Item.from(item)"
8
+ :size="size"
9
+ v-else-if="typeof item ==='object'"/>
10
+ </template>
11
+ </div>
12
+ <div class="flex-v-center">
13
+ <ToolBarItem v-for="(item, index) of rightItems" :key="index"
14
+ :item="Item.from(item)"
15
+ :size="size"/>
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ import ToolBarItem from './ToolBarItem.vue';
22
+ import Item from './ToolBarItem.js';
23
+
24
+ export default {
25
+ name: 'TnxelToolbar',
26
+ components: {ToolBarItem},
27
+ props: {
28
+ leftItems: Array,
29
+ rightItems: Array,
30
+ size: {
31
+ type: String,
32
+ validator: value => {
33
+ return ['small', 'default', 'large'].includes(value);
34
+ },
35
+ default: 'default',
36
+ },
37
+ },
38
+ data() {
39
+ return {
40
+ Item,
41
+ model: {},
42
+ };
43
+ },
44
+ methods: {}
45
+ }
46
+ </script>
47
+
48
+ <style>
49
+ .tnxel-toolbar {
50
+ height: 32px;
51
+ padding: 0 8px;
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: space-between;
55
+ }
56
+ </style>
@@ -37,8 +37,10 @@ function addRoute(routes, superiorPath, item, fnImportPage) {
37
37
  function applyItemsToRoutes(superiorPath, items, routes, fnImportPage) {
38
38
  if (items && items.length) {
39
39
  items.forEach(item => {
40
- addRoute(routes, superiorPath, item, fnImportPage);
41
- applyItemsToRoutes(item.path, item.subs, routes, fnImportPage);
40
+ if (item) {
41
+ addRoute(routes, superiorPath, item, fnImportPage);
42
+ applyItemsToRoutes(item.path, item.subs, routes, fnImportPage);
43
+ }
42
44
  });
43
45
  }
44
46
  }
@@ -68,7 +70,11 @@ export default function (VueRouter, menu, fnImportPage) {
68
70
  if (Array.isArray(menu)) {
69
71
  items = [];
70
72
  menu.forEach(function (m) {
71
- items = items.concat(m.items);
73
+ if (Array.isArray(m.items)) {
74
+ items = items.concat(m.items);
75
+ } else { // menu实际上是items
76
+ items.push(m);
77
+ }
72
78
  });
73
79
  } else {
74
80
  items = menu.items;
@@ -124,8 +130,8 @@ export default function (VueRouter, menu, fnImportPage) {
124
130
 
125
131
  router.afterEach(function (to, from) {
126
132
  router.prev = from;
127
- // 前后hash相同,但全路径不同(意味着参数不同),则需要刷新页面,否则页面不会刷新
128
- if (to.href === from.href && to.fullPath !== from.fullPath) {
133
+ // 前后路径相同,但全路径不同(意味着参数不同),则需要刷新页面,否则页面不会刷新
134
+ if (to.path === from.path && to.fullPath !== from.fullPath) {
129
135
  window.location.reload();
130
136
  }
131
137
  });
package/src/tnxvue.js CHANGED
@@ -126,6 +126,16 @@ export default build('tnxvue', () => {
126
126
  }
127
127
  }
128
128
  }];
129
+ } else if (type === 'close') {
130
+ return [{
131
+ text: '关闭',
132
+ type: theme || 'default',
133
+ click(close) {
134
+ if (typeof callback === 'function') {
135
+ return callback.call(this, close);
136
+ }
137
+ }
138
+ }];
129
139
  } else {
130
140
  return [{
131
141
  text: '确定',