|
@@ -9,9 +9,13 @@
|
|
|
<div class="fsd">
|
|
|
<ui-input
|
|
|
type="text"
|
|
|
- readonly
|
|
|
- :modelValue="[current[current.length - 1]] .map((i: any) => i.title).join('/')"
|
|
|
+ :modelValue="focus ? keyword : [current[current.length - 1]]
|
|
|
+ .map((i: any) => i.title)
|
|
|
+ .join('/')"
|
|
|
+ @update:modelValue="(val) => (keyword = val)"
|
|
|
width="100%"
|
|
|
+ @focus="focus = true"
|
|
|
+ @blur="focus = false"
|
|
|
>
|
|
|
<template #icon>
|
|
|
<DownOutlined />
|
|
@@ -23,28 +27,29 @@
|
|
|
<div class="flat" @click.stop="visible = true">
|
|
|
<div>
|
|
|
<span
|
|
|
- v-for="item in items"
|
|
|
+ v-for="item in filterItems"
|
|
|
@click.stop="
|
|
|
() => {
|
|
|
handleClick(item), !item.children && (visible = false);
|
|
|
}
|
|
|
"
|
|
|
- :class="{ active: current?.includes(item) }"
|
|
|
+ :class="{ active: current?.some((i) => item.key === i.key) }"
|
|
|
>
|
|
|
{{ item.title }}
|
|
|
<DownOutlined v-if="item.children?.length" class="jdd" />
|
|
|
</span>
|
|
|
</div>
|
|
|
<div>
|
|
|
- <template v-if="current[0].children">
|
|
|
+ <template v-if="filterItems.find((item) => item.key === current[0].key)">
|
|
|
<span
|
|
|
- v-for="item in current[0].children"
|
|
|
+ v-for="item in filterItems.find((item) => item.key === current[0].key)
|
|
|
+ .children"
|
|
|
@click.stop="
|
|
|
() => {
|
|
|
handleClick(item), (visible = false);
|
|
|
}
|
|
|
"
|
|
|
- :class="{ active: current?.includes(item) }"
|
|
|
+ :class="{ active: current?.some((i) => item.key === i.key) }"
|
|
|
>
|
|
|
{{ item.title }}
|
|
|
</span>
|
|
@@ -64,6 +69,7 @@ import { taggings, getTaggingStyle } from "@/store";
|
|
|
|
|
|
const props = defineProps<{ value: number; all?: boolean; count?: boolean }>();
|
|
|
const emit = defineEmits<{ (e: "update:value", v: number): void }>();
|
|
|
+const keyword = ref("");
|
|
|
const allType = { name: "全部", id: -1 };
|
|
|
const getTypeCount = (item: any) => {
|
|
|
if (item.id === allType.id) {
|
|
@@ -85,19 +91,23 @@ const getTypeCount = (item: any) => {
|
|
|
};
|
|
|
const open = ref(false);
|
|
|
|
|
|
-const getItems = (types = styleTypes): any => {
|
|
|
+const getItems = (types = styleTypes, parentHit = 0): any => {
|
|
|
return types
|
|
|
.map((item) => {
|
|
|
let count = 0;
|
|
|
if (props.count) {
|
|
|
count = getTypeCount(item);
|
|
|
}
|
|
|
+ const hit = item.name.includes(keyword.value) ? 1 : 0;
|
|
|
+ const children = "children" in item ? getItems(item.children as any, hit) : null;
|
|
|
+
|
|
|
return {
|
|
|
label: item.name + (props.count ? ` (${count}) ` : ""),
|
|
|
title: item.name,
|
|
|
+ hit: children?.length ? children.reduce((t, c) => t + c.hit, 0) : hit + parentHit,
|
|
|
count,
|
|
|
key: item.id,
|
|
|
- children: "children" in item ? getItems(item.children) : null,
|
|
|
+ children,
|
|
|
};
|
|
|
})
|
|
|
.filter((item) => !props.count || item.count || item.key === allType.id);
|
|
@@ -124,11 +134,27 @@ const types = computed(() => {
|
|
|
});
|
|
|
const visible = ref(false);
|
|
|
const items = computed(() => getItems(types.value));
|
|
|
+const filterItems = computed(() => {
|
|
|
+ const filter = (items: any[]): any => {
|
|
|
+ return items
|
|
|
+ .map((item) => {
|
|
|
+ if (item.children) {
|
|
|
+ return { ...item, children: filter(item.children) };
|
|
|
+ } else {
|
|
|
+ return { ...item };
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .filter((item) => {
|
|
|
+ return item.hit > 0;
|
|
|
+ });
|
|
|
+ };
|
|
|
+ return filter(items.value);
|
|
|
+});
|
|
|
const current = computed(() => getCurrentItem(props.value));
|
|
|
|
|
|
const oldValue = ref(props.value);
|
|
|
watchEffect(() => {
|
|
|
- if (!current.value[current.value.length - 1].children?.length) {
|
|
|
+ if (current.value && !current.value[current.value.length - 1].children?.length) {
|
|
|
oldValue.value = props.value;
|
|
|
}
|
|
|
});
|
|
@@ -162,6 +188,17 @@ if (props.count && props.all) {
|
|
|
const handleClick = (info: any) => {
|
|
|
emit("update:value", info.key);
|
|
|
};
|
|
|
+
|
|
|
+const focus = ref(false);
|
|
|
+watchEffect(() => {
|
|
|
+ if (!focus.value) {
|
|
|
+ // setTimeout(() => {
|
|
|
+ // keyword.value = [current.value[current.value.length - 1]]
|
|
|
+ // .map((i: any) => i.title)
|
|
|
+ // .join("/");
|
|
|
+ // }, 50);
|
|
|
+ }
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
@@ -229,12 +266,12 @@ span {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
cursor: pointer;
|
|
|
- &::after {
|
|
|
- content: "";
|
|
|
- position: absolute;
|
|
|
- inset: 0;
|
|
|
- z-index: 999;
|
|
|
- }
|
|
|
+ // &::after {
|
|
|
+ // content: "";
|
|
|
+ // position: absolute;
|
|
|
+ // inset: 0;
|
|
|
+ // z-index: 999;
|
|
|
+ // }
|
|
|
}
|
|
|
</style>
|
|
|
|
|
@@ -246,6 +283,7 @@ span {
|
|
|
.ant-dropdown-menu {
|
|
|
border-radius: 2px !important;
|
|
|
}
|
|
|
+
|
|
|
.style-float-select-overlay-parent {
|
|
|
position: absolute;
|
|
|
inset: 0;
|