| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import { defineStore } from 'pinia'
- import type { BizCategoryVo } from '~/types/api'
- import { categoryApi } from '~/api/category'
- import { CATEGORY_TREE_CACHE_KEY } from '~/constants'
- interface CategoryState {
- // 完整品类树(一级 + 二级)
- categoryTree: BizCategoryVo[]
- // 当前选中的一级品类 code
- activeFirstCode: string
- // 当前选中的二级品类 code
- activeSecondCode: string
- // 是否正在加载
- loading: boolean
- // 是否已经初始化过(避免重复请求)
- initialized: boolean
- }
- export const useCategoryStore = defineStore('category', {
- state: (): CategoryState => ({
- categoryTree: [],
- activeFirstCode: '',
- activeSecondCode: '',
- loading: false,
- initialized: false,
- }),
- actions: {
- /**
- * 加载品类树
- * 默认只在首次调用时请求,可以通过 force=true 强制刷新
- */
- async loadCategories(force = false) {
- // 先尝试从 localStorage 读取缓存(仅在客户端且尚未初始化时执行)
- if (import.meta.client && !this.initialized && this.categoryTree.length === 0) {
- try {
- const cached = localStorage.getItem(CATEGORY_TREE_CACHE_KEY)
- if (cached) {
- const parsed = JSON.parse(cached) as BizCategoryVo[]
- if (Array.isArray(parsed) && parsed.length > 0) {
- this.categoryTree = parsed
- }
- }
- }
- catch (e) {
- console.warn('Failed to read category tree from localStorage:', e)
- }
- }
- // 如果已经通过接口拿到过最新数据,且不强制刷新,则直接返回
- if (this.initialized && !force)
- return
- this.loading = true
- try {
- const res = await categoryApi.listTree()
- if (!res || !res.list || res.list.length === 0)
- return
- // 保留完整的品类树;展示逻辑由组件自己控制(如只展示前三个)
- this.categoryTree = res.list
- this.initialized = true
- // 成功后将最新数据写入 localStorage,供下次快速恢复
- if (import.meta.client) {
- try {
- localStorage.setItem(CATEGORY_TREE_CACHE_KEY, JSON.stringify(this.categoryTree))
- }
- catch (e) {
- console.warn('Failed to write category tree to localStorage:', e)
- }
- }
- }
- catch (error) {
- // 这里的错误已经在 http 拦截器里有统一处理,这里仅做兜底日志
- console.error('Failed to load category tree:', error)
- }
- finally {
- this.loading = false
- }
- },
- /**
- * 根据当前品类树初始化默认选中项(第一个一级 + 其第一个二级)
- * 仅在还没有选中任何一级品类时生效
- */
- initDefaultSelection() {
- if (this.activeFirstCode)
- return
- const first = this.categoryTree[0]
- if (!first)
- return
- this.activeFirstCode = first.code
- const firstChildren = first.children
- if (firstChildren && firstChildren.length > 0 && firstChildren[0]) {
- this.activeSecondCode = firstChildren[0].code
- }
- },
- /**
- * 切换一级品类时,同时联动重置二级为当前一级下的第一个子品类
- */
- setActiveFirst(code: string) {
- if (this.activeFirstCode === code)
- return
- this.activeFirstCode = code
- const current = this.categoryTree.find(item => item.code === code)
- const firstChild = current?.children?.[0]
- this.activeSecondCode = firstChild?.code ?? ''
- },
- /**
- * 更新当前二级品类 code
- */
- setActiveSecond(code: string) {
- if (this.activeSecondCode === code)
- return
- this.activeSecondCode = code
- },
- },
- })
|