diff --git a/src/components/NTRPEvaluatePopup/index.tsx b/src/components/NTRPEvaluatePopup/index.tsx
index ed3bec4..6c7c53a 100644
--- a/src/components/NTRPEvaluatePopup/index.tsx
+++ b/src/components/NTRPEvaluatePopup/index.tsx
@@ -104,7 +104,12 @@ const NTRPEvaluatePopup = (props: NTRPEvaluatePopupProps, ref) => {
async function getNtrp() {
const res = await evaluateService.getLastResult();
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 {
setNtrp("");
}
@@ -128,7 +133,7 @@ const NTRPEvaluatePopup = (props: NTRPEvaluatePopupProps, ref) => {
title: "NTRP水平修改成功",
icon: "none",
});
- evaCallback.next(true);
+ evaCallback.next({ flag: true, score: String(ntrp) });
handleClose();
}
diff --git a/src/components/NTRPTestEntryCard/index.tsx b/src/components/NTRPTestEntryCard/index.tsx
index 4471f18..e433ab6 100644
--- a/src/components/NTRPTestEntryCard/index.tsx
+++ b/src/components/NTRPTestEntryCard/index.tsx
@@ -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 Taro from "@tarojs/taro";
import { useUserInfo, useUserActions } from "@/store/userStore";
// import { getCurrentFullPath } from "@/utils";
+import evaluateService, { StageType } from "@/services/evaluateService";
import DocCopy from "@/static/ntrp/ntrp_doc_copy.svg";
import ArrowRight from "@/static/ntrp/ntrp_arrow_right_color.svg";
import {
@@ -16,54 +17,96 @@ function NTRPTestEntryCard(props: {
type: EvaluateScene;
evaluateCallback?: EvaluateCallback;
}) {
+ const [testFlag, setTestFlag] = useState(false);
const { type, evaluateCallback } = props;
const userInfo = useUserInfo();
const { setCallback } = useEvaluate();
- // const { fetchUserInfo } = useUserActions()
+ const { fetchUserInfo } = useUserActions();
- // useEffect(() => {
- // fetchUserInfo()
- // }, [])
+ console.log(userInfo);
- function handleTest() {
- switch (type) {
- case (EvaluateScene.list, EvaluateScene.share):
- 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" });
- },
- });
+ useEffect(() => {
+ if (!userInfo.id) {
+ fetchUserInfo();
}
- Taro.redirectTo({
- url: `/other_pages/ntrp-evaluate/index?stage=test`,
+ evaluateService.getLastResult().then((res) => {
+ 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 ? (
@@ -131,4 +174,5 @@ function NTRPTestEntryCard(props: {
);
}
-export default NTRPTestEntryCard;
+export default memo(NTRPTestEntryCard);
+// export default NTRPTestEntryCard;
diff --git a/src/components/PublishMenu/PublishMenu.tsx b/src/components/PublishMenu/PublishMenu.tsx
index ecddbf7..6f60789 100644
--- a/src/components/PublishMenu/PublishMenu.tsx
+++ b/src/components/PublishMenu/PublishMenu.tsx
@@ -22,7 +22,7 @@ export interface PublishMenuProps {
const PublishMenu: React.FC = (props) => {
const { onVisibleChange } = props;
const [isVisible, setIsVisible] = useState(false);
-
+
// 使用 useEffect 监听 isVisible 变化,确保所有情况都能触发回调
useEffect(() => {
onVisibleChange?.(isVisible);
@@ -55,7 +55,7 @@ const PublishMenu: React.FC = (props) => {
if (!userInfo.ntrp_level) {
ntrpRef.current.show({
type: EvaluateScene.publish,
- next: (flag) => {
+ next: ({ flag }) => {
if (flag) {
handleMenuClick(type);
} else if (type === "ai") {
diff --git a/src/container/listContainer/index.tsx b/src/container/listContainer/index.tsx
index 6d1439c..cdcf4cf 100644
--- a/src/container/listContainer/index.tsx
+++ b/src/container/listContainer/index.tsx
@@ -8,7 +8,7 @@ import { setStorage, getStorage } from "@/store/storage";
import { NTRPTestEntryCard } from "@/components";
import { EvaluateScene } from "@/store/evaluateStore";
import "./index.scss";
-import { useRef, useEffect, useState } from "react";
+import { useRef, useEffect, useState, useMemo } from "react";
const ListContainer = (props) => {
const {
@@ -26,6 +26,7 @@ const ListContainer = (props) => {
style,
collapse = false,
defaultShowNum,
+ evaluateFlag,
} = props;
const timerRef = useRef(null);
const loadingStartTimeRef = useRef(null);
@@ -47,19 +48,17 @@ const ListContainer = (props) => {
});
useEffect(() => {
- setShowNumber(
- () => {
- return defaultShowNum === undefined ? data?.length : defaultShowNum
-
- })
- }, [data])
+ setShowNumber(() => {
+ return defaultShowNum === undefined ? data?.length : defaultShowNum;
+ });
+ }, [data]);
// 控制骨架屏显示逻辑
useEffect(() => {
if (loading) {
// 开始加载时记录时间
loadingStartTimeRef.current = Date.now();
-
+
// 延迟 300ms 后再显示骨架屏
skeletonTimerRef.current = setTimeout(() => {
setShowSkeleton(true);
@@ -102,6 +101,7 @@ const ListContainer = (props) => {
// 对于没有ntrp等级的用户每个月展示一次, 插在第三个位置
function insertEvaluateCard(list) {
+ if (!evaluateFlag) return list;
if (!list || list.length === 0) {
return list;
}
@@ -122,6 +122,11 @@ const ListContainer = (props) => {
return [item1, item2, item3, { type: "evaluateCard" }, ...rest];
}
+ const memoizedList = useMemo(
+ () => insertEvaluateCard(data),
+ [evaluateFlag, data, userInfo.ntrp_level]
+ );
+
// 渲染列表
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 (
<>
- {insertEvaluateCard(list).map((match, index) => {
+ {memoizedList.map((match, index) => {
if (match.type === "evaluateCard") {
return (
@@ -164,20 +169,33 @@ const ListContainer = (props) => {
{renderList(recommendList)} */}
{/* 到底了 */}
- {collapse ?
- data?.length > defaultShowNum ?
- data?.length > showNumber ?
- { setShowNumber(data?.length) }}>
+ {collapse ? (
+ data?.length > defaultShowNum ? (
+ data?.length > showNumber ? (
+ {
+ setShowNumber(data?.length);
+ }}
+ >
更多球局
- :
- { setShowNumber(defaultShowNum) }}>
+
+ ) : (
+ {
+ setShowNumber(defaultShowNum);
+ }}
+ >
收起
- :
- null
- : data?.length > 0 && 到底了}
+ )
+ ) : null
+ ) : (
+ data?.length > 0 && 到底了
+ )}
);
};
diff --git a/src/game_pages/detail/components/GameInfo/index.tsx b/src/game_pages/detail/components/GameInfo/index.tsx
index cf2b7c4..fba6529 100644
--- a/src/game_pages/detail/components/GameInfo/index.tsx
+++ b/src/game_pages/detail/components/GameInfo/index.tsx
@@ -204,6 +204,9 @@ export default function GameInfo(props) {
// hide business msg
showLocation
theme="dark"
+ enableScroll={false}
+ enableZoom={false}
+ onTap={openMap}
/>
)}
diff --git a/src/game_pages/detail/components/GamePlayAndReq/index.tsx b/src/game_pages/detail/components/GamePlayAndReq/index.tsx
index ae81fe2..c2f456d 100644
--- a/src/game_pages/detail/components/GamePlayAndReq/index.tsx
+++ b/src/game_pages/detail/components/GamePlayAndReq/index.tsx
@@ -1,5 +1,5 @@
import { View, Text } from "@tarojs/components";
-import { genNTRPRequirementText } from "../../utils/helper";
+import { genNTRPRequirementText } from "@/utils/helper";
import styles from "./index.module.scss";
// 玩法要求
diff --git a/src/game_pages/detail/components/OrganizerInfo/index.tsx b/src/game_pages/detail/components/OrganizerInfo/index.tsx
index 37861ca..408d673 100644
--- a/src/game_pages/detail/components/OrganizerInfo/index.tsx
+++ b/src/game_pages/detail/components/OrganizerInfo/index.tsx
@@ -6,7 +6,7 @@ import { calculateDistance } from "@/utils";
import { useUserInfo } from "@/store/userStore";
import * as LoginService from "@/services/loginService";
import img from "@/config/images";
-import { navto } from "../../utils/helper";
+import { navto } from "@/utils/helper";
import styles from "./index.module.scss";
function genRecommendGames(games, location, avatar) {
diff --git a/src/game_pages/detail/components/SharePopup/index.tsx b/src/game_pages/detail/components/SharePopup/index.tsx
index 3a5f698..8fefc8f 100644
--- a/src/game_pages/detail/components/SharePopup/index.tsx
+++ b/src/game_pages/detail/components/SharePopup/index.tsx
@@ -12,7 +12,7 @@ import WechatLogo from "@/static/detail/wechat_icon.svg";
// import WechatTimeline from "@/static/detail/wechat_timeline.svg";
import LinkIcon from "@/static/detail/link.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 styles from "./index.module.scss";
diff --git a/src/game_pages/detail/components/StickyBottom/index.module.scss b/src/game_pages/detail/components/StickyBottom/index.module.scss
index adcf285..9d2f356 100644
--- a/src/game_pages/detail/components/StickyBottom/index.module.scss
+++ b/src/game_pages/detail/components/StickyBottom/index.module.scss
@@ -88,7 +88,7 @@
&.disabled > .sticky-bottom-bar-join-game {
background: #b4b4b4;
color: rgba(60, 60, 67, 0.6);
- pointer-events: none;
+ // pointer-events: none;
}
.sticky-bottom-bar-join-game {
@@ -147,6 +147,7 @@
font-feature-settings: "liga" off, "clig" off;
font-family: "DingTalk JinBuTi";
// font-style: italic;
+ font-style: normal;
font-size: 18px;
font-weight: 400;
line-height: 20px;
diff --git a/src/game_pages/detail/components/StickyBottom/index.tsx b/src/game_pages/detail/components/StickyBottom/index.tsx
index 17e8711..0f232be 100644
--- a/src/game_pages/detail/components/StickyBottom/index.tsx
+++ b/src/game_pages/detail/components/StickyBottom/index.tsx
@@ -9,7 +9,7 @@ import { MATCH_STATUS, IsSubstituteSupported } from "@/services/detailService";
import { GameManagePopup, NTRPEvaluatePopup } from "@/components";
import img from "@/config/images";
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";
function isFull(counts) {
@@ -36,6 +36,34 @@ function isFull(counts) {
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) {
const {
@@ -45,6 +73,7 @@ export default function StickyButton(props) {
onStatusChange,
handleAddComment,
getCommentCount,
+ currentUserInfo,
} = props;
const [commentCount, setCommentCount] = useState(0);
const ntrpRef = useRef<{
@@ -58,14 +87,28 @@ export default function StickyButton(props) {
start_time,
end_time,
is_organizer,
+ skill_level_max,
+ skill_level_min,
} = detail || {};
+ const { ntrp_level } = currentUserInfo || {};
+
+ const matchNtrpReq = matchNtrpRequestment(
+ ntrp_level,
+ skill_level_min,
+ skill_level_max
+ );
+
const gameManageRef = useRef();
function handleSelfEvaluate() {
ntrpRef?.current?.show({
type: EvaluateScene.detail,
- next: (flag) => {
+ next: ({ flag, score }) => {
+ if (!matchNtrpRequestment(score, skill_level_min, skill_level_max)) {
+ toast("您当前不符合此球局NTRP水平要求,去看看其他活动吧~");
+ return;
+ }
if (flag) {
Taro.navigateTo({
url: `/order_pages/orderDetail/index?gameId=${id}`,
@@ -123,31 +166,31 @@ export default function StickyButton(props) {
return {
text: "活动已取消",
available: false,
- // action: () => toast("活动已取消"),
+ action: () => toast("活动已取消,去看看其他活动吧~"),
};
} else if (MATCH_STATUS.FINISHED === match_status) {
return {
text: "活动已结束",
available: false,
- // action: () => toast("活动已取消"),
+ action: () => toast("活动已结束,去看看其他活动吧~"),
};
} else if (dayjs(end_time).isBefore(dayjs())) {
return {
text: "活动已结束",
available: false,
- // action: () => toast("活动已结束"),
+ action: () => toast("活动已结束,去看看其他活动吧~"),
};
} else if (dayjs(start_time).isBefore(dayjs())) {
return {
text: "活动已开始",
available: false,
- // action: () => toast("活动已开始"),
+ action: () => toast("活动已开始,去看看其他活动吧~"),
};
} else if (isFull(detail)) {
return {
text: "活动已满员",
available: false,
- // action: () => toast("活动已满员"),
+ action: () => toast("活动已满员,去看看其他活动吧~"),
};
}
if (waiting_start) {
@@ -159,7 +202,7 @@ export default function StickyButton(props) {
已加入
>
),
- action: () => toast("已加入"),
+ action: () => toast("您已参与了本次活动"),
};
} else if (is_substituting) {
return {
@@ -170,7 +213,7 @@ export default function StickyButton(props) {
已加入候补
>
),
- action: () => toast("已加入候补"),
+ action: () => toast("您已加入候补,候补失败会全额退款~"),
};
} else if (can_pay) {
return {
@@ -190,6 +233,19 @@ export default function StickyButton(props) {
}
},
};
+ } else if (!matchNtrpReq) {
+ return {
+ text: () => (
+ <>
+
+ {displayPrice}
+ 立即加入
+ >
+ ),
+ available: false,
+ action: () =>
+ toast("您当前不符合此球局NTRP水平要求,去看看其他活动吧~"),
+ };
} else if (can_substitute) {
return {
text: () => (
diff --git a/src/game_pages/detail/components/SupplementalNotes/index.tsx b/src/game_pages/detail/components/SupplementalNotes/index.tsx
index 08bcdf9..480dc9b 100644
--- a/src/game_pages/detail/components/SupplementalNotes/index.tsx
+++ b/src/game_pages/detail/components/SupplementalNotes/index.tsx
@@ -1,6 +1,6 @@
import { Text, View } from "@tarojs/components";
import styles from "./index.module.scss";
-import { insertDotInTags } from "../../utils/helper";
+import { insertDotInTags } from "@/utils/helper";
export default function SupplementalNotes(props) {
const {
diff --git a/src/game_pages/detail/components/VenueInfo/index.tsx b/src/game_pages/detail/components/VenueInfo/index.tsx
index 2cb8533..9316002 100644
--- a/src/game_pages/detail/components/VenueInfo/index.tsx
+++ b/src/game_pages/detail/components/VenueInfo/index.tsx
@@ -4,7 +4,7 @@ import Taro from "@tarojs/taro";
import { CommonPopup } from "@/components";
import img from "@/config/images";
import styles from "./index.module.scss";
-import { insertDotInTags } from "../../utils/helper";
+import { insertDotInTags } from "@/utils/helper";
// 场馆信息
export default function VenueInfo(props) {
diff --git a/src/game_pages/detail/index.module.scss b/src/game_pages/detail/index.module.scss
index 6185373..f3de38b 100644
--- a/src/game_pages/detail/index.module.scss
+++ b/src/game_pages/detail/index.module.scss
@@ -1,8 +1,7 @@
.detail-page {
width: 100%;
height: 100%;
- // background-color: #FAFAFA;
- // padding-bottom: env(safe-area-inset-bottom);
+ position: relative;
.custom-navbar {
height: 56px; /* 通常与原生导航栏高度一致 */
@@ -11,43 +10,55 @@
justify-content: center;
// background-color: #fff;
color: #000;
- padding-top: 44px; /* 适配状态栏 */
- position: sticky;
+ // padding-top: 44px; /* 适配状态栏 */
+ position: fixed;
+ width: 100%;
top: 0;
+ box-sizing: border-box;
z-index: 100;
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 {
- height: 30px;
+ height: 40px;
width: 80px;
border-radius: 15px;
position: absolute;
left: 12px;
- border: 1px solid #888;
+ // border: 1px solid #888;
box-sizing: border-box;
color: #fff;
display: flex;
align-items: center;
- background: rgba(0, 0, 0, 0.1);
+ // background: rgba(0, 0, 0, 0.1);
- .detail-navigator-back {
- border-right: 1px solid #444;
- }
+ // .detail-navigator-back {
+ // border-right: 1px solid #444;
+ // }
.detail-navigator-back,
.detail-navigator-icon {
- height: 20px;
- width: 50%;
+ height: 100%;
+ width: 100%;
display: flex;
- justify-content: center;
+ justify-content: flex-start;
+ align-items: center;
& > .detail-navigator-back-icon {
- width: 20px;
- height: 20px;
+ width: 16px;
+ height: 16px;
color: #fff;
+ margin-left: 8px;
}
& > .detail-navigator-logo-icon {
diff --git a/src/game_pages/detail/index.tsx b/src/game_pages/detail/index.tsx
index c948f02..a1656c5 100644
--- a/src/game_pages/detail/index.tsx
+++ b/src/game_pages/detail/index.tsx
@@ -1,6 +1,8 @@
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 classnames from "classnames";
+import { throttle } from "@tarojs/runtime";
// 导入API服务
import { withAuth, Comments } from "@/components";
import DetailService from "@/services/detailService";
@@ -18,9 +20,9 @@ import Participants from "./components/Participants";
import SupplementalNotes from "./components/SupplementalNotes";
import OrganizerInfo from "./components/OrganizerInfo";
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 Logo from "@/static/detail/icon-logo-go.svg";
+// import Logo from "@/static/detail/icon-logo-go.svg";
import styles from "./index.module.scss";
function Index() {
@@ -35,7 +37,7 @@ function Index() {
const myInfo = useUserInfo();
const { statusNavbarHeightInfo } = useGlobalState();
- const { statusBarHeight, navBarHeight } = statusNavbarHeightInfo;
+ const { statusBarHeight, navBarHeight, totalHeight } = statusNavbarHeightInfo;
const isMyOwn = userInfo.id === myInfo.id;
@@ -150,14 +152,33 @@ function Index() {
? { 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 (
-
+ {
+ setGlass(false);
+ }}
+ enhanced
+ showScrollbar={false}
+ >
{/* custom navbar */}
-
@@ -170,14 +191,14 @@ function Index() {
src={ArrowLeft}
/>
-
+ {/*
-
+ */}
-
+
{/* swiper */}
@@ -238,6 +259,7 @@ function Index() {
getCommentCount={
commentRef.current && commentRef.current.getCommentCount
}
+ currentUserInfo={myInfo}
/>
{/* share popup */}
-
+
);
}
diff --git a/src/game_pages/detail/utils/helper.ts b/src/game_pages/detail/utils/helper.ts
deleted file mode 100644
index cf7998e..0000000
--- a/src/game_pages/detail/utils/helper.ts
+++ /dev/null
@@ -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 "-";
-}
\ No newline at end of file
diff --git a/src/game_pages/list/index.tsx b/src/game_pages/list/index.tsx
index 502ff3a..1acc70e 100644
--- a/src/game_pages/list/index.tsx
+++ b/src/game_pages/list/index.tsx
@@ -66,7 +66,7 @@ const ListPage = () => {
const scrollViewRef = useRef(null); // ScrollView 的 ref
const scrollTimeoutRef = useRef(null);
const lastScrollTopRef = useRef(0);
- const scrollDirectionRef = useRef<'up' | 'down' | null>(null);
+ const scrollDirectionRef = useRef<"up" | "down" | null>(null);
const lastScrollTimeRef = useRef(Date.now());
const loadingMoreRef = useRef(false); // 防止重复加载更多
const scrollStartPositionRef = useRef(0); // 记录开始滚动的位置
@@ -74,45 +74,54 @@ const ListPage = () => {
const [scrollTop, setScrollTop] = useState(0); // 控制 ScrollView 滚动位置
// 动态控制 GuideBar 的 z-index
- const [guideBarZIndex, setGuideBarZIndex] = useState<'low' | 'high'>('high');
+ const [guideBarZIndex, setGuideBarZIndex] = useState<"low" | "high">("high");
const [isPublishMenuVisible, setIsPublishMenuVisible] = useState(false);
const [isDistanceFilterVisible, setIsDistanceFilterVisible] = useState(false);
const [isCityPickerVisible, setIsCityPickerVisible] = useState(false);
-
+
// 处理 PublishMenu 显示/隐藏
const handlePublishMenuVisibleChange = useCallback((visible: boolean) => {
setIsPublishMenuVisible(visible);
}, []);
-
+
// 处理 DistanceQuickFilter 显示/隐藏
const handleDistanceFilterVisibleChange = useCallback((visible: boolean) => {
setIsDistanceFilterVisible(visible);
}, []);
-
+
// 处理 CityPicker 显示/隐藏
const handleCityPickerVisibleChange = useCallback((visible: boolean) => {
setIsCityPickerVisible(visible);
}, []);
-
+
// 滚动到顶部的方法
const scrollToTop = useCallback(() => {
// 使用一个唯一值触发 scrollTop 更新,确保每次都能滚动到顶部
- setScrollTop(prev => prev === 0 ? 0.1 : 0);
+ setScrollTop((prev) => (prev === 0 ? 0.1 : 0));
}, []);
-
+
// 监听所有弹窗和菜单的状态,动态调整 GuideBar 的 z-index
useEffect(() => {
if (isPublishMenuVisible) {
// PublishMenu 展开时,GuideBar 保持高层级
- setGuideBarZIndex('high');
- } else if (isShowFilterPopup || isDistanceFilterVisible || isCityPickerVisible) {
+ setGuideBarZIndex("high");
+ } else if (
+ isShowFilterPopup ||
+ isDistanceFilterVisible ||
+ isCityPickerVisible
+ ) {
// 任何筛选组件或选择器展开时,GuideBar 降低层级
- setGuideBarZIndex('low');
+ setGuideBarZIndex("low");
} else {
// 都关闭时,GuideBar 保持高层级
- setGuideBarZIndex('high');
+ setGuideBarZIndex("high");
}
- }, [isShowFilterPopup, isPublishMenuVisible, isDistanceFilterVisible, isCityPickerVisible]);
+ }, [
+ isShowFilterPopup,
+ isPublishMenuVisible,
+ isDistanceFilterVisible,
+ isCityPickerVisible,
+ ]);
// ScrollView 滚动处理函数
const handleScrollViewScroll = useCallback(
@@ -133,28 +142,34 @@ const ListPage = () => {
if (Math.abs(scrollDiff) > 15) {
if (scrollDiff > 0) {
// 方向改变时,记录新的起始位置
- if (newDirection !== 'up') {
+ if (newDirection !== "up") {
scrollStartPositionRef.current = lastScrollTop;
}
- newDirection = 'up';
+ newDirection = "up";
} else {
// 方向改变时,记录新的起始位置
- if (newDirection !== 'down') {
+ if (newDirection !== "down") {
scrollStartPositionRef.current = lastScrollTop;
}
- newDirection = 'down';
+ newDirection = "down";
}
scrollDirectionRef.current = newDirection;
}
// 计算从开始滚动到现在的累计距离
- const totalScrollDistance = Math.abs(currentScrollTop - scrollStartPositionRef.current);
+ const totalScrollDistance = Math.abs(
+ currentScrollTop - scrollStartPositionRef.current
+ );
// 滚动阈值
const positionThreshold = 120; // 需要滚动到距离顶部120px
const distanceThreshold = 80; // 需要连续滚动80px才触发
- if (newDirection === 'up' && currentScrollTop > positionThreshold && totalScrollDistance > distanceThreshold) {
+ if (
+ newDirection === "up" &&
+ currentScrollTop > positionThreshold &&
+ totalScrollDistance > distanceThreshold
+ ) {
// 上滑超过阈值,且连续滚动距离足够,隐藏搜索框
if (showSearchBar || !isShowInputCustomerNavBar) {
setShowSearchBar(false);
@@ -164,7 +179,10 @@ const ListPage = () => {
// 重置起始位置
scrollStartPositionRef.current = currentScrollTop;
}
- } else if ((newDirection === 'down' && totalScrollDistance > distanceThreshold) || currentScrollTop <= positionThreshold) {
+ } else if (
+ (newDirection === "down" && totalScrollDistance > distanceThreshold) ||
+ currentScrollTop <= positionThreshold
+ ) {
// 下滑且连续滚动距离足够,或者回到顶部附近,显示搜索框
if (!showSearchBar || isShowInputCustomerNavBar) {
setShowSearchBar(true);
@@ -296,7 +314,7 @@ const ListPage = () => {
updateFilterOptions(params);
};
- const handleSearchChange = () => { };
+ const handleSearchChange = () => {};
// 距离筛选
const handleDistanceOrQuickChange = (name, value) => {
@@ -433,7 +451,6 @@ const ListPage = () => {
return (
<>
-
{/* 自定义导航 */}
{
{/* 固定在顶部的搜索框和筛选 */}
{/* 搜索框 - 可隐藏 */}
-
+
0}
@@ -507,7 +528,11 @@ const ListPage = () => {
lowerThreshold={100}
onScrollToLower={async () => {
// 防止重复调用,检查 loading 状态和是否正在加载更多
- if (!loading && !loadingMoreRef.current && listPageState?.isHasMoreData) {
+ if (
+ !loading &&
+ !loadingMoreRef.current &&
+ listPageState?.isHasMoreData
+ ) {
loadingMoreRef.current = true;
try {
await loadMoreMatches();
@@ -529,14 +554,19 @@ const ListPage = () => {
error={error}
reload={refreshMatches}
loadMoreMatches={loadMoreMatches}
+ evaluateFlag
/>
)}
-
>
diff --git a/src/game_pages/sharePoster/index.tsx b/src/game_pages/sharePoster/index.tsx
index d53fb0f..1933994 100644
--- a/src/game_pages/sharePoster/index.tsx
+++ b/src/game_pages/sharePoster/index.tsx
@@ -13,7 +13,7 @@ import WechatLogo from "@/static/detail/wechat_icon.svg";
import WechatTimeline from "@/static/detail/wechat_timeline.svg";
import { useUserActions } from "@/store/userStore";
import { DayOfWeekMap } from "../detail/config";
-import { genNTRPRequirementText } from "@/game_pages/detail/utils/helper";
+import { genNTRPRequirementText } from "@/utils/helper";
import styles from "./index.module.scss";
function SharePoster(props) {
diff --git a/src/main_pages/components/ListPageContent.tsx b/src/main_pages/components/ListPageContent.tsx
index d0fc120..dd0a10a 100644
--- a/src/main_pages/components/ListPageContent.tsx
+++ b/src/main_pages/components/ListPageContent.tsx
@@ -36,9 +36,10 @@ const ListPageContent: React.FC = ({
}) => {
const store = useListStore() || {};
const { fetchUserInfo } = useUserActions();
- const { statusNavbarHeightInfo, getCurrentLocationInfo } = useGlobalState() || {};
+ const { statusNavbarHeightInfo, getCurrentLocationInfo } =
+ useGlobalState() || {};
const { totalHeight = 98 } = statusNavbarHeightInfo || {};
-
+
const {
listPageState,
loading,
@@ -77,7 +78,7 @@ const ListPageContent: React.FC = ({
const scrollViewRef = useRef(null);
const scrollTimeoutRef = useRef(null);
const lastScrollTopRef = useRef(0);
- const scrollDirectionRef = useRef<'up' | 'down' | null>(null);
+ const scrollDirectionRef = useRef<"up" | "down" | null>(null);
const lastScrollTimeRef = useRef(Date.now());
const loadingMoreRef = useRef(false);
const scrollStartPositionRef = useRef(0);
@@ -86,17 +87,20 @@ const ListPageContent: React.FC = ({
const [refreshing, setRefreshing] = useState(false);
// 处理距离筛选显示/隐藏
- const handleDistanceFilterVisibleChange = useCallback((visible: boolean) => {
- onDistanceFilterVisibleChange?.(visible);
- onNavStateChange?.({ isDistanceFilterVisible: visible });
- }, [onDistanceFilterVisibleChange, onNavStateChange]);
+ const handleDistanceFilterVisibleChange = useCallback(
+ (visible: boolean) => {
+ onDistanceFilterVisibleChange?.(visible);
+ onNavStateChange?.({ isDistanceFilterVisible: visible });
+ },
+ [onDistanceFilterVisibleChange, onNavStateChange]
+ );
// 处理城市选择器显示/隐藏(由主容器统一管理,通过 onNavStateChange 通知)
// 注意:CustomerNavBar 的 onCityPickerVisibleChange 由主容器直接处理
// 滚动到顶部(用于 ScrollView 内部滚动)
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 = ({
let newDirection = scrollDirectionRef.current;
if (Math.abs(scrollDiff) > 15) {
if (scrollDiff > 0) {
- if (newDirection !== 'up') {
+ if (newDirection !== "up") {
scrollStartPositionRef.current = lastScrollTop;
}
- newDirection = 'up';
+ newDirection = "up";
} else {
- if (newDirection !== 'down') {
+ if (newDirection !== "down") {
scrollStartPositionRef.current = lastScrollTop;
}
- newDirection = 'down';
+ newDirection = "down";
}
scrollDirectionRef.current = newDirection;
}
- const totalScrollDistance = Math.abs(currentScrollTop - scrollStartPositionRef.current);
+ const totalScrollDistance = Math.abs(
+ currentScrollTop - scrollStartPositionRef.current
+ );
const positionThreshold = 120;
const distanceThreshold = 80;
- if (newDirection === 'up' && currentScrollTop > positionThreshold && totalScrollDistance > distanceThreshold) {
+ if (
+ newDirection === "up" &&
+ currentScrollTop > positionThreshold &&
+ totalScrollDistance > distanceThreshold
+ ) {
if (showSearchBar || !isShowInputCustomerNavBar) {
setShowSearchBar(false);
updateListPageState({
@@ -146,7 +156,10 @@ const ListPageContent: React.FC = ({
onNavStateChange?.({ isShowInputCustomerNavBar: true });
scrollStartPositionRef.current = currentScrollTop;
}
- } else if ((newDirection === 'down' && totalScrollDistance > distanceThreshold) || currentScrollTop <= positionThreshold) {
+ } else if (
+ (newDirection === "down" && totalScrollDistance > distanceThreshold) ||
+ currentScrollTop <= positionThreshold
+ ) {
if (!showSearchBar || isShowInputCustomerNavBar) {
setShowSearchBar(true);
updateListPageState({
@@ -160,7 +173,12 @@ const ListPageContent: React.FC = ({
lastScrollTopRef.current = currentScrollTop;
lastScrollTimeRef.current = currentTime;
},
- [showSearchBar, isShowInputCustomerNavBar, updateListPageState, onNavStateChange]
+ [
+ showSearchBar,
+ isShowInputCustomerNavBar,
+ updateListPageState,
+ onNavStateChange,
+ ]
);
useEffect(() => {
@@ -253,7 +271,7 @@ const ListPageContent: React.FC = ({
updateFilterOptions(params);
};
- const handleSearchChange = () => { };
+ const handleSearchChange = () => {};
const handleDistanceOrQuickChange = (name, value) => {
updateDistanceQuickFilter({
@@ -341,7 +359,11 @@ const ListPageContent: React.FC = ({
)}
-
+
0}
@@ -378,7 +400,11 @@ const ListPageContent: React.FC = ({
onRefresherRefresh={handleRefresh}
lowerThreshold={100}
onScrollToLower={async () => {
- if (!loading && !loadingMoreRef.current && listPageState?.isHasMoreData) {
+ if (
+ !loading &&
+ !loadingMoreRef.current &&
+ listPageState?.isHasMoreData
+ ) {
loadingMoreRef.current = true;
try {
await loadMoreMatches();
@@ -399,6 +425,7 @@ const ListPageContent: React.FC = ({
error={error}
reload={refreshMatches}
loadMoreMatches={loadMoreMatches}
+ evaluateFlag
/>
@@ -409,4 +436,3 @@ const ListPageContent: React.FC = ({
};
export default ListPageContent;
-
diff --git a/src/main_pages/components/MyselfPageContent.tsx b/src/main_pages/components/MyselfPageContent.tsx
index 0cc724c..3e52662 100644
--- a/src/main_pages/components/MyselfPageContent.tsx
+++ b/src/main_pages/components/MyselfPageContent.tsx
@@ -16,7 +16,7 @@ const MyselfPageContent: React.FC = () => {
const pickerOption = usePickerOption();
const { statusNavbarHeightInfo } = useGlobalState() || {};
const { totalHeight = 98 } = statusNavbarHeightInfo || {};
-
+
const instance = (Taro as any).getCurrentInstance();
const user_id = instance.router?.params?.userid || "";
const is_current_user = !user_id;
@@ -26,7 +26,9 @@ const MyselfPageContent: React.FC = () => {
const [ended_game_records, setEndedGameRecords] = useState([]);
const [loading] = 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(() => {
pickerOption.getCities();
@@ -66,7 +68,7 @@ const MyselfPageContent: React.FC = () => {
const load_game_data = async () => {
try {
- if (!user_info || !('id' in user_info)) {
+ if (!user_info || !("id" in user_info)) {
return;
}
let games_data;
@@ -136,7 +138,10 @@ const MyselfPageContent: React.FC = () => {
return (
-
+
{
};
export default MyselfPageContent;
-
diff --git a/src/order_pages/orderDetail/index.tsx b/src/order_pages/orderDetail/index.tsx
index 2a93571..42b0653 100644
--- a/src/order_pages/orderDetail/index.tsx
+++ b/src/order_pages/orderDetail/index.tsx
@@ -400,15 +400,49 @@ function OrderMsg(props) {
},
{
title: "报名人电话",
- content: registrant_phone,
+ // content: registrant_phone,
+ content: registrant_phone ? (
+ {
+ Taro.makePhoneCall({ phoneNumber: registrant_phone });
+ }}
+ >
+ {registrant_phone}
+
+ ) : (
+ "-"
+ ),
},
{
title: "组织人微信号",
- content: wechat_contact,
+ content: wechat_contact || "-",
},
{
title: "组织人电话",
- content: wechat_contact,
+ // content: wechat_contact,
+ content: wechat_contact ? (
+ {
+ Taro.makePhoneCall({ phoneNumber: wechat_contact });
+ }}
+ >
+ {wechat_contact}
+
+ ) : (
+ "-"
+ ),
},
{
title: "费用",
diff --git a/src/order_pages/orderList/index.module.scss b/src/order_pages/orderList/index.module.scss
index 1a4d4f0..417a694 100644
--- a/src/order_pages/orderList/index.module.scss
+++ b/src/order_pages/orderList/index.module.scss
@@ -10,7 +10,7 @@
}
.container {
- padding: 100px 12px 40px;
+ padding: 100px 0 40px;
background-color: #fafafa;
height: 100vh;
width: 100%;
@@ -24,7 +24,7 @@
height: 100%;
width: 100%;
position: relative;
- background-color: #fff;
+ background-color: #fafafa;
// .bg {
// position: absolute;
@@ -48,12 +48,13 @@
font-style: normal;
font-weight: 500;
line-height: 18px;
- background-color: #f9f9f9;
+ // background-color: #f9f9f9;
}
}
.orderItem {
- width: 100%;
+ // width: calc(100% - 3px);
+ margin: 0 12px;
// height: 222px;
background-color: #fff;
border-radius: 12px;
diff --git a/src/order_pages/orderList/index.tsx b/src/order_pages/orderList/index.tsx
index ca6b15d..89baf9f 100644
--- a/src/order_pages/orderList/index.tsx
+++ b/src/order_pages/orderList/index.tsx
@@ -17,7 +17,7 @@ import { withAuth, RefundPopup, GeneralNavbar } from "@/components";
import { payOrder, generateOrderActions } from "@/utils";
import emptyContent from "@/static/emptyStatus/publish-empty.png";
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";
dayjs.locale("zh-cn");
@@ -363,11 +363,7 @@ const OrderList = () => {
{max_players}
- {skill_level_max !== skill_level_min
- ? `${skill_level_min || "-"} 至 ${skill_level_max || "-"}`
- : skill_level_min === 1
- ? "无要求"
- : `${skill_level_min} 以上`}
+ {genNTRPRequirementText(skill_level_min, skill_level_max)}
{play_type}
diff --git a/src/other_pages/ntrp-evaluate/index.tsx b/src/other_pages/ntrp-evaluate/index.tsx
index 7a68aed..249ce0a 100644
--- a/src/other_pages/ntrp-evaluate/index.tsx
+++ b/src/other_pages/ntrp-evaluate/index.tsx
@@ -8,6 +8,7 @@ import evaluateService, {
LastTimeTestResult,
Question,
TestResultData,
+ StageType,
} from "@/services/evaluateService";
import { useUserInfo, useUserActions } from "@/store/userStore";
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 styles from "./index.module.scss";
-enum StageType {
- INTRO = "intro",
- TEST = "test",
- RESULT = "result",
-}
-
const sourceTypeToTextMap = new Map([
[EvaluateScene.detail, "继续加入球局"],
[EvaluateScene.publish, "继续发布球局"],
@@ -174,20 +169,17 @@ function Intro() {
}
function handleNext(type) {
- setCallback({
- type: EvaluateScene.share,
- next: () => {
- Taro.redirectTo({ url: "/main_pages/index" });
- },
- onCancel: () => {
- Taro.redirectTo({ url: "/main_pages/index" });
- // if (userInfo.id) {
- // Taro.redirectTo({ url: "/game_pages/list/index" });
- // } else {
- // Taro.exitMiniProgram();
- // }
- },
- });
+ if (!id) {
+ setCallback({
+ type: EvaluateScene.share,
+ next: () => {
+ Taro.redirectTo({ url: "/main_pages/index" });
+ },
+ onCancel: () => {
+ Taro.redirectTo({ url: "/main_pages/index" });
+ },
+ });
+ }
Taro.redirectTo({
url: `/other_pages/ntrp-evaluate/index?stage=${type}${
type === StageType.RESULT ? `&id=${id}` : ""
@@ -497,7 +489,7 @@ function Result() {
async function handleGoon() {
if (type) {
- next();
+ next({ flag: false, score: result?.ntrp_level as string });
await delay(1500);
clear();
} else {
diff --git a/src/publish_pages/publishBall/index.tsx b/src/publish_pages/publishBall/index.tsx
index 3340cad..ff0854f 100644
--- a/src/publish_pages/publishBall/index.tsx
+++ b/src/publish_pages/publishBall/index.tsx
@@ -1,82 +1,93 @@
-import React, { useState, useEffect, useRef } from 'react'
-import { View, Text, Button, Image } from '@tarojs/components'
-import { Checkbox } from '@nutui/nutui-react-taro'
-import dayjs from 'dayjs'
-import Taro from '@tarojs/taro'
-import { type ActivityType } from '../../components/ActivityTypeSwitch'
-import CommonDialog from '../../components/CommonDialog'
-import { withAuth } from '@/components'
-import PublishForm from './publishForm'
-import { FormFieldConfig, publishBallFormSchema } from '../../config/formSchema/publishBallFormSchema';
-import { PublishBallFormData } from '../../../types/publishBall';
-import PublishService from '@/services/publishService';
-import { getNextHourTime, getEndTime, delay } from '@/utils';
-import { useGlobalState } from "@/store/global"
-import GeneralNavbar from "@/components/GeneralNavbar"
-import images from '@/config/images'
-import { useUserInfo } from '@/store/userStore'
-import styles from './index.module.scss'
-import { usePublishBallData } from '@/store/publishBallStore'
-import { useKeyboardHeight } from '@/store/keyboardStore'
+import React, { useState, useEffect, useRef } from "react";
+import { View, Text, Button, Image } from "@tarojs/components";
+import { Checkbox } from "@nutui/nutui-react-taro";
+import dayjs from "dayjs";
+import Taro from "@tarojs/taro";
+import { type ActivityType } from "../../components/ActivityTypeSwitch";
+import CommonDialog from "../../components/CommonDialog";
+import { withAuth } from "@/components";
+import PublishForm from "./publishForm";
+import {
+ FormFieldConfig,
+ publishBallFormSchema,
+} from "../../config/formSchema/publishBallFormSchema";
+import { PublishBallFormData } from "../../../types/publishBall";
+import PublishService from "@/services/publishService";
+import { getNextHourTime, getEndTime, delay } from "@/utils";
+import { useGlobalState } from "@/store/global";
+import GeneralNavbar from "@/components/GeneralNavbar";
+import images from "@/config/images";
+import { useUserInfo } from "@/store/userStore";
+import styles from "./index.module.scss";
+import { usePublishBallData } from "@/store/publishBallStore";
+import { useKeyboardHeight } from "@/store/keyboardStore";
import DetailService from "@/services/detailService";
const defaultFormData: PublishBallFormData = {
- title: '',
+ title: "",
image_list: [],
timeRange: {
start_time: getNextHourTime(),
- end_time: getEndTime(getNextHourTime())
+ end_time: getEndTime(getNextHourTime()),
},
activityInfo: {
- play_type: '不限',
- price: '',
+ play_type: "不限",
+ price: "",
venue_id: null,
- location_name: '',
- location: '',
- latitude: '',
- longitude: '',
- court_type: '',
- court_surface: '',
+ location_name: "",
+ location: "",
+ latitude: "",
+ longitude: "",
+ court_type: "",
+ court_surface: "",
venue_description_tag: [],
- venue_description: '',
+ venue_description: "",
venue_image_list: [],
},
players: {
min: 1,
max: 1,
- organizer_joined: true
+ organizer_joined: true,
},
skill_level: [1.0, 5.0],
descriptionInfo: {
- description: '',
+ description: "",
description_tag: [],
},
is_substitute_supported: true,
wechat: {
is_wechat_contact: true,
- wechat_contact: '',
- default_wechat_contact: ''
- }
-
-}
+ wechat_contact: "",
+ default_wechat_contact: "",
+ },
+};
const PublishBall: React.FC = () => {
- const [activityType, setActivityType] = useState('individual')
- const [isSubmitDisabled, setIsSubmitDisabled] = useState(false)
+ const [activityType, setActivityType] = useState("individual");
+ const [isSubmitDisabled, setIsSubmitDisabled] = useState(false);
const userInfo = useUserInfo();
- const publishAiData = usePublishBallData()
+ const publishAiData = usePublishBallData();
const { statusNavbarHeightInfo } = useGlobalState();
// 使用全局键盘状态
- const { keyboardHeight, isKeyboardVisible, addListener, initializeKeyboardListener } = useKeyboardHeight()
+ const {
+ keyboardHeight,
+ isKeyboardVisible,
+ addListener,
+ initializeKeyboardListener,
+ } = useKeyboardHeight();
// 获取页面参数并设置导航标题
- const [optionsConfig, setOptionsConfig] = useState(publishBallFormSchema)
- console.log(userInfo, 'userInfo');
- const [formData, setFormData] = useState([defaultFormData])
- const [checked, setChecked] = useState(true)
- const [titleBar, setTitleBar] = useState('发布球局')
+ const [optionsConfig, setOptionsConfig] = useState(
+ publishBallFormSchema
+ );
+ console.log(userInfo, "userInfo");
+ const [formData, setFormData] = useState([
+ defaultFormData,
+ ]);
+ const [checked, setChecked] = useState(true);
+ const [titleBar, setTitleBar] = useState("发布球局");
// 控制是否响应全局键盘(由具体输入框 focus/blur 控制)
- const [shouldReactToKeyboard, setShouldReactToKeyboard] = useState(false)
+ const [shouldReactToKeyboard, setShouldReactToKeyboard] = useState(false);
// 删除确认弹窗状态
const [deleteConfirm, setDeleteConfirm] = useState<{
@@ -84,113 +95,129 @@ const PublishBall: React.FC = () => {
index: number;
}>({
visible: false,
- index: -1
- })
+ index: -1,
+ });
// 更新表单数据
- const updateFormData = (key: keyof PublishBallFormData, value: any, index: number) => {
- console.log(key, value, index, 'key, value, index');
- setFormData(prev => {
- const newData = [...prev]
- newData[index] = { ...newData[index], [key]: value }
- console.log(newData, 'newData');
- return newData
- })
- }
-
-
+ const updateFormData = (
+ key: keyof PublishBallFormData,
+ value: any,
+ index: number
+ ) => {
+ console.log(key, value, index, "key, value, index");
+ setFormData((prev) => {
+ const newData = [...prev];
+ newData[index] = { ...newData[index], [key]: value };
+ console.log(newData, "newData");
+ return newData;
+ });
+ };
// 检查相邻两组数据是否相同
const checkAdjacentDataSame = (formDataArray: PublishBallFormData[]) => {
- if (formDataArray.length < 2) return false
+ if (formDataArray.length < 2) return false;
- const lastIndex = formDataArray.length - 1
- const secondLastIndex = formDataArray.length - 2
+ const lastIndex = formDataArray.length - 1;
+ const secondLastIndex = formDataArray.length - 2;
- const lastData = formDataArray[lastIndex]
- const secondLastData = formDataArray[secondLastIndex]
+ const lastData = formDataArray[lastIndex];
+ const secondLastData = formDataArray[secondLastIndex];
// 比较关键字段是否相同
- return (JSON.stringify(lastData) === JSON.stringify(secondLastData))
- }
+ return JSON.stringify(lastData) === JSON.stringify(secondLastData);
+ };
const handleAdd = () => {
// 检查最后两组数据是否相同
if (checkAdjacentDataSame(formData)) {
Taro.showToast({
- title: '信息不可与前序场完全一致',
- icon: 'none'
- })
- return
+ title: "信息不可与前序场完全一致",
+ icon: "none",
+ });
+ return;
}
- const newStartTime = getNextHourTime()
- setFormData(prev => [...prev, {
- ...defaultFormData,
- title: '',
- timeRange: {
- start_time: newStartTime,
- end_time: getEndTime(newStartTime)
- }
- }])
- }
-
+ const newStartTime = getNextHourTime();
+ setFormData((prev) => [
+ ...prev,
+ {
+ ...defaultFormData,
+ title: "",
+ timeRange: {
+ start_time: newStartTime,
+ end_time: getEndTime(newStartTime),
+ },
+ },
+ ]);
+ };
// 复制上一场数据
const handleCopyPrevious = (index: number) => {
if (index > 0) {
- setFormData(prev => {
- const newData = [...prev]
- newData[index] = { ...newData[index - 1] }
- return newData
- })
+ setFormData((prev) => {
+ const newData = [...prev];
+ newData[index] = { ...newData[index - 1] };
+ return newData;
+ });
Taro.showToast({
- title: '复制上一场填入',
- icon: 'success'
- })
+ title: "复制上一场填入",
+ icon: "success",
+ });
}
- }
+ };
// 删除确认弹窗
const showDeleteConfirm = (index: number) => {
setDeleteConfirm({
visible: true,
- index
- })
- }
+ index,
+ });
+ };
// 关闭删除确认弹窗
const closeDeleteConfirm = () => {
setDeleteConfirm({
visible: false,
- index: -1
- })
- }
+ index: -1,
+ });
+ };
// 确认删除
const confirmDelete = () => {
if (deleteConfirm.index >= 0) {
- setFormData(prev => prev.filter((_, index) => index !== deleteConfirm.index))
- closeDeleteConfirm()
+ setFormData((prev) =>
+ prev.filter((_, index) => index !== deleteConfirm.index)
+ );
+ closeDeleteConfirm();
Taro.showToast({
- title: '已删除该场次',
- icon: 'success'
- })
+ title: "已删除该场次",
+ icon: "success",
+ });
}
- }
+ };
- const validateFormData = (formData: PublishBallFormData, isOnSubmit: boolean = false) => {
- const { activityInfo, title, timeRange, image_list, players, current_players } = formData;
+ const validateFormData = (
+ formData: PublishBallFormData,
+ isOnSubmit: boolean = false
+ ) => {
+ const {
+ activityInfo,
+ title,
+ timeRange,
+ image_list,
+ players,
+ current_players,
+ } = formData;
const { play_type, price, location_name } = activityInfo;
- const { max } = players;
- if (!image_list?.length && activityType === 'group') {
+ const { max } = players;
+ if (!image_list?.length && activityType === "group") {
if (!isOnSubmit) {
Taro.showToast({
title: `请上传活动封面`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
// 判断图片是否上传完成
if (image_list?.length > 0) {
@@ -209,117 +236,135 @@ const PublishBall: React.FC = () => {
if (!isOnSubmit) {
Taro.showToast({
title: `请输入活动标题`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
- if (!price || (typeof price === 'number' && price <= 0) || (typeof price === 'string' && !price.trim())) {
+ if (
+ !price ||
+ (typeof price === "number" && price <= 0) ||
+ (typeof price === "string" && !price.trim())
+ ) {
if (!isOnSubmit) {
Taro.showToast({
title: `请输入费用`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
if (!play_type || !play_type.trim()) {
if (!isOnSubmit) {
Taro.showToast({
title: `请选择玩法类型`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
if (!location_name || !location_name.trim()) {
if (!isOnSubmit) {
Taro.showToast({
title: `请选择场地`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
// 时间范围校验:结束时间需晚于开始时间,且至少间隔30分钟(支持跨天)
if (timeRange?.start_time && timeRange?.end_time) {
- const start = dayjs(timeRange.start_time)
- const end = dayjs(timeRange.end_time)
- const currentTime = dayjs()
+ const start = dayjs(timeRange.start_time);
+ const end = dayjs(timeRange.end_time);
+ const currentTime = dayjs();
if (!end.isAfter(start)) {
if (!isOnSubmit) {
Taro.showToast({
title: `结束时间需晚于开始时间`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
- if (end.isBefore(start.add(30, 'minute'))) {
+ if (end.isBefore(start.add(30, "minute"))) {
if (!isOnSubmit) {
Taro.showToast({
title: `时间间隔至少30分钟`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
if (start.isBefore(currentTime)) {
if (!isOnSubmit) {
Taro.showToast({
title: `开始时间需晚于当前时间`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
if (end.isBefore(currentTime)) {
if (!isOnSubmit) {
Taro.showToast({
title: `结束时间需晚于当前时间`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
}
- if (current_players && (current_players > max)) {
+ if (current_players && current_players > max) {
if (!isOnSubmit) {
Taro.showToast({
title: `最大人数不能小于当前参与人数${current_players}`,
- icon: 'none'
- })
+ icon: "none",
+ });
}
- return false
+ return false;
}
- return true
- }
+ return true;
+ };
const validateOnSubmit = () => {
- const isValid = activityType === 'individual' ? validateFormData(formData[0], true) : formData.every(item => validateFormData(item, true))
+ const isValid =
+ activityType === "individual"
+ ? validateFormData(formData[0], true)
+ : formData.every((item) => validateFormData(item, true));
if (!isValid) {
- return false
+ return false;
}
- return true
- }
+ return true;
+ };
const getParams = () => {
- const currentInstance = Taro.getCurrentInstance()
- const params = currentInstance.router?.params
- return params
- }
+ const currentInstance = Taro.getCurrentInstance();
+ const params = currentInstance.router?.params;
+ return params;
+ };
// 提交表单
const handleSubmit = async () => {
// 基础验证
- console.log(formData, 'formData');
- const params = getParams()
+ console.log(formData, "formData");
+ const params = getParams();
const { republish } = params || {};
- if (activityType === 'individual') {
- const isValid = validateFormData(formData[0])
+ if (activityType === "individual") {
+ const isValid = validateFormData(formData[0]);
if (!isValid) {
- return
+ return;
}
- const { activityInfo, descriptionInfo,is_substitute_supported, timeRange, players, skill_level, image_list, wechat, id, ...rest } = formData[0];
+ const {
+ activityInfo,
+ descriptionInfo,
+ is_substitute_supported,
+ timeRange,
+ players,
+ skill_level,
+ image_list,
+ wechat,
+ id,
+ ...rest
+ } = formData[0];
const { min, max, organizer_joined } = players;
const options = {
...rest,
@@ -331,50 +376,69 @@ const PublishBall: React.FC = () => {
organizer_joined: organizer_joined === true ? 1 : 0,
skill_level_min: skill_level[0],
skill_level_max: skill_level[1],
- image_list: image_list.map(item => item.url),
+ image_list: image_list.map((item) => item.url),
is_wechat_contact: wechat.is_wechat_contact ? 1 : 0,
wechat_contact: wechat.wechat_contact || wechat.default_wechat_contact,
- is_substitute_supported: is_substitute_supported ? '1' : '0',
- ...(republish === '0' ? { id } : {}),
- }
- const res = republish === '0' ? await PublishService.gamesUpdate(options) : await PublishService.createPersonal(options);
- const successText = republish === '0' ? '更新成功' : '发布成功';
+ is_substitute_supported: is_substitute_supported ? "1" : "0",
+ ...(republish === "0" ? { id } : {}),
+ };
+ const res =
+ republish === "0"
+ ? await PublishService.gamesUpdate(options)
+ : await PublishService.createPersonal(options);
+ const successText = republish === "0" ? "更新成功" : "发布成功";
if (res.code === 0 && res.data) {
Taro.showToast({
title: successText,
- icon: 'success'
- })
- delay(1000)
+ icon: "success",
+ });
+ delay(1000);
// 如果是个人球局,则跳转到详情页,并自动分享
// 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰
const id = (res as any).data?.id;
- Taro.navigateTo({
- // @ts-expect-error: id
- url: `/game_pages/detail/index?id=${id || 1}&from=publish&autoShare=1`
- })
+ // 如果是编辑,就返回,否则就是新发布
+ if (republish === "0") {
+ Taro.navigateBack();
+ } else {
+ Taro.navigateTo({
+ // @ts-expect-error: id
+ url: `/game_pages/detail/index?id=${
+ id || 1
+ }&from=publish&autoShare=1`,
+ });
+ }
} else {
Taro.showToast({
title: res.message,
- icon: 'none'
- })
+ icon: "none",
+ });
}
}
- if (activityType === 'group') {
- const isValid = formData.every(item => validateFormData(item))
+ if (activityType === "group") {
+ const isValid = formData.every((item) => validateFormData(item));
if (!isValid) {
- return
+ return;
}
if (checkAdjacentDataSame(formData)) {
Taro.showToast({
- title: '信息不可与前序场完全一致',
- icon: 'none'
- })
- return
+ title: "信息不可与前序场完全一致",
+ icon: "none",
+ });
+ return;
}
const options = formData.map((item) => {
- const { activityInfo, descriptionInfo, timeRange, players, skill_level, is_substitute_supported, id, ...rest } = item;
+ const {
+ activityInfo,
+ descriptionInfo,
+ timeRange,
+ players,
+ skill_level,
+ is_substitute_supported,
+ id,
+ ...rest
+ } = item;
const { min, max, organizer_joined } = players;
- return {
+ return {
...rest,
...activityInfo,
...descriptionInfo,
@@ -384,267 +448,362 @@ const PublishBall: React.FC = () => {
organizer_joined: organizer_joined === true ? 1 : 0,
skill_level_min: skill_level[0],
skill_level_max: skill_level[1],
- is_substitute_supported: is_substitute_supported ? '1' : '0',
- image_list: item.image_list.map(img => img.url),
- ...(republish === '0' ? { id } : {}),
- }
- })
- const successText = republish === '0' ? '更新成功' : '发布成功';
- const res = republish === '0' ? await PublishService.gamesUpdate(options[0]) : await PublishService.create_play_pmoothlys({rows: options});
+ is_substitute_supported: is_substitute_supported ? "1" : "0",
+ image_list: item.image_list.map((img) => img.url),
+ ...(republish === "0" ? { id } : {}),
+ };
+ });
+ const successText = republish === "0" ? "更新成功" : "发布成功";
+ const res =
+ republish === "0"
+ ? await PublishService.gamesUpdate(options[0])
+ : await PublishService.create_play_pmoothlys({ rows: options });
if (res.code === 0 && res.data) {
Taro.showToast({
title: successText,
- icon: 'success'
- })
- delay(1000)
+ icon: "success",
+ });
+ delay(1000);
// 如果是个人球局,则跳转到详情页,并自动分享
// 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰
- const id = republish === '0' ? (res as any).data?.id : (res as any).data?.[0]?.id;
+ const id =
+ republish === "0"
+ ? (res as any).data?.id
+ : (res as any).data?.[0]?.id;
Taro.navigateTo({
- // @ts-expect-error: id
- url: `/game_pages/detail/index?id=${id || 1}&from=publish&autoShare=1`
- })
+ // @ts-expect-error: id
+ url: `/game_pages/detail/index?id=${
+ id || 1
+ }&from=publish&autoShare=1`,
+ });
} else {
Taro.showToast({
title: res.message,
- icon: 'none'
- })
+ icon: "none",
+ });
}
}
- }
+ };
- const mergeWithDefault = (data: any, isDetail: boolean = false): PublishBallFormData => {
+ const mergeWithDefault = (
+ data: any,
+ isDetail: boolean = false
+ ): PublishBallFormData => {
// ai导入与详情数据处理
- const { start_time, end_time, play_type, price, venue_id, location_name, location, latitude,
- longitude, court_type, court_surface, venue_description_tag, venue_description, venue_image_list,
- description, description_tag, max_players, min_players, skill_level_max, skill_level_min,
- venueDtl, wechat_contact, image_list, id: publish_id, is_wechat_contact,
- is_substitute_supported, title, current_players, organizer_joined
- } = data;
- const level_max = skill_level_max ? Number(skill_level_max) : 5.0;
- const level_min = skill_level_min ? Number(skill_level_min) : 1.0;
- const userPhone = wechat_contact || (userInfo as any)?.phone || ''
- let activityInfo = {};
- if (venueDtl) {
- const { latitude, longitude,venue_type, surface_type, facilities, name, id } = venueDtl;
- activityInfo = {
- latitude,
- longitude,
- court_type: venue_type,
- court_surface: surface_type,
- venue_description: facilities,
- location_name: name,
- venue_id: id
- }
- }
- if (isDetail) {
- activityInfo = {
- venue_id,
- location_name,
- location,
- latitude,
- longitude,
- court_type,
- court_surface,
- venue_description_tag,
- venue_description,
- venue_image_list
- }
- }
- return {
- ...defaultFormData,
- title,
- ...(is_substitute_supported === '0' ? { is_substitute_supported: false } : {}),
- ...(publish_id ? { id: publish_id } : {}),
- timeRange: {
- ...defaultFormData.timeRange,
- start_time,
- end_time,
- },
- activityInfo: {
- ...defaultFormData.activityInfo,
- ...(play_type ? { play_type } : {}),
- ...((price) ? { price } : {}),
- ...activityInfo
- },
- descriptionInfo: {
- ...defaultFormData.descriptionInfo,
- ...(description ? { description } : {}),
- ...(description_tag ? { description_tag } : {}),
- },
- ...(level_max && level_min ? { skill_level: [level_min, level_max] } : {}),
- ...(max_players && min_players ? { players: { min: min_players, max: max_players, organizer_joined: organizer_joined === 0 ? false : true } } : {}),
- wechat: { ...defaultFormData.wechat, default_wechat_contact: userPhone, is_wechat_contact: is_wechat_contact === 0 ? false : true},
- image_list: image_list?.map(item => ({ url: item, id: item })) || [],
- ...(current_players ? { current_players } : {}),
-
- }
+ const {
+ start_time,
+ end_time,
+ play_type,
+ price,
+ venue_id,
+ location_name,
+ location,
+ latitude,
+ longitude,
+ court_type,
+ court_surface,
+ venue_description_tag,
+ venue_description,
+ venue_image_list,
+ description,
+ description_tag,
+ max_players,
+ min_players,
+ skill_level_max,
+ skill_level_min,
+ venueDtl,
+ wechat_contact,
+ image_list,
+ id: publish_id,
+ is_wechat_contact,
+ is_substitute_supported,
+ title,
+ current_players,
+ organizer_joined,
+ } = data;
+ const level_max = skill_level_max ? Number(skill_level_max) : 5.0;
+ const level_min = skill_level_min ? Number(skill_level_min) : 1.0;
+ const userPhone = wechat_contact || (userInfo as any)?.phone || "";
+ let activityInfo = {};
+ if (venueDtl) {
+ const {
+ latitude,
+ longitude,
+ venue_type,
+ surface_type,
+ facilities,
+ name,
+ id,
+ } = venueDtl;
+ activityInfo = {
+ latitude,
+ longitude,
+ court_type: venue_type,
+ court_surface: surface_type,
+ venue_description: facilities,
+ location_name: name,
+ venue_id: id,
+ };
}
+ if (isDetail) {
+ activityInfo = {
+ venue_id,
+ location_name,
+ location,
+ latitude,
+ longitude,
+ court_type,
+ court_surface,
+ venue_description_tag,
+ venue_description,
+ venue_image_list,
+ };
+ }
+ return {
+ ...defaultFormData,
+ title,
+ ...(is_substitute_supported === "0"
+ ? { is_substitute_supported: false }
+ : {}),
+ ...(publish_id ? { id: publish_id } : {}),
+ timeRange: {
+ ...defaultFormData.timeRange,
+ start_time,
+ end_time,
+ },
+ activityInfo: {
+ ...defaultFormData.activityInfo,
+ ...(play_type ? { play_type } : {}),
+ ...(price ? { price } : {}),
+ ...activityInfo,
+ },
+ descriptionInfo: {
+ ...defaultFormData.descriptionInfo,
+ ...(description ? { description } : {}),
+ ...(description_tag ? { description_tag } : {}),
+ },
+ ...(level_max && level_min
+ ? { skill_level: [level_min, level_max] }
+ : {}),
+ ...(max_players && min_players
+ ? {
+ players: {
+ min: min_players,
+ max: max_players,
+ organizer_joined: organizer_joined === 0 ? false : true,
+ },
+ }
+ : {}),
+ wechat: {
+ ...defaultFormData.wechat,
+ default_wechat_contact: userPhone,
+ is_wechat_contact: is_wechat_contact === 0 ? false : true,
+ },
+ image_list: image_list?.map((item) => ({ url: item, id: item })) || [],
+ ...(current_players ? { current_players } : {}),
+ };
+ };
- const formatConfig = () => {
+ const formatConfig = () => {
const newFormSchema = publishBallFormSchema.reduce((acc, item) => {
- if (item.prop === 'wechat') {
- return acc
+ if (item.prop === "wechat") {
+ return acc;
}
- if (item.prop === 'image_list') {
+ if (item.prop === "image_list") {
if (item.props) {
- item.props.source = ['album', 'history']
+ item.props.source = ["album", "history"];
}
}
- if (item.prop === 'players') {
+ if (item.prop === "players") {
if (item.props) {
- item.props.max = 100
+ item.props.max = 100;
}
}
- acc.push(item)
- return acc
- }, [] as FormFieldConfig[])
- setOptionsConfig(newFormSchema)
- }
+ acc.push(item);
+ return acc;
+ }, [] as FormFieldConfig[]);
+ setOptionsConfig(newFormSchema);
+ };
const initFormData = () => {
- const params = getParams()
- const userPhone = (userInfo as any)?.phone || ''
+ const params = getParams();
+ const userPhone = (userInfo as any)?.phone || "";
if (params?.type) {
- const type = params.type as ActivityType
- if (type === 'individual' || type === 'group') {
- setActivityType(type)
- if (type === 'group') {
- formatConfig()
- setFormData([defaultFormData])
- setTitleBar('发布畅打活动')
+ const type = params.type as ActivityType;
+ if (type === "individual" || type === "group") {
+ setActivityType(type);
+ if (type === "group") {
+ formatConfig();
+ setFormData([defaultFormData]);
+ setTitleBar("发布畅打活动");
} else {
- setTitleBar('发布球局')
- setFormData([{...defaultFormData, wechat: { ...defaultFormData.wechat, default_wechat_contact: userPhone } }])
+ setTitleBar("发布球局");
+ setFormData([
+ {
+ ...defaultFormData,
+ wechat: {
+ ...defaultFormData.wechat,
+ default_wechat_contact: userPhone,
+ },
+ },
+ ]);
}
- } else if (type === 'ai') {
+ } else if (type === "ai") {
// 从 Store 注入 AI 生成的表单 JSON
- if (publishAiData && Array.isArray(publishAiData) && publishAiData.length > 0) {
+ if (
+ publishAiData &&
+ Array.isArray(publishAiData) &&
+ publishAiData.length > 0
+ ) {
Taro.showToast({
- title: '智能识别成功,请完善剩余信息',
- icon: 'none'
- })
- const merged = publishAiData.map(item => mergeWithDefault(item))
- setFormData(merged.length ? merged : [defaultFormData])
+ title: "智能识别成功,请完善剩余信息",
+ icon: "none",
+ });
+ const merged = publishAiData.map((item) => mergeWithDefault(item));
+ setFormData(merged.length ? merged : [defaultFormData]);
if (merged.length === 1) {
- setTitleBar('发布球局')
- setActivityType('individual')
+ setTitleBar("发布球局");
+ setActivityType("individual");
} else {
- formatConfig()
- setTitleBar('发布畅打活动')
- setActivityType('group')
+ formatConfig();
+ setTitleBar("发布畅打活动");
+ setActivityType("group");
}
} else {
- setFormData([defaultFormData])
- setTitleBar('发布球局')
- setActivityType('individual')
+ setFormData([defaultFormData]);
+ setTitleBar("发布球局");
+ setActivityType("individual");
}
}
}
if (params?.gameId) {
- getGameDetail(params.gameId)
+ getGameDetail(params.gameId);
}
- }
-
-
+ };
const getGameDetail = async (gameId) => {
if (!gameId) return;
try {
const res = await DetailService.getDetail(Number(gameId));
if (res.code === 0) {
- const merged = mergeWithDefault(res.data, true)
- setFormData([merged])
- if (res.data.game_type === '个人球局') {
- setTitleBar('发布球局')
- setActivityType('individual')
+ const merged = mergeWithDefault(res.data, true);
+ setFormData([merged]);
+ if (res.data.game_type === "个人球局") {
+ setTitleBar("发布球局");
+ setActivityType("individual");
} else {
- setTitleBar('发布畅打活动')
- setActivityType('group')
+ setTitleBar("发布畅打活动");
+ setActivityType("group");
}
}
} catch (e) {
- Taro.showToast({
+ Taro.showToast({
title: e.message,
- icon: 'none'
- })
+ icon: "none",
+ });
}
};
const onCheckedChange = (checked: boolean) => {
- setChecked(checked)
- }
+ setChecked(checked);
+ };
useEffect(() => {
- const isValid = validateOnSubmit()
+ const isValid = validateOnSubmit();
if (!isValid) {
- setIsSubmitDisabled(true)
+ setIsSubmitDisabled(true);
} else {
- setIsSubmitDisabled(false)
+ setIsSubmitDisabled(false);
}
- console.log(formData, 'formData');
- }, [formData])
+ console.log(formData, "formData");
+ }, [formData]);
useEffect(() => {
- initFormData()
- }, [])
+ initFormData();
+ }, []);
-// 使用全局键盘状态监听
-useEffect(() => {
- // 初始化全局键盘监听器
- initializeKeyboardListener()
+ // 使用全局键盘状态监听
+ useEffect(() => {
+ // 初始化全局键盘监听器
+ initializeKeyboardListener();
- // 添加本地监听器
- const removeListener = addListener((height, visible) => {
- console.log('PublishBall 收到键盘变化:', height, visible)
- // 这里只记录或用于其他逻辑,布局是否响应交由 shouldReactToKeyboard 决定
- })
+ // 添加本地监听器
+ const removeListener = addListener((height, visible) => {
+ console.log("PublishBall 收到键盘变化:", height, visible);
+ // 这里只记录或用于其他逻辑,布局是否响应交由 shouldReactToKeyboard 决定
+ });
- return () => {
- removeListener()
- }
-}, [initializeKeyboardListener, addListener])
+ return () => {
+ removeListener();
+ };
+ }, [initializeKeyboardListener, addListener]);
const handleAnyInputFocus = (item: FormFieldConfig, e: any) => {
- const { prop } = item
- if (prop === 'descriptionInfo') {
- setShouldReactToKeyboard(true)
+ const { prop } = item;
+ if (prop === "descriptionInfo") {
+ setShouldReactToKeyboard(true);
}
- }
+ };
const handleAnyInputBlur = () => {
- setShouldReactToKeyboard(false)
- }
+ setShouldReactToKeyboard(false);
+ };
return (
-
-
-
- {/* 活动类型切换 */}
- {/*
+
+
+
+ {/* 活动类型切换 */}
+ {/*
*/}
-
- {
- formData.map((item, index) => (
+
+ {formData.map((item, index) => (
{/* 场次标题行 */}
- {activityType === 'group' && index > 0 && (
-
-
- 第{index + 1}场
- 0 && (
+
+
+ 第{index + 1}场
+ showDeleteConfirm(index)}
>
-
-
+
-
-
+
{index > 0 && (
handleCopyPrevious(index)}
>
复制上一场
@@ -661,57 +820,65 @@ useEffect(() => {
onAnyInputBlur={handleAnyInputBlur}
/>
- ))
- }
- {
- activityType === 'group' && (
-
-
+ ))}
+ {activityType === "group" && (
+
+
再添加一场
- )
- }
-
+ )}
+
- {/* 删除确认弹窗 */}
-
- {/* 完成按钮 */}
-
-
- {
- activityType === 'individual' && (
-
+ {/* 删除确认弹窗 */}
+
+ {/* 完成按钮 */}
+
+
+ {activityType === "individual" && (
+
点击确定发布约球,即表示已经同意条款
- Taro.navigateTo({url: '/publish_pages/footballRules/index'})}>《约球规则》
+
+ Taro.navigateTo({ url: "/publish_pages/footballRules/index" })
+ }
+ >
+ 《约球规则》
+
- )
- }
- {
- activityType === 'group' && (
-
+ )}
+ {activityType === "group" && (
+
已认证 徐汇爱打球官方球场,请严格遵守签约协议
- )
- }
+ )}
+
-
- )
-}
+ );
+};
-export default withAuth(PublishBall)
+export default withAuth(PublishBall);
diff --git a/src/services/evaluateService.ts b/src/services/evaluateService.ts
index 60ca1fd..178577b 100644
--- a/src/services/evaluateService.ts
+++ b/src/services/evaluateService.ts
@@ -1,6 +1,12 @@
import httpService from "./httpService";
import type { ApiResponse } from "./httpService";
+export enum StageType {
+ INTRO = "intro",
+ TEST = "test",
+ RESULT = "result",
+}
+
// 单个选项类型
interface Option {
text: string;
diff --git a/src/store/evaluateStore.ts b/src/store/evaluateStore.ts
index eb49ac9..b08e264 100644
--- a/src/store/evaluateStore.ts
+++ b/src/store/evaluateStore.ts
@@ -10,18 +10,25 @@ export enum EvaluateScene {
}
export interface EvaluateCallback {
- type: EvaluateScene | ''
- next: (flag?: boolean) => void,
- onCancel: () => void,
+ type: EvaluateScene | "";
+ // flag是用来区分跳转ntrp测试后的操作和直接修改ntrp水平成功后的操作
+ // score是用在加入球局前判断是否满足球局要求的返回值,限定为必传
+ // next有两个地方调用:ntrp结果页handleGoon、ntrp弹窗(NTRPEvaluatePopup)直接修改点击保存按钮时
+ next: ({ flag, score }: { flag?: boolean; score: string }) => void;
+ onCancel: () => void;
}
export interface EvaluateCallbackType extends EvaluateCallback {
- setCallback: (options: { type: EvaluateScene | '', next: () => void, onCancel: () => void }) => void,
- clear: () => void,
+ setCallback: (options: {
+ type: EvaluateScene | "";
+ next: ({ flag, score }: { flag?: boolean; score: string }) => void;
+ onCancel: () => void;
+ }) => void;
+ clear: () => void;
}
export const useEvaluateCallback = create()((set) => ({
- type: '',
+ type: "",
next: () => { },
onCancel: () => { },
setCallback: ({ type, next, onCancel }) => {
@@ -29,15 +36,18 @@ export const useEvaluateCallback = create()((set) => ({
type,
next,
onCancel,
- })
+ });
+ },
+ clear: () => {
+ set({ type: "", next: () => { }, onCancel: () => { } });
},
- clear: () => { set({ type: '', next: () => { }, onCancel: () => { } }) }
}));
-export const useEvaluate = () => useEvaluateCallback(({ type, next, onCancel, setCallback, clear }) => ({
- type,
- next,
- onCancel,
- setCallback,
- clear,
-}))
+export const useEvaluate = () =>
+ useEvaluateCallback(({ type, next, onCancel, setCallback, clear }) => ({
+ type,
+ next,
+ onCancel,
+ setCallback,
+ clear,
+ }));
diff --git a/src/utils/helper.ts b/src/utils/helper.ts
index a223ad3..6e3df48 100644
--- a/src/utils/helper.ts
+++ b/src/utils/helper.ts
@@ -23,4 +23,35 @@ export const sceneRedirectLogic = (options, defaultPage: string) => {
} catch (e) {
console.error(e);
}
-};
\ No newline at end of file
+};
+
+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 "-";
+}
\ No newline at end of file
diff --git a/types/ntrp-evaluate.ts b/types/ntrp-evaluate.ts
new file mode 100644
index 0000000..2f9dbab
--- /dev/null
+++ b/types/ntrp-evaluate.ts
@@ -0,0 +1,5 @@
+export enum StageType {
+ INTRO = "intro",
+ TEST = "test",
+ RESULT = "result",
+}
\ No newline at end of file