From 9a022f3b312b3ce7b683839298170baae82f3fc4 Mon Sep 17 00:00:00 2001 From: NanGua-QWQ Date: Mon, 30 Mar 2026 22:26:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=AE=BE=E7=BD=AE):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=AD=97=E4=BD=93=E9=80=89=E6=8B=A9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=20fix:=20=E8=87=AA=E5=8A=A8=E5=8C=96=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E4=BF=9D=E5=AD=98=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/data.sql | Bin 110592 -> 110592 bytes src/components/AutoScoreManager.tsx | 13 ++- .../AutoScoreManagerPage/ActionEditor.tsx | 26 +++-- .../AutoScoreManagerPage/AutoScoreUtils.ts | 37 ++++++- src/components/Settings.tsx | 95 ++++++++++++++++++ src/i18n/locales/en-US.json | 2 + src/i18n/locales/zh-CN.json | 2 + 7 files changed, 161 insertions(+), 14 deletions(-) diff --git a/src-tauri/data.sql b/src-tauri/data.sql index 34d90ab2dce15664a56a5aa31abc6e565262ad60..c8b719d7e76cc8be4136486613277bd871ad7fd4 100644 GIT binary patch delta 787 zcmaJXe6gBQn$b)=Ns%d zIurzsb^3ve9;_{&Y0BAVu9aZgGHS$>e>d8z$smwKAa6hhY8Akt+yB!o#>1L%5)e58PfSfo6S zYv8uOncleqO)(0_rJf`{rdjHkJrz^=>FlIy)Q<~ h{Ml%=&kn2Zt48(N&B>dYMx$|Y=Xmn&cw)?1zX0ko^sWE^ delta 112 zcmV-$0FVEG;0A!;29O&8FOeKW0WYy&p??_w000mTNdXV+57ZCC51 setActionDrafts(normalizeActionDrafts(nextDrafts))} />
diff --git a/src/components/AutoScoreManagerPage/ActionEditor.tsx b/src/components/AutoScoreManagerPage/ActionEditor.tsx index ab97de4..8508edb 100644 --- a/src/components/AutoScoreManagerPage/ActionEditor.tsx +++ b/src/components/AutoScoreManagerPage/ActionEditor.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from "react" +import React, { useEffect, useMemo } from "react" import { Button, Card, InputNumber, Select, Space } from "antd" import { DeleteOutlined, PlusOutlined } from "@ant-design/icons" import { useTranslation } from "react-i18next" @@ -19,6 +19,14 @@ export const ActionEditor: React.FC = ({ onChange, }) => { const { t } = useTranslation() + const fallbackDraft = useMemo(() => createDefaultActionDraft(), []) + const safeValue = value.length > 0 ? value : [fallbackDraft] + + useEffect(() => { + if (value.length === 0) { + onChange([fallbackDraft]) + } + }, [fallbackDraft, onChange, value.length]) const actionOptions = useMemo( () => [ @@ -31,7 +39,7 @@ export const ActionEditor: React.FC = ({ const mergedTagOptions = useMemo(() => { const optionMap = new Map(tagOptions.map((option) => [option.value, option])) - for (const action of value) { + for (const action of safeValue) { if (action.event !== "add_tag") continue const tagValues = Array.isArray(action.value) ? action.value @@ -47,19 +55,19 @@ export const ActionEditor: React.FC = ({ } return Array.from(optionMap.values()) - }, [tagOptions, value]) + }, [safeValue, tagOptions]) const updateAction = (id: string, patch: Partial>) => { - onChange(value.map((item) => (item.id === id ? { ...item, ...patch } : item))) + onChange(safeValue.map((item) => (item.id === id ? { ...item, ...patch } : item))) } const handleAddAction = () => { - onChange([...value, createDefaultActionDraft()]) + onChange([...safeValue, createDefaultActionDraft()]) } const handleRemoveAction = (id: string) => { - if (value.length <= 1) return - onChange(value.filter((item) => item.id !== id)) + if (safeValue.length <= 1) return + onChange(safeValue.filter((item) => item.id !== id)) } return ( @@ -68,7 +76,7 @@ export const ActionEditor: React.FC = ({ title={t("autoScore.triggeredActions")} > - {value.map((action) => ( + {safeValue.map((action) => (
{ + const fontOpt = fontOptions.find((f) => f.value === v) + if (!fontOpt) return + applyFontFamily(fontOpt.fontFamily) + setSettings((prev) => ({ ...prev, font_family: v })) + if ((window as any).api) { + const res = await (window as any).api.setSetting("font_family", v) + if (res.success) { + messageApi.success(t("settings.general.saved")) + } else { + messageApi.error(res.message || t("settings.general.saveFailed")) + } + } else { + messageApi.success(t("settings.general.saved")) + } + }} + style={{ width: "320px" }} + loading={isLoadingFonts} + options={fontOptions.map((opt) => ({ + value: opt.value, + label: opt.label, + }))} + showSearch + filterOption={(input, option) => + (option?.label ?? "").toLowerCase().includes(input.toLowerCase()) + } + /> +
+ {t("settings.fontFamilyHint")} +
+ + {!isMobile && ( <> diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 6947474..75a8700 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -135,6 +135,8 @@ }, "language": "Language", "languageHint": "Select interface display language", + "fontFamily": "Global Font", + "fontFamilyHint": "Select the application interface font (page refresh required for full effect)", "theme": "Theme", "password": "Set Password", "themeMode": "Mode", diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json index 5a7266b..d35a659 100644 --- a/src/i18n/locales/zh-CN.json +++ b/src/i18n/locales/zh-CN.json @@ -135,6 +135,8 @@ }, "language": "语言", "languageHint": "选择界面显示语言", + "fontFamily": "全局字体", + "fontFamilyHint": "选择应用界面的字体(需要刷新页面以完全生效)", "theme": "主题", "password": "设置密码", "themeMode": "模式",