From 98bcafda504e0c626b3db43f8566ea22929de67e 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, 8 Jul 2025 15:55:41 +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?=E8=AE=B0=E5=BD=95=E5=88=97=E8=A1=A8=E6=90=9E=E5=A5=BD=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nkebao/src/api/autoLike.ts | 189 ++--- nkebao/src/api/request.ts | 2 +- nkebao/src/components/LayoutWrapper.tsx | 1 + nkebao/src/components/ui/separator.tsx | 28 + nkebao/src/components/ui/skeleton.tsx | 15 + .../pages/workspace/auto-like/AutoLike.tsx | 4 +- .../workspace/auto-like/AutoLikeDetail.tsx | 701 ++++++------------ nkebao/src/types/auto-like.ts | 234 +++--- 8 files changed, 511 insertions(+), 663 deletions(-) create mode 100644 nkebao/src/components/ui/separator.tsx create mode 100644 nkebao/src/components/ui/skeleton.tsx diff --git a/nkebao/src/api/autoLike.ts b/nkebao/src/api/autoLike.ts index 3b6ca7d9..e163692d 100644 --- a/nkebao/src/api/autoLike.ts +++ b/nkebao/src/api/autoLike.ts @@ -1,90 +1,101 @@ -import { get, post, del } from './request'; -import { - LikeTask, - CreateLikeTaskData, - UpdateLikeTaskData, - LikeRecord, - ApiResponse, - PaginatedResponse -} from '@/types/auto-like'; - -// 获取自动点赞任务列表 -export async function fetchAutoLikeTasks(): Promise { - try { - const res = await get>>('/v1/workbench/list?type=1&page=1&limit=100'); - - if (res.code === 200 && res.data) { - return res.data.list || []; - } - return []; - } catch (error) { - console.error('获取自动点赞任务失败:', error); - return []; - } -} - -// 获取单个任务详情 -export async function fetchAutoLikeTaskDetail(id: string): Promise { - try { - const res = await get>(`/v1/workbench/detail/${id}`); - if (res.code === 200 && res.data) { - return res.data; - } - return null; - } catch (error) { - console.error('获取任务详情失败:', error); - return null; - } -} - -// 创建自动点赞任务 -export async function createAutoLikeTask(data: CreateLikeTaskData): Promise { - return post('/v1/workbench/create', { - ...data, - type: 1 // 自动点赞类型 - }); -} - -// 更新自动点赞任务 -export async function updateAutoLikeTask(data: UpdateLikeTaskData): Promise { - return post('/v1/workbench/update', { - ...data, - type: 1 // 自动点赞类型 - }); -} - -// 删除自动点赞任务 -export async function deleteAutoLikeTask(id: string): Promise { - return del('/v1/workbench/delete', { params: { id } }); -} - -// 切换任务状态 -export async function toggleAutoLikeTask(id: string, status: string): Promise { - return post('/v1/workbench/update-status', { id, status }); -} - -// 复制自动点赞任务 -export async function copyAutoLikeTask(id: string): Promise { - return post('/v1/workbench/copy', { id }); -} - -// 获取点赞记录 -export async function fetchLikeRecords( - workbenchId: string, - page: number = 1, - limit: number = 20 -): Promise> { - try { - const res = await get>>(`/v1/workbench/like-records?workbenchId=${workbenchId}&page=${page}&limit=${limit}`); - - if (res.code === 200 && res.data) { - return res.data; - } - return { list: [], total: 0, page, limit }; - } catch (error) { - console.error('获取点赞记录失败:', error); - return { list: [], total: 0, page, limit }; - } -} - +import { get, post, del } from './request'; +import { + LikeTask, + CreateLikeTaskData, + UpdateLikeTaskData, + LikeRecord, + ApiResponse, + PaginatedResponse +} from '@/types/auto-like'; + +// 获取自动点赞任务列表 +export async function fetchAutoLikeTasks(): Promise { + try { + const res = await get>>('/v1/workbench/list?type=1&page=1&limit=100'); + + if (res.code === 200 && res.data) { + return res.data.list || []; + } + return []; + } catch (error) { + console.error('获取自动点赞任务失败:', error); + return []; + } +} + +// 获取单个任务详情 +export async function fetchAutoLikeTaskDetail(id: string): Promise { + try { + const res = await get>(`/v1/workbench/detail/${id}`); + if (res.code === 200 && res.data) { + return res.data; + } + return null; + } catch (error) { + console.error('获取任务详情失败:', error); + return null; + } +} + +// 创建自动点赞任务 +export async function createAutoLikeTask(data: CreateLikeTaskData): Promise { + return post('/v1/workbench/create', { + ...data, + type: 1 // 自动点赞类型 + }); +} + +// 更新自动点赞任务 +export async function updateAutoLikeTask(data: UpdateLikeTaskData): Promise { + return post('/v1/workbench/update', { + ...data, + type: 1 // 自动点赞类型 + }); +} + +// 删除自动点赞任务 +export async function deleteAutoLikeTask(id: string): Promise { + return del('/v1/workbench/delete', { params: { id } }); +} + +// 切换任务状态 +export async function toggleAutoLikeTask(id: string, status: string): Promise { + return post('/v1/workbench/update-status', { id, status }); +} + +// 复制自动点赞任务 +export async function copyAutoLikeTask(id: string): Promise { + return post('/v1/workbench/copy', { id }); +} + +// 获取点赞记录 +export async function fetchLikeRecords( + workbenchId: string, + page: number = 1, + limit: number = 20, + keyword?: string +): Promise> { + try { + const params = new URLSearchParams({ + workbenchId, + page: page.toString(), + limit: limit.toString() + }); + + if (keyword) { + params.append('keyword', keyword); + } + + const res = await get>>(`/v1/workbench/like-records?${params.toString()}`); + + if (res.code === 200 && res.data) { + return res.data; + } + return { list: [], total: 0, page, limit }; + } catch (error) { + console.error('获取点赞记录失败:', error); + return { list: [], total: 0, page, limit }; + } +} + export type { LikeTask, LikeRecord, CreateLikeTaskData }; \ No newline at end of file diff --git a/nkebao/src/api/request.ts b/nkebao/src/api/request.ts index f152a431..af971f10 100644 --- a/nkebao/src/api/request.ts +++ b/nkebao/src/api/request.ts @@ -4,7 +4,7 @@ import { requestInterceptor, responseInterceptor, errorInterceptor } from './int // 创建axios实例 const request: AxiosInstance = axios.create({ baseURL: process.env.REACT_APP_API_BASE_URL || 'http://www.yishi.com', - timeout: 10000, + timeout: 20000, headers: { 'Content-Type': 'application/json', }, diff --git a/nkebao/src/components/LayoutWrapper.tsx b/nkebao/src/components/LayoutWrapper.tsx index 10fae72e..21d43a23 100644 --- a/nkebao/src/components/LayoutWrapper.tsx +++ b/nkebao/src/components/LayoutWrapper.tsx @@ -18,6 +18,7 @@ const NO_BOTTOM_NAV_PATHS = [ '/workspace/auto-group/', '/workspace/moments-sync/', '/workspace/traffic-distribution/', + '/workspace/auto-like', '/404', '/500' ]; diff --git a/nkebao/src/components/ui/separator.tsx b/nkebao/src/components/ui/separator.tsx new file mode 100644 index 00000000..54cb453f --- /dev/null +++ b/nkebao/src/components/ui/separator.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" +import { cn } from "../../utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } \ No newline at end of file diff --git a/nkebao/src/components/ui/skeleton.tsx b/nkebao/src/components/ui/skeleton.tsx new file mode 100644 index 00000000..ccbb294a --- /dev/null +++ b/nkebao/src/components/ui/skeleton.tsx @@ -0,0 +1,15 @@ +import { cn } from "../../utils"; + +function Skeleton({ + className, + ...props +}: React.HTMLAttributes) { + return ( +
+ ) +} + +export { Skeleton } \ No newline at end of file diff --git a/nkebao/src/pages/workspace/auto-like/AutoLike.tsx b/nkebao/src/pages/workspace/auto-like/AutoLike.tsx index 2db1b551..d9e7cf71 100644 --- a/nkebao/src/pages/workspace/auto-like/AutoLike.tsx +++ b/nkebao/src/pages/workspace/auto-like/AutoLike.tsx @@ -9,7 +9,7 @@ import { Search, RefreshCw, ThumbsUp, - ChevronDown, + ChevronLeft, } from "lucide-react"; import { Card } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; @@ -209,7 +209,7 @@ export default function AutoLike() {

自动点赞

diff --git a/nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx b/nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx index 994038ec..78da36d4 100644 --- a/nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx +++ b/nkebao/src/pages/workspace/auto-like/AutoLikeDetail.tsx @@ -1,455 +1,248 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import { useParams, useNavigate } from 'react-router-dom'; -import { - Edit, - Trash2, - Copy, - ThumbsUp, - Settings, - Calendar, - Eye, - RefreshCw, -} from 'lucide-react'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Button } from '@/components/ui/button'; -import { Badge } from '@/components/ui/badge'; -import { Progress } from '@/components/ui/progress'; -import { Switch } from '@/components/ui/switch'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from '@/components/ui/dropdown-menu'; -import Layout from '@/components/Layout'; -import PageHeader from '@/components/PageHeader'; -import BottomNav from '@/components/BottomNav'; -import { useToast } from '@/components/ui/toast'; -import '@/components/Layout.css'; -import { - fetchAutoLikeTaskDetail, - toggleAutoLikeTask, - deleteAutoLikeTask, - copyAutoLikeTask, - fetchLikeRecords, - LikeTask, - LikeRecord, -} from '@/api/autoLike'; - -export default function AutoLikeDetail() { - const { id } = useParams<{ id: string }>(); - const navigate = useNavigate(); - const { toast } = useToast(); - const [task, setTask] = useState(null); - const [records, setRecords] = useState([]); - const [loading, setLoading] = useState(true); - const [recordsLoading, setRecordsLoading] = useState(false); - - const fetchTaskDetail = useCallback(async () => { - if (!id) return; - - try { - const taskData = await fetchAutoLikeTaskDetail(id); - if (taskData) { - setTask(taskData); - } else { - toast({ - title: '任务不存在', - description: '该任务可能已被删除', - variant: 'destructive', - }); - navigate('/workspace/auto-like'); - } - } catch (error) { - console.error('获取任务详情失败:', error); - toast({ - title: '获取失败', - description: '请稍后重试', - variant: 'destructive', - }); - } finally { - setLoading(false); - } - }, [id, toast, navigate]); - - const fetchRecords = useCallback(async () => { - if (!id) return; - - setRecordsLoading(true); - try { - const response = await fetchLikeRecords(id, 1, 20); - setRecords(response.list || []); - } catch (error) { - console.error('获取点赞记录失败:', error); - } finally { - setRecordsLoading(false); - } - }, [id]); - - useEffect(() => { - if (id) { - fetchTaskDetail(); - fetchRecords(); - } - }, [id, fetchTaskDetail, fetchRecords]); - - const handleToggleStatus = async () => { - 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 { - const response = await toggleAutoLikeTask(task.id, String(newStatus)); - - if (response.code === 200) { - toast({ title: '操作成功' }); - // 成功时保持本地状态,不重新获取数据 - } else { - // 请求失败,回退本地状态 - setTask(prev => prev ? { ...prev, status: originalStatus } : null); - toast({ - title: '操作失败', - description: response.msg || '请稍后重试', - variant: 'destructive', - }); - } - } catch (error) { - console.error('操作失败:', error); - // 请求异常,回退本地状态 - setTask(prev => prev ? { ...prev, status: originalStatus } : null); - toast({ - title: '操作失败', - description: '请稍后重试', - variant: 'destructive', - }); - } - }; - - const handleDelete = async () => { - if (!task || !window.confirm('确定要删除该任务吗?')) return; - - try { - const response = await deleteAutoLikeTask(task.id); - if (response.code === 200) { - toast({ title: '删除成功' }); - navigate('/workspace/auto-like'); - } else { - toast({ - title: '删除失败', - description: response.msg || '请稍后重试', - variant: 'destructive', - }); - } - } catch (error) { - console.error('删除失败:', error); - toast({ - title: '删除失败', - description: '请稍后重试', - variant: 'destructive', - }); - } - }; - - const handleCopy = async () => { - if (!task) return; - - try { - const response = await copyAutoLikeTask(task.id); - if (response.code === 200) { - toast({ title: '复制成功' }); - navigate('/workspace/auto-like'); - } else { - toast({ - title: '复制失败', - description: response.msg || '请稍后重试', - variant: 'destructive', - }); - } - } catch (error) { - console.error('复制失败:', error); - toast({ - title: '复制失败', - description: '请稍后重试', - variant: 'destructive', - }); - } - }; - - const getStatusColor = (status: number) => { - switch (status) { - case 1: - return 'bg-green-100 text-green-800'; - case 2: - return 'bg-gray-100 text-gray-800'; - default: - return 'bg-gray-100 text-gray-800'; - } - }; - - const getStatusText = (status: number) => { - switch (status) { - case 1: - return '进行中'; - case 2: - return '已暂停'; - default: - return '未知'; - } - }; - - if (loading) { - return ( - } - footer={} - > -
-
- - -

加载中...

-

请稍候,正在获取任务详情

-
-
-
-
- ); - } - - if (!task) { - return null; - } - - return ( - - - - - - navigate(`/workspace/auto-like/${task.id}/edit`)}> - - 编辑 - - - - 复制 - - - - 删除 - - - - } - /> - } - footer={} - > -
-
- {/* 任务基本信息 */} - - -
- - - {task.name} - -
- - {getStatusText(Number(task.status))} - - -
-
-
- -
-
-
创建时间
-
{task.createTime}
-
-
-
创建人
-
{task.creator}
-
-
-
执行设备
-
{task.deviceCount} 个
-
-
-
目标人群
-
{task.targetGroup}
-
-
-
-
- - {/* 执行进度 */} - - - - - 执行进度 - - - -
-
- 今日已点赞 - - {task.todayLikeCount} / {task.maxLikesPerDay} - -
- -
-
-
-
总点赞数
-
{task.totalLikeCount} 次
-
-
-
上次点赞
-
{task.lastLikeTime}
-
-
-
-
- - {/* 任务配置 */} - - - - - 任务配置 - - - -
-
-
点赞间隔
-
{task.likeInterval} 秒
-
-
-
每日最大点赞数
-
{task.maxLikesPerDay} 次
-
-
-
单个好友最大点赞数
-
{task.friendMaxLikes} 次
-
-
-
执行时间段
-
- {task.timeRange.start} - {task.timeRange.end} -
-
-
- -
-
内容类型
-
- {task.contentTypes.map((type) => ( - - {type === 'text' ? '文字' : type === 'image' ? '图片' : type === 'video' ? '视频' : '链接'} - - ))} -
-
- - {task.targetTags.length > 0 && ( -
-
目标标签
-
- {task.targetTags.map((tag) => ( - - {tag} - - ))} -
-
- )} - - {task.enableFriendTags && task.friendTags && ( -
-
好友标签
-
- {task.friendTags} -
-
- )} -
-
- - {/* 点赞记录 */} - - -
- - - 点赞记录 - - -
-
- - {recordsLoading ? ( -
- -

加载中...

-
- ) : records.length === 0 ? ( -
- -

暂无点赞记录

-
- ) : ( -
- {records.slice(0, 10).map((record) => ( -
-
- -
-
-
- {record.friendName} -
-
- {record.content} -
-
-
- {record.likeTime} -
-
- ))} -
- )} -
-
-
-
-
- ); +import React, { useState, useEffect, useCallback } from 'react'; +import { useParams } from 'react-router-dom'; +import { + ThumbsUp, + RefreshCw, + Search, + Filter, +} from 'lucide-react'; +import { Card, CardContent } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Badge } from '@/components/ui/badge'; +import { Input } from '@/components/ui/input'; +import { Avatar } from '@/components/ui/avatar'; +import { Skeleton } from '@/components/ui/skeleton'; +import { Separator } from '@/components/ui/separator'; +import Layout from '@/components/Layout'; +import PageHeader from '@/components/PageHeader'; +import { useToast } from '@/components/ui/toast'; +import '@/components/Layout.css'; +import { + fetchLikeRecords, + LikeRecord, +} from '@/api/autoLike'; + +// 格式化日期 +const formatDate = (dateString: string) => { + try { + const date = new Date(dateString); + return date.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + } catch (error) { + return dateString; + } +}; + +export default function AutoLikeDetail() { + const { id } = useParams<{ id: string }>(); + const { toast } = useToast(); + const [records, setRecords] = useState([]); + const [recordsLoading, setRecordsLoading] = useState(false); + const [searchTerm, setSearchTerm] = useState(''); + const [currentPage, setCurrentPage] = useState(1); + const [total, setTotal] = useState(0); + const pageSize = 10; + + const fetchRecords = useCallback(async (page: number = 1, keyword?: string) => { + if (!id) return; + setRecordsLoading(true); + try { + const response = await fetchLikeRecords(id, page, pageSize, keyword); + setRecords(response.list || []); + setTotal(response.total || 0); + setCurrentPage(page); + } catch (error) { + console.error('获取点赞记录失败:', error); + toast({ + title: '获取点赞记录失败', + description: '请稍后重试', + variant: 'destructive', + }); + } finally { + setRecordsLoading(false); + } + }, [id, toast]); + + useEffect(() => { + if (id) { + fetchRecords(1); + } + }, [id, fetchRecords]); // 加上 fetchRecords 依赖 + + const handleSearch = () => { + setCurrentPage(1); + fetchRecords(1, searchTerm); + }; + + const handleRefresh = () => { + fetchRecords(currentPage, searchTerm); + }; + + const handlePageChange = (newPage: number) => { + fetchRecords(newPage, searchTerm); + }; + + return ( + + } + > +
+
+ + +
+
+ + setSearchTerm(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && handleSearch()} + /> +
+ +
+
+
+ {recordsLoading ? ( +
+ {Array.from({ length: 3 }).map((_, index) => ( + +
+ +
+ + +
+
+ +
+ + +
+ + +
+
+
+ ))} +
+ ) : records.length === 0 ? ( +
+ +

暂无点赞记录

+
+ ) : ( + <> + {records.map((record) => ( +
+
+
+ + {record.friendName} + +
+
+ {record.friendName} +
+
内容发布者
+
+
+ + {formatDate(record.momentTime || record.likeTime)} + +
+ +
+ {record.content && ( +

+ {record.content} +

+ )} + {Array.isArray(record.resUrls) && record.resUrls.length > 0 && ( +
+ {record.resUrls.slice(0, 9).map((image: string, idx: number) => ( +
+ {`内容图片 +
+ ))} +
+ )} +
+
+ + {record.operatorName} + +
+ + {record.operatorName} + + 点赞了这条内容 +
+
+
+ ))} + + )} + {/* 分页 */} + {records.length > 0 && total > pageSize && ( +
+ + + 第 {currentPage} 页,共 {Math.ceil(total / pageSize)} 页 + + +
+ )} +
+
+
+ ); } \ No newline at end of file diff --git a/nkebao/src/types/auto-like.ts b/nkebao/src/types/auto-like.ts index b9aae51a..2cf88776 100644 --- a/nkebao/src/types/auto-like.ts +++ b/nkebao/src/types/auto-like.ts @@ -1,118 +1,118 @@ -// 自动点赞任务状态 -export type LikeTaskStatus = 1 | 2; // 1: 开启, 2: 关闭 - -// 内容类型 -export type ContentType = 'text' | 'image' | 'video' | 'link'; - -// 设备信息 -export interface Device { - id: string; - name: string; - status: 'online' | 'offline'; - lastActive: string; -} - -// 好友信息 -export interface Friend { - id: string; - nickname: string; - wechatId: string; - avatar: string; - tags: string[]; - region: string; - source: string; -} - -// 点赞记录 -export interface LikeRecord { - id: string; - workbenchId: string; - momentsId: string; - snsId: string; - wechatAccountId: string; - wechatFriendId: string; - likeTime: string; - content: string; - resUrls: string; - momentTime: string; - userName: string; - operatorName: string; - operatorAvatar: string; - friendName: string; - friendAvatar: string; -} - -// 自动点赞任务 -export interface LikeTask { - id: string; - name: string; - status: LikeTaskStatus; - deviceCount: number; - targetGroup: string; - likeCount: number; - lastLikeTime: string; - createTime: string; - creator: string; - likeInterval: number; - maxLikesPerDay: number; - timeRange: { start: string; end: string }; - contentTypes: ContentType[]; - targetTags: string[]; - devices: string[]; - friends: string[]; - friendMaxLikes: number; - friendTags: string; - enableFriendTags: boolean; - todayLikeCount: number; - totalLikeCount: number; - updateTime: string; -} - -// 创建任务数据 -export interface CreateLikeTaskData { - name: string; - interval: number; - maxLikes: number; - startTime: string; - endTime: string; - contentTypes: ContentType[]; - devices: string[]; - friends?: string[]; - friendMaxLikes: number; - friendTags?: string; - enableFriendTags: boolean; - targetTags: string[]; -} - -// 更新任务数据 -export interface UpdateLikeTaskData extends CreateLikeTaskData { - id: string; -} - -// 任务配置 -export interface TaskConfig { - interval: number; - maxLikes: number; - startTime: string; - endTime: string; - contentTypes: ContentType[]; - devices: string[]; - friends: string[]; - friendMaxLikes: number; - friendTags: string; - enableFriendTags: boolean; -} - -// API 响应格式 -export interface ApiResponse { - code: number; - msg: string; - data: T; -} - -export interface PaginatedResponse { - list: T[]; - total: number; - page: number; - limit: number; +// 自动点赞任务状态 +export type LikeTaskStatus = 1 | 2; // 1: 开启, 2: 关闭 + +// 内容类型 +export type ContentType = 'text' | 'image' | 'video' | 'link'; + +// 设备信息 +export interface Device { + id: string; + name: string; + status: 'online' | 'offline'; + lastActive: string; +} + +// 好友信息 +export interface Friend { + id: string; + nickname: string; + wechatId: string; + avatar: string; + tags: string[]; + region: string; + source: string; +} + +// 点赞记录 +export interface LikeRecord { + id: string; + workbenchId: string; + momentsId: string; + snsId: string; + wechatAccountId: string; + wechatFriendId: string; + likeTime: string; + content: string; + resUrls: string[]; + momentTime: string; + userName: string; + operatorName: string; + operatorAvatar: string; + friendName: string; + friendAvatar: string; +} + +// 自动点赞任务 +export interface LikeTask { + id: string; + name: string; + status: LikeTaskStatus; + deviceCount: number; + targetGroup: string; + likeCount: number; + lastLikeTime: string; + createTime: string; + creator: string; + likeInterval: number; + maxLikesPerDay: number; + timeRange: { start: string; end: string }; + contentTypes: ContentType[]; + targetTags: string[]; + devices: string[]; + friends: string[]; + friendMaxLikes: number; + friendTags: string; + enableFriendTags: boolean; + todayLikeCount: number; + totalLikeCount: number; + updateTime: string; +} + +// 创建任务数据 +export interface CreateLikeTaskData { + name: string; + interval: number; + maxLikes: number; + startTime: string; + endTime: string; + contentTypes: ContentType[]; + devices: string[]; + friends?: string[]; + friendMaxLikes: number; + friendTags?: string; + enableFriendTags: boolean; + targetTags: string[]; +} + +// 更新任务数据 +export interface UpdateLikeTaskData extends CreateLikeTaskData { + id: string; +} + +// 任务配置 +export interface TaskConfig { + interval: number; + maxLikes: number; + startTime: string; + endTime: string; + contentTypes: ContentType[]; + devices: string[]; + friends: string[]; + friendMaxLikes: number; + friendTags: string; + enableFriendTags: boolean; +} + +// API 响应格式 +export interface ApiResponse { + code: number; + msg: string; + data: T; +} + +export interface PaginatedResponse { + list: T[]; + total: number; + page: number; + limit: number; } \ No newline at end of file