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>
244 lines
9.1 KiB
TypeScript
244 lines
9.1 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 { Label } from "@/components/ui/label"
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
|
import { Switch } from "@/components/ui/switch"
|
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
|
import {
|
|
Webhook, Plus, Settings, Trash2, Play, Pause,
|
|
CheckCircle2, XCircle, Clock, RefreshCw, Eye
|
|
} from "lucide-react"
|
|
|
|
const subscriptions = [
|
|
{
|
|
id: "1",
|
|
name: "用户标签变更通知",
|
|
type: "webhook",
|
|
endpoint: "https://api.example.com/webhook/tags",
|
|
event: "tag_changed",
|
|
status: "active",
|
|
lastTriggered: "2024-01-15 14:20:00",
|
|
successRate: 99.5,
|
|
},
|
|
{
|
|
id: "2",
|
|
name: "高价值用户预警",
|
|
type: "webhook",
|
|
endpoint: "https://api.example.com/webhook/alerts",
|
|
event: "high_value_alert",
|
|
status: "active",
|
|
lastTriggered: "2024-01-15 10:15:00",
|
|
successRate: 98.2,
|
|
},
|
|
{
|
|
id: "3",
|
|
name: "数据同步完成通知",
|
|
type: "email",
|
|
endpoint: "admin@example.com",
|
|
event: "sync_completed",
|
|
status: "paused",
|
|
lastTriggered: "2024-01-14 23:00:00",
|
|
successRate: 100,
|
|
},
|
|
]
|
|
|
|
export default function SubscriptionPage() {
|
|
const [showCreateDialog, setShowCreateDialog] = useState(false)
|
|
|
|
const getStatusBadge = (status: string) => {
|
|
switch (status) {
|
|
case "active":
|
|
return <Badge className="bg-green-100 text-green-700">运行中</Badge>
|
|
case "paused":
|
|
return <Badge className="bg-yellow-100 text-yellow-700">已暂停</Badge>
|
|
case "error":
|
|
return <Badge className="bg-red-100 text-red-700">异常</Badge>
|
|
default:
|
|
return <Badge variant="secondary">未知</Badge>
|
|
}
|
|
}
|
|
|
|
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 onClick={() => setShowCreateDialog(true)}>
|
|
<Plus 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">8</p>
|
|
</div>
|
|
<Webhook 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">1,256</p>
|
|
</div>
|
|
<RefreshCw 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">99.2%</p>
|
|
</div>
|
|
<CheckCircle2 className="h-8 w-8 text-purple-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">6</p>
|
|
</div>
|
|
<Play className="h-8 w-8 text-cyan-500" />
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* 订阅列表 */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>订阅列表</CardTitle>
|
|
<CardDescription>管理所有数据订阅配置</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>订阅名称</TableHead>
|
|
<TableHead>类型</TableHead>
|
|
<TableHead>目标地址</TableHead>
|
|
<TableHead>触发事件</TableHead>
|
|
<TableHead>状态</TableHead>
|
|
<TableHead>成功率</TableHead>
|
|
<TableHead className="text-right">操作</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{subscriptions.map((sub) => (
|
|
<TableRow key={sub.id}>
|
|
<TableCell className="font-medium">{sub.name}</TableCell>
|
|
<TableCell>
|
|
<Badge variant="outline">{sub.type === "webhook" ? "Webhook" : "邮件"}</Badge>
|
|
</TableCell>
|
|
<TableCell>
|
|
<code className="text-xs bg-muted px-2 py-1 rounded truncate max-w-[200px] block">
|
|
{sub.endpoint}
|
|
</code>
|
|
</TableCell>
|
|
<TableCell>{sub.event}</TableCell>
|
|
<TableCell>{getStatusBadge(sub.status)}</TableCell>
|
|
<TableCell>{sub.successRate}%</TableCell>
|
|
<TableCell className="text-right">
|
|
<div className="flex items-center justify-end gap-1">
|
|
<Button variant="ghost" size="sm">
|
|
{sub.status === "active" ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />}
|
|
</Button>
|
|
<Button variant="ghost" size="sm">
|
|
<Settings className="h-4 w-4" />
|
|
</Button>
|
|
<Button variant="ghost" size="sm" className="text-red-600">
|
|
<Trash2 className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* 创建订阅弹窗 */}
|
|
<Dialog open={showCreateDialog} onOpenChange={setShowCreateDialog}>
|
|
<DialogContent className="max-w-lg">
|
|
<DialogHeader>
|
|
<DialogTitle>创建数据订阅</DialogTitle>
|
|
<DialogDescription>配置数据变更的实时推送</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label>订阅名称</Label>
|
|
<Input placeholder="输入订阅名称" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>推送类型</Label>
|
|
<Select>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="选择推送类型" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="webhook">Webhook</SelectItem>
|
|
<SelectItem value="email">邮件通知</SelectItem>
|
|
<SelectItem value="sms">短信通知</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>目标地址</Label>
|
|
<Input placeholder="输入Webhook URL或邮箱地址" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>触发事件</Label>
|
|
<Select>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="选择触发事件" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="tag_changed">标签变更</SelectItem>
|
|
<SelectItem value="portrait_updated">画像更新</SelectItem>
|
|
<SelectItem value="high_value_alert">高价值用户预警</SelectItem>
|
|
<SelectItem value="churn_alert">流失预警</SelectItem>
|
|
<SelectItem value="sync_completed">数据同步完成</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="flex items-center justify-between p-3 bg-muted rounded-lg">
|
|
<div>
|
|
<Label>启用订阅</Label>
|
|
<p className="text-sm text-muted-foreground">创建后立即开始推送</p>
|
|
</div>
|
|
<Switch defaultChecked />
|
|
</div>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button variant="outline" onClick={() => setShowCreateDialog(false)}>取消</Button>
|
|
<Button>创建订阅</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
)
|
|
}
|