zouling 1 anno fa
parent
commit
50b5990e42

+ 22 - 0
components/zb-table/all.js

@@ -0,0 +1,22 @@
+export const column1 = [
+    { type:'index', label: '序号',align:'center',fixed:true,},
+    { name: 'exit', label: '出入口',align:'center',align:'center',emptyString:'--' },
+    { name: 'time', label: '开门时间',align:'center',},
+    // { name: 'sex', label: '性别',filters:{0:'男',1:'女'}},
+ //    { name: 'sx', label: '数学',sorter:true },
+ //    { name: 'yy', label: '英语',sorter:true },
+	// { name: 'operation', type:'operation',label: '操作',renders:[
+	// 	{
+	// 	    name:'编辑',
+	// 	    func:'edit' // func 代表子元素点击的事件 父元素接收的事件 父元素 @edit
+	// 	  },
+	// 	  {
+	// 	    name:'删除',
+	// 	    type:'warn',
+	// 	    func:"dele"
+	// 	  },
+	// ]},
+
+]
+
+

+ 180 - 0
components/zb-table/components/table-checkbox.vue

@@ -0,0 +1,180 @@
+<template>
+	<view class="uni-table-checkbox" @click.stop="selected">
+		<view v-if="!indeterminate" class="checkbox__inner" :class="{'is-checked':isChecked,'is-disable':isDisabled}">
+			<view class="checkbox__inner-icon"></view>
+		</view>
+		<view v-else class="checkbox__inner checkbox--indeterminate">
+			<view class="checkbox__inner-icon"></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'TableCheckbox',
+		emits:['checkboxSelected'],
+		props: {
+			indeterminate: {
+				type: Boolean,
+				default: false
+			},
+			checked: {
+				type: [Boolean,String],
+				default: false
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			index: {
+				type: Number,
+				default: -1
+			},
+			cellData: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		watch:{
+			checked(newVal){
+				if(typeof this.checked === 'boolean'){
+					this.isChecked = newVal
+				}else{
+					this.isChecked = true
+				}
+			},
+			indeterminate(newVal){
+				this.isIndeterminate = newVal
+			}
+		},
+		data() {
+			return {
+				isChecked: false,
+				isDisabled: false,
+				isIndeterminate:false
+			}
+		},
+		created() {
+			if(typeof this.checked === 'boolean'){
+				this.isChecked = this.checked
+			}
+			this.isDisabled = this.disabled
+		},
+		methods: {
+			selected() {
+				if (this.isDisabled) return
+				this.isIndeterminate = false
+				this.isChecked = !this.isChecked
+        console.log('===',this.indeterminate,this.isChecked)
+				this.$emit('checkboxSelected', {
+					checked: this.isChecked,
+					data: this.cellData
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$checked-color: #007aff;
+	$border-color: #DCDFE6;
+	$disable:0.4;
+
+	.uni-table-checkbox {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		position: relative;
+		margin: 10rpx 0;
+		cursor: pointer;
+
+		// 多选样式
+		.checkbox__inner {
+			/* #ifndef APP-NVUE */
+			flex-shrink: 0;
+			box-sizing: border-box;
+			/* #endif */
+			position: relative;
+			width: 32rpx;
+			height: 32rpx;
+			border: 2rpx solid $border-color;
+			border-radius: 4rpx;
+			background-color: #fff;
+			z-index: 1;
+
+			.checkbox__inner-icon {
+				position: absolute;
+				/* #ifdef APP-NVUE */
+				top: 4rpx;
+				/* #endif */
+				/* #ifndef APP-NVUE */
+				top: 4rpx;
+				/* #endif */
+				left: 10rpx;
+				height: 14rpx;
+				width: 6rpx;
+				border: 2rpx solid #fff;
+				border-left: 0;
+				border-top: 0;
+				opacity: 0;
+				transform-origin: center;
+				transform: rotate(45deg);
+				box-sizing: content-box;
+			}
+
+			&.checkbox--indeterminate {
+				border-color: $checked-color;
+				background-color: $checked-color;
+
+				.checkbox__inner-icon {
+					position: absolute;
+					opacity: 1;
+					transform: rotate(0deg);
+					height: 4rpx;
+					top: 0;
+					bottom: 0;
+					margin: auto;
+					left: 0px;
+					right: 0px;
+					bottom: 0;
+					width: auto;
+					border: none;
+					border-radius: 4rpx;
+					transform: scale(0.5);
+					background-color: #fff;
+				}
+			}
+			&:hover{
+				border-color: $checked-color;
+			}
+			// 禁用
+			&.is-disable {
+				/* #ifdef H5 */
+				cursor: not-allowed;
+				/* #endif */
+				background-color: #F2F6FC;
+				border-color: $border-color;
+			}
+
+			// 选中
+			&.is-checked {
+				border-color: $checked-color;
+				background-color: $checked-color;
+
+				.checkbox__inner-icon {
+					opacity: 1;
+					transform: rotate(45deg);
+				}
+
+				// 选中禁用
+				&.is-disable {
+					opacity: $disable;
+				}
+			}
+
+		}
+	}
+</style>

+ 78 - 0
components/zb-table/components/table-h5-summary.vue

@@ -0,0 +1,78 @@
+<template>
+  <view class="table-h5-footer top-header-uni" :style="{paddingRight:`${scrollbarSize}rpx`}">
+    <scroll-view class="zb-table-headers"
+                 @scroll="handleFooterTableScrollLeft"
+                 scroll-x="true"
+                 scroll-y="false"
+                 id="tableFooterHeaders"
+                 scroll-anchoring="true"
+                 :scroll-left="headerFooterTableLeft"
+                 style="padding-bottom: 0px;
+						background: #fafafa;height: 100%">
+      <view class="zb-table-fixed" >
+        <view class="zb-table-thead" style="position: relative;" >
+          <view class="item-tr">
+            <view
+                class="item-th"
+                :style="{
+	                              width:`${item.width?item.width:'200'}rpx`,
+															  flex:index===transColumns.length-1?1:'none',
+															  minWidth:`${item.width?item.width:'200'}rpx`,
+															  borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+															  borderTop:`${border?'2rpx solid #e8e8e8':''}`,
+															  textAlign:item.align||'left'
+														  }"
+                v-for="(item,index) in transColumns" :key="index">
+              {{ sums[index] }}
+            </view>
+          </view>
+        </view>
+      </view>
+    </scroll-view>
+  </view>
+</template>
+<script>
+import summary from '../js/summary.js'
+export default {
+  name:'table-footer',
+  mixins:[summary],
+}
+</script>
+<style lang="scss" scoped>
+.table-h5-footer {
+  background: #fafafa;
+  /*每个页面公共css */
+  scroll-view ::-webkit-scrollbar {
+    display: none !important;
+    width: 0 !important;
+    height: 0 !important;
+    -webkit-appearance: none;
+    background: transparent;
+  }
+  //第二种
+  ::-webkit-scrollbar{
+    display: none;
+  }
+  .item-tr{
+    display: flex;
+  }
+  .item-th{
+    padding-left: 8rpx;
+    line-height: 78rpx;
+    height: 80rpx;
+    //display: flex;
+    //align-items: center;
+    box-sizing: border-box;
+    flex-shrink: 0;
+    width: 200rpx;
+    padding-right: 8rpx;
+    word-break: keep-all;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    overflow-wrap: break-word;
+    border-bottom: 2rpx solid #e8e8e8;
+  }
+
+}
+</style>

+ 59 - 0
components/zb-table/components/table-side-summary.vue

@@ -0,0 +1,59 @@
+<template>
+  <view class="zb-table-header" style="display: flex;" >
+    <view class="item-tr" >
+      <view class='item-td'
+            :style="{
+	                       width:`${item.width?item.width:'200'}rpx`,
+	                       borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+	                       textAlign:item.align||'left'
+	                      }"
+            :key="`${index}`"
+            v-for="(item,index) in fixedLeftColumns">
+        <template >
+          {{sums[index]}}
+        </template>
+      </view>
+    </view>
+  </view>
+
+</template>
+<script>
+import summary from '../js/summary.js'
+export default {
+  mixins:[summary]
+}
+</script>
+<style lang="scss" scoped>
+.zb-table-header {
+  overflow: hidden;
+  background: #fafafa;
+  .item-th{
+    padding-left: 8rpx;
+    line-height: 78rpx;
+    height: 80rpx;
+    //display: flex;
+    //align-items: center;
+    box-sizing: border-box;
+  }
+}
+.item-tr{
+  display: flex;
+  box-sizing: border-box;
+}
+.item-td{
+  flex-shrink: 0;
+  width: 200rpx;
+  padding-left:8rpx;
+  height: 80rpx;
+  line-height: 80rpx;
+  padding-right: 8rpx;
+  box-sizing: border-box;
+  word-break: keep-all;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  overflow-wrap: break-word;
+  border-bottom: 2rpx solid #e8e8e8;
+  background: rgb(250, 250, 250);
+}
+</style>

+ 77 - 0
components/zb-table/components/table-summary.vue

@@ -0,0 +1,77 @@
+<template>
+  <view class="zb-table-footer" style="height: 80rpx;">
+    <view class="zb-table-fixed" >
+      <view class="zb-table-thead" style="position: relative;" >
+        <view class="item-tr">
+          <view
+              :class="['item-th',index <fixedLeftColumns.length&&'zb-stick-side']"
+              :style="{
+	                              left:`${item.left}rpx`,
+	                              width:`${item.width?item.width:'200'}rpx`,
+															  flex:index===transColumns.length-1?1:'none',
+															  minWidth:`${item.width?item.width:'200'}rpx`,
+															   borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+															  borderTop:`${border?'2rpx solid #e8e8e8':''}`,
+															   textAlign:item.align||'left'
+														  }"
+              v-for="(item,index) in transColumns" :key="index">
+            <template>
+              {{ sums[index]||item.emptyString }}
+            </template>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+  import summary from '../js/summary.js'
+  export default {
+    mixins:[summary]
+  }
+</script>
+<style lang="scss" scoped>
+  .zb-table-footer {
+    background: #fafafa;
+    width: fit-content;
+    min-width: 100%;
+    position: sticky;
+    bottom: 0;
+    z-index: 2;
+    .item-tr{
+      display: flex;
+      min-width: 100%;
+    }
+    .item-th{
+      padding-left: 8rpx;
+      line-height: 78rpx;
+      height: 80rpx;
+      //display: flex;
+      //align-items: center;
+      box-sizing: border-box;
+      flex-shrink: 0;
+      width: 200rpx;
+      padding-right: 8rpx;
+      word-break: keep-all;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      overflow-wrap: break-word;
+      border-bottom: 2rpx solid #e8e8e8;
+    }
+    .zb-table-fixed{
+      min-width: 100%;
+
+    }
+    .zb-stick-side{
+      position: sticky;
+      bottom:0 ;
+      left: 0;
+      z-index: 2;
+      //border-right: solid 1rpx #dbdbdb;
+      box-sizing: border-box;
+      background: #fafafa;
+      //box-shadow: 6px 0 6px -4px #ccc;
+    }
+  }
+</style>

+ 50 - 0
components/zb-table/components/zb-load-more.vue

@@ -0,0 +1,50 @@
+<template >
+  <view class="zb-load-more">
+    <image :src="base64Flower" style="" class="loading-custom-image"></image>
+    <text>正在加载中...</text>
+  </view>
+</template>
+<script>
+const base64Flower = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC';
+export default {
+  data(){
+    return{
+      base64Flower
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.zb-load-more {
+  width: 100%;
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  z-index: 999;
+  background: white;
+  display: flex;
+  height: 80rpx;
+  flex-shrink: 0;
+  align-items: center;
+  justify-content: center;
+  .loading-custom-image{
+    color: #a4a4a4;
+    margin-right: 8rpx;
+    width: 48rpx;
+    height: 48rpx;
+    /* #ifndef APP-NVUE */
+    animation: loading-circle 1s linear infinite;
+    /* #endif */
+  }
+  @keyframes loading-circle {
+    0% {
+      -webkit-transform: rotate(0deg);
+      transform: rotate(0deg);
+    }
+    100% {
+      -webkit-transform: rotate(360deg);
+      transform: rotate(360deg);
+    }
+  }
+}
+</style>

+ 88 - 0
components/zb-table/js/summary.js

@@ -0,0 +1,88 @@
+export default {
+    props:{
+        scrollbarSize:{
+            type:Number,
+            default:0
+        },
+        fixedLeftColumns:{
+            type:Array,
+            default:()=>[]
+        },
+        data:{
+            type:Array,
+            default:()=>[]
+        },
+        transColumns:{
+            type:Array,
+            default:()=>[]
+        },
+        border:{
+            type:Boolean,
+            default:false
+        },
+        showSummary:{
+            type:Boolean,
+            default:false
+        },
+        summaryMethod:{
+            type:Function
+        },
+        sumText:{
+            type:String,
+            default:'合计'
+        },
+        headerFooterTableLeft:{
+            type:Number,
+            default:0
+        },
+        handleFooterTableScrollLeft:Function,
+    },
+    data(){
+        return{
+            sums:[]
+        }
+    },
+    watch:{
+        'data':{
+            deep:true,
+            immediate:true,
+            handler(newValue,oldValue){
+                let sums = [];
+                if (this.summaryMethod) {
+                    sums = this.summaryMethod({ columns: this.transColumns, data: this.data });
+                } else {
+                    this.transColumns.forEach((column, index) => {
+                        if (index === 0) {
+                            sums[index] = this.sumText;
+                            return;
+                        }
+                        const values = this.data.map(item => Number(item[column.name]));
+                        const precisions = [];
+                        let notNumber = true;
+                        values.forEach(value => {
+                            if (!isNaN(value)) {
+                                notNumber = false;
+                                let decimal = ('' + value).split('.')[1];
+                                precisions.push(decimal ? decimal.length : 0);
+                            }
+                        });
+                        const precision = Math.max.apply(null, precisions);
+                        if (!notNumber) {
+                            sums[index] = values.reduce((prev, curr) => {
+                                const value = Number(curr);
+                                if (!isNaN(value)) {
+                                    return parseFloat((prev + curr).toFixed(Math.min(precision, 20)));
+                                } else {
+                                    return prev;
+                                }
+                            }, 0);
+                        } else {
+                            sums[index] = '';
+                        }
+                    });
+                }
+                this.sums = sums
+            },
+        }
+    }
+}

+ 51 - 0
components/zb-table/js/util.js

@@ -0,0 +1,51 @@
+/**
+ * 获取滚动条宽度
+ */
+let cached = undefined;
+
+export const getScrollbarSize = fresh => {
+	// #ifdef H5
+	
+    if (fresh || cached === undefined) {
+        let inner = document.createElement("div");
+        let innerStyle = inner.style;
+
+        innerStyle.width = "100%";
+        innerStyle.height = "200px";
+
+        let outer = document.createElement("div");
+        let outerStyle = outer.style;
+
+        outerStyle.position = "absolute";
+        outerStyle.top = 0;
+        outerStyle.left = 0;
+        outerStyle.pointerEvents = "none";
+        outerStyle.width = "200px";
+        outerStyle.height = "150px";
+        outerStyle.visibility = "hidden";
+
+        outer.appendChild(inner);
+        document.body.appendChild(outer);
+
+        // 设置子元素超出部分隐藏
+        outerStyle.overflow = "hidden";
+
+        let width1 = inner.offsetWidth;
+
+        // 设置子元素超出部分滚动
+        outer.style.overflow = "scroll";
+
+        let width2 = inner.offsetWidth;
+
+        if (width1 === width2) {
+            width2 = outer.clientWidth;
+        }
+
+        document.body.removeChild(outer);
+
+        cached = width1 - width2;
+    }
+	//#endif
+
+    return cached;
+};

+ 1255 - 0
components/zb-table/zb-table.vue

@@ -0,0 +1,1255 @@
+<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" :style="{paddingRight:`${scrollbarSize}px`}"
+          >
+	          <scroll-view class="zb-table-headers"
+							@touchmove.stop="getMove"
+	                       @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':''}`,
+															  borderRight:`${(scrollbarSize&&index===transColumns.length-1)?'':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>
+	              </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"
+					   @touchmove.stop="getMove"
+                     @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)]"
+
+	                    :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">
+                      <image
+                    @click.stop="previewImage(item,item[ite.name],index)"
+                    v-if="item[ite.name]"
+                    :show-menu-by-longpress="false"
+                    :src="item[ite.name]" style="width: 40px;height:30px; " mode="aspectFit"></image>
+                    <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'
+                      :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">
+      <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)]"
+                    :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'">
+                    <image
+                        @click.stop="previewImage(item,item[ite.name],index)"
+                        v-if="item[ite.name]"
+                        :show-menu-by-longpress="false"
+                        :src="item[ite.name]" style="width: 40px;height:30px; " mode="aspectFit"></image>
+                    <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'
+
+import {getScrollbarSize} from "./js/util";
+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:[Object,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
+    },
+    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.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&&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
+          }
+        }
+      }
+      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(){
+  },
+  methods: {
+getMove(){
+	
+},
+    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){
+		  uni.previewImage({
+			  current,
+			  urls:[url]
+		  })
+	  },
+    resetHighlight(){
+      this.currentRowIndex = null
+      this.currentRow = {}
+    },
+    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: 4px;
+  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: 4px;
+    height: 40px;
+    line-height: 40px;
+	padding-right: 4px;
+    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: 4px;
+      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: 4px;
+    height: 40px;
+    line-height: 40px;
+	padding-right:4px;
+    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: 4px;
+      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;
+}
+</style>

+ 1267 - 0
components/zb-table/zb-tables.vue

@@ -0,0 +1,1267 @@
+<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" :style="{paddingRight:`${scrollbarSize}rpx`}"
+          >
+	          <scroll-view class="zb-table-headers"
+							@touchmove.stop="getMove"
+	                       @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:'200'}rpx`,
+															  flex:index===transColumns.length-1?1:'none',
+															  minWidth:`${item.width?item.width:'200'}rpx`,
+															  borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+															  borderRight:`${(scrollbarSize&&index===transColumns.length-1)?'':border?'2rpx solid #e8e8e8':''}`,
+															  borderTop:`${border?'2rpx solid #e8e8e8':''}`,
+															  textAlign:item.align||'left',
+															  paddingRight:`${item.paddingRight?item.paddingRight:'8'}rpx`,
+														  },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 }}
+						  <block v-if="item.manfen">/{{item.manfen}}</block>
+                        <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>
+	          </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"
+					   @touchmove.stop="getMove"
+                     @scrolltolower="scrolltolower"
+	                   @scrolltoupper="(e)=>debounce(scrollToLeft)(e)"
+                     @scroll="handleBodyScroll"	:scroll-left="bodyTableLeft"	:scroll-top="bodyScrollTop"
+                     :style=" `height: calc(100% - ${showSummary?160:80}rpx)`" >
+	          <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:'200'}rpx`,
+															  flex:i===transColumns.length-1?1:'none',
+															  minWidth:`${ite.width?ite.width:'200'}rpx`,
+															  borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+                                textAlign:ite.align||'left',
+														  },cellStyle&&getCellStyle(item,ite,index,i)]"
+
+	                    :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?'16rpx':'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">
+                      <image
+                    @click.stop="previewImage(item,item[ite.name],index)"
+                    v-if="item[ite.name]"
+                    :show-menu-by-longpress="false"
+                    :src="item[ite.name]" style="width: 80rpx;height:60rpx; " mode="aspectFit"></image>
+                    <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}rpx)`}"
+      >
+	      <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:'200'}rpx`,
+	               borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+	               borderTop:`${border?'2rpx 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 }}
+				  <block v-if="item.manfen">/{{item.manfen}}</block>
+                  <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?160:80}rpx)`">
+          <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'
+                      :style="[{
+	                       width:`${item.width?item.width:'200'}rpx`,
+	                       borderRight:`${border?'2rpx 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">
+      <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}rpx`,
+	                              width:`${item.width?item.width:'200'}rpx`,
+															  flex:index===transColumns.length-1?1:'none',
+															  minWidth:`${item.width?item.width:'200'}rpx`,
+															   borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+															  borderTop:`${border?'2rpx 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||'' }}
+						<block v-if="item.manfen">/{{item.manfen}}</block>
+                        <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}rpx`,
+                      width:`${ite.width?ite.width:'200'}rpx`,
+                      flex:i===transColumns.length-1?1:'none',
+                      minWidth:`${ite.width?ite.width:'200'}rpx`,
+                      borderRight:`${border?'2rpx solid #e8e8e8':''}`,
+                      textAlign:ite.align||'left',
+                    },getCellStyle(item,ite,index,i)]"
+                    :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?'16rpx':'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'">
+                    <image
+                        @click.stop="previewImage(item,item[ite.name],index)"
+                        v-if="item[ite.name]"
+                        :show-menu-by-longpress="false"
+                        :src="item[ite.name]" style="width: 80rpx;height:60rpx; " mode="aspectFit"></image>
+                    <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'
+
+import {getScrollbarSize} from "./js/util";
+// fit 列的宽度是否自撑开
+// column 显示的列数据
+// stripe 是否为斑马纹 table
+// show-header 是否显示表头
+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:[Object,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
+    },
+    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{
+				console.log(column,23)
+			let arr = [this.getTextWidth(column.label)]
+            this.data.forEach(data=>{
+              let str = (data[column.name]+'')
+			  if(str==='undefined'){
+				   arr.push(60)
+			  }else{
+				   let width = this.getTextWidth(str)
+				   arr.push(width)
+			  }
+            })
+			      column.width = Math.max(...arr)+40
+          }
+        })
+      }
+      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.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&&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
+          }
+        }
+      }
+      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(){
+  },
+  methods: {
+getMove(){
+	
+},
+    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){
+		  uni.previewImage({
+			  current,
+			  urls:[url]
+		  })
+	  },
+    resetHighlight(){
+      this.currentRowIndex = null
+      this.currentRow = {}
+    },
+    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 80
+      }
+      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 += 20
+        } else if (char >= '\u4e00' && char <= '\u9fa5') {
+          // 如果是中文字符,为字符分配15个单位宽度
+          flexWidth += 30
+        } else if(regx.test(char)){
+          flexWidth += 18
+        }else {
+          // 其他种类字符,为字符分配8个单位宽度
+          flexWidth += 14
+        }
+      }
+      return flexWidth
+    },
+    width(item){
+      return `${item.width?item.width:'200'}rpx`
+    },
+    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: 2rpx;
+  top:50%;
+  transform:translateY(-50%);
+  .sorter-table-icon{
+    width: 0;
+    height: 0;
+    color: #dcdcdc;
+    border-right: 8rpx solid transparent;
+    border-left: 8rpx solid transparent;
+  }
+  .sorter-table-icon:first-child{
+    border-bottom: 14rpx solid currentColor;
+  }
+  .sorter-table-icon:last-child{
+    margin-top: 3rpx;
+    border-top: 14rpx 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: 200rpx;
+  overflow-wrap: break-word;
+  border-bottom: 2rpx solid #e8e8e8;
+  transition: background 0.3s;
+  padding-right: 8rpx;
+  word-break:keep-all;           /* 不换行 */
+  white-space:nowrap;          /* 不换行 */
+  overflow:hidden;               /* 内容超出宽度时隐藏超出部分的内容 */
+  text-overflow:ellipsis;         /* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
+  overflow-wrap: break-word;
+  font-weight: bold;
+  font-size: 26rpx;
+  color: #161616;
+}
+.zb-table{
+  height: 100%;
+  overflow: hidden;
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  font-size: 28rpx;
+  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:200rpx;
+    padding-left: 8rpx;
+    height: 80rpx;
+    line-height: 80rpx;
+	padding-right: 8rpx;
+    box-sizing: border-box;
+    word-break:keep-all;           /* 不换行 */
+    white-space:nowrap;          /* 不换行 */
+    overflow:hidden;               /* 内容超出宽度时隐藏超出部分的内容 */
+    text-overflow:ellipsis;         /* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
+    overflow-wrap: break-word;
+    border-bottom: 2rpx solid #e8e8e8;
+    //transition: background 0.3s;
+  }
+
+  .zb-table-fixed-left .zb-table-header{
+    overflow-y: hidden;
+  }
+  .zb-table-header {
+    overflow: hidden;
+    background: #F4F9FC;
+    .item-th{
+      padding-left: 8rpx;
+      line-height: 78rpx;
+      height: 80rpx;
+      //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: #F4F9FC;
+    //height: 100%;
+    width: 100%;
+  }
+  .even{
+    background-color:white ;
+    //height: 100%;
+    width: 100%;
+  }
+}
+.scroll-left-fixed{
+  .zb-table-fixed-left {
+    left: 0;
+    box-shadow: 12rpx 0 12rpx -8rpx #ccc;
+  }
+}
+.zb-table-applet{
+  height: 100%;
+  //overflow: hidden;
+  width: 100%;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  font-size: 28rpx;
+  .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: 200rpx;
+    padding-left: 8rpx;
+    height: 80rpx;
+    line-height: 80rpx;
+	padding-right:8rpx;
+    box-sizing: border-box;
+    word-break:keep-all;           /* 不换行 */
+    white-space:nowrap;          /* 不换行 */
+    overflow:hidden;               /* 内容超出宽度时隐藏超出部分的内容 */
+    text-overflow:ellipsis;         /* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
+    overflow-wrap: break-word;
+    border-bottom: 2rpx 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: 8rpx;
+      line-height: 78rpx;
+      height: 80rpx;
+      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: 12rpx 0 12rpx -8rpx #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: 80rpx;
+}
+</style>

+ 363 - 0
pages/video/index.vue

@@ -0,0 +1,363 @@
+<template>
+	<view>
+		<view class="navbox">
+			<uni-nav-bar  color="#ffffff" leftWidth="200rpx" title="实时监控"  :background-color="backgroundColor" :border="false" statusBar='true' fixed="true">
+				<block slot="left">
+					<picker range-key='name' :value="adridx" :range="adrlist"    @change='bindDateChangea'>
+						<view class="chekt">
+							<view class="over">{{address|| "南大门"}}</view>
+							<image :src="upimg"></image>
+						</view>
+					</picker>
+				</block>
+			</uni-nav-bar>
+		</view>
+		<image :src="navbg" class="navbg"></image>
+		<view class="zxmain" :style="'margin-top:-'+marTop+'rpx;'">
+			<view class="vidbox mb18">
+				<!-- #ifdef APP-PLUS -->
+				<video :src="videourl" id="myvideo" autoplay controls></video>
+				<!-- #endif -->
+				<!-- #ifdef H5 -->
+				<!-- #endif -->
+				<!-- #ifdef MP-WEIXIN -->
+				<!-- #endif -->
+				
+				<!-- <image :src="mjimg"></image>
+				<view class="vidfot flexc">
+					<view class="flex1 vtit">2024/06/21 星期五 15:59:12</view>
+					<view class="vimgs">
+						<image :src="voiceimg" class="imga"></image>
+					</view>
+					<view class="vimgs">
+						<image :src="bigimg" class="imgb"></image>
+					</view>
+				</view> -->
+			</view>
+			<view class="openbox flexcj">
+				<view class="btns bga">
+					<image :src="openimg"></image>
+					开门
+				</view>
+				<view class="btns bgb">
+					<image :src="openimg"></image>
+					关门
+				</view>
+			</view>
+			<!-- 列表 -->
+			<view class="vlisttop flexcj">
+				<view class="vlleft flexc">
+					<image :src="mjimg"></image>门禁记录
+				</view>
+				<picker mode="date" @change='bindDateChangeb'>
+					<view class="rlleft flexc">
+						<view>2024/06/21</view>
+						<image :src="hupimg"></image>
+					</view>
+				</picker>
+			</view>
+			<!-- 表格 -->
+			<view class="table" :style="tabflag?'height:calc(100vh - '+tabscheight+'rpx)':''">
+				<zb-table
+				  :show-header="true"
+				  :columns="column1"
+				  :stripe="true"
+				  :fit="false"
+				  :isShowLoadMore="reachflag"
+				  
+				  :data="list"></zb-table>
+				  <!-- @rowClick="rowClick"
+				  @toggleRowSelection="toggleRowSelection"
+				  @toggleAllSelection="toggleAllSelection"   -->
+			</view>
+		</view>
+		
+		<!-- 第一道;手机号,发送验证码,门就开,记录车牌号,直接进
+		第二种:需要审核,预约
+		办公人员,配置进门区域,
+		访客配置 进门区域 -->
+		
+	<footers v-if="isfootflag" :footerindex="footerindex"></footers>
+  </view>
+</template>
+
+<script>
+	import { checkPermi, checkRole } from "@/utils/permission"; // 权限判断函数
+	import self from '@/utils/location.js';
+	import yList from "@/components/order/list.vue"
+	let { calendar } = require("@/components/lunc-calendar/calendar.js");
+	import {getCameraList,getCameraVideo} from "@/api/mine/order.js"
+	import {column1} from '@/components/zb-table/all.js'
+	import {getDictionaryFn} from "@/api/mine/register.js"
+	import footers from '@/components/footer/footer.vue'
+	import zbTable from "@/components/zb-table/zb-tables.vue"
+  export default {
+	components:{yList,footers,zbTable},
+	data(){
+		return{
+			column1,
+			footerindex:'video',
+			isfootflag:true,
+			navbg:require("@/static/images/vibg.png"),
+			upimg:require("@/static/images/order/up.png"),
+			hupimg:require("@/static/images/order/hup.png"),
+			mjimg:require("@/static/images/order/control.png"),
+			bigimg:require("@/static/images/order/pre.png"),
+			voiceimg:require("@/static/images/order/voice.png"),
+			openimg:require("@/static/images/order/open.png"),
+			closeimg:require("@/static/images/order/close.png"),
+			resetimg:require('@/static/images/order/reset.png'),
+			wresetimg:require('@/static/images/order/wreset.png'),
+			backgroundColor: "transparent",
+			list:[{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+				{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+				{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+				{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+				{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+				{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+				{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+				{exit:'南大门',time:'16:26:37'},{exit:'北大门',time:'16:26:38'},
+			],
+			pageSize: 10,
+			pageNum: 1,
+			reachflag: false,
+			wtdt:'',
+			adridx:0,
+			address:'',
+			adrlist:[{label:'南大门',value:'0'},{label:'北大门',value:'1'}],//阅读状态
+			fixedflag:false,
+			videourl:'',
+			nvaHeight:44,
+			marTop:0,//距离顶部的距离
+			stubarHeight:0,//
+			tabtop:0,//表格距离顶部的距离
+			tabflag:false,
+			tabscheight:0,//减去的部分
+		}
+	},
+	onPageScroll(e) {
+		var scrollTop = Number(e.scrollTop);
+		if (scrollTop > 0) {
+			this.backgroundColor = '#0491FD'
+		} else {
+			this.backgroundColor = 'transparent'
+		}
+		if(scrollTop<this.tabtop){
+			this.tabflag=false;
+		}else{
+			this.tabflag=true;
+		}
+	},
+	onLoad: function() {
+		uni.$on('refreshdatalist',(e) => {
+			this.reachflag=false;
+			this.pageNum=1;
+			this.list=[];
+			this.getDataFn();
+		})
+		
+		this.init()
+		// this.getDataFn()
+		uni.getSystemInfo({
+			success: (e) => {
+				this.stubarHeight=Number(e.statusBarHeight);
+				this.nvaHeight = Number(e.statusBarHeight)+44;
+				this.tabscheight=Number(this.nvaHeight)*2+100;
+			}
+		})
+		// 3c8cadac11af4f1298a2882addc8788d
+	},
+	onUnload() {
+		uni.$off('refreshdatalist')
+	},
+
+	onShow() {
+	},
+	mounted() {
+		this.getHeightFn()
+	},
+	// 上拉触底加载更多触发事件
+	onReachBottom() {
+		if (this.reachflag) {
+			this.pageNum++
+			this.getDataFn()
+		}
+	},
+	methods:{
+		checkPermi, checkRole,
+		bindDateChangea(e){
+			var val=e.detail.value;
+			this.address=this.adrlist[val].name;
+			this.indexCode=this.adrlist[val].indexCode;
+			// 获取直播视频
+			this.getCameraVideo()
+		},
+		getCameraVideo(){
+			// 设备
+			getCameraVideo(this.indexCode).then(res=>{
+				if(res.code==200){
+					var data=res.data.data;
+					if(data){
+						this.videourl=data.url
+					}
+				}else{
+					this.$toast(res.msg)
+				}
+			}) 
+		},
+		bindDateChangeb(){
+			
+		},
+		getrefreshData(){
+			this.pageNum=1;
+			this.list=[];
+			this.reachflag=true;
+			this.getDataFn()
+		},
+		getHeightFn(){
+			let query = uni.createSelectorQuery().in(this);
+			//需要给黄色区域设置一个id标识,在这里是demo
+			query.select('.navbox').boundingClientRect(data => {
+				var top=data.top<0 ? -data.top : data.top;
+				var stubarHeight=Number(this.stubarHeight);
+				this.marTop =stubarHeight > 0?692 - Number(data.height)*2 : 692 - Number(data.height)*2 + 40 //赋值,待会要用
+				if (top <=this.nvaHeight) {
+					const opacity = top / 100 // 计算透明度值
+					const color = `rgba(4, 145, 253, ${opacity})`
+					this.backgroundColor = color // 更新盒子背景颜色
+				} else {
+					this.backgroundColor = '#00A9F0'
+				}
+				if(top>2){
+					this.scroflag=true
+				}else{
+					this.scroflag=false
+				}
+			}).exec();
+			query.select(".table").boundingClientRect(data => {
+				var top=data.top<0 ? -data.top : data.top;
+				this.tabtop=Number(top)-Number(this.nvaHeight)
+			}).exec();
+		},
+		init(){
+			// 设备
+			var params={
+				pageSize:100,
+				pageNo: 1,
+			}
+			getCameraList(params).then(res=>{
+				if(res.code==200){
+					var data=res.data.data;
+					if(data.list&&data.list.length>0){
+						this.adrlist =data.list;
+						this.address=data.list[0].name;
+						this.indexCode=data.list[0].indexCode;
+						this.getCameraVideo()
+					}
+				}else{
+					this.$toast(res.msg)
+				}
+			}) 
+			// 门卫
+			// getDictionaryFn('is_read').then(res=>{
+			// 	if(res.code==200){
+			// 		this.ydztlist = res.data.map(v => {
+			// 			return {
+			// 				label: v.dictLabel,
+			// 				value: v.dictValue
+			// 			}
+			// 		})
+			// 	}
+			// })
+		},
+		getDataFn(){
+			var params={
+				pageSize:this.pageSize,
+				pageNo: this.pageNum,
+				// visitType:3
+			}
+			getCameraList(params).then(res=>{
+				if(res.code==200){
+					if (res.rows.length < this.pageSize) {
+						this.reachflag = false
+						this.wtdt = '到底了~';
+					} else {
+						var num = parseInt(res.rows.length) + parseInt(this.pageSize) * parseInt(this.pageNum -	1)
+						if (num < res.total) {
+							this.reachflag = true
+							this.wtdt = '上拉加载更多'
+						} else {
+							this.reachflag = false
+							this.wtdt = '到底了~';
+						}
+					}
+					if (this.pageNum == 1) {
+						this.list = res.rows;
+					} else {
+						this.list = this.list.concat(res.rows)
+					}
+				}else{
+					this.$toast(res.msg)
+				}
+			}) 
+			
+		},
+	},
+	
+  }
+</script>
+<style>
+page{background: #ffffff;}
+</style>
+<style lang="scss" scoped>
+.navbox /deep/ .uni-navbar__header-container {align-items: center;padding-left: 0;}
+.navbox /deep/ uni-picker{flex: 1;}
+.navbox{position: fixed;left: 0;right: 0;top: 0;z-index: 4;	
+}
+.chekt{font-weight: bold;font-size: 30rpx;color: #FFFFFF;display: flex;align-items: center;width: 200rpx;
+	view{flex: 0 1 auto;min-width: 100rpx;}
+	image{width: 16rpx;height: 10rpx;margin-left: 10rpx;flex: 0 0 auto;}
+}
+.reset{width:56rpx; height: 88rpx;display: flex;align-items: center;justify-content: center;
+	image{width: 26rpx;height: 30rpx;}
+}
+.navbg{width: 100%;height: 692rpx;}	
+.vidbox{overflow: hidden;
+	border-radius: 14rpx;box-sizing: border-box;width:100%;height: 444rpx;position: relative;
+	video{width: 100%;height: 450rpx;}
+	.vidfot{padding: 0 20rpx 0 30rpx;
+		height: 76rpx;background: rgba(0, 0, 0, 0.5);position: absolute;left: 0;right: 0;bottom: 0;
+		.vtit{font-weight: 500;font-size: 22rpx;color: #FFFFFF;}
+		.vimgs{width: 50rpx;height: 50rpx;display: flex;align-items: center;justify-content: center;margin-left: 28rpx;
+			.imga{width: 30rpx;height: 22rpx;}
+			.imgb{width: 30rpx;height: 30rpx;}
+		}
+	}
+}
+.openbox{margin-bottom: 36rpx;
+	.btns{width: 320rpx;height: 98rpx;border-radius: 14rpx;display: flex;align-items: center;justify-content: center;
+		font-weight: bold;font-size: 28rpx;color: #FFFFFF;
+		image{width: 24rpx;height: 20rpx;margin-right: 14rpx;}
+		
+		&.bga{background: #0391FD;}
+		&.bgb{background: #58CA5C;}
+	}
+}
+.vlisttop{font-weight: bold;font-size: 30rpx;color: #161616;padding: 16rpx 0;margin-bottom: 20rpx;
+	.vlleft{flex: 1;
+		image{width: 26rpx;height: 26rpx;margin-right: 12rpx;}
+	}
+	.rlleft{
+		view{font-weight: bold;font-size: 26rpx;color: #0391FD;min-width: 152rpx;}
+		image{width: 18rpx;height: 10rpx;margin-left: 12rpx;}
+	}
+}
+.table{
+	// height: calc();
+	overflow: auto;
+}
+.zxmain{position: relative;padding: 0 32rpx;
+				
+}
+
+</style>

BIN
static/images/order/close.png


BIN
static/images/order/control.png


BIN
static/images/order/hup.png


BIN
static/images/order/open.png


BIN
static/images/order/pre.png


BIN
static/images/order/reset.png


BIN
static/images/order/up.png


BIN
static/images/order/voice.png


BIN
static/images/order/wreset.png


BIN
static/images/tabbar/icon_yq_sx_xl.png


BIN
static/images/tabbar/video.png


BIN
static/images/tabbar/video_.png


BIN
static/images/vibg.png