refactor: 更新风险监控页面标题为国际化支持,优化风险池控制台的标题处理

This commit is contained in:
2026-05-22 16:11:36 +08:00
parent 51891548a5
commit 2d4a23968e
29 changed files with 491 additions and 94 deletions

View File

@@ -13,6 +13,7 @@ import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { LotteryApiBizError } from "@/types/api/errors";
const DRAW_GROUP = "draw";
@@ -24,10 +25,16 @@ const DRAW_KEYS = {
AUTO_SETTLEMENT: "settlement.auto_run_on_tick",
} as const;
const FRONTEND_GROUP = "frontend";
const FRONTEND_KEYS = {
PLAY_RULES_HTML: "frontend.play_rules_html",
} as const;
interface RuntimeDraft {
requireManualReview: boolean;
cooldownMinutes: string;
autoSettlement: boolean;
playRulesHtml: string;
}
function BinaryChoice({
@@ -75,11 +82,13 @@ export function SystemSettingsScreen() {
requireManualReview: false,
cooldownMinutes: "15",
autoSettlement: true,
playRulesHtml: "",
});
const [saved, setSaved] = useState<RuntimeDraft>({
requireManualReview: false,
cooldownMinutes: "15",
autoSettlement: true,
playRulesHtml: "",
});
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
@@ -88,13 +97,14 @@ export function SystemSettingsScreen() {
const load = useCallback(async () => {
setLoading(true);
try {
const [drawRes, settlementRes] = await Promise.all([
const [drawRes, settlementRes, frontendRes] = await Promise.all([
getAdminSettings(DRAW_GROUP),
getAdminSettings(SETTLEMENT_GROUP),
getAdminSettings(FRONTEND_GROUP),
]);
const kv: Record<string, unknown> = {};
for (const item of [...drawRes.items, ...settlementRes.items]) {
for (const item of [...drawRes.items, ...settlementRes.items, ...frontendRes.items]) {
kv[item.key] = item.value;
}
@@ -102,6 +112,7 @@ export function SystemSettingsScreen() {
requireManualReview: Boolean(kv[DRAW_KEYS.REQUIRE_MANUAL_REVIEW] ?? false),
cooldownMinutes: String(kv[DRAW_KEYS.COOLDOWN_MINUTES] ?? 15),
autoSettlement: Boolean(kv[DRAW_KEYS.AUTO_SETTLEMENT] ?? true),
playRulesHtml: String(kv[FRONTEND_KEYS.PLAY_RULES_HTML] ?? ""),
};
setDraft(nextDraft);
setSaved(nextDraft);
@@ -133,6 +144,7 @@ export function SystemSettingsScreen() {
Math.max(0, Number.parseInt(draft.cooldownMinutes || "0", 10) || 0),
);
await updateAdminSetting(DRAW_KEYS.AUTO_SETTLEMENT, draft.autoSettlement);
await updateAdminSetting(FRONTEND_KEYS.PLAY_RULES_HTML, draft.playRulesHtml);
toast.success(t("system.saveSuccess", { ns: "config" }));
setSaved(draft);
setDirty(false);
@@ -233,6 +245,48 @@ export function SystemSettingsScreen() {
</div>
</section>
<section className="space-y-4 border-t border-border/60 pt-6">
<div className="space-y-1">
<h3 className="text-base font-semibold">{t("system.frontendConfig", { ns: "config", defaultValue: "前端配置" })}</h3>
</div>
<div className="space-y-5 rounded-2xl border border-border/60 bg-muted/10 px-4 py-4">
<div className="grid gap-2">
<Label htmlFor="play-rules-html" className="text-sm font-medium">
{t("system.fields.playRulesHtml", { ns: "config", defaultValue: "玩法规则 HTML 内容" })}
</Label>
<p className="text-xs text-muted-foreground">
{t("system.fields.playRulesHtmlDesc", { ns: "config", defaultValue: "该内容将直接在玩家端的玩法规则页面作为 HTML 渲染。留空则显示前端默认提示。" })}
</p>
<Textarea
id="play-rules-html"
value={draft.playRulesHtml}
onChange={(e) => updateDraft("playRulesHtml", e.target.value)}
disabled={loading || saving}
className="font-mono text-xs min-h-[200px]"
placeholder="<div>...</div>"
/>
</div>
<div className="flex items-center gap-4 pt-2">
<Button onClick={() => void handleSave()} disabled={!dirty || loading || saving}>
{saving ? t("saving", { ns: "adminUsers" }) : t("actions.save", { ns: "adminUsers" })}
</Button>
{dirty && (
<Button
variant="outline"
onClick={() => {
setDraft(saved);
setDirty(false);
}}
>
{t("system.discard", { ns: "config" })}
</Button>
)}
</div>
</div>
</section>
<section className="space-y-4 border-t border-border/60 pt-6">
<div className="space-y-1">
<h3 className="text-base font-semibold">{t("wallet.title", { ns: "config" })}</h3>