import React, { useState, useEffect, useRef } 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";
import "dayjs/locale/zh-cn";
import classnames from "classnames";
import orderService, {
OrderStatus,
CancelType,
refundTextMap,
RefundStatus,
} from "@/services/orderService";
import { getStorage, removeStorage, setStorage } from "@/store/storage";
import { useGlobalStore } from "@/store/global";
import { handleCustomerService } from "@/services/userService";
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 styles from "./index.module.scss";
dayjs.locale("zh-cn");
const PAGESIZE = 100;
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 (
<>
{diffDay <= 2 && diffDay >= 0
? diffDayMap.get(diffDay)
: startTime.format("YYYY-MM-DD")}
({DayOfWeekMap.get(dayofWeek)})
{startTime.format("ah")}点
{gameLength}
>
);
}
const OrderList = () => {
const [list, setList] = useState([]);
const [total, setTotal] = useState(0);
const [refreshing, setRefreshing] = useState(false);
const refundRef = useRef(null);
const end = list.length * PAGESIZE >= total;
useEffect(() => {
getOrders(1);
}, []);
useDidShow(() => {
const targetPage = getStorage("list_reload_page_number");
if (targetPage) {
removeStorage("list_reload_page_number");
getOrders(Number(targetPage));
}
});
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) {
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;
});
}
}
function handleFetchNext() {
console.log("scroll");
if (!end) {
getOrders(list.length + 1);
}
}
// 下拉刷新:重新加载第一页订单
async function handle_refresh() {
setRefreshing(true);
try {
await getOrders(1);
} catch (error) {
Taro.showToast({
title: "刷新失败,请重试",
icon: "none",
duration: 2000,
});
} finally {
setRefreshing(false);
}
}
async function handlePayNow(item) {
// 检查登录状态和手机号
if (!requireLoginWithPhone()) {
return; // 未登录或未绑定手机号,已跳转到登录页
}
try {
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(item.page, false);
} else {
throw new Error("支付调用失败");
}
} catch (e) {
console.log(e, 1111);
Taro.showToast({
title: e.message,
icon: "none",
});
}
}
function handleViewGame(gameId) {
if (!gameId) {
Taro.showToast({ title: "球局未找到", icon: "error" });
return;
}
Taro.navigateTo({
url: `/game_pages/detail/index?id=${gameId}&from=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: (
),
onConfirm,
onCancel,
});
}
async function handleCancelOrder(item) {
const { order_no } = item;
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: (
取消订单后,您将无法恢复订单。请确认是否继续取消?
),
footer: (
),
onConfirm,
onCancel,
});
}
async function handleQuit(item) {
if (refundRef.current) {
const res = await orderService.getRefundPolicy({ order_id: item.id });
refundRef.current.show(
{ ...item, refund_policy: res.data.refund_policy },
(result) => {
if (result) {
getOrders(item.page);
}
},
);
}
}
function handleViewOrderDetail({ page, id: orderId }) {
setStorage("list_reload_page_number", page);
Taro.navigateTo({
url: `/order_pages/orderDetail/index?id=${orderId}`,
});
}
const flatList = list.flat();
const { statusNavbarHeightInfo } = useGlobalStore();
const { totalHeight } = statusNavbarHeightInfo;
return (
{/* */}
{flatList.map((item) => {
const unPay =
item.order_status === OrderStatus.PENDING &&
item.cancel_type === CancelType.NONE;
const canceled = [CancelType.USER, CancelType.TIMEOUT].includes(
item.cancel_type,
);
const { game_info } = item;
const {
skill_level_max,
skill_level_min,
play_type,
participants,
location_name,
current_players,
max_players,
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 (
handleViewOrderDetail(item)}
>
{item?.game_info?.title}
{!canceled && (
{unPay
? "待支付"
: refundTextMap.get(item.refund_status)}
{" "}
¥{" "}
{[
RefundStatus.PENDING,
RefundStatus.SUCCESS,
].includes(item.refund_status)
? item.refund_amount
: item.amount}
)}
{generateTimeMsg(item.game_info || {})}
{insertDotInTags([location_name, court_type, "3.5km"]).map(
(text, index) => (
{text}
),
)}
{participants?.length >= 0 ? (
{participants.map((participant) => {
const {
user: { avatar_url, id },
} = participant;
return (
);
})}
) : (
""
)}
报名人数 {current_players}
/
{max_players}
{genNTRPRequirementText(skill_level_min, skill_level_max)}
{play_type}
客服
{generateOrderActions(
item,
{
handleDeleteOrder,
handleCancelOrder,
handleQuit,
handlePayNow,
handleViewGame,
},
"list",
)?.map((obj) => (
{obj.text}
))}
{unPay && diffMs > 0 && (
{current_players > 0 ? (
{`已有${current_players}人参加, `}
) : (
""
)}
请在
{timeLeft}
分钟内完成支付
)}
);
})}
{flatList.length > 0 && end && (
已经到底了~
)}
{flatList.length === 0 && (
暂时没有订单
)}
);
};
export default withAuth(OrderList);