送礼记录
This commit is contained in:
parent
59901a3cab
commit
da6d2dfdb9
@ -3206,6 +3206,71 @@
|
|||||||
"x-permissions": ["coin-adjustment:create"]
|
"x-permissions": ["coin-adjustment:create"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/operations/gift-records": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "listGiftRecords",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/components/responses/GiftRecordPageResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/Page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/PageSize"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scene",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["room", "direct"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sender_display_user_id",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sender_user_id",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sender_username",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "start_at_ms",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "end_at_ms",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"x-permission": "gift-record:view",
|
||||||
|
"x-permissions": ["gift-record:view"]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/operations/coin-ledger": {
|
"/admin/operations/coin-ledger": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "listCoinLedger",
|
"operationId": "listCoinLedger",
|
||||||
@ -7810,6 +7875,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"GiftRecordPageResponse": {
|
||||||
|
"description": "OK",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ApiResponseGiftRecordPage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"BDProfilePageResponse": {
|
"BDProfilePageResponse": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"content": {
|
"content": {
|
||||||
@ -9289,6 +9364,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ApiPageGiftRecord": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["items", "page", "pageSize", "total"],
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/GiftRecord"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"pageSize": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ApiPageBDProfile": {
|
"ApiPageBDProfile": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["items", "page", "pageSize", "total"],
|
"required": ["items", "page", "pageSize", "total"],
|
||||||
@ -9669,6 +9765,21 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"ApiResponseGiftRecordPage": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Envelope"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/components/schemas/ApiPageGiftRecord"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ApiResponseBDProfilePage": {
|
"ApiResponseBDProfilePage": {
|
||||||
"allOf": [
|
"allOf": [
|
||||||
{
|
{
|
||||||
@ -10878,6 +10989,99 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"GiftRecordUser": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["userId"],
|
||||||
|
"properties": {
|
||||||
|
"avatar": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"defaultDisplayUserId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"displayUserId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"prettyDisplayUserId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"prettyId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"GiftRecordGift": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["giftId", "name", "coverUrl"],
|
||||||
|
"properties": {
|
||||||
|
"coverUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"giftId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"GiftRecord": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"transactionId",
|
||||||
|
"scene",
|
||||||
|
"sender",
|
||||||
|
"receiver",
|
||||||
|
"gift",
|
||||||
|
"giftCount",
|
||||||
|
"unitValue",
|
||||||
|
"giftValue",
|
||||||
|
"createdAtMs"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"createdAtMs": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"gift": {
|
||||||
|
"$ref": "#/components/schemas/GiftRecordGift"
|
||||||
|
},
|
||||||
|
"giftCount": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"giftValue": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"receiver": {
|
||||||
|
"$ref": "#/components/schemas/GiftRecordUser"
|
||||||
|
},
|
||||||
|
"roomId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"scene": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["room", "direct"]
|
||||||
|
},
|
||||||
|
"sender": {
|
||||||
|
"$ref": "#/components/schemas/GiftRecordUser"
|
||||||
|
},
|
||||||
|
"transactionId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"unitValue": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"CoinLedgerUser": {
|
"CoinLedgerUser": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["userId"],
|
"required": ["userId"],
|
||||||
|
|||||||
@ -186,6 +186,7 @@ export const fallbackNavigation = [
|
|||||||
id: "operations",
|
id: "operations",
|
||||||
label: "运营管理",
|
label: "运营管理",
|
||||||
children: [
|
children: [
|
||||||
|
routeNavItem("operation-gift-records", { icon: CardGiftcardOutlined }),
|
||||||
routeNavItem("operation-coin-ledger", { icon: ReceiptLongOutlined }),
|
routeNavItem("operation-coin-ledger", { icon: ReceiptLongOutlined }),
|
||||||
routeNavItem("operation-coin-seller-ledger", { icon: ReceiptLongOutlined }),
|
routeNavItem("operation-coin-seller-ledger", { icon: ReceiptLongOutlined }),
|
||||||
routeNavItem("operation-coin-adjustment", { icon: WalletOutlined }),
|
routeNavItem("operation-coin-adjustment", { icon: WalletOutlined }),
|
||||||
|
|||||||
@ -57,6 +57,7 @@ export const PERMISSIONS = {
|
|||||||
financeOrderCoinSellerRechargeGrant: "finance-order:coin-seller-recharge:grant",
|
financeOrderCoinSellerRechargeGrant: "finance-order:coin-seller-recharge:grant",
|
||||||
coinLedgerView: "coin-ledger:view",
|
coinLedgerView: "coin-ledger:view",
|
||||||
coinSellerLedgerView: "coin-seller-ledger:view",
|
coinSellerLedgerView: "coin-seller-ledger:view",
|
||||||
|
giftRecordView: "gift-record:view",
|
||||||
coinAdjustmentView: "coin-adjustment:view",
|
coinAdjustmentView: "coin-adjustment:view",
|
||||||
coinAdjustmentCreate: "coin-adjustment:create",
|
coinAdjustmentCreate: "coin-adjustment:create",
|
||||||
reportView: "report:view",
|
reportView: "report:view",
|
||||||
@ -250,6 +251,7 @@ export const MENU_CODES = {
|
|||||||
operations: "operations",
|
operations: "operations",
|
||||||
operationCoinLedger: "operation-coin-ledger",
|
operationCoinLedger: "operation-coin-ledger",
|
||||||
operationCoinSellerLedger: "operation-coin-seller-ledger",
|
operationCoinSellerLedger: "operation-coin-seller-ledger",
|
||||||
|
operationGiftRecords: "operation-gift-records",
|
||||||
operationCoinAdjustment: "operation-coin-adjustment",
|
operationCoinAdjustment: "operation-coin-adjustment",
|
||||||
operationReports: "operation-reports",
|
operationReports: "operation-reports",
|
||||||
operationGiftDiamond: "operation-gift-diamond",
|
operationGiftDiamond: "operation-gift-diamond",
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export interface GamePlatformDto {
|
|||||||
platformName: string;
|
platformName: string;
|
||||||
status: string;
|
status: string;
|
||||||
apiBaseUrl: string;
|
apiBaseUrl: string;
|
||||||
// 服务端按 adapterType 选择真实厂商协议:yomi_v4/leadercc_v1/zeeone_v1/baishun_v1/vivagames_v1/reyou_v1。
|
// 服务端按 adapterType 选择真实厂商协议;AMG 使用 amg_v1,RSA 私钥仍通过 callbackSecret 单独提交。
|
||||||
adapterType: string;
|
adapterType: string;
|
||||||
// callbackSecret 由后台列表返回,用于配置页直接核对和轮换厂商 key。
|
// callbackSecret 由后台列表返回,用于配置页直接核对和轮换厂商 key。
|
||||||
callbackSecret?: string;
|
callbackSecret?: string;
|
||||||
|
|||||||
@ -65,6 +65,7 @@ const writableBridgeAdapterTypes = new Set([
|
|||||||
"vivagames_v1",
|
"vivagames_v1",
|
||||||
"reyou_v1",
|
"reyou_v1",
|
||||||
"zgame_v1",
|
"zgame_v1",
|
||||||
|
"amg_v1",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const emptyCatalog = { items: [], pageSize: 50 };
|
const emptyCatalog = { items: [], pageSize: 50 };
|
||||||
|
|||||||
@ -54,6 +54,7 @@ const adapterTypeOptions = [
|
|||||||
["vivagames_v1", "VIVAGAMES V1"],
|
["vivagames_v1", "VIVAGAMES V1"],
|
||||||
["reyou_v1", "热游 Reyou V1"],
|
["reyou_v1", "热游 Reyou V1"],
|
||||||
["zgame_v1", "ZGame V1"],
|
["zgame_v1", "ZGame V1"],
|
||||||
|
["amg_v1", "AMG V1"],
|
||||||
];
|
];
|
||||||
|
|
||||||
const baseColumns = [
|
const baseColumns = [
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import {
|
|||||||
listCoinLedger,
|
listCoinLedger,
|
||||||
listCoinAdjustments,
|
listCoinAdjustments,
|
||||||
listCoinSellerLedger,
|
listCoinSellerLedger,
|
||||||
|
listGiftRecords,
|
||||||
listWheelDraws,
|
listWheelDraws,
|
||||||
lookupCoinAdjustmentTarget,
|
lookupCoinAdjustmentTarget,
|
||||||
updateGiftDiamondRatios,
|
updateGiftDiamondRatios,
|
||||||
@ -110,6 +111,36 @@ test("coin ledger API sends type filter", async () => {
|
|||||||
expect(listInit?.method).toBe("GET");
|
expect(listInit?.method).toBe("GET");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("gift record API uses generated path with sender, scene and UTC range filters", async () => {
|
||||||
|
vi.stubGlobal(
|
||||||
|
"fetch",
|
||||||
|
vi.fn(
|
||||||
|
async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 30, total: 0 } })),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await listGiftRecords({
|
||||||
|
end_at_ms: 2000,
|
||||||
|
page: 1,
|
||||||
|
page_size: 30,
|
||||||
|
scene: "room",
|
||||||
|
sender_display_user_id: "888888",
|
||||||
|
sender_user_id: "1001",
|
||||||
|
sender_username: "送礼人",
|
||||||
|
start_at_ms: 1000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [listUrl, listInit] = vi.mocked(fetch).mock.calls[0];
|
||||||
|
expect(String(listUrl)).toContain("/api/v1/admin/operations/gift-records?");
|
||||||
|
expect(String(listUrl)).toContain("scene=room");
|
||||||
|
expect(String(listUrl)).toContain("sender_display_user_id=888888");
|
||||||
|
expect(String(listUrl)).toContain("sender_user_id=1001");
|
||||||
|
expect(String(listUrl)).toContain("sender_username=%E9%80%81%E7%A4%BC%E4%BA%BA");
|
||||||
|
expect(String(listUrl)).toContain("start_at_ms=1000");
|
||||||
|
expect(String(listUrl)).toContain("end_at_ms=2000");
|
||||||
|
expect(listInit?.method).toBe("GET");
|
||||||
|
});
|
||||||
|
|
||||||
test("coin seller ledger API uses generated admin path and filters", async () => {
|
test("coin seller ledger API uses generated admin path and filters", async () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
"fetch",
|
"fetch",
|
||||||
|
|||||||
@ -22,6 +22,33 @@ export interface GiftDiamondRatioItem {
|
|||||||
updatedAtMs?: number;
|
updatedAtMs?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GiftRecordUserDto {
|
||||||
|
userId: string;
|
||||||
|
displayUserId?: string;
|
||||||
|
defaultDisplayUserId?: string;
|
||||||
|
prettyDisplayUserId?: string;
|
||||||
|
prettyId?: string;
|
||||||
|
username?: string;
|
||||||
|
avatar?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftRecordDto {
|
||||||
|
transactionId: string;
|
||||||
|
scene: "room" | "direct";
|
||||||
|
roomId?: string;
|
||||||
|
sender: GiftRecordUserDto;
|
||||||
|
receiver: GiftRecordUserDto;
|
||||||
|
gift: {
|
||||||
|
giftId: string;
|
||||||
|
name: string;
|
||||||
|
coverUrl?: string;
|
||||||
|
};
|
||||||
|
giftCount: number;
|
||||||
|
unitValue: number;
|
||||||
|
giftValue: number;
|
||||||
|
createdAtMs: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface GiftDiamondRatioResponse {
|
export interface GiftDiamondRatioResponse {
|
||||||
regionId: number;
|
regionId: number;
|
||||||
items: GiftDiamondRatioItem[];
|
items: GiftDiamondRatioItem[];
|
||||||
@ -132,6 +159,14 @@ export function listCoinLedger(query: PageQuery = {}): Promise<ApiPage<CoinLedge
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function listGiftRecords(query: PageQuery = {}): Promise<ApiPage<GiftRecordDto>> {
|
||||||
|
const endpoint = API_ENDPOINTS.listGiftRecords;
|
||||||
|
return apiRequest<ApiPage<GiftRecordDto>>(apiEndpointPath(API_OPERATIONS.listGiftRecords), {
|
||||||
|
method: endpoint.method,
|
||||||
|
query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function listCoinSellerLedger(query: PageQuery = {}): Promise<ApiPage<CoinSellerLedgerDto>> {
|
export function listCoinSellerLedger(query: PageQuery = {}): Promise<ApiPage<CoinSellerLedgerDto>> {
|
||||||
const endpoint = API_ENDPOINTS.listCoinSellerLedger;
|
const endpoint = API_ENDPOINTS.listCoinSellerLedger;
|
||||||
return apiRequest<ApiPage<CoinSellerLedgerDto>>(apiEndpointPath(API_OPERATIONS.listCoinSellerLedger), {
|
return apiRequest<ApiPage<CoinSellerLedgerDto>>(apiEndpointPath(API_OPERATIONS.listCoinSellerLedger), {
|
||||||
|
|||||||
220
src/features/operations/components/GiftRecordTable.jsx
Normal file
220
src/features/operations/components/GiftRecordTable.jsx
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
import CardGiftcardOutlined from "@mui/icons-material/CardGiftcardOutlined";
|
||||||
|
import { useMemo, useState } from "react";
|
||||||
|
import { listGiftRecords } from "@/features/operations/api";
|
||||||
|
import styles from "@/features/operations/operations.module.css";
|
||||||
|
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
|
||||||
|
import { AdminFilterResetButton, AdminListBody, AdminListToolbar } from "@/shared/ui/AdminListLayout.jsx";
|
||||||
|
import { AdminUserIdentity } from "@/shared/ui/AdminUserIdentity.jsx";
|
||||||
|
import { DataState } from "@/shared/ui/DataState.jsx";
|
||||||
|
import { DataTable } from "@/shared/ui/DataTable.jsx";
|
||||||
|
import { TimeRangeFilter } from "@/shared/ui/TimeRangeFilter.jsx";
|
||||||
|
import { TimeText } from "@/shared/ui/TimeText.jsx";
|
||||||
|
import { createOptionsColumnFilter, createUserIdentityColumnFilter } from "@/shared/ui/tableFilters.js";
|
||||||
|
import {
|
||||||
|
emptyUserIdentityFilter,
|
||||||
|
isUserIdentityFilterEmpty,
|
||||||
|
userIdentityFilterParams,
|
||||||
|
} from "@/shared/ui/userIdentityFilter.js";
|
||||||
|
|
||||||
|
const pageSize = 30;
|
||||||
|
|
||||||
|
const sceneOptions = [
|
||||||
|
{ label: "房间送礼", value: "room" },
|
||||||
|
{ label: "私聊送礼", value: "direct" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export function GiftRecordTable() {
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [scene, setScene] = useState("");
|
||||||
|
const [senderFilter, setSenderFilter] = useState(emptyUserIdentityFilter);
|
||||||
|
const [timeRange, setTimeRange] = useState({ endMs: "", startMs: "" });
|
||||||
|
const filters = useMemo(
|
||||||
|
() => ({
|
||||||
|
end_at_ms: timeRange.endMs || "",
|
||||||
|
scene,
|
||||||
|
...userIdentityFilterParams(senderFilter, {
|
||||||
|
displayUserId: "sender_display_user_id",
|
||||||
|
userId: "sender_user_id",
|
||||||
|
username: "sender_username",
|
||||||
|
}),
|
||||||
|
start_at_ms: timeRange.startMs || "",
|
||||||
|
}),
|
||||||
|
[scene, senderFilter, timeRange.endMs, timeRange.startMs],
|
||||||
|
);
|
||||||
|
const query = usePaginatedQuery({
|
||||||
|
errorMessage: "获取送礼记录失败",
|
||||||
|
fetcher: listGiftRecords,
|
||||||
|
filters,
|
||||||
|
page,
|
||||||
|
pageSize,
|
||||||
|
queryKey: ["gift-records", filters, page],
|
||||||
|
});
|
||||||
|
const data = query.data || { items: [], page, pageSize, total: 0 };
|
||||||
|
const items = data.items || [];
|
||||||
|
const total = data.total || 0;
|
||||||
|
const hasActiveFilters = Boolean(
|
||||||
|
!isUserIdentityFilterEmpty(senderFilter) || scene || timeRange.startMs || timeRange.endMs,
|
||||||
|
);
|
||||||
|
|
||||||
|
const changeScene = (value) => {
|
||||||
|
setScene(value);
|
||||||
|
setPage(1);
|
||||||
|
};
|
||||||
|
const changeSenderFilter = (value) => {
|
||||||
|
setSenderFilter(value);
|
||||||
|
setPage(1);
|
||||||
|
};
|
||||||
|
const changeTimeRange = (value) => {
|
||||||
|
setTimeRange(value);
|
||||||
|
setPage(1);
|
||||||
|
};
|
||||||
|
const resetFilters = () => {
|
||||||
|
setScene("");
|
||||||
|
setSenderFilter(emptyUserIdentityFilter);
|
||||||
|
setTimeRange({ endMs: "", startMs: "" });
|
||||||
|
setPage(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
key: "index",
|
||||||
|
label: "序号",
|
||||||
|
render: (_entry, index) => <span className={styles.giftRecordIndex}>{index + 1}</span>,
|
||||||
|
resizable: false,
|
||||||
|
width: "72px",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filter: createUserIdentityColumnFilter({
|
||||||
|
value: senderFilter,
|
||||||
|
onChange: changeSenderFilter,
|
||||||
|
}),
|
||||||
|
key: "sender",
|
||||||
|
label: "送礼人",
|
||||||
|
render: (entry) => <AdminUserIdentity openInAppUserDetail user={entry.sender} />,
|
||||||
|
width: "minmax(210px, 1fr)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "receiver",
|
||||||
|
label: "收礼人",
|
||||||
|
render: (entry) => <AdminUserIdentity openInAppUserDetail user={entry.receiver} />,
|
||||||
|
width: "minmax(210px, 1fr)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "gift",
|
||||||
|
label: "礼物",
|
||||||
|
render: (entry) => <GiftCell gift={entry.gift} />,
|
||||||
|
width: "minmax(220px, 1fr)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "giftValue",
|
||||||
|
label: "数量与价值",
|
||||||
|
render: (entry) => <GiftValueCell entry={entry} />,
|
||||||
|
width: "minmax(190px, 0.9fr)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filter: createOptionsColumnFilter({
|
||||||
|
emptyLabel: "全部场景",
|
||||||
|
options: sceneOptions,
|
||||||
|
placeholder: "送礼场景",
|
||||||
|
value: scene,
|
||||||
|
onChange: changeScene,
|
||||||
|
}),
|
||||||
|
key: "scene",
|
||||||
|
label: "场景",
|
||||||
|
render: (entry) => <SceneCell entry={entry} />,
|
||||||
|
width: "minmax(132px, 0.7fr)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "createdAtMs",
|
||||||
|
label: "送礼时间",
|
||||||
|
render: (entry) => <TimeText value={entry.createdAtMs} />,
|
||||||
|
width: "minmax(170px, 0.8fr)",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[scene, senderFilter],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.ledgerTableShell}>
|
||||||
|
<AdminListToolbar
|
||||||
|
filters={
|
||||||
|
<>
|
||||||
|
<TimeRangeFilter value={timeRange} onChange={changeTimeRange} />
|
||||||
|
<AdminFilterResetButton disabled={!hasActiveFilters} onClick={resetFilters} />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<DataState error={query.error} loading={query.loading} onRetry={query.reload}>
|
||||||
|
<AdminListBody>
|
||||||
|
<DataTable
|
||||||
|
columns={columns}
|
||||||
|
emptyLabel="当前无送礼记录"
|
||||||
|
items={items}
|
||||||
|
minWidth="1230px"
|
||||||
|
pagination={
|
||||||
|
total > 0
|
||||||
|
? {
|
||||||
|
page,
|
||||||
|
pageSize: data.pageSize || pageSize,
|
||||||
|
total,
|
||||||
|
onPageChange: setPage,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
rowKey={(entry) => entry.transactionId}
|
||||||
|
/>
|
||||||
|
</AdminListBody>
|
||||||
|
</DataState>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function GiftCell({ gift = {} }) {
|
||||||
|
return (
|
||||||
|
<div className={styles.giftRecordGift}>
|
||||||
|
<span className={styles.giftRecordCover}>
|
||||||
|
{gift.coverUrl ? <img src={gift.coverUrl} alt="" /> : <CardGiftcardOutlined fontSize="small" />}
|
||||||
|
</span>
|
||||||
|
<span className={styles.giftRecordGiftText}>
|
||||||
|
<span className={styles.giftRecordGiftName}>{gift.name || "-"}</span>
|
||||||
|
{gift.giftId ? <span className={styles.giftRecordGiftId}>{gift.giftId}</span> : null}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function GiftValueCell({ entry }) {
|
||||||
|
return (
|
||||||
|
<div className={styles.giftRecordMetrics}>
|
||||||
|
<span className={styles.giftRecordMetric}>
|
||||||
|
<span>数量</span>
|
||||||
|
<strong>× {formatNumber(entry.giftCount)}</strong>
|
||||||
|
</span>
|
||||||
|
<span className={styles.giftRecordMetric}>
|
||||||
|
<span>单价</span>
|
||||||
|
<strong>{formatNumber(entry.unitValue)}</strong>
|
||||||
|
</span>
|
||||||
|
<span className={`${styles.giftRecordMetric} ${styles.giftRecordTotal}`}>
|
||||||
|
<span>总价值</span>
|
||||||
|
<strong>{formatNumber(entry.giftValue)}</strong>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SceneCell({ entry }) {
|
||||||
|
const direct = entry.scene === "direct";
|
||||||
|
return (
|
||||||
|
<span className={styles.giftRecordScene}>
|
||||||
|
<span className={`${styles.giftRecordSceneBadge} ${direct ? styles.giftRecordSceneDirect : styles.giftRecordSceneRoom}`}>
|
||||||
|
{direct ? "私聊" : "房间"}
|
||||||
|
</span>
|
||||||
|
{!direct && entry.roomId ? <span className={styles.giftRecordRoomId}>{entry.roomId}</span> : null}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatNumber(value) {
|
||||||
|
return Number(value || 0).toLocaleString("zh-CN");
|
||||||
|
}
|
||||||
69
src/features/operations/components/GiftRecordTable.test.jsx
Normal file
69
src/features/operations/components/GiftRecordTable.test.jsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
import { afterEach, expect, test, vi } from "vitest";
|
||||||
|
import { GiftRecordTable } from "@/features/operations/components/GiftRecordTable.jsx";
|
||||||
|
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
|
||||||
|
|
||||||
|
vi.mock("@/shared/hooks/usePaginatedQuery.js", () => ({
|
||||||
|
usePaginatedQuery: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("gift record table uses public user identities and keeps gift facts compact", () => {
|
||||||
|
vi.mocked(usePaginatedQuery).mockReturnValue({
|
||||||
|
data: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
createdAtMs: 1770000000000,
|
||||||
|
gift: { coverUrl: "https://cdn.example/rose.webp", giftId: "rose", name: "玫瑰" },
|
||||||
|
giftCount: 3,
|
||||||
|
giftValue: 300,
|
||||||
|
receiver: { displayUserId: "202", userId: "2002", username: "收礼人" },
|
||||||
|
roomId: "room-9",
|
||||||
|
scene: "room",
|
||||||
|
sender: {
|
||||||
|
defaultDisplayUserId: "101",
|
||||||
|
displayUserId: "888888",
|
||||||
|
prettyDisplayUserId: "888888",
|
||||||
|
prettyId: "pretty-1",
|
||||||
|
userId: "1001",
|
||||||
|
username: "送礼人",
|
||||||
|
},
|
||||||
|
transactionId: "wallet-gift-1",
|
||||||
|
unitValue: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
page: 1,
|
||||||
|
pageSize: 30,
|
||||||
|
total: 1,
|
||||||
|
},
|
||||||
|
error: null,
|
||||||
|
loading: false,
|
||||||
|
reload: vi.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<GiftRecordTable />);
|
||||||
|
|
||||||
|
expect(screen.getByText("1")).toBeInTheDocument();
|
||||||
|
expect(screen.getAllByText("送礼人").length).toBeGreaterThanOrEqual(2);
|
||||||
|
expect(screen.getAllByText("收礼人").length).toBeGreaterThanOrEqual(2);
|
||||||
|
expect(screen.getByText("玫瑰")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("× 3")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("300")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("房间")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("room-9")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("已加载 1 条 · 共 1 条")).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "送礼人" }));
|
||||||
|
fireEvent.change(screen.getByPlaceholderText("输入短 ID"), { target: { value: "888888" } });
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "搜索" }));
|
||||||
|
|
||||||
|
expect(usePaginatedQuery).toHaveBeenLastCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
filters: expect.objectContaining({ sender_display_user_id: "888888" }),
|
||||||
|
page: 1,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
@ -36,6 +36,140 @@
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.giftRecordIndex {
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordGift {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordCover {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--border-soft);
|
||||||
|
border-radius: 14px;
|
||||||
|
background: linear-gradient(145deg, var(--bg-card-strong), var(--primary-hover));
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordCover img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordGiftText,
|
||||||
|
.giftRecordScene {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordGiftName {
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-weight: 780;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordGiftId,
|
||||||
|
.giftRecordRoomId {
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
font-size: 12px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordMetrics {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, auto));
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordMetric {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordMetric span {
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
font-size: 11px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordMetric strong {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: var(--admin-font-size);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
font-weight: 760;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordTotal {
|
||||||
|
padding-left: var(--space-3);
|
||||||
|
border-left: 1px solid var(--border-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordTotal strong {
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordSceneBadge {
|
||||||
|
display: inline-flex;
|
||||||
|
width: max-content;
|
||||||
|
min-height: 24px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 9px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 760;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordSceneRoom {
|
||||||
|
border-color: var(--primary-border);
|
||||||
|
background: var(--primary-hover);
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordSceneDirect {
|
||||||
|
border-color: rgba(124, 58, 237, 0.2);
|
||||||
|
background: rgba(124, 58, 237, 0.08);
|
||||||
|
color: #7c3aed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.giftRecordCover,
|
||||||
|
.giftRecordSceneBadge {
|
||||||
|
transition:
|
||||||
|
border-color 160ms ease,
|
||||||
|
box-shadow 160ms ease,
|
||||||
|
transform 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.giftRecordGift:hover .giftRecordCover {
|
||||||
|
border-color: var(--primary-border-strong);
|
||||||
|
box-shadow: 0 8px 18px rgba(37, 99, 235, 0.1);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.adjustmentAmount {
|
.adjustmentAmount {
|
||||||
font-size: calc(var(--admin-font-size) + 4px);
|
font-size: calc(var(--admin-font-size) + 4px);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/features/operations/pages/GiftRecordPage.jsx
Normal file
10
src/features/operations/pages/GiftRecordPage.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { GiftRecordTable } from "@/features/operations/components/GiftRecordTable.jsx";
|
||||||
|
import { AdminListPage } from "@/shared/ui/AdminListLayout.jsx";
|
||||||
|
|
||||||
|
export function GiftRecordPage() {
|
||||||
|
return (
|
||||||
|
<AdminListPage>
|
||||||
|
<GiftRecordTable />
|
||||||
|
</AdminListPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,6 +1,14 @@
|
|||||||
import { MENU_CODES, PERMISSIONS } from "@/app/permissions";
|
import { MENU_CODES, PERMISSIONS } from "@/app/permissions";
|
||||||
|
|
||||||
export const operationsRoutes = [
|
export const operationsRoutes = [
|
||||||
|
{
|
||||||
|
label: "送礼记录",
|
||||||
|
loader: () => import("./pages/GiftRecordPage.jsx").then((module) => module.GiftRecordPage),
|
||||||
|
menuCode: MENU_CODES.operationGiftRecords,
|
||||||
|
pageKey: "operation-gift-records",
|
||||||
|
path: "/operations/gift-records",
|
||||||
|
permission: PERMISSIONS.giftRecordView,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "金币流水",
|
label: "金币流水",
|
||||||
loader: () => import("./pages/CoinLedgerPage.jsx").then((module) => module.CoinLedgerPage),
|
loader: () => import("./pages/CoinLedgerPage.jsx").then((module) => module.CoinLedgerPage),
|
||||||
|
|||||||
@ -203,6 +203,7 @@ export const API_OPERATIONS = {
|
|||||||
listFinanceWithdrawalApplications: "listFinanceWithdrawalApplications",
|
listFinanceWithdrawalApplications: "listFinanceWithdrawalApplications",
|
||||||
listFirstRechargeRewardClaims: "listFirstRechargeRewardClaims",
|
listFirstRechargeRewardClaims: "listFirstRechargeRewardClaims",
|
||||||
listGameWhitelistUsers: "listGameWhitelistUsers",
|
listGameWhitelistUsers: "listGameWhitelistUsers",
|
||||||
|
listGiftRecords: "listGiftRecords",
|
||||||
listGifts: "listGifts",
|
listGifts: "listGifts",
|
||||||
listGiftTypes: "listGiftTypes",
|
listGiftTypes: "listGiftTypes",
|
||||||
listH5Links: "listH5Links",
|
listH5Links: "listH5Links",
|
||||||
@ -1710,6 +1711,13 @@ export const API_ENDPOINTS: Record<ApiOperationId, ApiEndpoint> = {
|
|||||||
permission: "game:view",
|
permission: "game:view",
|
||||||
permissions: ["game:view"]
|
permissions: ["game:view"]
|
||||||
},
|
},
|
||||||
|
listGiftRecords: {
|
||||||
|
method: "GET",
|
||||||
|
operationId: API_OPERATIONS.listGiftRecords,
|
||||||
|
path: "/v1/admin/operations/gift-records",
|
||||||
|
permission: "gift-record:view",
|
||||||
|
permissions: ["gift-record:view"]
|
||||||
|
},
|
||||||
listGifts: {
|
listGifts: {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
operationId: API_OPERATIONS.listGifts,
|
operationId: API_OPERATIONS.listGifts,
|
||||||
|
|||||||
86
src/shared/api/generated/schema.d.ts
vendored
86
src/shared/api/generated/schema.d.ts
vendored
@ -2060,6 +2060,22 @@ export interface paths {
|
|||||||
patch?: never;
|
patch?: never;
|
||||||
trace?: never;
|
trace?: never;
|
||||||
};
|
};
|
||||||
|
"/admin/operations/gift-records": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
get: operations["listGiftRecords"];
|
||||||
|
put?: never;
|
||||||
|
post?: never;
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
"/admin/operations/coin-ledger": {
|
"/admin/operations/coin-ledger": {
|
||||||
parameters: {
|
parameters: {
|
||||||
query?: never;
|
query?: never;
|
||||||
@ -4887,6 +4903,12 @@ export interface components {
|
|||||||
pageSize: number;
|
pageSize: number;
|
||||||
total: number;
|
total: number;
|
||||||
};
|
};
|
||||||
|
ApiPageGiftRecord: {
|
||||||
|
items: components["schemas"]["GiftRecord"][];
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
ApiPageBDProfile: {
|
ApiPageBDProfile: {
|
||||||
items: components["schemas"]["BDProfile"][];
|
items: components["schemas"]["BDProfile"][];
|
||||||
page: number;
|
page: number;
|
||||||
@ -5043,6 +5065,9 @@ export interface components {
|
|||||||
ApiResponseCoinSellerLedgerPage: components["schemas"]["Envelope"] & {
|
ApiResponseCoinSellerLedgerPage: components["schemas"]["Envelope"] & {
|
||||||
data?: components["schemas"]["ApiPageCoinSellerLedger"];
|
data?: components["schemas"]["ApiPageCoinSellerLedger"];
|
||||||
};
|
};
|
||||||
|
ApiResponseGiftRecordPage: components["schemas"]["Envelope"] & {
|
||||||
|
data?: components["schemas"]["ApiPageGiftRecord"];
|
||||||
|
};
|
||||||
ApiResponseBDProfilePage: components["schemas"]["Envelope"] & {
|
ApiResponseBDProfilePage: components["schemas"]["Envelope"] & {
|
||||||
data?: components["schemas"]["ApiPageBDProfile"];
|
data?: components["schemas"]["ApiPageBDProfile"];
|
||||||
};
|
};
|
||||||
@ -5403,6 +5428,37 @@ export interface components {
|
|||||||
child?: components["schemas"]["CoinSellerSubApplicationReviewChild"];
|
child?: components["schemas"]["CoinSellerSubApplicationReviewChild"];
|
||||||
relation?: components["schemas"]["CoinSellerSubRelation"];
|
relation?: components["schemas"]["CoinSellerSubRelation"];
|
||||||
};
|
};
|
||||||
|
GiftRecordUser: {
|
||||||
|
avatar?: string;
|
||||||
|
defaultDisplayUserId?: string;
|
||||||
|
displayUserId?: string;
|
||||||
|
prettyDisplayUserId?: string;
|
||||||
|
prettyId?: string;
|
||||||
|
userId: string;
|
||||||
|
username?: string;
|
||||||
|
};
|
||||||
|
GiftRecordGift: {
|
||||||
|
coverUrl: string;
|
||||||
|
giftId: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
GiftRecord: {
|
||||||
|
/** Format: int64 */
|
||||||
|
createdAtMs: number;
|
||||||
|
gift: components["schemas"]["GiftRecordGift"];
|
||||||
|
/** Format: int32 */
|
||||||
|
giftCount: number;
|
||||||
|
/** Format: int64 */
|
||||||
|
giftValue: number;
|
||||||
|
receiver: components["schemas"]["GiftRecordUser"];
|
||||||
|
roomId?: string;
|
||||||
|
/** @enum {string} */
|
||||||
|
scene: "room" | "direct";
|
||||||
|
sender: components["schemas"]["GiftRecordUser"];
|
||||||
|
transactionId: string;
|
||||||
|
/** Format: int64 */
|
||||||
|
unitValue: number;
|
||||||
|
};
|
||||||
CoinLedgerUser: {
|
CoinLedgerUser: {
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
displayUserId?: string;
|
displayUserId?: string;
|
||||||
@ -6147,6 +6203,15 @@ export interface components {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
/** @description OK */
|
/** @description OK */
|
||||||
|
GiftRecordPageResponse: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["ApiResponseGiftRecordPage"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/** @description OK */
|
||||||
BDProfilePageResponse: {
|
BDProfilePageResponse: {
|
||||||
headers: {
|
headers: {
|
||||||
[name: string]: unknown;
|
[name: string]: unknown;
|
||||||
@ -9193,6 +9258,27 @@ export interface operations {
|
|||||||
200: components["responses"]["EmptyResponse"];
|
200: components["responses"]["EmptyResponse"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
listGiftRecords: {
|
||||||
|
parameters: {
|
||||||
|
query?: {
|
||||||
|
page?: components["parameters"]["Page"];
|
||||||
|
page_size?: components["parameters"]["PageSize"];
|
||||||
|
scene?: "room" | "direct";
|
||||||
|
sender_display_user_id?: string;
|
||||||
|
sender_user_id?: string;
|
||||||
|
sender_username?: string;
|
||||||
|
start_at_ms?: number;
|
||||||
|
end_at_ms?: number;
|
||||||
|
};
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody?: never;
|
||||||
|
responses: {
|
||||||
|
200: components["responses"]["GiftRecordPageResponse"];
|
||||||
|
};
|
||||||
|
};
|
||||||
listCoinLedger: {
|
listCoinLedger: {
|
||||||
parameters: {
|
parameters: {
|
||||||
query?: {
|
query?: {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user