diff --git a/nkebao/src/App.tsx b/nkebao/src/App.tsx index c3fd82fd..90d16eb1 100644 --- a/nkebao/src/App.tsx +++ b/nkebao/src/App.tsx @@ -1,44 +1,44 @@ -import React, { useEffect } from 'react'; -import { BrowserRouter, Routes, Route } from 'react-router-dom'; -import { AuthProvider } from './contexts/AuthContext'; -import { WechatAccountProvider } from './contexts/WechatAccountContext'; -import ProtectedRoute from './components/ProtectedRoute'; -import LayoutWrapper from './components/LayoutWrapper'; -import { initInterceptors } from './api'; -import Home from './pages/Home'; -import Login from './pages/login/Login'; -import Devices from './pages/devices/Devices'; -import DeviceDetail from './pages/devices/DeviceDetail'; -import WechatAccounts from './pages/wechat-accounts/WechatAccounts'; -import WechatAccountDetail from './pages/wechat-accounts/WechatAccountDetail'; -import Workspace from './pages/workspace/Workspace'; -import AutoLike from './pages/workspace/auto-like/AutoLike'; -import NewAutoLike from './pages/workspace/auto-like/NewAutoLike'; -import AutoLikeDetail from './pages/workspace/auto-like/AutoLikeDetail'; -import NewDistribution from './pages/workspace/traffic-distribution/NewDistribution'; -import AutoGroup from './pages/workspace/auto-group/AutoGroup'; -import AutoGroupDetail from './pages/workspace/auto-group/Detail'; -import GroupPush from './pages/workspace/group-push/GroupPush'; -import MomentsSync from './pages/workspace/moments-sync/MomentsSync'; -import MomentsSyncDetail from './pages/workspace/moments-sync/Detail'; -import NewMomentsSync from './pages/workspace/moments-sync/new'; -import AIAssistant from './pages/workspace/ai-assistant/AIAssistant'; -import TrafficDistribution from './pages/workspace/traffic-distribution/TrafficDistribution'; -import TrafficDistributionDetail from './pages/workspace/traffic-distribution/Detail'; -import Scenarios from './pages/scenarios/Scenarios'; -import NewPlan from './pages/scenarios/new/page'; -import ScenarioDetail from './pages/scenarios/ScenarioDetail'; -import Profile from './pages/profile/Profile'; -import Plans from './pages/plans/Plans'; -import PlanDetail from './pages/plans/PlanDetail'; -import Orders from './pages/orders/Orders'; -import TrafficPool from './pages/traffic-pool/TrafficPool'; -import ContactImport from './pages/contact-import/ContactImport'; -import Content from './pages/content/Content'; -import TrafficPoolDetail from './pages/traffic-pool/TrafficPoolDetail'; -import NewContent from './pages/content/NewContent'; -import Materials from './pages/content/materials/List'; -import MaterialsNew from './pages/content/materials/New'; +import React, { useEffect } from "react"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { AuthProvider } from "./contexts/AuthContext"; +import { WechatAccountProvider } from "./contexts/WechatAccountContext"; +import ProtectedRoute from "./components/ProtectedRoute"; +import LayoutWrapper from "./components/LayoutWrapper"; +import { initInterceptors } from "./api"; +import Home from "./pages/Home"; +import Login from "./pages/login/Login"; +import Devices from "./pages/devices/Devices"; +import DeviceDetail from "./pages/devices/DeviceDetail"; +import WechatAccounts from "./pages/wechat-accounts/WechatAccounts"; +import WechatAccountDetail from "./pages/wechat-accounts/WechatAccountDetail"; +import Workspace from "./pages/workspace/Workspace"; +import AutoLike from "./pages/workspace/auto-like/AutoLike"; +import NewAutoLike from "./pages/workspace/auto-like/NewAutoLike"; +import AutoLikeDetail from "./pages/workspace/auto-like/AutoLikeDetail"; +import NewDistribution from "./pages/workspace/traffic-distribution/NewDistribution"; +import AutoGroup from "./pages/workspace/auto-group/AutoGroup"; +import AutoGroupDetail from "./pages/workspace/auto-group/Detail"; +import GroupPush from "./pages/workspace/group-push/GroupPush"; +import MomentsSync from "./pages/workspace/moments-sync/MomentsSync"; +import MomentsSyncDetail from "./pages/workspace/moments-sync/Detail"; +import NewMomentsSync from "./pages/workspace/moments-sync/new"; +import AIAssistant from "./pages/workspace/ai-assistant/AIAssistant"; +import TrafficDistribution from "./pages/workspace/traffic-distribution/TrafficDistribution"; +import TrafficDistributionDetail from "./pages/workspace/traffic-distribution/Detail"; +import Scenarios from "./pages/scenarios/Scenarios"; +import NewPlan from "./pages/scenarios/new/page"; +import ScenarioList from "./pages/scenarios/ScenarioList"; +import Profile from "./pages/profile/Profile"; +import Plans from "./pages/plans/Plans"; +import PlanDetail from "./pages/plans/PlanDetail"; +import Orders from "./pages/orders/Orders"; +import TrafficPool from "./pages/traffic-pool/TrafficPool"; +import ContactImport from "./pages/contact-import/ContactImport"; +import Content from "./pages/content/Content"; +import TrafficPoolDetail from "./pages/traffic-pool/TrafficPoolDetail"; +import NewContent from "./pages/content/NewContent"; +import Materials from "./pages/content/materials/List"; +import MaterialsNew from "./pages/content/materials/New"; function App() { // 初始化HTTP拦截器 @@ -48,57 +48,118 @@ function App() { }, []); return ( - + - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - {/* 通用场景路由 - 支持查询参数传递name */} - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - {/* 你可以继续添加更多路由 */} - - - + + + + } /> + } /> + } /> + } /> + } /> + } + /> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } /> + } + /> + } /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + {/* 场景计划开始 */} + } /> + } /> + } /> + } + /> + {/* 场景计划结束 */} + } /> + } /> + } /> + } /> + } /> + } + /> + } /> + } /> + } /> + } /> + } /> + } + /> + } + /> + {/* 你可以继续添加更多路由 */} + + + diff --git a/nkebao/src/components/Layout.tsx b/nkebao/src/components/Layout.tsx index 5ea387ef..1f4a1f6b 100644 --- a/nkebao/src/components/Layout.tsx +++ b/nkebao/src/components/Layout.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react"; interface LayoutProps { loading?: boolean; @@ -7,29 +7,19 @@ interface LayoutProps { footer?: React.ReactNode; } -const Layout: React.FC = ({ - loading, - children, - header, - footer +const Layout: React.FC = ({ + loading, + children, + header, + footer, }) => { return (
- {header && ( -
- {header} -
- )} -
- {children} -
- {footer && ( -
- {footer} -
- )} + {header &&
{header}
} +
{children}
+ {footer &&
{footer}
}
); }; -export default Layout; \ No newline at end of file +export default Layout; diff --git a/nkebao/src/pages/scenarios/ScenarioDetail.tsx b/nkebao/src/pages/scenarios/ScenarioList.tsx similarity index 52% rename from nkebao/src/pages/scenarios/ScenarioDetail.tsx rename to nkebao/src/pages/scenarios/ScenarioList.tsx index 2059daeb..b31dcd0a 100644 --- a/nkebao/src/pages/scenarios/ScenarioDetail.tsx +++ b/nkebao/src/pages/scenarios/ScenarioList.tsx @@ -1,12 +1,33 @@ -import React, { useEffect, useState, useCallback } from 'react'; -import { useParams, useNavigate, useSearchParams } from 'react-router-dom'; -import PageHeader from '@/components/PageHeader'; -import Layout from '@/components/Layout'; -import BottomNav from '@/components/BottomNav'; -import { Plus, Users, TrendingUp, Calendar, Copy, Trash2, Play, Pause, Settings, Loader2, Code } from 'lucide-react'; -import { fetchPlanList, fetchPlanDetail, copyPlan, deletePlan, type Task } from '@/api/scenarios'; -import { useToast } from '@/components/ui/toast'; -import '@/components/Layout.css'; +import React, { useEffect, useState, useCallback } from "react"; +import { useParams, useNavigate, useSearchParams } from "react-router-dom"; +import PageHeader from "@/components/PageHeader"; +import Layout from "@/components/Layout"; +import BottomNav from "@/components/BottomNav"; +import { + Plus, + Users, + Calendar, + Copy, + Trash2, + Play, + Pause, + Settings, + Loader2, + Code, + Search, + RefreshCw, +} from "lucide-react"; +import { + fetchPlanList, + fetchPlanDetail, + copyPlan, + deletePlan, + type Task, +} from "@/api/scenarios"; +import { useToast } from "@/components/ui/toast"; +import "@/components/Layout.css"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; interface ScenarioData { id: string; @@ -26,20 +47,25 @@ interface ApiSettings { } export default function ScenarioDetail() { - const { scenarioId } = useParams<{ scenarioId: string }>(); + const { scenarioId, scenarioName } = useParams<{ + scenarioId: string; + scenarioName: string; + }>(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const { toast } = useToast(); const [scenario, setScenario] = useState(null); const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(true); - const [error, setError] = useState(''); + const [error, setError] = useState(""); const [showApiDialog, setShowApiDialog] = useState(false); const [currentApiSettings, setCurrentApiSettings] = useState({ - apiKey: '', - webhookUrl: '', - taskId: '', + apiKey: "", + webhookUrl: "", + taskId: "", }); + const [searchTerm, setSearchTerm] = useState(""); + const [loadingTasks, setLoadingTasks] = useState(false); // 获取渠道中文名称 const getChannelName = (channel: string) => { @@ -61,61 +87,61 @@ export default function ScenarioDetail() { // 获取场景描述 const getScenarioDescription = (channel: string) => { const descriptions: Record = { - douyin: '通过抖音平台进行精准获客,利用短视频内容吸引目标用户', - xiaohongshu: '利用小红书平台进行内容营销获客,通过优质内容建立品牌形象', - gongzhonghao: '通过微信公众号进行获客,建立私域流量池', - haibao: '通过海报分享进行获客,快速传播品牌信息', - phone: '通过电话营销进行获客,直接与客户沟通', - weixinqun: '通过微信群进行获客,利用社交裂变效应', - payment: '通过付款码进行获客,便捷的支付方式', - api: '通过API接口进行获客,支持第三方系统集成', + douyin: "通过抖音平台进行精准获客,利用短视频内容吸引目标用户", + xiaohongshu: "利用小红书平台进行内容营销获客,通过优质内容建立品牌形象", + gongzhonghao: "通过微信公众号进行获客,建立私域流量池", + haibao: "通过海报分享进行获客,快速传播品牌信息", + phone: "通过电话营销进行获客,直接与客户沟通", + weixinqun: "通过微信群进行获客,利用社交裂变效应", + payment: "通过付款码进行获客,便捷的支付方式", + api: "通过API接口进行获客,支持第三方系统集成", }; - return descriptions[channel] || '通过该平台进行获客'; + return descriptions[channel] || "通过该平台进行获客"; }; useEffect(() => { const fetchScenarioData = async () => { if (!scenarioId) return; - + setLoading(true); - setError(''); - + setError(""); + try { // 获取计划列表 const response = await fetchPlanList(scenarioId, 1, 20); - + // 设置计划列表(可能为空) if (response && response.data && response.data.list) { setTasks(response.data.list); } else { setTasks([]); } - + // 构建场景数据(无论是否有计划都要创建) const scenarioData: ScenarioData = { id: scenarioId, - name: getScenarioName(), - image: '', // 可以根据需要设置图片 + name: scenarioName || "", + image: "", // 可以根据需要设置图片 description: getScenarioDescription(scenarioId), totalPlans: response?.data?.list?.length || 0, totalCustomers: 0, // 移除统计 todayCustomers: 0, // 移除统计 - growth: '', // 移除增长 + growth: "", // 移除增长 }; setScenario(scenarioData); } catch (error) { - console.error('获取场景数据失败:', error); + console.error("获取场景数据失败:", error); // 即使API失败也要创建基本的场景数据 const scenarioData: ScenarioData = { id: scenarioId, name: getScenarioName(), - image: '', + image: "", description: getScenarioDescription(scenarioId), totalPlans: 0, totalCustomers: 0, todayCustomers: 0, - growth: '', + growth: "", }; setScenario(scenarioData); setTasks([]); @@ -130,28 +156,31 @@ export default function ScenarioDetail() { // 获取场景名称 - 优先使用URL查询参数,其次使用映射 const getScenarioName = useCallback(() => { // 优先使用URL查询参数中的name - const urlName = searchParams.get('name'); + const urlName = searchParams.get("name"); if (urlName) { return urlName; } - + // 如果没有URL参数,使用映射 - return getChannelName(scenarioId || ''); + return getChannelName(scenarioId || ""); }, [searchParams, scenarioId]); // 更新场景数据中的名称 useEffect(() => { - setScenario(prev => prev ? { - ...prev, - name: (() => { - const urlName = searchParams.get('name'); - if (urlName) return urlName; - return getChannelName(scenarioId || ''); - })() - } : null); + setScenario((prev) => + prev + ? { + ...prev, + name: (() => { + const urlName = searchParams.get("name"); + if (urlName) return urlName; + return getChannelName(scenarioId || ""); + })(), + } + : null + ); }, [searchParams, scenarioId]); - const handleCopyPlan = async (taskId: string) => { const taskToCopy = tasks.find((task) => task.id === taskId); if (!taskToCopy) return; @@ -160,24 +189,28 @@ export default function ScenarioDetail() { const response = await copyPlan(taskId); if (response && response.code === 200) { toast({ - title: '计划已复制', + title: "计划已复制", description: `已成功复制"${taskToCopy.name}"`, }); - + // 重新加载数据 const refreshResponse = await fetchPlanList(scenarioId!, 1, 20); - if (refreshResponse && refreshResponse.code === 200 && refreshResponse.data) { + if ( + refreshResponse && + refreshResponse.code === 200 && + refreshResponse.data + ) { setTasks(refreshResponse.data.list); } } else { - throw new Error(response?.msg || '复制失败'); + throw new Error(response?.msg || "复制失败"); } } catch (error) { - console.error('复制计划失败:', error); + console.error("复制计划失败:", error); toast({ - title: '复制失败', - description: error instanceof Error ? error.message : '复制计划失败', - variant: 'destructive', + title: "复制失败", + description: error instanceof Error ? error.message : "复制计划失败", + variant: "destructive", }); } }; @@ -192,24 +225,28 @@ export default function ScenarioDetail() { const response = await deletePlan(taskId); if (response && response.code === 200) { toast({ - title: '计划已删除', + title: "计划已删除", description: `已成功删除"${taskToDelete.name}"`, }); - + // 重新加载数据 const refreshResponse = await fetchPlanList(scenarioId!, 1, 20); - if (refreshResponse && refreshResponse.code === 200 && refreshResponse.data) { + if ( + refreshResponse && + refreshResponse.code === 200 && + refreshResponse.data + ) { setTasks(refreshResponse.data.list); } } else { - throw new Error(response?.msg || '删除失败'); + throw new Error(response?.msg || "删除失败"); } } catch (error) { - console.error('删除计划失败:', error); + console.error("删除计划失败:", error); toast({ - title: '删除失败', - description: error instanceof Error ? error.message : '删除计划失败', - variant: 'destructive', + title: "删除失败", + description: error instanceof Error ? error.message : "删除计划失败", + variant: "destructive", }); } }; @@ -217,20 +254,22 @@ export default function ScenarioDetail() { const handleStatusChange = async (taskId: string, newStatus: 1 | 0) => { try { // 这里应该调用状态切换API,暂时模拟 - setTasks(prev => prev.map(task => - task.id === taskId ? { ...task, status: newStatus } : task - )); - + setTasks((prev) => + prev.map((task) => + task.id === taskId ? { ...task, status: newStatus } : task + ) + ); + toast({ - title: '状态已更新', - description: `计划已${newStatus === 1 ? '启动' : '暂停'}`, + title: "状态已更新", + description: `计划已${newStatus === 1 ? "启动" : "暂停"}`, }); } catch (error) { - console.error('状态切换失败:', error); + console.error("状态切换失败:", error); toast({ - title: '状态切换失败', - description: '请稍后重试', - variant: 'destructive', + title: "状态切换失败", + description: "请稍后重试", + variant: "destructive", }); } }; @@ -240,20 +279,22 @@ export default function ScenarioDetail() { const response = await fetchPlanDetail(taskId); if (response && response.code === 200 && response.data) { setCurrentApiSettings({ - apiKey: response.data.apiKey || 'demo-api-key-123456', - webhookUrl: response.data.textUrl?.fullUrl || `https://api.example.com/webhook/${taskId}`, + apiKey: response.data.apiKey || "demo-api-key-123456", + webhookUrl: + response.data.textUrl?.fullUrl || + `https://api.example.com/webhook/${taskId}`, taskId, }); setShowApiDialog(true); } else { - throw new Error(response?.msg || '获取API设置失败'); + throw new Error(response?.msg || "获取API设置失败"); } } catch (error) { - console.error('获取API设置失败:', error); + console.error("获取API设置失败:", error); toast({ - title: '获取API设置失败', - description: '请稍后重试', - variant: 'destructive', + title: "获取API设置失败", + description: "请稍后重试", + variant: "destructive", }); } }; @@ -261,8 +302,8 @@ export default function ScenarioDetail() { const handleCopyApiUrl = (url: string) => { navigator.clipboard.writeText(url); toast({ - title: '已复制', - description: '接口地址已复制到剪贴板', + title: "已复制", + description: "接口地址已复制到剪贴板", }); }; @@ -273,22 +314,22 @@ export default function ScenarioDetail() { const getStatusColor = (status: number) => { switch (status) { case 1: - return 'text-green-600 bg-green-50'; + return "text-green-600 bg-green-50"; case 0: - return 'text-yellow-600 bg-yellow-50'; + return "text-yellow-600 bg-yellow-50"; default: - return 'text-gray-600 bg-gray-50'; + return "text-gray-600 bg-gray-50"; } }; const getStatusText = (status: number) => { switch (status) { case 1: - return '进行中'; + return "进行中"; case 0: - return '已暂停'; + return "已暂停"; default: - return '未知'; + return "未知"; } }; @@ -297,11 +338,10 @@ export default function ScenarioDetail() { } - footer={} >
@@ -316,25 +356,20 @@ export default function ScenarioDetail() { if (error) { return ( - } + header={} footer={} >

{error}

- +
-
); } @@ -342,12 +377,7 @@ export default function ScenarioDetail() { if (!scenario) { return ( - } + header={} footer={} >
@@ -355,141 +385,153 @@ export default function ScenarioDetail() {

加载场景数据中...

-
+
); } + const handleRefresh = async () => { + setLoadingTasks(true); + await fetchPlanList(scenarioId!, 1, 20); + setLoadingTasks(false); + }; + + const filteredTasks = tasks.filter((task) => task.name.includes(searchTerm)); + return ( - - 新建计划 - - } - /> - } - footer={} - > -
-
- {/* 场景描述 */} -
-

{scenario.description}

-
- - {/* 数据统计 */} - {/*
-
-
-
-

总获客数

-

{scenario.totalCustomers}

-
- -
-
- - {scenario.growth} -
-
- -
-
-
-

今日获客

-

{scenario.todayCustomers}

-
- -
-
- 活跃计划: {scenario.totalPlans} -
-
-
*/} - - {/* 计划列表 */} -
-
-

获客计划

-
- - {tasks.length === 200 ? ( -
-
- -

暂无获客计划

-

创建您的第一个获客计划,开始获取客户

-
+ <> + - - 创建第一个计划 + + 新建计划 + + } + /> +
+
+ + setSearchTerm(e.target.value)} + /> +
+ +
+ + } + > +
+ {/* 计划列表 */} +
+ {filteredTasks.length === 0 ? ( +
+
+ +

+ 暂无获客计划 +

+

+ 创建您的第一个获客计划,开始获取客户 +

+
+
) : (
- {tasks.map((task) => ( -
+ {filteredTasks.map((task) => ( +
-

{task.name}

- - {getStatusText(task.status)} +

+ {task.name} +

+ + {getStatusText(task.status)}
- 最后更新: {task.lastUpdated} + 最后更新: {task.lastUpdated} +
+
+ + 设备: {task.stats?.devices || 0} | 获客:{" "} + {task.stats?.acquired || 0} | 添加:{" "} + {task.stats?.added || 0} +
-
- 设备: {task.stats?.devices || 0} | 获客: {task.stats?.acquired || 0} | 添加: {task.stats?.added || 0}
-
- -
- - - - - - - + +
+ + + + + + +
@@ -498,8 +540,6 @@ export default function ScenarioDetail() { )}
-
- {/* API接口设置对话框 */} {showApiDialog && (
@@ -511,7 +551,9 @@ export default function ScenarioDetail() {

计划接口配置

-

通过API接口直接导入客资到该获客计划

+

+ 通过API接口直接导入客资到该获客计划 +

@@ -560,7 +605,9 @@ export default function ScenarioDetail() {

接口地址

- POST请求 + + POST请求 +
- +
-
必要参数
+
+ 必要参数 +
-
name - 客户姓名
-
phone - 手机号码
+
+ name{" "} + - 客户姓名 +
+
+ phone{" "} + - 手机号码 +
可选参数
-
source - 来源标识
-
remark - 备注信息
-
tags - 客户标签
+
+ source{" "} + - 来源标识 +
+
+ remark{" "} + - 备注信息 +
+
+ tags - + 客户标签 +
@@ -601,4 +667,4 @@ export default function ScenarioDetail() { )} ); -} \ No newline at end of file +} diff --git a/nkebao/src/pages/scenarios/Scenarios.tsx b/nkebao/src/pages/scenarios/Scenarios.tsx index 721fd198..6fe27e81 100644 --- a/nkebao/src/pages/scenarios/Scenarios.tsx +++ b/nkebao/src/pages/scenarios/Scenarios.tsx @@ -1,11 +1,11 @@ -import React, { useEffect, useState, useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Plus, TrendingUp, Loader2 } from 'lucide-react'; -import UnifiedHeader from '@/components/UnifiedHeader'; -import Layout from '@/components/Layout'; -import BottomNav from '@/components/BottomNav'; -import { fetchScenes, type SceneItem } from '@/api/scenarios'; -import '@/components/Layout.css'; +import React, { useEffect, useState, useMemo } from "react"; +import { useNavigate } from "react-router-dom"; +import { Plus, TrendingUp, Loader2 } from "lucide-react"; +import UnifiedHeader from "@/components/UnifiedHeader"; +import Layout from "@/components/Layout"; +import BottomNav from "@/components/BottomNav"; +import { fetchScenes, type SceneItem } from "@/api/scenarios"; +import "@/components/Layout.css"; interface Scenario { id: string; @@ -21,45 +21,54 @@ export default function Scenarios() { const navigate = useNavigate(); const [scenarios, setScenarios] = useState([]); const [loading, setLoading] = useState(true); - const [error, setError] = useState(''); + const [error, setError] = useState(""); // 场景描述映射 - const scenarioDescriptions: Record = useMemo(() => ({ - douyin: '通过抖音平台进行精准获客', - xiaohongshu: '利用小红书平台进行内容营销获客', - gongzhonghao: '通过微信公众号进行获客', - haibao: '通过海报分享进行获客', - phone: '通过电话营销进行获客', - weixinqun: '通过微信群进行获客', - payment: '通过付款码进行获客', - api: '通过API接口进行获客', - }), []); + const scenarioDescriptions: Record = useMemo( + () => ({ + douyin: "通过抖音平台进行精准获客", + xiaohongshu: "利用小红书平台进行内容营销获客", + gongzhonghao: "通过微信公众号进行获客", + haibao: "通过海报分享进行获客", + phone: "通过电话营销进行获客", + weixinqun: "通过微信群进行获客", + payment: "通过付款码进行获客", + api: "通过API接口进行获客", + }), + [] + ); useEffect(() => { const fetchScenarios = async () => { setLoading(true); - setError(''); - + setError(""); + try { const response = await fetchScenes({ page: 1, limit: 20 }); - + if (response && response.code === 200 && response.data) { // 转换API数据为前端需要的格式 - const transformedScenarios: Scenario[] = response.data.map((item: SceneItem) => ({ - id: item.id.toString(), - name: item.name, - image: item.image|| 'https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-api.png', - description: scenarioDescriptions[item.name.toLowerCase()] || '通过该平台进行获客', - count: Math.floor(Math.random() * 200) + 50, // 模拟今日数据 - growth: `+${Math.floor(Math.random() * 20) + 5}%`, // 模拟增长率 - status: item.status === 1 ? 'active' : 'inactive', - })); - + const transformedScenarios: Scenario[] = response.data.map( + (item: SceneItem) => ({ + id: item.id.toString(), + name: item.name, + image: + item.image || + "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-api.png", + description: + scenarioDescriptions[item.name.toLowerCase()] || + "通过该平台进行获客", + count: Math.floor(Math.random() * 200) + 50, // 模拟今日数据 + growth: `+${Math.floor(Math.random() * 20) + 5}%`, // 模拟增长率 + status: item.status === 1 ? "active" : "inactive", + }) + ); + setScenarios(transformedScenarios); - } + } } catch (error) { - console.error('获取场景数据失败:', error); - setError('获取场景数据失败,请稍后重试'); + console.error("获取场景数据失败:", error); + setError("获取场景数据失败,请稍后重试"); } finally { setLoading(false); } @@ -68,23 +77,20 @@ export default function Scenarios() { fetchScenarios(); }, [scenarioDescriptions]); - const handleScenarioClick = (scenarioId: string,scenarioName:string) => { - navigate(`/scenarios/${scenarioId}?name=${encodeURIComponent(scenarioName)}`); + const handleScenarioClick = (scenarioId: string, scenarioName: string) => { + navigate( + `/scenarios/list/${scenarioId}/${encodeURIComponent(scenarioName)}` + ); }; const handleNewPlan = () => { - navigate('/scenarios/new'); + navigate("/scenarios/new"); }; if (loading) { return ( - } + header={} footer={} >
@@ -100,18 +106,13 @@ export default function Scenarios() { if (error && scenarios.length === 0) { return ( - } + header={} footer={} >

{error}

-
)} - +
{scenarios.map((scenario) => (
handleScenarioClick(scenario.id,scenario.name)} + onClick={() => handleScenarioClick(scenario.id, scenario.name)} >
- {scenario.name} { // 图片加载失败时使用默认图标 - e.currentTarget.src = 'https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-api.png'; + e.currentTarget.src = + "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-api.png"; }} />
-

{scenario.name}

+

+ {scenario.name} +

{scenario.description && ( -

{scenario.description}

+

+ {scenario.description} +

)}
今日: @@ -190,4 +196,4 @@ export default function Scenarios() {
); -} \ No newline at end of file +} diff --git a/nkebao/src/pages/scenarios/new/page.tsx b/nkebao/src/pages/scenarios/new/page.tsx index ec7e5ba4..b31c7488 100644 --- a/nkebao/src/pages/scenarios/new/page.tsx +++ b/nkebao/src/pages/scenarios/new/page.tsx @@ -2,7 +2,7 @@ import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { ChevronLeft } from "lucide-react"; import { Button } from "@/components/ui/button"; -import { Message } from "tdesign-mobile-react"; +import { Toast } from "tdesign-mobile-react"; import { Steps, StepItem } from "tdesign-mobile-react"; import { BasicSettings } from "./steps/BasicSettings"; import { FriendRequestSettings } from "./steps/FriendRequestSettings"; @@ -55,20 +55,28 @@ export default function NewPlan() { // 处理保存 const handleSave = async () => { - console.log("保存数据:", formData); - try { - await createScenarioPlan(formData); - Message.success("获客计划已创建"); - // router("/scenarios"); + const result = await createScenarioPlan(formData); + console.log(result); + if (result.code === 200) { + Toast({ message: "获客计划已创建", theme: "success" }); + // router("/scenarios/1?name=海报获客"); + } else { + Toast({ + message: result.msg, + theme: "error", + }); + } } catch (error) { - Message.error( - error instanceof Error - ? error.message - : typeof error === "string" - ? error - : "创建计划失败,请重试" - ); + Toast({ + message: + error instanceof Error + ? error.message + : typeof error === "string" + ? error + : "创建计划失败,请重试", + theme: "error", + }); } };