feat(user): 新增收货地址管理及售后申请页面
- 新增地址类型定义,增强前端地址数据结构 - 新增地址编辑页面,支持地址智能识别和定位选点功能 - 地址编辑支持省市区选择及默认地址设置 - 新增地址列表页面,支持地址展示、删除、编辑和选择功能 - 实现售后申请页面,支持选择售后类型和退款原因 - 售后申请支持商品选择、退款金额计算和凭证上传 - 新增售后详情页面,支持售后状态展示及申请取消 - 优化页面加载和用户交互体验,增加错误提示和权限处理
This commit is contained in:
130
src_bak/hooks/useCountUp.ts
Normal file
130
src_bak/hooks/useCountUp.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
|
||||
export interface CountUpResult {
|
||||
/** 当前秒数 */
|
||||
seconds: number
|
||||
/** 当前分钟 */
|
||||
minutes: number
|
||||
/** 当前小时 */
|
||||
hours: number
|
||||
/** 总秒数 */
|
||||
totalSeconds: number
|
||||
/** 是否在运行 */
|
||||
isRunning: boolean
|
||||
/** 格式化后的字符串 */
|
||||
formatted: string
|
||||
/** 暂停 */
|
||||
pause: () => void
|
||||
/** 继续 */
|
||||
resume: () => void
|
||||
/** 重置 */
|
||||
reset: (newStartFrom?: number) => void
|
||||
}
|
||||
|
||||
export interface CountUpOptions {
|
||||
/** 起始值(秒),默认 0 */
|
||||
startFrom?: number
|
||||
/** 触发间隔(毫秒),默认 1000 */
|
||||
interval?: number
|
||||
/** 最大值,超出后停止 */
|
||||
maxValue?: number
|
||||
/** 格式化函数 */
|
||||
format?: (result: Pick<CountUpResult, 'hours' | 'minutes' | 'seconds'>) => string
|
||||
}
|
||||
|
||||
/**
|
||||
* 正向计时 Hook
|
||||
* @param options 配置选项
|
||||
*/
|
||||
export function useCountUp(options: CountUpOptions = {}): CountUpResult {
|
||||
const { startFrom = 0, interval = 1000, maxValue, format } = options
|
||||
|
||||
const startRef = useRef(startFrom)
|
||||
const maxRef = useRef(maxValue)
|
||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)
|
||||
|
||||
const [totalSeconds, setTotalSeconds] = useState(startFrom)
|
||||
const [isRunning, setIsRunning] = useState(false)
|
||||
|
||||
// 计算时分秒
|
||||
const calcTime = useCallback((total: number) => ({
|
||||
totalSeconds: total,
|
||||
hours: Math.floor(total / 3600),
|
||||
minutes: Math.floor((total % 3600) / 60),
|
||||
seconds: total % 60,
|
||||
}), [])
|
||||
|
||||
const [time, setTime] = useState(() => calcTime(startFrom))
|
||||
|
||||
// 默认格式化
|
||||
const defaultFormat = useCallback((r: Pick<CountUpResult, 'hours' | 'minutes' | 'seconds'>) => {
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
return `${pad(r.hours)}:${pad(r.minutes)}:${pad(r.seconds)}`
|
||||
}, [])
|
||||
|
||||
const startInterval = useCallback(() => {
|
||||
if (intervalRef.current) clearInterval(intervalRef.current)
|
||||
intervalRef.current = setInterval(() => {
|
||||
setTotalSeconds(prev => {
|
||||
const next = prev + Math.floor(interval / 1000)
|
||||
const max = maxRef.current
|
||||
if (max !== undefined && next >= max) {
|
||||
if (intervalRef.current) clearInterval(intervalRef.current)
|
||||
setIsRunning(false)
|
||||
return max
|
||||
}
|
||||
return next
|
||||
})
|
||||
}, interval)
|
||||
}, [interval])
|
||||
|
||||
// 更新 refs
|
||||
useEffect(() => {
|
||||
startRef.current = startFrom
|
||||
setTotalSeconds(startFrom)
|
||||
setTime(calcTime(startFrom))
|
||||
}, [startFrom, calcTime])
|
||||
|
||||
useEffect(() => {
|
||||
maxRef.current = maxValue
|
||||
}, [maxValue])
|
||||
|
||||
// 同步 totalSeconds 到 time
|
||||
useEffect(() => {
|
||||
setTime(calcTime(totalSeconds))
|
||||
}, [totalSeconds, calcTime])
|
||||
|
||||
// 控制定时器
|
||||
useEffect(() => {
|
||||
if (isRunning) {
|
||||
startInterval()
|
||||
} else {
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current)
|
||||
intervalRef.current = null
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
if (intervalRef.current) clearInterval(intervalRef.current)
|
||||
}
|
||||
}, [isRunning, startInterval])
|
||||
|
||||
const pause = useCallback(() => setIsRunning(false), [])
|
||||
const resume = useCallback(() => setIsRunning(true), [])
|
||||
const reset = useCallback((newStart?: number) => {
|
||||
const start = newStart ?? startFrom
|
||||
startRef.current = start
|
||||
setTotalSeconds(start)
|
||||
setTime(calcTime(start))
|
||||
setIsRunning(true)
|
||||
}, [startFrom, calcTime])
|
||||
|
||||
return {
|
||||
...time,
|
||||
isRunning,
|
||||
formatted: (format ?? defaultFormat)(time),
|
||||
pause,
|
||||
resume,
|
||||
reset,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user