feat: 订单列表 & 球局详情头像
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { View, Text, Button, Image } from "@tarojs/components";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { View, Text, Button, Image, ScrollView } from "@tarojs/components";
|
||||
import Taro, { useDidShow } from "@tarojs/taro";
|
||||
import { Avatar, Dialog } from "@nutui/nutui-react-taro";
|
||||
import dayjs from "dayjs";
|
||||
@@ -8,29 +8,98 @@ 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";
|
||||
// import orderListArrowRight from "@/static/order/orderListArrowRight.svg";
|
||||
dayjs.locale("zh-cn");
|
||||
|
||||
const PAGESIZE = 20;
|
||||
|
||||
// 将·作为连接符插入到标签文本之间
|
||||
function insertDotInTags(tags: string[]) {
|
||||
return tags.join("-·-").split("-");
|
||||
}
|
||||
|
||||
const diffDayMap = new Map([
|
||||
[0, "今天"],
|
||||
[1, "明天"],
|
||||
[2, "后天"],
|
||||
]);
|
||||
|
||||
const DayOfWeekMap = new Map([
|
||||
[0, "周日"],
|
||||
[1, "周一"],
|
||||
[2, "周二"],
|
||||
[3, "周三"],
|
||||
[4, "周四"],
|
||||
[5, "周五"],
|
||||
[6, "周六"],
|
||||
]);
|
||||
|
||||
function generateTimeMsg(game_info) {
|
||||
const { start_time, end_time } = game_info;
|
||||
const startTime = dayjs(start_time);
|
||||
const endTime = dayjs(end_time);
|
||||
const diffDay = startTime.startOf("day").diff(dayjs().startOf("day"), "day");
|
||||
|
||||
const dayofWeek = startTime.day();
|
||||
const gameLength = `${endTime.diff(startTime, "hour")}小时`;
|
||||
return (
|
||||
<>
|
||||
<Text>
|
||||
{diffDay <= 2
|
||||
? diffDayMap.get(diffDay)
|
||||
: startTime.format("YYYY-MM-DD")}
|
||||
</Text>
|
||||
<Text>({DayOfWeekMap.get(dayofWeek)})</Text>
|
||||
<Text>{gameLength}</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const OrderList = () => {
|
||||
const [list, setList] = useState([]);
|
||||
const [list, setList] = useState<any[][]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
|
||||
useDidShow(() => {
|
||||
getOrders();
|
||||
});
|
||||
const end = list.length * PAGESIZE >= total;
|
||||
|
||||
async function getOrders() {
|
||||
const res = await orderService.getOrderList();
|
||||
console.log(res);
|
||||
useEffect(() => {
|
||||
getOrders(1);
|
||||
}, []);
|
||||
|
||||
function addPageInfo(arr, page) {
|
||||
return arr.map((item) => ({ ...item, page }));
|
||||
}
|
||||
|
||||
// clear 是否清除当前页后面的数据(如果有的话,没有也不影响)
|
||||
async function getOrders(page, clear = true) {
|
||||
const res = await orderService.getOrderList({ page, pageSize: PAGESIZE });
|
||||
if (res.code === 0) {
|
||||
setList(res.data.rows);
|
||||
setTotal(res.data.count);
|
||||
setList((prev) => {
|
||||
const newList = [...prev];
|
||||
const index = page - 1
|
||||
newList.splice(
|
||||
index,
|
||||
clear ? newList.length - index : 1,
|
||||
addPageInfo(res.data.rows, page)
|
||||
);
|
||||
return newList;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePayNow(gameId) {
|
||||
function handleFetchNext() {
|
||||
console.log("scroll");
|
||||
if (!end) {
|
||||
getOrders(list.length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePayNow(item) {
|
||||
try {
|
||||
const unPaidRes = await orderService.getUnpaidOrder(gameId);
|
||||
const unPaidRes = await orderService.getUnpaidOrder(item.game_info.id);
|
||||
if (unPaidRes.code === 0 && unPaidRes.data.has_unpaid_order) {
|
||||
await payOrder(unPaidRes.data.payment_params);
|
||||
getOrders();
|
||||
getOrders(item.page, false);
|
||||
} else {
|
||||
throw new Error("支付调用失败");
|
||||
}
|
||||
@@ -43,6 +112,12 @@ const OrderList = () => {
|
||||
}
|
||||
}
|
||||
|
||||
function handleViewGame(gameId) {
|
||||
Taro.navigateTo({
|
||||
url: `/game_pages/detail/index?id=${gameId}&from=orderList`,
|
||||
});
|
||||
}
|
||||
|
||||
function renderCancelContent(checkOrderInfo) {
|
||||
const { refund_policy = [] } = checkOrderInfo;
|
||||
const policyList = [
|
||||
@@ -51,14 +126,18 @@ const OrderList = () => {
|
||||
rule: "退款规则",
|
||||
},
|
||||
...refund_policy.map((item, index) => {
|
||||
const [, theTime] = item.application_time.split("undefined ");
|
||||
const theTimeObj = dayjs(theTime);
|
||||
const isLast = index === refund_policy.length - 1;
|
||||
const theTimeObj = dayjs(
|
||||
isLast
|
||||
? refund_policy.at(-2).deadline_formatted
|
||||
: item.deadline_formatted
|
||||
);
|
||||
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 ? "前" : "后"}`,
|
||||
time: `${year}年${month}月${day}日${time} ${isLast ? "后" : "前"}`,
|
||||
rule: item.refund_rule,
|
||||
};
|
||||
}),
|
||||
@@ -81,34 +160,104 @@ const OrderList = () => {
|
||||
);
|
||||
}
|
||||
|
||||
async function handleDeleteOrder(item) {
|
||||
const { id: order_id } = item
|
||||
// TODO:删除订单,刷新这一页,然后后面的全清除掉
|
||||
const onCancel = () => {
|
||||
Dialog.close("cancelOrder");
|
||||
};
|
||||
const onConfirm = async () => {
|
||||
try {
|
||||
const deleteRes = await orderService.deleteOrder({
|
||||
order_id,
|
||||
});
|
||||
if (deleteRes.code !== 0) {
|
||||
throw new Error(deleteRes.message);
|
||||
}
|
||||
getOrders(item.page);
|
||||
Taro.showToast({
|
||||
title: "删除成功",
|
||||
icon: "none",
|
||||
})
|
||||
} catch (e) {
|
||||
Taro.showToast({
|
||||
title: e.message,
|
||||
icon: "error",
|
||||
});
|
||||
} finally {
|
||||
Dialog.close("cancelOrder");
|
||||
}
|
||||
};
|
||||
Dialog.open("cancelOrder", {
|
||||
title: "确定删除订单吗?",
|
||||
content: "删除订单后,您将无法恢复订单。请确认是否继续取消?",
|
||||
footer: (
|
||||
<View className={styles.dialogFooter}>
|
||||
<Button className={styles.cancel} onClick={onCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
className={styles.confirm}
|
||||
type="primary"
|
||||
onClick={onConfirm}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
</View>
|
||||
),
|
||||
onConfirm,
|
||||
onCancel,
|
||||
})
|
||||
}
|
||||
|
||||
async function handleCancelOrder(item) {
|
||||
const { order_no, order_status, game_info, amount } = item;
|
||||
if (order_status === OrderStatus.PENDING) {
|
||||
const onCancel = () => {
|
||||
Dialog.close("cancelOrder");
|
||||
};
|
||||
const onConfirm = async () => {
|
||||
try {
|
||||
const cancelRes = await orderService.cancelUnpaidOrder({
|
||||
order_no,
|
||||
cancel_reason: "用户主动取消",
|
||||
});
|
||||
if (cancelRes.code !== 0) {
|
||||
throw new Error(cancelRes.message);
|
||||
}
|
||||
getOrders(item.page, false);
|
||||
Taro.showToast({
|
||||
title: "取消成功",
|
||||
icon: "none",
|
||||
})
|
||||
} catch (e) {
|
||||
Taro.showToast({
|
||||
title: e.message,
|
||||
icon: "error",
|
||||
});
|
||||
} finally {
|
||||
Dialog.close("cancelOrder");
|
||||
}
|
||||
};
|
||||
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");
|
||||
},
|
||||
footer: (
|
||||
<View className={styles.dialogFooter}>
|
||||
<Button className={styles.cancel} onClick={onCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
className={styles.confirm}
|
||||
type="primary"
|
||||
onClick={onConfirm}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
</View>
|
||||
),
|
||||
onConfirm,
|
||||
onCancel,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -126,7 +275,11 @@ const OrderList = () => {
|
||||
if (refundRes.code !== 0) {
|
||||
throw new Error(refundRes.message);
|
||||
}
|
||||
getOrders();
|
||||
getOrders(item.page, false);
|
||||
Taro.showToast({
|
||||
title: "退出成功",
|
||||
icon: "none",
|
||||
})
|
||||
} catch (e) {
|
||||
Taro.showToast({
|
||||
title: e.message,
|
||||
@@ -150,89 +303,149 @@ const OrderList = () => {
|
||||
|
||||
return (
|
||||
<View className={styles.container}>
|
||||
{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;
|
||||
<ScrollView
|
||||
scrollY
|
||||
scrollWithAnimation
|
||||
lowerThreshold={20}
|
||||
onScrollToLower={handleFetchNext}
|
||||
enhanced
|
||||
showScrollbar={false}
|
||||
className={styles.list}
|
||||
>
|
||||
{/* <View className={styles.bg} /> */}
|
||||
{list.flat().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.PENDING &&
|
||||
item.cancel_type === CancelType.NONE;
|
||||
const showQuit =
|
||||
item.order_status === OrderStatus.PAID &&
|
||||
item.cancel_type === CancelType.NONE;
|
||||
|
||||
return (
|
||||
<View key={item.id} className={styles.orderItem}>
|
||||
<View className={styles.orderTitle}>
|
||||
<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
|
||||
const {
|
||||
game_info: {
|
||||
skill_level_max,
|
||||
skill_level_min,
|
||||
play_type,
|
||||
participants,
|
||||
location_name,
|
||||
current_players,
|
||||
max_players,
|
||||
court_type,
|
||||
},
|
||||
} = item;
|
||||
|
||||
return (
|
||||
<View key={item.id} className={styles.orderItem}>
|
||||
<View
|
||||
className={styles.gameInfo}
|
||||
onClick={handleViewOrderDetail.bind(null, item.id)}
|
||||
>
|
||||
<View className={styles.gameTitle}>
|
||||
<View className={styles.title}>{item?.game_info?.title}</View>
|
||||
<View
|
||||
className={classnames(
|
||||
styles.payNum,
|
||||
styles[unPay ? "pending" : "paid"],
|
||||
styles[unPay && !expired ? "pending" : "paid"]
|
||||
)}
|
||||
>
|
||||
{unPay ? "待支付" : "已支付"} ¥ {item.amount}
|
||||
</Text>
|
||||
<Text>{unPay && !expired ? "待支付" : "已支付"}</Text> ¥{" "}
|
||||
<Text>{item.amount}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.gameTime}>
|
||||
{generateTimeMsg(item.game_info)}
|
||||
</View>
|
||||
<View className={styles.address}>
|
||||
{insertDotInTags([location_name, court_type, "3.5km"]).map(
|
||||
(text, index) => (
|
||||
<Text key={index}>{text}</Text>
|
||||
)
|
||||
)}
|
||||
</View>
|
||||
<View className={styles.gameOtherInfo}>
|
||||
{participants.length >= 0 ? (
|
||||
<View className={styles.avatarCards}>
|
||||
{/* participants */[{ user: { avatar_url: 'https://img.yzcdn.cn/vant/cat.jpeg', id: 1 } }, { user: { avatar_url: 'https://img.yzcdn.cn/vant/cat.jpeg', id: 2 } }, { user: { avatar_url: 'https://img.yzcdn.cn/vant/cat.jpeg', id: 3 } }].map((participant) => {
|
||||
const {
|
||||
user: { avatar_url, id },
|
||||
} = participant;
|
||||
return <Image className={styles.avatar} mode="aspectFill" key={id} src={avatar_url} />;
|
||||
})}
|
||||
</View>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<View className={styles.participantProgress}>
|
||||
<Text className={styles.current}>报名人数 {current_players}</Text>
|
||||
<Text>/</Text>
|
||||
<Text>{max_players}</Text>
|
||||
</View>
|
||||
<View className={styles.levelReq}>
|
||||
{skill_level_max !== skill_level_min
|
||||
? `${skill_level_min || "-"} 至 ${skill_level_max || "-"}`
|
||||
: skill_level_min === 1
|
||||
? "无要求"
|
||||
: `${skill_level_min} 以上`}
|
||||
</View>
|
||||
<View className={styles.playType}>{play_type}</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.orderActions}>
|
||||
<View className={styles.extraActions}></View>
|
||||
<View className={styles.mainActions}>
|
||||
{expired && (
|
||||
<Button
|
||||
className={classnames(styles.button, styles.cancelOrder)}
|
||||
onClick={handleDeleteOrder.bind(null, item)}
|
||||
>
|
||||
删除订单
|
||||
</Button>
|
||||
)}
|
||||
{showCancel && (
|
||||
<Button
|
||||
className={classnames(styles.button, styles.cancelOrder)}
|
||||
onClick={handleCancelOrder.bind(null, item)}
|
||||
>
|
||||
取消订单
|
||||
</Button>
|
||||
)}
|
||||
{showQuit && (
|
||||
<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)}
|
||||
>
|
||||
立即支付
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
className={classnames(styles.button, styles.gameDetail)}
|
||||
onClick={handleViewGame.bind(null, item.game_info.id)}
|
||||
>
|
||||
球局详情
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View
|
||||
className={styles.gameInfo}
|
||||
onClick={handleViewOrderDetail.bind(null, item.id)}
|
||||
>
|
||||
{item?.game_info?.title}
|
||||
</View>
|
||||
<View className={styles.orderActions}>
|
||||
<View className={styles.extraActions}></View>
|
||||
<View className={styles.mainActions}>
|
||||
{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>
|
||||
);
|
||||
})}
|
||||
);
|
||||
})}
|
||||
{end && <View className={styles.endTips}>已经到底了~</View>}
|
||||
</ScrollView>
|
||||
<Dialog id="cancelOrder" />
|
||||
</View>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user