From df72e84ea1beed8019a2da2b2f7c1c1c36d04b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Tue, 15 Jul 2025 16:08:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=AC=E6=AC=A1=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E5=A6=82=E4=B8=8B=20?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nkebao/src/api/scenarios.ts | 2 +- nkebao/src/components/UploadImage.tsx | 13 +- nkebao/src/pages/content/materials/New.tsx | 19 +- nkebao/src/pages/scenarios/ScenarioDetail.tsx | 82 ++-- .../pages/scenarios/douyin/DouyinScenario.tsx | 249 ---------- .../gongzhonghao/GongzhonghaoScenario.tsx | 442 ------------------ .../pages/scenarios/haibao/HaibaoScenario.tsx | 249 ---------- .../xiaohongshu/XiaohongshuScenario.tsx | 244 ---------- 8 files changed, 38 insertions(+), 1262 deletions(-) delete mode 100644 nkebao/src/pages/scenarios/douyin/DouyinScenario.tsx delete mode 100644 nkebao/src/pages/scenarios/gongzhonghao/GongzhonghaoScenario.tsx delete mode 100644 nkebao/src/pages/scenarios/haibao/HaibaoScenario.tsx delete mode 100644 nkebao/src/pages/scenarios/xiaohongshu/XiaohongshuScenario.tsx diff --git a/nkebao/src/api/scenarios.ts b/nkebao/src/api/scenarios.ts index c926606b..f64ac2b2 100644 --- a/nkebao/src/api/scenarios.ts +++ b/nkebao/src/api/scenarios.ts @@ -38,7 +38,7 @@ export interface Plan { export interface Task { id: string; name: string; - status: "running" | "paused" | "completed"; + status: number; stats: { devices: number; acquired: number; diff --git a/nkebao/src/components/UploadImage.tsx b/nkebao/src/components/UploadImage.tsx index 489b8137..8b4d84d9 100644 --- a/nkebao/src/components/UploadImage.tsx +++ b/nkebao/src/components/UploadImage.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { Upload } from 'tdesign-mobile-react'; import type { UploadFile as TDesignUploadFile } from 'tdesign-mobile-react/es/upload/type'; import { uploadImage } from '@/api/upload'; @@ -12,14 +12,6 @@ interface UploadImageProps { } const UploadImage: React.FC = ({ value = [], onChange, ...props }) => { - // 受控 files 状态 - const [files, setFiles] = useState(value.map(url => ({ url }))); - - // value 变化时同步 files - useEffect(() => { - setFiles(value.map(url => ({ url }))); - }, [value]); - // 处理上传 const requestMethod = async (file: TDesignUploadFile) => { try { @@ -42,14 +34,13 @@ const UploadImage: React.FC = ({ value = [], onChange, ...prop // 处理文件变更 const handleChange = (newFiles: TDesignUploadFile[]) => { - setFiles(newFiles); const urls = newFiles.map(f => f.url).filter((url): url is string => Boolean(url)); onChange?.(urls); }; return ( ({ url }))} requestMethod={requestMethod} onChange={handleChange} multiple diff --git a/nkebao/src/pages/content/materials/New.tsx b/nkebao/src/pages/content/materials/New.tsx index 57f4c84d..f7e7b251 100644 --- a/nkebao/src/pages/content/materials/New.tsx +++ b/nkebao/src/pages/content/materials/New.tsx @@ -9,10 +9,6 @@ import { toast } from '@/components/ui/toast'; import Layout from '@/components/Layout'; import UnifiedHeader from '@/components/UnifiedHeader'; import { get, post } from '@/api/request'; -import { UploadCloud } from 'lucide-react'; -import { Upload } from 'tdesign-mobile-react'; -import type { UploadFile as TDesignUploadFile } from 'tdesign-mobile-react/es/upload/type'; -import { uploadImage } from '@/api/upload'; import UploadImage from '@/components/UploadImage'; import UploadVideo from '@/components/UploadVideo'; @@ -32,7 +28,7 @@ export default function NewMaterial() { const [images, setImages] = useState([]); const [isFirstLoad, setIsFirstLoad] = useState(true); // 优化图片上传逻辑,确保每次选择图片后立即上传并回显 - const [uploadFiles, setUploadFiles] = useState([]); + // 判断模式并拉取详情 useEffect(() => { @@ -121,15 +117,7 @@ export default function NewMaterial() { } }; - // 上传图片,接入接口 - const handleUploadImage = async (file: File) => { - try { - const url = await uploadImage(file); - setImages(prev => [...prev, url]); - } catch (e: any) { - toast({ title: '上传失败', description: e.message || '图片上传失败', variant: 'destructive' }); - } - }; + // 移除未用的 handleUploadImage 及 uploadImage 相关代码 return ( { setCoverImage(urls[0]); - setUploadFiles(urls.map(url => ({ url }))); }} max={1} accept="image/*" @@ -237,7 +224,6 @@ export default function NewMaterial() { value={images} onChange={urls => { setImages(urls); - setUploadFiles(urls.map(url => ({ url }))); }} max={9} accept="image/*" @@ -255,7 +241,6 @@ export default function NewMaterial() { value={images} onChange={urls => { setImages(urls); - setUploadFiles(urls.map(url => ({ url }))); }} max={9} accept="image/*" diff --git a/nkebao/src/pages/scenarios/ScenarioDetail.tsx b/nkebao/src/pages/scenarios/ScenarioDetail.tsx index bb4a40ba..2059daeb 100644 --- a/nkebao/src/pages/scenarios/ScenarioDetail.tsx +++ b/nkebao/src/pages/scenarios/ScenarioDetail.tsx @@ -91,23 +91,16 @@ export default function ScenarioDetail() { setTasks([]); } - // 计算统计数据 - 添加安全检查 - const planList = response?.data?.list || []; - const totalCustomers = planList.reduce((sum, task) => { - return sum + (task.stats?.acquired || 0); - }, 0); - const todayCustomers = Math.floor(totalCustomers * 0.1); // 模拟今日数据 - // 构建场景数据(无论是否有计划都要创建) const scenarioData: ScenarioData = { id: scenarioId, name: getScenarioName(), image: '', // 可以根据需要设置图片 description: getScenarioDescription(scenarioId), - totalPlans: planList.length, - totalCustomers, - todayCustomers, - growth: `+${Math.floor(Math.random() * 20) + 5}%`, + totalPlans: response?.data?.list?.length || 0, + totalCustomers: 0, // 移除统计 + todayCustomers: 0, // 移除统计 + growth: '', // 移除增长 }; setScenario(scenarioData); @@ -122,7 +115,7 @@ export default function ScenarioDetail() { totalPlans: 0, totalCustomers: 0, todayCustomers: 0, - growth: '+0%', + growth: '', }; setScenario(scenarioData); setTasks([]); @@ -148,21 +141,16 @@ export default function ScenarioDetail() { // 更新场景数据中的名称 useEffect(() => { - if (scenario) { - setScenario(prev => prev ? { - ...prev, - name: (() => { - const urlName = searchParams.get('name'); - if (urlName) return urlName; - return getChannelName(scenarioId || ''); - })() - } : null); - } - }, [searchParams, scenarioId, scenario]); + setScenario(prev => prev ? { + ...prev, + name: (() => { + const urlName = searchParams.get('name'); + if (urlName) return urlName; + return getChannelName(scenarioId || ''); + })() + } : null); + }, [searchParams, scenarioId]); - // const handleEditPlan = (taskId: string) => { - // navigate(`/scenarios/${scenarioId}/edit/${taskId}`); - // }; const handleCopyPlan = async (taskId: string) => { const taskToCopy = tasks.find((task) => task.id === taskId); @@ -170,7 +158,7 @@ export default function ScenarioDetail() { try { const response = await copyPlan(taskId); - if (response && response.code === 0) { + if (response && response.code === 200) { toast({ title: '计划已复制', description: `已成功复制"${taskToCopy.name}"`, @@ -178,7 +166,7 @@ export default function ScenarioDetail() { // 重新加载数据 const refreshResponse = await fetchPlanList(scenarioId!, 1, 20); - if (refreshResponse && refreshResponse.code === 0 && refreshResponse.data) { + if (refreshResponse && refreshResponse.code === 200 && refreshResponse.data) { setTasks(refreshResponse.data.list); } } else { @@ -202,7 +190,7 @@ export default function ScenarioDetail() { try { const response = await deletePlan(taskId); - if (response && response.code === 0) { + if (response && response.code === 200) { toast({ title: '计划已删除', description: `已成功删除"${taskToDelete.name}"`, @@ -210,7 +198,7 @@ export default function ScenarioDetail() { // 重新加载数据 const refreshResponse = await fetchPlanList(scenarioId!, 1, 20); - if (refreshResponse && refreshResponse.code === 0 && refreshResponse.data) { + if (refreshResponse && refreshResponse.code === 200 && refreshResponse.data) { setTasks(refreshResponse.data.list); } } else { @@ -226,7 +214,7 @@ export default function ScenarioDetail() { } }; - const handleStatusChange = async (taskId: string, newStatus: 'running' | 'paused') => { + const handleStatusChange = async (taskId: string, newStatus: 1 | 0) => { try { // 这里应该调用状态切换API,暂时模拟 setTasks(prev => prev.map(task => @@ -235,7 +223,7 @@ export default function ScenarioDetail() { toast({ title: '状态已更新', - description: `计划已${newStatus === 'running' ? '启动' : '暂停'}`, + description: `计划已${newStatus === 1 ? '启动' : '暂停'}`, }); } catch (error) { console.error('状态切换失败:', error); @@ -250,7 +238,7 @@ export default function ScenarioDetail() { const handleOpenApiSettings = async (taskId: string) => { try { const response = await fetchPlanDetail(taskId); - if (response && response.code === 0 && response.data) { + 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}`, @@ -282,27 +270,23 @@ export default function ScenarioDetail() { navigate(`/scenarios/new?scenario=${scenarioId}`); }; - const getStatusColor = (status: string) => { + const getStatusColor = (status: number) => { switch (status) { - case 'running': + case 1: return 'text-green-600 bg-green-50'; - case 'paused': + case 0: return 'text-yellow-600 bg-yellow-50'; - case 'completed': - return 'text-gray-600 bg-gray-50'; default: return 'text-gray-600 bg-gray-50'; } }; - const getStatusText = (status: string) => { + const getStatusText = (status: number) => { switch (status) { - case 'running': + case 1: return '进行中'; - case 'paused': + case 0: return '已暂停'; - case 'completed': - return '已完成'; default: return '未知'; } @@ -403,7 +387,7 @@ export default function ScenarioDetail() { {/* 数据统计 */} -
+ {/*
@@ -430,7 +414,7 @@ export default function ScenarioDetail() { 活跃计划: {scenario.totalPlans}
-
+
*/} {/* 计划列表 */}
@@ -438,7 +422,7 @@ export default function ScenarioDetail() {

获客计划

- {tasks.length === 0 ? ( + {tasks.length === 200 ? (
@@ -476,14 +460,14 @@ export default function ScenarioDetail() {
- } - /> - } - > -
-
- {tasks.map((task) => ( -
- {/* 任务头部 */} -
-
-
-
- {getStatusIcon(task.status)} -
-
-

{task.name}

-
- - {getStatusText(task.status)} - - 最后更新: {task.lastUpdated} -
-
-
-
- - -
-
-
- - {/* 统计信息 */} -
-
-
-
- - 设备数 -
-
{task.stats.devices}
-
-
-
- - 已获客 -
-
{task.stats.acquired}
-
-
-
- - 已添加 -
-
{task.stats.added}
-
-
- - {/* 趋势图表 */} -
-

7天趋势

-
- {task.trend.map((item, index) => ( -
-
- {item.date} -
- ))} -
-
- - {/* 执行信息 */} -
-
- 执行时间: {task.executionTime} - {task.nextExecutionTime} -
-
-
-
- ))} - - {/* 设备树图表 */} -
-

设备分布

-
- -

设备树图表功能开发中...

-
-
-
-
- - ); -} \ No newline at end of file diff --git a/nkebao/src/pages/scenarios/gongzhonghao/GongzhonghaoScenario.tsx b/nkebao/src/pages/scenarios/gongzhonghao/GongzhonghaoScenario.tsx deleted file mode 100644 index 094ff610..00000000 --- a/nkebao/src/pages/scenarios/gongzhonghao/GongzhonghaoScenario.tsx +++ /dev/null @@ -1,442 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Copy, Link, HelpCircle, Shield, Plus } from 'lucide-react'; -import { Button } from '@/components/ui/button'; -import { useToast } from '@/components/ui/toast'; -import { ScenarioAcquisitionCard } from '@/components/ScenarioAcquisitionCard'; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogDescription, - DialogFooter, -} from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; -import PageHeader from '@/components/PageHeader'; -import Layout from '@/components/Layout'; -import '@/components/Layout.css'; -import { - fetchSceneName, - fetchPlanList, - copyPlan, - deletePlan, - type Task -} from '@/api/scenarios'; -import { log } from 'console'; - -interface DeviceStats { - active: number; -} - -const API_BASE_URL = process.env.REACT_APP_API_BASE_URL || 'http://yishi.com'; - -// API文档提示组件 -function ApiDocumentationTooltip() { - return ( - - - - - - -

- 计划接口允许您通过API将外部系统的客户数据直接导入到存客宝。支持多种编程语言和第三方平台集成。 -

-
-
-
- ); -} - -export default function GongzhonghaoScenario() { - const navigate = useNavigate(); - const { toast } = useToast(); - const channel = "gongzhonghao"; - const [channelName, setChannelName] = useState(""); - - // 1. tasks 初始值设为 [] - const [tasks, setTasks] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(""); - const [page, setPage] = useState(1); - const [pageSize, setPageSize] = useState(10); - const [total, setTotal] = useState(0); - - useEffect(() => { - fetchSceneName(channel) - .then((res) => { - if (res.code === 200 && res.data?.name) { - setChannelName(res.data.name); - } else { - setChannelName(channel); - } - }) - .catch(() => setChannelName(channel)); - }, [channel]); - - // 抽出请求列表的函数 - const fetchTasks = () => { - setLoading(true); - setError(""); - fetchPlanList(channel, page, pageSize) - .then((res) => { - if (res.code === 200 && res.data && Array.isArray(res.data.list)) { - setTasks(res.data.list); - setTotal(res.data.total || 0); - } else { - setError(res.msg || "接口返回异常"); - } - }) - .catch((err: any) => setError(err?.message || "接口请求失败")) - .finally(() => setLoading(false)); - }; - - useEffect(() => { - fetchTasks(); - }, [channel, page, pageSize]); - - const [deviceStats, setDeviceStats] = useState({ - active: 5, - }); - - const [showApiDialog, setShowApiDialog] = useState(false); - const [currentApiSettings, setCurrentApiSettings] = useState({ - apiKey: "", - webhookUrl: "", - taskId: "", - fullUrl: "" - }); - - const handleEditPlan = (taskId: string) => { - navigate(`/scenarios/${channel}/edit/${taskId}`); - }; - - const handleCopyPlan = (taskId: string) => { - const taskToCopy = tasks.find((task) => task.id === taskId); - if (!taskToCopy) return; - copyPlan(taskId) - .then((res) => { - if (res.code === 200) { - toast({ - title: "计划已复制", - description: `已成功复制"${taskToCopy.name}"`, - variant: "default", - }); - setPage(1); - fetchTasks(); - } else { - toast({ - title: "复制失败", - description: res.msg || "复制计划失败,请重试", - variant: "destructive", - }); - } - }) - .catch((err: any) => { - toast({ - title: "复制失败", - description: err?.message || "复制计划失败,请重试", - variant: "destructive", - }); - }); - }; - - const handleDeletePlan = (taskId: string) => { - const taskToDelete = tasks.find((t) => t.id === taskId); - if (!taskToDelete) return; - deletePlan(taskId) - .then((res) => { - if (res.code === 200) { - setTasks(tasks.filter((t) => t.id !== taskId)); - toast({ - title: "计划已删除", - description: `已成功删除"${taskToDelete.name}"`, - variant: "default", - }); - } else { - toast({ - title: "删除失败", - description: res.msg || "删除计划失败,请重试", - variant: "destructive", - }); - } - }) - .catch((err: any) => { - toast({ - title: "删除失败", - description: err?.message || "删除计划失败,请重试", - variant: "destructive", - }); - }); - }; - - const handleStatusChange = (taskId: string, newStatus: "running" | "paused") => { - setTasks(tasks.map((task) => (task.id === taskId ? { ...task, status: newStatus } : task))); - - toast({ - title: newStatus === "running" ? "计划已启动" : "计划已暂停", - description: `已${newStatus === "running" ? "启动" : "暂停"}获客计划`, - variant: "default", - }); - }; - - const handleOpenApiSettings = (taskId: string) => { - const task = tasks.find((t) => t.id === taskId); - if (task) { - // 直接使用列表数据,不调用详情API - setCurrentApiSettings({ - apiKey: `api_key_${taskId}`, // 使用任务ID生成API密钥 - webhookUrl: `${API_BASE_URL}/v1/api/scenarios/${taskId}`, - fullUrl: `${API_BASE_URL}/v1/api/scenarios/${taskId}/text`, - taskId, - }); - setShowApiDialog(true); - } - }; - - const handleCopyApiUrl = (url: string, withParams = false) => { - let copyUrl = url; - if (withParams) { - copyUrl = `${url}?name=张三&phone=13800138000&source=外部系统&remark=测试数据`; - } - navigator.clipboard.writeText(copyUrl); - toast({ - title: "已复制", - description: withParams ? "接口地址(含示例参数)已复制到剪贴板" : "接口地址已复制到剪贴板", - variant: "default", - }); - }; - - const handleCreateNewPlan = () => { - navigate(`/scenarios/new?type=${channel}`); - }; - - return ( - - - 新建计划 - - } - /> - } - > -
-
-
- {loading ? ( -
加载中...
- ) : error ? ( -
{error}
- ) : tasks.length > 0 ? ( - <> - {tasks.map((task) => ( -
- handleEditPlan(task.id)} - onCopy={handleCopyPlan} - onDelete={handleDeletePlan} - onStatusChange={handleStatusChange} - onOpenSettings={handleOpenApiSettings} - /> -
- ))} -
- - 第 {page} 页 / 共 {Math.max(1, Math.ceil(total / pageSize))} 页 - -
- - ) : ( -
-
暂无获客计划
- -
- )} -
-
-
- {/* API接口设置对话框 */} - - - -
- 计划接口 - -
- 使用此接口直接导入客资到该获客计划,支持多种编程语言。 -
- -
- {/* API密钥部分 */} -
-
- - 用于接口身份验证 -
-
-
- - -
-
-
- - {/* 接口地址部分 */} -
-
- - -
-
-
- - -
-
-
-

- 必要参数:name(姓名)、phone(电话) -
- 可选参数:source(来源)、remark(备注)、tags(标签) -

-
-
- - {/* 接口文档部分 */} -
-
- -
-
-
- - -
- - - -
-
-
-
- - {/* 快速测试部分 */} -
-
- -
-
-

使用以下URL可以快速测试接口是否正常工作:

-
- {`${currentApiSettings.webhookUrl}?${currentApiSettings.fullUrl}`} -
-
-
-
- - -
- - - 接口安全加密传输 - -
- -
-
-
-
- ); -} diff --git a/nkebao/src/pages/scenarios/haibao/HaibaoScenario.tsx b/nkebao/src/pages/scenarios/haibao/HaibaoScenario.tsx deleted file mode 100644 index d6fee539..00000000 --- a/nkebao/src/pages/scenarios/haibao/HaibaoScenario.tsx +++ /dev/null @@ -1,249 +0,0 @@ -import React, { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Plus, Copy, Trash2, Play, Pause, TrendingUp, Users, Clock, Image } from 'lucide-react'; -import PageHeader from '@/components/PageHeader'; -import { useToast } from '@/components/ui/toast'; -import Layout from '@/components/Layout'; -import '@/components/Layout.css'; - -interface Task { - id: string; - name: string; - status: "running" | "paused" | "completed"; - stats: { - devices: number; - acquired: number; - added: number; - }; - lastUpdated: string; - executionTime: string; - nextExecutionTime: string; - trend: { date: string; customers: number }[]; - dailyData: { date: string; acquired: number; added: number }[]; -} - -export default function HaibaoScenario() { - const navigate = useNavigate(); - const { toast } = useToast(); - const channel = "haibao"; - - const [tasks, setTasks] = useState([ - { - id: "1", - name: "海报分享获客计划", - status: "running", - stats: { - devices: 5, - acquired: 89, - added: 62, - }, - lastUpdated: "2024-03-18 17:30", - executionTime: "2024-03-18 17:30", - nextExecutionTime: "预计15分钟后", - trend: Array.from({ length: 7 }, (_, i) => ({ - date: `3月${String(i + 12)}日`, - customers: Math.floor(Math.random() * 20) + 10, - })), - dailyData: [ - { date: "3/12", acquired: 25, added: 18 }, - { date: "3/13", acquired: 32, added: 22 }, - { date: "3/14", acquired: 18, added: 12 }, - { date: "3/15", acquired: 28, added: 19 }, - { date: "3/16", acquired: 35, added: 24 }, - { date: "3/17", acquired: 22, added: 15 }, - { date: "3/18", acquired: 30, added: 21 }, - ], - }, - ]); - - const handleCopyPlan = (taskId: string) => { - const taskToCopy = tasks.find((task) => task.id === taskId); - if (taskToCopy) { - const newTask = { - ...taskToCopy, - id: `${Date.now()}`, - name: `${taskToCopy.name} (副本)`, - status: "paused" as const, - }; - setTasks([...tasks, newTask]); - toast({ - title: "计划已复制", - description: `已成功复制"${taskToCopy.name}"`, - }); - } - }; - - const handleDeletePlan = (taskId: string) => { - const taskToDelete = tasks.find((t) => t.id === taskId); - if (taskToDelete) { - setTasks(tasks.filter((t) => t.id !== taskId)); - toast({ - title: "计划已删除", - description: `已成功删除"${taskToDelete.name}"`, - }); - } - }; - - const getStatusColor = (status: string) => { - switch (status) { - case 'running': - return 'text-green-600 bg-green-50'; - case 'paused': - return 'text-yellow-600 bg-yellow-50'; - case 'completed': - return 'text-gray-600 bg-gray-50'; - default: - return 'text-gray-600 bg-gray-50'; - } - }; - - const getStatusText = (status: string) => { - switch (status) { - case 'running': - return '进行中'; - case 'paused': - return '已暂停'; - case 'completed': - return '已完成'; - default: - return '未知'; - } - }; - - const getStatusIcon = (status: string) => { - switch (status) { - case 'running': - return ; - case 'paused': - return ; - case 'completed': - return ; - default: - return ; - } - }; - - return ( - navigate('/scenarios/new?scenario=haibao')} - className="flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm" - > - - 新建计划 - - } - /> - } - > -
-
- {tasks.map((task) => ( -
- {/* 任务头部 */} -
-
-
-
- {getStatusIcon(task.status)} -
-
-

{task.name}

-
- - {getStatusText(task.status)} - - 最后更新: {task.lastUpdated} -
-
-
-
- - -
-
-
- - {/* 统计信息 */} -
-
-
-
- - 设备数 -
-
{task.stats.devices}
-
-
-
- - 已获客 -
-
{task.stats.acquired}
-
-
-
- - 已添加 -
-
{task.stats.added}
-
-
- - {/* 趋势图表 */} -
-

7天趋势

-
- {task.trend.map((item, index) => ( -
-
- {item.date} -
- ))} -
-
- - {/* 执行信息 */} -
-
- 执行时间: {task.executionTime} - {task.nextExecutionTime} -
-
-
-
- ))} - - {/* 海报管理 */} -
-

海报管理

-
- -

海报管理功能开发中...

-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/nkebao/src/pages/scenarios/xiaohongshu/XiaohongshuScenario.tsx b/nkebao/src/pages/scenarios/xiaohongshu/XiaohongshuScenario.tsx deleted file mode 100644 index 4f400497..00000000 --- a/nkebao/src/pages/scenarios/xiaohongshu/XiaohongshuScenario.tsx +++ /dev/null @@ -1,244 +0,0 @@ -import React, { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Plus, Copy, Trash2, Play, Pause, TrendingUp, Users, Clock } from 'lucide-react'; -import PageHeader from '@/components/PageHeader'; -import { useToast } from '@/components/ui/toast'; - -interface Task { - id: string; - name: string; - status: "running" | "paused" | "completed"; - stats: { - devices: number; - acquired: number; - added: number; - }; - lastUpdated: string; - executionTime: string; - nextExecutionTime: string; - trend: { date: string; customers: number }[]; - dailyData: { date: string; acquired: number; added: number }[]; -} - -export default function XiaohongshuScenario() { - const navigate = useNavigate(); - const { toast } = useToast(); - const channel = "xiaohongshu"; - - const [tasks, setTasks] = useState([ - { - id: "1", - name: "小红书内容营销计划", - status: "running", - stats: { - devices: 2, - acquired: 28, - added: 19, - }, - lastUpdated: "2024-03-18 14:20", - executionTime: "2024-03-18 14:20", - nextExecutionTime: "预计45分钟后", - trend: Array.from({ length: 7 }, (_, i) => ({ - date: `3月${String(i + 12)}日`, - customers: Math.floor(Math.random() * 8) + 3, - })), - dailyData: [ - { date: "3/12", acquired: 8, added: 5 }, - { date: "3/13", acquired: 12, added: 8 }, - { date: "3/14", acquired: 6, added: 4 }, - { date: "3/15", acquired: 9, added: 6 }, - { date: "3/16", acquired: 11, added: 7 }, - { date: "3/17", acquired: 7, added: 5 }, - { date: "3/18", acquired: 10, added: 7 }, - ], - }, - ]); - - const handleCopyPlan = (taskId: string) => { - const taskToCopy = tasks.find((task) => task.id === taskId); - if (taskToCopy) { - const newTask = { - ...taskToCopy, - id: `${Date.now()}`, - name: `${taskToCopy.name} (副本)`, - status: "paused" as const, - }; - setTasks([...tasks, newTask]); - toast({ - title: "计划已复制", - description: `已成功复制"${taskToCopy.name}"`, - }); - } - }; - - const handleDeletePlan = (taskId: string) => { - const taskToDelete = tasks.find((t) => t.id === taskId); - if (taskToDelete) { - setTasks(tasks.filter((t) => t.id !== taskId)); - toast({ - title: "计划已删除", - description: `已成功删除"${taskToDelete.name}"`, - }); - } - }; - - const getStatusColor = (status: string) => { - switch (status) { - case 'running': - return 'text-green-600 bg-green-50'; - case 'paused': - return 'text-yellow-600 bg-yellow-50'; - case 'completed': - return 'text-gray-600 bg-gray-50'; - default: - return 'text-gray-600 bg-gray-50'; - } - }; - - const getStatusText = (status: string) => { - switch (status) { - case 'running': - return '进行中'; - case 'paused': - return '已暂停'; - case 'completed': - return '已完成'; - default: - return '未知'; - } - }; - - const getStatusIcon = (status: string) => { - switch (status) { - case 'running': - return ; - case 'paused': - return ; - case 'completed': - return ; - default: - return ; - } - }; - - return ( -
- navigate('/scenarios/new?scenario=xiaohongshu')} - className="flex items-center px-3 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700 transition-colors text-sm" - > - - 新建计划 - - } - /> - - {/* 添加pt-16来避免被固定导航栏遮挡 */} -
- {tasks.map((task) => ( -
- {/* 任务头部 */} -
-
-
-
- {getStatusIcon(task.status)} -
-
-

{task.name}

-
- - {getStatusText(task.status)} - - 最后更新: {task.lastUpdated} -
-
-
-
- - -
-
-
- - {/* 统计信息 */} -
-
-
-
- - 设备数 -
-
{task.stats.devices}
-
-
-
- - 已获客 -
-
{task.stats.acquired}
-
-
-
- - 已添加 -
-
{task.stats.added}
-
-
- - {/* 趋势图表 */} -
-

7天趋势

-
- {task.trend.map((item, index) => ( -
-
- {item.date} -
- ))} -
-
- - {/* 执行信息 */} -
-
- 执行时间: {task.executionTime} - {task.nextExecutionTime} -
-
-
-
- ))} - - {/* 内容分析 */} -
-

内容分析

-
- -

内容分析功能开发中...

-
-
-
-
- ); -} \ No newline at end of file