|
|
@@ -9,7 +9,7 @@ import type { ApiConfig, FieldNames } from '#/components/form/types';
|
|
|
|
|
|
import { computed, reactive, ref, toRaw, unref, watch, watchEffect } from 'vue';
|
|
|
|
|
|
-import { VbenLoading, VbenScrollbar } from '@vben/common-ui';
|
|
|
+import { Loading, VbenScrollbar } from '@vben/common-ui';
|
|
|
import { EmptyIcon } from '@vben/icons';
|
|
|
import { isFunction } from '@vben/utils';
|
|
|
|
|
|
@@ -61,6 +61,10 @@ const props = defineProps({
|
|
|
type: Boolean,
|
|
|
default: true,
|
|
|
},
|
|
|
+ toolbar: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
checkable: {
|
|
|
type: Boolean,
|
|
|
default: false,
|
|
|
@@ -73,6 +77,10 @@ const props = defineProps({
|
|
|
type: Boolean,
|
|
|
default: false,
|
|
|
},
|
|
|
+ treeData: {
|
|
|
+ type: Array as PropType<TreeDataItem[]>,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
});
|
|
|
const emit = defineEmits([
|
|
|
'update:searchValue',
|
|
|
@@ -155,7 +163,7 @@ const handleSelect = (keys: Key[], e: any) => {
|
|
|
emit('change', keys, e);
|
|
|
};
|
|
|
|
|
|
-const handleCheck = (keys: any) => {
|
|
|
+const handleCheck = (keys: any, info: any) => {
|
|
|
let currentValue = [...keys];
|
|
|
if (searchState.startSearch) {
|
|
|
currentValue = currentValue.filter((item: number | string) => {
|
|
|
@@ -167,7 +175,7 @@ const handleCheck = (keys: any) => {
|
|
|
|
|
|
const rawVal = toRaw(state.checkedKeys);
|
|
|
emit('update:value', rawVal);
|
|
|
- emit('check', rawVal);
|
|
|
+ emit('check', rawVal, info);
|
|
|
};
|
|
|
|
|
|
const contentStyle = computed<StyleValue>(() => {
|
|
|
@@ -208,6 +216,12 @@ watchEffect(() => {
|
|
|
state.checkedKeys = props.checkedKeys;
|
|
|
});
|
|
|
|
|
|
+watchEffect(() => {
|
|
|
+ if (props.treeData) {
|
|
|
+ treeDataRef.value = props.treeData as TreeDataItem[];
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
watch(
|
|
|
() => props.api.params,
|
|
|
() => {
|
|
|
@@ -216,6 +230,15 @@ watch(
|
|
|
{ deep: true },
|
|
|
);
|
|
|
|
|
|
+watch(
|
|
|
+ () => props.treeData,
|
|
|
+ (val) => {
|
|
|
+ if (val) {
|
|
|
+ handleSearch(searchState.searchText);
|
|
|
+ }
|
|
|
+ },
|
|
|
+);
|
|
|
+
|
|
|
const setExpandedKeys = (keys: (number | string)[]) => {
|
|
|
state.expandedKeys = keys;
|
|
|
};
|
|
|
@@ -349,56 +372,59 @@ const handleMenuClick = async (e: any) => {
|
|
|
/>
|
|
|
</div>
|
|
|
<VbenScrollbar :style="contentStyle">
|
|
|
- <VbenLoading :spinning="loading" />
|
|
|
- <DirectoryTree
|
|
|
- :expanded-keys="state.expandedKeys"
|
|
|
- :auto-expand-parent="state.autoExpandParent"
|
|
|
- :checked-keys="state.checkedKeys"
|
|
|
- :tree-data="getTreeData"
|
|
|
- :field-names="{
|
|
|
- title: fieldNames.label,
|
|
|
- key: fieldNames.value,
|
|
|
- children: fieldNames.children,
|
|
|
- }"
|
|
|
- block-node
|
|
|
- :show-icon="false"
|
|
|
- class="px-2"
|
|
|
- :checkable="checkable"
|
|
|
- @expand="handleExpand"
|
|
|
- @select="handleSelect"
|
|
|
- @check="handleCheck"
|
|
|
- :check-strictly="state.checkStrictly"
|
|
|
- >
|
|
|
- <template #title="treeDataItem">
|
|
|
- <slot name="title" v-bind="treeDataItem">
|
|
|
- <span
|
|
|
- v-if="treeDataItem[fieldNames.label].indexOf(searchListData) > -1"
|
|
|
- >
|
|
|
- {{
|
|
|
- treeDataItem[fieldNames.label].substring(
|
|
|
- 0,
|
|
|
- treeDataItem[fieldNames.label].indexOf(searchListData),
|
|
|
- )
|
|
|
- }}
|
|
|
- <span style="color: #f50">{{ searchListData }}</span>
|
|
|
- {{
|
|
|
- treeDataItem[fieldNames.label].substring(
|
|
|
- treeDataItem[fieldNames.label].indexOf(searchListData) +
|
|
|
- searchListData.length,
|
|
|
- )
|
|
|
- }}
|
|
|
- </span>
|
|
|
- <span v-else>{{ treeDataItem[fieldNames.label] }}</span>
|
|
|
- </slot>
|
|
|
- </template>
|
|
|
- </DirectoryTree>
|
|
|
- <div
|
|
|
- v-if="getNotFound"
|
|
|
- class="flex-col-center text-muted-foreground min-h-[150px] w-full"
|
|
|
- >
|
|
|
- <EmptyIcon class="size-10" />
|
|
|
- <div class="mt-1 text-sm">暂无数据</div>
|
|
|
- </div>
|
|
|
+ <Loading :spinning="loading" text="正在加载...">
|
|
|
+ <DirectoryTree
|
|
|
+ :expanded-keys="state.expandedKeys"
|
|
|
+ :auto-expand-parent="state.autoExpandParent"
|
|
|
+ :checked-keys="state.checkedKeys"
|
|
|
+ :tree-data="getTreeData"
|
|
|
+ :field-names="{
|
|
|
+ title: fieldNames.label,
|
|
|
+ key: fieldNames.value,
|
|
|
+ children: fieldNames.children,
|
|
|
+ }"
|
|
|
+ block-node
|
|
|
+ :show-icon="false"
|
|
|
+ class="px-2"
|
|
|
+ :checkable="checkable"
|
|
|
+ @expand="handleExpand"
|
|
|
+ @select="handleSelect"
|
|
|
+ @check="handleCheck"
|
|
|
+ :check-strictly="state.checkStrictly"
|
|
|
+ >
|
|
|
+ <template #title="treeDataItem">
|
|
|
+ <slot name="title" v-bind="treeDataItem">
|
|
|
+ <span
|
|
|
+ v-if="
|
|
|
+ treeDataItem[fieldNames.label].indexOf(searchListData) > -1
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ treeDataItem[fieldNames.label].substring(
|
|
|
+ 0,
|
|
|
+ treeDataItem[fieldNames.label].indexOf(searchListData),
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ <span style="color: #f50">{{ searchListData }}</span>
|
|
|
+ {{
|
|
|
+ treeDataItem[fieldNames.label].substring(
|
|
|
+ treeDataItem[fieldNames.label].indexOf(searchListData) +
|
|
|
+ searchListData.length,
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </span>
|
|
|
+ <span v-else>{{ treeDataItem[fieldNames.label] }}</span>
|
|
|
+ </slot>
|
|
|
+ </template>
|
|
|
+ </DirectoryTree>
|
|
|
+ <div
|
|
|
+ v-if="getNotFound"
|
|
|
+ class="flex-col-center text-muted-foreground min-h-[150px] w-full"
|
|
|
+ >
|
|
|
+ <EmptyIcon class="size-10" />
|
|
|
+ <div class="mt-1 text-sm">暂无数据</div>
|
|
|
+ </div>
|
|
|
+ </Loading>
|
|
|
</VbenScrollbar>
|
|
|
</div>
|
|
|
</template>
|