
## 表格

通过`cl-table`组件可以快速构建表格页面。

```html
<template>
  <div class="test-container">
    <cl-table
      ref="myTable"
      :data="data"
      :page-result="pageResult"
      quick-search-props="title,author"
      :custom-table-height="height"
      :quick-search-width="300"
      :page-sizes="[20, 50, 100, 200, 300, 500]"
      pagination-justify="end"
      @loading="loadData"
      @export="exportData"
      @card-click="card => $message(card.title)"
      @view-change="cardView => $message(JSON.stringify(cardView))"
      @selection-change="selection => $message(JSON.stringify(selection))"
    >
      <template #toolbar>
        <el-button type="primary" size="small">添加</el-button>
        <el-button size="small" v-popconfirm="{before:removeValid,confirm:handleRemove}">删除</el-button>
      </template>
      <template #search>
        <cl-table-search-panel v-model="searchModel" :label-width="100" :divide="4">
          <cl-table-search-field label="标题" prop="title" />
          <cl-table-search-field label="作者" prop="author" :span="6"/>
          <cl-table-search-field label="作者" prop="author" />
          <cl-table-search-field label="作者" prop="author" />
          <cl-table-search-field label="作者" prop="author" />
          <cl-table-search-field
            label="创建时间"
            prop="pageViews"
            type="daterange"
            :span="6"
          />
          <cl-table-search-field label="作者(用户选择器)" prop="author" v-model="searchModel.author">
            <cl-user-selector-input v-model="searchModel.author" />
          </cl-table-search-field>
          <cl-table-search-field label="作者" prop="author" />
          <cl-table-search-field label="作者" prop="author" />
          <cl-table-search-field label="作者" prop="author" :span="6"/>
          <cl-table-search-field label="作者" prop="author" />
        </cl-table-search-panel>
      </template>
      <template #card="{ item }">
        <div class="cl-table__card-item">
          <el-image :preview-src-list="imageList" :src="item.img"></el-image>
          <span>{{ item.title }}</span>
        </div>
      </template>
      <template #default>
        <cl-table-column type="index" width="50" required align="center" label="序号" />
        <cl-table-column
          prop="title"
          label="标题"
          min-width="200"
          :sortable="true"
          :show-overflow-tooltip="true"
        />
        <cl-table-column prop="author" width="120" :required="true" label="作者" :sortable="true" />
        <cl-table-column label="头像">
          <template #default="{ row }">
            <el-image :preview-src-list="imageList" :src="row.smallImg"></el-image>
          </template>
        </cl-table-column>
        <cl-table-column prop="pageViews" label="点击量" sortable />
        <cl-table-column label="状态" width="100" :filters="statusAry">
          <template #default="{ row }">
            <el-tag :type="statusMap(row.status, 'type')">
              {{ statusMap(row.status, 'text') }}
            </el-tag>
          </template>
        </cl-table-column>
        <cl-table-column label="操作">
          <template #default>
            <el-button type="text" @click="$message('编辑')">编辑</el-button>
          </template>
        </cl-table-column>
      </template>
    </cl-table>
  </div>
</template>
<script>
  import { getList } from '$exp/api/table'

  export default {
    name: 'TableTest',
    data() {
      return {
        data: [],
        searchModel: {
          author: null,
          authorId: null,
        },
        statusAry: [
          { text: '成功', value: 'published', type: 'success' },
          { text: '草稿', value: 'draft', type: 'gray' },
          { text: '已删除', value: 'deleted', type: 'danger' },
        ],
        imageList: [],
        pageResult: {
          page: 1,
          pageSize: 20,
          total: 999,
        },
      }
    },
    computed: {
      statusMap() {
        return (status, prop) => {
          return this.statusAry.find((m) => m.value === status)[prop]
        }
      },
      height() {
        return this.$baseTableHeight()
      },
    },
    methods: {
      loadData(param, cb) {
        getList(param)
          .then((response) => {
            this.data = response.data
            this.pageResult = {
              page: response.page,
              pageSize: response.pageSize,
              total: response.totalCount,
            }
          })
          .finally(() => cb())
      },
      removeValid(){
        if(this.$refs.myTable.selection.length == 0){
          this.$message({message: '请至少选择一条记录', type:'warning'})
          return false
        }
        return true
      },
      handleRemove(){
        // TODO 删除数据 then
        // req.reomve(this.$refs.myTable.selection)
        this.$refs.myTable.load()
      },
      exportData() {
        this.$message('导出数据')
      },
    },
  }
</script>
<style lang="scss">
  .cl-table__card-item {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;

    span {
      margin-top: 10px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
</style>
<!-- table1.vue -->
```

## 表格组件

* `cl-table`表格组件
* `cl-table-search-panel`高级搜索面板
* `cl-table-search-field`高级搜索字段
* `cl-table-column`表格的列

## 1.表格组件
表格组件的代码如下所示：
```html
<cl-table
    :data="data"
    :pageResult="pageResult"
    :selection="true"
    quick-search-props="account,name,mobile"
    @load="loadData">
</cl-table>
```

### 属性说明
|属性|类型|默认值|说明|
|:---|:---|:---|:---|
|just-show-search|boolean|false|是否只显示高级搜索面板|
|pagination-justify|string|`start`|分页组件的显示位置，可选值为：`start`,`center`,`end`|
|show-header|boolean|true|是否显示表头|
|data|array|-|表格的数据，格式为数组|
|page-result|object|```{ page: 1, pageSize: 50, total: 0 }```|分页对象，`page`表示当前页，`pageSize`表示每页条数，`total`表示总数|
|page-sizes|Array|[10, 20, 50, 100, 200, 300, 500]|每页条数下拉可选项|
|pager-count|number|11|分页组件中最多显示多少个分页按钮|
|nopagination|boolean|false|false 显示分页组件 true 不显示分页组件 |
|highlight-current-row|boolean|false|是否高亮当前选中行|
|selectable|boolean|true|是否在第一列显示复选框|
|quick-search-props|string/array|-|快速搜索，格式为`string`时提供逗号分割的任意多个属性`"name,account,email"`，而且这些属性必须与表格的列中`prop`能够对应；格式为`array`时为```[{prop:"name",label:"姓名"},{prop:"u.account_",label:"账号"}]```的格式，此时`prop`可以不对应表格的列。|
|header-row-class-name|string|-|表格列头的样式`class`|
|show-export|boolean|false|是否显示导出数据的按钮|
|show-custom-column|boolean|true|是否显示自定义显示列的按钮|
|default-querys|Array|[]|默认的查询条件，数组中的对象格式为`{group:"defaultQueryGroup",operation: "EQUAL",relation: "AND",property:"prop",value:"val"}` <br/>例如 `:default-querys="[{property:'account',value:'lisi'}]"`,`:default-querys="[{property:'account',value:'lisi',operation:"LIKE"}]"` |
|default-sorter|Array|[]|默认的排序规则，如果设置了默认排序的列，该列不支持更改排序规则，只能使用默认的排序规则。<br />其中`direction`属性的可选值为`DESC`,`ASC`，例如`:default-sorter="[{direction: 'DESC',property: 'name'}]"`|
|is-load-table|boolean|true|是否默认加载表格数据，设置为`false`时表格默认不触发`loading`事件，需要调用`load`方法或者用户点击查询按钮来触发。|
|custom-table-height|number/string|-|设置表格组件的高度|
|quick-search-width|number|400|设置快速搜索框的宽度|
|multi-view-switch|boolean|false|支持多视图切换，可以在表格视图和卡片视图之间切换|
|card-view|boolean|false|是否默认以卡片视图展示数据|
|card-item-mode|boolean|true|是否默认以每条数据作为一个卡片数据渲染，设置为`true`时传递单条数据`item`的作用域插槽，设置为`false`时传递整份`data`数据的作用域插槽。|
|no-header|boolean|false|不显示整个工具栏|
|empty-text|string|暂无数据|数据为空时显示的文本|
|row-click-select|boolean|true|单击行时是否选中该行数据|
|hide-page-sizes|boolean|false|是否隐藏选择每页条数的下拉框|

### 方法说明
|方法|说明|
|:---|:---|
|load(doNotResetPage)|触发查询，参数`doNotResetPage`不传或者传`false`时，会将页码重置为第一页来查询，传`true`时，会按照当前页码来查询。|

### 插槽
|name|说明|
|:---|:---|
|-|表格数据区的内容。|
|toolbar|工具栏插槽，可以自定义显示在快捷搜索框旁边的内容。|
|search|高级搜索面板中的内容|
|card|卡片视图下的数据区内容，参数为{ item }|


### 事件说明
|事件|说明|参数|
|:---|:---|:---|
|loading|表格加载数据时会触发的事件，监听该事件调用后台接口加载数据。|param|
|row-click|当用户点击某一行数据时触发的事件|row,column,event|
|select|当用户手动勾选数据行的 Checkbox 时触发的事件(要获取当前表格所选中的数据，可以通过`this.refs.table.selection`获取)|selection,row|
|select-all|当用户手动勾选全选 Checkbox 时触发的事件|selection|
|sort-change|当用户执行排序操作时触发的事件|column|
|filter-change|当用户选择对某一列进行筛选时触发的事件|prop|
|export|当用户点击导出按钮时会触发该事件|-|
|card-click|卡片视图下点击某个卡片时触发|card|
|view-change|切换视图时触发|isCardView|

`loading`事件中的`param`参数，格式如下：
```javascript
{
    pageBean: {
        page: 1,
        pageSize: 50
    },
    sorter: [
        {property: "age", direction: "ASC"}
    ],
    querys: [
        {property: "name", operation: "LIKE", value: "", group: "filter", relation: "AND"},
        {property: "account", operation: "LIKE", value: "", group: "filter", relation: "AND"}
    ],
    groupRelation: "AND"
}
```
以上`param`的各项参数说明如下：
+ `pageBean`分页对象，`page`为当前页码，`pageSize`为每一页的条数；
- `sorter`排序对象，`property`为要排序的字段，`direction`为排序的方向，可选值为：`ASC`,`DESC`；
- `querys`查询对象，查询对象中各个参数说明如下：
    * `property`为查询字段；
    * `value`为参数的值；
    * `group`为查询条件所属分组，分组名相同的多个条件会组合为一个查询分组；
    * `relation`为当前分组中多个条件之间的组合关系，可选值有`AND`,`OR`，在同一组中，只有第一个查询条件中的`relation`生效且整组都以这个关系来组合；
    * `operation`为查询操作类型，可选值有：
        1. `EQUAL`等于
        2. `EQUAL_IGNORE_CASE`忽略大小写等于
        2. `LESS`小于
        2. `GREAT`大于
        2. `LESS_EQUAL`小于等于
        2. `GREAT_EQUAL`大于等于
        2. `NOT_EQUAL`不等于
        2. `LIKE`类似
        2. `LEFT_LIKE`左类似
        2. `RIGHT_LIKE`右类似
        2. `IS_NULL`为空
        2. `NOTNULL`不为空
        2. `IN`在集合中
        2. `BETWEEN`介于
- `groupRelation`多组查询条件之间的组合关系，可选值：`AND`,`OR`。

## 2.高级搜索面板

如下面的代码所示，高级搜索面板对应的组件为`cl-table-search-panel`，因为该搜索面板要出现在表格中的特定位置，所以我们以插槽`<template v-slot:search>`的形式放在`<cl-table>`中。

```html
<template v-slot:search>
    <cl-table-search-panel v-model="searchModel" :divide="4">
        <cl-table-search-field label="姓名(用户选择器)" prop="name" v-model="searchModel.userId">
          <cl-user-selector-input v-model="searchModel.name" :config="{ id: 'data.searchModel.userId' }"/>
        </cl-table-search-field>
        <cl-table-search-field label="账号" prop="account" />
        <cl-table-search-field label="邮箱" prop="email" />
        <cl-table-search-field label="电话" prop="mobile" />
    </cl-table-search-panel>
</template>
<script>
  export default{
    data(){
      return {
        searchModel: {
          name: null,
          userId: null,
        }
      }
    }
  }
</script>
```

### 属性说明
|属性|类型|默认值|说明|
|:---|:---|:---|:---|
|v-model|高级搜索面板中的搜索条件|-| 搜索条件可以使用选择器，选择器有多个返回值可以绑定，而绑定的返回值必须在该`v-model`对象中。 |
|divide|搜索条件分为几列|4|在搜索条件较多时，搜索面板会按照每行`divide`列的方式来展示搜索条件，该属性的可选值为`0<divide<5`的整数。|
|label-width|搜索条件中标签的宽度(px)|70|搜索条件中标签部分的宽度|
|is-flex-layout|boolean|false|搜索面板中的条件字段按照流式布局自动排列。|


## 3.高级搜索字段
如下面的代码所示，`<cl-table-search-field />` 必须出现在`<cl-table-search-panel>`中。
不设置type时默认为text
```html
<cl-table-search-field label="姓名" prop="name" />
```
当`type="select"`时会显示为下拉框
```html
<cl-table-search-field label="状态" prop="status" type="select" :options="[{value:'男士', key:'0'},{value:'女士', key:'1'}]" />
```
当`type="date"` 时会显示为日期
```html
<cl-table-search-field label="创建时间" prop="createTime" type="date"/>
```
当`type="daterange"`时会显示为日期范围
```html
<cl-table-search-field label="完成时间" prop="completeTime" type="daterange"/>
```
也可以使用插槽来配置更多类型的搜索字段，***<span style="color:red">特别注意：类似选择器的值绑定配置必须添加`data.`的前缀，因为`cl-table-search-panel`中的`v-model`会添加到`data`属性上。</span>***
```html
<cl-table-search-field label="姓名(用户选择器)" prop="name" v-model="searchModel.userId">
  <cl-user-selector-input v-model="searchModel.name" :config="{ id: 'data.searchModel.userId' }"/>
</cl-table-search-field>
```


### 属性说明
|属性|类型|默认值|说明|
|:---|:---|:---|:---|
|v-model|string|-|当搜索条件是插槽时，对应搜索条件的值。|
|prop|string|-|用于查询的参数属性名，必填。|
|operation|string|LIKE|查询时的操作类型，其可选值与上述表格组件中`param`参数中`querys`中的`operation`的可选值一致。|
|relation|string|AND|多个查询条件之间的组合关系，可选值`AND`,`OR`。|
|label|string|-|查询条件的标签内容|
|label-width|number|默认会由`cl-table-search-panel`传入|查询条件标签的宽度|
|type|string|text|查询条件的类型，可选值：`text`,`date`,`daterange`,`select`|
|props|object|`{key: 'key',value: 'value'}`|`type="select"`时指定选项的选项值(key)和选项标签(value)的配置|
|span|number|-|搜索条件对应的`el-col`的`span`值。|
| hide-label      | boolean |`false`| 是否隐藏label标签。|
| display-style   | string  | `inline`| 搜索条件中的组件是以`block`还是`inline`方式显示|
| enter-to-search | boolean | false| 对于类型为text的查询条件，是否在回车时触发查询动作。|

## 4.表格的列

代码如下所示，通过`cl-table-column`来配置表格显示的列。

```html
<cl-table-column
        prop="name"
        label="名称"
        width="300"
        :sortable="true"
        :show-overflow-tooltip="true"/>
```

### 属性说明
|属性|类型|默认值|说明|
|:---|:---|:---|:---|
|type|string|-|对应列的类型。如果设置了`selection`则显示多选框；如果设置了`index`则显示该行的索引（从 1 开始计算）；如果设置了`expand`则显示为一个可展开的按钮|
|align|string|center|列在横向上的布局方式，可选值有`left`,`center`,`right`。|
|prop|string|-|列对应的属性，必须与`data`返回的数据的属性对应上。|
|label|string|-|列标签|
|width|string|-|对应列的宽度|
|sortable|boolean|false|当前列是否支持排序|
|filters|Array[{text, value}]|-|数据过滤的选项，数组格式，数组中的元素需要有`text`和`value`属性。|
|show-overflow-tooltip|boolean|false|当内容过长被隐藏时显示 tooltip。|
|fixed|string,boolean|-|列是否固定在左侧或者右侧，true 表示固定在左侧。为字符串时可选值有：`left`,`right`|
|formatter|Function(row, column, cellValue, index)|-|用来格式化内容|
|renderHeader|Function(h, { column, $index })|-|列标题 Label 区域渲染使用的 Function|
|hidden|boolean|false|默认是否隐藏列，隐藏的列在自定义显示列对话框中可以勾选显示。|
|required|boolean|false|是否禁止隐藏的列。|

### 插槽
|name|说明|
|:---|:---|
|-|自定义列的内容，参数为{ row, column, cellValue, index }|
|header|自定义表头的内容，参数为{ column, $index }|
