This commit is contained in:
oneao committed 2025-11-15 17:31:36 +08:00
1 parent 33113f279c
commit c2c5cc92af
16 files changed
+864 -352

No files matched your search

@@ -0,0 +1,81 @@
import type { DateTimePickerProps } from 'react-native-modal-datetime-picker'
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
import React, { useMemo } from 'react'
import DateTimePickerModal from 'react-native-modal-datetime-picker'
dayjs.extend(customParseFormat)
interface ADatePickerProps extends Omit<DateTimePickerProps, 'onConfirm' | 'onCancel' | 'date'> {
format?: string
onConfirm?: (value: string) => void
date?: Date | string
is24Hour?: boolean
onCancel?: () => void
}
export default function DatePicker({
mode = 'date',
format,
date,
onConfirm,
is24Hour = true,
onCancel,
...restProps
}: ADatePickerProps) {
const parsedDate = useMemo(() => {
if (!date)
return new Date()
if (typeof date === 'string') {
// 支持多种常见日期格式
const formats = ['YYYY-MM-DD', 'YYYY/MM/DD', 'YYYY-MM-DDTHH:mm:ssZ', 'YYYY/MM/DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss']
for (const fmt of formats) {
const d = dayjs(date, fmt, true)
if (d.isValid())
return d.toDate()
}
// fallback: 尝试直接解析
const d = dayjs(date)
if (d.isValid())
return d.toDate()
// 仍然不合法就返回当前时间
return new Date()
}
return date
}, [date])
const handleConfirm = (selectedDate: Date) => {
const fmt = format || (() => {
switch (mode) {
case 'time':
return 'HH:mm:00'
case 'datetime':
return 'YYYY-MM-DD HH:mm:00'
case 'date':
default:
return 'YYYY-MM-DD'
}
})()
const localTimeStr = dayjs(selectedDate).format(fmt)
onConfirm?.(localTimeStr)
}
const handleCancel = () => {
onCancel?.()
}
return (
<DateTimePickerModal
{...restProps}
mode={mode}
date={parsedDate}
locale="zh-CN"
onConfirm={handleConfirm}
onCancel={handleCancel}
is24Hour={is24Hour}
/>
)
}
@@ -0,0 +1,106 @@
import type { DateType, OrderedDateParts } from 'react-native-dates-picker/lib/typescript/types'
import dayjs from 'dayjs'
import { useEffect, useRef, useState } from 'react'
import { View } from 'react-native'
import DateTimePicker from 'react-native-dates-picker'
import { Drawer, DrawerBackdrop, DrawerContent, DrawerFooter, DrawerHeader } from '@/components/ui/drawer'
import AButton from './Button'
type DateWheelMode
= | 'year-month'
| 'year-month-day'
| 'hour-minute-second'
| 'year-month-day-hour-minute-second'
interface DateDrawerProps {
isOpen?: boolean
defaultDate?: DateType
modeType?: DateWheelMode
onClose?: () => void
onConfirm?: (dateStr: string) => void
}
const modeColumnsMap: Record<DateWheelMode, OrderedDateParts[]> = {
'year-month': ['year', 'month'],
'year-month-day': ['year', 'month', 'day'],
'hour-minute-second': ['hour', 'minute', 'second'],
'year-month-day-hour-minute-second': ['year', 'month', 'day', 'hour', 'minute', 'second'],
}
const modeFormatMap: Record<DateWheelMode, string> = {
'year-month': 'YYYY-MM',
'year-month-day': 'YYYY-MM-DD',
'hour-minute-second': 'HH:mm:ss',
'year-month-day-hour-minute-second': 'YYYY-MM-DD HH:mm:ss',
}
export default function DateWheelDrawer({
isOpen,
defaultDate = dayjs(),
onClose,
onConfirm,
modeType = 'year-month-day',
}: DateDrawerProps) {
const columns = modeColumnsMap[modeType]
const format = modeFormatMap[modeType]
// 当前选择的值
const [date, setDate] = useState<DateType>(defaultDate)
// 保存上一次确认的值
const lastConfirmedRef = useRef<DateType>(defaultDate)
// 每次弹窗打开时,把滚轮显示初始化为上一次确认的值
useEffect(() => {
if (isOpen) {
setDate(lastConfirmedRef.current)
}
}, [isOpen])
// 点击取消
const handleCancel = () => {
onClose?.()
}
// 点击确认
const handleConfirm = () => {
console.log("确实")
onClose?.()
lastConfirmedRef.current = date // 保存为上一次确认的值
if (onConfirm) {
const formatted = dayjs(date).format(format)
onConfirm(formatted)
}
}
return (
<Drawer
isOpen={isOpen}
anchor="bottom"
closeOnOverlayClick
onClose={onClose}
size="md"
>
<DrawerBackdrop />
<DrawerContent className="p-0 flex-1">
<DrawerHeader className="flex items-center justify-between p-4">
<AButton action="secondary" onPress={handleCancel}>取消</AButton>
<AButton onPress={handleConfirm}>确认</AButton>
</DrawerHeader>
<View className="flex-1 flex items-center justify-center">
<DateTimePicker
mode="wheel"
date={date}
columns={columns}
wheelPickerSelectedIndicatorStyle={{ backgroundColor: '#eee' }}
onChange={params => setDate(params.date)}
/>
</View>
<DrawerFooter></DrawerFooter>
</DrawerContent>
</Drawer>
)
}
@@ -1,5 +1,7 @@
import Button from './Button'
import Checkbox from './Checkbox'
import DatePicker from './DatePicker'
import DateTimeDrawer from './DateTimeDrawer'
import Form, { FormRef } from './Form'
import FormItem from './FormItem'
import Input from './Input'
@@ -8,6 +10,8 @@ import LucideIcon from './LucideIcon'
export {
Button as AButton,
Checkbox as ACheckbox,
DatePicker as ADatePicker,
DateTimeDrawer as ADateTimeDrawer,
Form as AForm,
FormItem as AFormItem,
FormRef as AFormRef,