mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-27 08:14:33 +08:00
fix(config): defer common config save until form submission
- Change handleExtract and handleCommonConfigSnippetChange to use delayed save pattern - Add hasUnsavedCommonConfig state to track pending changes - Add getPendingCommonConfigSnippet and markCommonConfigSaved helper functions - Remove immediate backend API calls, save only on form submit - Add extractSuccessNeedSave and saveCommonConfigFailed i18n keys
This commit is contained in:
@@ -8,6 +8,7 @@ import { Form, FormField, FormItem, FormMessage } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { providerSchema, type ProviderFormData } from "@/lib/schemas/provider";
|
||||
import type { AppId } from "@/lib/api";
|
||||
import { configApi } from "@/lib/api";
|
||||
import type {
|
||||
ProviderCategory,
|
||||
ProviderMeta,
|
||||
@@ -478,6 +479,8 @@ export function ProviderForm({
|
||||
handleExtract: handleClaudeExtract,
|
||||
isLoading: isClaudeCommonConfigLoading,
|
||||
finalConfig: claudeFinalConfig,
|
||||
getPendingCommonConfigSnippet: getPendingClaudeCommonConfigSnippet,
|
||||
markCommonConfigSaved: markClaudeCommonConfigSaved,
|
||||
} = useCommonConfigSnippet({
|
||||
settingsConfig: form.getValues("settingsConfig"),
|
||||
onConfigChange: (config) => form.setValue("settingsConfig", config),
|
||||
@@ -498,6 +501,8 @@ export function ProviderForm({
|
||||
handleExtract: handleCodexExtract,
|
||||
isLoading: isCodexCommonConfigLoading,
|
||||
finalConfig: codexFinalConfig,
|
||||
getPendingCommonConfigSnippet: getPendingCodexCommonConfigSnippet,
|
||||
markCommonConfigSaved: markCodexCommonConfigSaved,
|
||||
} = useCodexCommonConfig({
|
||||
codexConfig,
|
||||
onConfigChange: handleCodexConfigChange,
|
||||
@@ -587,6 +592,8 @@ export function ProviderForm({
|
||||
handleExtract: handleGeminiExtract,
|
||||
isLoading: isGeminiCommonConfigLoading,
|
||||
finalEnv: geminiFinalEnv,
|
||||
getPendingCommonConfigSnippet: getPendingGeminiCommonConfigSnippet,
|
||||
markCommonConfigSaved: markGeminiCommonConfigSaved,
|
||||
} = useGeminiCommonConfig({
|
||||
envValue: geminiEnv,
|
||||
onEnvChange: handleGeminiEnvChange,
|
||||
@@ -817,7 +824,7 @@ export function ProviderForm({
|
||||
|
||||
const [isCommonConfigModalOpen, setIsCommonConfigModalOpen] = useState(false);
|
||||
|
||||
const handleSubmit = (values: ProviderFormData) => {
|
||||
const handleSubmit = async (values: ProviderFormData) => {
|
||||
// 检查通用配置是否仍在加载中
|
||||
const isCommonConfigLoading =
|
||||
(appId === "claude" && isClaudeCommonConfigLoading) ||
|
||||
@@ -970,6 +977,37 @@ export function ProviderForm({
|
||||
}
|
||||
}
|
||||
|
||||
// 保存待保存的通用配置(延迟保存模式:在表单提交时统一保存)
|
||||
try {
|
||||
if (appId === "claude") {
|
||||
const pendingSnippet = getPendingClaudeCommonConfigSnippet();
|
||||
if (pendingSnippet !== null) {
|
||||
await configApi.setCommonConfigSnippet("claude", pendingSnippet);
|
||||
markClaudeCommonConfigSaved();
|
||||
}
|
||||
} else if (appId === "codex") {
|
||||
const pendingSnippet = getPendingCodexCommonConfigSnippet();
|
||||
if (pendingSnippet !== null) {
|
||||
await configApi.setCommonConfigSnippet("codex", pendingSnippet);
|
||||
markCodexCommonConfigSaved();
|
||||
}
|
||||
} else if (appId === "gemini") {
|
||||
const pendingSnippet = getPendingGeminiCommonConfigSnippet();
|
||||
if (pendingSnippet !== null) {
|
||||
await configApi.setCommonConfigSnippet("gemini", pendingSnippet);
|
||||
markGeminiCommonConfigSaved();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("保存通用配置失败:", error);
|
||||
toast.error(
|
||||
t("providerForm.saveCommonConfigFailed", {
|
||||
defaultValue: "保存通用配置失败",
|
||||
}),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let settingsConfig: string;
|
||||
|
||||
// Codex: 组合 auth 和 config
|
||||
|
||||
@@ -88,6 +88,12 @@ export interface UseCodexCommonConfigReturn {
|
||||
handleExtract: () => Promise<void>;
|
||||
/** 最终配置(运行时合并结果,只读) */
|
||||
finalConfig: string;
|
||||
/** 是否有待保存的通用配置变更 */
|
||||
hasUnsavedCommonConfig: boolean;
|
||||
/** 获取待保存的通用配置片段(用于 handleSubmit) */
|
||||
getPendingCommonConfigSnippet: () => string | null;
|
||||
/** 标记通用配置已保存 */
|
||||
markCommonConfigSaved: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,18 +124,8 @@ export function useCodexCommonConfig({
|
||||
const [commonConfigError, setCommonConfigError] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isExtracting, setIsExtracting] = useState(false);
|
||||
|
||||
// 用于避免异步保存乱序
|
||||
const saveSequenceRef = useRef(0);
|
||||
const saveQueueRef = useRef<Promise<void>>(Promise.resolve());
|
||||
const enqueueSave = useCallback((saveFn: () => Promise<void>) => {
|
||||
const next = saveQueueRef.current.then(saveFn);
|
||||
// Log errors to help with debugging, but don't block subsequent saves
|
||||
saveQueueRef.current = next.catch((e) => {
|
||||
console.error("[SaveQueue] Codex common config save failed:", e);
|
||||
});
|
||||
return next;
|
||||
}, []);
|
||||
// 是否有待保存的通用配置变更
|
||||
const [hasUnsavedCommonConfig, setHasUnsavedCommonConfig] = useState(false);
|
||||
|
||||
// 用于跟踪编辑模式是否已初始化
|
||||
const hasInitializedEditMode = useRef(false);
|
||||
@@ -340,24 +336,15 @@ export function useCodexCommonConfig({
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// 处理通用配置片段变化
|
||||
// 处理通用配置片段变化(延迟保存模式:只更新本地状态,实际保存在表单提交时)
|
||||
// ============================================================================
|
||||
const handleCommonConfigSnippetChange = useCallback(
|
||||
(value: string) => {
|
||||
setCommonConfigSnippetState(value);
|
||||
|
||||
if (!value.trim()) {
|
||||
const saveId = ++saveSequenceRef.current;
|
||||
setCommonConfigError("");
|
||||
enqueueSave(() => configApi.setCommonConfigSnippet("codex", "")).catch(
|
||||
(error) => {
|
||||
if (saveSequenceRef.current !== saveId) return;
|
||||
console.error("保存 Codex 通用配置失败:", error);
|
||||
setCommonConfigError(
|
||||
t("codexConfig.saveFailed", { error: String(error) }),
|
||||
);
|
||||
},
|
||||
);
|
||||
setHasUnsavedCommonConfig(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -372,26 +359,17 @@ export function useCodexCommonConfig({
|
||||
return;
|
||||
}
|
||||
|
||||
const saveId = ++saveSequenceRef.current;
|
||||
setCommonConfigError("");
|
||||
enqueueSave(() => configApi.setCommonConfigSnippet("codex", value)).catch(
|
||||
(error) => {
|
||||
if (saveSequenceRef.current !== saveId) return;
|
||||
console.error("保存 Codex 通用配置失败:", error);
|
||||
setCommonConfigError(
|
||||
t("codexConfig.saveFailed", { error: String(error) }),
|
||||
);
|
||||
},
|
||||
);
|
||||
setHasUnsavedCommonConfig(true);
|
||||
|
||||
// 注意:新架构下不再需要同步到其他供应商的 settingsConfig
|
||||
// 因为 finalConfig 是运行时计算的
|
||||
},
|
||||
[enqueueSave, t],
|
||||
[t],
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// 从当前最终配置提取通用配置片段
|
||||
// 从当前最终配置提取通用配置片段(延迟保存模式:只更新本地状态,实际保存在表单提交时)
|
||||
// ============================================================================
|
||||
const handleExtract = useCallback(async () => {
|
||||
setIsExtracting(true);
|
||||
@@ -420,11 +398,9 @@ export function useCodexCommonConfig({
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新片段状态
|
||||
// 更新片段状态(延迟保存:不立即调用后端 API)
|
||||
setCommonConfigSnippetState(extracted);
|
||||
|
||||
// 保存到后端
|
||||
await configApi.setCommonConfigSnippet("codex", extracted);
|
||||
setHasUnsavedCommonConfig(true);
|
||||
|
||||
// 提取成功后,从 config 中移除与 extracted 相同的部分
|
||||
const customToml = extractConfigToml(codexConfig);
|
||||
@@ -435,10 +411,10 @@ export function useCodexCommonConfig({
|
||||
const parsed = JSON.parse(codexConfig);
|
||||
parsed.config = diffResult.customToml;
|
||||
onConfigChange(JSON.stringify(parsed, null, 2));
|
||||
// Notify user that config was modified
|
||||
// Notify user that config was modified (提示用户需要保存)
|
||||
toast.success(
|
||||
t("codexConfig.extractSuccess", {
|
||||
defaultValue: "已提取通用配置,自定义配置已自动更新",
|
||||
t("codexConfig.extractSuccessNeedSave", {
|
||||
defaultValue: "已提取通用配置,点击保存按钮完成保存",
|
||||
}),
|
||||
);
|
||||
} catch (parseError) {
|
||||
@@ -458,6 +434,20 @@ export function useCodexCommonConfig({
|
||||
}
|
||||
}, [finalConfig, codexConfig, onConfigChange, extractConfigToml, t]);
|
||||
|
||||
// ============================================================================
|
||||
// 获取待保存的通用配置片段(用于 handleSubmit 中统一保存)
|
||||
// ============================================================================
|
||||
const getPendingCommonConfigSnippet = useCallback(() => {
|
||||
return hasUnsavedCommonConfig ? commonConfigSnippet : null;
|
||||
}, [hasUnsavedCommonConfig, commonConfigSnippet]);
|
||||
|
||||
// ============================================================================
|
||||
// 标记通用配置已保存
|
||||
// ============================================================================
|
||||
const markCommonConfigSaved = useCallback(() => {
|
||||
setHasUnsavedCommonConfig(false);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
useCommonConfig,
|
||||
commonConfigSnippet,
|
||||
@@ -468,5 +458,8 @@ export function useCodexCommonConfig({
|
||||
handleCommonConfigSnippetChange,
|
||||
handleExtract,
|
||||
finalConfig,
|
||||
hasUnsavedCommonConfig,
|
||||
getPendingCommonConfigSnippet,
|
||||
markCommonConfigSaved,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,6 +65,12 @@ export interface UseCommonConfigSnippetReturn {
|
||||
handleExtract: () => Promise<void>;
|
||||
/** 最终配置(运行时合并结果,只读) */
|
||||
finalConfig: string;
|
||||
/** 是否有待保存的通用配置变更 */
|
||||
hasUnsavedCommonConfig: boolean;
|
||||
/** 获取待保存的通用配置片段(用于 handleSubmit) */
|
||||
getPendingCommonConfigSnippet: () => string | null;
|
||||
/** 标记通用配置已保存 */
|
||||
markCommonConfigSaved: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,18 +102,8 @@ export function useCommonConfigSnippet({
|
||||
const [commonConfigError, setCommonConfigError] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isExtracting, setIsExtracting] = useState(false);
|
||||
|
||||
// 用于避免异步保存乱序
|
||||
const saveSequenceRef = useRef(0);
|
||||
const saveQueueRef = useRef<Promise<void>>(Promise.resolve());
|
||||
const enqueueSave = useCallback((saveFn: () => Promise<void>) => {
|
||||
const next = saveQueueRef.current.then(saveFn);
|
||||
// Log errors to help with debugging, but don't block subsequent saves
|
||||
saveQueueRef.current = next.catch((e) => {
|
||||
console.error("[SaveQueue] Claude common config save failed:", e);
|
||||
});
|
||||
return next;
|
||||
}, []);
|
||||
// 是否有待保存的通用配置变更
|
||||
const [hasUnsavedCommonConfig, setHasUnsavedCommonConfig] = useState(false);
|
||||
|
||||
// 用于跟踪编辑模式是否已初始化
|
||||
const hasInitializedEditMode = useRef(false);
|
||||
@@ -344,54 +340,33 @@ export function useCommonConfigSnippet({
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// 处理通用配置片段变化
|
||||
// 处理通用配置片段变化(延迟保存模式:只更新本地状态,实际保存在表单提交时)
|
||||
// ============================================================================
|
||||
const handleCommonConfigSnippetChange = useCallback(
|
||||
(value: string) => {
|
||||
setCommonConfigSnippetState(value);
|
||||
const handleCommonConfigSnippetChange = useCallback((value: string) => {
|
||||
setCommonConfigSnippetState(value);
|
||||
|
||||
if (!value.trim()) {
|
||||
const saveId = ++saveSequenceRef.current;
|
||||
setCommonConfigError("");
|
||||
enqueueSave(() => configApi.setCommonConfigSnippet("claude", "")).catch(
|
||||
(error) => {
|
||||
if (saveSequenceRef.current !== saveId) return;
|
||||
console.error("保存通用配置失败:", error);
|
||||
setCommonConfigError(
|
||||
t("claudeConfig.saveFailed", { error: String(error) }),
|
||||
);
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// JSON 格式校验
|
||||
const validationError = validateJsonConfig(value, "通用配置片段");
|
||||
if (validationError) {
|
||||
setCommonConfigError(validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
const saveId = ++saveSequenceRef.current;
|
||||
if (!value.trim()) {
|
||||
setCommonConfigError("");
|
||||
enqueueSave(() =>
|
||||
configApi.setCommonConfigSnippet("claude", value),
|
||||
).catch((error) => {
|
||||
if (saveSequenceRef.current !== saveId) return;
|
||||
console.error("保存通用配置失败:", error);
|
||||
setCommonConfigError(
|
||||
t("claudeConfig.saveFailed", { error: String(error) }),
|
||||
);
|
||||
});
|
||||
setHasUnsavedCommonConfig(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// 注意:新架构下不再需要同步到其他供应商的 settingsConfig
|
||||
// 因为 finalConfig 是运行时计算的
|
||||
},
|
||||
[enqueueSave, t],
|
||||
);
|
||||
// JSON 格式校验
|
||||
const validationError = validateJsonConfig(value, "通用配置片段");
|
||||
if (validationError) {
|
||||
setCommonConfigError(validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
setCommonConfigError("");
|
||||
setHasUnsavedCommonConfig(true);
|
||||
|
||||
// 注意:新架构下不再需要同步到其他供应商的 settingsConfig
|
||||
// 因为 finalConfig 是运行时计算的
|
||||
}, []);
|
||||
|
||||
// ============================================================================
|
||||
// 从当前最终配置提取通用配置片段
|
||||
// 从当前最终配置提取通用配置片段(延迟保存模式:只更新本地状态,实际保存在表单提交时)
|
||||
// ============================================================================
|
||||
const handleExtract = useCallback(async () => {
|
||||
setIsExtracting(true);
|
||||
@@ -414,11 +389,9 @@ export function useCommonConfigSnippet({
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新片段状态
|
||||
// 更新片段状态(延迟保存:不立即调用后端 API)
|
||||
setCommonConfigSnippetState(extracted);
|
||||
|
||||
// 保存到后端
|
||||
await configApi.setCommonConfigSnippet("claude", extracted);
|
||||
setHasUnsavedCommonConfig(true);
|
||||
|
||||
// 提取成功后,从 settingsConfig 中移除与 extracted 相同的部分
|
||||
try {
|
||||
@@ -428,10 +401,10 @@ export function useCommonConfigSnippet({
|
||||
if (isPlainObject(customParsed) && isPlainObject(extractedParsed)) {
|
||||
const diffResult = extractDifference(customParsed, extractedParsed);
|
||||
onConfigChange(JSON.stringify(diffResult.customConfig, null, 2));
|
||||
// Notify user that config was modified
|
||||
// Notify user that config was modified (提示用户需要保存)
|
||||
toast.success(
|
||||
t("claudeConfig.extractSuccess", {
|
||||
defaultValue: "已提取通用配置,自定义配置已自动更新",
|
||||
t("claudeConfig.extractSuccessNeedSave", {
|
||||
defaultValue: "已提取通用配置,点击保存按钮完成保存",
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -451,6 +424,20 @@ export function useCommonConfigSnippet({
|
||||
}
|
||||
}, [finalConfig, settingsConfig, onConfigChange, t]);
|
||||
|
||||
// ============================================================================
|
||||
// 获取待保存的通用配置片段(用于 handleSubmit 中统一保存)
|
||||
// ============================================================================
|
||||
const getPendingCommonConfigSnippet = useCallback(() => {
|
||||
return hasUnsavedCommonConfig ? commonConfigSnippet : null;
|
||||
}, [hasUnsavedCommonConfig, commonConfigSnippet]);
|
||||
|
||||
// ============================================================================
|
||||
// 标记通用配置已保存
|
||||
// ============================================================================
|
||||
const markCommonConfigSaved = useCallback(() => {
|
||||
setHasUnsavedCommonConfig(false);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
useCommonConfig,
|
||||
commonConfigSnippet,
|
||||
@@ -461,5 +448,8 @@ export function useCommonConfigSnippet({
|
||||
handleCommonConfigSnippetChange,
|
||||
handleExtract,
|
||||
finalConfig,
|
||||
hasUnsavedCommonConfig,
|
||||
getPendingCommonConfigSnippet,
|
||||
markCommonConfigSaved,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,6 +65,12 @@ export interface UseGeminiCommonConfigReturn {
|
||||
handleExtract: () => Promise<void>;
|
||||
/** 最终 env 对象(运行时合并结果,只读) */
|
||||
finalEnv: Record<string, string>;
|
||||
/** 是否有待保存的通用配置变更 */
|
||||
hasUnsavedCommonConfig: boolean;
|
||||
/** 获取待保存的通用配置片段(用于 handleSubmit) */
|
||||
getPendingCommonConfigSnippet: () => string | null;
|
||||
/** 标记通用配置已保存 */
|
||||
markCommonConfigSaved: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,18 +103,8 @@ export function useGeminiCommonConfig({
|
||||
const [commonConfigError, setCommonConfigError] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isExtracting, setIsExtracting] = useState(false);
|
||||
|
||||
// 用于避免异步保存乱序
|
||||
const saveSequenceRef = useRef(0);
|
||||
const saveQueueRef = useRef<Promise<void>>(Promise.resolve());
|
||||
const enqueueSave = useCallback((saveFn: () => Promise<void>) => {
|
||||
const next = saveQueueRef.current.then(saveFn);
|
||||
// Log errors to help with debugging, but don't block subsequent saves
|
||||
saveQueueRef.current = next.catch((e) => {
|
||||
console.error("[SaveQueue] Gemini common config save failed:", e);
|
||||
});
|
||||
return next;
|
||||
}, []);
|
||||
// 是否有待保存的通用配置变更
|
||||
const [hasUnsavedCommonConfig, setHasUnsavedCommonConfig] = useState(false);
|
||||
|
||||
// 用于跟踪编辑模式是否已初始化
|
||||
const hasInitializedEditMode = useRef(false);
|
||||
@@ -330,24 +326,15 @@ export function useGeminiCommonConfig({
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// 处理通用配置片段变化
|
||||
// 处理通用配置片段变化(延迟保存模式:只更新本地状态,实际保存在表单提交时)
|
||||
// ============================================================================
|
||||
const handleCommonConfigSnippetChange = useCallback(
|
||||
(value: string) => {
|
||||
setCommonConfigSnippetState(value);
|
||||
|
||||
if (!value.trim()) {
|
||||
const saveId = ++saveSequenceRef.current;
|
||||
setCommonConfigError("");
|
||||
enqueueSave(() => configApi.setCommonConfigSnippet("gemini", "")).catch(
|
||||
(error) => {
|
||||
if (saveSequenceRef.current !== saveId) return;
|
||||
console.error("保存 Gemini 通用配置失败:", error);
|
||||
setCommonConfigError(
|
||||
t("geminiConfig.saveFailed", { error: String(error) }),
|
||||
);
|
||||
},
|
||||
);
|
||||
setHasUnsavedCommonConfig(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -358,26 +345,17 @@ export function useGeminiCommonConfig({
|
||||
return;
|
||||
}
|
||||
|
||||
const saveId = ++saveSequenceRef.current;
|
||||
setCommonConfigError("");
|
||||
enqueueSave(() =>
|
||||
configApi.setCommonConfigSnippet("gemini", value),
|
||||
).catch((error) => {
|
||||
if (saveSequenceRef.current !== saveId) return;
|
||||
console.error("保存 Gemini 通用配置失败:", error);
|
||||
setCommonConfigError(
|
||||
t("geminiConfig.saveFailed", { error: String(error) }),
|
||||
);
|
||||
});
|
||||
setHasUnsavedCommonConfig(true);
|
||||
|
||||
// 注意:新架构下不再需要同步到其他供应商的 settingsConfig
|
||||
// 因为 finalEnv 是运行时计算的
|
||||
},
|
||||
[enqueueSave, parseSnippetEnv, t],
|
||||
[parseSnippetEnv],
|
||||
);
|
||||
|
||||
// ============================================================================
|
||||
// 从当前最终 env 提取通用配置片段
|
||||
// 从当前最终 env 提取通用配置片段(延迟保存模式:只更新本地状态,实际保存在表单提交时)
|
||||
// ============================================================================
|
||||
const handleExtract = useCallback(async () => {
|
||||
setIsExtracting(true);
|
||||
@@ -402,11 +380,9 @@ export function useGeminiCommonConfig({
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新片段状态
|
||||
// 更新片段状态(延迟保存:不立即调用后端 API)
|
||||
setCommonConfigSnippetState(extracted);
|
||||
|
||||
// 保存到后端
|
||||
await configApi.setCommonConfigSnippet("gemini", extracted);
|
||||
setHasUnsavedCommonConfig(true);
|
||||
|
||||
// 提取成功后,从 customEnv 中移除与 extracted 相同的部分
|
||||
const diffResult = extractDifference(
|
||||
@@ -420,10 +396,10 @@ export function useGeminiCommonConfig({
|
||||
}
|
||||
}
|
||||
onEnvChange(envObjToString(newCustomEnv));
|
||||
// Notify user that config was modified
|
||||
// Notify user that config was modified (提示用户需要保存)
|
||||
toast.success(
|
||||
t("geminiConfig.extractSuccess", {
|
||||
defaultValue: "已提取通用配置,自定义配置已自动更新",
|
||||
t("geminiConfig.extractSuccessNeedSave", {
|
||||
defaultValue: "已提取通用配置,点击保存按钮完成保存",
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -436,6 +412,20 @@ export function useGeminiCommonConfig({
|
||||
}
|
||||
}, [finalEnv, customEnv, onEnvChange, envObjToString, parseSnippetEnv, t]);
|
||||
|
||||
// ============================================================================
|
||||
// 获取待保存的通用配置片段(用于 handleSubmit 中统一保存)
|
||||
// ============================================================================
|
||||
const getPendingCommonConfigSnippet = useCallback(() => {
|
||||
return hasUnsavedCommonConfig ? commonConfigSnippet : null;
|
||||
}, [hasUnsavedCommonConfig, commonConfigSnippet]);
|
||||
|
||||
// ============================================================================
|
||||
// 标记通用配置已保存
|
||||
// ============================================================================
|
||||
const markCommonConfigSaved = useCallback(() => {
|
||||
setHasUnsavedCommonConfig(false);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
useCommonConfig,
|
||||
commonConfigSnippet,
|
||||
@@ -446,5 +436,8 @@ export function useGeminiCommonConfig({
|
||||
handleCommonConfigSnippetChange,
|
||||
handleExtract,
|
||||
finalEnv,
|
||||
hasUnsavedCommonConfig,
|
||||
getPendingCommonConfigSnippet,
|
||||
markCommonConfigSaved,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"extractFromCurrent": "Extract from Editor",
|
||||
"extractNoCommonConfig": "No common config available to extract from editor",
|
||||
"extractFailed": "Extract failed: {{error}}",
|
||||
"extractSuccessNeedSave": "Common config extracted, click Save to complete",
|
||||
"saveFailed": "Save failed: {{error}}",
|
||||
"hidePreview": "Hide merged preview",
|
||||
"showPreview": "Show merged preview",
|
||||
@@ -493,7 +494,8 @@
|
||||
"categoryAggregation": "Aggregation",
|
||||
"categoryThirdParty": "Third Party",
|
||||
"commonConfigLoading": "Common config is still loading, please wait before saving",
|
||||
"commonConfigSyncFailed": "Common config sync failed for some providers. Please retry."
|
||||
"commonConfigSyncFailed": "Common config sync failed for some providers. Please retry.",
|
||||
"saveCommonConfigFailed": "Failed to save common config"
|
||||
},
|
||||
"endpointTest": {
|
||||
"title": "API Endpoint Management",
|
||||
@@ -563,6 +565,7 @@
|
||||
"extractFromCurrent": "Extract from Editor",
|
||||
"extractNoCommonConfig": "No common config available to extract from editor",
|
||||
"extractFailed": "Extract failed: {{error}}",
|
||||
"extractSuccessNeedSave": "Common config extracted, click Save to complete",
|
||||
"saveFailed": "Save failed: {{error}}"
|
||||
},
|
||||
"geminiConfig": {
|
||||
@@ -577,6 +580,7 @@
|
||||
"extractFromCurrent": "Extract from Editor",
|
||||
"extractNoCommonConfig": "No common config available to extract from editor",
|
||||
"extractFailed": "Extract failed: {{error}}",
|
||||
"extractSuccessNeedSave": "Common config extracted, click Save to complete",
|
||||
"saveFailed": "Save failed: {{error}}",
|
||||
"extractedConfigInvalid": "Extracted config format is invalid",
|
||||
"invalidJsonFormat": "Common config snippet format error (must be valid JSON)",
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"extractFromCurrent": "編集内容から抽出",
|
||||
"extractNoCommonConfig": "編集内容から抽出できる共通設定がありません",
|
||||
"extractFailed": "抽出に失敗しました: {{error}}",
|
||||
"extractSuccessNeedSave": "共通設定を抽出しました。保存ボタンをクリックして完了してください",
|
||||
"saveFailed": "保存に失敗しました: {{error}}",
|
||||
"hidePreview": "マージプレビューを非表示",
|
||||
"showPreview": "マージプレビューを表示",
|
||||
@@ -493,7 +494,8 @@
|
||||
"categoryAggregation": "アグリゲーター",
|
||||
"categoryThirdParty": "サードパーティ",
|
||||
"commonConfigLoading": "共通設定を読み込み中です。保存する前にお待ちください",
|
||||
"commonConfigSyncFailed": "共通設定の同期に失敗しました。再試行してください"
|
||||
"commonConfigSyncFailed": "共通設定の同期に失敗しました。再試行してください",
|
||||
"saveCommonConfigFailed": "共通設定の保存に失敗しました"
|
||||
},
|
||||
"endpointTest": {
|
||||
"title": "API エンドポイント管理",
|
||||
@@ -563,6 +565,7 @@
|
||||
"extractFromCurrent": "編集内容から抽出",
|
||||
"extractNoCommonConfig": "編集内容から抽出できる共通設定がありません",
|
||||
"extractFailed": "抽出に失敗しました: {{error}}",
|
||||
"extractSuccessNeedSave": "共通設定を抽出しました。保存ボタンをクリックして完了してください",
|
||||
"saveFailed": "保存に失敗しました: {{error}}"
|
||||
},
|
||||
"geminiConfig": {
|
||||
@@ -577,6 +580,7 @@
|
||||
"extractFromCurrent": "編集内容から抽出",
|
||||
"extractNoCommonConfig": "編集内容から抽出できる共通設定がありません",
|
||||
"extractFailed": "抽出に失敗しました: {{error}}",
|
||||
"extractSuccessNeedSave": "共通設定を抽出しました。保存ボタンをクリックして完了してください",
|
||||
"saveFailed": "保存に失敗しました: {{error}}",
|
||||
"extractedConfigInvalid": "抽出した設定のフォーマットが不正です",
|
||||
"invalidJsonFormat": "共通設定スニペットの形式が不正です(有効な JSON でなければなりません)",
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"extractFromCurrent": "从编辑内容提取",
|
||||
"extractNoCommonConfig": "当前编辑内容没有可提取的通用配置",
|
||||
"extractFailed": "提取失败: {{error}}",
|
||||
"extractSuccessNeedSave": "已提取通用配置,点击保存按钮完成保存",
|
||||
"saveFailed": "保存失败: {{error}}",
|
||||
"hidePreview": "隐藏合并预览",
|
||||
"showPreview": "显示合并预览",
|
||||
@@ -493,7 +494,8 @@
|
||||
"categoryAggregation": "聚合服务",
|
||||
"categoryThirdParty": "第三方",
|
||||
"commonConfigLoading": "通用配置正在加载中,请稍候再保存",
|
||||
"commonConfigSyncFailed": "通用配置同步部分失败,请重试"
|
||||
"commonConfigSyncFailed": "通用配置同步部分失败,请重试",
|
||||
"saveCommonConfigFailed": "保存通用配置失败"
|
||||
},
|
||||
"endpointTest": {
|
||||
"title": "请求地址管理",
|
||||
@@ -577,6 +579,7 @@
|
||||
"extractFromCurrent": "从编辑内容提取",
|
||||
"extractNoCommonConfig": "当前编辑内容没有可提取的通用配置",
|
||||
"extractFailed": "提取失败: {{error}}",
|
||||
"extractSuccessNeedSave": "已提取通用配置,点击保存按钮完成保存",
|
||||
"saveFailed": "保存失败: {{error}}",
|
||||
"extractedConfigInvalid": "提取的配置格式错误",
|
||||
"invalidJsonFormat": "通用配置片段格式错误(必须是有效的 JSON)",
|
||||
|
||||
Reference in New Issue
Block a user