瀏覽代碼

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>
CG.gatspy 12 小時之前
父節點
當前提交
3230781538

+ 67 - 23
packages/@core/ui-kit/shadcn-ui/src/ui/tree/tree.vue

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

+ 2 - 0
packages/@core/ui-kit/shadcn-ui/src/ui/tree/types.ts

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