feat: 标签调整宽度和图标,top 3 -> top 4
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
520cfd96c7
commit
fea99d37fe
@ -24,30 +24,27 @@ interface ScreenTimeOverviewChartProps {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
refreshing: boolean;
|
refreshing: boolean;
|
||||||
onSelectDate: (date: string, nextUnit?: 'day' | 'week') => void;
|
onSelectDate: (date: string, nextUnit?: 'day' | 'week') => void;
|
||||||
onSpotlightAppClick: (processId: string) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WeekChartDatum {
|
const SPOTLIGHT_COLORS = ['#2f7cff', '#17c3d1', '#ff9f43', '#ff6b6b'] as const;
|
||||||
|
const SPOTLIGHT_KEYS = ['spotlight_0', 'spotlight_1', 'spotlight_2', 'spotlight_3'] as const;
|
||||||
|
type SpotlightKey = typeof SPOTLIGHT_KEYS[number];
|
||||||
|
|
||||||
|
type WeekChartDatum = Record<SpotlightKey, number> & {
|
||||||
date: string;
|
date: string;
|
||||||
label: string;
|
label: string;
|
||||||
totalDurationSeconds: number;
|
totalDurationSeconds: number;
|
||||||
mutedDuration: number;
|
mutedDuration: number;
|
||||||
selectedRemainder: number;
|
selectedRemainder: number;
|
||||||
spotlight_0: number;
|
|
||||||
spotlight_1: number;
|
|
||||||
spotlight_2: number;
|
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
interface HourChartDatum {
|
type HourChartDatum = Record<SpotlightKey, number> & {
|
||||||
hour: number;
|
hour: number;
|
||||||
label: string;
|
label: string;
|
||||||
totalDurationSeconds: number;
|
totalDurationSeconds: number;
|
||||||
spotlight_0: number;
|
|
||||||
spotlight_1: number;
|
|
||||||
spotlight_2: number;
|
|
||||||
otherDurationSeconds: number;
|
otherDurationSeconds: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
interface TooltipPayloadRow<T> {
|
interface TooltipPayloadRow<T> {
|
||||||
payload: T;
|
payload: T;
|
||||||
@ -62,11 +59,10 @@ interface RoundedBarShapeProps {
|
|||||||
payload?: Record<string, unknown>;
|
payload?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPOTLIGHT_COLORS = ['#2f7cff', '#17c3d1', '#ff9f43'];
|
|
||||||
const OTHER_COLOR = '#d4d7df';
|
const OTHER_COLOR = '#d4d7df';
|
||||||
const MUTED_BAR_COLOR = '#cfd3dc';
|
const MUTED_BAR_COLOR = '#cfd3dc';
|
||||||
const WEEK_STACK_KEYS = ['mutedDuration', 'spotlight_0', 'spotlight_1', 'spotlight_2', 'selectedRemainder'] as const;
|
const WEEK_STACK_KEYS = ['mutedDuration', ...SPOTLIGHT_KEYS, 'selectedRemainder'] as const;
|
||||||
const HOUR_STACK_KEYS = ['spotlight_0', 'spotlight_1', 'spotlight_2', 'otherDurationSeconds'] as const;
|
const HOUR_STACK_KEYS = [...SPOTLIGHT_KEYS, 'otherDurationSeconds'] as const;
|
||||||
|
|
||||||
const getNumericValue = (value: unknown) => {
|
const getNumericValue = (value: unknown) => {
|
||||||
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
return typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
||||||
@ -218,10 +214,10 @@ function HourTooltip({
|
|||||||
if (!active || !payload || payload.length === 0) return null;
|
if (!active || !payload || payload.length === 0) return null;
|
||||||
|
|
||||||
const datum = payload[0].payload;
|
const datum = payload[0].payload;
|
||||||
const rows = [0, 1, 2]
|
const rows: Array<{ label: string; value: number; color: string }> = SPOTLIGHT_KEYS
|
||||||
.map((index) => ({
|
.map((key, index) => ({
|
||||||
label: spotlightNames[index],
|
label: spotlightNames[index] ?? '',
|
||||||
value: datum[`spotlight_${index}` as keyof HourChartDatum] as number,
|
value: datum[key],
|
||||||
color: SPOTLIGHT_COLORS[index]
|
color: SPOTLIGHT_COLORS[index]
|
||||||
}))
|
}))
|
||||||
.filter((row) => row.label && row.value > 0);
|
.filter((row) => row.label && row.value > 0);
|
||||||
@ -261,7 +257,6 @@ export default function ScreenTimeOverviewChart({
|
|||||||
loading,
|
loading,
|
||||||
refreshing,
|
refreshing,
|
||||||
onSelectDate,
|
onSelectDate,
|
||||||
onSpotlightAppClick
|
|
||||||
}: ScreenTimeOverviewChartProps) {
|
}: ScreenTimeOverviewChartProps) {
|
||||||
const weekChartData = useMemo(() => {
|
const weekChartData = useMemo(() => {
|
||||||
if (!data) return [] as WeekChartDatum[];
|
if (!data) return [] as WeekChartDatum[];
|
||||||
@ -269,32 +264,46 @@ export default function ScreenTimeOverviewChart({
|
|||||||
const spotlightTotal = data.overview.selectedDay.spotlightApps
|
const spotlightTotal = data.overview.selectedDay.spotlightApps
|
||||||
.reduce((sum, app) => sum + app.durationSeconds, 0);
|
.reduce((sum, app) => sum + app.durationSeconds, 0);
|
||||||
|
|
||||||
return data.overview.week.days.map((day) => ({
|
return data.overview.week.days.map((day) => {
|
||||||
date: day.date,
|
const spotlightDurations = Object.fromEntries(
|
||||||
label: day.weekdayLabel,
|
SPOTLIGHT_KEYS.map((key, index) => [
|
||||||
totalDurationSeconds: day.totalDurationSeconds,
|
key,
|
||||||
mutedDuration: day.isSelected ? 0 : day.totalDurationSeconds,
|
day.isSelected ? (data.overview.selectedDay.spotlightApps[index]?.durationSeconds ?? 0) : 0
|
||||||
selectedRemainder: day.isSelected ? Math.max(day.totalDurationSeconds - spotlightTotal, 0) : 0,
|
])
|
||||||
spotlight_0: day.isSelected ? (data.overview.selectedDay.spotlightApps[0]?.durationSeconds ?? 0) : 0,
|
) as Record<SpotlightKey, number>;
|
||||||
spotlight_1: day.isSelected ? (data.overview.selectedDay.spotlightApps[1]?.durationSeconds ?? 0) : 0,
|
|
||||||
spotlight_2: day.isSelected ? (data.overview.selectedDay.spotlightApps[2]?.durationSeconds ?? 0) : 0,
|
return {
|
||||||
isSelected: day.isSelected
|
date: day.date,
|
||||||
}));
|
label: day.weekdayLabel,
|
||||||
|
totalDurationSeconds: day.totalDurationSeconds,
|
||||||
|
mutedDuration: day.isSelected ? 0 : day.totalDurationSeconds,
|
||||||
|
selectedRemainder: day.isSelected ? Math.max(day.totalDurationSeconds - spotlightTotal, 0) : 0,
|
||||||
|
...spotlightDurations,
|
||||||
|
isSelected: day.isSelected
|
||||||
|
};
|
||||||
|
});
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const hourChartData = useMemo(() => {
|
const hourChartData = useMemo(() => {
|
||||||
if (!data) return [] as HourChartDatum[];
|
if (!data) return [] as HourChartDatum[];
|
||||||
|
|
||||||
const spotlightApps = data.overview.selectedDay.spotlightApps;
|
const spotlightApps = data.overview.selectedDay.spotlightApps;
|
||||||
return data.overview.selectedDay.hours.map((hour) => ({
|
return data.overview.selectedDay.hours.map((hour) => {
|
||||||
hour: hour.hour,
|
const spotlightDurations = Object.fromEntries(
|
||||||
label: hour.label,
|
SPOTLIGHT_KEYS.map((key, index) => [
|
||||||
totalDurationSeconds: hour.totalDurationSeconds,
|
key,
|
||||||
spotlight_0: spotlightApps[0] ? hour.spotlightDurations[spotlightApps[0].processId] ?? 0 : 0,
|
spotlightApps[index] ? hour.spotlightDurations[spotlightApps[index].processId] ?? 0 : 0
|
||||||
spotlight_1: spotlightApps[1] ? hour.spotlightDurations[spotlightApps[1].processId] ?? 0 : 0,
|
])
|
||||||
spotlight_2: spotlightApps[2] ? hour.spotlightDurations[spotlightApps[2].processId] ?? 0 : 0,
|
) as Record<SpotlightKey, number>;
|
||||||
otherDurationSeconds: hour.otherDurationSeconds
|
|
||||||
}));
|
return {
|
||||||
|
hour: hour.hour,
|
||||||
|
label: hour.label,
|
||||||
|
totalDurationSeconds: hour.totalDurationSeconds,
|
||||||
|
...spotlightDurations,
|
||||||
|
otherDurationSeconds: hour.otherDurationSeconds
|
||||||
|
};
|
||||||
|
});
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const spotlightNames = data?.overview.selectedDay.spotlightApps.map((app) => app.processName) ?? [];
|
const spotlightNames = data?.overview.selectedDay.spotlightApps.map((app) => app.processName) ?? [];
|
||||||
@ -402,12 +411,12 @@ export default function ScreenTimeOverviewChart({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Bar>
|
</Bar>
|
||||||
{[0, 1, 2].map((index) => (
|
{SPOTLIGHT_KEYS.map((key, index) => (
|
||||||
<Bar
|
<Bar
|
||||||
key={`spotlight-${index}`}
|
key={key}
|
||||||
dataKey={`spotlight_${index}`}
|
dataKey={key}
|
||||||
stackId="week"
|
stackId="week"
|
||||||
shape={createRoundedTopShape(`spotlight_${index}`, WEEK_STACK_KEYS, 12)}
|
shape={createRoundedTopShape(key, WEEK_STACK_KEYS, 12)}
|
||||||
onClick={(_, clickedIndex) => {
|
onClick={(_, clickedIndex) => {
|
||||||
const day = data.overview.week.days[clickedIndex];
|
const day = data.overview.week.days[clickedIndex];
|
||||||
if (day) {
|
if (day) {
|
||||||
@ -417,7 +426,7 @@ export default function ScreenTimeOverviewChart({
|
|||||||
>
|
>
|
||||||
{weekChartData.map((entry) => (
|
{weekChartData.map((entry) => (
|
||||||
<Cell
|
<Cell
|
||||||
key={`spotlight-cell-${index}-${entry.date}`}
|
key={`spotlight-cell-${key}-${entry.date}`}
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
fill={entry.isSelected ? SPOTLIGHT_COLORS[index] : 'transparent'}
|
fill={entry.isSelected ? SPOTLIGHT_COLORS[index] : 'transparent'}
|
||||||
/>
|
/>
|
||||||
@ -477,13 +486,13 @@ export default function ScreenTimeOverviewChart({
|
|||||||
tickFormatter={formatAxisDuration}
|
tickFormatter={formatAxisDuration}
|
||||||
/>
|
/>
|
||||||
<Tooltip content={<HourTooltip spotlightNames={spotlightNames} />} cursor={{ fill: 'rgba(148, 163, 184, 0.08)' }} />
|
<Tooltip content={<HourTooltip spotlightNames={spotlightNames} />} cursor={{ fill: 'rgba(148, 163, 184, 0.08)' }} />
|
||||||
{[0, 1, 2].map((index) => (
|
{SPOTLIGHT_KEYS.map((key, index) => (
|
||||||
<Bar
|
<Bar
|
||||||
key={`hour-spotlight-${index}`}
|
key={`hour-${key}`}
|
||||||
dataKey={`spotlight_${index}`}
|
dataKey={key}
|
||||||
stackId="hours"
|
stackId="hours"
|
||||||
fill={SPOTLIGHT_COLORS[index]}
|
fill={SPOTLIGHT_COLORS[index]}
|
||||||
shape={createRoundedTopShape(`spotlight_${index}`, HOUR_STACK_KEYS, 10)}
|
shape={createRoundedTopShape(key, HOUR_STACK_KEYS, 10)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<Bar
|
<Bar
|
||||||
@ -496,11 +505,10 @@ export default function ScreenTimeOverviewChart({
|
|||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-3 grid gap-2 sm:grid-cols-3">
|
<div className="mt-3 grid grid-cols-2 gap-2">
|
||||||
{data.overview.selectedDay.spotlightApps.length > 0 ? data.overview.selectedDay.spotlightApps.map((app, index) => (
|
{data.overview.selectedDay.spotlightApps.length > 0 ? data.overview.selectedDay.spotlightApps.map((app, index) => (
|
||||||
<button
|
<button
|
||||||
key={app.processId}
|
key={app.processId}
|
||||||
onClick={() => onSpotlightAppClick(app.processId)}
|
|
||||||
className="flex min-w-0 items-center gap-2 rounded-2xl bg-gray-50 px-3 py-2 text-left transition-colors hover:bg-gray-100 dark:bg-gray-900/70 dark:hover:bg-gray-900"
|
className="flex min-w-0 items-center gap-2 rounded-2xl bg-gray-50 px-3 py-2 text-left transition-colors hover:bg-gray-100 dark:bg-gray-900/70 dark:hover:bg-gray-900"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@ -519,7 +527,7 @@ export default function ScreenTimeOverviewChart({
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
)) : (
|
)) : (
|
||||||
<div className="rounded-2xl bg-gray-50 px-3 py-2 text-sm text-gray-500 dark:bg-gray-900/70 dark:text-gray-400">
|
<div className="col-span-2 rounded-2xl bg-gray-50 px-3 py-2 text-sm text-gray-500 dark:bg-gray-900/70 dark:text-gray-400">
|
||||||
暂无应用数据
|
暂无应用数据
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -28,7 +28,6 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [expandedApps, setExpandedApps] = useState<Set<string>>(new Set());
|
const [expandedApps, setExpandedApps] = useState<Set<string>>(new Set());
|
||||||
const [highlightedProcessId, setHighlightedProcessId] = useState<string | null>(null);
|
|
||||||
const [initialLoading, setInitialLoading] = useState(true);
|
const [initialLoading, setInitialLoading] = useState(true);
|
||||||
|
|
||||||
const abortControllerRef = React.useRef<AbortController | null>(null);
|
const abortControllerRef = React.useRef<AbortController | null>(null);
|
||||||
@ -125,11 +124,6 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
|
|||||||
setSelectedDate(date);
|
setSelectedDate(date);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSpotlightAppClick = (processId: string) => {
|
|
||||||
setHighlightedProcessId(processId);
|
|
||||||
setExpandedApps((previous) => new Set(previous).add(processId));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="rounded-[1.75rem] border border-gray-200 bg-white p-3 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
<div className="rounded-[1.75rem] border border-gray-200 bg-white p-3 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||||
@ -202,7 +196,6 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
|
|||||||
loading={loading || initialLoading}
|
loading={loading || initialLoading}
|
||||||
refreshing={isRefreshing}
|
refreshing={isRefreshing}
|
||||||
onSelectDate={handleOverviewDateSelect}
|
onSelectDate={handleOverviewDateSelect}
|
||||||
onSpotlightAppClick={handleSpotlightAppClick}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
@ -250,16 +243,13 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
|
|||||||
{screenTime.apps.map((app, index) => {
|
{screenTime.apps.map((app, index) => {
|
||||||
const isExpanded = expandedApps.has(app.processId);
|
const isExpanded = expandedApps.has(app.processId);
|
||||||
const processWidth = maxDurationSeconds > 0
|
const processWidth = maxDurationSeconds > 0
|
||||||
? Math.max((app.durationSeconds / maxDurationSeconds) * 100, 4)
|
? Math.max((app.durationSeconds / maxDurationSeconds) * 100, 2)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={app.processId}
|
key={app.processId}
|
||||||
className={`px-4 py-3 transition-colors ${highlightedProcessId === app.processId
|
className={`px-4 py-3 transition-colors`}
|
||||||
? 'bg-blue-50/70 dark:bg-blue-500/8'
|
|
||||||
: ''
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onClick={() => toggleExpanded(app.processId)}
|
onClick={() => toggleExpanded(app.processId)}
|
||||||
@ -280,11 +270,6 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
|
|||||||
<div className="truncate text-base font-semibold text-gray-900 dark:text-white" title={app.processName}>
|
<div className="truncate text-base font-semibold text-gray-900 dark:text-white" title={app.processName}>
|
||||||
{app.processName}
|
{app.processName}
|
||||||
</div>
|
</div>
|
||||||
{highlightedProcessId === app.processId && (
|
|
||||||
<span className="shrink-0 rounded-full bg-blue-100 px-2 py-0.5 text-[11px] font-medium text-blue-700 dark:bg-blue-500/15 dark:text-blue-300">
|
|
||||||
聚焦
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
<span className="shrink-0 rounded-full bg-gray-100 px-2 py-0.5 text-[11px] text-gray-600 dark:bg-gray-700 dark:text-gray-300">
|
<span className="shrink-0 rounded-full bg-gray-100 px-2 py-0.5 text-[11px] text-gray-600 dark:bg-gray-700 dark:text-gray-300">
|
||||||
{app.titleCount} 个标题
|
{app.titleCount} 个标题
|
||||||
</span>
|
</span>
|
||||||
@ -335,7 +320,7 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
|
|||||||
<div className="mt-1.5 h-1.5 overflow-hidden rounded-full bg-white dark:bg-gray-800">
|
<div className="mt-1.5 h-1.5 overflow-hidden rounded-full bg-white dark:bg-gray-800">
|
||||||
<div
|
<div
|
||||||
className="h-full rounded-full bg-emerald-500 dark:bg-emerald-400"
|
className="h-full rounded-full bg-emerald-500 dark:bg-emerald-400"
|
||||||
style={{ width: `${Math.max(title.percentage, 4)}%` }}
|
style={{ width: `${Math.max(title.percentage, 2)}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { ArrowLeft, BarChart3, Star } from 'lucide-react';
|
import { ArrowLeft, BarChart3, Star, KeySquare, ChartNoAxesGantt } from 'lucide-react';
|
||||||
import ScreenshotsTab from './components/ScreenshotsTab';
|
import ScreenshotsTab from './components/ScreenshotsTab';
|
||||||
import ScreenTimeTab from './components/ScreenTimeTab';
|
import ScreenTimeTab from './components/ScreenTimeTab';
|
||||||
import StarredTab from './components/StarredTab';
|
import StarredTab from './components/StarredTab';
|
||||||
@ -59,15 +59,15 @@ export default function HostDetail() {
|
|||||||
|
|
||||||
{/* 选项卡导航 */}
|
{/* 选项卡导航 */}
|
||||||
<div className="mb-6 border-b border-gray-200 dark:border-gray-700">
|
<div className="mb-6 border-b border-gray-200 dark:border-gray-700">
|
||||||
<nav className="-mb-px flex space-x-8">
|
<nav className="-mb-px flex space-x-6">
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveTab('screenshots')}
|
onClick={() => setActiveTab('screenshots')}
|
||||||
className={`py-2 px-1 border-b-2 font-medium text-sm ${activeTab === 'screenshots'
|
className={`py-2 px-1 border-b-2 font-medium text-sm flex items-center ${activeTab === 'screenshots'
|
||||||
? 'border-blue-600 text-blue-600'
|
? 'border-blue-600 text-blue-600'
|
||||||
: 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
|
: 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
|
||||||
}`}
|
}`}
|
||||||
>
|
><ChartNoAxesGantt className="h-4 w-4 mr-1"/>
|
||||||
截图时间线
|
时间线
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveTab('screen-time')}
|
onClick={() => setActiveTab('screen-time')}
|
||||||
@ -87,16 +87,17 @@ export default function HostDetail() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Star className="h-4 w-4 mr-1" />
|
<Star className="h-4 w-4 mr-1" />
|
||||||
星标记录
|
星标
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveTab('credentials')}
|
onClick={() => setActiveTab('credentials')}
|
||||||
className={`py-2 px-1 border-b-2 font-medium text-sm ${activeTab === 'credentials'
|
className={`py-2 px-1 border-b-2 font-medium text-sm flex items-center ${activeTab === 'credentials'
|
||||||
? 'border-blue-600 text-blue-600'
|
? 'border-blue-600 text-blue-600'
|
||||||
: 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
|
: 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
凭据信息
|
<KeySquare className="h-4 w-4 mr-1" />
|
||||||
|
凭据
|
||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Prisma } from '@prisma/client'
|
|||||||
const MAX_GAP_MS = 5 * 60 * 1000
|
const MAX_GAP_MS = 5 * 60 * 1000
|
||||||
const DEFAULT_SAMPLE_MS = 30 * 1000
|
const DEFAULT_SAMPLE_MS = 30 * 1000
|
||||||
const MIN_SAMPLE_MS = 5 * 1000
|
const MIN_SAMPLE_MS = 5 * 1000
|
||||||
|
const SPOTLIGHT_APP_LIMIT = 4
|
||||||
const LABEL_TOKEN_THRESHOLD_RATIO = 0.5
|
const LABEL_TOKEN_THRESHOLD_RATIO = 0.5
|
||||||
const HOUR_MS = 60 * 60 * 1000
|
const HOUR_MS = 60 * 60 * 1000
|
||||||
const DAY_MS = 24 * HOUR_MS
|
const DAY_MS = 24 * HOUR_MS
|
||||||
@ -458,7 +459,7 @@ async function handleScreenTime(req: NextRequest) {
|
|||||||
|
|
||||||
const aggregateSummary = buildAppList(aggregateUsageMap)
|
const aggregateSummary = buildAppList(aggregateUsageMap)
|
||||||
const selectedDaySummary = buildAppList(selectedDayUsageMap)
|
const selectedDaySummary = buildAppList(selectedDayUsageMap)
|
||||||
const spotlightApps = selectedDaySummary.apps.slice(0, 3).map(app => ({
|
const spotlightApps = selectedDaySummary.apps.slice(0, SPOTLIGHT_APP_LIMIT).map(app => ({
|
||||||
processId: app.processId,
|
processId: app.processId,
|
||||||
processName: app.processName,
|
processName: app.processName,
|
||||||
durationSeconds: app.durationSeconds,
|
durationSeconds: app.durationSeconds,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user