cxc-szcx-uniapp/uni_modules/zb-table/components/zb-table/zb-table.vue

1343 lines
41 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- #ifdef H5 || APP-PLUS -->
<view :class="['zb-table','zb-table-fixed-header',!border&&(bodyTableLeft>50||headerTableLeft>50)&&'scroll-left-fixed']">
<view class="zb-table-content" style="flex: 1">
<view class="zb-table-scroll" style="height: 100%;">
<template v-if="showHeader">
<view class="zb-table-header top-header-uni"
>
<scroll-view class="zb-table-headers"
@scroll="handleTableScrollLeft"
scroll-x="true"
scroll-y="false"
id="tableHeaders"
scroll-anchoring="true"
:scroll-left="headerTableLeft"
style="
height: 100%">
<view class="zb-table-fixed" >
<view class="zb-table-thead" style="position: relative;" >
<view class="item-tr">
<view
@click.stop="sortAction(item,index)"
class="item-th"
:style="[{
width:`${item.width?item.width:'100'}px`,
flex:index===transColumns.length-1?1:'none',
minWidth:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
},getHeaderCellStyle(item,index)]"
v-for="(item,index) in transColumns" :key="index">
<template v-if="item.type==='selection'">
<view class="checkbox-item">
<tableCheckbox
:indeterminate="indeterminate" :checked="checkedAll" @checkboxSelected="checkboxSelectedAll"></tableCheckbox>
</view>
</template>
<template v-else>
{{ item.label }}
<view class="sorter-table" v-if="item.sorter">
<view :class="['sorter-table-icon',item.sorterMode==='_asc'&&`sorting${item.sorterMode||''}`]"></view>
<view :class="['sorter-table-icon',item.sorterMode==='_desc'&&`sorting${item.sorterMode||''}`]"></view>
</view>
</template>
</view>
<view
v-if="scrollbarSize"
class="item-th "
:style="{
borderTop:`${border?'1px solid #e8e8e8':''}`,
padding:0,
width:`${scrollbarSize}px`,
}">
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<template v-if="!data.length">
<view class="no-data">暂无数据~~</view>
</template>
<scroll-view
class="zb-table-body" ref="tableBody" scroll-x="true" scroll-y="true" id="tableBody"
:lower-threshold="40"
:upper-threshold="10"
@scrolltolower="scrolltolower"
@scrolltoupper="(e)=>debounce(scrollToLeft)(e)"
@scroll="handleBodyScroll" :scroll-left="bodyTableLeft" :scroll-top="bodyScrollTop"
:style=" `height: calc(100% - ${showSummary?80:40}px)`" >
<view class="zb-table-fixed">
<view class="zb-table-tbody">
<view :class="['item-tr',highlight&&isHighlight(item,index)?'current-row':'']"
@click.stop="rowClick(item,index)"
v-for="(item,index) in transData" :key="item.key" >
<view
:style="[{
width:`${ite.width?ite.width:'100'}px`,
flex:i===transColumns.length-1?1:'none',
minWidth:`${ite.width?ite.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:ite.align||'left',
},cellStyle&&getCellStyle(item,ite,index,i)]"
@click="cellClick(item,index,ite)"
:class="['item-td',stripe?(index % 2) != 0?'odd':'even':'']"
v-for="(ite,i) in transColumns" :key="i">
<template v-if="ite.type==='operation'">
<view style="display: flex;align-items: center;height: 100%">
<view
v-for="ren,ind in permission(item,ite.renders,index)"
:key="ind"
@click.stop="$emit(ren.func,item,index)"
:style="{
display:'flex',
alignItems: 'center',
marginRight:ite.renders.length>1?'8px':'0'
}">
<template v-if="ren.type==='custom'">
<view :class="ren.class||''" style="cursor: pointer">
{{ren.name}}
</view>
</template>
<template v-else>
<button
:class="ren.class||''"
:type="ren.type||'primary'" :size="ren.size||'mini'">{{ren.name}}</button>
</template>
</view>
</view>
</template>
<template v-else-if="ite.type==='selection'">
<view class="checkbox-item">
<tableCheckbox @checkboxSelected="(e)=>checkboxSelected(e,item)" :cellData="item" :checked="item.checked"/>
</view>
</template>
<template v-else-if="ite.type==='index'">
{{index+1}}
</template>
<template v-else-if="ite.type==='img'">
<view class="checkbox-item">
<template v-if="item[ite.name]">
<image
@click.stop="previewImage(item,item[ite.name],iImage)"
v-for="iImageTem,iImage in imgs(item[ite.name])"
:show-menu-by-longpress="false"
:key="iImage"
:src="iImageTem" style="width: 40px;height:30px; " mode="aspectFit"></image>
</template>
<text v-else>{{ite.emptyString}}</text>
</view>
</template>
<template v-else>
<!-- {{ ite.filters?itemFilter(item,ite):(item[ite.name]==null||item[ite.name]==='')?ite.emptyString:item[ite.name] }}-->
{{ ite.filters?itemFilter(item,ite):formatterAction(item,ite,index,i) }}
</template>
</view>
</view>
</view>
</view>
</scroll-view>
<table-h5-summary
:scrollbarSize="scrollbarSize"
:data="data"
:handleFooterTableScrollLeft="handleFooterTableScrollLeft"
:headerFooterTableLeft="headerFooterTableLeft"
v-if="showSummary"
:showSummary="showSummary"
:transColumns="transColumns"
:border="border"
:summary-method="summaryMethod"
:sumText="sumText"
:fixedLeftColumns="fixedLeftColumns"/>
</view>
<view class="zb-table-fixed-left"
v-if="isFixedLeft"
:style=" {height: `calc(100% - ${scrollbarSize}px)`}"
>
<template v-if="showHeader">
<view class="zb-table-header" style="display: flex">
<view class="item-tr"
style=""
@click.stop="rowClick(item,index)"
v-for="(item,index) in fixedLeftColumns" :key="index">
<view
:style="{
width:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
@click.stop="sortAction(item,index)"
class="item-th"
>
<template v-if="item.type==='selection'">
<view class="checkbox-item">
<tableCheckbox
:indeterminate="indeterminate" :checked="checkedAll" @checkboxSelected="checkboxSelectedAll"></tableCheckbox>
</view>
</template>
<template v-else>
{{ item.label }}
<view class="sorter-table" v-if="item.sorter">
<view :class="['sorter-table-icon',item.sorterMode==='_asc'&&`sorting${item.sorterMode||''}`]"></view>
<view :class="['sorter-table-icon',item.sorterMode==='_desc'&&`sorting${item.sorterMode||''}`]"></view>
</view>
</template>
</view>
</view>
</view>
</template>
<scroll-view
scroll-y="true"
id="leftTableFixed"
:upper-threshold="15"
@scrolltoupper="(e)=>scrollToFixedLeft(e)"
@scroll="leftFixedScrollAction"
:scroll-top="leftFiexScrollTop"
class="zb-table-body-inner"
:style=" `height: calc(100% - ${showSummary?80:40}px)`">
<view class="zb-table-fixed">
<view class="zb-table-tbody">
<view
:class="['item-tr',stripe?(i % 2) != 0?'odd':'even':'',highlight&&isHighlight(ite,i)?'current-row':'']"
v-for="(ite,i) in transData"
@click.stop="rowClick(ite,i)"
:key="ite.key"
style="">
<view class='item-td'
@click="cellClick(ite,index,item)"
:style="[{
width:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
},cellStyle&&getCellStyle(ite,item,i,index)]"
:key="index"
v-for="(item,index) in fixedLeftColumns">
<template v-if="item.type==='selection'">
<view class="checkbox-item">
<tableCheckbox @checkboxSelected="(e)=>checkboxSelected(e,ite)" :cellData="ite" :checked="ite.checked"/>
</view>
</template>
<template v-else-if="item.type==='index'">
{{i+1}}
</template>
<template v-else>
{{ite[item.name]||item.emptyString}}
</template>
</view>
</view>
</view>
</view>
</scroll-view>
<table-side-summary
:scrollbarSize="scrollbarSize"
v-if="showSummary&&!(scrollbarSize>0)"
:data="data"
:showSummary="showSummary"
:transColumns="transColumns"
:border="border"
:summary-method="summaryMethod"
:sumText="sumText"
:fixedLeftColumns="fixedLeftColumns"/>
</view>
</view>
<zb-load-more v-if="isLoadMore&&!completeLoading"/>
</view>
<!-- #endif -->
<!-- #ifndef H5 || APP-PLUS -->
<view class="zb-table-applet">
<view class="zb-table-content" style="white-space: nowrap">
<scroll-view
<!-- #ifdef MP-ALIPAY -->
@scroll="scrollAlipay"
<!-- #endif -->
@scrolltolower="scrolltolower"
<!-- #ifdef MP-ALIPAY -->
style=" height: 100%;overflow-x:scroll"
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
style=" height: 100%"
<!-- #endif -->
scroll-y="true"
scroll-x="true">
<view class="zb-table-scroll" >
<template v-if="showHeader">
<view class="zb-table-header top-header-uni" style="">
<view class="zb-table-fixed" >
<view class="zb-table-thead" style="position: relative;" >
<view class="item-tr">
<view
@click.stop="sortAction(item,index)"
:class="['item-th',index <fixedLeftColumns.length&&'zb-stick-side']"
:style="{
left:`${item.left}px`,
width:`${item.width?item.width:'100'}px`,
flex:index===transColumns.length-1?1:'none',
minWidth:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
v-for="(item,index) in transColumns" :key="index">
<template v-if="item.type==='selection'">
<view class="checkbox-item">
<tableCheckbox
:indeterminate="indeterminate" :checked="checkedAll" @checkboxSelected="checkboxSelectedAll"></tableCheckbox>
</view>
</template>
<template v-else>
{{ item.label||'' }}
<view class="sorter-table" v-if="item.sorter">
<view :class="['sorter-table-icon',item.sorterMode==='_asc'&&`sorting${item.sorterMode||''}`]"></view>
<view :class="['sorter-table-icon',item.sorterMode==='_desc'&&`sorting${item.sorterMode||''}`]"></view>
</view>
</template>
</view>
</view>
</view>
</view>
</view>
</template>
<template v-if="!data.length">
<view class="no-data">暂无数据~~</view>
</template>
<view class="zb-table-fixed">
<view class="zb-table-tbody">
<view :class="['item-tr',highlight&&isHighlight(item,index)?'current-row':'']"
@click.stop="rowClick(item,index)"
v-for="(item,index) in transData" :key="item.key" >
<view
:style="[{
left:`${ite.left}px`,
width:`${ite.width?ite.width:'100'}px`,
flex:i===transColumns.length-1?1:'none',
minWidth:`${ite.width?ite.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:ite.align||'left',
},getCellStyle(item,ite,index,i)]"
@click="cellClick(item,index,ite)"
:class="['item-td', i <fixedLeftColumns.length&&'zb-stick-side',stripe?(index % 2) != 0?'odd':'even':'']"
v-for="(ite,i) in transColumns" :key="i">
<template v-if="ite.type==='operation'">
<view style="display: flex;align-items: center;height: 100%">
<view
v-for="ren,ind in permission(item,ite.renders,index)"
:key="ind"
@click.stop="$emit(ren.func,item,index)"
:style="{
display:'flex',
alignItems: 'center',
marginRight:ite.renders.length>1?'8px':'0'
}">
<template v-if="ren.type==='custom'">
<view :class="ren.class||''" style="cursor: pointer">
{{ren.name}}
</view>
</template>
<template v-else>
<button
:class="ren.class||''"
:type="ren.type||'primary'" :size="ren.size||'mini'">{{ren.name}}</button>
</template>
</view>
</view>
</template>
<template v-else-if="ite.type==='selection'">
<view class="checkbox-item">
<tableCheckbox @checkboxSelected="(e)=>checkboxSelected(e,item)" :cellData="item" :checked="item.checked"/>
</view>
</template>
<template v-else-if="ite.type==='img'">
<template v-if="item[ite.name]">
<view class="checkbox-item" @click.stop>
<image
@click.stop="previewImage(iImageTem,item[ite.name],iImage)"
v-for="iImageTem,iImage in imgs(item[ite.name])"
:show-menu-by-longpress="false"
:key="iImage"
:src="iImageTem" style="width: 40px;height:30px; " mode="aspectFit"></image>
</view>
</template>
<text v-else>{{ite.emptyString}}</text>
</template>
<template v-else-if="ite.type==='index'">
{{index+1}}
</template>
<template v-else>
<!-- {{ ite.filters?itemFilter(item,ite):(item[ite.name]==null||item[ite.name]==='')?ite.emptyString:item[ite.name] }}-->
{{ ite.filters?itemFilter(item,ite):formatterAction(item,ite,index,i) }}
</template>
</view>
</view>
</view>
</view>
<table-summary
v-if="showSummary"
:data="data"
:showSummary="showSummary"
:fixedLeftColumns="fixedLeftColumns"
:transColumns="transColumns"
:border="border"
:summary-method="summaryMethod"
:sumText="sumText"
/>
</view>
</scroll-view>
</view>
<zb-load-more v-if="isLoadMore&&!completeLoading"/>
</view>
<!-- #endif -->
</template>
<script>
import TableCheckbox from './components/table-checkbox.vue'
import TableSummary from "./components/table-summary.vue";
import TableSideSummary from "./components/table-side-summary.vue";
import TableH5Summary from './components/table-h5-summary'
import ZbLoadMore from './components/zb-load-more'
// #ifdef H5
import {getScrollbarSize} from "./js/util";
// #endif
export default {
components:{
TableCheckbox,
TableSummary,
TableSideSummary,
TableH5Summary,
ZbLoadMore
},
props:{
highlight:{
type:Boolean,
default:false
},
itemDate:{
type:Object,
default:()=>{}
},
columns:{
type:Array,
default:()=>[]
},
showSummary:{
type:Boolean,
default:false
},
isShowLoadMore:{
type:Boolean,
default:false
},
data:{
type:Array,
default:()=>[]
},
sumText:{
type:String,
default:'合计'
},
showHeader:{
type:Boolean,
default:true
},
border:{
type:Boolean,
default:false
},
stripe:{
type:Boolean,
default:true
},
fit:{
type:Boolean,
default:false
},
rowKey:[String, Function],
summaryMethod:Function,
pullUpLoading:Function,
formatter:Function,
cellStyle:Function,
cellHeaderStyle:Function,
permissionBtn:Function,
},
computed:{
loadMoreHeight(){
return this.isLoadMore?40:0
},
fixedLeftColumns(){
let arr = []
for(let i=0;i<this.columns.length;i++){
let item = this.columns[i]
if(item.fixed){
arr.push(item)
}else {
break
}
}
return arr
},
imgs(){
return (item)=>{
return typeof item==='string'?[item]:item
}
},
itemfilters(){
return(item,ite)=>{
if(item[ite.name]==null){
return ite.emptyString
}
return item[ite.name]
}
},
scrollbarSize(){
// #ifdef H5
return getScrollbarSize()
// #endif
// #ifndef H5
return 0
// #endif
},
isFixedLeft(){
if(!this.columns.length){
return false
}
if(!this.data.length){
return false
}
let [firstArr] = this.columns
return !!firstArr.fixed;
},
transColumns(){
if(this.fit){
this.columns.forEach(column=>{
if(column.type==="operation"&&column.renders){
let str = ''
column.renders.map((item)=>{
str+=item.name
})
column.width = this.getTextWidth(str)+column.renders.length*40
}else if(column.type==="img"){
}else if(column.type==="selection"){
}else{
let arr = [this.getTextWidth(column.label)]
this.data.forEach(data=>{
let str = (data[column.name]+'')
if(str==='undefined'){
arr.push(30)
}else{
let width = this.getTextWidth(str)
arr.push(width)
}
})
column.width = Math.max(...arr)+20
}
})
}
let number = 0
this.columns.forEach((item,index)=>{
if(item.type==="operation"&&item.renders&&!item.width){
let str = ''
item.renders.map((item)=>{
str+=item.name
})
item.width = this.getTextWidth(str)+item.renders.length*40
}
if(item.type==="img"){
if(!item.width){
let arr = []
let widImg = this.getTextWidth(item.label)
this.data.forEach(data=>{
if(data[item.name]){
let urls = typeof data[item.name]==='string'?[data[item.name]]:data[item.name]
arr.push(urls.length)
}
item.width = Math.max(...arr)*40+widImg
})
}
}
if(item.fixed){
if(index===0){
item.left = 0
number+=item.width
}else {
item.left = number
number+=item.width
}
}
item.emptyString = item.emptyString||'--'
})
return this.columns
},
transData(){
let flag = this.columns.some(item=>item.type==='selection')
this.data.forEach((item,index)=>{
if(flag){
if(item.checked){
if(!this.selectArr.length){
this.selectArr.push(item)
}
}
}
if(this.rowKey){
if(typeof this.rowKey==='function'){
item.key = Object.freeze(this.rowKey(item))||Date.now()
}else {
item.key = Object.freeze(item[this.rowKey])||Date.now()
}
}else {
item.key = index
}
})
if(flag){
if(this.data.length){
let le = this.data.filter(item=>item.checked).length
if(le){
if(le===this.data.length){
this.checkedAll = true
}else {
this.indeterminate = true
}
}else {
this.checkedAll = false
this.indeterminate = false
this.selectArr = []
}
}else {
this.checkedAll = false
this.indeterminate = false
this.selectArr = []
}
}
return this.data
},
isHighlight(){
return (item,index)=>{
if(this.rowKey){
return item.key === this.currentRow['key']
}else{
return index === this.currentRowIndex
}
}
},
getHeaderCellStyle() {
return (column, columnIndex,childIndex)=>{
const cellStyle = this.cellHeaderStyle;
if(typeof cellStyle==='function'){
return cellStyle({ column, columnIndex})
}
return {}
}
},
getCellStyle() {
return (row, column, rowIndex, columnIndex)=>{
const cellStyle = this.cellStyle;
if(typeof cellStyle==='function'){
return cellStyle({row, column, rowIndex, columnIndex})
}
return {}
}
},
},
data() {
return {
button:[],
alipayScrollTop:0,
alipayScrollOldTop:0,
alipayFlag:false,
bodyTableLeft:0,
headerTableLeft:0,
lastScrollLeft:0,
isLoadMore:false,
headerFooterTableLeft:0,
leftFiexScrollTop:0,
bodyScrollTop:0,
currentDriver:null,
currentDriver1:null,
bodyTime:null,
currentRowIndex:null,
currentRow: {},
bodyTime1:null,
headerTime:null,
debounceTime:null,
operation:{},
completedFlag:false,
selectArr:[],
indeterminate:false,
checkedAll:false,
completeLoading:false,
aliTime:null,
}
},
created(){
},
mounted(){
// setTimeout(()=>{
// uni.createSelectorQuery().in(this).select(".top-header-uni").boundingClientRect( data => {
// console.log('data=======',data)
// //data 可以打印data输出看详细数据有很多数据信息
// var left = data.width;//表示元素宽度
// }).exec();
// },1000)
},
beforeDestroy(){
this.aliTime&&clearTimeout(this.aliTime)
this.debounceTime&&clearTimeout(this.debounceTime)
this.bodyTime1&&clearTimeout(this.bodyTime1)
this.bodyTime&&clearTimeout(this.bodyTime)
this.selectArr = []
this.indeterminate = false
this.checkedAll = false
},
methods: {
clearSelection(){
this.transData.forEach(item=>{
item.checked = false
})
this.selectArr = []
this.indeterminate = false
this.checkedAll = false
},
formatterAction(row,column,rowIndex,columnIndex){
if(column.formatter&&typeof this.formatter==='function'){
return this.formatter(row,column,rowIndex,columnIndex)
}
return (row[column.name]==null||row[column.name]==='')?column.emptyString:row[column.name]
},
permission(item,renders,index){
if(this.permissionBtn&&typeof this.permissionBtn==='function'){
return this.permissionBtn(item,renders,index)
}
return renders
},
pullUpCompleteLoading(type){
this.isLoadMore = false
if(type==='ok'){
this.completeLoading = true
}
},
scrollAlipay(e){
if(!this.alipayScrollOldTop){
this.alipayScrollOldTop = e.detail.scrollTop
}
this.aliTime&&clearTimeout(this.aliTime)
this.aliTime = setTimeout(()=>{
if(this.alipayFlag&&e.detail.scrollTop>this.alipayScrollOldTop){
this.pullLoad()
}
this.alipayFlag = false
this.alipayScrollOldTop = null
},500)
},
pullLoad(){
if(this.isShowLoadMore){
this.isLoadMore = true
this.$emit('pullUpLoading')
let that = this
this.pullUpLoading&&this.pullUpLoading.call(this.$parent.$parent, (type)=>{
that.isLoadMore = false
if(type==='ok'){
that.completeLoading=true
}
})
}
},
scrolltolower(e){
this.alipayFlag = true
if(e.detail.direction==='bottom'){
this.pullLoad()
}
// this.pullUpLoading.call(this.$parent)
},
previewImage(item,url,current){
let urls = typeof url==='string'?[url]:url
uni.previewImage({
current,
urls:urls
})
},
resetHighlight(){
this.currentRowIndex = null
this.currentRow = {}
},
cellClick(row,index,column){
this.$emit('cellClick',row,index,column)
},
rowClick(row,index){
if(this.highlight){
this.currentRowIndex = index
this.currentRow = row
this.$emit('currentChange',row,index)
}
this.$emit('rowClick',row,index)
},
checkboxSelectedAll(e){
this.indeterminate = false
if(e.checked){
this.selectArr = []
this.checkedAll = true
this.data.forEach(item=>{
// this.$set(item,'checked',true)
item.checked = true
this.selectArr.push(item)
})
}else{
this.checkedAll = false
this.data.forEach(item=>{
this.$set(item,'checked',false)
})
this.selectArr = []
}
// #ifndef H5 || APP-PLUS
this.$forceUpdate()
// #endif
this.$emit('toggleAllSelection',e.checked,this.selectArr)
},
checkboxSelected(e,item){
// #ifdef H5 || APP-PLUS
this.$set(item,'checked',e.checked)
// #endif
// #ifndef H5 || APP-PLUS
this.data.forEach(item=>{
if(item.key===e.data.key){
item.checked = e.checked
}
})
// #endif
item.checked = e.checked
e.data.checked = e.checked
if(e.checked){
this.selectArr.push(e.data)
}else{
this.selectArr = this.selectArr.filter(item=>item.key!==e.data.key)
}
if(this.selectArr.length===this.transData.length){
this.indeterminate = false
this.checkedAll = true
}else{
this.indeterminate = true
this.checkedAll = false
}
if(!this.selectArr.length){
this.checkedAll = false
this.indeterminate = false
}
// #ifndef H5 || APP-PLUS
this.$forceUpdate()
// #endif
this.$emit('toggleRowSelection',e.checked,this.selectArr)
},
itemFilter(item,ite){
if(ite.filters&&ite.name){
let key = item[ite.name]
return ite.filters[key]||''
}
return item[ite.name]||ite.emptyString
},
// 默认字体为微软雅黑 Microsoft YaHei,字体大小为 14px
getTextWidth(str) {
if(str.length<3){
return 40
}
let regx = /^[0-9]+.?[0-9]*$/
let flexWidth = 0
for (const char of str) {
if ((char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z')) {
// 如果是英文字符为字符分配8个单位宽度
flexWidth += 10
} else if (char >= '\u4e00' && char <= '\u9fa5') {
// 如果是中文字符为字符分配15个单位宽度
flexWidth += 15
} else if(regx.test(char)){
flexWidth += 9
}else {
// 其他种类字符为字符分配8个单位宽度
flexWidth += 7
}
}
return flexWidth
},
width(item){
return `${item.width?item.width:'100'}px`
},
showStripe(index){
if(this.currentDriver)return
if(this.stripe){
return (index % 2) != 0?'odd':'even'
}else{
return ''
}
},
//验证字符串是否是数字
checkNumber(theObj) {
var reg = /^[0-9]+.?[0-9]*$/;
if (reg.test(theObj)) {
return true;
}
return false;
},
isDate(data){
if(isNaN(data)&&!isNaN(Date.parse(data))){
return true
}
return false
},
sortAction(item,index){
if(!item.sorter){return false}
this.$set(item,'sorterMode',item.sorterMode==='_asc'?'_desc':'_asc')
if(item.sorter==='custom'){
this.$emit('sort-change',item,item.sorterMode.replace('_',''),index)
}else {
this.sortData(item)
}
// #ifndef H5 || APP-PLUS
this.$forceUpdate()
// #endif
},
sortData(item){
let key = item.name
if(item.sorterMode==='_asc'){
this.data.sort((a,b)=>{
if(this.checkNumber(a[key])){
return a[key]-b[key]
}
if(this.isDate(a[key])){
let a1 = new Date(a[key]).getTime()
let b1 = new Date(b[key]).getTime()
return a1-b1
}
})
}else {
this.data.sort((a,b)=>{
if(this.checkNumber(a[key])){
return b[key]-a[key]
}
if(this.isDate(a[key])){
let a1 = new Date(a[key]).getTime()
let b1 = new Date(b[key]).getTime()
return b1-a1
}
})
}
},
throttle(method,delay=60){
let time = null
return (...args)=>{
if(!time){
time = setTimeout(()=>{
method(...args)
time = null;
},delay)
}
}
},
debounce(method,delay=1000){
return (...args)=>{
this.debounceTime&&clearTimeout(this.debounceTime)
this.debounceTime = setTimeout(()=>{
method(...args)
},delay)
}
},
handleBodyScroll(e){
if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
this.currentDriver = e.currentTarget.id
this.headerTableLeft = e.detail.scrollLeft
this.headerFooterTableLeft = e.detail.scrollLeft
this.leftFiexScrollTop = e.detail.scrollTop
this.bodyTime&&clearTimeout(this.bodyTime)
this.bodyTime = setTimeout(()=>{
this.currentDriver=null
},200)
},
leftFixedScrollAction(e){
if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
this.currentDriver = e.currentTarget.id
this.bodyScrollTop = e.detail.scrollTop
this.bodyTime&&clearTimeout(this.bodyTime)
this.bodyTime = setTimeout(()=>{
this.currentDriver=null
},200)
},
scrollToLeft(e){
if(this.currentDriver1&&this.currentDriver1!==e.currentTarget.id)return
this.currentDriver1 = e.currentTarget.id
if(e.detail.direction==='left'&&this.headerTableLeft<10){
this.headerTableLeft = 0
}else if(e.detail.direction==='top'&&this.leftFiexScrollTop<10){
this.leftFiexScrollTop = 0
}
this.bodyTime&&clearTimeout(this.bodyTime)
this.bodyTime = setTimeout(()=>{
this.currentDriver1=null
},200)
},
scrollToFixedLeft(e){
if(this.currentDriver1&&this.currentDriver1!==e.currentTarget.id)return
this.currentDriver1 = e.currentTarget.id
if(e.detail.direction==='top'&&this.bodyScrollTop<10){
this.bodyScrollTop = 0
}
this.bodyTime&&clearTimeout(this.bodyTime)
this.bodyTime = setTimeout(()=>{
this.currentDriver1=null
},200)
},
handleTableScrollLeft(e,type){
if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
this.currentDriver = e.currentTarget.id
this.bodyTableLeft = e.detail.scrollLeft
this.headerFooterTableLeft = e.detail.scrollLeft
this.bodyTime&&clearTimeout(this.bodyTime)
this.bodyTime = setTimeout(()=>{
this.currentDriver=null
},200)
},
handleFooterTableScrollLeft(e){
if(this.currentDriver&&this.currentDriver!==e.currentTarget.id)return
this.currentDriver = e.currentTarget.id
this.bodyTableLeft = e.detail.scrollLeft
this.headerTableLeft = e.detail.scrollLeft
this.bodyTime&&clearTimeout(this.bodyTime)
this.bodyTime = setTimeout(()=>{
this.currentDriver=null
},200)
}
}
}
</script>
<style lang="scss">
.zb-table-fixed-left{
/*去除左边滚动条 */
scroll-view ::-webkit-scrollbar {
display: none !important;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
}
.zb-table-header{
///*去除头部滚动条 */
scroll-view ::-webkit-scrollbar {
display: none !important;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
}
</style>
<style lang="scss" scoped>
.sorter-table{
position: absolute;
right: 6px;
top:50%;
transform:translateY(-50%);
.sorter-table-icon{
width: 0;
height: 0;
color: #dcdcdc;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
.sorter-table-icon:first-child{
border-bottom: 5px solid currentColor;
}
.sorter-table-icon:last-child{
margin-top: 1.5px;
border-top: 5px solid currentColor;
}
.sorting_desc{
color: #2979ff;
}
.sorting_asc{
color: #2979ff;
}
}
.checkbox-item{
display: flex;align-items: center;justify-content: center;width: 100%;height: 100%
}
.no-data{
width: 100%;
height: 80rpx;
display: flex;
justify-content: center;
align-items: center;
border-bottom: 1px solid #e8e8e8;
}
.item-th{
position: relative;
flex-shrink: 0;
width: 100px;
overflow-wrap: break-word;
border-bottom: 1px solid #e8e8e8;
transition: background 0.3s;
padding-right: 20px;
word-break:keep-all; /* 不换行 */
white-space:nowrap; /* 不换行 */
overflow:hidden; /* 内容超出宽度时隐藏超出部分的内容 */
text-overflow:ellipsis; /* 当对象内文本溢出时显示省略标记(...) 需与overflow:hidden;一起使用。*/
overflow-wrap: break-word;
}
.zb-table{
height: 100%;
overflow: hidden;
width: 100%;
display: flex;
flex-direction: column;
font-size: 12px;
position: relative;
.zb-table-content{
//height: 100%;
//flex: 1;
position: relative;
overflow: hidden;
}
.zb-table-fixed{
min-width: 100%;
}
.zb-table-body{
position: relative;
background: #fff;
transition: opacity 0.3s;
}
.item-tr{
display: flex;
//height: 41px;
}
.item-td{
flex-shrink: 0;
width: 100px;
padding-left: 8px;
height: 40px;
line-height: 40px;
padding-right: 20px;
box-sizing: border-box;
word-break:keep-all; /* 不换行 */
white-space:nowrap; /* 不换行 */
overflow:hidden; /* 内容超出宽度时隐藏超出部分的内容 */
text-overflow:ellipsis; /* 当对象内文本溢出时显示省略标记(...) 需与overflow:hidden;一起使用。*/
overflow-wrap: break-word;
border-bottom: 1px solid #e8e8e8;
//transition: background 0.3s;
}
.zb-table-fixed-left .zb-table-header{
overflow-y: hidden;
}
.zb-table-header {
overflow: hidden;
background: #fafafa;
.item-th{
padding-left: 8px;
line-height: 39px;
height: 40px;
//display: flex;
//align-items: center;
box-sizing: border-box;
}
}
.zb-table-fixed-left .zb-table-fixed{
background: #fff;
}
.zb-table-fixed-right .zb-table-fixed{
background: #fff;
}
.zb-table-body-inner{
height: 100%;
// overflow: scroll;
}
.zb-table-fixed-left{
position: absolute;
top: 0;
z-index: 1;
overflow: hidden;
border-radius: 0;
height: 100%;
//transition: box-shadow 0.3s ease;
}
.odd{
background-color:rgba(249,249,249,0.6);
//height: 100%;
width: 100%;
}
.even{
background-color:white ;
//height: 100%;
width: 100%;
}
}
.scroll-left-fixed{
.zb-table-fixed-left {
left: 0;
box-shadow: 6px 0 6px -4px #ccc;
}
}
.zb-table-applet{
height: 100%;
//overflow: hidden;
width: 100%;
position: relative;
display: flex;
flex-direction: column;
font-size: 12px;
.zb-table-content{
//height: 100%;
flex: 1;
overflow: hidden;
position: relative;
}
.zb-table-fixed{
min-width: 100%;
width: fit-content;
}
.zb-table-body{
position: relative;
background: #fff;
transition: opacity 0.3s;
}
.item-tr{
display: flex;
//height: 41px;
}
.item-td{
flex-shrink: 0;
width: 100px;
padding-left: 8px;
height: 40px;
line-height: 40px;
padding-right:20px;
box-sizing: border-box;
word-break:keep-all; /* 不换行 */
white-space:nowrap; /* 不换行 */
overflow:hidden; /* 内容超出宽度时隐藏超出部分的内容 */
text-overflow:ellipsis; /* 当对象内文本溢出时显示省略标记(...) 需与overflow:hidden;一起使用。*/
overflow-wrap: break-word;
border-bottom: 1px solid #e8e8e8;
//transition: background 0.3s;
}
.zb-table-header {
//overflow: hidden;
position: sticky;
top: 0;
z-index: 2;
//width: fit-content;
.item-th{
padding-left: 8px;
line-height: 39px;
height: 40px;
box-sizing: border-box;
background: #fafafa;
}
.zb-stick-side{
position: sticky;
top: 0;
left: 0;
z-index: 2;
//border-right: solid 1rpx #dbdbdb;
box-sizing: border-box;
background: #fafafa;
//box-shadow: 6px 0 6px -4px #ccc;
}
}
.zb-table-fixed-left .zb-table-fixed{
background: #fff;
}
.zb-table-fixed-right .zb-table-fixed{
background: #fff;
}
.zb-table-fixed-header .zb-table-body-inner{
height: 100%;
// overflow: scroll;
}
.zb-table-fixed-left{
position: absolute;
top: 0;
z-index: 1;
overflow: hidden;
border-radius: 0;
height: 100%;
//transition: box-shadow 0.3s ease;
}
.scroll-left-fixed{
.zb-table-fixed-left {
left: 0;
box-shadow: 6px 0 6px -4px #ccc;
}
}
.odd{
background-color:rgba(249,249,249,0.6);
//height: 100%;
width: 100%;
}
.even{
background-color:white ;
//height: 100%;
width: 100%;
}
.zb-table-tbody {
.zb-stick-side{
position: sticky;
left: 0;
z-index: 1;
box-sizing: border-box;
background:white;
//box-shadow: 6px 0 6px -2px #ccc;
}
.odd{
background:#f9f9f9;
//height: 100%;
width: 100%;
}
.even{
background:white ;
//height: 100%;
width: 100%;
}
}
.current-row{
.item-td{
background-color: #ecf5ff;
}
}
}
.current-row{
.item-td{
background-color: #ecf5ff;
}
}
.zb-table-header{
height: 40px;
}
.scrollPosition{
position: absolute;right: 0;top: 0;height: 100%;background: red;
z-index: 999;
}
</style>