Merge branch feat/juguohong/20260206
This commit is contained in:
@@ -10,6 +10,7 @@ import { EvaluateScene } from "@/store/evaluateStore";
|
|||||||
import { waitForAuthInit } from "@/utils/authInit";
|
import { waitForAuthInit } from "@/utils/authInit";
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import { useRef, useEffect, useState, useMemo } from "react";
|
import { useRef, useEffect, useState, useMemo } from "react";
|
||||||
|
import { useDictionaryStore } from "@/store/dictionaryStore";
|
||||||
|
|
||||||
const ListContainer = (props) => {
|
const ListContainer = (props) => {
|
||||||
const {
|
const {
|
||||||
@@ -44,7 +45,7 @@ const ListContainer = (props) => {
|
|||||||
const { fetchUserInfo, fetchLastTestResult } = useUserActions();
|
const { fetchUserInfo, fetchLastTestResult } = useUserActions();
|
||||||
// 使用全局状态中的测试结果,避免重复调用接口
|
// 使用全局状态中的测试结果,避免重复调用接口
|
||||||
const lastTestResult = useLastTestResult();
|
const lastTestResult = useLastTestResult();
|
||||||
|
const { bannerListImage, bannerDetailImage, bannerListIndex = 0 } = useDictionaryStore((s) => s.bannerDict) || {};
|
||||||
useReachBottom(() => {
|
useReachBottom(() => {
|
||||||
// 加载更多方法
|
// 加载更多方法
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -130,6 +131,16 @@ const ListContainer = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 插入 banner 卡片
|
||||||
|
function insertBannerCard(list) {
|
||||||
|
if (!bannerListImage) return list;
|
||||||
|
return [
|
||||||
|
...list.slice(0, Number(bannerListIndex)),
|
||||||
|
{ type: "banner", banner_image_url: bannerListImage, banner_detail_url: bannerDetailImage },
|
||||||
|
...list.slice(Number(bannerListIndex))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// 对于没有ntrp等级的用户每个月展示一次, 插在第二个位置后面
|
// 对于没有ntrp等级的用户每个月展示一次, 插在第二个位置后面
|
||||||
function insertEvaluateCard(list) {
|
function insertEvaluateCard(list) {
|
||||||
if (!evaluateFlag)
|
if (!evaluateFlag)
|
||||||
@@ -146,17 +157,23 @@ const ListContainer = (props) => {
|
|||||||
return [...list, { type: "evaluateCard" }];
|
return [...list, { type: "evaluateCard" }];
|
||||||
}
|
}
|
||||||
const [item1, item2, ...rest] = list;
|
const [item1, item2, ...rest] = list;
|
||||||
return [
|
|
||||||
|
let result = [
|
||||||
item1,
|
item1,
|
||||||
item2,
|
item2,
|
||||||
{ type: "evaluateCard" },
|
{ type: "evaluateCard" },
|
||||||
...(showNumber !== undefined ? rest.slice(0, showNumber - 3) : rest),
|
...(showNumber !== undefined ? rest.slice(0, showNumber - 3) : rest),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (bannerListImage) {
|
||||||
|
return insertBannerCard(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const memoizedList = useMemo(
|
const memoizedList = useMemo(
|
||||||
() => insertEvaluateCard(data),
|
() => insertEvaluateCard(data),
|
||||||
[evaluateFlag, data, hasTestInLastMonth, showNumber]
|
[evaluateFlag, data, hasTestInLastMonth, showNumber, bannerListImage, bannerDetailImage, bannerListIndex]
|
||||||
);
|
);
|
||||||
|
|
||||||
// 渲染 banner 卡片
|
// 渲染 banner 卡片
|
||||||
@@ -168,7 +185,7 @@ const ListContainer = (props) => {
|
|||||||
<View
|
<View
|
||||||
key={item.id || `banner-${index}`}
|
key={item.id || `banner-${index}`}
|
||||||
style={{
|
style={{
|
||||||
height: "122px",
|
height: "100px",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
backgroundImage: `url(${item.banner_image_url})`,
|
backgroundImage: `url(${item.banner_image_url})`,
|
||||||
@@ -204,10 +221,10 @@ const ListContainer = (props) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{memoizedList.map((match, index) => {
|
{memoizedList.map((match, index) => {
|
||||||
if (match.type === "banner") {
|
if (match?.type === "banner") {
|
||||||
return renderBanner(match, index);
|
return renderBanner(match, index);
|
||||||
}
|
}
|
||||||
if (match.type === "evaluateCard") {
|
if (match?.type === "evaluateCard") {
|
||||||
return (
|
return (
|
||||||
<NTRPTestEntryCard key={`evaluate-${index}`} type={EvaluateScene.list} />
|
<NTRPTestEntryCard key={`evaluate-${index}`} type={EvaluateScene.list} />
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import {
|
|||||||
getCityQrCode,
|
getCityQrCode,
|
||||||
getDistricts,
|
getDistricts,
|
||||||
} from "../services/listApi";
|
} from "../services/listApi";
|
||||||
// 不再在这里请求 banner 字典,统一由 dictionaryStore 启动时获取
|
|
||||||
import { useDictionaryStore } from "./dictionaryStore";
|
|
||||||
import {
|
import {
|
||||||
ListActions,
|
ListActions,
|
||||||
IFilterOptions,
|
IFilterOptions,
|
||||||
@@ -20,26 +18,6 @@ import {
|
|||||||
IPayload,
|
IPayload,
|
||||||
} from "../../types/list/types";
|
} from "../../types/list/types";
|
||||||
|
|
||||||
// 将 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;
|
|
||||||
const parsed = parseInt(indexRaw, 10);
|
|
||||||
const normalized = Number.isFinite(parsed) ? parsed : 0;
|
|
||||||
// 先移除已有的 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",
|
|
||||||
id: `banner-${target}`,
|
|
||||||
banner_image_url: img,
|
|
||||||
banner_detail_url: (dictData?.bannerDetailImage || "").trim(),
|
|
||||||
} as any);
|
|
||||||
return resultRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
function translateCityData(dataTree) {
|
function translateCityData(dataTree) {
|
||||||
return dataTree.map((item) => {
|
return dataTree.map((item) => {
|
||||||
const { children, ...rest } = item;
|
const { children, ...rest } = item;
|
||||||
@@ -272,14 +250,11 @@ 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: processedData,
|
data: newData,
|
||||||
isHasMoreData,
|
isHasMoreData,
|
||||||
// 使用插入后的最终数据判断是否显示空状态,避免有 banner 时仍显示空
|
// 使用插入后的最终数据判断是否显示空状态,避免有 banner 时仍显示空
|
||||||
isShowNoData: processedData?.length === 0,
|
isShowNoData: newData?.length === 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
set({
|
set({
|
||||||
|
|||||||
Reference in New Issue
Block a user