Skip to content

Commit 3bc03c3

Browse files
committed
refactor(ui): 将导入导出功能抽离为独立组件
- 新增 ImportExportDialog 组件,专门处理导入导出功能 - 重构 ContextEditor,移除内联的导入导出对话框代码 - 支持 4 种导入格式 (smart/openai/langfuse/conversation) - 支持 2 种导出格式 (standard/openai) - 更新相关单元测试和 E2E 测试 - 同步更新三语言国际化文件 优化: - 代码量减少约 586 行 (24%) - 组件职责更清晰,符合单一职责原则 - 提高代码可维护性和复用性
1 parent dee32ae commit 3bc03c3

File tree

8 files changed

+935
-714
lines changed

8 files changed

+935
-714
lines changed

packages/ui/src/components/context-mode/ContextEditor.vue

Lines changed: 37 additions & 530 deletions
Large diffs are not rendered by default.

packages/ui/src/components/context-mode/ImportExportDialog.vue

Lines changed: 613 additions & 0 deletions
Large diffs are not rendered by default.

packages/ui/src/i18n/locales/en-US.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,22 +1654,21 @@ export default {
16541654
// Import/Export formats
16551655
importFormats: {
16561656
smart: { name: "Smart Detection", description: "Auto-detect format and convert" },
1657-
conversation: { name: "Conversation", description: "Standard conversation message format" },
16581657
openai: { name: "OpenAI", description: "OpenAI API request format" },
16591658
langfuse: { name: "LangFuse", description: "LangFuse tracking data format" },
1659+
conversation: { name: "Internal Format", description: "Prompt Optimizer internal JSON structure" },
16601660
},
16611661
exportFormats: {
1662-
standard: { name: "Standard", description: "Internal standard data format" },
1662+
standard: { name: "Internal Format", description: "Prompt Optimizer internal standard format" },
16631663
openai: { name: "OpenAI", description: "OpenAI API compatible format" },
1664-
template: { name: "Template", description: "Reusable template format" },
16651664
},
16661665

1667-
// Import placeholders
1666+
// Import placeholders (localized text, JSON snippet fixed in component)
16681667
importPlaceholders: {
1669-
openai: 'OpenAI API request format, e.g.:\n{\n "messages": [...],\n "model": "gpt-4"\n}',
1670-
langfuse: 'LangFuse tracking data, e.g.:\n{\n "input": {\n "messages": [...]\n }\n}',
1671-
conversation: 'Standard conversation format, e.g.:\n{\n "messages": [\n {"role": "system", "content": "..."},\n {"role": "user", "content": "..."}\n ]\n}',
1672-
smart: "Paste any supported JSON format, system will auto-detect",
1668+
openai: "OpenAI API request format (example below):",
1669+
langfuse: "LangFuse trace payload (example below):",
1670+
conversation: "Standard conversation JSON (example below):",
1671+
smart: "Paste any supported JSON format (OpenAI, LangFuse, or conversation array). The editor will auto-detect the format.",
16731672
},
16741673

16751674
// Console errors (developer logs)

packages/ui/src/i18n/locales/zh-CN.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,22 +1595,21 @@ export default {
15951595
// Import/Export formats
15961596
importFormats: {
15971597
smart: { name: "智能识别", description: "自动检测格式并转换" },
1598-
conversation: { name: "会话格式", description: "标准的会话消息格式" },
15991598
openai: { name: "OpenAI", description: "OpenAI API 请求格式" },
16001599
langfuse: { name: "LangFuse", description: "LangFuse 追踪数据格式" },
1600+
conversation: { name: "内部格式", description: "Prompt Optimizer 内部标准 JSON 结构" },
16011601
},
16021602
exportFormats: {
1603-
standard: { name: "标准格式", description: "内部标准数据格式" },
1603+
standard: { name: "内部格式", description: "Prompt Optimizer 内部标准数据格式" },
16041604
openai: { name: "OpenAI", description: "OpenAI API 兼容格式" },
1605-
template: { name: "模板格式", description: "可复用的模板格式" },
16061605
},
16071606

1608-
// Import placeholders
1607+
// Import placeholders (文本可本地化,JSON 示例固定为英文)
16091608
importPlaceholders: {
1610-
openai: 'OpenAI API 请求格式,例如:\n{\n "messages": [...],\n "model": "gpt-4"\n}',
1611-
langfuse: 'LangFuse 追踪数据,例如:\n{\n "input": {\n "messages": [...]\n }\n}',
1612-
conversation: '标准会话格式,例如:\n{\n "messages": [\n {"role": "system", "content": "..."},\n {"role": "user", "content": "..."}\n ]\n}',
1613-
smart: "粘贴任意支持格式的 JSON 数据,系统将自动识别",
1609+
openai: "OpenAI API 请求格式(示例见下方):",
1610+
langfuse: "LangFuse 追踪数据格式(示例见下方):",
1611+
conversation: "标准会话 JSON 格式(示例见下方):",
1612+
smart: "粘贴任意受支持的 JSON(OpenAI、LangFuse 或会话数组),系统会自动识别格式。",
16141613
},
16151614

16161615
// Console errors (开发者日志)

packages/ui/src/i18n/locales/zh-TW.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,22 +1559,21 @@ export default {
15591559
// Import/Export formats
15601560
importFormats: {
15611561
smart: { name: "智慧識別", description: "自動偵測格式並轉換" },
1562-
conversation: { name: "會話格式", description: "標準的會話訊息格式" },
15631562
openai: { name: "OpenAI", description: "OpenAI API 請求格式" },
15641563
langfuse: { name: "LangFuse", description: "LangFuse 追蹤資料格式" },
1564+
conversation: { name: "內部格式", description: "Prompt Optimizer 內部標準 JSON 結構" },
15651565
},
15661566
exportFormats: {
1567-
standard: { name: "標準格式", description: "內部標準資料格式" },
1567+
standard: { name: "內部格式", description: "Prompt Optimizer 內部標準資料格式" },
15681568
openai: { name: "OpenAI", description: "OpenAI API 相容格式" },
1569-
template: { name: "範本格式", description: "可複用的範本格式" },
15701569
},
15711570

1572-
// Import placeholders
1571+
// Import placeholders (文字本地化,JSON 範例固定英文)
15731572
importPlaceholders: {
1574-
openai: 'OpenAI API 請求格式,例如:\n{\n "messages": [...],\n "model": "gpt-4"\n}',
1575-
langfuse: 'LangFuse 追蹤資料,例如:\n{\n "input": {\n "messages": [...]\n }\n}',
1576-
conversation: '標準會話格式,例如:\n{\n "messages": [\n {"role": "system", "content": "..."},\n {"role": "user", "content": "..."}\n ]\n}',
1577-
smart: "貼上任意支援格式的 JSON 資料,系統將自動識別",
1573+
openai: "OpenAI API 請求格式(下方示例):",
1574+
langfuse: "LangFuse 追蹤資料格式(下方示例):",
1575+
conversation: "標準會話 JSON 格式(下方示例):",
1576+
smart: "貼上任意支援的 JSON(OpenAI、LangFuse 或會話陣列),系統會自動辨識格式。",
15781577
},
15791578

15801579
// Console errors (開發者日誌)

packages/ui/tests/e2e/context-editor-refactor.spec.ts

Lines changed: 63 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { nextTick } from 'vue'
55
// 组件导入
66
import ConversationManager from '../../src/components/context-mode/ConversationManager.vue'
77
import ContextEditor from '../../src/components/context-mode/ContextEditor.vue'
8+
import ImportExportDialog from '../../src/components/context-mode/ImportExportDialog.vue'
89
import VariableManagerModal from '../../src/components/variable/VariableManagerModal.vue'
910

1011
// Mock Naive UI 组件 - 简化版本用于E2E测试
@@ -214,17 +215,31 @@ vi.mock('../../src/composables/useAccessibility', () => ({
214215
})
215216
}))
216217

217-
vi.mock('../../src/composables/useContextEditor', () => ({
218+
const mockConverter = {
219+
toOpenAI: vi.fn().mockImplementation((data) => ({
220+
success: true,
221+
data: {
222+
model: data.model || 'gpt-test',
223+
messages: data.messages,
224+
tools: data.tools
225+
}
226+
}))
227+
}
228+
229+
vi.mock('../../src/composables/context/useContextEditor', () => ({
218230
useContextEditor: () => ({
219231
currentData: { value: null },
220232
isLoading: { value: false },
221233
smartImport: vi.fn(),
222234
convertFromOpenAI: vi.fn(),
223235
convertFromLangFuse: vi.fn(),
224236
importFromFile: vi.fn(),
225-
exportToFile: vi.fn().mockResolvedValue(true),
237+
exportToFile: vi.fn().mockReturnValue(true),
226238
exportToClipboard: vi.fn().mockResolvedValue(true),
227-
setData: vi.fn()
239+
setData: vi.fn(),
240+
services: {
241+
converter: mockConverter
242+
}
228243
})
229244
}))
230245

@@ -509,21 +524,12 @@ describe('完整用户流程E2E测试', () => {
509524

510525
describe('3. 导入导出和格式转换功能', () => {
511526
it('应该支持多种格式的导入功能', async () => {
512-
contextEditorWrapper = mount(ContextEditor, {
527+
const dialogWrapper = mount(ImportExportDialog, {
513528
props: {
514529
visible: true,
515-
state: {
516-
messages: [],
517-
variables: {},
518-
tools: [],
519-
showVariablePreview: true,
520-
showToolManager: false,
521-
mode: 'edit'
522-
},
523-
scanVariables,
524-
replaceVariables,
525-
isPredefinedVariable: () => false,
526-
variableManager: createMockVariableManager()
530+
mode: 'import',
531+
messages: [],
532+
tools: []
527533
},
528534
global: {
529535
stubs: {},
@@ -535,40 +541,48 @@ describe('完整用户流程E2E测试', () => {
535541

536542
await nextTick()
537543

538-
// 验证导入功能存在
539-
expect(contextEditorWrapper.vm.handleImport).toBeDefined()
540-
expect(contextEditorWrapper.vm.handleImportSubmit).toBeDefined()
541-
542-
// 验证支持的导入格式
543-
const importFormats = contextEditorWrapper.vm.importFormats
544-
expect(importFormats).toEqual([
545-
{ id: 'smart', name: '智能识别', description: '自动检测格式并转换' },
546-
{ id: 'conversation', name: '会话格式', description: '标准的会话消息格式' },
547-
{ id: 'openai', name: 'OpenAI', description: 'OpenAI API 请求格式' },
548-
{ id: 'langfuse', name: 'LangFuse', description: 'LangFuse 追踪数据格式' }
549-
])
550-
551-
// 测试对话格式导入
552-
const conversationData = {
544+
const formats = dialogWrapper.vm.importFormats
545+
expect(formats.map(f => f.id)).toEqual(['smart', 'openai', 'langfuse', 'conversation'])
546+
547+
dialogWrapper.vm.importData = JSON.stringify({
553548
messages: [
554-
{ role: 'system', content: '测试系统消息' },
555-
{ role: 'user', content: '测试用户消息' }
549+
{ role: 'system', content: '系统消息' },
550+
{ role: 'user', content: '用户消息' }
556551
],
557-
variables: { testVar: 'testValue' }
558-
}
552+
tools: []
553+
})
554+
dialogWrapper.vm.selectedImportFormat = 'conversation'
559555

560-
// 设置导入数据
561-
contextEditorWrapper.vm.importData = JSON.stringify(conversationData)
562-
contextEditorWrapper.vm.selectedImportFormat = 'conversation'
563-
564-
// 执行导入
565-
await contextEditorWrapper.vm.handleImportSubmit()
566-
await nextTick()
556+
await dialogWrapper.vm.handleImportSubmit()
567557

568-
// 验证导入结果
569-
expect(contextEditorWrapper.emitted('update:state')).toBeTruthy()
558+
expect(dialogWrapper.emitted('import-success')).toBeTruthy()
570559
})
571560

561+
it('应该支持多种格式的导出功能', async () => {
562+
const dialogWrapper = mount(ImportExportDialog, {
563+
props: {
564+
visible: true,
565+
mode: 'export',
566+
messages: [{ role: 'user', content: '测试消息' }],
567+
tools: []
568+
},
569+
global: {
570+
stubs: {},
571+
mocks: {
572+
announcements: []
573+
}
574+
}
575+
})
576+
577+
await nextTick()
578+
579+
const formats = dialogWrapper.vm.exportFormats
580+
expect(formats.map(f => f.id)).toEqual(['standard', 'openai'])
581+
582+
await dialogWrapper.vm.handleExportToFile()
583+
584+
expect(dialogWrapper.emitted('export-success')).toBeTruthy()
585+
})
572586
})
573587

574588
describe('4. 变量管理的跨组件协作', () => {
@@ -887,10 +901,11 @@ describe('完整用户流程E2E测试', () => {
887901
// 验证最终状态(简化验证)
888902
expect(contextEditorWrapper.exists()).toBe(true)
889903
expect(contextEditorWrapper.vm).toBeTruthy()
890-
891-
// 验证导出功能可用
892-
expect(contextEditorWrapper.vm.handleExportToClipboard).toBeDefined()
893-
expect(contextEditorWrapper.vm.handleExportToFile).toBeDefined()
904+
905+
// 注意:导出功能已移至 ImportExportDialog 组件
906+
// 验证导入导出对话框可以打开
907+
expect(contextEditorWrapper.vm.handleImport).toBeDefined()
908+
expect(contextEditorWrapper.vm.handleExport).toBeDefined()
894909
})
895910

896911
it('应该正确处理错误和边界情况', async () => {

0 commit comments

Comments
 (0)