feat: 本次提交更新内容如下
列表迁移成功
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
ChevronDown,
|
|
||||||
ChevronUp,
|
|
||||||
MoreVertical,
|
MoreVertical,
|
||||||
Eye,
|
Eye,
|
||||||
Edit,
|
Edit,
|
||||||
@@ -10,10 +8,8 @@ import {
|
|||||||
Plus,
|
Plus,
|
||||||
Search,
|
Search,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
Settings,
|
|
||||||
Calendar,
|
|
||||||
Users,
|
|
||||||
ThumbsUp,
|
ThumbsUp,
|
||||||
|
ChevronDown,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Card } from "@/components/ui/card";
|
import { Card } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -22,7 +18,7 @@ import { Badge } from "@/components/ui/badge";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { useToast } from "@/components/ui/toast";
|
import { useToast } from "@/components/ui/toast";
|
||||||
import { Progress } from "@/components/ui/progress";
|
|
||||||
import { fetchAutoLikeTasks, deleteAutoLikeTask, toggleAutoLikeTask, copyAutoLikeTask, LikeTask } from '@/api/autoLike';
|
import { fetchAutoLikeTasks, deleteAutoLikeTask, toggleAutoLikeTask, copyAutoLikeTask, LikeTask } from '@/api/autoLike';
|
||||||
|
|
||||||
type CardMenuProps = {
|
type CardMenuProps = {
|
||||||
@@ -87,7 +83,6 @@ function CardMenu({ onView, onEdit, onCopy, onDelete }: CardMenuProps) {
|
|||||||
export default function AutoLike() {
|
export default function AutoLike() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [expandedTaskId, setExpandedTaskId] = useState<string | null>(null);
|
|
||||||
const [tasks, setTasks] = React.useState<LikeTask[]>([]);
|
const [tasks, setTasks] = React.useState<LikeTask[]>([]);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -127,10 +122,7 @@ export default function AutoLike() {
|
|||||||
fetchTasks();
|
fetchTasks();
|
||||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const toggleExpand = (taskId: string) => {
|
|
||||||
setExpandedTaskId(expandedTaskId === taskId ? null : taskId);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = async (id: string) => {
|
const handleDelete = async (id: string) => {
|
||||||
if (!window.confirm("确定要删除该任务吗?")) return;
|
if (!window.confirm("确定要删除该任务吗?")) return;
|
||||||
@@ -170,17 +162,35 @@ export default function AutoLike() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleTaskStatus = async (id: string, status: number) => {
|
const toggleTaskStatus = async (id: string, status: number) => {
|
||||||
|
// 先更新本地状态
|
||||||
|
const newStatus = (status === 1 ? 2 : 1) as 1 | 2;
|
||||||
|
setTasks(prevTasks =>
|
||||||
|
prevTasks.map(task =>
|
||||||
|
task.id === id ? { ...task, status: newStatus } : task
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// status: 1(开启)-> 2(要关闭),2(关闭)-> 1(要开启)
|
|
||||||
const newStatus = status === 1 ? 2 : 1;
|
|
||||||
const response = await toggleAutoLikeTask(id, String(newStatus));
|
const response = await toggleAutoLikeTask(id, String(newStatus));
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
toast({ title: "操作成功" });
|
toast({ title: "操作成功" });
|
||||||
fetchTasks();
|
// 成功时不刷新列表,保持本地状态
|
||||||
} else {
|
} else {
|
||||||
|
// 请求失败,回退本地状态
|
||||||
|
setTasks(prevTasks =>
|
||||||
|
prevTasks.map(task =>
|
||||||
|
task.id === id ? { ...task, status: status as 1 | 2 } : task
|
||||||
|
)
|
||||||
|
);
|
||||||
toast({ title: "操作失败", description: response.msg || "请稍后重试", variant: "destructive" });
|
toast({ title: "操作失败", description: response.msg || "请稍后重试", variant: "destructive" });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// 请求异常,回退本地状态
|
||||||
|
setTasks(prevTasks =>
|
||||||
|
prevTasks.map(task =>
|
||||||
|
task.id === id ? { ...task, status: status as 1 | 2 } : task
|
||||||
|
)
|
||||||
|
);
|
||||||
toast({ title: "操作失败", description: "请稍后重试", variant: "destructive" });
|
toast({ title: "操作失败", description: "请稍后重试", variant: "destructive" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -244,107 +254,48 @@ export default function AutoLike() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4 mb-4">
|
<div className="grid grid-cols-2 gap-6 mb-6">
|
||||||
<div className="text-sm text-gray-500">
|
<div className="space-y-3">
|
||||||
<div>执行设备:{task.deviceCount} 个</div>
|
<div className="flex justify-between items-center">
|
||||||
<div>目标人群:{task.targetGroup}</div>
|
<span className="text-sm text-gray-500 font-medium">执行设备</span>
|
||||||
<div>更新时间:{task.updateTime}</div>
|
<span className="text-sm text-gray-900 font-semibold">{task.deviceCount} 个</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-500">
|
<div className="flex justify-between items-center">
|
||||||
<div>点赞间隔:{task.likeInterval} 秒</div>
|
<span className="text-sm text-gray-500 font-medium">目标人群</span>
|
||||||
<div>每日上限:{task.maxLikesPerDay} 次</div>
|
<span className="text-sm text-gray-900 font-semibold">{task.targetGroup}</span>
|
||||||
<div>创建时间:{task.createTime}</div>
|
</div>
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<span className="text-sm text-gray-500 font-medium">更新时间</span>
|
||||||
|
<span className="text-sm text-gray-900 font-semibold">{task.updateTime}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between text-xs text-gray-500 border-t pt-4">
|
<div className="space-y-3">
|
||||||
<div className="flex items-center">
|
<div className="flex justify-between items-center">
|
||||||
<ThumbsUp className="w-4 h-4 mr-1" />今日点赞:{task.lastLikeTime}
|
<span className="text-sm text-gray-500 font-medium">点赞间隔</span>
|
||||||
|
<span className="text-sm text-gray-900 font-semibold">{task.likeInterval} 秒</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex justify-between items-center">
|
||||||
<ThumbsUp className="w-4 h-4 mr-1" />
|
<span className="text-sm text-gray-500 font-medium">每日上限</span>
|
||||||
<span>总点赞数:{task.createTime}</span>
|
<span className="text-sm text-gray-900 font-semibold">{task.maxLikesPerDay} 次</span>
|
||||||
<Button variant="ghost" size="sm" className="ml-2 p-0 h-6 w-6" onClick={() => toggleExpand(task.id)}>
|
|
||||||
{expandedTaskId === task.id ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="flex justify-between items-center">
|
||||||
{expandedTaskId === task.id && (
|
<span className="text-sm text-gray-500 font-medium">创建时间</span>
|
||||||
<div className="mt-4 pt-4 border-t border-dashed">
|
<span className="text-sm text-gray-900 font-semibold">{task.createTime}</span>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<Settings className="h-5 w-5 mr-2 text-gray-500" />
|
|
||||||
<h4 className="font-medium">基本设置</h4>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2 pl-7">
|
|
||||||
<div className="flex justify-between text-sm">
|
|
||||||
<span className="text-gray-500">点赞间隔:</span>
|
|
||||||
<span>{task.likeInterval} 秒</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between text-sm">
|
|
||||||
<span className="text-gray-500">每日最大点赞数:</span>
|
|
||||||
<span>{task.maxLikesPerDay} 次</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between text-sm">
|
|
||||||
<span className="text-gray-500">执行时间段:</span>
|
|
||||||
<span>
|
|
||||||
{task.timeRange.start} - {task.timeRange.end}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="flex items-center justify-between text-sm text-gray-500 border-t pt-5">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center space-x-2">
|
||||||
<Users className="h-5 w-5 mr-2 text-gray-500" />
|
<ThumbsUp className="w-4 h-4 text-blue-500" />
|
||||||
<h4 className="font-medium">目标人群</h4>
|
<span className="font-medium">今日点赞:</span>
|
||||||
|
<span className="text-gray-900 font-semibold">{task.lastLikeTime}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2 pl-7">
|
<div className="flex items-center space-x-2">
|
||||||
<div className="flex flex-wrap gap-2">
|
<ThumbsUp className="w-4 h-4 text-green-500" />
|
||||||
{task.targetTags.map((tag) => (
|
<span className="font-medium">总点赞数:</span>
|
||||||
<Badge key={tag} variant="outline" className="bg-gray-50">
|
<span className="text-gray-900 font-semibold">{task.totalLikeCount || 0}</span>
|
||||||
{tag}
|
|
||||||
</Badge>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<ThumbsUp className="h-5 w-5 mr-2 text-gray-500" />
|
|
||||||
<h4 className="font-medium">点赞内容类型</h4>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2 pl-7">
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{task.contentTypes.map((type) => (
|
|
||||||
<Badge key={type} variant="outline" className="bg-gray-50">
|
|
||||||
{type === "text" ? "文字" : type === "image" ? "图片" : "视频"}
|
|
||||||
</Badge>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<Calendar className="h-5 w-5 mr-2 text-gray-500" />
|
|
||||||
<h4 className="font-medium">执行进度</h4>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2 pl-7">
|
|
||||||
<div className="flex justify-between text-sm mb-1">
|
|
||||||
<span className="text-gray-500">今日已点赞:</span>
|
|
||||||
<span>
|
|
||||||
{task.likeCount} / {task.maxLikesPerDay}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<Progress
|
|
||||||
value={(task.likeCount / task.maxLikesPerDay) * 100}
|
|
||||||
className="h-2"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -96,15 +96,20 @@ export default function AutoLikeDetail() {
|
|||||||
const handleToggleStatus = async () => {
|
const handleToggleStatus = async () => {
|
||||||
if (!task) return;
|
if (!task) return;
|
||||||
|
|
||||||
|
// 先更新本地状态
|
||||||
|
const newStatus = (Number(task.status) === 1 ? 2 : 1) as 1 | 2;
|
||||||
|
const originalStatus = Number(task.status) as 1 | 2;
|
||||||
|
setTask(prev => prev ? { ...prev, status: newStatus } : null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// status: 1(开启)-> 2(要关闭),2(关闭)-> 1(要开启)
|
|
||||||
const newStatus = task.status === 1 ? 2 : 1;
|
|
||||||
const response = await toggleAutoLikeTask(task.id, String(newStatus));
|
const response = await toggleAutoLikeTask(task.id, String(newStatus));
|
||||||
|
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
setTask(prev => prev ? { ...prev, status: newStatus } : null);
|
|
||||||
toast({ title: '操作成功' });
|
toast({ title: '操作成功' });
|
||||||
|
// 成功时保持本地状态,不重新获取数据
|
||||||
} else {
|
} else {
|
||||||
|
// 请求失败,回退本地状态
|
||||||
|
setTask(prev => prev ? { ...prev, status: originalStatus } : null);
|
||||||
toast({
|
toast({
|
||||||
title: '操作失败',
|
title: '操作失败',
|
||||||
description: response.msg || '请稍后重试',
|
description: response.msg || '请稍后重试',
|
||||||
@@ -113,6 +118,8 @@ export default function AutoLikeDetail() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('操作失败:', error);
|
console.error('操作失败:', error);
|
||||||
|
// 请求异常,回退本地状态
|
||||||
|
setTask(prev => prev ? { ...prev, status: originalStatus } : null);
|
||||||
toast({
|
toast({
|
||||||
title: '操作失败',
|
title: '操作失败',
|
||||||
description: '请稍后重试',
|
description: '请稍后重试',
|
||||||
@@ -267,7 +274,6 @@ export default function AutoLikeDetail() {
|
|||||||
<Switch
|
<Switch
|
||||||
checked={Number(task.status) === 1}
|
checked={Number(task.status) === 1}
|
||||||
onCheckedChange={handleToggleStatus}
|
onCheckedChange={handleToggleStatus}
|
||||||
disabled={false}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user