refactor(ui): 优化高级模式测试区域布局结构,统一图像模式和基础模式测试面板布局

- **统一布局结构**:图像模式、基础模式和高级模式测试面板布局保持一致,提升用户体验。
  - 使用 `NCard` 包裹测试控制栏和输入区域,使左右两侧卡片结构对称。
  - 使用 `NFlex gap` 替换 `marginBottom` 实现统一间距管理。
  - 移除冗余的 `div` 包装层、`NFlex` 和 `NCard` 层级,节省垂直空间。
- **简化UI**:
  - 移除冗余的"测试区域"标题卡片。
  - 将"全局变量"按钮整合到临时变量卡片的 header 区域。
- **代码优化**:
  - 移除测试运行时隐藏变量表单的逻辑,保持始终可见。
  - 清理未使用的 `useBreakpoints` / `isMobile` 和 `showVariableForm`。
This commit is contained in:
linshen committed 2025-12-19 11:29:26 +08:00
1 parent 53126588d2
commit 2e20b0cd2b
7 files changed
+540 -635

No files matched your search

+6 -9
View File
@@ -1,7 +1,7 @@
<template>
<NFlex vertical :style="{ height: '100%' }">
<NFlex vertical :style="{ height: '100%', gap: '12px' }">
<!-- 测试输入区域 (仅在系统提示词优化模式下显示) -->
<div v-if="showTestInput" :style="{ flexShrink: 0 }">
<NCard v-if="showTestInput" :style="{ flexShrink: 0 }" size="small">
<TestInputSection
v-model="testContentProxy"
:label="t('test.content')"
@@ -11,14 +11,11 @@
:mode="adaptiveInputMode"
:size="inputSize"
:enable-fullscreen="enableFullscreen"
:style="{ marginBottom: '16px' }"
/>
</div>
</NCard>
<!-- 控制工具栏 -->
<div :style="{ flexShrink: 0 }">
<NCard :style="{ flexShrink: 0 }" size="small">
<TestControlBar
:model-label="t('test.model')"
:show-compare-toggle="enableCompareMode"
@@ -30,7 +27,6 @@
:button-size="adaptiveButtonSize"
@compare-toggle="handleCompareToggle"
@primary-action="handleTest"
:style="{ marginBottom: '16px' }"
>
<template #model-select>
<slot name="model-select"></slot>
@@ -42,7 +38,7 @@
<slot name="custom-actions"></slot>
</template>
</TestControlBar>
</div>
</NCard>
<!-- 测试结果区域 -->
<TestResultSection
@@ -137,6 +133,7 @@ import { computed, ref, onUnmounted } from 'vue'
import { useI18n } from "vue-i18n";
import {
NFlex,
NCard,
} from "naive-ui";
import type {
OptimizationMode,
@@ -132,119 +132,83 @@
</NFlex>
<!-- 右侧:测试区域 -->
<NFlex
vertical
<ConversationTestPanel
ref="testAreaPanelRef"
:style="{
flex: 1,
overflow: 'auto',
height: '100%',
gap: '12px',
minHeight: 0,
}"
:optimization-mode="optimizationMode"
:is-test-running="conversationTester.testResults.isTestingOriginal || conversationTester.testResults.isTestingOptimized"
:is-compare-mode="isCompareMode"
:enable-compare-mode="true"
@update:isCompareMode="emit('update:isCompareMode', $event)"
@compare-toggle="emit('compare-toggle')"
:global-variables="globalVariables"
:predefined-variables="predefinedVariables"
:temporary-variables="tempVars.temporaryVariables.value"
:input-mode="inputMode"
:control-bar-layout="controlBarLayout"
:button-size="buttonSize"
:result-vertical-layout="resultVerticalLayout"
@test="handleTestWithVariables"
@open-variable-manager="emit('open-variable-manager')"
@open-global-variables="emit('open-global-variables')"
@variable-change="handleVariableChange"
@save-to-global="(name: string, value: string) => emit('save-to-global', name, value)"
@temporary-variable-remove="handleVariableRemove"
@temporary-variables-clear="handleVariablesClear"
v-bind="evaluationHandler.testAreaEvaluationProps.value"
@evaluate-original="evaluationHandler.handlers.onEvaluateOriginal"
@evaluate-optimized="evaluationHandler.handlers.onEvaluateOptimized"
@show-original-detail="evaluationHandler.handlers.onShowOriginalDetail"
@show-optimized-detail="evaluationHandler.handlers.onShowOptimizedDetail"
@apply-improvement="handleApplyImprovement"
>
<!-- 测试区域操作栏 -->
<NCard size="small" :style="{ flexShrink: 0 }">
<NFlex justify="space-between" align="center">
<!-- 左侧:区域标识 -->
<NFlex align="center" :size="8">
<NText strong>{{ $t("test.areaTitle") }}</NText>
</NFlex>
<!-- 模型选择插槽 -->
<template #model-select>
<slot name="test-model-select"></slot>
</template>
<!-- 右侧:快捷操作按钮 -->
<NFlex :size="8">
<NButton
size="small"
quaternary
@click="emit('open-global-variables')"
:title="$t('contextMode.actions.globalVariables')"
>
<template #icon><span>📊</span></template>
<span v-if="!isMobile">{{
$t("contextMode.actions.globalVariables")
}}</span>
</NButton>
</NFlex>
</NFlex>
</NCard>
<!-- 对比模式结果插槽 -->
<template #original-result>
<OutputDisplay
:content="conversationTester.testResults.originalResult"
:reasoning="conversationTester.testResults.originalReasoning"
:streaming="conversationTester.testResults.isTestingOriginal"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
<!-- 测试区域主内容 -->
<NCard
:style="{ flex: 1, overflow: 'auto' }"
content-style="height: 100%; max-height: 100%; overflow: hidden;"
>
<ConversationTestPanel
ref="testAreaPanelRef"
:optimization-mode="optimizationMode"
:is-test-running="conversationTester.testResults.isTestingOriginal || conversationTester.testResults.isTestingOptimized"
:is-compare-mode="isCompareMode"
:enable-compare-mode="true"
@update:isCompareMode="emit('update:isCompareMode', $event)"
@compare-toggle="emit('compare-toggle')"
:global-variables="globalVariables"
:predefined-variables="predefinedVariables"
:temporary-variables="tempVars.temporaryVariables.value"
:input-mode="inputMode"
:control-bar-layout="controlBarLayout"
:button-size="buttonSize"
:result-vertical-layout="resultVerticalLayout"
@test="handleTestWithVariables"
@open-variable-manager="emit('open-variable-manager')"
@variable-change="handleVariableChange"
@save-to-global="
(name: string, value: string) => emit('save-to-global', name, value)
"
@temporary-variable-remove="handleVariableRemove"
@temporary-variables-clear="handleVariablesClear"
v-bind="evaluationHandler.testAreaEvaluationProps.value"
@evaluate-original="evaluationHandler.handlers.onEvaluateOriginal"
@evaluate-optimized="evaluationHandler.handlers.onEvaluateOptimized"
@show-original-detail="evaluationHandler.handlers.onShowOriginalDetail"
@show-optimized-detail="evaluationHandler.handlers.onShowOptimizedDetail"
@apply-improvement="handleApplyImprovement"
>
<!-- 模型选择插槽 -->
<template #model-select>
<slot name="test-model-select"></slot>
</template>
<template #optimized-result>
<OutputDisplay
:content="conversationTester.testResults.optimizedResult"
:reasoning="conversationTester.testResults.optimizedReasoning"
:streaming="conversationTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
<!-- 🆕 对比模式结果插槽:直接绑定测试结果 -->
<template #original-result>
<OutputDisplay
:content="conversationTester.testResults.originalResult"
:reasoning="conversationTester.testResults.originalReasoning"
:streaming="conversationTester.testResults.isTestingOriginal"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
<!-- 单一结果插槽 -->
<template #single-result>
<OutputDisplay
:content="conversationTester.testResults.optimizedResult"
:reasoning="conversationTester.testResults.optimizedReasoning"
:streaming="conversationTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
</ConversationTestPanel>
<template #optimized-result>
<OutputDisplay
:content="conversationTester.testResults.optimizedResult"
:reasoning="conversationTester.testResults.optimizedReasoning"
:streaming="conversationTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
<!-- 单一结果插槽 -->
<template #single-result>
<OutputDisplay
:content="conversationTester.testResults.optimizedResult"
:reasoning="conversationTester.testResults.optimizedReasoning"
:streaming="conversationTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
</ConversationTestPanel>
</NCard>
</NFlex>
<!-- 🆕 评估详情面板 -->
<!-- 评估详情面板 -->
<EvaluationPanel
v-bind="evaluationHandler.panelProps.value"
@close="evaluationHandler.evaluation.closePanel"
@@ -259,7 +223,6 @@ import { ref, computed, inject, provide, type Ref } from 'vue'
import { useI18n } from "vue-i18n";
import { NCard, NFlex, NButton, NText, NEmpty } from "naive-ui";
import { useBreakpoints } from "@vueuse/core";
import PromptPanelUI from "../PromptPanel.vue";
import ConversationTestPanel from "./ConversationTestPanel.vue";
import ConversationManager from "./ConversationManager.vue";
@@ -283,14 +246,6 @@ import type { IteratePayload, SaveFavoritePayload } from "../../types/workspace"
import type { VariableManagerHooks } from '../../composables/prompt/useVariableManager'
import type { AppServices } from '../../types/services'
// 响应式断点
const breakpoints = useBreakpoints({
mobile: 640,
tablet: 1024,
});
const isMobile = breakpoints.smaller("mobile");
// Props 定义
interface Props {
// 核心状态
optimizedReasoning?: string;
@@ -1,106 +1,109 @@
<template>
<NFlex vertical :style="{ height: '100%' }">
<NFlex vertical :style="{ height: '100%', gap: '12px' }">
<!-- 变量值输入表单 -->
<div
v-if="showVariableForm"
:style="{ flexShrink: 0, marginBottom: '16px' }"
<NCard
:title="t('test.variables.formTitle')"
size="small"
:bordered="true"
:style="{ flexShrink: 0 }"
>
<NCard
:title="t('test.variables.formTitle')"
size="small"
:bordered="true"
>
<template #header-extra>
<NSpace :size="8">
<NTag :bordered="false" type="info" size="small">
{{ t("test.variables.tempCount", { count: displayVariables.length }) }}
</NTag>
<NButton
size="small"
quaternary
@click="handleClearAllVariables"
>
{{ t("test.variables.clearAll") }}
</NButton>
</NSpace>
</template>
<NSpace vertical :size="12">
<!-- 变量输入项 -->
<div
v-for="varName in displayVariables"
:key="varName"
:style="{
display: 'flex',
alignItems: 'center',
gap: '8px',
}"
>
<NTag
size="small"
:bordered="false"
:type="
getVariableSource(varName) === 'predefined'
? 'success'
: getVariableSource(varName) === 'test'
? 'warning'
: 'default'
"
:style="{ minWidth: '120px', flexShrink: 0 }"
>
<span v-text="`{{${varName}}}`"></span>
</NTag>
<NInput
:value="getVariableDisplayValue(varName)"
:placeholder="getVariablePlaceholder(varName)"
size="small"
:style="{ flex: 1 }"
@update:value="
handleVariableValueChange(varName, $event)
"
/>
<!-- 删除按钮 (仅临时变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleDeleteVariable(varName)"
:title="t('test.variables.delete')"
>
🗑️
</NButton>
<!-- 保存到全局按钮 (仅测试变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleSaveToGlobal(varName)"
:title="t('test.variables.saveToGlobal')"
>
💾
</NButton>
</div>
<!-- 无变量提示 -->
<NEmpty
v-if="displayVariables.length === 0"
:description="t('test.variables.noVariables')"
<template #header-extra>
<NSpace :size="8">
<NTag :bordered="false" type="info" size="small">
{{ t("test.variables.tempCount", { count: displayVariables.length }) }}
</NTag>
<NButton
size="small"
/>
<!-- 操作按钮 -->
<NSpace :size="8" justify="end">
<!-- 添加变量按钮 -->
<NButton
size="small"
@click="showAddVariableDialog = true"
>
{{ t("test.variables.addVariable") }}
</NButton>
</NSpace>
quaternary
@click="handleClearAllVariables"
>
{{ t("test.variables.clearAll") }}
</NButton>
<NButton
size="small"
quaternary
@click="emit('open-global-variables')"
>
{{ t("contextMode.actions.globalVariables") }}
</NButton>
</NSpace>
</NCard>
</div>
</template>
<NSpace vertical :size="12">
<!-- 变量输入项 -->
<div
v-for="varName in displayVariables"
:key="varName"
:style="{
display: 'flex',
alignItems: 'center',
gap: '8px',
}"
>
<NTag
size="small"
:bordered="false"
:type="
getVariableSource(varName) === 'predefined'
? 'success'
: getVariableSource(varName) === 'test'
? 'warning'
: 'default'
"
:style="{ minWidth: '120px', flexShrink: 0 }"
>
<span v-text="`{{${varName}}}`"></span>
</NTag>
<NInput
:value="getVariableDisplayValue(varName)"
:placeholder="getVariablePlaceholder(varName)"
size="small"
:style="{ flex: 1 }"
@update:value="
handleVariableValueChange(varName, $event)
"
/>
<!-- 删除按钮 (仅临时变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleDeleteVariable(varName)"
:title="t('test.variables.delete')"
>
🗑️
</NButton>
<!-- 保存到全局按钮 (仅测试变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleSaveToGlobal(varName)"
:title="t('test.variables.saveToGlobal')"
>
💾
</NButton>
</div>
<!-- 无变量提示 -->
<NEmpty
v-if="displayVariables.length === 0"
:description="t('test.variables.noVariables')"
size="small"
/>
<!-- 操作按钮 -->
<NSpace :size="8" justify="end">
<!-- 添加变量按钮 -->
<NButton
size="small"
@click="showAddVariableDialog = true"
>
{{ t("test.variables.addVariable") }}
</NButton>
</NSpace>
</NSpace>
</NCard>
<!-- 添加变量对话框 -->
<NModal
@@ -141,7 +144,7 @@
</NModal>
<!-- 控制工具栏 -->
<div :style="{ flexShrink: 0 }">
<NCard :style="{ flexShrink: 0 }" size="small">
<TestControlBar
:model-label="t('test.model')"
:show-compare-toggle="enableCompareMode"
@@ -153,7 +156,6 @@
:layout="adaptiveControlBarLayout"
:button-size="adaptiveButtonSize"
@primary-action="handleTest"
:style="{ marginBottom: '16px' }"
>
<template #model-select>
<slot name="model-select"></slot>
@@ -165,7 +167,7 @@
<slot name="custom-actions"></slot>
</template>
</TestControlBar>
</div>
</NCard>
<!-- 测试结果区域(不支持工具调用,仅显示文本结果)-->
<TestResultSection
@@ -329,6 +331,7 @@ const emit = defineEmits<{
test: [testVariables: Record<string, string>];
"compare-toggle": [];
"open-variable-manager": [];
"open-global-variables": [];
"variable-change": [name: string, value: string];
"save-to-global": [name: string, value: string];
"temporary-variable-remove": [name: string];
@@ -432,9 +435,6 @@ const {
setVariableValues,
} = variableManager;
// 是否显示变量表单
const showVariableForm = computed(() => true);
// 开发环境下的性能调试
if (import.meta.env.DEV) {
const logPerformance = debounce(
@@ -107,113 +107,83 @@
</NFlex>
<!-- 右侧:测试区域 -->
<NFlex
vertical
:size="12"
style="flex: 1; height: 100%; overflow: auto"
<ContextUserTestPanel
ref="testAreaPanelRef"
:style="{
flex: 1,
overflow: 'auto',
height: '100%',
minHeight: 0,
}"
:optimized-prompt="contextUserOptimization.optimizedPrompt"
:is-test-running="contextUserTester.testResults.isTestingOriginal || contextUserTester.testResults.isTestingOptimized"
:is-compare-mode="isCompareMode"
@update:isCompareMode="emit('update:isCompareMode', $event)"
:global-variables="globalVariables"
:predefined-variables="predefinedVariables"
:temporary-variables="temporaryVariables"
:control-bar-layout="controlBarLayout"
:button-size="buttonSize"
:result-vertical-layout="resultVerticalLayout"
:single-result-title="t('test.testResult')"
@test="handleTestWithVariables"
@compare-toggle="emit('compare-toggle')"
@open-variable-manager="emit('open-variable-manager')"
@open-global-variables="emit('open-global-variables')"
@variable-change="handleTestVariableChange"
@save-to-global="
(name: string, value: string) =>
emit('save-to-global', name, value)
"
@temporary-variable-remove="handleTestVariableRemove"
@temporary-variables-clear="handleClearTemporaryVariables"
v-bind="evaluationHandler.testAreaEvaluationProps.value"
@evaluate-original="evaluationHandler.handlers.onEvaluateOriginal"
@evaluate-optimized="evaluationHandler.handlers.onEvaluateOptimized"
@show-original-detail="evaluationHandler.handlers.onShowOriginalDetail"
@show-optimized-detail="evaluationHandler.handlers.onShowOptimizedDetail"
@apply-improvement="handleApplyImprovement"
>
<!-- 测试区域操作栏 -->
<NCard size="small" style="flex-shrink: 0">
<NFlex justify="space-between" align="center">
<!-- 左侧:区域标识 -->
<NText strong>{{ $t("test.areaTitle") }}</NText>
<!-- 模型选择插槽 -->
<template #model-select>
<slot name="test-model-select"></slot>
</template>
<!-- 右侧:快捷操作按钮 -->
<NFlex :size="8">
<!-- 全局变量管理 -->
<NButton
size="small"
quaternary
@click="emit('open-global-variables')"
:title="$t('contextMode.actions.globalVariables')"
>
<template #icon><span>📊</span></template>
<span v-if="!isMobile">{{
$t("contextMode.actions.globalVariables")
}}</span>
</NButton>
<!-- 🆕 对比模式结果插槽:直接绑定测试结果 -->
<template #original-result>
<OutputDisplay
:content="contextUserTester.testResults.originalResult"
:reasoning="contextUserTester.testResults.originalReasoning"
:streaming="contextUserTester.testResults.isTestingOriginal"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
</NFlex>
</NFlex>
</NCard>
<template #optimized-result>
<OutputDisplay
:content="contextUserTester.testResults.optimizedResult"
:reasoning="contextUserTester.testResults.optimizedReasoning"
:streaming="contextUserTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
<!-- 测试区域主内容 -->
<NCard
style="flex: 1; overflow: auto"
content-style="height: 100%; max-height: 100%; overflow: hidden;"
>
<ContextUserTestPanel
ref="testAreaPanelRef"
:optimized-prompt="contextUserOptimization.optimizedPrompt"
:is-test-running="contextUserTester.testResults.isTestingOriginal || contextUserTester.testResults.isTestingOptimized"
:is-compare-mode="isCompareMode"
@update:isCompareMode="emit('update:isCompareMode', $event)"
:global-variables="globalVariables"
:predefined-variables="predefinedVariables"
:temporary-variables="temporaryVariables"
:control-bar-layout="controlBarLayout"
:button-size="buttonSize"
:result-vertical-layout="resultVerticalLayout"
:single-result-title="t('test.testResult')"
@test="handleTestWithVariables"
@compare-toggle="emit('compare-toggle')"
@open-variable-manager="emit('open-variable-manager')"
@variable-change="handleTestVariableChange"
@save-to-global="
(name: string, value: string) =>
emit('save-to-global', name, value)
"
@temporary-variable-remove="handleTestVariableRemove"
@temporary-variables-clear="handleClearTemporaryVariables"
v-bind="evaluationHandler.testAreaEvaluationProps.value"
@evaluate-original="evaluationHandler.handlers.onEvaluateOriginal"
@evaluate-optimized="evaluationHandler.handlers.onEvaluateOptimized"
@show-original-detail="evaluationHandler.handlers.onShowOriginalDetail"
@show-optimized-detail="evaluationHandler.handlers.onShowOptimizedDetail"
@apply-improvement="handleApplyImprovement"
>
<!-- 模型选择插槽 -->
<template #model-select>
<slot name="test-model-select"></slot>
</template>
<!-- 🆕 对比模式结果插槽:直接绑定测试结果 -->
<template #original-result>
<OutputDisplay
:content="contextUserTester.testResults.originalResult"
:reasoning="contextUserTester.testResults.originalReasoning"
:streaming="contextUserTester.testResults.isTestingOriginal"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
<template #optimized-result>
<OutputDisplay
:content="contextUserTester.testResults.optimizedResult"
:reasoning="contextUserTester.testResults.optimizedReasoning"
:streaming="contextUserTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
<!-- 单一结果插槽 -->
<template #single-result>
<OutputDisplay
:content="contextUserTester.testResults.optimizedResult"
:reasoning="contextUserTester.testResults.optimizedReasoning"
:streaming="contextUserTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
</ContextUserTestPanel>
</NCard>
</NFlex>
<!-- 单一结果插槽 -->
<template #single-result>
<OutputDisplay
:content="contextUserTester.testResults.optimizedResult"
:reasoning="contextUserTester.testResults.optimizedReasoning"
:streaming="contextUserTester.testResults.isTestingOptimized"
:enableDiff="false"
mode="readonly"
:style="{ height: '100%', minHeight: '0' }"
/>
</template>
</ContextUserTestPanel>
<!-- 🆕 评估详情面板 -->
<EvaluationPanel
@@ -257,8 +227,7 @@
import { ref, computed, inject, type Ref } from 'vue'
import { useI18n } from "vue-i18n";
import { NCard, NFlex, NButton, NText } from "naive-ui";
import { useBreakpoints } from "@vueuse/core";
import { NCard, NFlex } from "naive-ui";
import InputPanelUI from "../InputPanel.vue";
import PromptPanelUI from "../PromptPanel.vue";
import ContextUserTestPanel from "./ContextUserTestPanel.vue";
@@ -280,15 +249,6 @@ import { useContextUserOptimization } from '../../composables/prompt/useContextU
import { useContextUserTester } from '../../composables/prompt/useContextUserTester';
import { useEvaluationHandler } from '../../composables/prompt/useEvaluationHandler';
// ========================
// 响应式断点配置
// ========================
const breakpoints = useBreakpoints({
mobile: 640,
tablet: 1024,
});
const isMobile = breakpoints.smaller("mobile");
// ========================
// Props 定义
// ========================
@@ -1,106 +1,109 @@
<template>
<NFlex vertical :style="{ height: '100%' }">
<NFlex vertical :style="{ height: '100%', gap: '12px' }">
<!-- 变量值输入表单 -->
<div
v-if="showVariableForm"
:style="{ flexShrink: 0, marginBottom: '16px' }"
<NCard
:title="t('test.variables.formTitle')"
size="small"
:bordered="true"
:style="{ flexShrink: 0 }"
>
<NCard
:title="t('test.variables.formTitle')"
size="small"
:bordered="true"
>
<template #header-extra>
<NSpace :size="8">
<NTag :bordered="false" type="info" size="small">
{{ t("test.variables.tempCount", { count: displayVariables.length }) }}
</NTag>
<NButton
size="small"
quaternary
@click="handleClearAllVariables"
>
{{ t("test.variables.clearAll") }}
</NButton>
</NSpace>
</template>
<NSpace vertical :size="12">
<!-- 变量输入项 -->
<div
v-for="varName in displayVariables"
:key="varName"
:style="{
display: 'flex',
alignItems: 'center',
gap: '8px',
}"
>
<NTag
size="small"
:bordered="false"
:type="
getVariableSource(varName) === 'predefined'
? 'success'
: getVariableSource(varName) === 'test'
? 'warning'
: 'default'
"
:style="{ minWidth: '120px', flexShrink: 0 }"
>
<span v-text="`{{${varName}}}`"></span>
</NTag>
<NInput
:value="getVariableDisplayValue(varName)"
:placeholder="getVariablePlaceholder(varName)"
size="small"
:style="{ flex: 1 }"
@update:value="
handleVariableValueChange(varName, $event)
"
/>
<!-- 删除按钮 (仅临时变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleDeleteVariable(varName)"
:title="t('test.variables.delete')"
>
🗑️
</NButton>
<!-- 保存到全局按钮 (仅测试变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleSaveToGlobal(varName)"
:title="t('test.variables.saveToGlobal')"
>
💾
</NButton>
</div>
<!-- 无变量提示 -->
<NEmpty
v-if="displayVariables.length === 0"
:description="t('test.variables.noVariables')"
<template #header-extra>
<NSpace :size="8">
<NTag :bordered="false" type="info" size="small">
{{ t("test.variables.tempCount", { count: displayVariables.length }) }}
</NTag>
<NButton
size="small"
/>
<!-- 操作按钮 -->
<NSpace :size="8" justify="end">
<!-- 添加变量按钮 -->
<NButton
size="small"
@click="showAddVariableDialog = true"
>
{{ t("test.variables.addVariable") }}
</NButton>
</NSpace>
quaternary
@click="handleClearAllVariables"
>
{{ t("test.variables.clearAll") }}
</NButton>
<NButton
size="small"
quaternary
@click="emit('open-global-variables')"
>
{{ t("contextMode.actions.globalVariables") }}
</NButton>
</NSpace>
</NCard>
</div>
</template>
<NSpace vertical :size="12">
<!-- 变量输入项 -->
<div
v-for="varName in displayVariables"
:key="varName"
:style="{
display: 'flex',
alignItems: 'center',
gap: '8px',
}"
>
<NTag
size="small"
:bordered="false"
:type="
getVariableSource(varName) === 'predefined'
? 'success'
: getVariableSource(varName) === 'test'
? 'warning'
: 'default'
"
:style="{ minWidth: '120px', flexShrink: 0 }"
>
<span v-text="`{{${varName}}}`"></span>
</NTag>
<NInput
:value="getVariableDisplayValue(varName)"
:placeholder="getVariablePlaceholder(varName)"
size="small"
:style="{ flex: 1 }"
@update:value="
handleVariableValueChange(varName, $event)
"
/>
<!-- 删除按钮 (仅临时变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleDeleteVariable(varName)"
:title="t('test.variables.delete')"
>
🗑️
</NButton>
<!-- 保存到全局按钮 (仅测试变量显示) -->
<NButton
v-if="getVariableSource(varName) === 'test'"
size="small"
quaternary
@click="handleSaveToGlobal(varName)"
:title="t('test.variables.saveToGlobal')"
>
💾
</NButton>
</div>
<!-- 无变量提示 -->
<NEmpty
v-if="displayVariables.length === 0"
:description="t('test.variables.noVariables')"
size="small"
/>
<!-- 操作按钮 -->
<NSpace :size="8" justify="end">
<!-- 添加变量按钮 -->
<NButton
size="small"
@click="showAddVariableDialog = true"
>
{{ t("test.variables.addVariable") }}
</NButton>
</NSpace>
</NSpace>
</NCard>
<!-- 添加变量对话框 -->
<NModal
@@ -141,7 +144,7 @@
</NModal>
<!-- 控制工具栏 -->
<div :style="{ flexShrink: 0 }">
<NCard :style="{ flexShrink: 0 }" size="small">
<TestControlBar
:model-label="t('test.model')"
:show-compare-toggle="enableCompareMode"
@@ -153,7 +156,6 @@
:layout="adaptiveControlBarLayout"
:button-size="adaptiveButtonSize"
@primary-action="handleTest"
:style="{ marginBottom: '16px' }"
>
<template #model-select>
<slot name="model-select"></slot>
@@ -165,7 +167,7 @@
<slot name="custom-actions"></slot>
</template>
</TestControlBar>
</div>
</NCard>
<!-- 测试结果区域(支持对比模式)-->
<TestResultSection
@@ -388,6 +390,7 @@ const emit = defineEmits<{
"update:isCompareMode": [value: boolean];
"compare-toggle": [];
"open-variable-manager": [];
"open-global-variables": [];
"variable-change": [name: string, value: string];
"save-to-global": [name: string, value: string];
"tool-call": [toolCall: ToolCallResult];
@@ -553,11 +556,6 @@ const displayVariables = computed(() => {
return sortedTestVariables.value;
});
// 是否显示变量表单
const showVariableForm = computed(() => {
return !props.isTestRunning;
});
// 获取变量的显示值
const getVariableDisplayValue = (varName: string): string => {
return mergedVariables.value[varName] || "";
@@ -308,17 +308,17 @@
</NFlex>
<!-- 右侧:图像生成测试区域(图像模型) -->
<NCard
<NFlex
vertical
:style="{
flex: 1,
overflow: 'auto',
height: '100%',
gap: '12px',
}"
content-style="height: 100%; max-height: 100%; overflow: hidden;"
>
<NFlex vertical :style="{ height: '100%' }">
<!-- 测试控制栏 -->
<div :style="{ flexShrink: 0 }">
<!-- 测试控制栏 -->
<NCard :style="{ flexShrink: 0 }" size="small">
<n-form label-placement="left" size="medium">
<n-form-item
:label="t('imageWorkspace.generation.imageModel')"
@@ -485,9 +485,9 @@
</n-space>
</n-form-item>
</n-form>
</div>
</NCard>
<!-- 图像结果展示区域(使用统一的 TestResultSection 布局) -->
<!-- 图像结果展示区域(使用统一的 TestResultSection 布局) -->
<TestResultSection
:is-compare-mode="isCompareMode"
:style="{ flex: 1, minHeight: 0 }"
@@ -1015,8 +1015,7 @@
</template>
</template>
</TestResultSection>
</NFlex>
</NCard>
</NFlex>
</NFlex>
<!-- 原始提示词 - 全屏编辑器 -->
+177 -181
View File
@@ -577,198 +577,194 @@
</NFlex>
<!-- 右侧:测试区域 -->
<NCard
<TestAreaPanel
ref="testPanelRef"
:style="{
flex: 1,
overflow: 'auto',
height: '100%',
minHeight: 0,
}"
content-style="height: 100%; max-height: 100%; overflow: hidden;"
:optimization-mode="
selectedOptimizationMode
"
:context-mode="contextMode"
:optimized-prompt="
optimizer.optimizedPrompt
"
:is-test-running="false"
:global-variables="
variableManager?.customVariables?.value ||
{}
"
:predefined-variables="predefinedVariables"
v-model:test-content="testContent"
v-model:is-compare-mode="isCompareMode"
:enable-compare-mode="true"
:enable-fullscreen="true"
:input-mode="
responsiveLayout.recommendedInputMode
.value
"
:control-bar-layout="
responsiveLayout
.recommendedControlBarLayout.value
"
:button-size="
responsiveLayout.smartButtonSize.value
"
:conversation-max-height="
responsiveLayout.responsiveHeights.value
.conversationMax
"
:show-original-result="true"
:result-vertical-layout="
responsiveLayout.isMobile.value
"
:show-evaluation="true"
:has-original-result="!!testResults.originalResult"
:has-optimized-result="!!testResults.optimizedResult"
:is-evaluating-original="evaluation.isEvaluatingOriginal.value"
:is-evaluating-optimized="evaluation.isEvaluatingOptimized.value"
:original-score="evaluation.originalScore.value"
:optimized-score="evaluation.optimizedScore.value"
:has-original-evaluation="evaluation.hasOriginalResult.value"
:has-optimized-evaluation="evaluation.hasOptimizedResult.value"
:original-evaluation-result="evaluation.state.original.result"
:optimized-evaluation-result="evaluation.state.optimized.result"
:original-score-level="evaluation.originalLevel.value"
:optimized-score-level="evaluation.optimizedLevel.value"
@test="handleTestAreaTest"
@compare-toggle="
handleTestAreaCompareToggle
"
@open-variable-manager="
handleOpenVariableManager
"
@evaluate-original="() => handleEvaluate('original')"
@evaluate-optimized="() => handleEvaluate('optimized')"
@show-original-detail="() => evaluation.showDetail('original')"
@show-optimized-detail="() => evaluation.showDetail('optimized')"
@apply-improvement="handleApplyImprovement"
>
<!-- 使用新的统一TestAreaPanel组件 -->
<TestAreaPanel
ref="testPanelRef"
:optimization-mode="
selectedOptimizationMode
"
:context-mode="contextMode"
:optimized-prompt="
optimizer.optimizedPrompt
"
:is-test-running="false"
:global-variables="
variableManager?.customVariables?.value ||
{}
"
:predefined-variables="predefinedVariables"
v-model:test-content="testContent"
v-model:is-compare-mode="isCompareMode"
:enable-compare-mode="true"
:enable-fullscreen="true"
:input-mode="
responsiveLayout.recommendedInputMode
.value
"
:control-bar-layout="
responsiveLayout
.recommendedControlBarLayout.value
"
:button-size="
responsiveLayout.smartButtonSize.value
"
:conversation-max-height="
responsiveLayout.responsiveHeights.value
.conversationMax
"
:show-original-result="true"
:result-vertical-layout="
responsiveLayout.isMobile.value
"
:show-evaluation="true"
:has-original-result="!!testResults.originalResult"
:has-optimized-result="!!testResults.optimizedResult"
:is-evaluating-original="evaluation.isEvaluatingOriginal.value"
:is-evaluating-optimized="evaluation.isEvaluatingOptimized.value"
:original-score="evaluation.originalScore.value"
:optimized-score="evaluation.optimizedScore.value"
:has-original-evaluation="evaluation.hasOriginalResult.value"
:has-optimized-evaluation="evaluation.hasOptimizedResult.value"
:original-evaluation-result="evaluation.state.original.result"
:optimized-evaluation-result="evaluation.state.optimized.result"
:original-score-level="evaluation.originalLevel.value"
:optimized-score-level="evaluation.optimizedLevel.value"
@test="handleTestAreaTest"
@compare-toggle="
handleTestAreaCompareToggle
"
@open-variable-manager="
handleOpenVariableManager
"
@evaluate-original="() => handleEvaluate('original')"
@evaluate-optimized="() => handleEvaluate('optimized')"
@show-original-detail="() => evaluation.showDetail('original')"
@show-optimized-detail="() => evaluation.showDetail('optimized')"
@apply-improvement="handleApplyImprovement"
>
<!-- 模型选择插槽 -->
<template #model-select>
<SelectWithConfig
v-model="
modelManager.selectedTestModel
"
:options="textModelOptions"
:getPrimary="
OptionAccessors.getPrimary
"
:getSecondary="
OptionAccessors.getSecondary
"
:getValue="OptionAccessors.getValue"
:placeholder="
t('model.select.placeholder')
"
size="medium"
filterable
:show-config-action="true"
:show-empty-config-c-t-a="true"
@focus="refreshTextModels"
@config="
modelManager.showConfig = true
"
/>
</template>
<!-- 模型选择插槽 -->
<template #model-select>
<SelectWithConfig
v-model="
modelManager.selectedTestModel
"
:options="textModelOptions"
:getPrimary="
OptionAccessors.getPrimary
"
:getSecondary="
OptionAccessors.getSecondary
"
:getValue="OptionAccessors.getValue"
:placeholder="
t('model.select.placeholder')
"
size="medium"
filterable
:show-config-action="true"
:show-empty-config-c-t-a="true"
@focus="refreshTextModels"
@config="
modelManager.showConfig = true
"
/>
</template>
<!-- 原始结果插槽 -->
<template #original-result>
<OutputDisplay
:content="
testResults.originalResult
"
:reasoning="
testResults.originalReasoning
"
:streaming="
testResults.isTestingOriginal
"
:enableDiff="false"
mode="readonly"
:style="{
height: '100%',
minHeight: '0',
}"
/>
</template>
<!-- 原始结果插槽 -->
<template #original-result>
<OutputDisplay
:content="
testResults.originalResult
"
:reasoning="
testResults.originalReasoning
"
:streaming="
testResults.isTestingOriginal
"
:enableDiff="false"
mode="readonly"
:style="{
height: '100%',
minHeight: '0',
}"
/>
</template>
<!-- 优化结果插槽 -->
<template #optimized-result>
<OutputDisplay
:content="
testResults.optimizedResult
"
:reasoning="
testResults.optimizedReasoning
"
:streaming="
testResults.isTestingOptimized
"
:enableDiff="false"
mode="readonly"
:style="{
height: '100%',
minHeight: '0',
}"
/>
</template>
<!-- 优化结果插槽 -->
<template #optimized-result>
<OutputDisplay
:content="
testResults.optimizedResult
"
:reasoning="
testResults.optimizedReasoning
"
:streaming="
testResults.isTestingOptimized
"
:enableDiff="false"
mode="readonly"
:style="{
height: '100%',
minHeight: '0',
}"
/>
</template>
<!-- 单一结果插槽 -->
<template #single-result>
<OutputDisplay
:content="
testResults.optimizedResult
"
:reasoning="
testResults.optimizedReasoning
"
:streaming="
testResults.isTestingOptimized
"
:enableDiff="false"
mode="readonly"
:style="{
height: '100%',
minHeight: '0',
}"
/>
</template>
<!-- 单一结果插槽 -->
<template #single-result>
<OutputDisplay
:content="
testResults.optimizedResult
"
:reasoning="
testResults.optimizedReasoning
"
:streaming="
testResults.isTestingOptimized
"
:enableDiff="false"
mode="readonly"
:style="{
height: '100%',
minHeight: '0',
}"
/>
</template>
<!-- 对比评估按钮(仅在对比模式且有两个结果时显示) -->
<template #custom-actions>
<template v-if="isCompareMode && testResults.originalResult && testResults.optimizedResult">
<!-- 已评估或评估中:显示分数徽章 -->
<EvaluationScoreBadge
v-if="evaluation.hasCompareResult.value || evaluation.isEvaluatingCompare.value"
:score="evaluation.compareScore.value"
:level="evaluation.compareLevel.value"
:loading="evaluation.isEvaluatingCompare.value"
:result="evaluation.state.compare.result"
type="compare"
size="small"
@show-detail="() => evaluation.showDetail('compare')"
@apply-improvement="handleApplyImprovement"
/>
<!-- 未评估:显示评估按钮 -->
<NButton
v-else
quaternary
size="small"
@click="() => handleEvaluate('compare')"
>
{{ t('evaluation.compareEvaluate') }}
</NButton>
</template>
<!-- 对比评估按钮(仅在对比模式且有两个结果时显示) -->
<template #custom-actions>
<template v-if="isCompareMode && testResults.originalResult && testResults.optimizedResult">
<!-- 已评估或评估中:显示分数徽章 -->
<EvaluationScoreBadge
v-if="evaluation.hasCompareResult.value || evaluation.isEvaluatingCompare.value"
:score="evaluation.compareScore.value"
:level="evaluation.compareLevel.value"
:loading="evaluation.isEvaluatingCompare.value"
:result="evaluation.state.compare.result"
type="compare"
size="small"
@show-detail="() => evaluation.showDetail('compare')"
@apply-improvement="handleApplyImprovement"
/>
<!-- 未评估:显示评估按钮 -->
<NButton
v-else
quaternary
size="small"
@click="() => handleEvaluate('compare')"
>
{{ t('evaluation.compareEvaluate') }}
</NButton>
</template>
</TestAreaPanel>
</NCard>
</template>
</TestAreaPanel>
</NFlex>
</template>
<!-- 图像模式:渲染新的工作区组件,不破坏现有结构 -->