update at 2026-02-07 11:14:09

This commit is contained in:
douboer
2026-02-07 11:14:09 +08:00
parent 2d18aa5137
commit 591bd9ba05
67 changed files with 4885 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
<script setup lang="ts">
import type { FontTreeNode } from '../types/font'
import { useFontStore } from '../stores/fontStore'
const props = defineProps<{
nodes: FontTreeNode[]
}>()
const fontStore = useFontStore()
function toggleExpand(node: FontTreeNode) {
const next = !node.expanded
node.expanded = next
fontStore.setCategoryExpanded(node.name, next)
}
function handlePreviewClick(node: FontTreeNode, event: Event) {
event.stopPropagation()
if (node.type === 'font' && node.fontInfo) {
fontStore.togglePreview(node.fontInfo.id)
}
}
function handleFavoriteClick(node: FontTreeNode, event: Event) {
event.stopPropagation()
if (node.type === 'font' && node.fontInfo) {
fontStore.toggleFavorite(node.fontInfo.id)
}
}
function isFavorite(node: FontTreeNode): boolean {
return node.type === 'font' && node.fontInfo ? fontStore.favoriteFontIds.has(node.fontInfo.id) : false
}
function isInPreview(node: FontTreeNode): boolean {
return node.type === 'font' && node.fontInfo ? fontStore.previewFontIds.has(node.fontInfo.id) : false
}
</script>
<template>
<div class="space-y-0">
<div v-for="node in nodes" :key="node.name">
<!-- 分类节点 -->
<div v-if="node.type === 'category'" class="relative mb-3">
<div class="flex items-center">
<!-- 左侧展开图标 -->
<div class="tree-icon-wrapper">
<button
@click="toggleExpand(node)"
class="tree-toggle"
>
<img
v-if="node.expanded"
src="/assets/icons/zhedie.svg"
alt="收起"
class="w-[15px] h-[15px]"
/>
<img
v-else
src="/assets/icons/icons_idx%20_12.svg"
alt="展开"
class="w-[15px] h-[15px]"
/>
</button>
</div>
<!-- 分类标题 -->
<div
@click="toggleExpand(node)"
class="text-base font-medium text-black cursor-pointer flex-1 ml-2"
>
{{ node.name }}
</div>
</div>
<!-- 竖直连接线 -->
<div v-if="node.expanded && node.children" class="tree-vertical-line"></div>
<!-- 字体列表 -->
<div v-if="node.expanded && node.children" class="flex flex-col gap-3 mt-3">
<div
v-for="(child, index) in node.children"
:key="child.name"
class="flex items-center gap-2 border-b border-[#c9cdd4] pb-2 relative"
>
<!-- 水平连接线 -->
<div class="tree-horizontal-line"></div>
<!-- 字体图标 -->
<div class="w-4 h-4 shrink-0 ml-[17px]">
<img src="/assets/icons/icons_idx%20_18.svg" alt="font" class="w-full h-full" />
</div>
<!-- 字体名称 -->
<div class="flex-1 text-xs text-[#86909c]">
{{ child.name }}
</div>
<!-- 预览复选框 -->
<button
@click="handlePreviewClick(child, $event)"
class="w-[18px] h-[18px] shrink-0 border rounded-full flex items-center justify-center p-0 bg-transparent"
:class="isInPreview(child) ? 'bg-[#9b6bc2] border-[#9b6bc2]' : 'border-[#c9cdd4]'"
>
<img v-if="isInPreview(child)" src="/assets/icons/checkbox.svg" alt="选中" class="w-[11px] h-[9px]" />
</button>
<!-- 收藏按钮 -->
<button
@click="handleFavoriteClick(child, $event)"
class="w-[18px] h-[17px] shrink-0 p-0 border-0 bg-transparent"
>
<img
src="/assets/icons/icons_idx%20_19.svg"
alt="收藏"
class="w-full h-full"
:class="isFavorite(child) ? 'favorite-active' : ''"
/>
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.tree-icon-wrapper {
position: relative;
width: 17px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.tree-toggle {
width: 15px;
height: 15px;
padding: 0;
border: 0;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
position: relative;
z-index: 1;
}
.tree-vertical-line {
position: absolute;
left: 8px;
top: 20px;
bottom: 12px;
width: 1px;
background: #c9cdd4;
}
.tree-horizontal-line {
position: absolute;
left: 8px;
top: 12px;
width: 10px;
height: 1px;
background: #c9cdd4;
}
.favorite-active {
filter: brightness(0) saturate(100%) invert(16%) sepia(96%) saturate(7491%) hue-rotate(356deg) brightness(99%) contrast(119%);
}
</style>