update at 2026-02-07 15:51:08

This commit is contained in:
douboer
2026-02-07 15:51:08 +08:00
parent 0b2595b0e0
commit 91fcd79203
3 changed files with 57 additions and 2411 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -9,26 +9,45 @@ const searchKeyword = ref('')
const fontTree = computed(() => fontStore.fontTree)
const normalizedSearchKeyword = computed(() => searchKeyword.value.trim().toLowerCase())
const isSelectedOnlyMode = computed(() => {
const keyword = normalizedSearchKeyword.value
return keyword.includes('选中') || keyword.includes('选择') || keyword.includes('已选')
})
const normalizedNameSearchKeyword = computed(() => {
return isSelectedOnlyMode.value ? '' : normalizedSearchKeyword.value
})
const hasSearchKeyword = computed(() => normalizedSearchKeyword.value.length > 0)
function nodeHasMatch(node: (typeof fontTree.value)[number]): boolean {
if (node.type !== 'category') {
return false
}
const fontChildren = (node.children ?? []).filter((child) => {
return child.type === 'font' && !!child.fontInfo
})
const selectedFilteredChildren = isSelectedOnlyMode.value
? fontChildren.filter(child => !!child.fontInfo && fontStore.previewFontIds.has(child.fontInfo.id))
: fontChildren
if (normalizedNameSearchKeyword.value.length === 0) {
return selectedFilteredChildren.length > 0
}
const keyword = normalizedNameSearchKeyword.value
if (node.name.toLowerCase().includes(keyword)) {
return selectedFilteredChildren.length > 0
}
return selectedFilteredChildren.some(child => child.name.toLowerCase().includes(keyword))
}
const hasMatchedFonts = computed(() => {
if (!hasSearchKeyword.value) {
return fontTree.value.length > 0
}
const keyword = normalizedSearchKeyword.value
return fontTree.value.some((node) => {
if (node.type !== 'category') {
return false
}
if (node.name.toLowerCase().includes(keyword)) {
return true
}
return (node.children ?? []).some(child => {
return child.type === 'font' && child.name.toLowerCase().includes(keyword)
})
})
return fontTree.value.some(node => nodeHasMatch(node))
})
</script>
@@ -66,7 +85,8 @@ const hasMatchedFonts = computed(() => {
<FontTree
v-else
:nodes="fontTree"
:search-keyword="normalizedSearchKeyword"
:search-keyword="normalizedNameSearchKeyword"
:selected-only="isSelectedOnlyMode"
/>
</div>
</template>

View File

@@ -8,11 +8,13 @@ import { useFontStore } from '../stores/fontStore'
const props = defineProps<{
nodes: FontTreeNode[]
searchKeyword?: string
selectedOnly?: boolean
}>()
const fontStore = useFontStore()
const normalizedSearchKeyword = computed(() => (props.searchKeyword ?? '').trim().toLowerCase())
const isSearchMode = computed(() => normalizedSearchKeyword.value.length > 0)
const isFilterMode = computed(() => isSearchMode.value || props.selectedOnly === true)
type FontLeafNode = FontTreeNode & { fontInfo: NonNullable<FontTreeNode['fontInfo']> }
@@ -24,16 +26,20 @@ function getVisibleChildren(node: FontTreeNode): FontLeafNode[] {
const fontChildren = node.children.filter(
(child): child is FontLeafNode => child.type === 'font' && !!child.fontInfo,
)
const selectedFilteredChildren = props.selectedOnly
? fontChildren.filter(child => fontStore.previewFontIds.has(child.fontInfo.id))
: fontChildren
if (!isSearchMode.value) {
return fontChildren
return selectedFilteredChildren
}
const keyword = normalizedSearchKeyword.value
if (node.name.toLowerCase().includes(keyword)) {
return fontChildren
return selectedFilteredChildren
}
return fontChildren.filter(child => child.name.toLowerCase().includes(keyword))
return selectedFilteredChildren.filter(child => child.name.toLowerCase().includes(keyword))
}
function shouldRenderCategory(node: FontTreeNode): boolean {
@@ -41,11 +47,11 @@ function shouldRenderCategory(node: FontTreeNode): boolean {
}
function isCategoryExpanded(node: FontTreeNode): boolean {
return isSearchMode.value ? true : !!node.expanded
return isFilterMode.value ? true : !!node.expanded
}
function toggleExpand(node: FontTreeNode) {
if (isSearchMode.value) {
if (isFilterMode.value) {
return
}
const next = !node.expanded
@@ -115,14 +121,14 @@ function handleCategorySelectAll(node: FontTreeNode, event: Event) {
<button
@click="toggleExpand(node)"
class="tree-toggle"
:disabled="isSearchMode"
:disabled="isFilterMode"
>
<img
v-if="isCategoryExpanded(node)"
src="../assets/icons/zhedie.svg"
alt="收起"
class="w-[15px] h-[15px]"
:class="{ 'opacity-70': isSearchMode }"
:class="{ 'opacity-70': isFilterMode }"
/>
<img
v-else
@@ -137,7 +143,7 @@ function handleCategorySelectAll(node: FontTreeNode, event: Event) {
<div
@click="toggleExpand(node)"
class="text-base font-medium text-black flex-1 ml-2"
:class="isSearchMode ? 'cursor-default' : 'cursor-pointer'"
:class="isFilterMode ? 'cursor-default' : 'cursor-pointer'"
>
{{ node.name }}{{ getCategoryFontCount(node) }}字体
</div>