From d7c24ca8b34b8d28905cef27fdb8ffe94bcf9623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=91=9E?= Date: Thu, 1 Jan 2026 15:37:27 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E6=98=BE=E7=A4=BA=E7=A9=BA=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main_pages/components/ListPageContent.tsx | 4 +++- src/store/listStore.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main_pages/components/ListPageContent.tsx b/src/main_pages/components/ListPageContent.tsx index 58703b4..986fbf7 100644 --- a/src/main_pages/components/ListPageContent.tsx +++ b/src/main_pages/components/ListPageContent.tsx @@ -385,7 +385,9 @@ const ListPageContent: React.FC = ({ }; const handleRefresh = async () => { - + if (refreshing) { + return; + } setRefreshing(true); try { diff --git a/src/store/listStore.ts b/src/store/listStore.ts index 0c41c7c..40616d7 100644 --- a/src/store/listStore.ts +++ b/src/store/listStore.ts @@ -319,7 +319,7 @@ export const useListStore = create()((set, get) => ({ return Promise.resolve(); } catch (error) { setListData({ - error: "-1", + error: "", data: [], loading: false, count: 0, From fa328f893d2ddc9317a0506591df71f9bba2a31c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Mon, 5 Jan 2026 18:34:05 +0800 Subject: [PATCH 02/11] 1 --- .../components/MessagePageContent.tsx | 10 +++++++-- src/other_pages/comment_reply/index.tsx | 21 ++++++++++++------- src/other_pages/new_follow/index.tsx | 21 ++++++++++++------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/main_pages/components/MessagePageContent.tsx b/src/main_pages/components/MessagePageContent.tsx index 8f79305..0f77599 100644 --- a/src/main_pages/components/MessagePageContent.tsx +++ b/src/main_pages/components/MessagePageContent.tsx @@ -64,11 +64,17 @@ const MessagePageContent: React.FC = ({ isActive = true } }; - // 只有当页面激活且未加载过数据时才加载接口 + // 当切换到消息 tab 时,调用红点信息接口 + useEffect(() => { + if (isActive) { + fetchReddotInfo(); + } + }, [isActive]); + + // 只有当页面激活且未加载过数据时才加载通知列表 useEffect(() => { if (isActive && !hasLoaded) { getNoticeList(); - fetchReddotInfo(); setHasLoaded(true); } }, [isActive, hasLoaded]); diff --git a/src/other_pages/comment_reply/index.tsx b/src/other_pages/comment_reply/index.tsx index 75c29a9..6a94d53 100644 --- a/src/other_pages/comment_reply/index.tsx +++ b/src/other_pages/comment_reply/index.tsx @@ -71,14 +71,12 @@ const CommentReply = () => { setCommentList(mappedList); - // 获取未读评论ID并标记已读 - const unreadIds = res.data.rows - .filter((item: any) => item.is_read === 0) - .map((item: any) => item.id); + // 获取所有评论ID列表并标记已读(传入所有ID,包括已读和未读) + const allCommentIds = res.data.rows.map((item: any) => item.id); - if (unreadIds.length > 0) { - // 使用统一接口标记已读 - messageService.markAsRead('comment', unreadIds).catch(e => { + if (allCommentIds.length > 0) { + // 使用统一接口标记已读,传入所有评论ID + messageService.markAsRead('comment', allCommentIds).catch(e => { console.error("标记评论已读失败:", e); }); } @@ -217,6 +215,15 @@ const CommentReply = () => { })); setCommentList(mappedList); + + // 获取所有评论ID列表并标记已读(传入所有ID) + const allCommentIds = res.data.rows.map((item: any) => item.id); + + if (allCommentIds.length > 0) { + messageService.markAsRead('comment', allCommentIds).catch(e => { + console.error("标记评论已读失败:", e); + }); + } } } catch (e) { Taro.showToast({ diff --git a/src/other_pages/new_follow/index.tsx b/src/other_pages/new_follow/index.tsx index cfddbfb..61eec71 100644 --- a/src/other_pages/new_follow/index.tsx +++ b/src/other_pages/new_follow/index.tsx @@ -56,14 +56,12 @@ const NewFollow = () => { setFollowList(mappedList); - // 获取未读关注ID并标记已读 - const unreadFanIds = res.list - .filter((item: any) => item.is_read === 0) - .map((item: any) => item.id); + // 获取所有关注者ID列表并标记已读(传入所有ID,包括已读和未读) + const allFanIds = res.list.map((item: any) => item.id); - if (unreadFanIds.length > 0) { - // 使用统一接口标记已读 - messageService.markAsRead('follow', unreadFanIds).catch(e => { + if (allFanIds.length > 0) { + // 使用统一接口标记已读,传入所有关注者ID + messageService.markAsRead('follow', allFanIds).catch(e => { console.error("标记关注已读失败:", e); }); } @@ -164,6 +162,15 @@ const NewFollow = () => { })); setFollowList(mappedList); + + // 获取所有关注者ID列表并标记已读(传入所有ID) + const allFanIds = res.list.map((item: any) => item.id); + + if (allFanIds.length > 0) { + messageService.markAsRead('follow', allFanIds).catch(e => { + console.error("标记关注已读失败:", e); + }); + } } else { // 如果没有数据,设置为空数组以显示空状态 setFollowList([]); From 3ab647f7c668ff890889090fea370774c75a4a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E9=87=8E?= Date: Mon, 5 Jan 2026 21:26:02 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E4=BB=85=E4=B8=8A=E6=B5=B7=E5=9C=B0=E5=8C=BA=E5=8F=AF=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E3=80=81=E5=8F=91=E5=B8=83=E9=98=B2=E6=8A=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/PublishMenu/PublishMenu.tsx | 17 +++++++++++++++++ .../components/SelectStadium/SelectStadium.tsx | 9 ++++++++- .../components/SelectStadium/StadiumDetail.tsx | 13 ++++++++----- src/publish_pages/publishBall/index.tsx | 9 +++++++-- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/components/PublishMenu/PublishMenu.tsx b/src/components/PublishMenu/PublishMenu.tsx index 07f250c..98a5cd0 100644 --- a/src/components/PublishMenu/PublishMenu.tsx +++ b/src/components/PublishMenu/PublishMenu.tsx @@ -7,6 +7,8 @@ import { EvaluateCallback, EvaluateScene, } from "@/store/evaluateStore"; +import { useListState } from "@/store/listStore"; + import { navigateTo, redirectTo, navigateBack } from "@/utils/navigation"; import { requireLoginWithPhone } from "@/utils/helper"; import styles from "./index.module.scss"; @@ -24,6 +26,11 @@ const PublishMenu: React.FC = (props) => { const { onVisibleChange } = props; const [isVisible, setIsVisible] = useState(false); + const { + area + } = useListState(); + + // 使用 useEffect 监听 isVisible 变化,确保所有情况都能触发回调 useEffect(() => { onVisibleChange?.(isVisible); @@ -59,6 +66,16 @@ const PublishMenu: React.FC = (props) => { }); }; const handleMenuItemClick = (type: "individual" | "group" | "ai") => { + const [_, address] = area; + if (address !== '上海') { + (Taro as any).showModal({ + title: '提示', + content: '仅上海地区开放,您可加入社群或切换城市', + showCancel: false, + confirmText: '知道了' + }) + return; + } if (!userInfo.ntrp_level) { ntrpRef.current.show({ type: EvaluateScene.publish, diff --git a/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.tsx b/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.tsx index 73d5cac..307fb0e 100644 --- a/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.tsx +++ b/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.tsx @@ -106,8 +106,15 @@ const SelectStadium: React.FC = ({ }) setShowDetail(true) }, - fail: (err) => { + fail: (err: { errMsg: string }) => { console.error('选择位置失败:', err) + const { errMsg } = err || {}; + if (!errMsg.includes('fail cancel')) { + Taro.showToast({ + title: errMsg, + icon: "none", + }); + } } }) } diff --git a/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx b/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx index d60150c..2e4a2e6 100644 --- a/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx +++ b/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx @@ -145,12 +145,15 @@ const StadiumDetail = forwardRef(({ istance: null }) }, - fail: (err) => { + fail: (err: { errMsg: string }) => { console.error('选择位置失败:', err) - Taro.showToast({ - title: '位置选择失败', - icon: 'error' - }) + const { errMsg } = err || {}; + if (!errMsg.includes('fail cancel')) { + Taro.showToast({ + title: errMsg, + icon: "none", + }); + } } }) } diff --git a/src/publish_pages/publishBall/index.tsx b/src/publish_pages/publishBall/index.tsx index a4e2787..d0c5595 100644 --- a/src/publish_pages/publishBall/index.tsx +++ b/src/publish_pages/publishBall/index.tsx @@ -85,6 +85,7 @@ const PublishBall: React.FC = () => { defaultFormData, ]); const [checked, setChecked] = useState(true); + const [publishLoading, setPublishLoading] = useState(false); const [titleBar, setTitleBar] = useState("发布球局"); // 控制是否响应全局键盘(由具体输入框 focus/blur 控制) const [shouldReactToKeyboard, setShouldReactToKeyboard] = useState(false); @@ -372,9 +373,10 @@ const PublishBall: React.FC = () => { const { republish } = params || {}; if (activityType === "individual") { const isValid = validateFormData(formData[0]); - if (!isValid) { + if (!isValid || publishLoading) { return; } + setPublishLoading(true); const { activityInfo, descriptionInfo, @@ -435,13 +437,15 @@ const PublishBall: React.FC = () => { title: res.message, icon: "none", }); + setPublishLoading(false); } } if (activityType === "group") { const isValid = formData.every((item) => validateFormData(item)); - if (!isValid) { + if (!isValid || publishLoading) { return; } + setPublishLoading(true); if (checkAdjacentDataSame(formData)) { Taro.showToast({ title: "信息不可与前序场完全一致", @@ -505,6 +509,7 @@ const PublishBall: React.FC = () => { title: res.message, icon: "none", }); + setPublishLoading(false); } } }; From de8677c64cab21e44d8e4b151a97b4adae8f8486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E9=87=8E?= Date: Mon, 26 Jan 2026 22:13:52 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CommonPopup/index.module.scss | 3 ++- .../publishBall/components/SelectStadium/SelectStadium.scss | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/CommonPopup/index.module.scss b/src/components/CommonPopup/index.module.scss index 7357ba9..681b905 100644 --- a/src/components/CommonPopup/index.module.scss +++ b/src/components/CommonPopup/index.module.scss @@ -7,7 +7,8 @@ border-radius: 20px 20px 0 0 !important; } .common-popup__drag-handle-container { - position: position; + position: relative; + height: 0; } .common-popup__drag-handle { diff --git a/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.scss b/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.scss index 65253d3..6dbef8d 100644 --- a/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.scss +++ b/src/publish_pages/publishBall/components/SelectStadium/SelectStadium.scss @@ -9,7 +9,7 @@ flex-direction: column; overflow: hidden; padding-bottom: env(safe-area-inset-bottom); - + box-sizing: border-box; // 搜索区域 .search-section { background: #f5f5f5; From 4a6ac73ad77d2542b36a783e2d958cb14980a97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E9=87=8E?= Date: Mon, 26 Jan 2026 22:51:01 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E5=9F=9F=E9=95=BF=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TextareaTag/TextareaTag.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/TextareaTag/TextareaTag.tsx b/src/components/TextareaTag/TextareaTag.tsx index 484c009..e2b475d 100644 --- a/src/components/TextareaTag/TextareaTag.tsx +++ b/src/components/TextareaTag/TextareaTag.tsx @@ -29,8 +29,10 @@ const TextareaTag: React.FC = ({ // 处理文本输入变化 const handleTextChange = useCallback((val: string) => { console.log(val,'e.detail.value') - onChange({...value, description: val}) - }, [onChange]) + const maxAllowedLength = Math.floor(maxLength * 1.2) + const truncatedVal = val.length > maxAllowedLength ? val.slice(0, maxAllowedLength) : val + onChange({...value, description: truncatedVal}) + }, [onChange, maxLength, value]) // 处理标签选择变化 const handleTagChange = useCallback((selectedTags: string[]) => { From dade2e2491f1051e98c30886bdc7a396b64bcdae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E9=87=8E?= Date: Tue, 27 Jan 2026 22:15:28 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E9=A1=B5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/publish_pages/publishBall/index.config.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/publish_pages/publishBall/index.config.ts b/src/publish_pages/publishBall/index.config.ts index 74ddf4b..8ef482a 100644 --- a/src/publish_pages/publishBall/index.config.ts +++ b/src/publish_pages/publishBall/index.config.ts @@ -1,3 +1,5 @@ export default definePageConfig({ - navigationStyle: 'custom' -}) + navigationStyle: 'custom', + // 禁止原生页面滚动,改用内部自定义滚动容器,避免顶部/底部回弹后中间无法继续滚动的问题 + disableScroll: true, +}) From 6d576540051e941f8923d72477fc4833bdc8fefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Thu, 29 Jan 2026 22:56:33 +0800 Subject: [PATCH 07/11] 1 --- project.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.config.json b/project.config.json index 145631b..fcd025f 100644 --- a/project.config.json +++ b/project.config.json @@ -2,7 +2,7 @@ "miniprogramRoot": "dist/", "projectname": "playBallTogether", "description": "playBallTogether", - "appid": "wx815b533167eb7b53", + "appid": "wx915ecf6c01bea4ec", "setting": { "urlCheck": true, "es6": true, From 1cbec87f7769e8a5d2061d63805b2a759bb3e627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=91=9E?= Date: Sun, 1 Feb 2026 16:12:04 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0banneer=E5=8D=A0?= =?UTF-8?q?=E4=BD=8D=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.config.ts | 1 + src/container/listContainer/index.tsx | 33 ++++++ src/other_pages/bannerDetail/index.config.ts | 8 ++ src/other_pages/bannerDetail/index.scss | 16 +++ src/other_pages/bannerDetail/index.tsx | 36 ++++++ src/store/listStore.ts | 111 +++++++++++++++---- 6 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 src/other_pages/bannerDetail/index.config.ts create mode 100644 src/other_pages/bannerDetail/index.scss create mode 100644 src/other_pages/bannerDetail/index.tsx diff --git a/src/app.config.ts b/src/app.config.ts index 5b5af4f..9816e39 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -57,6 +57,7 @@ export default defineAppConfig({ "ntrp-evaluate/index", // NTRP评估页 "enable_notification/index", // 开启消息通知 "emptyState/index", // 空状态页面 + "bannerDetail/index", // Banner 图片详情页 ], }, ], diff --git a/src/container/listContainer/index.tsx b/src/container/listContainer/index.tsx index ec5a412..a75bf0e 100644 --- a/src/container/listContainer/index.tsx +++ b/src/container/listContainer/index.tsx @@ -3,6 +3,7 @@ import ListCard from "@/components/ListCard"; import ListLoadError from "@/components/ListLoadError"; import ListCardSkeleton from "@/components/ListCardSkeleton"; import { useReachBottom } from "@tarojs/taro"; +import Taro from "@tarojs/taro"; import { useUserInfo, useUserActions, useLastTestResult } from "@/store/userStore"; import { NTRPTestEntryCard } from "@/components"; import { EvaluateScene } from "@/store/evaluateStore"; @@ -158,6 +159,35 @@ const ListContainer = (props) => { [evaluateFlag, data, hasTestInLastMonth, showNumber] ); + // 渲染 banner 卡片 + const renderBanner = (item, index) => { + if (!item?.banner_image_url) return null; + return ( + + { + const target = item.banner_detail_url; + if (target) { + (Taro as any).navigateTo({ + url: `/other_pages/bannerDetail/index?img=${encodeURIComponent(target)}`, + }); + } + }} + /> + + ); + }; + // 渲染列表 const renderList = () => { // 请求数据为空 @@ -181,6 +211,9 @@ const ListContainer = (props) => { return ( <> {memoizedList.map((match, index) => { + if (match.type === "banner") { + return renderBanner(match, index); + } if (match.type === "evaluateCard") { return ( diff --git a/src/other_pages/bannerDetail/index.config.ts b/src/other_pages/bannerDetail/index.config.ts new file mode 100644 index 0000000..7d94eab --- /dev/null +++ b/src/other_pages/bannerDetail/index.config.ts @@ -0,0 +1,8 @@ +export default definePageConfig({ + navigationBarTitleText: '', + navigationStyle: 'custom', + navigationBarBackgroundColor: '#FFFFFF', + backgroundColor: '#FFFFFF', +}); + + diff --git a/src/other_pages/bannerDetail/index.scss b/src/other_pages/bannerDetail/index.scss new file mode 100644 index 0000000..e29887d --- /dev/null +++ b/src/other_pages/bannerDetail/index.scss @@ -0,0 +1,16 @@ +.banner_detail_page { + min-height: 100vh; + background: #ffffff; +} + +.banner_detail_content { + padding: 12px; +} + +.banner_detail_image { + width: 100%; + border-radius: 12px; + display: block; +} + + diff --git a/src/other_pages/bannerDetail/index.tsx b/src/other_pages/bannerDetail/index.tsx new file mode 100644 index 0000000..cc80521 --- /dev/null +++ b/src/other_pages/bannerDetail/index.tsx @@ -0,0 +1,36 @@ +import { useEffect, useState } from 'react'; +import { View, Image } from '@tarojs/components'; +import Taro from '@tarojs/taro'; +import { GeneralNavbar } from '@/components'; +import './index.scss'; + +function Index() { + const [imgUrl, setImgUrl] = useState(''); + + useEffect(() => { + const instance = (Taro as any).getCurrentInstance?.(); + const params = instance?.router?.params || {}; + const url = params?.img ? decodeURIComponent(params.img) : ''; + setImgUrl(url); + }, []); + + return ( + + + + {imgUrl ? ( + + ) : null} + + + ); +} + +export default Index; + + diff --git a/src/store/listStore.ts b/src/store/listStore.ts index 40616d7..046e9a2 100644 --- a/src/store/listStore.ts +++ b/src/store/listStore.ts @@ -11,6 +11,7 @@ import { getCityQrCode, getDistricts, } from "../services/listApi"; +import commonApi from "../services/commonApi"; import { ListActions, IFilterOptions, @@ -18,6 +19,27 @@ import { IPayload, } from "../../types/list/types"; +// 将 banner 按索引插入到 rows 的工具方法 +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]; + 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) { return dataTree.map((item) => { const { children, ...rest } = item; @@ -296,7 +318,31 @@ export const useListStore = create()((set, get) => ({ } } - const resData = (await fetchFn(reqParams)) || {}; + // 并发请求:列表接口 + 字典接口(仅第一页且非追加时插入 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)) || {}; + } + const { data = {}, code } = resData; if (code !== 0) { setListData({ @@ -308,7 +354,14 @@ export const useListStore = create()((set, get) => ({ }); return Promise.reject(new Error('获取数据失败')); } - const { count, rows } = data; + const { count } = data; + let { rows } = data as any; + + // 将 banner 插入到指定位置(仅第一页且非追加) + if (shouldInsertBanner && Array.isArray(rows) && dictData) { + rows = insertBannersToRows(rows, dictData); + } + setListData({ error: '', data: rows || [], @@ -344,24 +397,30 @@ export const useListStore = create()((set, get) => ({ try { const searchParams = getSearchParams() || {}; + const keys = "bannerListImage,bannerDetailImage,bannerListIndex"; - // 调用常规列表接口 - const listParams = { - ...searchParams, - order: searchParams.order || "distance", - }; - const listRes = await getGamesList(listParams); - - // 调用智能排序列表接口 - const integrateParams = { - ...searchParams, - order: "", - seachOption: { - ...searchParams.seachOption, - isRefresh: true, - }, - }; - const integrateRes = await getGamesIntegrateList(integrateParams); + // 并发请求:常规列表、智能排序列表、字典 + const [listResSettled, integrateResSettled, dictSettled] = await Promise.allSettled([ + getGamesList({ + ...searchParams, + order: searchParams.order || "distance", + }), + getGamesIntegrateList({ + ...searchParams, + order: "", + seachOption: { + ...searchParams.seachOption, + 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; @@ -369,7 +428,12 @@ export const useListStore = create()((set, get) => ({ const isIntegrate = distanceQuickFilter?.order === "0"; if (listRes?.code === 0 && listRes?.data) { - const { count, rows } = 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({ @@ -383,7 +447,12 @@ export const useListStore = create()((set, get) => ({ } if (integrateRes?.code === 0 && integrateRes?.data) { - const { count, rows, recommendList } = 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({ From 8abf6e6f2b78f03f62b397c4016854ede03f6067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Sun, 1 Feb 2026 18:46:30 +0800 Subject: [PATCH 09/11] 1 --- src/app.scss | 2 +- src/config/api.ts | 2 +- src/game_pages/detail/components/Participants/index.tsx | 2 +- src/user_pages/setTransactionPassword/index.scss | 2 +- src/user_pages/validPhone/index.scss | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app.scss b/src/app.scss index 9cb3e4f..58ee657 100644 --- a/src/app.scss +++ b/src/app.scss @@ -21,6 +21,6 @@ page { font-family: "Quicksand"; // 注意:此路径来自 @/config/api.ts 中的 OSS_BASE_URL 配置 // 如需修改,请更新配置文件中的 OSS_BASE_URL - src: url("https://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/other/57dc951f-f10e-45b7-9157-0b1e468187fd.ttf") format("truetype"); + src: url("https://youchang2026.oss-cn-shanghai.aliyuncs.com/front/ball/other/57dc951f-f10e-45b7-9157-0b1e468187fd.ttf") format("truetype"); font-display: swap; } \ No newline at end of file diff --git a/src/config/api.ts b/src/config/api.ts index e7d494b..262666c 100644 --- a/src/config/api.ts +++ b/src/config/api.ts @@ -1,7 +1,7 @@ import envConfig from './env'// API配置 // OSS 基础路径配置 -export const OSS_BASE_URL = 'https://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball' +export const OSS_BASE_URL = 'https://youchang2026.oss-cn-shanghai.aliyuncs.com/front/ball' export const API_CONFIG = { // 基础URL diff --git a/src/game_pages/detail/components/Participants/index.tsx b/src/game_pages/detail/components/Participants/index.tsx index bc2ec8e..56e3e10 100644 --- a/src/game_pages/detail/components/Participants/index.tsx +++ b/src/game_pages/detail/components/Participants/index.tsx @@ -85,7 +85,7 @@ export default function Participants(props) { // id: 18, // nickname: "小猫开刀削面店往猫毛里面下面条", // avatar_url: - // "https://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/d284060f-248b-4d58-a153-4d37c0ca77c8.jpg", + // "https://youchang2026.oss-cn-shanghai.aliyuncs.com/front/ball/images/d284060f-248b-4d58-a153-4d37c0ca77c8.jpg", // phone: "18513125687", // ntrp_level: "1.5", // }, diff --git a/src/user_pages/setTransactionPassword/index.scss b/src/user_pages/setTransactionPassword/index.scss index 646958d..eaa59d8 100644 --- a/src/user_pages/setTransactionPassword/index.scss +++ b/src/user_pages/setTransactionPassword/index.scss @@ -76,7 +76,7 @@ } .btn { - width: 78px; + width: 90px; height: 24px; border: 1px solid rgba(0, 0, 0, 0.06); display: flex; diff --git a/src/user_pages/validPhone/index.scss b/src/user_pages/validPhone/index.scss index 6224b72..08afa60 100644 --- a/src/user_pages/validPhone/index.scss +++ b/src/user_pages/validPhone/index.scss @@ -64,7 +64,7 @@ } .btn { - width: 78px; + width: 90px; height: 24px; border: 1px solid rgba(0, 0, 0, 0.06); display: flex; From 4c75368fe8127dd3312bd5a73c14b46eba9f3d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=91=9E?= Date: Sun, 1 Feb 2026 23:37:31 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E4=BC=98=E5=8C=96banner=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main_pages/index.tsx | 7 ++++ src/store/dictionaryStore.ts | 29 ++++++++++++++++ src/store/listStore.ts | 64 ++++++++---------------------------- 3 files changed, 50 insertions(+), 50 deletions(-) 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({ From ee579df16204ef7c5b34399d97e64c3414a74583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E9=87=8E?= Date: Sun, 1 Feb 2026 23:56:47 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E5=BC=B9=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SelectStadium/StadiumDetail.tsx | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx b/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx index 2e4a2e6..dcbf857 100644 --- a/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx +++ b/src/publish_pages/publishBall/components/SelectStadium/StadiumDetail.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback, forwardRef, useImperativeHandle, useEffect } from 'react' +import React, { useState, useCallback, forwardRef, useImperativeHandle } from 'react' import Taro from '@tarojs/taro' import { View, Text, Image, ScrollView } from '@tarojs/components' import images from '@/config/images' @@ -70,6 +70,7 @@ const StadiumDetail = forwardRef(({ onAnyInput }, ref) => { const [openPicker, setOpenPicker] = useState(false); + const [scrollTop, setScrollTop] = useState(0); const { getDictionaryValue } = useDictionaryActions() const court_type = getDictionaryValue('court_type') || [] const court_surface = getDictionaryValue('court_surface') || [] @@ -170,14 +171,27 @@ const StadiumDetail = forwardRef(({ + const changeTextarea = (value) => { + if (value) { + // 先滚动到底部 + setScrollTop(scrollTop ? scrollTop + 1 : 9999); + // 使用 setTimeout 确保滚动后再更新 openPicker + } + } + const changePicker = (value) => { - setOpenPicker(value) + setOpenPicker(value); } console.log(stadium,'stadiumstadium'); return ( - + {/* 已选球场 */} (({ updateFormData(item.prop, value)} - onBlur={() => changePicker(false)} - onFocus={() => changePicker(true)} + onChange={(value) => { + changeTextarea(true) + updateFormData(item.prop, value) + }} + // onBlur={() => changeTextarea(false)} + onFocus={() => changeTextarea(true)} placeholder='有其他场地信息可备注' options={(item.options || []).map((o) => ({ label: o, value: o }))} />