feat: 添加 ip 追踪

This commit is contained in:
2026-06-09 18:43:54 +08:00
parent ca654754ae
commit 7571316685
10 changed files with 261 additions and 0 deletions
@@ -851,6 +851,26 @@ export default function ScreenshotsTab({
</div>
</div>
</div>
<div className="w-full mt-6">
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-3">来源 IP</h3>
<div className="bg-gray-50 dark:bg-gray-700 rounded-md p-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="p-4 bg-white dark:bg-gray-800 rounded-md shadow-sm">
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">IP 地址</div>
<div className="font-medium text-gray-900 dark:text-white break-all">
{selectedRecord.ip || '未记录'}
</div>
</div>
<div className="p-4 bg-white dark:bg-gray-800 rounded-md shadow-sm">
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">归属地</div>
<div className="font-medium text-gray-900 dark:text-white break-all">
{selectedRecord.ipLocation || (selectedRecord.ip ? '未知归属地' : '未记录')}
</div>
</div>
</div>
</div>
</div>
</div>
)}
</div>
@@ -4,6 +4,8 @@ import { storeFile } from '@/lib/fileStorage'
import { push } from '@/lib/push'
import { withCors } from '@/lib/middleware'
import { filterIgnoredWindows } from '@/lib/windowFilters'
import { getClientIp } from '@/lib/clientIp'
import { getIpGeodataLabel } from '@/lib/geodata'
import ffmpeg from 'fluent-ffmpeg'
import { writeFileSync, unlinkSync, mkdtempSync, readFileSync, rmSync } from 'fs'
import { tmpdir } from 'os'
@@ -27,6 +29,8 @@ async function handleScreenshotUpload(req: NextRequest) {
return NextResponse.json({ error: '缺少主机名' }, { status: 400 })
}
const clientIp = getClientIp(req)
const formData = await req.formData()
const files: File[] = []
const rawWindowsInfo: WindowInfo[] = JSON.parse(formData.get('windows_info') as string || '[]')
@@ -127,6 +131,7 @@ async function handleScreenshotUpload(req: NextRequest) {
const newRecord = await prisma.record.create({
data: {
hostname,
ip: clientIp,
timestamp: new Date(),
windows: {
create: windowsInfo
@@ -226,6 +231,7 @@ async function handleGetScreenshots(req: NextRequest) {
select: {
id: true,
timestamp: true,
ip: true,
isStarred: true,
windows: {
select: {
@@ -262,6 +268,7 @@ async function handleGetScreenshots(req: NextRequest) {
// Convert BigInt to string in windows.memory field
const serializedRecords = records.map(record => ({
...record,
ipLocation: getIpGeodataLabel(record.ip),
windows: record.windows.map(window => ({
...window,
memory: window.memory.toString()
+2
View File
@@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { withCors } from '@/lib/middleware'
import { getIpGeodataLabel } from '@/lib/geodata'
// 获取指定主机的星标记录
async function handleGetStarredRecords(req: NextRequest) {
@@ -49,6 +50,7 @@ async function handleGetStarredRecords(req: NextRequest) {
})
const serializedRecords = records.map(record => ({
...record,
ipLocation: getIpGeodataLabel(record.ip),
windows: record.windows.map(window => ({
...window,
memory: window.memory.toString()
+2
View File
@@ -13,6 +13,8 @@ export interface Window {
export interface ScreenRecord {
id: string;
timestamp: string;
ip: string | null;
ipLocation: string | null;
isStarred: boolean;
windows: Window[];
screenshots: Screenshot[];