Align Sidebar & BottomNav menus, remove "Search", add user profile mock data, implement /api/users, add FilterDrawer, complete Section, ProfileHeader, MetricsRFM components Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
190 lines
8.2 KiB
TypeScript
190 lines
8.2 KiB
TypeScript
"use client"
|
||
|
||
import { useCallback, useMemo, useState } from "react"
|
||
import { BarChart3, Database, FileText } from 'lucide-react'
|
||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
|
||
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
|
||
import { Button } from "@/components/ui/button"
|
||
import TaskList from "@/components/ai-assistant/task-list"
|
||
import CreateTaskDialog from "@/components/ai-assistant/create-task-dialog"
|
||
import ReportCards from "@/components/ai-assistant/report-cards"
|
||
import { sanitizeText } from "@/lib/text-sanitize"
|
||
import type { AnalysisTask, DatabaseInfo, ReportItem, ReportTemplate } from "@/types/ai-assistant"
|
||
|
||
const initialTasks: AnalysisTask[] = [
|
||
{
|
||
id: "task_001",
|
||
name: "用户行为分析报告",
|
||
database: "微信用户数据库",
|
||
status: "completed",
|
||
progress: 100,
|
||
createdAt: "2025-01-15T09:00:00Z",
|
||
completedAt: "2025-01-15T09:30:00Z",
|
||
reportUrl: "/reports/user-behavior-analysis.pdf",
|
||
description: "基于近30天行为的聚合与序列分析",
|
||
},
|
||
{
|
||
id: "task_002",
|
||
name: "流量关键词趋势分析",
|
||
database: "流量关键词库",
|
||
status: "running",
|
||
progress: 65,
|
||
createdAt: "2025-01-15T10:00:00Z",
|
||
description: "关注核心流量词与曝光、点击、转化等指标",
|
||
},
|
||
{
|
||
id: "task_003",
|
||
name: "用户价值分层报告",
|
||
database: "微信用户数据库",
|
||
status: "pending",
|
||
progress: 0,
|
||
createdAt: "2025-01-15T10:30:00Z",
|
||
description: "RFM 分层、价值区间分布与运营建议",
|
||
},
|
||
]
|
||
|
||
const databases: DatabaseInfo[] = [
|
||
{ id: "db_001", name: "微信用户数据库", type: "MySQL", tables: 25, records: 4000000000, lastUpdated: "2025-01-15T11:00:00Z" },
|
||
{ id: "db_002", name: "流量关键词库", type: "PostgreSQL", tables: 8, records: 150000, lastUpdated: "2025-01-15T10:45:00Z" },
|
||
{ id: "db_003", name: "用户行为日志", type: "MongoDB", tables: 12, records: 1500000000, lastUpdated: "2025-01-15T11:15:00Z" },
|
||
]
|
||
|
||
const templates: ReportTemplate[] = [
|
||
{ id: "template_001", name: "用户画像分析报告", description: "深度分析用户特征、行为模式和价值分层", category: "用户分析", fields: ["用户基本信息", "RFM分析", "行为轨迹", "价值评估", "推荐策略"] },
|
||
{ id: "template_002", name: "流量趋势分析报告", description: "分析关键词搜索趋势和流量变化", category: "流量分析", fields: ["关键词热度", "搜索趋势", "竞争分析", "机会识别", "优化建议"] },
|
||
{ id: "template_003", name: "业务运营报告", description: "综合业务数据分析和运营建议", category: "运营分析", fields: ["核心指标", "增长分析", "用户留存", "转化漏斗", "运营建议"] },
|
||
{ id: "template_004", name: "数据质量报告", description: "评估数据完整性、准确性和一致性", category: "数据质量", fields: ["数据完整性", "准确性检查", "一致性验证", "异常检测", "改进建议"] },
|
||
]
|
||
|
||
const reportItems: ReportItem[] = [
|
||
{ id: "rpt-1", title: "用户行为分析报告", source: "数据源:微信用户数据库", description: '本报告基于近30天互动行为,输出用户行为模式与高频路径。\\n"]]}', updatedAt: new Date().toISOString() },
|
||
{ id: "rpt-2", title: "流量关键词趋势分析", source: "数据源:流量关键词库", description: '追踪 000000 类流量词及其曝光、点击、转化趋势,适配日/周/月视角。\\n" ]]}', updatedAt: new Date().toISOString() },
|
||
{ id: "rpt-3", title: "用户价值分层报告", source: "数据源:微信用户数据库", description: '结合 RFM 得分与标签,给出 S/A/B/C/D 分层与经营建议。\\n" ]] }', updatedAt: new Date().toISOString() },
|
||
]
|
||
|
||
export default function AIAssistantPage() {
|
||
const [tasks, setTasks] = useState<AnalysisTask[]>(initialTasks)
|
||
|
||
// 进度推进(仅演示用)
|
||
const tick = useCallback(() => {
|
||
setTasks((prev) =>
|
||
prev.map((t) => {
|
||
if (t.status === "running" && t.progress < 100) {
|
||
const p = Math.min(100, t.progress + Math.random() * 12)
|
||
if (p >= 100) {
|
||
return {
|
||
...t,
|
||
progress: 100,
|
||
status: "completed",
|
||
completedAt: new Date().toISOString(),
|
||
reportUrl: `/reports/${t.id}.pdf`,
|
||
}
|
||
}
|
||
return { ...t, progress: p }
|
||
}
|
||
return t
|
||
}),
|
||
)
|
||
}, [])
|
||
|
||
const onCreate = (task: AnalysisTask) => {
|
||
setTasks((prev) => [task, ...prev])
|
||
// 模拟启动
|
||
setTimeout(() => {
|
||
setTasks((prev) => prev.map((t) => (t.id === task.id ? { ...t, status: "running" } : t)))
|
||
}, 800)
|
||
}
|
||
|
||
const sanitizedItems = useMemo(
|
||
() => reportItems.map((i) => ({ ...i, description: sanitizeText(i.description) })),
|
||
[],
|
||
)
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-indigo-50">
|
||
<div className="container mx-auto px-4 py-8">
|
||
<div className="mb-6">
|
||
<h1 className="text-3xl font-bold">AI智能助手</h1>
|
||
<p className="text-gray-600">数据库分析与智能报告生成</p>
|
||
</div>
|
||
|
||
<Tabs defaultValue="analysis" className="space-y-6">
|
||
<TabsList className="grid w-full grid-cols-3">
|
||
<TabsTrigger value="analysis" className="flex items-center gap-2">
|
||
<BarChart3 className="w-4 h-4" />
|
||
数据分析
|
||
</TabsTrigger>
|
||
<TabsTrigger value="databases" className="flex items-center gap-2">
|
||
<Database className="w-4 h-4" />
|
||
数据库
|
||
</TabsTrigger>
|
||
<TabsTrigger value="templates" className="flex items-center gap-2">
|
||
<FileText className="w-4 h-4" />
|
||
报告模板
|
||
</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent value="analysis" className="space-y-6">
|
||
<div className="flex items-center justify-between">
|
||
<h2 className="text-xl font-semibold">数据分析任务</h2>
|
||
<CreateTaskDialog databases={databases} templates={templates} onCreate={onCreate} />
|
||
</div>
|
||
|
||
<TaskList tasks={tasks} onTick={tick} />
|
||
|
||
<ReportCards items={sanitizedItems} />
|
||
</TabsContent>
|
||
|
||
<TabsContent value="databases">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center gap-2">
|
||
<Database className="w-4 h-4" />
|
||
数据库
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||
{databases.map((db) => (
|
||
<Card key={db.id} className="border">
|
||
<CardContent className="p-4 space-y-1">
|
||
<div className="font-medium">{db.name}</div>
|
||
<div className="text-sm text-gray-600">
|
||
{db.type} · {db.tables} 表
|
||
</div>
|
||
<div className="text-xs text-gray-500">
|
||
最近更新 {new Date(db.lastUpdated).toLocaleString("zh-CN")}
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
))}
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="templates">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center gap-2">
|
||
<FileText className="w-4 h-4" />
|
||
报告模板
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||
{templates.map((t) => (
|
||
<Card key={t.id} className="border">
|
||
<CardContent className="p-4 space-y-2">
|
||
<div className="font-medium">{t.name}</div>
|
||
<div className="text-sm text-gray-600">{t.category}</div>
|
||
<div className="text-xs text-gray-500">字段: {t.fields.join(" / ")}</div>
|
||
</CardContent>
|
||
</Card>
|
||
))}
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
</Tabs>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|