change tooltip color

This commit is contained in:
锦恢 2025-06-18 17:04:33 +08:00
parent 3700857aa8
commit c2a634118b
27 changed files with 109 additions and 35 deletions

View File

@ -3,6 +3,7 @@
## [main] 0.1.6 ## [main] 0.1.6
- 针对 0.1.5 无法在 Windows 启动的紧急修复。 - 针对 0.1.5 无法在 Windows 启动的紧急修复。
- 修复环境变量中添加 token 失效的问题。 - 修复环境变量中添加 token 失效的问题。
- 优化工具展示的页面布局。
## [main] 0.1.5 ## [main] 0.1.5
- 修复 gemini 获取模型列表时存在 models 前缀的问题 - 修复 gemini 获取模型列表时存在 models 前缀的问题

View File

@ -228,3 +228,4 @@ a {
.ͼo .cm-gutters { .ͼo .cm-gutters {
background-color: transparent !important; background-color: transparent !important;
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('context-length')" placement="top"> <el-tooltip :content="t('context-length')" placement="top" effect="light">
<div class="setting-button width-30" @click="showContextLengthDialog = true"> <div class="setting-button width-30" @click="showContextLengthDialog = true">
<span class="iconfont icon-length"></span> <span class="iconfont icon-length"></span>
<span class="value-badge">{{ tabStorage.settings.contextLength }}</span> <span class="value-badge">{{ tabStorage.settings.contextLength }}</span>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('choose-model')" placement="top"> <el-tooltip :content="t('choose-model')" placement="top" effect="light">
<div class="setting-button" @click="showModelDialog = true"> <div class="setting-button" @click="showModelDialog = true">
<span class="iconfont icon-model"> <span class="iconfont icon-model">
{{ currentServerName }}/{{ currentModelName }} {{ currentServerName }}/{{ currentModelName }}

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('parallel-tool-calls')" placement="top"> <el-tooltip :content="t('parallel-tool-calls')" placement="top" effect="light">
<div class="setting-button" :class="{ 'active': tabStorage.settings.parallelToolCalls }" size="small" <div class="setting-button" :class="{ 'active': tabStorage.settings.parallelToolCalls }" size="small"
@click="toggle"> @click="toggle">
<span class="iconfont icon-parallel"></span> <span class="iconfont icon-parallel"></span>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('prompts')" placement="top"> <el-tooltip :content="t('prompts')" placement="top" effect="light">
<div class="setting-button" @click="showChoosePrompt = true; saveCursorPosition();"> <div class="setting-button" @click="showChoosePrompt = true; saveCursorPosition();">
<span class="iconfont icon-chat"></span> <span class="iconfont icon-chat"></span>
</div> </div>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('resources')" placement="top"> <el-tooltip :content="t('resources')" placement="top" effect="light">
<div class="setting-button" @click="showChooseResource = true; saveCursorPosition();"> <div class="setting-button" @click="showChooseResource = true; saveCursorPosition();">
<span class="iconfont icon-file"></span> <span class="iconfont icon-file"></span>
</div> </div>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('system-prompt')" placement="top"> <el-tooltip :content="t('system-prompt')" placement="top" effect="light">
<div class="setting-button" :class="{ 'active': hasSystemPrompt }" size="small" <div class="setting-button" :class="{ 'active': hasSystemPrompt }" size="small"
@click="showSystemPromptDialog = true"> @click="showSystemPromptDialog = true">
<span class="iconfont icon-prompt"></span> <span class="iconfont icon-prompt"></span>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('temperature-parameter')" placement="top"> <el-tooltip :content="t('temperature-parameter')" placement="top" effect="light">
<div class="setting-button width-30" @click="showTemperatureSlider = true"> <div class="setting-button width-30" @click="showTemperatureSlider = true">
<span class="iconfont icon-temperature"></span> <span class="iconfont icon-temperature"></span>
<span class="value-badge">{{ tabStorage.settings.temperature.toFixed(1) }}</span> <span class="value-badge">{{ tabStorage.settings.temperature.toFixed(1) }}</span>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('tool-use')" placement="top"> <el-tooltip :content="t('tool-use')" placement="top" effect="light">
<div class="setting-button" :class="{ 'active': availableToolsNum > 0 }" size="small" @click="toggleTools"> <div class="setting-button" :class="{ 'active': availableToolsNum > 0 }" size="small" @click="toggleTools">
<span class="iconfont icon-tool badge-outer"> <span class="iconfont icon-tool badge-outer">
<span class="badge-inner"> <span class="badge-inner">
@ -10,7 +10,21 @@
</el-tooltip> </el-tooltip>
<el-dialog v-model="showToolsDialog" title="工具管理" width="800px"> <el-dialog v-model="showToolsDialog" width="800px">
<template #header>
<div>
<span>{{ t('tool-manage') }}</span>
<el-tooltip :content="t('enable-xml-wrapper')" placement="top" effect="light">
<span class="xml-tag" :class="{
'active': tabStorage.settings.enableXmlWrapper
}"
@click="tabStorage.settings.enableXmlWrapper = !tabStorage.settings.enableXmlWrapper"
>xml</span>
</el-tooltip>
</div>
</template>
<div class="tools-dialog-container"> <div class="tools-dialog-container">
<el-scrollbar height="400px" class="tools-list"> <el-scrollbar height="400px" class="tools-list">
<div v-for="(tool, index) in tabStorage.settings.enableTools" :key="index" class="tool-item"> <div v-for="(tool, index) in tabStorage.settings.enableTools" :key="index" class="tool-item">
@ -23,12 +37,15 @@
</el-scrollbar> </el-scrollbar>
<el-scrollbar height="400px" class="schema-viewer"> <el-scrollbar height="400px" class="schema-viewer">
<div v-html="activeToolsSchemaHTML"></div> <!-- 如果激活 xml 指令包裹则展示对应的 prompt -->
<div v-if="tabStorage.settings.enableXmlWrapper" v-html="activeToolsXmlPrompt" />
<!-- 如果是普通模式则展示普通的工具列表 -->
<div v-else v-html="activeToolsSchemaHTML" />
</el-scrollbar> </el-scrollbar>
</div> </div>
<template #footer> <template #footer>
<el-button type="primary" @click="enableAllTools">激活所有工具</el-button> <el-button type="primary" @click="enableAllTools">{{ t('enable-all-tools') }}</el-button>
<el-button type="danger" @click="disableAllTools">禁用所有工具</el-button> <el-button type="danger" @click="disableAllTools">{{ t('disable-all-tools') }}</el-button>
<el-button type="primary" @click="showToolsDialog = false">{{ t("cancel") }}</el-button> <el-button type="primary" @click="showToolsDialog = false">{{ t("cancel") }}</el-button>
</template> </template>
</el-dialog> </el-dialog>
@ -40,6 +57,7 @@ import { useI18n } from 'vue-i18n';
import { type ChatStorage, type EnableToolItem, getToolSchema } from '../chat'; import { type ChatStorage, type EnableToolItem, getToolSchema } from '../chat';
import { markdownToHtml } from '@/components/main-panel/chat/markdown/markdown'; import { markdownToHtml } from '@/components/main-panel/chat/markdown/markdown';
import { mcpClientAdapter } from '@/views/connect/core'; import { mcpClientAdapter } from '@/views/connect/core';
import { toolSchemaToPromptDescription } from '../../core/prompt';
const { t } = useI18n(); const { t } = useI18n();
@ -65,6 +83,17 @@ const activeToolsSchemaHTML = computed(() => {
); );
}); });
const activeToolsXmlPrompt = computed(() => {
if (tabStorage.settings.enableXmlWrapper) {
const prompt = toolSchemaToPromptDescription(tabStorage.settings.enableTools);
return markdownToHtml(
"```markdown\n" + prompt + "\n```"
);
} else {
return '';
}
});
// - // -
const enableAllTools = () => { const enableAllTools = () => {
tabStorage.settings.enableTools.forEach(tool => { tabStorage.settings.enableTools.forEach(tool => {
@ -121,4 +150,24 @@ onMounted(async () => {
</script> </script>
<style></style> <style scoped>
.xml-tag {
margin-left: 10px;
border-radius: .5em;
padding: 2px 5px;
font-size: 12px;
font-weight: 900;
color: black;
background-color: var(--main-color);
opacity: 0.3;
transition: var(--animation-3s);
cursor: pointer;
}
.xml-tag.active {
opacity: 1;
transition: var(--animation-3s);
}
</style>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('websearch')" placement="top"> <el-tooltip :content="t('websearch')" placement="top" effect="light">
<div class="setting-button" :class="{ 'active': tabStorage.settings.enableWebSearch }" size="small" <div class="setting-button" :class="{ 'active': tabStorage.settings.enableWebSearch }" size="small"
@click="toggleWebSearch"> @click="toggleWebSearch">
<span class="iconfont icon-web"></span> <span class="iconfont icon-web"></span>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="t('enable-xml-wrapper')" placement="top"> <el-tooltip :content="t('enable-xml-wrapper')" placement="top" effect="light">
<div class="setting-button" :class="{ 'active': tabStorage.settings.enableXmlWrapper }" size="small" <div class="setting-button" :class="{ 'active': tabStorage.settings.enableXmlWrapper }" size="small"
@click="toggle"> @click="toggle">
<span class="iconfont icon-suffix-xml"></span> <span class="iconfont icon-suffix-xml"></span>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip :content="props.messages[0].content.text" placement="top"> <el-tooltip :content="props.messages[0].content.text" placement="top" effect="light">
<span class="chat-prompt-item" contenteditable="false"> <span class="chat-prompt-item" contenteditable="false">
<span class="iconfont icon-chat"></span> <span class="iconfont icon-chat"></span>
<span class="real-text">{{ props.messages[0].content.text }}</span> <span class="real-text">{{ props.messages[0].content.text }}</span>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-tooltip placement="top"> <el-tooltip placement="top" effect="light">
<template #content> <template #content>
<div class="resource-chat-item-tooltip"> <div class="resource-chat-item-tooltip">
<div v-for="(item, index) of toolRenderItems" :key="index"> <div v-for="(item, index) of toolRenderItems" :key="index">

View File

@ -28,7 +28,7 @@ export function toolSchemaToPromptDescription(tools: ToolItem[]) {
Object.entries(tool.inputSchema.properties).forEach(([name, prop]) => { Object.entries(tool.inputSchema.properties).forEach(([name, prop]) => {
const required = tool.inputSchema.required?.includes(name) || false; const required = tool.inputSchema.required?.includes(name) || false;
prompt += `- \`${name}\`: ${prop.description || '无描述'} (${prop.type}) ${required ? '(required)' : ''}\n`; prompt += `- \`${name}\`: ${prop.description || 'No Description'} (${prop.type}) ${required ? '(required)' : ''}\n`;
}); });
prompt += '\n'; prompt += '\n';

View File

@ -158,9 +158,5 @@ onMounted(async () => {
.tool-description { .tool-description {
opacity: 0.6; opacity: 0.6;
font-size: 12.5px; font-size: 12.5px;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
</style> </style>

View File

@ -2,7 +2,7 @@
<div v-if="!isConnecting" class="connected-status-container" id="connected-status-container" <div v-if="!isConnecting" class="connected-status-container" id="connected-status-container"
@click.stop="toggleConnectionPanel()" :class="{ 'connected': client.connectionResult.success }"> @click.stop="toggleConnectionPanel()" :class="{ 'connected': client.connectionResult.success }">
<span class="mcp-server-info"> <span class="mcp-server-info">
<el-tooltip class="extra-connect-container" effect="dark" placement="right" <el-tooltip class="extra-connect-container" effect="light" placement="right"
:content="fullDisplayServerName"> :content="fullDisplayServerName">
<span class="name">{{ displayServerName }}</span> <span class="name">{{ displayServerName }}</span>
</el-tooltip> </el-tooltip>
@ -20,7 +20,7 @@
</div> </div>
<div v-else class="connected-status-container"> <div v-else class="connected-status-container">
<span class="mcp-server-info"> <span class="mcp-server-info">
<el-tooltip class="extra-connect-container" effect="dark" placement="right" <el-tooltip class="extra-connect-container" effect="light" placement="right"
:content="fullDisplayServerName"> :content="fullDisplayServerName">
<span class="name"> <span class="name">
加载中 加载中

View File

@ -3,7 +3,7 @@
<div v-for="(item, index) of sidebarItems" :key="index" <div v-for="(item, index) of sidebarItems" :key="index"
:id="`sidebar-${item.ident}`" :id="`sidebar-${item.ident}`"
> >
<el-tooltip :content="t(item.ident)" placement="right"> <el-tooltip :content="t(item.ident)" placement="right" effect="light">
<div class="sidebar-option-item" :class="{ 'active': isActive(item.ident) }" <div class="sidebar-option-item" :class="{ 'active': isActive(item.ident) }"
@click="gotoOption(item.ident)"> @click="gotoOption(item.ident)">
<span :class="`iconfont ${item.icon}`"></span> <span :class="`iconfont ${item.icon}`"></span>

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "تمكين تغليف تعليمات XML" "enable-xml-wrapper": "تمكين تغليف تعليمات XML",
"tool-manage": "إدارة الأدوات",
"enable-all-tools": "تفعيل جميع الأدوات",
"disable-all-tools": "تعطيل جميع الأدوات"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "XML-Befehlsverpackung aktivieren" "enable-xml-wrapper": "XML-Befehlsverpackung aktivieren",
"tool-manage": "Werkzeugverwaltung",
"enable-all-tools": "Alle Tools aktivieren",
"disable-all-tools": "Alle Tools deaktivieren"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "Enable XML command wrapping" "enable-xml-wrapper": "Enable XML command wrapping",
"tool-manage": "Tool Management",
"enable-all-tools": "Activate all tools",
"disable-all-tools": "Disable all tools"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "Activer l'encapsulation de commande XML" "enable-xml-wrapper": "Activer l'encapsulation de commande XML",
"tool-manage": "Gestion des outils",
"enable-all-tools": "Activer tous les outils",
"disable-all-tools": "Désactiver tous les outils"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "XMLコマンドラッピングを有効にする" "enable-xml-wrapper": "XMLコマンドラッピングを有効にする",
"tool-manage": "ツール管理",
"enable-all-tools": "すべてのツールを有効にする",
"disable-all-tools": "すべてのツールを無効にする"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "XML 명령 래핑 활성화" "enable-xml-wrapper": "XML 명령 래핑 활성화",
"tool-manage": "도구 관리",
"enable-all-tools": "모든 도구 활성화",
"disable-all-tools": "모든 도구 비활성화"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "Включить обёртку XML-команд" "enable-xml-wrapper": "Включить обёртку XML-команд",
"tool-manage": "Управление инструментами",
"enable-all-tools": "Активировать все инструменты",
"disable-all-tools": "Отключить все инструменты"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "为我们撰写评价!", "comment-for-us": "为我们撰写评价!",
"openmcp-developed-by": "OpenMCP Client {version} 由 {author} 开发", "openmcp-developed-by": "OpenMCP Client {version} 由 {author} 开发",
"error-parse-json": "JSON 解析错误:", "error-parse-json": "JSON 解析错误:",
"enable-xml-wrapper": "开启 XML 指令包裹" "enable-xml-wrapper": "开启 XML 指令包裹",
"tool-manage": "工具管理",
"enable-all-tools": "激活所有工具",
"disable-all-tools": "禁用所有工具"
} }

View File

@ -172,5 +172,8 @@
"comment-for-us": "Écrivez un avis pour nous !", "comment-for-us": "Écrivez un avis pour nous !",
"openmcp-developed-by": "OpenMCP Client {version} développé par {author}", "openmcp-developed-by": "OpenMCP Client {version} développé par {author}",
"error-parse-json": "Erreur d'analyse JSON :", "error-parse-json": "Erreur d'analyse JSON :",
"enable-xml-wrapper": "開啟 XML 指令包裹" "enable-xml-wrapper": "開啟 XML 指令包裹",
"tool-manage": "工具管理",
"enable-all-tools": "啟用所有工具",
"disable-all-tools": "禁用所有工具"
} }