Redesign navigation, home overview, user portrait, and valuation pages with improved functionality and responsive design. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
787 lines
34 KiB
TypeScript
787 lines
34 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from "react"
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/ui/card"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||
import { Textarea } from "@/components/ui/textarea"
|
||
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 { Badge } from "@/components/ui/badge"
|
||
import { Separator } from "@/components/ui/separator"
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
} from "@/components/ui/dialog"
|
||
import { Sparkles, BarChart, TrendingUp, Users, Mail, Clock, Download, ChevronRight } from "lucide-react"
|
||
|
||
export default function AIAssistantPage() {
|
||
const [activeTab, setActiveTab] = useState("data-analysis")
|
||
const [selectedUserGroup, setSelectedUserGroup] = useState("")
|
||
const [isUserGroupDialogOpen, setIsUserGroupDialogOpen] = useState(false)
|
||
const [emailAddress, setEmailAddress] = useState("")
|
||
const [scheduleReport, setScheduleReport] = useState(false)
|
||
|
||
// 分析流程步骤
|
||
const [analysisStep, setAnalysisStep] = useState(1)
|
||
const [analysisType, setAnalysisType] = useState("")
|
||
|
||
// 营销策略步骤
|
||
const [strategyStep, setStrategyStep] = useState(1)
|
||
const [strategyType, setStrategyType] = useState("")
|
||
|
||
return (
|
||
<div className="container mx-auto py-6 space-y-8">
|
||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
|
||
<div>
|
||
<h1 className="text-3xl font-bold tracking-tight">AI 智能助手</h1>
|
||
<p className="text-muted-foreground">利用AI技术分析数据并提供营销策略</p>
|
||
</div>
|
||
</div>
|
||
|
||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||
<TabsList className="grid w-full max-w-md grid-cols-2">
|
||
<TabsTrigger value="data-analysis">数据分析</TabsTrigger>
|
||
<TabsTrigger value="marketing-strategy">营销策略</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent value="data-analysis" className="space-y-6">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>AI 数据分析</CardTitle>
|
||
<CardDescription>使用AI分析用户数据并生成洞察报告</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* 第1步:选择用户分群 */}
|
||
<div className={`space-y-4 ${analysisStep !== 1 ? "opacity-60" : ""}`}>
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-medium flex items-center">
|
||
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-white text-sm mr-2">
|
||
1
|
||
</div>
|
||
选择用户分群
|
||
</h3>
|
||
{analysisStep > 1 ? (
|
||
<Button variant="outline" size="sm" onClick={() => setAnalysisStep(1)}>
|
||
修改
|
||
</Button>
|
||
) : (
|
||
<Button variant="outline" onClick={() => setIsUserGroupDialogOpen(true)}>
|
||
<Users className="mr-2 h-4 w-4" />
|
||
选择用户分群
|
||
</Button>
|
||
)}
|
||
</div>
|
||
|
||
{selectedUserGroup && (
|
||
<div className="p-4 border rounded-lg bg-muted/50">
|
||
<div className="flex justify-between items-center">
|
||
<div className="flex items-center gap-2">
|
||
<Users className="h-5 w-5 text-muted-foreground" />
|
||
<span className="font-medium">已选择用户分群:</span>
|
||
<Badge className="bg-blue-100 text-blue-800">{selectedUserGroup}</Badge>
|
||
</div>
|
||
{analysisStep === 1 && (
|
||
<Button
|
||
onClick={() => {
|
||
setAnalysisStep(2)
|
||
}}
|
||
disabled={!selectedUserGroup}
|
||
>
|
||
下一步 <ChevronRight className="ml-1 h-4 w-4" />
|
||
</Button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
{/* 第2步:选择分析类型 */}
|
||
<div
|
||
className={`space-y-4 ${analysisStep !== 2 ? (analysisStep > 2 ? "opacity-60" : "opacity-40") : ""}`}
|
||
>
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-medium flex items-center">
|
||
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-white text-sm mr-2">
|
||
2
|
||
</div>
|
||
选择分析类型
|
||
</h3>
|
||
{analysisStep > 2 && (
|
||
<Button variant="outline" size="sm" onClick={() => setAnalysisStep(2)}>
|
||
修改
|
||
</Button>
|
||
)}
|
||
</div>
|
||
|
||
{analysisStep >= 2 && (
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
<Card
|
||
className={`border-2 cursor-pointer hover:shadow-md transition-all ${analysisType === "behavior" ? "border-primary" : "border-transparent"}`}
|
||
onClick={() => setAnalysisType("behavior")}
|
||
>
|
||
<CardHeader className="pb-2">
|
||
<CardTitle className="text-base">用户行为分析</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="text-sm text-muted-foreground">
|
||
分析用户的行为模式、偏好和习惯
|
||
</CardContent>
|
||
<CardFooter>
|
||
{analysisType === "behavior" && <Badge className="bg-primary/10 text-primary">已选择</Badge>}
|
||
</CardFooter>
|
||
</Card>
|
||
<Card
|
||
className={`border-2 cursor-pointer hover:shadow-md transition-all ${analysisType === "value" ? "border-primary" : "border-transparent"}`}
|
||
onClick={() => setAnalysisType("value")}
|
||
>
|
||
<CardHeader className="pb-2">
|
||
<CardTitle className="text-base">用户估值分析</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="text-sm text-muted-foreground">分析用户的价值分布和潜在价值</CardContent>
|
||
<CardFooter>
|
||
{analysisType === "value" && <Badge className="bg-primary/10 text-primary">已选择</Badge>}
|
||
</CardFooter>
|
||
</Card>
|
||
<Card
|
||
className={`border-2 cursor-pointer hover:shadow-md transition-all ${analysisType === "churn" ? "border-primary" : "border-transparent"}`}
|
||
onClick={() => setAnalysisType("churn")}
|
||
>
|
||
<CardHeader className="pb-2">
|
||
<CardTitle className="text-base">用户流失预警</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="text-sm text-muted-foreground">
|
||
预测可能流失的用户并提供挽留建议
|
||
</CardContent>
|
||
<CardFooter>
|
||
{analysisType === "churn" && <Badge className="bg-primary/10 text-primary">已选择</Badge>}
|
||
</CardFooter>
|
||
</Card>
|
||
</div>
|
||
)}
|
||
|
||
{analysisStep === 2 && analysisType && (
|
||
<div className="flex justify-end">
|
||
<Button onClick={() => setAnalysisStep(3)}>
|
||
下一步 <ChevronRight className="ml-1 h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
{/* 第3步:分析参数设置 */}
|
||
<div
|
||
className={`space-y-4 ${analysisStep !== 3 ? (analysisStep > 3 ? "opacity-60" : "opacity-40") : ""}`}
|
||
>
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-medium flex items-center">
|
||
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-white text-sm mr-2">
|
||
3
|
||
</div>
|
||
分析参数设置
|
||
</h3>
|
||
{analysisStep > 3 && (
|
||
<Button variant="outline" size="sm" onClick={() => setAnalysisStep(3)}>
|
||
修改
|
||
</Button>
|
||
)}
|
||
</div>
|
||
|
||
{analysisStep >= 3 && (
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="time-range">时间范围</Label>
|
||
<Select defaultValue="30days">
|
||
<SelectTrigger id="time-range">
|
||
<SelectValue placeholder="选择时间范围" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="7days">最近7天</SelectItem>
|
||
<SelectItem value="30days">最近30天</SelectItem>
|
||
<SelectItem value="90days">最近90天</SelectItem>
|
||
<SelectItem value="custom">自定义范围</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label htmlFor="analysis-depth">分析深度</Label>
|
||
<Select defaultValue="medium">
|
||
<SelectTrigger id="analysis-depth">
|
||
<SelectValue placeholder="选择分析深度" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="basic">基础分析</SelectItem>
|
||
<SelectItem value="medium">中等深度</SelectItem>
|
||
<SelectItem value="deep">深度分析</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{analysisStep === 3 && (
|
||
<div className="flex justify-end">
|
||
<Button onClick={() => setAnalysisStep(4)}>
|
||
下一步 <ChevronRight className="ml-1 h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
{/* 第4步:报告设置 */}
|
||
<div className={`space-y-4 ${analysisStep !== 4 ? "opacity-40" : ""}`}>
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-medium flex items-center">
|
||
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-white text-sm mr-2">
|
||
4
|
||
</div>
|
||
报告设置
|
||
</h3>
|
||
</div>
|
||
|
||
{analysisStep >= 4 && (
|
||
<div className="space-y-4">
|
||
<div className="flex flex-col space-y-2">
|
||
<Label htmlFor="email">发送分析报告至</Label>
|
||
<Input
|
||
id="email"
|
||
type="email"
|
||
placeholder="输入邮箱地址"
|
||
value={emailAddress}
|
||
onChange={(e) => setEmailAddress(e.target.value)}
|
||
/>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch id="schedule-report" checked={scheduleReport} onCheckedChange={setScheduleReport} />
|
||
<Label htmlFor="schedule-report">定期发送报告</Label>
|
||
</div>
|
||
{scheduleReport && (
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 pl-6">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="schedule-frequency">发送频率</Label>
|
||
<Select defaultValue="weekly">
|
||
<SelectTrigger id="schedule-frequency">
|
||
<SelectValue placeholder="选择发送频率" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="daily">每日</SelectItem>
|
||
<SelectItem value="weekly">每周</SelectItem>
|
||
<SelectItem value="monthly">每月</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label htmlFor="schedule-time">发送时间</Label>
|
||
<Select defaultValue="morning">
|
||
<SelectTrigger id="schedule-time">
|
||
<SelectValue placeholder="选择发送时间" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="morning">上午 9:00</SelectItem>
|
||
<SelectItem value="noon">中午 12:00</SelectItem>
|
||
<SelectItem value="evening">下午 6:00</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</CardContent>
|
||
<CardFooter className="flex justify-between">
|
||
<Button
|
||
variant="outline"
|
||
onClick={() => {
|
||
setAnalysisStep(1)
|
||
setAnalysisType("")
|
||
}}
|
||
>
|
||
重置
|
||
</Button>
|
||
<Button disabled={analysisStep < 4 || !emailAddress}>
|
||
<Sparkles className="mr-2 h-4 w-4" />
|
||
开始分析
|
||
</Button>
|
||
</CardFooter>
|
||
</Card>
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>分析结果预览</CardTitle>
|
||
<CardDescription>AI生成的数据分析结果</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="h-96 flex items-center justify-center">
|
||
{selectedUserGroup && analysisStep === 4 ? (
|
||
<div className="text-center space-y-4">
|
||
<BarChart className="h-16 w-16 mx-auto text-primary" />
|
||
<p className="text-lg font-medium">分析结果将在这里显示</p>
|
||
<p className="text-muted-foreground">点击"开始分析"按钮生成分析报告</p>
|
||
<div className="flex justify-center gap-2 pt-4">
|
||
<Button variant="outline">
|
||
<Download className="mr-2 h-4 w-4" />
|
||
下载报告
|
||
</Button>
|
||
<Button>
|
||
<Mail className="mr-2 h-4 w-4" />
|
||
发送报告
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="text-center text-muted-foreground">
|
||
<Users className="h-16 w-16 mx-auto mb-4" />
|
||
<p className="text-lg">请完成所有分析步骤</p>
|
||
<Button variant="outline" className="mt-4" onClick={() => setIsUserGroupDialogOpen(true)}>
|
||
<Users className="mr-2 h-4 w-4" />
|
||
开始设置
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="marketing-strategy" className="space-y-6">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>AI 营销策略</CardTitle>
|
||
<CardDescription>使用AI生成针对性的营销策略和建议</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* 第1步:选择目标用户分群 */}
|
||
<div className={`space-y-4 ${strategyStep !== 1 ? "opacity-60" : ""}`}>
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-medium flex items-center">
|
||
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-white text-sm mr-2">
|
||
1
|
||
</div>
|
||
选择目标用户分群
|
||
</h3>
|
||
{strategyStep > 1 ? (
|
||
<Button variant="outline" size="sm" onClick={() => setStrategyStep(1)}>
|
||
修改
|
||
</Button>
|
||
) : (
|
||
<Button variant="outline" onClick={() => setIsUserGroupDialogOpen(true)}>
|
||
<Users className="mr-2 h-4 w-4" />
|
||
选择用户分群
|
||
</Button>
|
||
)}
|
||
</div>
|
||
|
||
{selectedUserGroup && (
|
||
<div className="p-4 border rounded-lg bg-muted/50">
|
||
<div className="flex justify-between items-center">
|
||
<div className="flex items-center gap-2">
|
||
<Users className="h-5 w-5 text-muted-foreground" />
|
||
<span className="font-medium">已选择用户分群:</span>
|
||
<Badge className="bg-blue-100 text-blue-800">{selectedUserGroup}</Badge>
|
||
</div>
|
||
{strategyStep === 1 && (
|
||
<Button
|
||
onClick={() => {
|
||
setStrategyStep(2)
|
||
}}
|
||
disabled={!selectedUserGroup}
|
||
>
|
||
下一步 <ChevronRight className="ml-1 h-4 w-4" />
|
||
</Button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
{/* 第2步:选择策略类型 */}
|
||
<div
|
||
className={`space-y-4 ${strategyStep !== 2 ? (strategyStep > 2 ? "opacity-60" : "opacity-40") : ""}`}
|
||
>
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-medium flex items-center">
|
||
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-white text-sm mr-2">
|
||
2
|
||
</div>
|
||
选择策略类型
|
||
</h3>
|
||
{strategyStep > 2 && (
|
||
<Button variant="outline" size="sm" onClick={() => setStrategyStep(2)}>
|
||
修改
|
||
</Button>
|
||
)}
|
||
</div>
|
||
|
||
{strategyStep >= 2 && (
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
<Card
|
||
className={`border-2 cursor-pointer hover:shadow-md transition-all ${strategyType === "sales" ? "border-primary" : "border-transparent"}`}
|
||
onClick={() => setStrategyType("sales")}
|
||
>
|
||
<CardHeader className="pb-2">
|
||
<CardTitle className="text-base">销售预测</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="text-sm text-muted-foreground">
|
||
预测未来销售趋势并提供增长建议
|
||
</CardContent>
|
||
<CardFooter>
|
||
{strategyType === "sales" && <Badge className="bg-primary/10 text-primary">已选择</Badge>}
|
||
</CardFooter>
|
||
</Card>
|
||
<Card
|
||
className={`border-2 cursor-pointer hover:shadow-md transition-all ${strategyType === "reach" ? "border-primary" : "border-transparent"}`}
|
||
onClick={() => setStrategyType("reach")}
|
||
>
|
||
<CardHeader className="pb-2">
|
||
<CardTitle className="text-base">用户触达策略</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="text-sm text-muted-foreground">
|
||
生成针对性的用户触达和转化策略
|
||
</CardContent>
|
||
<CardFooter>
|
||
{strategyType === "reach" && <Badge className="bg-primary/10 text-primary">已选择</Badge>}
|
||
</CardFooter>
|
||
</Card>
|
||
<Card
|
||
className={`border-2 cursor-pointer hover:shadow-md transition-all ${strategyType === "content" ? "border-primary" : "border-transparent"}`}
|
||
onClick={() => setStrategyType("content")}
|
||
>
|
||
<CardHeader className="pb-2">
|
||
<CardTitle className="text-base">内容营销策略</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="text-sm text-muted-foreground">
|
||
生成针对目标用户的内容营销策略
|
||
</CardContent>
|
||
<CardFooter>
|
||
{strategyType === "content" && <Badge className="bg-primary/10 text-primary">已选择</Badge>}
|
||
</CardFooter>
|
||
</Card>
|
||
</div>
|
||
)}
|
||
|
||
{strategyStep === 2 && strategyType && (
|
||
<div className="flex justify-end">
|
||
<Button onClick={() => setStrategyStep(3)}>
|
||
下一步 <ChevronRight className="ml-1 h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
{/* 第3步:策略参数设置 */}
|
||
<div className={`space-y-4 ${strategyStep !== 3 ? "opacity-40" : ""}`}>
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-medium flex items-center">
|
||
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-white text-sm mr-2">
|
||
3
|
||
</div>
|
||
策略参数设置
|
||
</h3>
|
||
</div>
|
||
|
||
{strategyStep >= 3 && (
|
||
<>
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="strategy-goal">营销目标</Label>
|
||
<Select defaultValue="conversion">
|
||
<SelectTrigger id="strategy-goal">
|
||
<SelectValue placeholder="选择营销目标" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="awareness">提升品牌认知</SelectItem>
|
||
<SelectItem value="engagement">增加用户互动</SelectItem>
|
||
<SelectItem value="conversion">提高转化率</SelectItem>
|
||
<SelectItem value="retention">提升用户留存</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label htmlFor="strategy-budget">预算范围</Label>
|
||
<Select defaultValue="medium">
|
||
<SelectTrigger id="strategy-budget">
|
||
<SelectValue placeholder="选择预算范围" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="low">低预算</SelectItem>
|
||
<SelectItem value="medium">中等预算</SelectItem>
|
||
<SelectItem value="high">高预算</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label htmlFor="strategy-notes">补充说明</Label>
|
||
<Textarea
|
||
id="strategy-notes"
|
||
placeholder="请输入任何补充说明或特殊要求..."
|
||
className="min-h-[100px]"
|
||
/>
|
||
</div>
|
||
<div className="space-y-4">
|
||
<div className="flex flex-col space-y-2">
|
||
<Label htmlFor="email-strategy">发送策略报告至</Label>
|
||
<Input
|
||
id="email-strategy"
|
||
type="email"
|
||
placeholder="输入邮箱地址"
|
||
value={emailAddress}
|
||
onChange={(e) => setEmailAddress(e.target.value)}
|
||
/>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch id="schedule-strategy" checked={scheduleReport} onCheckedChange={setScheduleReport} />
|
||
<Label htmlFor="schedule-strategy">定期更新策略</Label>
|
||
</div>
|
||
{scheduleReport && (
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 pl-6">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="update-frequency">更新频率</Label>
|
||
<Select defaultValue="monthly">
|
||
<SelectTrigger id="update-frequency">
|
||
<SelectValue placeholder="选择更新频率" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="weekly">每周</SelectItem>
|
||
<SelectItem value="biweekly">每两周</SelectItem>
|
||
<SelectItem value="monthly">每月</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
</CardContent>
|
||
<CardFooter className="flex justify-between">
|
||
<Button
|
||
variant="outline"
|
||
onClick={() => {
|
||
setStrategyStep(1)
|
||
setStrategyType("")
|
||
}}
|
||
>
|
||
重置
|
||
</Button>
|
||
<Button disabled={strategyStep < 3 || !emailAddress}>
|
||
<Sparkles className="mr-2 h-4 w-4" />
|
||
生成策略
|
||
</Button>
|
||
</CardFooter>
|
||
</Card>
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>策略建议预览</CardTitle>
|
||
<CardDescription>AI生成的营销策略建议</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="h-96 flex items-center justify-center">
|
||
{selectedUserGroup && strategyStep === 3 ? (
|
||
<div className="text-center space-y-4">
|
||
<TrendingUp className="h-16 w-16 mx-auto text-primary" />
|
||
<p className="text-lg font-medium">策略建议将在这里显示</p>
|
||
<p className="text-muted-foreground">点击"生成策略"按钮生成营销策略</p>
|
||
<div className="flex justify-center gap-2 pt-4">
|
||
<Button variant="outline">
|
||
<Download className="mr-2 h-4 w-4" />
|
||
下载策略
|
||
</Button>
|
||
<Button>
|
||
<Mail className="mr-2 h-4 w-4" />
|
||
发送策略
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="text-center text-muted-foreground">
|
||
<Users className="h-16 w-16 mx-auto mb-4" />
|
||
<p className="text-lg">请完成所有策略步骤</p>
|
||
<Button variant="outline" className="mt-4" onClick={() => setIsUserGroupDialogOpen(true)}>
|
||
<Users className="mr-2 h-4 w-4" />
|
||
开始设置
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
</Tabs>
|
||
|
||
<UserGroupSelectionDialog
|
||
isOpen={isUserGroupDialogOpen}
|
||
setIsOpen={setIsUserGroupDialogOpen}
|
||
onSelect={setSelectedUserGroup}
|
||
/>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
// 用户分群选择对话框
|
||
function UserGroupSelectionDialog({
|
||
isOpen,
|
||
setIsOpen,
|
||
onSelect,
|
||
}: {
|
||
isOpen: boolean
|
||
setIsOpen: (open: boolean) => void
|
||
onSelect: (group: string) => void
|
||
}) {
|
||
// 模拟用户分群数据
|
||
const userGroups = [
|
||
{
|
||
id: "1",
|
||
name: "高价值用户",
|
||
description: "消费能力强,购买频率高的用户",
|
||
count: 12456,
|
||
category: "用户资产",
|
||
lastUpdated: "2023-07-20",
|
||
},
|
||
{
|
||
id: "2",
|
||
name: "活跃用户",
|
||
description: "近30天内有活动的用户",
|
||
count: 45678,
|
||
category: "用户资产",
|
||
lastUpdated: "2023-07-20",
|
||
},
|
||
{
|
||
id: "3",
|
||
name: "地摊商户",
|
||
description: "从事地摊相关业务的用户",
|
||
count: 8765,
|
||
category: "地摊相关",
|
||
lastUpdated: "2023-07-19",
|
||
},
|
||
{
|
||
id: "4",
|
||
name: "樊登读书会员",
|
||
description: "樊登读书平台的会员用户",
|
||
count: 15678,
|
||
category: "樊登读书",
|
||
lastUpdated: "2023-07-18",
|
||
},
|
||
{
|
||
id: "5",
|
||
name: "魔兽玩家",
|
||
description: "魔兽世界游戏的活跃玩家",
|
||
count: 23456,
|
||
category: "魔兽世界",
|
||
lastUpdated: "2023-07-17",
|
||
},
|
||
{
|
||
id: "6",
|
||
name: "流失风险用户",
|
||
description: "有流失风险的高价值用户",
|
||
count: 5678,
|
||
category: "用户资产",
|
||
lastUpdated: "2023-07-16",
|
||
},
|
||
]
|
||
|
||
const [searchQuery, setSearchQuery] = useState("")
|
||
const [selectedCategory, setSelectedCategory] = useState("all")
|
||
|
||
// 过滤用户分群
|
||
const filteredGroups = userGroups.filter((group) => {
|
||
const matchesSearch =
|
||
group.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||
group.description.toLowerCase().includes(searchQuery.toLowerCase())
|
||
|
||
const matchesCategory = selectedCategory === "all" || group.category === selectedCategory
|
||
|
||
return matchesSearch && matchesCategory
|
||
})
|
||
|
||
// 获取所有分类
|
||
const categories = ["all", ...new Set(userGroups.map((group) => group.category))]
|
||
|
||
const handleSelect = (group: string) => {
|
||
onSelect(group)
|
||
setIsOpen(false)
|
||
}
|
||
|
||
return (
|
||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||
<DialogContent className="sm:max-w-[600px]">
|
||
<DialogHeader>
|
||
<DialogTitle>选择用户分群</DialogTitle>
|
||
<DialogDescription>从用户画像中选择要分析的用户分群</DialogDescription>
|
||
</DialogHeader>
|
||
<div className="py-4 space-y-4">
|
||
<div className="flex flex-col md:flex-row gap-4">
|
||
<div className="relative flex-1">
|
||
<Input
|
||
placeholder="搜索用户分群..."
|
||
value={searchQuery}
|
||
onChange={(e) => setSearchQuery(e.target.value)}
|
||
/>
|
||
</div>
|
||
<Select value={selectedCategory} onValueChange={setSelectedCategory}>
|
||
<SelectTrigger className="w-full md:w-[180px]">
|
||
<SelectValue placeholder="选择场景分类" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
{categories.map((category) => (
|
||
<SelectItem key={category} value={category}>
|
||
{category === "all" ? "所有场景" : category}
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
<div className="max-h-[300px] overflow-y-auto space-y-2">
|
||
{filteredGroups.map((group) => (
|
||
<div
|
||
key={group.id}
|
||
className="p-3 border rounded-lg hover:bg-muted/50 cursor-pointer"
|
||
onClick={() => handleSelect(group.name)}
|
||
>
|
||
<div className="flex justify-between items-start">
|
||
<div>
|
||
<div className="font-medium">{group.name}</div>
|
||
<div className="text-sm text-muted-foreground">{group.description}</div>
|
||
</div>
|
||
<Badge className="bg-blue-100 text-blue-800">{group.category}</Badge>
|
||
</div>
|
||
<div className="flex justify-between items-center mt-2 text-sm text-muted-foreground">
|
||
<div className="flex items-center">
|
||
<Users className="h-3 w-3 mr-1" />
|
||
{group.count.toLocaleString()} 用户
|
||
</div>
|
||
<div className="flex items-center">
|
||
<Clock className="h-3 w-3 mr-1" />
|
||
更新于 {group.lastUpdated}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => setIsOpen(false)}>
|
||
取消
|
||
</Button>
|
||
<Button onClick={() => setIsOpen(false)}>创建新分群</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
)
|
||
}
|