From c6107f56af56f27a79d0624bdd95805dab01f341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=B0=B8=E5=B9=B3?= Date: Wed, 9 Jul 2025 18:08:17 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E7=BC=93=E5=AD=98=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nkebao/src/App.tsx | 2 + nkebao/src/api/autoLike.ts | 2 +- nkebao/src/api/momentsSync.ts | 2 +- .../pages/workspace/moments-sync/Detail.tsx | 178 ++++++++++++++- .../src/pages/workspace/moments-sync/edit.tsx | 213 ++++++++++++++++++ .../pages/workspace/moments-sync/index.tsx | 5 + 6 files changed, 397 insertions(+), 5 deletions(-) create mode 100644 nkebao/src/pages/workspace/moments-sync/edit.tsx diff --git a/nkebao/src/App.tsx b/nkebao/src/App.tsx index d1725282a..5c88d4c4c 100644 --- a/nkebao/src/App.tsx +++ b/nkebao/src/App.tsx @@ -21,6 +21,7 @@ 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 EditMomentsSync from './pages/workspace/moments-sync/edit'; import AIAssistant from './pages/workspace/ai-assistant/AIAssistant'; import TrafficDistribution from './pages/workspace/traffic-distribution/TrafficDistribution'; import TrafficDistributionDetail from './pages/workspace/traffic-distribution/Detail'; @@ -65,6 +66,7 @@ function App() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/nkebao/src/api/autoLike.ts b/nkebao/src/api/autoLike.ts index e163692db..aee536a93 100644 --- a/nkebao/src/api/autoLike.ts +++ b/nkebao/src/api/autoLike.ts @@ -26,7 +26,7 @@ export async function fetchAutoLikeTasks(): Promise { // 获取单个任务详情 export async function fetchAutoLikeTaskDetail(id: string): Promise { try { - const res = await get>(`/v1/workbench/detail/${id}`); + const res = await get>(`/v1/workbench/detail?id=${id}`); if (res.code === 200 && res.data) { return res.data; } diff --git a/nkebao/src/api/momentsSync.ts b/nkebao/src/api/momentsSync.ts index b481709bf..4d7ab0d9b 100644 --- a/nkebao/src/api/momentsSync.ts +++ b/nkebao/src/api/momentsSync.ts @@ -26,7 +26,7 @@ export async function fetchMomentsSyncTasks(): Promise { // 获取单个任务详情 export async function fetchMomentsSyncTaskDetail(id: string): Promise { try { - const res = await get>(`/v1/workbench/detail/${id}`); + const res = await get>(`/v1/workbench/detail?id=${id}`); if (res.code === 200 && res.data) { return res.data; } diff --git a/nkebao/src/pages/workspace/moments-sync/Detail.tsx b/nkebao/src/pages/workspace/moments-sync/Detail.tsx index f67a5ab5d..b05363221 100644 --- a/nkebao/src/pages/workspace/moments-sync/Detail.tsx +++ b/nkebao/src/pages/workspace/moments-sync/Detail.tsx @@ -1,7 +1,179 @@ -import React from 'react'; -import { useParams } from 'react-router-dom'; +import React, { useState, useEffect } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import { Button } from '@/components/ui/button'; +import { Card } from '@/components/ui/card'; +import { Badge } from '@/components/ui/badge'; +import { Switch } from '@/components/ui/switch'; +import { useToast } from '@/components/ui/toast'; +import { + fetchMomentsSyncTaskDetail, + toggleMomentsSyncTask, + syncMoments +} from '@/api/momentsSync'; +import { MomentsSyncTask } from '@/types/moments-sync'; +import { ChevronLeft, Edit2, RefreshCw } from 'lucide-react'; export default function MomentsSyncDetail() { const { id } = useParams(); - return
朋友圈同步详情页,当前ID: {id}
; + const navigate = useNavigate(); + const { toast } = useToast(); + const [task, setTask] = useState(null); + const [loading, setLoading] = useState(false); + + useEffect(() => { + if (id) { + fetchTaskDetail(); + } + }, [id]); + + const fetchTaskDetail = async () => { + if (!id) return; + setLoading(true); + try { + const taskData = await fetchMomentsSyncTaskDetail(id); + if (taskData) { + setTask(taskData); + } + } catch (error) { + toast({ title: '获取任务详情失败', variant: 'destructive' }); + } finally { + setLoading(false); + } + }; + + + + const handleToggleStatus = async () => { + if (!task || !id) return; + try { + const newStatus = task.status === 1 ? 2 : 1; + await toggleMomentsSyncTask(id, newStatus.toString()); + setTask({ ...task, status: newStatus }); + toast({ title: newStatus === 1 ? '任务已开启' : '任务已暂停' }); + } catch (error) { + toast({ title: '操作失败', variant: 'destructive' }); + } + }; + + const handleSync = async () => { + if (!id) return; + try { + await syncMoments(id); + toast({ title: '同步任务已启动' }); + fetchTaskDetail(); // 刷新任务详情 + } catch (error) { + toast({ title: '同步失败', variant: 'destructive' }); + } + }; + + const handleEdit = () => { + if (id) { + navigate(`/workspace/moments-sync/edit/${id}`); + } + }; + + if (loading) { + return ( +
+
+
+

加载中...

+
+
+ ); + } + + if (!task) { + return ( +
+
+

任务不存在

+ +
+
+ ); + } + + return ( +
+ {/* Header */} +
+
+
+ +

朋友圈同步任务详情

+
+
+ + +
+
+
+ +
+ {/* 基本信息卡片 */} + +
+
+

{task.name}

+ + {task.status === 1 ? "进行中" : "已暂停"} + +
+ +
+ +
+
+

任务详情

+
+

推送设备:{task.deviceCount} 个

+

内容库:{task.contentLib || '未设置'}

+

已同步:{task.syncCount} 条

+

创建人:{task.creator}

+
+
+
+

时间信息

+
+

创建时间:{task.createTime}

+

上次同步:{task.lastSyncTime || '暂无'}

+

更新时间:{task.updateTime}

+
+
+
+

同步设置

+
+

同步间隔:{task.syncInterval} 秒

+

每日最大:{task.maxSyncPerDay} 条

+

时间范围:{task.timeRange.start} - {task.timeRange.end}

+

同步模式:{task.syncMode === 'auto' ? '自动' : '手动'}

+
+
+
+

今日统计

+
+

今日同步:{task.todaySyncCount} 条

+

总同步数:{task.totalSyncCount} 条

+

目标标签:{task.targetTags.length} 个

+

内容类型:{task.contentTypes.join(', ')}

+
+
+
+
+ + +
+
+ ); } \ No newline at end of file diff --git a/nkebao/src/pages/workspace/moments-sync/edit.tsx b/nkebao/src/pages/workspace/moments-sync/edit.tsx new file mode 100644 index 000000000..543c21e34 --- /dev/null +++ b/nkebao/src/pages/workspace/moments-sync/edit.tsx @@ -0,0 +1,213 @@ +import React, { useState, useEffect } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { useToast } from '@/components/ui/toast'; +import { fetchMomentsSyncTaskDetail, updateMomentsSyncTask } from '@/api/momentsSync'; +import { MomentsSyncTask } from '@/types/moments-sync'; +import { ChevronLeft } from 'lucide-react'; + +export default function EditMomentsSyncTask() { + const { id } = useParams(); + const navigate = useNavigate(); + const { toast } = useToast(); + const [loading, setLoading] = useState(false); + const [task, setTask] = useState(null); + const [form, setForm] = useState({ + name: '', + deviceIds: '', + contentLib: '', + syncMode: 'auto', + syncInterval: '30', + maxSyncPerDay: '100', + timeStart: '08:00', + timeEnd: '22:00', + targetTags: '', + contentTypes: '', + filterKeywords: '', + }); + + useEffect(() => { + if (id) { + fetchTaskDetail(); + } + }, [id]); + + const fetchTaskDetail = async () => { + if (!id) return; + setLoading(true); + try { + const taskData = await fetchMomentsSyncTaskDetail(id); + if (taskData) { + setTask(taskData); + setForm({ + name: taskData.name, + deviceIds: taskData.devices.join(','), + contentLib: taskData.contentLib || '', + syncMode: taskData.syncMode, + syncInterval: taskData.syncInterval.toString(), + maxSyncPerDay: taskData.maxSyncPerDay.toString(), + timeStart: taskData.timeRange.start, + timeEnd: taskData.timeRange.end, + targetTags: taskData.targetTags.join(','), + contentTypes: taskData.contentTypes.join(','), + filterKeywords: taskData.filterKeywords.join(','), + }); + } + } catch (error) { + toast({ title: '获取任务详情失败', variant: 'destructive' }); + } finally { + setLoading(false); + } + }; + + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setForm(prev => ({ + ...prev, + [name]: value, + })); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!id) return; + + if (!form.name.trim()) { + toast({ title: '请输入任务名称', variant: 'destructive' }); + return; + } + if (!form.deviceIds.trim()) { + toast({ title: '请输入推送设备', variant: 'destructive' }); + return; + } + if (!form.contentLib.trim()) { + toast({ title: '请输入内容库', variant: 'destructive' }); + return; + } + + setLoading(true); + try { + await updateMomentsSyncTask({ + id, + name: form.name, + devices: form.deviceIds.split(',').map(s => s.trim()).filter(Boolean), + contentLib: form.contentLib, + syncMode: form.syncMode as 'auto' | 'manual', + interval: Number(form.syncInterval), + maxSync: Number(form.maxSyncPerDay), + startTime: form.timeStart, + endTime: form.timeEnd, + targetTags: form.targetTags.split(',').map(s => s.trim()).filter(Boolean), + contentTypes: form.contentTypes.split(',').map(s => s.trim()).filter(Boolean) as ('text' | 'image' | 'video' | 'link')[], + filterKeywords: form.filterKeywords.split(',').map(s => s.trim()).filter(Boolean), + }); + toast({ title: '更新成功' }); + navigate(`/workspace/moments-sync/${id}`); + } catch (error) { + toast({ title: '更新失败', variant: 'destructive' }); + } finally { + setLoading(false); + } + }; + + if (loading && !task) { + return ( +
+
+
+

加载中...

+
+
+ ); + } + + if (!task) { + return ( +
+
+

任务不存在

+ +
+
+ ); + } + + return ( +
+ {/* Header */} +
+
+
+ +

编辑朋友圈同步任务

+
+
+
+ +
+

编辑任务配置

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+ ); +} \ No newline at end of file diff --git a/nkebao/src/pages/workspace/moments-sync/index.tsx b/nkebao/src/pages/workspace/moments-sync/index.tsx index 22af2d04d..c10b3ac24 100644 --- a/nkebao/src/pages/workspace/moments-sync/index.tsx +++ b/nkebao/src/pages/workspace/moments-sync/index.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import Layout from '@/components/Layout'; import PageHeader from '@/components/PageHeader'; import { Card } from '@/components/ui/card'; @@ -11,6 +12,7 @@ import { fetchMomentsSyncTasks, syncMoments, syncAllMoments, MomentsSyncTask } f import { useToast } from '@/components/ui/toast'; export default function MomentsSyncPage() { + const navigate = useNavigate(); const { toast } = useToast(); const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(false); @@ -107,6 +109,9 @@ export default function MomentsSyncPage() {
已同步:{task.syncCount || 0} 条
+