perf: 优化TreeSelectPanel组件
This commit is contained in:
parent
e5ba0a2f31
commit
0112514339
@ -9,6 +9,7 @@ import { findGroupParentIds, treeToList } from '@vben/utils';
|
|||||||
|
|
||||||
import { Checkbox, Tree } from 'ant-design-vue';
|
import { Checkbox, Tree } from 'ant-design-vue';
|
||||||
|
|
||||||
|
/** 需要禁止透传 */
|
||||||
defineOptions({ inheritAttrs: false });
|
defineOptions({ inheritAttrs: false });
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -24,6 +25,11 @@ const props = defineProps({
|
|||||||
default: () => ({ key: 'id', title: 'label' }),
|
default: () => ({ key: 'id', title: 'label' }),
|
||||||
type: Object as PropType<{ key: string; title: string }>,
|
type: Object as PropType<{ key: string; title: string }>,
|
||||||
},
|
},
|
||||||
|
/** 点击节点关联/独立时 清空已勾选的节点 */
|
||||||
|
resetOnStrictlyChange: {
|
||||||
|
default: true,
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
treeData: {
|
treeData: {
|
||||||
default: () => [],
|
default: () => [],
|
||||||
type: Array as PropType<DataNode[]>,
|
type: Array as PropType<DataNode[]>,
|
||||||
@ -43,10 +49,6 @@ const innerCheckedStrictly = computed(() => {
|
|||||||
return !props.checkStrictly;
|
return !props.checkStrictly;
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleCheckStrictlyChange(e: CheckboxChangeEvent) {
|
|
||||||
emit('checkStrictlyChange', e.target.checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
const associationText = computed(() => {
|
const associationText = computed(() => {
|
||||||
return props.checkStrictly ? '父子节点关联' : '父子节点独立';
|
return props.checkStrictly ? '父子节点关联' : '父子节点独立';
|
||||||
});
|
});
|
||||||
@ -61,11 +63,11 @@ const checkedKeys = defineModel('value', {
|
|||||||
});
|
});
|
||||||
// 所有节点的ID
|
// 所有节点的ID
|
||||||
const allKeys = computed(() => {
|
const allKeys = computed(() => {
|
||||||
const id = props.fieldNames.key;
|
const idField = props.fieldNames.key;
|
||||||
return treeToList(props.treeData).map((item: any) => item[id]);
|
return treeToList(props.treeData).map((item: any) => item[idField]);
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 已经选择的所有节点 包括子/父节点 */
|
/** 已经选择的所有节点 包括子/父节点 用于提交 */
|
||||||
const checkedRealKeys = ref<(number | string)[]>([]);
|
const checkedRealKeys = ref<(number | string)[]>([]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,29 +124,45 @@ function handleExpandOrCollapseAll(e: CheckboxChangeEvent) {
|
|||||||
expandedKeys.value = expand ? allKeys.value : [];
|
expandedKeys.value = expand ? allKeys.value : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleCheckStrictlyChange(e: CheckboxChangeEvent) {
|
||||||
|
emit('checkStrictlyChange', e.target.checked);
|
||||||
|
if (props.resetOnStrictlyChange) {
|
||||||
|
checkedKeys.value = [];
|
||||||
|
checkedRealKeys.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暴露方法来获取用于提交的全部节点
|
||||||
|
*/
|
||||||
defineExpose({
|
defineExpose({
|
||||||
getCheckedKeys: () => checkedRealKeys.value,
|
getCheckedKeys: () => checkedRealKeys.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
if (props.expandAllOnInit) {
|
if (props.expandAllOnInit) {
|
||||||
nextTick(() => {
|
await nextTick();
|
||||||
expandedKeys.value = allKeys.value;
|
expandedKeys.value = allKeys.value;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bg-background w-full rounded-lg border-[1px] p-[12px]">
|
<div class="bg-background w-full rounded-lg border-[1px] p-[12px]">
|
||||||
<div class="flex items-center gap-2 border-b-[1px] pb-2">
|
<div class="flex items-center justify-between gap-2 border-b-[1px] pb-2">
|
||||||
<span>节点状态: </span>
|
<div>
|
||||||
<span
|
<span>节点状态: </span>
|
||||||
:class="[props.checkStrictly ? 'text-primary' : 'text-red-500']"
|
<span :class="[props.checkStrictly ? 'text-primary' : 'text-red-500']">
|
||||||
class="font-semibold"
|
{{ associationText }}
|
||||||
>
|
</span>
|
||||||
{{ associationText }}
|
</div>
|
||||||
</span>
|
<div>
|
||||||
|
已选中
|
||||||
|
<span class="text-primary mx-1 font-semibold">
|
||||||
|
{{ checkedRealKeys.length }}
|
||||||
|
</span>
|
||||||
|
个节点
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="flex flex-wrap items-center justify-between border-b-[1px] py-2"
|
class="flex flex-wrap items-center justify-between border-b-[1px] py-2"
|
||||||
|
@ -8,9 +8,9 @@ import { cloneDeep } from '@vben/utils';
|
|||||||
import { useVbenForm } from '#/adapter';
|
import { useVbenForm } from '#/adapter';
|
||||||
import { menuTreeSelect, roleMenuTreeSelect } from '#/api/system/menu';
|
import { menuTreeSelect, roleMenuTreeSelect } from '#/api/system/menu';
|
||||||
import { roleAdd, roleInfo, roleUpdate } from '#/api/system/role';
|
import { roleAdd, roleInfo, roleUpdate } from '#/api/system/role';
|
||||||
|
import { TreeSelectPanel } from '#/components/tree';
|
||||||
|
|
||||||
import { drawerSchema } from './data';
|
import { drawerSchema } from './data';
|
||||||
import MenuSelect from './menu-select.vue';
|
|
||||||
|
|
||||||
const emit = defineEmits<{ reload: [] }>();
|
const emit = defineEmits<{ reload: [] }>();
|
||||||
|
|
||||||
@ -115,11 +115,11 @@ function handleMenuCheckStrictlyChange(value: boolean) {
|
|||||||
<BasicForm>
|
<BasicForm>
|
||||||
<template #menuIds="slotProps">
|
<template #menuIds="slotProps">
|
||||||
<!-- check-strictly为readonly 不能通过v-model绑定 -->
|
<!-- check-strictly为readonly 不能通过v-model绑定 -->
|
||||||
<MenuSelect
|
<TreeSelectPanel
|
||||||
ref="menuSelectRef"
|
ref="menuSelectRef"
|
||||||
v-bind="slotProps"
|
v-bind="slotProps"
|
||||||
:check-strictly="formApi.form.values.menuCheckStrictly"
|
:check-strictly="formApi.form.values.menuCheckStrictly"
|
||||||
:menu-tree="menuTree"
|
:tree-data="menuTree"
|
||||||
@check-strictly-change="handleMenuCheckStrictlyChange"
|
@check-strictly-change="handleMenuCheckStrictlyChange"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user