import { apiRequest } from "@/shared/api/request"; import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints"; import type { QueryParams } from "@/shared/api/request"; export interface GamePlatformDto { appCode?: string; platformCode: string; platformName: string; status: string; apiBaseUrl: string; // 服务端按 adapterType 选择厂商协议:demo/yomi_v4/leadercc_v1/zeeone_v1/baishun_v1。 adapterType: string; // callbackSecret 由后台列表返回,用于配置页直接核对和轮换厂商 key。 callbackSecret?: string; callbackSecretSet: boolean; callbackIpWhitelist: string[]; // 厂商扩展配置保留 JSON 字符串,后台前端不绑定具体字段结构。 adapterConfigJson: string; sortOrder: number; createdAtMs?: number; updatedAtMs?: number; } export interface GameCatalogDto { appCode?: string; gameId: string; platformCode: string; providerGameId: string; gameName: string; category: string; iconUrl: string; coverUrl: string; launchUrl?: string; launchMode: string; orientation: string; safeHeight: number; minCoin: number; status: string; sortOrder: number; tags: string[]; createdAtMs?: number; updatedAtMs?: number; } export interface GameCatalogPage { items: GameCatalogDto[]; nextCursor?: string; pageSize?: number; serverTimeMs?: number; total?: number; totalPages?: number; } export interface GamePlatformPage { items: GamePlatformDto[]; serverTimeMs?: number; } export interface GameSyncPayload { dryRun?: boolean; status?: string; category?: string; launchMode?: string; minCoin?: number; tags?: string[]; gameListType?: number; providerGameIds?: string[]; } export interface GameSyncResult { platformCode: string; synced: number; dryRun: boolean; items: GameCatalogDto[]; } export type GamePlatformPayload = Omit< GamePlatformDto, "appCode" | "createdAtMs" | "updatedAtMs" | "callbackSecretSet" >; export type GameCatalogPayload = Omit; export interface GameCatalogQuery { platformCode?: string; status?: string; pageSize?: number; cursor?: string; } export function listGamePlatforms(status = ""): Promise { const endpoint = API_ENDPOINTS.listPlatforms; return apiRequest(apiEndpointPath(API_OPERATIONS.listPlatforms), { method: endpoint.method, query: { status }, }).then((page) => ({ ...page, items: (page.items || []).map(normalizePlatform), })); } export function upsertGamePlatform(payload: GamePlatformPayload, platformCode = ""): Promise { const operation = platformCode ? API_OPERATIONS.updatePlatform : API_OPERATIONS.createPlatform; const endpoint = API_ENDPOINTS[operation]; return apiRequest( apiEndpointPath(operation, platformCode ? { platform_code: platformCode } : {}), { body: payload, method: endpoint.method, }, ).then(normalizePlatform); } export function listGameCatalog(query: GameCatalogQuery = {}): Promise { const endpoint = API_ENDPOINTS.listCatalog; return apiRequest(apiEndpointPath(API_OPERATIONS.listCatalog), { method: endpoint.method, query: query as QueryParams, }).then((page) => ({ ...page, items: (page.items || []).map(normalizeCatalog), })); } export function upsertGameCatalog(payload: GameCatalogPayload, gameId = ""): Promise { const operation = gameId ? API_OPERATIONS.updateCatalog : API_OPERATIONS.createCatalog; const endpoint = API_ENDPOINTS[operation]; return apiRequest( apiEndpointPath(operation, gameId ? { game_id: gameId } : {}), { body: payload, method: endpoint.method, }, ).then(normalizeCatalog); } export function setGameStatus(gameId: string, status: string): Promise { const endpoint = API_ENDPOINTS.setGameStatus; return apiRequest( apiEndpointPath(API_OPERATIONS.setGameStatus, { game_id: gameId }), { body: { status }, method: endpoint.method, }, ).then(normalizeCatalog); } export function deleteGameCatalog(gameId: string): Promise { const endpoint = API_ENDPOINTS.deleteCatalog; return apiRequest(apiEndpointPath(API_OPERATIONS.deleteCatalog, { game_id: gameId }), { method: endpoint.method, }); } export function syncGamePlatformCatalog(platformCode: string, payload: GameSyncPayload = {}): Promise { return apiRequest( `/v1/admin/game/platforms/${encodeURIComponent(platformCode)}/sync-games`, { body: payload, method: "POST", }, ).then((result) => ({ ...result, items: (result.items || []).map(normalizeCatalog), synced: numberValue(result.synced), dryRun: Boolean(result.dryRun), })); } function normalizePlatform(platform: Partial): GamePlatformDto { return { appCode: stringValue(platform.appCode), platformCode: stringValue(platform.platformCode), platformName: stringValue(platform.platformName), status: stringValue(platform.status || "active"), apiBaseUrl: stringValue(platform.apiBaseUrl), adapterType: stringValue(platform.adapterType || "demo"), callbackSecret: stringValue(platform.callbackSecret), callbackSecretSet: Boolean(platform.callbackSecretSet), callbackIpWhitelist: Array.isArray(platform.callbackIpWhitelist) ? platform.callbackIpWhitelist.map(String).filter(Boolean) : [], adapterConfigJson: stringValue(platform.adapterConfigJson || "{}"), sortOrder: numberValue(platform.sortOrder), createdAtMs: numberValue(platform.createdAtMs), updatedAtMs: numberValue(platform.updatedAtMs), }; } function normalizeCatalog(game: Partial): GameCatalogDto { return { appCode: stringValue(game.appCode), gameId: stringValue(game.gameId), platformCode: stringValue(game.platformCode), providerGameId: stringValue(game.providerGameId), gameName: stringValue(game.gameName), category: stringValue(game.category), iconUrl: stringValue(game.iconUrl), coverUrl: stringValue(game.coverUrl), launchUrl: stringValue(game.launchUrl), launchMode: normalizeLaunchMode(game.launchMode), orientation: stringValue(game.orientation || "portrait"), safeHeight: numberValue(game.safeHeight), minCoin: numberValue(game.minCoin), status: stringValue(game.status || "active"), sortOrder: numberValue(game.sortOrder), tags: Array.isArray(game.tags) ? game.tags.map(String).filter(Boolean) : [], createdAtMs: numberValue(game.createdAtMs), updatedAtMs: numberValue(game.updatedAtMs), }; } function stringValue(value: unknown) { return typeof value === "string" ? value : value === undefined || value === null ? "" : String(value); } function numberValue(value: unknown) { const number = Number(value || 0); return Number.isFinite(number) ? number : 0; } function normalizeLaunchMode(value: unknown) { const mode = stringValue(value); return mode === "half_screen" || mode === "three_quarter_screen" || mode === "full_screen" ? mode : "full_screen"; }