import { useMemo, useState } from "react";
import { listRechargeBills } from "@/features/payment/api";
import {
AdminListBody,
AdminListPage,
} from "@/shared/ui/AdminListLayout.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
import { formatMillis } from "@/shared/utils/time.js";
const pageSize = 20;
const statusOptions = [
["", "全部状态"],
["succeeded", "成功"],
];
const rechargeTypeOptions = [
["", "全部途径"],
["coin_seller_transfer", "币商充值"],
];
const columns = [
{
key: "bill",
label: "账单",
width: "minmax(240px, 1.4fr)",
render: (bill) => ,
},
{
key: "userId",
label: "用户 ID",
width: "minmax(120px, 0.65fr)",
render: (bill) => bill.userId || "-",
},
{
key: "sellerUserId",
label: "币商 ID",
width: "minmax(120px, 0.65fr)",
render: (bill) => bill.sellerUserId || "-",
},
{
key: "amount",
label: "金币 / 金额",
width: "minmax(150px, 0.75fr)",
render: (bill) => (
),
},
{
key: "policy",
label: "兑换口径",
width: "minmax(170px, 0.9fr)",
render: (bill) => (
),
},
{
key: "region",
label: "区域",
width: "minmax(110px, 0.55fr)",
render: (bill) => (
),
},
{
key: "rechargeType",
label: "充值途径",
width: "minmax(130px, 0.7fr)",
render: (bill) => rechargeTypeLabel(bill.rechargeType),
},
{
key: "status",
label: "状态",
width: "minmax(100px, 0.55fr)",
render: (bill) => ,
},
{
key: "time",
label: "创建时间",
width: "minmax(160px, 0.8fr)",
render: (bill) => formatMillis(bill.createdAtMs),
},
];
export function PaymentBillListPage() {
const [page, setPage] = useState(1);
const [keyword, setKeyword] = useState("");
const [status, setStatus] = useState("");
const [rechargeType, setRechargeType] = useState("");
const [userId, setUserId] = useState("");
const [sellerUserId, setSellerUserId] = useState("");
const filters = useMemo(
() => ({
keyword,
recharge_type: rechargeType,
seller_user_id: sellerUserId,
status,
user_id: userId,
}),
[keyword, rechargeType, sellerUserId, status, userId],
);
const query = usePaginatedQuery({
errorMessage: "获取账单列表失败",
fetcher: listRechargeBills,
filters,
page,
pageSize,
queryKey: ["payment-bills", filters, page],
});
const data = query.data || { items: [], total: 0, page, pageSize };
const items = data.items || [];
const total = data.total || 0;
const resetPage = (setter) => (value) => {
setter(value);
setPage(1);
};
const tableColumns = columns.map((column) => {
if (column.key === "bill") {
return {
...column,
filter: createTextColumnFilter({
placeholder: "搜索账单号、命令号、外部单号",
value: keyword,
onChange: resetPage(setKeyword),
}),
};
}
if (column.key === "userId") {
return {
...column,
filter: createTextColumnFilter({
placeholder: "搜索用户 ID",
value: userId,
onChange: (value) => resetPage(setUserId)(digitsOnly(value)),
}),
};
}
if (column.key === "sellerUserId") {
return {
...column,
filter: createTextColumnFilter({
placeholder: "搜索币商 ID",
value: sellerUserId,
onChange: (value) => resetPage(setSellerUserId)(digitsOnly(value)),
}),
};
}
if (column.key === "rechargeType") {
return {
...column,
filter: createOptionsColumnFilter({
options: rechargeTypeOptions,
placeholder: "搜索充值途径",
value: rechargeType,
onChange: resetPage(setRechargeType),
}),
};
}
if (column.key === "status") {
return {
...column,
filter: createOptionsColumnFilter({
options: statusOptions,
placeholder: "搜索状态",
value: status,
onChange: resetPage(setStatus),
}),
};
}
return column;
});
return (
0
? {
page,
pageSize: data.pageSize || pageSize,
total,
onPageChange: setPage,
}
: undefined
}
rowKey={(bill) => bill.transactionId}
/>
);
}
function Stack({ primary, secondary }) {
return (
{primary || "-"}
{secondary || "-"}
);
}
function StatusBadge({ status }) {
const tone = status === "succeeded" ? "succeeded" : status === "failed" ? "danger" : "stopped";
return (
{statusLabel(status)}
);
}
function rechargeTypeLabel(value) {
return rechargeTypeOptions.find(([optionValue]) => optionValue === value)?.[1] || value || "-";
}
function statusLabel(value) {
if (value === "succeeded") {
return "成功";
}
if (value === "failed") {
return "失败";
}
return value || "-";
}
function formatNumber(value) {
if (value === 0 || value) {
return Number(value).toLocaleString("zh-CN");
}
return "-";
}
function formatMoney(value, currency = "USD") {
if (!(value === 0 || value)) {
return "-";
}
return `${currency || "USD"} ${(Number(value) / 100).toLocaleString("zh-CN", {
maximumFractionDigits: 2,
minimumFractionDigits: 2,
})}`;
}
function digitsOnly(value) {
return value.replace(/\D/g, "");
}