"use client" import type React from "react" import { useState, useEffect } from "react" import { Card } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Switch } from "@/components/ui/switch" import { QrCode, X, ChevronDown, Plus, Maximize2, Upload, Download, Settings } from "lucide-react" import { TooltipProvider } from "@/components/ui/tooltip" import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/ui/table" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription, } from "@/components/ui/dialog" import { fetchScenes } from "@/api/scenarios" import type { SceneItem } from "@/api/scenarios" // 调整场景顺序,确保API获客在最后,并且前三个是最常用的场景 const scenarios = [ { id: "haibao", name: "海报获客", type: "material" }, { id: "order", name: "订单获客", type: "api" }, { id: "douyin", name: "抖音获客", type: "social" }, { id: "xiaohongshu", name: "小红书获客", type: "social" }, { id: "phone", name: "电话获客", type: "social" }, { id: "gongzhonghao", name: "公众号获客", type: "social" }, { id: "weixinqun", name: "微信群获客", type: "social" }, { id: "payment", name: "付款码获客", type: "material" }, { id: "api", name: "API获客", type: "api" }, // API获客放在最后 ] interface Account { id: string nickname: string avatar: string } interface Material { id: string name: string type: "poster" | "payment" preview: string } interface BasicSettingsProps { formData: any onChange: (data: any) => void onNext?: () => void } const posterTemplates = [ { id: "poster-1", name: "点击领取", preview: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%82%B9%E5%87%BB%E9%A2%86%E5%8F%961-tipd1HI7da6qooY5NkhxQnXBnT5LGU.gif", }, { id: "poster-2", name: "点击合作", preview: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%82%B9%E5%87%BB%E5%90%88%E4%BD%9C-LPlMdgxtvhqCSr4IM1bZFEFDBF3ztI.gif", }, { id: "poster-3", name: "点击咨询", preview: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%82%B9%E5%87%BB%E5%92%A8%E8%AF%A2-FTiyAMAPop2g9LvjLOLDz0VwPg3KVu.gif", }, { id: "poster-4", name: "点击签到", preview: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%82%B9%E5%87%BB%E7%AD%BE%E5%88%B0-94TZIkjLldb4P2jTVlI6MkSDg0NbXi.gif", }, { id: "poster-5", name: "点击了解", preview: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%82%B9%E5%87%BB%E4%BA%86%E8%A7%A3-6GCl7mQVdO4WIiykJyweSubLsTwj71.gif", }, { id: "poster-6", name: "点击报名", preview: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%82%B9%E5%87%BB%E6%8A%A5%E5%90%8D-Mj0nnva0BiASeDAIhNNaRRAbjPgjEj.gif", }, ] const generateRandomAccounts = (count: number): Account[] => { return Array.from({ length: count }, (_, index) => ({ id: `account-${index + 1}`, nickname: `账号-${Math.random().toString(36).substring(2, 7)}`, avatar: `/placeholder.svg?height=40&width=40&text=${index + 1}`, })) } const generatePosterMaterials = (): Material[] => { return posterTemplates.map((template) => ({ id: template.id, name: template.name, type: "poster", preview: template.preview, })) } // 格式化场景名称,移除"获客"二字 function formatSceneName(name: string): string { return name.replace(/获客/g, ""); } export function BasicSettings({ formData, onChange, onNext }: BasicSettingsProps) { const [isAccountDialogOpen, setIsAccountDialogOpen] = useState(false) const [isMaterialDialogOpen, setIsMaterialDialogOpen] = useState(false) const [isQRCodeOpen, setIsQRCodeOpen] = useState(false) const [isPreviewOpen, setIsPreviewOpen] = useState(false) const [isPhoneSettingsOpen, setIsPhoneSettingsOpen] = useState(false) const [previewImage, setPreviewImage] = useState("") const [accounts] = useState(generateRandomAccounts(50)) const [materials] = useState(generatePosterMaterials()) const [selectedAccounts, setSelectedAccounts] = useState( formData.accounts?.length > 0 ? formData.accounts : [], ) const [selectedMaterials, setSelectedMaterials] = useState( formData.materials?.length > 0 ? formData.materials : [], ) // 添加场景列表状态 const [scenes, setScenes] = useState([]) const [loadingScenes, setLoadingScenes] = useState(true) const [sceneError, setSceneError] = useState(null) const [showAllScenarios, setShowAllScenarios] = useState(false) const [isImportDialogOpen, setIsImportDialogOpen] = useState(false) const [importedTags, setImportedTags] = useState< Array<{ phone: string wechat: string source?: string orderAmount?: number orderDate?: string }> >(formData.importedTags || []) // 初始化电话获客设置 const [phoneSettings, setPhoneSettings] = useState({ autoAdd: formData.phoneSettings?.autoAdd ?? true, speechToText: formData.phoneSettings?.speechToText ?? true, questionExtraction: formData.phoneSettings?.questionExtraction ?? true, }) // 加载场景列表 useEffect(() => { const loadScenes = async () => { try { setLoadingScenes(true) setSceneError(null) const response = await fetchScenes({ limit: 30 }) if (response.code === 200 && response.data?.list) { setScenes(response.data.list) } else { setSceneError(response.msg || "获取场景列表失败") console.error("获取场景列表失败:", response.msg) } } catch (err) { console.error("获取场景列表失败:", err) setSceneError("获取场景列表失败,请稍后重试") } finally { setLoadingScenes(false) } } loadScenes() }, []) // 初始化时,如果没有选择场景,默认选择海报获客 useEffect(() => { if (!formData.scenario) { onChange({ ...formData, scenario: "haibao" }) } if (!formData.planName) { if (formData.materials?.length > 0) { const today = new Date().toLocaleDateString("zh-CN").replace(/\//g, "") onChange({ ...formData, planName: `海报${today}` }) } else { onChange({ ...formData, planName: "场景" }) } } }, [formData, onChange]) // 处理从API获取的场景选择 const handleSceneSelect = (scene: SceneItem) => { // 更新formData中的场景相关数据 const formattedName = formatSceneName(scene.name); onChange({ ...formData, sceneId: scene.id, sceneName: scene.name, scenario: getLocalScenarioType(scene.name), // 基于名称推断本地场景类型 }); // 如果是电话场景,自动设置计划名称 if (scene.name.includes("电话")) { const today = new Date().toLocaleDateString("zh-CN").replace(/\//g, ""); onChange({ ...formData, planName: `${formattedName}${today}` }); } } // 处理本地场景选择 const handleScenarioSelect = (scenarioId: string) => { onChange({ ...formData, scenario: scenarioId }) // 如果选择了电话获客,自动更新计划名称 if (scenarioId === "phone") { const today = new Date().toLocaleDateString("zh-CN").replace(/\//g, "") onChange({ ...formData, planName: `电话${today}` }) } } // 根据场景名称推断本地场景类型 const getLocalScenarioType = (name: string): string => { if (name.includes("海报")) return "haibao"; if (name.includes("订单")) return "order"; if (name.includes("抖音")) return "douyin"; if (name.includes("小红书")) return "xiaohongshu"; if (name.includes("电话")) return "phone"; if (name.includes("公众号")) return "gongzhonghao"; if (name.includes("微信群")) return "weixinqun"; if (name.includes("付款码")) return "payment"; if (name.includes("API")) return "api"; return "haibao"; // 默认返回海报获客类型 } const handleAccountSelect = (account: Account) => { const updatedAccounts = [...selectedAccounts, account] setSelectedAccounts(updatedAccounts) onChange({ ...formData, accounts: updatedAccounts }) } const handleMaterialSelect = (material: Material) => { const updatedMaterials = [material] setSelectedMaterials(updatedMaterials) onChange({ ...formData, materials: updatedMaterials }) setIsMaterialDialogOpen(false) // 更新计划名称 const today = new Date().toLocaleDateString("zh-CN").replace(/\//g, "") onChange({ ...formData, planName: `海报${today}`, materials: updatedMaterials }) } const handleRemoveAccount = (accountId: string) => { const updatedAccounts = selectedAccounts.filter((a) => a.id !== accountId) setSelectedAccounts(updatedAccounts) onChange({ ...formData, accounts: updatedAccounts }) } const handleRemoveMaterial = (materialId: string) => { const updatedMaterials = selectedMaterials.filter((m) => m.id !== materialId) setSelectedMaterials(updatedMaterials) onChange({ ...formData, materials: updatedMaterials }) } const handlePreviewImage = (imageUrl: string) => { setPreviewImage(imageUrl) setIsPreviewOpen(true) } // 只显示前三个场景,其他的需要点击展开 const displayedScenarios = showAllScenarios ? scenarios : scenarios.slice(0, 3) const handleFileImport = (event: React.ChangeEvent) => { const file = event.target.files?.[0] if (file) { const reader = new FileReader() reader.onload = (e) => { try { const content = e.target?.result as string const rows = content.split("\n").filter((row) => row.trim()) const tags = rows.slice(1).map((row) => { const [phone, wechat, source, orderAmount, orderDate] = row.split(",") return { phone: phone.trim(), wechat: wechat.trim(), source: source?.trim(), orderAmount: orderAmount ? Number(orderAmount) : undefined, orderDate: orderDate?.trim(), } }) setImportedTags(tags) onChange({ ...formData, importedTags: tags }) } catch (error) { console.error("导入失败:", error) } } reader.readAsText(file) } } const handleDownloadTemplate = () => { const template = "电话号码,微信号,来源,订单金额,下单日期\n13800138000,wxid_123,抖音,99.00,2024-03-03" const blob = new Blob([template], { type: "text/csv" }) const url = window.URL.createObjectURL(blob) const a = document.createElement("a") a.href = url a.download = "订单导入模板.csv" document.body.appendChild(a) a.click() document.body.removeChild(a) window.URL.revokeObjectURL(url) } // 处理电话获客设置更新 const handlePhoneSettingsUpdate = () => { onChange({ ...formData, phoneSettings }) setIsPhoneSettingsOpen(false) } return (
{/* 场景按钮阵列 */}
{loadingScenes ? ( // 加载中状态 Array.from({ length: 6 }).map((_, index) => (
)) ) : sceneError || scenes.length === 0 ? ( // 加载失败或无数据时显示本地场景 displayedScenarios.map((scenario) => ( )) ) : ( // 从API获取的场景列表 scenes.map((scene) => ( )) )}
{/* 展开更多按钮 - 仅当显示本地场景且未展开全部时显示 */} {(!loadingScenes && (sceneError || scenes.length === 0) && !showAllScenarios) && ( )}
onChange({ ...formData, planName: e.target.value })} placeholder="请输入计划名称" className="mt-2" />
{formData.scenario && ( <> {scenarios.find((s) => s.id === formData.scenario)?.type === "social" && (
{selectedAccounts.length > 0 && (
{selectedAccounts.map((account) => (
{account.nickname} {account.nickname}
))}
)}
)} {/* 电话获客特殊设置 */} {formData.scenario === "phone" && (
自动添加客户
{phoneSettings.autoAdd ? "已开启" : "已关闭"}
语音转文字
{phoneSettings.speechToText ? "已开启" : "已关闭"}
问题提取
{phoneSettings.questionExtraction ? "已开启" : "已关闭"}

提示:电话获客功能将自动记录来电信息,并根据设置执行相应操作

)} {scenarios.find((s) => s.id === formData.scenario)?.type === "material" && (
{/* 海报展示区域 */}
{materials.map((material) => (
m.id === material.id) ? "ring-2 ring-blue-600" : "hover:ring-2 hover:ring-blue-600" }`} onClick={() => handleMaterialSelect(material)} > {material.name}
{material.name}
))}
{selectedMaterials.length > 0 && (
{selectedMaterials[0].name} handlePreviewImage(selectedMaterials[0].preview)} />
)}
)} {scenarios.find((s) => s.id === formData.scenario)?.id === "order" && (
{importedTags.length > 0 && (

已导入 {importedTags.length} 条数据

电话号码 微信号 来源 订单金额 {importedTags.slice(0, 5).map((tag, index) => ( {tag.phone} {tag.wechat} {tag.source} {tag.orderAmount} ))} {importedTags.length > 5 && ( 还有 {importedTags.length - 5} 条数据未显示 )}
)}
)} )}
onChange({ ...formData, enabled: checked })} />
{/* 账号选择对话框 */} 选择账号
{accounts.map((account) => (
handleAccountSelect(account)} > {account.nickname} {selectedAccounts.find((a) => a.id === account.id) && (
)}
))}
{/* 二维码对话框 */} 绑定账号
二维码

请用相应的APP扫码

{/* 图片预览对话框 */} 海报预览
预览
{/* 电话获客设置对话框 */} 电话获客设置 配置电话获客的自动化功能,提高获客效率

来电后自动将客户添加为微信好友

推荐:开启此功能可提高转化率约30%

setPhoneSettings({ ...phoneSettings, autoAdd: checked })} className="data-[state=checked]:bg-blue-600" />

自动将通话内容转换为文字记录

支持普通话、粤语等多种方言识别

setPhoneSettings({ ...phoneSettings, speechToText: checked })} className="data-[state=checked]:bg-blue-600" />

自动从通话中提取客户的首句问题

AI智能识别客户意图,提高回复精准度

setPhoneSettings({ ...phoneSettings, questionExtraction: checked })} className="data-[state=checked]:bg-blue-600" />
{/* 订单导入对话框 */} 导入订单标签
电话号码 微信号 来源 订单金额 下单日期 {importedTags.map((tag, index) => ( {tag.phone} {tag.wechat} {tag.source} {tag.orderAmount} {tag.orderDate} ))}
) }