feat(payment): 更新支付倒计时组件以支持过期时间

- 添加 expirationTime 属性作为首选时间源
- 当 expirationTime 缺失时回退到 createTime + timeoutHours 方式
- 更新订单详情页和订单列表页组件以传递 expirationTime
- 修改 usePaymentCountdown Hook 以支持新的参数结构
- 更新组件文档以反映新的 API 和使用方式
- 增强时间计算逻辑以处理无效时间情况
This commit is contained in:
2026-02-07 13:16:31 +08:00
parent 6e0a5aa1fe
commit 80653f7ac2
5 changed files with 73 additions and 30 deletions

View File

@@ -13,19 +13,30 @@ export interface CountdownTime {
totalMinutes: number; // 总剩余分钟数
}
export interface UsePaymentCountdownParams {
/** 订单创建时间(用于兼容:当 expirationTime 缺失时按 createTime + timeoutHours 计算) */
createTime?: string;
/** 订单过期时间(推荐直接传后端返回的 expirationTime */
expirationTime?: string;
/** 支付状态 */
payStatus?: boolean;
/** 是否实时更新详情页用true列表页用false */
realTime?: boolean;
/** 超时小时数默认24小时仅在 expirationTime 缺失时生效) */
timeoutHours?: number;
}
/**
* 支付倒计时Hook
* @param createTime 订单创建时间
* @param payStatus 支付状态
* @param realTime 是否实时更新详情页用true列表页用false
* @param timeoutHours 超时小时数默认24小时
* 优先使用 expirationTime当 expirationTime 缺失时回退到 createTime + timeoutHours。
*/
export const usePaymentCountdown = (
createTime?: string,
payStatus?: boolean,
realTime: boolean = false,
timeoutHours: number = 24
): CountdownTime => {
export const usePaymentCountdown = ({
createTime,
expirationTime,
payStatus,
realTime = false,
timeoutHours = 24
}: UsePaymentCountdownParams): CountdownTime => {
const [timeLeft, setTimeLeft] = useState<CountdownTime>({
hours: 0,
minutes: 0,
@@ -37,7 +48,7 @@ export const usePaymentCountdown = (
// 计算剩余时间的函数
const calculateTimeLeft = useMemo(() => {
return (): CountdownTime => {
if (!createTime || payStatus) {
if (payStatus || (!expirationTime && !createTime)) {
return {
hours: 0,
minutes: 0,
@@ -47,8 +58,27 @@ export const usePaymentCountdown = (
};
}
const createTimeObj = dayjs(createTime);
const expireTime = createTimeObj.add(timeoutHours, 'hour');
// 优先使用后端过期时间;如果无法解析,再回退到 createTime + timeoutHours
const expireTimeFromExpiration = expirationTime ? dayjs(expirationTime) : null;
const expireTimeFromCreate =
createTime ? dayjs(createTime).add(timeoutHours, 'hour') : null;
const expireTime =
expireTimeFromExpiration?.isValid()
? expireTimeFromExpiration
: expireTimeFromCreate?.isValid()
? expireTimeFromCreate
: null;
if (!expireTime) {
return {
hours: 0,
minutes: 0,
seconds: 0,
isExpired: true,
totalMinutes: 0
};
}
const now = dayjs();
const diff = expireTime.diff(now);
@@ -76,10 +106,10 @@ export const usePaymentCountdown = (
totalMinutes
};
};
}, [createTime, payStatus, timeoutHours]);
}, [createTime, expirationTime, payStatus, timeoutHours]);
useEffect(() => {
if (!createTime || payStatus) {
if (payStatus || (!expirationTime && !createTime)) {
setTimeLeft({
hours: 0,
minutes: 0,
@@ -111,7 +141,7 @@ export const usePaymentCountdown = (
}, 1000);
return () => clearInterval(timer);
}, [createTime, payStatus, realTime, calculateTimeLeft]);
}, [createTime, expirationTime, payStatus, realTime, calculateTimeLeft]);
return timeLeft;
};