Files
Cli-Proxy-API-Management-Ce…/src/components/monitor/TimeRangeSelector.tsx
kongkongyo e4850656a5 feat: 增强文档和监控功能
主要更新:
- 完善 README 文档,新增中文详细使用说明与监控中心介绍
- 优化 README.md 文档内容和格式,增加英文和中文文档切换链接
- 新增监控中心模块,支持请求日志、统计分析和模型管理
- 增强 AI 提供商配置页面,添加配置搜索功能
- 更新 .gitignore,移除无效注释和调整条目名称
- 删除 README_CN.md 文件,统一文档结构

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 00:58:48 +08:00

159 lines
4.7 KiB
TypeScript

import { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import styles from '@/pages/MonitorPage.module.scss';
export type TimeRange = 1 | 7 | 14 | 30 | 'custom';
interface DateRange {
start: Date;
end: Date;
}
interface TimeRangeSelectorProps {
value: TimeRange;
onChange: (range: TimeRange, customRange?: DateRange) => void;
customRange?: DateRange;
}
export function TimeRangeSelector({ value, onChange, customRange }: TimeRangeSelectorProps) {
const { t } = useTranslation();
const [showCustom, setShowCustom] = useState(value === 'custom');
const [startDate, setStartDate] = useState(() => {
if (customRange?.start) {
return formatDateForInput(customRange.start);
}
const date = new Date();
date.setDate(date.getDate() - 7);
return formatDateForInput(date);
});
const [endDate, setEndDate] = useState(() => {
if (customRange?.end) {
return formatDateForInput(customRange.end);
}
return formatDateForInput(new Date());
});
const handleTimeClick = useCallback((range: TimeRange) => {
if (range === 'custom') {
setShowCustom(true);
onChange(range);
} else {
setShowCustom(false);
onChange(range);
}
}, [onChange]);
const handleApplyCustom = useCallback(() => {
if (startDate && endDate) {
const start = new Date(startDate);
start.setHours(0, 0, 0, 0);
const end = new Date(endDate);
end.setHours(23, 59, 59, 999);
if (start <= end) {
onChange('custom', { start, end });
}
}
}, [startDate, endDate, onChange]);
return (
<div className={styles.timeRangeSelector}>
<div className={styles.timeButtons}>
{([1, 7, 14, 30, 'custom'] as TimeRange[]).map((range) => (
<button
key={range}
className={`${styles.timeButton} ${value === range ? styles.active : ''}`}
onClick={() => handleTimeClick(range)}
>
{range === 1
? t('monitor.time.today')
: range === 'custom'
? t('monitor.time.custom')
: t('monitor.time.last_n_days', { n: range })}
</button>
))}
</div>
{showCustom && (
<div className={styles.customDatePicker}>
<input
type="date"
className={styles.dateInput}
value={startDate}
onChange={(e) => setStartDate(e.target.value)}
/>
<span className={styles.dateSeparator}>{t('monitor.time.to')}</span>
<input
type="date"
className={styles.dateInput}
value={endDate}
onChange={(e) => setEndDate(e.target.value)}
/>
<button className={styles.dateApplyBtn} onClick={handleApplyCustom}>
{t('monitor.time.apply')}
</button>
</div>
)}
</div>
);
}
function formatDateForInput(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
// 根据时间范围过滤数据的工具函数
export function filterByTimeRange<T extends { timestamp?: string }>(
items: T[],
range: TimeRange,
customRange?: DateRange
): T[] {
const now = new Date();
let cutoffStart: Date;
let cutoffEnd: Date = new Date(now.getTime());
cutoffEnd.setHours(23, 59, 59, 999);
if (range === 'custom' && customRange) {
cutoffStart = customRange.start;
cutoffEnd = customRange.end;
} else if (typeof range === 'number') {
cutoffStart = new Date(now.getTime() - range * 24 * 60 * 60 * 1000);
cutoffStart.setHours(0, 0, 0, 0);
} else {
// 默认7天
cutoffStart = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
cutoffStart.setHours(0, 0, 0, 0);
}
return items.filter((item) => {
if (!item.timestamp) return false;
const timestamp = new Date(item.timestamp);
return timestamp >= cutoffStart && timestamp <= cutoffEnd;
});
}
// 格式化时间范围显示
export function formatTimeRangeCaption(
range: TimeRange,
customRange?: DateRange,
t?: (key: string, options?: any) => string
): string {
if (range === 'custom' && customRange) {
const startStr = formatDateForDisplay(customRange.start);
const endStr = formatDateForDisplay(customRange.end);
return `${startStr} - ${endStr}`;
}
if (range === 1) {
return t ? t('monitor.time.today') : '今天';
}
return t ? t('monitor.time.last_n_days', { n: range }) : `最近 ${range}`;
}
function formatDateForDisplay(date: Date): string {
const month = date.getMonth() + 1;
const day = date.getDate();
return `${month}/${day}`;
}