import React, { useState, useRef } from "react"; import { View, Text, Button, Image } from "@tarojs/components"; import { Dialog } from "@nutui/nutui-react-taro"; import Taro, { useDidShow, useRouter } from "@tarojs/taro"; import dayjs from "dayjs"; import classnames from "classnames"; import orderService, { CancelType, GameOrderRes, OrderStatus, RefundStatus, } from "@/services/orderService"; import { payOrder, delay, calculateDistance, getCurrentLocation, getOrderStatus, generateOrderActions, reloadPage, } from "@/utils"; import detailService, { GameData } from "@/services/detailService"; import { withAuth, RefundPopup } from "@/components"; import img from "@/config/images"; import { DECLAIMER } from "./config"; import styles from "./index.module.scss"; dayjs.locale("zh-cn"); const refundTextMap = new Map([ [RefundStatus.NONE, "已支付"], [RefundStatus.PENDING, "退款中"], [RefundStatus.SUCCESS, "已退款"], ]); const gameNoticeMap = new Map([ [ "pending", { title: "球局暂未开始", content: "球局开始前2小时,我们将通过短信通知你" }, ], [ "pendinging", { title: "球局即将开始,请按时抵达球局", content: "球局开始前2小时,我们将通过短信通知你", }, ], ["progress", { title: "球局已开始", content: "友谊第一,比赛第二" }], ["finish", { title: "球局已结束", content: "" }], ]); function genGameNotice(order_status, start_time) { const startTime = dayjs(start_time); let key = ""; if (order_status === OrderStatus.FINISHED) { key = "finish"; } const leftHour = startTime.diff(dayjs(), "hour"); const start = startTime.isBefore(dayjs()); if (start) { key = "progress"; } else if (leftHour > 2) { key = "pending"; } else if (leftHour < 2) { key = "pendinging"; } return gameNoticeMap.get(key) || {}; } function GameInfo(props) { const { detail, currentLocation, orderDetail } = props; const { order_status, refund_status } = orderDetail; const { latitude, longitude, location, location_name, start_time, end_time } = detail || {}; const refundRef = useRef(null); const openMap = () => { Taro.openLocation({ latitude, // 纬度(必填) longitude, // 经度(必填) name: location_name, // 位置名(可选) address: location, // 地址详情(可选) scale: 15, // 地图缩放级别(1-28) }); }; const [c_latitude, c_longitude] = currentLocation; const distance = c_latitude + c_longitude === 0 ? 0 : calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000; const startTime = dayjs(start_time); const endTime = dayjs(end_time); const game_length = endTime.diff(startTime, "minutes") / 60; const startMonth = startTime.format("M"); const startDay = startTime.format("D"); const theDayOfWeek = startTime.format("dddd"); const startDate = `${startMonth}月${startDay}日 ${theDayOfWeek}`; const gameRange = `${startTime.format("HH:mm")} - ${endTime.format("HH:mm")}`; const orderStatus = getOrderStatus(orderDetail); const gameNotice = genGameNotice(order_status, start_time); function handleViewGame(gameId) { Taro.navigateTo({ url: `/game_pages/detail/index?id=${gameId}&from=orderList`, }); } async function handleDeleteOrder(item) { const { order_id } = item; // TODO:删除订单,刷新这一页,然后后面的全清除掉 const onCancel = () => { Dialog.close("detailCancelOrder"); }; const onConfirm = async () => { try { const deleteRes = await orderService.deleteOrder({ order_id, }); if (deleteRes.code !== 0) { throw new Error(deleteRes.message); } Taro.showToast({ title: "删除成功", icon: "none", }); delay(2000); Taro.redirectTo({ url: "/order_pages/orderList/index" }); } catch (e) { Taro.showToast({ title: e.message, icon: "error", }); } finally { Dialog.close("detailCancelOrder"); } }; Dialog.open("detailCancelOrder", { title: "确定删除订单吗?", content: "删除订单后,您将无法恢复订单。请确认是否继续取消?", footer: ( ), onConfirm, onCancel, }); } async function handleCancelOrder(item) { const { order_no } = item; const onCancel = () => { Dialog.close("detailCancelOrder"); }; const onConfirm = async () => { try { const cancelRes = await orderService.cancelUnpaidOrder({ order_no, cancel_reason: "用户主动取消", }); if (cancelRes.code !== 0) { throw new Error(cancelRes.message); } reloadPage(); Taro.showToast({ title: "取消成功", icon: "none", }); } catch (e) { Taro.showToast({ title: e.message, icon: "error", }); } finally { Dialog.close("detailCancelOrder"); } }; Dialog.open("detailCancelOrder", { title: "确定取消订单吗?", content: "取消订单后,您将无法恢复订单。请确认是否继续取消?", footer: ( ), onConfirm, onCancel, }); } function handleQuit(item) { if (refundRef.current) { refundRef.current.show(item, (result) => { if (result) { reloadPage(); } }); } } return ( {["progress", "expired"].includes(orderStatus) && ( <> {refundTextMap.get(refund_status)} ¥ 90 {gameNotice.title} {gameNotice.content && {gameNotice.content}} )} {/* Date and Weather */} {/* Calendar and Date time */} {/* Calendar */} {startMonth}月 {startDay} {/* Date time */} {startDate} {gameRange} ({game_length}小时) {/* Place */} {/* venue location message */} {/* location icon */} {/* location message */} {/* venue name and distance */} {location_name || "-"} {distance ? ( <> · {distance.toFixed(1)}km ) : null} {/* venue address */} {location || "-"} {/* Action bar */} {orderDetail.order_id ? generateOrderActions( orderDetail, { handleDeleteOrder, handleCancelOrder, handleQuit, handlePayNow: () => {}, handleViewGame, }, "detail" )?.map((obj) => ( )) : ""} ); } function OrderMsg(props) { const { detail, orderDetail, checkOrderInfo } = props; const { start_time, end_time, location, location_name, wechat_contact, price, } = detail; const { order_no } = orderDetail; const { order_info: { registrant_phone } = {} } = checkOrderInfo; const startTime = dayjs(start_time); const endTime = dayjs(end_time); const startYear = startTime.format("YYYY"); const startMonth = startTime.format("M"); const startDay = startTime.format("D"); const startDate = `${startYear}年${startMonth}月${startDay}日`; const gameRange = `${startTime.format("HH:mm")} - ${endTime.format("HH:mm")}`; const summary = [ { title: "时间", content: `${startDate} ${gameRange}`, }, { title: "地址", content: ( {location} {location_name} ), }, { title: "报名人电话", content: registrant_phone, }, { title: "组织人微信号", content: wechat_contact, }, { title: "组织人电话", content: wechat_contact, }, { title: "费用", content: `${price} 元 / 人`, }, ...(order_no ? [ { title: "订单号", content: order_no, }, ] : []), ]; return ( 确认订单信息 {/* 订单信息摘要 */} {summary.map((item, index) => ( {item.title} {item.content} ))} ); } function RefundPolicy(props) { const { checkOrderInfo } = props; const { refund_policy = [] } = checkOrderInfo; const policyList = [ { time: "申请退款时间", rule: "退款规则", }, ...refund_policy.map((item, index) => { 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} ${isLast ? "后" : "前"}`, rule: item.refund_rule, }; }), ]; return ( 退款政策 {/* 订单信息摘要 */} {policyList.map((item, index) => ( {item.time} {item.rule} ))} ); } function Disclaimer() { return ( 免责声明 {DECLAIMER} ); } const OrderCheck = () => { const { params } = useRouter(); const { id: stringId, gameId: stringGameId } = params; const [id, gameId] = [Number(stringId), Number(stringGameId)]; const [detail, setDetail] = useState({}); const [location, setLocation] = useState([0, 0]); const [checkOrderInfo, setCheckOrderInfo] = useState({}); const [orderDetail, setOrderDetail] = useState({}); useDidShow(async () => { let gameDetail = {}; if (id) { const res = await orderService.getOrderDetail(id); if (res.code === 0) { setOrderDetail(res.data); gameDetail = res.data.game_info; } } else if (gameId) { const res = await detailService.getDetail(gameId); if (res.code === 0) { gameDetail = res.data; } } if (gameDetail.id) { setDetail(gameDetail); onInit(gameDetail.id); } }); async function checkOrder(gid) { const orderRes = await orderService.getCheckOrderInfo(gid); setCheckOrderInfo(orderRes.data); } async function onInit(gid) { checkOrder(gid); const location = await getCurrentLocation(); 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 const handlePay = async () => { Taro.showLoading({ title: "支付中...", mask: true, }); try { const payment_params = await getPaymentParams(); await payOrder(payment_params); Taro.hideLoading(); Taro.showToast({ title: "支付成功", icon: "success", }); await delay(1000); Taro.navigateBack({ delta: 1, }); } catch (error) { Taro.hideLoading(); Taro.showToast({ title: error.message, icon: "none", }); } }; if (!id && !gameId) { return ( 异常订单 ); } const { order_status, cancel_type } = orderDetail; return ( {/* Game Date and Address */} {/* Order message */} {/* Refund policy */} {/* Disclaimer */} {(!id || (order_status === OrderStatus.PENDING && cancel_type === CancelType.NONE)) && ( )} ); }; export default withAuth(OrderCheck);