diff --git a/src/stores/menu.ts b/src/stores/menu.ts index e69de29..c27177e 100644 --- a/src/stores/menu.ts +++ b/src/stores/menu.ts @@ -0,0 +1,44 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import type { CategoryTreeNode } from '@/api/category' + +export const useMenuStore = defineStore('menu', () => { + /** 分类树(顶层) */ + const categoryTree = ref([]) + + /** 每层选中的 id,[layer0, layer1?, layer2?] */ + const layerActiveValues = ref([]) + + /** 过滤:仅当 forceShow 明确为 false 时不显示,其他(null/undefined/true 等)均显示;排除 forceHide 的节点 */ + function filterVisible(nodes: CategoryTreeNode[] | undefined): CategoryTreeNode[] { + if (!nodes?.length) return [] + return nodes.filter((n) => n.forceShow !== false && !n.forceHide) + } + + /** 当前展示的层级数据:[[layer0], [layer1]?, [layer2]?] */ + const categoryLayers = computed(() => { + const root = filterVisible(categoryTree.value) + if (root.length === 0) return [] + + const layers: CategoryTreeNode[][] = [root] + const active = layerActiveValues.value + + let currentNodes = root + for (let i = 0; i < 2; i++) { + const selectedId = active[i] + const node = selectedId ? currentNodes.find((n) => n.id === selectedId) : currentNodes[0] + const children = filterVisible(node?.children) + if (children.length === 0) break + layers.push(children) + currentNodes = children + } + return layers + }) + + return { + categoryTree, + layerActiveValues, + categoryLayers, + filterVisible + } +}) diff --git a/src/views/Home.vue b/src/views/Home.vue index e4b6c8e..e3a23e6 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -155,13 +155,14 @@ import { enrichWithIcons, getPmTagMain, MOCK_CATEGORY_TREE, - type CategoryTreeNode, } from '../api/category' import { USE_MOCK_CATEGORY } from '../config/mock' import { useI18n } from 'vue-i18n' import { useSearchHistory } from '../composables/useSearchHistory' import { useToastStore } from '../stores/toast' import { useLocaleStore } from '../stores/locale' +import { useMenuStore } from '../stores/menu' +import { storeToRefs } from 'pinia' const { mobile } = useDisplay() const { t } = useI18n() @@ -169,10 +170,10 @@ const searchHistory = useSearchHistory() const searchHistoryList = computed(() => searchHistory.list.value) const isMobile = computed(() => mobile.value) -/** 分类树(顶层) */ -const categoryTree = ref([]) -/** 每层选中的 id,[layer0, layer1?, layer2?] */ -const layerActiveValues = ref([]) +const menuStore = useMenuStore() +const { categoryTree, layerActiveValues, categoryLayers } = storeToRefs(menuStore) +const { filterVisible } = menuStore + /** 第三层搜索框是否展开 */ const searchExpanded = ref(false) /** 搜索关键词 */ @@ -225,12 +226,6 @@ function doSearch(keyword: string) { loadEvents(1, false, keyword) } -/** 过滤:仅当 forceShow 明确为 false 时不显示,其他(null/undefined/true 等)均显示;排除 forceHide 的节点 */ -function filterVisible(nodes: CategoryTreeNode[] | undefined): CategoryTreeNode[] { - if (!nodes?.length) return [] - return nodes.filter((n) => n.forceShow !== false && !n.forceHide) -} - /** 当前选中分类的 tagIds:收集所有选中层级节点的 tagId 数组(含父级),用于事件筛选 */ const activeTagIds = computed(() => { const activeIds = layerActiveValues.value @@ -255,26 +250,6 @@ const activeTagIds = computed(() => { return Array.from(tagIdSet) }) -/** 当前展示的层级数据:[[layer0], [layer1]?, [layer2]?] */ -const categoryLayers = computed(() => { - const root = filterVisible(categoryTree.value) - if (root.length === 0) return [] - - const layers: CategoryTreeNode[][] = [root] - const active = layerActiveValues.value - - let currentNodes = root - for (let i = 0; i < 2; i++) { - const selectedId = active[i] - const node = selectedId ? currentNodes.find((n) => n.id === selectedId) : currentNodes[0] - const children = filterVisible(node?.children) - if (children.length === 0) break - layers.push(children) - currentNodes = children - } - return layers -}) - /** 分类选中时:若有 children 则展开下一层并默认选中第一个,并重新加载列表 */ function onCategorySelect(layerIndex: number, selectedId: string) { if (!selectedId || layerActiveValues.value[layerIndex] === selectedId) {