Files
users/app/ai-assistant/page.tsx
v0 4eed69520c feat: refactor data asset center for enhanced search and analytics
Refactor homepage for focused search and data display; streamline data platform; enhance user and tag management; focus AI assistant on data analysis and report generation.

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
2025-07-25 06:42:34 +00:00

517 lines
22 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState } from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Switch } from "@/components/ui/switch"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import {
BarChart3,
Send,
FileText,
Mail,
MessageSquare,
Download,
Database,
Target,
Zap,
Eye,
Share,
} from "lucide-react"
import { TooltipHelp, TooltipProvider } from "@/components/ui/tooltip-help"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogFooter,
} from "@/components/ui/dialog"
export default function AIAssistantPage() {
const [selectedDatabase, setSelectedDatabase] = useState("all")
const [reportTitle, setReportTitle] = useState("")
const [isGeneratingReport, setIsGeneratingReport] = useState(false)
const [isSendingReport, setIsSendingReport] = useState(false)
const [selectedReport, setSelectedReport] = useState<string | null>(null)
// 数据库列表
const databases = [
{ id: "user_behavior", name: "用户行为数据库", records: "1.2M", description: "用户行为轨迹和交互数据" },
{ id: "user_profile", name: "用户画像数据库", records: "856K", description: "用户基本信息和标签数据" },
{ id: "transaction", name: "交易数据库", records: "324K", description: "用户交易和消费记录" },
{ id: "content", name: "内容数据库", records: "567K", description: "内容互动和偏好数据" },
{ id: "traffic", name: "流量数据库", records: "2.3M", description: "流量关键词和来源数据" },
]
// 生成的报告列表
const [reports, setReports] = useState([
{
id: "1",
title: "用户行为分析报告",
database: "用户行为数据库",
generatedAt: "2024-01-15 14:30",
status: "completed",
insights: [
"用户在晚间时段活跃度最高占总活跃时间的35%",
"移动端用户占比87%其中iOS用户转化率更高",
"用户平均会话时长为8.5分钟,高于行业平均水平",
],
recommendations: [
"建议在晚间时段增加营销活动投入",
"优化iOS端用户体验提升转化率",
"延长用户会话时长,增加内容推荐精准度",
],
},
{
id: "2",
title: "用户价值分析报告",
database: "用户画像数据库",
generatedAt: "2024-01-14 16:45",
status: "completed",
insights: [
"高价值用户占比7.2%贡献了45%的总收入",
"用户生命周期价值平均为¥2,580",
"新用户转化为高价值用户的概率为12.5%",
],
recommendations: [
"针对高价值用户制定专属服务策略",
"优化新用户引导流程,提升转化率",
"建立用户价值预警机制,及时挽留流失用户",
],
},
{
id: "3",
title: "流量关键词分析报告",
database: "流量数据库",
generatedAt: "2024-01-13 10:20",
status: "completed",
insights: [
"热门关键词TOP10贡献了60%的流量",
"长尾关键词转化率普遍高于热门关键词",
"品牌相关关键词的用户质量最高",
],
recommendations: ["加大长尾关键词的投入和优化", "提升品牌关键词的覆盖范围", "建立关键词效果监控体系"],
},
])
// 生成报告
const handleGenerateReport = () => {
if (!reportTitle.trim()) return
setIsGeneratingReport(true)
// 模拟报告生成过程
setTimeout(() => {
const newReport = {
id: Date.now().toString(),
title: reportTitle,
database: databases.find((db) => db.id === selectedDatabase)?.name || "全部数据库",
generatedAt: new Date().toLocaleString(),
status: "completed",
insights: ["AI分析发现的关键洞察1", "AI分析发现的关键洞察2", "AI分析发现的关键洞察3"],
recommendations: ["基于数据分析的建议1", "基于数据分析的建议2", "基于数据分析的建议3"],
}
setReports((prev) => [newReport, ...prev])
setReportTitle("")
setIsGeneratingReport(false)
}, 3000)
}
// 发送报告
const handleSendReport = (reportId: string, method: string, target: string) => {
setIsSendingReport(true)
// 模拟发送过程
setTimeout(() => {
setIsSendingReport(false)
setSelectedReport(null)
// 这里可以添加成功提示
}, 2000)
}
return (
<TooltipProvider>
<div className="container mx-auto p-6 space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold">AI智能助手</h1>
<p className="text-muted-foreground mt-2"></p>
</div>
</div>
{/* 核心指标概览 */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<TooltipHelp content="可分析的数据库总数,包含用户、交易、行为等各类数据" />
</CardTitle>
<Database className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{databases.length}</div>
<p className="text-xs text-muted-foreground"></p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<TooltipHelp content="AI自动生成的数据分析报告总数" />
</CardTitle>
<FileText className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{reports.length}</div>
<p className="text-xs text-muted-foreground">
<span className="text-green-600">+2</span>
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<TooltipHelp content="AI数据分析的准确率基于历史验证结果计算" />
</CardTitle>
<Target className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">94.2%</div>
<p className="text-xs text-muted-foreground">
<span className="text-green-600">+1.8%</span>
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<TooltipHelp content="AI分析处理的平均速度包括数据读取和分析时间" />
</CardTitle>
<Zap className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">2.3s</div>
<p className="text-xs text-muted-foreground"></p>
</CardContent>
</Card>
</div>
<Tabs defaultValue="generate" className="space-y-6">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="generate"></TabsTrigger>
<TabsTrigger value="reports"></TabsTrigger>
</TabsList>
<TabsContent value="generate" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<BarChart3 className="h-5 w-5" />
<TooltipHelp content="选择数据库并配置分析参数AI将自动生成详细的数据分析报告" />
</CardTitle>
<CardDescription>AI智能分析数据库</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-4">
<div>
<Label htmlFor="report-title"></Label>
<Input
id="report-title"
placeholder="请输入报告标题..."
value={reportTitle}
onChange={(e) => setReportTitle(e.target.value)}
className="mt-1"
/>
</div>
<div>
<Label htmlFor="database-select"></Label>
<Select value={selectedDatabase} onValueChange={setSelectedDatabase}>
<SelectTrigger id="database-select" className="mt-1">
<SelectValue placeholder="选择要分析的数据库" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all"></SelectItem>
{databases.map((db) => (
<SelectItem key={db.id} value={db.id}>
{db.name} ({db.records})
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="analysis-type"></Label>
<Select defaultValue="comprehensive">
<SelectTrigger id="analysis-type" className="mt-1">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="comprehensive"></SelectItem>
<SelectItem value="behavior"></SelectItem>
<SelectItem value="value"></SelectItem>
<SelectItem value="trend"></SelectItem>
<SelectItem value="conversion"></SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="time-range"></Label>
<Select defaultValue="30days">
<SelectTrigger id="time-range" className="mt-1">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="7days">7</SelectItem>
<SelectItem value="30days">30</SelectItem>
<SelectItem value="90days">90</SelectItem>
<SelectItem value="1year">1</SelectItem>
<SelectItem value="custom"></SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="space-y-4">
<div>
<Label htmlFor="analysis-depth"></Label>
<Select defaultValue="standard">
<SelectTrigger id="analysis-depth" className="mt-1">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="basic"></SelectItem>
<SelectItem value="standard"></SelectItem>
<SelectItem value="deep"></SelectItem>
<SelectItem value="expert"></SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="output-format"></Label>
<Select defaultValue="detailed">
<SelectTrigger id="output-format" className="mt-1">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="summary"></SelectItem>
<SelectItem value="detailed"></SelectItem>
<SelectItem value="executive"></SelectItem>
<SelectItem value="technical"></SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label></Label>
<div className="space-y-2">
<div className="flex items-center space-x-2">
<Switch id="include-insights" defaultChecked />
<Label htmlFor="include-insights"></Label>
</div>
<div className="flex items-center space-x-2">
<Switch id="include-recommendations" defaultChecked />
<Label htmlFor="include-recommendations"></Label>
</div>
<div className="flex items-center space-x-2">
<Switch id="include-charts" defaultChecked />
<Label htmlFor="include-charts"></Label>
</div>
<div className="flex items-center space-x-2">
<Switch id="include-predictions" />
<Label htmlFor="include-predictions"></Label>
</div>
</div>
</div>
</div>
</div>
<div className="flex justify-center">
<Button
onClick={handleGenerateReport}
disabled={isGeneratingReport || !reportTitle.trim()}
className="px-8"
>
{isGeneratingReport ? (
<>
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
...
</>
) : (
<>
<BarChart3 className="h-4 w-4 mr-2" />
AI分析报告
</>
)}
</Button>
</div>
</div>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="reports" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<FileText className="h-5 w-5" />
<TooltipHelp content="管理所有生成的AI分析报告支持查看、下载和分享" />
</CardTitle>
<CardDescription>AI生成的数据分析报告</CardDescription>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{reports.map((report) => (
<TableRow key={report.id}>
<TableCell className="font-medium">{report.title}</TableCell>
<TableCell>{report.database}</TableCell>
<TableCell>{report.generatedAt}</TableCell>
<TableCell>
<Badge className="bg-green-100 text-green-800"></Badge>
</TableCell>
<TableCell>
<div className="flex space-x-2">
<Button variant="ghost" size="sm">
<Eye className="h-4 w-4 mr-1" />
</Button>
<Button variant="ghost" size="sm">
<Download className="h-4 w-4 mr-1" />
</Button>
<Button variant="ghost" size="sm" onClick={() => setSelectedReport(report.id)}>
<Share className="h-4 w-4 mr-1" />
</Button>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
</TabsContent>
</Tabs>
{/* 发送报告对话框 */}
<Dialog open={!!selectedReport} onOpenChange={(open) => !open && setSelectedReport(null)}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogDescription></DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="space-y-4">
<div>
<Label></Label>
<div className="grid grid-cols-2 gap-4 mt-2">
<Card className="cursor-pointer hover:bg-gray-50 p-4">
<div className="flex items-center space-x-3">
<Mail className="h-6 w-6 text-blue-500" />
<div>
<div className="font-medium"></div>
<div className="text-sm text-muted-foreground"></div>
</div>
</div>
</Card>
<Card className="cursor-pointer hover:bg-gray-50 p-4">
<div className="flex items-center space-x-3">
<MessageSquare className="h-6 w-6 text-green-500" />
<div>
<div className="font-medium"></div>
<div className="text-sm text-muted-foreground"></div>
</div>
</div>
</Card>
</div>
</div>
<div>
<Label htmlFor="send-target"></Label>
<Input id="send-target" placeholder="请输入邮箱地址或微信号" className="mt-1" />
</div>
<div>
<Label htmlFor="send-message"></Label>
<Textarea id="send-message" placeholder="可选:添加附加消息" className="mt-1" rows={3} />
</div>
<div className="space-y-2">
<Label></Label>
<div className="space-y-2">
<div className="flex items-center space-x-2">
<Switch id="include-pdf" defaultChecked />
<Label htmlFor="include-pdf">PDF版本</Label>
</div>
<div className="flex items-center space-x-2">
<Switch id="include-data" />
<Label htmlFor="include-data"></Label>
</div>
<div className="flex items-center space-x-2">
<Switch id="schedule-send" />
<Label htmlFor="schedule-send"></Label>
</div>
</div>
</div>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setSelectedReport(null)}>
</Button>
<Button
onClick={() => handleSendReport(selectedReport!, "email", "target@example.com")}
disabled={isSendingReport}
>
{isSendingReport ? (
<>
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
...
</>
) : (
<>
<Send className="mr-2 h-4 w-4" />
</>
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</TooltipProvider>
)
}