refactor(config): 将AI配置逻辑迁移至统一的状态管理store

- 移除独立的ai-config.ts文件,将其功能整合到use-config-store
- 更新所有组件导入路径从 "@/lib/ai-config" 到 "@/stores/use-config-store"
- 实现云端渠道和本地直连两种配置模式的支持
- 添加模型渠道配置管理和API请求代理转发功能
- 统一配置验证逻辑和有效配置获取方法
- 更新组件中使用的配置状态钩子和API调用方式
This commit is contained in:
HouYunFei
2026-05-21 13:36:30 +08:00
parent afd9631735
commit 6f1e0d347b
23 changed files with 431 additions and 201 deletions
@@ -7,15 +7,13 @@ import { motion } from "motion/react";
import { ImageGenerationPending } from "@/components/image-generation-pending";
import { ModelPicker } from "@/components/model-picker";
import type { AiConfig } from "@/lib/ai-config";
import { isAiConfigReady, useConfigStore, useEffectiveAiConfig, type AiConfig } from "@/stores/use-config-store";
import { canvasThemes } from "@/lib/canvas-theme";
import { createId } from "@/lib/id";
import { cn } from "@/lib/utils";
import { requestEdit, requestGeneration, requestImageQuestion, type ChatCompletionMessage } from "@/services/api/image";
import { imageToDataUrl, uploadImage } from "@/services/image-storage";
import { useAiConfigStore } from "@/stores/use-ai-config-store";
import { useAssetStore } from "@/stores/use-asset-store";
import { useConfigDialogStore } from "@/stores/use-config-dialog-store";
import { useThemeStore } from "@/stores/use-theme-store";
import type { ReferenceImage } from "@/types/image";
import { DiaTextReveal } from "@/components/ui/dia-text-reveal";
@@ -42,10 +40,11 @@ type CanvasAssistantPanelProps = {
export function CanvasAssistantPanel({ nodes, selectedNodeIds, sessions, activeSessionId, onSelectNodeIds, onSessionsChange, onInsertImage, onInsertText, onPasteImage, onCollapseStart, onCollapse }: CanvasAssistantPanelProps) {
const theme = canvasThemes[useThemeStore((state) => state.theme)];
const config = useAiConfigStore((state) => state.config);
const config = useConfigStore((state) => state.config);
const effectiveConfig = useEffectiveAiConfig(config);
const cleanupImages = useAssetStore((state) => state.cleanupImages);
const updateConfig = useAiConfigStore((state) => state.updateConfig);
const openConfigDialog = useConfigDialogStore((state) => state.openConfigDialog);
const updateConfig = useConfigStore((state) => state.updateConfig);
const openConfigDialog = useConfigStore((state) => state.openConfigDialog);
const [width, setWidth] = useState(390);
const [view, setView] = useState<"chat" | "history">("chat");
const [mode, setMode] = useState<AssistantMode>("image");
@@ -137,8 +136,8 @@ export function CanvasAssistantPanel({ nodes, selectedNodeIds, sessions, activeS
};
const sendMessage = async (text: string, nextMode: AssistantMode, history: CanvasAssistantMessage[], savedReferences?: CanvasAssistantReference[]) => {
const requestConfig = { ...config, model: nextMode === "image" ? config.imageModel || config.model : config.textModel || config.model };
if (!requestConfig.baseUrl.trim() || !requestConfig.model.trim() || !requestConfig.apiKey.trim()) {
const requestConfig = { ...effectiveConfig, model: nextMode === "image" ? effectiveConfig.imageModel || effectiveConfig.model : effectiveConfig.textModel || effectiveConfig.model };
if (!isAiConfigReady(requestConfig, requestConfig.model)) {
openConfigDialog(true);
return;
}
@@ -290,7 +289,7 @@ export function CanvasAssistantPanel({ nodes, selectedNodeIds, sessions, activeS
prompt={prompt}
isRunning={isRunning}
references={selectedReferences}
config={config}
config={effectiveConfig}
onModeChange={setMode}
onPromptChange={setPrompt}
onSubmit={submit}
@@ -6,10 +6,8 @@ import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Edit3, Eye, Image as ImageIc
import { App, Button, Empty, Input, InputNumber, Modal, Segmented } from "antd";
import { ModelPicker } from "@/components/model-picker";
import { defaultConfig, type AiConfig } from "@/lib/ai-config";
import { defaultConfig, useConfigStore, type AiConfig } from "@/stores/use-config-store";
import { canvasThemes } from "@/lib/canvas-theme";
import { useAiConfigStore } from "@/stores/use-ai-config-store";
import { useConfigDialogStore } from "@/stores/use-config-dialog-store";
import { useThemeStore } from "@/stores/use-theme-store";
import { CanvasSizePicker } from "./canvas-size-picker";
import type { NodeGenerationInput } from "./canvas-node-generation";
@@ -30,8 +28,8 @@ export function CanvasConfigNodePanel({ node, isRunning, inputSummary, inputs, o
const [previewOpen, setPreviewOpen] = useState(false);
const [editingTextId, setEditingTextId] = useState<string | null>(null);
const [editingText, setEditingText] = useState("");
const globalConfig = useAiConfigStore((state) => state.config);
const openConfigDialog = useConfigDialogStore((state) => state.openConfigDialog);
const globalConfig = useConfigStore((state) => state.config);
const openConfigDialog = useConfigStore((state) => state.openConfigDialog);
const theme = canvasThemes[useThemeStore((state) => state.theme)];
const mode = node.metadata?.generationMode || "image";
const config = buildNodeConfig(globalConfig, node, mode);
@@ -5,10 +5,8 @@ import { ArrowUp, LoaderCircle } from "lucide-react";
import { Button, InputNumber } from "antd";
import { ModelPicker } from "@/components/model-picker";
import { defaultConfig, type AiConfig } from "@/lib/ai-config";
import { defaultConfig, useConfigStore, type AiConfig } from "@/stores/use-config-store";
import { canvasThemes } from "@/lib/canvas-theme";
import { useAiConfigStore } from "@/stores/use-ai-config-store";
import { useConfigDialogStore } from "@/stores/use-config-dialog-store";
import { useThemeStore } from "@/stores/use-theme-store";
import { CanvasPromptLibrary } from "./canvas-prompt-library";
import { CanvasSizePicker } from "./canvas-size-picker";
@@ -25,8 +23,8 @@ type CanvasNodePromptPanelProps = {
};
export function CanvasNodePromptPanel({ node, isRunning, onPromptChange, onConfigChange, onGenerate }: CanvasNodePromptPanelProps) {
const globalConfig = useAiConfigStore((state) => state.config);
const openConfigDialog = useConfigDialogStore((state) => state.openConfigDialog);
const globalConfig = useConfigStore((state) => state.config);
const openConfigDialog = useConfigStore((state) => state.openConfigDialog);
const theme = canvasThemes[useThemeStore((state) => state.theme)];
const mode = defaultMode(node.type);
const config = buildNodeConfig(globalConfig, node, mode);