AntDesign中a-tree使用案例

<template>
<a-modal :visible='true' :title='数据授权' @cancel='handleClose()' @ok='onSubmit' :width='600' :maskClosable='false'>
<div class='tree-box'>
<a-input-search style='margin-bottom: 8px' placeholder='请输入关键字搜索' @change='onChange'/>
<a-tree v-if='treeData.length > 0' checkable :tree-data='treeData' @check='onCheck'
:replace-fields='replaceFields' :multiple='true' :checkStrictly='false'
:defaultExpandAll='true' :default-checked-keys='checkedKeys'>
<a-tree>
</div>
</a-modal>
</template>
<script setup lang='ts'>
import {getOrgList} from '@/api/system.js'
import {authUserDataScope, queryUserDataScope, authRoleDataScope, queryRoleDataScope} from '@/api/dataAuthorization.js'
import {ref, reactive} from "vue"
export default {
props: {
id: String,
type: String
},
data() {
return {
replaceFields: {
title: 'label',
key: 'id',
},
keyWorld: '',
treeData: [],
checkedKeys: [],
}
},
created() {
},
methods() {
// 获取组织树结构
onLoadTreeData() {
getOrgList().then((res) => {
if(res.status === 0) {
this.treeData = res.data;
}
})
},
// ★★★★★★ 获取数据授权
getDataScope() {
let requestFunc = '';
let param = '';
// ★ 通过方法引用充分减少代码冗余
if(this.type === 'role') {
requestFunc = queryRoleDataScope
param = 'roleId'
}else {
requestFunc = queryUserDataScope
param = 'userId'
}
func({[param]: this.id}).then((res) => {
this.checkedKeys = res.data;
message.info('授权成功!')
})
},
onSubmit() {
// !this.checkedKeys.length = true 等价于 this.checkedKeys.length = 0
if(!this.checkedKeys.length) {
message.warn('请选择需要授权的数据!');
return;
}else {
this.getDataScope();
}
},
onCheck(checkedKeys) {
this.checkedKeys = checkedKeys || [];
},
onChange(e) {
this.keyWord = e.target.value;
},
handleClose() {
this.$emit('handle')
}
}
}
</script>
<style lang="less" scoped>
.tree-box > .ant-tree {
height: 600px;
overflow-y: auto;
}
</style>

AntDesign Vue中:checkStrictly的作用

在 Ant Design Vue 中,checkStrictly 是 Tree(树形控件)组件的一个属性。它用于指定是否严格遵守父子节点间的勾选关联规则。
当 checkStrictly 属性设置为 true 时,父节点和子节点之间的勾选状态不会相互影响。也就是说,勾选或取消勾选父节点不会影响子节点的勾选状态,同时子节点的勾选状态也不会影响父节点> 的勾选状态。这意味着父节点和子节点之间的勾选状态是相互独立的。
当 checkStrictly 属性设置为 false 时,父节点和子节点之间的勾选状态是关联的。如果一个父节点被勾选或取消勾选,其所有子节点也会相应地被勾选或取消勾选。同样地,如果一个子节点> > 被勾选或取消勾选,它的父节点也会根据子节点的状态相应地被勾选或取消勾选。
通过设置 checkStrictly 属性,您可以根据自己的需求来控制树形控件中勾选状态的关联性。

Example Usage

<template>
<div>
<a-input-search style="margin-bottom: 8px" placeholder="请输入关键字搜索" @change="onChange" />
<div class="allnode" :class="{'active': selectId === ''}">
全部
<a-icon type="plus-circle" @click.stop="nodeHandle({}, true)" />
</div>
<a-tree
ref="nodeTree"
class="group-tree"
:tree-data="nodeData"
:selectedKeys="selectedKeys"
:replace-fields="replaceFields"
:expanded-keys="expandedKeys"
:auto-expand-parent="autoExpandParent"
default-expand-all
show-icon
blockNode
@select="onSelect"
@expand="onExpand"
>
<template slot="title" slot-scope="{ groupName }">
<span v-if="groupName.indexOf(searchValue) > -1">
{{ groupName.substr(0, groupName.indexOf(searchValue)) }}
<span style="color: #f50">{{ searchValue }}</span>
{{ groupName.substr(groupName.indexOf(searchValue) + searchValue.length) }}
</span>
<span v-else>{{ groupName }}</span>
</template>
<!-- 新增、修改、删除图标 -->
<template slot="plus" slot-scope="record">
<!-- <a-popover placement="bottom">
<template slot="content"> -->
<!-- <p @click.stop="nodeHandle(record, false)">编辑</p>
<p @click.stop="nodeDel(record)">删除</p> -->
<!-- </template> -->
<!-- <img src="../../../assets/dict/more.png" class="more-btn" /> -->
<!-- </a-popover> -->
<a-icon type="edit" @click.stop="nodeHandle(record, false)" />
<a-icon type="delete" @click.stop="nodeDel(record)" />
</template>
</a-tree>
<a-modal v-model="visible" :title="title" destroyOnClose @ok="handleSubmit">
<AddForm ref="addFormRef" :editData="editData" @setVisibleHide="setVisibleHide" />
</a-modal>
</div>
</template>
<script>
import { getGroupList, existPerson,deleteGroupData } from '@/api/group.js'
import AddForm from './modal/addGroupForm.vue'
// 数组对象中查找符合目标的对象
const parseArray = function (objArray, key, value) {
for (let i in objArray) {
let element = objArray[i]
if (typeof element === 'object') {
let result = parseArray(element, key, value)
if (result) return result
} else {
if (i === key) {
if (element === value) return objArray
}
}
}
}
export default {
name: 'treeComponent',
data() {
return {
replaceFields: {
title: 'groupName',
key: 'groupCode',
},
nodeData: [],
groupName: '',
selectedKeys: null,
filterResource: null,
expandedKeys: [],
searchValue: '',
autoExpandParent: true,
dataList: [],
visible: false,
editData: {},
title: '新增',
selectId: '',
}
},
components: {
AddForm,
},
mounted() {
this.GetLimsConfigNode()
},
methods: {
onExpand(expandedKeys) {
this.expandedKeys = expandedKeys;
this.autoExpandParent = false;
},
// 获取全部节点树
async GetLimsConfigNode() {
getGroupList({keyWord: ''}).then((res) => {
this.nodeData = res.data;
this.generateList(this.nodeData);
})
},
generateList(data) {
for (let i = 0; i < data.length; i++) {
const node = data[i];
this.dataList.push({ groupCode: node.groupCode, groupName: node.groupName });
if (node.children) {
this.generateList(node.children);
}
}
},
// 新增、修改节点操作,此处为打开新增修改界面,调用实际后端接口进行节点的处理操作
async nodeHandle(record, isAdd) {
this.visible = true;
this.title = isAdd ? '新增' : '编辑';
this.editData = record;
},
setVisibleHide() {
this.visible = false;
this.GetLimsConfigNode()
},
nodeDel(record) {
this.$confirm({
title: `您确定要删除该节点:${record.groupName}?`,
okText: '删除',
cancelText: '取消',
onOk: async () => {
existPerson({id: record.id}).then((res) => {
if (res.status === 0) {
if(!res.data) {
delGroup(record.id)
} else {
this.$message.warning('请先删除组内人员!')
}
}
})
},
})
},
delGroup(id) {
deleteGroupData({id}).then((res) => {
if (res.status === 0) {
this.$message.success('删除成功!')
this.GetLimsConfigNode()
} else {
this.$message.warning(res.msg)
}
})
},
async onSelect(params, e) {
if (this.filterResource) {
this.$set(this.filterResource, 'scopedSlots', {})
}
if (e.selected) {
let groupName = e.selectedNodes[0].data.props.groupName
let arr = groupName.split('-')
this.filterResource = parseArray(this.nodeData, 'groupCode', params[0])
let iconStr
if (arr.length < 4) {
iconStr = 'plus'
} else {
iconStr = 'edit'
}
this.$set(this.filterResource, 'scopedSlots', { icon: iconStr })
this.selectedKeys = params
this.groupName = groupName
this.selectId = e.selectedNodes[0].data.props.id
this.$emit('getCurrentGroupId', this.selectId)
} else {
this.selectedKeys = null
this.groupName = ''
this.selectId = '';
this.$emit('getCurrentGroupId', this.selectId)
}
},
onChange(e) {
const value = e.target.value;
const expandedKeys = this.dataList
.map(item => {
if (item.groupName.indexOf(value) > -1) {
return this.getParentKey(item.groupCode, this.nodeData);
}
return null;
})
.filter((item, i, self) => item && self.indexOf(item) === i);
Object.assign(this, {
expandedKeys,
searchValue: value,
autoExpandParent: true,
});
},
getParentKey(groupCode, tree) {
let parentKey;
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
if (node.children) {
if (node.children.some(item => item.groupCode === groupCode)) {
parentKey = node.groupCode;
} else if (this.getParentKey(groupCode, node.children)) {
parentKey = this.getParentKey(groupCode, node.children);
}
}
}
return parentKey;
},
handleSubmit() {
this.$refs.addFormRef.onSubmit();
},
},
}
</script>
<style lang="scss">
.ant-tree.group-tree {
li {
position: relative;
padding: 6px 0;
ul {
padding: 0;
margin-left: -30px;
li {
padding-left: 40px;
.ant-tree-switcher {
display: none;
}
}
}
.ant-tree-node-content-wrapper.ant-tree-node-selected {
background: transparent;
}
.ant-tree-switcher_close,.ant-tree-switcher_open {
position: absolute;
left: 10px;
z-index: 9;
background: url('../../../assets/dict/organization.png') no-repeat;
background-size: 16px 16px;
background-position: center;
i {
display: none !important;
}
}
.ant-tree-node-content-wrapper:hover {
background-color: transparent;
}
span.ant-tree-iconEle {
position: absolute;
right: 10px;
width: auto;
.anticon {
margin: 0 5px;
}
}
&:hover {
background: rgba(15, 34, 67, 0.05);
}
}
li.ant-tree-treenode-selected {
background: rgba(43, 121, 255, 0.1);
border-radius: 4px;
.ant-tree-title {
color: #1F71FF;
}
ul {
li {
.ant-tree-title {
color: rgba(0, 0, 0, 0.65);
}
}
}
&:before {
content: '';
position: absolute;
width: 2px;
height: 8px;
left: 0px;
top: calc(50% - 8px/2);
background: #1F71FF;
border-radius: 0px 3px 3px 0px;
}
}
}
.ant-tree li span.ant-tree-switcher.ant-tree-switcher-noop {
width: 10px;
}
.allnode {
padding: 6px 16px;
position: relative;
.anticon {
float: right;
line-height: 24px;
}
}
.allnode.active {
background: rgba(43, 121, 255, 0.1);
&:before {
content: '';
position: absolute;
width: 2px;
height: 8px;
left: 0px;
top: calc(50% - 8px/2);
background: #1F71FF;
border-radius: 0px 3px 3px 0px;
}
}
.ant-popover {
padding-top: 0px;
margin-top: 5px;
.ant-popover-arrow {
display: none;
}
.ant-popover-inner {
box-shadow: 0px 16px 32px -6px rgba(15, 34, 67, 0.18), 0px 3px 8px -2px rgba(15, 34, 67, 0.16), 0px 0px 1px rgba(15, 34, 67, 0.16);
border-radius: 8px;
.ant-popover-inner-content {
padding: 8px;
p {
padding: 5px 16px;
margin: 0;
cursor: pointer;
&:hover {
background: rgba(15, 34, 67, 0.05);
border-radius: 6px;
}
}
}
}
}
</style>
posted @   Felix_Openmind  阅读(2085)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
*{cursor: url(https://files-cdn.cnblogs.com/files/morango/fish-cursor.ico),auto;}
点击右上角即可分享
微信分享提示