Merge branch 'feat/liujie'
This commit is contained in:
@@ -18,10 +18,53 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gameInfoContainer {
|
.gameInfoContainer {
|
||||||
.gameInfo {
|
|
||||||
border-top-left-radius: 12px;
|
|
||||||
border-top-right-radius: 12px;
|
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.paidInfo {
|
||||||
|
border-bottom: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||||
|
padding: 8px 12px;
|
||||||
|
color: #000;
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 28px;
|
||||||
|
letter-spacing: -0.23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gameStatus {
|
||||||
|
padding: 12px 12px 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
color: rgba(60, 60, 67, 0.6);
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: -0.23px;
|
||||||
|
|
||||||
|
.statusText {
|
||||||
|
color: #000;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gameInfo {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -186,11 +229,7 @@
|
|||||||
|
|
||||||
.gameInfoActions {
|
.gameInfoActions {
|
||||||
min-height: 12px;
|
min-height: 12px;
|
||||||
/* height: 12px; */
|
|
||||||
background-color: #fff;
|
|
||||||
border-top: 0.5px solid rgba(0, 0, 0, 0.06);
|
border-top: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||||
border-bottom-left-radius: 12px;
|
|
||||||
border-bottom-right-radius: 12px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,18 @@ import React, { useState } from "react";
|
|||||||
import { View, Text, Button, Image } from "@tarojs/components";
|
import { View, Text, Button, Image } from "@tarojs/components";
|
||||||
import Taro, { useDidShow, useRouter } from "@tarojs/taro";
|
import Taro, { useDidShow, useRouter } from "@tarojs/taro";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { delay } from "@/utils";
|
|
||||||
import orderService, {
|
import orderService, {
|
||||||
GameOrderRes,
|
GameOrderRes,
|
||||||
OrderStatus,
|
OrderStatus,
|
||||||
} from "@/services/orderService";
|
} from "@/services/orderService";
|
||||||
|
import {
|
||||||
|
payOrder,
|
||||||
|
delay,
|
||||||
|
calculateDistance,
|
||||||
|
getCurrentLocation,
|
||||||
|
} from "@/utils";
|
||||||
import detailService, { GameData } from "@/services/detailService";
|
import detailService, { GameData } from "@/services/detailService";
|
||||||
import { withAuth } from "@/components";
|
import { withAuth } from "@/components";
|
||||||
import { calculateDistance, getCurrentLocation } from "@/utils";
|
|
||||||
import img from "@/config/images";
|
import img from "@/config/images";
|
||||||
import { DECLAIMER } from "./config";
|
import { DECLAIMER } from "./config";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
@@ -17,7 +21,8 @@ import styles from "./index.module.scss";
|
|||||||
dayjs.locale("zh-cn");
|
dayjs.locale("zh-cn");
|
||||||
|
|
||||||
function GameInfo(props) {
|
function GameInfo(props) {
|
||||||
const { detail, currentLocation } = props;
|
const { detail, currentLocation, orderDetail } = props;
|
||||||
|
const { order_status } = orderDetail;
|
||||||
const { latitude, longitude, location, location_name, start_time, end_time } =
|
const { latitude, longitude, location, location_name, start_time, end_time } =
|
||||||
detail || {};
|
detail || {};
|
||||||
|
|
||||||
@@ -49,6 +54,15 @@ function GameInfo(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={styles.gameInfoContainer}>
|
<View className={styles.gameInfoContainer}>
|
||||||
|
{order_status !== OrderStatus.PENDING && (
|
||||||
|
<>
|
||||||
|
<View className={styles.paidInfo}>已支付 ¥ 90</View>
|
||||||
|
<View className={styles.gameStatus}>
|
||||||
|
<Text className={styles.statusText}>球局暂未开始</Text>
|
||||||
|
<Text>球局开始前2小时,我们将通过短信通知你</Text>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<View className={styles.gameInfo}>
|
<View className={styles.gameInfo}>
|
||||||
{/* Date and Weather */}
|
{/* Date and Weather */}
|
||||||
<View className={styles.gameInfoDateWeather}>
|
<View className={styles.gameInfoDateWeather}>
|
||||||
@@ -150,7 +164,7 @@ function OrderMsg(props) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "费用",
|
title: "费用",
|
||||||
content: `${price} 元`,
|
content: `${price} 元 / 人`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
@@ -259,53 +273,28 @@ const OrderCheck = () => {
|
|||||||
setLocation([location.latitude, location.longitude]);
|
setLocation([location.latitude, location.longitude]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getPaymentParams() {
|
||||||
|
const unPaidRes = await orderService.getUnpaidOrder(detail.id);
|
||||||
|
if (unPaidRes.code === 0 && unPaidRes.data.has_unpaid_order) {
|
||||||
|
return unPaidRes.data.payment_params;
|
||||||
|
}
|
||||||
|
const createOrderRes = await orderService.createOrder(detail.id);
|
||||||
|
if (createOrderRes.code === 0) {
|
||||||
|
return createOrderRes.data.payment_params;
|
||||||
|
}
|
||||||
|
throw new Error("支付调用失败");
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: get order msg from id
|
//TODO: get order msg from id
|
||||||
const handlePay = async () => {
|
const handlePay = async () => {
|
||||||
Taro.showLoading({
|
Taro.showLoading({
|
||||||
title: "支付中...",
|
title: "支付中...",
|
||||||
mask: true,
|
mask: true,
|
||||||
});
|
});
|
||||||
let wxPayRes: any = {};
|
|
||||||
try {
|
|
||||||
if (orderDetail.game_info?.id) {
|
|
||||||
const res = await orderService.getUnpaidOrder(orderDetail.game_info.id);
|
|
||||||
if (res.code === 0) {
|
|
||||||
wxPayRes = {
|
|
||||||
...res.data,
|
|
||||||
payment_required: res.data.has_unpaid_order,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const res = await orderService.createOrder(detail.id);
|
|
||||||
if (res.code === 0) {
|
|
||||||
wxPayRes = res.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
Taro.hideLoading();
|
|
||||||
Taro.showToast({
|
|
||||||
title: "支付调用失败",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { payment_required, payment_params } = wxPayRes;
|
try {
|
||||||
if (payment_required) {
|
const payment_params = await getPaymentParams();
|
||||||
const {
|
await payOrder(payment_params);
|
||||||
timeStamp,
|
|
||||||
nonceStr,
|
|
||||||
package: package_,
|
|
||||||
signType,
|
|
||||||
paySign,
|
|
||||||
} = payment_params;
|
|
||||||
await Taro.requestPayment({
|
|
||||||
timeStamp,
|
|
||||||
nonceStr,
|
|
||||||
package: package_,
|
|
||||||
signType,
|
|
||||||
paySign,
|
|
||||||
success: async () => {
|
|
||||||
Taro.hideLoading();
|
Taro.hideLoading();
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
title: "支付成功",
|
title: "支付成功",
|
||||||
@@ -315,15 +304,12 @@ const OrderCheck = () => {
|
|||||||
Taro.navigateBack({
|
Taro.navigateBack({
|
||||||
delta: 1,
|
delta: 1,
|
||||||
});
|
});
|
||||||
},
|
} catch (error) {
|
||||||
fail: () => {
|
|
||||||
Taro.hideLoading();
|
Taro.hideLoading();
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
title: "支付失败",
|
title: error.message,
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!id && !gameId) {
|
if (!id && !gameId) {
|
||||||
@@ -344,23 +330,22 @@ const OrderCheck = () => {
|
|||||||
return (
|
return (
|
||||||
<View className={styles.container}>
|
<View className={styles.container}>
|
||||||
{/* Game Date and Address */}
|
{/* Game Date and Address */}
|
||||||
<GameInfo detail={detail} currentLocation={location} />
|
<GameInfo
|
||||||
|
detail={detail}
|
||||||
|
orderDetail={orderDetail}
|
||||||
|
currentLocation={location}
|
||||||
|
/>
|
||||||
{/* Order message */}
|
{/* Order message */}
|
||||||
<OrderMsg detail={detail} checkOrderInfo={checkOrderInfo} />
|
<OrderMsg detail={detail} checkOrderInfo={checkOrderInfo} />
|
||||||
{/* Refund policy */}
|
{/* Refund policy */}
|
||||||
<RefundPolicy checkOrderInfo={checkOrderInfo} />
|
<RefundPolicy checkOrderInfo={checkOrderInfo} />
|
||||||
{/* Disclaimer */}
|
{/* Disclaimer */}
|
||||||
<Disclaimer />
|
<Disclaimer />
|
||||||
{!id ||
|
{(!id || orderDetail.order_status === OrderStatus.PENDING) && (
|
||||||
(orderDetail.order_status === OrderStatus.PENDING && (
|
<Button className={styles.payButton} type="primary" onClick={handlePay}>
|
||||||
<Button
|
|
||||||
className={styles.payButton}
|
|
||||||
type="primary"
|
|
||||||
onClick={handlePay}
|
|
||||||
>
|
|
||||||
{orderDetail.order_status === OrderStatus.PENDING ? "继续" : ""}支付
|
{orderDetail.order_status === OrderStatus.PENDING ? "继续" : ""}支付
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@use '~@/scss/images.scss' as img;
|
@use "~@/scss/images.scss" as img;
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
@@ -18,6 +18,84 @@
|
|||||||
height: 18px;
|
height: 18px;
|
||||||
padding: 15px 15px 12px;
|
padding: 15px 15px 12px;
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.userInfo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nickName {
|
||||||
|
display: contents;
|
||||||
|
.nickNameText {
|
||||||
|
color: #000;
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
.arrowRight {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.paidInfo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.payTime {
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 18px;
|
||||||
|
|
||||||
|
&.paid {
|
||||||
|
color: rgba(60, 60, 67, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pending {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payNum {
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 18px;
|
||||||
|
&.paid {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pending {
|
||||||
|
color: #ff3b30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.gameInfo {
|
.gameInfo {
|
||||||
@@ -28,6 +106,112 @@
|
|||||||
height: 28px;
|
height: 28px;
|
||||||
padding: 12px 12px 15px;
|
padding: 12px 12px 15px;
|
||||||
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.extraActions {
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainActions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
& > .button {
|
||||||
|
padding: 4px 10px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||||
|
color: #000;
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: -0.23px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancelOrder {
|
||||||
|
}
|
||||||
|
|
||||||
|
.payNow {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.refundPolicy {
|
||||||
|
.moduleTitle {
|
||||||
|
display: flex;
|
||||||
|
padding: 15px 0 8px;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
align-self: stretch;
|
||||||
|
color: #000;
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: -0.23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policyList {
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.policyItem {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
color: #000;
|
||||||
|
text-align: center;
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
color: #000;
|
||||||
|
text-align: center;
|
||||||
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
|
font-family: "PingFang SC";
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 20px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time,
|
||||||
|
.rule {
|
||||||
|
width: 50%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rule {
|
||||||
|
border-left: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,44 +1,241 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from "react";
|
||||||
import { View, Text, Button } from '@tarojs/components'
|
import { View, Text, Button, Image } from "@tarojs/components";
|
||||||
import Taro, { useDidShow } from '@tarojs/taro'
|
import Taro, { useDidShow } from "@tarojs/taro";
|
||||||
import { delay } from '@/utils'
|
import { Avatar, Dialog } from "@nutui/nutui-react-taro";
|
||||||
import orderService from '@/services/orderService'
|
import dayjs from "dayjs";
|
||||||
import { withAuth } from '@/components'
|
import classnames from "classnames";
|
||||||
import styles from './index.module.scss'
|
import orderService, { OrderStatus, CancelType } from "@/services/orderService";
|
||||||
|
import { withAuth } from "@/components";
|
||||||
|
import { payOrder } from "@/utils";
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
import orderListArrowRight from "@/static/order/orderListArrowRight.svg";
|
||||||
|
|
||||||
const OrderList = () => {
|
const OrderList = () => {
|
||||||
const [list, setList] = useState([])
|
const [list, setList] = useState([]);
|
||||||
|
|
||||||
useDidShow(async () => {
|
useDidShow(() => {
|
||||||
const res = await orderService.getOrderList()
|
getOrders();
|
||||||
console.log(res)
|
});
|
||||||
|
|
||||||
|
async function getOrders() {
|
||||||
|
const res = await orderService.getOrderList();
|
||||||
|
console.log(res);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
setList(res.data.rows)
|
setList(res.data.rows);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
console.log(list, 'list')
|
async function handlePayNow(gameId) {
|
||||||
|
try {
|
||||||
|
const unPaidRes = await orderService.getUnpaidOrder(gameId);
|
||||||
|
if (unPaidRes.code === 0 && unPaidRes.data.has_unpaid_order) {
|
||||||
|
await payOrder(unPaidRes.data.payment_params);
|
||||||
|
getOrders();
|
||||||
|
} else {
|
||||||
|
throw new Error("支付调用失败");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e, 1111);
|
||||||
|
Taro.showToast({
|
||||||
|
title: e.message,
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCancelContent(checkOrderInfo) {
|
||||||
|
const { refund_policy = [] } = checkOrderInfo;
|
||||||
|
const policyList = [
|
||||||
|
{
|
||||||
|
time: "申请退款时间",
|
||||||
|
rule: "退款规则",
|
||||||
|
},
|
||||||
|
...refund_policy.map((item, index) => {
|
||||||
|
const [, theTime] = item.application_time.split("undefined ");
|
||||||
|
const theTimeObj = dayjs(theTime);
|
||||||
|
const year = theTimeObj.format("YYYY");
|
||||||
|
const month = theTimeObj.format("M");
|
||||||
|
const day = theTimeObj.format("D");
|
||||||
|
const time = theTimeObj.format("HH:MM");
|
||||||
|
return {
|
||||||
|
time: `${year}年${month}月${day}日${time}${index === 0 ? "前" : "后"}`,
|
||||||
|
rule: item.refund_rule,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<View className={styles.refundPolicy}>
|
||||||
|
<View className={styles.moduleTitle}>
|
||||||
|
<Text>退款政策</Text>
|
||||||
|
</View>
|
||||||
|
{/* 订单信息摘要 */}
|
||||||
|
<View className={styles.policyList}>
|
||||||
|
{policyList.map((item, index) => (
|
||||||
|
<View key={index} className={styles.policyItem}>
|
||||||
|
<View className={styles.time}>{item.time}</View>
|
||||||
|
<View className={styles.rule}>{item.rule}</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCancelOrder(item) {
|
||||||
|
const { order_no, order_status, game_info, amount } = item;
|
||||||
|
if (order_status === OrderStatus.PENDING) {
|
||||||
|
Dialog.open("cancelOrder", {
|
||||||
|
title: "确定取消订单吗?",
|
||||||
|
content: "取消订单后,您将无法恢复订单。请确认是否继续取消?",
|
||||||
|
onConfirm: async () => {
|
||||||
|
try {
|
||||||
|
const cancelRes = await orderService.cancelUnpaidOrder({
|
||||||
|
order_no,
|
||||||
|
cancel_reason: "用户主动取消",
|
||||||
|
});
|
||||||
|
if (cancelRes.code !== 0) {
|
||||||
|
throw new Error(cancelRes.message);
|
||||||
|
}
|
||||||
|
getOrders();
|
||||||
|
} catch (e) {
|
||||||
|
Taro.showToast({
|
||||||
|
title: e.message,
|
||||||
|
icon: "error",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
Dialog.close("cancelOrder");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
Dialog.close("cancelOrder");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await orderService.getCheckOrderInfo(game_info.id);
|
||||||
|
Dialog.open("cancelOrder", {
|
||||||
|
title: "确定取消订单吗?",
|
||||||
|
content: renderCancelContent(res.data),
|
||||||
|
onConfirm: async () => {
|
||||||
|
try {
|
||||||
|
const refundRes = await orderService.applicateRefund({
|
||||||
|
order_no,
|
||||||
|
refund_amount: amount,
|
||||||
|
refund_reason: "用户主动退款",
|
||||||
|
});
|
||||||
|
if (refundRes.code !== 0) {
|
||||||
|
throw new Error(refundRes.message);
|
||||||
|
}
|
||||||
|
getOrders();
|
||||||
|
} catch (e) {
|
||||||
|
Taro.showToast({
|
||||||
|
title: e.message,
|
||||||
|
icon: "error",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
Dialog.close("cancelOrder");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
Dialog.close("cancelOrder");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleViewOrderDetail(orderId) {
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: `/mod_user/orderDetail/index?id=${orderId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={styles.container}>
|
<View className={styles.container}>
|
||||||
{
|
{list.map((item) => {
|
||||||
list.map(item => {
|
const unPay = item.order_status === OrderStatus.PENDING;
|
||||||
|
const expired =
|
||||||
|
item.order_status === OrderStatus.FINISHED ||
|
||||||
|
[CancelType.TIMEOUT, CancelType.USER].includes(item.cancel_type);
|
||||||
|
const expiredTime = dayjs(item.expire_time).isSame(dayjs(), "day")
|
||||||
|
? dayjs(item.expire_time).format("HH:mm:ss")
|
||||||
|
: dayjs(item.expire_time).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
const showCancel =
|
||||||
|
item.order_status !== OrderStatus.FINISHED &&
|
||||||
|
item.cancel_type === CancelType.NONE;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View key={item.id} className={styles.orderItem}>
|
<View key={item.id} className={styles.orderItem}>
|
||||||
<View className={styles.orderTitle}></View>
|
<View className={styles.orderTitle}>
|
||||||
<View className={styles.gameInfo}>{item?.game_info?.title}</View>
|
<View className={styles.userInfo}>
|
||||||
|
<Avatar
|
||||||
|
className={styles.avatar}
|
||||||
|
src="https://img.yzcdn.cn/vant/cat.jpeg"
|
||||||
|
/>
|
||||||
|
<View className={styles.nickName}>
|
||||||
|
<Text className={styles.nickNameText}>Light</Text>
|
||||||
|
<Image
|
||||||
|
className={styles.arrowRight}
|
||||||
|
src={orderListArrowRight}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{expired ? (
|
||||||
|
""
|
||||||
|
) : (
|
||||||
|
<View className={styles.paidInfo}>
|
||||||
|
<Text
|
||||||
|
className={classnames(
|
||||||
|
styles.payTime,
|
||||||
|
styles[unPay ? "pending" : "paid"],
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{unPay
|
||||||
|
? `请在 ${expiredTime} 前支付`
|
||||||
|
: dayjs(item.pay_time).format("YYYY-MM-DD HH:mm:ss")}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
className={classnames(
|
||||||
|
styles.payNum,
|
||||||
|
styles[unPay ? "pending" : "paid"],
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{unPay ? "待支付" : "已支付"} ¥ {item.amount}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
className={styles.gameInfo}
|
||||||
|
onClick={handleViewOrderDetail.bind(null, item.id)}
|
||||||
|
>
|
||||||
|
{item?.game_info?.title}
|
||||||
|
</View>
|
||||||
<View className={styles.orderActions}>
|
<View className={styles.orderActions}>
|
||||||
<View></View>
|
<View className={styles.extraActions}></View>
|
||||||
<View>
|
<View className={styles.mainActions}>
|
||||||
<Button>取消订单</Button>
|
{showCancel && (
|
||||||
|
<Button
|
||||||
|
className={classnames(styles.button, styles.cancelOrder)}
|
||||||
|
onClick={handleCancelOrder.bind(null, item)}
|
||||||
|
>
|
||||||
|
取消订单
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{unPay && !expired && (
|
||||||
|
<Button
|
||||||
|
className={classnames(styles.button, styles.payNow)}
|
||||||
|
onClick={handlePayNow.bind(null, item.game_info.id)}
|
||||||
|
>
|
||||||
|
立即支付
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
})
|
})}
|
||||||
}
|
<Dialog id="cancelOrder" />
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default withAuth(OrderList)
|
export default withAuth(OrderList);
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ function insertDotInTags(tags: string[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function GameTags(props) {
|
function GameTags(props) {
|
||||||
const { detail } = props;
|
const { userInfo } = props;
|
||||||
|
const { avatar_url } = userInfo;
|
||||||
const tags = [
|
const tags = [
|
||||||
{
|
{
|
||||||
name: "🕙 急招",
|
name: "🕙 急招",
|
||||||
@@ -63,7 +64,7 @@ function GameTags(props) {
|
|||||||
{/* network image mock */}
|
{/* network image mock */}
|
||||||
<Image
|
<Image
|
||||||
className="detail-page-content-avatar-tags-avatar-image"
|
className="detail-page-content-avatar-tags-avatar-image"
|
||||||
src="https://img.yzcdn.cn/vant/cat.jpeg"
|
src={avatar_url}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View className="detail-page-content-avatar-tags-tags">
|
<View className="detail-page-content-avatar-tags-tags">
|
||||||
@@ -1014,7 +1015,7 @@ function Index() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function fetchUserInfoById(user_id) {
|
async function fetchUserInfoById(user_id) {
|
||||||
const userDetailInfo = await LoginService.getUserInfoById(Number(user_id));
|
const userDetailInfo = await LoginService.getUserInfoById(user_id);
|
||||||
if (userDetailInfo.code === 0) {
|
if (userDetailInfo.code === 0) {
|
||||||
// console.log(userDetailInfo.data);
|
// console.log(userDetailInfo.data);
|
||||||
setUserInfo(userDetailInfo.data);
|
setUserInfo(userDetailInfo.data);
|
||||||
@@ -1072,7 +1073,7 @@ function Index() {
|
|||||||
{/* content */}
|
{/* content */}
|
||||||
<View className="detail-page-content">
|
<View className="detail-page-content">
|
||||||
{/* avatar and tags */}
|
{/* avatar and tags */}
|
||||||
<GameTags detail={detail} />
|
<GameTags detail={detail} userInfo={userInfo} />
|
||||||
{/* title */}
|
{/* title */}
|
||||||
<View className="detail-page-content-title">
|
<View className="detail-page-content-title">
|
||||||
<Text className="detail-page-content-title-text">{detail.title}</Text>
|
<Text className="detail-page-content-title-text">{detail.title}</Text>
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ export enum OrderStatus {
|
|||||||
FINISHED,
|
FINISHED,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum CancelType {
|
||||||
|
NONE = 0, // 未取消
|
||||||
|
USER, // 用户主动取消
|
||||||
|
TIMEOUT, // 超时
|
||||||
|
}
|
||||||
|
|
||||||
export interface PayMentParams {
|
export interface PayMentParams {
|
||||||
order_id: number;
|
order_id: number;
|
||||||
order_no: string;
|
order_no: string;
|
||||||
@@ -119,6 +125,42 @@ class OrderService {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 取消未支付订单
|
||||||
|
async cancelUnpaidOrder({
|
||||||
|
order_no,
|
||||||
|
cancel_reason,
|
||||||
|
}: {
|
||||||
|
order_no: number;
|
||||||
|
cancel_reason: string;
|
||||||
|
}): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post(
|
||||||
|
"/payment/cancel_order",
|
||||||
|
{ order_no, cancel_reason },
|
||||||
|
{
|
||||||
|
showLoading: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 申请退款
|
||||||
|
async applicateRefund({
|
||||||
|
order_no,
|
||||||
|
refund_reason,
|
||||||
|
refund_amount,
|
||||||
|
}: {
|
||||||
|
order_no: number;
|
||||||
|
refund_reason: string;
|
||||||
|
refund_amount: number;
|
||||||
|
}): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post(
|
||||||
|
"/payment/apply_refund",
|
||||||
|
{ order_no, refund_reason, refund_amount },
|
||||||
|
{
|
||||||
|
showLoading: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出认证服务实例
|
// 导出认证服务实例
|
||||||
|
|||||||
3
src/static/order/orderListArrowRight.svg
Normal file
3
src/static/order/orderListArrowRight.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0.75 1L3.75 4L0.75 7" stroke="#3C3C43" stroke-opacity="0.6" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 241 B |
@@ -1,10 +1,7 @@
|
|||||||
export * from './getNavbarHeight'
|
export * from "./getNavbarHeight";
|
||||||
export * from './genderUtils'
|
export * from "./genderUtils";
|
||||||
export * from './locationUtils'
|
export * from "./locationUtils";
|
||||||
export * from './processImage'
|
export * from "./processImage";
|
||||||
export * from './timeUtils'
|
export * from "./timeUtils";
|
||||||
export * from './tokenManager'
|
export * from "./tokenManager";
|
||||||
|
export * from "./order.pay";
|
||||||
export function delay(ms: number) {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms))
|
|
||||||
}
|
|
||||||
|
|||||||
20
src/utils/order.pay.ts
Normal file
20
src/utils/order.pay.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import Taro from "@tarojs/taro";
|
||||||
|
|
||||||
|
export function delay(ms: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function payOrder(params) {
|
||||||
|
const { timeStamp, nonceStr, package: _package, signType, paySign } = params;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Taro.requestPayment({
|
||||||
|
timeStamp,
|
||||||
|
nonceStr,
|
||||||
|
package: _package,
|
||||||
|
signType,
|
||||||
|
paySign,
|
||||||
|
success: resolve,
|
||||||
|
fail: reject.bind(null, new Error("支付失败")),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user