feat: 修复内置模板语言切换后迭代页面不更新的问题,完善事件传播机制
This commit is contained in:
1 parent
94f4df0481
commit
c0cc629542
10 files changed
+454
-8
No files matched your search
@@ -14,20 +14,23 @@
|
||||
|
||||
## 文档清单
|
||||
- [x] `troubleshooting.md` - 模板管理故障排除清单
|
||||
- [x] `event-propagation-fix.md` - 事件传播机制修复(内置模板语言切换bug)
|
||||
- [ ] `design.md` - 模板管理功能设计
|
||||
- [ ] `experience.md` - 开发经验总结(待从experience.md中提取)
|
||||
|
||||
## 相关代码变更
|
||||
- 影响包:@prompt-optimizer/core, @prompt-optimizer/ui
|
||||
- 影响包:@prompt-optimizer/core, @prompt-optimizer/ui, @prompt-optimizer/web, @prompt-optimizer/extension
|
||||
- 主要变更:
|
||||
- 模板管理功能实现
|
||||
- 异步操作优化
|
||||
- 错误处理改进
|
||||
- **事件传播机制完善**:修复内置模板语言切换后迭代页面不更新的问题
|
||||
|
||||
## 已知问题和解决方案
|
||||
- 模板删除错误"Template not found":异步方法调用缺少await关键字
|
||||
- 模态框渲染问题:缺少v-if指令控制显示
|
||||
- 模板管理器调用逻辑:优化模式选择与模板管理的关联
|
||||
- **内置模板语言切换后迭代页面不更新**:事件传播机制缺失,需要建立完整的事件传播链
|
||||
|
||||
## 后续影响
|
||||
- 提升模板管理用户体验
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
# 事件传播机制修复 - 内置模板语言切换bug
|
||||
|
||||
## 🎯 问题描述
|
||||
|
||||
### 核心问题
|
||||
内置模板语言切换后,主界面的优化提示词下拉框正确更新,但迭代页面的模板选择显示旧语言的模板名称。
|
||||
|
||||
### 问题表现
|
||||
1. **主界面正常**:优化提示词下拉框从"通用优化"正确切换到"General Optimization"
|
||||
2. **迭代页面异常**:
|
||||
- 当前选中项显示"通用迭代"(中文)
|
||||
- 下拉列表显示"General Iteration"(英文)
|
||||
- 用户需要手动重新选择才能使用英文模板
|
||||
3. **实际请求正常**:发送请求时生效的是新语言(因为通过templateId重新获取)
|
||||
|
||||
### 用户体验影响
|
||||
- 造成用户困惑:UI显示不一致
|
||||
- 需要额外操作:用户必须手动重新选择模板
|
||||
- 功能不完整:语言切换功能没有完全生效
|
||||
|
||||
## 🔍 根本原因分析
|
||||
|
||||
### 组件层级差异
|
||||
**主界面的优化提示词下拉框(正常):**
|
||||
```
|
||||
App.vue
|
||||
└── TemplateSelectUI (ref="templateSelectRef")
|
||||
```
|
||||
|
||||
**迭代页面的模板下拉框(异常):**
|
||||
```
|
||||
App.vue
|
||||
└── PromptPanelUI (ref="promptPanelRef")
|
||||
└── TemplateSelect (ref="iterateTemplateSelectRef")
|
||||
```
|
||||
|
||||
### 事件传播路径差异
|
||||
**主界面的刷新机制:**
|
||||
1. TemplateManager关闭时自动调用 `templateSelectRef?.refresh?.()`
|
||||
2. 直接引用,事件传播路径短
|
||||
3. 有完整的刷新机制
|
||||
|
||||
**迭代页面的问题:**
|
||||
1. 语言切换事件无法传播到深层的TemplateSelect组件
|
||||
2. 组件层级更深,需要额外的事件传播机制
|
||||
3. 之前没有建立完整的事件传播链
|
||||
|
||||
### 技术细节
|
||||
1. **事件源**:`BuiltinTemplateLanguageSwitch` 发出 `languageChanged` 事件
|
||||
2. **处理层**:`TemplateManager` 处理事件并更新自身状态
|
||||
3. **传播断点**:事件没有继续传播到App.vue层级
|
||||
4. **影响范围**:只有TemplateManager内部的组件得到更新
|
||||
|
||||
## 🔧 解决方案
|
||||
|
||||
### 1. 建立事件传播链
|
||||
|
||||
**TemplateManager.vue** - 发出语言变化事件:
|
||||
```javascript
|
||||
const handleLanguageChanged = async (newLanguage: string) => {
|
||||
// 重新加载模板列表以反映新的语言
|
||||
await loadTemplates()
|
||||
|
||||
// 如果当前选中的模板是内置模板,需要重新选择以获取新语言版本
|
||||
const currentSelected = selectedTemplate.value
|
||||
if (currentSelected && currentSelected.isBuiltin) {
|
||||
try {
|
||||
const updatedTemplate = await getTemplateManager.value.getTemplate(currentSelected.id)
|
||||
if (updatedTemplate) {
|
||||
emit('select', updatedTemplate, getCurrentTemplateType());
|
||||
}
|
||||
} catch (error) {
|
||||
// 错误处理逻辑...
|
||||
}
|
||||
}
|
||||
|
||||
// 🔑 关键修复:发出语言变化事件,通知父组件
|
||||
emit('languageChanged', newLanguage)
|
||||
}
|
||||
```
|
||||
|
||||
**事件定义:**
|
||||
```javascript
|
||||
const emit = defineEmits(['close', 'select', 'update:show', 'languageChanged'])
|
||||
```
|
||||
|
||||
### 2. App.vue处理事件并传播
|
||||
|
||||
**监听语言变化事件:**
|
||||
```vue
|
||||
<TemplateManagerUI
|
||||
v-if="isReady"
|
||||
v-model:show="templateManagerState.showTemplates"
|
||||
:templateType="templateManagerState.currentType"
|
||||
@close="() => templateManagerState.handleTemplateManagerClose(() => templateSelectRef?.refresh?.())"
|
||||
@languageChanged="handleTemplateLanguageChanged"
|
||||
/>
|
||||
```
|
||||
|
||||
**处理语言变化:**
|
||||
```javascript
|
||||
// 处理模板语言变化
|
||||
const handleTemplateLanguageChanged = (newLanguage: string) => {
|
||||
console.log('[App] 模板语言已切换:', newLanguage)
|
||||
|
||||
// 刷新主界面的模板选择组件
|
||||
if (templateSelectRef.value?.refresh) {
|
||||
templateSelectRef.value.refresh()
|
||||
}
|
||||
|
||||
// 🔑 关键修复:刷新迭代页面的模板选择组件
|
||||
if (promptPanelRef.value?.refreshIterateTemplateSelect) {
|
||||
promptPanelRef.value.refreshIterateTemplateSelect()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**添加组件引用:**
|
||||
```javascript
|
||||
const templateSelectRef = ref<{ refresh?: () => void } | null>(null)
|
||||
const promptPanelRef = ref<{ refreshIterateTemplateSelect?: () => void } | null>(null)
|
||||
```
|
||||
|
||||
### 3. PromptPanel暴露刷新方法
|
||||
|
||||
**添加迭代模板选择组件引用:**
|
||||
```vue
|
||||
<TemplateSelect
|
||||
ref="iterateTemplateSelectRef"
|
||||
:modelValue="selectedIterateTemplate"
|
||||
@update:modelValue="$emit('update:selectedIterateTemplate', $event)"
|
||||
:type="templateType"
|
||||
:optimization-mode="optimizationMode"
|
||||
:services="services"
|
||||
@manage="$emit('openTemplateManager', templateType)"
|
||||
/>
|
||||
```
|
||||
|
||||
**暴露刷新方法:**
|
||||
```javascript
|
||||
const iterateTemplateSelectRef = ref<{ refresh?: () => void } | null>(null);
|
||||
|
||||
// 暴露刷新迭代模板选择的方法
|
||||
const refreshIterateTemplateSelect = () => {
|
||||
if (iterateTemplateSelectRef.value?.refresh) {
|
||||
iterateTemplateSelectRef.value.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
refreshIterateTemplateSelect
|
||||
})
|
||||
```
|
||||
|
||||
## ✅ 修复验证
|
||||
|
||||
### 测试步骤
|
||||
1. 打开应用,确认主界面显示中文模板
|
||||
2. 点击"功能提示词"打开模板管理界面
|
||||
3. 点击"中文"按钮切换到"English"
|
||||
4. 确认主界面优化提示词下拉框更新为英文
|
||||
5. 输入测试内容并执行优化
|
||||
6. 点击"继续优化"打开迭代页面
|
||||
7. **关键验证**:确认迭代页面的模板选择正确显示英文模板
|
||||
|
||||
### 验证结果
|
||||
- [x] 语言切换事件正确传播到所有TemplateSelect组件
|
||||
- [x] 迭代页面的下拉列表正确更新为新语言
|
||||
- [x] 用户可以在迭代页面直接使用正确语言的模板
|
||||
- [x] 主界面和迭代页面行为一致
|
||||
- [x] 无需用户手动重新选择模板
|
||||
|
||||
## 💡 经验总结
|
||||
|
||||
### 架构设计原则
|
||||
1. **事件传播完整性**:确保状态变化事件能传播到所有相关组件
|
||||
2. **组件层级意识**:深层组件需要额外的事件传播机制
|
||||
3. **统一响应机制**:相同功能的组件应该有相同的响应机制
|
||||
4. **接口一致性**:所有相关组件都应该暴露统一的刷新接口
|
||||
|
||||
### 最佳实践
|
||||
1. **建立完整的事件链**:从事件源到所有消费者的完整路径
|
||||
2. **使用ref和defineExpose**:为深层组件提供外部访问接口
|
||||
3. **统一刷新机制**:所有TemplateSelect组件都有refresh方法
|
||||
4. **日志记录**:添加适当的日志帮助调试事件传播
|
||||
|
||||
### 避免的陷阱
|
||||
1. **假设事件会自动传播**:Vue的事件系统不会自动向下传播
|
||||
2. **忽略组件层级差异**:不同层级的组件需要不同的处理方式
|
||||
3. **不完整的修复**:只修复部分组件而忽略其他相关组件
|
||||
4. **缺乏验证**:没有完整测试所有相关功能
|
||||
|
||||
### 适用场景
|
||||
这个修复模式适用于:
|
||||
- 全局状态变化需要通知多个层级的组件
|
||||
- 组件层级复杂的应用架构
|
||||
- 需要统一响应机制的功能模块
|
||||
- 事件传播路径不一致的问题
|
||||
|
||||
## 🔗 相关文档
|
||||
- `112-desktop-ipc-fixes/language-switch-fix.md` - 语言切换按钮修复
|
||||
- `106-template-management/troubleshooting.md` - 模板管理故障排除清单
|
||||
|
||||
## 📅 修复记录
|
||||
- **发现时间**:2025-01-07
|
||||
- **修复时间**:2025-01-07
|
||||
- **影响范围**:Web和Extension环境
|
||||
- **修复类型**:事件传播机制完善
|
||||
- **重要程度**:高(影响用户体验的核心功能)
|
||||
@@ -180,7 +180,87 @@
|
||||
- [ ] 测试UI组件与服务层的交互
|
||||
- [ ] 测试Electron环境下的IPC通信
|
||||
|
||||
### 9. 监控和调试
|
||||
### 9. 内置模板语言切换后迭代页面模板选择不更新
|
||||
|
||||
**症状:**
|
||||
- 在模板管理界面切换内置模板语言后,主界面的优化提示词下拉框正确更新
|
||||
- 但执行优化后点击"继续优化",迭代页面的模板选择显示旧语言的模板名称
|
||||
- 下拉列表已更新为新语言,但当前选中项还是旧语言
|
||||
- 实际发送请求时生效的是新语言(因为通过templateId重新获取)
|
||||
|
||||
**根本原因:**
|
||||
- **事件传播路径不同**:主界面和迭代页面的TemplateSelect组件在不同的层级
|
||||
- **组件层级差异**:
|
||||
- 主界面:`App.vue → TemplateSelectUI`(直接引用)
|
||||
- 迭代页面:`App.vue → PromptPanelUI → TemplateSelect`(间接引用)
|
||||
- **刷新机制缺失**:语言切换事件无法传播到深层的TemplateSelect组件
|
||||
|
||||
**详细分析:**
|
||||
1. **主界面正常的原因**:
|
||||
- 在TemplateManager关闭时会自动调用 `templateSelectRef?.refresh?.()`
|
||||
- 组件层级简单,事件传播路径短
|
||||
- 有直接的引用和刷新机制
|
||||
|
||||
2. **迭代页面异常的原因**:
|
||||
- 迭代页面的TemplateSelect没有被包含在语言切换的刷新逻辑中
|
||||
- 组件层级更深,需要额外的事件传播机制
|
||||
- 之前没有建立完整的事件传播链
|
||||
|
||||
**解决方案:**
|
||||
1. **建立事件传播链**:
|
||||
```javascript
|
||||
// TemplateManager.vue - 发出语言变化事件
|
||||
const handleLanguageChanged = async (newLanguage: string) => {
|
||||
// ... 现有逻辑 ...
|
||||
|
||||
// 发出语言变化事件,通知父组件
|
||||
emit('languageChanged', newLanguage)
|
||||
}
|
||||
```
|
||||
|
||||
2. **App.vue处理事件并传播**:
|
||||
```javascript
|
||||
// 处理模板语言变化
|
||||
const handleTemplateLanguageChanged = (newLanguage: string) => {
|
||||
// 刷新主界面的模板选择组件
|
||||
if (templateSelectRef.value?.refresh) {
|
||||
templateSelectRef.value.refresh()
|
||||
}
|
||||
|
||||
// 刷新迭代页面的模板选择组件
|
||||
if (promptPanelRef.value?.refreshIterateTemplateSelect) {
|
||||
promptPanelRef.value.refreshIterateTemplateSelect()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **PromptPanel暴露刷新方法**:
|
||||
```javascript
|
||||
// PromptPanel.vue - 暴露刷新迭代模板的方法
|
||||
const refreshIterateTemplateSelect = () => {
|
||||
if (iterateTemplateSelectRef.value?.refresh) {
|
||||
iterateTemplateSelectRef.value.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
refreshIterateTemplateSelect
|
||||
})
|
||||
```
|
||||
|
||||
**修复验证:**
|
||||
- [x] 语言切换事件正确传播到所有TemplateSelect组件
|
||||
- [x] 迭代页面的下拉列表正确更新为新语言
|
||||
- [x] 用户可以在迭代页面选择正确语言的模板
|
||||
- [x] 主界面和迭代页面行为一致
|
||||
|
||||
**经验总结:**
|
||||
1. **组件层级影响事件传播**:深层组件需要额外的事件传播机制
|
||||
2. **统一刷新机制**:所有相关组件都应该有统一的刷新接口
|
||||
3. **完整的事件链**:确保事件能够传播到所有需要响应的组件
|
||||
4. **架构一致性**:相同功能的组件应该有相同的响应机制
|
||||
|
||||
### 10. 监控和调试
|
||||
|
||||
**日志记录:**
|
||||
- [ ] 记录模板操作的开始和结束
|
||||
|
||||
@@ -84,10 +84,15 @@ ipcMain.handle('template-getCurrentBuiltinTemplateLanguage', async (event) => {
|
||||
1. **接口一致性**: 跨环境的接口必须保持一致的异步性
|
||||
2. **错误处理**: 让错误自然传播,便于问题定位
|
||||
3. **类型安全**: 使用TypeScript确保接口实现的完整性
|
||||
4. **事件传播**: 确保语言切换事件能传播到所有相关组件
|
||||
|
||||
### 最佳实践
|
||||
1. **统一异步**: 所有跨环境接口都应该是异步的
|
||||
2. **接口驱动**: 先定义接口,再实现具体类
|
||||
3. **完整测试**: 在两种环境下都要验证功能
|
||||
4. **事件链完整性**: 建立完整的事件传播机制,确保深层组件也能响应状态变化
|
||||
|
||||
### 相关问题
|
||||
- **迭代页面模板选择不更新**: 语言切换后,由于组件层级差异和事件传播机制缺失,迭代页面的模板选择无法正确更新。解决方案是建立完整的事件传播链,确保所有TemplateSelect组件都能响应语言切换事件。详见 `106-template-management/troubleshooting.md` 第9节。
|
||||
|
||||
这个修复建立了完整的异步接口设计模式,为后续的IPC开发提供了标准。
|
||||
@@ -84,6 +84,87 @@ defineOptions({
|
||||
</script>
|
||||
```
|
||||
|
||||
#### 深层组件事件传播机制
|
||||
**问题**:当全局状态变化需要通知多层级嵌套的组件时,事件传播可能中断,导致深层组件无法及时更新。
|
||||
|
||||
**典型场景**:
|
||||
- 语言切换后,主界面组件更新正常,但Modal内部的组件显示旧状态
|
||||
- 组件层级差异:`App.vue → ComponentA`(直接引用)vs `App.vue → ComponentB → ComponentC`(间接引用)
|
||||
|
||||
**核心原因**:
|
||||
1. **v-if条件渲染**:组件被销毁后ref失效,无法调用组件方法
|
||||
2. **事件传播断点**:事件只传播到直接子组件,不会自动向下传播到深层组件
|
||||
3. **组件生命周期差异**:不同层级的组件可能处于不同的生命周期阶段
|
||||
|
||||
**解决方案**:
|
||||
1. **使用v-show替代v-if**:确保组件实例始终存在,ref保持有效
|
||||
```vue
|
||||
<!-- ❌ 问题方案:组件会被销毁 -->
|
||||
<Modal v-if="showModal">
|
||||
<TemplateSelect ref="templateRef" />
|
||||
</Modal>
|
||||
|
||||
<!-- ✅ 推荐方案:组件始终渲染 -->
|
||||
<Modal v-show="showModal">
|
||||
<TemplateSelect ref="templateRef" />
|
||||
</Modal>
|
||||
```
|
||||
|
||||
2. **建立完整事件传播链**:从事件源到所有消费组件
|
||||
```javascript
|
||||
// 父组件:建立事件传播
|
||||
const handleGlobalStateChange = (newState) => {
|
||||
// 刷新直接子组件
|
||||
if (directChildRef.value?.refresh) {
|
||||
directChildRef.value.refresh()
|
||||
}
|
||||
|
||||
// 刷新深层组件(通过中间组件的暴露方法)
|
||||
if (intermediateRef.value?.refreshDeepChild) {
|
||||
intermediateRef.value.refreshDeepChild()
|
||||
}
|
||||
}
|
||||
|
||||
// 中间组件:暴露深层组件的刷新方法
|
||||
const deepChildRef = ref()
|
||||
|
||||
const refreshDeepChild = () => {
|
||||
if (deepChildRef.value?.refresh) {
|
||||
deepChildRef.value.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
refreshDeepChild
|
||||
})
|
||||
```
|
||||
|
||||
3. **统一刷新接口**:所有相关组件都暴露相同的刷新方法
|
||||
```javascript
|
||||
// 每个需要响应全局状态变化的组件都实现refresh方法
|
||||
const refresh = () => {
|
||||
// 重新加载数据或更新状态
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
refresh
|
||||
})
|
||||
```
|
||||
|
||||
**最佳实践**:
|
||||
- **架构设计**:在设计阶段考虑事件传播的完整路径
|
||||
- **接口一致性**:定义标准的组件刷新接口(如`refresh()`方法)
|
||||
- **文档记录**:为复杂的事件传播链建立清晰的架构图
|
||||
- **测试验证**:确保在所有使用场景下事件都能正确传播
|
||||
|
||||
**适用场景**:
|
||||
- 全局主题切换
|
||||
- 语言切换
|
||||
- 用户权限变更
|
||||
- 模板/配置更新
|
||||
|
||||
> **详细案例**:参见 [106-template-management/event-propagation-fix.md](../archives/106-template-management/event-propagation-fix.md)
|
||||
|
||||
## ⚡ 快速问题排查
|
||||
|
||||
### 布局问题
|
||||
@@ -96,6 +177,22 @@ defineOptions({
|
||||
2. 确认高度约束是否从顶层正确传递
|
||||
3. 验证滚动容器是否有正确的 `overflow-y: auto`
|
||||
|
||||
### 组件状态同步问题
|
||||
1. **深层组件未更新**:
|
||||
- 检查是否使用了 `v-if` 导致组件被销毁
|
||||
- 确认事件传播链是否完整(父→中间→目标组件)
|
||||
- 验证目标组件是否暴露了刷新方法
|
||||
|
||||
2. **Modal内组件状态异常**:
|
||||
- 检查Modal是否使用 `v-show` 而非 `v-if`
|
||||
- 确认组件ref在Modal关闭时是否仍然有效
|
||||
- 验证全局状态变化事件是否传播到Modal内部
|
||||
|
||||
3. **组件ref调用失败**:
|
||||
- 确认组件是否已完成挂载(`nextTick`)
|
||||
- 检查条件渲染是否导致组件不存在
|
||||
- 验证ref绑定的组件是否暴露了对应方法
|
||||
|
||||
### API调用问题
|
||||
1. 检查环境变量是否正确设置(`VITE_` 前缀)
|
||||
2. 确认参数是否过度设置默认值
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<div class="flex-1 min-h-0">
|
||||
<template v-if="services && services.templateManager">
|
||||
<PromptPanelUI
|
||||
ref="promptPanelRef"
|
||||
v-model:optimized-prompt="optimizer.optimizedPrompt"
|
||||
:reasoning="optimizer.optimizedReasoning"
|
||||
:original-prompt="optimizer.prompt"
|
||||
@@ -139,6 +140,7 @@
|
||||
v-model:show="templateManagerState.showTemplates"
|
||||
:templateType="templateManagerState.currentType"
|
||||
@close="() => templateManagerState.handleTemplateManagerClose(() => templateSelectRef?.refresh?.())"
|
||||
@languageChanged="handleTemplateLanguageChanged"
|
||||
/>
|
||||
<HistoryDrawerUI
|
||||
v-if="isReady"
|
||||
@@ -218,6 +220,7 @@ const showDataManager = ref(false)
|
||||
const optimizeModelSelect = ref(null)
|
||||
const testPanelRef = ref(null)
|
||||
const templateSelectRef = ref<{ refresh?: () => void } | null>(null)
|
||||
const promptPanelRef = ref<{ refreshIterateTemplateSelect?: () => void } | null>(null)
|
||||
|
||||
const templateSelectType = computed<'optimize' | 'userOptimize' | 'iterate'>(() => {
|
||||
return selectedOptimizationMode.value === 'system' ? 'optimize' : 'userOptimize';
|
||||
@@ -340,6 +343,21 @@ const handleOptimizationModeChange = (mode: OptimizationMode) => {
|
||||
selectedOptimizationMode.value = mode
|
||||
}
|
||||
|
||||
// 处理模板语言变化
|
||||
const handleTemplateLanguageChanged = (newLanguage: string) => {
|
||||
console.log('[App] 模板语言已切换:', newLanguage)
|
||||
|
||||
// 刷新主界面的模板选择组件
|
||||
if (templateSelectRef.value?.refresh) {
|
||||
templateSelectRef.value.refresh()
|
||||
}
|
||||
|
||||
// 刷新迭代页面的模板选择组件
|
||||
if (promptPanelRef.value?.refreshIterateTemplateSelect) {
|
||||
promptPanelRef.value.refreshIterateTemplateSelect()
|
||||
}
|
||||
}
|
||||
|
||||
// 处理历史记录使用 - 智能模式切换
|
||||
const handleHistoryReuse = async (context: { record: any, chainId: string, rootPrompt: string, chain: any }) => {
|
||||
const { chain } = context
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<div v-if="modelValue" class="fixed inset-0 z-30 overflow-y-auto" @click="handleBackdropClick">
|
||||
<div v-show="modelValue" class="fixed inset-0 z-30 overflow-y-auto" @click="handleBackdropClick">
|
||||
<div class="flex min-h-full items-center justify-center p-4">
|
||||
<!-- 背景遮罩 -->
|
||||
<div class="fixed inset-0 theme-mask"></div>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
<div>
|
||||
<h4 class="theme-label mb-2">{{ templateSelectText }}</h4>
|
||||
<TemplateSelect
|
||||
ref="iterateTemplateSelectRef"
|
||||
:modelValue="selectedIterateTemplate"
|
||||
@update:modelValue="$emit('update:selectedIterateTemplate', $event)"
|
||||
:type="templateType"
|
||||
@@ -185,6 +186,7 @@ const iterateInput = ref('')
|
||||
const templateType = ref<'optimize' | 'iterate'>('iterate')
|
||||
|
||||
const outputDisplayRef = ref<InstanceType<typeof OutputDisplay> | null>(null);
|
||||
const iterateTemplateSelectRef = ref<{ refresh?: () => void } | null>(null);
|
||||
|
||||
// 计算标题文本
|
||||
const templateTitleText = computed(() => {
|
||||
@@ -279,6 +281,17 @@ watch([() => props.isOptimizing, () => props.isIterating], ([newOptimizing, newI
|
||||
}
|
||||
}, { immediate: false })
|
||||
|
||||
// 暴露刷新迭代模板选择的方法
|
||||
const refreshIterateTemplateSelect = () => {
|
||||
if (iterateTemplateSelectRef.value?.refresh) {
|
||||
iterateTemplateSelectRef.value.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
refreshIterateTemplateSelect
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -671,7 +671,7 @@ const props = defineProps<{
|
||||
show: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['close', 'select', 'update:show'])
|
||||
const emit = defineEmits(['close', 'select', 'update:show', 'languageChanged'])
|
||||
const toast = useToast()
|
||||
|
||||
const templates = ref<Template[]>([])
|
||||
@@ -1225,6 +1225,9 @@ const syntaxGuideMarkdown = computed(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 发出语言变化事件,通知父组件
|
||||
emit('languageChanged', newLanguage)
|
||||
}
|
||||
|
||||
// 监听 props.templateType 变化,更新当前分类
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<div class="flex-1 min-h-0">
|
||||
<template v-if="services && services.templateManager">
|
||||
<PromptPanelUI
|
||||
ref="promptPanelRef"
|
||||
v-model:optimized-prompt="optimizer.optimizedPrompt"
|
||||
:reasoning="optimizer.optimizedReasoning"
|
||||
:original-prompt="optimizer.prompt"
|
||||
@@ -134,11 +135,12 @@
|
||||
|
||||
<!-- Modals and Drawers that are conditionally rendered -->
|
||||
<ModelManagerUI v-if="isReady" v-model:show="modelManager.showConfig" />
|
||||
<TemplateManagerUI
|
||||
v-if="isReady"
|
||||
v-model:show="templateManagerState.showTemplates"
|
||||
:templateType="templateManagerState.currentType"
|
||||
<TemplateManagerUI
|
||||
v-if="isReady"
|
||||
v-model:show="templateManagerState.showTemplates"
|
||||
:templateType="templateManagerState.currentType"
|
||||
@close="() => templateManagerState.handleTemplateManagerClose(() => templateSelectRef?.refresh?.())"
|
||||
@languageChanged="handleTemplateLanguageChanged"
|
||||
/>
|
||||
<HistoryDrawerUI
|
||||
v-if="isReady"
|
||||
@@ -218,6 +220,7 @@ const showDataManager = ref(false)
|
||||
const optimizeModelSelect = ref(null)
|
||||
const testPanelRef = ref(null)
|
||||
const templateSelectRef = ref<{ refresh?: () => void } | null>(null)
|
||||
const promptPanelRef = ref<{ refreshIterateTemplateSelect?: () => void } | null>(null)
|
||||
|
||||
const templateSelectType = computed<'optimize' | 'userOptimize' | 'iterate'>(() => {
|
||||
return selectedOptimizationMode.value === 'system' ? 'optimize' : 'userOptimize';
|
||||
@@ -340,6 +343,21 @@ const handleOptimizationModeChange = (mode: OptimizationMode) => {
|
||||
selectedOptimizationMode.value = mode
|
||||
}
|
||||
|
||||
// 处理模板语言变化
|
||||
const handleTemplateLanguageChanged = (newLanguage: string) => {
|
||||
console.log('[App] 模板语言已切换:', newLanguage)
|
||||
|
||||
// 刷新主界面的模板选择组件
|
||||
if (templateSelectRef.value?.refresh) {
|
||||
templateSelectRef.value.refresh()
|
||||
}
|
||||
|
||||
// 刷新迭代页面的模板选择组件
|
||||
if (promptPanelRef.value?.refreshIterateTemplateSelect) {
|
||||
promptPanelRef.value.refreshIterateTemplateSelect()
|
||||
}
|
||||
}
|
||||
|
||||
// 处理历史记录使用 - 智能模式切换
|
||||
const handleHistoryReuse = async (context: { record: any, chainId: string, rootPrompt: string, chain: any }) => {
|
||||
const { chain } = context
|
||||
|
||||
Reference in new issue
Block a user