feat: 申请加入、退款政策、支付倒计时、详情页发布者信息展示

This commit is contained in:
2025-11-24 15:17:37 +08:00
parent 23fba49741
commit 6e03de0259
9 changed files with 642 additions and 145 deletions

View File

@@ -441,6 +441,44 @@
line-height: 20px;
border-top: 1px solid rgba(0, 0, 0, 0.06);
&.pastItem {
color: #3c3c43;
}
&.currentItem {
position: relative;
&::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 3px;
height: 100%;
background: #007aff;
z-index: 0;
}
&::after {
content: "";
position: absolute;
left: 3px;
top: 15px;
width: 0;
height: 0;
border-style: solid;
border-width: 3px 0 3px 6px;
border-color: transparent transparent transparent #007bff;
z-index: 0;
}
.currentTag {
color: #007aff;
font-size: 12px;
font-weight: 600;
line-height: 20px;
font-family: "pingfang SC";
text-align: left;
}
}
&:nth-child(1) {
color: #000;
text-align: center;
@@ -459,6 +497,11 @@
padding: 10px 12px;
}
.time {
text-align: left;
padding-left: 30px;
}
.rule {
border-left: 1px solid rgba(0, 0, 0, 0.06);
}

View File

@@ -82,6 +82,7 @@ function GameInfo(props) {
start_time,
end_time,
weather,
title,
} = detail || {};
const [{ iconDay, tempMax, tempMin }] = weather || [{}];
@@ -106,7 +107,9 @@ function GameInfo(props) {
const startTime = dayjs(start_time);
const endTime = dayjs(end_time);
const game_length = endTime.diff(startTime, "minutes") / 60;
const game_length = Number(
(endTime.diff(startTime, "minutes") / 60).toFixed()
);
const startMonth = startTime.format("M");
const startDay = startTime.format("D");
@@ -248,6 +251,11 @@ function GameInfo(props) {
{gameNotice.content && <Text>{gameNotice.content}</Text>}
</View>
)}
{!orderDetail.order_id && (
<View className={styles.gameStatus}>
<Text className={styles.statusText}>{title}</Text>
</View>
)}
<View className={styles.gameInfo}>
{/* Date and Weather */}
<View className={styles.gameInfoDateWeather}>
@@ -322,41 +330,32 @@ function GameInfo(props) {
</View>
</View>
{/* Action bar */}
<View className={styles.gameInfoActions}>
{orderDetail.order_id ? (
<>
{generateOrderActions(
orderDetail,
{
handleDeleteOrder,
handleCancelOrder,
handleQuit,
handlePayNow: () => {},
handleViewGame,
},
"detail"
)?.map((obj) => (
<View
className={classnames(styles.button, styles[obj.className])}
>
<Text className={styles.buttonText}>{obj.text}</Text>
<Button
className={styles.transparentButton}
onClick={obj.action}
>
{obj.text}
</Button>
</View>
))}
<View className={styles.customer} onClick={handleCustomerService}>
<Image className={styles.customerIcon} src={CustomerIcon} />
<Text></Text>
{orderDetail.order_id && (
<View className={styles.gameInfoActions}>
{generateOrderActions(
orderDetail,
{
handleDeleteOrder,
handleCancelOrder,
handleQuit,
handlePayNow: () => {},
handleViewGame,
},
"detail"
)?.map((obj) => (
<View className={classnames(styles.button, styles[obj.className])}>
<Text className={styles.buttonText}>{obj.text}</Text>
<Button className={styles.transparentButton} onClick={obj.action}>
{obj.text}
</Button>
</View>
</>
) : (
""
)}
</View>
))}
<View className={styles.customer} onClick={handleCustomerService}>
<Image className={styles.customerIcon} src={CustomerIcon} />
<Text></Text>
</View>
</View>
)}
<Dialog id="detailCancelOrder" />
<RefundPopup ref={refundRef} />
</View>
@@ -489,6 +488,7 @@ function OrderMsg(props) {
function RefundPolicy(props) {
const { checkOrderInfo } = props;
const { refund_policy = [] } = checkOrderInfo;
const current = dayjs();
const policyList = [
{
time: "申请退款时间",
@@ -508,9 +508,11 @@ function RefundPolicy(props) {
return {
time: `${year}${month}${day}${time} ${isLast ? "后" : "前"}`,
rule: item.refund_rule,
beforeCurrent: isLast ? true : current.isBefore(theTimeObj),
};
}),
];
const targetIndex = policyList.findIndex((item) => item.beforeCurrent);
return (
<View className={styles.refundPolicy}>
<View className={styles.moduleTitle}>
@@ -519,8 +521,22 @@ function RefundPolicy(props) {
{/* 订单信息摘要 */}
<View className={styles.policyList}>
{policyList.map((item, index) => (
<View key={index} className={styles.policyItem}>
<View className={styles.time}>{item.time}</View>
<View
key={index}
className={classnames(
styles.policyItem,
targetIndex > index && index !== 0 ? styles.pastItem : "",
targetIndex === index ? styles.currentItem : ""
)}
>
<View className={styles.time}>
{targetIndex === index && (
<View className={styles.currentTag}>
<Text></Text>
</View>
)}
<Text>{item.time}</Text>
</View>
<View className={styles.rule}>{item.rule}</View>
</View>
))}
@@ -588,7 +604,7 @@ const OrderCheck = () => {
if (!requireLoginWithPhone()) {
throw new Error("请先绑定手机号");
}
const unPaidRes = await orderService.getUnpaidOrder(detail.id);
if (unPaidRes.code === 0 && unPaidRes.data.has_unpaid_order) {
return unPaidRes.data.payment_params;

View File

@@ -151,7 +151,7 @@
.gameTitle {
display: flex;
align-items: center;
align-items: flex-start;
justify-content: space-between;
padding: 12px 15px 0;
@@ -168,12 +168,14 @@
}
.payNum {
width: 90px;
font-feature-settings: "liga" off, "clig" off;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 600;
line-height: 18px;
line-height: 26px;
text-align: right;
&.paid {
color: #000;
}
@@ -359,6 +361,45 @@
}
}
}
.payTipContainer {
margin-top: -8px;
display: flex;
justify-content: flex-end;
align-items: flex-start;
padding: 0 12px 14px 12px;
.payTip {
font-family: PingFang SC;
font-weight: 400;
font-style: Regular;
font-size: 12px;
line-height: 20px;
// letter-spacing: -0.23px;
padding: 4px 12px;
background-color: #f7f7f7;
border-radius: 4px;
position: relative;
&::before {
content: "";
position: absolute;
top: -6px;
right: 30px;
width: 0;
height: 0;
border-style: solid;
border-width: 0 4px 6px 4px;
border-color: transparent transparent #f7f7f7 transparent;
}
.timeLeft {
display: inline-block;
color: #ff3b30;
font-weight: 600;
padding: 0 4px;
}
}
}
}
}

View File

@@ -17,7 +17,11 @@ 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, genNTRPRequirementText, requireLoginWithPhone } from "@/utils/helper";
import {
insertDotInTags,
genNTRPRequirementText,
requireLoginWithPhone,
} from "@/utils/helper";
import styles from "./index.module.scss";
dayjs.locale("zh-cn");
@@ -115,7 +119,7 @@ const OrderList = () => {
if (!requireLoginWithPhone()) {
return; // 未登录或未绑定手机号,已跳转到登录页
}
try {
const unPaidRes = await orderService.getUnpaidOrder(item.game_info?.id);
if (unPaidRes.code === 0 && unPaidRes.data.has_unpaid_order) {
@@ -306,6 +310,12 @@ const OrderList = () => {
court_type,
} = game_info || {};
const diffMs = dayjs(item.expire_time).diff();
const mm = String(Math.floor(diffMs / 1000 / 60)).padStart(2, "0");
const ss = String(Math.floor((diffMs / 1000) % 60)).padStart(2, "0");
const timeLeft = `${mm}:${ss}`;
return (
<View key={item.id} className={styles.orderItem}>
<View
@@ -412,6 +422,20 @@ const OrderList = () => {
))}
</View>
</View>
{unPay && diffMs > 0 && (
<View className={styles.payTipContainer}>
<View className={styles.payTip}>
{current_players > 0 ? (
<Text>{`已有${current_players}人参加, `}</Text>
) : (
""
)}
<Text></Text>
<Text className={styles.timeLeft}>{timeLeft}</Text>
<Text></Text>
</View>
</View>
)}
</View>
);
})}