diff --git a/src/main_pages/index.tsx b/src/main_pages/index.tsx index 90af2fe..b71b954 100644 --- a/src/main_pages/index.tsx +++ b/src/main_pages/index.tsx @@ -13,6 +13,7 @@ import MessagePageContent from "./components/MessagePageContent"; import MyselfPageContent from "./components/MyselfPageContent"; import "./index.scss"; import FamilyContext from "@/context"; +import { useDictionaryStore } from "@/store/dictionaryStore"; type TabType = "list" | "message" | "personal"; @@ -66,6 +67,12 @@ const MainPage: React.FC = () => { try { await fetchUserInfo(); await checkNicknameChangeStatus(); + // 启动时预取 Banner 字典(与业务无强依赖,失败不影响主流程) + try { + await useDictionaryStore.getState().fetchBannerDictionary(); + } catch (e) { + console.error("预取 Banner 字典失败:", e); + } } catch (error) { console.error("获取用户信息失败:", error); } diff --git a/src/store/dictionaryStore.ts b/src/store/dictionaryStore.ts index 1e504d4..7d8995e 100644 --- a/src/store/dictionaryStore.ts +++ b/src/store/dictionaryStore.ts @@ -14,6 +14,13 @@ interface DictionaryState { fetchDictionary: () => Promise getDictionaryValue: (key: string, defaultValue?: any) => any clearDictionary: () => void + // banner 字典(单独管理,保持原始值) + bannerDict: { + bannerListImage: string + bannerDetailImage: string + bannerListIndex: string + } | null + fetchBannerDictionary: () => Promise } // 创建字典Store @@ -22,6 +29,7 @@ export const useDictionaryStore = create()((set, get) => ({ dictionaryData: {}, isLoading: false, error: null, + bannerDict: null, // 获取字典数据 fetchDictionary: async () => { @@ -56,6 +64,27 @@ export const useDictionaryStore = create()((set, get) => ({ } }, + // 获取 Banner 字典(启动时或手动调用) + fetchBannerDictionary: async () => { + try { + const keys = 'bannerListImage,bannerDetailImage,bannerListIndex'; + const response = await commonApi.getDictionaryManyKey(keys) + if (response.code === 0 && response.data) { + const data = response.data || {}; + set({ + bannerDict: { + bannerListImage: data.bannerListImage || '', + bannerDetailImage: data.bannerDetailImage || '', + bannerListIndex: (data.bannerListIndex ?? '').toString(), + } + }) + } + } catch (error) { + // 保持静默,避免影响启动流程 + console.error('获取 Banner 字典失败:', error) + } + }, + // 获取字典值 getDictionaryValue: (key: string, defaultValue?: any) => { const { dictionaryData } = get() diff --git a/src/store/listStore.ts b/src/store/listStore.ts index 046e9a2..128589e 100644 --- a/src/store/listStore.ts +++ b/src/store/listStore.ts @@ -11,7 +11,8 @@ import { getCityQrCode, getDistricts, } from "../services/listApi"; -import commonApi from "../services/commonApi"; +// 不再在这里请求 banner 字典,统一由 dictionaryStore 启动时获取 +import { useDictionaryStore } from "./dictionaryStore"; import { ListActions, IFilterOptions, @@ -19,17 +20,16 @@ import { IPayload, } from "../../types/list/types"; -// 将 banner 按索引插入到 rows 的工具方法 +// 将 banner 按索引插入到列表的工具方法(0基;长度不足则插末尾;先移除已存在的 banner) function insertBannersToRows(rows: any[], dictData: any) { if (!Array.isArray(rows) || !dictData) return rows; - // 仅单张图片与单个索引 const img = (dictData?.bannerListImage || "").trim(); const indexRaw = (dictData?.bannerListIndex || "").toString().trim(); if (!img) return rows; - // 固定采用 0 基索引 const parsed = parseInt(indexRaw, 10); const normalized = Number.isFinite(parsed) ? parsed : 0; - const resultRows = [...rows]; + // 先移除已有的 banner,确保列表中仅一条 banner + const resultRows = rows?.filter((item) => item?.type !== "banner") || []; const target = Math.max(0, Math.min(normalized, resultRows.length)); resultRows.splice(target, 0, { type: "banner", @@ -272,10 +272,14 @@ export const useListStore = create()((set, get) => ({ const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState; const currentData = currentPageState?.data || []; const newData = isAppend ? [...currentData, ...(data || [])] : (data || []); + // 从字典缓存获取 banner,并将其插入到最终列表指定位置(全局索引) + const dictData = useDictionaryStore.getState().bannerDict; + const processedData = dictData ? insertBannersToRows(newData, dictData) : newData; state.updateCurrentPageState({ - data: newData, + data: processedData, isHasMoreData, - isShowNoData: newData?.length === 0, + // 使用插入后的最终数据判断是否显示空状态,避免有 banner 时仍显示空 + isShowNoData: processedData?.length === 0, }); set({ @@ -318,30 +322,8 @@ export const useListStore = create()((set, get) => ({ } } - // 并发请求:列表接口 + 字典接口(仅第一页且非追加时插入 Banner) - const shouldInsertBanner = (currentPageState?.pageOption?.page || 1) === 1 && !isAppend; - const keys = "bannerListImage,bannerDetailImage,bannerListIndex"; let resData: any = {}; - let dictData: any = null; - - if (shouldInsertBanner) { - const [listResult, dictResult] = await Promise.allSettled([ - fetchFn(reqParams), - commonApi.getDictionaryManyKey(keys), - ]); - // 列表接口请求成功 - if (listResult.status === "fulfilled") { - resData = listResult.value || {}; - } else { - throw listResult.reason || new Error("获取数据失败"); - } - // 字典接口请求成功 - if (dictResult.status === "fulfilled" && (dictResult.value as any)?.code === 0) { - dictData = (dictResult.value as any)?.data || null; - } - } else { - resData = (await fetchFn(reqParams)) || {}; - } + resData = (await fetchFn(reqParams)) || {}; const { data = {}, code } = resData; if (code !== 0) { @@ -357,11 +339,6 @@ export const useListStore = create()((set, get) => ({ const { count } = data; let { rows } = data as any; - // 将 banner 插入到指定位置(仅第一页且非追加) - if (shouldInsertBanner && Array.isArray(rows) && dictData) { - rows = insertBannersToRows(rows, dictData); - } - setListData({ error: '', data: rows || [], @@ -397,10 +374,9 @@ export const useListStore = create()((set, get) => ({ try { const searchParams = getSearchParams() || {}; - const keys = "bannerListImage,bannerDetailImage,bannerListIndex"; - // 并发请求:常规列表、智能排序列表、字典 - const [listResSettled, integrateResSettled, dictSettled] = await Promise.allSettled([ + // 并发请求:常规列表、智能排序列表 + const [listResSettled, integrateResSettled] = await Promise.allSettled([ getGamesList({ ...searchParams, order: searchParams.order || "distance", @@ -413,14 +389,10 @@ export const useListStore = create()((set, get) => ({ isRefresh: true, }, }), - commonApi.getDictionaryManyKey(keys), ]); const listRes = listResSettled.status === "fulfilled" ? listResSettled.value : null; const integrateRes = integrateResSettled.status === "fulfilled" ? integrateResSettled.value : null; - const dictData = dictSettled.status === "fulfilled" && (dictSettled.value as any)?.code === 0 - ? (dictSettled.value as any)?.data - : null; // 根据当前排序方式更新对应的数据 const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState; @@ -430,10 +402,6 @@ export const useListStore = create()((set, get) => ({ if (listRes?.code === 0 && listRes?.data) { const { count } = listRes.data; let { rows } = listRes.data as any; - // 插入 banner(当为第一页时) - if ((currentPageState?.pageOption?.page || 1) === 1 && Array.isArray(rows) && dictData) { - rows = insertBannersToRows(rows, dictData); - } if (!isIntegrate) { // 如果当前是常规排序,更新常规列表数据 setListData({ @@ -449,10 +417,6 @@ export const useListStore = create()((set, get) => ({ if (integrateRes?.code === 0 && integrateRes?.data) { const { count } = integrateRes.data; let { rows, recommendList } = integrateRes.data as any; - // 插入 banner(当为第一页时) - if ((currentPageState?.pageOption?.page || 1) === 1 && Array.isArray(rows) && dictData) { - rows = insertBannersToRows(rows, dictData); - } if (isIntegrate) { // 如果当前是智能排序,更新智能排序列表数据 setListData({