You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
12 KiB
405 lines
12 KiB
<template>
|
|
<!-- 选择发送对象 -->
|
|
<el-dialog append-to-body :close-on-click-modal="false" :visible.sync="sendObjVisible" title="发布通知" @close="handleClose">
|
|
<span class="dialog-right-top" />
|
|
<span class="dialog-left-bottom" />
|
|
<div class="setting-dialog">
|
|
<el-form ref="selectObjForm" :rules="rulesObj" :model="selectObjForm" size="small" label-width="100px">
|
|
<el-form-item label="发送对象" prop="sendObj" class="down-select">
|
|
<el-radio-group v-model="selectObjForm.sendObj" size="mini" style="width: 178px">
|
|
<el-radio-button label="0">用户</el-radio-button>
|
|
<el-radio-button label="1">设备</el-radio-button>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
</el-form>
|
|
<div class="obj-tree-select">
|
|
<div class="obj-tree">
|
|
<el-tree ref="tree" :data="fondsDatas" :props="defaultProps" :expand-on-click-node="false" :default-expanded-keys="defaultExpandedKeys" node-key="id" highlight-current @node-click="handleNodeClick">
|
|
<template slot-scope="{ node, data }">
|
|
<div :class="{'top-level': data.id === 0}">
|
|
<span v-if="data.label.length <= 8 " class="tree-text"> {{ data.label }}</span>
|
|
<el-tooltip
|
|
v-else
|
|
effect="dark"
|
|
:content="data.label"
|
|
:enterable="false"
|
|
placement="left"
|
|
>
|
|
<span class="tree-text">
|
|
{{ data.label }}
|
|
</span>
|
|
</el-tooltip>
|
|
</div>
|
|
</template>
|
|
</el-tree>
|
|
</div>
|
|
<div class="obj-list">
|
|
<!-- <i class="el-icon-circle-plus-outline" /> -->
|
|
<p class="obj-title">用户列表</p>
|
|
<div v-if="userListWithCheck.length !== 0">
|
|
<el-checkbox
|
|
v-model="checkAll"
|
|
class="checkbox-all"
|
|
:indeterminate="indeterminate"
|
|
@change="checkedAll"
|
|
>用户</el-checkbox>
|
|
<div v-for="user in userListWithCheck" :key="user.userId">
|
|
<el-checkbox v-model="user.checked" @change="handleChange(user)">{{ user.username }}</el-checkbox>
|
|
</div>
|
|
</div>
|
|
<div v-else style="font-size:12px; text-align: center; line-height: 80px; color: #999;">暂无数据</div>
|
|
</div>
|
|
<div class="obj-selected">
|
|
<p class="obj-title">已选中<i class="iconfont icon-shanchu" @click="clearSelectAll" /></p>
|
|
<div class="selected-list">
|
|
<el-tag
|
|
v-for="tag in selectedItems"
|
|
:key="tag.userId"
|
|
closable
|
|
:disable-transitions="false"
|
|
@close="handleDelt(tag)"
|
|
>
|
|
{{ tag.username }}
|
|
</el-tag>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button type="primary" @click="handleSaveSelectObj">保存</el-button>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script>
|
|
import { FetchFondsAll } from '@/api/system/fonds'
|
|
import { FetchInitUserList } from '@/api/system/user'
|
|
import Vue from 'vue'
|
|
export default {
|
|
props: {
|
|
selectedCategory: {
|
|
type: Object,
|
|
default: function() {
|
|
return {}
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
fondsDatas: [],
|
|
defaultExpandedKeys: [],
|
|
defaultProps: { children: 'children', label: 'label' },
|
|
|
|
sendObjVisible: false,
|
|
selectObjForm: {
|
|
sendObj: 0
|
|
},
|
|
checkAll: false,
|
|
indeterminate: false,
|
|
userList: [],
|
|
selectedItems: [],
|
|
userListWithCheck: [], // 中间用户列表数据带有选中状态的数组
|
|
rulesObj: {
|
|
sendObj: [
|
|
{ required: true, message: '请选择发送对象', trigger: 'change' }
|
|
]
|
|
}
|
|
}
|
|
},
|
|
watch: {
|
|
selectedItems: {
|
|
handler(val) {
|
|
this.updateCheckedState()
|
|
},
|
|
deep: true
|
|
},
|
|
userListWithCheck: {
|
|
handler(val) {
|
|
this.updateCheckedState()
|
|
},
|
|
deep: true
|
|
}
|
|
},
|
|
created() {
|
|
},
|
|
mounted() {
|
|
},
|
|
methods: {
|
|
getFondsDatas() {
|
|
const parent = {}
|
|
this.fondsDatas = []
|
|
parent.id = 0
|
|
parent.fondsName = '全宗选择'
|
|
FetchFondsAll().then(res => {
|
|
res.forEach(item => {
|
|
// 1. 全宗节点:将fondsName赋值给label
|
|
item.label = item.fondsName
|
|
// 2. 部门节点(depts -> children):将deptsName赋值给label
|
|
if (item.depts && item.depts.length) {
|
|
item.children = this.formatDeptNodes(item.depts)
|
|
} else {
|
|
item.children = []
|
|
}
|
|
})
|
|
// 根节点添加label
|
|
parent.label = parent.fondsName
|
|
parent.children = res
|
|
this.fondsDatas.push(parent)
|
|
|
|
console.log('this.fondsDatas', this.fondsDatas)
|
|
this.$nextTick(() => {
|
|
Vue.set(this.defaultExpandedKeys, 0, this.fondsDatas[0].children[0].id)
|
|
this.$refs.tree.setCurrentKey(this.fondsDatas[0].children[0].id)
|
|
this.handleNodeClick(this.fondsDatas[0].children[0])
|
|
})
|
|
})
|
|
},
|
|
// 格式化部门节点:添加label字段
|
|
formatDeptNodes(depts) {
|
|
return depts.map(dept => {
|
|
const node = { ...dept }
|
|
node.label = dept.deptsName // 部门节点用deptsName作为label
|
|
// 如果有子部门(childDepts),递归处理
|
|
if (dept.childDepts && dept.childDepts.length) {
|
|
node.children = this.formatDeptNodes(dept.childDepts)
|
|
}
|
|
return node
|
|
})
|
|
},
|
|
// 可选:格式化分类节点(如果需要展示categorys)
|
|
formatCategoryNodes(categorys) {
|
|
return categorys.map(cate => {
|
|
const node = { ...cate }
|
|
node.label = cate.cnName // 分类节点用cnName作为label
|
|
return node
|
|
})
|
|
},
|
|
|
|
// 切换部门
|
|
handleNodeClick(data) {
|
|
let params = {}
|
|
if (data.pid === 0) {
|
|
params = {
|
|
'deptsId': null,
|
|
'deptsName': null
|
|
}
|
|
} else {
|
|
if (data.fondsNo) {
|
|
params = {
|
|
'fondsId': data.id,
|
|
'deptsId': null,
|
|
'deptsName': null
|
|
}
|
|
} else {
|
|
params = {
|
|
'deptsId': data.id,
|
|
'deptsName': data.deptsName
|
|
}
|
|
}
|
|
}
|
|
this.getUserList(params)
|
|
},
|
|
checkedAll(checked) {
|
|
if (this.selectedItems.length !== 0) {
|
|
const missingUsers = this.userListWithCheck.filter(user => !this.isSelected(user))
|
|
console.log('missingUsers', missingUsers)
|
|
if (missingUsers.length !== 0) {
|
|
if (this.checkAll) {
|
|
missingUsers.forEach(user => {
|
|
this.selectedItems.push(user)
|
|
})
|
|
} else {
|
|
this.selectedItems = []
|
|
}
|
|
} else {
|
|
this.userListWithCheck.forEach(user => {
|
|
const index = this.selectedItems.findIndex(selectedUser => selectedUser.userId === user.userId)
|
|
if (index > -1) {
|
|
this.selectedItems.splice(index, 1)
|
|
this.checkAll = false
|
|
}
|
|
})
|
|
}
|
|
} else {
|
|
if (checked) {
|
|
this.selectedItems = this.userListWithCheck.map(item => item)
|
|
this.checkAll = true
|
|
} else {
|
|
this.selectedItems = []
|
|
this.checkAll = false
|
|
}
|
|
}
|
|
},
|
|
isSelected(user) {
|
|
return this.selectedItems.some(selectedUser => selectedUser.userId === user.userId)
|
|
},
|
|
resetCheckedState() {
|
|
// 重置中间用户列表的选中状态
|
|
this.userListWithCheck = this.userList.map(user => {
|
|
return { ...user, checked: false }
|
|
})
|
|
if (this.selectedItems.length !== 0) {
|
|
const isAllSelected = this.userListWithCheck.every(user => this.isSelected(user))
|
|
if (isAllSelected) {
|
|
this.checkAll = true
|
|
} else {
|
|
this.checkAll = false
|
|
}
|
|
}
|
|
},
|
|
updateCheckedState() {
|
|
this.userListWithCheck.forEach(user => {
|
|
user.checked = this.selectedItems.some(selectedUser => selectedUser.userId === user.userId)
|
|
})
|
|
},
|
|
getUserList(params) {
|
|
FetchInitUserList(params).then(res => {
|
|
const newArr = res.content.map(item => {
|
|
const json = {}
|
|
json.userId = item.userId
|
|
json.username = item.username
|
|
return json
|
|
})
|
|
this.userList = newArr
|
|
this.resetCheckedState()
|
|
})
|
|
},
|
|
handleChange(user) {
|
|
if (user.checked) {
|
|
this.selectedItems.push(user)
|
|
if (this.selectedItems.length !== 0) {
|
|
const allUsersSelected = this.userListWithCheck.every(user => this.isSelected(user))
|
|
if (allUsersSelected) {
|
|
console.log('所有左边的用户都已加入到右边已选中的列表中')
|
|
this.checkAll = true
|
|
} else {
|
|
this.checkAll = false
|
|
console.log('左边的用户列表还有未加入到右边已选中的列表中的用户')
|
|
}
|
|
} else {
|
|
this.checkAll = this.selectedItems.length === this.userListWithCheck.length
|
|
}
|
|
} else {
|
|
const index = this.selectedItems.findIndex(selectedUser => selectedUser.userId === user.userId)
|
|
if (index > -1) {
|
|
this.selectedItems.splice(index, 1)
|
|
this.checkAll = false
|
|
}
|
|
}
|
|
},
|
|
handleClose() {
|
|
this.sendObjVisible = false
|
|
},
|
|
handleDelt(tag) {
|
|
this.selectedItems.splice(this.selectedItems.indexOf(tag), 1)
|
|
if (this.selectedItems.length !== 0) {
|
|
const allUsersSelected = this.userListWithCheck.every(user => this.isSelected(user))
|
|
if (allUsersSelected) {
|
|
console.log('所有左边的用户都已加入到右边已选中的列表中')
|
|
this.checkAll = true
|
|
} else {
|
|
this.checkAll = false
|
|
console.log('左边的用户列表还有未加入到右边已选中的列表中的用户')
|
|
}
|
|
} else {
|
|
this.checkAll = this.selectedItems.length === this.userListWithCheck.length
|
|
}
|
|
},
|
|
clearSelectAll() {
|
|
this.checkAll = false
|
|
this.selectedItems = []
|
|
},
|
|
handleSaveSelectObj() {
|
|
this.$emit('selectObjItem', this.selectObjForm.sendObj, this.selectedItems)
|
|
this.sendObjVisible = false
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style lang='scss' scoped>
|
|
.obj-tree-select{
|
|
display: flex;
|
|
justify-content: space-between;
|
|
height: 367px;
|
|
border: 1px solid #E6E8ED;
|
|
.obj-tree{
|
|
width: 194px;
|
|
overflow: hidden;
|
|
overflow-y: scroll;
|
|
border-right: 1px solid #E6E8ED;
|
|
}
|
|
.obj-list{
|
|
width: 184px;
|
|
overflow: hidden;
|
|
overflow-y: scroll;
|
|
border-right: 1px solid #E6E8ED;
|
|
.obj-title{
|
|
padding: 0 12px;
|
|
i{
|
|
font-weight: bold;
|
|
font-size: 18px;
|
|
right: 12px;
|
|
}
|
|
}
|
|
::v-deep .el-checkbox{
|
|
width: 100%;
|
|
height: 40px;
|
|
line-height: 40px;
|
|
padding-left: 16px;
|
|
&:hover{
|
|
background-color: #F5F9FC;
|
|
}
|
|
}
|
|
}
|
|
.obj-selected{
|
|
flex: 1;
|
|
.obj-title{
|
|
padding: 0 15px;
|
|
border-bottom: 1px solid #E6E8ED;
|
|
i{
|
|
right: 15px;
|
|
}
|
|
}
|
|
::v-deep .el-tag{
|
|
margin: 14px 0 0 10px;
|
|
height: 24px;
|
|
line-height: 24px;
|
|
padding: 0 8px;
|
|
font-size: 12px;
|
|
color: #0348F3;
|
|
background: #E8F2FF;
|
|
border: none;
|
|
border-radius: 3px;
|
|
.el-icon-close{
|
|
color: #0348F3;
|
|
&:hover{
|
|
color: #fff;
|
|
background-color: #0348F3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.obj-title{
|
|
position: relative;
|
|
font-size: 16px;
|
|
color: #0C0E1E;
|
|
height: 48px;
|
|
line-height: 48px;
|
|
i{
|
|
position: absolute;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #0348F3;
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
}
|
|
.checkbox-all{
|
|
font-weight: bold;
|
|
background-color: #f5f9fc;
|
|
color: #0c0e1e;
|
|
}
|
|
.el-tree .el-tooltip{
|
|
width: 140px !important;
|
|
}
|
|
</style>
|