feat(optimize): 重构优化面板,整合提示词类型选择器
- 将原有的输入面板和优化结果区域替换为新的优化面板组件 OptimizePanelUI,提升代码可维护性 - 在优化面板中集成提示词类型选择器,优化用户交互体验 - 更新相关的状态管理逻辑,确保提示词和优化结果的正确传递 - 修改国际化文件,确保新组件的文本支持多语言 - 更新测试用例,验证新功能的正确性和稳定性
This commit is contained in:
1 parent
ebf4d2730b
commit
1237fa4e5e
7 files changed
+137
-211
No files matched your search
+58
-132
@@ -43,65 +43,22 @@
|
||||
|
||||
<!-- 主要内容插槽 -->
|
||||
<!-- 提示词区 -->
|
||||
<ContentCardUI>
|
||||
<!-- 输入区域 -->
|
||||
<div class="flex-none">
|
||||
<InputPanelUI
|
||||
v-model="prompt"
|
||||
v-model:selectedModel="selectedOptimizeModel"
|
||||
:label="$t('promptOptimizer.originalPrompt')"
|
||||
:placeholder="$t('promptOptimizer.inputPlaceholder')"
|
||||
:model-label="$t('promptOptimizer.optimizeModel')"
|
||||
:template-label="$t('promptOptimizer.templateLabel')"
|
||||
:button-text="$t('promptOptimizer.optimize')"
|
||||
:loading-text="$t('common.loading')"
|
||||
:loading="isOptimizing"
|
||||
:disabled="isOptimizing"
|
||||
@submit="handleOptimizePrompt"
|
||||
@configModel="showConfig = true"
|
||||
>
|
||||
<template #model-select>
|
||||
<ModelSelectUI
|
||||
ref="optimizeModelSelect"
|
||||
:modelValue="selectedOptimizeModel"
|
||||
@update:modelValue="selectedOptimizeModel = $event"
|
||||
:disabled="isOptimizing"
|
||||
@config="showConfig = true"
|
||||
/>
|
||||
</template>
|
||||
<template #template-select>
|
||||
<TemplateSelectUI
|
||||
v-model="selectedOptimizeTemplate"
|
||||
type="optimize"
|
||||
@manage="openTemplateManager('optimize')"
|
||||
@select="handleTemplateSelect"
|
||||
/>
|
||||
</template>
|
||||
</InputPanelUI>
|
||||
</div>
|
||||
|
||||
<!-- 优化结果区域 -->
|
||||
<div class="flex-1 min-h-0 overflow-y-auto">
|
||||
<PromptPanelUI
|
||||
v-model:optimized-prompt="optimizedPrompt"
|
||||
:original-prompt="prompt"
|
||||
:is-iterating="isIterating"
|
||||
v-model:selected-iterate-template="selectedIterateTemplate"
|
||||
:versions="currentVersions"
|
||||
:current-version-id="currentVersionId"
|
||||
@iterate="handleIteratePrompt"
|
||||
@openTemplateManager="openTemplateManager"
|
||||
@switchVersion="handleSwitchVersion"
|
||||
@templateSelect="handleTemplateSelect"
|
||||
/>
|
||||
</div>
|
||||
</ContentCardUI>
|
||||
<OptimizePanelUI
|
||||
ref="optimizePanel"
|
||||
:model-manager="modelManager"
|
||||
:template-manager="templateManager"
|
||||
:history-manager="historyManager"
|
||||
:prompt-service="promptServiceRef"
|
||||
@showConfig="showConfig = true"
|
||||
@openTemplateManager="openTemplateManager"
|
||||
/>
|
||||
|
||||
<!-- 测试区域 -->
|
||||
<TestPanelUI
|
||||
:prompt-service="promptServiceRef"
|
||||
:original-prompt="prompt"
|
||||
:optimized-prompt="optimizedPrompt"
|
||||
:prompt-type="selectedPromptType"
|
||||
v-model="selectedTestModel"
|
||||
@showConfig="showConfig = true"
|
||||
/>
|
||||
@@ -123,8 +80,9 @@
|
||||
<TemplateManagerUI
|
||||
v-if="showTemplates"
|
||||
:template-type="currentType"
|
||||
:selected-optimize-template="selectedOptimizeTemplate"
|
||||
:selected-iterate-template="selectedIterateTemplate"
|
||||
:prompt-type="selectedPromptType"
|
||||
:selected-optimize-template="optimizePanel?.selectedOptimizeTemplate"
|
||||
:selected-iterate-template="optimizePanel?.selectedIterateTemplate"
|
||||
@close="handleTemplateManagerClose"
|
||||
@select="handleTemplateSelect"
|
||||
/>
|
||||
@@ -150,31 +108,24 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {
|
||||
// UI组件
|
||||
ToastUI,
|
||||
ModelManagerUI,
|
||||
ThemeToggleUI,
|
||||
OutputPanelUI,
|
||||
PromptPanelUI,
|
||||
TemplateManagerUI,
|
||||
TemplateSelectUI,
|
||||
ModelSelectUI,
|
||||
HistoryDrawerUI,
|
||||
InputPanelUI,
|
||||
MainLayoutUI,
|
||||
ContentCardUI,
|
||||
ActionButtonUI,
|
||||
TestPanelUI,
|
||||
LanguageSwitchUI,
|
||||
DataManagerUI,
|
||||
OptimizePanelUI,
|
||||
// composables
|
||||
usePromptOptimizer,
|
||||
usePromptTester,
|
||||
useToast,
|
||||
usePromptHistory,
|
||||
useServiceInitializer,
|
||||
useTemplateManager,
|
||||
useModelManager,
|
||||
@@ -208,6 +159,9 @@ const toast = useToast()
|
||||
// 初始化国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// OptimizePanel 引用
|
||||
const optimizePanel = ref(null)
|
||||
|
||||
// 初始化服务
|
||||
const {
|
||||
promptServiceRef
|
||||
@@ -233,79 +187,51 @@ const {
|
||||
testModelSelect
|
||||
})
|
||||
|
||||
// 初始化组合式函数
|
||||
const {
|
||||
prompt,
|
||||
optimizedPrompt,
|
||||
isOptimizing,
|
||||
isIterating,
|
||||
selectedOptimizeTemplate,
|
||||
selectedIterateTemplate,
|
||||
currentVersions,
|
||||
currentVersionId,
|
||||
currentChainId,
|
||||
handleOptimizePrompt,
|
||||
handleIteratePrompt,
|
||||
handleSwitchVersion,
|
||||
saveTemplateSelection
|
||||
} = usePromptOptimizer(
|
||||
modelManager,
|
||||
templateManager,
|
||||
historyManager,
|
||||
promptServiceRef,
|
||||
selectedOptimizeModel,
|
||||
selectedTestModel
|
||||
)
|
||||
// 通过 OptimizePanel 获取状态
|
||||
const prompt = computed(() => optimizePanel.value?.prompt || '')
|
||||
const optimizedPrompt = computed(() => optimizePanel.value?.optimizedPrompt || '')
|
||||
const selectedPromptType = computed(() => optimizePanel.value?.selectedPromptType || 'system')
|
||||
|
||||
// 初始化历史记录管理器
|
||||
const {
|
||||
history,
|
||||
handleSelectHistory: handleSelectHistoryBase,
|
||||
handleClearHistory: handleClearHistoryBase,
|
||||
handleDeleteChain: handleDeleteChainBase
|
||||
} = usePromptHistory(
|
||||
historyManager,
|
||||
prompt,
|
||||
optimizedPrompt,
|
||||
currentChainId,
|
||||
currentVersions,
|
||||
currentVersionId
|
||||
)
|
||||
// 历史记录管理
|
||||
const showHistory = ref(false)
|
||||
const history = computed(() => historyManager.getHistory())
|
||||
|
||||
// 初始化历史记录管理器UI
|
||||
const {
|
||||
showHistory,
|
||||
handleSelectHistory,
|
||||
handleClearHistory,
|
||||
handleDeleteChain
|
||||
} = useHistoryManager(
|
||||
historyManager,
|
||||
prompt,
|
||||
optimizedPrompt,
|
||||
currentChainId,
|
||||
currentVersions,
|
||||
currentVersionId,
|
||||
handleSelectHistoryBase,
|
||||
handleClearHistoryBase,
|
||||
handleDeleteChainBase
|
||||
)
|
||||
const handleSelectHistory = (record) => {
|
||||
if (optimizePanel.value) {
|
||||
optimizePanel.value.handleSelectHistory(record)
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化模板管理器
|
||||
const {
|
||||
showTemplates,
|
||||
currentType,
|
||||
handleTemplateSelect,
|
||||
openTemplateManager,
|
||||
handleTemplateManagerClose
|
||||
} = useTemplateManager({
|
||||
selectedOptimizeTemplate,
|
||||
selectedIterateTemplate,
|
||||
saveTemplateSelection,
|
||||
templateManager
|
||||
})
|
||||
const handleClearHistory = () => {
|
||||
historyManager.clearHistory()
|
||||
toast.success(t('history.cleared'))
|
||||
}
|
||||
|
||||
const handleDeleteChain = (chainId) => {
|
||||
historyManager.deleteChain(chainId)
|
||||
toast.success(t('history.chainDeleted'))
|
||||
}
|
||||
|
||||
// 模板管理器
|
||||
const showTemplates = ref(false)
|
||||
const currentType = ref('optimize')
|
||||
|
||||
const openTemplateManager = (type) => {
|
||||
currentType.value = type
|
||||
showTemplates.value = true
|
||||
}
|
||||
|
||||
const handleTemplateManagerClose = () => {
|
||||
showTemplates.value = false
|
||||
}
|
||||
|
||||
const handleTemplateSelect = (template, type) => {
|
||||
if (optimizePanel.value) {
|
||||
optimizePanel.value.handleTemplateSelect(template, type)
|
||||
}
|
||||
}
|
||||
|
||||
// 数据管理器
|
||||
import { ref } from 'vue'
|
||||
const showDataManager = ref(false)
|
||||
|
||||
const handleDataManagerClose = () => {
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
<template>
|
||||
<div class="space-y-3">
|
||||
<!-- 标题 -->
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-2">
|
||||
<label class="block text-lg theme-label">{{ label }}</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex items-center space-x-3">
|
||||
<slot name="prompt-type-selector"></slot>
|
||||
<button
|
||||
@click="openFullscreen"
|
||||
class="px-3 py-1.5 theme-button-secondary flex items-center space-x-2"
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
<template>
|
||||
<ContentCardUI>
|
||||
<!-- 提示词类型选择器 -->
|
||||
<div class="flex-none mb-4">
|
||||
<PromptTypeSelectorUI
|
||||
v-model="selectedPromptType"
|
||||
@change="handlePromptTypeChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- 输入区域 -->
|
||||
<div class="flex-none">
|
||||
<InputPanelUI
|
||||
@@ -26,6 +16,12 @@
|
||||
@submit="handleOptimizePrompt"
|
||||
@configModel="$emit('showConfig')"
|
||||
>
|
||||
<template #prompt-type-selector>
|
||||
<PromptTypeSelectorUI
|
||||
v-model="selectedPromptType"
|
||||
@change="handlePromptTypeChange"
|
||||
/>
|
||||
</template>
|
||||
<template #model-select>
|
||||
<ModelSelectUI
|
||||
ref="optimizeModelSelect"
|
||||
@@ -38,9 +34,9 @@
|
||||
<template #template-select>
|
||||
<TemplateSelectUI
|
||||
v-model="selectedOptimizeTemplate"
|
||||
type="optimize"
|
||||
:type="selectedPromptType === 'system' ? 'optimize' : 'userOptimize'"
|
||||
:prompt-type="selectedPromptType"
|
||||
@manage="$emit('openTemplateManager', 'optimize')"
|
||||
@manage="$emit('openTemplateManager', selectedPromptType === 'system' ? 'optimize' : 'userOptimize')"
|
||||
@select="handleTemplateSelect"
|
||||
/>
|
||||
</template>
|
||||
@@ -162,6 +158,18 @@ defineExpose({
|
||||
initModelSelection,
|
||||
loadModels,
|
||||
saveTemplateSelection,
|
||||
selectedPromptType
|
||||
selectedPromptType,
|
||||
selectedOptimizeTemplate,
|
||||
selectedIterateTemplate,
|
||||
handleTemplateSelect,
|
||||
handleSelectHistory: (record) => {
|
||||
// 处理历史记录选择
|
||||
prompt.value = record.originalPrompt
|
||||
optimizedPrompt.value = record.optimizedPrompt
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* OptimizePanel 样式 */
|
||||
</style>
|
||||
@@ -1,41 +1,36 @@
|
||||
<!-- 提示词类型选择器组件 - 简化版 -->
|
||||
<template>
|
||||
<div class="prompt-type-selector">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t('promptOptimizer.promptType') }}:
|
||||
</span>
|
||||
<div class="inline-flex bg-gray-50 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-600 text-xs">
|
||||
<button
|
||||
@click="updatePromptType('system')"
|
||||
:class="[
|
||||
'px-2 py-1 transition-colors duration-150 rounded-l',
|
||||
'focus:outline-none focus:ring-1 focus:ring-blue-400',
|
||||
modelValue === 'system'
|
||||
? 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
|
||||
: 'text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-75 dark:hover:bg-gray-750'
|
||||
]"
|
||||
:aria-pressed="modelValue === 'system'"
|
||||
:title="t('promptOptimizer.systemPromptHelp')"
|
||||
>
|
||||
{{ t('promptOptimizer.systemPrompt') }}
|
||||
</button>
|
||||
<div class="w-px bg-gray-200 dark:bg-gray-600"></div>
|
||||
<button
|
||||
@click="updatePromptType('user')"
|
||||
:class="[
|
||||
'px-2 py-1 transition-colors duration-150 rounded-r',
|
||||
'focus:outline-none focus:ring-1 focus:ring-blue-400',
|
||||
modelValue === 'user'
|
||||
? 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
|
||||
: 'text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-75 dark:hover:bg-gray-750'
|
||||
]"
|
||||
:aria-pressed="modelValue === 'user'"
|
||||
:title="t('promptOptimizer.userPromptHelp')"
|
||||
>
|
||||
{{ t('promptOptimizer.userPrompt') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="inline-flex bg-gray-50 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-600 text-[10px]">
|
||||
<button
|
||||
@click="updatePromptType('system')"
|
||||
:class="[
|
||||
'px-1.5 py-0.5 transition-colors duration-150 rounded-l',
|
||||
'focus:outline-none focus:ring-1 focus:ring-blue-400',
|
||||
modelValue === 'system'
|
||||
? 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
|
||||
: 'text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-75 dark:hover:bg-gray-750'
|
||||
]"
|
||||
:aria-pressed="modelValue === 'system'"
|
||||
:title="t('promptOptimizer.systemPromptHelp')"
|
||||
>
|
||||
{{ t('promptOptimizer.systemPrompt') }}
|
||||
</button>
|
||||
<div class="w-px bg-gray-200 dark:bg-gray-600"></div>
|
||||
<button
|
||||
@click="updatePromptType('user')"
|
||||
:class="[
|
||||
'px-1.5 py-0.5 transition-colors duration-150 rounded-r',
|
||||
'focus:outline-none focus:ring-1 focus:ring-blue-400',
|
||||
modelValue === 'user'
|
||||
? 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
|
||||
: 'text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-75 dark:hover:bg-gray-750'
|
||||
]"
|
||||
:aria-pressed="modelValue === 'user'"
|
||||
:title="t('promptOptimizer.userPromptHelp')"
|
||||
>
|
||||
{{ t('promptOptimizer.userPrompt') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 导入样式
|
||||
// 导入样式
|
||||
import 'element-plus/dist/index.css'
|
||||
import './styles/index.css'
|
||||
import './styles/scrollbar.css'
|
||||
@@ -32,6 +32,7 @@ export { default as LanguageSwitchUI } from './components/LanguageSwitch.vue'
|
||||
export { default as BuiltinTemplateLanguageSwitchUi } from './components/BuiltinTemplateLanguageSwitch.vue'
|
||||
export { default as DataManagerUI } from './components/DataManager.vue'
|
||||
export { default as PromptTypeSelectorUI } from './components/PromptTypeSelector.vue'
|
||||
export { default as OptimizePanelUI } from './components/OptimizePanel.vue'
|
||||
|
||||
// 导出指令
|
||||
export { clickOutside } from './directives/clickOutside'
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('PromptTypeSelector', () => {
|
||||
})
|
||||
|
||||
expect(wrapper.find('.prompt-type-selector').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('Prompt Type')
|
||||
// 移除了"优化模式:"标签前缀,只显示按钮
|
||||
expect(wrapper.text()).toContain('System Prompt')
|
||||
expect(wrapper.text()).toContain('User Prompt')
|
||||
})
|
||||
@@ -162,11 +162,11 @@ describe('PromptTypeSelector', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Should show prompt type label and buttons, but no help text
|
||||
expect(wrapper.text()).toContain('Prompt Type')
|
||||
// Should show buttons but no label prefix or help text (simplified design)
|
||||
expect(wrapper.text()).toContain('System Prompt')
|
||||
expect(wrapper.text()).toContain('User Prompt')
|
||||
// Should not contain help text (simplified design)
|
||||
// Should not contain label prefix or help text (simplified design)
|
||||
expect(wrapper.text()).not.toContain('Prompt Type')
|
||||
expect(wrapper.text()).not.toContain('Optimize system prompts to define AI assistant role')
|
||||
})
|
||||
|
||||
@@ -180,11 +180,11 @@ describe('PromptTypeSelector', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Should show compact design without help text
|
||||
expect(wrapper.text()).toContain('Prompt Type')
|
||||
// Should show compact design without label prefix or help text
|
||||
expect(wrapper.text()).toContain('System Prompt')
|
||||
expect(wrapper.text()).toContain('User Prompt')
|
||||
// Should not contain help text (simplified design)
|
||||
// Should not contain label prefix or help text (simplified design)
|
||||
expect(wrapper.text()).not.toContain('Prompt Type')
|
||||
expect(wrapper.text()).not.toContain('Optimize user prompts to improve AI interaction')
|
||||
})
|
||||
|
||||
|
||||
+15
-20
@@ -44,16 +44,6 @@
|
||||
<!-- 主要内容插槽 -->
|
||||
<!-- 提示词区 -->
|
||||
<ContentCardUI>
|
||||
<!-- 提示词类型选择器 -->
|
||||
<div class="flex-none mb-4">
|
||||
<PromptTypeSelectorUI
|
||||
v-model="selectedPromptType"
|
||||
@change="handlePromptTypeChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- 输入区域 -->
|
||||
<div class="flex-none">
|
||||
<InputPanelUI
|
||||
@@ -70,6 +60,12 @@
|
||||
@submit="handleOptimizePrompt"
|
||||
@configModel="showConfig = true"
|
||||
>
|
||||
<template #prompt-type-selector>
|
||||
<PromptTypeSelectorUI
|
||||
v-model="selectedPromptType"
|
||||
@change="handlePromptTypeChange"
|
||||
/>
|
||||
</template>
|
||||
<template #model-select>
|
||||
<ModelSelectUI
|
||||
ref="optimizeModelSelect"
|
||||
@@ -92,7 +88,7 @@
|
||||
|
||||
<!-- 优化结果区域 -->
|
||||
<div class="flex-1 min-h-0 overflow-y-auto">
|
||||
<PromptPanelUI
|
||||
<PromptPanelUI
|
||||
v-model:optimized-prompt="optimizedPrompt"
|
||||
:original-prompt="prompt"
|
||||
:is-iterating="isIterating"
|
||||
@@ -169,20 +165,19 @@ import {
|
||||
ToastUI,
|
||||
ModelManagerUI,
|
||||
ThemeToggleUI,
|
||||
OutputPanelUI,
|
||||
PromptPanelUI,
|
||||
TemplateManagerUI,
|
||||
TemplateSelectUI,
|
||||
ModelSelectUI,
|
||||
HistoryDrawerUI,
|
||||
InputPanelUI,
|
||||
MainLayoutUI,
|
||||
ContentCardUI,
|
||||
ActionButtonUI,
|
||||
TestPanelUI,
|
||||
LanguageSwitchUI,
|
||||
DataManagerUI,
|
||||
InputPanelUI,
|
||||
PromptPanelUI,
|
||||
PromptTypeSelectorUI,
|
||||
ModelSelectUI,
|
||||
TemplateSelectUI,
|
||||
ContentCardUI,
|
||||
// composables
|
||||
usePromptOptimizer,
|
||||
usePromptTester,
|
||||
@@ -287,9 +282,9 @@ const {
|
||||
templateManager,
|
||||
historyManager,
|
||||
promptServiceRef,
|
||||
selectedPromptType, // 新增:提示词类型
|
||||
selectedOptimizeModel, // 新增:优化模型选择
|
||||
selectedTestModel // 新增:测试模型选择
|
||||
selectedPromptType,
|
||||
selectedOptimizeModel,
|
||||
selectedTestModel
|
||||
)
|
||||
|
||||
// 初始化历史记录管理器
|
||||
|
||||
Reference in new issue
Block a user