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