xt-element-ui 1.2.2 → 1.2.4
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/lib/index.common.js +1322 -1281
- package/lib/index.css +1 -1
- package/lib/index.umd.js +1327 -1286
- package/lib/index.umd.min.js +5 -5
- package/package.json +1 -1
- package/src/components/ex-button/index.vue +1 -1
- package/src/components/ex-button/style/index.scss +10 -4
- package/src/components/ex-chart/ExPie.vue +1 -4
- package/src/components/ex-chart/theme/dark.js +15 -13
- package/src/components/ex-chart/utils.js +1 -1
- package/src/components/ex-page/index.js +2 -0
- package/src/components/ex-select-tree/index.js +2 -0
- package/src/components/{xt-select-tree → ex-select-tree}/index.vue +1 -1
- package/src/components/ex-table/ExTableCell.vue +3 -2
- package/src/components/ex-table/VirtualElTable.vue +234 -0
- package/src/components/ex-table/index.vue +176 -445
- package/src/components/ex-upload/index.js +2 -0
- package/src/components/xt-button/index.vue +2 -2
- package/src/components/xt-button/style/index.scss +524 -614
- package/src/components/xt-card-item/index copy.vue +93 -0
- package/src/components/xt-card-item/index.vue +23 -83
- package/src/components/xt-card-item/style/index copy.scss +72 -0
- package/src/components/xt-card-item/style/index.scss +51 -40
- package/src/components/xt-config-provider/index.js +2 -2
- package/src/components/xt-config-provider/index.vue +9 -5
- package/src/components/xt-text/index.vue +58 -29
- package/src/components/xt-text/style/index.scss +13 -13
- package/src/styles/css-variables.scss +1 -1
- package/src/styles/element-theme.scss +1 -1
- package/src/utils/index.js +11 -2
- package/src/components/xt-page/index.js +0 -0
- package/src/components/xt-select-tree/index.js +0 -0
- package/src/components/xt-upload/index.js +0 -2
- /package/src/components/{xt-page → ex-page}/index.vue +0 -0
- /package/src/components/{xt-upload → ex-upload}/index.vue +0 -0
- /package/src/components/{xt-upload → ex-upload}/preview.vue +0 -0
|
@@ -8,113 +8,16 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
|
-
<!--
|
|
12
|
-
<div
|
|
13
|
-
|
|
14
|
-
ref="fixedHeader"
|
|
15
|
-
class="ex-table-fixed-header"
|
|
16
|
-
>
|
|
17
|
-
<el-table
|
|
18
|
-
ref="headerTable"
|
|
19
|
-
:data="headerTableData"
|
|
20
|
-
class="ex-table ex-table-header-only"
|
|
21
|
-
>
|
|
22
|
-
<el-table-column v-if="selection" type="selection" width="55" :fixed="selectionFixed" />
|
|
23
|
-
<el-table-column
|
|
24
|
-
v-if="showIndex"
|
|
25
|
-
type="index"
|
|
26
|
-
width="60"
|
|
27
|
-
label="#"
|
|
28
|
-
:fixed="indexFixed"
|
|
29
|
-
/>
|
|
30
|
-
<template v-for="col in flattenedColumns">
|
|
31
|
-
<el-table-column
|
|
32
|
-
v-if="col.children && col.children.length"
|
|
33
|
-
:key="col._key"
|
|
34
|
-
v-bind="getColumnProps(col)"
|
|
35
|
-
>
|
|
36
|
-
<el-table-column
|
|
37
|
-
v-for="child in col.children"
|
|
38
|
-
:key="child._key || child.prop"
|
|
39
|
-
v-bind="getColumnProps(child)"
|
|
40
|
-
/>
|
|
41
|
-
</el-table-column>
|
|
42
|
-
<el-table-column v-else :key="col._key" v-bind="getColumnProps(col)" />
|
|
43
|
-
</template>
|
|
44
|
-
</el-table>
|
|
45
|
-
</div>
|
|
46
|
-
|
|
47
|
-
<!-- 表格主体 -->
|
|
48
|
-
<div
|
|
49
|
-
class="ex-table-body"
|
|
50
|
-
:class="{ 'ex-table-virtual': virtualScroll }"
|
|
51
|
-
:style="virtualScroll ? { height: computedHeight + 'px' } : {}"
|
|
52
|
-
ref="tableBody"
|
|
53
|
-
@scroll="handleBodyScroll"
|
|
54
|
-
>
|
|
55
|
-
<!-- 虚拟滚动:包裹层 + 占位撑开 -->
|
|
56
|
-
<div v-if="virtualScroll" class="ex-table-virtual-inner" :style="{ height: virtualTotalHeight + 'px' }">
|
|
57
|
-
<div :style="{ transform: 'translateY(' + virtualOffsetY + 'px)' }">
|
|
58
|
-
<el-table
|
|
59
|
-
ref="table"
|
|
60
|
-
:data="visibleData"
|
|
61
|
-
:span-method="groupColumns.length ? handleSpanMethod : undefined"
|
|
62
|
-
:row-class-name="getRowClassName"
|
|
63
|
-
:show-header="false"
|
|
64
|
-
v-bind="$attrs"
|
|
65
|
-
v-on="$listeners"
|
|
66
|
-
@selection-change="handleSelectionChange"
|
|
67
|
-
@sort-change="handleSortChange"
|
|
68
|
-
class="ex-table"
|
|
69
|
-
>
|
|
70
|
-
<el-table-column v-if="selection" type="selection" width="55" :fixed="selectionFixed" />
|
|
71
|
-
<el-table-column
|
|
72
|
-
v-if="showIndex"
|
|
73
|
-
type="index"
|
|
74
|
-
width="60"
|
|
75
|
-
label="#"
|
|
76
|
-
:fixed="indexFixed"
|
|
77
|
-
:index="indexMethod"
|
|
78
|
-
/>
|
|
79
|
-
<template v-for="col in flattenedColumns">
|
|
80
|
-
<el-table-column
|
|
81
|
-
v-if="col.children && col.children.length"
|
|
82
|
-
:key="col._key"
|
|
83
|
-
v-bind="getColumnProps(col)"
|
|
84
|
-
>
|
|
85
|
-
<template v-for="child in col.children">
|
|
86
|
-
<el-table-column :key="child._key" v-bind="getColumnProps(child)">
|
|
87
|
-
<template v-if="child.render" v-slot="scope">{{ child.render(scope) }}</template>
|
|
88
|
-
<template v-else-if="child.formatter" v-slot="scope">
|
|
89
|
-
<ExTableCell :row="scope.row" :index="scope.$index" :formatter="child.formatter" :column="child" />
|
|
90
|
-
</template>
|
|
91
|
-
<template v-else-if="child.slot" v-slot="scope">
|
|
92
|
-
<slot :name="child.slot" :row="scope.row" :index="scope.$index" :column="child" />
|
|
93
|
-
</template>
|
|
94
|
-
</el-table-column>
|
|
95
|
-
</template>
|
|
96
|
-
</el-table-column>
|
|
97
|
-
<el-table-column v-else :key="col._key" v-bind="getColumnProps(col)">
|
|
98
|
-
<template v-if="col.render" v-slot="scope">{{ col.render(scope) }}</template>
|
|
99
|
-
<template v-else-if="col.formatter" v-slot="scope">
|
|
100
|
-
<ExTableCell :row="scope.row" :index="scope.$index" :formatter="col.formatter" :column="col" />
|
|
101
|
-
</template>
|
|
102
|
-
<template v-else-if="col.slot" v-slot="scope">
|
|
103
|
-
<slot :name="col.slot" :row="scope.row" :index="scope.$index" :column="col" />
|
|
104
|
-
</template>
|
|
105
|
-
</el-table-column>
|
|
106
|
-
</template>
|
|
107
|
-
</el-table>
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
|
|
111
|
-
<!-- 非虚拟滚动:直接渲染 -->
|
|
112
|
-
<el-table
|
|
113
|
-
v-else
|
|
11
|
+
<!-- 主体表格:单 Table + 内置虚拟滚动(核心改造) -->
|
|
12
|
+
<div class="ex-table-body">
|
|
13
|
+
<VirtualElTable
|
|
114
14
|
ref="table"
|
|
115
|
-
:data="
|
|
15
|
+
:data="processedTableData"
|
|
116
16
|
:height="computedHeight"
|
|
117
17
|
:max-height="computedMaxHeight"
|
|
18
|
+
:virtual-scroll="virtualScroll"
|
|
19
|
+
:row-height="rowInitHeight"
|
|
20
|
+
:buffer-size="bufferSize"
|
|
118
21
|
:span-method="groupColumns.length ? handleSpanMethod : undefined"
|
|
119
22
|
:row-class-name="getRowClassName"
|
|
120
23
|
v-bind="$attrs"
|
|
@@ -123,7 +26,14 @@
|
|
|
123
26
|
@sort-change="handleSortChange"
|
|
124
27
|
class="ex-table"
|
|
125
28
|
>
|
|
126
|
-
|
|
29
|
+
<!-- 选择列 -->
|
|
30
|
+
<el-table-column
|
|
31
|
+
v-if="selection"
|
|
32
|
+
type="selection"
|
|
33
|
+
width="55"
|
|
34
|
+
:fixed="selectionFixed"
|
|
35
|
+
/>
|
|
36
|
+
<!-- 序号列 -->
|
|
127
37
|
<el-table-column
|
|
128
38
|
v-if="showIndex"
|
|
129
39
|
type="index"
|
|
@@ -132,6 +42,7 @@
|
|
|
132
42
|
:fixed="indexFixed"
|
|
133
43
|
:index="indexMethod"
|
|
134
44
|
/>
|
|
45
|
+
<!-- 多级列配置 -->
|
|
135
46
|
<template v-for="col in flattenedColumns">
|
|
136
47
|
<el-table-column
|
|
137
48
|
v-if="col.children && col.children.length"
|
|
@@ -142,10 +53,20 @@
|
|
|
142
53
|
<el-table-column :key="child._key" v-bind="getColumnProps(child)">
|
|
143
54
|
<template v-if="child.render" v-slot="scope">{{ child.render(scope) }}</template>
|
|
144
55
|
<template v-else-if="child.formatter" v-slot="scope">
|
|
145
|
-
<ExTableCell
|
|
56
|
+
<ExTableCell
|
|
57
|
+
:row="scope.row"
|
|
58
|
+
:index="scope.$index"
|
|
59
|
+
:formatter="child.formatter"
|
|
60
|
+
:column="child"
|
|
61
|
+
/>
|
|
146
62
|
</template>
|
|
147
63
|
<template v-else-if="child.slot" v-slot="scope">
|
|
148
|
-
<slot
|
|
64
|
+
<slot
|
|
65
|
+
:name="child.slot"
|
|
66
|
+
:row="scope.row"
|
|
67
|
+
:index="scope.$index"
|
|
68
|
+
:column="child"
|
|
69
|
+
/>
|
|
149
70
|
</template>
|
|
150
71
|
</el-table-column>
|
|
151
72
|
</template>
|
|
@@ -153,14 +74,24 @@
|
|
|
153
74
|
<el-table-column v-else :key="col._key" v-bind="getColumnProps(col)">
|
|
154
75
|
<template v-if="col.render" v-slot="scope">{{ col.render(scope) }}</template>
|
|
155
76
|
<template v-else-if="col.formatter" v-slot="scope">
|
|
156
|
-
<ExTableCell
|
|
77
|
+
<ExTableCell
|
|
78
|
+
:row="scope.row"
|
|
79
|
+
:index="scope.$index"
|
|
80
|
+
:formatter="col.formatter"
|
|
81
|
+
:column="col"
|
|
82
|
+
/>
|
|
157
83
|
</template>
|
|
158
84
|
<template v-else-if="col.slot" v-slot="scope">
|
|
159
|
-
<slot
|
|
85
|
+
<slot
|
|
86
|
+
:name="col.slot"
|
|
87
|
+
:row="scope.row"
|
|
88
|
+
:index="scope.$index"
|
|
89
|
+
:column="col"
|
|
90
|
+
/>
|
|
160
91
|
</template>
|
|
161
92
|
</el-table-column>
|
|
162
93
|
</template>
|
|
163
|
-
</
|
|
94
|
+
</VirtualElTable>
|
|
164
95
|
</div>
|
|
165
96
|
|
|
166
97
|
<!-- 分页 -->
|
|
@@ -180,68 +111,39 @@
|
|
|
180
111
|
|
|
181
112
|
<script>
|
|
182
113
|
import ExTableCell from './ExTableCell.vue'
|
|
183
|
-
|
|
184
|
-
import { Table as ElTable, TableColumn as ElTableColumn } from 'element-ui'
|
|
114
|
+
import VirtualElTable from './VirtualElTable.vue'
|
|
185
115
|
|
|
186
116
|
export default {
|
|
187
117
|
name: 'ExTable',
|
|
188
118
|
inheritAttrs: false,
|
|
189
|
-
components: { ExTableCell,
|
|
119
|
+
components: { ExTableCell, VirtualElTable },
|
|
120
|
+
|
|
190
121
|
props: {
|
|
191
|
-
// 表格数据
|
|
192
122
|
tableData: { type: Array, default: () => [] },
|
|
193
|
-
// 列配置(支持 children 多级表头)
|
|
194
123
|
columns: { type: Array, default: () => [] },
|
|
195
|
-
// 分组列配置(按配置的层级合并单元格)
|
|
196
124
|
groupColumns: { type: Array, default: () => [] },
|
|
197
|
-
// 标题
|
|
198
125
|
title: { type: String, default: '' },
|
|
199
|
-
// 高度
|
|
200
126
|
height: { type: [Number, String], default: null },
|
|
201
|
-
// 最大高度(非虚拟滚动时与 height 二选一,均支持固定表头)
|
|
202
127
|
maxHeight: { type: [Number, String], default: null },
|
|
203
|
-
// 虚拟滚动
|
|
204
128
|
virtualScroll: { type: Boolean, default: false },
|
|
205
|
-
// 预估行高
|
|
206
129
|
rowInitHeight: { type: Number, default: 48 },
|
|
207
|
-
// 缓冲区行数
|
|
208
130
|
bufferSize: { type: Number, default: 5 },
|
|
209
|
-
// 分页配置
|
|
210
131
|
pagination: { type: Object, default: null },
|
|
211
|
-
// 总条数
|
|
212
132
|
total: { type: Number, default: 0 },
|
|
213
|
-
// 是否显示序号
|
|
214
133
|
showIndex: { type: Boolean, default: false },
|
|
215
|
-
// 是否可选
|
|
216
134
|
selection: { type: Boolean, default: false },
|
|
217
|
-
// 选择列固定位置
|
|
218
135
|
selectionFixed: { type: [String, Boolean], default: false },
|
|
219
|
-
// 序号列固定位置
|
|
220
136
|
indexFixed: { type: [String, Boolean], default: false },
|
|
221
|
-
// 加载状态
|
|
222
137
|
loading: { type: Boolean, default: false },
|
|
223
|
-
// 空数据文案
|
|
224
138
|
emptyText: { type: String, default: '暂无数据' },
|
|
225
|
-
// 小计配置
|
|
226
139
|
subtotalConfig: { type: Object, default: () => ({ enabled: false }) },
|
|
227
|
-
// 总计配置
|
|
228
140
|
totalConfig: { type: Object, default: () => ({ enabled: false }) }
|
|
229
141
|
},
|
|
230
142
|
|
|
231
143
|
data() {
|
|
232
144
|
return {
|
|
233
|
-
// 虚拟滚动相关
|
|
234
|
-
scrollTop: 0,
|
|
235
|
-
scrollLeft: 0,
|
|
236
|
-
rowHeight: 48,
|
|
237
|
-
visibleStartIndex: 0,
|
|
238
|
-
visibleEndIndex: 0,
|
|
239
|
-
visibleCount: 0,
|
|
240
|
-
// 分组合并缓存
|
|
241
145
|
spanCache: {},
|
|
242
|
-
// 列扁平化缓存
|
|
243
146
|
flattenedColumnsCache: [],
|
|
244
|
-
// 选中数据
|
|
245
147
|
selectedRows: []
|
|
246
148
|
}
|
|
247
149
|
},
|
|
@@ -250,75 +152,44 @@ export default {
|
|
|
250
152
|
showPagination() {
|
|
251
153
|
return this.pagination && this.total > 0
|
|
252
154
|
},
|
|
253
|
-
|
|
254
155
|
computedHeight() {
|
|
255
|
-
if (this.virtualScroll) {
|
|
256
|
-
return this.height || this.maxHeight || 400
|
|
257
|
-
}
|
|
258
156
|
return this.height || undefined
|
|
259
157
|
},
|
|
260
|
-
|
|
261
158
|
computedMaxHeight() {
|
|
262
|
-
|
|
263
|
-
return this.maxHeight || undefined
|
|
159
|
+
return this.height ? undefined : this.maxHeight || undefined
|
|
264
160
|
},
|
|
265
161
|
|
|
266
|
-
//
|
|
267
|
-
headerTableData() {
|
|
268
|
-
return []
|
|
269
|
-
},
|
|
270
|
-
|
|
271
|
-
// 处理后的数据(注入小计/总计行)
|
|
162
|
+
// 处理小计、总计后的最终数据
|
|
272
163
|
processedTableData() {
|
|
273
164
|
if (!this.tableData.length) return []
|
|
274
|
-
|
|
275
165
|
let data = [...this.tableData]
|
|
276
166
|
const hasSubtotal = this.subtotalConfig && this.subtotalConfig.enabled
|
|
277
167
|
const hasTotal = this.totalConfig && this.totalConfig.enabled
|
|
278
168
|
|
|
279
169
|
if (!hasSubtotal && !hasTotal) return data
|
|
280
170
|
|
|
281
|
-
// 找到第一个数据列作为标签列
|
|
282
171
|
const labelColumn = this.findLabelColumn()
|
|
283
|
-
|
|
284
172
|
let result = []
|
|
285
173
|
|
|
286
174
|
if (hasSubtotal && this.subtotalConfig.groupBy && this.subtotalConfig.groupBy.length) {
|
|
287
|
-
// 按 groupBy 分组
|
|
288
175
|
const groups = this.groupData(data, this.subtotalConfig.groupBy)
|
|
289
|
-
groups.forEach((groupRows
|
|
290
|
-
// 插入数据行
|
|
176
|
+
groups.forEach((groupRows) => {
|
|
291
177
|
result.push(...groupRows)
|
|
292
|
-
|
|
293
|
-
const subtotalRow = this.createSubtotalRow(groupRows, groupKey)
|
|
178
|
+
const subtotalRow = this.createSubtotalRow(groupRows)
|
|
294
179
|
result.push(subtotalRow)
|
|
295
180
|
})
|
|
296
181
|
} else {
|
|
297
182
|
result = data
|
|
298
183
|
}
|
|
299
184
|
|
|
300
|
-
// 插入总计行
|
|
301
185
|
if (hasTotal) {
|
|
302
186
|
const totalRow = this.createTotalRow(data)
|
|
303
187
|
result.push(totalRow)
|
|
304
188
|
}
|
|
305
|
-
|
|
306
189
|
return result
|
|
307
190
|
},
|
|
308
191
|
|
|
309
|
-
//
|
|
310
|
-
virtualTotalHeight() {
|
|
311
|
-
const data = this.processedTableData
|
|
312
|
-
return data.length * this.rowHeight
|
|
313
|
-
},
|
|
314
|
-
|
|
315
|
-
// 虚拟滚动偏移量
|
|
316
|
-
virtualOffsetY() {
|
|
317
|
-
const start = Math.max(0, this.visibleStartIndex - this.bufferSize)
|
|
318
|
-
return start * this.rowHeight
|
|
319
|
-
},
|
|
320
|
-
|
|
321
|
-
// 扁平化列配置(为每级列补充 _key)
|
|
192
|
+
// 扁平化列配置,添加唯一 key
|
|
322
193
|
flattenedColumns() {
|
|
323
194
|
if (this.flattenedColumnsCache.length) return this.flattenedColumnsCache
|
|
324
195
|
const assignKeys = (cols, parentPath = '') => {
|
|
@@ -334,91 +205,47 @@ export default {
|
|
|
334
205
|
}
|
|
335
206
|
this.flattenedColumnsCache = assignKeys(this.columns)
|
|
336
207
|
return this.flattenedColumnsCache
|
|
337
|
-
},
|
|
338
|
-
|
|
339
|
-
// 虚拟滚动时的可见数据(附带 _realIndex 供序号列使用)
|
|
340
|
-
visibleData() {
|
|
341
|
-
const data = this.processedTableData
|
|
342
|
-
if (!this.virtualScroll || data.length === 0) {
|
|
343
|
-
return data
|
|
344
|
-
}
|
|
345
|
-
const start = Math.max(0, this.visibleStartIndex - this.bufferSize)
|
|
346
|
-
const end = Math.min(data.length, this.visibleEndIndex + this.bufferSize)
|
|
347
|
-
return data.slice(start, end).map((row, i) => ({
|
|
348
|
-
...row,
|
|
349
|
-
_realIndex: start + i
|
|
350
|
-
}))
|
|
351
208
|
}
|
|
352
209
|
},
|
|
353
210
|
|
|
354
211
|
watch: {
|
|
355
|
-
tableData
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
this.flattenedColumnsCache = []
|
|
359
|
-
if (this.virtualScroll) {
|
|
360
|
-
this.$nextTick(() => {
|
|
361
|
-
this.measureRowHeight()
|
|
362
|
-
this.updateVisibleRange()
|
|
363
|
-
this.syncTableLayout()
|
|
364
|
-
})
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
immediate: false
|
|
212
|
+
tableData() {
|
|
213
|
+
this.spanCache = {}
|
|
214
|
+
this.flattenedColumnsCache = []
|
|
368
215
|
},
|
|
369
|
-
|
|
370
216
|
columns: {
|
|
371
217
|
handler() {
|
|
372
218
|
this.flattenedColumnsCache = []
|
|
373
|
-
|
|
374
|
-
this.$nextTick(() => this.syncTableLayout())
|
|
375
|
-
}
|
|
219
|
+
this.spanCache = {}
|
|
376
220
|
},
|
|
377
221
|
deep: true
|
|
378
222
|
},
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
},
|
|
385
|
-
|
|
386
|
-
maxHeight() {
|
|
387
|
-
if (this.virtualScroll) {
|
|
388
|
-
this.$nextTick(() => this.syncTableLayout())
|
|
389
|
-
}
|
|
390
|
-
},
|
|
391
|
-
|
|
392
|
-
virtualScroll(val) {
|
|
393
|
-
if (val) {
|
|
394
|
-
this.$nextTick(() => this.initVirtualScroll())
|
|
395
|
-
} else {
|
|
396
|
-
this.destroyVirtualScroll()
|
|
397
|
-
}
|
|
223
|
+
groupColumns: {
|
|
224
|
+
handler() {
|
|
225
|
+
this.spanCache = {}
|
|
226
|
+
},
|
|
227
|
+
deep: true
|
|
398
228
|
}
|
|
399
229
|
},
|
|
400
230
|
|
|
401
231
|
mounted() {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
// 监听窗口resize,更新表格宽度
|
|
406
|
-
this.resizeHandler = () => {
|
|
407
|
-
if (this.virtualScroll) {
|
|
408
|
-
this.$nextTick(() => this.syncTableLayout())
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
window.addEventListener('resize', this.resizeHandler)
|
|
232
|
+
this.$nextTick(() => {
|
|
233
|
+
window.addEventListener('resize', this.handleResize)
|
|
234
|
+
})
|
|
412
235
|
},
|
|
413
236
|
|
|
414
237
|
beforeDestroy() {
|
|
415
|
-
this.
|
|
416
|
-
window.removeEventListener('resize', this.resizeHandler)
|
|
238
|
+
window.removeEventListener('resize', this.handleResize)
|
|
417
239
|
},
|
|
418
240
|
|
|
419
241
|
methods: {
|
|
420
|
-
|
|
421
|
-
|
|
242
|
+
handleResize() {
|
|
243
|
+
this.$nextTick(() => {
|
|
244
|
+
this.$refs.table && this.$refs.table.doLayout()
|
|
245
|
+
})
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
// ========== 小计 / 总计 相关 ==========
|
|
422
249
|
findLabelColumn() {
|
|
423
250
|
for (const col of this.columns) {
|
|
424
251
|
if (col.children && col.children.length) {
|
|
@@ -432,33 +259,25 @@ export default {
|
|
|
432
259
|
return { prop: '', label: '' }
|
|
433
260
|
},
|
|
434
261
|
|
|
435
|
-
// 按指定字段分组(保持分组顺序)
|
|
436
262
|
groupData(data, groupBy) {
|
|
437
263
|
const map = new Map()
|
|
438
264
|
data.forEach(row => {
|
|
439
265
|
const key = groupBy.map(f => row[f]).join('|||')
|
|
440
|
-
if (!map.has(key))
|
|
441
|
-
map.set(key, [])
|
|
442
|
-
}
|
|
266
|
+
if (!map.has(key)) map.set(key, [])
|
|
443
267
|
map.get(key).push(row)
|
|
444
268
|
})
|
|
445
269
|
return map
|
|
446
270
|
},
|
|
447
271
|
|
|
448
|
-
// 计算单列的聚合值
|
|
449
272
|
_calcValue(rows, calc) {
|
|
450
|
-
// 自定义函数
|
|
451
273
|
if (typeof calc === 'function') return calc(rows)
|
|
452
|
-
|
|
453
|
-
// 字符串:'sum' | 'avg' | 'count' | 'min' | 'max'(需配合 prop 使用)
|
|
454
|
-
|
|
455
|
-
// 对象:{ prop: 'field', type: 'sum' } 或 { prop: 'field' } (默认 sum)
|
|
456
274
|
const prop = calc.prop
|
|
457
275
|
const type = calc.type || 'sum'
|
|
458
276
|
const vals = prop ? rows.map(r => parseFloat(r[prop]) || 0) : []
|
|
459
277
|
switch (type) {
|
|
460
278
|
case 'sum': return vals.reduce((s, v) => s + v, 0)
|
|
461
|
-
case 'avg':
|
|
279
|
+
case 'avg':
|
|
280
|
+
case 'average': return vals.length ? vals.reduce((s, v) => s + v, 0) / vals.length : 0
|
|
462
281
|
case 'count': return rows.length
|
|
463
282
|
case 'min': return vals.length ? Math.min(...vals) : 0
|
|
464
283
|
case 'max': return vals.length ? Math.max(...vals) : 0
|
|
@@ -466,20 +285,16 @@ export default {
|
|
|
466
285
|
}
|
|
467
286
|
},
|
|
468
287
|
|
|
469
|
-
|
|
470
|
-
createSubtotalRow(groupRows, groupKey) {
|
|
288
|
+
createSubtotalRow(groupRows) {
|
|
471
289
|
const config = this.subtotalConfig
|
|
472
290
|
const rawLabelProp = this.findLabelColumn()
|
|
473
|
-
|
|
474
|
-
// 获取第一个 groupBy 列的值显示
|
|
475
291
|
const labelField = config.groupBy ? config.groupBy[0] : ''
|
|
476
|
-
const groupValue = groupRows[0] ? groupRows[0][labelField] :
|
|
292
|
+
const groupValue = groupRows[0] ? groupRows[0][labelField] : ''
|
|
477
293
|
const labelText = config.labelText || `${groupValue} 小计`
|
|
478
294
|
|
|
479
|
-
const row = { _rowType: 'subtotal'
|
|
295
|
+
const row = { _rowType: 'subtotal' }
|
|
480
296
|
row[rawLabelProp.prop] = labelText
|
|
481
297
|
|
|
482
|
-
// 计算各列的聚合值
|
|
483
298
|
if (config.columns) {
|
|
484
299
|
Object.keys(config.columns).forEach(prop => {
|
|
485
300
|
const calc = config.columns[prop]
|
|
@@ -488,11 +303,9 @@ export default {
|
|
|
488
303
|
: this._calcValue(groupRows, calc)
|
|
489
304
|
})
|
|
490
305
|
}
|
|
491
|
-
|
|
492
306
|
return row
|
|
493
307
|
},
|
|
494
308
|
|
|
495
|
-
// 创建总计行
|
|
496
309
|
createTotalRow(allRows) {
|
|
497
310
|
const config = this.totalConfig
|
|
498
311
|
const rawLabelProp = this.findLabelColumn()
|
|
@@ -501,7 +314,6 @@ export default {
|
|
|
501
314
|
const row = { _rowType: 'total' }
|
|
502
315
|
row[rawLabelProp.prop] = labelText
|
|
503
316
|
|
|
504
|
-
// 计算各列的聚合值
|
|
505
317
|
if (config.columns) {
|
|
506
318
|
Object.keys(config.columns).forEach(prop => {
|
|
507
319
|
const calc = config.columns[prop]
|
|
@@ -510,55 +322,40 @@ export default {
|
|
|
510
322
|
: this._calcValue(allRows, calc)
|
|
511
323
|
})
|
|
512
324
|
}
|
|
513
|
-
|
|
514
325
|
return row
|
|
515
326
|
},
|
|
516
327
|
|
|
517
|
-
// 行类名(小计/总计行样式)
|
|
518
328
|
getRowClassName({ row }) {
|
|
519
|
-
if (!row) return ''
|
|
520
329
|
if (row._rowType === 'subtotal') return 'ex-table-row-subtotal'
|
|
521
330
|
if (row._rowType === 'total') return 'ex-table-row-total'
|
|
522
331
|
return ''
|
|
523
332
|
},
|
|
524
333
|
|
|
525
|
-
//
|
|
334
|
+
// ========== 列处理 ==========
|
|
526
335
|
getColumnProps(col) {
|
|
527
336
|
const { _key, children, render, formatter, slot, ...props } = col
|
|
528
337
|
return props
|
|
529
338
|
},
|
|
530
339
|
|
|
531
|
-
// ==================== 序号方法 ====================
|
|
532
340
|
indexMethod(index) {
|
|
533
|
-
if (this.virtualScroll && this.visibleData.length > 0) {
|
|
534
|
-
const row = this.visibleData[index]
|
|
535
|
-
if (row && row._realIndex !== undefined) {
|
|
536
|
-
return row._realIndex + 1
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
341
|
return index + 1
|
|
540
342
|
},
|
|
541
343
|
|
|
542
|
-
//
|
|
344
|
+
// ========== 合并单元格 ==========
|
|
543
345
|
handleSpanMethod({ row, column, rowIndex }) {
|
|
544
|
-
// 跳过小计/总计行,不做合并
|
|
545
346
|
if (row._rowType === 'subtotal' || row._rowType === 'total') {
|
|
546
347
|
return { rowspan: 1, colspan: 1 }
|
|
547
348
|
}
|
|
548
|
-
|
|
549
349
|
if (!this.groupColumns.length) return { rowspan: 1, colspan: 1 }
|
|
550
350
|
|
|
551
|
-
const data = this.
|
|
351
|
+
const data = this.processedTableData
|
|
552
352
|
const prop = column.property
|
|
553
353
|
const groupIndex = this.groupColumns.indexOf(prop)
|
|
554
|
-
|
|
555
354
|
if (groupIndex === -1) return { rowspan: 1, colspan: 1 }
|
|
556
355
|
|
|
557
|
-
// 检查缓存
|
|
558
356
|
const cacheKey = `${rowIndex}_${prop}`
|
|
559
357
|
if (this.spanCache[cacheKey]) return this.spanCache[cacheKey]
|
|
560
358
|
|
|
561
|
-
// 判断当前行是否与前一行在分组列上完全相同
|
|
562
359
|
if (rowIndex > 0) {
|
|
563
360
|
const prevRow = data[rowIndex - 1]
|
|
564
361
|
let isSame = true
|
|
@@ -570,185 +367,76 @@ export default {
|
|
|
570
367
|
}
|
|
571
368
|
}
|
|
572
369
|
if (isSame) {
|
|
573
|
-
const
|
|
574
|
-
this.spanCache[cacheKey] =
|
|
575
|
-
return
|
|
370
|
+
const res = { rowspan: 0, colspan: 1 }
|
|
371
|
+
this.spanCache[cacheKey] = res
|
|
372
|
+
return res
|
|
576
373
|
}
|
|
577
374
|
}
|
|
578
375
|
|
|
579
|
-
// 向下扫描计算合并行数
|
|
580
376
|
let count = 1
|
|
581
377
|
for (let i = rowIndex + 1; i < data.length; i++) {
|
|
582
378
|
const nextRow = data[i]
|
|
583
|
-
let
|
|
379
|
+
let same = true
|
|
584
380
|
for (let j = 0; j <= groupIndex; j++) {
|
|
585
381
|
const gp = this.groupColumns[j]
|
|
586
382
|
if (nextRow[gp] !== row[gp]) {
|
|
587
|
-
|
|
383
|
+
same = false
|
|
588
384
|
break
|
|
589
385
|
}
|
|
590
386
|
}
|
|
591
|
-
if (
|
|
592
|
-
|
|
593
|
-
} else {
|
|
594
|
-
break
|
|
595
|
-
}
|
|
387
|
+
if (same) count++
|
|
388
|
+
else break
|
|
596
389
|
}
|
|
597
390
|
|
|
598
|
-
const
|
|
599
|
-
this.spanCache[cacheKey] =
|
|
600
|
-
return
|
|
391
|
+
const res = { rowspan: count > 1 ? count : 1, colspan: 1 }
|
|
392
|
+
this.spanCache[cacheKey] = res
|
|
393
|
+
return res
|
|
601
394
|
},
|
|
602
395
|
|
|
603
|
-
//
|
|
396
|
+
// ========== 选择、排序、分页 ==========
|
|
604
397
|
handleSelectionChange(rows) {
|
|
605
|
-
// 过滤掉小计/总计行
|
|
606
398
|
this.selectedRows = rows.filter(r => !r._rowType)
|
|
607
399
|
this.$emit('selection-change', this.selectedRows)
|
|
608
400
|
},
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
handleSortChange({ prop, order }) {
|
|
612
|
-
this.$emit('sort-change', { prop, order })
|
|
401
|
+
handleSortChange(info) {
|
|
402
|
+
this.$emit('sort-change', info)
|
|
613
403
|
},
|
|
614
|
-
|
|
615
|
-
// ==================== 分页 ====================
|
|
616
404
|
handleSizeChange(size) {
|
|
617
405
|
this.$emit('size-change', size)
|
|
618
406
|
},
|
|
619
|
-
|
|
620
407
|
handleCurrentChange(page) {
|
|
621
408
|
this.$emit('page-change', page)
|
|
622
409
|
},
|
|
623
410
|
|
|
624
|
-
//
|
|
411
|
+
// ========== 对外暴露方法 ==========
|
|
625
412
|
getSelection() {
|
|
626
413
|
return this.selectedRows
|
|
627
414
|
},
|
|
628
|
-
|
|
629
415
|
clearSelection() {
|
|
630
416
|
this.$refs.table && this.$refs.table.clearSelection()
|
|
631
417
|
this.selectedRows = []
|
|
632
418
|
},
|
|
633
|
-
|
|
634
419
|
toggleRowSelection(row, selected) {
|
|
635
420
|
this.$refs.table && this.$refs.table.toggleRowSelection(row, selected)
|
|
636
421
|
},
|
|
637
|
-
|
|
638
422
|
toggleRowsSelection(rows, selected) {
|
|
639
|
-
if (rows
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
423
|
+
if (!rows || !rows.length) return
|
|
424
|
+
rows.forEach(row => {
|
|
425
|
+
this.$refs.table && this.$refs.table.toggleRowSelection(row, selected)
|
|
426
|
+
})
|
|
644
427
|
},
|
|
645
|
-
|
|
646
428
|
doLayout() {
|
|
647
|
-
this.
|
|
648
|
-
},
|
|
649
|
-
|
|
650
|
-
// ==================== 虚拟滚动固定表头 ====================
|
|
651
|
-
syncTableLayout() {
|
|
652
|
-
const bodyTable = this.$refs.table
|
|
653
|
-
const headerTable = this.$refs.headerTable
|
|
654
|
-
if (bodyTable) bodyTable.doLayout()
|
|
655
|
-
if (headerTable) headerTable.doLayout()
|
|
656
|
-
this.syncHeaderScroll(this.scrollLeft)
|
|
657
|
-
},
|
|
658
|
-
|
|
659
|
-
syncHeaderScroll(scrollLeft) {
|
|
660
|
-
const headerTable = this.$refs.headerTable
|
|
661
|
-
if (!headerTable) return
|
|
662
|
-
const headerWrapper = headerTable.$el.querySelector('.el-table__header-wrapper')
|
|
663
|
-
if (headerWrapper) {
|
|
664
|
-
headerWrapper.scrollLeft = scrollLeft
|
|
665
|
-
}
|
|
666
|
-
},
|
|
667
|
-
|
|
668
|
-
// ==================== 虚拟滚动 ====================
|
|
669
|
-
initVirtualScroll() {
|
|
670
|
-
this.rowHeight = this.rowInitHeight
|
|
671
|
-
this.measureRowHeight()
|
|
672
|
-
if (this.processedTableData.length > 0) {
|
|
673
|
-
this.updateVisibleRange()
|
|
674
|
-
}
|
|
675
|
-
this.syncTableLayout()
|
|
676
|
-
},
|
|
677
|
-
|
|
678
|
-
measureRowHeight() {
|
|
679
|
-
const el = this.$refs.table && this.$refs.table.$el
|
|
680
|
-
if (!el) return
|
|
681
|
-
const row = el.querySelector('.el-table__row')
|
|
682
|
-
if (row) {
|
|
683
|
-
this.rowHeight = row.offsetHeight || this.rowInitHeight
|
|
684
|
-
}
|
|
685
|
-
},
|
|
686
|
-
|
|
687
|
-
handleBodyScroll(event) {
|
|
688
|
-
const target = event.target
|
|
689
|
-
this.scrollLeft = target.scrollLeft
|
|
690
|
-
if (this.virtualScroll) {
|
|
691
|
-
this.scrollTop = target.scrollTop
|
|
692
|
-
this.updateVisibleRange()
|
|
693
|
-
this.syncHeaderScroll(target.scrollLeft)
|
|
694
|
-
}
|
|
695
|
-
},
|
|
696
|
-
|
|
697
|
-
updateVisibleRange() {
|
|
698
|
-
const totalCount = this.processedTableData.length
|
|
699
|
-
if (totalCount === 0 || this.rowHeight === 0) return
|
|
700
|
-
|
|
701
|
-
const visibleCount = Math.ceil((this.computedHeight || 400) / this.rowHeight)
|
|
702
|
-
|
|
703
|
-
this.visibleStartIndex = Math.max(0, Math.floor(this.scrollTop / this.rowHeight))
|
|
704
|
-
this.visibleEndIndex = Math.min(
|
|
705
|
-
totalCount,
|
|
706
|
-
this.visibleStartIndex + visibleCount
|
|
707
|
-
)
|
|
708
|
-
this.visibleCount = visibleCount
|
|
709
|
-
},
|
|
710
|
-
|
|
711
|
-
destroyVirtualScroll() {
|
|
712
|
-
this.scrollTop = 0
|
|
713
|
-
this.visibleStartIndex = 0
|
|
714
|
-
this.visibleEndIndex = 0
|
|
429
|
+
this.$refs.table && this.$refs.table.doLayout()
|
|
715
430
|
}
|
|
716
431
|
}
|
|
717
432
|
}
|
|
718
433
|
</script>
|
|
719
|
-
|
|
720
434
|
<style scoped>
|
|
721
435
|
.ex-table-wrapper {
|
|
722
436
|
width: 100%;
|
|
723
437
|
}
|
|
724
438
|
|
|
725
|
-
/*
|
|
726
|
-
.ex-table-wrapper >>> .ex-table-row-subtotal,
|
|
727
|
-
.ex-table >>> .ex-table-row-subtotal {
|
|
728
|
-
background-color: #f5f7fa;
|
|
729
|
-
font-weight: 600;
|
|
730
|
-
color: #303133;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
/* 总计行样式 */
|
|
734
|
-
.ex-table-wrapper >>> .ex-table-row-total,
|
|
735
|
-
.ex-table >>> .ex-table-row-total {
|
|
736
|
-
background-color: #e8eaed;
|
|
737
|
-
font-weight: 700;
|
|
738
|
-
color: #303133;
|
|
739
|
-
border-top: 2px solid #c0c4cc;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
.ex-table-wrapper >>> .ex-table-row-subtotal:hover > td,
|
|
743
|
-
.ex-table >>> .ex-table-row-subtotal:hover > td {
|
|
744
|
-
background-color: #ebeef5 !important;
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
.ex-table-wrapper >>> .ex-table-row-total:hover > td,
|
|
748
|
-
.ex-table >>> .ex-table-row-total:hover > td {
|
|
749
|
-
background-color: #dcdfe6 !important;
|
|
750
|
-
}
|
|
751
|
-
|
|
439
|
+
/* 表头栏 */
|
|
752
440
|
.ex-table-header {
|
|
753
441
|
display: flex;
|
|
754
442
|
align-items: center;
|
|
@@ -756,7 +444,6 @@ export default {
|
|
|
756
444
|
padding: 12px 0;
|
|
757
445
|
margin-bottom: 8px;
|
|
758
446
|
}
|
|
759
|
-
|
|
760
447
|
.ex-table-title {
|
|
761
448
|
font-size: 16px;
|
|
762
449
|
font-weight: 600;
|
|
@@ -764,7 +451,6 @@ export default {
|
|
|
764
451
|
position: relative;
|
|
765
452
|
padding-left: 12px;
|
|
766
453
|
}
|
|
767
|
-
|
|
768
454
|
.ex-table-title::before {
|
|
769
455
|
content: '';
|
|
770
456
|
position: absolute;
|
|
@@ -776,7 +462,6 @@ export default {
|
|
|
776
462
|
background: #409eff;
|
|
777
463
|
border-radius: 2px;
|
|
778
464
|
}
|
|
779
|
-
|
|
780
465
|
.ex-table-toolbar {
|
|
781
466
|
display: flex;
|
|
782
467
|
align-items: center;
|
|
@@ -785,52 +470,98 @@ export default {
|
|
|
785
470
|
|
|
786
471
|
.ex-table-body {
|
|
787
472
|
position: relative;
|
|
473
|
+
z-index: 1;
|
|
788
474
|
}
|
|
789
475
|
|
|
790
|
-
/*
|
|
791
|
-
.ex-table-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
scrollbar-width: none;
|
|
796
|
-
/* IE/旧 Edge 隐藏滚动条 */
|
|
797
|
-
-ms-overflow-style: none;
|
|
476
|
+
/* 分页区域 */
|
|
477
|
+
.ex-table-footer {
|
|
478
|
+
display: flex;
|
|
479
|
+
justify-content: flex-end;
|
|
480
|
+
padding: 16px 0;
|
|
798
481
|
}
|
|
799
482
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
483
|
+
/* ========== 小计/合计行样式 ========== */
|
|
484
|
+
::v-deep .ex-table-row-subtotal {
|
|
485
|
+
background-color: #f5f7fa;
|
|
486
|
+
font-weight: 600;
|
|
487
|
+
color: #303133;
|
|
803
488
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
489
|
+
::v-deep .ex-table-row-total {
|
|
490
|
+
background-color: #e8eaed;
|
|
491
|
+
font-weight: 700;
|
|
492
|
+
color: #303133;
|
|
493
|
+
border-top: 2px solid #c0c4cc;
|
|
494
|
+
}
|
|
495
|
+
::v-deep .ex-table-row-subtotal:hover > td {
|
|
496
|
+
background-color: #ebeef5 !important;
|
|
497
|
+
}
|
|
498
|
+
::v-deep .ex-table-row-total:hover > td {
|
|
499
|
+
background-color: #dcdfe6 !important;
|
|
807
500
|
}
|
|
808
501
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
502
|
+
/* ========== 滚动条:Y轴 + X轴 统一处理 ========== */
|
|
503
|
+
/* 合并为一个选择器块,避免重复导致的优先级问题 */
|
|
504
|
+
::v-deep .el-table__body-wrapper {
|
|
505
|
+
overflow-y: auto !important;
|
|
506
|
+
overflow-x: auto !important;
|
|
507
|
+
user-select: none;
|
|
508
|
+
-webkit-user-select: none;
|
|
509
|
+
}
|
|
510
|
+
::v-deep .el-table__body-wrapper::-webkit-scrollbar {
|
|
511
|
+
width: 8px;
|
|
512
|
+
height: 8px;
|
|
513
|
+
}
|
|
514
|
+
::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb {
|
|
515
|
+
background: #c1c1c1;
|
|
516
|
+
border-radius: 4px;
|
|
517
|
+
}
|
|
518
|
+
::v-deep .el-table__body-wrapper::-webkit-scrollbar-track {
|
|
519
|
+
background: #f1f1f1;
|
|
520
|
+
}
|
|
521
|
+
/* 滚动条角落(Y+X 交汇处) */
|
|
522
|
+
::v-deep .el-table__body-wrapper::-webkit-scrollbar-corner {
|
|
523
|
+
background: #f1f1f1;
|
|
813
524
|
}
|
|
814
525
|
|
|
815
|
-
/*
|
|
816
|
-
.
|
|
817
|
-
|
|
818
|
-
|
|
526
|
+
/* 允许单元格内文字选中,但容器本身不可选中 */
|
|
527
|
+
::v-deep .el-table__body-wrapper .el-table__cell {
|
|
528
|
+
user-select: text;
|
|
529
|
+
-webkit-user-select: text;
|
|
819
530
|
}
|
|
820
531
|
|
|
821
|
-
/*
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
532
|
+
/* ========== 固定列层级 + 背景 防文字穿透 ========== */
|
|
533
|
+
::v-deep .el-table__fixed {
|
|
534
|
+
z-index: 10 !important;
|
|
535
|
+
box-shadow: 4px 0 8px rgba(0, 0, 0, 0.08);
|
|
536
|
+
}
|
|
537
|
+
::v-deep .el-table__fixed-right {
|
|
538
|
+
z-index: 10 !important;
|
|
539
|
+
box-shadow: -4px 0 8px rgba(0, 0, 0, 0.08);
|
|
825
540
|
}
|
|
826
541
|
|
|
542
|
+
/* 固定列单元格底色(纯白兜底,盖住滚动穿透文字) */
|
|
543
|
+
::v-deep .el-table__fixed .el-table__cell,
|
|
544
|
+
::v-deep .el-table__fixed-right .el-table__cell {
|
|
545
|
+
background-color: #ffffff !important;
|
|
546
|
+
}
|
|
547
|
+
::v-deep .el-table__fixed .el-table__row:nth-child(even) .el-table__cell,
|
|
548
|
+
::v-deep .el-table__fixed-right .el-table__row:nth-child(even) .el-table__cell {
|
|
549
|
+
background-color: #fafafa !important;
|
|
550
|
+
}
|
|
551
|
+
::v-deep .el-table__fixed .el-table__row:hover .el-table__cell,
|
|
552
|
+
::v-deep .el-table__fixed-right .el-table__row:hover .el-table__cell {
|
|
553
|
+
background-color: #f5f7fa !important;
|
|
554
|
+
}
|
|
827
555
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
556
|
+
::v-deep .el-table__fixed-header-wrapper,
|
|
557
|
+
::v-deep .el-table__fixed-right-header-wrapper {
|
|
558
|
+
z-index: 11 !important;
|
|
831
559
|
}
|
|
832
560
|
|
|
833
|
-
|
|
834
|
-
|
|
561
|
+
/* ========== 虚拟滚动容器:正常布局流撑开滚动条 ========== */
|
|
562
|
+
::v-deep .vs-phantom {
|
|
563
|
+
position: relative;
|
|
564
|
+
box-sizing: border-box;
|
|
565
|
+
z-index: 1 !important;
|
|
835
566
|
}
|
|
836
|
-
</style>
|
|
567
|
+
</style>
|