增加活动页面
Change-Id: I63cf84e250d16b2af401f335562fcadd3be13170
diff --git a/react-ui/src/pages/Activity/service.ts b/react-ui/src/pages/Activity/service.ts
new file mode 100644
index 0000000..25c1d9a
--- /dev/null
+++ b/react-ui/src/pages/Activity/service.ts
@@ -0,0 +1,219 @@
+// service.ts - 活动系统服务层文件
+
+import { request } from '@umijs/max';
+import type {
+ GetActivityListResponse,
+ GetLeaderboardResponse,
+ ParticipateActivityResponse,
+ ActivityListParams,
+ LeaderboardParams,
+ SysActivity,
+ LeaderboardEntry,
+ StandardizedActivityListResponse,
+ StandardizedLeaderboardResponse
+} from './data';
+
+// 开发环境模拟数据开关
+const USE_MOCK = process.env.NODE_ENV === 'development' && false;
+
+// 模拟活动数据 - 适配后端格式
+const mockActivities: SysActivity[] = [
+ {
+ createBy: null,
+ createTime: null,
+ updateBy: null,
+ updateTime: null,
+ remark: null,
+ activityId: 1,
+ activityName: '新手上传挑战',
+ rewardBonus: 100,
+ conditionValue: '10GB',
+ startTime: '2025-06-01T00:00:00.000+08:00',
+ endTime: '2025-06-30T23:59:59.000+08:00',
+ status: 1,
+ activityType: 'UPLOAD'
+ },
+ {
+ createBy: null,
+ createTime: null,
+ updateBy: null,
+ updateTime: null,
+ remark: null,
+ activityId: 2,
+ activityName: '种子下载任务',
+ rewardBonus: 50,
+ conditionValue: '94',
+ startTime: '2025-06-01T00:00:00.000+08:00',
+ endTime: '2025-06-15T23:59:59.000+08:00',
+ status: 1,
+ activityType: 'DOWNLOAD'
+ }
+];
+
+// 模拟排行榜数据
+const mockLeaderboard: LeaderboardEntry[] = [
+ { userId: 1, userName: 'user001', score: 1500 },
+ { userId: 2, userName: 'user002', score: 1200 },
+ { userId: 3, userName: 'user003', score: 1000 }
+];
+
+/**
+ * 时间格式转换工具函数
+ * 将 ISO 8601 格式转换为显示格式
+ */
+export function formatDateTime(isoString: string): string {
+ const date = new Date(isoString);
+ return date.toLocaleString('zh-CN', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit',
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit'
+ }).replace(/\//g, '-');
+}
+
+/**
+ * 数据格式标准化函数
+ * 将后端返回格式转换为前端组件期望的格式
+ */
+function normalizeActivityListResponse(
+ backendResponse: GetActivityListResponse,
+ params?: ActivityListParams
+): StandardizedActivityListResponse {
+ return {
+ code: backendResponse.code === 200 ? 0 : backendResponse.code, // 后端成功码是200,前端期望0
+ msg: backendResponse.msg,
+ data: {
+ list: backendResponse.rows,
+ total: backendResponse.total,
+ pageSize: params?.pageSize || 10,
+ current: params?.pageNum || 1,
+ }
+ };
+}
+
+function normalizeLeaderboardResponse(
+ backendResponse: GetLeaderboardResponse,
+ params?: LeaderboardParams
+): StandardizedLeaderboardResponse {
+ return {
+ code: backendResponse.code === 200 ? 0 : backendResponse.code,
+ msg: backendResponse.msg,
+ data: {
+ list: backendResponse.rows,
+ total: backendResponse.total,
+ pageSize: params?.pageSize || 10,
+ current: params?.pageNum || 1,
+ }
+ };
+}
+
+/**
+ * 获取活动列表
+ */
+export async function getActivityList(params?: ActivityListParams): Promise<StandardizedActivityListResponse> {
+ if (USE_MOCK) {
+ let filteredList = mockActivities;
+
+ // 按状态筛选
+ if (params?.status !== undefined) {
+ filteredList = filteredList.filter(item => item.status === params.status);
+ }
+
+ // 按活动类型筛选
+ if (params?.activityType) {
+ filteredList = filteredList.filter(item => item.activityType === params.activityType);
+ }
+
+ // 按活动名称搜索
+ if (params?.activityName) {
+ filteredList = filteredList.filter(item =>
+ item.activityName.includes(params.activityName!)
+ );
+ }
+
+ // 模拟后端返回格式
+ const mockBackendResponse: GetActivityListResponse = {
+ total: filteredList.length,
+ rows: filteredList,
+ code: 200,
+ msg: '查询成功'
+ };
+
+ return normalizeActivityListResponse(mockBackendResponse, params);
+ }
+
+ try {
+ // 调用实际后端接口
+ const response: GetActivityListResponse = await request('/api/system/activity/list', {
+ method: 'GET',
+ params: {
+ pageNum: params?.pageNum,
+ pageSize: params?.pageSize,
+ activityName: params?.activityName,
+ activityType: params?.activityType,
+ status: params?.status,
+ },
+ });
+
+ // 标准化响应格式
+ return normalizeActivityListResponse(response, params);
+ } catch (error) {
+ console.error('获取活动列表失败:', error);
+ throw error;
+ }
+}
+
+/**
+ * 参与活动
+ */
+export async function participateActivity(activityId: number): Promise<ParticipateActivityResponse> {
+ if (USE_MOCK) {
+ return Promise.resolve({
+ code: 0,
+ msg: '参与成功',
+ data: null,
+ });
+ }
+
+ try {
+ return await request(`/api/system/activity/participate/${activityId}`, {
+ method: 'POST',
+ });
+ } catch (error) {
+ console.error('参与活动失败:', error);
+ throw error;
+ }
+}
+
+/**
+ * 获取排行榜
+ */
+export async function getLeaderboard(params?: LeaderboardParams): Promise<StandardizedLeaderboardResponse> {
+ if (USE_MOCK) {
+ const mockBackendResponse: GetLeaderboardResponse = {
+ total: mockLeaderboard.length,
+ rows: mockLeaderboard,
+ code: 200,
+ msg: '查询成功'
+ };
+
+ return normalizeLeaderboardResponse(mockBackendResponse, params);
+ }
+
+ try {
+ const response: GetLeaderboardResponse = await request('/api/system/activity/leaderboard', {
+ method: 'GET',
+ params: {
+ pageNum: params?.pageNum,
+ pageSize: params?.pageSize,
+ },
+ });
+
+ return normalizeLeaderboardResponse(response, params);
+ } catch (error) {
+ console.error('获取排行榜失败:', error);
+ throw error;
+ }
+}
\ No newline at end of file