{"repo": "cheng-ren/flowlens", "files": {"src/renderer/src/components/settings/LLMSettingsView.tsx": {"ec98c8d0a1e6109890dd4bdd0e0b45a0c0113292": {"t": 1785747362.5800986, "n": 11439, "h": "dfbe5d9956d52a5a", "c": "import React, { useEffect, useState } from \"react\";\nimport { C } from \"../../styles\";\n\nconst DEFAULT = {\n baseUrl: \"http://localhost:11434\",\n apiKey: \"\",\n model: \"qwen2.5:7b\",\n};\n\nconst PRESETS = [\n {\n label: \"Ollama 本地\",\n baseUrl: \"http://localhost:11434\",\n model: \"qwen2.5:7b\",\n apiKey: \"\",\n },\n {\n label: \"阿里百炼\",\n baseUrl: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n model: \"qwen-plus\",\n apiKey: \"\",\n },\n {\n label: \"DeepSeek\",\n baseUrl: \"https://api.deepseek.com/v1\",\n model: \"deepseek-chat\",\n apiKey: \"\",\n },\n {\n label: \"OpenAI\",\n baseUrl: \"https://api.openai.com/v1\",\n model: \"gpt-4o-mini\",\n apiKey: \"\",\n },\n];\n\nconst inputStyle: React.CSSProperties = {\n width: \"100%\",\n padding: \"9px 12px\",\n background: C.bgSurface,\n border: `1px solid ${C.borderMd}`,\n borderRadius: 8,\n color: C.text1,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n transition: \"border-color 0.15s\",\n fontFamily: \"inherit\",\n};\n\nconst labelStyle: React.CSSProperties = {\n fontSize: 11,\n color: C.text2,\n fontWeight: 600,\n marginBottom: 6,\n display: \"block\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.07em\",\n};\n\nconst hintStyle: React.CSSProperties = {\n fontSize: 12,\n color: C.text3,\n marginTop: 5,\n lineHeight: 1.5,\n};\n\nexport function LLMSettingsView() {\n const [baseUrl, setBaseUrl] = useState(DEFAULT.baseUrl);\n const [apiKey, setApiKey] = useState(DEFAULT.apiKey);\n const [model, setModel] = useState(DEFAULT.model);\n const [showKey, setShowKey] = useState(false);\n const [status, setStatus] = useState<\"idle\" | \"saved\" | \"error\">(\"idle\");\n const [testState, setTestState] = useState<\"idle\" | \"testing\" | \"ok\" | \"fail\">(\"idle\");\n const [testMsg, setTestMsg] = useState(\"\");\n\n useEffect(() => {\n // @ts-ignore\n window.api.getLlmConfig().then((cfg: typeof DEFAULT) => {\n setBaseUrl(cfg.baseUrl || DEFAULT.baseUrl);\n setApiKey(cfg.apiKey || \"\");\n setModel(cfg.model || DEFAULT.model);\n });\n }, []);\n\n const handleTest = async () => {\n setTestState(\"testing\");\n setTestMsg(\"\");\n try {\n // @ts-ignore\n const result: { ok: boolean; reply?: string; error?: string } = await window.api.testLlmConfig({ baseUrl, apiKey, model });\n if (result.ok) {\n setTestState(\"ok\");\n setTestMsg(result.reply || \"连接成功\");\n } else {\n setTestState(\"fail\");\n setTestMsg(result.error || \"连接失败\");\n }\n } catch (e: any) {\n setTestState(\"fail\");\n setTestMsg(e?.message || \"未知错误\");\n }\n };\n\n const handleSave = async () => {\n try {\n // @ts-ignore\n await window.api.saveLlmConfig({ baseUrl, apiKey, model });\n setStatus(\"saved\");\n } catch {\n setStatus(\"error\");\n } finally {\n setTimeout(() => setStatus(\"idle\"), 2500);\n }\n };\n\n const isOllama = baseUrl.includes(\"11434\") || !apiKey;\n\n return (\n
\n 用于商品账单的自动分类,默认使用本机 Ollama。\n
\n\n {isOllama\n ? \"Ollama 本地模式,无需 API Key\"\n : \"OpenAI 兼容接口,请填写 /v1 结尾的地址,例如 https://api.deepseek.com/v1\"}\n
\n\n Ollama 示例:qwen2.5:7b、llama3.2 | 云端示例:deepseek-chat、gpt-4o-mini\n
\nollama pull qwen2.5:7b,无需填写 API Key。\n https://dashscope.aliyuncs.com/compatible-mode/v1,\n 填入百炼 API Key,模型填 qwen-plus 或 qwen-turbo。\n https://api.deepseek.com/v1,\n 填入 API Key,模型填 deepseek-chat。\n \n 用于商品账单的自动分类,默认使用本机 Ollama。\n
\n\n {isOllama\n ? \"Ollama 本地模式,无需 API Key\"\n : \"OpenAI 兼容接口,请填写 /v1 结尾的地址,例如 https://api.deepseek.com/v1\"}\n
\n\n Ollama 示例:qwen2.5:7b、llama3.2 | 云端示例:deepseek-chat、gpt-4o-mini\n
\nollama pull qwen2.5:7b,无需填写 API Key。\n https://dashscope.aliyuncs.com/compatible-mode/v1,\n 填入百炼 API Key,模型填 qwen-plus 或 qwen-turbo。\n https://api.deepseek.com/v1,\n 填入 API Key,模型填 deepseek-chat。\n \n 配置用于账单分析与报表生成的 AI 大模型接入信息\n
\n