feat: 增加角色管理与奖池配置迁移,优化管理端权限与样式

This commit is contained in:
2026-05-19 14:40:04 +08:00
parent d625c59393
commit a1fb163f1b
45 changed files with 1080 additions and 518 deletions

View File

@@ -213,6 +213,17 @@ function walletAdminSelectDisplayedLabel(
return key ? (t ? t(key) : key) : v;
}
function canReverseTransferOrder(row: { status: string; can_reverse?: boolean }): boolean {
return row.can_reverse ?? row.status === "pending_reconcile";
}
function canManuallyProcessTransferOrder(row: {
status: string;
can_manually_process?: boolean;
}): boolean {
return row.can_manually_process ?? ["processing", "failed", "pending_reconcile"].includes(row.status);
}
export function TransferOrdersPanel(): React.ReactElement {
const { t } = useTranslation(["wallet", "common"]);
const formatTs = useAdminDateTimeFormatter();
@@ -473,26 +484,30 @@ export function TransferOrdersPanel(): React.ReactElement {
{formatTs(row.finished_at)}
</TableCell>
<TableCell>
{row.status === "pending_reconcile" ? (
{canReverseTransferOrder(row) || canManuallyProcessTransferOrder(row) ? (
<div className="flex flex-col gap-1">
<Button
size="sm"
variant="destructive"
className="h-6 px-2 text-xs"
disabled={actionLoading.has(row.transfer_no)}
onClick={() => handleReverse(row.transfer_no)}
>
{actionLoading.has(row.transfer_no) ? t("processing") : t("reverse")}
</Button>
<Button
size="sm"
variant="outline"
className="h-6 px-2 text-xs"
disabled={actionLoading.has(row.transfer_no)}
onClick={() => handleManuallyProcess(row.transfer_no)}
>
{actionLoading.has(row.transfer_no) ? t("processing") : t("manualProcess")}
</Button>
{canReverseTransferOrder(row) ? (
<Button
size="sm"
variant="destructive"
className="h-6 px-2 text-xs"
disabled={actionLoading.has(row.transfer_no)}
onClick={() => handleReverse(row.transfer_no)}
>
{actionLoading.has(row.transfer_no) ? t("processing") : t("reverse")}
</Button>
) : null}
{canManuallyProcessTransferOrder(row) ? (
<Button
size="sm"
variant="outline"
className="h-6 px-2 text-xs"
disabled={actionLoading.has(row.transfer_no)}
onClick={() => handleManuallyProcess(row.transfer_no)}
>
{actionLoading.has(row.transfer_no) ? t("processing") : t("manualProcess")}
</Button>
) : null}
</div>
) : (
<span className="text-xs text-muted-foreground"></span>