refactor: 更新风险监控页面标题为国际化支持,优化风险池控制台的标题处理
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user