多表格,多表头
2020-02-12 本文已影响0人
Biao_349d
bem.js
/*
* @Description: In User Settings Edit
* @Author: your name
* @Date: 2019-09-23 17:20:11
* @LastEditTime : 2020-02-02 19:22:15
* @LastEditors : Please set LastEditors
*/
/**
* bem helper
* b() // 'button'
* b('text') // 'button__text'
* b({ disabled }) // 'button button--disabled'
* b('text', { disabled }) // 'button__text button__text--disabled'
* b(['disabled', 'primary']) // 'button button--disabled button--primary'
*/
const ELEMENT = '__'
const MODS = '--'
const join = (name, el, symbol) =>
el ? (name ? name + symbol + el : el) : name
const prefix = (name, mods) => {
if (typeof mods === 'string') {
return join(name, mods, MODS)
}
if (Array.isArray(mods)) {
return mods.map(item => prefix(name, item))
}
const ret = {}
Object.keys(mods).forEach(key => {
ret[name + MODS + key] = mods[key]
})
return ret
}
export default {
methods: {
b(el, mods) {
const { name } = this.$options
if (el && typeof el !== 'string') {
mods = el
el = ''
}
el = join(name, el, ELEMENT)
return mods ? [el, prefix(el, mods)] : el
}
}
}
more-table.vue
<!--
* @Author: your name
* @Date: 2020-02-02 21:42:27
* @LastEditTime : 2020-02-08 10:25:59
* @LastEditors : Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \whyqh5\src\components\hd.vue
-->
<template>
<div :class="b('wrapper', ['wrapper'])">
<table cellpadding="0" cellspacing="0" border="1">
<tbody :class="b('wrapper', ['wrapper--th'])">
<tr
v-for="(item, index) in theadColumns"
:key="index"
:class="b('wrapper', ['wrapper--tr'])" class="clearfix"
:colspan="getMax((item || []), 'colspan') || 1"
:rowspan="getMax((item || []), 'rowspan') || 1"
>
<td
v-for="(item2, index2) in item || []"
:key="index2"
:class="b('wrapper', ['wrapper--tr--td'])"
v-bind="{
...(item2.bind || {})
}"
>
<div :class="b('wrapper', ['wrapper--tr--td--context'])">
{{ item2.name }}
</div>
</td>
</tr>
</tbody>
</table>
<table
v-for="(column, columnIndex) in columns"
:key="columnIndex"
cellpadding="0" cellspacing="0" border="1"
>
<tbody :class="b('wrapper', ['wrapper--tb'])">
<tr
v-for="(item, index) in column"
:key="index"
:class="b('wrapper', ['wrapper--tr'])" class="clearfix"
:colspan="getMax((item || []), 'colspan') || 1"
:rowspan="getMax((item || []), 'rowspan') || 1"
>
<td
v-for="(item2, index2) in item || []"
v-show="((data[columnIndex] || [])[index] || {})[item[index2].key]"
:key="index2"
:class="b('wrapper', ['wrapper--tr--td'])"
v-bind="{
...(item2.bind || {})
}"
>
<div :class="b('wrapper', ['wrapper--tr--td--context'])">
{{filterZero((( data[columnIndex] || [])[index] || {})[item[index2].key]) }}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'CommonMoreTable',
props: {
columns: {
type: Array,
default: () => {
return [
[] // 这里按照tbodyColumns的数据填
]
}
},
theadColumns: {
type: Array,
default: () => {
return []
// [
// [
// {
// name: '类别',
// key: 'name1',
// bind: {
// rowspan: '2',
// width: '20%',
// }
// },
// {
// name: '品名',
// key: 'name2',
// bind: {
// rowspan: '2',
// width: '20%',
// }
// },
// {
// name: '未来需求量',
// key: 'name3',
// bind: {
// colspan: "3",
// rowspan: "1",
// width: '40%',
// dataShow: false
// }
// },
// {
// name: '单位',
// key: 'name4',
// bind: {
// rowspan: '2',
// width: '20%',
// }
// }
// ],
// [
// {
// name: '未来7天',
// key: 'name5',
// bind: {
// rowspan: '1',
// }
// },
// {
// name: '未来15天',
// key: 'name6',
// bind: {
// rowspan: '1',
// }
// },
// {
// name: '未来30天',
// key: 'name7',
// bind: {
// rowspan: '1',
// }
// }
// ]
// ]
}
},
tbodyColumns: {
type: Array,
default: () => {
return []
// [
// [
// {
// key: 'name1',
// bind: {
// rowspan: '4',
// width: '20%',
// }
// },
// {
// key: 'name2',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// },
// {
// key: 'name4',
// bind: {
// colspan: "1",
// rowspan: "1",
// width: '10%',
// }
// },
// {
// key: 'name5',
// bind: {
// rowspan: '1',
// width: '13.4%',
// }
// },
// {
// key: 'name6',
// bind: {
// rowspan: '1',
// width: '13.4%',
// }
// },
// {
// key: 'name7',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// }
// ],
// [
// {
// key: 'name1',
// bind: {
// rowspan: '4',
// width: '20%',
// }
// },
// {
// key: 'name2',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// },
// {
// key: 'name4',
// bind: {
// colspan: "1",
// rowspan: "1",
// width: '13.33%',
// }
// },
// {
// key: 'name5',
// bind: {
// rowspan: '1',
// width: '13.33%',
// }
// },
// {
// key: 'name6',
// bind: {
// rowspan: '1',
// width: '13.34%',
// }
// },
// {
// key: 'name7',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// }
// ],
// [
// {
// key: 'name1',
// bind: {
// rowspan: '4',
// width: '20%',
// }
// },
// {
// key: 'name2',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// },
// {
// key: 'name4',
// bind: {
// colspan: "1",
// rowspan: "1",
// width: '13.33%',
// }
// },
// {
// key: 'name5',
// bind: {
// rowspan: '1',
// width: '13.33%',
// }
// },
// {
// key: 'name6',
// bind: {
// rowspan: '1',
// width: '13.34%',
// }
// },
// {
// key: 'name7',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// }
// ],
// [
// {
// key: 'name1',
// bind: {
// rowspan: '4',
// width: '20%',
// }
// },
// {
// key: 'name2',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// },
// {
// key: 'name4',
// bind: {
// colspan: "1",
// rowspan: "1",
// width: '13.33%',
// }
// },
// {
// key: 'name5',
// bind: {
// rowspan: '1',
// width: '13.33%',
// }
// },
// {
// key: 'name6',
// bind: {
// rowspan: '1',
// width: '13.34%',
// }
// },
// {
// key: 'name7',
// bind: {
// rowspan: '1',
// width: '20%',
// }
// }
// ],
// ]
}
},
data: {
type: Array,
default: () => {
return [
[] // 按照下面的数据放
]
// [
// {
// name1: '防护',
// name2: '外科口罩',
// name4: '861',
// name5: '1845万',
// name6: '3690万',
// name7: '万个'
// },
// {
// // name1: '防护',
// name2: '医用防护口罩',
// name4: '105',
// name5: '210',
// name6: '420',
// name7: '万个'
// },
// {
// // name1: '防护',
// name2: '医用防护服',
// name4: '530',
// name5: '105',
// name6: '210',
// name7: '万个'
// },
// {
// // name1: '防护',
// name2: '医用目镜/医用隔离眼罩',
// name4: '7000',
// name5: '120000',
// name6: '120000',
// name7: '套'
// }
// ]
}
},
border: {
type: Boolean,
default: false
},
tableStyle: {
type: Object,
default: () => {
return {}
}
},
},
// computed: {
// isShowTd(columnIndex, index, index2, item) {
// const val = ((this.data[columnIndex] || [])[index] || {})[item[index2].key]
// if (typeof val === 'number') {
// return '' + val
// }
// return val
// }
// },
filters: {
filterZero(val) {
if (typeof val === 'number') {
return '' + val
}
return val
}
},
methods: {
getMax(arr, name) {
return (arr.reduce(function (pre, curv) {
return pre[name] < curv[name] ? curv : pre;
}).bind || {})[name]
},
filterZero(val) {
if (typeof val === 'number') {
return '' + val
}
return val
}
}
}
</script>
<style lang="less">
.CommonMoreTable{
&__wrapper{
&--wrapper{
table, caption, tbody, tfoot, thead, tr, th, td{
// border: 1px solid #000;
}
table{
display: table;
width: 100%;
border-color: #E6E6E6;
border: none;
box-sizing: border-box;
TABLE-LAYOUT: fixed;
WORD-BREAK: break-all;
&:not(:first-child){
border-top: 0;
}
}
tbody{
border-color: #E6E6E6;
display: table;
width: 100%;
border: none;
box-sizing: border-box;
TABLE-LAYOUT: fixed;
WORD-BREAK: break-all;
}
&--th{
background:rgba(253,248,248,1);
// overflow: hidden;
// display: block;
display: table;
width: 100%;
.CommonMoreTable__wrapper--wrapper--tr{
&--td{
font-size:12px;
font-family:PingFangSC-Light,PingFang SC;
font-weight:300;
color:rgba(208,2,27,1);
line-height:20px;
padding: 8px 0px;
&--context{
display: inline;
word-break:break-all;
word-wrap:break-word;
font-size:12px;
box-sizing: border-box;
color:rgba(208,2,27,1);
}
}
}
// &:after{
// content: "";
// width:374px;
// height:1px;
// background:rgba(255,236,239,1);
// display: block;
// }
}
&--tb{
}
&--tr{
// padding: 3px 0;
// display: flex;
// justify-content: center; /* 水平居中 */
// align-items: center; /* 垂直居中 */
border: none;
box-sizing: border-box;
&--td{
padding: 8px 3px;
text-align: left;
box-sizing: border-box;
text-align:center; /** 设置水平方向居中 */
vertical-align:middle; /** 设置垂直方向居中 */
border-color: #E6E6E6;
&:first-child{
// padding-left: 14px;
}
&--context{
display: inline;
word-break:break-all;
word-wrap:break-word;
font-size:12px;
box-sizing: border-box;
color: #666666;
}
}
}
&--tr&--tr--border{
// border-bottom: 1px solid #E1E1E1;
&:not(:last-child){
// margin-top: 3px;
// border-bottom: 1px solid #E1E1E1;
}
}
}
}
}
</style>
调用方法
<template>
<div>
<CommonMoreTable :theadColumns="theadColumns" :columns="columns2" :data="data2"></CommonMoreTable>
</div>
</template>
<script>
import CommonMoreTable from '@/components/more-table/_base';
import { mapState, mapActions } from 'vuex';
const keyObj = {
key1: 'category',
key2: 'productName',
key3: 'name3',
key4: 'next7Days',
key5: 'next15Days',
key6: 'next30Days',
key7: 'unit',
}
const columnsObj = {
key1: {
key: keyObj.key1,
bind: {
rowspan: '4',
width: '15%',
}
},
key2: {
key: keyObj.key2,
bind: {
rowspan: '1',
width: '20%',
}
},
key4: {
key: keyObj.key4,
bind: {
colspan: "1",
rowspan: "1",
width: '18.3%',
}
},
key5: {
key: keyObj.key5,
bind: {
rowspan: '1',
width: '18.3%',
}
},
key6: {
key: keyObj.key6,
bind: {
rowspan: '1',
width: '18.3%',
}
},
key7:{
key: keyObj.key7,
bind: {
rowspan: '1',
width: '10%',
}
}
}
export default {
components: {
CommonMoreTable
},
data() {
return {
theadColumns: [
[
{
name: '类别',
key: keyObj.key1,
bind: {
rowspan: '2',
width: '15%',
}
},
{
name: '品名',
key: keyObj.key2,
bind: {
rowspan: '2',
width: '20%',
}
},
{
name: '未来需求量',
key: keyObj.key3,
bind: {
colspan: "3",
rowspan: "1",
width: '55%',
}
},
{
name: '单位',
key: keyObj.key7,
bind: {
rowspan: '2',
width: '10%',
}
}
],
[
{
name: '未来7天',
key: keyObj.key4,
bind: {
rowspan: '1',
width: '18.3%',
}
},
{
name: '未来15天',
key: keyObj.key5,
bind: {
rowspan: '1',
width: '18.3%',
}
},
{
name: '未来30天',
key: keyObj.key6,
bind: {
rowspan: '1',
width: '18.3%',
}
}
]
],
protectKeyMaterials: [
{
"category":"分类一",
"next15Days":"111",
"next30Days":"222",
"next7Days":"333",
"productName":"A",
"unit":"万个"
},
{
"category":"分类一",
"next15Days":"210",
"next30Days":"420",
"next7Days":"105",
"productName":"B",
"unit":"万个"
},
{
"category":"分类一",
"next15Days":"105",
"next30Days":"210",
"next7Days":"53",
"productName":"c",
"unit":"万套"
},
{
"category":"分类一",
"next15Days":"120000",
"next30Days":"120000",
"next7Days":"70000",
"productName":"d",
"unit":"副"
},
{
"category":"分类2",
"next15Days":"22500",
"next30Days":"45000",
"next7Days":"10500",
"productName":"A",
"unit":"箱"
},
{
"category":"分类2",
"next15Days":"225000",
"next30Days":"450000",
"next7Days":"105000",
"productName":"B",
"unit":"瓶"
},
{
"category":"分类2",
"next15Days":"225000",
"next30Days":"450000",
"next7Days":"105000",
"productName":"C",
"unit":"台"
},
{
"category":"分类3",
"next15Days":"600",
"next30Days":"600",
"next7Days":"600",
"productName":"A",
"unit":"台"
},
]
}
},
computed: {
columns2() {
return this.data2.map(item => {
return (item || []).map((item2, index) => {
const arr = []
if (index == 0) {
arr.push(
{
...columnsObj.key1,
bind: {
...columnsObj.key1.bind,
rowspan: item.length
}
}
)
}
return [
...arr,
...[
columnsObj.key2,
columnsObj.key4,
columnsObj.key5,
columnsObj.key6,
columnsObj.key7,
]
]
})
})
},
data2() {
const obj = {}
this.protectKeyMaterials.forEach(item => {
// category
if (Object.keys(obj).indexOf(item[keyObj.key1]) === -1) {
obj[item[keyObj.key1]] = []
obj[item[keyObj.key1]].push(item)
} else {
obj[item[keyObj.key1]].push(item)
}
})
return Object.values(obj)
}
},
created() {
this.getProtectKeyMaterials()
},
mounted() {
},
methods: {
...mapActions(['getProtectKeyMaterials'])
}
}
</script>
image.png