| | |
| | | <template> |
| | | <a-spin :spinning="spinning"> |
| | | <a-transfer |
| | | class="transfer-container" |
| | | class="tree-transfer" |
| | | :data-source="dataSource" |
| | | show-search |
| | | :list-style="{flex:1,height: '500px'}" |
| | | :titles="['未分配部门', '已分配部门']" |
| | | :operations="['分配部门', '移除部门']" |
| | | :target-keys="targetKeys" |
| | | :render="item => `${item.departName}`" |
| | | :render="item => `${item.title}`" |
| | | @change="handleChange" |
| | | :rowKey="record => record.departId" |
| | | @search="handleSearch" |
| | | > |
| | | <template slot="children" slot-scope="{ props: { direction, selectedKeys }, on: { itemSelect } }"> |
| | | <a-tree |
| | | v-if="direction === 'left'" |
| | | blockNode |
| | | checkable |
| | | checkStrictly |
| | | :expandedKeys="expandedKeys" |
| | | :autoExpandParent="autoExpandParent" |
| | | @expand="handleTreeNodeExpand" |
| | | :checkedKeys="[...selectedKeys, ...targetKeys]" |
| | | :treeData="treeData" |
| | | @check="(_, props) => {onChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect);}" |
| | | @select="(_, props) => {onChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect); }"> |
| | | <template slot="title" slot-scope="{title}"> |
| | | <span v-if="title.indexOf(searchValue) > -1">{{ title.substr(0, title.indexOf(searchValue)) }}<span |
| | | class="replaceSearch">{{ searchValue }}</span>{{ title.substr(title.indexOf(searchValue) + searchValue.length) }}</span> |
| | | <span v-else>{{ title }}</span> |
| | | </template> |
| | | </a-tree> |
| | | </template> |
| | | |
| | | <template slot="footer" slot-scope="{direction}" v-if="direction==='left'"> |
| | | <a-button type="primary" style="float:right;margin: 5px;margin-right: 10px" |
| | | @click="isExpandAllTreeNode=!isExpandAllTreeNode"> |
| | | 展开/折叠 |
| | | </a-button> |
| | | </template> |
| | | |
| | | <span slot="notFoundContent">暂无数据</span> |
| | | </a-transfer> |
| | |
| | | <script> |
| | | import dncApi from '@/api/dnc' |
| | | |
| | | const transferDataSource = [] |
| | | |
| | | export default { |
| | | name: 'DepartPermissionTransfer', |
| | | components: {}, |
| | |
| | | currentTreeNodeInfo: { |
| | | type: Object |
| | | }, |
| | | dataSource: { |
| | | allTreeKeys: { |
| | | type: Array |
| | | }, |
| | | treeDataProps: { |
| | | type: Array |
| | | }, |
| | | isAssignSonNode: { |
| | |
| | | data() { |
| | | return { |
| | | targetKeys: [], |
| | | spinning: false |
| | | spinning: false, |
| | | isExpandAllTreeNode: true, |
| | | searchValue: '', |
| | | expandedKeys: [], |
| | | autoExpandParent: true, |
| | | dataSource: transferDataSource |
| | | } |
| | | }, |
| | | watch: { |
| | | isExpandAllTreeNode: { |
| | | handler(value) { |
| | | if (value) this.expandedKeys = this.allTreeKeys |
| | | else this.expandedKeys = [] |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | treeData() { |
| | | return this.handleTreeData(this.treeDataProps, this.targetKeys) |
| | | } |
| | | }, |
| | | methods: { |
| | | // 调用接口获取有权限的部门列表 |
| | | getHasPermissionDepartByApi() { |
| | | const that = this |
| | | that.spinning = true |
| | | dncApi.getHasPermissionDepartApi(this.currentTreeNodeInfo) |
| | | .then(res => { |
| | | if (res.success) this.targetKeys = res.list.map(item => item.departId) |
| | | if (res.success) this.targetKeys = res.list.map(item => item.id) |
| | | }) |
| | | .finally(() => { |
| | | that.spinning = false |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 穿梭框搜索框输入时触发 |
| | | * @param direction 穿梭框的左右 "left"||"right" |
| | | * @param value 输入值 |
| | | */ |
| | | handleSearch(direction, value) { |
| | | if (direction === 'left') { |
| | | let search = value |
| | | let expandedKeys = transferDataSource |
| | | .map(item => { |
| | | if (item.title != null) { |
| | | if (item.title.indexOf(search) > -1) { |
| | | return this.getParentKey(item.key, this.treeDataProps) |
| | | } |
| | | return null |
| | | } |
| | | }) |
| | | .filter((item, i, self) => item && self.indexOf(item) === i) |
| | | Object.assign(this, { |
| | | expandedKeys, |
| | | searchValue: search, |
| | | autoExpandParent: true |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | handleChange(targetKeys, direction, moveKeys) { |
| | |
| | | .finally(() => { |
| | | that.spinning = false |
| | | }) |
| | | }, |
| | | |
| | | onChecked(_, e, checkedKeys, itemSelect) { |
| | | const { eventKey } = e.node |
| | | itemSelect(eventKey, !this.isChecked(checkedKeys, eventKey)) |
| | | }, |
| | | |
| | | handleTreeData(data, targetKeys = []) { |
| | | data.forEach(item => { |
| | | item['disabled'] = targetKeys.includes(item.key) |
| | | if (item.children) { |
| | | this.handleTreeData(item.children, targetKeys) |
| | | } |
| | | }) |
| | | return data |
| | | }, |
| | | |
| | | handleTreeNodeExpand(expandedKeys) { |
| | | this.expandedKeys = expandedKeys |
| | | this.autoExpandParent = false |
| | | }, |
| | | |
| | | /** |
| | | * 递归获得输入项的父级key |
| | | * @param key 子项key |
| | | * @param tree 子项 |
| | | */ |
| | | getParentKey(key, tree) { |
| | | let parentKey |
| | | for (let i = 0; i < tree.length; i++) { |
| | | const node = tree[i] |
| | | if (node.children) { |
| | | if (node.children.some(item => item.key === key)) { |
| | | parentKey = node.key |
| | | } else if ( |
| | | this.getParentKey(key, node.children)) { |
| | | parentKey = this.getParentKey(key, node.children) |
| | | } |
| | | } |
| | | } |
| | | return parentKey |
| | | }, |
| | | |
| | | isChecked(selectedKeys, eventKey) { |
| | | return selectedKeys.indexOf(eventKey) !== -1 |
| | | }, |
| | | |
| | | flatten(list = []) { |
| | | list.forEach(item => { |
| | | transferDataSource.push(item) |
| | | if (item.children) { |
| | | this.flatten(item.children) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .transfer-container { |
| | | .tree-transfer { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | ::-webkit-scrollbar { |
| | | width: 8px; |
| | | } |
| | | } |
| | | |
| | | .tree-transfer .ant-transfer-list .ant-transfer-list-body { |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | /deep/ .ant-transfer-list-body { |
| | | display: flex; |
| | | flex-direction: column; |
| | | .ant-transfer-list-body-customize-wrapper { |
| | | flex: 1; |
| | | overflow: auto; |
| | | } |
| | | } |
| | | |
| | | .replaceSearch { |
| | | color: #40a9ff; |
| | | font-weight: bold; |
| | | background-color: rgb(204, 204, 204); |
| | | } |
| | | </style> |