Reorganize modules, add AI Agent smart interaction, include prompt settings, enhance data output with subscriptions, and separate system monitoring. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
239 lines
8.0 KiB
TypeScript
239 lines
8.0 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from "react"
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Badge } from "@/components/ui/badge"
|
||
import { Input } from "@/components/ui/input"
|
||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||
import {
|
||
ScrollText, Search, Download, Filter, User,
|
||
Database, Settings, Tag, Package, Bot
|
||
} from "lucide-react"
|
||
|
||
const logs = [
|
||
{
|
||
id: "1",
|
||
time: "2024-01-15 14:35:22",
|
||
user: "admin@example.com",
|
||
action: "创建流量包",
|
||
module: "数据输出",
|
||
detail: "创建流量包「高价值用户包」,包含15,680个用户",
|
||
ip: "192.168.1.100",
|
||
status: "success",
|
||
},
|
||
{
|
||
id: "2",
|
||
time: "2024-01-15 14:30:15",
|
||
user: "analyst@example.com",
|
||
action: "执行AI打标",
|
||
module: "AI Agent",
|
||
detail: "执行AI打标任务,处理8,500条用户数据",
|
||
ip: "192.168.1.101",
|
||
status: "success",
|
||
},
|
||
{
|
||
id: "3",
|
||
time: "2024-01-15 14:25:08",
|
||
user: "admin@example.com",
|
||
action: "修改标签规则",
|
||
module: "标签画像",
|
||
detail: "修改标签「高价值用户」的计算规则",
|
||
ip: "192.168.1.100",
|
||
status: "success",
|
||
},
|
||
{
|
||
id: "4",
|
||
time: "2024-01-15 14:20:00",
|
||
user: "system",
|
||
action: "数据同步",
|
||
module: "数据接入",
|
||
detail: "MySQL数据源同步完成,新增12,500条记录",
|
||
ip: "-",
|
||
status: "success",
|
||
},
|
||
{
|
||
id: "5",
|
||
time: "2024-01-15 14:15:30",
|
||
user: "analyst@example.com",
|
||
action: "导出数据",
|
||
module: "数据输出",
|
||
detail: "导出用户画像数据,共5,000条记录",
|
||
ip: "192.168.1.101",
|
||
status: "success",
|
||
},
|
||
{
|
||
id: "6",
|
||
time: "2024-01-15 14:10:00",
|
||
user: "system",
|
||
action: "任务执行失败",
|
||
module: "数据接入",
|
||
detail: "API数据源同步失败:连接超时",
|
||
ip: "-",
|
||
status: "failed",
|
||
},
|
||
]
|
||
|
||
const getModuleIcon = (module: string) => {
|
||
switch (module) {
|
||
case "数据接入":
|
||
return <Database className="h-4 w-4" />
|
||
case "标签画像":
|
||
return <Tag className="h-4 w-4" />
|
||
case "AI Agent":
|
||
return <Bot className="h-4 w-4" />
|
||
case "数据输出":
|
||
return <Package className="h-4 w-4" />
|
||
default:
|
||
return <Settings className="h-4 w-4" />
|
||
}
|
||
}
|
||
|
||
export default function LogsPage() {
|
||
const [searchTerm, setSearchTerm] = useState("")
|
||
const [moduleFilter, setModuleFilter] = useState("all")
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* 页面标题 */}
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<h1 className="text-2xl font-bold text-foreground">操作日志</h1>
|
||
<p className="text-muted-foreground">查看系统操作记录和审计日志</p>
|
||
</div>
|
||
<Button variant="outline">
|
||
<Download className="mr-2 h-4 w-4" />
|
||
导出日志
|
||
</Button>
|
||
</div>
|
||
|
||
{/* 统计卡片 */}
|
||
<div className="grid gap-4 md:grid-cols-4">
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">今日操作</p>
|
||
<p className="text-2xl font-bold">256</p>
|
||
</div>
|
||
<ScrollText className="h-8 w-8 text-blue-500" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">活跃用户</p>
|
||
<p className="text-2xl font-bold">12</p>
|
||
</div>
|
||
<User className="h-8 w-8 text-green-500" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">成功率</p>
|
||
<p className="text-2xl font-bold">98.5%</p>
|
||
</div>
|
||
<Badge className="bg-green-100 text-green-700 text-lg">正常</Badge>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">失败操作</p>
|
||
<p className="text-2xl font-bold text-red-600">4</p>
|
||
</div>
|
||
<Badge className="bg-red-100 text-red-700 text-lg">异常</Badge>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
|
||
{/* 日志列表 */}
|
||
<Card>
|
||
<CardHeader>
|
||
<div className="flex items-center justify-between">
|
||
<div>
|
||
<CardTitle>操作记录</CardTitle>
|
||
<CardDescription>系统所有操作的详细记录</CardDescription>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<div className="relative">
|
||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
||
<Input
|
||
placeholder="搜索操作..."
|
||
className="pl-9 w-64"
|
||
value={searchTerm}
|
||
onChange={(e) => setSearchTerm(e.target.value)}
|
||
/>
|
||
</div>
|
||
<Select value={moduleFilter} onValueChange={setModuleFilter}>
|
||
<SelectTrigger className="w-36">
|
||
<SelectValue placeholder="所有模块" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="all">所有模块</SelectItem>
|
||
<SelectItem value="data-ingestion">数据接入</SelectItem>
|
||
<SelectItem value="tag-portrait">标签画像</SelectItem>
|
||
<SelectItem value="ai-agent">AI Agent</SelectItem>
|
||
<SelectItem value="data-output">数据输出</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<Table>
|
||
<TableHeader>
|
||
<TableRow>
|
||
<TableHead>时间</TableHead>
|
||
<TableHead>用户</TableHead>
|
||
<TableHead>操作</TableHead>
|
||
<TableHead>模块</TableHead>
|
||
<TableHead>详情</TableHead>
|
||
<TableHead>IP</TableHead>
|
||
<TableHead>状态</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
{logs.map((log) => (
|
||
<TableRow key={log.id}>
|
||
<TableCell className="text-muted-foreground whitespace-nowrap">
|
||
{log.time}
|
||
</TableCell>
|
||
<TableCell className="font-medium">{log.user}</TableCell>
|
||
<TableCell>{log.action}</TableCell>
|
||
<TableCell>
|
||
<div className="flex items-center gap-1">
|
||
{getModuleIcon(log.module)}
|
||
<span>{log.module}</span>
|
||
</div>
|
||
</TableCell>
|
||
<TableCell className="max-w-[300px] truncate text-muted-foreground">
|
||
{log.detail}
|
||
</TableCell>
|
||
<TableCell className="text-muted-foreground">{log.ip}</TableCell>
|
||
<TableCell>
|
||
{log.status === "success" ? (
|
||
<Badge className="bg-green-100 text-green-700">成功</Badge>
|
||
) : (
|
||
<Badge className="bg-red-100 text-red-700">失败</Badge>
|
||
)}
|
||
</TableCell>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
)
|
||
}
|