+
+
+
+
-
-
-
{selectedReview.ruleName}
+
+
+
-
-
-
{(selectedReview.confidence * 100).toFixed(0)}%
+
+
+
-
-
-
{selectedReview.originalValue}
-
-
-
-
{selectedReview.aiSuggestedValue}
-
-
-
-
{selectedReview.reason}
+
+
+
+ {rules.map(rule => (
+
+
+
+ {rule.name}
+
+ {getRuleTypeBadge(rule.ruleType)}
+
+ ))}
+
- )}
-
-
-
-
-
-
+
+
+
+
+
+
+
)
}
diff --git a/app/ai-agent/page.tsx b/app/ai-agent/page.tsx
new file mode 100644
index 0000000..c53ad6e
--- /dev/null
+++ b/app/ai-agent/page.tsx
@@ -0,0 +1,279 @@
+"use client"
+
+import { useState, useEffect } from "react"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Button } from "@/components/ui/button"
+import { Badge } from "@/components/ui/badge"
+import Link from "next/link"
+import {
+ Bot,
+ MessageSquare,
+ Webhook,
+ Sparkles,
+ Zap,
+ FileText,
+ ArrowRight,
+ CheckCircle2,
+ Activity,
+ Users,
+ Send,
+ Settings,
+ ExternalLink,
+ Copy,
+} from "lucide-react"
+
+interface ChannelStats {
+ name: string
+ icon: string
+ status: 'connected' | 'disconnected'
+ todayMessages: number
+}
+
+export default function AIAgentPage() {
+ const [aiStatus, setAiStatus] = useState<'online' | 'offline'>('online')
+ const [stats, setStats] = useState({
+ totalQueries: 156000,
+ todayQueries: 2340,
+ avgLatency: 380,
+ accuracy: 97.5,
+ })
+
+ const channels: ChannelStats[] = [
+ { name: 'é£ä¹Š', icon: 'ðª¶', status: 'connected', todayMessages: 156 },
+ { name: 'äŒäžåŸ®ä¿¡', icon: 'ðŒ', status: 'connected', todayMessages: 89 },
+ { name: '埮信(å客å®)', icon: 'ð¬', status: 'connected', todayMessages: 320 },
+ { name: 'APIæ¥å£', icon: 'ð', status: 'connected', todayMessages: 2340 },
+ ]
+
+ const API_BASE_URL = 'https://your-domain.com/api/shensheshou'
+
+ const modules = [
+ {
+ title: 'æºèœå¯¹è¯',
+ description: 'äžAI婿坹è¯ïŒæ¥è¯¢çšæ·ä¿¡æ¯åæ§è¡æ°æ®åæ',
+ icon: MessageSquare,
+ href: '/ai-agent/chat',
+ color: 'from-blue-500 to-cyan-500',
+ },
+ {
+ title: 'æž éé
眮',
+ description: 'é
眮é£ä¹ŠãäŒåŸ®ãåŸ®ä¿¡çæž 鿥å
¥',
+ icon: Webhook,
+ href: '/ai-agent/channels',
+ color: 'from-green-500 to-emerald-500',
+ },
+ {
+ title: 'AIææ ',
+ description: '䜿çšAIèªåšäžºçšæ·ææ çŸ',
+ icon: Sparkles,
+ href: '/ai-agent/smart-tag',
+ color: 'from-purple-500 to-pink-500',
+ },
+ {
+ title: 'AIæž
æŽ',
+ description: 'æºèœæ°æ®æž
æŽåæ ŒåŒå',
+ icon: Zap,
+ href: '/ai-agent/data-cleaning',
+ color: 'from-orange-500 to-red-500',
+ },
+ {
+ title: 'æºèœæ¥å',
+ description: 'èªåšçææ°æ®åææ¥å',
+ icon: FileText,
+ href: '/ai-agent/report',
+ color: 'from-indigo-500 to-purple-500',
+ },
+ ]
+
+ const copyToClipboard = (text: string) => {
+ navigator.clipboard.writeText(text)
+ }
+
+ return (
+
+
+ {/* é¡¶éšæ é¢ */}
+
+
+
AI Agent
+
æºèœå©æïŒå¯¹æ¥é£ä¹Š/äŒåŸ®/埮信ç倿ž é
+
+
+
+
+ {aiStatus === 'online' ? 'AIåšçº¿' : 'AI犻线'}
+
+
{stats.avgLatency}ms
+
+
+
+ {/* ç»è®¡å¡ç */}
+
+
+
+
+
+
仿¥æ¥è¯¢
+
{stats.todayQueries.toLocaleString()}
+
+
+
+
+
+
+
+
+
+
环计æ¥è¯¢
+
{(stats.totalQueries / 1000).toFixed(0)}K
+
+
+
+
+
+
+
+
+
+
æ¥å
¥æž é
+
{channels.filter(c => c.status === 'connected').length}
+
+
+
+
+
+
+
+
+
+
åç¡®ç
+
{stats.accuracy}%
+
+
+
+
+
+
+
+ {/* æž éç¶æ */}
+
+
+
+
+
+ æ¥å
¥æž éç¶æ
+
+
+
+
+
+
+
+
+ {channels.map((channel, i) => (
+
+
+ {channel.icon}
+
+ {channel.status === 'connected' ? 'å·²è¿æ¥' : 'æªè¿æ¥'}
+
+
+
{channel.name}
+
仿¥ {channel.todayMessages} æ¡æ¶æ¯
+
+ ))}
+
+
+
+
+ {/* APIæ¥å
¥è¯Žæ */}
+
+
+
+
+
+
+ ç¥å°æ Skill API æ¥å£
+
+
ä»»äœç³»ç»éœå¯éè¿ä»¥äžæ¥å£äžç¥å°æSkillçŽæ¥éä¿¡
+
+
+
+ POST {API_BASE_URL}/chat
+
+
+
+
+
+ POST {API_BASE_URL}/query?phone=13800138000
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* åèœæš¡å */}
+
+ {modules.map((module, i) => (
+
+
+
+
+
+
+ {module.title}
+ {module.description}
+
+
+
+
+ ))}
+
+
+ {/* 䜿çšè¯Žæ */}
+
+
+ å¿«éæ¥å
¥æå
+
+
+
+
+
1
+
é
çœ®æž é
+
åšæž éé
çœ®äžæ·»å é£ä¹Š/äŒåŸ®/åŸ®ä¿¡çæž é
+
+
+
2
+
å¡«åå¯é¥
+
å¡«å
¥å¯¹åºå¹³å°çAppIDåSecret
+
+
+
3
+
åŒå§å¯¹è¯
+
åšå¯¹åºå¹³å°@æºåšäººå³å¯äžç¥å°æå¯¹è¯
+
+
+
+
+
+
+ )
+}
diff --git a/app/ai-agent/report/page.tsx b/app/ai-agent/report/page.tsx
index e82e563..c57359d 100644
--- a/app/ai-agent/report/page.tsx
+++ b/app/ai-agent/report/page.tsx
@@ -1,234 +1,709 @@
"use client"
import { useState } from "react"
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
-import { Input } from "@/components/ui/input"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select"
import { Label } from "@/components/ui/label"
+import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
-import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
-import {
- FileText, Download, Share2, Clock, Eye, Sparkles,
- BarChart3, Users, TrendingUp, Calendar, Plus, Trash2
+import {
+ FileText,
+ Plus,
+ Download,
+ RefreshCw,
+ Eye,
+ Calendar,
+ Users,
+ TrendingUp,
+ PieChart,
+ BarChart3,
+ Clock,
+ CheckCircle2,
+ Loader2,
+ Send,
+ Mail,
+ MessageSquare,
+ Play,
+ Sparkles,
} from "lucide-react"
-const reportTemplates = [
- { id: "1", name: "çšæ·å¢é¿åææ¥å", description: "åæçšæ·å¢é¿è¶å¿åæž éææ", icon: TrendingUp },
- { id: "2", name: "çšæ·ç»åæŽå¯æ¥å", description: "深床åæçšæ·ç¹åŸåè¡äžºå奜", icon: Users },
- { id: "3", name: "æ°æ®èŽšéè¯äŒ°æ¥å", description: "è¯äŒ°æ°æ®å®æŽæ§ååç¡®æ§", icon: BarChart3 },
- { id: "4", name: "è¥éææåææ¥å", description: "è¯äŒ°è¥é掻åšROIåèœ¬åææ", icon: TrendingUp },
-]
+// æ¥åè§åæ¥å£
+interface ReportRule {
+ id: string
+ name: string
+ templateId: string
+ schedule: string
+ enabled: boolean
+ isDefault: boolean
+ config: {
+ dateRange: string
+ includeCharts: boolean
+ sendTo: string[]
+ format: 'pdf' | 'html' | 'markdown'
+ }
+ promptTemplate: string
+}
-const recentReports = [
+// æ¥åæš¡æ¿
+interface ReportTemplate {
+ id: string
+ name: string
+ description: string
+ type: 'daily' | 'weekly' | 'monthly' | 'custom'
+ sections: string[]
+ icon: string
+}
+
+// é»è®€æ¥åè§å
+const DEFAULT_RULES: ReportRule[] = [
{
- id: "r1",
- name: "2024幎1æçšæ·å¢é¿åææ¥å",
- template: "çšæ·å¢é¿åææ¥å",
- createdAt: "2024-01-15 14:30",
- status: "completed",
- pages: 12,
+ id: 'rule_daily',
+ name: 'æ¯æ¥è¿è¥æ¥æ¥è§å',
+ templateId: 'tpl_daily',
+ schedule: 'æ¯æ¥ 23:59',
+ enabled: true,
+ isDefault: true,
+ config: {
+ dateRange: 'today',
+ includeCharts: true,
+ sendTo: ['admin@company.com'],
+ format: 'pdf',
+ },
+ promptTemplate: `çææ¯æ¥è¿è¥æ¥æ¥ïŒå
å«ä»¥äžå
容ïŒ
+
+1. æ žå¿ææ
+ - æ»çšæ·æ°åæ¥å¢é
+ - 掻è·çšæ·æ°å掻è·ç
+ - æ°å¢çšæ·æ°
+
+2. çšæ·æŽ»è·
+ - åççº§çšæ·æŽ»è·æ
åµ
+ - æŽ»è·æ¶æ®µååž
+
+3. æž éæ¶æ¯
+ - åæž éæ¶æ¯éç»è®¡
+ - ååºæ¶éŽåæ
+
+4. AIæ¥è¯¢ç»è®¡
+ - æ¥è¯¢æ¬¡æ°
+ - å¹³åååºæ¶éŽ
+ - çéšæ¥è¯¢ç±»å
+
+èŸåºæ ŒåŒïŒç»æåæ¥åïŒå
嫿°æ®è¡šæ Œåè¶å¿æè¿°`,
},
{
- id: "r2",
- name: "é«ä»·åŒçšæ·ç»åæŽå¯",
- template: "çšæ·ç»åæŽå¯æ¥å",
- createdAt: "2024-01-14 10:20",
- status: "completed",
- pages: 8,
+ id: 'rule_weekly',
+ name: 'åšåºŠæ°æ®èŽšéè§å',
+ templateId: 'tpl_weekly',
+ schedule: 'æ¯å𿥠00:00',
+ enabled: true,
+ isDefault: true,
+ config: {
+ dateRange: 'week',
+ includeCharts: true,
+ sendTo: ['data@company.com'],
+ format: 'pdf',
+ },
+ promptTemplate: `çæåšåºŠæ°æ®èŽšéæ¥åïŒ
+
+1. èŽšéæŠè§
+ - æ°æ®å®æŽåºŠè¯å
+ - æ°æ®å确床è¯å
+ - æ¬åšèŽšéè¶å¿
+
+2. æž
æŽç»è®¡
+ - æž
æŽè®°åœæ°
+ - æ ŒåŒååæ®µæ°
+ - åŒåžžæ°æ®å€ç
+
+3. å»éææ
+ - å»éåå对æ¯
+ - éå€çç»è®¡
+
+4. æ°æ®å®æŽåºŠ
+ - ååæ®µå¡«å
ç
+ - çŒºå€±åæ®µåæ`,
},
{
- id: "r3",
- name: "Q4æ°æ®èŽšéè¯äŒ°",
- template: "æ°æ®èŽšéè¯äŒ°æ¥å",
- createdAt: "2024-01-10 16:45",
- status: "generating",
- pages: 0,
+ id: 'rule_monthly',
+ name: 'æåºŠèµäº§æ¥åè§å',
+ templateId: 'tpl_monthly',
+ schedule: 'æ¯æ1æ¥ 08:00',
+ enabled: true,
+ isDefault: true,
+ config: {
+ dateRange: 'month',
+ includeCharts: true,
+ sendTo: ['admin@company.com', 'ceo@company.com'],
+ format: 'pdf',
+ },
+ promptTemplate: `çææåºŠçšæ·èµäº§æ¥åïŒ
+
+1. èµäº§æ»è§
+ - çšæ·æ»èµäº§ä»·åŒ
+ - æåºŠååè¶å¿
+ - æ žå¿ææ æ±æ»
+
+2. çšæ·å¢é¿
+ - æ°å¢çšæ·åæ
+ - æµå€±çšæ·åæ
+ - åå¢é¿æ
åµ
+
+3. RFMåæ
+ - RFMè¯åååž
+ - åççº§çšæ·å æ¯
+ - ä»·åŒè¿ç§»åæ
+
+4. æµéæ± ååž
+ - 念鿱 è§æš¡
+ - æåºŠåå
+ - 蜬ååæ
+
+5. æ çŸèŠç
+ - æ çŸèŠçç
+ - çéšæ çŸTOP10`,
},
]
-export default function AIReportPage() {
- const [showCreateDialog, setShowCreateDialog] = useState(false)
- const [selectedTemplate, setSelectedTemplate] = useState("")
- const [reportConfig, setReportConfig] = useState({
- name: "",
- dateRange: "last_30_days",
- userSegment: "all",
- customPrompt: "",
- })
+// é¢å®ä¹æ¥åæš¡æ¿
+const REPORT_TEMPLATES: ReportTemplate[] = [
+ {
+ id: 'tpl_daily',
+ name: 'æ¯æ¥è¿è¥æ¥æ¥',
+ description: 'å
å«åœæ¥ç𿷿޻è·ãæž éæ¶æ¯ãAIæ¥è¯¢ç宿¶æ°æ®æ±æ»',
+ type: 'daily',
+ sections: ['æ žå¿ææ ', 'çšæ·æŽ»è·', 'æž éæ¶æ¯', 'AIæ¥è¯¢ç»è®¡'],
+ icon: 'ð',
+ },
+ {
+ id: 'tpl_weekly',
+ name: 'åšåºŠæ°æ®èŽšéæ¥å',
+ description: 'æ°æ®æž
æŽãå»éãè¡¥å
šçèŽšéææ åšåºŠæ±æ»',
+ type: 'weekly',
+ sections: ['èŽšéæŠè§', 'æž
æŽç»è®¡', 'å»éææ', 'æ°æ®å®æŽåºŠ'],
+ icon: 'ð',
+ },
+ {
+ id: 'tpl_monthly',
+ name: 'æåºŠçšæ·èµäº§æ¥å',
+ description: 'çšæ·å¢é¿ãRFMååžãæµéæ± ååçæ žå¿èµäº§ææ ',
+ type: 'monthly',
+ sections: ['èµäº§æ»è§', 'çšæ·å¢é¿', 'RFMåæ', 'æµéæ± ååž', 'æ çŸèŠç'],
+ icon: 'ð',
+ },
+ {
+ id: 'tpl_rfm',
+ name: 'RFMåææ¥å',
+ description: '诊ç»çRFMè¯åååžåçšæ·ä»·åŒåå±åæ',
+ type: 'custom',
+ sections: ['RFMæŠè§', 'è¯åååž', 'ç级åå±', 'ä»·åŒè¶å¿'],
+ icon: 'ð',
+ },
+ {
+ id: 'tpl_portrait',
+ name: 'çšæ·ç»åæ¥å',
+ description: 'çšæ·ç»åç¹åŸåæïŒå
å«å°åã幎éŸãå奜ç绎床',
+ type: 'custom',
+ sections: ['ç»åæŠè§', 'å°åååž', 'è¡äžºç¹åŸ', 'å奜åæ'],
+ icon: 'ð€',
+ },
+ {
+ id: 'tpl_traffic',
+ name: 'æµéæ± åææ¥å',
+ description: '念鿱 çšæ·è§æš¡ã蜬åçãä»·åŒèŽ¡ç®åæ',
+ type: 'custom',
+ sections: ['æ± è§æš¡', 'èœ¬åæŒæ', 'ä»·åŒèŽ¡ç®', 'å¢é¿è¶å¿'],
+ icon: 'ð',
+ },
+]
+
+// çæçæ¥å
+interface GeneratedReport {
+ id: string
+ templateId: string
+ title: string
+ generatedAt: string
+ status: 'ready' | 'generating'
+ content?: string
+ metrics: {
+ totalUsers: number
+ activeUsers: number
+ newUsers: number
+ rfmAvg: number
+ }
+}
+
+const GENERATED_REPORTS: GeneratedReport[] = [
+ {
+ id: 'rpt_1',
+ templateId: 'tpl_monthly',
+ title: '2024幎1æçšæ·èµäº§ææ¥',
+ generatedAt: '2024-02-01 08:00',
+ status: 'ready',
+ metrics: { totalUsers: 2013000000, activeUsers: 450000000, newUsers: 15000000, rfmAvg: 52.3 },
+ },
+ {
+ id: 'rpt_2',
+ templateId: 'tpl_weekly',
+ title: 'æ¬åšæ°æ®èŽšéæ¥å',
+ generatedAt: '2024-01-28 00:00',
+ status: 'ready',
+ metrics: { totalUsers: 2013000000, activeUsers: 320000000, newUsers: 2500000, rfmAvg: 51.8 },
+ },
+ {
+ id: 'rpt_3',
+ templateId: 'tpl_daily',
+ title: '仿¥è¿è¥æ¥æ¥',
+ generatedAt: '2024-01-30 23:59',
+ status: 'ready',
+ metrics: { totalUsers: 2013000000, activeUsers: 45000000, newUsers: 350000, rfmAvg: 52.5 },
+ },
+]
+
+export default function ReportPage() {
+ const [reports, setReports] = useState
(GENERATED_REPORTS)
+ const [rules, setRules] = useState(DEFAULT_RULES)
+ const [activeTab, setActiveTab] = useState("templates")
+ const [generating, setGenerating] = useState(null)
+ const [showGenerateDialog, setShowGenerateDialog] = useState(false)
+ const [selectedTemplate, setSelectedTemplate] = useState(null)
+ const [showPreviewDialog, setShowPreviewDialog] = useState(false)
+ const [previewReport, setPreviewReport] = useState(null)
+ const [showRuleDialog, setShowRuleDialog] = useState(false)
+ const [selectedRule, setSelectedRule] = useState(null)
+ const [editingPrompt, setEditingPrompt] = useState('')
+
+ const formatNumber = (num: number): string => {
+ if (num >= 1000000000) return `${(num / 1000000000).toFixed(2)}B`
+ if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`
+ if (num >= 1000) return `${(num / 1000).toFixed(0)}K`
+ return num.toLocaleString()
+ }
+
+ // éè¿Skillçææ¥å
+ const generateReport = async (template: ReportTemplate) => {
+ setGenerating(template.id)
+ setShowGenerateDialog(false)
+
+ try {
+ // è°çšAI Chat APIæ§è¡æ¥åçæ
+ const response = await fetch('/api/ai-chat', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ message: `çæ${template.name}ïŒå
å«ä»¥äžç« èïŒ${template.sections.join('ã')}`
+ })
+ })
+
+ const data = await response.json()
+
+ // æ·»å æ°æ¥åå°å衚
+ const newReport: GeneratedReport = {
+ id: `rpt_${Date.now()}`,
+ templateId: template.id,
+ title: `${template.name} - ${new Date().toLocaleDateString()}`,
+ generatedAt: new Date().toLocaleString(),
+ status: 'ready',
+ content: data.success ? data.response?.content : 'æ¥åçæå€±èŽ¥',
+ metrics: {
+ totalUsers: 2013000000,
+ activeUsers: 450000000,
+ newUsers: 15000000,
+ rfmAvg: 52.3,
+ },
+ }
+
+ setReports([newReport, ...reports])
+ } catch (error) {
+ console.error('æ¥åçæå€±èŽ¥:', error)
+ } finally {
+ setGenerating(null)
+ }
+ }
+
+ const openPreview = (report: GeneratedReport) => {
+ setPreviewReport(report)
+ setShowPreviewDialog(true)
+ }
return (
-
- {/* 页颿 é¢ */}
-
-
-
æºèœæ¥å
-
AIèªåšçææ°æ®åææ¥åïŒæ¯æèªå®ä¹æš¡æ¿åæç€ºè¯
+
+
+ {/* é¡¶éšæ é¢ */}
+
+
+
æºèœæ¥å
+
AIèªåšçææ°æ®åææ¥åïŒæ¯æå€ç§æ¥åæš¡æ¿
+
+
-
-
- {/* æ¥åæš¡æ¿ */}
-
-
æ¥åæš¡æ¿
-
- {reportTemplates.map((template) => (
-
{
- setSelectedTemplate(template.id)
- setShowCreateDialog(true)
- }}
- >
-
-
-
-
-
-
{template.name}
-
{template.description}
+ {/* æ çŸé¡µ */}
+
+
+ æ¥åæš¡æ¿
+ è§åé
眮
+ å岿¥å
+
+
+ {/* æ¥åæš¡æ¿ */}
+
+
+ {REPORT_TEMPLATES.map(template => (
+
+
+
+ {template.icon}
+ {
+ template.type === 'daily' ? 'æ¥æ¥' :
+ template.type === 'weekly' ? 'åšæ¥' :
+ template.type === 'monthly' ? 'ææ¥' : 'èªå®ä¹'
+ }
+
+ {template.name}
+ {template.description}
+
+ {template.sections.map((section, i) => (
+ {section}
+ ))}
+
+
+
+
+ ))}
+
+
+
+ {/* è§åé
眮 */}
+
+ {rules.map(rule => {
+ const template = REPORT_TEMPLATES.find(t => t.id === rule.templateId)
+ return (
+
+
+
+
+
+ {template?.icon || 'ð'}
+
+
+
+
{rule.name}
+ {rule.isDefault && é»è®€è§å}
+ {rule.enabled ? (
+ å·²å¯çš
+ ) : (
+ å·²çŠçš
+ )}
+
+
{template?.name}
+
+
+
+ {rule.schedule}
+
+ æ ŒåŒ: {rule.config.format.toUpperCase()}
+ åé: {rule.config.sendTo.join(', ')}
+
+
+
+
+
+
+
+
+
+
+ )
+ })}
+
+
+ {/* å岿¥å */}
+
+
+
+
+ {reports.map(report => {
+ const template = REPORT_TEMPLATES.find(t => t.id === report.templateId)
+
+ return (
+
+
+
+ {template?.icon || 'ð'}
+
+
+
{report.title}
+
+
+
+ {report.generatedAt}
+
+
+
+ {formatNumber(report.metrics.totalUsers)} çšæ·
+
+ RFMååŒ: {report.metrics.rfmAvg}
+
+
+
+
+
+
+
+
+
+ )
+ })}
- ))}
-
-
+
+
- {/* æè¿æ¥å */}
-
-
- æè¿æ¥å
- æ¥çå管çå·²çæçæ¥å
-
-
-
- {recentReports.map((report) => (
-
-
-
-
+ {/* çææ¥ååŒ¹çª */}
+