初版编写交叉评查页面,增加非范围日期选择器
This commit is contained in:
@@ -16,6 +16,17 @@ export interface DateRangePickerProps {
|
||||
colorMode?: 'light' | 'dark' | 'auto';
|
||||
}
|
||||
|
||||
export interface SingleDatePickerProps {
|
||||
date: string;
|
||||
onDateChange: (value: string) => void;
|
||||
label?: string;
|
||||
className?: string;
|
||||
id?: string;
|
||||
format?: string;
|
||||
placeholder?: string;
|
||||
colorMode?: 'light' | 'dark' | 'auto';
|
||||
}
|
||||
|
||||
export function links() {
|
||||
return [
|
||||
{ rel: "stylesheet", href: dateRangePickerStyles }
|
||||
@@ -199,6 +210,117 @@ export function DateRangePicker({
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单日期选择器组件
|
||||
* 用于选择单个日期
|
||||
*/
|
||||
export function SingleDatePicker({
|
||||
date,
|
||||
onDateChange,
|
||||
label = "日期",
|
||||
className = "",
|
||||
id = "date-single",
|
||||
format = "yyyy-MM-dd",
|
||||
placeholder = "请选择日期",
|
||||
colorMode = 'auto'
|
||||
}: SingleDatePickerProps) {
|
||||
// 使用ref获取input元素
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// 添加状态跟踪日期输入框是否被聚焦
|
||||
const [isFocused, setIsFocused] = useState<boolean>(false);
|
||||
|
||||
// 格式化显示日期
|
||||
const formattedDate = date ? formatDate(date, format) : "";
|
||||
|
||||
// 保持原始日期输入框的显示格式
|
||||
useEffect(() => {
|
||||
if (inputRef.current) {
|
||||
inputRef.current.setAttribute('data-display-value', formattedDate || placeholder);
|
||||
}
|
||||
}, [formattedDate, placeholder]);
|
||||
|
||||
// 处理日期输入框全局点击
|
||||
const handleWrapperClick = () => {
|
||||
if (inputRef.current) {
|
||||
// 点击整个包装器区域时,触发输入框点击
|
||||
inputRef.current.focus();
|
||||
inputRef.current.click();
|
||||
|
||||
try {
|
||||
// 检查并使用showPicker API
|
||||
const hasShowPicker = typeof inputRef.current.showPicker === 'function';
|
||||
|
||||
// 尝试使用showPicker API
|
||||
if (hasShowPicker) {
|
||||
inputRef.current.showPicker();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to show date picker:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 处理键盘事件
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleWrapperClick();
|
||||
}
|
||||
};
|
||||
|
||||
// 处理聚焦和失焦
|
||||
const handleFocus = () => {
|
||||
setIsFocused(true);
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
setIsFocused(false);
|
||||
};
|
||||
|
||||
// 获取颜色模式类名
|
||||
const getColorModeClass = () => {
|
||||
if (colorMode === 'light') return 'color-mode-light';
|
||||
if (colorMode === 'dark') return 'color-mode-dark';
|
||||
return ''; // auto模式不添加额外类名
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`date-picker single-date-picker ${getColorModeClass()} ${className}`}>
|
||||
<div className="date-field">
|
||||
<label htmlFor={id} className="date-label">{label}</label>
|
||||
<div
|
||||
className={`date-input-wrapper ${isFocused ? 'focused' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleWrapperClick();
|
||||
}}
|
||||
onKeyDown={handleKeyDown}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
aria-label={`选择${label}`}
|
||||
>
|
||||
<input
|
||||
id={id}
|
||||
ref={inputRef}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={date}
|
||||
onChange={(e) => onDateChange(e.target.value)}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
<div
|
||||
className={`date-display ${!formattedDate ? 'placeholder' : ''}`}
|
||||
>
|
||||
{formattedDate || placeholder}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 简化版日期范围选择器,适用于紧凑布局,不显示标签
|
||||
export function SimpleDateRangePicker({
|
||||
startDate,
|
||||
@@ -344,4 +466,4 @@ export function SimpleDateRangePicker({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user