修复文件上传可以传文档bug
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useRef, useEffect, useState } from "react";
|
||||
import dateRangePickerStyles from "~/styles/components/date-range-picker.css?url";
|
||||
|
||||
export interface DateRangePickerProps {
|
||||
@@ -10,6 +11,8 @@ export interface DateRangePickerProps {
|
||||
className?: string;
|
||||
startId?: string;
|
||||
endId?: string;
|
||||
format?: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export function links() {
|
||||
@@ -18,6 +21,27 @@ export function links() {
|
||||
];
|
||||
}
|
||||
|
||||
// 格式化日期函数
|
||||
function formatDate(dateString: string, format = "yyyy-MM-dd"): string {
|
||||
if (!dateString) return "";
|
||||
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
if (isNaN(date.getTime())) return dateString;
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
|
||||
return format
|
||||
.replace("yyyy", year.toString())
|
||||
.replace("MM", month)
|
||||
.replace("dd", day);
|
||||
} catch (e) {
|
||||
return dateString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期范围选择器组件
|
||||
* 用于选择日期范围,如开始日期和结束日期
|
||||
@@ -31,31 +55,135 @@ export function DateRangePicker({
|
||||
endLabel = "至",
|
||||
className = "",
|
||||
startId = "date-start",
|
||||
endId = "date-end"
|
||||
endId = "date-end",
|
||||
format = "yyyy-MM-dd",
|
||||
placeholder = "请选择时间"
|
||||
}: DateRangePickerProps) {
|
||||
// 使用ref获取input元素
|
||||
const startInputRef = useRef<HTMLInputElement>(null);
|
||||
const endInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// 添加状态跟踪哪个日期输入框被聚焦
|
||||
const [focusedInput, setFocusedInput] = useState<string | null>(null);
|
||||
|
||||
// 格式化显示日期
|
||||
const formattedStartDate = startDate ? formatDate(startDate, format) : "";
|
||||
const formattedEndDate = endDate ? formatDate(endDate, format) : "";
|
||||
|
||||
// 保持原始日期输入框的显示格式
|
||||
useEffect(() => {
|
||||
if (startInputRef.current) {
|
||||
startInputRef.current.setAttribute('data-display-value', formattedStartDate || placeholder);
|
||||
}
|
||||
if (endInputRef.current) {
|
||||
endInputRef.current.setAttribute('data-display-value', formattedEndDate || placeholder);
|
||||
}
|
||||
}, [formattedStartDate, formattedEndDate, placeholder]);
|
||||
|
||||
// 处理日期输入框全局点击
|
||||
const handleWrapperClick = (inputRef: React.RefObject<HTMLInputElement>) => {
|
||||
if (inputRef.current) {
|
||||
// console.log('Wrapper clicked, triggering date input');
|
||||
// 点击整个包装器区域时,触发输入框点击
|
||||
inputRef.current.focus();
|
||||
inputRef.current.click();
|
||||
|
||||
try {
|
||||
// 检查并记录showPicker是否可用
|
||||
const hasShowPicker = typeof inputRef.current.showPicker === 'function';
|
||||
console.log('showPicker API available:', hasShowPicker);
|
||||
|
||||
// 尝试使用showPicker API
|
||||
if (hasShowPicker) {
|
||||
inputRef.current.showPicker();
|
||||
console.log('showPicker called successfully');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to show date picker:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 处理键盘事件
|
||||
const handleKeyDown = (e: React.KeyboardEvent, inputRef: React.RefObject<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleWrapperClick(inputRef);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理聚焦和失焦
|
||||
const handleFocus = (id: string) => {
|
||||
setFocusedInput(id);
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
setFocusedInput(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`date-range-picker ${className}`}>
|
||||
<div className="date-range-fields">
|
||||
<div className="date-field">
|
||||
<label htmlFor={startId} className="date-label">{startLabel}</label>
|
||||
<input
|
||||
id={startId}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={startDate}
|
||||
onChange={(e) => onStartDateChange(e.target.value)}
|
||||
/>
|
||||
<div
|
||||
className={`date-input-wrapper ${focusedInput === startId ? 'focused' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleWrapperClick(startInputRef);
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, startInputRef)}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
aria-label={`选择${startLabel}日期`}
|
||||
>
|
||||
<input
|
||||
id={startId}
|
||||
ref={startInputRef}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={startDate}
|
||||
onChange={(e) => onStartDateChange(e.target.value)}
|
||||
onFocus={() => handleFocus(startId)}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
<div
|
||||
className={`date-display ${!formattedStartDate ? 'placeholder' : ''}`}
|
||||
>
|
||||
{formattedStartDate || placeholder}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span className="date-separator">至</span>
|
||||
<div className="date-field">
|
||||
<label htmlFor={endId} className="date-label">{endLabel}</label>
|
||||
<input
|
||||
id={endId}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={endDate}
|
||||
onChange={(e) => onEndDateChange(e.target.value)}
|
||||
/>
|
||||
<div
|
||||
className={`date-input-wrapper ${focusedInput === endId ? 'focused' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleWrapperClick(endInputRef);
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, endInputRef)}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
aria-label={`选择${endLabel}日期`}
|
||||
>
|
||||
<input
|
||||
id={endId}
|
||||
ref={endInputRef}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={endDate}
|
||||
onChange={(e) => onEndDateChange(e.target.value)}
|
||||
onFocus={() => handleFocus(endId)}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
<div
|
||||
className={`date-display ${!formattedEndDate ? 'placeholder' : ''}`}
|
||||
>
|
||||
{formattedEndDate || placeholder}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,28 +198,132 @@ export function SimpleDateRangePicker({
|
||||
onEndDateChange,
|
||||
className = "",
|
||||
startId = "date-start-simple",
|
||||
endId = "date-end-simple"
|
||||
endId = "date-end-simple",
|
||||
format = "yyyy-MM-dd",
|
||||
placeholder = "请选择时间"
|
||||
}: Omit<DateRangePickerProps, 'startLabel' | 'endLabel'>) {
|
||||
// 使用ref获取input元素
|
||||
const startInputRef = useRef<HTMLInputElement>(null);
|
||||
const endInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// 添加状态跟踪哪个日期输入框被聚焦
|
||||
const [focusedInput, setFocusedInput] = useState<string | null>(null);
|
||||
|
||||
// 格式化显示日期
|
||||
const formattedStartDate = startDate ? formatDate(startDate, format) : "";
|
||||
const formattedEndDate = endDate ? formatDate(endDate, format) : "";
|
||||
|
||||
// 保持原始日期输入框的显示格式
|
||||
useEffect(() => {
|
||||
if (startInputRef.current) {
|
||||
startInputRef.current.setAttribute('data-display-value', formattedStartDate || placeholder);
|
||||
}
|
||||
if (endInputRef.current) {
|
||||
endInputRef.current.setAttribute('data-display-value', formattedEndDate || placeholder);
|
||||
}
|
||||
}, [formattedStartDate, formattedEndDate, placeholder]);
|
||||
|
||||
// 处理日期输入框全局点击
|
||||
const handleWrapperClick = (inputRef: React.RefObject<HTMLInputElement>) => {
|
||||
if (inputRef.current) {
|
||||
console.log('Wrapper clicked, triggering date input');
|
||||
// 点击整个包装器区域时,触发输入框点击
|
||||
inputRef.current.focus();
|
||||
inputRef.current.click();
|
||||
|
||||
try {
|
||||
// 检查并记录showPicker是否可用
|
||||
const hasShowPicker = typeof inputRef.current.showPicker === 'function';
|
||||
console.log('showPicker API available:', hasShowPicker);
|
||||
|
||||
// 尝试使用showPicker API
|
||||
if (hasShowPicker) {
|
||||
inputRef.current.showPicker();
|
||||
console.log('showPicker called successfully');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to show date picker:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 处理键盘事件
|
||||
const handleKeyDown = (e: React.KeyboardEvent, inputRef: React.RefObject<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleWrapperClick(inputRef);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理聚焦和失焦
|
||||
const handleFocus = (id: string) => {
|
||||
setFocusedInput(id);
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
setFocusedInput(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`date-range-picker simple-date-range-picker ${className}`}>
|
||||
<div className="date-range-fields">
|
||||
<input
|
||||
id={startId}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={startDate}
|
||||
onChange={(e) => onStartDateChange(e.target.value)}
|
||||
aria-label="开始日期"
|
||||
/>
|
||||
<div
|
||||
className={`date-input-wrapper ${focusedInput === startId ? 'focused' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleWrapperClick(startInputRef);
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, startInputRef)}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
aria-label="选择开始日期"
|
||||
>
|
||||
<input
|
||||
id={startId}
|
||||
ref={startInputRef}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={startDate}
|
||||
onChange={(e) => onStartDateChange(e.target.value)}
|
||||
onFocus={() => handleFocus(startId)}
|
||||
onBlur={handleBlur}
|
||||
aria-label="开始日期"
|
||||
/>
|
||||
<div
|
||||
className={`date-display ${!formattedStartDate ? 'placeholder' : ''}`}
|
||||
>
|
||||
{formattedStartDate || placeholder}
|
||||
</div>
|
||||
</div>
|
||||
<span className="date-separator">至</span>
|
||||
<input
|
||||
id={endId}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={endDate}
|
||||
onChange={(e) => onEndDateChange(e.target.value)}
|
||||
aria-label="结束日期"
|
||||
/>
|
||||
<div
|
||||
className={`date-input-wrapper ${focusedInput === endId ? 'focused' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleWrapperClick(endInputRef);
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, endInputRef)}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
aria-label="选择结束日期"
|
||||
>
|
||||
<input
|
||||
id={endId}
|
||||
ref={endInputRef}
|
||||
type="date"
|
||||
className="date-input"
|
||||
value={endDate}
|
||||
onChange={(e) => onEndDateChange(e.target.value)}
|
||||
onFocus={() => handleFocus(endId)}
|
||||
onBlur={handleBlur}
|
||||
aria-label="结束日期"
|
||||
/>
|
||||
<div
|
||||
className={`date-display ${!formattedEndDate ? 'placeholder' : ''}`}
|
||||
>
|
||||
{formattedEndDate || placeholder}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user