feat: 后台抽奖活动管理(Stage 1)
- 服务层:12 个 /v1/admin/lottery 接口封装与 API 类型定义 - 活动列表:状态筛选、上架/暂停(带确认)、编辑、管理、发次数 - 奖品管理:3×3 九宫格可视化编辑、概率预览、保底奖警告、佣金元↔分转换、无限库存 - 规则设置:chance_sources 动态编辑,eligibility 简单/高级(JSON)双模式,本地 rulecaps 校验(深度≤8/节点≤64/≤8KB),Stage 1 未接线警示 - 手动发次数:自动生成幂等 source_ref - 路由 /dashboard/lottery、Commerce 菜单项、en-US/zh-CN 双语文案 - 对接文档见 vpn/aaaa.txt(Stage 1)
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
/* eslint-disable */
|
||||
import request from "@workspace/ui/lib/request";
|
||||
|
||||
/**
|
||||
* 创建抽奖活动
|
||||
* POST /v1/admin/lottery/activities
|
||||
* @param body - 创建抽奖活动请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 创建结果
|
||||
*/
|
||||
export async function createLotteryActivity(
|
||||
body: API.CreateLotteryActivityRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: API.LotteryActivity }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/activities`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新抽奖活动
|
||||
* PUT /v1/admin/lottery/activities
|
||||
* @param body - 更新抽奖活动请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 更新结果
|
||||
*/
|
||||
export async function updateLotteryActivity(
|
||||
body: API.UpdateLotteryActivityRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: API.LotteryActivity }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/activities`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取抽奖活动分页列表
|
||||
* GET /v1/admin/lottery/activities
|
||||
* @param params - 分页及筛选参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 抽奖活动列表及总数
|
||||
*/
|
||||
export async function getLotteryActivityList(
|
||||
params: API.GetLotteryActivityListParams,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: API.GetLotteryActivityListResponse }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/activities`,
|
||||
{
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取抽奖活动详情
|
||||
* GET /v1/admin/lottery/activities/detail
|
||||
* @param params - 活动 ID 参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 抽奖活动详情
|
||||
*/
|
||||
export async function getLotteryActivityDetail(
|
||||
params: API.GetLotteryActivityDetailParams,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: API.LotteryActivity }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/activities/detail`,
|
||||
{
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上架抽奖活动(draft → running)
|
||||
* POST /v1/admin/lottery/activities/publish
|
||||
* @param body - 上架活动请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 上架结果
|
||||
*/
|
||||
export async function publishLotteryActivity(
|
||||
body: API.PublishLotteryActivityRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: any }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/activities/publish`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停抽奖活动
|
||||
* POST /v1/admin/lottery/activities/pause
|
||||
* @param body - 暂停活动请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 暂停结果
|
||||
*/
|
||||
export async function pauseLotteryActivity(
|
||||
body: API.PauseLotteryActivityRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: any }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/activities/pause`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新抽奖活动规则(eligibility + chance_sources)
|
||||
* PUT /v1/admin/lottery/activities/rules
|
||||
* @param body - 更新活动规则请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 更新结果
|
||||
*/
|
||||
export async function updateLotteryActivityRules(
|
||||
body: API.UpdateLotteryActivityRulesRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: any }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/activities/rules`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建抽奖奖品
|
||||
* POST /v1/admin/lottery/prizes
|
||||
* @param body - 创建奖品请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 创建结果
|
||||
*/
|
||||
export async function createLotteryPrize(
|
||||
body: API.CreateLotteryPrizeRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: API.LotteryPrize }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/prizes`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新抽奖奖品
|
||||
* PUT /v1/admin/lottery/prizes
|
||||
* @param body - 更新奖品请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 更新结果
|
||||
*/
|
||||
export async function updateLotteryPrize(
|
||||
body: API.UpdateLotteryPrizeRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: API.LotteryPrize }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/prizes`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除抽奖奖品
|
||||
* DELETE /v1/admin/lottery/prizes
|
||||
* @param body - 删除奖品请求参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 删除结果
|
||||
*/
|
||||
export async function deleteLotteryPrize(
|
||||
body: API.DeleteLotteryPrizeRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: any }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/prizes`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取抽奖奖品列表
|
||||
* GET /v1/admin/lottery/prizes
|
||||
* @param params - 活动 ID 筛选参数
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 奖品列表
|
||||
*/
|
||||
export async function getLotteryPrizeList(
|
||||
params: API.GetLotteryPrizeListParams,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: API.GetLotteryPrizeListResponse }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/prizes`,
|
||||
{
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动发放抽奖次数
|
||||
* POST /v1/admin/lottery/chances/grant
|
||||
* @param body - 发放次数请求参数(source_ref 为幂等键)
|
||||
* @param options - 可选的请求配置
|
||||
* @returns 发放结果
|
||||
*/
|
||||
export async function grantLotteryChances(
|
||||
body: API.GrantLotteryChancesRequest,
|
||||
options?: { [key: string]: any }
|
||||
) {
|
||||
return request<API.Response & { data?: any }>(
|
||||
`${import.meta.env.VITE_API_PREFIX || ""}/v1/admin/lottery/chances/grant`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
}
|
||||
);
|
||||
}
|
||||
+115
@@ -3300,4 +3300,119 @@ declare namespace API {
|
||||
};
|
||||
|
||||
type AdminWithdrawalLog = WithdrawalLog;
|
||||
|
||||
type LotteryPrizeType =
|
||||
| 'vpn_duration'
|
||||
| 'commission'
|
||||
| 'none'
|
||||
| 'crypto'
|
||||
| 'physical'
|
||||
| 'manual_other'
|
||||
| 'coupon'
|
||||
| 'points';
|
||||
|
||||
type LotteryActivityStatus = 'draft' | 'running' | 'paused' | 'ended';
|
||||
|
||||
type LotteryChanceSourceType =
|
||||
| 'daily_signin'
|
||||
| 'new_subscription'
|
||||
| 'invite_success'
|
||||
| 'manual_grant';
|
||||
|
||||
type LotteryEligibilityNode = {
|
||||
op?: 'AND' | 'OR';
|
||||
children?: LotteryEligibilityNode[];
|
||||
type?: string;
|
||||
params?: Record<string, any>;
|
||||
};
|
||||
|
||||
type LotteryChanceSource = {
|
||||
source: LotteryChanceSourceType;
|
||||
amount: number;
|
||||
daily_limit?: number;
|
||||
};
|
||||
|
||||
type LotteryPrize = {
|
||||
id: number;
|
||||
activity_id: number;
|
||||
slot: number;
|
||||
type: LotteryPrizeType;
|
||||
name: string;
|
||||
icon_url: string;
|
||||
config: Record<string, any>;
|
||||
weight: number;
|
||||
total_stock: number | null;
|
||||
is_fallback: boolean;
|
||||
sold_out?: boolean;
|
||||
};
|
||||
|
||||
type LotteryActivity = {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
start_at: number; // Unix 秒
|
||||
end_at: number; // Unix 秒
|
||||
status: LotteryActivityStatus;
|
||||
grid_size: number;
|
||||
eligibility?: LotteryEligibilityNode | Record<string, never> | null;
|
||||
chance_sources?: LotteryChanceSource[];
|
||||
unmet_action?: string;
|
||||
prizes?: LotteryPrize[];
|
||||
};
|
||||
|
||||
type CreateLotteryActivityRequest = {
|
||||
title: string;
|
||||
description: string;
|
||||
start_at: number;
|
||||
end_at: number;
|
||||
grid_size: number;
|
||||
eligibility: LotteryEligibilityNode | Record<string, never> | null;
|
||||
chance_sources: LotteryChanceSource[];
|
||||
unmet_action: string;
|
||||
};
|
||||
|
||||
type UpdateLotteryActivityRequest = CreateLotteryActivityRequest & { id: number };
|
||||
|
||||
type GetLotteryActivityListParams = { page: number; size: number; status?: string };
|
||||
|
||||
type GetLotteryActivityListResponse = { total: number; list: LotteryActivity[] };
|
||||
|
||||
type GetLotteryActivityDetailParams = { id: number };
|
||||
|
||||
type PublishLotteryActivityRequest = { id: number };
|
||||
|
||||
type PauseLotteryActivityRequest = { id: number };
|
||||
|
||||
type UpdateLotteryActivityRulesRequest = {
|
||||
id: number;
|
||||
eligibility: LotteryEligibilityNode | Record<string, never> | null;
|
||||
chance_sources: LotteryChanceSource[];
|
||||
};
|
||||
|
||||
type CreateLotteryPrizeRequest = {
|
||||
activity_id: number;
|
||||
slot: number;
|
||||
type: LotteryPrizeType;
|
||||
name: string;
|
||||
icon_url: string;
|
||||
config: Record<string, any>;
|
||||
weight: number;
|
||||
total_stock: number | null;
|
||||
is_fallback: boolean;
|
||||
};
|
||||
|
||||
type UpdateLotteryPrizeRequest = CreateLotteryPrizeRequest & { id: number };
|
||||
|
||||
type DeleteLotteryPrizeRequest = { id: number };
|
||||
|
||||
type GetLotteryPrizeListParams = { activity_id: number };
|
||||
|
||||
type GetLotteryPrizeListResponse = { total?: number; list: LotteryPrize[] };
|
||||
|
||||
type GrantLotteryChancesRequest = {
|
||||
activity_id: number;
|
||||
user_id: number;
|
||||
amount: number;
|
||||
source_ref: string;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user