imetting/frontend/src/components/DateTimePicker.jsx

260 lines
7.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;