From 6342419a8574fa948bd5842aa5fcb13fb3db243c Mon Sep 17 00:00:00 2001 From: Forrest Date: Sun, 28 Dec 2025 13:58:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201=E3=80=81=E6=96=B0=E5=A2=9EGLM?= =?UTF-8?q?=E4=B8=A4=E4=B8=AA=E5=85=8D=E8=B4=B9=E8=B0=83=E7=94=A8=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=202=E3=80=81=E6=96=B0=E5=A2=9E=E8=B1=86=E5=8C=85?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=95=86=E5=92=8C=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E6=9C=80=E6=96=B0=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron.vite.config.ts | 5 +++++ electron/main/ai/llm/index.ts | 23 ++++++++++++++++++++- electron/main/ai/llm/types.ts | 2 +- electron/main/index.ts | 4 ++-- package.json | 2 +- src/assets/styles/main.css | 25 +++++++++++++++++++++++ src/components.d.ts | 38 +++++++++++++++++------------------ 7 files changed, 75 insertions(+), 24 deletions(-) diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 8794ee9..47a9ccf 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -60,6 +60,11 @@ export default defineConfig(() => { server: { host: '0.0.0.0', port: 3400, + hmr: { + protocol: 'ws', + host: 'localhost', + port: 3400, + }, }, }, } diff --git a/electron/main/ai/llm/index.ts b/electron/main/ai/llm/index.ts index 7f80961..5f50be0 100644 --- a/electron/main/ai/llm/index.ts +++ b/electron/main/ai/llm/index.ts @@ -53,6 +53,8 @@ const GLM_INFO: ProviderInfo = { { id: 'glm-4-flash', name: 'GLM-4-Flash', description: '高速模型,性价比高' }, { id: 'glm-4', name: 'GLM-4', description: '标准模型' }, { id: 'glm-4v-plus', name: 'GLM-4V-Plus', description: '多模态视觉模型' }, + { id: 'glm-4.6v-flash', name: '4.6V免费版', description: '4.6V免费版模型' }, + { id: 'glm-4.5-flash', name: '4.5免费版', description: '4.5免费版模型' }, ], } @@ -69,6 +71,20 @@ const KIMI_INFO: ProviderInfo = { ], } +/** 豆包 (字节跳动 ByteDance) 提供商信息 */ +const DOUBAO_INFO: ProviderInfo = { + id: 'doubao', + name: '豆包', + description: '字节跳动豆包 AI 大语言模型', + defaultBaseUrl: 'https://ark.cn-beijing.volces.com/api/v3', + models: [ + { id: 'doubao-seed-1-6-lite-251015', name: '性价比豆包1.6', description: '性价比豆包1.6模型' }, + { id: 'doubao-seed-1-6-251015', name: '更强豆包1.6', description: '更强豆包1.6模型' }, + { id: 'doubao-seed-1-6-flash-250828', name: '更快豆包1.6', description: '更快豆包1.6模型' }, + { id: 'doubao-1-5-lite-32k-250115', name: '豆包1.5Pro', description: '豆包1.5Pro模型' }, + ], +} + // 所有支持的提供商信息 export const PROVIDERS: ProviderInfo[] = [ DEEPSEEK_INFO, @@ -77,6 +93,7 @@ export const PROVIDERS: ProviderInfo[] = [ MINIMAX_INFO, GLM_INFO, KIMI_INFO, + DOUBAO_INFO, OPENAI_COMPATIBLE_INFO, ] @@ -333,6 +350,7 @@ export function createLLMService(config: ExtendedLLMConfig): ILLMService { case 'minimax': case 'glm': case 'kimi': + case 'doubao': return new OpenAICompatibleService(config.apiKey, config.model, baseUrl) case 'openai-compatible': return new OpenAICompatibleService(config.apiKey, config.model, config.baseUrl, config.disableThinking) @@ -370,7 +388,10 @@ export function getProviderInfo(provider: LLMProvider): ProviderInfo | null { /** * 验证 API Key */ -export async function validateApiKey(provider: LLMProvider, apiKey: string): Promise { +export async function validateApiKey( + provider: LLMProvider, + apiKey: string +): Promise<{ success: boolean; error?: string }> { const service = createLLMService({ provider, apiKey }) return service.validateApiKey() } diff --git a/electron/main/ai/llm/types.ts b/electron/main/ai/llm/types.ts index 4918e7a..e7d4f81 100644 --- a/electron/main/ai/llm/types.ts +++ b/electron/main/ai/llm/types.ts @@ -5,7 +5,7 @@ /** * 支持的 LLM 提供商 */ -export type LLMProvider = 'deepseek' | 'qwen' | 'minimax' | 'glm' | 'kimi' | 'gemini' | 'openai-compatible' +export type LLMProvider = 'deepseek' | 'qwen' | 'minimax' | 'glm' | 'kimi' | 'gemini' | 'doubao' | 'openai-compatible' /** * LLM 配置 diff --git a/electron/main/index.ts b/electron/main/index.ts index 7539482..92a17ea 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -61,9 +61,9 @@ class MainProcess { async createWindow() { this.mainWindow = new BrowserWindow({ width: 1180, - height: 752, + height: 800, minWidth: 1180, - minHeight: 752, + minHeight: 800, show: false, autoHideMenuBar: true, webPreferences: { diff --git a/package.json b/package.json index 1598d16..7496ae1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ChatLab", - "version": "0.1.3", + "version": "0.1.4", "description": "获取你的聊天记录年度分析报告", "repository": { "type": "git", diff --git a/src/assets/styles/main.css b/src/assets/styles/main.css index 20ca0a6..8400366 100644 --- a/src/assets/styles/main.css +++ b/src/assets/styles/main.css @@ -16,3 +16,28 @@ --color-pink-900: #84173b; --color-pink-950: #4a071c; } + +/* 隐藏下拉框滚动条 - 针对所有下拉菜单 */ +/* 只针对下拉菜单相关的元素,不影响页面其他滚动容器 */ + +/* Firefox - 隐藏滚动条但保留滚动功能 */ +[data-headlessui-state], +[role="listbox"], +[role="menu"], +.select-menu, +.dropdown-menu, +[data-headlessui-state] > ul, +[data-headlessui-state] > div, +[role="listbox"] > ul, +[role="listbox"] > div, +[data-headlessui-state] ul, +[data-headlessui-state] div, +[role="listbox"] ul, +[role="listbox"] div, +body > [data-headlessui-state], +body > [role="listbox"], +body [data-headlessui-state][style*="position"], +body [role="listbox"][style*="position"] { + scrollbar-width: none !important; + -ms-overflow-style: none !important; +} \ No newline at end of file diff --git a/src/components.d.ts b/src/components.d.ts index 04a1c7c..d0d113e 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -13,25 +13,25 @@ declare module 'vue' { export interface GlobalComponents { RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] - UAlert: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Alert.vue')['default'] - UApp: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/App.vue')['default'] + UAlert: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Alert.vue')['default'] + UApp: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/App.vue')['default'] UAvatar: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Avatar.vue')['default'] - UBadge: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Badge.vue')['default'] - UButton: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Button.vue')['default'] - UChatPrompt: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/ChatPrompt.vue')['default'] - UChatPromptSubmit: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/ChatPromptSubmit.vue')['default'] - UContextMenu: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/ContextMenu.vue')['default'] - UDrawer: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Drawer.vue')['default'] - UIcon: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/vue/components/Icon.vue')['default'] - UInput: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Input.vue')['default'] - UInputTags: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/InputTags.vue')['default'] - UModal: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Modal.vue')['default'] - UPopover: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Popover.vue')['default'] - UProgress: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Progress.vue')['default'] - USelect: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Select.vue')['default'] - USwitch: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Switch.vue')['default'] - UTabs: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Tabs.vue')['default'] - UTextarea: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Textarea.vue')['default'] - UTooltip: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parser@7.28.5_axios@1.13.2_embla-carousel@8.6.0_typescript@5.9.3__1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Tooltip.vue')['default'] + UBadge: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Badge.vue')['default'] + UButton: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Button.vue')['default'] + UChatPrompt: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/ChatPrompt.vue')['default'] + UChatPromptSubmit: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/ChatPromptSubmit.vue')['default'] + UContextMenu: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/ContextMenu.vue')['default'] + UDrawer: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Drawer.vue')['default'] + UIcon: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/vue/components/Icon.vue')['default'] + UInput: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Input.vue')['default'] + UInputTags: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/InputTags.vue')['default'] + UModal: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Modal.vue')['default'] + UPopover: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Popover.vue')['default'] + UProgress: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Progress.vue')['default'] + USelect: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Select.vue')['default'] + USwitch: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Switch.vue')['default'] + UTabs: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Tabs.vue')['default'] + UTextarea: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Textarea.vue')['default'] + UTooltip: typeof import('./../node_modules/.pnpm/@nuxt+ui@4.2.1_@babel+parse_1572391ae10a8169a5c9784ec5cec455/node_modules/@nuxt/ui/dist/runtime/components/Tooltip.vue')['default'] } }