This commit is contained in:
2025-09-16 14:35:45 +08:00
13 changed files with 799 additions and 288 deletions

View File

@@ -1,26 +1,9 @@
import React, { useEffect, useState } from "react";
import { View } from "@tarojs/components";
import Taro from "@tarojs/taro";
import { getCurrentFullPath } from '@/utils';
import { check_login_status } from "@/services/loginService";
export function getCurrentFullPath(): string {
const pages = Taro.getCurrentPages();
const currentPage = pages.at(-1);
if (currentPage) {
console.log(currentPage, "currentPage get");
const route = currentPage.route;
const options = currentPage.options || {};
const query = Object.keys(options)
.map((key) => `${key}=${options[key]}`)
.join("&");
return query ? `/${route}?${query}` : `/${route}`;
}
return "";
}
export default function withAuth<P extends object>(
WrappedComponent: React.ComponentType<P>,
) {

View File

@@ -16,6 +16,7 @@ import EditModal from "./EditModal/index";
import withAuth from "./Auth";
import { CustomPicker, PopupPicker } from "./Picker";
import NTRPEvaluatePopup from "./NTRPEvaluatePopup";
import RefundPopup from "./refundPopup";
export {
ActivityTypeSwitch,
@@ -37,4 +38,5 @@ export {
CustomPicker,
PopupPicker,
NTRPEvaluatePopup,
RefundPopup,
};

View File

@@ -0,0 +1,132 @@
.refundPolicy {
padding-top: 20px;
// .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;
// }
.specTips {
padding-bottom: 20px;
color: rgba(60, 60, 67, 0.60);
text-align: center;
font-feature-settings: 'liga' off, 'clig' off;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 18px;
}
.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);
}
}
}
}
.container {
padding: 0 15px 40px;
.header {
padding: 24px 15px 0;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
.title {
color: #000;
text-align: center;
font-feature-settings: 'liga' off, 'clig' off;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 20px;
margin-left: auto;
}
.closeIcon {
margin-left: auto;
width: 20px;
height: 20px;
}
}
.action {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
padding: 2px 6px;
height: 52px;
border-radius: 16px;
border: 1px solid rgba(0, 0, 0, 0.06);
box-shadow: 0 8px 64px 0 rgba(0, 0, 0, 0.10);
backdrop-filter: blur(16px);
color: #fff;
background-color: #000;
font-feature-settings: 'liga' off, 'clig' off;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 20px;
letter-spacing: -0.23px;
}
}

View File

@@ -0,0 +1,139 @@
import React, { useState, useRef, forwardRef, useImperativeHandle } from 'react';
import { View, Text, Button, Image } from '@tarojs/components'
import Taro from '@tarojs/taro';
import dayjs from 'dayjs'
import { CommonPopup } from '@/components';
import orderService from '@/services/orderService';
import styles from './index.module.scss'
import closeIcon from '@/static/order/orderListClose.svg'
function genRefundNotice (refund_policy) {
if (refund_policy.length === 0) {
return {}
}
const now = dayjs()
const deadlines = refund_policy.map(item => dayjs(item.deadline_formatted))
let matchPolicyIndex = deadlines.findIndex(d => d.isAfter(now))
if (matchPolicyIndex === -1) {
matchPolicyIndex = refund_policy.length - 1
}
const { deadline_formatted, price, refund_rate } = refund_policy[matchPolicyIndex]
if (refund_rate === 1) {
return { refundPrice: price, notice: `本次可全额退款, ¥${price} 将原路退回,请查收` }
} else if (refund_rate === 0) {
return { refundPrice: 0, notice: `当前退出不可退款,后续流程未明确,@麻真瑜` }
}
const refundPrice = price * refund_rate
const leftHours = dayjs(deadline_formatted).diff(dayjs(), 'hour')
return { refundPrice, notice: `距活动开始已不足${leftHours}h当前退出您需扣除${price - refundPrice}` }
}
function renderCancelContent(checkOrderInfo) {
const { refund_policy = [] } = checkOrderInfo;
const policyList = [
{
time: "申请退款时间",
rule: "退款规则",
},
...refund_policy.map((item) => {
return {
time: item.application_time,
rule: item.refund_rule,
};
}),
];
const { notice } = genRefundNotice(refund_policy)
return (
<View className={styles.refundPolicy}>
{/* <View className={styles.moduleTitle}>
<Text>退款政策</Text>
</View> */}
{<View className={styles.specTips}>{notice}</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>
);
}
export type RefundRef = {
show: (item: any, callback: (result: boolean) => void) => void
}
export default forwardRef<RefundRef>(function RefundPopup(_props, ref) {
const [visible, setVisible] = useState(false)
const [checkOrderInfo, setCheckOrderInfo] = useState({})
const [orderData, setOrderData] = useState({})
const onDown = useRef<((result: boolean) => void) | null>(null)
useImperativeHandle(ref, () => ({
show: onShow,
}))
async function onShow (orderItem, onFinish: (result: boolean) => void) {
const {
game_info,
} = orderItem
onDown.current = onFinish
setOrderData(orderItem)
const res = await orderService.getCheckOrderInfo(game_info.id);
setCheckOrderInfo(res.data);
setVisible(true)
}
function onClose () {
setVisible(false)
onDown.current?.(false)
}
async function handleConfirmQuit () {
const { order_no, amount } = orderData
try {
const refundRes = await orderService.applicateRefund({
order_no,
refund_amount: amount,
refund_reason: "用户主动退款",
});
if (refundRes.code !== 0) {
throw new Error(refundRes.message);
}
Taro.showToast({
title: "退出成功",
icon: "none",
})
onDown.current?.(true)
} catch (e) {
Taro.showToast({
title: e.message,
icon: "error",
});
} finally {
onClose()
}
}
return (
<CommonPopup
visible={visible}
onClose={onClose}
// title="退出活动"
enableDragToClose={false}
zIndex={1001}
hideFooter
>
<View className={styles.container}>
<View className={styles.header}>
<Text className={styles.title}>退</Text>
<Image className={styles.closeIcon} src={closeIcon} onClick={onClose} />
</View>
{renderCancelContent(checkOrderInfo)}
<Button className={styles.action} onClick={handleConfirmQuit}>退</Button>
</View>
</CommonPopup>
)
})