返回 AiToEarn
popTask.tsx
根目录 / project / aitoearn-electron / src / views / task / popTask.tsx
1 /*
2 * @Author: nevin
3 * @Date: 2025-02-10 22:20:15
4 * @LastEditTime: 2025-03-24 14:11:29
5 * @LastEditors: nevin
6 * @Description: 推广任务
7 */
8 import { Button, Card, Tag, Spin, message, Tooltip } from 'antd';
9 import { useState, useEffect, useRef } from 'react';
10 import { Task, TaskPromotion, TaskType } from '@@/types/task';
11 import { taskApi } from '@/api/task';
12 import { TaskInfoRef } from './components/popInfo';
13 import TaskInfo from './components/popInfo';
14 import styles from './popTask.module.scss';
15 import {
16 ClockCircleOutlined,
17 TeamOutlined,
18 RightOutlined,
19 CopyOutlined,
20 } from '@ant-design/icons';
21 import dayjs from 'dayjs';
22
23 const FILE_BASE_URL = import.meta.env.VITE_APP_FILE_HOST;
24
25 export default function Page() {
26 const [taskList, setTaskList] = useState<Task<TaskPromotion>[]>([]);
27 const [pageInfo, setPageInfo] = useState({
28 pageSize: 10,
29 pageNo: 1,
30 totalCount: 0,
31 });
32 const [loading, setLoading] = useState(true);
33 const [hasMore, setHasMore] = useState(true);
34
35 const Ref_TaskInfo = useRef<TaskInfoRef>(null);
36
37 async function getTaskList(isLoadMore = false) {
38 setLoading(true);
39 try {
40 const res = await taskApi.getTaskList({
41 ...pageInfo,
42 type: TaskType.PROMOTION,
43 });
44
45 if (isLoadMore) {
46 setTaskList((prev) => [...prev, ...res.items]);
47 } else {
48 setTaskList(res.items);
49 }
50
51 setPageInfo((prev) => ({
52 ...prev,
53 totalCount: (res as any).totalCount,
54 }));
55
56 // 检查是否还有更多数据
57 setHasMore(pageInfo.pageNo * pageInfo.pageSize < (res as any).totalCount);
58 } catch (error) {
59 console.error('获取任务列表失败', error);
60 } finally {
61 setLoading(false);
62 }
63 }
64
65 useEffect(() => {
66 getTaskList();
67 }, []);
68
69 // 加载更多数据
70 const loadMore = () => {
71 setPageInfo((prev) => ({
72 ...prev,
73 pageNo: prev.pageNo + 1,
74 }));
75 getTaskList(true);
76 };
77
78 // 格式化日期
79 const formatDate = (dateString: string) => {
80 if (!dateString) return '2025/03/17';
81 return dayjs(dateString).format('YYYY/MM/DD');
82 };
83
84 // 复制任务ID
85 const copyTaskId = (id: string) => {
86 navigator.clipboard
87 .writeText(id)
88 .then(() => {
89 message.success('任务ID已复制到剪贴板');
90 })
91 .catch(() => {
92 message.error('复制失败,请手动复制');
93 });
94 };
95
96 // 刷新任务列表的函数
97 const refreshTaskList = () => {
98 setPageInfo({
99 pageSize: 10,
100 pageNo: 1,
101 totalCount: 0,
102 });
103 getTaskList();
104 };
105
106 return (
107 <div className={styles.popTaskContainer}>
108 <TaskInfo ref={Ref_TaskInfo} onTaskApplied={refreshTaskList} />
109
110 <div className={styles.taskList}>
111 {taskList.map((task) => (
112 <Card key={task._id} className={styles.taskCard}>
113 <div className={styles.taskCardContent}>
114 <div className={styles.taskImageContainer}>
115 <img
116 src={`${FILE_BASE_URL}${task.imageUrl}`}
117 alt={task.title}
118 className={styles.taskImage}
119 />
120 </div>
121
122 <div className={styles.taskInfo}>
123 <div className={styles.taskHeader}>
124 <h3 className={styles.taskTitle}>
125 {task.title}
126 <span className={styles.taskId}>
127 ID: {task._id}
128 <Tooltip title="复制任务ID">
129 <CopyOutlined
130 className={styles.copyIcon}
131 onClick={() => copyTaskId(task._id)}
132 />
133 </Tooltip>
134 </span>
135 </h3>
136 <Tag color="#a66ae4" className={styles.taskTag}>
137 {(task.dataInfo as any)?.type || '推广APP'}
138 </Tag>
139 </div>
140
141 <div
142 className={styles.taskDescription}
143 dangerouslySetInnerHTML={{
144 __html: task.description || '扫二维码下载APP并完成注册任务',
145 }}
146 />
147
148 <div className={styles.taskDetails}>
149 <div className={styles.taskDetail}>
150 <ClockCircleOutlined className={styles.detailIcon} />
151 <span className={styles.detailLabel}>截止时间:</span>
152 <span className={styles.detailValue}>
153 {formatDate(task.deadline)}
154 </span>
155 </div>
156
157 <div className={styles.taskDetail}>
158 <TeamOutlined className={styles.detailIcon} />
159 <span className={styles.detailLabel}>招募人数:</span>
160 <span className={styles.detailValue}>
161 {task.maxRecruits || 100}
162 </span>
163 </div>
164 </div>
165
166 <div className={styles.taskRequirement}>
167 <span className={styles.requirementLabel}>任务要求:</span>
168 <span className={styles.requirementValue}>
169 {task.requirement || '扫二维码'}
170 </span>
171 </div>
172 </div>
173
174 <div className={styles.taskAction}>
175 <div className={styles.taskStatus}>
176 <Tag color="#a66ae4">进行中</Tag>
177 </div>
178
179 <div className={styles.taskReward}>
180 <span className={styles.rewardLabel}>每篇可赚</span>
181 <span className={styles.rewardValue}>
182 ¥{task.reward || 5}
183 </span>
184 </div>
185
186 <Button
187 type="primary"
188 className={styles.viewButton}
189 onClick={() => Ref_TaskInfo.current?.init(task)}
190 style={{ backgroundColor: '#a66ae4' }}
191 >
192 去查看 <RightOutlined />
193 </Button>
194 </div>
195 </div>
196 </Card>
197 ))}
198
199 {loading && (
200 <div className={styles.loadingContainer}>
201 <Spin size="large" />
202 </div>
203 )}
204
205 {!loading && hasMore && (
206 <div className={styles.loadMoreContainer}>
207 <Button onClick={loadMore}>查看更多任务</Button>
208 </div>
209 )}
210 </div>
211 </div>
212 );
213 }
214
214 lines Plain Text