<template> <div class="vant-table"> <div class="positionColumn" v-if="isPosition"> <table cellspacing="0" style="width: 100%" class="table"> <thead> <tr> <th class="th">{{ option.collectColumn[0].label }}</th> </tr> </thead> <tbody> <template v-if="tableData.length > 0"> <tr v-for="(item, index) in tableData" :key="index" :class="{ grey: item.isChildren, isOdd: item.isOdd }" class="list-tr" @click="getChildren(item, index)" > <td v-for="(context, key) in option.collectColumn" :key="key"> <van-icon v-if="item.level > 1" :class="{ img01: item.show }" name="arrow-up" /> <span :class="{ div: isPosition }">{{ item[context.prop] }}</span> </td> </tr> </template> </tbody> </table> </div> <div :class="{ positionBody: isPosition }"> <table cellspacing="0" class="table" :class="{ tableWidth: isPosition }"> <thead> <tr> <th class="th" v-for="(item, index) in option.column" :key="index">{{ item.label }}</th> </tr> </thead> <tbody> <template v-if="tableData.length > 0"> <tr @click="getChildren(item, index)" :class="{ grey: item.isChildren, isOdd: item.isOdd }" v-for="(item, index) in tableData" :key="index" class="list-tr" > <td v-for="(context, key) in option.column" :key="key"> <van-icon v-if="!isPosition && !key && item.level > 1" :class="{ img01: item.show }" name="arrow-up" /> <span :class="{ div: !isPosition && !key }">{{ item[context.prop] }}</span> </td> </tr> </template> </tbody> </table> </div> </div></template><script>export default { name: 'VantTable', data() { return { bgcolor: { background: 'black' } } }, props: { isPosition: { // 是否固定列 default: false, type: Boolean }, tableData: Array, option: Object }, created() { this.tableData.forEach(item => { item.show = false }) }, methods: { getChildren(item, index) { if (!item.level || item.level <= 1) { return } if (item.show) { this.$emit('deleteChildren', item, index) } else { this.$emit('getChildren', item, index) } } }}</script><style lang="scss" scoped>* { padding: 0;}.img01 { transform: rotate(180deg); transition-duration: 0.3s;}.tableWidth { min-width: 400px;}.isOdd { background: #f4f7f9;}.vant-table { width: 100%; position: relative; .positionColumn { position: absolute; left: 0; top: 0; width: 150px; background: #fff; padding-bottom: 8px; .table { .list-tr { width: 100%; height: 56px; th, td { text-align: left !important; display: flex; width: 150px; .van-icon { width: 15px; padding-right: 5px; color: #a5abb9; } &:first-child { text-align: left; span { width: 130px; } } i { top: 0px; } } } } } .positionBody { width: calc(100% - 150px); padding-left: 150px; overflow-x: scroll; padding-bottom: 8px; .table { table-layout: fixed; thead th:first-child { padding: 0; width: 70px; text-align: center; } .list-tr td:first-child { padding: 0; width: 70px; text-align: center; span { width: 70px; } } } } .table { width: 100%; table-layout: fixed; thead { background: #ecf3fe; border-radius: 1px; .th { height: 56px; text-align: center; width: 70px; &:first-child { text-align: center; width: 120px; } } } .list-tr { height: 56px; text-align: center; td { color: #078eff; // display: flex; height: 56px; align-items: center; width: 70px; @include textoverflow; &:first-child { padding-left: 10px; text-align: left; width: 120px; span { width: 90px; } } span { @include textoverflow; width: 70px; // display: inline-block; } i { // top: -4px; transition-duration: 0.3s; } } } .grey { background: #f5f5f5; td { color: #0e0e0e; .div { // padding-left: 25px; } } } }}</style>
调用组件代码
// html
<vantTable :option="option" :tableData="accountList" @deleteChildren="deleteChildren" @getChildren="getChildren" />
// js 数据源
// 表头
option=[
{
label: '部门名称',
prop: 'departName'
},
{
label: '总数',
prop: 'total'
},
{
label: '已完成',
prop: 'patrolTotal'
},
{
label: '完成率',
prop: 'patrolRate'
}
]
// 数据
accountList=[{ departName: "部门1", level: 1, noPatrolTotal: 3, orgCode: "A03A13A15A14A04A06A08", parentId: "GO_33356fd59b024a73be1fbee20f1fba5b", patrolRate: "25%", patrolTotal: 1, total: 4}]
// js 组装数据
geChildren(item, index) { item.show = !item.show this.getPatrolAccount( item.orgCode, index, item) },
getPatrolAccount( orgCode, index, targetItem) { try { var collectParams = { departId: orgCode } // 获取数据
let res = await getCollectStatistics(collectParams) if (res && res.success && res.result) { if (orgCode) { // 添加子集 res.result.forEach(item => { item.isChildren = true item.parent = targetItem }) targetItem.childrenLength = res.result.length // 给当前节点所有父级的childrenLength追加子集的长度 const addLenToGrandParent = (targetItem) => { if (targetItem.parent) { targetItem.parent.childrenLength += res.result.length addLenToGrandParent(targetItem.parent) } } addLenToGrandParent(targetItem) this.accountList.splice(index + 1, 0, ...res.result) this.$set(this.accountList[index], 'length', res.result.length) } } else { this.$toast(res.message, '查询数据失败,请稍后再试') } } catch (error) { console.log('error', error) this.$toast('查询数据失败,请稍后再试') } },// 删除当前节点所有的子孙数据,并把当前所属父集节点length 减掉对应的长度deleteChildren(item, index) { const deletedLen = item.childrenLength this.accountList.splice(index + 1, deletedLen) const reduceLenToGrandParent = (target) => { if (target.parent) { target.parent.childrenLength -= deletedLen reduceLenToGrandParent(target.parent) } } item.childrenLength = 0 reduceLenToGrandParent(item) item.show = !item.show },