diff --git a/contracts/admin-openapi.json b/contracts/admin-openapi.json index 615e952..fd13df1 100644 --- a/contracts/admin-openapi.json +++ b/contracts/admin-openapi.json @@ -4556,6 +4556,27 @@ ] } }, + "/integrations/withdrawal-applications": { + "post": { + "operationId": "createExternalWithdrawalApplication", + "description": "来源钱包使用 App 独立 Bearer token 幂等提交提现申请,不使用后台用户 JWT。", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExternalWithdrawalApplicationInput" + } + } + } + }, + "responses": { + "201": { + "$ref": "#/components/responses/FinanceWithdrawalApplicationResponse" + } + } + } + }, "/admin/finance/withdrawal-applications": { "get": { "operationId": "listFinanceWithdrawalApplications", @@ -14288,6 +14309,14 @@ "appName": { "type": "string" }, + "sourceSystem": { + "type": "string", + "description": "资金执行来源;hyapp_wallet 为平台钱包,likei 为 Aslan legacy 钱包" + }, + "sourceApplicationId": { + "type": "string", + "description": "来源钱包的提现申请号,用于跨系统审计和幂等回调" + }, "userId": { "type": "string" }, @@ -14362,6 +14391,32 @@ } } }, + "ExternalWithdrawalApplicationInput": { + "type": "object", + "required": [ + "appCode", + "sourceSystem", + "sourceApplicationId", + "userId", + "salaryAssetType", + "withdrawAmount", + "withdrawAmountMinor", + "withdrawMethod", + "withdrawAddress" + ], + "properties": { + "appCode": { "type": "string" }, + "sourceSystem": { "type": "string" }, + "sourceApplicationId": { "type": "string" }, + "userId": { "type": "string" }, + "salaryAssetType": { "type": "string" }, + "withdrawAmount": { "type": "string" }, + "withdrawAmountMinor": { "type": "integer", "minimum": 1 }, + "withdrawMethod": { "type": "string" }, + "withdrawAddress": { "type": "string" }, + "createdAtMs": { "type": "integer", "format": "int64" } + } + }, "FinanceCoinSellerRechargeOrderInput": { "type": "object", "required": ["appCode", "targetUserId", "usdAmount", "providerCode", "externalOrderNo"], diff --git a/finance/src/components/FinanceWithdrawalApplicationList.jsx b/finance/src/components/FinanceWithdrawalApplicationList.jsx index 97926ac..c057974 100644 --- a/finance/src/components/FinanceWithdrawalApplicationList.jsx +++ b/finance/src/components/FinanceWithdrawalApplicationList.jsx @@ -73,6 +73,7 @@ export function FinanceWithdrawalApplicationList({ APP + 来源单号 用户ID 提现金额 提现方式 @@ -107,6 +108,12 @@ export function FinanceWithdrawalApplicationList({ size="small" /> + + + {item.userId || "-"} $ {formatAmount(item.withdrawAmount)} {item.withdrawMethod || "-"} @@ -214,7 +221,7 @@ export function FinanceWithdrawalApplicationList({ )) ) : ( - + 当前无数据 @@ -240,6 +247,16 @@ export function FinanceWithdrawalApplicationList({ ); } +function sourceSystemLabel(value) { + if (!value || value === "hyapp_wallet") { + return "HY 钱包"; + } + if (value === "likei") { + return "Likei"; + } + return value; +} + function ReviewContext({ application }) { return ( diff --git a/finance/src/components/FinanceWithdrawalApplicationList.test.jsx b/finance/src/components/FinanceWithdrawalApplicationList.test.jsx index f145c4c..e6bf048 100644 --- a/finance/src/components/FinanceWithdrawalApplicationList.test.jsx +++ b/finance/src/components/FinanceWithdrawalApplicationList.test.jsx @@ -50,6 +50,8 @@ test("renders withdrawal application table with requested finance columns", () = operationsReviewerName: "运营一", operationsReviewerUserId: 11, operationsStatus: "approved", + sourceApplicationId: "991001", + sourceSystem: "likei", status: "approved", userId: "10001", withdrawAddress: "TRX-address", @@ -62,6 +64,7 @@ test("renders withdrawal application table with requested finance columns", () = }); expect(screen.getByRole("columnheader", { name: "APP" })).toBeInTheDocument(); + expect(screen.getByRole("columnheader", { name: "来源单号" })).toBeInTheDocument(); expect(screen.getByRole("columnheader", { name: "用户ID" })).toBeInTheDocument(); expect(screen.getByRole("columnheader", { name: "提现金额" })).toBeInTheDocument(); expect(screen.getByRole("columnheader", { name: "提现方式" })).toBeInTheDocument(); @@ -73,6 +76,8 @@ test("renders withdrawal application table with requested finance columns", () = expect(screen.getByRole("columnheader", { name: "财务审核原因" })).toBeInTheDocument(); expect(screen.getByRole("columnheader", { name: "操作" })).toBeInTheDocument(); expect(screen.getByText("lalu")).toBeInTheDocument(); + expect(screen.getByText("Likei")).toBeInTheDocument(); + expect(screen.getByText("991001")).toBeInTheDocument(); expect(screen.getByText("10001")).toBeInTheDocument(); expect(screen.getByText("$ 12.5")).toBeInTheDocument(); expect(screen.getByText("USDT-TRC20")).toBeInTheDocument(); @@ -88,7 +93,7 @@ test("renders withdrawal application table with requested finance columns", () = test("keeps empty withdrawal table colspan aligned with visible columns", () => { const { container } = renderList(baseProps); - expect(container.querySelector("tbody td")?.colSpan).toBe(11); + expect(container.querySelector("tbody td")?.colSpan).toBe(12); expect(screen.getByText("当前无数据")).toBeInTheDocument(); }); diff --git a/finance/src/format.js b/finance/src/format.js index e6cd2a8..9d6ccc1 100644 --- a/finance/src/format.js +++ b/finance/src/format.js @@ -31,6 +31,8 @@ export function normalizeWithdrawalApplication(item = {}) { operationsReviewerUserId: item.operationsReviewerUserId ?? item.operations_reviewer_user_id, operationsStatus: stringValue(item.operationsStatus ?? item.operations_status), salaryAssetType: stringValue(item.salaryAssetType ?? item.salary_asset_type), + sourceApplicationId: stringValue(item.sourceApplicationId ?? item.source_application_id), + sourceSystem: stringValue(item.sourceSystem ?? item.source_system), status: stringValue(item.status), updatedAtMs: numberOrNull(item.updatedAtMs ?? item.updated_at_ms), userId: stringValue(item.userId ?? item.user_id), diff --git a/src/shared/api/generated/endpoints.ts b/src/shared/api/generated/endpoints.ts index ec27259..556cc35 100644 --- a/src/shared/api/generated/endpoints.ts +++ b/src/shared/api/generated/endpoints.ts @@ -54,6 +54,7 @@ export const API_OPERATIONS = { createEmojiPack: "createEmojiPack", createExploreTab: "createExploreTab", createExternalAdminUser: "createExternalAdminUser", + createExternalWithdrawalApplication: "createExternalWithdrawalApplication", createFinanceCoinSellerRechargeOrder: "createFinanceCoinSellerRechargeOrder", createFullServerNoticeFanout: "createFullServerNoticeFanout", createGift: "createGift", @@ -712,6 +713,11 @@ export const API_ENDPOINTS: Record = { permission: "external-admin-user:create", permissions: ["external-admin-user:create","external-admin-user:permissions"] }, + createExternalWithdrawalApplication: { + method: "POST", + operationId: API_OPERATIONS.createExternalWithdrawalApplication, + path: "/v1/integrations/withdrawal-applications" + }, createFinanceCoinSellerRechargeOrder: { method: "POST", operationId: API_OPERATIONS.createFinanceCoinSellerRechargeOrder, diff --git a/src/shared/api/generated/schema.d.ts b/src/shared/api/generated/schema.d.ts index d72578d..a4643b9 100644 --- a/src/shared/api/generated/schema.d.ts +++ b/src/shared/api/generated/schema.d.ts @@ -2636,6 +2636,23 @@ export interface paths { patch?: never; trace?: never; }; + "/integrations/withdrawal-applications": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** @description 来源钱包使用 App 独立 Bearer token 幂等提交提现申请,不使用后台用户 JWT。 */ + post: operations["createExternalWithdrawalApplication"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/admin/finance/withdrawal-applications": { parameters: { query?: never; @@ -6652,6 +6669,10 @@ export interface components { id: number; appCode: string; appName?: string; + /** @description 资金执行来源;hyapp_wallet 为平台钱包,likei 为 Aslan legacy 钱包 */ + sourceSystem?: string; + /** @description 来源钱包的提现申请号,用于跨系统审计和幂等回调 */ + sourceApplicationId?: string; userId: string; salaryAssetType?: string; withdrawAmount: string; @@ -6679,6 +6700,19 @@ export interface components { createdAtMs: number; updatedAtMs?: number; }; + ExternalWithdrawalApplicationInput: { + appCode: string; + sourceSystem: string; + sourceApplicationId: string; + userId: string; + salaryAssetType: string; + withdrawAmount: string; + withdrawAmountMinor: number; + withdrawMethod: string; + withdrawAddress: string; + /** Format: int64 */ + createdAtMs?: number; + }; FinanceCoinSellerRechargeOrderInput: { appCode: string; targetUserId: string; @@ -11482,6 +11516,22 @@ export interface operations { 200: components["responses"]["FinanceScopeCatalogResponse"]; }; }; + createExternalWithdrawalApplication: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ExternalWithdrawalApplicationInput"]; + }; + }; + responses: { + 201: components["responses"]["FinanceWithdrawalApplicationResponse"]; + }; + }; listFinanceWithdrawalApplications: { parameters: { query?: {