210 lines
7.3 KiB
JavaScript
210 lines
7.3 KiB
JavaScript
import Avatar from "@mui/material/Avatar";
|
|
import { CumulativeRechargeRewardConfigDrawer } from "@/features/cumulative-recharge-reward/components/CumulativeRechargeRewardConfigDrawer.jsx";
|
|
import { CumulativeRechargeRewardConfigSummary } from "@/features/cumulative-recharge-reward/components/CumulativeRechargeRewardConfigSummary.jsx";
|
|
import { useCumulativeRechargeRewardPage } from "@/features/cumulative-recharge-reward/hooks/useCumulativeRechargeRewardPage.js";
|
|
import styles from "@/features/cumulative-recharge-reward/cumulative-recharge-reward.module.css";
|
|
import { AdminListBody, AdminListPage } from "@/shared/ui/AdminListLayout.jsx";
|
|
import { DataState } from "@/shared/ui/DataState.jsx";
|
|
import { DataTable } from "@/shared/ui/DataTable.jsx";
|
|
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
|
|
import { formatMillis } from "@/shared/utils/time.js";
|
|
|
|
const grantStatusOptions = [
|
|
["pending", "发放中"],
|
|
["granted", "已发放"],
|
|
["failed", "发放失败"],
|
|
];
|
|
|
|
const columnsBase = [
|
|
{
|
|
key: "user",
|
|
label: "用户信息",
|
|
width: "minmax(260px, 1.1fr)",
|
|
render: (grant) => <GrantUser grant={grant} />,
|
|
},
|
|
{
|
|
key: "cycle",
|
|
label: "周期",
|
|
width: "minmax(150px, 0.7fr)",
|
|
render: (grant) => grant.cycleKey || "-",
|
|
},
|
|
{
|
|
key: "tier",
|
|
label: "命中档位",
|
|
width: "minmax(190px, 0.85fr)",
|
|
render: (grant) => (
|
|
<div className={styles.stack}>
|
|
<span>{grant.tierCode || "-"}</span>
|
|
<span className={styles.meta}>{formatUSD(grant.thresholdUsdMinor)}</span>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: "amount",
|
|
label: "累计 / 本次",
|
|
width: "minmax(210px, 0.9fr)",
|
|
render: (grant) => (
|
|
<div className={styles.stack}>
|
|
<span>{formatUSD(grant.reachedUsdMinor)}</span>
|
|
<span className={styles.meta}>本次 {formatUSD(grant.qualifyingUsdMinor)}</span>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: "source",
|
|
label: "来源",
|
|
width: "minmax(190px, 0.85fr)",
|
|
render: (grant) => (
|
|
<div className={styles.stack}>
|
|
<span>{grant.rechargeType || "-"}</span>
|
|
<span className={styles.meta}>
|
|
{grant.rechargeCoinAmount ? `${formatNumber(grant.rechargeCoinAmount)} 金币` : "-"}
|
|
</span>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: "status",
|
|
label: "状态",
|
|
width: "minmax(120px, 0.55fr)",
|
|
render: (grant) => grantStatusLabel(grant.status),
|
|
},
|
|
{
|
|
key: "createdAt",
|
|
label: "创建时间",
|
|
width: "minmax(180px, 0.85fr)",
|
|
render: (grant) => formatMillis(grant.createdAtMs),
|
|
},
|
|
{
|
|
key: "grantId",
|
|
label: "记录",
|
|
width: "minmax(280px, 1fr)",
|
|
render: (grant) => (
|
|
<div className={styles.stack}>
|
|
<span>{grant.grantId}</span>
|
|
<span className={styles.meta}>{grant.transactionId || grant.eventId || "-"}</span>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
key: "failure",
|
|
label: "失败原因",
|
|
width: "minmax(180px, 0.85fr)",
|
|
render: (grant) => grant.failureReason || "-",
|
|
},
|
|
];
|
|
|
|
export function CumulativeRechargeRewardPage() {
|
|
const page = useCumulativeRechargeRewardPage();
|
|
const total = page.grants.total || 0;
|
|
const columns = columnsBase.map((column) => {
|
|
if (column.key === "user") {
|
|
return {
|
|
...column,
|
|
filter: createTextColumnFilter({
|
|
placeholder: "搜索用户 ID、短号、名称",
|
|
value: page.query,
|
|
onChange: page.changeQuery,
|
|
}),
|
|
};
|
|
}
|
|
if (column.key === "cycle") {
|
|
return {
|
|
...column,
|
|
filter: createTextColumnFilter({
|
|
placeholder: "周期,如 2026-W23",
|
|
value: page.cycleKey,
|
|
onChange: page.changeCycleKey,
|
|
}),
|
|
};
|
|
}
|
|
if (column.key === "status") {
|
|
return {
|
|
...column,
|
|
filter: createOptionsColumnFilter({
|
|
options: [["", "全部状态"], ...grantStatusOptions],
|
|
placeholder: "搜索状态",
|
|
value: page.status,
|
|
onChange: page.changeStatus,
|
|
}),
|
|
};
|
|
}
|
|
return column;
|
|
});
|
|
|
|
return (
|
|
<AdminListPage>
|
|
<CumulativeRechargeRewardConfigSummary
|
|
canUpdate={page.abilities.canUpdate}
|
|
config={page.config}
|
|
configLoading={page.configLoading}
|
|
resourceGroups={page.resourceGroups}
|
|
onEdit={page.openConfigDrawer}
|
|
onRefresh={page.reloadConfig}
|
|
/>
|
|
<DataState error={page.grantsError} loading={page.grantsLoading} onRetry={page.reloadGrants}>
|
|
<AdminListBody>
|
|
<DataTable
|
|
columns={columns}
|
|
items={page.grants.items || []}
|
|
minWidth="1500px"
|
|
pagination={
|
|
total > 0
|
|
? {
|
|
page: page.page,
|
|
pageSize: page.grants.pageSize || 50,
|
|
total,
|
|
onPageChange: page.setPage,
|
|
}
|
|
: undefined
|
|
}
|
|
rowKey={(grant) => grant.grantId}
|
|
/>
|
|
</AdminListBody>
|
|
</DataState>
|
|
<CumulativeRechargeRewardConfigDrawer
|
|
abilities={page.abilities}
|
|
configLoading={page.configLoading}
|
|
configSaving={page.configSaving}
|
|
form={page.form}
|
|
open={page.configDrawerOpen}
|
|
resourceGroups={page.resourceGroups}
|
|
setForm={page.setForm}
|
|
onClose={page.closeConfigDrawer}
|
|
onSubmit={page.submitConfig}
|
|
/>
|
|
</AdminListPage>
|
|
);
|
|
}
|
|
|
|
function GrantUser({ grant }) {
|
|
const user = grant.user || {};
|
|
return (
|
|
<div className={styles.identity}>
|
|
<Avatar
|
|
alt={user.username || String(grant.userId)}
|
|
src={user.avatar || ""}
|
|
sx={{ width: 36, height: 36 }}
|
|
/>
|
|
<div className={styles.stack}>
|
|
<span className={styles.name}>{user.username || `用户 ${grant.userId}`}</span>
|
|
<span className={styles.meta}>
|
|
{user.displayUserId ? `短号 ${user.displayUserId}` : `ID ${grant.userId}`}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function grantStatusLabel(status) {
|
|
return grantStatusOptions.find(([value]) => value === status)?.[1] || status || "-";
|
|
}
|
|
|
|
function formatUSD(value) {
|
|
return `$${(Number(value || 0) / 100).toFixed(2)}`;
|
|
}
|
|
|
|
function formatNumber(value) {
|
|
return new Intl.NumberFormat("zh-CN").format(Number(value || 0));
|
|
}
|