From f919487506c5a2b99a5ac041809489eed7eca64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=94=A6=E9=BA=9F=20=E7=8E=8B?= Date: Fri, 6 Feb 2026 10:59:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=AF=B9=E6=96=B0?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E6=8F=90=E4=BE=9B=E5=95=86=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=8C=E5=8C=85=E6=8B=AC=E6=99=BA=E8=B0=B1=E3=80=81?= =?UTF-8?q?MiniMax=20=E5=92=8C=20Moonshot=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE=E5=92=8C=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/minenasai/webtui/server.py | 19 +- .../webtui/static/webui/css/webui.css | 260 +++++++++++++++--- .../webui/js/components/channels-config.js | 6 +- .../static/webui/js/components/llm-config.js | 92 ++++++- 4 files changed, 326 insertions(+), 51 deletions(-) diff --git a/src/minenasai/webtui/server.py b/src/minenasai/webtui/server.py index e065152..1b26f63 100644 --- a/src/minenasai/webtui/server.py +++ b/src/minenasai/webtui/server.py @@ -428,17 +428,30 @@ async def test_llm_with_config(request: LLMTestRequest) -> dict[str, Any]: # 根据提供商进行测试 start = time.time() - if provider in ["openai-compatible", "openai", "deepseek"]: + if provider in ["openai-compatible", "openai", "deepseek", "zhipu", "minimax", "moonshot"]: # OpenAI 兼容接口 import httpx url = base_url or "https://api.openai.com/v1" model_name = model or "gpt-3.5-turbo" - # 获取代理设置 + # 设置各提供商默认 URL + if provider == "deepseek" and not base_url: + url = "https://api.deepseek.com/v1" + elif provider == "zhipu" and not base_url: + url = "https://open.bigmodel.cn/api/paas/v4" + model_name = model or "glm-4-flash" + elif provider == "minimax" and not base_url: + url = "https://api.minimax.chat/v1" + model_name = model or "abab6.5s-chat" + elif provider == "moonshot" and not base_url: + url = "https://api.moonshot.cn/v1" + model_name = model or "moonshot-v1-8k" + + # 国内 API 不需要代理 settings = get_settings() proxy_url = None - if settings.proxy.enabled and provider not in ["deepseek"]: + if settings.proxy.enabled and provider not in ["deepseek", "zhipu", "minimax", "moonshot"]: proxy_url = settings.proxy.http or settings.proxy.https async with httpx.AsyncClient( diff --git a/src/minenasai/webtui/static/webui/css/webui.css b/src/minenasai/webtui/static/webui/css/webui.css index c2af379..61643fc 100644 --- a/src/minenasai/webtui/static/webui/css/webui.css +++ b/src/minenasai/webtui/static/webui/css/webui.css @@ -458,99 +458,277 @@ body { } } -/* 亮色主题额外样式覆盖 */ +/* ========== 亮色主题全面覆盖 ========== */ + +/* 全局背景 & 文字 */ +.theme-light, +.theme-light body { + background-color: #f0f2f5 !important; + color: #303133 !important; +} + +.theme-light .app-container { + background-color: #f0f2f5; +} + +/* 侧边栏 */ +.theme-light .sidebar { + background-color: #fff !important; + border-right-color: #e4e7ed !important; +} + +.theme-light .logo { + border-bottom-color: #e4e7ed !important; +} + .theme-light .el-menu { - background-color: var(--bg-primary) !important; + background-color: #fff !important; } .theme-light .el-menu-item, .theme-light .el-sub-menu__title { - color: var(--text-primary) !important; + color: #303133 !important; } .theme-light .el-menu-item.is-active { - background-color: var(--bg-secondary) !important; - color: var(--accent-primary) !important; + background-color: #ecf5ff !important; + color: #409eff !important; } .theme-light .el-menu-item:hover, .theme-light .el-sub-menu__title:hover { - background-color: var(--bg-tertiary) !important; + background-color: #f5f7fa !important; } +/* 头部 */ +.theme-light .header { + background-color: #fff !important; + border-bottom-color: #e4e7ed !important; + color: #303133 !important; +} + +.theme-light .header h3, +.theme-light .header span { + color: #303133 !important; +} + +/* 主内容区 */ +.theme-light .main-content { + background-color: #f0f2f5 !important; +} + +/* 卡片 */ .theme-light .el-card { - background-color: var(--bg-secondary); - border-color: var(--border-color); + background-color: #fff !important; + border-color: #e4e7ed !important; + color: #303133 !important; + --el-card-bg-color: #fff; +} + +.theme-light .el-card__header { + background-color: #fafbfc !important; + border-bottom-color: #e4e7ed !important; + color: #303133 !important; +} + +.theme-light .el-card__body { + color: #303133 !important; +} + +.theme-light .config-card { + background-color: #fff !important; +} + +.theme-light .config-card .el-card__header { + background-color: #fafbfc !important; + border-bottom-color: #e4e7ed !important; +} + +.theme-light .provider-card { + background-color: #fafbfc !important; + border-color: #e4e7ed !important; +} + +.theme-light .stat-card { + background-color: #fff !important; + border-color: #e4e7ed !important; +} + +/* 表单 */ +.theme-light .el-form-item__label { + color: #606266 !important; } .theme-light .el-input__inner, .theme-light .el-textarea__inner { - background-color: var(--bg-primary) !important; - border-color: var(--border-color) !important; - color: var(--text-primary) !important; + background-color: #fff !important; + border-color: #dcdfe6 !important; + color: #303133 !important; +} + +.theme-light .el-input__wrapper { + background-color: #fff !important; + box-shadow: 0 0 0 1px #dcdfe6 inset !important; +} + +.theme-light .el-input__wrapper:hover { + box-shadow: 0 0 0 1px #c0c4cc inset !important; +} + +.theme-light .el-input__wrapper.is-focus { + box-shadow: 0 0 0 1px #409eff inset !important; } .theme-light .el-select-dropdown { - background-color: var(--bg-primary) !important; + background-color: #fff !important; } .theme-light .el-select-dropdown__item { - color: var(--text-primary) !important; + color: #303133 !important; } -.theme-light .config-card { - background-color: var(--bg-secondary); +/* 按钮 */ +.theme-light .el-button--default { + --el-button-bg-color: #fff; + --el-button-border-color: #dcdfe6; + --el-button-text-color: #606266; + --el-button-hover-bg-color: #ecf5ff; + --el-button-hover-border-color: #c6e2ff; + --el-button-hover-text-color: #409eff; } -.theme-light .provider-card { - background-color: var(--bg-primary); +.theme-light .el-button--primary { + --el-button-bg-color: #409eff; + --el-button-border-color: #409eff; + --el-button-hover-bg-color: #66b1ff; + --el-button-hover-border-color: #66b1ff; } -.theme-light .stat-card { - background-color: var(--bg-secondary); +/* 分割线 */ +.theme-light .el-divider { + border-color: #e4e7ed !important; } +/* 标签 */ +.theme-light .el-tag { + --el-tag-bg-color: #ecf5ff; + --el-tag-border-color: #d9ecff; + --el-tag-text-color: #409eff; +} + +/* Alert */ +.theme-light .el-alert--info { + background-color: #f4f4f5 !important; + color: #909399 !important; +} + +.theme-light .el-alert--info .el-alert__title { + color: #606266 !important; +} + +/* 表格 */ +.theme-light .el-table { + --el-table-bg-color: #fff; + --el-table-header-bg-color: #fafbfc; + --el-table-tr-bg-color: #fff; + --el-table-row-hover-bg-color: #f5f7fa; + --el-table-text-color: #303133; + --el-table-header-text-color: #909399; + --el-table-border-color: #ebeef5; +} + +/* Tabs */ +.theme-light .el-tabs__item { + color: #909399 !important; +} + +.theme-light .el-tabs__item.is-active { + color: #409eff !important; +} + +.theme-light .el-tabs--border-card { + background-color: #fff !important; + border-color: #dcdfe6 !important; +} + +.theme-light .el-tabs__header { + background-color: #f5f7fa !important; + border-bottom-color: #e4e7ed !important; +} + +/* Switch */ +.theme-light .el-switch__label { + color: #606266 !important; +} + +/* 对话框 */ +.theme-light .el-dialog { + --el-dialog-bg-color: #fff; +} + +.theme-light .el-dialog__title { + color: #303133 !important; +} + +.theme-light .el-breadcrumb__inner { + color: #303133 !important; +} + +/* 终端 & 日志 */ .theme-light .terminal-container, .theme-light .logs-container { - background-color: var(--bg-primary); + background-color: #fff !important; + border-color: #e4e7ed !important; } .theme-light .terminal-header, .theme-light .logs-header { - background-color: var(--bg-secondary); + background-color: #fafbfc !important; + border-bottom-color: #e4e7ed !important; } -.theme-light .el-breadcrumb__inner { - color: var(--text-primary) !important; -} - -.theme-light .el-dialog { - --el-dialog-bg-color: var(--bg-primary); -} - -.theme-light .el-table { - --el-table-bg-color: var(--bg-secondary); - --el-table-header-bg-color: var(--bg-tertiary); - --el-table-tr-bg-color: var(--bg-secondary); - --el-table-row-hover-bg-color: var(--bg-tertiary); - --el-table-text-color: var(--text-primary); - --el-table-header-text-color: var(--text-secondary); - --el-table-border-color: var(--border-color); +.theme-light .log-entry { + border-bottom-color: #ebeef5 !important; } +/* LLM 配置状态卡片 */ .theme-light .status-chip { - background-color: var(--bg-primary); + background-color: #fff !important; + border-color: #e4e7ed !important; } .theme-light .status-chip:hover, .theme-light .status-chip.selected { - background-color: rgba(64, 158, 255, 0.1); + background-color: #ecf5ff !important; + border-color: #409eff !important; } .theme-light .test-result.success { - background-color: rgba(103, 194, 58, 0.15); + color: #67c23a; + background-color: rgba(103, 194, 58, 0.1); } .theme-light .test-result.error { - background-color: rgba(245, 108, 108, 0.15); + color: #f56c6c; + background-color: rgba(245, 108, 108, 0.1); +} + +/* 文字颜色确保 */ +.theme-light span, +.theme-light p, +.theme-light div, +.theme-light label { + color: inherit; +} + +.theme-light .provider-name, +.theme-light .status-name, +.theme-light .stat-card-title, +.theme-light .log-message { + color: #303133; +} + +.theme-light .stat-card-sub, +.theme-light .log-time { + color: #909399; } diff --git a/src/minenasai/webtui/static/webui/js/components/channels-config.js b/src/minenasai/webtui/static/webui/js/components/channels-config.js index a13c0d2..ef02811 100644 --- a/src/minenasai/webtui/static/webui/js/components/channels-config.js +++ b/src/minenasai/webtui/static/webui/js/components/channels-config.js @@ -72,7 +72,8 @@ app.component('channels-config-page', {
  • 登录企业微信管理后台 → 应用管理 → 创建应用
  • 获取 CorpID、AgentID、Secret
  • 在「接收消息」中配置 URL、Token、EncodingAESKey
  • -
  • Webhook URL: https://your-domain.com/webhook/wework
  • +
  • 回调地址指向 Gateway 服务(默认端口 8000)
  • +
  • Webhook URL: http://你的服务器IP:8000/webhook/wework
  • @@ -125,7 +126,8 @@ app.component('channels-config-page', {
  • 登录飞书开放平台 → 创建企业自建应用
  • 获取 App ID 和 App Secret
  • 在「事件订阅」中配置请求地址和 Token
  • -
  • Webhook URL: https://your-domain.com/webhook/feishu
  • +
  • 事件请求地址指向 Gateway 服务(默认端口 8000)
  • +
  • Webhook URL: http://你的服务器IP:8000/webhook/feishu
  • diff --git a/src/minenasai/webtui/static/webui/js/components/llm-config.js b/src/minenasai/webtui/static/webui/js/components/llm-config.js index 6027073..2894a96 100644 --- a/src/minenasai/webtui/static/webui/js/components/llm-config.js +++ b/src/minenasai/webtui/static/webui/js/components/llm-config.js @@ -26,7 +26,7 @@ app.component('llm-config-page', { // 保存状态 const saving = ref(false); - // 表单数据 - 简化为通用的 OpenAI 兼容格式 + // 表单数据 const form = reactive({ // 当前使用的配置 provider: 'openai-compatible', @@ -62,6 +62,28 @@ app.component('llm-config-page', { base_url: '', model: 'gemini-2.5-flash-preview-05-20', configured: false + }, + 'zhipu': { + name: '智谱 GLM', + api_key: '', + base_url: 'https://open.bigmodel.cn/api/paas/v4', + model: 'glm-4-flash', + configured: false + }, + 'minimax': { + name: 'MiniMax', + api_key: '', + base_url: 'https://api.minimax.chat/v1', + model: 'abab6.5s-chat', + group_id: '', + configured: false + }, + 'moonshot': { + name: 'Moonshot (Kimi)', + api_key: '', + base_url: 'https://api.moonshot.cn/v1', + model: 'moonshot-v1-8k', + configured: false } } }); @@ -107,6 +129,37 @@ app.component('llm-config-page', { defaultModel: 'gemini-2.5-flash-preview-05-20', keyPlaceholder: 'AIzaSy-xxx', domestic: false + }, + { + id: 'zhipu', + name: '智谱 GLM', + icon: '🧠', + description: '智谱 AI 大模型,国内直连', + defaultUrl: 'https://open.bigmodel.cn/api/paas/v4', + defaultModel: 'glm-4-flash', + keyPlaceholder: 'xxx.xxx', + domestic: true + }, + { + id: 'minimax', + name: 'MiniMax', + icon: '🎯', + description: 'MiniMax 大模型,国内直连(需 Group ID)', + defaultUrl: 'https://api.minimax.chat/v1', + defaultModel: 'abab6.5s-chat', + keyPlaceholder: 'eyJhbGci-xxx', + domestic: true, + extraFields: ['group_id'] + }, + { + id: 'moonshot', + name: 'Moonshot (Kimi)', + icon: '🌙', + description: 'Moonshot/Kimi 大模型,国内直连', + defaultUrl: 'https://api.moonshot.cn/v1', + defaultModel: 'moonshot-v1-8k', + keyPlaceholder: 'sk-xxx', + domestic: true } ]; @@ -137,6 +190,13 @@ app.component('llm-config-page', { migrateConfig('anthropic', newVal.anthropic_api_key, newVal.anthropic_base_url); migrateConfig('deepseek', newVal.deepseek_api_key, newVal.deepseek_base_url); migrateConfig('gemini', newVal.gemini_api_key, newVal.gemini_base_url); + migrateConfig('zhipu', newVal.zhipu_api_key, newVal.zhipu_base_url); + migrateConfig('minimax', newVal.minimax_api_key, newVal.minimax_base_url); + migrateConfig('moonshot', newVal.moonshot_api_key, newVal.moonshot_base_url); + // MiniMax group_id + if (newVal.minimax_group_id) { + form.configs['minimax'].group_id = newVal.minimax_group_id; + } } }, { immediate: true, deep: true }); @@ -147,9 +207,9 @@ app.component('llm-config-page', { 'anthropic': 'anthropic', 'deepseek': 'deepseek', 'gemini': 'gemini', - 'zhipu': 'openai-compatible', - 'minimax': 'openai-compatible', - 'moonshot': 'openai-compatible' + 'zhipu': 'zhipu', + 'minimax': 'minimax', + 'moonshot': 'moonshot' }; return map[name] || 'openai-compatible'; } @@ -263,7 +323,17 @@ app.component('llm-config-page', { deepseek_base_url: form.configs['deepseek'].base_url, // Gemini gemini_api_key: form.configs['gemini'].api_key, - gemini_base_url: form.configs['gemini'].base_url + gemini_base_url: form.configs['gemini'].base_url, + // 智谱 + zhipu_api_key: form.configs['zhipu'].api_key, + zhipu_base_url: form.configs['zhipu'].base_url, + // MiniMax + minimax_api_key: form.configs['minimax'].api_key, + minimax_base_url: form.configs['minimax'].base_url, + minimax_group_id: form.configs['minimax'].group_id || '', + // Moonshot + moonshot_api_key: form.configs['moonshot'].api_key, + moonshot_base_url: form.configs['moonshot'].base_url }; emit('save', saveData); @@ -406,6 +476,18 @@ app.component('llm-config-page', { 留空将使用默认模型:{{ currentProvider.defaultModel }} + + + + +
    + 在 MiniMax 控制台获取,用于 API 调用 +
    +