This commit is contained in:
houjunxiang
2025-10-09 18:19:55 +08:00
parent f2ffc65094
commit 386f1e7466
1553 changed files with 284685 additions and 32820 deletions

View File

@@ -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: 5px 0;
cursor: pointer;
// 多选样式
.checkbox__inner {
/* #ifndef APP-NVUE */
flex-shrink: 0;
box-sizing: border-box;
/* #endif */
position: relative;
width: 16px;
height: 16px;
border: 1px solid $border-color;
border-radius: 2px;
background-color: #fff;
z-index: 1;
.checkbox__inner-icon {
position: absolute;
/* #ifdef APP-NVUE */
top: 2px;
/* #endif */
/* #ifndef APP-NVUE */
top: 2px;
/* #endif */
left: 5px;
height: 7px;
width: 3px;
border: 1px 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: 2px;
top: 0;
bottom: 0;
margin: auto;
left: 0px;
right: 0px;
bottom: 0;
width: auto;
border: none;
border-radius: 2px;
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>

View File

@@ -0,0 +1,78 @@
<template>
<view class="table-h5-footer top-header-uni" :style="{paddingRight:`${scrollbarSize}px`}">
<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:'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">
{{ 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: 8px;
line-height: 39px;
height: 40px;
//display: flex;
//align-items: center;
box-sizing: border-box;
flex-shrink: 0;
width: 100px;
padding-right: 20px;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
overflow-wrap: break-word;
border-bottom: 1px solid #e8e8e8;
}
}
</style>

View File

@@ -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:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
:key="`15255966555${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: 8px;
line-height: 39px;
height: 40px;
//display: flex;
//align-items: center;
box-sizing: border-box;
}
}
.item-tr{
display: flex;
box-sizing: border-box;
}
.item-td{
flex-shrink: 0;
width: 100px;
padding-left: 8px;
height: 40px;
line-height: 40px;
padding-right: 20px;
box-sizing: border-box;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
overflow-wrap: break-word;
border-bottom: 1px solid #e8e8e8;
background: rgb(250, 250, 250);
}
</style>

View File

@@ -0,0 +1,77 @@
<template>
<view class="zb-table-footer" style="height: 40px;">
<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}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>
{{ 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: 8px;
line-height: 39px;
height: 40px;
//display: flex;
//align-items: center;
box-sizing: border-box;
flex-shrink: 0;
width: 100px;
padding-right: 20px;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
overflow-wrap: break-word;
border-bottom: 1px 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>

View File

@@ -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: 40px;
flex-shrink: 0;
align-items: center;
justify-content: center;
.loading-custom-image{
color: #a4a4a4;
margin-right: 8rpx;
width: 24px;
height: 24px;
/* #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>

View File

@@ -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
},
}
}
}

View File

@@ -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;
};

File diff suppressed because it is too large Load Diff