el-plus-crud 0.0.35 → 0.0.39

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.
@@ -1,767 +1,773 @@
1
- <template>
2
- <div class="el-plus-table-content">
3
- <!-- <div class="select-items" v-if="type === 'selection' && selectRowList && selectRowList.length > 0">
4
- <span class="title">已选择({{ selectRowList.length }}个): </span>
5
- <el-tag v-for="(item, i) in selectRowList" :key="item.id" class="select-item" size="small" closable @close="() => handelRemoveSelect(i, item)">
6
- {{ item[tableConfig.showSelectNameKey || 'name'] }}
7
- </el-tag>
8
- </div> -->
9
- <EleTabletHeader ref="tableHeaderRef" v-if="Object.keys(tableConfig?.toolbar || {}).length || tableConfig.tbName" v-model="toolFormData" :tbName="tableConfig.tbName" :column="tableConfig.column" :size="size" :isShowRefresh="isShowRefresh" :loading="loading" :toolbar="tableConfig.toolbar" :isDialog="isDialog" @query="handelTopQuery" />
10
-
11
- <!-- 中部的Tabs -->
12
- <div class="table-tabs-panel" v-if="tableConfig.tabConf">
13
- <el-radio-group v-model="tableTabVal" size="default" @change="handelTabChange">
14
- <el-radio-button v-for="(item, i) in tableConfig.tabConf?.tabs" :key="i" :label="item.value" :loading="true">
15
- {{ item.label }}
16
- <template v-if="loadingTab">
17
- <el-icon class="is-loading"><Loading /></el-icon>
18
- </template>
19
- <template v-else>
20
- {{ getTabLabel(item) }}
21
- </template>
22
- </el-radio-button>
23
- </el-radio-group>
24
- </div>
25
-
26
- <!-- 中间列表 -->
27
- <div class="el-plus-table-main" v-loading="loading">
28
- <template v-if="isDIYMain">
29
- <slot name="main" :tableData="tableData"></slot>
30
- </template>
31
- <!-- 这里开始是表格内容 -->
32
- <el-table ref="elPlusTableRef" v-else style="width: 100%" height="100%" :maxHeight="tableConfig.maxHeight || 'auto'" v-bind="tableConfig.tableAttr" :data="tableData" :row-key="rowKey" lazy :load="loadExpandData" :size="size" :row-class-name="initRowClassName" @select="handelTableSelect" @select-all="handelTableSelectAll" @expand-change="handelTableExpandChange" :treeProps="treeProps">
33
- <!-- 复选框 -->
34
- <el-table-column v-if="type === 'selection'" type="selection" width="55px" :selectable="(row: any, index: number) => tableConfig?.tableAttr?.selectable(row, index) ?? true" header-align="center" align="center" />
35
- <!-- 下标 -->
36
- <el-table-column v-if="isIndex" type="index" width="60" label="序号" />
37
- <!-- 首列 -->
38
- <template v-if="useSlots().firstColumn">
39
- <slot name="firstColumn" />
40
- </template>
41
- <template v-for="(item, i) in headerColumns" :key="item.prop + item.label + i">
42
- <!-- 二级表头 -->
43
- <template v-if="item.children && item.children.length > 0">
44
- <el-table-column v-if="columnShowList[i]?.some((t: boolean) => t)" :prop="item.label" :label="item.label" header-align="center">
45
- <template v-for="(item2, j) in item.children" :key="item2.label + i + j">
46
- <el-table-column :prop="item2.prop" v-if="columnShowList[i][j]" v-bind="item2">
47
- <template #header>
48
- <div :class="{ 'th-required': item2.required }">
49
- {{ item2.label }}
50
- </div>
51
- </template>
52
- <template #default="scope: any">
53
- <slot name="default"></slot>
54
- <ColumnItem v-if="scope.$index >= 0" :field="item2.prop" :desc="item2" :scope="scope" :size="size" v-model="scope.row[item2.prop]" />
55
- </template>
56
- </el-table-column>
57
- </template>
58
- </el-table-column>
59
- </template>
60
- <!-- 单级表头 -->
61
- <template v-else>
62
- <el-table-column v-if="columnShowList[i]" :prop="item.prop" v-bind="item">
63
- <template #header="{ column }: any">
64
- <div :class="{ 'th-required': item.required }" :style="item.hstyle">
65
- {{ column.label }}
66
- </div>
67
- </template>
68
- <template #default="scope: any">
69
- <ColumnItem v-if="scope.$index >= 0" :field="item.prop" :desc="item" :scope="scope" :size="size" v-model="scope.row[item.prop]" />
70
- </template>
71
- </el-table-column>
72
- </template>
73
- </template>
74
- <template v-if="!loading && loadingStatus === 2" #empty>
75
- <el-empty v-if="isEmptyImg" :description="nullText" />
76
- <span v-else>{{ nullText }}</span>
77
- </template>
78
- <!-- 合计行 -->
79
- <template v-if="tableConfig.summaryConf?.prop" #append>
80
- <div :style="tableConfig.summaryConf?.hstyle" class="summary-row" v-if="summaryList && summaryList.length > 0">
81
- <div class="summary-item" v-for="(item, i) in summaryList" :key="i">
82
- <span>{{ item.label || '合计' }}:</span>
83
- <p>{{ item.value || 0 }}</p>
84
- </div>
85
- </div>
86
- </template>
87
- </el-table>
88
- </div>
89
- <div class="bottom-page-static-info" v-if="isPager || tableConfig.statistic">
90
- <el-pagination class="page-info" small @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="+pageInfo.current" :page-sizes="[5, 10, 20, 50, 100]" :page-size="pageInfo.size" layout="total, sizes, prev, pager, next, jumper" :total="pageInfo.total" />
91
- </div>
92
- <slot name="bottom"></slot>
93
- </div>
94
- </template>
95
- <script lang="ts">
96
- export default {
97
- name: 'ElPlusTable',
98
- inheritAttrs: false,
99
- customOptions: {}
100
- }
101
- </script>
102
- <script lang="ts" setup>
103
- import { ref, reactive, onMounted, computed, watch, nextTick, useSlots, inject } from 'vue'
104
- import EleTabletHeader from './components/header.vue'
105
- import ColumnItem from './components/columnItem.vue'
106
- import { handelListColumn } from './util'
107
- import { cloneDeep } from 'lodash'
108
- import { Loading } from '@element-plus/icons-vue'
109
-
110
- const defaultConf = inject('defaultConf') as ICRUDConfig
111
- const format = inject('format') as any
112
-
113
- const emits = defineEmits(['getUrlConsumerIds', 'selection', 'select', 'selectAll', 'update:modelValue', 'tabChange', 'expandChange'])
114
- const props = withDefaults(
115
- defineProps<{
116
- tableConfig: ITableConfig
117
- // 外部数据
118
- modelValue?: Array<any> | null
119
- // 列表类型 默认为index
120
- type?: string
121
- // 是否显示第一列的Index下标
122
- isIndex?: boolean
123
- // 是否分页
124
- isPager?: boolean
125
- // 每页显示条数
126
- pageSize?: number
127
- // 是否在弹框中
128
- isDialog?: boolean
129
- // 空占位文本
130
- nullText?: string
131
- // 是否显示暂无数据的图片
132
- isEmptyImg?: boolean
133
- // 是否显示刷新文本
134
- isShowRefresh?: boolean
135
- // rowKey默认为id
136
- rowKey?: string
137
- // 自定义table主体
138
- isDIYMain?: boolean
139
- // 默认选中项
140
- selectList?: Array<any> | []
141
- // 默认列宽
142
- colMinWidth?: string
143
- }>(),
144
- {
145
- modelValue: null,
146
- type: 'index',
147
- isIndex: true,
148
- isPager: true,
149
- pageSize: 10,
150
- isDialog: false,
151
- nullText: '暂无数据',
152
- isShowRefresh: true,
153
- rowKey: 'id',
154
- isEmptyImg: true,
155
- isDIYMain: false,
156
- selectList: () => [],
157
- colMinWidth: 'auto'
158
- }
159
- )
160
-
161
- const elPlusTableRef = ref()
162
-
163
- // 顶部Tab数据
164
- const tableTabVal = ref(props.tableConfig?.tabConf?.tabs[0].value ?? '')
165
- const tabStatic = ref({} as any)
166
- const getTabLabel = computed(() => (item: ITableTabItem) => {
167
- if (item.key) {
168
- return tabStatic.value[item.key] || 0
169
- }
170
- return ''
171
- })
172
-
173
- const tableHeaderRef = ref()
174
-
175
- // 加载
176
- const loading = ref(false)
177
- const loadingTab = ref(!!props.tableConfig.tabConf?.fetch)
178
- const listLoading = ref(false)
179
- const size = defaultConf.size || 'small'
180
-
181
- // 顶部查询条件数据缓存
182
- const topQueryData = ref({} as any)
183
-
184
- // 数据
185
- let toolFormData = reactive({} as any)
186
- const tableData = reactive((props.modelValue || []) as any[])
187
- const haveClassRowList = reactive([])
188
-
189
- // 初始化表头
190
- const headerColumns = reactive(handelListColumn(props.tableConfig.column, props.isDialog ? 'auto' : props.colMinWidth))
191
-
192
- // 0:未加载; 1:加载中;2:加载完成
193
- const loadingStatus = ref(0)
194
-
195
- // 保存所有的选中行
196
- const allSelectRowList = reactive((cloneDeep(props.selectList) || []) as any[])
197
- // 记录树形展开的数组的下标
198
- const treeIndexList = reactive([] as any[][])
199
-
200
- // 分页信息
201
- const pageInfo = reactive({
202
- current: !props.isDialog && toolFormData.current ? parseInt(toolFormData.current as any) : 1,
203
- total: 0,
204
- size: !props.isDialog && toolFormData.size ? parseInt(toolFormData.size as any) : props.pageSize
205
- })
206
- // 数型解析
207
- const treeProps = (props.tableConfig?.explan?.treeProps || { children: 'children', hasChildren: 'hasChildren' }) as ITreeProps
208
-
209
- // 列的显示
210
- const columnShowList = computed(() => {
211
- return handelVIfList(handelListColumn(props.tableConfig.column, props.isDialog ? 'auto' : props.colMinWidth))
212
- })
213
-
214
- // 合计行数据
215
- const summaryList = computed(() => {
216
- const tempList = [] as any[]
217
- if (props.tableConfig.summaryConf?.vif) {
218
- if (typeof props.tableConfig.summaryConf?.vif === 'boolean') {
219
- if (!props.tableConfig.summaryConf?.vif) {
220
- return tempList
221
- }
222
- } else {
223
- if (!props.tableConfig.summaryConf?.vif()) {
224
- return tempList
225
- }
226
- }
227
- }
228
- if (props.tableConfig.summaryConf?.prop) {
229
- const propList = props.tableConfig.summaryConf.prop.split(',')
230
- const labelList = props.tableConfig.summaryConf?.label?.split(',') || []
231
- // 遍历
232
- propList.map((prop, i: number) => {
233
- let value = ''
234
- if (props.tableConfig.summaryConf?.sumFn) {
235
- value = props.tableConfig.summaryConf?.sumFn(tableData, allSelectRowList)
236
- } else {
237
- value = format.yuan(tableData.reduce((total: number, current) => (total += current[prop]), 0))
238
- }
239
- tempList.push({ label: labelList[i], value })
240
- })
241
- }
242
- return tempList
243
- })
244
-
245
- /**
246
- * 处理列表的vif
247
- * @param list
248
- */
249
- function handelVIfList(list: any[]): any[] {
250
- return list.map((item) => {
251
- if (item.children) {
252
- return handelVIfList(item.children)
253
- }
254
- if (props.tableConfig.tbName) {
255
- return item._vif && item.scShow
256
- } else {
257
- // 这里初始化一下vif
258
- if (item.vif !== undefined && item.vif !== null) {
259
- if (typeof item.vif === 'function') {
260
- item._vif = item.vif(item)
261
- } else {
262
- item._vif = !!item.vif
263
- }
264
- } else {
265
- item._vif = true
266
- }
267
- return item._vif
268
- }
269
- })
270
- }
271
-
272
- /**
273
- * Tab切换
274
- * @param val
275
- */
276
- function handelTabChange(val: string | number | boolean) {
277
- // 这里直接重新查询
278
- reload(true)
279
- // 通知父类
280
- emits('tabChange', val)
281
- }
282
-
283
- /**
284
- * 加载自身展开的数据
285
- * @param row
286
- * @param treeNode
287
- * @param resolve
288
- */
289
- function loadExpandData(row: any, treeNode: any, resolve: any) {
290
- const postData = getListQueryData()
291
- postData[props.tableConfig?.explan?.idName || 'parentId'] = row.id
292
- props.tableConfig.fetch &&
293
- props.tableConfig.fetch(postData).then((pageInfo) => {
294
- resolve(pageInfo?.records)
295
- })
296
- }
297
-
298
- /**
299
- * 初始化每行的颜色
300
- * @param data
301
- */
302
- function initRowClassName(data: any) {
303
- if (haveClassRowList.length > data.rowIndex) {
304
- return haveClassRowList[data.rowIndex * 1]
305
- }
306
- return ''
307
- }
308
-
309
- /**
310
- * 处理单个选中的情况
311
- * @param selection
312
- * @param row
313
- */
314
- function handelTableSelect(selection: any[], item: any) {
315
- checkAndRemove(item, !selection.some((i) => i[props.rowKey] === item[props.rowKey]))
316
- // 通知父类
317
- emits('select', selection, item)
318
- emits('selection', cloneDeep(allSelectRowList))
319
- }
320
-
321
- /**
322
- * 处理全选
323
- * @param selection
324
- * @param row
325
- */
326
- function handelTableSelectAll(selection: any[]) {
327
- const isRemove = !(selection && selection.length > 0)
328
- ;(isRemove ? tableData : selection).map((item) => {
329
- checkAndRemove(item, isRemove)
330
- })
331
- // 通知父类
332
- emits('selectAll', selection, isRemove)
333
- emits('selection', cloneDeep(allSelectRowList))
334
- }
335
-
336
- /**
337
- * 处理行展开
338
- * @param row
339
- * @param expanded
340
- */
341
- function handelTableExpandChange(row: any, expanded: boolean) {
342
- // console.log('row: ', row, expanded)
343
- emits('expandChange', row, expanded)
344
- }
345
-
346
- /**
347
- * 选中或者取消
348
- * @param item
349
- */
350
- function checkAndRemove(item: any, isRemove: boolean = false) {
351
- // 校验是否已经有了
352
- const index = allSelectRowList.findIndex((i) => i[props.rowKey] === item[props.rowKey])
353
- if (isRemove) {
354
- if (index >= 0) {
355
- allSelectRowList.splice(index, 1)
356
- }
357
- } else {
358
- if (index < 0) {
359
- allSelectRowList.push(item)
360
- }
361
- }
362
- }
363
-
364
- /**
365
- * 外部修改选中项
366
- * @param item
367
- */
368
- function changeSelect(itemList: any[], isSelect: boolean = false) {
369
- if (itemList && itemList.length) {
370
- itemList.map((item) => {
371
- checkAndRemove(
372
- allSelectRowList.find((i) => i[props.rowKey] === item[props.rowKey]),
373
- !isSelect
374
- )
375
- })
376
- }
377
- // 这里要刷新一下tab的选中
378
- refreshTableSelect()
379
- }
380
-
381
- /**
382
- * 重置选中
383
- */
384
- function resetSelect() {
385
- allSelectRowList.splice(0, allSelectRowList.length, ...props.selectList)
386
- }
387
-
388
- /**
389
- * 封装分页查询条件
390
- */
391
- async function getListQueryData() {
392
- let queryMap = {
393
- // 封装查询条件
394
- // ...route.query,
395
- // ...tableHeaderRef.value.getData(),
396
- ...topQueryData.value,
397
- ...(typeof props.tableConfig.queryMap === 'function' ? await props.tableConfig.queryMap() : props.tableConfig.queryMap),
398
- t_: new Date().getTime()
399
- } as any
400
- if (props.isPager) {
401
- // 封装分页信息
402
- queryMap.current = pageInfo.current
403
- queryMap.size = pageInfo.size
404
- }
405
- // 这里处理一下列表Tab的查询条件
406
- if (props.tableConfig.tabConf && props.tableConfig.tabConf.prop) {
407
- queryMap[props.tableConfig.tabConf.prop] = tableTabVal.value
408
- }
409
-
410
- queryMap = handelQueryData(queryMap)
411
- if (!props.isDialog) {
412
- // setQuery(route.path, queryMap)
413
- }
414
- // 这里是导出的权限判定-增加登陆信息
415
- if (props.tableConfig?.toolbar?.export?.isAuth) {
416
- // TODO GET Auth
417
- }
418
- return queryMap
419
- }
420
-
421
- /**
422
- * 处理下请求参数
423
- * @param queryMap
424
- */
425
- function handelQueryData(queryMap: object) {
426
- if (!queryMap) return {}
427
- const tempMap = {}
428
- Object.keys(queryMap).map((key) => {
429
- if (queryMap[key] !== undefined && queryMap[key] !== null && queryMap[key] !== '') {
430
- tempMap[key] = queryMap[key]
431
- }
432
- })
433
- return tempMap
434
- }
435
-
436
- /**
437
- * 处理显示
438
- * @param rowInfo
439
- */
440
- // function handelHeaderVIf(rowInfo: any) {
441
- // let vif = false
442
- // if (rowInfo.children && rowInfo.children.length > 0) {
443
- // vif = rowInfo.children.some((item: any) => {
444
- // return !(item.vif === false)
445
- // })
446
- // }
447
- // return vif
448
- // }
449
-
450
- /**
451
- * 处理列的显示
452
- * @param item
453
- */
454
- // function handelColumnVIf(item: any) {
455
- // if (item.vif !== undefined && item.vif !== null && item.vif !== '') {
456
- // if (typeof item.vif === 'boolean') return item.vif
457
- // if (typeof item.vif === 'function') return item.vif(item)
458
- // return !!item.vif
459
- // }
460
- // return true
461
- // }
462
-
463
- /**
464
- * 处理分页工具中pageSize变化
465
- * @param val
466
- */
467
- function handleSizeChange(val: number) {
468
- // 回到第一页
469
- pageInfo.current = 1
470
- pageInfo.size = val
471
- loadData(true)
472
- }
473
-
474
- /**
475
- * 处理分页工具中current变化
476
- * @param val
477
- */
478
- function handleCurrentChange(val: number) {
479
- if (pageInfo.current !== val) {
480
- pageInfo.current = val
481
- loadData(false)
482
- }
483
- }
484
-
485
- /**
486
- * 处理行展开
487
- * @param list
488
- * @param pIndexList
489
- */
490
- function handelTreeIndex(list: any[], pIndexList: number[]) {
491
- let tempList = []
492
- if (list && list.length > 0) {
493
- list.map((item, i) => {
494
- treeIndexList.push([...pIndexList, i])
495
- tempList = item[treeProps.children] as any[]
496
- if (tempList && tempList.length > 0) {
497
- handelTreeIndex(tempList, [i])
498
- }
499
- })
500
- }
501
- }
502
-
503
- /**
504
- * 真正调用查询的接口
505
- * @param isInit
506
- */
507
- async function loadData(isInit: Boolean) {
508
- if (!props.tableConfig.fetch) {
509
- loadingStatus.value = 2
510
- // if (props.modelValue) {
511
- // tableData.splice(0, tableData.length, ...props.modelValue)
512
- // }
513
- return false
514
- }
515
- if (loadingStatus.value === 1 || loading.value) return false
516
- loadingStatus.value = 1
517
- loading.value = true
518
- tableData.splice(0, tableData.length)
519
- if (isInit) {
520
- pageInfo.current = 1
521
- }
522
- let postData = await getListQueryData()
523
- // 这里处理一下外部数据格式化
524
- if (props.tableConfig?.toolbar?.formConfig?.beforeRequest) {
525
- postData = props.tableConfig?.toolbar?.formConfig?.beforeRequest(JSON.parse(JSON.stringify(postData))) || postData
526
- }
527
- const dataPage = (await props.tableConfig.fetch(postData)) as any
528
- try {
529
- if (props.isPager) {
530
- pageInfo.total = dataPage?.total * 1 || 0
531
- pageInfo.current = dataPage?.current || 1
532
- tableData.push(...(dataPage?.records || null))
533
- } else {
534
- tableData.push(...(dataPage?.records || dataPage || null))
535
- }
536
- if (isInit) {
537
- // 初始化完毕后,调用一次父类更新
538
- // emits('update:modelValue', tableData)
539
- }
540
- // 如果是树形结构
541
- if (props.type === 'expand') {
542
- treeIndexList.splice(0, treeIndexList.length)
543
- handelTreeIndex(tableData, [])
544
- }
545
- listLoading.value = false
546
- nextTick(() => {
547
- // 遍历以及选中当前页面数据
548
- refreshTableSelect()
549
- })
550
- } catch (e) {
551
- // eslint-disable-next-line no-console
552
- console.log('error: ', e)
553
- }
554
- loadingStatus.value = 2
555
- loading.value = false
556
- }
557
-
558
- /**
559
- * 渲染列表的选中项
560
- */
561
- function refreshTableSelect() {
562
- if (tableData && tableData.length > 0 && props.type === 'selection') {
563
- tableData.map((item: any) => {
564
- elPlusTableRef.value!.toggleRowSelection(
565
- item,
566
- allSelectRowList.some((i) => i[props.rowKey] === item[props.rowKey])
567
- )
568
- })
569
- }
570
- }
571
-
572
- /**
573
- * 重新加载
574
- */
575
- async function reload(isTab: boolean = false) {
576
- await loadData(true)
577
- // 这里判断一下Tab
578
- if (!isTab && props.tableConfig.tabConf && props.tableConfig.tabConf.fetch) {
579
- tabStatic.value = await props.tableConfig.tabConf.fetch(Object.assign({}, await getListQueryData(), props.tableConfig.tabConf.queryMap))
580
- loadingTab.value = false
581
- }
582
- return tableData
583
- }
584
-
585
- /**
586
- * 处理顶部条件表单筛选
587
- */
588
- function handelTopQuery() {
589
- topQueryData.value = cloneDeep(tableHeaderRef.value.getData())
590
- reload()
591
- }
592
-
593
- /**
594
- * 初始化列
595
- */
596
- function initCol() {
597
- tableHeaderRef.value?.initCol()
598
- }
599
-
600
- // 监听父类数据变更
601
- watch(
602
- () => props.modelValue,
603
- (data) => {
604
- // console.log('data: ', JSON.parse(JSON.stringify(data)))
605
- if (!props.tableConfig.fetch) {
606
- if (JSON.parse(JSON.stringify(data)) !== JSON.parse(JSON.stringify(tableData))) {
607
- loadingStatus.value = 2
608
- tableData.splice(0, tableData.length, ...(data || []))
609
- }
610
- }
611
- },
612
- { deep: true }
613
- )
614
-
615
- watch(
616
- () => props.selectList,
617
- (val: any[]) => {
618
- allSelectRowList.splice(0, allSelectRowList.length, ...val)
619
- // 遍历以及选中当前页面数据
620
- refreshTableSelect()
621
- },
622
- { deep: true }
623
- )
624
-
625
- onMounted(() => {
626
- reload()
627
- })
628
-
629
- defineExpose({ reload, tableData, changeSelect, resetSelect, initCol })
630
- </script>
631
- <style lang="scss">
632
- .el-plus-table-content {
633
- background-color: #ffffff;
634
- border-radius: 5px;
635
- padding: 10px;
636
- width: 100%;
637
- max-height: 100%;
638
- overflow: hidden;
639
- display: flex;
640
- flex-direction: column;
641
- position: relative;
642
- .th-required {
643
- position: relative;
644
- &::before {
645
- content: '*';
646
- position: absolute;
647
- left: -10px;
648
- font-size: 16px;
649
- top: 2px;
650
- color: #ff3b30;
651
- font-weight: bold;
652
- }
653
- }
654
- .select-items {
655
- display: flex;
656
- flex-wrap: wrap;
657
- align-items: center;
658
-
659
- .title {
660
- font-size: 18px;
661
- font-weight: bold;
662
- margin-right: 20px;
663
- }
664
-
665
- .select-item {
666
- margin: 5px 10px 5px 0;
667
-
668
- &:last-child {
669
- margin-right: 0;
670
- }
671
- }
672
- }
673
-
674
- .table-tabs-panel {
675
- margin-bottom: 16px;
676
- }
677
- .summary-row {
678
- width: 100%;
679
- background-color: var(--el-table-row-hover-bg-color);
680
- color: var(--el-table-text-color);
681
- padding: 16px 20px;
682
- line-height: 24px;
683
- height: 40px;
684
- display: flex;
685
- position: relative;
686
- .summary-item {
687
- display: flex;
688
- align-items: center;
689
- margin-right: 30px;
690
- & > span {
691
- margin-right: 20px;
692
- }
693
- }
694
- }
695
-
696
- .el-plus-table-main {
697
- width: 100%;
698
- flex: 1;
699
- max-height: 100%;
700
- display: flex;
701
- flex-direction: column;
702
- .el-table {
703
- .cell {
704
- display: flex;
705
- }
706
- .is-center {
707
- .cell {
708
- align-items: center;
709
- justify-content: center;
710
- }
711
- }
712
- }
713
- }
714
-
715
- .pager-statistic {
716
- width: 100%;
717
- position: fixed;
718
- height: 32px;
719
- line-height: 32px;
720
- bottom: 0;
721
- text-align: right;
722
- min-width: 900px;
723
-
724
- .statistic-item {
725
- display: inline-block;
726
- }
727
- }
728
-
729
- .el-cascader__label {
730
- width: 300px !important;
731
- }
732
-
733
- .bottom-page-static-info {
734
- display: flex;
735
- flex-wrap: wrap;
736
- justify-content: center;
737
- align-items: center;
738
- min-height: 41px;
739
- margin-top: 10px;
740
-
741
- .page-info {
742
- margin-right: 30px;
743
- }
744
- }
745
-
746
- .common-list-export-excel {
747
- background: #20a0ff;
748
- text-decoration: none;
749
- color: #ffffff;
750
- font-size: 12px;
751
- height: 29px;
752
- line-height: 30px;
753
- display: block;
754
- margin-top: 5px;
755
- border-radius: 3px;
756
- padding: 0 10px;
757
- }
758
-
759
- .common-list-export-excel:hover {
760
- background: #58b6ff;
761
- }
762
-
763
- .el-table__empty-block {
764
- height: auto !important;
765
- }
766
- }
767
- </style>
1
+ <template>
2
+ <div class="el-plus-table-content">
3
+ <!-- <div class="select-items" v-if="type === 'selection' && selectRowList && selectRowList.length > 0">
4
+ <span class="title">已选择({{ selectRowList.length }}个): </span>
5
+ <el-tag v-for="(item, i) in selectRowList" :key="item.id" class="select-item" size="small" closable @close="() => handelRemoveSelect(i, item)">
6
+ {{ item[tableConfig.showSelectNameKey || 'name'] }}
7
+ </el-tag>
8
+ </div> -->
9
+ <EleTabletHeader ref="tableHeaderRef" v-if="Object.keys(tableConfig?.toolbar || {}).length || tableConfig.tbName" v-model="toolFormData" :tbName="tableConfig.tbName" :column="tableConfig.column" :size="size" :isShowRefresh="isShowRefresh" :loading="loading" :toolbar="tableConfig.toolbar" :isDialog="isDialog" @query="handelTopQuery" />
10
+
11
+ <!-- 中部的Tabs -->
12
+ <div class="table-tabs-panel" v-if="tableConfig.tabConf">
13
+ <el-radio-group v-model="tableTabVal" size="default" @change="handelTabChange">
14
+ <el-radio-button v-for="(item, i) in tableConfig.tabConf?.tabs" :key="i" :label="item.value" :loading="true">
15
+ {{ item.label }}
16
+ <template v-if="loadingTab">
17
+ <el-icon class="is-loading"><Loading /></el-icon>
18
+ </template>
19
+ <template v-else>
20
+ {{ getTabLabel(item) }}
21
+ </template>
22
+ </el-radio-button>
23
+ </el-radio-group>
24
+ </div>
25
+
26
+ <!-- 中间列表 -->
27
+ <div class="el-plus-table-main" v-loading="loading">
28
+ <template v-if="isDIYMain">
29
+ <slot name="main" :tableData="tableData"></slot>
30
+ </template>
31
+ <!-- 这里开始是表格内容 -->
32
+ <el-table ref="elPlusTableRef" v-else style="width: 100%" height="100%" :maxHeight="tableConfig.maxHeight || 'auto'" v-bind="tableConfig.tableAttr" :data="tableData" :row-key="rowKey" lazy :load="loadExpandData" :size="size" :row-class-name="initRowClassName" @select="handelTableSelect" @select-all="handelTableSelectAll" @expand-change="handelTableExpandChange" :treeProps="treeProps">
33
+ <!-- 复选框 -->
34
+ <el-table-column v-if="type === 'selection'" type="selection" width="55px" :selectable="(row: any, index: number) => tableConfig?.tableAttr?.selectable(row, index) ?? true" header-align="center" align="center" />
35
+ <!-- 下标 -->
36
+ <el-table-column v-if="isIndex" type="index" width="60" label="序号" />
37
+ <!-- 首列 -->
38
+ <template v-if="useSlots().firstColumn">
39
+ <slot name="firstColumn" />
40
+ </template>
41
+ <template v-for="(item, i) in headerColumns" :key="item.prop + item.label + i">
42
+ <!-- 二级表头 -->
43
+ <template v-if="item.children && item.children.length > 0">
44
+ <el-table-column v-if="columnShowList[i]?.some((t: boolean) => t)" :prop="item.label" :label="item.label" header-align="center">
45
+ <template v-for="(item2, j) in item.children" :key="item2.label + i + j">
46
+ <el-table-column :prop="item2.prop" v-if="columnShowList[i][j]" v-bind="item2">
47
+ <template #header>
48
+ <div :class="{ 'th-required': item2.required }">
49
+ {{ item2.label }}
50
+ </div>
51
+ </template>
52
+ <template #default="scope: any">
53
+ <slot name="default"></slot>
54
+ <ColumnItem v-if="scope.$index >= 0" :field="item2.prop" :desc="item2" :scope="scope" :size="size" v-model="scope.row[item2.prop]" />
55
+ </template>
56
+ </el-table-column>
57
+ </template>
58
+ </el-table-column>
59
+ </template>
60
+ <!-- 单级表头 -->
61
+ <template v-else>
62
+ <el-table-column v-if="columnShowList[i]" :prop="item.prop" v-bind="item">
63
+ <template #header="{ column }: any">
64
+ <div :class="{ 'th-required': item.required }" :style="item.hstyle">
65
+ {{ column.label }}
66
+ </div>
67
+ </template>
68
+ <template #default="scope: any">
69
+ <ColumnItem v-if="scope.$index >= 0" :field="item.prop" :desc="item" :scope="scope" :size="size" v-model="scope.row[item.prop]" />
70
+ </template>
71
+ </el-table-column>
72
+ </template>
73
+ </template>
74
+ <template v-if="!loading && loadingStatus === 2" #empty>
75
+ <el-empty v-if="isEmptyImg" :description="nullText" />
76
+ <span v-else>{{ nullText }}</span>
77
+ </template>
78
+ <!-- 合计行 -->
79
+ <template v-if="tableConfig.summaryConf?.prop" #append>
80
+ <div :style="tableConfig.summaryConf?.hstyle" class="summary-row" v-if="summaryList && summaryList.length > 0">
81
+ <div class="summary-item" v-for="(item, i) in summaryList" :key="i">
82
+ <span>{{ item.label || '合计' }}:</span>
83
+ <p>{{ item.value || 0 }}</p>
84
+ </div>
85
+ </div>
86
+ </template>
87
+ </el-table>
88
+ </div>
89
+ <div class="bottom-page-static-info" v-if="isPager || tableConfig.statistic">
90
+ <el-pagination class="page-info" small @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="+pageInfo.current" :page-sizes="[5, 10, 20, 50, 100]" :page-size="pageInfo.size" layout="total, sizes, prev, pager, next, jumper" :total="pageInfo.total" />
91
+ </div>
92
+ <slot name="bottom"></slot>
93
+ </div>
94
+ </template>
95
+ <script lang="ts">
96
+ export default {
97
+ name: 'ElPlusTable',
98
+ inheritAttrs: false,
99
+ customOptions: {}
100
+ }
101
+ </script>
102
+ <script lang="ts" setup>
103
+ import { ref, reactive, onMounted, computed, watch, nextTick, useSlots, inject } from 'vue'
104
+ import EleTabletHeader from './components/header.vue'
105
+ import ColumnItem from './components/columnItem.vue'
106
+ import { handelListColumn } from './util'
107
+ import { cloneDeep } from 'lodash'
108
+ import { Loading } from '@element-plus/icons-vue'
109
+
110
+ const defaultConf = inject('defaultConf') as ICRUDConfig
111
+ const format = inject('format') as any
112
+
113
+ const emits = defineEmits(['getUrlConsumerIds', 'selection', 'select', 'selectAll', 'update:modelValue', 'tabChange', 'expandChange'])
114
+ const props = withDefaults(
115
+ defineProps<{
116
+ tableConfig: ITableConfig
117
+ // 外部数据
118
+ modelValue?: Array<any> | null
119
+ // 列表类型 默认为index
120
+ type?: string
121
+ // 是否显示第一列的Index下标
122
+ isIndex?: boolean
123
+ // 是否分页
124
+ isPager?: boolean
125
+ // 每页显示条数
126
+ pageSize?: number
127
+ // 是否在弹框中
128
+ isDialog?: boolean
129
+ // 空占位文本
130
+ nullText?: string
131
+ // 是否显示暂无数据的图片
132
+ isEmptyImg?: boolean
133
+ // 是否显示刷新文本
134
+ isShowRefresh?: boolean
135
+ // rowKey默认为id
136
+ rowKey?: string
137
+ // 自定义table主体
138
+ isDIYMain?: boolean
139
+ // 默认选中项
140
+ selectList?: Array<any> | []
141
+ // 默认列宽
142
+ colMinWidth?: string
143
+ }>(),
144
+ {
145
+ modelValue: null,
146
+ type: 'index',
147
+ isIndex: true,
148
+ isPager: true,
149
+ pageSize: 10,
150
+ isDialog: false,
151
+ nullText: '暂无数据',
152
+ isShowRefresh: true,
153
+ rowKey: 'id',
154
+ isEmptyImg: true,
155
+ isDIYMain: false,
156
+ selectList: () => [],
157
+ colMinWidth: 'auto'
158
+ }
159
+ )
160
+
161
+ const elPlusTableRef = ref()
162
+
163
+ // 顶部Tab数据
164
+ const tableTabVal = ref(props.tableConfig?.tabConf?.tabs[0].value ?? '')
165
+ const tabStatic = ref({} as any)
166
+ const getTabLabel = computed(() => (item: ITableTabItem) => {
167
+ if (item.key) {
168
+ return tabStatic.value[item.key] || 0
169
+ }
170
+ return ''
171
+ })
172
+
173
+ const tableHeaderRef = ref()
174
+
175
+ // 加载
176
+ const loading = ref(false)
177
+ const loadingTab = ref(!!props.tableConfig.tabConf?.fetch)
178
+ const listLoading = ref(false)
179
+ const size = defaultConf.size || 'small'
180
+
181
+ // 顶部查询条件数据缓存
182
+ const topQueryData = ref({} as any)
183
+
184
+ // 数据
185
+ let toolFormData = reactive({} as any)
186
+ const tableData = reactive((props.modelValue || []) as any[])
187
+ const haveClassRowList = reactive([])
188
+
189
+ // 初始化表头
190
+ const headerColumns = reactive(handelListColumn(props.tableConfig.column, props.isDialog ? 'auto' : props.colMinWidth))
191
+
192
+ // 0:未加载; 1:加载中;2:加载完成
193
+ const loadingStatus = ref(0)
194
+
195
+ // 保存所有的选中行
196
+ const allSelectRowList = reactive((cloneDeep(props.selectList) || []) as any[])
197
+ // 记录树形展开的数组的下标
198
+ const treeIndexList = reactive([] as any[][])
199
+
200
+ // 分页信息
201
+ const pageInfo = reactive({
202
+ current: !props.isDialog && toolFormData.current ? parseInt(toolFormData.current as any) : 1,
203
+ total: 0,
204
+ size: !props.isDialog && toolFormData.size ? parseInt(toolFormData.size as any) : props.pageSize
205
+ })
206
+ // 数型解析
207
+ const treeProps = (props.tableConfig?.explan?.treeProps || { children: 'children', hasChildren: 'hasChildren' }) as ITreeProps
208
+
209
+ // 列的显示
210
+ const columnShowList = computed(() => {
211
+ return handelVIfList(handelListColumn(props.tableConfig.column, props.isDialog ? 'auto' : props.colMinWidth))
212
+ })
213
+
214
+ // 合计行数据
215
+ const summaryList = computed(() => {
216
+ const tempList = [] as any[]
217
+ if (props.tableConfig.summaryConf?.vif) {
218
+ if (typeof props.tableConfig.summaryConf?.vif === 'boolean') {
219
+ if (!props.tableConfig.summaryConf?.vif) {
220
+ return tempList
221
+ }
222
+ } else {
223
+ if (!props.tableConfig.summaryConf?.vif()) {
224
+ return tempList
225
+ }
226
+ }
227
+ }
228
+ if (props.tableConfig.summaryConf?.prop) {
229
+ const propList = props.tableConfig.summaryConf.prop.split(',')
230
+ const labelList = props.tableConfig.summaryConf?.label?.split(',') || []
231
+ // 遍历
232
+ propList.map((prop, i: number) => {
233
+ let value = ''
234
+ if (props.tableConfig.summaryConf?.sumFn) {
235
+ value = props.tableConfig.summaryConf?.sumFn(tableData, allSelectRowList)
236
+ } else {
237
+ value = format.yuan(tableData.reduce((total: number, current) => (total += current[prop]), 0))
238
+ }
239
+ tempList.push({ label: labelList[i], value })
240
+ })
241
+ }
242
+ return tempList
243
+ })
244
+
245
+ /**
246
+ * 处理列表的vif
247
+ * @param list
248
+ */
249
+ function handelVIfList(list: any[]): any[] {
250
+ return list.map((item) => {
251
+ if (item.children) {
252
+ return handelVIfList(item.children)
253
+ }
254
+ if (props.tableConfig.tbName) {
255
+ return item._vif && item.scShow
256
+ } else {
257
+ // 这里初始化一下vif
258
+ if (item.vif !== undefined && item.vif !== null) {
259
+ if (typeof item.vif === 'function') {
260
+ item._vif = item.vif(item)
261
+ } else {
262
+ item._vif = !!item.vif
263
+ }
264
+ } else {
265
+ item._vif = true
266
+ }
267
+ return item._vif
268
+ }
269
+ })
270
+ }
271
+
272
+ /**
273
+ * Tab切换
274
+ * @param val
275
+ */
276
+ async function handelTabChange(val: string | number | boolean) {
277
+ // 这里直接重新查询
278
+ reload(true)
279
+
280
+ // 通知父类 第二个参数是回调
281
+ await emits('tabChange', val, initCol)
282
+
283
+ // 这里触发下initCol
284
+ nextTick(() => {
285
+ initCol()
286
+ })
287
+ }
288
+
289
+ /**
290
+ * 加载自身展开的数据
291
+ * @param row
292
+ * @param treeNode
293
+ * @param resolve
294
+ */
295
+ function loadExpandData(row: any, treeNode: any, resolve: any) {
296
+ const postData = getListQueryData()
297
+ postData[props.tableConfig?.explan?.idName || 'parentId'] = row.id
298
+ props.tableConfig.fetch &&
299
+ props.tableConfig.fetch(postData).then((pageInfo) => {
300
+ resolve(pageInfo?.records)
301
+ })
302
+ }
303
+
304
+ /**
305
+ * 初始化每行的颜色
306
+ * @param data
307
+ */
308
+ function initRowClassName(data: any) {
309
+ if (haveClassRowList.length > data.rowIndex) {
310
+ return haveClassRowList[data.rowIndex * 1]
311
+ }
312
+ return ''
313
+ }
314
+
315
+ /**
316
+ * 处理单个选中的情况
317
+ * @param selection
318
+ * @param row
319
+ */
320
+ function handelTableSelect(selection: any[], item: any) {
321
+ checkAndRemove(item, !selection.some((i) => i[props.rowKey] === item[props.rowKey]))
322
+ // 通知父类
323
+ emits('select', selection, item)
324
+ emits('selection', cloneDeep(allSelectRowList))
325
+ }
326
+
327
+ /**
328
+ * 处理全选
329
+ * @param selection
330
+ * @param row
331
+ */
332
+ function handelTableSelectAll(selection: any[]) {
333
+ const isRemove = !(selection && selection.length > 0)
334
+ ;(isRemove ? tableData : selection).map((item) => {
335
+ checkAndRemove(item, isRemove)
336
+ })
337
+ // 通知父类
338
+ emits('selectAll', selection, isRemove)
339
+ emits('selection', cloneDeep(allSelectRowList))
340
+ }
341
+
342
+ /**
343
+ * 处理行展开
344
+ * @param row
345
+ * @param expanded
346
+ */
347
+ function handelTableExpandChange(row: any, expanded: boolean) {
348
+ // console.log('row: ', row, expanded)
349
+ emits('expandChange', row, expanded)
350
+ }
351
+
352
+ /**
353
+ * 选中或者取消
354
+ * @param item
355
+ */
356
+ function checkAndRemove(item: any, isRemove: boolean = false) {
357
+ // 校验是否已经有了
358
+ const index = allSelectRowList.findIndex((i) => i[props.rowKey] === item[props.rowKey])
359
+ if (isRemove) {
360
+ if (index >= 0) {
361
+ allSelectRowList.splice(index, 1)
362
+ }
363
+ } else {
364
+ if (index < 0) {
365
+ allSelectRowList.push(item)
366
+ }
367
+ }
368
+ }
369
+
370
+ /**
371
+ * 外部修改选中项
372
+ * @param item
373
+ */
374
+ function changeSelect(itemList: any[], isSelect: boolean = false) {
375
+ if (itemList && itemList.length) {
376
+ itemList.map((item) => {
377
+ checkAndRemove(
378
+ allSelectRowList.find((i) => i[props.rowKey] === item[props.rowKey]),
379
+ !isSelect
380
+ )
381
+ })
382
+ }
383
+ // 这里要刷新一下tab的选中
384
+ refreshTableSelect()
385
+ }
386
+
387
+ /**
388
+ * 重置选中
389
+ */
390
+ function resetSelect() {
391
+ allSelectRowList.splice(0, allSelectRowList.length, ...props.selectList)
392
+ }
393
+
394
+ /**
395
+ * 封装分页查询条件
396
+ */
397
+ async function getListQueryData() {
398
+ let queryMap = {
399
+ // 封装查询条件
400
+ // ...route.query,
401
+ // ...tableHeaderRef.value.getData(),
402
+ ...topQueryData.value,
403
+ ...(typeof props.tableConfig.queryMap === 'function' ? await props.tableConfig.queryMap() : props.tableConfig.queryMap),
404
+ t_: new Date().getTime()
405
+ } as any
406
+ if (props.isPager) {
407
+ // 封装分页信息
408
+ queryMap.current = pageInfo.current
409
+ queryMap.size = pageInfo.size
410
+ }
411
+ // 这里处理一下列表Tab的查询条件
412
+ if (props.tableConfig.tabConf && props.tableConfig.tabConf.prop) {
413
+ queryMap[props.tableConfig.tabConf.prop] = tableTabVal.value
414
+ }
415
+
416
+ queryMap = handelQueryData(queryMap)
417
+ if (!props.isDialog) {
418
+ // setQuery(route.path, queryMap)
419
+ }
420
+ // 这里是导出的权限判定-增加登陆信息
421
+ if (props.tableConfig?.toolbar?.export?.isAuth) {
422
+ // TODO GET Auth
423
+ }
424
+ return queryMap
425
+ }
426
+
427
+ /**
428
+ * 处理下请求参数
429
+ * @param queryMap
430
+ */
431
+ function handelQueryData(queryMap: object) {
432
+ if (!queryMap) return {}
433
+ const tempMap = {}
434
+ Object.keys(queryMap).map((key) => {
435
+ if (queryMap[key] !== undefined && queryMap[key] !== null && queryMap[key] !== '') {
436
+ tempMap[key] = queryMap[key]
437
+ }
438
+ })
439
+ return tempMap
440
+ }
441
+
442
+ /**
443
+ * 处理显示
444
+ * @param rowInfo
445
+ */
446
+ // function handelHeaderVIf(rowInfo: any) {
447
+ // let vif = false
448
+ // if (rowInfo.children && rowInfo.children.length > 0) {
449
+ // vif = rowInfo.children.some((item: any) => {
450
+ // return !(item.vif === false)
451
+ // })
452
+ // }
453
+ // return vif
454
+ // }
455
+
456
+ /**
457
+ * 处理列的显示
458
+ * @param item
459
+ */
460
+ // function handelColumnVIf(item: any) {
461
+ // if (item.vif !== undefined && item.vif !== null && item.vif !== '') {
462
+ // if (typeof item.vif === 'boolean') return item.vif
463
+ // if (typeof item.vif === 'function') return item.vif(item)
464
+ // return !!item.vif
465
+ // }
466
+ // return true
467
+ // }
468
+
469
+ /**
470
+ * 处理分页工具中pageSize变化
471
+ * @param val
472
+ */
473
+ function handleSizeChange(val: number) {
474
+ // 回到第一页
475
+ pageInfo.current = 1
476
+ pageInfo.size = val
477
+ loadData(true)
478
+ }
479
+
480
+ /**
481
+ * 处理分页工具中current变化
482
+ * @param val
483
+ */
484
+ function handleCurrentChange(val: number) {
485
+ if (pageInfo.current !== val) {
486
+ pageInfo.current = val
487
+ loadData(false)
488
+ }
489
+ }
490
+
491
+ /**
492
+ * 处理行展开
493
+ * @param list
494
+ * @param pIndexList
495
+ */
496
+ function handelTreeIndex(list: any[], pIndexList: number[]) {
497
+ let tempList = []
498
+ if (list && list.length > 0) {
499
+ list.map((item, i) => {
500
+ treeIndexList.push([...pIndexList, i])
501
+ tempList = item[treeProps.children] as any[]
502
+ if (tempList && tempList.length > 0) {
503
+ handelTreeIndex(tempList, [i])
504
+ }
505
+ })
506
+ }
507
+ }
508
+
509
+ /**
510
+ * 真正调用查询的接口
511
+ * @param isInit
512
+ */
513
+ async function loadData(isInit: Boolean) {
514
+ if (!props.tableConfig.fetch) {
515
+ loadingStatus.value = 2
516
+ // if (props.modelValue) {
517
+ // tableData.splice(0, tableData.length, ...props.modelValue)
518
+ // }
519
+ return false
520
+ }
521
+ if (loadingStatus.value === 1 || loading.value) return false
522
+ loadingStatus.value = 1
523
+ loading.value = true
524
+ tableData.splice(0, tableData.length)
525
+ if (isInit) {
526
+ pageInfo.current = 1
527
+ }
528
+ let postData = await getListQueryData()
529
+ // 这里处理一下外部数据格式化
530
+ if (props.tableConfig?.toolbar?.formConfig?.beforeRequest) {
531
+ postData = props.tableConfig?.toolbar?.formConfig?.beforeRequest(JSON.parse(JSON.stringify(postData))) || postData
532
+ }
533
+ const dataPage = (await props.tableConfig.fetch(postData)) as any
534
+ try {
535
+ if (props.isPager) {
536
+ pageInfo.total = dataPage?.total * 1 || 0
537
+ pageInfo.current = dataPage?.current || 1
538
+ tableData.push(...(dataPage?.records || null))
539
+ } else {
540
+ tableData.push(...(dataPage?.records || dataPage || null))
541
+ }
542
+ if (isInit) {
543
+ // 初始化完毕后,调用一次父类更新
544
+ // emits('update:modelValue', tableData)
545
+ }
546
+ // 如果是树形结构
547
+ if (props.type === 'expand') {
548
+ treeIndexList.splice(0, treeIndexList.length)
549
+ handelTreeIndex(tableData, [])
550
+ }
551
+ listLoading.value = false
552
+ nextTick(() => {
553
+ // 遍历以及选中当前页面数据
554
+ refreshTableSelect()
555
+ })
556
+ } catch (e) {
557
+ // eslint-disable-next-line no-console
558
+ console.log('error: ', e)
559
+ }
560
+ loadingStatus.value = 2
561
+ loading.value = false
562
+ }
563
+
564
+ /**
565
+ * 渲染列表的选中项
566
+ */
567
+ function refreshTableSelect() {
568
+ if (tableData && tableData.length > 0 && props.type === 'selection') {
569
+ tableData.map((item: any) => {
570
+ elPlusTableRef.value!.toggleRowSelection(
571
+ item,
572
+ allSelectRowList.some((i) => i[props.rowKey] === item[props.rowKey])
573
+ )
574
+ })
575
+ }
576
+ }
577
+
578
+ /**
579
+ * 重新加载
580
+ */
581
+ async function reload(isTab: boolean = false) {
582
+ await loadData(true)
583
+ // 这里判断一下Tab
584
+ if (!isTab && props.tableConfig.tabConf && props.tableConfig.tabConf.fetch) {
585
+ tabStatic.value = await props.tableConfig.tabConf.fetch(Object.assign({}, await getListQueryData(), props.tableConfig.tabConf.queryMap))
586
+ loadingTab.value = false
587
+ }
588
+ return tableData
589
+ }
590
+
591
+ /**
592
+ * 处理顶部条件表单筛选
593
+ */
594
+ function handelTopQuery() {
595
+ topQueryData.value = cloneDeep(tableHeaderRef.value.getData())
596
+ reload()
597
+ }
598
+
599
+ /**
600
+ * 初始化列
601
+ */
602
+ function initCol() {
603
+ tableHeaderRef.value?.initCol()
604
+ }
605
+
606
+ // 监听父类数据变更
607
+ watch(
608
+ () => props.modelValue,
609
+ (data) => {
610
+ // console.log('data: ', JSON.parse(JSON.stringify(data)))
611
+ if (!props.tableConfig.fetch) {
612
+ if (JSON.parse(JSON.stringify(data)) !== JSON.parse(JSON.stringify(tableData))) {
613
+ loadingStatus.value = 2
614
+ tableData.splice(0, tableData.length, ...(data || []))
615
+ }
616
+ }
617
+ },
618
+ { deep: true }
619
+ )
620
+
621
+ watch(
622
+ () => props.selectList,
623
+ (val: any[]) => {
624
+ allSelectRowList.splice(0, allSelectRowList.length, ...val)
625
+ // 遍历以及选中当前页面数据
626
+ refreshTableSelect()
627
+ },
628
+ { deep: true }
629
+ )
630
+
631
+ onMounted(() => {
632
+ reload()
633
+ })
634
+
635
+ defineExpose({ reload, tableData, changeSelect, resetSelect, initCol })
636
+ </script>
637
+ <style lang="scss">
638
+ .el-plus-table-content {
639
+ background-color: #ffffff;
640
+ border-radius: 5px;
641
+ padding: 10px;
642
+ width: 100%;
643
+ max-height: 100%;
644
+ overflow: hidden;
645
+ display: flex;
646
+ flex-direction: column;
647
+ position: relative;
648
+ .th-required {
649
+ position: relative;
650
+ &::before {
651
+ content: '*';
652
+ position: absolute;
653
+ left: -10px;
654
+ font-size: 16px;
655
+ top: 2px;
656
+ color: #ff3b30;
657
+ font-weight: bold;
658
+ }
659
+ }
660
+ .select-items {
661
+ display: flex;
662
+ flex-wrap: wrap;
663
+ align-items: center;
664
+
665
+ .title {
666
+ font-size: 18px;
667
+ font-weight: bold;
668
+ margin-right: 20px;
669
+ }
670
+
671
+ .select-item {
672
+ margin: 5px 10px 5px 0;
673
+
674
+ &:last-child {
675
+ margin-right: 0;
676
+ }
677
+ }
678
+ }
679
+
680
+ .table-tabs-panel {
681
+ margin-bottom: 16px;
682
+ }
683
+ .summary-row {
684
+ width: 100%;
685
+ background-color: var(--el-table-row-hover-bg-color);
686
+ color: var(--el-table-text-color);
687
+ padding: 16px 20px;
688
+ line-height: 24px;
689
+ height: 40px;
690
+ display: flex;
691
+ position: relative;
692
+ .summary-item {
693
+ display: flex;
694
+ align-items: center;
695
+ margin-right: 30px;
696
+ & > span {
697
+ margin-right: 20px;
698
+ }
699
+ }
700
+ }
701
+
702
+ .el-plus-table-main {
703
+ width: 100%;
704
+ flex: 1;
705
+ max-height: 100%;
706
+ display: flex;
707
+ flex-direction: column;
708
+ .el-table {
709
+ .cell {
710
+ display: flex;
711
+ }
712
+ .is-center {
713
+ .cell {
714
+ align-items: center;
715
+ justify-content: center;
716
+ }
717
+ }
718
+ }
719
+ }
720
+
721
+ .pager-statistic {
722
+ width: 100%;
723
+ position: fixed;
724
+ height: 32px;
725
+ line-height: 32px;
726
+ bottom: 0;
727
+ text-align: right;
728
+ min-width: 900px;
729
+
730
+ .statistic-item {
731
+ display: inline-block;
732
+ }
733
+ }
734
+
735
+ .el-cascader__label {
736
+ width: 300px !important;
737
+ }
738
+
739
+ .bottom-page-static-info {
740
+ display: flex;
741
+ flex-wrap: wrap;
742
+ justify-content: center;
743
+ align-items: center;
744
+ min-height: 41px;
745
+ margin-top: 10px;
746
+
747
+ .page-info {
748
+ margin-right: 30px;
749
+ }
750
+ }
751
+
752
+ .common-list-export-excel {
753
+ background: #20a0ff;
754
+ text-decoration: none;
755
+ color: #ffffff;
756
+ font-size: 12px;
757
+ height: 29px;
758
+ line-height: 30px;
759
+ display: block;
760
+ margin-top: 5px;
761
+ border-radius: 3px;
762
+ padding: 0 10px;
763
+ }
764
+
765
+ .common-list-export-excel:hover {
766
+ background: #58b6ff;
767
+ }
768
+
769
+ .el-table__empty-block {
770
+ height: auto !important;
771
+ }
772
+ }
773
+ </style>