You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

672 lines
20 KiB
Vue

<template>
<div
ref="tableContainer"
:style="bg_class"
style="padding: 8px; width: 100%; height: 100%; overflow: hidden"
>
<el-row style="height: 100%">
<p v-show="title_show" ref="title" :style="title_class">
{{ chart.title }}
</p>
<ux-grid
ref="plxTable"
size="mini"
style="width: 100%"
:height="height"
:checkbox-config="{ highlight: true }"
:width-resize="true"
:header-row-style="table_header_class"
:row-style="getRowStyle"
:merge-cells="mergeCells"
class="table-class"
show-overflow="tooltip"
show-header-overflow="tooltip"
:class="chart.id"
:show-summary="showSummary"
:summary-method="summaryMethod"
>
<ux-table-column
v-for="(field, index) in fields"
:key="field.dataeaseName + index"
:field="field.subFields ? '' : field.dataeaseName"
:resizable="true"
:fixed="field.fixed"
:title="field.name"
>
<template v-if="field.subFields">
<ux-table-column
v-for="subfield in field.subFields"
:key="subfield.dataeaseName"
:field="subfield.dataeaseName"
:resizable="true"
:title="subfield.name"
/>
</template>
</ux-table-column>
</ux-grid>
<el-row v-show="chart.type === 'table-info'" class="table-page">
<span class="total-style">
{{ $t('chart.total') }}
<span>{{
chart.data && chart.data.tableRow ? chart.data.tableRow.length : 0
}}</span>
{{ $t('chart.items') }}
</span>
<el-pagination
small
:current-page="currentPage.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="currentPage.pageSize"
:pager-count="5"
layout="sizes, prev, pager, next"
:total="currentPage.show"
class="page-style"
@current-change="pageClick"
@size-change="pageChange"
/>
</el-row>
</el-row>
</div>
</template>
<script>
import { hexColorToRGBA } from '../../chart/util'
import eventBus from '@/components/canvas/utils/eventBus'
export default {
name: 'TableNormal',
props: {
chart: {
type: Object,
required: true
},
filter: {
type: Object,
required: false,
default: function() {
return {}
}
},
showSummary: {
type: Boolean,
required: false,
default: true
}
},
data() {
return {
fields: [],
height: 'auto',
mergeCells: [],
title_class: {
margin: '0 0',
width: '100%',
fontSize: '18px',
color: '#303133',
textAlign: 'left',
fontStyle: 'normal',
fontWeight: 'normal'
},
// bg_class: {
// background: hexColorToRGBA('#ffffff', 0),
// borderRadius: this.borderRadius
// },
table_header_class: {
fontSize: '12px',
color: '#606266',
backgroundColor: '#e8eaec',
height: '36px'
},
table_item_class: {
fontSize: '12px',
color: '#606266',
background: '#ffffff',
height: '36px'
},
table_item_class_stripe: {
fontSize: '12px',
color: '#606266',
background: '#ffffff',
height: '36px'
},
cellDimension: 0,
tableLength: 0,
title_show: true,
borderRadius: '0px',
currentPage: {
page: 1,
pageSize: 10,
show: 0
}
}
},
computed: {
bg_class() {
return {
background: hexColorToRGBA('#ffffff', 0),
borderRadius: this.borderRadius
}
}
},
created() {
this.init()
console.log('init')
// 监听元素变动事件
eventBus.$on('resizing', (componentId) => {
this.chartResize()
})
},
methods: {
init() {
this.resetHeight()
this.$nextTick(() => {
this.initData()
this.calcHeightDelay()
})
this.setBackGroundBorder()
},
setBackGroundBorder() {
if (this.chart.customStyle) {
const customStyle = JSON.parse(this.chart.customStyle)
if (customStyle.background) {
this.borderRadius = (customStyle.background.borderRadius || 0) + 'px'
}
}
},
deteleObject(obj) {
var uniques = []
var stringify = {}
for (var i = 0; i < obj.length; i++) {
var keys = Object.keys(obj[i])
keys.sort(function(a, b) {
return Number(a) - Number(b)
})
var str = ''
for (var j = 0; j < keys.length; j++) {
str += JSON.stringify(keys[j])
str += JSON.stringify(obj[i][keys[j]])
}
if (!stringify.hasOwnProperty(str)) {
uniques.push(obj[i])
stringify[str] = true
}
}
return uniques
},
initData() {
const that = this
let datas = []
if (this.chart.data) {
this.fields = JSON.parse(JSON.stringify(this.chart.data.fields))
datas = JSON.parse(JSON.stringify(this.chart.data.tableRow))
const findRowIndex = this.fields.findIndex((e) => e.chartType === 'row')
const findValueIndex = this.fields.findIndex(
(e) => e.chartType === 'bar'
)
if (this.chart.type === 'table-info') {
// 计算分页
this.currentPage.show = datas.length
const pageStart =
(this.currentPage.page - 1) * this.currentPage.pageSize
const pageEnd = pageStart + this.currentPage.pageSize
datas = datas.slice(pageStart, pageEnd)
} else if (this.chart.type === 'table-normal' && findRowIndex >= 0) {
// 交叉表数据处理
const xaxis = this.chart.xaxis ? JSON.parse(this.chart.xaxis) : []
const yaxisExt = this.chart.yaxisExt
? JSON.parse(this.chart.yaxisExt)
: []
const xaxisFieldId = xaxis.map((e) => e.dataeaseName)
const yaxisExtFieldId = yaxisExt.map((e) => e.dataeaseName)
const fieldValueName = this.fields[findValueIndex].dataeaseName
this.cellDimension = xaxisFieldId.length
let fields = this.fields.filter((e) =>
xaxisFieldId.includes(e.dataeaseName)
)
console.log(fields)
let rowSum = 0
let columnValue = []
let rowName = []
yaxisExtFieldId.forEach((e, index) => {
const arr = []
datas.forEach((ele) => {
if (index > 0) {
arr.push({
dataeaseName:
e +
ele[e] +
',' +
yaxisExtFieldId[0] +
ele[yaxisExtFieldId[0]],
name: ele[e]
})
} else {
rowName.push({
dataeaseName: e + ele[e],
name: ele[e]
})
}
})
if (index > 0) {
const copyArr = this.deteleObject(arr)
rowName.forEach((item) => {
const newArr = []
copyArr.forEach((sube) => {
if (item.dataeaseName === sube.dataeaseName.split(',')[1]) {
newArr.push(sube)
}
})
item.subFields = newArr
})
} else {
rowName = this.deteleObject(rowName)
}
})
if (xaxisFieldId.length > 1) {
let arr1 = []
let arr2 = []
datas.forEach((obj) => {
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
const element = obj[key]
if (xaxisFieldId[0] === key) {
arr1.push({
[key]: element
})
} else if (xaxisFieldId[1] === key) {
arr2.push({
[key]: element
})
}
}
}
})
arr1 = this.deteleObject(arr1)
arr2 = this.deteleObject(arr2)
let rowIndex = 0
arr1.forEach((e) => {
this.mergeCells.push({
col: 0,
row: rowIndex,
rowspan: arr2.length,
colspan: 1
})
arr2.forEach((item) => {
const obj = {}
columnValue.push(Object.assign(obj, e, item))
rowIndex += 1
})
})
columnValue.forEach((ele) => {
if (yaxisExtFieldId.length > 1) {
datas.forEach((subEle) => {
if (
ele[xaxisFieldId[0]] === subEle[xaxisFieldId[0]] &&
ele[xaxisFieldId[1]] === subEle[xaxisFieldId[1]]
) {
const key =
yaxisExtFieldId[1] +
subEle[yaxisExtFieldId[1]] +
',' +
yaxisExtFieldId[0] +
subEle[yaxisExtFieldId[0]]
ele[key] = subEle[fieldValueName]
rowSum += subEle[fieldValueName]
}
})
} else {
datas.forEach((subEle) => {
if (
ele[xaxisFieldId[0]] === subEle[xaxisFieldId[0]] &&
ele[xaxisFieldId[1]] === subEle[xaxisFieldId[1]]
) {
const key = yaxisExtFieldId[0] + subEle[yaxisExtFieldId[0]]
ele[key] = subEle[fieldValueName]
rowSum += subEle[fieldValueName]
}
})
}
rowSum = rowSum.toFixed(2)
if (this.fields[findValueIndex].summary === 'ratio') {
rowSum += '%'
}
ele.rowTotal = rowSum
rowSum = 0
})
} else {
datas.forEach((obj) => {
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
const element = obj[key]
if (xaxisFieldId.includes(key)) {
columnValue.push({
[key]: element
})
}
}
}
})
columnValue = this.deteleObject(columnValue)
columnValue.forEach((ele) => {
if (yaxisExtFieldId.length > 1) {
datas.forEach((subEle) => {
if (ele[xaxisFieldId[0]] === subEle[xaxisFieldId[0]]) {
const key =
yaxisExtFieldId[1] +
subEle[yaxisExtFieldId[1]] +
',' +
yaxisExtFieldId[0] +
subEle[yaxisExtFieldId[0]]
ele[key] = subEle[fieldValueName]
rowSum += subEle[fieldValueName]
}
})
} else {
datas.forEach((subEle) => {
if (ele[xaxisFieldId[0]] === subEle[xaxisFieldId[0]]) {
const key = yaxisExtFieldId[0] + subEle[yaxisExtFieldId[0]]
ele[key] = subEle[fieldValueName]
rowSum += subEle[fieldValueName]
console.log(3, subEle)
}
})
}
rowSum = rowSum.toFixed(2)
if (this.fields[findValueIndex].summary === 'ratio') {
rowSum += '%'
}
ele.rowTotal = rowSum
rowSum = 0
})
}
fields = fields.concat(rowName)
fields.push({
dataeaseName: 'rowTotal',
name: `合计(${this.fields[findValueIndex].name})`
})
datas = columnValue
this.fields = fields
console.log(columnValue)
console.log(fields)
}
} else {
this.fields = []
datas = []
this.resetPage()
}
this.tableLength = datas.length
this.$refs.plxTable.reloadData(datas)
this.$nextTick(() => {
this.initStyle()
})
window.onresize = function() {
that.calcHeightDelay()
}
},
calcHeightRightNow() {
this.$nextTick(() => {
if (this.$refs.tableContainer) {
let pageHeight = 0
if (this.chart.type === 'table-info') {
pageHeight = 36
}
const currentHeight = this.$refs.tableContainer.offsetHeight
const tableMaxHeight =
currentHeight - this.$refs.title.offsetHeight - 16 - pageHeight
let tableHeight
if (this.chart.data) {
if (this.chart.type === 'table-info') {
tableHeight = (this.currentPage.pageSize + 2) * 36 - pageHeight
} else {
tableHeight = (this.tableLength + 2) * 36 - pageHeight
}
} else {
tableHeight = 0
}
if (tableHeight > tableMaxHeight) {
this.height = tableMaxHeight + 'px'
} else {
this.height = 'auto'
}
}
})
},
calcHeightDelay() {
setTimeout(() => {
this.calcHeightRightNow()
}, 100)
},
initStyle() {
if (this.chart.customAttr) {
const customAttr = JSON.parse(this.chart.customAttr)
if (customAttr.color) {
this.table_header_class.color = customAttr.color.tableFontColor
this.table_header_class.backgroundColor = hexColorToRGBA(
customAttr.color.tableHeaderBgColor,
customAttr.color.alpha
)
this.table_item_class.color = customAttr.color.tableFontColor
this.table_item_class.background = hexColorToRGBA(
customAttr.color.tableItemBgColor,
customAttr.color.alpha
)
}
if (customAttr.size) {
this.table_header_class.fontSize =
customAttr.size.tableTitleFontSize + 'px'
this.table_item_class.fontSize =
customAttr.size.tableItemFontSize + 'px'
this.table_header_class.height =
customAttr.size.tableTitleHeight + 'px'
this.table_item_class.height = customAttr.size.tableItemHeight + 'px'
}
this.table_item_class_stripe = JSON.parse(
JSON.stringify(this.table_item_class)
)
// 暂不支持斑马纹
// if (customAttr.color.tableStripe) {
// // this.table_item_class_stripe.background = hexColorToRGBA(customAttr.color.tableItemBgColor, customAttr.color.alpha - 40)
// if (this.chart.customStyle) {
// const customStyle = JSON.parse(this.chart.customStyle)
// if (customStyle.background) {
// this.table_item_class_stripe.background = hexColorToRGBA(customStyle.background.color, customStyle.background.alpha)
// }
// }
// }
}
if (this.chart.customStyle) {
const customStyle = JSON.parse(this.chart.customStyle)
if (customStyle.text) {
this.title_show = customStyle.text.show
this.title_class.fontSize = customStyle.text.fontSize + 'px'
this.title_class.color = customStyle.text.color
this.title_class.textAlign = customStyle.text.hPosition
this.title_class.fontStyle = customStyle.text.isItalic
? 'italic'
: 'normal'
this.title_class.fontWeight = customStyle.text.isBolder
? 'bold'
: 'normal'
}
if (customStyle.background) {
this.bg_class.background = hexColorToRGBA(
customStyle.background.color,
customStyle.background.alpha
)
}
}
// 修改footer合计样式
const table = document.getElementsByClassName(this.chart.id)
for (let i = 0; i < table.length; i++) {
const s_table = table[i].getElementsByClassName('elx-table--footer')
// console.log(s_table)
let s = ''
for (const i in this.table_header_class) {
s +=
(i === 'fontSize'
? 'font-size'
: i === 'backgroundColor'
? 'background-color'
: i) +
':' +
this.table_header_class[i] +
';'
}
// console.log(s_table)
for (let i = 0; i < s_table.length; i++) {
s_table[i].setAttribute('style', s)
}
}
},
getRowStyle({ row, rowIndex }) {
if (rowIndex % 2 !== 0) {
return this.table_item_class_stripe
} else {
return this.table_item_class
}
},
getColumStyle({ columnIndex }) {
if (
this.chart.type === 'table-normal' &&
this.cellDimension > 0 &&
(columnIndex < this.cellDimension ||
columnIndex === this.fields.length - 1)
) {
return this.table_header_class
} else {
return ''
}
},
summaryMethod({ columns, data }) {
const that = this
const means = [] // 合计
const findValueIndex = this.chart.data.fields.findIndex(
(e) => e.chartType === 'bar'
)
columns.forEach((column, columnIndex) => {
if (columnIndex === 0) {
if (this.cellDimension > 0 && findValueIndex !== -1) {
means.push(`合计(${this.chart.data.fields[findValueIndex].name})`)
} else {
means.push('合计')
}
} else {
let isRatio = false
if (
columnIndex >=
that.chart.data.fields.length - that.chart.data.series.length ||
this.cellDimension > 0
) {
const values = data.map((item) => {
let a = item[column.property]
if (typeof a === 'string' && a.indexOf('%') >= 0) {
a = a.replace('%', '')
isRatio = true
}
return Number(a)
})
// 合计
if (!values.every((value) => isNaN(value))) {
means[columnIndex] = values.reduce((prev, curr) => {
const value = Number(curr)
if (!isNaN(value)) {
return prev + curr
} else {
return prev
}
}, 0)
means[columnIndex] = (means[columnIndex] + '').includes('.')
? means[columnIndex].toFixed(2)
: means[columnIndex]
if (isRatio) {
means[columnIndex] =
means[columnIndex] > 100 ? 100 : means[columnIndex]
means[columnIndex] += '%'
}
} else {
means[columnIndex] = ''
}
} else {
means[columnIndex] = ''
}
}
})
// 返回一个二维数组的表尾合计(不要平均值,就不要在数组中添加)
return [means]
},
chartResize() {
// 指定图表的配置项和数据
this.calcHeightDelay()
},
initClass() {
return this.chart.id
},
resetHeight() {
this.height = 100
},
pageChange(val) {
this.currentPage.pageSize = val
this.init()
},
pageClick(val) {
this.currentPage.page = val
this.init()
},
resetPage() {
this.currentPage = {
page: 1,
pageSize: 10,
show: 0
}
}
}
}
</script>
<style scoped>
.table-class >>> .body--wrapper {
background: rgba(1, 1, 1, 0);
}
.table-class >>> .elx-cell {
max-height: none !important;
line-height: normal !important;
}
.table-page {
position: absolute;
bottom: 0;
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
overflow: hidden;
}
.page-style {
margin-right: auto;
}
.total-style {
flex: 1;
font-size: 12px;
color: #606266;
white-space: nowrap;
}
.page-style >>> .el-input__inner {
height: 24px;
}
.colum-header {
font-size: 12px;
color: #000;
background: rgb(78, 129, 187);
height: 36px;
}
</style>