@truenewx/tnxvue3 3.0.6 → 3.0.7
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 +1 -1
- package/src/bootstrap-vue/cascader/Cascader.vue +41 -1
- package/src/bootstrap-vue/dialog/Dialog.vue +1 -0
- package/src/bootstrap-vue/enum-select/EnumSelect.vue +1 -3
- package/src/bootstrap-vue/form/Form.vue +4 -1
- package/src/bootstrap-vue/form/FormGroup.vue +22 -1
- package/src/bootstrap-vue/query-form/QueryForm.vue +41 -0
- package/src/bootstrap-vue/select/Select.vue +13 -8
- package/src/bootstrap-vue/tnxbsv.css +11 -7
- package/src/bootstrap-vue/tnxbsv.js +13 -0
package/package.json
CHANGED
|
@@ -113,7 +113,7 @@ export default {
|
|
|
113
113
|
data() {
|
|
114
114
|
return {
|
|
115
115
|
visible: false,
|
|
116
|
-
selections:
|
|
116
|
+
selections: this.initSelections(),
|
|
117
117
|
optionsArray: [this.options],
|
|
118
118
|
inputValue: '',
|
|
119
119
|
filtering: false,
|
|
@@ -140,6 +140,12 @@ export default {
|
|
|
140
140
|
this.inputValue = this.displayValue;
|
|
141
141
|
}
|
|
142
142
|
},
|
|
143
|
+
modelValue(newValue) {
|
|
144
|
+
const currentValue = this.selections.length > 0 ? this.selections[this.selections.length - 1][this.props.value] : '';
|
|
145
|
+
if (newValue !== currentValue) {
|
|
146
|
+
this.selections = this.initSelections();
|
|
147
|
+
}
|
|
148
|
+
},
|
|
143
149
|
options: {
|
|
144
150
|
deep: true,
|
|
145
151
|
handler(newOptions) {
|
|
@@ -165,6 +171,40 @@ export default {
|
|
|
165
171
|
document.removeEventListener('click', this.handleClickOutside);
|
|
166
172
|
},
|
|
167
173
|
methods: {
|
|
174
|
+
initSelections() {
|
|
175
|
+
if (!this.modelValue || !this.options) {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
const path = this.findPathByValue(this.options, this.modelValue);
|
|
179
|
+
if (path) {
|
|
180
|
+
// 初始化 optionsArray
|
|
181
|
+
path.forEach((option, index) => {
|
|
182
|
+
if (index < path.length - 1) {
|
|
183
|
+
const children = option[this.props.children];
|
|
184
|
+
if (children) {
|
|
185
|
+
this.optionsArray[index + 1] = children;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
return path;
|
|
190
|
+
}
|
|
191
|
+
return [];
|
|
192
|
+
},
|
|
193
|
+
findPathByValue(options, value, path = []) {
|
|
194
|
+
for (const option of options) {
|
|
195
|
+
const currentPath = [...path, option];
|
|
196
|
+
if (option[this.props.value] === value) {
|
|
197
|
+
return currentPath;
|
|
198
|
+
}
|
|
199
|
+
if (option[this.props.children]) {
|
|
200
|
+
const foundPath = this.findPathByValue(option[this.props.children], value, currentPath);
|
|
201
|
+
if (foundPath) {
|
|
202
|
+
return foundPath;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
},
|
|
168
208
|
clearValue(e) {
|
|
169
209
|
e.stopPropagation();
|
|
170
210
|
this.selections = [];
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
:default-value="defaultValue"
|
|
8
8
|
:empty="empty"
|
|
9
9
|
:empty-value="emptyValue"
|
|
10
|
-
:placeholder="placeholder"
|
|
11
10
|
:disabled="disabled"
|
|
12
11
|
:filterable="filterable"
|
|
13
12
|
:theme="theme"
|
|
@@ -39,9 +38,8 @@ export default {
|
|
|
39
38
|
},
|
|
40
39
|
emptyValue: {
|
|
41
40
|
type: [String, Number, Boolean, Array],
|
|
42
|
-
default:
|
|
41
|
+
default: null,
|
|
43
42
|
},
|
|
44
|
-
placeholder: String,
|
|
45
43
|
disabled: Boolean,
|
|
46
44
|
tagClick: Function,
|
|
47
45
|
change: Function,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<BForm :id="id" class="tnxbsv-form" :class="{initializing: initializing}">
|
|
2
|
+
<BForm :id="id" class="tnxbsv-form" :class="{initializing: initializing, 'form-inline': inline}">
|
|
3
3
|
<slot></slot>
|
|
4
4
|
</BForm>
|
|
5
5
|
</template>
|
|
@@ -132,6 +132,9 @@ export default {
|
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
updateLabelWidth() {
|
|
135
|
+
if (this.inline) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
135
138
|
let maxWidth = 0;
|
|
136
139
|
let groupElements = this.$el.querySelectorAll('.b-form-group');
|
|
137
140
|
for (let groupElement of groupElements) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="tnxbsv-form-group b-form-group" :prop="prop">
|
|
3
3
|
<div class="tnxbsv-form-group__label-wrapper">
|
|
4
4
|
<slot name="label">
|
|
5
|
-
<label class="form-label">{{ label }}</label>
|
|
5
|
+
<label class="form-label" :style="labelStyle">{{ label }}</label>
|
|
6
6
|
</slot>
|
|
7
7
|
</div>
|
|
8
8
|
<div class="tnxbsv-form-group__content-wrapper">
|
|
@@ -16,6 +16,7 @@ export default {
|
|
|
16
16
|
name: 'TnxbsvFormGroup',
|
|
17
17
|
props: {
|
|
18
18
|
label: String,
|
|
19
|
+
labelWidth: [String, Number],
|
|
19
20
|
prop: String,
|
|
20
21
|
},
|
|
21
22
|
data() {
|
|
@@ -23,6 +24,26 @@ export default {
|
|
|
23
24
|
model: {},
|
|
24
25
|
};
|
|
25
26
|
},
|
|
27
|
+
computed: {
|
|
28
|
+
labelStyle() {
|
|
29
|
+
let style = {};
|
|
30
|
+
if (this.labelWidth) {
|
|
31
|
+
let width;
|
|
32
|
+
if (typeof this.labelWidth === 'string') {
|
|
33
|
+
// 如果是纯数字内容,则附加px单位
|
|
34
|
+
if (/^\d+$/.test(this.labelWidth)) {
|
|
35
|
+
width = this.labelWidth + 'px';
|
|
36
|
+
} else {
|
|
37
|
+
width = this.labelWidth;
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
width = this.labelWidth + 'px';
|
|
41
|
+
}
|
|
42
|
+
style.width = width;
|
|
43
|
+
}
|
|
44
|
+
return style;
|
|
45
|
+
},
|
|
46
|
+
},
|
|
26
47
|
methods: {}
|
|
27
48
|
}
|
|
28
49
|
</script>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TnxbsvForm class="tnxbsv-query-form" :model="params" inline>
|
|
3
|
+
<slot></slot>
|
|
4
|
+
<slot name="actions">
|
|
5
|
+
<div class="tnxbsv-query-form-actions">
|
|
6
|
+
<TnxbsvButton variant="outline-primary" icon="bi bi-search" @click="query" v-if="query">
|
|
7
|
+
{{ queryText }}
|
|
8
|
+
</TnxbsvButton>
|
|
9
|
+
</div>
|
|
10
|
+
</slot>
|
|
11
|
+
</TnxbsvForm>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
import TnxbsvForm from '../form/Form.vue';
|
|
16
|
+
import TnxbsvButton from '../button/Button.vue';
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
name: 'TnxbsvQueryForm',
|
|
20
|
+
components: {TnxbsvForm, TnxbsvButton},
|
|
21
|
+
props: {
|
|
22
|
+
params: {
|
|
23
|
+
type: Object,
|
|
24
|
+
default: () => ({}),
|
|
25
|
+
},
|
|
26
|
+
query: Function,
|
|
27
|
+
queryText: {
|
|
28
|
+
type: String,
|
|
29
|
+
default: '查询',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
data() {
|
|
33
|
+
return {};
|
|
34
|
+
},
|
|
35
|
+
methods: {}
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style>
|
|
40
|
+
|
|
41
|
+
</style>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
:variant="theme"
|
|
14
14
|
:size="size"
|
|
15
15
|
v-else-if="selector==='dropdown'">
|
|
16
|
-
<BDropdownItem :active="isSelected(emptyValue)" @click="select(emptyValue)" v-if="empty">
|
|
16
|
+
<BDropdownItem class="empty-item" :active="isSelected(emptyValue)" @click="select(emptyValue)" v-if="empty">
|
|
17
17
|
<span>{{ emptyText || ' ' }}</span>
|
|
18
18
|
</BDropdownItem>
|
|
19
19
|
<template v-if="items">
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
</BDropdownItem>
|
|
34
34
|
</BDropdown>
|
|
35
35
|
<BFormSelect class="tnxbsv-select"
|
|
36
|
+
:class="{'is-empty': model === emptyValue}"
|
|
36
37
|
v-model="model"
|
|
37
38
|
:key="groupKey"
|
|
38
39
|
:variant="theme"
|
|
@@ -40,13 +41,9 @@
|
|
|
40
41
|
:value-field="valueName"
|
|
41
42
|
:text-field="textName"
|
|
42
43
|
:size="size"
|
|
43
|
-
:required="!empty"
|
|
44
44
|
v-else-if="items">
|
|
45
|
-
<template #default>
|
|
46
|
-
{{ currentText || placeholder }}
|
|
47
|
-
</template>
|
|
48
45
|
<template #first v-if="empty">
|
|
49
|
-
<BFormSelectOption :value="emptyValue">{{ emptyText || ' ' }}</BFormSelectOption>
|
|
46
|
+
<BFormSelectOption class="empty-item" :value="emptyValue">{{ emptyText || ' ' }}</BFormSelectOption>
|
|
50
47
|
</template>
|
|
51
48
|
<template #option="{value, text}">
|
|
52
49
|
<slot name="option" :item="getItem(value)" v-if="$slots.option"></slot>
|
|
@@ -105,10 +102,9 @@ export default {
|
|
|
105
102
|
},
|
|
106
103
|
emptyValue: {
|
|
107
104
|
type: [String, Number, Boolean, Array],
|
|
108
|
-
default:
|
|
105
|
+
default: null,
|
|
109
106
|
},
|
|
110
107
|
emptyClass: String,
|
|
111
|
-
placeholder: String,
|
|
112
108
|
disabled: Boolean,
|
|
113
109
|
tagClick: Function, // 点击一个标签选项时调用,如果返回false,则选项不会被选中
|
|
114
110
|
change: Function, // 选中值变化后的事件处理函数,比change事件传递更多参数数据
|
|
@@ -358,6 +354,15 @@ export default {
|
|
|
358
354
|
box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25);
|
|
359
355
|
}
|
|
360
356
|
|
|
357
|
+
select.tnxbsv-select.is-empty,
|
|
358
|
+
.tnxbsv-select .empty-item {
|
|
359
|
+
color: var(--bs-tertiary-color);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
select.tnxbsv-select.is-empty option:not(.empty-item) {
|
|
363
|
+
color: var(--bs-body-color);
|
|
364
|
+
}
|
|
365
|
+
|
|
361
366
|
.tnxbsv-radio-group.btn-group > .btn {
|
|
362
367
|
flex: none;
|
|
363
368
|
--bs-btn-padding-x: 1rem;
|
|
@@ -18,22 +18,17 @@
|
|
|
18
18
|
.form-inline {
|
|
19
19
|
display: flex;
|
|
20
20
|
flex-wrap: wrap;
|
|
21
|
-
align-items: center;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
.form-inline-group {
|
|
23
|
+
.form-inline .b-form-group {
|
|
25
24
|
display: flex;
|
|
26
25
|
flex-wrap: nowrap;
|
|
27
26
|
height: fit-content;
|
|
27
|
+
margin-right: 1.5rem;
|
|
28
28
|
margin-bottom: 1rem;
|
|
29
29
|
width: fit-content;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
.form-inline-group .col-form-label {
|
|
33
|
-
white-space: nowrap;
|
|
34
|
-
margin-right: 1rem;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
32
|
.badge {
|
|
38
33
|
border: 1px solid transparent;
|
|
39
34
|
}
|
|
@@ -70,3 +65,12 @@
|
|
|
70
65
|
.form-check > * {
|
|
71
66
|
cursor: pointer;
|
|
72
67
|
}
|
|
68
|
+
|
|
69
|
+
.tnxbsv-dialog-confirm {
|
|
70
|
+
display: flex;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.tnxbsv-dialog-confirm i {
|
|
74
|
+
color: var(--bs-secondary-color);
|
|
75
|
+
margin-right: 0.5rem;
|
|
76
|
+
}
|
|
@@ -15,6 +15,7 @@ import FormGroup from './form/FormGroup.vue';
|
|
|
15
15
|
import LoadingIcon from './loading-icon/LoadingIcon.vue';
|
|
16
16
|
import LoadingOverlay from './loading-overlay/LoadingOverlay.vue';
|
|
17
17
|
import Paged from './paged/Paged.vue';
|
|
18
|
+
import QueryForm from './query-form/QueryForm.vue';
|
|
18
19
|
import QueryTable from './query-table/QueryTable.vue';
|
|
19
20
|
import RegionCascader from './region-cascader/RegionCascader.vue';
|
|
20
21
|
import Select from './select/Select.vue';
|
|
@@ -33,6 +34,7 @@ export default build('tnxbsv', () => {
|
|
|
33
34
|
FormGroup,
|
|
34
35
|
LoadingIcon,
|
|
35
36
|
Paged,
|
|
37
|
+
QueryForm,
|
|
36
38
|
QueryTable,
|
|
37
39
|
RegionCascader,
|
|
38
40
|
Select,
|
|
@@ -75,6 +77,17 @@ export default build('tnxbsv', () => {
|
|
|
75
77
|
this.hideLoading();
|
|
76
78
|
this.removeToast();
|
|
77
79
|
},
|
|
80
|
+
confirm(message, title, callback, options) {
|
|
81
|
+
if (typeof title === 'function') {
|
|
82
|
+
options = callback;
|
|
83
|
+
callback = title;
|
|
84
|
+
title = '确认';
|
|
85
|
+
}
|
|
86
|
+
let buttons = tnxvue.getDefaultDialogButtons('confirm', callback);
|
|
87
|
+
message =
|
|
88
|
+
`<div class="tnxbsv-dialog-confirm"><i class="bi bi-question-circle-fill"></i><div>${message}</div></div>`;
|
|
89
|
+
return this.dialog(message, title, buttons, options);
|
|
90
|
+
},
|
|
78
91
|
toast(message, timeout, callback, options = {}) {
|
|
79
92
|
if (typeof timeout === 'function') {
|
|
80
93
|
options = callback || {};
|