diff --git a/src/components/GameManagePopup/index.module.scss b/src/components/GameManagePopup/index.module.scss index 24fe1dc..eefab2e 100644 --- a/src/components/GameManagePopup/index.module.scss +++ b/src/components/GameManagePopup/index.module.scss @@ -24,4 +24,89 @@ border-top: 8px solid #f5f5f5; } } +} + +.centerContainer { + overflow: hidden; + .title { + padding-top: 24px; + color: #000; + text-align: center; + font-feature-settings: 'liga' off, 'clig' off; + font-family: "PingFang SC"; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 20px; + } + + .content { + padding: 24px 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .tips { + color: rgba(60, 60, 67, 0.60); + font-feature-settings: 'liga' off, 'clig' off; + font-family: "PingFang SC"; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; + } + + .cancelReason { + width: 100%; + margin-top: 8px; + padding: 8px; + border-radius: 4px; + background: #F0F0F0; + + .input { + width: 100%; + &:placeholder-shown { + color: rgba(60, 60, 67, 0.30); + font-feature-settings: 'liga' off, 'clig' off; + font-family: "PingFang SC"; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 24px; + } + } + } + } + + .actions { + display: flex; + justify-content: space-between; + align-items: center; + height: 44px; + border-top: 0.5px solid #CECECE; + background: #FFF; + margin-top: 2px; + + .confirm, .cancel { + width: 50%; + height: 44px; + display: flex; + justify-content: center; + align-items: center; + color: #000; + text-align: center; + font-feature-settings: 'liga' off, 'clig' off; + font-family: "PingFang SC"; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: 20px; + + &.cancel { + background-color: #000; + color: #fff; + } + } + } } \ No newline at end of file diff --git a/src/components/GameManagePopup/index.tsx b/src/components/GameManagePopup/index.tsx index 446b95f..e4c7283 100644 --- a/src/components/GameManagePopup/index.tsx +++ b/src/components/GameManagePopup/index.tsx @@ -5,26 +5,56 @@ import React, { useRef, } from "react"; import Taro from "@tarojs/taro"; -import { View } from "@tarojs/components"; +import { View, Text, Input } from "@tarojs/components"; import CommonPopup from "../CommonPopup"; import styles from "./index.module.scss"; -import detailService from "@/services/detailService"; +import detailService, { MATCH_STATUS } from "@/services/detailService"; import { useUserInfo } from "@/store/userStore"; const CancelPopup = forwardRef((props, ref) => { + const { detail } = props; const [visible, setVisible] = useState(false); + const [cancelReason, setCancelReason] = useState(""); const onFinish = useRef(null); + const inputRef = useRef(null); + + const { current_players, participants = [], publisher_id } = detail; + const realParticipants = participants + .filter((item) => item.status === "joined") + .map((item) => item.user.id); + const hasOtherJoin = + current_players > 1 || + realParticipants.some((id) => id !== Number(publisher_id)); + // const hasOtherJoin = true; useImperativeHandle(ref, () => ({ show: (onAct) => { onFinish.current = onAct; setVisible(true); + setTimeout(() => { + inputRef.current.focus(); + }, 0); }, })); function onClose() { setVisible(false); + setCancelReason(""); } + + async function handleConfirm() { + if (!cancelReason) { + Taro.showToast({ title: "请输入取消原因", icon: "none" }); + return; + } + try { + await onFinish.current(cancelReason); + onClose(); + } catch (e) { + console.log(e, 1221); + } + } + return ( <> { zIndex={1002} enableDragToClose={false} onClose={onClose} + position="center" + style={{ + width: hasOtherJoin ? "360px" : "300px", + borderRadius: "16px", + }} > - + + 确定要取消活动吗? + + + {hasOtherJoin + ? "已有球友报名,取消后将为他们自动退款" + : "有100+球友正在浏览您的球局哦~"} + + {hasOtherJoin && ( + + setCancelReason(e.detail.value)} + /> + + )} + + + + 确认取消 + + + 再想想 + + + ); @@ -60,7 +124,7 @@ export default forwardRef(function GameManagePopup(props, ref) { Taro.navigateTo({ url: `/publish_pages/publishBall/index?gameId=${detail.id}`, }); - onClose() + onClose(); } const handleRepubGame = handleEditGame; @@ -79,11 +143,11 @@ export default forwardRef(function GameManagePopup(props, ref) { } } catch (e) { Taro.showToast({ title: e.message, icon: "error" }); - } finally { - onClose(); + return e; } } }); + onClose(); } async function handleQuitGame() { @@ -107,7 +171,13 @@ export default forwardRef(function GameManagePopup(props, ref) { setVisible(false); } - const hasJoin = (detail.participants || []).some(item => item.user.id === userInfo.id) + const hasJoin = (detail.participants || []) + .filter((item) => item.status === "joined") + .some((item) => item.user.id === userInfo.id); + + const finished = [MATCH_STATUS.FINISHED, MATCH_STATUS.CANCELED].includes( + detail.match_status + ); return ( <> @@ -126,9 +196,11 @@ export default forwardRef(function GameManagePopup(props, ref) { 重新发布 - - 取消活动 - + {!finished && ( + + 取消活动 + + )} {hasJoin && ( 退出活动 @@ -139,7 +211,7 @@ export default forwardRef(function GameManagePopup(props, ref) { - + ); }); diff --git a/src/game_pages/detail/index.scss b/src/game_pages/detail/index.scss index d851af7..1f92417 100644 --- a/src/game_pages/detail/index.scss +++ b/src/game_pages/detail/index.scss @@ -1130,19 +1130,26 @@ // padding: 2px 6px; box-sizing: border-box; justify-content: center; - gap: 12px; + // gap: 12px; flex: 1 0 0; border-radius: 16px; // border: 1px solid rgba(0, 0, 0, 0.06); background: #fff; overflow: hidden; + &.disabled { + background-color: #B4B4B4; + color: rgba(60, 60, 67, 0.60); + pointer-events: none; + } + .sticky-bottom-bar-join-game { margin-left: auto; - width: 151px; + // width: 151px; display: flex; align-items: center; justify-content: center; + flex: 1; &-price { font-family: "PoetsenOne"; @@ -1163,6 +1170,7 @@ justify-content: center; background: #000; color: #fff; + pointer-events: all; } } } diff --git a/src/game_pages/detail/index.tsx b/src/game_pages/detail/index.tsx index 4ca90a9..88f8fef 100644 --- a/src/game_pages/detail/index.tsx +++ b/src/game_pages/detail/index.tsx @@ -13,6 +13,7 @@ import Taro, { useShareTimeline, useDidShow, } from "@tarojs/taro"; +import classnames from 'classnames' import dayjs from "dayjs"; import "dayjs/locale/zh-cn"; // 导入API服务 @@ -27,7 +28,7 @@ import { SceneType, DisplayConditionType, } from "@/components/NTRPEvaluatePopup"; -import DetailService, { MATCH_STATUS } from "@/services/detailService"; +import DetailService, { MATCH_STATUS, IsSubstituteSupported } from "@/services/detailService"; import * as LoginService from "@/services/loginService"; import OrderService from "@/services/orderService"; import { getCurrentLocation, calculateDistance } from "@/utils/locationUtils"; @@ -228,11 +229,19 @@ function toast(message) { Taro.showToast({ title: message, icon: "none" }); } +function isFull (counts) { + const { max_players, current_players, max_substitute_players, current_substitute_count, is_substitute_supported } = counts + if (is_substitute_supported === IsSubstituteSupported.SUPPORT) { + return max_substitute_players === current_substitute_count + } + return max_players === current_players +} + // 底部操作栏 function StickyButton(props) { const { handleShare, handleJoinGame, detail, onStatusChange } = props; const ntrpRef = useRef(null); - const { id, price, user_action_status, end_time, is_organizer } = + const { id, price, user_action_status, match_status, start_time, end_time, is_organizer } = detail || {}; const gameManageRef = useRef(); @@ -244,7 +253,7 @@ function StickyButton(props) { function generateTextAndAction( user_action_status: null | { [key: string]: boolean } - ): undefined | { text: string | React.FC; action: () => void } { + ): undefined | { text: string | React.FC; action?: () => void; available?: boolean } { if (!user_action_status) { return; } @@ -259,13 +268,29 @@ function StickyButton(props) { is_substituting, waiting_start, } = user_action_status || {}; - if ( - Object.values(user_action_status).every((value) => !value) && - dayjs(end_time).isBefore(dayjs()) - ) { + if (MATCH_STATUS.CANCELED === match_status) { + return { + text: "活动已取消", + available: false, + // action: () => toast("活动已取消"), + }; + } else if (dayjs(end_time).isBefore(dayjs())) { return { text: "活动已结束", - action: () => toast("活动已结束"), + available: false, + // action: () => toast("活动已结束"), + }; + } else if (dayjs(start_time).isBefore(dayjs())) { + return { + text: "活动已开始", + available: false, + // action: () => toast("活动已开始"), + }; + } else if (isFull(detail)) { + return { + text: "活动已满员", + available: false, + // action: () => toast("活动已满员"), }; } if (waiting_start) { @@ -284,7 +309,9 @@ function StickyButton(props) { action: async () => { const res = await OrderService.getUnpaidOrder(id); if (res.code === 0) { - navto(`/order_pages/orderDetail/index?id=${res.data.order_info.order_id}`); + navto( + `/order_pages/orderDetail/index?id=${res.data.order_info.order_id}` + ); } }, }; @@ -317,7 +344,8 @@ function StickyButton(props) { } return { text: "球局无法加入", - action: () => {}, + available: false, + // action: () => {}, }; } @@ -325,7 +353,7 @@ function StickyButton(props) { return ""; } - const { text, action } = generateTextAndAction(user_action_status)!; + const { text, available = true, action = () => {} } = generateTextAndAction(user_action_status)!; let ActionText: React.FC | string = text; @@ -360,8 +388,12 @@ function StickyButton(props) { 32 - - + + {is_organizer && ( diff --git a/src/order_pages/orderDetail/index.module.scss b/src/order_pages/orderDetail/index.module.scss index 3c518c1..abe0d98 100644 --- a/src/order_pages/orderDetail/index.module.scss +++ b/src/order_pages/orderDetail/index.module.scss @@ -326,6 +326,17 @@ justify-content: center; gap: 8px; } + + .orderNo { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 8px; + + .copy { + color: #007AFF; + } + } } } } @@ -503,3 +514,15 @@ border-radius: 0; } } + +.cancelTip { + padding: 12px 15px; + color: rgba(60, 60, 67, 0.60); + text-align: center; + font-feature-settings: 'liga' off, 'clig' off; + font-family: "PingFang SC"; + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 24px; +} diff --git a/src/order_pages/orderDetail/index.tsx b/src/order_pages/orderDetail/index.tsx index 0bfacfa..6890c8a 100644 --- a/src/order_pages/orderDetail/index.tsx +++ b/src/order_pages/orderDetail/index.tsx @@ -3,6 +3,7 @@ import { View, Text, Button, Image } from "@tarojs/components"; import { Dialog } from "@nutui/nutui-react-taro"; import Taro, { useDidShow, useRouter } from "@tarojs/taro"; import dayjs from "dayjs"; +import "dayjs/locale/zh-cn"; import classnames from "classnames"; import orderService, { CancelType, @@ -64,11 +65,13 @@ function genGameNotice(order_status, start_time) { } else if (leftHour < 2) { key = "pendinging"; } + return gameNoticeMap.get(key) || {}; } function GameInfo(props) { const { detail, currentLocation, orderDetail } = props; + console.log(orderDetail, "orderDetail"); const { order_status, refund_status } = orderDetail; const { latitude, longitude, location, location_name, start_time, end_time } = detail || {}; @@ -142,7 +145,11 @@ function GameInfo(props) { }; Dialog.open("detailCancelOrder", { title: "确定删除订单吗?", - content: "删除订单后,您将无法恢复订单。请确认是否继续取消?", + content: ( + + 删除订单后,您将无法恢复订单。请确认是否继续取消? + + ), footer: (