Files
laws-sinotruk-client/src/components/selection/WorkGroupSelectionModal.vue
T
2023-12-19 11:07:57 +08:00

377 lines
11 KiB
Vue

<template>
<j-modal
:title="$t('workGroupSelect.selectWorkGroup')"
:width="modalWidth"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleSubmit"
@cancel="handleCancel"
@update:fullscreen="isFullscreen"
wrapClassName="j-depart-select-modal"
switchFullscreen
:cancelText="$t('close')">
<a-spin tip="Loading..." :spinning="false">
<a-input-search style="margin-bottom: 1px" :placeholder="$t('workGroupSelect.enterWorkGroupPressEnter')" @search="onSearch" />
<a-tree
:checkable="true"
:class="treeScreenClass"
class="select-work-group-tree"
:treeData="treeData"
:checkStrictly="checkStrictly"
@check="onCheck"
@select="onSelect"
@expand="onExpand"
:autoExpandParent="autoExpandParent"
:expandedKeys="expandedKeys"
:selectedKeys.sync="selectedKeys"
:checkedKeys="checkedKeys">
<template slot="title" slot-scope="{title}">
<span v-if="title.indexOf(searchValue) > -1">
{{title.substr(0, title.indexOf(searchValue))}}
<span style="color: #f50">{{searchValue}}</span>
{{title.substr(title.indexOf(searchValue) + searchValue.length)}}
</span>
<span v-else>{{title}}</span>
</template>
</a-tree>
</a-spin>
<!--底部父子关联操作和确认取消按钮-->
<template slot="footer" v-if="treeOpera && multi">
<div class="drawer-bootom-button">
<a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
<a-menu slot="overlay">
<a-menu-item key="1" @click="switchCheckStrictly(1)">{{ $t('parentChildConnection') }}</a-menu-item>
<a-menu-item key="2" @click="switchCheckStrictly(2)">{{ $t('cancelConnection') }}</a-menu-item>
</a-menu>
<a-button>
{{ $t('treeOperation') }} <a-icon type="up" />
</a-button>
</a-dropdown>
<a-button @click="handleCancel" type="primary" style="margin-right: 0.8rem">{{ $t('close') }}</a-button>
<a-button @click="handleSubmit" type="primary" >{{ $t('confirm') }}</a-button>
</div>
</template>
</j-modal>
</template>
<script>
import { getWorkGroupTreeList } from '@api/api'
export default {
name: 'WorkGroupSelectionModal',
props: ['modalWidth', 'multi', 'rootOpened', 'departId', 'store', 'text', 'treeOpera'],
data () {
return {
visible: false,
confirmLoading: false,
treeData: [],
autoExpandParent: true,
expandedKeys: [],
dataList: [],
checkedKeys: [],
checkedRows: [],
searchValue: '',
checkStrictly: true,
fullscreen: false,
selectedKeys: []
}
},
created () {
this.loadWorkGroup()
},
watch: {
departId () {
this.initDepartComponent()
},
visible: {
handler () {
this.initDepartComponent(true)
}
}
},
computed: {
treeScreenClass () {
return {
'my-dept-select-tree': true,
fullscreen: this.fullscreen,
'radio-tree': !this.multi
}
}
},
methods: {
show (textVals) {
this.visible = true
this.checkedRows = []
this.checkedKeys = []
if (textVals) {
this.$nextTick(() => {
// 如果是多选就以逗号分开查找,否则就直接查找
const nodes = this.findKeysByNodes(this.multi ? textVals.split(',') : textVals)
this.checkedRows = nodes
this.checkedKeys = nodes.map(item => item.key)
this.selectedKeys = [...this.checkedKeys]
})
}
},
findKeysByNodes (titles) {
const _this = this
const nodes = []
function searchTree (node) {
// 如果是单选模式已经找到一个,就不继续查找了
if (!_this.multi && nodes.length) {
return
}
if (titles.includes(node.title)) {
nodes.push(node)
}
if (node.children) {
for (const child of node.children) {
searchTree(child)
}
}
}
this.treeData.forEach(data => {
searchTree(data)
})
return nodes
},
// 处理工作组树数据结构
dealTreeData (treeData) {
return treeData.map(item => {
item.title = item.name
item.value = item.id
item.key = item.id
item.disabled = !!(item.subset && item.subset.length)
item.children = this.dealTreeData(item.subset)
return item
})
},
loadWorkGroup () {
getWorkGroupTreeList().then(res => {
if (res.success) {
console.log(res.result)
const arr = this.dealTreeData(res.result)
this.reWriterWithSlot(arr)
this.treeData = arr
this.initDepartComponent()
if (this.rootOpened) {
this.initExpandedKeys(res.result)
}
}
})
},
initDepartComponent (flag) {
const arr = []
// 该方法两个地方用 1.visible改变事件重新设置选中项 2.组件编辑页面回显
const fieldName = flag === true ? 'key' : this.text
if (this.departId) {
const arr2 = this.departId.split(',')
for (const item of this.dataList) {
if (arr2.indexOf(item[this.store]) >= 0) {
arr.push(item[fieldName])
}
}
}
if (flag === true) {
this.checkedKeys = [...arr]
} else {
this.$emit('initComp', arr.join(','))
}
},
reWriterWithSlot (arr) {
for (const item of arr) {
if (item.children && item.children.length > 0) {
this.reWriterWithSlot(item.children)
const temp = Object.assign({}, item)
temp.children = {}
this.dataList.push(temp)
} else {
this.dataList.push(item)
item.scopedSlots = { title: 'title' }
}
}
},
initExpandedKeys (arr) {
if (arr && arr.length > 0) {
const keys = []
for (const item of arr) {
if (item.children && item.children.length > 0) {
keys.push(item.id)
}
}
this.expandedKeys = [...keys]
} else {
this.expandedKeys = []
}
},
onCheck (checkedKeys, info) {
if (!this.multi) {
const arr = checkedKeys.checked.filter(item => this.checkedKeys.indexOf(item) < 0)
this.checkedKeys = [...arr]
this.checkedRows = (this.checkedKeys.length === 0) ? [] : [info.node.dataRef]
} else {
if (this.checkStrictly) {
this.checkedKeys = checkedKeys.checked
} else {
this.checkedKeys = checkedKeys
}
this.checkedRows = this.getCheckedRows(this.checkedKeys)
}
},
onSelect (selectedKeys, info) {
// 取消关联的情况下才走onSelect的逻辑
if (this.checkStrictly) {
const keys = []
keys.push(selectedKeys[0])
if (!this.checkedKeys || this.checkedKeys.length === 0 || !this.multi) {
this.checkedKeys = [...keys]
this.checkedRows = [info.node.dataRef]
} else {
const currKey = info.node.dataRef.key
if (this.checkedKeys.indexOf(currKey) >= 0) {
this.checkedKeys = this.checkedKeys.filter(item => item !== currKey)
} else {
this.checkedKeys.push(...keys)
}
}
this.checkedRows = this.getCheckedRows(this.checkedKeys)
}
},
onExpand (expandedKeys) {
this.expandedKeys = expandedKeys
this.autoExpandParent = false
},
handleSubmit () {
if (!this.checkedKeys || this.checkedKeys.length === 0) {
this.$emit('ok', '')
} else {
const checkRow = this.getCheckedRows(this.checkedKeys)
const keyStr = this.checkedKeys.join(',')
this.$emit('ok', checkRow, keyStr)
}
this.handleClear()
},
handleCancel () {
this.handleClear()
},
handleClear () {
this.visible = false
this.checkedKeys = []
},
getParentKey (currKey, treeData) {
let parentKey
for (let i = 0; i < treeData.length; i++) {
const node = treeData[i]
if (node.children) {
if (node.children.some(item => item.key === currKey)) {
parentKey = node.key
} else if (this.getParentKey(currKey, node.children)) {
parentKey = this.getParentKey(currKey, node.children)
}
}
}
return parentKey
},
onSearch (value) {
const expandedKeys = this.dataList.map((item) => {
if (item.title.indexOf(value) > -1) {
return this.getParentKey(item.key, this.treeData)
}
return null
}).filter((item, i, self) => item && self.indexOf(item) === i)
Object.assign(this, {
expandedKeys,
searchValue: value,
autoExpandParent: true
})
},
// 根据 checkedKeys 获取 rows
getCheckedRows (checkedKeys) {
const forChildren = (list, key) => {
for (const item of list) {
if (item.id === key) {
return item
}
if (Array.isArray(item.children)) {
const value = forChildren(item.children, key)
if (value != null) {
return value
}
}
}
return null
}
const rows = []
for (const key of checkedKeys) {
const row = forChildren(this.treeData, key)
if (row != null) {
rows.push(row)
}
}
return rows
},
switchCheckStrictly (v) {
if (v === 1) {
this.checkStrictly = false
} else if (v === 2) {
this.checkStrictly = true
}
},
isFullscreen (val) {
this.fullscreen = val
}
}
}
</script>
<style lang="less" scoped>
// 限制部门选择树高度,避免部门太多时点击确定不便
.my-dept-select-tree{
height:350px;
&.fullscreen{
height: calc(100vh - 250px);
}
overflow-y: scroll;
}
.drawer-bootom-button {
position: absolute;
bottom: 0;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
// 禁用的不需要显示选择框
.select-work-group-tree {
/deep/.ant-tree-checkbox-disabled {
display: none;
}
/deep/li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper span {
color: rgba(0, 0, 0, .65)
}
}
// 单选不显示选择框
.select-work-group-tree.radio-tree {
/deep/.ant-tree-checkbox {
//display: none;
opacity: 0;
position: absolute;
}
}
// 单选鼠标悬浮时宽度调整
.ant-tree.radio-tree /deep/ li .ant-tree-node-content-wrapper:hover {
margin-left: 0;
padding-left: 5px;
}
</style>