时间范围联动数据:Dashboard 管理 rangeKey 状态,useDashboardData 按天数生成 dailyStats

This commit is contained in:
wangxiaoji 2026-06-30 14:35:03 +08:00
parent d2913ff260
commit 65c28251f9
3 changed files with 26 additions and 11 deletions

View File

@ -48,9 +48,10 @@ const BentoTrend = ({
className = '',
onRefresh,
loading = false,
rangeKey = '7d',
onRangeChange,
}) => {
const [rangeOpen, setRangeOpen] = useState(false);
const [selectedKey, setSelectedKey] = useState('7d');
const [customStart, setCustomStart] = useState('');
const [customEnd, setCustomEnd] = useState('');
const [tooltip, setTooltip] = useState(null); // { dayIdx, x, y } or null
@ -67,11 +68,11 @@ const BentoTrend = ({
return () => document.removeEventListener('mousedown', handler);
}, []);
const selectedLabel = RANGE_OPTIONS.find((r) => r.key === selectedKey)?.label || '近 7 天';
const selectedLabel = RANGE_OPTIONS.find((r) => r.key === rangeKey)?.label || '近 7 天';
const handleApply = () => {
if (customStart && customEnd) {
setSelectedKey('custom');
onRangeChange('custom');
}
setRangeOpen(false);
};
@ -150,13 +151,13 @@ const BentoTrend = ({
<button
key={opt.key}
onClick={() => {
setSelectedKey(opt.key);
onRangeChange(opt.key);
setCustomStart('');
setCustomEnd('');
setRangeOpen(false);
}}
className={`w-full rounded-lg px-3 py-1.5 text-left text-xs transition-colors ${
selectedKey === opt.key
rangeKey === opt.key
? 'bg-blue-50 font-medium text-blue-700 dark:bg-blue-500/10 dark:text-blue-400'
: 'text-slate-600 hover:bg-slate-50 dark:text-white/60 dark:hover:bg-white/5'
}`}

View File

@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import React, { useContext } from 'react';
import React, { useContext, useState } from 'react';
import { UserContext } from '../../context/User';
import { useUserMessageUnreadCount } from '../../hooks/common/useUserMessageUnreadCount';
import { useDashboardData } from '../../hooks/dashboard/useDashboardData';
@ -30,11 +30,23 @@ import BentoTrend from './BentoTrend';
import MonthlyForecast from './MonthlyForecast';
import RecentActivity from './RecentActivity';
const RANGE_DAYS = {
today: 1,
yesterday: 1,
'24h': 1,
'7d': 7,
'14d': 14,
'30d': 30,
};
const Dashboard = () => {
const [userState] = useContext(UserContext);
const user = userState?.user;
const [rangeKey, setRangeKey] = useState('7d');
const dashboard = useDashboardData(userState);
const rangeDays = RANGE_DAYS[rangeKey] || 7;
const dashboard = useDashboardData(userState, rangeDays);
const { unreadCount } = useUserMessageUnreadCount(user);
return (
@ -66,6 +78,8 @@ const Dashboard = () => {
topModels={dashboard.topModels}
onRefresh={dashboard.refresh}
loading={dashboard.loading}
rangeKey={rangeKey}
onRangeChange={setRangeKey}
className='md:col-span-2'
/>
<MonthlyForecast
@ -88,4 +102,4 @@ const Dashboard = () => {
);
};
export default Dashboard;
export default Dashboard;

View File

@ -28,7 +28,7 @@ const isSuccess = (l) =>
const sum = (arr, key) =>
arr.reduce((s, l) => s + (Number(l[key]) || 0), 0);
export const useDashboardData = (userState) => {
export const useDashboardData = (userState, rangeDays = 7) => {
const initialized = useRef(false);
const [loading, setLoading] = useState(false);
const [recentLogs, setRecentLogs] = useState([]);
@ -138,7 +138,7 @@ export const useDashboardData = (userState) => {
const dailyStats = useMemo(() => {
const now = new Date();
const days = [];
const n = 7;
const n = rangeDays;
for (let i = n - 1; i >= 0; i--) {
const d = new Date(now.getFullYear(), now.getMonth(), now.getDate() - i);
const dayStart = Math.floor(d.getTime() / 1000);
@ -160,7 +160,7 @@ export const useDashboardData = (userState) => {
});
}
return days;
}, [recentLogs]);
}, [recentLogs, rangeDays]);
// ========== MoM delta (this month cost vs last month) ==========
const monthDelta = useMemo(() => {