优化banner逻辑

This commit is contained in:
李瑞
2026-02-01 23:37:31 +08:00
parent 8abf6e6f2b
commit 4c75368fe8
3 changed files with 50 additions and 50 deletions

View File

@@ -13,6 +13,7 @@ import MessagePageContent from "./components/MessagePageContent";
import MyselfPageContent from "./components/MyselfPageContent"; import MyselfPageContent from "./components/MyselfPageContent";
import "./index.scss"; import "./index.scss";
import FamilyContext from "@/context"; import FamilyContext from "@/context";
import { useDictionaryStore } from "@/store/dictionaryStore";
type TabType = "list" | "message" | "personal"; type TabType = "list" | "message" | "personal";
@@ -66,6 +67,12 @@ const MainPage: React.FC = () => {
try { try {
await fetchUserInfo(); await fetchUserInfo();
await checkNicknameChangeStatus(); await checkNicknameChangeStatus();
// 启动时预取 Banner 字典(与业务无强依赖,失败不影响主流程)
try {
await useDictionaryStore.getState().fetchBannerDictionary();
} catch (e) {
console.error("预取 Banner 字典失败:", e);
}
} catch (error) { } catch (error) {
console.error("获取用户信息失败:", error); console.error("获取用户信息失败:", error);
} }

View File

@@ -14,6 +14,13 @@ interface DictionaryState {
fetchDictionary: () => Promise<void> fetchDictionary: () => Promise<void>
getDictionaryValue: (key: string, defaultValue?: any) => any getDictionaryValue: (key: string, defaultValue?: any) => any
clearDictionary: () => void clearDictionary: () => void
// banner 字典(单独管理,保持原始值)
bannerDict: {
bannerListImage: string
bannerDetailImage: string
bannerListIndex: string
} | null
fetchBannerDictionary: () => Promise<void>
} }
// 创建字典Store // 创建字典Store
@@ -22,6 +29,7 @@ export const useDictionaryStore = create<DictionaryState>()((set, get) => ({
dictionaryData: {}, dictionaryData: {},
isLoading: false, isLoading: false,
error: null, error: null,
bannerDict: null,
// 获取字典数据 // 获取字典数据
fetchDictionary: async () => { fetchDictionary: async () => {
@@ -56,6 +64,27 @@ export const useDictionaryStore = create<DictionaryState>()((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) => { getDictionaryValue: (key: string, defaultValue?: any) => {
const { dictionaryData } = get() const { dictionaryData } = get()

View File

@@ -11,7 +11,8 @@ import {
getCityQrCode, getCityQrCode,
getDistricts, getDistricts,
} from "../services/listApi"; } from "../services/listApi";
import commonApi from "../services/commonApi"; // 不再在这里请求 banner 字典,统一由 dictionaryStore 启动时获取
import { useDictionaryStore } from "./dictionaryStore";
import { import {
ListActions, ListActions,
IFilterOptions, IFilterOptions,
@@ -19,17 +20,16 @@ import {
IPayload, IPayload,
} from "../../types/list/types"; } from "../../types/list/types";
// 将 banner 按索引插入到 rows 的工具方法 // 将 banner 按索引插入到列表的工具方法0基长度不足则插末尾先移除已存在的 banner
function insertBannersToRows(rows: any[], dictData: any) { function insertBannersToRows(rows: any[], dictData: any) {
if (!Array.isArray(rows) || !dictData) return rows; if (!Array.isArray(rows) || !dictData) return rows;
// 仅单张图片与单个索引
const img = (dictData?.bannerListImage || "").trim(); const img = (dictData?.bannerListImage || "").trim();
const indexRaw = (dictData?.bannerListIndex || "").toString().trim(); const indexRaw = (dictData?.bannerListIndex || "").toString().trim();
if (!img) return rows; if (!img) return rows;
// 固定采用 0 基索引
const parsed = parseInt(indexRaw, 10); const parsed = parseInt(indexRaw, 10);
const normalized = Number.isFinite(parsed) ? parsed : 0; 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)); const target = Math.max(0, Math.min(normalized, resultRows.length));
resultRows.splice(target, 0, { resultRows.splice(target, 0, {
type: "banner", type: "banner",
@@ -272,10 +272,14 @@ export const useListStore = create<TennisStore>()((set, get) => ({
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState; const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
const currentData = currentPageState?.data || []; const currentData = currentPageState?.data || [];
const newData = isAppend ? [...currentData, ...(data || [])] : (data || []); const newData = isAppend ? [...currentData, ...(data || [])] : (data || []);
// 从字典缓存获取 banner并将其插入到最终列表指定位置全局索引
const dictData = useDictionaryStore.getState().bannerDict;
const processedData = dictData ? insertBannersToRows(newData, dictData) : newData;
state.updateCurrentPageState({ state.updateCurrentPageState({
data: newData, data: processedData,
isHasMoreData, isHasMoreData,
isShowNoData: newData?.length === 0, // 使用插入后的最终数据判断是否显示空状态,避免有 banner 时仍显示空
isShowNoData: processedData?.length === 0,
}); });
set({ set({
@@ -318,30 +322,8 @@ export const useListStore = create<TennisStore>()((set, get) => ({
} }
} }
// 并发请求:列表接口 + 字典接口(仅第一页且非追加时插入 Banner
const shouldInsertBanner = (currentPageState?.pageOption?.page || 1) === 1 && !isAppend;
const keys = "bannerListImage,bannerDetailImage,bannerListIndex";
let resData: any = {}; 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; const { data = {}, code } = resData;
if (code !== 0) { if (code !== 0) {
@@ -357,11 +339,6 @@ export const useListStore = create<TennisStore>()((set, get) => ({
const { count } = data; const { count } = data;
let { rows } = data as any; let { rows } = data as any;
// 将 banner 插入到指定位置(仅第一页且非追加)
if (shouldInsertBanner && Array.isArray(rows) && dictData) {
rows = insertBannersToRows(rows, dictData);
}
setListData({ setListData({
error: '', error: '',
data: rows || [], data: rows || [],
@@ -397,10 +374,9 @@ export const useListStore = create<TennisStore>()((set, get) => ({
try { try {
const searchParams = getSearchParams() || {}; const searchParams = getSearchParams() || {};
const keys = "bannerListImage,bannerDetailImage,bannerListIndex";
// 并发请求:常规列表、智能排序列表、字典 // 并发请求:常规列表、智能排序列表
const [listResSettled, integrateResSettled, dictSettled] = await Promise.allSettled([ const [listResSettled, integrateResSettled] = await Promise.allSettled([
getGamesList({ getGamesList({
...searchParams, ...searchParams,
order: searchParams.order || "distance", order: searchParams.order || "distance",
@@ -413,14 +389,10 @@ export const useListStore = create<TennisStore>()((set, get) => ({
isRefresh: true, isRefresh: true,
}, },
}), }),
commonApi.getDictionaryManyKey(keys),
]); ]);
const listRes = listResSettled.status === "fulfilled" ? listResSettled.value : null; const listRes = listResSettled.status === "fulfilled" ? listResSettled.value : null;
const integrateRes = integrateResSettled.status === "fulfilled" ? integrateResSettled.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; const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
@@ -430,10 +402,6 @@ export const useListStore = create<TennisStore>()((set, get) => ({
if (listRes?.code === 0 && listRes?.data) { if (listRes?.code === 0 && listRes?.data) {
const { count } = listRes.data; const { count } = listRes.data;
let { rows } = listRes.data as any; let { rows } = listRes.data as any;
// 插入 banner当为第一页时
if ((currentPageState?.pageOption?.page || 1) === 1 && Array.isArray(rows) && dictData) {
rows = insertBannersToRows(rows, dictData);
}
if (!isIntegrate) { if (!isIntegrate) {
// 如果当前是常规排序,更新常规列表数据 // 如果当前是常规排序,更新常规列表数据
setListData({ setListData({
@@ -449,10 +417,6 @@ export const useListStore = create<TennisStore>()((set, get) => ({
if (integrateRes?.code === 0 && integrateRes?.data) { if (integrateRes?.code === 0 && integrateRes?.data) {
const { count } = integrateRes.data; const { count } = integrateRes.data;
let { rows, recommendList } = integrateRes.data as any; let { rows, recommendList } = integrateRes.data as any;
// 插入 banner当为第一页时
if ((currentPageState?.pageOption?.page || 1) === 1 && Array.isArray(rows) && dictData) {
rows = insertBannersToRows(rows, dictData);
}
if (isIntegrate) { if (isIntegrate) {
// 如果当前是智能排序,更新智能排序列表数据 // 如果当前是智能排序,更新智能排序列表数据
setListData({ setListData({