1275 lines
38 KiB
Vue
1275 lines
38 KiB
Vue
<template>
|
|
<view class="wyb-table-box">
|
|
<view
|
|
v-if="loading"
|
|
class="wyb-table-loading-box"
|
|
:style="{
|
|
width: width === 'auto' ? screenWidth : width,
|
|
height: height === 'auto' ? '300rpx' : height,
|
|
backgroundColor: loaderBgColor,
|
|
borderTop: '1px solid' + borderColor,
|
|
borderBottom: '1px solid' + borderColor,
|
|
borderLeft: showLeftAndRightBorder ? '1px solid' + borderColor : 'none',
|
|
borderRight: showLeftAndRightBorder ? '1px solid' + borderColor : 'none',
|
|
}"
|
|
>
|
|
<view
|
|
class="loader-one"
|
|
:style="{
|
|
width: loaderSize + 'rpx',
|
|
height: loaderSize + 'rpx',
|
|
borderTop: '3px solid ' + loadingColor.top,
|
|
borderRight: '3px solid ' + loadingColor.right,
|
|
borderBottom: '3px solid ' + loadingColor.bottom,
|
|
borderLeft: '3px solid ' + loadingColor.left,
|
|
}"
|
|
/>
|
|
</view>
|
|
<view
|
|
v-if="!loading"
|
|
class="wyb-table-scroll-view"
|
|
:style="{
|
|
height: height,
|
|
borderTop: '1px solid' + borderColor,
|
|
borderBottom: '1px solid' + borderColor,
|
|
borderLeft: showLeftAndRightBorder ? '1px solid' + borderColor : 'none',
|
|
borderRight: showLeftAndRightBorder ? '1px solid' + borderColor : 'none',
|
|
}"
|
|
>
|
|
<view class="wyb-table-header" :style="{ borderBottom: '1px solid' + borderColor }">
|
|
<view
|
|
class="wyb-table-header-item"
|
|
v-if="enableCheck"
|
|
:style="{
|
|
minWidth: checkColWidth + 'rpx',
|
|
maxWidth: checkColWidth * 2 + 'rpx',
|
|
minHeight: minHeight[0] + 'rpx',
|
|
textAlign: textAlign,
|
|
justifyContent:
|
|
textAlign === 'center'
|
|
? textAlign
|
|
: textAlign === 'left'
|
|
? 'flex-start'
|
|
: 'flex-end',
|
|
fontSize: fontSize[0] + 'rpx',
|
|
color: headerFtColor,
|
|
padding: padding[0] + 'rpx ' + (padding[1] || padding[0]) + 'rpx',
|
|
backgroundColor: headerBgColor,
|
|
borderRight: '1px solid' + borderColor,
|
|
zIndex: 30,
|
|
left: 0,
|
|
color: headerFtColor,
|
|
backgroundColor: headerBgColor,
|
|
position: 'sticky',
|
|
}"
|
|
>
|
|
<!-- <view
|
|
class="wyb-table-checkbox"
|
|
v-if="enableCheck === 'multiple'"
|
|
@tap.stop="onCheckAllTap"
|
|
:style="{
|
|
width: checkColWidth * 0.5 + 'rpx',
|
|
height: checkColWidth * 0.5 + 'rpx',
|
|
backgroundColor: checkerBoxBgColor,
|
|
border: '1px solid ' + checkerBorderColor}">
|
|
<text
|
|
class="iconfont icon-check"
|
|
v-show="checkAll"
|
|
:style="{
|
|
color: checkerColor,
|
|
backgroundColor: checkerBgColor,
|
|
paddingTop: (fontSize[1] || fontSize[0]) * 0.15 + 'rpx',
|
|
fontSize: (fontSize[1] || fontSize[0]) + 'rpx'}" />
|
|
</view> -->
|
|
</view>
|
|
<view
|
|
class="wyb-table-header-item"
|
|
v-for="(item, index) in headers"
|
|
:key="item.key"
|
|
@tap="onHeaderItemTap(index)"
|
|
:style="{
|
|
minHeight: minHeight[0] + 'rpx',
|
|
textAlign: textAlign,
|
|
justifyContent:
|
|
textAlign === 'center'
|
|
? textAlign
|
|
: textAlign === 'left'
|
|
? 'flex-start'
|
|
: 'flex-end',
|
|
fontSize: fontSize[0] + 'rpx',
|
|
fontWeight: headerWeight ? 'bold' : 'normal',
|
|
color: headerFtColor,
|
|
padding: padding[0] + 'rpx ' + (padding[1] || padding[0]) + 'rpx',
|
|
backgroundColor: headerBgColor,
|
|
borderRight:
|
|
index === headers.length - 1 || (!showVertBorder && index !== 0)
|
|
? 'none'
|
|
: '1px solid' + borderColor,
|
|
zIndex: index === 0 ? 20 : 0,
|
|
left:
|
|
index === 0 && firstLineFixed
|
|
? enableCheck
|
|
? checkColWidth + 'rpx'
|
|
: 0
|
|
: 'auto',
|
|
position: index === 0 ? 'sticky' : 'static',
|
|
}"
|
|
>
|
|
<text
|
|
:style="{
|
|
marginLeft:
|
|
autoSortShow(index) && textAlign !== 'left'
|
|
? fontSize[0] * 0.65 + 'rpx'
|
|
: 0,
|
|
}"
|
|
>
|
|
{{ item.label || emptyString }}
|
|
</text>
|
|
<view class="wyb-table-header-icon" v-if="autoSortShow(index)">
|
|
<text
|
|
class="iconfont icon-arrow-up"
|
|
:style="{
|
|
color:
|
|
sortWays[sortWay] === 'asc' && sortActiveKey === item.key
|
|
? headerFtColor
|
|
: RGBChange(headerFtColor, 0.7, 'light'),
|
|
fontWeight: 'normal',
|
|
marginBottom: fontSize[0] * -0.85 + 'rpx',
|
|
transform: 'scale(0.4)',
|
|
}"
|
|
/>
|
|
<text
|
|
class="iconfont icon-arrow-down"
|
|
:style="{
|
|
color:
|
|
sortWays[sortWay] === 'inv' && sortActiveKey === item.key
|
|
? headerFtColor
|
|
: RGBChange(headerFtColor, 0.7, 'light'),
|
|
fontWeight: 'normal',
|
|
transform: 'scale(0.4)',
|
|
}"
|
|
/>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="wyb-table-content">
|
|
<view
|
|
class="wyb-table-content-line"
|
|
v-for="(content, cIndex) in contentsSort"
|
|
:key="contentLineKey(content, cIndex)"
|
|
:style="{ borderTop: cIndex === 0 ? 'none' : '1px solid' + borderColor }"
|
|
>
|
|
<view
|
|
class="wyb-table-content-item"
|
|
v-if="enableCheck"
|
|
:style="{
|
|
minWidth: checkColWidth + 'rpx',
|
|
maxWidth: checkColWidth * 2 + 'rpx',
|
|
textAlign: textAlign,
|
|
justifyContent:
|
|
textAlign === 'center'
|
|
? textAlign
|
|
: textAlign === 'left'
|
|
? 'flex-start'
|
|
: 'flex-end',
|
|
fontSize: (fontSize[1] || fontSize[0]) + 'rpx',
|
|
minHeight: (minHeight[1] || minHeight[0]) + 'rpx',
|
|
padding: padding[0] + 'rpx ' + (padding[1] || padding[0]) + 'rpx',
|
|
borderRight: '1px solid' + borderColor,
|
|
zIndex: 21,
|
|
color: contentFtColor,
|
|
|
|
left: 0,
|
|
position: 'sticky',
|
|
}"
|
|
>
|
|
<view
|
|
class="wyb-table-checkbox"
|
|
@tap.stop="onCheckItemTap(cIndex)"
|
|
:style="{
|
|
width: checkColWidth * 0.5 + 'rpx',
|
|
height: checkColWidth * 0.5 + 'rpx',
|
|
backgroundColor: checkerBoxBgColor,
|
|
border: '1px solid ' + checkerBorderColor,
|
|
}"
|
|
>
|
|
<text
|
|
class="iconfont icon-check"
|
|
v-show="contentsSort[cIndex].checked"
|
|
:style="{
|
|
color: checkerColor,
|
|
backgroundColor: checkerBgColor,
|
|
paddingTop: (fontSize[1] || fontSize[0]) * 0.15 + 'rpx',
|
|
fontSize: (fontSize[1] || fontSize[0]) + 'rpx',
|
|
}"
|
|
/>
|
|
</view>
|
|
</view>
|
|
<view
|
|
class="wyb-table-content-item"
|
|
v-for="(header, hIndex) in headers"
|
|
@tap.stop="onContentItemTap(cIndex, hIndex)"
|
|
:key="contentItemKey(header, hIndex)"
|
|
:style="{
|
|
textAlign: textAlign,
|
|
justifyContent:
|
|
textAlign === 'center'
|
|
? textAlign
|
|
: textAlign === 'left'
|
|
? 'flex-start'
|
|
: 'flex-end',
|
|
fontSize: (fontSize[1] || fontSize[0]) + 'rpx',
|
|
textDecoration: autoTextDecoration(cIndex, hIndex),
|
|
color: autoContentColor(cIndex, hIndex),
|
|
minHeight: (minHeight[1] || minHeight[0]) + 'rpx',
|
|
padding: padding[0] + 'rpx ' + (padding[1] || padding[0]) + 'rpx',
|
|
borderRight:
|
|
hIndex === headers.length - 1 || (!showVertBorder && hIndex !== 0)
|
|
? 'none'
|
|
: '1px solid' + borderColor,
|
|
zIndex: hIndex === 0 ? 20 : 0,
|
|
left: enableCheck ? checkColWidth + 'rpx' : 0,
|
|
position: hIndex === 0 && firstLineFixed ? 'sticky' : 'static',
|
|
}"
|
|
>{{ autoContentItem(cIndex, hIndex) }}</view
|
|
>
|
|
</view>
|
|
<view
|
|
v-if="computedCol.length !== 0"
|
|
class="wyb-table-content-line"
|
|
:style="{
|
|
position: bottomComputedFixed ? 'sticky' : 'static',
|
|
bottom: 0,
|
|
zIndex: 25,
|
|
borderTop: '1px solid' + borderColor,
|
|
}"
|
|
>
|
|
<view
|
|
class="wyb-table-content-item"
|
|
v-if="enableCheck"
|
|
:style="{
|
|
minWidth: checkColWidth + 'rpx',
|
|
maxWidth: checkColWidth * 2 + 'rpx',
|
|
textAlign: textAlign,
|
|
justifyContent:
|
|
textAlign === 'center'
|
|
? textAlign
|
|
: textAlign === 'left'
|
|
? 'flex-start'
|
|
: 'flex-end',
|
|
fontSize: (fontSize[1] || fontSize[0]) + 'rpx',
|
|
minHeight: (minHeight[1] || minHeight[0]) + 'rpx',
|
|
padding: padding[0] + 'rpx ' + (padding[1] || padding[0]) + 'rpx',
|
|
borderRight: '1px solid' + borderColor,
|
|
zIndex: 25,
|
|
color: contentFtColor,
|
|
backgroundColor: checkerCellBgColor,
|
|
left: 0,
|
|
position: 'sticky',
|
|
}"
|
|
></view>
|
|
<view
|
|
class="wyb-table-content-item"
|
|
v-for="(header, index) in headers"
|
|
:key="index"
|
|
:style="{
|
|
textAlign: textAlign,
|
|
justifyContent:
|
|
textAlign === 'center'
|
|
? textAlign
|
|
: textAlign === 'left'
|
|
? 'flex-start'
|
|
: 'flex-end',
|
|
fontSize: (fontSize[1] || fontSize[0]) + 'rpx',
|
|
color: contentFtColor,
|
|
minHeight: (minHeight[1] || minHeight[0]) + 'rpx',
|
|
padding: padding[0] + 'rpx ' + (padding[1] || padding[0]) + 'rpx',
|
|
backgroundColor: index === 0 ? firstColBgColor : contentBgColor,
|
|
borderRight:
|
|
index === headers.length - 1 || (!showVertBorder && index !== 0)
|
|
? 'none'
|
|
: '1px solid' + borderColor,
|
|
zIndex: index === 0 ? 20 : 0,
|
|
left: enableCheck ? checkColWidth + 'rpx' : 0,
|
|
position: index === 0 && firstLineFixed ? 'sticky' : 'static',
|
|
}"
|
|
>
|
|
{{ autoBottomComputedItem(index) }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import Pinyin from "./characterToPinyin.js";
|
|
import { isEqual } from "./objEqual.js";
|
|
export default {
|
|
data() {
|
|
return {
|
|
bottomComputed: [],
|
|
colorList: [],
|
|
bgColorList: [],
|
|
contentsSort: this.contents.slice(),
|
|
oContentsSort: [],
|
|
sortWay: 0,
|
|
sortKeys: [],
|
|
sortActiveKey: "",
|
|
sortIsNumbers: [],
|
|
checkAll: false,
|
|
checkList: [],
|
|
onload: true,
|
|
event: {
|
|
checkType: this.enableCheck,
|
|
data: [],
|
|
},
|
|
chars: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
};
|
|
},
|
|
computed: {
|
|
loadingColor() {
|
|
let color = this.loaderColor.slice();
|
|
let rgbList = this.hexToRgb(color);
|
|
let top = "rgba(" + rgbList[0] + "," + rgbList[1] + "," + rgbList[2] + ", 0.3)";
|
|
let bottom = "rgba(" + rgbList[0] + "," + rgbList[1] + "," + rgbList[2] + ", 0.3)";
|
|
let right = "rgba(" + rgbList[0] + "," + rgbList[1] + "," + rgbList[2] + ", 0.3)";
|
|
let left = "rgb(" + rgbList[0] + "," + rgbList[1] + "," + rgbList[2] + ")";
|
|
return {
|
|
top,
|
|
bottom,
|
|
right,
|
|
left,
|
|
};
|
|
},
|
|
contentLineKey() {
|
|
return function (content, cIndex) {
|
|
return this.randomString(32, this.chars);
|
|
};
|
|
},
|
|
contentItemKey() {
|
|
return function (header, hIndex) {
|
|
return this.randomString(16, this.chars);
|
|
};
|
|
},
|
|
autoContentItem() {
|
|
return function (cIndex, hIndex) {
|
|
let content = this.contentsSort[cIndex];
|
|
let header = this.headers[hIndex];
|
|
let result = "";
|
|
if (content[header.key] || content[header.key] === 0) {
|
|
result = content[header.key];
|
|
if (this.urlCol.length !== 0) {
|
|
for (let i in this.urlCol) {
|
|
let item = this.urlCol[i];
|
|
if (header.key === item.key) {
|
|
// 该单元格为链接
|
|
result = content[header.key][0];
|
|
}
|
|
}
|
|
}
|
|
if (this.formatCol.length !== 0) {
|
|
this.formatCol.forEach((item) => {
|
|
if (header.key === item.key) {
|
|
let needRplace = new RegExp(`\#${item["key"]}\#`, "mg");
|
|
result = item.template.replace(needRplace, result);
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
result = this.emptyString;
|
|
}
|
|
return result;
|
|
};
|
|
},
|
|
autoBottomComputedItem() {
|
|
return function (index) {
|
|
let bottomComputed = {};
|
|
let needComputed = [];
|
|
this.computedCol.forEach((key) => {
|
|
let computedColData = [];
|
|
this.contentsSort.forEach((content) => {
|
|
computedColData.push(content[key] || "0");
|
|
});
|
|
needComputed.push(computedColData);
|
|
});
|
|
needComputed.forEach((item, index) => {
|
|
let total = 0;
|
|
item.forEach((num) => {
|
|
total += parseFloat(num);
|
|
});
|
|
bottomComputed[this.computedCol[index]] = total;
|
|
});
|
|
let header = this.headers[index];
|
|
let result = this.computedCol.includes(header.key)
|
|
? bottomComputed[header.key]
|
|
: index === 0
|
|
? "总计"
|
|
: this.emptyString;
|
|
if (this.formatCol.length !== 0) {
|
|
this.formatCol.forEach((item) => {
|
|
if (item.bottomComputedFormat) {
|
|
if (header.key === item.key) {
|
|
let needRplace = new RegExp(`\#${item["key"]}\#`, "mg");
|
|
result = item.template.replace(needRplace, bottomComputed[item.key]);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
};
|
|
},
|
|
autoTextDecoration() {
|
|
return function (cIndex, hIndex) {
|
|
let result = "auto";
|
|
let content = this.contentsSort[cIndex];
|
|
let header = this.headers[hIndex];
|
|
if (this.urlCol.length !== 0) {
|
|
for (let i in this.urlCol) {
|
|
let item = this.urlCol[i];
|
|
if (header.key === item.key) {
|
|
// 该单元格为链接
|
|
if (content[header.key]) {
|
|
result = "underline";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
},
|
|
autoContentBgColor() {
|
|
return function (cIndex, hIndex) {
|
|
let result = this.contentBgColor;
|
|
let content = this.contentsSort[cIndex];
|
|
let header = this.headers[hIndex];
|
|
let keys = [];
|
|
// 先判断是不是首列,设置基础样式
|
|
if (hIndex === 0) {
|
|
result = this.firstColBgColor;
|
|
}
|
|
// 再判断条件格式传没传值,设置条件样式
|
|
if (this.valueFormat.length !== 0) {
|
|
this.valueFormat.forEach((item) => {
|
|
keys.push(item.key);
|
|
});
|
|
if (keys.includes(header.key)) {
|
|
// 该列开启了条件格式
|
|
let key = header.key;
|
|
let type = this.valueFormat[keys.indexOf(key)].type;
|
|
let style = this.valueFormat[keys.indexOf(key)].style;
|
|
let range = this.valueFormat[keys.indexOf(key)].range || "";
|
|
switch (type) {
|
|
case "bigger":
|
|
if (parseFloat(content[key]) > range) {
|
|
if (style.bgColor) result = style.bgColor;
|
|
}
|
|
break;
|
|
case "smaller":
|
|
if (parseFloat(content[key]) < range) {
|
|
if (style.bgColor) result = style.bgColor;
|
|
}
|
|
break;
|
|
case "equal":
|
|
let val;
|
|
if (typeof range === "number") val = parseFloat(content[key]);
|
|
else val = content[key];
|
|
if (val === range) {
|
|
if (style.bgColor) result = style.bgColor;
|
|
}
|
|
break;
|
|
case "range":
|
|
if (
|
|
parseFloat(content[key]) > range[0] &&
|
|
parseFloat(content[key]) < range[1]
|
|
) {
|
|
if (style.bgColor) result = style.bgColor;
|
|
}
|
|
break;
|
|
case "average-bigger":
|
|
let average = this.getAverage(key);
|
|
if (parseFloat(content[key]) > average) {
|
|
if (style.bgColor) result = style.bgColor;
|
|
}
|
|
break;
|
|
case "average-smaller":
|
|
average = this.getAverage(key);
|
|
if (parseFloat(content[key]) < average) {
|
|
if (style.bgColor) result = style.bgColor;
|
|
}
|
|
break;
|
|
case "average-equal":
|
|
average = this.getAverage(key);
|
|
if (parseFloat(content[key]) === average) {
|
|
if (style.bgColor) result = style.bgColor;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
},
|
|
autoContentColor() {
|
|
return function (cIndex, hIndex) {
|
|
let result = this.contentFtColor;
|
|
let content = this.contentsSort[cIndex];
|
|
let header = this.headers[hIndex];
|
|
let keys = [];
|
|
// 先判断是不是链接,设置基础样式
|
|
if (this.urlCol.length !== 0) {
|
|
for (let i in this.urlCol) {
|
|
let item = this.urlCol[i];
|
|
if (header.key === item.key) {
|
|
// 该单元格为链接
|
|
if (content[header.key]) {
|
|
result = this.linkColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 再判断条件格式传没传值,设置条件样式
|
|
if (this.valueFormat.length !== 0) {
|
|
this.valueFormat.forEach((item) => {
|
|
keys.push(item.key);
|
|
});
|
|
if (keys.includes(header.key)) {
|
|
// 该列开启了条件格式
|
|
let key = header.key;
|
|
let type = this.valueFormat[keys.indexOf(key)].type;
|
|
let style = this.valueFormat[keys.indexOf(key)].style;
|
|
let range = this.valueFormat[keys.indexOf(key)].range || "";
|
|
switch (type) {
|
|
case "bigger":
|
|
if (parseFloat(content[key]) > range) {
|
|
if (style.color) result = style.color;
|
|
}
|
|
break;
|
|
case "smaller":
|
|
if (parseFloat(content[key]) < range) {
|
|
if (style.color) result = style.color;
|
|
}
|
|
break;
|
|
case "equal":
|
|
let val;
|
|
if (typeof range === "number") val = parseFloat(content[key]);
|
|
else val = content[key];
|
|
if (val === range) {
|
|
if (style.color) result = style.color;
|
|
}
|
|
break;
|
|
case "range":
|
|
if (
|
|
parseFloat(content[key]) > range[0] &&
|
|
parseFloat(content[key]) < range[1]
|
|
) {
|
|
if (style.color) result = style.color;
|
|
}
|
|
break;
|
|
case "average-bigger":
|
|
let average = this.getAverage(key);
|
|
if (parseFloat(content[key]) > average) {
|
|
if (style.color) result = style.color;
|
|
}
|
|
break;
|
|
case "average-smaller":
|
|
average = this.getAverage(key);
|
|
if (parseFloat(content[key]) < average) {
|
|
if (style.color) result = style.color;
|
|
}
|
|
break;
|
|
case "average-equal":
|
|
average = this.getAverage(key);
|
|
if (parseFloat(content[key]) === average) {
|
|
if (style.color) result = style.color;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
},
|
|
autoSortShow() {
|
|
return function (hIndex) {
|
|
let result = false;
|
|
let header = this.headers[hIndex];
|
|
let keys = [];
|
|
// 判断排序是否传值
|
|
if (this.sortCol.length !== 0 && this.sortKeys.length === 0) {
|
|
this.sortCol.forEach((item) => {
|
|
keys.push(item.key);
|
|
});
|
|
this.sortKeys = keys;
|
|
if (keys.includes(header.key)) {
|
|
result = true;
|
|
}
|
|
} else if (this.sortCol.length !== 0) {
|
|
if (this.sortKeys.includes(header.key)) {
|
|
result = true;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
},
|
|
screenWidth() {
|
|
return `${uni.getSystemInfoSync()["screenWidth"]}px`;
|
|
},
|
|
},
|
|
props: {
|
|
headers: {
|
|
type: Array,
|
|
default() {
|
|
return [
|
|
{
|
|
key: "name",
|
|
label: "姓名",
|
|
},
|
|
];
|
|
},
|
|
},
|
|
contents: {
|
|
type: Array,
|
|
default() {
|
|
return [
|
|
{
|
|
name: "张三",
|
|
},
|
|
{
|
|
name: "李四",
|
|
},
|
|
];
|
|
},
|
|
},
|
|
emptyString: {
|
|
type: String,
|
|
default: "-",
|
|
},
|
|
width: {
|
|
type: String,
|
|
default: `${uni.getSystemInfoSync().screenWidth}px`,
|
|
},
|
|
height: {
|
|
type: String,
|
|
default: "auto",
|
|
},
|
|
fontSize: {
|
|
type: Array,
|
|
default() {
|
|
return [8];
|
|
},
|
|
},
|
|
defaultColWidth: {
|
|
type: Number,
|
|
default: 165,
|
|
},
|
|
headerWeight: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
minHeight: {
|
|
type: Array,
|
|
default() {
|
|
return [20];
|
|
},
|
|
},
|
|
headerBgColor: {
|
|
type: String,
|
|
default: "#f1f1f1",
|
|
},
|
|
contentBgColor: {
|
|
type: String,
|
|
default: "#fff",
|
|
},
|
|
headerFtColor: {
|
|
type: String,
|
|
default: "#3e3e3e",
|
|
},
|
|
contentFtColor: {
|
|
type: String,
|
|
default: "#3e3e3e",
|
|
},
|
|
linkColor: {
|
|
type: String,
|
|
default: "#0024c8",
|
|
},
|
|
firstColBgColor: {
|
|
type: String,
|
|
default: "#f1f1f1",
|
|
},
|
|
firstLineFixed: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
textAlign: {
|
|
type: String,
|
|
default: "center",
|
|
},
|
|
padding: {
|
|
type: Array,
|
|
default() {
|
|
return [5, 10];
|
|
},
|
|
},
|
|
borderColor: {
|
|
type: String,
|
|
default: "#e1e1e1",
|
|
},
|
|
urlCol: {
|
|
type: Array,
|
|
default() {
|
|
return [];
|
|
},
|
|
},
|
|
computedCol: {
|
|
type: Array,
|
|
default() {
|
|
return [];
|
|
},
|
|
},
|
|
bottomComputedFixed: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
valueFormat: {
|
|
type: Array,
|
|
default() {
|
|
return [];
|
|
},
|
|
},
|
|
formatCol: {
|
|
type: Array,
|
|
default() {
|
|
return [];
|
|
},
|
|
},
|
|
showLeftAndRightBorder: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
showVertBorder: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
sortCol: {
|
|
type: Array,
|
|
default() {
|
|
return [];
|
|
},
|
|
},
|
|
sortWays: {
|
|
type: Array,
|
|
default() {
|
|
return ["none", "asc", "inv"];
|
|
},
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
loaderSize: {
|
|
type: [String, Number],
|
|
default: 50,
|
|
},
|
|
loaderColor: {
|
|
type: String,
|
|
default: "#a3a3a3",
|
|
},
|
|
loaderBgColor: {
|
|
type: String,
|
|
default: "#f8f8f8",
|
|
},
|
|
enableCheck: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
checkColWidth: {
|
|
type: [String, Number],
|
|
default: "40",
|
|
},
|
|
checkerColor: {
|
|
type: String,
|
|
default: "#3e3e3e",
|
|
},
|
|
checkerBorderColor: {
|
|
type: String,
|
|
default: "#d3d3d3",
|
|
},
|
|
checkerBgColor: {
|
|
type: String,
|
|
default: "rgba(0, 0, 0, 0)",
|
|
},
|
|
checkerBoxBgColor: {
|
|
type: String,
|
|
default: "rgba(0, 0, 0, 0)",
|
|
},
|
|
checkerCellBgColor: {
|
|
type: String,
|
|
default: "#f1f1f1",
|
|
},
|
|
},
|
|
watch: {
|
|
headers(val) {
|
|
this.$forceUpdate();
|
|
},
|
|
contents(val) {
|
|
this.contentsSort = val.slice();
|
|
if (this.onload) {
|
|
this.contentsSort.forEach((item) => {
|
|
this.$set(item, "checked", false);
|
|
});
|
|
this.oContentsSort = this.contentsSort.slice();
|
|
this.onload = false;
|
|
}
|
|
this.$forceUpdate();
|
|
},
|
|
},
|
|
mounted() {
|
|
this.contentsSort.forEach((item) => {
|
|
this.$set(item, "checked", false);
|
|
});
|
|
this.oContentsSort = this.contentsSort.slice();
|
|
if (this.sortCol.length !== 0) {
|
|
this.sortActiveKey = this.sortCol[0].key;
|
|
uni.setStorageSync("lastSortActiveKey", this.sortActiveKey);
|
|
this.doSort(
|
|
this.sortCol[0].key,
|
|
this.sortWays[this.sortWay],
|
|
this.sortCol[0].isNumber
|
|
);
|
|
}
|
|
},
|
|
methods: {
|
|
doSort(key, type, isNumber) {
|
|
let arr = this.contentsSort;
|
|
if (type === "asc") {
|
|
// 升序
|
|
if (isNumber) {
|
|
arr.sort((a, b) => {
|
|
return (
|
|
(parseFloat(a[key].toString().replace(/[^0-9]/gi, "")) || 0) -
|
|
(parseFloat(b[key].toString().replace(/[^0-9]/gi, "")) || 0)
|
|
);
|
|
});
|
|
} else {
|
|
arr.sort((a, b) => {
|
|
let A = Pinyin.getSpell(a[key].charAt(0), function (charactor, spell) {
|
|
return spell[1];
|
|
})
|
|
.charAt(0)
|
|
.charCodeAt();
|
|
let B = Pinyin.getSpell(b[key].charAt(0), function (charactor, spell) {
|
|
return spell[1];
|
|
})
|
|
.charAt(0)
|
|
.charCodeAt();
|
|
return A - B;
|
|
});
|
|
}
|
|
} else if (type === "inv") {
|
|
// 倒序
|
|
if (isNumber) {
|
|
arr.sort((a, b) => {
|
|
return (
|
|
(parseFloat(b[key].toString().replace(/[^0-9]/gi, "")) || 0) -
|
|
(parseFloat(a[key].toString().replace(/[^0-9]/gi, "")) || 0)
|
|
);
|
|
});
|
|
} else {
|
|
arr.sort((a, b) => {
|
|
let A = Pinyin.getSpell(a[key].charAt(0), function (charactor, spell) {
|
|
return spell[1];
|
|
})
|
|
.charAt(0)
|
|
.charCodeAt();
|
|
let B = Pinyin.getSpell(b[key].charAt(0), function (charactor, spell) {
|
|
return spell[1];
|
|
})
|
|
.charAt(0)
|
|
.charCodeAt();
|
|
return B - A;
|
|
});
|
|
}
|
|
} else {
|
|
this.contentsSort = this.oContentsSort.slice();
|
|
}
|
|
|
|
if (this.enableCheck) {
|
|
this.event.data.forEach((item) => {
|
|
this.contentsSort.forEach((content, index) => {
|
|
if (isEqual(item.lineData, content)) {
|
|
item.index = index;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
this.$forceUpdate();
|
|
},
|
|
initBottomComputed() {
|
|
let result = {};
|
|
let needComputed = [];
|
|
this.computedCol.forEach((key) => {
|
|
let computedColData = [];
|
|
this.contentsSort.forEach((content) => {
|
|
computedColData.push(content[key] || "0");
|
|
});
|
|
needComputed.push(computedColData);
|
|
});
|
|
needComputed.forEach((item, index) => {
|
|
let total = 0;
|
|
item.forEach((num) => {
|
|
total += parseFloat(num);
|
|
});
|
|
result[this.computedCol[index]] = total;
|
|
});
|
|
this.bottomComputed = result;
|
|
},
|
|
onHeaderItemTap(index) {
|
|
let header = this.headers[index];
|
|
const lastSortActiveKey = uni.getStorageSync("lastSortActiveKey") || "";
|
|
if (this.sortCol.length !== 0) {
|
|
if (this.sortKeys.includes(header.key)) {
|
|
// 当前列开启了排序
|
|
this.sortActiveKey = header.key;
|
|
uni.setStorageSync("lastSortActiveKey", this.sortActiveKey);
|
|
if (this.sortWay < 2 && lastSortActiveKey === this.sortActiveKey) {
|
|
this.sortWay++;
|
|
} else if (lastSortActiveKey !== this.sortActiveKey) {
|
|
this.sortWay = 1;
|
|
} else if (this.sortWay >= 2) {
|
|
this.sortWay = 0;
|
|
}
|
|
let isNumber = this.sortCol[this.sortKeys.indexOf(header.key)].isNumber;
|
|
this.doSort(header.key, this.sortWays[this.sortWay], isNumber);
|
|
}
|
|
}
|
|
},
|
|
onContentItemTap(cIndex, hIndex) {
|
|
let event = {};
|
|
let content = this.contentsSort[cIndex];
|
|
let header = this.headers[hIndex];
|
|
let keys = [];
|
|
|
|
if (this.urlCol.length !== 0) {
|
|
for (let i in this.urlCol) {
|
|
let item = this.urlCol[i];
|
|
keys.push(item.key);
|
|
}
|
|
}
|
|
|
|
if (content[header.key]) {
|
|
if (keys.includes(header.key)) {
|
|
// 该单元格为链接
|
|
switch (this.urlCol[keys.indexOf(header.key)].type) {
|
|
case "route":
|
|
let url = content[header.key][1];
|
|
if (content[header.key][2]) {
|
|
url = `${url}?`;
|
|
Object.keys(content[header.key][2]).forEach((key) => {
|
|
url += `&${key}=${content[header["key"]][2][key]}`;
|
|
});
|
|
}
|
|
uni.navigateTo({ url });
|
|
break;
|
|
case "http":
|
|
this.openURL(content[header.key][1]);
|
|
break;
|
|
}
|
|
} else {
|
|
event = {
|
|
content: content[header.key],
|
|
contentIndex: cIndex,
|
|
header: header.label,
|
|
headerIndex: hIndex,
|
|
key: header.key,
|
|
lineData: content,
|
|
};
|
|
this.$emit("onCellClick", event);
|
|
}
|
|
} else {
|
|
event = {
|
|
content: "",
|
|
contentIndex: cIndex,
|
|
header: header.label,
|
|
headerIndex: hIndex,
|
|
key: header.key,
|
|
lineData: content,
|
|
};
|
|
if (keys.includes(header.key)) {
|
|
// 该单元格为链接
|
|
event["isLink"] = true;
|
|
}
|
|
this.$emit("onCellClick", event);
|
|
}
|
|
},
|
|
onCheckAllTap() {
|
|
console.log(this.currentPageNo);
|
|
if (this.enableCheck === "multiple") {
|
|
let checkList = [];
|
|
this.contentsSort.forEach((item) => {
|
|
checkList.push(item.checked);
|
|
});
|
|
this.checkList = checkList;
|
|
if (!this.checkAll) {
|
|
this.checkAll = true;
|
|
console.log(this.contentsSort);
|
|
this.contentsSort.forEach((item) => {
|
|
item.checked = true;
|
|
});
|
|
this.event.data = [];
|
|
this.contentsSort.forEach((content, index) => {
|
|
this.event.data.push({
|
|
index,
|
|
lineData: content,
|
|
});
|
|
});
|
|
} else {
|
|
this.checkAll = false;
|
|
this.event.data = [];
|
|
this.contentsSort.forEach((item) => {
|
|
item.checked = false;
|
|
});
|
|
}
|
|
this.$emit("change", { detail: this.event });
|
|
}
|
|
},
|
|
onCheckItemTap(cIndex) {
|
|
let content = this.contentsSort[cIndex];
|
|
if (this.enableCheck === "single") {
|
|
this.contentsSort.forEach((item, index) => {
|
|
if (cIndex === index) {
|
|
item.checked = !item.checked;
|
|
} else {
|
|
item.checked = false;
|
|
}
|
|
});
|
|
} else if (this.enableCheck === "multiple") {
|
|
this.contentsSort[cIndex]["checked"] = !this.contentsSort[cIndex]["checked"];
|
|
}
|
|
if (this.contentsSort[cIndex]["checked"]) {
|
|
if (this.enableCheck === "single") {
|
|
this.event.data = [];
|
|
}
|
|
this.event.data.push({
|
|
index: cIndex,
|
|
lineData: this.contentsSort[cIndex],
|
|
});
|
|
} else {
|
|
this.event.data.forEach((item) => {
|
|
if (item.index === cIndex)
|
|
this.event.data.splice(this.event.data.indexOf(item), 1);
|
|
});
|
|
if (this.event.data.length === 0) {
|
|
this.checkAll = false;
|
|
}
|
|
}
|
|
this.$forceUpdate();
|
|
// this.$emit('onCheck', this.event)
|
|
this.$emit("change", {
|
|
detail: this.event,
|
|
});
|
|
},
|
|
openURL(href) {
|
|
// #ifdef APP-PLUS
|
|
plus.runtime.openURL(href);
|
|
// #endif
|
|
// #ifdef H5
|
|
window.open(href);
|
|
// #endif
|
|
// #ifdef MP
|
|
uni.setClipboardData({
|
|
data: href,
|
|
success() {
|
|
uni.showToast({
|
|
title: "网址已复制,请在手机浏览器里粘贴该网址",
|
|
icon: "none",
|
|
});
|
|
},
|
|
});
|
|
// #endif
|
|
},
|
|
getAverage(key) {
|
|
let numList = [];
|
|
this.contentsSort.forEach((content) => {
|
|
numList.push(parseFloat(content[key]) || 0);
|
|
});
|
|
return numList.reduce((a, b) => a + b) / numList.length;
|
|
},
|
|
getTotal(key) {
|
|
let numList = [];
|
|
this.contentsSort.forEach((content) => {
|
|
numList.push(parseFloat(content[key]) || 0);
|
|
});
|
|
return numList.reduce((a, b) => a + b);
|
|
},
|
|
RGBChange(color, level, type) {
|
|
// 判断颜色类型
|
|
let r = 0,
|
|
g = 0,
|
|
b = 0,
|
|
hasAlpha = false,
|
|
alpha = 1;
|
|
if (color.indexOf("#") !== -1) {
|
|
// hex转rgb
|
|
if (color.length === 4) {
|
|
let arr = color.split("");
|
|
color = "#" + arr[1] + arr[1] + arr[2] + arr[2] + arr[3] + arr[3];
|
|
}
|
|
let color16List = [
|
|
color.substring(1, 3),
|
|
color.substring(3, 5),
|
|
color.substring(5, 7),
|
|
];
|
|
r = parseInt(color16List[0], 16);
|
|
g = parseInt(color16List[1], 16);
|
|
b = parseInt(color16List[2], 16);
|
|
} else {
|
|
hasAlpha = color.indexOf("a") !== -1;
|
|
let root = color.slice();
|
|
let idx = root.indexOf("(") + 1;
|
|
root = root.substring(idx);
|
|
let firstDotIdx = root.indexOf(",");
|
|
r = parseFloat(root.substring(0, firstDotIdx));
|
|
root = root.substring(firstDotIdx + 1);
|
|
let secondDotIdx = root.indexOf(",");
|
|
g = parseFloat(root.substring(0, secondDotIdx));
|
|
root = root.substring(secondDotIdx + 1);
|
|
if (hasAlpha) {
|
|
let thirdDotIdx = root.indexOf(",");
|
|
b = parseFloat(root.substring(0, thirdDotIdx));
|
|
alpha = parseFloat(root.substring(thirdDotIdx + 1));
|
|
} else {
|
|
b = parseFloat(root);
|
|
}
|
|
}
|
|
|
|
let rgbc = [r, g, b];
|
|
// 减淡或加深
|
|
for (var i = 0; i < 3; i++)
|
|
type === "light"
|
|
? (rgbc[i] = Math.floor((255 - rgbc[i]) * level + rgbc[i]))
|
|
: (rgbc[i] = Math.floor(rgbc[i] * (1 - level)));
|
|
|
|
if (hasAlpha) {
|
|
return `rgba(${rgbc[0]}, ${rgbc[1]}, ${rgbc[2]}, ${alpha})`;
|
|
} else {
|
|
return `rgb(${rgbc[0]}, ${rgbc[1]}, ${rgbc[2]})`;
|
|
}
|
|
},
|
|
hexToRgb(color) {
|
|
if (color.length === 4) {
|
|
let arr = color.split("");
|
|
color = "#" + arr[1] + arr[1] + arr[2] + arr[2] + arr[3] + arr[3];
|
|
}
|
|
let color16List = [
|
|
color.substring(1, 3),
|
|
color.substring(3, 5),
|
|
color.substring(5, 7),
|
|
];
|
|
let r = parseInt(color16List[0], 16);
|
|
let g = parseInt(color16List[1], 16);
|
|
let b = parseInt(color16List[2], 16);
|
|
return [r, g, b];
|
|
},
|
|
randomString(length, chars) {
|
|
var result = "";
|
|
for (var i = length; i > 0; --i)
|
|
result += chars[Math.floor(Math.random() * chars.length)];
|
|
return result;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
@import "./iconfont.css";
|
|
@import "./loader.css";
|
|
.wyb-table-scroll-view {
|
|
overflow: scroll;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
.wyb-table-scroll-view::-webkit-scrollbar {
|
|
display: none;
|
|
/* #ifdef MP-WEIXIN */
|
|
width: 0;
|
|
height: 0;
|
|
/* #endif */
|
|
}
|
|
|
|
.wyb-table-loading-box {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 500;
|
|
}
|
|
|
|
.wyb-table-header {
|
|
position: sticky;
|
|
top: 0;
|
|
/* display: grid; */
|
|
/* grid-auto-flow: column; */
|
|
/* width: max-content; */
|
|
z-index: 25;
|
|
width: 100%;
|
|
display: flex;
|
|
}
|
|
|
|
.wyb-table-header-item {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
box-sizing: border-box;
|
|
position: relative;
|
|
}
|
|
|
|
.wyb-table-header-icon {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.wyb-table-content-line {
|
|
/* display: grid; */
|
|
/* grid-auto-flow: column; */
|
|
/* width: max-content; */
|
|
position: relative;
|
|
width: 100%;
|
|
display: flex;
|
|
}
|
|
|
|
.wyb-table-content-item {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
box-sizing: border-box;
|
|
flex: 1;
|
|
}
|
|
|
|
.wyb-table-checkbox {
|
|
width: 40px !important;
|
|
height: 40px !important;
|
|
border-radius: 3px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
/* overflow: hidden; */
|
|
position: relative;
|
|
line-height: 40px !important;
|
|
}
|
|
|
|
.icon-check {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: absolute;
|
|
border-radius: 0;
|
|
border-radius: 3px;
|
|
font-weight: bold;
|
|
box-sizing: border-box;
|
|
transform: scale(1.1);
|
|
}
|
|
.icon-check::before {
|
|
font-size: 36rpx;
|
|
}
|
|
</style>
|