Merge branch 'master' of http://git.bimwe.com/tennis/mini-programs
This commit is contained in:
@@ -104,7 +104,12 @@ const NTRPEvaluatePopup = (props: NTRPEvaluatePopupProps, ref) => {
|
|||||||
async function getNtrp() {
|
async function getNtrp() {
|
||||||
const res = await evaluateService.getLastResult();
|
const res = await evaluateService.getLastResult();
|
||||||
if (res.code === 0 && res.data.has_ntrp_level) {
|
if (res.code === 0 && res.data.has_ntrp_level) {
|
||||||
setNtrp(res.data.user_ntrp_level);
|
const match = res.data.user_ntrp_level.match(/-?\d+(\.\d+)?/);
|
||||||
|
if (!match) {
|
||||||
|
setNtrp("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setNtrp(match[0] as string);
|
||||||
} else {
|
} else {
|
||||||
setNtrp("");
|
setNtrp("");
|
||||||
}
|
}
|
||||||
@@ -128,7 +133,7 @@ const NTRPEvaluatePopup = (props: NTRPEvaluatePopupProps, ref) => {
|
|||||||
title: "NTRP水平修改成功",
|
title: "NTRP水平修改成功",
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
evaCallback.next(true);
|
evaCallback.next({ flag: true, score: String(ntrp) });
|
||||||
handleClose();
|
handleClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useState, useEffect, useCallback, memo } from "react";
|
||||||
import { View, Image, Text } from "@tarojs/components";
|
import { View, Image, Text } from "@tarojs/components";
|
||||||
import Taro from "@tarojs/taro";
|
import Taro from "@tarojs/taro";
|
||||||
import { useUserInfo, useUserActions } from "@/store/userStore";
|
import { useUserInfo, useUserActions } from "@/store/userStore";
|
||||||
// import { getCurrentFullPath } from "@/utils";
|
// import { getCurrentFullPath } from "@/utils";
|
||||||
|
import evaluateService, { StageType } from "@/services/evaluateService";
|
||||||
import DocCopy from "@/static/ntrp/ntrp_doc_copy.svg";
|
import DocCopy from "@/static/ntrp/ntrp_doc_copy.svg";
|
||||||
import ArrowRight from "@/static/ntrp/ntrp_arrow_right_color.svg";
|
import ArrowRight from "@/static/ntrp/ntrp_arrow_right_color.svg";
|
||||||
import {
|
import {
|
||||||
@@ -16,54 +17,96 @@ function NTRPTestEntryCard(props: {
|
|||||||
type: EvaluateScene;
|
type: EvaluateScene;
|
||||||
evaluateCallback?: EvaluateCallback;
|
evaluateCallback?: EvaluateCallback;
|
||||||
}) {
|
}) {
|
||||||
|
const [testFlag, setTestFlag] = useState(false);
|
||||||
const { type, evaluateCallback } = props;
|
const { type, evaluateCallback } = props;
|
||||||
const userInfo = useUserInfo();
|
const userInfo = useUserInfo();
|
||||||
const { setCallback } = useEvaluate();
|
const { setCallback } = useEvaluate();
|
||||||
// const { fetchUserInfo } = useUserActions()
|
const { fetchUserInfo } = useUserActions();
|
||||||
|
|
||||||
// useEffect(() => {
|
console.log(userInfo);
|
||||||
// fetchUserInfo()
|
|
||||||
// }, [])
|
|
||||||
|
|
||||||
function handleTest() {
|
useEffect(() => {
|
||||||
switch (type) {
|
if (!userInfo.id) {
|
||||||
case (EvaluateScene.list, EvaluateScene.share):
|
fetchUserInfo();
|
||||||
setCallback({
|
|
||||||
type,
|
|
||||||
next: () => {
|
|
||||||
Taro.redirectTo({ url: "/main_pages/index" });
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
Taro.redirectTo({ url: "/main_pages/index" });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
case (EvaluateScene.detail, EvaluateScene.publish):
|
|
||||||
setCallback(evaluateCallback as EvaluateCallback);
|
|
||||||
case (EvaluateScene.user, EvaluateScene.userEdit):
|
|
||||||
setCallback({
|
|
||||||
type,
|
|
||||||
next: () => {
|
|
||||||
Taro.redirectTo({ url: "/main_pages/index" });
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
Taro.redirectTo({ url: "/user_pages/myself/index" });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
default:
|
|
||||||
setCallback({
|
|
||||||
type,
|
|
||||||
next: () => {
|
|
||||||
Taro.redirectTo({ url: "/main_pages/index" });
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
Taro.redirectTo({ url: "/main_pages/index" });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Taro.redirectTo({
|
evaluateService.getLastResult().then((res) => {
|
||||||
url: `/other_pages/ntrp-evaluate/index?stage=test`,
|
setTestFlag(res.code === 0 && res.data.has_ntrp_level);
|
||||||
});
|
});
|
||||||
}
|
}, [userInfo.id]);
|
||||||
|
|
||||||
|
const handleTest = useCallback(
|
||||||
|
function () {
|
||||||
|
switch (type) {
|
||||||
|
case EvaluateScene.list:
|
||||||
|
setCallback({
|
||||||
|
type,
|
||||||
|
next: () => {
|
||||||
|
Taro.redirectTo({ url: "/game_pages/list/index" });
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
// Taro.redirectTo({ url: "/game_pages/list/index" });
|
||||||
|
Taro.navigateBack();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case EvaluateScene.share:
|
||||||
|
setCallback({
|
||||||
|
type,
|
||||||
|
next: () => {
|
||||||
|
Taro.redirectTo({ url: "/main_pages/index" });
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
Taro.redirectTo({ url: "/main_pages/index" });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case EvaluateScene.detail:
|
||||||
|
case EvaluateScene.publish:
|
||||||
|
setCallback(evaluateCallback as EvaluateCallback);
|
||||||
|
break;
|
||||||
|
case EvaluateScene.user:
|
||||||
|
setCallback({
|
||||||
|
type,
|
||||||
|
next: () => {
|
||||||
|
Taro.redirectTo({ url: "/main_pages/index" });
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
// Taro.redirectTo({ url: "/user_pages/myself/index" });
|
||||||
|
Taro.navigateBack();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case EvaluateScene.userEdit:
|
||||||
|
setCallback({
|
||||||
|
type,
|
||||||
|
next: () => {
|
||||||
|
Taro.redirectTo({ url: "/game_pages/list/index" });
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
// Taro.redirectTo({ url: "/user_pages/edit/index" });
|
||||||
|
Taro.navigateBack();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setCallback({
|
||||||
|
type,
|
||||||
|
next: () => {
|
||||||
|
Taro.redirectTo({ url: "/main_pages/index" });
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
Taro.redirectTo({ url: "/main_pages/index" });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: `/other_pages/ntrp-evaluate/index?stage=${
|
||||||
|
testFlag ? StageType.INTRO : StageType.TEST
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[setCallback]
|
||||||
|
);
|
||||||
|
|
||||||
return type === EvaluateScene.list ? (
|
return type === EvaluateScene.list ? (
|
||||||
<View className={styles.higher} onClick={handleTest}>
|
<View className={styles.higher} onClick={handleTest}>
|
||||||
@@ -131,4 +174,5 @@ function NTRPTestEntryCard(props: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NTRPTestEntryCard;
|
export default memo(NTRPTestEntryCard);
|
||||||
|
// export default NTRPTestEntryCard;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export interface PublishMenuProps {
|
|||||||
const PublishMenu: React.FC<PublishMenuProps> = (props) => {
|
const PublishMenu: React.FC<PublishMenuProps> = (props) => {
|
||||||
const { onVisibleChange } = props;
|
const { onVisibleChange } = props;
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
||||||
// 使用 useEffect 监听 isVisible 变化,确保所有情况都能触发回调
|
// 使用 useEffect 监听 isVisible 变化,确保所有情况都能触发回调
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onVisibleChange?.(isVisible);
|
onVisibleChange?.(isVisible);
|
||||||
@@ -55,7 +55,7 @@ const PublishMenu: React.FC<PublishMenuProps> = (props) => {
|
|||||||
if (!userInfo.ntrp_level) {
|
if (!userInfo.ntrp_level) {
|
||||||
ntrpRef.current.show({
|
ntrpRef.current.show({
|
||||||
type: EvaluateScene.publish,
|
type: EvaluateScene.publish,
|
||||||
next: (flag) => {
|
next: ({ flag }) => {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
handleMenuClick(type);
|
handleMenuClick(type);
|
||||||
} else if (type === "ai") {
|
} else if (type === "ai") {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { setStorage, getStorage } from "@/store/storage";
|
|||||||
import { NTRPTestEntryCard } from "@/components";
|
import { NTRPTestEntryCard } from "@/components";
|
||||||
import { EvaluateScene } from "@/store/evaluateStore";
|
import { EvaluateScene } from "@/store/evaluateStore";
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import { useRef, useEffect, useState } from "react";
|
import { useRef, useEffect, useState, useMemo } from "react";
|
||||||
|
|
||||||
const ListContainer = (props) => {
|
const ListContainer = (props) => {
|
||||||
const {
|
const {
|
||||||
@@ -26,6 +26,7 @@ const ListContainer = (props) => {
|
|||||||
style,
|
style,
|
||||||
collapse = false,
|
collapse = false,
|
||||||
defaultShowNum,
|
defaultShowNum,
|
||||||
|
evaluateFlag,
|
||||||
} = props;
|
} = props;
|
||||||
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const loadingStartTimeRef = useRef<number | null>(null);
|
const loadingStartTimeRef = useRef<number | null>(null);
|
||||||
@@ -47,19 +48,17 @@ const ListContainer = (props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowNumber(
|
setShowNumber(() => {
|
||||||
() => {
|
return defaultShowNum === undefined ? data?.length : defaultShowNum;
|
||||||
return defaultShowNum === undefined ? data?.length : defaultShowNum
|
});
|
||||||
|
}, [data]);
|
||||||
})
|
|
||||||
}, [data])
|
|
||||||
|
|
||||||
// 控制骨架屏显示逻辑
|
// 控制骨架屏显示逻辑
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
// 开始加载时记录时间
|
// 开始加载时记录时间
|
||||||
loadingStartTimeRef.current = Date.now();
|
loadingStartTimeRef.current = Date.now();
|
||||||
|
|
||||||
// 延迟 300ms 后再显示骨架屏
|
// 延迟 300ms 后再显示骨架屏
|
||||||
skeletonTimerRef.current = setTimeout(() => {
|
skeletonTimerRef.current = setTimeout(() => {
|
||||||
setShowSkeleton(true);
|
setShowSkeleton(true);
|
||||||
@@ -102,6 +101,7 @@ const ListContainer = (props) => {
|
|||||||
|
|
||||||
// 对于没有ntrp等级的用户每个月展示一次, 插在第三个位置
|
// 对于没有ntrp等级的用户每个月展示一次, 插在第三个位置
|
||||||
function insertEvaluateCard(list) {
|
function insertEvaluateCard(list) {
|
||||||
|
if (!evaluateFlag) return list;
|
||||||
if (!list || list.length === 0) {
|
if (!list || list.length === 0) {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -122,6 +122,11 @@ const ListContainer = (props) => {
|
|||||||
return [item1, item2, item3, { type: "evaluateCard" }, ...rest];
|
return [item1, item2, item3, { type: "evaluateCard" }, ...rest];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const memoizedList = useMemo(
|
||||||
|
() => insertEvaluateCard(data),
|
||||||
|
[evaluateFlag, data, userInfo.ntrp_level]
|
||||||
|
);
|
||||||
|
|
||||||
// 渲染列表
|
// 渲染列表
|
||||||
const renderList = (list) => {
|
const renderList = (list) => {
|
||||||
// 请求数据为空
|
// 请求数据为空
|
||||||
@@ -137,12 +142,12 @@ const ListContainer = (props) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
showNumber !== undefined && (list = list.slice(0, showNumber))
|
showNumber !== undefined && (list = list.slice(0, showNumber));
|
||||||
|
|
||||||
// 渲染数据
|
// 渲染数据
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{insertEvaluateCard(list).map((match, index) => {
|
{memoizedList.map((match, index) => {
|
||||||
if (match.type === "evaluateCard") {
|
if (match.type === "evaluateCard") {
|
||||||
return (
|
return (
|
||||||
<NTRPTestEntryCard key="evaluate" type={EvaluateScene.list} />
|
<NTRPTestEntryCard key="evaluate" type={EvaluateScene.list} />
|
||||||
@@ -164,20 +169,33 @@ const ListContainer = (props) => {
|
|||||||
</View>
|
</View>
|
||||||
{renderList(recommendList)} */}
|
{renderList(recommendList)} */}
|
||||||
{/* 到底了 */}
|
{/* 到底了 */}
|
||||||
{collapse ?
|
{collapse ? (
|
||||||
data?.length > defaultShowNum ?
|
data?.length > defaultShowNum ? (
|
||||||
data?.length > showNumber ?
|
data?.length > showNumber ? (
|
||||||
<View className="collapse-btn fold" onClick={() => { setShowNumber(data?.length) }}>
|
<View
|
||||||
|
className="collapse-btn fold"
|
||||||
|
onClick={() => {
|
||||||
|
setShowNumber(data?.length);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Text>更多球局</Text>
|
<Text>更多球局</Text>
|
||||||
<Image src={require("@/static/userInfo/fold.svg")}></Image>
|
<Image src={require("@/static/userInfo/fold.svg")}></Image>
|
||||||
</View> :
|
</View>
|
||||||
<View className="collapse-btn" onClick={() => { setShowNumber(defaultShowNum) }}>
|
) : (
|
||||||
|
<View
|
||||||
|
className="collapse-btn"
|
||||||
|
onClick={() => {
|
||||||
|
setShowNumber(defaultShowNum);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Text>收起</Text>
|
<Text>收起</Text>
|
||||||
<Image src={require("@/static/userInfo/fold.svg")}></Image>
|
<Image src={require("@/static/userInfo/fold.svg")}></Image>
|
||||||
</View>
|
</View>
|
||||||
:
|
)
|
||||||
null
|
) : null
|
||||||
: data?.length > 0 && <View className="bottomTextWrapper">到底了</View>}
|
) : (
|
||||||
|
data?.length > 0 && <View className="bottomTextWrapper">到底了</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -204,6 +204,9 @@ export default function GameInfo(props) {
|
|||||||
// hide business msg
|
// hide business msg
|
||||||
showLocation
|
showLocation
|
||||||
theme="dark"
|
theme="dark"
|
||||||
|
enableScroll={false}
|
||||||
|
enableZoom={false}
|
||||||
|
onTap={openMap}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { View, Text } from "@tarojs/components";
|
import { View, Text } from "@tarojs/components";
|
||||||
import { genNTRPRequirementText } from "../../utils/helper";
|
import { genNTRPRequirementText } from "@/utils/helper";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
// 玩法要求
|
// 玩法要求
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { calculateDistance } from "@/utils";
|
|||||||
import { useUserInfo } from "@/store/userStore";
|
import { useUserInfo } from "@/store/userStore";
|
||||||
import * as LoginService from "@/services/loginService";
|
import * as LoginService from "@/services/loginService";
|
||||||
import img from "@/config/images";
|
import img from "@/config/images";
|
||||||
import { navto } from "../../utils/helper";
|
import { navto } from "@/utils/helper";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
function genRecommendGames(games, location, avatar) {
|
function genRecommendGames(games, location, avatar) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import WechatLogo from "@/static/detail/wechat_icon.svg";
|
|||||||
// import WechatTimeline from "@/static/detail/wechat_timeline.svg";
|
// import WechatTimeline from "@/static/detail/wechat_timeline.svg";
|
||||||
import LinkIcon from "@/static/detail/link.svg";
|
import LinkIcon from "@/static/detail/link.svg";
|
||||||
import CrossIcon from "@/static/detail/cross.svg";
|
import CrossIcon from "@/static/detail/cross.svg";
|
||||||
import { genNTRPRequirementText, navto } from "../../utils/helper";
|
import { genNTRPRequirementText, navto } from "@/utils/helper";
|
||||||
import { DayOfWeekMap } from "../../config";
|
import { DayOfWeekMap } from "../../config";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@
|
|||||||
&.disabled > .sticky-bottom-bar-join-game {
|
&.disabled > .sticky-bottom-bar-join-game {
|
||||||
background: #b4b4b4;
|
background: #b4b4b4;
|
||||||
color: rgba(60, 60, 67, 0.6);
|
color: rgba(60, 60, 67, 0.6);
|
||||||
pointer-events: none;
|
// pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticky-bottom-bar-join-game {
|
.sticky-bottom-bar-join-game {
|
||||||
@@ -147,6 +147,7 @@
|
|||||||
font-feature-settings: "liga" off, "clig" off;
|
font-feature-settings: "liga" off, "clig" off;
|
||||||
font-family: "DingTalk JinBuTi";
|
font-family: "DingTalk JinBuTi";
|
||||||
// font-style: italic;
|
// font-style: italic;
|
||||||
|
font-style: normal;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { MATCH_STATUS, IsSubstituteSupported } from "@/services/detailService";
|
|||||||
import { GameManagePopup, NTRPEvaluatePopup } from "@/components";
|
import { GameManagePopup, NTRPEvaluatePopup } from "@/components";
|
||||||
import img from "@/config/images";
|
import img from "@/config/images";
|
||||||
import RMB_ICON from "@/static/detail/rmb.svg";
|
import RMB_ICON from "@/static/detail/rmb.svg";
|
||||||
import { toast, navto } from "../../utils/helper";
|
import { toast, navto } from "@/utils/helper";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
function isFull(counts) {
|
function isFull(counts) {
|
||||||
@@ -36,6 +36,34 @@ function isFull(counts) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function matchNtrpRequestment(
|
||||||
|
target?: string,
|
||||||
|
min?: string,
|
||||||
|
max?: string
|
||||||
|
): boolean {
|
||||||
|
// 目标值为空或 undefined
|
||||||
|
if (!target?.trim()) return true;
|
||||||
|
|
||||||
|
// 提取目标值中的第一个数字
|
||||||
|
const match = target.match(/-?\d+(\.\d+)?/);
|
||||||
|
if (!match) return true;
|
||||||
|
|
||||||
|
const value = parseFloat(match[0]);
|
||||||
|
const minNum = min !== undefined ? parseFloat(min) : undefined;
|
||||||
|
const maxNum = max !== undefined ? parseFloat(max) : undefined;
|
||||||
|
|
||||||
|
// min 和 max 都未定义 → 直接通过
|
||||||
|
if (minNum === undefined && maxNum === undefined) return true;
|
||||||
|
|
||||||
|
// min = max 或只有一边 undefined → 参考值判断,包含端点
|
||||||
|
if (minNum === undefined || maxNum === undefined || minNum === maxNum) {
|
||||||
|
return value >= (minNum ?? maxNum!);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正常区间判断,包含端点
|
||||||
|
return value >= minNum && value <= maxNum;
|
||||||
|
}
|
||||||
|
|
||||||
// 底部操作栏
|
// 底部操作栏
|
||||||
export default function StickyButton(props) {
|
export default function StickyButton(props) {
|
||||||
const {
|
const {
|
||||||
@@ -45,6 +73,7 @@ export default function StickyButton(props) {
|
|||||||
onStatusChange,
|
onStatusChange,
|
||||||
handleAddComment,
|
handleAddComment,
|
||||||
getCommentCount,
|
getCommentCount,
|
||||||
|
currentUserInfo,
|
||||||
} = props;
|
} = props;
|
||||||
const [commentCount, setCommentCount] = useState(0);
|
const [commentCount, setCommentCount] = useState(0);
|
||||||
const ntrpRef = useRef<{
|
const ntrpRef = useRef<{
|
||||||
@@ -58,14 +87,28 @@ export default function StickyButton(props) {
|
|||||||
start_time,
|
start_time,
|
||||||
end_time,
|
end_time,
|
||||||
is_organizer,
|
is_organizer,
|
||||||
|
skill_level_max,
|
||||||
|
skill_level_min,
|
||||||
} = detail || {};
|
} = detail || {};
|
||||||
|
|
||||||
|
const { ntrp_level } = currentUserInfo || {};
|
||||||
|
|
||||||
|
const matchNtrpReq = matchNtrpRequestment(
|
||||||
|
ntrp_level,
|
||||||
|
skill_level_min,
|
||||||
|
skill_level_max
|
||||||
|
);
|
||||||
|
|
||||||
const gameManageRef = useRef();
|
const gameManageRef = useRef();
|
||||||
|
|
||||||
function handleSelfEvaluate() {
|
function handleSelfEvaluate() {
|
||||||
ntrpRef?.current?.show({
|
ntrpRef?.current?.show({
|
||||||
type: EvaluateScene.detail,
|
type: EvaluateScene.detail,
|
||||||
next: (flag) => {
|
next: ({ flag, score }) => {
|
||||||
|
if (!matchNtrpRequestment(score, skill_level_min, skill_level_max)) {
|
||||||
|
toast("您当前不符合此球局NTRP水平要求,去看看其他活动吧~");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (flag) {
|
if (flag) {
|
||||||
Taro.navigateTo({
|
Taro.navigateTo({
|
||||||
url: `/order_pages/orderDetail/index?gameId=${id}`,
|
url: `/order_pages/orderDetail/index?gameId=${id}`,
|
||||||
@@ -123,31 +166,31 @@ export default function StickyButton(props) {
|
|||||||
return {
|
return {
|
||||||
text: "活动已取消",
|
text: "活动已取消",
|
||||||
available: false,
|
available: false,
|
||||||
// action: () => toast("活动已取消"),
|
action: () => toast("活动已取消,去看看其他活动吧~"),
|
||||||
};
|
};
|
||||||
} else if (MATCH_STATUS.FINISHED === match_status) {
|
} else if (MATCH_STATUS.FINISHED === match_status) {
|
||||||
return {
|
return {
|
||||||
text: "活动已结束",
|
text: "活动已结束",
|
||||||
available: false,
|
available: false,
|
||||||
// action: () => toast("活动已取消"),
|
action: () => toast("活动已结束,去看看其他活动吧~"),
|
||||||
};
|
};
|
||||||
} else if (dayjs(end_time).isBefore(dayjs())) {
|
} else if (dayjs(end_time).isBefore(dayjs())) {
|
||||||
return {
|
return {
|
||||||
text: "活动已结束",
|
text: "活动已结束",
|
||||||
available: false,
|
available: false,
|
||||||
// action: () => toast("活动已结束"),
|
action: () => toast("活动已结束,去看看其他活动吧~"),
|
||||||
};
|
};
|
||||||
} else if (dayjs(start_time).isBefore(dayjs())) {
|
} else if (dayjs(start_time).isBefore(dayjs())) {
|
||||||
return {
|
return {
|
||||||
text: "活动已开始",
|
text: "活动已开始",
|
||||||
available: false,
|
available: false,
|
||||||
// action: () => toast("活动已开始"),
|
action: () => toast("活动已开始,去看看其他活动吧~"),
|
||||||
};
|
};
|
||||||
} else if (isFull(detail)) {
|
} else if (isFull(detail)) {
|
||||||
return {
|
return {
|
||||||
text: "活动已满员",
|
text: "活动已满员",
|
||||||
available: false,
|
available: false,
|
||||||
// action: () => toast("活动已满员"),
|
action: () => toast("活动已满员,去看看其他活动吧~"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (waiting_start) {
|
if (waiting_start) {
|
||||||
@@ -159,7 +202,7 @@ export default function StickyButton(props) {
|
|||||||
<Text className={styles.btnText}>已加入</Text>
|
<Text className={styles.btnText}>已加入</Text>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
action: () => toast("已加入"),
|
action: () => toast("您已参与了本次活动"),
|
||||||
};
|
};
|
||||||
} else if (is_substituting) {
|
} else if (is_substituting) {
|
||||||
return {
|
return {
|
||||||
@@ -170,7 +213,7 @@ export default function StickyButton(props) {
|
|||||||
<Text className={styles.btnText}>已加入候补</Text>
|
<Text className={styles.btnText}>已加入候补</Text>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
action: () => toast("已加入候补"),
|
action: () => toast("您已加入候补,候补失败会全额退款~"),
|
||||||
};
|
};
|
||||||
} else if (can_pay) {
|
} else if (can_pay) {
|
||||||
return {
|
return {
|
||||||
@@ -190,6 +233,19 @@ export default function StickyButton(props) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
} else if (!matchNtrpReq) {
|
||||||
|
return {
|
||||||
|
text: () => (
|
||||||
|
<>
|
||||||
|
<Image className={styles.crrrencySymbol} src={RMB_ICON} />
|
||||||
|
{displayPrice}
|
||||||
|
<Text className={styles.btnText}>立即加入</Text>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
available: false,
|
||||||
|
action: () =>
|
||||||
|
toast("您当前不符合此球局NTRP水平要求,去看看其他活动吧~"),
|
||||||
|
};
|
||||||
} else if (can_substitute) {
|
} else if (can_substitute) {
|
||||||
return {
|
return {
|
||||||
text: () => (
|
text: () => (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Text, View } from "@tarojs/components";
|
import { Text, View } from "@tarojs/components";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
import { insertDotInTags } from "../../utils/helper";
|
import { insertDotInTags } from "@/utils/helper";
|
||||||
|
|
||||||
export default function SupplementalNotes(props) {
|
export default function SupplementalNotes(props) {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Taro from "@tarojs/taro";
|
|||||||
import { CommonPopup } from "@/components";
|
import { CommonPopup } from "@/components";
|
||||||
import img from "@/config/images";
|
import img from "@/config/images";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
import { insertDotInTags } from "../../utils/helper";
|
import { insertDotInTags } from "@/utils/helper";
|
||||||
|
|
||||||
// 场馆信息
|
// 场馆信息
|
||||||
export default function VenueInfo(props) {
|
export default function VenueInfo(props) {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
.detail-page {
|
.detail-page {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
// background-color: #FAFAFA;
|
position: relative;
|
||||||
// padding-bottom: env(safe-area-inset-bottom);
|
|
||||||
|
|
||||||
.custom-navbar {
|
.custom-navbar {
|
||||||
height: 56px; /* 通常与原生导航栏高度一致 */
|
height: 56px; /* 通常与原生导航栏高度一致 */
|
||||||
@@ -11,43 +10,55 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
// background-color: #fff;
|
// background-color: #fff;
|
||||||
color: #000;
|
color: #000;
|
||||||
padding-top: 44px; /* 适配状态栏 */
|
// padding-top: 44px; /* 适配状态栏 */
|
||||||
position: sticky;
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
border-bottom: 1px solid transparent;
|
||||||
|
transition: background 0.25s ease, backdrop-filter 0.25s ease;
|
||||||
|
|
||||||
|
&.glass {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: 0 0 4px 0 rgba(255, 255, 255, 0.25) inset;
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
|
border-color: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-navigator {
|
.detail-navigator {
|
||||||
height: 30px;
|
height: 40px;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 12px;
|
left: 12px;
|
||||||
border: 1px solid #888;
|
// border: 1px solid #888;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: rgba(0, 0, 0, 0.1);
|
// background: rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
.detail-navigator-back {
|
// .detail-navigator-back {
|
||||||
border-right: 1px solid #444;
|
// border-right: 1px solid #444;
|
||||||
}
|
// }
|
||||||
|
|
||||||
.detail-navigator-back,
|
.detail-navigator-back,
|
||||||
.detail-navigator-icon {
|
.detail-navigator-icon {
|
||||||
height: 20px;
|
height: 100%;
|
||||||
width: 50%;
|
width: 100%;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
& > .detail-navigator-back-icon {
|
& > .detail-navigator-back-icon {
|
||||||
width: 20px;
|
width: 16px;
|
||||||
height: 20px;
|
height: 16px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .detail-navigator-logo-icon {
|
& > .detail-navigator-logo-icon {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef } from "react";
|
||||||
import { View, Text, Image } from "@tarojs/components";
|
import { View, Text, Image, ScrollView } from "@tarojs/components";
|
||||||
import Taro, { useRouter, useDidShow } from "@tarojs/taro";
|
import Taro, { useRouter, useDidShow } from "@tarojs/taro";
|
||||||
|
import classnames from "classnames";
|
||||||
|
import { throttle } from "@tarojs/runtime";
|
||||||
// 导入API服务
|
// 导入API服务
|
||||||
import { withAuth, Comments } from "@/components";
|
import { withAuth, Comments } from "@/components";
|
||||||
import DetailService from "@/services/detailService";
|
import DetailService from "@/services/detailService";
|
||||||
@@ -18,9 +20,9 @@ import Participants from "./components/Participants";
|
|||||||
import SupplementalNotes from "./components/SupplementalNotes";
|
import SupplementalNotes from "./components/SupplementalNotes";
|
||||||
import OrganizerInfo from "./components/OrganizerInfo";
|
import OrganizerInfo from "./components/OrganizerInfo";
|
||||||
import SharePopup from "./components/SharePopup";
|
import SharePopup from "./components/SharePopup";
|
||||||
import { navto, toast } from "./utils/helper";
|
import { navto, toast } from "@/utils/helper";
|
||||||
import ArrowLeft from "@/static/detail/icon-arrow-left.svg";
|
import ArrowLeft from "@/static/detail/icon-arrow-left.svg";
|
||||||
import Logo from "@/static/detail/icon-logo-go.svg";
|
// import Logo from "@/static/detail/icon-logo-go.svg";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
function Index() {
|
function Index() {
|
||||||
@@ -35,7 +37,7 @@ function Index() {
|
|||||||
const myInfo = useUserInfo();
|
const myInfo = useUserInfo();
|
||||||
|
|
||||||
const { statusNavbarHeightInfo } = useGlobalState();
|
const { statusNavbarHeightInfo } = useGlobalState();
|
||||||
const { statusBarHeight, navBarHeight } = statusNavbarHeightInfo;
|
const { statusBarHeight, navBarHeight, totalHeight } = statusNavbarHeightInfo;
|
||||||
|
|
||||||
const isMyOwn = userInfo.id === myInfo.id;
|
const isMyOwn = userInfo.id === myInfo.id;
|
||||||
|
|
||||||
@@ -150,14 +152,33 @@ function Index() {
|
|||||||
? { backgroundImage: `url(${detail?.image_list?.[0]})` }
|
? { backgroundImage: `url(${detail?.image_list?.[0]})` }
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
|
const [glass, setGlass] = useState(false);
|
||||||
|
|
||||||
|
const onScroll = throttle((e) => {
|
||||||
|
const top = e.detail.scrollTop;
|
||||||
|
setGlass(top > 20);
|
||||||
|
}, 16);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={styles["detail-page"]}>
|
<ScrollView
|
||||||
|
className={styles["detail-page"]}
|
||||||
|
scrollY
|
||||||
|
onScroll={onScroll}
|
||||||
|
onScrollToUpper={() => {
|
||||||
|
setGlass(false);
|
||||||
|
}}
|
||||||
|
enhanced
|
||||||
|
showScrollbar={false}
|
||||||
|
>
|
||||||
{/* custom navbar */}
|
{/* custom navbar */}
|
||||||
<view
|
<View
|
||||||
className={styles["custom-navbar"]}
|
className={classnames(
|
||||||
|
styles["custom-navbar"],
|
||||||
|
glass ? styles.glass : ""
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
height: `${statusBarHeight}px`,
|
height: `${totalHeight}px`,
|
||||||
paddingTop: `${navBarHeight}px`,
|
paddingTop: `${statusBarHeight}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View className={styles["detail-navigator"]}>
|
<View className={styles["detail-navigator"]}>
|
||||||
@@ -170,14 +191,14 @@ function Index() {
|
|||||||
src={ArrowLeft}
|
src={ArrowLeft}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View className={styles["detail-navigator-icon"]}>
|
{/* <View className={styles["detail-navigator-icon"]}>
|
||||||
<Image
|
<Image
|
||||||
className={styles["detail-navigator-logo-icon"]}
|
className={styles["detail-navigator-logo-icon"]}
|
||||||
src={Logo}
|
src={Logo}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View> */}
|
||||||
</View>
|
</View>
|
||||||
</view>
|
</View>
|
||||||
<View className={styles["detail-page-bg"]} style={backgroundImage} />
|
<View className={styles["detail-page-bg"]} style={backgroundImage} />
|
||||||
{/* swiper */}
|
{/* swiper */}
|
||||||
<Carousel detail={detail} />
|
<Carousel detail={detail} />
|
||||||
@@ -238,6 +259,7 @@ function Index() {
|
|||||||
getCommentCount={
|
getCommentCount={
|
||||||
commentRef.current && commentRef.current.getCommentCount
|
commentRef.current && commentRef.current.getCommentCount
|
||||||
}
|
}
|
||||||
|
currentUserInfo={myInfo}
|
||||||
/>
|
/>
|
||||||
{/* share popup */}
|
{/* share popup */}
|
||||||
<SharePopup
|
<SharePopup
|
||||||
@@ -248,7 +270,7 @@ function Index() {
|
|||||||
userInfo={userInfo}
|
userInfo={userInfo}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
import Taro from "@tarojs/taro";
|
|
||||||
|
|
||||||
export function navto(url) {
|
|
||||||
Taro.navigateTo({
|
|
||||||
url: url,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toast(message) {
|
|
||||||
Taro.showToast({ title: message, icon: "none" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将·作为连接符插入到标签文本之间
|
|
||||||
export function insertDotInTags(tags: string[]) {
|
|
||||||
if (!tags) return [];
|
|
||||||
return tags.join("-·-").split("-");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function genNTRPRequirementText(min, max) {
|
|
||||||
if (min && max && min !== max) {
|
|
||||||
return `${min} - ${max} 之间`;
|
|
||||||
} else if (max === "1") {
|
|
||||||
return "无要求";
|
|
||||||
} else if (max) {
|
|
||||||
return `${max} 以上`;
|
|
||||||
}
|
|
||||||
return "-";
|
|
||||||
}
|
|
||||||
@@ -66,7 +66,7 @@ const ListPage = () => {
|
|||||||
const scrollViewRef = useRef(null); // ScrollView 的 ref
|
const scrollViewRef = useRef(null); // ScrollView 的 ref
|
||||||
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const lastScrollTopRef = useRef(0);
|
const lastScrollTopRef = useRef(0);
|
||||||
const scrollDirectionRef = useRef<'up' | 'down' | null>(null);
|
const scrollDirectionRef = useRef<"up" | "down" | null>(null);
|
||||||
const lastScrollTimeRef = useRef(Date.now());
|
const lastScrollTimeRef = useRef(Date.now());
|
||||||
const loadingMoreRef = useRef(false); // 防止重复加载更多
|
const loadingMoreRef = useRef(false); // 防止重复加载更多
|
||||||
const scrollStartPositionRef = useRef(0); // 记录开始滚动的位置
|
const scrollStartPositionRef = useRef(0); // 记录开始滚动的位置
|
||||||
@@ -74,45 +74,54 @@ const ListPage = () => {
|
|||||||
const [scrollTop, setScrollTop] = useState(0); // 控制 ScrollView 滚动位置
|
const [scrollTop, setScrollTop] = useState(0); // 控制 ScrollView 滚动位置
|
||||||
|
|
||||||
// 动态控制 GuideBar 的 z-index
|
// 动态控制 GuideBar 的 z-index
|
||||||
const [guideBarZIndex, setGuideBarZIndex] = useState<'low' | 'high'>('high');
|
const [guideBarZIndex, setGuideBarZIndex] = useState<"low" | "high">("high");
|
||||||
const [isPublishMenuVisible, setIsPublishMenuVisible] = useState(false);
|
const [isPublishMenuVisible, setIsPublishMenuVisible] = useState(false);
|
||||||
const [isDistanceFilterVisible, setIsDistanceFilterVisible] = useState(false);
|
const [isDistanceFilterVisible, setIsDistanceFilterVisible] = useState(false);
|
||||||
const [isCityPickerVisible, setIsCityPickerVisible] = useState(false);
|
const [isCityPickerVisible, setIsCityPickerVisible] = useState(false);
|
||||||
|
|
||||||
// 处理 PublishMenu 显示/隐藏
|
// 处理 PublishMenu 显示/隐藏
|
||||||
const handlePublishMenuVisibleChange = useCallback((visible: boolean) => {
|
const handlePublishMenuVisibleChange = useCallback((visible: boolean) => {
|
||||||
setIsPublishMenuVisible(visible);
|
setIsPublishMenuVisible(visible);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 处理 DistanceQuickFilter 显示/隐藏
|
// 处理 DistanceQuickFilter 显示/隐藏
|
||||||
const handleDistanceFilterVisibleChange = useCallback((visible: boolean) => {
|
const handleDistanceFilterVisibleChange = useCallback((visible: boolean) => {
|
||||||
setIsDistanceFilterVisible(visible);
|
setIsDistanceFilterVisible(visible);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 处理 CityPicker 显示/隐藏
|
// 处理 CityPicker 显示/隐藏
|
||||||
const handleCityPickerVisibleChange = useCallback((visible: boolean) => {
|
const handleCityPickerVisibleChange = useCallback((visible: boolean) => {
|
||||||
setIsCityPickerVisible(visible);
|
setIsCityPickerVisible(visible);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 滚动到顶部的方法
|
// 滚动到顶部的方法
|
||||||
const scrollToTop = useCallback(() => {
|
const scrollToTop = useCallback(() => {
|
||||||
// 使用一个唯一值触发 scrollTop 更新,确保每次都能滚动到顶部
|
// 使用一个唯一值触发 scrollTop 更新,确保每次都能滚动到顶部
|
||||||
setScrollTop(prev => prev === 0 ? 0.1 : 0);
|
setScrollTop((prev) => (prev === 0 ? 0.1 : 0));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 监听所有弹窗和菜单的状态,动态调整 GuideBar 的 z-index
|
// 监听所有弹窗和菜单的状态,动态调整 GuideBar 的 z-index
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isPublishMenuVisible) {
|
if (isPublishMenuVisible) {
|
||||||
// PublishMenu 展开时,GuideBar 保持高层级
|
// PublishMenu 展开时,GuideBar 保持高层级
|
||||||
setGuideBarZIndex('high');
|
setGuideBarZIndex("high");
|
||||||
} else if (isShowFilterPopup || isDistanceFilterVisible || isCityPickerVisible) {
|
} else if (
|
||||||
|
isShowFilterPopup ||
|
||||||
|
isDistanceFilterVisible ||
|
||||||
|
isCityPickerVisible
|
||||||
|
) {
|
||||||
// 任何筛选组件或选择器展开时,GuideBar 降低层级
|
// 任何筛选组件或选择器展开时,GuideBar 降低层级
|
||||||
setGuideBarZIndex('low');
|
setGuideBarZIndex("low");
|
||||||
} else {
|
} else {
|
||||||
// 都关闭时,GuideBar 保持高层级
|
// 都关闭时,GuideBar 保持高层级
|
||||||
setGuideBarZIndex('high');
|
setGuideBarZIndex("high");
|
||||||
}
|
}
|
||||||
}, [isShowFilterPopup, isPublishMenuVisible, isDistanceFilterVisible, isCityPickerVisible]);
|
}, [
|
||||||
|
isShowFilterPopup,
|
||||||
|
isPublishMenuVisible,
|
||||||
|
isDistanceFilterVisible,
|
||||||
|
isCityPickerVisible,
|
||||||
|
]);
|
||||||
|
|
||||||
// ScrollView 滚动处理函数
|
// ScrollView 滚动处理函数
|
||||||
const handleScrollViewScroll = useCallback(
|
const handleScrollViewScroll = useCallback(
|
||||||
@@ -133,28 +142,34 @@ const ListPage = () => {
|
|||||||
if (Math.abs(scrollDiff) > 15) {
|
if (Math.abs(scrollDiff) > 15) {
|
||||||
if (scrollDiff > 0) {
|
if (scrollDiff > 0) {
|
||||||
// 方向改变时,记录新的起始位置
|
// 方向改变时,记录新的起始位置
|
||||||
if (newDirection !== 'up') {
|
if (newDirection !== "up") {
|
||||||
scrollStartPositionRef.current = lastScrollTop;
|
scrollStartPositionRef.current = lastScrollTop;
|
||||||
}
|
}
|
||||||
newDirection = 'up';
|
newDirection = "up";
|
||||||
} else {
|
} else {
|
||||||
// 方向改变时,记录新的起始位置
|
// 方向改变时,记录新的起始位置
|
||||||
if (newDirection !== 'down') {
|
if (newDirection !== "down") {
|
||||||
scrollStartPositionRef.current = lastScrollTop;
|
scrollStartPositionRef.current = lastScrollTop;
|
||||||
}
|
}
|
||||||
newDirection = 'down';
|
newDirection = "down";
|
||||||
}
|
}
|
||||||
scrollDirectionRef.current = newDirection;
|
scrollDirectionRef.current = newDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算从开始滚动到现在的累计距离
|
// 计算从开始滚动到现在的累计距离
|
||||||
const totalScrollDistance = Math.abs(currentScrollTop - scrollStartPositionRef.current);
|
const totalScrollDistance = Math.abs(
|
||||||
|
currentScrollTop - scrollStartPositionRef.current
|
||||||
|
);
|
||||||
|
|
||||||
// 滚动阈值
|
// 滚动阈值
|
||||||
const positionThreshold = 120; // 需要滚动到距离顶部120px
|
const positionThreshold = 120; // 需要滚动到距离顶部120px
|
||||||
const distanceThreshold = 80; // 需要连续滚动80px才触发
|
const distanceThreshold = 80; // 需要连续滚动80px才触发
|
||||||
|
|
||||||
if (newDirection === 'up' && currentScrollTop > positionThreshold && totalScrollDistance > distanceThreshold) {
|
if (
|
||||||
|
newDirection === "up" &&
|
||||||
|
currentScrollTop > positionThreshold &&
|
||||||
|
totalScrollDistance > distanceThreshold
|
||||||
|
) {
|
||||||
// 上滑超过阈值,且连续滚动距离足够,隐藏搜索框
|
// 上滑超过阈值,且连续滚动距离足够,隐藏搜索框
|
||||||
if (showSearchBar || !isShowInputCustomerNavBar) {
|
if (showSearchBar || !isShowInputCustomerNavBar) {
|
||||||
setShowSearchBar(false);
|
setShowSearchBar(false);
|
||||||
@@ -164,7 +179,10 @@ const ListPage = () => {
|
|||||||
// 重置起始位置
|
// 重置起始位置
|
||||||
scrollStartPositionRef.current = currentScrollTop;
|
scrollStartPositionRef.current = currentScrollTop;
|
||||||
}
|
}
|
||||||
} else if ((newDirection === 'down' && totalScrollDistance > distanceThreshold) || currentScrollTop <= positionThreshold) {
|
} else if (
|
||||||
|
(newDirection === "down" && totalScrollDistance > distanceThreshold) ||
|
||||||
|
currentScrollTop <= positionThreshold
|
||||||
|
) {
|
||||||
// 下滑且连续滚动距离足够,或者回到顶部附近,显示搜索框
|
// 下滑且连续滚动距离足够,或者回到顶部附近,显示搜索框
|
||||||
if (!showSearchBar || isShowInputCustomerNavBar) {
|
if (!showSearchBar || isShowInputCustomerNavBar) {
|
||||||
setShowSearchBar(true);
|
setShowSearchBar(true);
|
||||||
@@ -296,7 +314,7 @@ const ListPage = () => {
|
|||||||
updateFilterOptions(params);
|
updateFilterOptions(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearchChange = () => { };
|
const handleSearchChange = () => {};
|
||||||
|
|
||||||
// 距离筛选
|
// 距离筛选
|
||||||
const handleDistanceOrQuickChange = (name, value) => {
|
const handleDistanceOrQuickChange = (name, value) => {
|
||||||
@@ -433,7 +451,6 @@ const ListPage = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
{/* 自定义导航 */}
|
{/* 自定义导航 */}
|
||||||
<HomeNavbar
|
<HomeNavbar
|
||||||
config={{
|
config={{
|
||||||
@@ -467,7 +484,11 @@ const ListPage = () => {
|
|||||||
{/* 固定在顶部的搜索框和筛选 */}
|
{/* 固定在顶部的搜索框和筛选 */}
|
||||||
<View className={styles.fixedHeader}>
|
<View className={styles.fixedHeader}>
|
||||||
{/* 搜索框 - 可隐藏 */}
|
{/* 搜索框 - 可隐藏 */}
|
||||||
<View className={`${styles.listTopSearchWrapper} ${showSearchBar ? styles.show : styles.hide}`}>
|
<View
|
||||||
|
className={`${styles.listTopSearchWrapper} ${
|
||||||
|
showSearchBar ? styles.show : styles.hide
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<SearchBar
|
<SearchBar
|
||||||
handleFilterIcon={toggleShowPopup}
|
handleFilterIcon={toggleShowPopup}
|
||||||
isSelect={filterCount > 0}
|
isSelect={filterCount > 0}
|
||||||
@@ -507,7 +528,11 @@ const ListPage = () => {
|
|||||||
lowerThreshold={100}
|
lowerThreshold={100}
|
||||||
onScrollToLower={async () => {
|
onScrollToLower={async () => {
|
||||||
// 防止重复调用,检查 loading 状态和是否正在加载更多
|
// 防止重复调用,检查 loading 状态和是否正在加载更多
|
||||||
if (!loading && !loadingMoreRef.current && listPageState?.isHasMoreData) {
|
if (
|
||||||
|
!loading &&
|
||||||
|
!loadingMoreRef.current &&
|
||||||
|
listPageState?.isHasMoreData
|
||||||
|
) {
|
||||||
loadingMoreRef.current = true;
|
loadingMoreRef.current = true;
|
||||||
try {
|
try {
|
||||||
await loadMoreMatches();
|
await loadMoreMatches();
|
||||||
@@ -529,14 +554,19 @@ const ListPage = () => {
|
|||||||
error={error}
|
error={error}
|
||||||
reload={refreshMatches}
|
reload={refreshMatches}
|
||||||
loadMoreMatches={loadMoreMatches}
|
loadMoreMatches={loadMoreMatches}
|
||||||
|
evaluateFlag
|
||||||
/>
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<GuideBar
|
<GuideBar
|
||||||
currentPage="list"
|
currentPage="list"
|
||||||
guideBarClassName={`${styles.guideBarList} ${guideBarZIndex === 'low' ? styles.guideBarLowZIndex : styles.guideBarHighZIndex}`}
|
guideBarClassName={`${styles.guideBarList} ${
|
||||||
|
guideBarZIndex === "low"
|
||||||
|
? styles.guideBarLowZIndex
|
||||||
|
: styles.guideBarHighZIndex
|
||||||
|
}`}
|
||||||
onPublishMenuVisibleChange={handlePublishMenuVisibleChange}
|
onPublishMenuVisibleChange={handlePublishMenuVisibleChange}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import WechatLogo from "@/static/detail/wechat_icon.svg";
|
|||||||
import WechatTimeline from "@/static/detail/wechat_timeline.svg";
|
import WechatTimeline from "@/static/detail/wechat_timeline.svg";
|
||||||
import { useUserActions } from "@/store/userStore";
|
import { useUserActions } from "@/store/userStore";
|
||||||
import { DayOfWeekMap } from "../detail/config";
|
import { DayOfWeekMap } from "../detail/config";
|
||||||
import { genNTRPRequirementText } from "@/game_pages/detail/utils/helper";
|
import { genNTRPRequirementText } from "@/utils/helper";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
function SharePoster(props) {
|
function SharePoster(props) {
|
||||||
|
|||||||
@@ -36,9 +36,10 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const store = useListStore() || {};
|
const store = useListStore() || {};
|
||||||
const { fetchUserInfo } = useUserActions();
|
const { fetchUserInfo } = useUserActions();
|
||||||
const { statusNavbarHeightInfo, getCurrentLocationInfo } = useGlobalState() || {};
|
const { statusNavbarHeightInfo, getCurrentLocationInfo } =
|
||||||
|
useGlobalState() || {};
|
||||||
const { totalHeight = 98 } = statusNavbarHeightInfo || {};
|
const { totalHeight = 98 } = statusNavbarHeightInfo || {};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
listPageState,
|
listPageState,
|
||||||
loading,
|
loading,
|
||||||
@@ -77,7 +78,7 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
const scrollViewRef = useRef(null);
|
const scrollViewRef = useRef(null);
|
||||||
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const lastScrollTopRef = useRef(0);
|
const lastScrollTopRef = useRef(0);
|
||||||
const scrollDirectionRef = useRef<'up' | 'down' | null>(null);
|
const scrollDirectionRef = useRef<"up" | "down" | null>(null);
|
||||||
const lastScrollTimeRef = useRef(Date.now());
|
const lastScrollTimeRef = useRef(Date.now());
|
||||||
const loadingMoreRef = useRef(false);
|
const loadingMoreRef = useRef(false);
|
||||||
const scrollStartPositionRef = useRef(0);
|
const scrollStartPositionRef = useRef(0);
|
||||||
@@ -86,17 +87,20 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
|
||||||
// 处理距离筛选显示/隐藏
|
// 处理距离筛选显示/隐藏
|
||||||
const handleDistanceFilterVisibleChange = useCallback((visible: boolean) => {
|
const handleDistanceFilterVisibleChange = useCallback(
|
||||||
onDistanceFilterVisibleChange?.(visible);
|
(visible: boolean) => {
|
||||||
onNavStateChange?.({ isDistanceFilterVisible: visible });
|
onDistanceFilterVisibleChange?.(visible);
|
||||||
}, [onDistanceFilterVisibleChange, onNavStateChange]);
|
onNavStateChange?.({ isDistanceFilterVisible: visible });
|
||||||
|
},
|
||||||
|
[onDistanceFilterVisibleChange, onNavStateChange]
|
||||||
|
);
|
||||||
|
|
||||||
// 处理城市选择器显示/隐藏(由主容器统一管理,通过 onNavStateChange 通知)
|
// 处理城市选择器显示/隐藏(由主容器统一管理,通过 onNavStateChange 通知)
|
||||||
// 注意:CustomerNavBar 的 onCityPickerVisibleChange 由主容器直接处理
|
// 注意:CustomerNavBar 的 onCityPickerVisibleChange 由主容器直接处理
|
||||||
|
|
||||||
// 滚动到顶部(用于 ScrollView 内部滚动)
|
// 滚动到顶部(用于 ScrollView 内部滚动)
|
||||||
const scrollToTopInternal = useCallback(() => {
|
const scrollToTopInternal = useCallback(() => {
|
||||||
setScrollTop(prev => prev === 0 ? 0.1 : 0);
|
setScrollTop((prev) => (prev === 0 ? 0.1 : 0));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 监听外部滚动触发
|
// 监听外部滚动触发
|
||||||
@@ -120,24 +124,30 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
let newDirection = scrollDirectionRef.current;
|
let newDirection = scrollDirectionRef.current;
|
||||||
if (Math.abs(scrollDiff) > 15) {
|
if (Math.abs(scrollDiff) > 15) {
|
||||||
if (scrollDiff > 0) {
|
if (scrollDiff > 0) {
|
||||||
if (newDirection !== 'up') {
|
if (newDirection !== "up") {
|
||||||
scrollStartPositionRef.current = lastScrollTop;
|
scrollStartPositionRef.current = lastScrollTop;
|
||||||
}
|
}
|
||||||
newDirection = 'up';
|
newDirection = "up";
|
||||||
} else {
|
} else {
|
||||||
if (newDirection !== 'down') {
|
if (newDirection !== "down") {
|
||||||
scrollStartPositionRef.current = lastScrollTop;
|
scrollStartPositionRef.current = lastScrollTop;
|
||||||
}
|
}
|
||||||
newDirection = 'down';
|
newDirection = "down";
|
||||||
}
|
}
|
||||||
scrollDirectionRef.current = newDirection;
|
scrollDirectionRef.current = newDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalScrollDistance = Math.abs(currentScrollTop - scrollStartPositionRef.current);
|
const totalScrollDistance = Math.abs(
|
||||||
|
currentScrollTop - scrollStartPositionRef.current
|
||||||
|
);
|
||||||
const positionThreshold = 120;
|
const positionThreshold = 120;
|
||||||
const distanceThreshold = 80;
|
const distanceThreshold = 80;
|
||||||
|
|
||||||
if (newDirection === 'up' && currentScrollTop > positionThreshold && totalScrollDistance > distanceThreshold) {
|
if (
|
||||||
|
newDirection === "up" &&
|
||||||
|
currentScrollTop > positionThreshold &&
|
||||||
|
totalScrollDistance > distanceThreshold
|
||||||
|
) {
|
||||||
if (showSearchBar || !isShowInputCustomerNavBar) {
|
if (showSearchBar || !isShowInputCustomerNavBar) {
|
||||||
setShowSearchBar(false);
|
setShowSearchBar(false);
|
||||||
updateListPageState({
|
updateListPageState({
|
||||||
@@ -146,7 +156,10 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
onNavStateChange?.({ isShowInputCustomerNavBar: true });
|
onNavStateChange?.({ isShowInputCustomerNavBar: true });
|
||||||
scrollStartPositionRef.current = currentScrollTop;
|
scrollStartPositionRef.current = currentScrollTop;
|
||||||
}
|
}
|
||||||
} else if ((newDirection === 'down' && totalScrollDistance > distanceThreshold) || currentScrollTop <= positionThreshold) {
|
} else if (
|
||||||
|
(newDirection === "down" && totalScrollDistance > distanceThreshold) ||
|
||||||
|
currentScrollTop <= positionThreshold
|
||||||
|
) {
|
||||||
if (!showSearchBar || isShowInputCustomerNavBar) {
|
if (!showSearchBar || isShowInputCustomerNavBar) {
|
||||||
setShowSearchBar(true);
|
setShowSearchBar(true);
|
||||||
updateListPageState({
|
updateListPageState({
|
||||||
@@ -160,7 +173,12 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
lastScrollTopRef.current = currentScrollTop;
|
lastScrollTopRef.current = currentScrollTop;
|
||||||
lastScrollTimeRef.current = currentTime;
|
lastScrollTimeRef.current = currentTime;
|
||||||
},
|
},
|
||||||
[showSearchBar, isShowInputCustomerNavBar, updateListPageState, onNavStateChange]
|
[
|
||||||
|
showSearchBar,
|
||||||
|
isShowInputCustomerNavBar,
|
||||||
|
updateListPageState,
|
||||||
|
onNavStateChange,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -253,7 +271,7 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
updateFilterOptions(params);
|
updateFilterOptions(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearchChange = () => { };
|
const handleSearchChange = () => {};
|
||||||
|
|
||||||
const handleDistanceOrQuickChange = (name, value) => {
|
const handleDistanceOrQuickChange = (name, value) => {
|
||||||
updateDistanceQuickFilter({
|
updateDistanceQuickFilter({
|
||||||
@@ -341,7 +359,11 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<View className={styles.fixedHeader}>
|
<View className={styles.fixedHeader}>
|
||||||
<View className={`${styles.listTopSearchWrapper} ${showSearchBar ? styles.show : styles.hide}`}>
|
<View
|
||||||
|
className={`${styles.listTopSearchWrapper} ${
|
||||||
|
showSearchBar ? styles.show : styles.hide
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<SearchBar
|
<SearchBar
|
||||||
handleFilterIcon={toggleShowPopup}
|
handleFilterIcon={toggleShowPopup}
|
||||||
isSelect={filterCount > 0}
|
isSelect={filterCount > 0}
|
||||||
@@ -378,7 +400,11 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
onRefresherRefresh={handleRefresh}
|
onRefresherRefresh={handleRefresh}
|
||||||
lowerThreshold={100}
|
lowerThreshold={100}
|
||||||
onScrollToLower={async () => {
|
onScrollToLower={async () => {
|
||||||
if (!loading && !loadingMoreRef.current && listPageState?.isHasMoreData) {
|
if (
|
||||||
|
!loading &&
|
||||||
|
!loadingMoreRef.current &&
|
||||||
|
listPageState?.isHasMoreData
|
||||||
|
) {
|
||||||
loadingMoreRef.current = true;
|
loadingMoreRef.current = true;
|
||||||
try {
|
try {
|
||||||
await loadMoreMatches();
|
await loadMoreMatches();
|
||||||
@@ -399,6 +425,7 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
error={error}
|
error={error}
|
||||||
reload={refreshMatches}
|
reload={refreshMatches}
|
||||||
loadMoreMatches={loadMoreMatches}
|
loadMoreMatches={loadMoreMatches}
|
||||||
|
evaluateFlag
|
||||||
/>
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
@@ -409,4 +436,3 @@ const ListPageContent: React.FC<ListPageContentProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default ListPageContent;
|
export default ListPageContent;
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const MyselfPageContent: React.FC = () => {
|
|||||||
const pickerOption = usePickerOption();
|
const pickerOption = usePickerOption();
|
||||||
const { statusNavbarHeightInfo } = useGlobalState() || {};
|
const { statusNavbarHeightInfo } = useGlobalState() || {};
|
||||||
const { totalHeight = 98 } = statusNavbarHeightInfo || {};
|
const { totalHeight = 98 } = statusNavbarHeightInfo || {};
|
||||||
|
|
||||||
const instance = (Taro as any).getCurrentInstance();
|
const instance = (Taro as any).getCurrentInstance();
|
||||||
const user_id = instance.router?.params?.userid || "";
|
const user_id = instance.router?.params?.userid || "";
|
||||||
const is_current_user = !user_id;
|
const is_current_user = !user_id;
|
||||||
@@ -26,7 +26,9 @@ const MyselfPageContent: React.FC = () => {
|
|||||||
const [ended_game_records, setEndedGameRecords] = useState<TennisMatch[]>([]);
|
const [ended_game_records, setEndedGameRecords] = useState<TennisMatch[]>([]);
|
||||||
const [loading] = useState(false);
|
const [loading] = useState(false);
|
||||||
const [is_following, setIsFollowing] = useState(false);
|
const [is_following, setIsFollowing] = useState(false);
|
||||||
const [active_tab, setActiveTab] = useState<"hosted" | "participated">("hosted");
|
const [active_tab, setActiveTab] = useState<"hosted" | "participated">(
|
||||||
|
"hosted"
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
pickerOption.getCities();
|
pickerOption.getCities();
|
||||||
@@ -66,7 +68,7 @@ const MyselfPageContent: React.FC = () => {
|
|||||||
|
|
||||||
const load_game_data = async () => {
|
const load_game_data = async () => {
|
||||||
try {
|
try {
|
||||||
if (!user_info || !('id' in user_info)) {
|
if (!user_info || !("id" in user_info)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let games_data;
|
let games_data;
|
||||||
@@ -136,7 +138,10 @@ const MyselfPageContent: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="myself_page">
|
<View className="myself_page">
|
||||||
<View className="myself_page_content_main" style={{ paddingTop: `${totalHeight}px` }}>
|
<View
|
||||||
|
className="myself_page_content_main"
|
||||||
|
style={{ paddingTop: `${totalHeight}px` }}
|
||||||
|
>
|
||||||
<View className="user_info_section">
|
<View className="user_info_section">
|
||||||
<UserInfoCard
|
<UserInfoCard
|
||||||
editable={is_current_user}
|
editable={is_current_user}
|
||||||
@@ -234,4 +239,3 @@ const MyselfPageContent: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default MyselfPageContent;
|
export default MyselfPageContent;
|
||||||
|
|
||||||
|
|||||||
@@ -400,15 +400,49 @@ function OrderMsg(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "报名人电话",
|
title: "报名人电话",
|
||||||
content: registrant_phone,
|
// content: registrant_phone,
|
||||||
|
content: registrant_phone ? (
|
||||||
|
<Text
|
||||||
|
selectable={true} // 支持长按复制
|
||||||
|
style={{
|
||||||
|
color: "#007AFF",
|
||||||
|
// textDecoration: "underline",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
Taro.makePhoneCall({ phoneNumber: registrant_phone });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{registrant_phone}
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "组织人微信号",
|
title: "组织人微信号",
|
||||||
content: wechat_contact,
|
content: wechat_contact || "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "组织人电话",
|
title: "组织人电话",
|
||||||
content: wechat_contact,
|
// content: wechat_contact,
|
||||||
|
content: wechat_contact ? (
|
||||||
|
<Text
|
||||||
|
selectable={true} // 支持长按复制
|
||||||
|
style={{
|
||||||
|
color: "#007AFF",
|
||||||
|
// textDecoration: "underline",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
Taro.makePhoneCall({ phoneNumber: wechat_contact });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{wechat_contact}
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "费用",
|
title: "费用",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: 100px 12px 40px;
|
padding: 100px 0 40px;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #fff;
|
background-color: #fafafa;
|
||||||
|
|
||||||
// .bg {
|
// .bg {
|
||||||
// position: absolute;
|
// position: absolute;
|
||||||
@@ -48,12 +48,13 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
background-color: #f9f9f9;
|
// background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.orderItem {
|
.orderItem {
|
||||||
width: 100%;
|
// width: calc(100% - 3px);
|
||||||
|
margin: 0 12px;
|
||||||
// height: 222px;
|
// height: 222px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { withAuth, RefundPopup, GeneralNavbar } from "@/components";
|
|||||||
import { payOrder, generateOrderActions } from "@/utils";
|
import { payOrder, generateOrderActions } from "@/utils";
|
||||||
import emptyContent from "@/static/emptyStatus/publish-empty.png";
|
import emptyContent from "@/static/emptyStatus/publish-empty.png";
|
||||||
import CustomerIcon from "@/static/order/customer.svg";
|
import CustomerIcon from "@/static/order/customer.svg";
|
||||||
import { insertDotInTags } from "@/game_pages/detail/utils/helper";
|
import { insertDotInTags, genNTRPRequirementText } from "@/utils/helper";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
dayjs.locale("zh-cn");
|
dayjs.locale("zh-cn");
|
||||||
@@ -363,11 +363,7 @@ const OrderList = () => {
|
|||||||
<Text>{max_players}</Text>
|
<Text>{max_players}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className={styles.levelReq}>
|
<View className={styles.levelReq}>
|
||||||
{skill_level_max !== skill_level_min
|
{genNTRPRequirementText(skill_level_min, skill_level_max)}
|
||||||
? `${skill_level_min || "-"} 至 ${skill_level_max || "-"}`
|
|
||||||
: skill_level_min === 1
|
|
||||||
? "无要求"
|
|
||||||
: `${skill_level_min} 以上`}
|
|
||||||
</View>
|
</View>
|
||||||
<View className={styles.playType}>{play_type}</View>
|
<View className={styles.playType}>{play_type}</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import evaluateService, {
|
|||||||
LastTimeTestResult,
|
LastTimeTestResult,
|
||||||
Question,
|
Question,
|
||||||
TestResultData,
|
TestResultData,
|
||||||
|
StageType,
|
||||||
} from "@/services/evaluateService";
|
} from "@/services/evaluateService";
|
||||||
import { useUserInfo, useUserActions } from "@/store/userStore";
|
import { useUserInfo, useUserActions } from "@/store/userStore";
|
||||||
import { useEvaluate, EvaluateScene } from "@/store/evaluateStore";
|
import { useEvaluate, EvaluateScene } from "@/store/evaluateStore";
|
||||||
@@ -24,12 +25,6 @@ import DownloadIcon from "@/static/ntrp/ntrp_download.svg";
|
|||||||
import ReTestIcon from "@/static/ntrp/ntrp_re-action.svg";
|
import ReTestIcon from "@/static/ntrp/ntrp_re-action.svg";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
enum StageType {
|
|
||||||
INTRO = "intro",
|
|
||||||
TEST = "test",
|
|
||||||
RESULT = "result",
|
|
||||||
}
|
|
||||||
|
|
||||||
const sourceTypeToTextMap = new Map([
|
const sourceTypeToTextMap = new Map([
|
||||||
[EvaluateScene.detail, "继续加入球局"],
|
[EvaluateScene.detail, "继续加入球局"],
|
||||||
[EvaluateScene.publish, "继续发布球局"],
|
[EvaluateScene.publish, "继续发布球局"],
|
||||||
@@ -174,20 +169,17 @@ function Intro() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleNext(type) {
|
function handleNext(type) {
|
||||||
setCallback({
|
if (!id) {
|
||||||
type: EvaluateScene.share,
|
setCallback({
|
||||||
next: () => {
|
type: EvaluateScene.share,
|
||||||
Taro.redirectTo({ url: "/main_pages/index" });
|
next: () => {
|
||||||
},
|
Taro.redirectTo({ url: "/main_pages/index" });
|
||||||
onCancel: () => {
|
},
|
||||||
Taro.redirectTo({ url: "/main_pages/index" });
|
onCancel: () => {
|
||||||
// if (userInfo.id) {
|
Taro.redirectTo({ url: "/main_pages/index" });
|
||||||
// Taro.redirectTo({ url: "/game_pages/list/index" });
|
},
|
||||||
// } else {
|
});
|
||||||
// Taro.exitMiniProgram();
|
}
|
||||||
// }
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Taro.redirectTo({
|
Taro.redirectTo({
|
||||||
url: `/other_pages/ntrp-evaluate/index?stage=${type}${
|
url: `/other_pages/ntrp-evaluate/index?stage=${type}${
|
||||||
type === StageType.RESULT ? `&id=${id}` : ""
|
type === StageType.RESULT ? `&id=${id}` : ""
|
||||||
@@ -497,7 +489,7 @@ function Result() {
|
|||||||
|
|
||||||
async function handleGoon() {
|
async function handleGoon() {
|
||||||
if (type) {
|
if (type) {
|
||||||
next();
|
next({ flag: false, score: result?.ntrp_level as string });
|
||||||
await delay(1500);
|
await delay(1500);
|
||||||
clear();
|
clear();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,12 @@
|
|||||||
import httpService from "./httpService";
|
import httpService from "./httpService";
|
||||||
import type { ApiResponse } from "./httpService";
|
import type { ApiResponse } from "./httpService";
|
||||||
|
|
||||||
|
export enum StageType {
|
||||||
|
INTRO = "intro",
|
||||||
|
TEST = "test",
|
||||||
|
RESULT = "result",
|
||||||
|
}
|
||||||
|
|
||||||
// 单个选项类型
|
// 单个选项类型
|
||||||
interface Option {
|
interface Option {
|
||||||
text: string;
|
text: string;
|
||||||
|
|||||||
@@ -10,18 +10,25 @@ export enum EvaluateScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface EvaluateCallback {
|
export interface EvaluateCallback {
|
||||||
type: EvaluateScene | ''
|
type: EvaluateScene | "";
|
||||||
next: (flag?: boolean) => void,
|
// flag是用来区分跳转ntrp测试后的操作和直接修改ntrp水平成功后的操作
|
||||||
onCancel: () => void,
|
// score是用在加入球局前判断是否满足球局要求的返回值,限定为必传
|
||||||
|
// next有两个地方调用:ntrp结果页handleGoon、ntrp弹窗(NTRPEvaluatePopup)直接修改点击保存按钮时
|
||||||
|
next: ({ flag, score }: { flag?: boolean; score: string }) => void;
|
||||||
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EvaluateCallbackType extends EvaluateCallback {
|
export interface EvaluateCallbackType extends EvaluateCallback {
|
||||||
setCallback: (options: { type: EvaluateScene | '', next: () => void, onCancel: () => void }) => void,
|
setCallback: (options: {
|
||||||
clear: () => void,
|
type: EvaluateScene | "";
|
||||||
|
next: ({ flag, score }: { flag?: boolean; score: string }) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}) => void;
|
||||||
|
clear: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useEvaluateCallback = create<EvaluateCallbackType>()((set) => ({
|
export const useEvaluateCallback = create<EvaluateCallbackType>()((set) => ({
|
||||||
type: '',
|
type: "",
|
||||||
next: () => { },
|
next: () => { },
|
||||||
onCancel: () => { },
|
onCancel: () => { },
|
||||||
setCallback: ({ type, next, onCancel }) => {
|
setCallback: ({ type, next, onCancel }) => {
|
||||||
@@ -29,15 +36,18 @@ export const useEvaluateCallback = create<EvaluateCallbackType>()((set) => ({
|
|||||||
type,
|
type,
|
||||||
next,
|
next,
|
||||||
onCancel,
|
onCancel,
|
||||||
})
|
});
|
||||||
|
},
|
||||||
|
clear: () => {
|
||||||
|
set({ type: "", next: () => { }, onCancel: () => { } });
|
||||||
},
|
},
|
||||||
clear: () => { set({ type: '', next: () => { }, onCancel: () => { } }) }
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useEvaluate = () => useEvaluateCallback(({ type, next, onCancel, setCallback, clear }) => ({
|
export const useEvaluate = () =>
|
||||||
type,
|
useEvaluateCallback(({ type, next, onCancel, setCallback, clear }) => ({
|
||||||
next,
|
type,
|
||||||
onCancel,
|
next,
|
||||||
setCallback,
|
onCancel,
|
||||||
clear,
|
setCallback,
|
||||||
}))
|
clear,
|
||||||
|
}));
|
||||||
|
|||||||
@@ -23,4 +23,35 @@ export const sceneRedirectLogic = (options, defaultPage: string) => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function navto(url) {
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toast(message) {
|
||||||
|
Taro.showToast({ title: message, icon: "none" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将·作为连接符插入到标签文本之间
|
||||||
|
export function insertDotInTags(tags: string[]) {
|
||||||
|
if (!tags) return [];
|
||||||
|
return tags.join("-·-").split("-");
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatNtrpDisplay(val) {
|
||||||
|
return Number(val).toFixed(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function genNTRPRequirementText(min, max) {
|
||||||
|
if (min && max && min !== max) {
|
||||||
|
return `${formatNtrpDisplay(min)} - ${formatNtrpDisplay(max)} 之间`;
|
||||||
|
} else if (max === "1") {
|
||||||
|
return "无要求";
|
||||||
|
} else if (max) {
|
||||||
|
return `${formatNtrpDisplay(max)} 以上`;
|
||||||
|
}
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
5
types/ntrp-evaluate.ts
Normal file
5
types/ntrp-evaluate.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export enum StageType {
|
||||||
|
INTRO = "intro",
|
||||||
|
TEST = "test",
|
||||||
|
RESULT = "result",
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user