# BiuTable 表格

# 基础用法

  • tb-height可以设置表格的高度,max-height可设置最大高度
  • biu-table默认是开启虚拟表格的,如果你想关闭只需要配置virtual=false
  • 自定义渲染可以使用render或者插槽两种方式,插槽优先级更高
<template>
    <div>
        <el-button @click="add(10)">添加10条数据</el-button>
        <el-button @click="add(100)">添加100条数据</el-button>
        <el-button @click="add(10000)">添加10000条数据</el-button>
        <el-button @click="tableData = []">清空数据</el-button>
        <el-button @click="Immutable = !Immutable"
            >{{ Immutable ? '取消' : '设置' }}固定高</el-button
        >
        <el-button @click="virtual = !virtual"
            >{{ virtual ? '关闭' : '开启' }}虚拟表格</el-button
        >
        <biu-table
            :loading="loading"
            :columns="columns"
            :virtual="virtual"
            :table-data="tableData"
            :tb-height="Immutable ? 300 : undefined"
            :max-height="500"
        >
            <!-- 总数量自定义显示 -->
            <template slot="number" slot-scope="{ row, col }">
                custom-{{ row[col.id] }}
            </template>
        </biu-table>
    </div>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import { tableColumnType } from 'calm-harbin/types/biu-table'

@Component
export default class BiuTableBase extends Vue {
    Immutable = false // 为true时固定高度

    virtual = true // 开启虚拟表格

    tableData: any[] = []

    loading = false

    get columns(): tableColumnType[] {
        return [
            {
                label: '商品编码',
                id: 'packing'
            },
            {
                label: '商品名称',
                id: 'goodsName',
                width: 150
            },
            {
                label: '总数量',
                id: 'number'
            },
            {
                label: '总重量(KG)',
                id: 'weight',
                // 使用render实现自定义渲染
                render: (h, { row, col }) => <div>custom-{row[col.id]}</div>
            },
            {
                label: '总体积(m³)',
                id: 'volume'
            },
            {
                label: '长(m)',
                id: 'length'
            },
            {
                label: '宽(m)',
                id: 'width'
            },
            {
                label: '高(m)',
                id: 'height'
            },
            {
                label: '净重',
                id: 'netWeight'
            },
            {
                label: '备注',
                id: 'remark',
                width: 200
            }
        ]
    }

    /**
     * 添加数据
     */
    add(num: number) {
        this.loading = true
        const length = this.tableData.length

        setTimeout(() => {
            new Array(num).fill('').forEach((_item, index) => {
                this.tableData.push({
                    id: length + index,
                    packing: 'apple',
                    goodsName: '苹果苹果苹果苹果苹果苹果苹果',
                    number: ~~(Math.random() * 1000),
                    remark: '',
                    weight: 10,
                    volume: 1000,
                    length: 10,
                    width: 10,
                    height: 10,
                    netWeight: 99.99
                })
            })
            this.loading = false
        }, 1000)
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
显示代码

# 可编辑表格

  • 给组件配置editable=true则开启可编辑功能。
  • 编辑模式默认使用的是 显示编辑按钮,一共提供 3 种编辑模式。
  • 给组件配置edit-action=false可以关闭 添加/删除 按钮
  • columns某一项配置了editable=true,则该列居有编辑功能,默认会提供一个 text 输入框。如果你想自定义内容,你可以使用editRender或者使用 slot。
  • columns配置了required=true后表头会变红色,可以用来表示必填,但是校验功能需要自行实现。
  • 可以通过plus来自定义插入的数据
<template>
    <div>
        <biu-form-item
            v-model="mode"
            form-type="select"
            :options="modeOptions"
            size="mini"
        ></biu-form-item>

        <el-button @click="editAction.show = !editAction.show"
            >{{ editAction.show ? '隐藏' : '显示' }}加减行按钮</el-button
        >
        <biu-table
            :columns="columns"
            :table-data="tableData"
            editable
            :max-height="300"
            :edit-config="editConfig"
            :edit-action="editAction"
            :plus="plus"
        >
            <!-- 宽度编辑状态下显示 -->
            <template slot="width-edit" slot-scope="{ row, col, $index }">
                <el-input-number
                    v-model="row[col.id]"
                    style="width: 100%"
                    :min="0"
                    :precision="2"
                    :controls="false"
                    size="mini"
                    @change="() => setVolume(row, $index)"
                ></el-input-number>
            </template>
        </biu-table>
    </div>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import { tableColumnType } from 'calm-harbin/types/biu-table'
import Decimal from 'decimal.js'

@Component
export default class BiuTableBase extends Vue {
    tableData: any[] = [
        {
            packing: 'apple',
            goodsName: '苹果',
            number: 999,
            weight: 666,
            volume: 888,
            length: 10,
            width: 10,
            height: 10,
            netWeight: 500,
            remark: '大苹果'
        },
        {
            goodsName: '橘子'
        },
        {
            goodsName: '梨'
        }
    ]

    packingOptions = [
        {
            label: '苹果apple',
            value: 'apple'
        },
        {
            label: '橘子orange',
            value: 'orange'
        },
        {
            label: '梨pear',
            value: 'pear'
        }
    ]

    mode = '1'
    modeOptions = [
        {
            label: '编辑按钮',
            value: '1'
        },
        {
            label: '点击行',
            value: '2'
        },
        {
            label: '点击单元格',
            value: '3'
        }
    ]

    editAction = {
        fixed: 'left',
        show: true
    }

    /**
     * 表格列
     */
    get columns(): tableColumnType[] {
        return [
            {
                label: '商品编码',
                id: 'packing',
                editable: true,
                // 因为要显示label,所以使用render
                render: (h, { row, col }) => (
                    <div>
                        {this.packingOptions.find(
                            (i) => i.value === row[col.id]
                        )?.label || row[col.id]}
                    </div>
                ),
                editRender: (h, { row, col }) => (
                    <biu-form-item
                        formType="select"
                        style="width: 100%"
                        v-model={row[col.id]}
                        options={this.packingOptions}
                        size="mini"
                    ></biu-form-item>
                )
            },
            {
                label: '商品名称',
                id: 'goodsName',
                width: 150,
                editable: true
            },
            {
                label: '总数量',
                id: 'number',
                editable: true,
                required: true
            },
            {
                label: '总重量(KG)',
                id: 'weight',
                editable: true,
                editRender: (h, { row, col }) => (
                    <el-input-number
                        style="width: 100%"
                        v-model={row[col.id]}
                        min={0}
                        precision={3}
                        controls={false}
                        size="mini"
                    ></el-input-number>
                )
            },
            {
                label: '总体积(m³)',
                id: 'volume'
            },
            {
                label: '长(cm)',
                id: 'length',
                editable: true,
                editRender: (h, { row, col, $index }) => (
                    <el-input-number
                        style="width: 100%"
                        v-model={row[col.id]}
                        min={0}
                        precision={2}
                        controls={false}
                        size="mini"
                        onchange={() => this.setVolume(row, $index)}
                    ></el-input-number>
                )
            },
            {
                label: '宽(cm)',
                id: 'width',
                editable: true
            },
            {
                label: '高(cm)',
                id: 'height',
                editable: true,
                editRender: (h, { row, col, $index }) => (
                    <el-input-number
                        style="width: 100%"
                        v-model={row[col.id]}
                        min={0}
                        precision={2}
                        controls={false}
                        size="mini"
                        onchange={() => this.setVolume(row, $index)}
                    ></el-input-number>
                )
            },
            {
                label: '净重',
                id: 'netWeight'
            },
            {
                label: '备注',
                id: 'remark',
                width: 200
            }
        ]
    }

    /**
     * 触发模式
     */
    get editConfig() {
        if (this.mode === '2') {
            return { trigger: 'click', mode: 'row' }
        }
        if (this.mode === '3') {
            return { trigger: 'click', mode: 'cell' }
        }
        return { trigger: 'manual', mode: 'row' }
    }

    /**
     * 改变体积
     */
    setVolume(row: any, $index: number) {
        const volume = new Decimal(row.length || 0)
            .times(row.width || 0)
            .times(row.height || 0)
            .dividedBy(1000000)
            .toNumber()

        /**
         * 这里不能使用:this.tableData[$index] = { ...row, volume }
         * 因为vue监听不到tableData的改变,需要改变tableData才会使页面渲染更新
         */
        this.tableData = [
            ...this.tableData.slice(0, $index),
            { ...row, volume },
            ...this.tableData.slice($index + 1)
        ]
    }

    /**
     * 可以通过这个方式自定义设置插入的数据
     * @param { Object } row 默认插入的数据
     */
    plus(row: any) {
        return {
            ...row,
            packing: 'apple'
        }
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
显示代码

# 可筛选表格

  • 给组件配置show-header-filter=true则开启表头筛选功能。

提示

关于 表头筛选的表单项配置 formType 可以查看 BiuForm 组件

警告

开启表头筛选后必须配置v-model,因为你肯定需要获取筛选的条件。

<template>
    <biu-table
        v-model="form"
        :columns="columns"
        :table-data="tableData"
        show-header-filter
        :max-height="500"
        @search="search"
    >
    </biu-table>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import { tableColumnType } from 'calm-harbin/types/biu-table'

@Component
export default class BiuTableBase extends Vue {
    form: any = {
        goodsName: ''
    }
    tableData: any[] = []

    packingOptions = [
        {
            label: '苹果apple',
            value: 'apple'
        },
        {
            label: '橘子orange',
            value: 'orange'
        },
        {
            label: '梨pear',
            value: 'pear'
        }
    ]

    get columns(): tableColumnType[] {
        return [
            {
                formType: 'slot',
                label: '商品编码',
                id: 'packing',
                // 因为要显示label,所以使用render
                render: (h, { row, col }) => (
                    <div>
                        {this.packingOptions.find(
                            (i) => i.value === row[col.id]
                        )?.label || row[col.id]}
                    </div>
                ),
                formAttr: {
                    render: (h, { col }) => (
                        <biu-form-item
                            formType="select"
                            style="width: 100%"
                            v-model={this.form[col.id]}
                            options={this.packingOptions}
                            size="mini"
                        ></biu-form-item>
                    )
                }
            },
            {
                formType: 'input',
                label: '商品名称',
                id: 'goodsName',
                width: 150
            },
            {
                formType: 'input',
                label: '总数量',
                id: 'number'
            },
            {
                formType: 'input',
                label: '总重量(KG)',
                id: 'weight',
                // 使用render实现自定义渲染
                render: (h, { row, col }) => <div>custom-{row[col.id]}</div>
            },
            {
                formType: 'input',
                label: '总体积(m³)',
                id: 'volume'
            },
            {
                label: '长(m)',
                id: 'length'
            },
            {
                label: '宽(m)',
                id: 'width'
            },
            {
                label: '高(m)',
                id: 'height'
            },
            {
                label: '净重',
                id: 'netWeight'
            },
            {
                label: '备注',
                id: 'remark',
                width: 200
            }
        ]
    }

    created() {
        this.add(5)
    }

    /**
     * 添加数据
     */
    add(num: number) {
        const length = this.tableData.length

        new Array(num).fill('').forEach((_item, index) => {
            this.tableData.push({
                id: length + index,
                packing: ['apple', 'orange', 'pear'][~~(Math.random() * 3)],
                goodsName: ['苹果', '橘子', '梨'][~~(Math.random() * 3)],
                number: ~~(Math.random() * 1000),
                remark: '',
                weight: 10,
                volume: 1000,
                length: 10,
                width: 10,
                height: 10,
                netWeight: 99.99
            })
        })
    }

    /**
     * 搜索
     */
    search() {
        // form含有最新的数据,可以用来自行实现过滤逻辑
        console.log(this.form)
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
显示代码

# 不固定的合计

  • 给组件配置custom-show-summary=true则开启合计功能。会自动将最后一行序号变为合计,如果你想自定义合计文本,可以使用sum-text来配置

提示

如果要使用不固定的合计功能,其原理是自行计算好数据放入表格最后一项。可以使用summary来帮助你计算。
summary的使用方法详见文档方法部分。

<template>
    <biu-table
        tb-height="350"
        :columns="columns"
        :table-data="tableData"
        custom-show-summary
    ></biu-table>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import { tableColumnType } from 'calm-harbin/types/biu-table'
import { summary } from 'calm-harbin'

@Component
export default class BiuTableSummary extends Vue {
    tableData: any[] = []

    packingOptions = [
        {
            label: '苹果apple',
            value: 'apple'
        },
        {
            label: '橘子orange',
            value: 'orange'
        },
        {
            label: '梨pear',
            value: 'pear'
        }
    ]

    get columns(): tableColumnType[] {
        return [
            {
                formType: 'slot',
                label: '商品编码',
                id: 'packing',
                // 因为要显示label,所以使用render
                render: (h, { row, col }) => (
                    <div>
                        {this.packingOptions.find(
                            (i) => i.value === row[col.id]
                        )?.label || row[col.id]}
                    </div>
                )
            },
            {
                formType: 'input',
                label: '商品名称',
                id: 'goodsName',
                width: 150
            },
            {
                formType: 'input',
                label: '总数量',
                id: 'number'
            },
            {
                formType: 'input',
                label: '总重量(KG)',
                id: 'weight',
                // 使用render实现自定义渲染
                render: (h, { row, col }) => <div>custom-{row[col.id]}</div>
            },
            {
                formType: 'input',
                label: '总体积(m³)',
                id: 'volume'
            },
            {
                label: '长(m)',
                id: 'length'
            },
            {
                label: '宽(m)',
                id: 'width'
            },
            {
                label: '高(m)',
                id: 'height'
            },
            {
                label: '净重',
                id: 'netWeight'
            },
            {
                label: '备注',
                id: 'remark',
                width: 200
            }
        ]
    }

    created() {
        this.add(5)
    }

    /**
     * 添加数据
     */
    add(num: number) {
        const length = this.tableData.length

        new Array(num).fill('').forEach((_item, index) => {
            this.tableData.push({
                id: length + index,
                packing: ['apple', 'orange', 'pear'][~~(Math.random() * 3)],
                goodsName: ['苹果', '橘子', '梨'][~~(Math.random() * 3)],
                number: ~~(Math.random() * 1000),
                remark: '',
                weight: 10,
                volume: 1000,
                length: 10,
                width: 10,
                height: 10,
                netWeight: 99.99
            })
        })

        // 计算合计数据
        const total = summary(this.tableData, {
            number: 0,
            weight: 0,
            volume: 0,
            length: 0,
            width: 0,
            height: 0,
            netWeight: 0
        })
        this.tableData.push(total)
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
显示代码

# 固定的合计

  • 给组件配置show-summary=true则开启合计功能。使用summary-method来自定义控制合计显示的内容
<template>
    <biu-table
        :columns="columns"
        :table-data="tableData"
        show-summary
        :summary-method="summaryMethod"
        :virtual="false"
        tb-height="200"
    ></biu-table>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import { tableColumnType } from 'calm-harbin/types/biu-table'
import { summary } from 'calm-harbin'

@Component
export default class BiuTableSummary extends Vue {
    tableData: any[] = []

    packingOptions = [
        {
            label: '苹果apple',
            value: 'apple'
        },
        {
            label: '橘子orange',
            value: 'orange'
        },
        {
            label: '梨pear',
            value: 'pear'
        }
    ]

    get columns(): tableColumnType[] {
        return [
            {
                formType: 'slot',
                label: '商品编码',
                id: 'packing',
                // 因为要显示label,所以使用render
                render: (h, { row, col }) => (
                    <div>
                        {this.packingOptions.find(
                            (i) => i.value === row[col.id]
                        )?.label || row[col.id]}
                    </div>
                )
            },
            {
                formType: 'input',
                label: '商品名称',
                id: 'goodsName',
                width: 150
            },
            {
                formType: 'input',
                label: '总数量',
                id: 'number'
            },
            {
                formType: 'input',
                label: '总重量(KG)',
                id: 'weight',
                // 使用render实现自定义渲染
                render: (h, { row, col }) => <div>custom-{row[col.id]}</div>
            },
            {
                formType: 'input',
                label: '总体积(m³)',
                id: 'volume'
            },
            {
                label: '长(m)',
                id: 'length'
            },
            {
                label: '宽(m)',
                id: 'width'
            },
            {
                label: '高(m)',
                id: 'height'
            },
            {
                label: '净重',
                id: 'netWeight'
            },
            {
                label: '备注',
                id: 'remark',
                width: 200
            }
        ]
    }

    created() {
        this.add(5)
    }

    /**
     * 添加数据
     */
    add(num: number) {
        const length = this.tableData.length

        new Array(num).fill('').forEach((_item, index) => {
            this.tableData.push({
                id: length + index,
                packing: ['apple', 'orange', 'pear'][~~(Math.random() * 3)],
                goodsName: ['苹果', '橘子', '梨'][~~(Math.random() * 3)],
                number: ~~(Math.random() * 1000),
                remark: '',
                weight: 10,
                volume: 1000,
                length: 10,
                width: 10,
                height: 10,
                netWeight: 99.99
            })
        })
    }

    /**
     * 自定义合计
     */
    summaryMethod() {
        const defaultTotal = {
            number: 0,
            weight: 0,
            volume: 0,
            length: 0,
            width: 0,
            height: 0,
            netWeight: 0
        }
        const total = summary(this.tableData, defaultTotal)
        const totalData = this.columns.map((item) => total[item.id] ?? '')

        return [['汇总', ...totalData]]
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
显示代码

# 单选/多选

多选

  • 配置selection=true可以开启多选功能,同时传入multipleSelection来控制勾选的数据
<template>
    <biu-table
        :columns="columns"
        :table-data="tableData"
        selection
        :multiple-selection.sync="multipleSelection"
    ></biu-table>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import { tableColumnType } from 'calm-harbin/types/biu-table'

@Component
export default class BiuTableSelection extends Vue {
    tableData: any[] = []

    packingOptions = [
        {
            label: '苹果apple',
            value: 'apple'
        },
        {
            label: '橘子orange',
            value: 'orange'
        },
        {
            label: '梨pear',
            value: 'pear'
        }
    ]

    // 这里记录了勾选的数据
    multipleSelection: any[] = []

    get columns(): tableColumnType[] {
        return [
            {
                formType: 'slot',
                label: '商品编码',
                id: 'packing',
                // 因为要显示label,所以使用render
                render: (h, { row, col }) => (
                    <div>
                        {this.packingOptions.find(
                            (i) => i.value === row[col.id]
                        )?.label || row[col.id]}
                    </div>
                )
            },
            {
                formType: 'input',
                label: '商品名称',
                id: 'goodsName',
                width: 150
            },
            {
                formType: 'input',
                label: '总数量',
                id: 'number'
            },
            {
                formType: 'input',
                label: '总重量(KG)',
                id: 'weight',
                // 使用render实现自定义渲染
                render: (h, { row, col }) => <div>custom-{row[col.id]}</div>
            },
            {
                formType: 'input',
                label: '总体积(m³)',
                id: 'volume'
            },
            {
                label: '长(m)',
                id: 'length'
            },
            {
                label: '宽(m)',
                id: 'width'
            },
            {
                label: '高(m)',
                id: 'height'
            },
            {
                label: '净重',
                id: 'netWeight'
            },
            {
                label: '备注',
                id: 'remark',
                width: 200
            }
        ]
    }

    created() {
        this.add(5)
    }

    /**
     * 添加数据
     */
    add(num: number) {
        const length = this.tableData.length

        new Array(num).fill('').forEach((_item, index) => {
            this.tableData.push({
                id: length + index,
                packing: ['apple', 'orange', 'pear'][~~(Math.random() * 3)],
                goodsName: ['苹果', '橘子', '梨'][~~(Math.random() * 3)],
                number: ~~(Math.random() * 1000),
                remark: '',
                weight: 10,
                volume: 1000,
                length: 10,
                width: 10,
                height: 10,
                netWeight: 99.99
            })
        })
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
显示代码

# 自定义展开

  • 使用expandRender配置展开内容
<template>
    <biu-table
        :columns="columns"
        :table-data="tableData"
        :expand-render="expandRender"
    ></biu-table>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import {
    tableColumnType,
    expandRenderPropType
} from 'calm-harbin/types/biu-table'

@Component
export default class BiuTableExpandRender extends Vue {
    tableData: any[] = []

    packingOptions = [
        {
            label: '苹果apple',
            value: 'apple'
        },
        {
            label: '橘子orange',
            value: 'orange'
        },
        {
            label: '梨pear',
            value: 'pear'
        }
    ]

    get columns(): tableColumnType[] {
        return [
            {
                formType: 'slot',
                label: '商品编码',
                id: 'packing',
                // 因为要显示label,所以使用render
                render: (h, { row, col }) => (
                    <div>
                        {this.packingOptions.find(
                            (i) => i.value === row[col.id]
                        )?.label || row[col.id]}
                    </div>
                )
            },
            {
                formType: 'input',
                label: '商品名称',
                id: 'goodsName',
                width: 150
            },
            {
                formType: 'input',
                label: '总数量',
                id: 'number'
            },
            {
                formType: 'input',
                label: '总重量(KG)',
                id: 'weight',
                // 使用render实现自定义渲染
                render: (h, { row, col }) => <div>custom-{row[col.id]}</div>
            },
            {
                formType: 'input',
                label: '总体积(m³)',
                id: 'volume'
            },
            {
                label: '长(m)',
                id: 'length'
            },
            {
                label: '宽(m)',
                id: 'width'
            },
            {
                label: '高(m)',
                id: 'height'
            },
            {
                label: '净重',
                id: 'netWeight'
            },
            {
                label: '备注',
                id: 'remark',
                width: 200
            }
        ]
    }

    /**
     * 控制展开渲染内容
     */
    expandRender(h: any, { row, $index }: expandRenderPropType) {
        return (
            <div style="padding-left: 80px;">{$index + 1}行,内容是 {JSON.stringify(row)}
            </div>
        )
    }

    created() {
        this.add(5)
    }

    /**
     * 添加数据
     */
    add(num: number) {
        const length = this.tableData.length

        new Array(num).fill('').forEach((_item, index) => {
            this.tableData.push({
                id: `${length + index}`,
                packing: ['apple', 'orange', 'pear'][~~(Math.random() * 3)],
                goodsName: ['苹果', '橘子', '梨'][~~(Math.random() * 3)],
                number: ~~(Math.random() * 1000),
                remark: '',
                weight: 10,
                volume: 1000,
                length: 10,
                width: 10,
                height: 10,
                netWeight: 99.99
            })
        })
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
显示代码

# 自定义渲染 Render/slot

  • 提供了两种自定义渲染的方式,render 函数和插槽。
<template>
    <biu-table
        v-model="form"
        :columns="columns"
        :table-data="tableData"
        show-header-filter
        :max-height="500"
        @search="search"
    >
        <!-- 头部插槽 -->
        <template slot="header-goodsName" slot-scope="{ col }">
            <span style="color: #409eff">{{ col.label }}</span>
        </template>
        <!-- 筛选框插槽 -->
        <template slot="form-goodsName" slot-scope="{ col }">
            <el-input
                v-model="form[col.id]"
                type="number"
                size="mini"
            ></el-input>
        </template>
        <!-- 单元格插槽 -->
        <template slot="goodsName" slot-scope="{ row, col, $index }">
            {{ row[col.id] }} - {{ $index }}
        </template>
    </biu-table>
</template>

<script lang="tsx">
import { Vue, Component } from 'vue-property-decorator'
import { tableColumnType } from 'calm-harbin/types/biu-table'

@Component
export default class BiuTableBase extends Vue {
    form: any = {
        goodsName: ''
    }
    tableData: any[] = []

    packingOptions = [
        {
            label: '苹果apple',
            value: 'apple'
        },
        {
            label: '橘子orange',
            value: 'orange'
        },
        {
            label: '梨pear',
            value: 'pear'
        }
    ]

    get columns(): tableColumnType[] {
        return [
            {
                formType: 'slot',
                label: '商品编码',
                id: 'packing',
                headRender: (h, col) => {
                    return <span style="color: #409eff">{col.label}</span>
                },
                // 因为要显示label,所以使用render
                render: (h, { row, col }) => (
                    <div>
                        {this.packingOptions.find(
                            (i) => i.value === row[col.id]
                        )?.label || row[col.id]}
                    </div>
                ),
                formAttr: {
                    render: (h, col) => {
                        return (
                            <biu-form-item
                                formType="select"
                                style="width: 100%"
                                v-model={this.form[col.id]}
                                options={this.packingOptions}
                                size="mini"
                            ></biu-form-item>
                        )
                    }
                }
            },
            {
                formType: 'slot',
                label: '商品名称',
                id: 'goodsName',
                width: 150
            },
            {
                formType: 'input',
                label: '总数量',
                id: 'number'
            }
        ]
    }

    created() {
        this.add(5)
    }

    /**
     * 添加数据
     */
    add(num: number) {
        const length = this.tableData.length

        new Array(num).fill('').forEach((_item, index) => {
            this.tableData.push({
                id: length + index,
                packing: ['apple', 'orange', 'pear'][~~(Math.random() * 3)],
                goodsName: ['苹果', '橘子', '梨'][~~(Math.random() * 3)],
                number: ~~(Math.random() * 1000),
                remark: '',
                weight: 10,
                volume: 1000,
                length: 10,
                width: 10,
                height: 10,
                netWeight: 99.99
            })
        })
    }

    /**
     * 搜索
     */
    search() {
        // form含有最新的数据,可以用来自行实现过滤逻辑
        console.log(this.form)
    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
显示代码

# 属性

参数 说明
必填
类型 默认值
columns 表格配置项 tableColumnType[]
value / v-model 筛选条件绑定值(当showHeaderFilter=true时必填) objType
table-data 表格显示的数据(支持.sync) objType[] []
rowId 每一行的唯一值 string id
loading 控制表格是否处于加载状态 boolean false
tb-height 表格的高度,设置高度后,超过高度的数据会在表格内部滚动 number
selection 是不是多选 boolean false
show-summary 是否显示汇总(会将最后一行认为是汇总数据,请自行计算汇总数据并插入tableData的最后一行) boolean false
expand-render 自定义展开功能渲染
(h: any, scope:scopeType) => VNode
table-postfix-options 表格右侧操作按钮 tablePostfixOptionsType[]
virtual 是否为虚拟表格 boolean true
editable 是否为可编辑表格(可编辑表格会强制virtual=true) boolean false
editAction 是否显示新增/删除一行按钮(仅可编辑表格生效),同时会传入给 el-table-column objType false
plus 自定义添加一行插入的数据(仅editAction.show=true生效) boolean false
show-header-filter 是否显示表头筛选功能 boolean false
show-index 是否显示索引列 boolean true

# 事件

事件名 说明 类型
search 搜索,表头筛选改变时触发 () => void

# 方法

方法名 说明 类型
headerDragend 表格重新渲染,同 element 的 doLayout () => void

# 插槽

插槽名 说明 类型
header-[id] 头部插槽 { col, $index, $columnIndex }
form-[id] 表头筛选插槽 { col, $index, $columnIndex }
[id] 单元格插槽 { row, col, $index }
edit-[id] 编辑时插槽 { row, col, $index }