refactor: 合并多语言支持的显示名称字段,优化奖池手动爆发功能的返回数据结构,增强管理端权限控制

This commit is contained in:
2026-05-25 14:31:24 +08:00
parent 7d01e5c47e
commit ddedef824e
101 changed files with 3033 additions and 641 deletions

View File

@@ -23,6 +23,10 @@ import { ConfigReadonlyValue } from "@/modules/config/config-readonly-value";
import { ConfigVersionActions } from "@/modules/config/config-version-actions";
import { ConfigVersionSwitcher } from "@/modules/config/config-version-switcher";
import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import { adminHasAnyPermission } from "@/lib/admin-permissions";
import { PRD_REBATE_MANAGE } from "@/lib/admin-prd";
import { useAdminProfile } from "@/stores/admin-session";
import { LotteryApiBizError } from "@/types/api/errors";
import type {
AdminPlayTypeRow,
@@ -54,6 +58,9 @@ type RebateConfigDocScreenProps = {
export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScreenProps) {
const { t } = useTranslation(["config", "common"]);
const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
const profile = useAdminProfile();
const canManage = adminHasAnyPermission(profile?.permissions, [PRD_REBATE_MANAGE]);
const formatDt = useAdminDateTimeFormatter();
const [types, setTypes] = useState<AdminPlayTypeRow[]>([]);
const [listRows, setListRows] = useState<ConfigVersionSummary[]>([]);
@@ -162,6 +169,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
const isSelectedDetail = detail !== null && String(detail.id) === selectedId;
const selectedStatus = isSelectedDetail ? detail.status : selectedVersionSummary?.status;
const isDraft = selectedStatus === "draft";
const canEditDraft = isDraft && canManage;
function applyDimensionPercentsToRows(rows: OddsItemRow[]): OddsItemRow[] {
const r2 = Number.parseFloat(p2);
@@ -179,7 +187,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
}
async function handleSave() {
if (!detail || !isDraft) {
if (!detail || !canEditDraft) {
return;
}
setSaving(true);
@@ -211,7 +219,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
}
async function handlePublish() {
if (!detail || !isDraft) {
if (!detail || !canEditDraft) {
return;
}
setSaving(true);
@@ -286,6 +294,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
actions={
<ConfigVersionActions
isDraft={isDraft}
canManage={canManage}
loadingList={loading}
loadingDetail={loadingDetail}
saving={saving}
@@ -293,7 +302,15 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
onRefresh={() => void refreshList()}
onNewDraft={() => void handleNewDraft()}
onSaveDraft={() => void handleSave()}
onPublish={() => void handlePublish()}
onPublish={() =>
requestConfirm({
title: t("rebate.publishDialog.title", { ns: "config" }),
description: t("rebate.publishDialog.description", { ns: "config" }),
confirmLabel: t("rebate.publishDialog.confirm", { ns: "config" }),
confirmVariant: "destructive",
onConfirm: () => handlePublish(),
})
}
/>
}
/>
@@ -326,7 +343,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
<div className="grid gap-5 sm:grid-cols-3">
<div className="grid gap-2">
<Label>{t("rebate.fields.d2", { ns: "config" })}</Label>
{isDraft ? (
{canEditDraft ? (
<Input
type="number"
step="0.01"
@@ -342,7 +359,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
</div>
<div className="grid gap-2">
<Label>{t("rebate.fields.d3", { ns: "config" })}</Label>
{isDraft ? (
{canEditDraft ? (
<Input
type="number"
step="0.01"
@@ -358,7 +375,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
</div>
<div className="grid gap-2">
<Label>{t("rebate.fields.d4", { ns: "config" })}</Label>
{isDraft ? (
{canEditDraft ? (
<Input
type="number"
step="0.01"
@@ -409,6 +426,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
<div className="space-y-6">
{contextBlock}
{fieldsBlock}
<ConfirmDialog />
</div>
);
}
@@ -420,6 +438,7 @@ export function RebateConfigDocScreen({ embedded = false }: RebateConfigDocScree
context={contextBlock}
>
{fieldsBlock}
<ConfirmDialog />
</ConfigDocPage>
);
}