@v2coding/ui 0.1.0

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.
Files changed (49) hide show
  1. package/README.md +6 -0
  2. package/dist/v2coding-ui.esm.js +10840 -0
  3. package/dist/v2coding-ui.min.js +1 -0
  4. package/dist/v2coding-ui.ssr.js +10747 -0
  5. package/package.json +54 -0
  6. package/src/components/dialog/dialog.vue +179 -0
  7. package/src/components/drawer/drawer.vue +523 -0
  8. package/src/components/exports/index.vue +53 -0
  9. package/src/components/exports/remote-exports-dialog.vue +202 -0
  10. package/src/components/field/field.autocomplete.vue +21 -0
  11. package/src/components/field/field.calendar.vue +117 -0
  12. package/src/components/field/field.cascade.vue +233 -0
  13. package/src/components/field/field.checkbox.vue +134 -0
  14. package/src/components/field/field.color.vue +24 -0
  15. package/src/components/field/field.date.vue +145 -0
  16. package/src/components/field/field.icons.vue +123 -0
  17. package/src/components/field/field.number.vue +43 -0
  18. package/src/components/field/field.radio.vue +100 -0
  19. package/src/components/field/field.rate.vue +37 -0
  20. package/src/components/field/field.rich.vue +165 -0
  21. package/src/components/field/field.select.vue +210 -0
  22. package/src/components/field/field.slider.vue +66 -0
  23. package/src/components/field/field.switch.vue +14 -0
  24. package/src/components/field/field.text.vue +66 -0
  25. package/src/components/field/field.timepicker.vue +70 -0
  26. package/src/components/field/field.timeselect.vue +24 -0
  27. package/src/components/field/field.trigger.dialog.vue +50 -0
  28. package/src/components/field/field.trigger.popover.vue +63 -0
  29. package/src/components/field/field.upload.file.vue +241 -0
  30. package/src/components/field/field.upload.image.vue +125 -0
  31. package/src/components/field/field.upload.portrait.vue +304 -0
  32. package/src/components/fill-view/index.vue +43 -0
  33. package/src/components/form/form.dialog.vue +174 -0
  34. package/src/components/form/form.drawer.vue +246 -0
  35. package/src/components/form/form.fieldset.vue +110 -0
  36. package/src/components/form/form.item.vue +213 -0
  37. package/src/components/form/form.vue +293 -0
  38. package/src/components/head-menu/index.vue +188 -0
  39. package/src/components/head-menu/menu-item.vue +84 -0
  40. package/src/components/history/index.vue +360 -0
  41. package/src/components/icon/icon.vue +63 -0
  42. package/src/components/minimize/index.vue +342 -0
  43. package/src/components/page/page.vue +43 -0
  44. package/src/components/provider/provider.vue +15 -0
  45. package/src/components/scroll-view/scroll-view.vue +384 -0
  46. package/src/components/table/column.vue +262 -0
  47. package/src/components/table/table.pagination.vue +71 -0
  48. package/src/components/table/table.select.vue +165 -0
  49. package/src/components/table/table.vue +805 -0
@@ -0,0 +1,202 @@
1
+ <template>
2
+ <ui-dialog :visible="visible" @update:visible="updateVisible" :title="dialogTitle" :buttons="buttons">
3
+ <div class="exports-dialog-wrapper">
4
+ <div v-show="!selectExportsColumn">
5
+ <h3>共{{validTotalPage}}页查询结果,当前第{{validCurrentPage}}页</h3>
6
+ <el-form inline :model="params" @submit.native.prevent="handleConfirm" class="exports-from" size="mini" :rules="rules">
7
+ <el-form-item prop="start">
8
+ <el-input v-model="params.start" class="start-input">
9
+ <template slot="prepend">导出第</template>
10
+ <template slot="append">页到</template>
11
+ </el-input>
12
+ </el-form-item>
13
+ <el-form-item prop="end">
14
+ <el-input v-model="params.end" class="end-input">
15
+ <template slot="append">页</template>
16
+ </el-input>
17
+ </el-form-item>
18
+ <el-form-item style="display: block; text-align: center;">
19
+ <el-button type="text" @click="resetSelectPage">选择当前页</el-button>
20
+ <el-divider direction="vertical"/>
21
+ <el-button type="text" @click="toggleColumnConfig(true)">选择导出列</el-button>
22
+ </el-form-item>
23
+ </el-form>
24
+ </div>
25
+ <div v-show="selectExportsColumn">
26
+ <el-checkbox-group v-model="selColumns" :min="1">
27
+ <el-row>
28
+ <el-col v-for="column in allColumns" :key="column.key" :span="12">
29
+ <el-checkbox :label="column.key">{{column.title}}</el-checkbox>
30
+ </el-col>
31
+ </el-row>
32
+ </el-checkbox-group>
33
+ </div>
34
+ </div>
35
+ </ui-dialog>
36
+ </template>
37
+
38
+ <script>
39
+
40
+ export default {
41
+ name: 'remote-exports-dialog',
42
+ props: {
43
+ visible: Boolean,
44
+ currentPage: {
45
+ type: Number,
46
+ default: 1,
47
+ },
48
+ totalPage: {
49
+ type: Number,
50
+ default: 1,
51
+ },
52
+ },
53
+ data() {
54
+ return {
55
+ params: {
56
+ start: 1,
57
+ end: 1,
58
+ },
59
+ type: 1, // 1:
60
+ selColumns: [],
61
+ columns: [],
62
+ rules: {
63
+ start: {validator: this.validateStart, trigger: 'blur'},
64
+ end: {validator: this.validateEnd, trigger: 'blur'},
65
+ },
66
+ allColumns: [],
67
+ };
68
+ },
69
+ computed: {
70
+ dialogTitle() {
71
+ if (this.selectExportsColumn) {
72
+ return '选择导出列';
73
+ }
74
+ return '导出数据';
75
+ },
76
+ buttons() {
77
+ if (this.selectExportsColumn) {
78
+ return [
79
+ {text: '取消', icon: 'el-icon-error', handle: this.handleColumnCancel},
80
+ {text: '确定', icon: 'el-icon-s-tools', type: 'primary', handle: this.handleColumnConfig},
81
+ ];
82
+ }
83
+ return [
84
+ {text: '取消', icon: 'el-icon-error', handle: this.handleClose},
85
+ {text: '导出', icon: 'el-icon-download', type: 'primary', handle: this.handleConfirm},
86
+ ];
87
+ },
88
+ selectExportsColumn() {
89
+ return this.type === 2;
90
+ },
91
+ validTotalPage() {
92
+ return Math.max(1, this.totalPage);
93
+ },
94
+ validCurrentPage() {
95
+ return Math.min(Math.max(1, this.currentPage), this.validTotalPage);
96
+ },
97
+ },
98
+ mounted() {
99
+ this.init();
100
+ },
101
+ methods: {
102
+ init() {
103
+ this.initColumns();
104
+ this.resetSelectPage();
105
+ },
106
+ initColumns() {
107
+ this.allColumns = this.table.columns.filter(column => column.type === 'default' && column.className !== 'ui-table-column-action').map(({label, property}) => ({key: property, title: label}));
108
+ this.columns = this.allColumns;
109
+ this.initSelect();
110
+ },
111
+ initSelect() {
112
+ this.selColumns = this.columns.map(column => column.key);
113
+ },
114
+ handleClose() {
115
+ this.updateVisible(false);
116
+ },
117
+ handleConfirm() {
118
+ this.updateVisible(false);
119
+ this.$emit('exports', {...this.params, columns: this.columns});
120
+ },
121
+ handleColumnCancel() {
122
+ this.toggleColumnConfig(false);
123
+ this.initSelect();
124
+ },
125
+ handleColumnConfig() {
126
+ this.toggleColumnConfig(false);
127
+ this.columns = this.allColumns.filter(column => this.selColumns.includes(column.key));
128
+ },
129
+ resetSelectPage() {
130
+ this.params.start = this.validCurrentPage;
131
+ this.params.end = this.validCurrentPage;
132
+ },
133
+ toggleColumnConfig(show) {
134
+ this.type = show ? 2 : 1;
135
+ },
136
+ updateVisible(visible) {
137
+ this.$emit('update:visible', visible);
138
+ },
139
+ validateStart(rules, value, callback) {
140
+ if (!value) {
141
+ value = this.validCurrentPage;
142
+ }
143
+ let validVal = String(value).replace(/[^0-9]/ig, '').replace(/^0/, '');
144
+ validVal = Math.min(this.validTotalPage, Math.max(1, +validVal));
145
+ const {end} = this.params;
146
+ if (end && validVal > end) {
147
+ validVal = end;
148
+ }
149
+ this.params.start = validVal;
150
+ callback();
151
+ },
152
+ validateEnd(rules, value, callback) {
153
+ if (!value) {
154
+ value = this.validCurrentPage;
155
+ }
156
+ let validVal = String(value).replace(/[^0-9]/ig, '').replace(/^0/, '');
157
+ validVal = Math.min(this.validTotalPage, Math.max(1, +validVal));
158
+ const {start} = this.params;
159
+ if (start && validVal < start) {
160
+ validVal = start;
161
+ }
162
+ this.params.end = validVal;
163
+ callback();
164
+ },
165
+ },
166
+ };
167
+ </script>
168
+
169
+ <style lang="less" scoped>
170
+ .exports-dialog-wrapper {
171
+ display: flex;
172
+ align-items: center;
173
+ flex-direction: column;
174
+ max-height: 320px;
175
+ overflow: auto;
176
+
177
+ h3 {
178
+ text-align: center;
179
+ margin-bottom: 15px;
180
+ }
181
+
182
+ .exports-from {
183
+ ::v-deep .el-form-item {
184
+ margin-right: 0;
185
+
186
+ .el-input__inner {
187
+ width: 60px;
188
+ text-align: center;
189
+ }
190
+ }
191
+ }
192
+
193
+ .start-input ::v-deep .el-input-group__append {
194
+ border-radius: 0;
195
+ border-right: 0;
196
+ }
197
+
198
+ .end-input ::v-deep .el-input__inner {
199
+ border-radius: 0;
200
+ }
201
+ }
202
+ </style>
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <el-autocomplete
3
+ v-bind="$attrs"
4
+ v-on="$listeners"
5
+ :value="value"
6
+ />
7
+ </template>
8
+
9
+ <script>
10
+ import FieldMixin from './field.mixin';
11
+
12
+ export default {
13
+ name: 'ui-field-autocomplete',
14
+ inheritAttrs: false,
15
+ mixins: [FieldMixin],
16
+ };
17
+ </script>
18
+
19
+ <style lang="less">
20
+
21
+ </style>
@@ -0,0 +1,117 @@
1
+ <template>
2
+ <div class="flex-row">
3
+ <div class="calendar flex-row">
4
+ <span
5
+ v-for="(item, index) in dateType"
6
+ :key="item.name"
7
+ class="calendarItem"
8
+ @click="activeIndex=index"
9
+ :class="{
10
+ 'calendar-active': activeIndex === index
11
+ }">{{ item.name }}</span>
12
+ </div>
13
+ <el-date-picker
14
+ v-model="dateVal"
15
+ align="right"
16
+ :type="datePickerType"
17
+ :format="valueFormat"
18
+ placeholder="请选择时间"
19
+ :value-format="valueFormat"
20
+ :picker-options="pickerOptions"
21
+ @input="changeHandle">
22
+ </el-date-picker>
23
+ </div>
24
+
25
+ </template>
26
+
27
+ <script>
28
+ import FieldMixin from './field.mixin';
29
+
30
+ Date.prototype.calendar = function() {
31
+ const month = this.getMonth() +1;
32
+ return [this.getFullYear(), month< 10 ? "0"+month : month, this.getDate()].join("-")
33
+ }
34
+
35
+ export default {
36
+ name: 'ui-field-datse',
37
+ mixins: [FieldMixin],
38
+ props: {
39
+ changeFunc: {
40
+ type: Function,
41
+ }
42
+ },
43
+ data() {
44
+ return {
45
+ activeIndex: 0,
46
+ dateType: [
47
+ {name: "日", type: 1},
48
+ {name: "月", type: 2},
49
+ ],
50
+ dateVal: '',
51
+ pickerOptions: {
52
+ disabledDate: (time) => {
53
+ return time.getTime() > Date.now()
54
+ },
55
+ },
56
+ }
57
+ },
58
+ watch: {
59
+ activeIndex() {
60
+ this.tempDate = "";
61
+ this.dateVal = ""
62
+ }
63
+ },
64
+ computed: {
65
+ datePickerType() {
66
+ return this.activeIndex === 0 ? "date" : "month"
67
+ },
68
+ valueFormat() {
69
+ return this.activeIndex === 0 ? "yyyy-MM-dd" : "yyyy-MM"
70
+ }
71
+ },
72
+ methods: {
73
+ changeHandle(val) {
74
+ this.emitChange(val);
75
+ },
76
+ },
77
+ };
78
+ </script>
79
+
80
+ <style lang="less" scoped>
81
+ .ui-date-field.el-date-editor {
82
+ width: 100%;
83
+ }
84
+ .calendar {
85
+ margin-right: 20px;
86
+ .calendarItem {
87
+ display: inline-block;
88
+ box-sizing: border-box;
89
+ width: 45px;
90
+ height: 35px;
91
+ cursor: pointer;
92
+ border-right: 1px solid #e3e3ee;
93
+ text-align: center;
94
+ border: 1px solid #e3e3e3;
95
+ font-size: 14px;
96
+ &:first-of-type{
97
+ border-right: none;
98
+ border-top-left-radius: 5px;
99
+ border-bottom-left-radius: 5px;
100
+ }
101
+ &:last-of-type{
102
+ border-left: none;
103
+ border-top-right-radius: 5px;
104
+ border-bottom-right-radius: 5px;
105
+ }
106
+ }
107
+ .calendar-active{
108
+ color: #1890FF;
109
+ background: #e3e3e3;
110
+ }
111
+ }
112
+ .separator{
113
+ margin-right: 10px;
114
+ color: #333;
115
+ }
116
+
117
+ </style>
@@ -0,0 +1,233 @@
1
+ <template>
2
+ <div>
3
+ <el-cascader
4
+ v-if="!hasRefresh"
5
+ v-bind="$attrs"
6
+ v-on="_listeners"
7
+ :key="key"
8
+ :value="pickerValue"
9
+ :props="realProps"
10
+ :options="realData"
11
+ :filterable="filterable"
12
+ :show-all-levels="showAllLevels"
13
+ :show-word-limit="showWordLimit"
14
+ @change="onChange"
15
+ class="ui-cascade-field"
16
+ popper-class="ui-cascade-field-popper"
17
+ v-loading="realLoading"
18
+ element-loading-spinner="el-icon-loading"
19
+ >
20
+ </el-cascader>
21
+ <div v-if="hasRefresh" class="el-input-group el-input-group--append">
22
+ <el-cascader
23
+ v-bind="$attrs"
24
+ v-on="_listeners"
25
+ :key="key"
26
+ :value="pickerValue"
27
+ :props="realProps"
28
+ :options="realData"
29
+ :filterable="filterable"
30
+ :show-all-levels="showAllLevels"
31
+ @change="onChange"
32
+ class="ui-cascade-field"
33
+ popper-class="ui-cascade-field-popper"
34
+ v-loading="realLoading"
35
+ element-loading-spinner="el-icon-loading"
36
+ >
37
+ </el-cascader>
38
+ <div class="el-input-group__append">
39
+ <el-button @click="init" icon="el-icon-refresh"></el-button>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </template>
44
+ <script>
45
+ import FieldMixin from './field.mixin';
46
+ import DataMixin from './field.data.mixin';
47
+ import Objects from '../../util/objects';
48
+ import Strings from '../../util/strings';
49
+
50
+ export default {
51
+ name: 'ui-field-cascade',
52
+ mixins: [FieldMixin, DataMixin],
53
+ props: {
54
+ // 是否初始选中
55
+ startNull: {
56
+ type: Boolean,
57
+ default: false,
58
+ },
59
+ filterable: {
60
+ type: Boolean,
61
+ default: true,
62
+ },
63
+ showAllLevels: {
64
+ type: Boolean,
65
+ default: false,
66
+ },
67
+ showWordLimit: {
68
+ type: Boolean,
69
+ default: false,
70
+ },
71
+ allValue: {
72
+ type: Boolean,
73
+ default: true,
74
+ },
75
+ refresh: Boolean,
76
+ },
77
+ data() {
78
+ return {
79
+ key: Strings.random(32),
80
+ };
81
+ },
82
+ computed: {
83
+ pickerValue() {
84
+ return this.matchValue(this.realData, this.value);
85
+ },
86
+ hasRefresh() {
87
+ return this.refresh && this.isRemote;
88
+ },
89
+ realProps() {
90
+ return Object.assign({
91
+ value: 'value',
92
+ label: 'label',
93
+ checkStrictly: true,
94
+ disabled: 'disabled',
95
+ }, this.props || {});
96
+ },
97
+ expandMap() {
98
+ return this.getExpandMap(this.realData);
99
+ },
100
+ },
101
+ watch: {
102
+ pickerValue() {
103
+ if (this.pickerValue.length) {
104
+ return;
105
+ }
106
+ this.initDefaultValue(this.realData);
107
+ },
108
+ realData(data, o) {
109
+ if (!Objects.isEquals(data, o)) {
110
+ this.key = Strings.random(32);
111
+ this.initDefaultValue(data);
112
+ }
113
+ },
114
+ },
115
+ methods: {
116
+ async init() {
117
+ if (this.startNull) {
118
+ this.done();
119
+ }
120
+ const data = await this.getData();
121
+ if (!this.startNull) {
122
+ this.initDefaultValue(data);
123
+ await this.$nextTick();
124
+ this.done();
125
+ }
126
+ },
127
+ initDefaultValue(data) {
128
+ if (this.value || !data.length || this.startNull) {
129
+ return;
130
+ }
131
+ const {value, disabled} = this.realProps;
132
+ const firstOption = this.getFirstOption(data, disabled)
133
+ if (!firstOption) {
134
+ return;
135
+ }
136
+ this.onChange([firstOption[value]]);
137
+ },
138
+ getFirstOption(data, disabledProp) {
139
+ if (!Array.isArray(data) || data.length <= 0) {
140
+ return null;
141
+ }
142
+ return data.reduce((result, item) => {
143
+ if (result) {
144
+ return result;
145
+ }
146
+ if (item[disabledProp] !== true) {
147
+ return item;
148
+ }
149
+ return this.getFirstOption(item.children, disabledProp);
150
+ }, null);
151
+ },
152
+ matchValue(data, value) {
153
+ if (!value) {
154
+ return [];
155
+ }
156
+ if (!this.allValue) {
157
+ const fullValues = this.expandMap[value] || [];
158
+ return [...fullValues].reverse();
159
+ }
160
+ return value.split(',');
161
+ },
162
+ /**
163
+ * 展开有层级关系的 list
164
+ */
165
+ getExpandList(data, valueKey, upValue) {
166
+ return data.reduce((prev, {children, ...item}) => {
167
+ prev.push({...item, $upValue: upValue});
168
+ if (Array.isArray(children) && children.length) {
169
+ prev.push(...this.getExpandList(children, valueKey, item[valueKey]));
170
+ }
171
+ return prev;
172
+ }, []);
173
+ },
174
+ /**
175
+ * 返回
176
+ * {
177
+ * child1: [father1,grandfather1,...],
178
+ * child2: [father2,grandfather2,...],
179
+ * ...
180
+ * }
181
+ */
182
+ getExpandMap(data) {
183
+ const {value: key} = this.realProps;
184
+ const expandList = this.getExpandList(data, key);
185
+ const listUpper = (list) => {
186
+ const last = list[list.length - 1];
187
+ const up = expandList.filter((d) => d[key] === last.$upValue);
188
+ if (!up.length) {
189
+ return list;
190
+ }
191
+ return listUpper([...list, ...up]);
192
+ };
193
+ return expandList.reduce((acc, item) => {
194
+ acc[item[key]] = listUpper([item]).map((d) => d[key]);
195
+ return acc;
196
+ }, {});
197
+ },
198
+ onChange(value) {
199
+ const lastVal = value.length ? value[value.length - 1] : '';
200
+ if (!lastVal) {
201
+ this.emitChange(undefined);
202
+ return;
203
+ }
204
+ if (!this.allValue) {
205
+ this.emitChange(lastVal);
206
+ return;
207
+ }
208
+ const _value = Array.from(this.expandMap[lastVal] || []).reverse().join(',');
209
+ this.emitChange(_value);
210
+ },
211
+ resetValue() {
212
+ this.onChange([]);
213
+ },
214
+ },
215
+ };
216
+ </script>
217
+ <style lang="less" scoped>
218
+ .ui-cascade-field {
219
+ width: 100%;
220
+ }
221
+
222
+ .ui-cascade-field-popper {
223
+ z-index: 99999 !important;
224
+ }
225
+
226
+ .ui-cascade-field-popper .el-cascader-menu__item {
227
+ padding-right: 30px;
228
+ }
229
+
230
+ ::v-deep .el-loading-mask .el-loading-spinner {
231
+ margin-top: -14px;
232
+ }
233
+ </style>
@@ -0,0 +1,134 @@
1
+ <template>
2
+ <div class="ui-field-checkbox" v-loading="realLoading" element-loading-spinner="el-icon-loading">
3
+ <el-checkbox-group v-show="all && realData.length" class="all" :value="checkAll">
4
+ <component :is="optionComponent" :indeterminate="indeterminate" @change="onCheckAllChange" :border="ui === 'border'">全选</component>
5
+ </el-checkbox-group>
6
+ <el-divider v-show="all && realData.length" direction="vertical"></el-divider>
7
+ <el-checkbox-group v-bind="$attrs" :value="pickerValue" @input="onChange" class="options">
8
+ <component
9
+ :is="optionComponent"
10
+ v-for="item in realData"
11
+ :key="item.value"
12
+ :label="item.value"
13
+ :border="ui === 'border'"
14
+ :checked="item.checked"
15
+ :disabled="item.disabled"
16
+ :true-label="item.trueLabel"
17
+ :false-label="item.falseLabel"
18
+ >
19
+ {{ item.label }}
20
+ </component>
21
+ </el-checkbox-group>
22
+ <div v-if="isEmpty" class="empty">暂无数据!&emsp;<el-button v-show="realError" type="text" @click="init">重新加载</el-button>
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script>
28
+ import FieldMixin from './field.mixin';
29
+ import DataMixin from './field.data.mixin';
30
+
31
+ export default {
32
+ name: 'ui-field-checkbox',
33
+ mixins: [FieldMixin, DataMixin],
34
+ props: {
35
+ ui: {
36
+ type: String,
37
+ validator: (val) => ['default', 'border', 'button'].includes(val),
38
+ },
39
+ all: {
40
+ type: Boolean,
41
+ default: true,
42
+ },
43
+ },
44
+ computed: {
45
+ pickerValue() {
46
+ return this.valueToArr(this.value);
47
+ },
48
+ optionComponent() {
49
+ if (this.ui === 'button') {
50
+ return 'el-checkbox-button';
51
+ }
52
+ return 'el-checkbox';
53
+ },
54
+ checkAll() {
55
+ const valueArr = this.value ? this.value.split(',') : [];
56
+ return !this.realData.some((item) => !valueArr.includes(String(item.value)));
57
+ },
58
+ indeterminate() {
59
+ if (this.checkAll) {
60
+ return false;
61
+ }
62
+ return !!this.pickerValue.length;
63
+ },
64
+ isEmpty() {
65
+ return !this.realData.length;
66
+ },
67
+ },
68
+ methods: {
69
+ init() {
70
+ this.getData().then(() => {
71
+ this.done();
72
+ });
73
+ },
74
+ valueToArr(value) {
75
+ return value ? value.split(',') : [];
76
+ },
77
+ onCheckAllChange(checkAll) {
78
+ if (checkAll) {
79
+ const vals = this.realData.map(({value}) => value);
80
+ this.onChange(vals);
81
+ } else {
82
+ this.onChange([]);
83
+ }
84
+ },
85
+ onChange(val) {
86
+ this.emitChange(val.join(','));
87
+ },
88
+ resetValue() {
89
+ this.onChange([]);
90
+ },
91
+ },
92
+ };
93
+ </script>
94
+
95
+ <style lang="less" scoped>
96
+ .ui-field-checkbox {
97
+ .all {
98
+ display: flex;
99
+
100
+ > .el-checkbox {
101
+ margin-right: 0;
102
+ }
103
+ }
104
+
105
+ .options {
106
+ display: flex;
107
+ flex-direction: row;
108
+ align-items: center;
109
+ }
110
+
111
+ .empty {
112
+ display: inline-flex;
113
+ align-items: center;
114
+ font-size: 12px;
115
+ color: #909399;
116
+ }
117
+
118
+ ::v-deep .el-checkbox {
119
+ margin: 0 8px 0 0;
120
+ }
121
+
122
+ ::v-deep .el-checkbox.is-bordered + .el-checkbox.is-bordered {
123
+ margin-left: 0;
124
+ }
125
+
126
+ ::v-deep .el-divider {
127
+ margin: 0 10px;
128
+ }
129
+ }
130
+
131
+ ::v-deep .el-loading-mask .el-loading-spinner {
132
+ margin-top: -14px;
133
+ }
134
+ </style>