一、前言
我司仓储系统需求,账号用户-拥有若干仓库权限(第一层记忆 大勾选)-仓库又包含若干个是否可使用的发车点(第二层记忆 小勾选) 这些要全部记忆+修改记忆。
ps:一年前做的,上一篇分页一直说要放第二篇的,最近做总结就放上来了。
二、实现
1.需要后端配合 提供前端需要 - 用户所拥有的 仓库及发车点的 权限数据结构 和 公司所有的仓库及权限点
1.1 公司的仓库权限数组 companyList-也就是 发车点授权列表里的数据
[{
"id": "1",
"code": "吉利湘潭发车点",
"name": "吉利湘潭发车点",
"province": "湖南省",
"city": "湘潭市",
"county": "湘潭县",
"address": null,
"linkMan": null,
"linkPhone": null,
"isSeek": "0",
"isSeekChecked": false,
"isMove": "0",
"isMoveChecked": false,
"isPick": "0",
"isPickChecked": false,
"isShip": "1",
"isShipChecked": false,
"status": "10",
"remark": null,
"userCreate": "赵xx",
"userModified": "赵xx",
"gmtCreate": "2018-09-07 14:45:18",
"gmtModified": "2018-09-07 14:45:18",
"exceShip": null,
"own": false
},
{
"id": "2",
"code": "吉利湘潭",
"name": "吉利湘潭",
"province": "湖南省",
"city": "湘潭市",
"county": "湘潭县",
"address": null,
"linkMan": null,
"linkPhone": null,
"isSeek": "0",
"isSeekChecked": false,
"isMove": "0",
"isMoveChecked": false,
"isPick": "0",
"isPickChecked": false,
"isShip": "1",
"isShipChecked": false,
"status": "10",
"remark": null,
"userCreate": "赵xx",
"userModified": "赵xx",
"gmtCreate": "2018-09-19 10:07:50",
"gmtModified": "2018-09-25 15:15:21",
"exceShip": null,
"own": false
}]
1.2 该账号用户拥有的仓库权限数组 userList
[{
"id": "1245745237930762",
"code": "成都-临时停车场",
"name": "成都-临时停车场",
"province": "四川省",
"city": "成都市",
"county": null,
"address": null,
"linkMan": null,
"linkPhone": null,
"isSeek": null,
"isSeekChecked": false,
"isMove": null,
"isMoveChecked": false,
"isPick": null,
"isPickChecked": false,
"isShip": null,
"isShipChecked": false,
"status": "10",
"remark": null,
"userCreate": "赵xx",
"userModified": "赵xx",
"gmtCreate": "2019-03-21 10:18:39",
"gmtModified": "2019-03-21 10:18:39",
"exceShip": null,
"own": false
},
{
"id": "8219",
"code": "宝安发车点",
"name": "宝安发车点",
"province": "广东省",
"city": "宝安区",
"county": null,
"address": null,
"linkMan": null,
"linkPhone": null,
"isSeek": null,
"isSeekChecked": false,
"isMove": null,
"isMoveChecked": false,
"isPick": null,
"isPickChecked": false,
"isShip": null,
"isShipChecked": true,
"status": "10",
"remark": null,
"userCreate": "赵xx",
"userModified": "赵xx",
"gmtCreate": "2019-03-21 10:18:39",
"gmtModified": "2019-03-21 10:18:39",
"exceShip": null,
"own": false
}]
2.逻辑 第一层的仓库列表勾选项-分页记忆 勾选的逻辑 请看 第一篇 element-ui的table组件-checkbox选中分页记忆-逻辑修改成
第二层的单个仓库-发车点勾选项-分页记忆
2.0 getOwnerIds()
根据账号用户拥有项请求返回userList, 知道 用户有那些所有的选中项(row)的集合(selectRowAll)
2.1 setSelectRow()
初始设置勾选项选中状态
2.2 changePageCoreRecordData()
页面用户操作(第一层)的勾选,selectRow数据变动 ,然后得到当前页(table_data)没有选中那些项(noSelectRow),然后依据没选中(noSelectRow)来做总选中 (selectRowAll)中的清除那些没有选中项。
这一步是 关于 第一层的记忆
2.3 小勾选 变化, demo上绑定的操作函数
isSeekChecked 是否勾选(小勾选)用户是否拥有该权限项 isSeek 该仓库是否开放了该勾选项的权限(0-禁用,1-启用)
handleSeekCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isSeekChecked', 'isSeek')
},
handleMoveCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isMoveChecked', 'isMove')
},
handlePickCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isPickChecked', 'isPick')
},
handleShipCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isShipChecked', 'isShip')
},
2.4 currencyIsChecked() 最后用于记录和提交 小勾选的选中状态
currencyIsChecked(index, row, isChecked, idKey, property1, property2) {
console.log('-----currencyIsChecked()-----')
console.log('index', index, 'row', row.id, 'isChecked', isChecked, 'property2', property2)
// 查询 总选中集合 内 是否有 小勾选改动时所属的 大勾选项
if (this.hasPermissions(this.selectRowAll, row, idKey)) {
this.selectRowAll.forEach((item1, index1) => {
// console.log('selectRowAll-id', item1.id, 'row', row.id)
if (parseInt(item1[idKey]) === parseInt(row[idKey])) {
this.selectRowAll[index1][property1] = isChecked
// this.selectRowAll[index1][property2] = !isChecked ? '1' : '0'
// console.log('property1', this.selectRowAll[index1][property1], 'property2', this.selectRowAll[index1][property2])
// 如果没有该小勾选项 则清理掉 小勾选所属的 大勾选项 -进而进行大勾选项勾选状态更新
if (!this.selectRowAll[index1].isSeekChecked && !this.selectRowAll[index1].isMoveChecked && !this.selectRowAll[index1].isPickChecked && !this.selectRowAll[index1].isShipChecked) {
this.selectRowAll.splice(index1, 1)
this.$refs.pointMultipleTable.toggleRowSelection(this.table_data[index], false)
}
}
})
} else {
// 如果有小勾选 勾中,所属大勾选项 加入总选集合中,同步进行 大勾选状态更新
this.selectRowAll.push(row)
this.table_data[index][property1] = isChecked
this.$refs.pointMultipleTable.toggleRowSelection(this.table_data[index], true)
}
// console.log('勾选状态改变后selectRowAll', this.selectRowAll)
this.setIsChecked(this.selectRowAll, idKey)
},
2.5 setIsChecked() demo上显示 小勾选的选中状态更新
setIsChecked(selectRowAll, idKey) {
// console.log('setIsChecked()-selectRowAll', selectRowAll)
if (selectRowAll && selectRowAll.length > 0) {
for (var i = 0; i < selectRowAll.length; i++) {
this.table_data.forEach((item1, index1) => {
if (selectRowAll[i][idKey] === item1[idKey]) {
// console.log('setIsChecked()', 'this.table_data[index1]', this.table_data[index1], 'selectRowAll[i]', selectRowAll[i])
this.table_data[index1].isSeekChecked = selectRowAll[i].isSeekChecked
this.table_data[index1].isMoveChecked = selectRowAll[i].isMoveChecked
this.table_data[index1].isPickChecked = selectRowAll[i].isPickChecked
this.table_data[index1].isShipChecked = selectRowAll[i].isShipChecked
// console.log('(selectRowAll[i]', selectRowAll[i], 'selectRowAll[i].id', selectRowAll[i].id)
// console.log('item1.id', item1.id, 'index1', index1, 'item1', item1, 'this.table_data', this.table_data)
}
})
}
}
},
2.6 本demo 是(发车授权)弹窗页面
全部代码如下
<template>
<div style="margin-bottom: 20px;">
<el-dialog :title="edit_main_title" append-to-body v-dialogDrag :visible.sync="edit_flag"
@open="handleOpenConfig" :before-close="handleClose" width="1100px">
<el-row type="flex" justify="space-between" style="padding: 10px 0">
<el-col>
<el-input style="width: 180px" v-model="page.condition.name" @keyup.enter.native="search" placeholder="发运点"></el-input>
<el-button type="primary" @click="search">查询</el-button>
</el-col>
<el-col style="text-align: right">
</el-col>
</el-row>
<el-table key="1" ref="pointMultipleTable" :data="table_data" v-loading="loadingShow"
element-loading-text="加载中" border fit highlight-current-row
style="width: 99%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column align="center" label="序号" width="">
<template slot-scope="scope">
<span>{{scope.$index+1}}</span>
</template>
</el-table-column>
<el-table-column width="190" align="center" label="编码">
<template slot-scope="scope">
<span>{{scope.row.code}}</span>
</template>
</el-table-column>
<el-table-column width="190" align="center" label="名称">
<template slot-scope="scope">
<span>{{scope.row.name}}</span>
</template>
</el-table-column>
<el-table-column width="100" align="center" label="所在省份">
<template slot-scope="scope">
<span>{{scope.row.province}}</span>
</template>
</el-table-column>
<el-table-column width="100" align="center" label="所在城市">
<template slot-scope="scope">
<span>{{scope.row.city}}</span>
</template>
</el-table-column>
<el-table-column width="100" align="center" label="所在区县">
<template slot-scope="scope">
<span>{{scope.row.county}}</span>
</template>
</el-table-column>
<el-table-column width="60" align="center" label="寻车">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.isSeekChecked" v-bind="{'checked': scope.row.isSeekChecked?true:false }"
:disabled="scope.row.isSeek !== '1'"
@change="handleSeekCheckedChange(scope.$index, scope.row,scope.row.isSeekChecked)"></el-checkbox>
</template>
</el-table-column>
<el-table-column width="60" align="center" label="移车">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.isMoveChecked" v-bind="{'checked': scope.row.isMoveChecked?true:false }"
:disabled="scope.row.isMove !== '1'"
@change="handleMoveCheckedChange(scope.$index, scope.row,scope.row.isMoveChecked)"></el-checkbox>
</template>
</el-table-column>
<el-table-column width="60" align="center" label="提车">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.isPickChecked" v-bind="{'checked': scope.row.isPickChecked?true:false }"
:disabled="scope.row.isPick !== '1'"
@change="handlePickCheckedChange(scope.$index, scope.row,scope.row.isPickChecked)"></el-checkbox>
</template>
</el-table-column>
<el-table-column width="60" align="center" label="发运">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.isShipChecked" v-bind="{'checked': scope.row.isShipChecked?true:false }"
:disabled="scope.row.isShip !== '1'"
@change="handleShipCheckedChange(scope.$index, scope.row,scope.row.isShipChecked)"></el-checkbox>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
style="margin-top: 8px"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page.current"
:page-sizes="[10, 20, 30, 40]"
:page-size="page.size"
layout="total, sizes, prev, pager, next, jumper"
:total="page.total">
</el-pagination>
<el-row type="flex" justify="end">
<el-button type="primary" @click="handleClose">取消</el-button>
<el-button type="primary" @click="confirmClick">确定</el-button>
</el-row>
<div style="height:20px"></div>
</el-dialog>
</div>
</template>
<script type="text/javascript">
import * as SysUserApi from '@/api/sys/sysuser'
import * as Utils from '@/utils/index'
export default {
name: '',
components: {
},
props: ['edit_flag', 'edit_main_title', 'edit_select_row', 'edit_params'],
data() {
return {
title_data: {},
loadingShow: false,
selectRow: [],
selectRowAll: [], // 当前角色拥有的权限
selectAllIds: [], // 当前角色拥有的权限
idKey: 'id', // 标识列表数据中每一行的唯一键的名称
haveReq: 0,
page: {
current: 1,
size: 10,
total: 1,
condition: {
name: ''
}
},
table_data: []
}
},
created() {
},
methods: {
// 弹窗初开执行
handleOpenConfig(data) {
this.table_data = []
this.page = {
current: 1,
size: 10,
total: 1,
condition: { name: '' }
}
this.haveReq = 0
this.selectAllIds = []
this.selectRowAll = []
this.getList()
},
// 分页查询
getList() {
this.loadingShow = true
SysUserApi.allUsablePoint(this.page).then(res => {
const t = res.data
this.table_data = t.records
this.page.current = t.current
this.page.size = t.size
this.page.total = t.total
// console.log('getList()-this.haveReq', this.haveReq)
if (this.haveReq === 0) {
console.log('---getOwnerIds()----')
this.getOwnerIds()
} else {
setTimeout(() => {
this.setSelectRow()
this.loadingShow = false
}, 50)
}
}).catch(() => {
this.loadingShow = false
})
},
// 表格改变时
handleSelectionChange(val) {
setTimeout(() => {
this.changePageCoreRecordData(val)
}, 50)
},
// 初始回填选中状态
setSelectRow() {
console.log('---setSelectRow()----')
const that = this
if (!this.selectRowAll || this.selectRowAll.length <= 0) {
return
}
// 标识当前行的唯一键的名称
const idKey = this.idKey
// 小勾选回填
this.setIsChecked(this.selectRowAll, idKey)
this.$refs.pointMultipleTable.clearSelection()
// 大勾选回填
for (var i = 0; i < this.table_data.length; i++) {
if (this.hasPermissions(this.selectRowAll, this.table_data[i], idKey)) {
that.$refs.pointMultipleTable.toggleRowSelection(this.table_data[i], true)
}
}
},
// 判断数集内是否有该对象,有则返回 true,无则返回false
hasPermissions(selectRowAll, item, key) {
if (item && item[key]) {
return selectRowAll.some(row => parseInt(item[key]) === parseInt(row[key]))
} else {
return true
}
},
// 表格改变修改选中数据记录
changePageCoreRecordData(val) {
console.log('changePageCoreRecordData()----')
console.log('初this.selectRowAll', this.selectRowAll)
console.log('初val', val)
// 标识当前行的唯一键的名称
const idKey = this.idKey
const that = this
if (val.length < 0) {
return
}
// 获取当前页选中的row
this.selectRow = []
this.selectRow = val
this.selectRowAll = Utils.addArrayFunc(this.selectRow, this.selectRowAll, idKey) // 数组合并去重
const noSelectRow = []
// 得到当前页没有选中的row
that.table_data.forEach(row => {
if (!that.hasPermissions(that.selectRow, row, idKey)) {
noSelectRow.push(row)
}
})
// console.log('noSelectRow', noSelectRow)
noSelectRow.forEach(row => {
if (that.hasPermissions(that.selectRowAll, row, idKey)) {
that.selectRowAll = Utils.array_cut_item(that.selectRowAll, row, idKey) // 对象集合 减掉某个对象
}
})
// console.log('依据没选中的row来做总选中 中的清除', this.selectRowAll)
},
// 请求该用户拥有的权限-选中状态
getOwnerIds() {
const that = this
SysUserApi.ownPoint(this.edit_select_row.id).then(response => {
this.loadingShow = false
this.selectRowAll = response.data
that.haveReq = 1
// console.log('getOwnerIds()-this.haveReq', that.haveReq, that)
that.setSelectRow()
}).catch(() => {
// this.haveReq = 0
this.loadingShow = false
})
},
handleSeekCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isSeekChecked', 'isSeek')
},
handleMoveCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isMoveChecked', 'isMove')
},
handlePickCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isPickChecked', 'isPick')
},
handleShipCheckedChange(index, row, isChecked) {
this.currencyIsChecked(index, row, isChecked, this.idKey, 'isShipChecked', 'isShip')
},
// demo上显示 小勾选的选中状态
setIsChecked(selectRowAll, idKey) {
// console.log('setIsChecked()-selectRowAll', selectRowAll)
if (selectRowAll && selectRowAll.length > 0) {
for (var i = 0; i < selectRowAll.length; i++) {
this.table_data.forEach((item1, index1) => {
if (selectRowAll[i][idKey] === item1[idKey]) {
// console.log('setIsChecked()', 'this.table_data[index1]', this.table_data[index1], 'selectRowAll[i]', selectRowAll[i])
this.table_data[index1].isSeekChecked = selectRowAll[i].isSeekChecked
this.table_data[index1].isMoveChecked = selectRowAll[i].isMoveChecked
this.table_data[index1].isPickChecked = selectRowAll[i].isPickChecked
this.table_data[index1].isShipChecked = selectRowAll[i].isShipChecked
// console.log('(selectRowAll[i]', selectRowAll[i], 'selectRowAll[i].id', selectRowAll[i].id)
// console.log('item1.id', item1.id, 'index1', index1, 'item1', item1, 'this.table_data', this.table_data)
}
})
}
}
},
// 最后用于记录和提交 小勾选的选中状态
currencyIsChecked(index, row, isChecked, idKey, property1, property2) {
console.log('-----currencyIsChecked()-----')
console.log('index', index, 'row', row.id, 'isChecked', isChecked, 'property2', property2)
// 查询 总选中集合 内 是否有 小勾选改动时所属的 大勾选项
if (this.hasPermissions(this.selectRowAll, row, idKey)) {
this.selectRowAll.forEach((item1, index1) => {
// console.log('selectRowAll-id', item1.id, 'row', row.id)
if (parseInt(item1[idKey]) === parseInt(row[idKey])) {
this.selectRowAll[index1][property1] = isChecked
// this.selectRowAll[index1][property2] = !isChecked ? '1' : '0'
// console.log('property1', this.selectRowAll[index1][property1], 'property2', this.selectRowAll[index1][property2])
// 如果没有该小勾选项 则清理掉 小勾选所属的 大勾选项 -进而进行大勾选项勾选状态更新
if (!this.selectRowAll[index1].isSeekChecked && !this.selectRowAll[index1].isMoveChecked && !this.selectRowAll[index1].isPickChecked && !this.selectRowAll[index1].isShipChecked) {
this.selectRowAll.splice(index1, 1)
this.$refs.pointMultipleTable.toggleRowSelection(this.table_data[index], false)
}
}
})
} else {
// 如果有小勾选 勾中,所属大勾选项 加入总选集合中,同步进行 大勾选状态更新
this.selectRowAll.push(row)
this.table_data[index][property1] = isChecked
this.$refs.pointMultipleTable.toggleRowSelection(this.table_data[index], true)
}
// console.log('勾选状态改变后selectRowAll', this.selectRowAll)
this.setIsChecked(this.selectRowAll, idKey)
},
// 查询
search() {
this.page.current = 1
this.page.size = 10
this.getList()
},
handleSizeChange(val) {
this.page.size = val
this.page.current = 1
this.getList()
},
handleCurrentChange(val) {
this.page.current = val
this.getList()
},
// 确认
confirmClick() {
if (this.checkOneSelect(this.selectRowAll)) {
const items = []
this.selectRowAll.forEach(function(item, index, array) {
items.push(item)
})
SysUserApi.grantPoint(this.edit_select_row.id, items).then(response => {
if (response.code === 0) {
this.$notify({
title: '成功',
message: '发运点分配成功',
type: 'success',
duration: 2000
})
this.$refs.pointMultipleTable.clearSelection()
} else {
this.$notify({
title: '失败',
message: response.message,
type: 'fail',
duration: 2000
})
}
this.$emit('edit-close', false)
})
}
},
// 检查是否选择单条
checkOneSelect(data) {
const l = data.length
if (l === 0) {
this.$message({
message: '未选择',
type: 'warning',
duration: 2000
})
return false
}
// if (l > 1) {
// this.$message({
// message: ' 不可多选, 请选择单条!',
// type: 'warning',
// duration: 2000
// })
// return false
// }
return true
},
handleClose() {
this.$emit('edit-close', false)
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
</style>
三、总结
该需求难点 主要是 小勾选的 更新选中记忆
做分页记忆 element-ui 的列表勾选 toggleRowSelection() 易写错 变 死循环,设置了 toggleRowSelection()后, 用户操作了选中项-执行了toggleRowSelection() -然后走逻辑后又进行toggleRowSelection()