integrated_traffic_uniapp/components/uni-table/uni-table.vue

260 lines
4.9 KiB
Vue
Raw Permalink Normal View History

2024-01-16 17:24:49 +08:00
<template>
<view class="uni-table-scroll" :class="{'table--border':border,'border-none':!noData}">
<view class="uni-table" :class="{ 'table--stripe':stripe}">
<slot></slot>
<view v-if="noData" class="uni-table-loading">
<view class="uni-table-text">{{emptyText}}</view>
</view>
<view v-if="loading" class="uni-table-mask">
<div class="uni-table--loader"></div>
</view>
</view>
</view>
</template>
<script>
/**
* Table 表格
* @description 用于展示多条结构类似的数据
* @tutorial https://ext.dcloud.net.cn/plugin?id=
* @property {Boolean} border 是否带有纵向边框
* @property {Boolean} stripe 是否显示斑马线
* @property {Boolean} type 是否开启多选
* @property {String} emptyText 空数据时显示的文本内容
* @property {Boolean} loading 显示加载中
* @event {Function} selection-change 开启多选时当选择项发生变化时会触发该事件
*/
export default {
name: 'uniTable',
options: {
virtualHost: true
},
props: {
// 是否有竖线
border: {
type: Boolean,
default: false
},
// 是否显示斑马线
stripe: {
type: Boolean,
default: false
},
// 多选
type: {
type: String,
default: ''
},
// 没有更多数据
emptyText: {
type: String,
default: '没有更多数据'
},
loading: {
type: Boolean,
default: false
},
},
data() {
return {
noData: true,
minWidth: 0
};
},
watch: {
loading(val) {
console.log(val);
}
},
created() {
// 定义tr的实例数组
this.trChildren = []
this.backData = []
},
methods: {
isNodata() {
if (this.trChildren.length > 1) {
this.noData = false
} else {
this.noData = true
}
},
/**
* 清除选中
*/
clearSelection() {
this.trChildren.forEach((item, index) => {
item.value = false
})
this.$emit('selection-change', {
detail: {
index: [],
value: []
}
})
},
check(child, check) {
const childDom = this.trChildren.find((item, index) => child === item)
const childDomIndex = this.trChildren.findIndex((item, index) => child === item)
if (childDomIndex === 0) {
if (childDom.value !== check) {
this.backData = []
this.trChildren.map((item, index) => item.value = check)
}
this.trChildren.forEach((item, index) => {
if (index > 0 && item.value) {
this.backData.push(index - 1)
}
})
} else {
if (!check) {
this.trChildren[0].value = false
}
childDom.value = check
if (check) {
this.backData.push(childDomIndex - 1)
} else {
const index = this.backData.findIndex(item => item === (childDomIndex - 1))
this.backData.splice(index, 1)
}
const domCheckAll = this.trChildren.find((item, index) => index > 0 && !item.value)
if (!domCheckAll) {
this.trChildren[0].value = true
}
}
this.$emit('selection-change', {
detail: {
index: this.backData.sort(),
value: []
}
})
}
}
}
</script>
<style scoped>
@charset "UTF-8";
.uni-table-scroll {
width: 100%;
overflow-x: auto;
}
.uni-table {
position: relative;
width: 100%;
display: table;
box-sizing: border-box;
border-radius: 5px;
box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
overflow-x: auto;
background-color: #fff;
}
.uni-table ::v-deep .uni-table-tr:nth-child(n+2):hover {
background-color: #f5f7fa;
}
.table--border {
border: 1px #ddd solid;
}
.border-none {
border-bottom: none;
}
.table--stripe ::v-deep .uni-table-tr:nth-child(2n+3) {
background-color: #fafafa;
}
/* 表格加载、无数据样式 */
.uni-table-loading {
position: relative;
display: table-row;
height: 50px;
line-height: 50px;
}
.uni-table-text {
position: absolute;
right: 0;
left: 0;
text-align: center;
font-size: 14px;
color: #999;
}
.uni-table-mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
background-color: rgba(255, 255, 255, 0.8);
z-index: 99;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.5s;
}
.uni-table--loader {
width: 30px;
height: 30px;
border: 2px solid #aaa;
border-radius: 50%;
animation: 2s uni-table--loader linear infinite;
position: relative;
}
@keyframes uni-table--loader {
0% {
transform: rotate(360deg);
}
10% {
border-left-color: transparent;
}
20% {
border-bottom-color: transparent;
}
30% {
border-right-color: transparent;
}
40% {
border-top-color: transparent;
}
50% {
transform: rotate(0deg);
}
60% {
border-top-color: transparent;
}
70% {
border-left-color: transparent;
}
80% {
border-bottom-color: transparent;
}
90% {
border-right-color: transparent;
}
100% {
transform: rotate(-360deg);
}
}
</style>