feat: 增加管理端多语言与风控/报表/奖池操作能力
This commit is contained in:
@@ -81,6 +81,8 @@ export function OddsConfigDocScreen() {
|
||||
|
||||
const [rollbackOpen, setRollbackOpen] = useState(false);
|
||||
const [rollbackTarget, setRollbackTarget] = useState<ConfigVersionSummary | null>(null);
|
||||
const [publishConfirmOpen, setPublishConfirmOpen] = useState(false);
|
||||
const [activeCompareRows, setActiveCompareRows] = useState<OddsItemRow[]>([]);
|
||||
|
||||
const refreshTypes = useCallback(async () => {
|
||||
setLoadingTypes(true);
|
||||
@@ -281,6 +283,24 @@ export function OddsConfigDocScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
async function requestPublishConfirm() {
|
||||
if (!detail || !isDraft) {
|
||||
return;
|
||||
}
|
||||
const active = list.find((x) => x.status === "active");
|
||||
if (active && active.id !== detail.id) {
|
||||
try {
|
||||
const d = await getOddsVersion(active.id);
|
||||
setActiveCompareRows(d.items);
|
||||
} catch {
|
||||
setActiveCompareRows([]);
|
||||
}
|
||||
} else {
|
||||
setActiveCompareRows([]);
|
||||
}
|
||||
setPublishConfirmOpen(true);
|
||||
}
|
||||
|
||||
async function handleNewDraft() {
|
||||
setSaving(true);
|
||||
try {
|
||||
@@ -343,6 +363,25 @@ export function OddsConfigDocScreen() {
|
||||
setRollbackOpen(true);
|
||||
}
|
||||
|
||||
const publishDiffRows = useMemo(() => {
|
||||
if (!detail) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const selectedPlay = resolvedPlayCode;
|
||||
|
||||
return PRIZE_SCOPE_ORDER.map((scope) => {
|
||||
const next = draftRows.find((r) => r.play_code === selectedPlay && r.prize_scope === scope);
|
||||
const old = activeCompareRows.find((r) => r.play_code === selectedPlay && r.prize_scope === scope);
|
||||
return {
|
||||
scope,
|
||||
label: PRIZE_SCOPE_LABELS[scope],
|
||||
oldValue: old?.odds_value ?? null,
|
||||
newValue: next?.odds_value ?? null,
|
||||
};
|
||||
});
|
||||
}, [activeCompareRows, detail, draftRows, resolvedPlayCode]);
|
||||
|
||||
const catTabs: { id: CatTab; label: string }[] = [
|
||||
{ id: "all", label: "全部" },
|
||||
{ id: "d4", label: "4D" },
|
||||
@@ -421,7 +460,7 @@ export function OddsConfigDocScreen() {
|
||||
onRefresh={() => void refreshList()}
|
||||
onNewDraft={() => void handleNewDraft()}
|
||||
onSaveDraft={() => void handleSave()}
|
||||
onPublish={() => void handlePublish()}
|
||||
onPublish={() => void requestPublishConfirm()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -532,6 +571,48 @@ export function OddsConfigDocScreen() {
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={publishConfirmOpen} onOpenChange={setPublishConfirmOpen}>
|
||||
<DialogContent showCloseButton className="sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>确认启用赔率版本?</DialogTitle>
|
||||
<DialogDescription>
|
||||
新赔率发布后立即影响新注单;已成功下注的订单继续按下注时赔率快照结算。
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="rounded-lg border">
|
||||
<div className="grid grid-cols-3 border-b bg-muted/40 px-3 py-2 text-sm font-medium">
|
||||
<span>奖项</span>
|
||||
<span className="text-right">当前查看值</span>
|
||||
<span className="text-right">发布后值</span>
|
||||
</div>
|
||||
{publishDiffRows.map((row) => (
|
||||
<div key={row.scope} className="grid grid-cols-3 px-3 py-2 text-sm">
|
||||
<span>{row.label}</span>
|
||||
<span className="text-right font-mono tabular-nums">
|
||||
{row.oldValue === null ? "—" : row.oldValue}
|
||||
</span>
|
||||
<span className="text-right font-mono tabular-nums">{row.newValue ?? "—"}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" onClick={() => setPublishConfirmOpen(false)}>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
disabled={saving}
|
||||
onClick={() => {
|
||||
setPublishConfirmOpen(false);
|
||||
void handlePublish();
|
||||
}}
|
||||
>
|
||||
确认发布
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user