feat: 增加智能体对话体验配置

- 支持欢迎语、猜你想问和输入提示的编辑、草稿预览与发布态展示

- 补充配置校验、发布快照持久化和发布后回显修复
This commit is contained in:
2026-07-14 21:21:57 +08:00
parent ce8b4fb420
commit 705e0faab6
18 changed files with 1351 additions and 160 deletions

View File

@@ -5,12 +5,13 @@ import type {
AgentValidationIssue,
} from '../types';
import { computed } from 'vue';
import { computed, nextTick, ref, watch } from 'vue';
import { Close } from '@element-plus/icons-vue';
import { ElButton } from 'element-plus';
import { ElButton, ElTabPane, ElTabs } from 'element-plus';
import AgentBaseForm from './AgentBaseForm.vue';
import AgentInteractionForm from './AgentInteractionForm.vue';
import AgentKnowledgeForm from './AgentKnowledgeForm.vue';
import AgentToolForm from './AgentToolForm.vue';
import AgentTryoutPanel from './AgentTryoutPanel.vue';
@@ -39,6 +40,36 @@ const selectedKnowledge = computed(() => {
return props.state.knowledgeBindings.find((item) => item.localId === localId);
});
const activeBaseTab = ref<'basic' | 'interaction'>('basic');
const interactionForm = ref<InstanceType<typeof AgentInteractionForm>>();
function isInteractionIssue(issue?: AgentValidationIssue) {
return issue?.field?.startsWith('interaction.');
}
async function focusIssue(issue: AgentValidationIssue) {
if (issue.nodeId !== 'agent-base') return;
activeBaseTab.value = isInteractionIssue(issue) ? 'interaction' : 'basic';
if (isInteractionIssue(issue)) {
await nextTick();
await interactionForm.value?.focusField(issue.field);
}
}
function handleIssueClick(issue: AgentValidationIssue) {
void focusIssue(issue);
emit('selectIssue', issue.nodeId);
}
watch(
() => props.issues,
(issues) => {
const firstIssue = issues[0];
if (firstIssue?.nodeId === 'agent-base') void focusIssue(firstIssue);
},
{ deep: true },
);
const selectedTool = computed(() => {
if (!props.state.selectedNodeId.startsWith('tool:')) return;
const localId = props.state.selectedNodeId.slice('tool:'.length);
@@ -88,19 +119,31 @@ const selectedToolOptions = computed(() => {
:key="`${issue.nodeId}-${issue.field || issue.message}`"
class="agent-inspector__issue"
type="button"
@click="emit('selectIssue', issue.nodeId)"
@click="handleIssueClick(issue)"
>
{{ issue.message }}
</button>
</div>
<AgentBaseForm
v-if="state.panelMode === 'base'"
:agent="state.agent"
:categories="categories"
:models="models"
@change="emit('change')"
/>
<template v-if="state.panelMode === 'base'">
<ElTabs v-model="activeBaseTab" class="agent-inspector__tabs">
<ElTabPane label="基础设置" name="basic">
<AgentBaseForm
:agent="state.agent"
:categories="categories"
:models="models"
@change="emit('change')"
/>
</ElTabPane>
<ElTabPane label="对话体验" name="interaction">
<AgentInteractionForm
ref="interactionForm"
:agent="state.agent"
@change="emit('change')"
/>
</ElTabPane>
</ElTabs>
</template>
<AgentKnowledgeForm
v-else-if="selectedKnowledge"
:binding="selectedKnowledge"
@@ -186,6 +229,20 @@ const selectedToolOptions = computed(() => {
border-radius: 8px;
}
.agent-inspector__tabs :deep(.el-tabs__header) {
position: sticky;
top: 0;
z-index: 2;
padding: 0 var(--space-4);
margin: 0;
background: hsl(var(--surface-panel));
border-bottom: 1px solid hsl(var(--line-subtle));
}
.agent-inspector__tabs :deep(.el-tabs__nav-wrap::after) {
display: none;
}
.agent-inspector__empty {
padding: 16px;
}