<template>
<div class="jzl-table">
<el-table
:data="tableData"
:ref="tableRef"
@select="select"
@select-all="selectAll"
@selection-change="selectionChange"
:height="filterParams(tableConfig.height,null)"
:max-height="filterParams(tableConfig.maxHeight,null)"
:stripe="filterParams(tableConfig.stripe,false)"
:empty-text="filterParams(tableConfig.emptyText,'暫無數據')"
:border="tableConfig.border||true"
:rowClassName="tableConfig.rowClassName || null"
:showSummary="tableConfig.showSummary || false"
:summaryMethod="tableConfig.summaryMethod?summaryMethod : null "
:sumText="tableConfig.sumText || '合計'"
:row-key="tableConfig.rowKey||null"
v-if="!hideTable"
class="jzl-table"
>
<template v-for="(item,index) in columnConfig">
<el-table-column
v-if="defaultColumnType.includes(item.type) && !item.hide"
:type="item.type"
:key="index"
:fixed="item.fixed||false"
:align="item.align||align"
:width="item.width||55"
:minWidth="item.minWidth|| 'auto'"
:label="item.label"
:reserve-selection="item.reserveSelection||false"
></el-table-column>
<el-table-column
v-else-if="item.type === 'switch' && !item.hide"
:fixed="item.fixed||false"
:width="item.width||''"
:minWidth="item.minWidth|| 'auto'"
:key="index"
:align="item.align||align"
:label="item.label"
:prop="item.prop"
>
<template slot-scope="{row,$index}">
<el-switch
class="switchBtn"
v-model="row[item.prop]"
:active-color="item.switchConfig.activeColor||'#13ce66'"
@change="item.switchCallBack?item.switchCallBack($event,row[item.prop],$index,row):new Function()"
:active-value="item.switchConfig.activeValue||1"
:inactive-value="item.switchConfig.inactiveValue||0"
:inactive-color="item.switchConfig.inactiveColor||'#cccccc'"
:disabled="item.switchConfig.permission||false"
></el-switch>
</template>
</el-table-column>
<el-table-column
v-else-if="item.type === 'button' && !item.hide"
:fixed="item.fixed||false"
:align="item.align||align"
:width="item.width||''"
:minWidth="item.minWidth|| 'auto'"
:key="index"
:label="item.label"
:prop="item.prop"
>
<template slot-scope="{row,$index}">
<div>
<template v-for="(btn,i) in item.buttonConfigArray">
<el-switch
:key="i"
class="switchBtn"
v-if="buttonType(btn.type) === 'switch' && !btnHide(btn.hide,row)"
v-model="btn.model"
:active-color="btn.switchConfig.activeColor||'#13ce66'"
@change="btn.switchCallBack?btn.switchCallBack($event,btn.prop,$index,row):new Function()"
:active-value="btn.switchConfig.activeValue||1"
:inactive-value="btn.switchConfig.inactiveValue||0"
:inactive-color="btn.switchConfig.inactiveColor||'#cccccc'"
:disabled="btn.permission||false"
></el-switch>
<slot
v-else-if="buttonType(btn.type)==='slot' && !btnHide(btn.hide,row)"
:name="btn.soltName"
:data="{row,$index}"
@click="btn.click?btn.click(row,$index):new Function()"
></slot>
<el-button
v-else-if="! btnHide(btn.hide,row)"
@click="btn.click?btn.click(row,$index):new Function()"
:key="i"
:class="btn.class"
:icon="btn.icon||''"
:type="buttonType(btn.type)"
:disabled="btn.permission || false"
>{{btn.name}}</el-button>
</template>
</div>
</template>
</el-table-column>
<slot
v-else-if="item.type==='solt' && !item.hide"
:name="item.soltName"
:prop="item.prop"
:label="item.label"
:width="item.label"
></slot>
<el-table-column
v-else-if="!item.hide"
:key="index"
:fixed="item.fixed||false"
:align="item.align||align"
:width="item.width||''"
:minWidth="item.minWidth|| 'auto'"
:label="item.label"
:prop="item.prop"
:show-overflow-tooltip="item.overflowHide||true"
>
<template slot-scope="{row,$index}">
<div
:class="`${item.clickFn?'alink':''} ${item.className} ${item.classNameFunc?item.classNameFunc(row,row[item.prop],$index):''} ${item.overflowHide===false?'':'overflowHide'}`"
@click="item.clickFn?item.clickFn(row,row[item.prop],$index,item.prop):()=>{}"
>{{ item.formatter?filterColText(row,row[item.prop],$index,item.formatter):row[item.prop]}}</div>
</template>
</el-table-column>
</template>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="this.pageConfig.page"
:page-sizes="pageConfig.sizes||[20,50,100,200]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageConfig.total||0"
v-if="!hidePage"
></el-pagination>
</div>
</template>
<script>
import draggable from 'vuedraggable'
import Sortable from 'sortablejs'
export default {
components: {
draggable,
Sortable
},
props: {
/**
* ref 標識
* 用於用戶獲取表格
* 調用element的Table Methods裏面的方法
*
*/
tableRef: {
type: String,
default: 'jzl_table'
},
// 表格數據
tableData: {
type: Array,
default: () => {
return []
}
},
/**
* 表格配置
*
* 目前支持的函數key有
* select(當用戶手動勾選數據行的 Checkbox 時觸發的事件)
* selectAll(當用戶手動勾選全選 Checkbox 時觸發的事件)
* selectionChange(當選擇項發生變化時會觸發該事件)
* 常用配置有
* height:string/number 表格高
* maxHeight:string/number 表格最大高度
* stripe:boolean 是否爲斑馬紋
* emptyText:string 空數據時的文本
* border:boolean
* showSummary:boolean是否顯示合計
* summaryMethod:function ({ columns, data } 自定義的合計計算方法
* sumText:String 合計行第一列的文本
* rowClassName:function({row, rowIndex}) /String 行的 className 的回調方法,
* 也可以使用字符串爲所有行設置一個固定的 className,通常用於控制某行的顏色
* rowKey:Function(row)/String行數據的 Key,用來優化 Table 的渲染;
* 在使用 reserve-selection 功能與顯示樹形數據時,
* 該屬性是必填的。類型爲 String 時,
* 支持多層訪問:user.info.id,但不支持 user.info[0].id,此種情況請使用 Function
*
* */
tableConfig: {
type: Object,
default: () => {
return {}
}
},
/**
* 表格列配置
* {
* label:string, // 列標題
* prop:string, // 對應列的字段名
* type:string, // 當前列類型支持solt(插槽,自定義)、selection(多選框)、index(索引)、switch(switch開關)、button(按鈕欄)、text(div,普通列,默認值))
* reserveSelection:boolean, // 它僅對 type=selection 的列有效,類型爲 Boolean,爲 true時會在數據更新之後記住之前選擇的數據。(需要指定row-key)
* switchCallBack:Function, // 當type爲switch時必傳
* buttonConfigArray:array, // 當type爲button時必傳
* width:string, // 對應列的寬度
* minWidth:string, // 最小列寬
* clickFn:function, //當前列點擊回調,常用於點跳轉Function(row, cellValue,$index,prop( 對應列的字段名))
* fixed:string, boolean // 列是否固定在左側或者右側,true 表示固定在左側
* formatter:Function,string,array // 回調函數參數Function(row, cellValue, index) ,
* string代表是掛載在全局的過濾函數 ,array代表val是下標array[val]
* align:string // 對齊方式
* className:string // 列的樣式類名,用於改變類顏色
* classNameFunc:function // 用於動態計算列類名函數,便於根據不用內容顯示不同樣式,Function(row, cellValue, index){return calss}
*overflowHide:boolean //是否超出隱藏,默認是
hide:boolean: true 代表隱藏此列
* }
*
*/
columnConfig: {
type: Array,
required: true,
default: () => []
},
/**
* 分頁配置
* page:number, // 初始頁數,默認1
* pageSize:number , // 初始條數 。默認20
* pageChange:Function // 點擊分頁頁數或者條數改變回調函數 Function(page.pageSize)
* sizes:array //下拉選擇頁數數組 默認[20,50,100,200]
* total:總數
*/
pageConfig: {
type: Object,
default: () => {
return {
page: 1,
pageSize: 20
}
}
},
/**
* 隱藏表格,單獨顯示分頁
*
*/
hideTable: {
type: Boolean,
default: false
},
/**
* 隱藏分頁,單獨顯示錶格
*
*/
hidePage: {
type: Boolean,
default: false
},
/**
* 默認表格對齊方式
* */
align: {
type: String,
default: 'left'
},
// 是否開啓拖拽
drag: {
type: Boolean,
default: false
},
// 拖拽結束回調函數
dragOnEnd: {
type: Function,
default: new Function()
}
},
data () {
return {
defaultFunction: new Function(),
defaultColumnType: ['index', 'selection'],
page: 1,
pageSize: 20
}
},
mounted () {
this.pageConfig.page = this.pageConfig.page || 1
this.pageSize = this.pageConfig.pageSize || 20
if (this.drag) {
if (!this.tableConfig.rowKey) {
console.warn('已開啓拖拽功能,請定義rowKey,rowKey爲行數據的 Key,用來優化 Table 的渲染;在使用 拖拽功能時,該屬性是必填的。類型爲 String 時,支持多層訪問:user.info.id,但不支持 user.info[0].id,此種情況請使用 Function。')
}
this.openDrag()
}
},
methods: {
// 行拖拽
openDrag () {
const tbody = document.querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd (data) {
_this.dragOnEnd(data)
// const currRow = _this.tableData.splice(oldIndex, 1)
// 在新位置插入新值
// _this.tableData.splice(newIndex, 0, currRow[0])
}
})
},
summaryMethod (params) {
if (this.tableConfig.summaryMethod) {
// 如果有高,表頭固定需要在初始化時主動觸發重新計算合計行位置
if (this.tableConfig.height) {
this.$nextTick(() => {
this.$refs.jzl_table.doLayout()
})
}
return this.tableConfig.summaryMethod(params)
}
},
buttonType (type) {
return type || 'primary'
},
handleCurrentChange (page) {
this.pageConfig.page = page
this.pageConfig.pageChange(page, this.pageSize)
},
// 改變每頁數量時,當前頁回到第一頁,防止請求不到數據
handleSizeChange (pageSize) {
this.pageSize = pageSize
this.pageConfig.page = 1
this.pageConfig.pageChange(this.pageConfig.page, pageSize)
},
// 過濾參數
filterParams (params, defaultVal) {
return params || defaultVal
},
filterColText (row, val, index, filterFn) {
try {
if (typeof filterFn === 'function') {
return filterFn(row, val, index)
} else if (typeof filterFn === 'string') {
if (this.__proto__.constructor.filter(filterFn)) {
return this.__proto__.constructor.filter(filterFn)(val)
} else {
console.warn('無法找到掛載在全局的過濾函數=== ' + filterFn + ' ====')
return val
}
} else if (Array.isArray(filterFn)) {
return filterFn[val]
}
} catch (e) {
console.error('表格過濾函數 == ' + filterFn + ' ==參數錯誤:' + e)
}
},
// 操作欄按鈕隱藏
btnHide(fn,row){
if(fn === undefined)
return false
try {
if (typeof fn === 'function') {
return fn(row)
}else{
console.error('buttonConfigArray配置項中的hide必須爲函數類型,現在獲取到的類型爲:'+typeof fn)
}
} catch (error) {
console.log('操作按鈕隱藏函數:'+error)
}
},
selectionChange (e) {
if (this.tableConfig.selectionChange) {
this.tableConfig.selectionChange(e)
}
},
selectAll (e) {
if (this.tableConfig.selectAll) {
this.tableConfig.selectAll(e)
}
},
select (selection, row) {
if (this.tableConfig.select) {
this.tableConfig.select(selection, row)
}
}
}
}
</script>
<style lang="scss" scoped>
.jzl-table {
width: 100%;
margin: 10px auto;
}
.el-select .el-input .el-select__caret {
line-height: 30px;
}
.delt.el-button--text {
color: #ff0000;
}
//排序圖標
.el-icon-sort-down,
.el-icon-sort-up {
transform: scale(1, 1.2);
margin: 0;
margin-right: -2px;
padding: 0;
}
.el-icon-sort-down:before,
.el-icon-sort-up:before {
color: #409eff;
font-size: 16px;
cursor: pointer;
}
.overflowHide {
width: 100%;
overflow: hidden; //超出的文本隱藏
text-overflow: ellipsis; //溢出用省略號顯示
white-space: nowrap; //溢出不換行
}
.alink {
color: #0068d0;
}
.alink:hover {
cursor: pointer;
text-decoration: underline;
}
</style>