feat: 功能迁移过来了,接下来优化样式
This commit is contained in:
@@ -1,5 +1,354 @@
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate, Link } from 'react-router-dom';
|
||||
import { Plus, Filter, Search, RefreshCw, MoreVertical, Clock, Edit, Trash2, Eye, Copy } from 'lucide-react';
|
||||
import { Card } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import { useToast } from '@/components/ui/toast';
|
||||
|
||||
interface SyncTask {
|
||||
id: string;
|
||||
name: string;
|
||||
status: number; // 1-运行中,0-暂停
|
||||
deviceCount: number;
|
||||
contentLib: string;
|
||||
syncCount: number;
|
||||
lastSyncTime: string;
|
||||
createTime: string;
|
||||
creator: string;
|
||||
config: {
|
||||
devices: string[];
|
||||
contentLibraryNames: string[];
|
||||
};
|
||||
creatorName: string;
|
||||
}
|
||||
|
||||
export default function MomentsSync() {
|
||||
return <div>朋友圈同步页</div>;
|
||||
const navigate = useNavigate();
|
||||
const { toast } = useToast();
|
||||
const [tasks, setTasks] = useState<SyncTask[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const [total, setTotal] = useState(0);
|
||||
|
||||
// 模拟数据
|
||||
const mockTasks: SyncTask[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: '朋友圈同步任务1',
|
||||
status: 1,
|
||||
deviceCount: 3,
|
||||
contentLib: '营销素材库',
|
||||
syncCount: 156,
|
||||
lastSyncTime: '2024-03-18 16:30:00',
|
||||
createTime: '2024-03-15 10:00:00',
|
||||
creator: 'admin',
|
||||
creatorName: '管理员',
|
||||
config: {
|
||||
devices: ['device1', 'device2', 'device3'],
|
||||
contentLibraryNames: ['营销素材库', '产品介绍库']
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '朋友圈同步任务2',
|
||||
status: 0,
|
||||
deviceCount: 2,
|
||||
contentLib: '产品介绍库',
|
||||
syncCount: 89,
|
||||
lastSyncTime: '2024-03-17 14:20:00',
|
||||
createTime: '2024-03-14 15:30:00',
|
||||
creator: 'user1',
|
||||
creatorName: '用户1',
|
||||
config: {
|
||||
devices: ['device4', 'device5'],
|
||||
contentLibraryNames: ['产品介绍库']
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// 获取任务列表
|
||||
const fetchTasks = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 模拟搜索过滤
|
||||
let filteredTasks = mockTasks;
|
||||
if (searchQuery) {
|
||||
filteredTasks = mockTasks.filter(task =>
|
||||
task.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
setTasks(filteredTasks);
|
||||
setTotal(filteredTasks.length);
|
||||
} catch (error: any) {
|
||||
console.error('获取朋友圈同步任务列表失败:', error);
|
||||
toast({
|
||||
title: '获取失败',
|
||||
description: error?.message || '请检查网络连接',
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 组件加载时获取任务列表
|
||||
useEffect(() => {
|
||||
fetchTasks();
|
||||
}, [currentPage, pageSize]);
|
||||
|
||||
// 处理页码变化
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
};
|
||||
|
||||
// 处理每页条数变化
|
||||
const handlePageSizeChange = (size: number) => {
|
||||
setPageSize(size);
|
||||
setCurrentPage(1); // 重置到第一页
|
||||
};
|
||||
|
||||
// 搜索任务
|
||||
const handleSearch = () => {
|
||||
fetchTasks();
|
||||
};
|
||||
|
||||
// 切换任务状态
|
||||
const toggleTaskStatus = async (taskId: string, currentStatus: number) => {
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
const newStatus = currentStatus === 1 ? 0 : 1;
|
||||
setTasks(
|
||||
tasks.map((task) =>
|
||||
task.id === taskId ? { ...task, status: newStatus } : task
|
||||
)
|
||||
);
|
||||
|
||||
toast({
|
||||
title: '状态更新成功',
|
||||
description: `任务已${newStatus === 1 ? '启用' : '暂停'}`,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('更新任务状态失败:', error);
|
||||
toast({
|
||||
title: '更新失败',
|
||||
description: error?.message || '更新任务状态失败',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 执行删除
|
||||
const handleDelete = async (taskId: string) => {
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
setTasks(tasks.filter((task) => task.id !== taskId));
|
||||
toast({
|
||||
title: '删除成功',
|
||||
description: '已成功删除同步任务',
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('删除任务失败:', error);
|
||||
toast({
|
||||
title: '删除失败',
|
||||
description: error?.message || '删除任务失败',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 编辑任务
|
||||
const handleEdit = (taskId: string) => {
|
||||
navigate(`/workspace/moments-sync/${taskId}/edit`);
|
||||
};
|
||||
|
||||
// 查看任务详情
|
||||
const handleView = (taskId: string) => {
|
||||
navigate(`/workspace/moments-sync/${taskId}`);
|
||||
};
|
||||
|
||||
// 复制任务
|
||||
const handleCopy = async (taskId: string) => {
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
const taskToCopy = tasks.find(task => task.id === taskId);
|
||||
if (taskToCopy) {
|
||||
const newTask = {
|
||||
...taskToCopy,
|
||||
id: Date.now().toString(),
|
||||
name: `${taskToCopy.name} (副本)`,
|
||||
status: 0,
|
||||
createTime: new Date().toLocaleString(),
|
||||
syncCount: 0,
|
||||
lastSyncTime: '-'
|
||||
};
|
||||
setTasks([newTask, ...tasks]);
|
||||
toast({
|
||||
title: '复制成功',
|
||||
description: '已成功复制同步任务',
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('复制任务失败:', error);
|
||||
toast({
|
||||
title: '复制失败',
|
||||
description: error?.message || '复制任务失败',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 过滤任务
|
||||
const filteredTasks = tasks.filter(
|
||||
(task) => task.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex-1 bg-gray-50 min-h-screen pb-20">
|
||||
<PageHeader
|
||||
title="朋友圈同步"
|
||||
defaultBackPath="/workspace"
|
||||
rightContent={
|
||||
<Link to="/workspace/moments-sync/new">
|
||||
<Button>
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
新建任务
|
||||
</Button>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="p-4">
|
||||
<Card className="p-4 mb-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="relative flex-1">
|
||||
<Search className="absolute left-3 top-2.5 h-4 w-4 text-gray-400" />
|
||||
<Input
|
||||
placeholder="搜索任务名称"
|
||||
className="pl-9"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
|
||||
/>
|
||||
</div>
|
||||
<Button variant="outline" size="icon" onClick={handleSearch}>
|
||||
<Filter className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button variant="outline" size="icon" onClick={fetchTasks} disabled={isLoading}>
|
||||
<RefreshCw className={`h-4 w-4 ${isLoading ? 'animate-spin' : ''}`} />
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<div className="space-y-4">
|
||||
{isLoading ? (
|
||||
<div className="text-center py-12 text-gray-400">加载中...</div>
|
||||
) : filteredTasks.length > 0 ? (
|
||||
filteredTasks.map((task) => (
|
||||
<Card key={task.id} className="p-4">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<h3 className="font-medium">{task.name}</h3>
|
||||
<Badge variant={task.status === 1 ? 'default' : 'secondary'}>
|
||||
{task.status === 1 ? '运行中' : '已暂停'}
|
||||
</Badge>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch checked={task.status === 1} onCheckedChange={() => toggleTaskStatus(task.id, task.status)} />
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="sm" className="h-8 w-8 p-0">
|
||||
<MoreVertical className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={() => handleView(task.id)}>
|
||||
<Eye className="h-4 w-4 mr-2" />
|
||||
查看
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleEdit(task.id)}>
|
||||
<Edit className="h-4 w-4 mr-2" />
|
||||
编辑
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleCopy(task.id)}>
|
||||
<Copy className="h-4 w-4 mr-2" />
|
||||
复制
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleDelete(task.id)}>
|
||||
<Trash2 className="h-4 w-4 mr-2" />
|
||||
删除
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4 mb-4">
|
||||
<div className="text-sm text-gray-500">
|
||||
<div className="mb-1">执行设备:{task.deviceCount} 个</div>
|
||||
<div className="mb-1">内容库:{task.contentLib}</div>
|
||||
<div>创建者:{task.creatorName}</div>
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
<div className="mb-1">同步次数:{task.syncCount} 次</div>
|
||||
<div className="mb-1">最后同步:{task.lastSyncTime}</div>
|
||||
<div>创建时间:{task.createTime}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t pt-4">
|
||||
<div className="flex items-center text-sm text-gray-500">
|
||||
<Clock className="h-4 w-4 mr-2" />
|
||||
<span>配置的设备:{task.config.devices.join(', ')}</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-12 text-gray-400">
|
||||
{searchQuery ? '没有找到匹配的任务' : '暂无同步任务'}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 分页 */}
|
||||
{total > pageSize && (
|
||||
<div className="flex justify-center mt-6 space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handlePageChange(Math.max(1, currentPage - 1))}
|
||||
disabled={currentPage === 1 || isLoading}
|
||||
>
|
||||
上一页
|
||||
</Button>
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="text-sm text-gray-500">第 {currentPage} 页</span>
|
||||
<span className="text-sm text-gray-500">共 {Math.ceil(total / pageSize)} 页</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handlePageChange(Math.min(Math.ceil(total / pageSize), currentPage + 1))}
|
||||
disabled={currentPage >= Math.ceil(total / pageSize) || isLoading}
|
||||
>
|
||||
下一页
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user