初版比较简陋,也没找到合适的插件,如在阅读过程中发现有的插件可以分享我一个,有错误的也希望给予指正。
1、先放两张成品图
2、部分代码说明
watch中对两个复杂数组进行监听需要增加deep:true属性,打印newVal和oldVal发现两个值都一样,原因是因为他两个指向是一样的,所以需要
通过计算属性computed来获取变化前后的值
通过for...in...可以获取对象的键
Array.from(new Set(tempArr)).toString()可以将简单数组先排序再转字符串
数组不能通过===或者==判断是否相同,所以组要转一下在判断是否相同JSON.stringify(newVal) !== JSON.stringify(oldVal)
3、完整代码部分
<vxe-table
:data="array"
:loading="loading"
row-id="id"
size="small"
ref="mandateTable"
align="center"
border
auto-resize
resizable
show-header-overflow
show-overflow
highlight-hover-row
class="table">
<vxe-column field="name" title="应用访问权限" align="left" header-align="center">
<template #default="scope">
<vxe-checkbox v-model="scope.row.check" :indeterminate="scope.row.check === '2'" @change="checkChangeEvent(scope.$rowIndex, scope.$columnIndex, scope.row.check, scope.type)" checked-value="1" unchecked-value="0">{{scope.row.name}}</vxe-checkbox>
</template>
</vxe-column>
<vxe-colgroup field="b" title="可用登录方式">
<vxe-column v-for="(item, index) in arrayHeader" :key="'arrayHeader' + index" :title="item.name" :field="item.field">
<template #header="scope">
<vxe-checkbox v-model="item.check" :indeterminate="item.check === '2'" @change="checkChangeEvent(scope.$rowIndex, scope.$columnIndex,item.check, scope.type, item.field)" checked-value="1" unchecked-value="0">{{item.name}}</vxe-checkbox>
</template>
<template #default="scope">
<span v-if="scope.row[item.field] === '2'" style="color: #DDE0E7;">/</span>
<vxe-checkbox v-else v-model="scope.row[item.field]" @change="checkChangeEvent(scope.$rowIndex, scope.$columnIndex, scope.row[item.field], scope.type, item.field, scope.row)" :disabled="scope.row[item.field] === '2'" checked-value="1" unchecked-value="0"></vxe-checkbox>
</template>
</vxe-column>
</vxe-colgroup>
</vxe-table>
<script>
export default {
name: 'mandate-form',
data() {
return {
loading: false,
arrayHeader: [
{ id: '11', name: '登录1', field: 'jobNum', check: '0'},
{ id: '12', name: '登录2', field: 'loginName', check: '0'},
{ id: '13', name: '登录3', field: 'IDcard', check: '0'},
{ id: '14', name: '登录4', field: 'phone', check: '0'},
{ id: '15', name: '登录5', field: 'captcha', check: '0'},
{ id: '16', name: '登录6', field: 'email', check: '0'},
{ id: '17', name: '登录7', field: 'certificate', check: '0'}
],
array: [
//check: 0 未选中 1选中 2半选中 其他: 0 未选中 1选中 2未选且禁止
{ id: 10001, name: '平台端', jobNum: '0', loginName: '2', IDcard: '0', phone: '0', captcha: '0', email: '0', certificate: '2', check: '0' },
{ id: 10002, name: 'APP', jobNum: '0', loginName: '2', IDcard: '2', phone: '2', captcha: '2', email: '0', certificate: '2', check: '0' },
{ id: 10003, name: 'XX系统', jobNum: '0', loginName: '2', IDcard: '0', phone: '0', captcha: '0', email: '2', certificate: '0', check: '0' },
{ id: 10004, name: 'XX APP', jobNum: '0', loginName: '0', IDcard: '0', phone: '0', captcha: '0', email: '0', certificate: '0', check: '0' },
]
}
},
computed: {
newArrayHeader() {
return JSON.parse(JSON.stringify(this.arrayHeader))
},
newArray() {
return JSON.parse(JSON.stringify(this.array))
}
},
watch:{
'newArrayHeader':{
handler: function (newVal, oldVal) {
//顶栏联动左栏全选
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.arrayHeader.forEach(h_item => {
this.array.forEach(item => {
if (item[h_item.field] !== '2') {
let tempArr = []
for (let key in item) {
if (key !== 'name' && key !== 'id') {
tempArr.push(item[key])
}
}
let tempStr = Array.from(new Set(tempArr)).toString()
if (tempStr === '0,2' || tempStr === '2,0' || tempStr === '0') {
item.check = '0'
} else if(tempStr === '1,2' || tempStr === '2,1' || tempStr === '1') {
item.check = '1'
} else {
item.check = '2'
}
}
})
})
}
},
deep:true
},
'newArray':{
handler: function (newVal, oldVal) {
//左栏联动顶栏全选
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.arrayHeader.forEach((h_item, index) => {
let tempArr = []
this.array.forEach(item => {
for(let key in item) {
if (key !== 'name' && key !== 'id') {
tempArr.push(item[h_item.field])
}
}
})
let tempStr = Array.from(new Set(tempArr)).toString()
if (tempStr === '1,2' || tempStr === '2,1' || tempStr === '1') {
this.arrayHeader[index].check = '1'
} else if (tempStr === '0,2' || tempStr === '2,0' || tempStr === '0') {
this.arrayHeader[index].check = '0'
} else {
this.arrayHeader[index].check = '2'
}
})
}
},
deep:true
}
},
methods: {
checkChangeEvent(row, col, value, type, field, rowData) {
/*
* value 表示点击项的值
* type 等于header为表头 等于body为主体
* field 表格右侧表头 用以区分列
* rowData 当前行的所有数据
* 当col为0 表示后面除过禁选项需要全选 不为0时需要判断除过禁选项是否都被选择从而决定前面是不是为1
* */
if (type === 'body' && col === 0) {
//表格左栏全选
for(let key in this.array[col]) {
if (key !== 'name' && key !== 'id' && (value === '1' || value === '2')) {
this.array[row][key] = this.array[row][key] === '2' ? '2' : '1'
} else if (key !== 'name' && key !== 'id' && value === '0') {
this.array[row][key] = this.array[row][key] === '2' ? '2' : '0'
}
}
} else if (type === 'header' && row === 1) {
//表格顶栏全选
this.array.forEach(item => {
if ((value === '1' || value === '2') && item[field] !== '2') {
this.$set(item, field, '1')
} else if (value === '0' && item[field] !== '2') {
this.$set(item, field, '0')
}
})
} else {
//表格中选择
let tempHead = []
this.array.forEach((item) => {
if (rowData.id === item.id) {
let tempArr = []
for(let i in item) {
if (i !== 'check' && i !== 'id' && i !== 'name') {
tempArr.push(item[i])
}
}
let finallyArr = Array.from(new Set(tempArr))
if (finallyArr.toString() === '0,2' || finallyArr.toString() === '0') {
item.check = '0'
} else if (finallyArr.toString() === '1,2' || finallyArr.toString() === '1') {
item.check = '1'
} else {
item.check = '2'
}
}
tempHead.push(item[field])
})
let finallyHead = Array.from(new Set(tempHead))
this.arrayHeader.forEach((head) => {
if (head.field === field) {
if (finallyHead.toString() === '0,2' || finallyHead.toString() === '0' || finallyHead.toString() === '2,0') {
head.check = '0'
} else if (finallyHead.toString() === '1,2' || finallyHead.toString() === '1' || finallyHead.toString() === '2,1') {
head.check = '1'
} else {
head.check = '2'
}
}
})
}
}
}
}
</script>