feat: 重构设置弹窗

This commit is contained in:
digua
2026-01-10 11:41:38 +08:00
committed by digua
parent 995936208e
commit 8d524bdd8b
12 changed files with 364 additions and 183 deletions
+8 -30
View File
@@ -1,11 +1,11 @@
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import AIConfigTab from './settings/AIConfigTab.vue'
import AIPromptConfigTab from './settings/AIPromptConfigTab.vue'
import AISettingsTab from './settings/AISettingsTab.vue'
import BasicSettingsTab from './settings/BasicSettingsTab.vue'
import StorageTab from './settings/StorageTab.vue'
import AboutTab from './settings/AboutTab.vue'
import SubTabs from '@/components/UI/SubTabs.vue'
const { t } = useI18n()
@@ -23,18 +23,15 @@ const emit = defineEmits<{
// Tab 配置(使用 computed 以便语言切换时自动更新)
const tabs = computed(() => [
{ id: 'settings', label: t('settings.tabs.basic'), icon: 'i-heroicons-cog-6-tooth' },
{ id: 'ai-config', label: t('settings.tabs.aiConfig'), icon: 'i-heroicons-sparkles' },
{ id: 'ai-prompt', label: t('settings.tabs.aiPrompt'), icon: 'i-heroicons-document-text' },
{ id: 'ai', label: t('settings.tabs.ai'), icon: 'i-heroicons-sparkles' },
{ id: 'storage', label: t('settings.tabs.storage'), icon: 'i-heroicons-folder-open' },
{ id: 'about', label: t('settings.tabs.about'), icon: 'i-heroicons-information-circle' },
])
const activeTab = ref('settings')
// Template refs - used via ref="xxx" in template
const aiConfigRef = ref<InstanceType<typeof AIConfigTab> | null>(null)
const storageTabRef = ref<InstanceType<typeof StorageTab> | null>(null)
// Ensure refs are tracked for vue-tsc
void aiConfigRef
void storageTabRef
// AI 配置变更回调
@@ -81,23 +78,8 @@ watch(
</div>
<!-- Tab 导航 -->
<div class="mb-6 border-b border-gray-200 dark:border-gray-700">
<div class="flex gap-1">
<button
v-for="tab in tabs"
:key="tab.id"
class="flex items-center gap-2 border-b-2 px-4 py-2.5 text-sm font-medium transition-colors"
:class="[
activeTab === tab.id
? 'border-primary-500 text-primary-600 dark:text-primary-400'
: 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300',
]"
@click="activeTab = tab.id"
>
<UIcon :name="tab.icon" class="h-4 w-4" />
<span>{{ tab.label }}</span>
</button>
</div>
<div class="mb-6 -mx-6">
<SubTabs v-model="activeTab" :items="tabs" />
</div>
<!-- Tab 内容 -->
@@ -106,14 +88,10 @@ watch(
<div v-show="activeTab === 'settings'">
<BasicSettingsTab />
</div>
<!-- 模型配置 -->
<div v-show="activeTab === 'ai-config'">
<AIConfigTab ref="aiConfigRef" @config-changed="handleAIConfigChanged" />
</div>
<!-- AI对话配 -->
<div v-show="activeTab === 'ai-prompt'">
<AIPromptConfigTab @config-changed="handleAIConfigChanged" />
<!-- AI -->
<div v-show="activeTab === 'ai'" class="h-full">
<AISettingsTab @config-changed="handleAIConfigChanged" />
</div>
<!-- 存储管理 -->
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import AIConfigEditModal from './AIConfigEditModal.vue'
import AIModelEditModal from './AIModelEditModal.vue'
import AlertTips from './AlertTips.vue'
const { t } = useI18n()
@@ -148,6 +148,11 @@ onMounted(() => {
<!-- 配置列表视图 -->
<div v-else class="space-y-4">
<!-- 标题 -->
<h4 class="flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white">
<UIcon name="i-heroicons-sparkles" class="h-4 w-4 text-violet-500" />
{{ t('settings.aiConfig.title') }}
</h4>
<AlertTips v-if="configs.length === 0 && aiTips.configTab?.show" :content="aiTips.configTab?.content" />
<!-- 配置列表 -->
<div v-if="configs.length > 0" class="space-y-2">
@@ -198,12 +203,14 @@ onMounted(() => {
<!-- 操作按钮 -->
<div class="flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100" @click.stop>
<UButton size="xs" color="gray" variant="ghost" @click="openEditModal(config)">
{{ t('settings.aiConfig.edit') }}
</UButton>
<UButton size="xs" color="error" variant="ghost" @click="deleteConfig(config.id)">
{{ t('settings.aiConfig.delete') }}
</UButton>
<UButton
size="xs"
color="neutral"
variant="ghost"
icon="i-heroicons-pencil-square"
@click="openEditModal(config)"
/>
<UButton size="xs" color="error" variant="ghost" icon="i-heroicons-trash" @click="deleteConfig(config.id)" />
</div>
</div>
</div>
@@ -228,7 +235,7 @@ onMounted(() => {
</div>
<!-- 编辑/添加弹窗 -->
<AIConfigEditModal
<AIModelEditModal
v-model:open="showEditModal"
:mode="editMode"
:config="editingConfig"
@@ -0,0 +1,141 @@
<script setup lang="ts">
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from 'vue-i18n'
import { usePromptStore } from '@/stores/prompt'
const { t } = useI18n()
// Store
const promptStore = usePromptStore()
const { aiGlobalSettings } = storeToRefs(promptStore)
// Emits
const emit = defineEmits<{
'config-changed': []
}>()
// 发送条数限制
const globalMaxMessages = computed({
get: () => aiGlobalSettings.value.maxMessagesPerRequest,
set: (val: number) => {
const clampedVal = Math.max(10, Math.min(10000, val || 200))
promptStore.updateAIGlobalSettings({ maxMessagesPerRequest: clampedVal })
emit('config-changed')
},
})
// AI上下文限制
const globalMaxHistoryRounds = computed({
get: () => aiGlobalSettings.value.maxHistoryRounds ?? 10,
set: (val: number) => {
const clampedVal = Math.max(1, Math.min(50, val || 10))
promptStore.updateAIGlobalSettings({ maxHistoryRounds: clampedVal })
emit('config-changed')
},
})
// 导出格式选项(AI 对话)
const exportFormatTabs = computed(() => [
{ label: 'Markdown', value: 'markdown' },
{ label: t('settings.aiPrompt.exportFormat.txtLabel'), value: 'txt' },
])
// 当前选中的导出格式(AI 对话)
const exportFormat = computed({
get: () => aiGlobalSettings.value.exportFormat ?? 'markdown',
set: (val: string) => {
promptStore.updateAIGlobalSettings({ exportFormat: val as 'markdown' | 'txt' })
emit('config-changed')
},
})
// SQL Lab 导出格式选项
const sqlExportFormatTabs = computed(() => [
{ label: 'CSV', value: 'csv' },
{ label: 'JSON', value: 'json' },
])
// 当前选中的 SQL Lab 导出格式
const sqlExportFormat = computed({
get: () => aiGlobalSettings.value.sqlExportFormat ?? 'csv',
set: (val: string) => {
promptStore.updateAIGlobalSettings({ sqlExportFormat: val as 'csv' | 'json' })
emit('config-changed')
},
})
</script>
<template>
<div class="space-y-6">
<!-- 对话设置 -->
<div>
<h4 class="mb-3 flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white">
<UIcon name="i-heroicons-chat-bubble-left-right" class="h-4 w-4 text-green-500" />
{{ t('settings.aiPrompt.chatSettings.title') }}
</h4>
<div class="space-y-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800/50">
<!-- 发送条数限制 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.maxMessages.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.maxMessages.description') }}
</p>
</div>
<UInput v-model.number="globalMaxMessages" type="number" min="1" max="10000" class="w-24" />
</div>
<!-- AI上下文限制 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.maxHistory.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.maxHistory.description') }}
</p>
</div>
<UInput v-model.number="globalMaxHistoryRounds" type="number" min="1" max="50" class="w-24" />
</div>
</div>
</div>
<!-- 导出设置 -->
<div>
<h4 class="mb-3 flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white">
<UIcon name="i-heroicons-arrow-down-tray" class="h-4 w-4 text-blue-500" />
{{ t('settings.aiPrompt.exportSettings.title') }}
</h4>
<div class="space-y-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800/50">
<!-- 导出格式AI 对话 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.exportFormat.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.exportFormat.description') }}
</p>
</div>
<UTabs v-model="exportFormat" :items="exportFormatTabs" size="xs" />
</div>
<!-- SQL Lab 导出格式 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.sqlExportFormat.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.sqlExportFormat.description') }}
</p>
</div>
<UTabs v-model="sqlExportFormat" :items="sqlExportFormatTabs" size="xs" />
</div>
</div>
</div>
</div>
</template>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useI18n } from 'vue-i18n'
import type { PromptPreset } from '@/types/ai'
@@ -11,7 +11,7 @@ const { t } = useI18n()
// Store
const promptStore = usePromptStore()
const { groupPresets, privatePresets, aiPromptSettings, aiGlobalSettings } = storeToRefs(promptStore)
const { groupPresets, privatePresets, aiPromptSettings } = storeToRefs(promptStore)
// Emits
const emit = defineEmits<{
@@ -25,56 +25,6 @@ const editMode = ref<'add' | 'edit'>('add')
const editingPreset = ref<PromptPreset | null>(null)
const defaultChatType = ref<'group' | 'private'>('group')
//
const globalMaxMessages = computed({
get: () => aiGlobalSettings.value.maxMessagesPerRequest,
set: (val: number) => {
const clampedVal = Math.max(10, Math.min(10000, val || 200))
promptStore.updateAIGlobalSettings({ maxMessagesPerRequest: clampedVal })
emit('config-changed')
},
})
// AI
const globalMaxHistoryRounds = computed({
get: () => aiGlobalSettings.value.maxHistoryRounds ?? 10,
set: (val: number) => {
const clampedVal = Math.max(1, Math.min(50, val || 10))
promptStore.updateAIGlobalSettings({ maxHistoryRounds: clampedVal })
emit('config-changed')
},
})
// AI
const exportFormatTabs = computed(() => [
{ label: 'Markdown', value: 'markdown' },
{ label: t('settings.aiPrompt.exportFormat.txtLabel'), value: 'txt' },
])
// AI
const exportFormat = computed({
get: () => aiGlobalSettings.value.exportFormat ?? 'markdown',
set: (val: string) => {
promptStore.updateAIGlobalSettings({ exportFormat: val as 'markdown' | 'txt' })
emit('config-changed')
},
})
// SQL Lab
const sqlExportFormatTabs = computed(() => [
{ label: 'CSV', value: 'csv' },
{ label: 'JSON', value: 'json' },
])
// SQL Lab
const sqlExportFormat = computed({
get: () => aiGlobalSettings.value.sqlExportFormat ?? 'csv',
set: (val: string) => {
promptStore.updateAIGlobalSettings({ sqlExportFormat: val as 'csv' | 'json' })
emit('config-changed')
},
})
/** 打开新增预设弹窗 */
function openAddModal(chatType: 'group' | 'private') {
editMode.value = 'add'
@@ -134,70 +84,6 @@ function handleImportPresetAdded() {
<template>
<div class="space-y-6">
<!-- 对话设置 -->
<div>
<h4 class="mb-3 flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white">
<UIcon name="i-heroicons-adjustments-horizontal" class="h-4 w-4 text-green-500" />
{{ t('settings.aiPrompt.title') }}
</h4>
<div class="space-y-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800/50">
<!-- 发送条数限制 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.maxMessages.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.maxMessages.description') }}
</p>
</div>
<UInput v-model.number="globalMaxMessages" type="number" min="1" max="10000" class="w-24" />
</div>
<!-- AI上下文限制 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.maxHistory.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.maxHistory.description') }}
</p>
</div>
<UInput v-model.number="globalMaxHistoryRounds" type="number" min="1" max="50" class="w-24" />
</div>
<!-- 导出格式AI 对话 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.exportFormat.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.exportFormat.description') }}
</p>
</div>
<UTabs v-model="exportFormat" :items="exportFormatTabs" size="xs" />
</div>
<!-- SQL Lab 导出格式 -->
<div class="flex items-center justify-between">
<div class="flex-1 pr-4">
<p class="text-sm font-medium text-gray-900 dark:text-white">
{{ t('settings.aiPrompt.sqlExportFormat.title') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ t('settings.aiPrompt.sqlExportFormat.description') }}
</p>
</div>
<UTabs v-model="sqlExportFormat" :items="sqlExportFormatTabs" size="xs" />
</div>
</div>
</div>
<!-- 分隔线 -->
<div class="border-t border-gray-200 dark:border-gray-700"></div>
<!-- 系统提示词标题和导入按钮 -->
<div class="flex items-center justify-between">
<h4 class="flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white">
@@ -210,8 +96,8 @@ function handleImportPresetAdded() {
</UButton>
</div>
<!-- 群聊和私聊系统提示词并排 -->
<div class="grid grid-cols-2 gap-4">
<!-- 群聊和私聊系统提示词 -->
<div class="space-y-6">
<!-- 群聊预设组 -->
<div>
<div class="mb-3 flex items-center justify-between">
@@ -261,21 +147,28 @@ function handleImportPresetAdded() {
<!-- 操作按钮 -->
<div class="flex items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100" @click.stop>
<UButton color="gray" variant="ghost" size="xs" @click="openEditModal(preset)">
{{ preset.isBuiltIn ? t('settings.aiPrompt.preset.view') : t('settings.aiPrompt.preset.edit') }}
</UButton>
<UButton color="gray" variant="ghost" size="xs" @click="duplicatePreset(preset.id)">
{{ t('settings.aiPrompt.preset.copy') }}
</UButton>
<UButton
color="neutral"
variant="ghost"
size="xs"
:icon="preset.isBuiltIn ? 'i-heroicons-eye' : 'i-heroicons-pencil-square'"
@click="openEditModal(preset)"
/>
<UButton
color="neutral"
variant="ghost"
size="xs"
icon="i-heroicons-document-duplicate"
@click="duplicatePreset(preset.id)"
/>
<UButton
v-if="!preset.isBuiltIn"
color="error"
variant="ghost"
size="xs"
icon="i-heroicons-trash"
@click="deletePreset(preset.id)"
>
{{ t('settings.aiPrompt.preset.delete') }}
</UButton>
/>
</div>
</div>
</div>
@@ -330,21 +223,28 @@ function handleImportPresetAdded() {
<!-- 操作按钮 -->
<div class="flex items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100" @click.stop>
<UButton color="gray" variant="ghost" size="xs" @click="openEditModal(preset)">
{{ preset.isBuiltIn ? t('settings.aiPrompt.preset.view') : t('settings.aiPrompt.preset.edit') }}
</UButton>
<UButton color="gray" variant="ghost" size="xs" @click="duplicatePreset(preset.id)">
{{ t('settings.aiPrompt.preset.copy') }}
</UButton>
<UButton
color="neutral"
variant="ghost"
size="xs"
:icon="preset.isBuiltIn ? 'i-heroicons-eye' : 'i-heroicons-pencil-square'"
@click="openEditModal(preset)"
/>
<UButton
color="neutral"
variant="ghost"
size="xs"
icon="i-heroicons-document-duplicate"
@click="duplicatePreset(preset.id)"
/>
<UButton
v-if="!preset.isBuiltIn"
color="error"
variant="ghost"
size="xs"
icon="i-heroicons-trash"
@click="deletePreset(preset.id)"
>
{{ t('settings.aiPrompt.preset.delete') }}
</UButton>
/>
</div>
</div>
</div>
@@ -0,0 +1,138 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useI18n } from 'vue-i18n'
import AIModelConfigTab from './AI/AIModelConfigTab.vue'
import AIPromptConfigTab from './AI/AIPromptConfigTab.vue'
import AIPromptPresetTab from './AI/AIPromptPresetTab.vue'
import SubTabs from '@/components/UI/SubTabs.vue'
const { t } = useI18n()
// Emits
const emit = defineEmits<{
'config-changed': []
}>()
// 导航配置
const navItems = computed(() => [
{ id: 'model', label: t('settings.tabs.aiConfig') },
{ id: 'chat', label: t('settings.tabs.aiPrompt') },
{ id: 'preset', label: t('settings.tabs.aiPreset') },
])
// 当前激活的导航项
const activeNav = ref('model')
// 是否由用户点击触发(用于区分点击滚动和手动滚动)
const isUserClick = ref(false)
// 滚动容器引用
const scrollContainerRef = ref<HTMLElement | null>(null)
// Section 引用
const sectionRefs = ref<Record<string, HTMLElement | null>>({
model: null,
chat: null,
preset: null,
})
// AI 配置变更回调
function handleAIConfigChanged() {
emit('config-changed')
}
// 处理导航点击(通过 @change 事件)
function handleNavChange(id: string) {
const section = sectionRefs.value[id]
if (section && scrollContainerRef.value) {
// 标记为用户点击触发
isUserClick.value = true
section.scrollIntoView({ behavior: 'smooth', block: 'start' })
// 滚动动画结束后恢复
setTimeout(() => {
isUserClick.value = false
}, 500)
}
}
// 监听滚动更新当前激活项
function handleScroll() {
// 如果是用户点击触发的滚动,不更新 activeNav(避免冲突)
if (isUserClick.value || !scrollContainerRef.value) return
const container = scrollContainerRef.value
const containerRect = container.getBoundingClientRect()
const offset = 50 // 偏移量,提前触发
// 检查是否滚动到底部(误差范围 5px)
const isAtBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 5
if (isAtBottom) {
// 滚动到底部时,激活最后一个导航项
const lastItem = navItems.value[navItems.value.length - 1]
if (lastItem) {
activeNav.value = lastItem.id
}
return
}
// 检查每个 section 的位置
for (const item of navItems.value) {
const section = sectionRefs.value[item.id]
if (section) {
const rect = section.getBoundingClientRect()
// 如果 section 顶部在容器可视区域内
if (rect.top <= containerRect.top + offset && rect.bottom > containerRect.top + offset) {
activeNav.value = item.id
break
}
}
}
}
// Template refs
const aiModelConfigRef = ref<InstanceType<typeof AIModelConfigTab> | null>(null)
void aiModelConfigRef
onMounted(() => {
scrollContainerRef.value?.addEventListener('scroll', handleScroll)
})
onUnmounted(() => {
scrollContainerRef.value?.removeEventListener('scroll', handleScroll)
})
</script>
<template>
<div class="flex h-full gap-6">
<!-- 左侧锚点导航 -->
<div class="w-28 shrink-0">
<SubTabs v-model="activeNav" :items="navItems" orientation="vertical" @change="handleNavChange" />
</div>
<!-- 右侧内容区域 -->
<div ref="scrollContainerRef" class="min-w-0 flex-1 overflow-y-auto">
<div class="space-y-8">
<!-- 模型配置 -->
<div :ref="(el) => (sectionRefs.model = el as HTMLElement)">
<AIModelConfigTab ref="aiModelConfigRef" @config-changed="handleAIConfigChanged" />
</div>
<!-- 分隔线 -->
<div class="border-t border-gray-200 dark:border-gray-700" />
<!-- 对话配置 -->
<div :ref="(el) => (sectionRefs.chat = el as HTMLElement)">
<AIPromptConfigTab @config-changed="handleAIConfigChanged" />
</div>
<!-- 分隔线 -->
<div class="border-t border-gray-200 dark:border-gray-700" />
<!-- 提示词配置 -->
<div :ref="(el) => (sectionRefs.preset = el as HTMLElement)">
<AIPromptPresetTab @config-changed="handleAIConfigChanged" />
</div>
</div>
</div>
</div>
</template>
+5 -4
View File
@@ -1,5 +1,6 @@
export { default as AIConfigTab } from './AIConfigTab.vue'
export { default as AIConfigEditModal } from './AIConfigEditModal.vue'
export { default as AIPromptConfigTab } from './AIPromptConfigTab.vue'
export { default as AIPromptEditModal } from './AIPromptEditModal.vue'
export { default as AISettingsTab } from './AISettingsTab.vue'
export { default as AIModelConfigTab } from './AI/AIModelConfigTab.vue'
export { default as AIModelEditModal } from './AI/AIModelEditModal.vue'
export { default as AIPromptConfigTab } from './AI/AIPromptConfigTab.vue'
export { default as AIPromptEditModal } from './AI/AIPromptEditModal.vue'
export { default as CacheManageTab } from './CacheManageTab.vue'
+10 -2
View File
@@ -2,8 +2,10 @@
"title": "Settings",
"tabs": {
"basic": "General",
"ai": "AI Settings",
"aiConfig": "AI Models",
"aiPrompt": "AI Chat Config",
"aiPrompt": "Chat Config",
"aiPreset": "Prompts",
"storage": "Storage",
"about": "About"
},
@@ -42,6 +44,7 @@
}
},
"aiConfig": {
"title": "Model Configuration",
"loading": "Loading...",
"inUse": "Active",
"defaultModel": "Default Model",
@@ -129,7 +132,12 @@
}
},
"aiPrompt": {
"title": "Chat Settings",
"chatSettings": {
"title": "Chat Settings"
},
"exportSettings": {
"title": "Export Settings"
},
"maxMessages": {
"title": "Max Messages per Request",
"description": "Max number of messages sent to AI per request. Higher values consume more tokens but provide more accurate context (recommended: 2000)."
+11 -3
View File
@@ -1,9 +1,11 @@
{
"title": "全局设置",
"title": "设置",
"tabs": {
"basic": "基础设置",
"ai": "AI 设置",
"aiConfig": "模型配置",
"aiPrompt": "AI 对话配置",
"aiPrompt": "对话配置",
"aiPreset": "提示词配置",
"storage": "存储管理",
"about": "关于"
},
@@ -42,6 +44,7 @@
}
},
"aiConfig": {
"title": "模型配置",
"loading": "加载中...",
"inUse": "使用中",
"defaultModel": "默认模型",
@@ -129,7 +132,12 @@
}
},
"aiPrompt": {
"title": "对话设置",
"chatSettings": {
"title": "对话设置"
},
"exportSettings": {
"title": "导出设置"
},
"maxMessages": {
"title": "发送条数限制",
"description": "每次提交给 AI 的最大消息数,数值越大 Token 消耗越多,分析也更准确(建议2000)"