style: group AI assistant settings in system page

This commit is contained in:
jxxghp
2026-04-25 10:48:55 +08:00
parent e043669a10
commit f9e74cf436
4 changed files with 228 additions and 195 deletions
+4 -1
View File
@@ -1322,13 +1322,16 @@ export default {
aiAgent: 'Enable AI Assistant', aiAgent: 'Enable AI Assistant',
aiAgentEnable: 'Enable AI Assistant', aiAgentEnable: 'Enable AI Assistant',
aiAgentEnableHint: 'Enable AI assistant functionality, requires LLM configuration', aiAgentEnableHint: 'Enable AI assistant functionality, requires LLM configuration',
aiAgentSectionTitle: 'AI Assistant Configuration',
aiAgentSectionDesc:
'After enabling it, you can use the Agent in message conversations and optionally turn on transfer-failure takeover and AI recommendations.',
llmProvider: 'LLM Provider', llmProvider: 'LLM Provider',
llmProviderHint: 'Select the LLM service provider to use', llmProviderHint: 'Select the LLM service provider to use',
llmModel: 'LLM Model Name', llmModel: 'LLM Model Name',
llmModelHint: 'Specify the LLM model to use, such as gpt-3.5-turbo, deepseek-chat, etc.', llmModelHint: 'Specify the LLM model to use, such as gpt-3.5-turbo, deepseek-chat, etc.',
llmThinking: 'Thinking Mode / Depth', llmThinking: 'Thinking Mode / Depth',
llmThinkingHint: llmThinkingHint:
'Use one setting to control both thinking off and depth: off/auto/minimal/low/medium/high/max/xhigh. Unsupported levels will be mapped to the nearest provider-supported value.', 'Thinking depth: off/auto/minimal/low/medium/high/max/xhigh. Unsupported levels will be mapped to the nearest provider-supported value.',
llmThinkingLevelOff: 'Off (off)', llmThinkingLevelOff: 'Off (off)',
llmThinkingLevelAuto: 'Auto (auto)', llmThinkingLevelAuto: 'Auto (auto)',
llmThinkingLevelMinimal: 'Minimal (minimal)', llmThinkingLevelMinimal: 'Minimal (minimal)',
+3 -1
View File
@@ -1317,13 +1317,15 @@ export default {
aiAgent: '启用智能助手', aiAgent: '启用智能助手',
aiAgentEnable: '启用智能助手', aiAgentEnable: '启用智能助手',
aiAgentEnableHint: '启用后可使用智能助手功能,需要配置LLM相关参数', aiAgentEnableHint: '启用后可使用智能助手功能,需要配置LLM相关参数',
aiAgentSectionTitle: '智能助手配置',
aiAgentSectionDesc: '启用后可在消息会话中使用 Agent 能力,也可开启失败整理接管和智能推荐。',
llmProvider: 'LLM提供商', llmProvider: 'LLM提供商',
llmProviderHint: '选择使用的LLM服务提供商', llmProviderHint: '选择使用的LLM服务提供商',
llmModel: 'LLM模型名称', llmModel: 'LLM模型名称',
llmModelHint: '指定使用的LLM模型,如gpt-3.5-turbo、deepseek-chat等', llmModelHint: '指定使用的LLM模型,如gpt-3.5-turbo、deepseek-chat等',
llmThinking: '思考模式 / 深度', llmThinking: '思考模式 / 深度',
llmThinkingHint: llmThinkingHint:
'用一个设置统一控制关闭与深度:off/auto/minimal/low/medium/high/max/xhigh;不支持的级别会按 provider 能力自动映射到最近值', '思考深度:off/auto/minimal/low/medium/high/max/xhigh;不支持的级别会按 provider 能力自动映射到最近值',
llmThinkingLevelOff: '关闭 (off)', llmThinkingLevelOff: '关闭 (off)',
llmThinkingLevelAuto: '自动 (auto)', llmThinkingLevelAuto: '自动 (auto)',
llmThinkingLevelMinimal: '最小 (minimal)', llmThinkingLevelMinimal: '最小 (minimal)',
+3 -1
View File
@@ -1319,13 +1319,15 @@ export default {
aiAgent: '啟用智能助手', aiAgent: '啟用智能助手',
aiAgentEnable: '啟用智能助手', aiAgentEnable: '啟用智能助手',
aiAgentEnableHint: '啟用後可使用智能助手功能,需要配置LLM相關參數', aiAgentEnableHint: '啟用後可使用智能助手功能,需要配置LLM相關參數',
aiAgentSectionTitle: '智能助手配置',
aiAgentSectionDesc: '啟用後可在消息對話中使用 Agent 能力,也可開啟失敗整理接管與智能推薦。',
llmProvider: 'LLM提供商', llmProvider: 'LLM提供商',
llmProviderHint: '選擇使用的LLM服務提供商', llmProviderHint: '選擇使用的LLM服務提供商',
llmModel: 'LLM模型名稱', llmModel: 'LLM模型名稱',
llmModelHint: '指定使用的LLM模型,如gpt-3.5-turbo、deepseek-chat等', llmModelHint: '指定使用的LLM模型,如gpt-3.5-turbo、deepseek-chat等',
llmThinking: '思考模式 / 深度', llmThinking: '思考模式 / 深度',
llmThinkingHint: llmThinkingHint:
'用一個設置統一控制關閉與深度:off/auto/minimal/low/medium/high/max/xhigh;不支援的級別會按 provider 能力自動映射到最近值', '思考深度:off/auto/minimal/low/medium/high/max/xhigh;不支援的級別會按 provider 能力自動映射到最近值',
llmThinkingLevelOff: '關閉 (off)', llmThinkingLevelOff: '關閉 (off)',
llmThinkingLevelAuto: '自動 (auto)', llmThinkingLevelAuto: '自動 (auto)',
llmThinkingLevelMinimal: '最小 (minimal)', llmThinkingLevelMinimal: '最小 (minimal)',
+218 -192
View File
@@ -202,7 +202,9 @@ function buildLlmTestPayload(snapshot: LlmSettingsSnapshot) {
} }
function normalizeThinkingLevelValue(value?: unknown) { function normalizeThinkingLevelValue(value?: unknown) {
const normalized = String(value ?? '').trim().toLowerCase() const normalized = String(value ?? '')
.trim()
.toLowerCase()
if (!normalized) return '' if (!normalized) return ''
const aliasMap: Record<string, string> = { const aliasMap: Record<string, string> = {
@@ -854,198 +856,216 @@ watch(currentLlmSnapshotKey, (snapshotKey, previousSnapshotKey) => {
/> />
</VCol> </VCol>
</VRow> </VRow>
<VDivider class="my-4" /> <VCard variant="outlined" class="ai-agent-settings-card mt-6">
<VRow> <VCardItem class="pb-2">
<VCol cols="12" md="4"> <template #prepend>
<VSwitch <VAvatar color="primary" variant="tonal" size="40">
v-model="SystemSettings.Basic.AI_AGENT_ENABLE" <VIcon icon="mdi-robot-outline" />
:label="t('setting.system.aiAgentEnable')" </VAvatar>
:hint="t('setting.system.aiAgentEnableHint')" </template>
persistent-hint <VCardTitle class="text-subtitle-1">
/> {{ t('setting.system.aiAgentSectionTitle') }}
</VCol> </VCardTitle>
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="4"> <VCardSubtitle>
<VSwitch {{ t('setting.system.aiAgentSectionDesc') }}
v-model="SystemSettings.Basic.AI_AGENT_GLOBAL" </VCardSubtitle>
:label="t('setting.system.aiAgentGlobal')" </VCardItem>
:hint="t('setting.system.aiAgentGlobalHint')" <VCardText class="pt-2">
persistent-hint <VRow>
/> <VCol cols="12" md="4">
</VCol> <VSwitch
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="4"> v-model="SystemSettings.Basic.AI_AGENT_ENABLE"
<VSwitch :label="t('setting.system.aiAgentEnable')"
v-model="SystemSettings.Basic.AI_AGENT_VERBOSE" :hint="t('setting.system.aiAgentEnableHint')"
:label="t('setting.system.aiAgentVerbose')" persistent-hint
:hint="t('setting.system.aiAgentVerboseHint')" />
persistent-hint </VCol>
/> <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="4">
</VCol> <VSwitch
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> v-model="SystemSettings.Basic.AI_AGENT_GLOBAL"
<VSelect :label="t('setting.system.aiAgentGlobal')"
v-model="SystemSettings.Basic.LLM_PROVIDER" :hint="t('setting.system.aiAgentGlobalHint')"
:label="t('setting.system.llmProvider')" persistent-hint
:hint="t('setting.system.llmProviderHint')" />
persistent-hint </VCol>
:items="[ <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="4">
{ title: 'OpenAI', value: 'openai' }, <VSwitch
{ title: 'Google', value: 'google' }, v-model="SystemSettings.Basic.AI_AGENT_VERBOSE"
{ title: 'DeepSeek', value: 'deepseek' }, :label="t('setting.system.aiAgentVerbose')"
]" :hint="t('setting.system.aiAgentVerboseHint')"
prepend-inner-icon="mdi-robot" persistent-hint
/> />
</VCol> </VCol>
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
<VTextField <VSelect
v-model="SystemSettings.Basic.LLM_BASE_URL" v-model="SystemSettings.Basic.LLM_PROVIDER"
:label="t('setting.system.llmBaseUrl')" :label="t('setting.system.llmProvider')"
:hint="t('setting.system.llmBaseUrlHint')" :hint="t('setting.system.llmProviderHint')"
placeholder="https://api.deepseek.com" persistent-hint
persistent-hint :items="[
prepend-inner-icon="mdi-link" { title: 'OpenAI', value: 'openai' },
/> { title: 'Google', value: 'google' },
</VCol> { title: 'DeepSeek', value: 'deepseek' },
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> ]"
<VTextField prepend-inner-icon="mdi-robot"
v-model="SystemSettings.Basic.LLM_API_KEY" />
:label="t('setting.system.llmApiKey')" </VCol>
:hint="t('setting.system.llmApiKeyHint')" <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
:placeholder="t('setting.system.llmApiKeyPlaceholder')" <VTextField
persistent-hint v-model="SystemSettings.Basic.LLM_BASE_URL"
type="password" :label="t('setting.system.llmBaseUrl')"
prepend-inner-icon="mdi-key-variant" :hint="t('setting.system.llmBaseUrlHint')"
/> placeholder="https://api.deepseek.com"
</VCol> persistent-hint
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> prepend-inner-icon="mdi-link"
<div> />
<VCombobox </VCol>
v-model="SystemSettings.Basic.LLM_MODEL" <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
:label="t('setting.system.llmModel')" <VTextField
:hint="t('setting.system.llmModelHint')" v-model="SystemSettings.Basic.LLM_API_KEY"
:placeholder="t('setting.system.llmModelHint')" :label="t('setting.system.llmApiKey')"
persistent-hint :hint="t('setting.system.llmApiKeyHint')"
:items="llmModels" :placeholder="t('setting.system.llmApiKeyPlaceholder')"
:loading="loadingModels" persistent-hint
prepend-inner-icon="mdi-brain" type="password"
> prepend-inner-icon="mdi-key-variant"
<template #append-inner> />
<VBtn </VCol>
variant="text" <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
icon="mdi-refresh" <div>
size="small" <VCombobox
@click="loadLlmModels" v-model="SystemSettings.Basic.LLM_MODEL"
:disabled="!SystemSettings.Basic.LLM_API_KEY" :label="t('setting.system.llmModel')"
/> :hint="t('setting.system.llmModelHint')"
</template> :placeholder="t('setting.system.llmModelHint')"
</VCombobox> persistent-hint
:items="llmModels"
:loading="loadingModels"
prepend-inner-icon="mdi-brain"
>
<template #append-inner>
<VBtn
variant="text"
icon="mdi-refresh"
size="small"
@click="loadLlmModels"
:disabled="!SystemSettings.Basic.LLM_API_KEY"
/>
</template>
</VCombobox>
<div class="d-flex justify-end mt-2"> <div class="d-flex justify-end mt-2">
<VBtn <VBtn
color="info" color="info"
variant="tonal" variant="tonal"
density="comfortable" density="comfortable"
prepend-icon="mdi-connection" prepend-icon="mdi-connection"
:disabled="!canTestLlm" :disabled="!canTestLlm"
:loading="testingLlm" :loading="testingLlm"
class="llm-test-trigger" class="llm-test-trigger"
@click="testLlmConnection" @click="testLlmConnection"
> >
{{ t('setting.system.llmTestAction') }} {{ t('setting.system.llmTestAction') }}
</VBtn> </VBtn>
</div> </div>
</div> </div>
</VCol> </VCol>
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
<VTextField <VTextField
v-model.number="SystemSettings.Basic.LLM_MAX_CONTEXT_TOKENS" v-model.number="SystemSettings.Basic.LLM_MAX_CONTEXT_TOKENS"
:label="t('setting.system.llmMaxContextTokens')" :label="t('setting.system.llmMaxContextTokens')"
:hint="t('setting.system.llmMaxContextTokensHint')" :hint="t('setting.system.llmMaxContextTokensHint')"
persistent-hint persistent-hint
type="number" type="number"
prepend-inner-icon="mdi-counter" prepend-inner-icon="mdi-counter"
/> />
</VCol> </VCol>
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
<VSelect <VSelect
v-model="SystemSettings.Basic.LLM_THINKING_LEVEL" v-model="SystemSettings.Basic.LLM_THINKING_LEVEL"
:label="t('setting.system.llmThinking')" :label="t('setting.system.llmThinking')"
:hint="t('setting.system.llmThinkingHint')" :hint="t('setting.system.llmThinkingHint')"
:items="thinkingLevelItems" :items="thinkingLevelItems"
persistent-hint persistent-hint
/> />
</VCol> </VCol>
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
<VSelect <VSelect
v-model="SystemSettings.Basic.AI_AGENT_JOB_INTERVAL" v-model="SystemSettings.Basic.AI_AGENT_JOB_INTERVAL"
:label="t('setting.system.aiAgentJobInterval')" :label="t('setting.system.aiAgentJobInterval')"
:hint="t('setting.system.aiAgentJobIntervalHint')" :hint="t('setting.system.aiAgentJobIntervalHint')"
persistent-hint persistent-hint
:items="[ :items="[
{ title: t('setting.system.aiAgentJobIntervalDisabled'), value: 0 }, { title: t('setting.system.aiAgentJobIntervalDisabled'), value: 0 },
{ title: t('setting.system.aiAgentJobInterval1h'), value: 1 }, { title: t('setting.system.aiAgentJobInterval1h'), value: 1 },
{ title: t('setting.system.aiAgentJobInterval3h'), value: 3 }, { title: t('setting.system.aiAgentJobInterval3h'), value: 3 },
{ title: t('setting.system.aiAgentJobInterval6h'), value: 6 }, { title: t('setting.system.aiAgentJobInterval6h'), value: 6 },
{ title: t('setting.system.aiAgentJobInterval12h'), value: 12 }, { title: t('setting.system.aiAgentJobInterval12h'), value: 12 },
{ title: t('setting.system.aiAgentJobInterval24h'), value: 24 }, { title: t('setting.system.aiAgentJobInterval24h'), value: 24 },
{ title: t('setting.system.aiAgentJobInterval1w'), value: 168 }, { title: t('setting.system.aiAgentJobInterval1w'), value: 168 },
{ title: t('setting.system.aiAgentJobInterval1M'), value: 720 }, { title: t('setting.system.aiAgentJobInterval1M'), value: 720 },
]" ]"
prepend-inner-icon="mdi-timer-outline" prepend-inner-icon="mdi-timer-outline"
/> />
</VCol> </VCol>
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> </VRow>
<VSwitch <VRow>
v-model="SystemSettings.Basic.LLM_SUPPORT_IMAGE_INPUT" <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
:label="t('setting.system.llmSupportImageInput')" <VSwitch
:hint="t('setting.system.llmSupportImageInputHint')" v-model="SystemSettings.Basic.LLM_SUPPORT_IMAGE_INPUT"
persistent-hint :label="t('setting.system.llmSupportImageInput')"
/> :hint="t('setting.system.llmSupportImageInputHint')"
</VCol> persistent-hint
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6"> />
<VSwitch </VCol>
v-model="SystemSettings.Basic.AI_AGENT_RETRY_TRANSFER" <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12" md="6">
:label="t('setting.system.aiAgentRetryTransfer')" <VSwitch
:hint="t('setting.system.aiAgentRetryTransferHint')" v-model="SystemSettings.Basic.AI_AGENT_RETRY_TRANSFER"
persistent-hint :label="t('setting.system.aiAgentRetryTransfer')"
/> :hint="t('setting.system.aiAgentRetryTransferHint')"
</VCol> persistent-hint
<VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12"> />
<VSwitch </VCol>
v-model="SystemSettings.Basic.AI_RECOMMEND_ENABLED" <VCol v-if="SystemSettings.Basic.AI_AGENT_ENABLE" cols="12">
:label="t('setting.system.aiRecommendEnabled')" <VSwitch
:hint="t('setting.system.aiRecommendEnabledHint')" v-model="SystemSettings.Basic.AI_RECOMMEND_ENABLED"
persistent-hint :label="t('setting.system.aiRecommendEnabled')"
/> :hint="t('setting.system.aiRecommendEnabledHint')"
</VCol> persistent-hint
<VCol />
v-if="SystemSettings.Basic.AI_AGENT_ENABLE && SystemSettings.Basic.AI_RECOMMEND_ENABLED" </VCol>
cols="12" <VCol
md="6" v-if="SystemSettings.Basic.AI_AGENT_ENABLE && SystemSettings.Basic.AI_RECOMMEND_ENABLED"
> cols="12"
<VTextarea md="6"
v-model="SystemSettings.Basic.AI_RECOMMEND_USER_PREFERENCE" >
:label="t('setting.system.aiRecommendUserPreference')" <VTextarea
:hint="t('setting.system.aiRecommendUserPreferenceHint')" v-model="SystemSettings.Basic.AI_RECOMMEND_USER_PREFERENCE"
persistent-hint :label="t('setting.system.aiRecommendUserPreference')"
rows="1" :hint="t('setting.system.aiRecommendUserPreferenceHint')"
auto-grow persistent-hint
prepend-inner-icon="mdi-account-heart" rows="1"
/> auto-grow
</VCol> prepend-inner-icon="mdi-account-heart"
<VCol />
v-if="SystemSettings.Basic.AI_AGENT_ENABLE && SystemSettings.Basic.AI_RECOMMEND_ENABLED" </VCol>
cols="12" <VCol
md="6" v-if="SystemSettings.Basic.AI_AGENT_ENABLE && SystemSettings.Basic.AI_RECOMMEND_ENABLED"
> cols="12"
<VTextField md="6"
v-model.number="SystemSettings.Basic.AI_RECOMMEND_MAX_ITEMS" >
:label="t('setting.system.aiRecommendMaxItems')" <VTextField
:hint="t('setting.system.aiRecommendMaxItemsHint')" v-model.number="SystemSettings.Basic.AI_RECOMMEND_MAX_ITEMS"
persistent-hint :label="t('setting.system.aiRecommendMaxItems')"
type="number" :hint="t('setting.system.aiRecommendMaxItemsHint')"
prepend-inner-icon="mdi-format-list-numbered" persistent-hint
/> type="number"
</VCol> prepend-inner-icon="mdi-format-list-numbered"
</VRow> />
</VCol>
</VRow>
</VCardText>
</VCard>
</VForm> </VForm>
</VCardText> </VCardText>
<VCardText> <VCardText>
@@ -1710,6 +1730,12 @@ watch(currentLlmSnapshotKey, (snapshotKey, previousSnapshotKey) => {
</template> </template>
<style scoped> <style scoped>
.ai-agent-settings-card {
border-color: rgba(var(--v-theme-primary), 0.16);
background: linear-gradient(180deg, rgba(var(--v-theme-primary), 0.04) 0%, rgba(var(--v-theme-surface), 0.92) 100%);
box-shadow: 0 12px 24px rgba(var(--v-theme-on-surface), 0.04);
}
.setting-actions { .setting-actions {
display: flex; display: flex;
align-items: center; align-items: center;