实现效果如上,表格内需要有checkbox,跨页记录状态,纯手写
组件内:
<template>
<div class="transDoubleTable">
<div class="content-data">
<div class="content-table">
<div class="row-ever" v-for="(item, index) in transTableOne" :key="'row1' + index">
<div :class="'column-ever column-ever'+childIndex" v-for="(childItem, childIndex) in item"
:key="'child1' + childIndex" :style="'width:calc((100% - 40px)/' + (item.length - 1) +')'">
<a-checkbox v-model="childItem.checkValue" v-if="childItem.hasCheckBox"
@change="changeValueOne(index,childIndex,childItem)" :indeterminate='childItem.indeterminate'></a-checkbox>
<span
:class="'content-title ' + (childItem.hasCheckBox === true && index !== 0 ? 'changeTitle' : '')">{{childItem.title}}</span>
</div>
</div>
</div>
</div>
<div class="content-data">
<div class="content-table">
<div class="row-ever" v-for="(item, index) in transTableTwo" :key="'row2' + index">
<div :class="'column-ever column-ever'+childIndex" v-for="(childItem, childIndex) in item"
:key="'child2' + childIndex" :style="'width:calc((100% - 40px)/' + (item.length - 1) +')'">
<a-checkbox v-model="childItem.checkValue" v-if="childItem.hasCheckBox"
@change="changeValueTwo(index,childIndex,childItem)" :indeterminate='childItem.indeterminate'></a-checkbox>
<span
:class="'content-title ' + (childItem.hasCheckBox === true && index !== 0 ? 'changeTitle' : '')">{{childItem.title}}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'transDoubleTable',
data() {
return {
transTableOne: [],
transTableTwo: [],
leftDisabled: false
}
},
props: {
// 选中数据列表
choosedDataList: {
type: Array,
default:() => {
return []
}
},
// 源数据列表
sourceList: {
type: Array,
default:() => {
return []
}
},
// 目标数据列表
targetList: {
type: Array,
default:() => {
return []
}
},
},
watch: {
sourceList: {
handler(val) {
this.transTableOne = []
for (let i=0;i<=val.length;i++) {
this.transTableOne.push([])
this.transTableOne[i][0] = {
hasCheckBox: false,
title: '',
checkValue: false,
indeterminate: false
}
if (i === 0) {
for (let j in this.sourceList[i]) {
this.transTableOne[i].push({
hasCheckBox: false,
title: j,
checkValue: false,
indeterminate: false
})
}
} else {
for (let j in this.sourceList[i - 1]) {
this.transTableOne[i].push({
hasCheckBox: false,
title: this.sourceList[i - 1][j],
checkValue: false,
indeterminate: false
})
}
}
}
// this.compareDifference()
// this.initDataCheckBox()
// this.initChoosedTable()
},
deep: true,
immediate: true
},
targetList: {
handler(val) {
this.transTableTwo = []
for (let i=0;i<=val.length;i++) {
this.transTableTwo.push([])
this.transTableTwo[i][0] = {
hasCheckBox: false,
title: '',
checkValue: false,
indeterminate: false
}
if (i === 0) {
for (let j in this.targetList[i]) {
this.transTableTwo[i].push({
hasCheckBox: false,
title: j,
checkValue: false,
indeterminate: false
})
}
} else {
for (let j in this.targetList[i - 1]) {
this.transTableTwo[i].push({
hasCheckBox: false,
title: this.targetList[i - 1][j],
checkValue: false,
indeterminate: false
})
}
}
}
this.compareDifference()
this.initDataCheckBox()
this.initChoosedTable()
},
deep: true,
immediate: true
},
},
mounted() {
},
methods: {
/**
* @desc: 对比两个表格差异
* @return {*}
*/
compareDifference () {
for (let i=0;i<this.transTableOne.length;i++) {
for (let j=0;j<this.transTableOne[i].length;j++) {
if (this.transTableOne[i][j].title !== this.transTableTwo[i][j].title) {
this.transTableOne[i][j].hasCheckBox = true
this.transTableTwo[i][j].hasCheckBox = true
}
}
}
},
/**
* @desc: 初始化全表内选择框
* @return {*}
*/
initDataCheckBox () {
let totalHasCheck = false
for (let i=1;i<this.transTableOne.length;i++) {
for (let j=1;j<this.transTableOne[i].length;j++) {
if (this.transTableOne[i][j].hasCheckBox === true) {
this.transTableOne[i][0].hasCheckBox = true
this.transTableOne[0][j].hasCheckBox = true
this.transTableTwo[i][0].hasCheckBox = true
this.transTableTwo[0][j].hasCheckBox = true
totalHasCheck = true
}
}
}
if (totalHasCheck) {
this.transTableOne[0][0].hasCheckBox = true
this.transTableTwo[0][0].hasCheckBox = true
}
},
/**
* @desc: 渲染选中内容
* @return {*}
*/
initChoosedTable () {
let nowSourceTitleList = this.choosedDataList.map(item => {
return item.sourceTitle
})
for (let i=0;i<this.transTableOne.length;i++) {
for (let j=0;j<this.transTableOne[i].length;j++) {
if (nowSourceTitleList.includes(this.transTableOne[i][j].title)) {
this.transTableOne[i][j].checkValue = true
this.transTableTwo[i][j].checkValue = true
}
}
}
this.playUpTableHead()
},
/**
* @desc: 渲染表头和首列的变化
* @return {*}
*/
playUpTableHead () {
// 第一行表头状态
let rowTrueList = new Array(this.transTableOne[0].length).fill(true)
// 第一列表头状态
let columnTrueList = new Array(this.transTableOne.length).fill(true)
for (let i = 1; i < this.transTableOne.length; i++) {
let totalJudgeList = this.transTableOne[i].filter((item, index) => {
return item.hasCheckBox === true && index > 0
})
let falseList = this.transTableOne[i].filter((item, index) => {
return item.checkValue !== true && item.hasCheckBox === true && index > 0
})
if (falseList.length === 0) {
columnTrueList[i] = true
} else if (falseList.length > 0 && falseList.length < totalJudgeList.length) {
columnTrueList[i] = 'indeterminate'
} else{
columnTrueList[i] = false
}
}
for (let j = 1; j < this.transTableOne[0].length; j++) {
let falseLength = 0
let totalJudgeLength = 0
for (let i = 1;i < this.transTableOne.length;i++) {
if (this.transTableOne[i][j].hasCheckBox === true) {
totalJudgeLength = totalJudgeLength + 1
if (this.transTableOne[i][j].checkValue !== true) {
falseLength = falseLength + 1
}
}
}
if (falseLength === 0) {
rowTrueList[j] = true
} else if (falseLength > 0 && falseLength < totalJudgeLength) {
rowTrueList[j] = 'indeterminate'
} else{
rowTrueList[j] = false
}
}
for (let i = 1; i < this.transTableOne[0].length; i++) {
if (rowTrueList[i] === 'indeterminate') {
this.transTableOne[0][i].indeterminate = true
this.transTableOne[0][i].checkValue = false
} else {
this.transTableOne[0][i].checkValue = rowTrueList[i]
this.transTableOne[0][i].indeterminate = false
}
}
for (let i = 1; i < this.transTableOne.length; i++) {
if (columnTrueList[i] === 'indeterminate') {
this.transTableOne[i][0].indeterminate = true
this.transTableOne[i][0].checkValue = false
} else {
this.transTableOne[i][0].checkValue = columnTrueList[i]
this.transTableOne[i][0].indeterminate = false
}
}
// 判断是否会造成全选变化
for (let i=0;i<this.transTableOne.length;i++) {
for (let j=0;j<this.transTableOne[i].length;j++) {
if ((i === 0 || j === 0) && this.transTableOne[i][j].hasCheckBox === false) {
if (i === 0) {
rowTrueList[j] = 'hasCheckBoxFalse'
}
if (j === 0) {
columnTrueList[i] = 'hasCheckBoxFalse'
}
}
}
}
let newList = rowTrueList.concat(columnTrueList)
newList.splice(0,1)
newList.splice(rowTrueList.length - 1,1)
if (!newList.includes(false) && !newList.includes('indeterminate')) {
this.transTableOne[0][0].checkValue = true
this.transTableOne[0][0].indeterminate = false
} else if (!newList.includes(true) && !newList.includes('indeterminate')) {
this.transTableOne[0][0].checkValue = false
this.transTableOne[0][0].indeterminate = false
} else {
this.transTableOne[0][0].checkValue = false
this.transTableOne[0][0].indeterminate = true
}
// 对第二个表格赋值
for (let i=0;i<this.transTableOne.length;i++) {
for (let j=0;j<this.transTableOne[i].length;j++) {
this.transTableTwo[i][j].checkValue = this.transTableOne[i][j].checkValue
this.transTableTwo[i][j].indeterminate = this.transTableOne[i][j].indeterminate
}
}
},
/**
* @desc: 左边表格点击变化
* @return {*}
*/
changeValueOne(rowIndex, columnIndex, item) {
let changeList = []
// 勾选左上角全选变化
if (rowIndex === 0 && columnIndex === 0) {
for (let i = 0; i < this.transTableOne.length; i++) {
for (let j = 0; j < this.transTableOne[j].length; j++) {
this.transTableOne[i][j].checkValue = item.checkValue
if (i !== 0 && j !== 0 && this.transTableOne[i][j].hasCheckBox) {
changeList.push({
sourceTitle: this.transTableOne[i][j].title,
targetTitle: this.transTableTwo[i][j].title
})
}
}
}
}
// 勾选第一行表头变化
if (rowIndex === 0 && columnIndex !== 0) {
for (let i = 0; i < this.transTableOne.length; i++) {
for (let j = 0; j < this.transTableOne[j].length; j++) {
if (j === columnIndex) {
this.transTableOne[i][columnIndex].checkValue = item.checkValue
if (i !== 0 && this.transTableOne[i][columnIndex].hasCheckBox) {
changeList.push({
sourceTitle: this.transTableOne[i][j].title,
targetTitle: this.transTableTwo[i][j].title
})
}
}
}
}
}
// 勾选第一列表头变化
if (rowIndex !== 0 && columnIndex === 0) {
for (let i = 0; i < this.transTableOne.length; i++) {
for (let j = 0; j < this.transTableOne[j].length; j++) {
if (i === rowIndex) {
this.transTableOne[rowIndex][j].checkValue = item.checkValue
if (j !== 0 && this.transTableOne[rowIndex][j].hasCheckBox) {
changeList.push({
sourceTitle: this.transTableOne[i][j].title,
targetTitle: this.transTableTwo[i][j].title
})
}
}
}
}
}
if (rowIndex !== 0 && columnIndex !== 0) {
changeList.push({
sourceTitle: this.transTableOne[rowIndex][columnIndex].title,
targetTitle: this.transTableTwo[rowIndex][columnIndex].title
})
}
this.$emit('changeChoosedData', changeList, item.checkValue)
this.playUpTableHead()
},
/**
* @desc: 右边表格点击变化
* @return {*}
*/
changeValueTwo(rowIndex, columnIndex, item) {
let changeList = []
// 勾选左上角全选变化
if (rowIndex === 0 && columnIndex === 0) {
for (let i = 0; i < this.transTableTwo.length; i++) {
for (let j = 0; j < this.transTableTwo[j].length; j++) {
this.transTableTwo[i][j].checkValue = item.checkValue
if (i !== 0 && j !== 0 && this.transTableTwo[i][j].hasCheckBox) {
changeList.push({
sourceTitle: this.transTableOne[i][j].title,
targetTitle: this.transTableTwo[i][j].title
})
}
}
}
}
// 勾选第一行表头变化
if (rowIndex === 0 && columnIndex !== 0) {
for (let i = 0; i < this.transTableTwo.length; i++) {
for (let j = 0; j < this.transTableTwo[j].length; j++) {
if (j === columnIndex) {
this.transTableTwo[i][columnIndex].checkValue = item.checkValue
if (i !== 0 && this.transTableTwo[i][columnIndex].hasCheckBox) {
changeList.push({
sourceTitle: this.transTableOne[i][j].title,
targetTitle: this.transTableTwo[i][j].title
})
}
}
}
}
}
// 勾选第一列表头变化
if (rowIndex !== 0 && columnIndex === 0) {
for (let i = 0; i < this.transTableTwo.length; i++) {
for (let j = 0; j < this.transTableTwo[j].length; j++) {
if (i === rowIndex) {
this.transTableTwo[rowIndex][j].checkValue = item.checkValue
if (j !== 0 && this.transTableTwo[rowIndex][j].hasCheckBox) {
changeList.push({
sourceTitle: this.transTableOne[i][j].title,
targetTitle: this.transTableTwo[i][j].title
})
}
}
}
}
}
if (rowIndex !== 0 && columnIndex !== 0) {
changeList.push({
sourceTitle: this.transTableOne[rowIndex][columnIndex].title,
targetTitle: this.transTableTwo[rowIndex][columnIndex].title
})
}
this.$emit('changeChoosedData', changeList, item.checkValue)
// 第一行表头状态
let rowTrueList = new Array(this.transTableTwo[0].length).fill(true)
// 第一列表头状态
let columnTrueList = new Array(this.transTableTwo.length).fill(true)
for (let i = 1; i < this.transTableTwo.length; i++) {
let totalJudgeList = this.transTableTwo[i].filter((item, index) => {
return item.hasCheckBox === true && index > 0
})
let falseList = this.transTableTwo[i].filter((item, index) => {
return item.checkValue !== true && item.hasCheckBox === true && index > 0
})
if (falseList.length === 0) {
columnTrueList[i] = true
} else if (falseList.length > 0 && falseList.length < totalJudgeList.length) {
columnTrueList[i] = 'indeterminate'
} else{
columnTrueList[i] = false
}
}
for (let j = 1; j < this.transTableTwo[0].length; j++) {
let falseLength = 0
let totalJudgeLength = 0
for (let i = 1;i < this.transTableTwo.length;i++) {
if (this.transTableTwo[i][j].hasCheckBox === true) {
totalJudgeLength = totalJudgeLength + 1
if (this.transTableTwo[i][j].checkValue !== true) {
falseLength = falseLength + 1
}
}
}
if (falseLength === 0) {
rowTrueList[j] = true
} else if (falseLength > 0 && falseLength < totalJudgeLength) {
rowTrueList[j] = 'indeterminate'
} else{
rowTrueList[j] = false
}
}
for (let i = 1; i < this.transTableTwo[0].length; i++) {
if (rowTrueList[i] === 'indeterminate') {
this.transTableTwo[0][i].indeterminate = true
this.transTableTwo[0][i].checkValue = false
} else {
this.transTableTwo[0][i].checkValue = rowTrueList[i]
this.transTableTwo[0][i].indeterminate = false
}
}
for (let i = 1; i < this.transTableTwo.length; i++) {
if (columnTrueList[i] === 'indeterminate') {
this.transTableTwo[i][0].indeterminate = true
this.transTableTwo[i][0].checkValue = false
} else {
this.transTableTwo[i][0].checkValue = columnTrueList[i]
this.transTableTwo[i][0].indeterminate = false
}
}
// 判断是否会造成全选变化
for (let i=0;i<this.transTableTwo.length;i++) {
for (let j=0;j<this.transTableTwo[i].length;j++) {
if ((i === 0 || j === 0) && this.transTableTwo[i][j].hasCheckBox === false) {
if (i === 0) {
rowTrueList[j] = 'hasCheckBoxFalse'
}
if (j === 0) {
columnTrueList[i] = 'hasCheckBoxFalse'
}
}
}
}
let newList = rowTrueList.concat(columnTrueList)
newList.splice(0,1)
newList.splice(rowTrueList.length - 1,1)
if (!newList.includes(false) && !newList.includes('indeterminate')) {
this.transTableTwo[0][0].checkValue = true
this.transTableTwo[0][0].indeterminate = false
} else if (!newList.includes(true) && !newList.includes('indeterminate')) {
this.transTableTwo[0][0].checkValue = false
this.transTableTwo[0][0].indeterminate = false
} else {
this.transTableTwo[0][0].checkValue = false
this.transTableTwo[0][0].indeterminate = true
}
// 对第二个表格赋值
for (let i=0;i<this.transTableTwo.length;i++) {
for (let j=0;j<this.transTableTwo[i].length;j++) {
this.transTableOne[i][j].checkValue = this.transTableTwo[i][j].checkValue
this.transTableOne[i][j].indeterminate = this.transTableTwo[i][j].indeterminate
}
}
}
}
}
</script>
样式(基本样式,需要调整):
.transDir {
display: flex;
flex-direction: column;
justify-content: center;
::v-deep .ant-btn-primary{
width: 120px;
text-align: center;
margin-top: 10px;
}
}
.column-ever {
text-align: center;
height: 40px;
line-height: 40px;
border-right: 1px solid #EFF2FB;
border-bottom: 1px solid #EFF2FB;
position: relative;
}
.changeTitle {
color: #D9001B !important;
}
.column-ever0 {
width: 40px !important;
::v-deep .ant-checkbox-wrapper {
position: relative !important;
left: 0px !important;
}
}
.transDoubleTable {
display: flex;
.content-data:last-of-type {
margin-right: 0px;
}
.content-data {
width: calc(50% - 10px);
margin-right: 20px;
border-left: 1px solid #E3E6EF;
border-bottom: 1px solid #E3E6EF;
border-right: 1px solid #E3E6EF;
.content-table{
margin: 23.64px 36px 0px 15px;
border-left: 1px solid #EFF2FB;
border-top: 1px solid #EFF2FB;
&:first-child{
background: #F5F6FA !important;
border-radius: 3px 3px 0px 0px;
}
}
.row-ever {
display: flex;
.content-title {
width: 80%;
margin-left: 10%;
text-align: center;
display: inline-block;
}
::v-deep .ant-checkbox-wrapper {
position: absolute;
left: 5px;
}
}
}
}
使用:
<template>
<div class="compare-detail">
<TransDoubleTable :choosedDataList='choosedDataList' :sourceList='sourceList' :targetList='targetList' @changeChoosedData='changeChoosedData'></TransDoubleTable>
<a-pagination :current="page.current" show-quick-jumper :showSizeChanger='page.showSizeChanger' :size='page.size' :total="page.total" :showTotal='page.showTotal' :pageSize='page.pageSize' :pageSizeOptions='page.pageSizeOptions' @change="onChangePage" @showSizeChange="onChangeSizePage"/>
</div>
</template>
<script>
import TransDoubleTable from '@/components/transDoubleTable/index'
export default {
name: 'compareDetail',
components: {
TransDoubleTable
},
data() {
return {
page: {
total: 50,
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '20', '50'],
showTotal: (total) => {
return ' 共 ' + total + ' 项数据'
},
showSizeChanger: true,
size: 'middle'
},
// 已选中的单个数据列表
choosedDataList: [],
// 源数据列表
sourceList: [],
// 目标数据列表
targetList: []
}
},
watch: {
},
created() {
this.initTransTableData(this.page.current, this.page.pageSize)
},
methods: {
/**
* @desc: 切换页码
* @return {*}
*/
onChangePage(current, pageSize){
this.initTransTableData(current, pageSize)
this.page.current = current
},
/**
* @desc: 页面数量大小变化
* @return {*}
*/
onChangeSizePage(current, pageSize){
this.initTransTableData(current, pageSize)
this.page.pageSize = pageSize
},
/**
* @desc: 获取对应页码和内容的源表数据和目标表数据
* @return {*}
*/
initTransTableData(current, pageSize){
let sourceList = []
for (let i = 0; i < pageSize; i++) {
sourceList.push({})
for (let j=0; j < 4; j++) {
sourceList[i]['column' + '-' + current + '-' + i + '-' + j] = 'content' + current + '-' + i + '-' + j
}
}
let targetList = []
for (let i = 0; i < pageSize; i++) {
targetList.push({})
for (let j=0; j < 4; j++) {
let nowStatsu = j > 1
targetList[i]['column' + '-' + current + '-' + i + '-' + j] = nowStatsu ? 'content' + current + '-' + i + '-' + j + 'C' : 'content' + current + '-' + i + '-' + j
}
}
this.sourceList = sourceList
this.targetList = targetList
},
/**
* @desc: 表格内选中数据变化
* @return {*}
*/
changeChoosedData (titleList, status) {
// status为true时,向选中数组内添加内容,为false,删除对应内容
if (status) {
// 合并列表
let totalList = this.choosedDataList.concat(titleList)
// 去除重复后新列表
let newList = []
totalList.map(item => {
let newListSourceTitleList = newList.map(item => {
return item.sourceTitle
})
if (!newListSourceTitleList.includes(item.sourceTitle)) {
newList.push(item)
}
})
this.choosedDataList = newList
} else {
let nowSourceTitleList = titleList.map(item => {
return item.sourceTitle
})
this.choosedDataList = this.choosedDataList.filter(item => {
if (!nowSourceTitleList.includes(item.sourceTitle)) {
return item
}
})
}
}
}
}
</script>
小小记录一手,写了差不多四个小时,龟龟~