feat: [vben-tree]增加数据disabled (#6343)

* feat: [vben-tree]增加数据disabled

* Update packages/@core/ui-kit/shadcn-ui/src/ui/tree/tree.vue

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: Jin Mao <50581550+jinmao88@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
pull/162/head^2^2
CG.gatspy 2025-06-27 19:09:30 +08:00 committed by GitHub
parent e7fd0e3b6a
commit 3230781538
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 69 additions and 23 deletions

View File

@ -23,6 +23,7 @@ const props = withDefaults(defineProps<TreeProps>(), {
defaultExpandedKeys: () => [], defaultExpandedKeys: () => [],
defaultExpandedLevel: 0, defaultExpandedLevel: 0,
disabled: false, disabled: false,
disabledField: 'disabled',
expanded: () => [], expanded: () => [],
iconField: 'icon', iconField: 'icon',
labelField: 'label', labelField: 'label',
@ -101,16 +102,37 @@ function updateTreeValue() {
if (val === undefined) { if (val === undefined) {
treeValue.value = undefined; treeValue.value = undefined;
} else { } else {
treeValue.value = Array.isArray(val) if (Array.isArray(val)) {
? val.map((v) => getItemByValue(v)) const filteredValues = val.filter((v) => {
: getItemByValue(val); const item = getItemByValue(v);
return item && !get(item, props.disabledField);
});
treeValue.value = filteredValues.map((v) => getItemByValue(v));
if (filteredValues.length !== val.length) {
modelValue.value = filteredValues;
}
} else {
const item = getItemByValue(val);
if (item && !get(item, props.disabledField)) {
treeValue.value = item;
} else {
treeValue.value = undefined;
modelValue.value = undefined;
}
}
} }
} }
function updateModelValue(val: Arrayable<Recordable<any>>) { function updateModelValue(val: Arrayable<Recordable<any>>) {
modelValue.value = Array.isArray(val) if (Array.isArray(val)) {
? val.map((v) => get(v, props.valueField)) const filteredVal = val.filter((v) => !get(v, props.disabledField));
: get(val, props.valueField); modelValue.value = filteredVal.map((v) => get(v, props.valueField));
} else {
if (val && !get(val, props.disabledField)) {
modelValue.value = get(val, props.valueField);
}
}
} }
function expandToLevel(level: number) { function expandToLevel(level: number) {
@ -149,10 +171,18 @@ function collapseAll() {
expanded.value = []; expanded.value = [];
} }
function isNodeDisabled(item: FlattenedItem<Recordable<any>>) {
return props.disabled || get(item.value, props.disabledField);
}
function onToggle(item: FlattenedItem<Recordable<any>>) { function onToggle(item: FlattenedItem<Recordable<any>>) {
emits('expand', item); emits('expand', item);
} }
function onSelect(item: FlattenedItem<Recordable<any>>, isSelected: boolean) { function onSelect(item: FlattenedItem<Recordable<any>>, isSelected: boolean) {
if (isNodeDisabled(item)) {
return;
}
if ( if (
!props.checkStrictly && !props.checkStrictly &&
props.multiple && props.multiple &&
@ -224,28 +254,34 @@ defineExpose({
:class=" :class="
cn('cursor-pointer', getNodeClass?.(item), { cn('cursor-pointer', getNodeClass?.(item), {
'data-[selected]:bg-accent': !multiple, 'data-[selected]:bg-accent': !multiple,
'cursor-not-allowed': disabled, 'cursor-not-allowed': isNodeDisabled(item),
}) })
" "
v-bind=" v-bind="
Object.assign(item.bind, { Object.assign(item.bind, {
onfocus: disabled ? 'this.blur()' : undefined, onfocus: isNodeDisabled(item) ? 'this.blur()' : undefined,
disabled: isNodeDisabled(item),
}) })
" "
@select=" @select="
(event) => { (event: any) => {
if (isNodeDisabled(item)) {
event.preventDefault();
event.stopPropagation();
return;
}
if (event.detail.originalEvent.type === 'click') { if (event.detail.originalEvent.type === 'click') {
event.preventDefault(); event.preventDefault();
} }
!disabled && onSelect(item, event.detail.isSelected); onSelect(item, event.detail.isSelected);
} }
" "
@toggle=" @toggle="
(event) => { (event: any) => {
if (event.detail.originalEvent.type === 'click') { if (event.detail.originalEvent.type === 'click') {
event.preventDefault(); event.preventDefault();
} }
!disabled && onToggle(item); !isNodeDisabled(item) && onToggle(item);
} }
" "
class="tree-node focus:ring-grass8 my-0.5 flex items-center rounded px-2 py-1 outline-none focus:ring-2" class="tree-node focus:ring-grass8 my-0.5 flex items-center rounded px-2 py-1 outline-none focus:ring-2"
@ -266,24 +302,32 @@ defineExpose({
</div> </div>
<Checkbox <Checkbox
v-if="multiple" v-if="multiple"
:checked="isSelected" :checked="isSelected && !isNodeDisabled(item)"
:disabled="disabled" :disabled="isNodeDisabled(item)"
:indeterminate="isIndeterminate" :indeterminate="isIndeterminate && !isNodeDisabled(item)"
@click=" @click="
() => { (event: MouseEvent) => {
!disabled && handleSelect(); if (isNodeDisabled(item)) {
// onSelect(item, !isSelected); event.preventDefault();
event.stopPropagation();
return;
}
handleSelect();
} }
" "
/> />
<div <div
class="flex items-center gap-1 pl-2" class="flex items-center gap-1 pl-2"
@click=" @click="
(_event) => { (event: MouseEvent) => {
// $event.stopPropagation(); if (isNodeDisabled(item)) {
// $event.preventDefault(); event.preventDefault();
!disabled && handleSelect(); event.stopPropagation();
// onSelect(item, !isSelected); return;
}
event.stopPropagation();
event.preventDefault();
handleSelect();
} }
" "
> >

View File

@ -22,6 +22,8 @@ export interface TreeProps {
defaultValue?: Arrayable<number | string>; defaultValue?: Arrayable<number | string>;
/** 禁用 */ /** 禁用 */
disabled?: boolean; disabled?: boolean;
/** 禁用字段名 */
disabledField?: string;
/** 自定义节点类名 */ /** 自定义节点类名 */
getNodeClass?: (item: FlattenedItem<Recordable<any>>) => string; getNodeClass?: (item: FlattenedItem<Recordable<any>>) => string;
iconField?: string; iconField?: string;