feat: add point activities and exchange

This commit is contained in:
Codex
2026-06-30 03:28:11 +08:00
parent e035f5be9a
commit 2fea68fe4d
22 changed files with 2121 additions and 43 deletions

View File

@@ -474,6 +474,88 @@ export interface CouponReport {
daily?: Array<Record<string, unknown>>;
}
export interface PointActivityTaskItem {
id: string;
legacyId?: string | null;
code?: string;
title?: string;
description?: string | null;
taskType?: 'daily_check_in' | 'feedback_submit' | 'feedback_resolved' | 'practice_complete' | 'vocabulary_review' | 'mock_exam_submit' | 'manual';
rewardPoints?: number;
claimLimitPerUser?: number;
periodType?: 'once' | 'daily' | 'weekly' | 'monthly' | 'unlimited';
validFrom?: string | null;
validTo?: string | null;
status?: 'active' | 'disabled' | 'archived';
order?: number;
metadata?: Record<string, unknown>;
claimCount?: number;
claimUserCount?: number;
createdAt?: string;
updatedAt?: string;
}
export interface PointActivityTaskInput {
id?: string;
legacyId?: string | null;
code: string;
title: string;
description?: string | null;
taskType?: PointActivityTaskItem['taskType'];
rewardPoints: number;
claimLimitPerUser?: number;
periodType?: PointActivityTaskItem['periodType'];
validFrom?: string | null;
validTo?: string | null;
status?: PointActivityTaskItem['status'];
order?: number;
metadata?: Record<string, unknown>;
}
export interface PointExchangeItem {
id: string;
legacyId?: string | null;
code?: string;
title?: string;
description?: string | null;
costPoints?: number;
itemType?: 'coupon' | 'manual' | 'asset' | 'custom';
couponId?: string | null;
couponCode?: string | null;
assetId?: string | null;
stockTotal?: number | null;
stockUsed?: number;
stockRemaining?: number | null;
perUserLimit?: number;
validFrom?: string | null;
validTo?: string | null;
status?: 'active' | 'disabled' | 'archived';
order?: number;
metadata?: Record<string, unknown>;
orderCount?: number;
createdAt?: string;
updatedAt?: string;
}
export interface PointExchangeItemInput {
id?: string;
legacyId?: string | null;
code: string;
title: string;
description?: string | null;
costPoints: number;
itemType?: PointExchangeItem['itemType'];
couponId?: string | null;
assetId?: string | null;
stockTotal?: number | null;
perUserLimit?: number;
validFrom?: string | null;
validTo?: string | null;
status?: PointExchangeItem['status'];
order?: number;
metadata?: Record<string, unknown>;
}
export interface CodeBatchItem {
id: string;
name?: string | null;
@@ -1083,6 +1165,49 @@ export async function loadCouponReport(query: {
return apiRequest<{ item?: CouponReport }>('/api/tenant-admin/coupons/report', { query });
}
export async function loadPointActivityTasks(query: { status?: string; taskType?: string; limit?: number } = {}) {
return apiRequest<{ items?: PointActivityTaskItem[] }>('/api/tenant-admin/point-activity-tasks', {
query: { ...query, limit: query.limit || 100 },
});
}
export async function upsertPointActivityTask(input: PointActivityTaskInput) {
return apiRequest<{ item?: PointActivityTaskItem }>('/api/tenant-admin/point-activity-tasks', {
method: 'PUT',
body: input,
});
}
export async function loadPointActivityClaims(query: { taskId?: string; userId?: string; limit?: number } = {}) {
return apiRequest<{ items?: Record<string, unknown>[] }>('/api/tenant-admin/point-activity-claims', {
query: { ...query, limit: query.limit || 100 },
});
}
export async function loadPointExchangeItems(query: { status?: string; itemType?: string; limit?: number } = {}) {
return apiRequest<{ items?: PointExchangeItem[] }>('/api/tenant-admin/point-exchange-items', {
query: { ...query, limit: query.limit || 100 },
});
}
export async function upsertPointExchangeItem(input: PointExchangeItemInput) {
return apiRequest<{ item?: PointExchangeItem }>('/api/tenant-admin/point-exchange-items', {
method: 'PUT',
body: input,
});
}
export async function loadPointExchangeOrders(query: {
itemId?: string;
userId?: string;
status?: 'completed' | 'pending_fulfillment' | 'cancelled';
limit?: number;
} = {}) {
return apiRequest<{ items?: Record<string, unknown>[] }>('/api/tenant-admin/point-exchange-orders', {
query: { ...query, limit: query.limit || 100 },
});
}
export async function loadCodeBatches() {
return apiRequest<{ items?: CodeBatchItem[] }>('/api/tenant-admin/code-batches');
}