feat: 添加遮罩筛选

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-04-25 13:02:05 +08:00
co-authored by Copilot
parent d1c5b818d9
commit d82872ad18
7 changed files with 109 additions and 6 deletions
@@ -141,9 +141,6 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
<h2 className="mt-2 text-2xl font-semibold text-gray-900 dark:text-white">
{periodLabel}
</h2>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
切换日期时会自动取消上一条请求,图表与排行保持同步刷新。
</p>
</div>
<div className="flex flex-col gap-3 sm:flex-row sm:items-center">
@@ -296,6 +293,10 @@ export default function ScreenTimeTab({ hostname }: ScreenTimeTabProps) {
<span>{app.percentage}%</span>
</div>
<div className="mt-2 truncate text-xs text-gray-500 dark:text-gray-400" title={app.processPath || '路径未知'}>
路径: {app.processPath || '路径未知'}
</div>
<div className="mt-3 h-2 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700">
<div
className="h-full rounded-full bg-blue-600 dark:bg-blue-500"
+12 -1
View File
@@ -28,6 +28,7 @@ interface TitleUsage {
interface MutableAppUsage {
processId: string
rawProcessName: string
rawProcessPath: string
durationMs: number
titleDurations: Map<string, number>
}
@@ -111,12 +112,14 @@ const getLocalDateUtcMs = (parts: DateParts, tzOffsetMinutes: number) => {
const normalizeProcess = (processPath: string, title: string) => {
const rawProcessName = win32.basename(processPath || '').trim()
const rawProcessPath = processPath.trim()
const normalizedTitle = cleanTitle(title)
const fallbackId = normalizedTitle ? `title:${normalizedTitle.toLowerCase()}` : 'unknown'
return {
processId: rawProcessName ? rawProcessName.toLowerCase() : fallbackId,
rawProcessName
rawProcessName,
rawProcessPath
}
}
@@ -228,6 +231,7 @@ const addDurationToUsageMap = (
usageMap: Map<string, MutableAppUsage>,
processId: string,
rawProcessName: string,
rawProcessPath: string,
title: string,
durationMs: number
) => {
@@ -240,12 +244,16 @@ const addDurationToUsageMap = (
if (!existing.rawProcessName && rawProcessName) {
existing.rawProcessName = rawProcessName
}
if (!existing.rawProcessPath && rawProcessPath) {
existing.rawProcessPath = rawProcessPath
}
return
}
usageMap.set(processId, {
processId,
rawProcessName,
rawProcessPath,
durationMs,
titleDurations: new Map([[title, durationMs]])
})
@@ -266,6 +274,7 @@ const buildAppList = (usageMap: Map<string, MutableAppUsage>) => {
processId: app.processId,
processName: resolveProcessDisplayName(app.rawProcessName, sortedTitles),
rawProcessName: app.rawProcessName,
processPath: app.rawProcessPath,
durationSeconds: Math.round(app.durationMs / 1000),
percentage: totalDurationMs > 0 ? Number(((app.durationMs / totalDurationMs) * 100).toFixed(2)) : 0,
titleCount: sortedTitles.length,
@@ -384,6 +393,7 @@ async function handleScreenTime(req: NextRequest) {
aggregateUsageMap,
process.processId,
process.rawProcessName,
process.rawProcessPath,
title,
aggregateContributionMs
)
@@ -393,6 +403,7 @@ async function handleScreenTime(req: NextRequest) {
selectedDayUsageMap,
process.processId,
process.rawProcessName,
process.rawProcessPath,
title,
selectedDayContributionMs
)
+3 -1
View File
@@ -3,6 +3,7 @@ import { prisma } from '@/lib/prisma'
import { storeFile } from '@/lib/fileStorage'
import { push } from '@/lib/push'
import { withCors } from '@/lib/middleware'
import { filterIgnoredWindows } from '@/lib/windowFilters'
import ffmpeg from 'fluent-ffmpeg'
import { writeFileSync, unlinkSync, mkdtempSync, readFileSync, rmSync } from 'fs'
import { tmpdir } from 'os'
@@ -28,7 +29,8 @@ async function handleScreenshotUpload(req: NextRequest) {
const formData = await req.formData()
const files: File[] = []
const windowsInfo: WindowInfo[] = JSON.parse(formData.get('windows_info') as string || '[]')
const rawWindowsInfo: WindowInfo[] = JSON.parse(formData.get('windows_info') as string || '[]')
const windowsInfo = filterIgnoredWindows(rawWindowsInfo)
// Extract files from formData
for (const [key, value] of formData.entries()) {
+1
View File
@@ -33,6 +33,7 @@ export interface ScreenTimeAppUsage {
processId: string;
processName: string;
rawProcessName: string;
processPath: string;
durationSeconds: number;
percentage: number;
titleCount: number;