由于管理系统经常会用到表格,而 iview 本身是没有合并 table 和 分页 以及 搜索条件 为一个组件调用,频繁的书写,不利于维护,因此急需一个组件去实现业务。
a-* 的组件来源于vue-ant-design
table封装
<template>
<a-spin :spinning="spinning">
<div class="tablePage">
<div class="searchBox">
<div class="tablesearch">
<slot name="search-option">
<Form
:model="data"
:label-width="table.searchFormWidth || 64"
class="search-option"
label-position="left">
<Row :gutter="32">
<Col
v-for="( item, index ) in table.searchForm"
:span="item.span || '8'"
:key="`srachOption-${index}`"
v-if="
table.searchForm.length < rowDataLength + 1
? true
: upDownSearchOption
? index < rowDataLength
: true">
<FormItem
:label="item.placeholder"
v-if=" item.type === 'input' ">
<Input
v-model="table.search[ item.key ]"
:maxlength="50" :style="{ width: '100%' }"
:placeholder="`请输入${ item.placeholder }`"/>
</FormItem>
<FormItem
:label="item.placeholder"
v-if=" item.type === 'select' ">
<Select
:filterable="item.filterable || false"
:multiple="item.mul || false"
v-model="table.search[ item.key ]"
:clearable="item.clearable || true"
:style="{ width: '100%' }"
:placeholder="`请选择${ item.placeholder }`">
<Option
v-for="( optionItem, optionIndex ) in item.options"
:value="optionItem[ item.valueKey || 'value' ]"
:key="`option-${ optionIndex }`">
<slot name="select-option">{{optionItem[ item.nameKey || 'label' ]}}</slot>
</Option>
</Select>
</FormItem>
<FormItem
:label="item.placeholder"
v-if=" item.type === 'datepicker' ">
<DatePicker
:type="item.dateType || 'date'"
v-model="table.search[ item.dateKey || `dateKey${index}` ]"
:options="item.options || {}"
:placeholder="`请选择${ item.placeholder || '' }`"
:style="{ width: '100%' }"
:format="
item.format || (['datetime','datetimeerange'].includes( item.dateType )
? 'yyyy-MM-dd HH:mm:ss'
: ['year'].includes( item.dateType )
? 'yyyy'
: ['month'].includes( item.dateType )
? 'yyyy-MM'
: 'yyyy-MM-dd')"
:placement="item.placement || 'bottom-start'"
@on-change="dateChange( $event, item.key || item.key1, item.key2 || null )"/>
</FormItem>
</Col>
</Row>
</Form>
</slot>
<div class="srarch-action"
:class="[
table.searchForm.length < rowDataLength + 1
? ''
: upDownSearchOption
? 'up'
: 'down'
]">
<slot name="action">
<a-button :type="table.btn.searchType || 'primary'" style="margin-right: 8px;" @click="onload">搜索</a-button>
<a-button :type="table.btn.resetType || 'default'" @click="reset">重置</a-button>
<a-button class="upDownBtn" type="link" v-if="table.searchForm.length > rowDataLength" @click="upDownSearchOption = !upDownSearchOption">
{{ upDownSearchOption? '展开': '收起' }}
<a-icon type="double-left" />
</a-button>
</slot>
</div>
</div>
</div>
<slot name="table-action"></slot>
<Table
:border="tableBorder"
@on-expand="onExpand"
stripe
:columns="table.columns"
:data="data[table.dataListKey]"
@on-select="select"
@on-select-all="selectAll"
@on-selection-change="selectionChange"/>
<div class="table-page" v-if="showPage">
<slot name="msg"><p></p></slot>
<!-- small page -->
<Page
v-if="pageSize != 'default'"
:total="data[totalKey]"
show-elevator
show-total
:page-size-opts="[10, 20, 30, 40]"
:page-size="table.search[pageSizeKey]"
:show-sizer="showSizer"
size="small"
:current="table.search[pageIndexKey]"
@on-change="pageChange"
@on-page-size-change="pageSizeChange" />
<!-- default page -->
<Page
v-else
:total="data[totalKey]"
show-elevator
show-total
:current="table.search[pageIndexKey]"
:page-size="table.search[pageSizeKey]"
:page-size-opts="[10, 20, 30, 40]"
:show-sizer="showSizer"
@on-change="pageChange"
@on-page-size-change="pageSizeChange" />
</div>
</div>
</a-spin>
</template>
<script scoped>
import { Table, Page, Input, Select, Option, DatePicker, Row, Col, Form, FormItem } from 'iview';
import _ from 'loadsh';
export default {
props: {
table: {
required: true,
type: Object,
},
// 是否显示分页
showPage: {
default: true,
},
// 显示分页,用来改变page-size
showSizer: {
default: true,
},
// 分页大小
pageSize: {
default: 'default',
},
pageSizeKey: {
default: 'pageSize',
},
// 每页的索引参数
pageIndexKey: {
default: 'pageCurrent',
},
// 总页数的key
totalKey: {
default: 'totalCount',
},
// 边框
tableBorder: {
default: true,
},
// 是否调用onload
isOnload: {
default: true,
},
},
components: {
Table,
Page,
Input,
Select,
Option,
DatePicker,
Row,
Col,
Form,
FormItem,
},
data () {
return {
data: {
list: [],
channels: [],
pageCurrent: 0,
pageSize: 0,
},
// loading
spinning: false,
// 展开收起选项
upDownSearchOption: true,
};
},
mounted () {
this.data[ this.table.dataListKey ] = [];
if ( this.isOnload ) {
this.onload();
}
},
computed: {
// 每行几条数据
rowDataLength () {
// 默认一行3个
let rowLength1 = 3;
// 默认一行2个
let rowLength2 = 2;
let searchFromLength = this.table.searchForm.length;
if ( searchFromLength > 1 ) {
if ( !this.table.searchForm[ 0 ].span && !this.table.searchForm[ 1 ].span ) {
return rowLength1;
} else if ( this.table.searchForm[ 0 ].span == '16' || this.table.searchForm[ 1 ].span == '16' ) {
return rowLength2;
}
}
return rowLength1;
},
},
methods: {
// 页面初始化
async onload () {
this.spinning = true;
const res = await this.$HTTP.post( this.table.apiUrl, this.table.search );
this.data = res.result;
this.$emit( 'sendDate', res.result );
this.spinning = false;
},
// 分页改变
pageChange ( pageIndex ) {
this.table.search[ this.pageIndexKey ] = pageIndex;
this.onload();
},
// 每页几条发生改变
pageSizeChange ( pageSize ) {
this.table.search[ this.pageIndexKey ] = 1;
this.table.search[ this.pageSizeKey ] = pageSize;
this.onload();
},
// 日期转换
dateChange ( date, key1, key2 ) {
if ( key2 ) {
this.table.search[ key1 ] = date[ 0 ];
this.table.search[ key2 ] = date[ 1 ];
} else {
this.table.search[ key1 ] = date;
}
},
// 重置
reset () {
let keys = Object.keys( this.table.search );
keys.map( ( key ) => {
if ( Object.prototype.toString.apply( this.table.search[ key ] ) == '[object Array]' ) {
this.table.search[ key ] = [];
} else {
if ( key != this.pageIndexKey || key != this.pageSizeKey ) {
this.table.search[ key ] = '';
}
}
} );
this.$emit( 'resetTable' );
this.table.search[ this.pageIndexKey ] = 1;
this.table.search[ this.pageSizeKey ] = 10;
this.onload();
},
// 全选
selectAll ( selection ) {
this.$emit( 'selectAll', selection );
},
// 选择
select ( selection, row ) {
this.$emit( 'select', selection, row );
},
// 选择发生改变
selectionChange ( selection ) {
this.$emit( 'selectionChange', selection );
},
// 替换数据源
setData ( list ) {
this.data[ this.table.dataListKey ] = list;
},
// 增行
setListPush ( obj ) {
this.data[ this.table.dataListKey ].push( obj );
},
/**
* [setListDel 批量删除行]
* @param {Function} arr [删除的集合体]
* @param {Function} key [通过哪个字段匹配]
* @return {[type]} [description]
*/
setListDel ( arr, key ) {
let newArr = [];
arr.map( ( item ) => newArr.push( item[ key ] ) );
let event = _.remove( this.data[ this.table.dataListKey ], function ( item ) {
return !newArr.includes( item[ key ] );
} );
this.data[ this.table.dataListKey ] = event;
},
/**
* [spliceListDel 批量删除行]
* @param {Function} i [要删除的索引]
* @return {[type]} [description]
*/
spliceListDel ( i ) {
this.data[ this.table.dataListKey ].splice( i, 1 );
},
/**
* [spliceSetData 批量删除行]
* @param {Function} i [要替换的索引]
* @param {Function} obj [数据]
* @return {[type]} [description]
*/
spliceSetData ( i, obj ) {
this.data[ this.table.dataListKey ].splice( i, 1, obj );
},
// 展开某一行
onExpand ( ...data ) {
this.$emit( 'onExpand', data );
},
},
};
</script>
<style scoped lang="less">
.mr ( @px: 8px ){
margin-right: @px;
}
.tablePage {
.searchBox {
.tablesearch {
display: flex;
.search-option {
flex: 1;
}
.srarch-action {
.w( 180px ); .t-c( right ); .pt( 2px );
.upDownBtn {
.p( 0 0 0 4px );
}
&.down {
.w( 180px );
.upDownBtn {
.mt( 24px );
}
/deep/ .anticon-double-left {
transform: rotate( 90deg );
}
}
&.up {
.w( 230px );
/deep/ .anticon-double-left {
transform: rotate( -90deg );
}
}
}
}
}
.table-page{
margin-top: 16px;
display: flex;
justify-content: space-between;
}
}
</style>
调用
<template>
<myTable :table="table" ref="myTable">
<div slot="table-action"></div>
</myTable>
</template>
<script>
// api地址
import api from '@/utils/api/hcx';
// 组件位置
import myTable from 'components/hcx/table';
export default {
data () {
return {
table: {
apiUrl: 'xxxx',
dataListKey: 'list',
btn: {
searchType: 'primary',
resetType: 'default',
},
searchForm: [
{ type: 'input', key: 'test1', placeholder: '文本框', width: '150px' },
{ type: 'select', mul: false, key: 'test2', placeholder: '选择框', width: '150px', options: [ {value: 'New York', label: 'New York'} ], valueKey: 'value', nameKey: 'label', clearable: true },
{ type: 'select', mul: true, key: 'test3', placeholder: '选择框', width: '150px', options: [ {value: 'New1', label: 'New1'}, {value: 'New2', label: 'New2'} ], valueKey: 'value', nameKey: 'label', clearable: true },
{ type: 'datepicker', dateType: 'date', key: 'test4', dateKey: 'dateKey', placeholder: '日期', width: '150px', options: {}, placement: 'left' },
{ type: 'datepicker', dataType: 'daterange', key1: 'test5', key2: 'test6', dateKey: 'twoDate', placeholder: '日期', width: '150px', options: {}, placement: 'left' },
],
search: {
pageIndex: 1,
pageSize: 10,
test1: '',
test2: '',
test3: [],
test4: '',
dateKey: '',
test5: '',
test6: '',
twoDate: [],
},
columns: [
{
title: 'Name',
minWidth: 200,
key: 'remark',
},
{
title: 'Age',
minWidth: 200,
key: 'remark',
},
{
title: 'Address',
minWidth: 200,
render: ( h, params ) => h( 'div', [
h( Button, {
props: {
type: 'primary',
size: 'small',
},
style: {
marginRight: '5px',
},
on: {
click: () => {
console.log( params );
},
},
}, 'View' ),
h( Button, {
props: {
type: 'error',
size: 'small',
},
on: {
click: () => {
console.log( 'click' )
},
},
}, 'Delete' ),
] ),
},
],
},
};
},
components: {
myTable,
},
};
</script>