imetting/frontend/src/components/DateTimePicker.jsx

260 lines
7.2 KiB
React
Raw Normal View History

import React, { useState, useEffect } from 'react';
import { Calendar, Clock } from 'lucide-react';
import './DateTimePicker.css';
const DateTimePicker = ({ value, onChange, placeholder = "选择会议时间" }) => {
const [date, setDate] = useState('');
const [time, setTime] = useState('');
const [showQuickSelect, setShowQuickSelect] = useState(false);
const [isInitialized, setIsInitialized] = useState(false);
// 组件卸载时清理状态
useEffect(() => {
return () => {
setShowQuickSelect(false);
};
}, []);
// 初始化时间值
useEffect(() => {
if (value && !isInitialized) {
const dateObj = new Date(value);
if (!isNaN(dateObj.getTime())) {
// 转换为本地时间字符串
const timeZoneOffset = dateObj.getTimezoneOffset() * 60000;
const localDate = new Date(dateObj.getTime() - timeZoneOffset);
const isoString = localDate.toISOString();
setDate(isoString.split('T')[0]);
setTime(isoString.split('T')[1].slice(0, 5));
}
setIsInitialized(true);
} else if (!value && !isInitialized) {
setDate('');
setTime('');
setIsInitialized(true);
}
}, [value, isInitialized]);
// 当日期或时间改变时,更新父组件的值
useEffect(() => {
// 只在初始化完成后才触发onChange
if (!isInitialized) return;
if (date && time) {
const dateTimeString = `${date}T${time}`;
onChange?.(dateTimeString);
} else if (!date && !time) {
onChange?.('');
}
}, [date, time, isInitialized]); // 移除onChange依赖
// 快速选择时间的选项
const timeOptions = [
{ label: '09:00', value: '09:00' },
{ label: '10:00', value: '10:00' },
{ label: '11:00', value: '11:00' },
{ label: '14:00', value: '14:00' },
{ label: '15:00', value: '15:00' },
{ label: '16:00', value: '16:00' },
{ label: '17:00', value: '17:00' },
];
// 快速选择日期的选项
const getQuickDateOptions = () => {
const today = new Date();
const options = [];
// 今天
options.push({
label: '今天',
value: today.toISOString().split('T')[0]
});
// 明天
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
options.push({
label: '明天',
value: tomorrow.toISOString().split('T')[0]
});
// 后天
const dayAfterTomorrow = new Date(today);
dayAfterTomorrow.setDate(today.getDate() + 2);
options.push({
label: '后天',
value: dayAfterTomorrow.toISOString().split('T')[0]
});
return options;
};
const quickDateOptions = getQuickDateOptions();
const formatDisplayText = () => {
if (!date && !time) return placeholder;
if (date && time) {
const dateObj = new Date(`${date}T${time}`);
return dateObj.toLocaleString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
if (date) {
const dateObj = new Date(date);
return dateObj.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
return placeholder;
};
const clearDateTime = () => {
setDate('');
setTime('');
// 重置初始化状态,允许后续值的设定
setIsInitialized(false);
onChange?.('');
};
return (
<div className="datetime-picker">
<div className="datetime-display" onClick={(e) => {
e.stopPropagation();
setShowQuickSelect(!showQuickSelect);
}}>
<Calendar size={18} />
<span className={`display-text ${(!date && !time) ? 'placeholder' : ''}`}>
{formatDisplayText()}
</span>
{(date || time) && (
<button
type="button"
className="clear-btn"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
clearDateTime();
}}
>
×
</button>
)}
</div>
{showQuickSelect && (
<div className="datetime-picker-panel">
<div className="picker-section">
<h4>选择日期</h4>
<div className="quick-date-options">
{quickDateOptions.map((option) => (
<button
key={option.value}
type="button"
className={`quick-option ${date === option.value ? 'selected' : ''}`}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setDate(option.value);
}}
>
{option.label}
</button>
))}
</div>
<div className="custom-date-input">
<input
type="date"
value={date}
onChange={(e) => {
e.preventDefault();
e.stopPropagation();
setDate(e.target.value);
}}
onClick={(e) => e.stopPropagation()}
className="date-input"
/>
</div>
</div>
<div className="picker-section">
<h4>选择时间</h4>
<div className="quick-time-options">
{timeOptions.map((option) => (
<button
key={option.value}
type="button"
className={`quick-option ${time === option.value ? 'selected' : ''}`}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setTime(option.value);
}}
>
{option.label}
</button>
))}
</div>
<div className="custom-time-input">
<Clock size={16} />
<input
type="time"
value={time}
onChange={(e) => {
e.preventDefault();
e.stopPropagation();
setTime(e.target.value);
}}
onClick={(e) => e.stopPropagation()}
className="time-input"
/>
</div>
</div>
<div className="picker-actions">
<button
type="button"
className="action-btn cancel"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setShowQuickSelect(false);
}}
>
取消
</button>
<button
type="button"
className="action-btn confirm"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setShowQuickSelect(false);
}}
>
确认
</button>
</div>
</div>
)}
{showQuickSelect && (
<div
className="datetime-picker-overlay"
onClick={() => setShowQuickSelect(false)}
/>
)}
</div>
);
};
export default DateTimePicker;