|
@@ -10,12 +10,12 @@ interface TreeOption {
|
|
|
}
|
|
}
|
|
|
const props = withDefaults(
|
|
const props = withDefaults(
|
|
|
defineProps<{
|
|
defineProps<{
|
|
|
- value: string | number | Array<string | number> | null | undefined
|
|
|
|
|
|
|
+ modelValue: string | number | Array<string | number> | null | undefined
|
|
|
id?: string //id变化后重新加载树
|
|
id?: string //id变化后重新加载树
|
|
|
name?: string
|
|
name?: string
|
|
|
url?: string
|
|
url?: string
|
|
|
dataFun?: () => Promise<any>
|
|
dataFun?: () => Promise<any>
|
|
|
- data?: Array<any>
|
|
|
|
|
|
|
+ data?: Array<any> | (() => Array<any>)
|
|
|
method?: string
|
|
method?: string
|
|
|
configs?: AxiosRequestConfig
|
|
configs?: AxiosRequestConfig
|
|
|
multiple?: boolean
|
|
multiple?: boolean
|
|
@@ -29,22 +29,23 @@ const props = withDefaults(
|
|
|
// "LEAF_PRIORITY"- 如果选中分支节点,则该节点本身及其分支后代将从数组中排除,但其叶子代将被包括在内value
|
|
// "LEAF_PRIORITY"- 如果选中分支节点,则该节点本身及其分支后代将从数组中排除,但其叶子代将被包括在内value
|
|
|
// "ALL_WITH_INDETERMINATE"- 任何被选中的节点都将包含在数组中,加上不确定的节点value (默认值)
|
|
// "ALL_WITH_INDETERMINATE"- 任何被选中的节点都将包含在数组中,加上不确定的节点value (默认值)
|
|
|
valueConsistsOf?: "ALL" | "BRANCH_PRIORITY" | "LEAF_PRIORITY" | "ALL_WITH_INDETERMINATE"
|
|
valueConsistsOf?: "ALL" | "BRANCH_PRIORITY" | "LEAF_PRIORITY" | "ALL_WITH_INDETERMINATE"
|
|
|
- expandedKeys?: Array<string>
|
|
|
|
|
defaultExpandLevel?: number
|
|
defaultExpandLevel?: number
|
|
|
placeholder?: string
|
|
placeholder?: string
|
|
|
loadingText?: string
|
|
loadingText?: string
|
|
|
staticOptions?: Array<TreeOption>
|
|
staticOptions?: Array<TreeOption>
|
|
|
dataFormatFunction?: (data: any) => TreeOption
|
|
dataFormatFunction?: (data: any) => TreeOption
|
|
|
- optionMap?: {
|
|
|
|
|
|
|
+ props?: {
|
|
|
id: string
|
|
id: string
|
|
|
label: string
|
|
label: string
|
|
|
children: string
|
|
children: string
|
|
|
}
|
|
}
|
|
|
|
|
+ listeners?: any
|
|
|
}>(),
|
|
}>(),
|
|
|
{
|
|
{
|
|
|
|
|
+ data: () => [],
|
|
|
multiple: false,
|
|
multiple: false,
|
|
|
- flat: false,
|
|
|
|
|
- clearable: false,
|
|
|
|
|
|
|
+ flat: true,
|
|
|
|
|
+ clearable: true,
|
|
|
searchable: false,
|
|
searchable: false,
|
|
|
method: "get",
|
|
method: "get",
|
|
|
sortValueBy: "LEVEL",
|
|
sortValueBy: "LEVEL",
|
|
@@ -52,46 +53,52 @@ const props = withDefaults(
|
|
|
staticOptions: () => {
|
|
staticOptions: () => {
|
|
|
return [] as Array<TreeOption>
|
|
return [] as Array<TreeOption>
|
|
|
},
|
|
},
|
|
|
- optionMap: () => {
|
|
|
|
|
|
|
+ props: () => {
|
|
|
return {
|
|
return {
|
|
|
id: "id",
|
|
id: "id",
|
|
|
label: "label",
|
|
label: "label",
|
|
|
children: "children",
|
|
children: "children",
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
-
|
|
|
|
|
|
|
+ defaultExpandLevel: 1,
|
|
|
placeholder: "请选择...",
|
|
placeholder: "请选择...",
|
|
|
loadingText: "加载中,请稍后...",
|
|
loadingText: "加载中,请稍后...",
|
|
|
}
|
|
}
|
|
|
)
|
|
)
|
|
|
const emits = defineEmits<{
|
|
const emits = defineEmits<{
|
|
|
- (e: "update:value", v: string | number | Array<string | number> | null | undefined): void
|
|
|
|
|
|
|
+ (e: "update:modelValue", v: string | number | Array<string | number> | null | undefined): void
|
|
|
(e: "select", v: any): void
|
|
(e: "select", v: any): void
|
|
|
(e: "deselect", v: any): void
|
|
(e: "deselect", v: any): void
|
|
|
}>()
|
|
}>()
|
|
|
-const { staticOptions, data: dataOptions, value, id } = toRefs(props)
|
|
|
|
|
-const options = ref<Array<TreeOption>>(Object.assign([], staticOptions.value ?? []))
|
|
|
|
|
-
|
|
|
|
|
|
|
+const { staticOptions, data: dataOptions, modelValue, id } = toRefs(props)
|
|
|
|
|
+const _data = ref<Array<TreeOption>>(Object.assign([], staticOptions.value ?? []))
|
|
|
|
|
+const options = computed(() => {
|
|
|
|
|
+ if (props.dataFun || props.url) {
|
|
|
|
|
+ return _data.value
|
|
|
|
|
+ }
|
|
|
|
|
+ return formatDatas(typeof props.data == "function" ? props.data() : props.data)
|
|
|
|
|
+})
|
|
|
|
|
+function formatDatas(data: Array<any>) {
|
|
|
|
|
+ const list: any = []
|
|
|
|
|
+ data.forEach((v: any) => {
|
|
|
|
|
+ list.push(formatData(v))
|
|
|
|
|
+ })
|
|
|
|
|
+ return list
|
|
|
|
|
+}
|
|
|
function formatData(data: any) {
|
|
function formatData(data: any) {
|
|
|
if (props.dataFormatFunction) {
|
|
if (props.dataFormatFunction) {
|
|
|
return props.dataFormatFunction(data)
|
|
return props.dataFormatFunction(data)
|
|
|
} else {
|
|
} else {
|
|
|
const item = {} as TreeOption
|
|
const item = {} as TreeOption
|
|
|
- if (props.optionMap.id in data) {
|
|
|
|
|
- item.id = data[props.optionMap.id]
|
|
|
|
|
- }
|
|
|
|
|
- if (props.optionMap.label in data) {
|
|
|
|
|
- item.label = data[props.optionMap.label]
|
|
|
|
|
- }
|
|
|
|
|
- if (props.optionMap.children in data) {
|
|
|
|
|
- const childrenItem = [] as Array<TreeOption>
|
|
|
|
|
- const children = data[props.optionMap.children]
|
|
|
|
|
- children?.forEach((v: any) => {
|
|
|
|
|
- childrenItem.push(formatData(v))
|
|
|
|
|
- })
|
|
|
|
|
- if (childrenItem.length) {
|
|
|
|
|
- item.children = childrenItem
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ item.id = data[props.props.id ?? "id"]
|
|
|
|
|
+ item.label = data[props.props.label ?? "label"]
|
|
|
|
|
+ const childrenItem = [] as Array<TreeOption>
|
|
|
|
|
+ const children = data[props.props.children ?? "children"]
|
|
|
|
|
+ children?.forEach((v: any) => {
|
|
|
|
|
+ childrenItem.push(formatData(v))
|
|
|
|
|
+ })
|
|
|
|
|
+ if (childrenItem.length) {
|
|
|
|
|
+ item.children = childrenItem
|
|
|
}
|
|
}
|
|
|
return item
|
|
return item
|
|
|
}
|
|
}
|
|
@@ -99,51 +106,53 @@ function formatData(data: any) {
|
|
|
|
|
|
|
|
function load() {
|
|
function load() {
|
|
|
if (dataOptions?.value) {
|
|
if (dataOptions?.value) {
|
|
|
- console.log("dataOptions", dataOptions)
|
|
|
|
|
- dataOptions.value.map((v) => {
|
|
|
|
|
|
|
+ dataOptions.value = (typeof props.data == "function" ? props.data() : props.data).map((v) => {
|
|
|
return formatData(v)
|
|
return formatData(v)
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
- options.value = Object.assign([], staticOptions.value ?? [], dataOptions?.value ?? [])
|
|
|
|
|
|
|
+ _data.value = Object.assign([], staticOptions.value ?? [], dataOptions?.value ?? [])
|
|
|
if (props.url) {
|
|
if (props.url) {
|
|
|
const configs = Object.assign({}, { url: props.url, method: props.method, successAlert: false }, props.configs)
|
|
const configs = Object.assign({}, { url: props.url, method: props.method, successAlert: false }, props.configs)
|
|
|
Rs.request(configs).then((res: any) => {
|
|
Rs.request(configs).then((res: any) => {
|
|
|
processData(res.data)
|
|
processData(res.data)
|
|
|
})
|
|
})
|
|
|
- // if (props.method.toLowerCase() == "get") {
|
|
|
|
|
- // Rs.get(configs).then((res: any) => {
|
|
|
|
|
- // processData(res.data)
|
|
|
|
|
- // })
|
|
|
|
|
- // } else if (props.method.toLowerCase() == "post") {
|
|
|
|
|
- // Rs.post(configs).then((res: any) => {
|
|
|
|
|
- // processData(res.data)
|
|
|
|
|
- // })
|
|
|
|
|
- // }
|
|
|
|
|
} else if (props.dataFun) {
|
|
} else if (props.dataFun) {
|
|
|
props.dataFun().then((res) => {
|
|
props.dataFun().then((res) => {
|
|
|
- console.log("deptOptions.value3", res)
|
|
|
|
|
processData(res?.data || res)
|
|
processData(res?.data || res)
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
function processData(data: any) {
|
|
function processData(data: any) {
|
|
|
- console.log("deptOptions.value4", data)
|
|
|
|
|
data.forEach((v: any) => {
|
|
data.forEach((v: any) => {
|
|
|
const item = formatData(v)
|
|
const item = formatData(v)
|
|
|
- options.value.push(item)
|
|
|
|
|
|
|
+ _data.value.push(item)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- if (!value.value) {
|
|
|
|
|
- const val = props.multiple ? [options.value[0].id] : options.value[0].id
|
|
|
|
|
- emits("update:value", val)
|
|
|
|
|
|
|
+ if (!modelValue.value) {
|
|
|
|
|
+ const val = props.multiple ? [_data.value[0].id] : _data.value[0].id
|
|
|
|
|
+ emits("update:modelValue", val)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function onSelect(data: any) {
|
|
function onSelect(data: any) {
|
|
|
- emits("deselect", data)
|
|
|
|
|
|
|
+ let val = modelValue.value as any
|
|
|
|
|
+ if (props.multiple) {
|
|
|
|
|
+ val.push(data.id)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ val = data.id
|
|
|
|
|
+ }
|
|
|
|
|
+ emits("update:modelValue", val)
|
|
|
|
|
+ emits("select", data)
|
|
|
}
|
|
}
|
|
|
function onDeselect(data: any) {
|
|
function onDeselect(data: any) {
|
|
|
- emits("select", data)
|
|
|
|
|
|
|
+ let val = modelValue.value as any
|
|
|
|
|
+ if (props.multiple) {
|
|
|
|
|
+ val.splice(val.indexOf(data.id), 1)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ val = undefined
|
|
|
|
|
+ }
|
|
|
|
|
+ emits("update:modelValue", val)
|
|
|
|
|
+ emits("deselect", data)
|
|
|
}
|
|
}
|
|
|
watch(() => props.id, init)
|
|
watch(() => props.id, init)
|
|
|
onMounted(init)
|
|
onMounted(init)
|
|
@@ -154,7 +163,7 @@ defineExpose({ load })
|
|
|
</script>
|
|
</script>
|
|
|
<template>
|
|
<template>
|
|
|
<tree-select
|
|
<tree-select
|
|
|
- v-model="value"
|
|
|
|
|
|
|
+ v-model="modelValue"
|
|
|
:id="id"
|
|
:id="id"
|
|
|
:placeholder="placeholder"
|
|
:placeholder="placeholder"
|
|
|
:loadingText="loadingText"
|
|
:loadingText="loadingText"
|
|
@@ -167,8 +176,21 @@ defineExpose({ load })
|
|
|
:flat="flat"
|
|
:flat="flat"
|
|
|
:sort-value-by="sortValueBy"
|
|
:sort-value-by="sortValueBy"
|
|
|
:value-consists-of="valueConsistsOf"
|
|
:value-consists-of="valueConsistsOf"
|
|
|
- v-bind="$attrs"
|
|
|
|
|
@select="onSelect"
|
|
@select="onSelect"
|
|
|
@deselect="onDeselect"
|
|
@deselect="onDeselect"
|
|
|
|
|
+ v-bind="$attrs"
|
|
|
|
|
+ v-on="listeners"
|
|
|
/>
|
|
/>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+:deep(.vue-treeselect__list) {
|
|
|
|
|
+ .vue-treeselect__option--highlight {
|
|
|
|
|
+ color: var(--bs-primary);
|
|
|
|
|
+ background: var(--bs-primary-light);
|
|
|
|
|
+ }
|
|
|
|
|
+ .vue-treeselect__option--selected {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ background: var(--bs-primary);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|