diff --git a/src/mod_user/orderDetail/index.tsx b/src/mod_user/orderDetail/index.tsx
index cec8780..ec6659b 100644
--- a/src/mod_user/orderDetail/index.tsx
+++ b/src/mod_user/orderDetail/index.tsx
@@ -2,14 +2,18 @@ import React, { useState } from "react";
import { View, Text, Button, Image } from "@tarojs/components";
import Taro, { useDidShow, useRouter } from "@tarojs/taro";
import dayjs from "dayjs";
-import { delay } from "@/utils";
import orderService, {
GameOrderRes,
OrderStatus,
} from "@/services/orderService";
+import {
+ payOrder,
+ delay,
+ calculateDistance,
+ getCurrentLocation,
+} from "@/utils";
import detailService, { GameData } from "@/services/detailService";
import { withAuth } from "@/components";
-import { calculateDistance, getCurrentLocation } from "@/utils";
import img from "@/config/images";
import { DECLAIMER } from "./config";
import styles from "./index.module.scss";
@@ -290,38 +294,15 @@ const OrderCheck = () => {
try {
const payment_params = await getPaymentParams();
-
- const {
- timeStamp,
- nonceStr,
- package: package_,
- signType,
- paySign,
- } = payment_params;
- await Taro.requestPayment({
- timeStamp,
- nonceStr,
- package: package_,
- signType,
- paySign,
- success: async () => {
- Taro.hideLoading();
- Taro.showToast({
- title: "支付成功",
- icon: "success",
- });
- await delay(1000);
- Taro.navigateBack({
- delta: 1,
- });
- },
- fail: () => {
- Taro.hideLoading();
- Taro.showToast({
- title: "支付失败",
- icon: "none",
- });
- },
+ await payOrder(payment_params);
+ Taro.hideLoading();
+ Taro.showToast({
+ title: "支付成功",
+ icon: "success",
+ });
+ await delay(1000);
+ Taro.navigateBack({
+ delta: 1,
});
} catch (error) {
Taro.hideLoading();
diff --git a/src/mod_user/orderList/index.module.scss b/src/mod_user/orderList/index.module.scss
index a41d76c..e42fc43 100644
--- a/src/mod_user/orderList/index.module.scss
+++ b/src/mod_user/orderList/index.module.scss
@@ -1,4 +1,4 @@
-@use '~@/scss/images.scss' as img;
+@use "~@/scss/images.scss" as img;
.container {
padding: 12px;
@@ -18,6 +18,84 @@
height: 18px;
padding: 15px 15px 12px;
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 {
@@ -28,6 +106,112 @@
height: 28px;
padding: 12px 12px 15px;
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 {
+ }
+ }
}
}
-}
\ No newline at end of file
+}
+
+.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);
+ }
+ }
+ }
+}
diff --git a/src/mod_user/orderList/index.tsx b/src/mod_user/orderList/index.tsx
index b72ccc3..5a7049d 100644
--- a/src/mod_user/orderList/index.tsx
+++ b/src/mod_user/orderList/index.tsx
@@ -1,44 +1,241 @@
-import React, { useState } from 'react'
-import { View, Text, Button } from '@tarojs/components'
-import Taro, { useDidShow } from '@tarojs/taro'
-import { delay } from '@/utils'
-import orderService from '@/services/orderService'
-import { withAuth } from '@/components'
-import styles from './index.module.scss'
+import React, { useState } from "react";
+import { View, Text, Button, Image } from "@tarojs/components";
+import Taro, { useDidShow } from "@tarojs/taro";
+import { Avatar, Dialog } from "@nutui/nutui-react-taro";
+import dayjs from "dayjs";
+import classnames from "classnames";
+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 [list, setList] = useState([])
+ const [list, setList] = useState([]);
- useDidShow(async () => {
- const res = await orderService.getOrderList()
- console.log(res)
+ useDidShow(() => {
+ getOrders();
+ });
+
+ async function getOrders() {
+ const res = await orderService.getOrderList();
+ console.log(res);
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 (
+
+
+ 退款政策
+
+ {/* 订单信息摘要 */}
+
+ {policyList.map((item, index) => (
+
+ {item.time}
+ {item.rule}
+
+ ))}
+
+
+ );
+ }
+
+ 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 (
- {
- list.map(item => {
- return (
-
-
- {item?.game_info?.title}
-
-
-
-
+ {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 (
+
+
+
+
+
+ Light
+
+ {expired ? (
+ ""
+ ) : (
+
+
+ {unPay
+ ? `请在 ${expiredTime} 前支付`
+ : dayjs(item.pay_time).format("YYYY-MM-DD HH:mm:ss")}
+
+
+ {unPay ? "待支付" : "已支付"} ¥ {item.amount}
+
+
+ )}
- )
- })
- }
+
+ {item?.game_info?.title}
+
+
+
+
+ {showCancel && (
+
+ )}
+ {unPay && !expired && (
+
+ )}
+
+
+
+ );
+ })}
+
- )
-}
+ );
+};
-export default withAuth(OrderList)
\ No newline at end of file
+export default withAuth(OrderList);
diff --git a/src/pages/detail/index.tsx b/src/pages/detail/index.tsx
index fb7659b..789085e 100644
--- a/src/pages/detail/index.tsx
+++ b/src/pages/detail/index.tsx
@@ -38,7 +38,8 @@ function insertDotInTags(tags: string[]) {
}
function GameTags(props) {
- const { detail } = props;
+ const { userInfo } = props;
+ const { avatar_url } = userInfo;
const tags = [
{
name: "🕙 急招",
@@ -63,7 +64,7 @@ function GameTags(props) {
{/* network image mock */}
@@ -1072,7 +1073,7 @@ function Index() {
{/* content */}
{/* avatar and tags */}
-
+
{/* title */}
{detail.title}
diff --git a/src/services/orderService.ts b/src/services/orderService.ts
index 7272cd0..8b2646f 100644
--- a/src/services/orderService.ts
+++ b/src/services/orderService.ts
@@ -16,6 +16,12 @@ export enum OrderStatus {
FINISHED,
}
+export enum CancelType {
+ NONE = 0, // 未取消
+ USER, // 用户主动取消
+ TIMEOUT, // 超时
+}
+
export interface PayMentParams {
order_id: number;
order_no: string;
@@ -119,6 +125,42 @@ class OrderService {
},
);
}
+
+ // 取消未支付订单
+ async cancelUnpaidOrder({
+ order_no,
+ cancel_reason,
+ }: {
+ order_no: number;
+ cancel_reason: string;
+ }): Promise> {
+ 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> {
+ return httpService.post(
+ "/payment/apply_refund",
+ { order_no, refund_reason, refund_amount },
+ {
+ showLoading: true,
+ },
+ );
+ }
}
// 导出认证服务实例
diff --git a/src/static/order/orderListArrowRight.svg b/src/static/order/orderListArrowRight.svg
new file mode 100644
index 0000000..01f71b4
--- /dev/null
+++ b/src/static/order/orderListArrowRight.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 044bd88..af30b5d 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,10 +1,7 @@
-export * from './getNavbarHeight'
-export * from './genderUtils'
-export * from './locationUtils'
-export * from './processImage'
-export * from './timeUtils'
-export * from './tokenManager'
-
-export function delay(ms: number) {
- return new Promise(resolve => setTimeout(resolve, ms))
-}
\ No newline at end of file
+export * from "./getNavbarHeight";
+export * from "./genderUtils";
+export * from "./locationUtils";
+export * from "./processImage";
+export * from "./timeUtils";
+export * from "./tokenManager";
+export * from "./order.pay";
diff --git a/src/utils/order.pay.ts b/src/utils/order.pay.ts
new file mode 100644
index 0000000..060fc7b
--- /dev/null
+++ b/src/utils/order.pay.ts
@@ -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("支付失败")),
+ });
+ });
+}