feat: 全新智能体功能

- 基于先进智能体框架,增加智能体编排功能
- 增加智能体聊天,并对接持久化
This commit is contained in:
2026-05-25 11:42:48 +08:00
parent 6c3d98eaac
commit 72df00f25b
168 changed files with 22045 additions and 400 deletions

View File

@@ -0,0 +1,334 @@
<script setup lang="ts">
import type {AgentCapabilityKind} from '../types';
import {onBeforeUnmount, onMounted, ref} from 'vue';
import {
Connection,
Files,
Loading,
Plus,
Promotion,
Share,
VideoPlay,
} from '@element-plus/icons-vue';
defineProps<{
publishDisabled?: boolean;
publishLoading?: boolean;
publishText: string;
saveLoading?: boolean;
tryoutDisabled?: boolean;
}>();
const emit = defineEmits<{
add: [kind: AgentCapabilityKind];
publish: [];
save: [];
tryout: [];
}>();
const capabilityOpen = ref(false);
const capabilityRef = ref<HTMLElement>();
const capabilityItems = [
{
kind: 'knowledge' as const,
title: '知识库',
desc: '检索企业知识',
icon: Files,
},
{
kind: 'workflow' as const,
title: '工作流',
desc: '调用已发布流程',
icon: Share,
},
{
kind: 'plugin' as const,
title: '插件',
desc: '执行工具能力',
icon: Connection,
},
];
function handleAdd(kind: AgentCapabilityKind) {
capabilityOpen.value = false;
emit('add', kind);
}
function handlePointerDown(event: PointerEvent) {
if (!capabilityOpen.value || !capabilityRef.value) return;
const target = event.target as Node | null;
if (target && !capabilityRef.value.contains(target)) {
capabilityOpen.value = false;
}
}
onMounted(() => {
window.addEventListener('pointerdown', handlePointerDown);
});
onBeforeUnmount(() => {
window.removeEventListener('pointerdown', handlePointerDown);
});
</script>
<template>
<div class="agent-command-bar">
<div class="agent-command-bar__group">
<div ref="capabilityRef" class="agent-command-bar__capability">
<div v-if="capabilityOpen" class="agent-command-bar__capability-panel">
<button
v-for="item in capabilityItems"
:key="item.kind"
class="agent-command-bar__capability-item"
type="button"
@click="handleAdd(item.kind)"
>
<span class="agent-command-bar__capability-icon">
<component :is="item.icon" />
</span>
<span class="agent-command-bar__capability-meta">
<span class="agent-command-bar__capability-title">
{{ item.title }}
</span>
<span class="agent-command-bar__capability-desc">
{{ item.desc }}
</span>
</span>
</button>
</div>
<button
class="agent-command-bar__button agent-command-bar__button--add"
type="button"
:aria-expanded="capabilityOpen"
@click="capabilityOpen = !capabilityOpen"
>
<Plus />
<span>{{ capabilityOpen ? '收起能力' : '增加能力' }}</span>
</button>
</div>
<div class="agent-command-bar__divider"></div>
<button
class="agent-command-bar__button agent-command-bar__button--primary"
type="button"
:disabled="saveLoading"
@click="emit('save')"
>
<Loading v-if="saveLoading" class="is-loading" />
<span>保存</span>
</button>
<div class="agent-command-bar__divider"></div>
<button
class="agent-command-bar__button agent-command-bar__button--ghost"
type="button"
:disabled="publishDisabled || publishLoading"
@click="emit('publish')"
>
<Loading v-if="publishLoading" class="is-loading" />
<Promotion v-else />
<span>{{ publishText }}</span>
</button>
</div>
<button
class="agent-command-bar__run"
type="button"
:disabled="tryoutDisabled"
@click="emit('tryout')"
>
<VideoPlay />
<span>试运行</span>
</button>
</div>
</template>
<style scoped>
.agent-command-bar {
position: absolute;
bottom: 16px;
left: 50%;
z-index: 30;
display: flex;
gap: 8px;
align-items: center;
transform: translateX(-50%);
}
.agent-command-bar__group {
display: inline-flex;
gap: 2px;
align-items: center;
height: 40px;
padding: 0 4px;
background: var(--el-bg-color);
border: 1px solid var(--el-border-color);
border-radius: 10px;
box-shadow: 0 2px 8px rgb(0 0 0 / 8%);
}
.agent-command-bar__button,
.agent-command-bar__run {
all: unset;
box-sizing: border-box;
display: inline-flex;
flex-shrink: 0;
gap: 6px;
align-items: center;
justify-content: center;
height: 32px;
font-size: 14px;
font-weight: 600;
line-height: 1;
cursor: pointer;
border-radius: 8px;
transition:
background 0.15s,
color 0.15s,
filter 0.15s,
opacity 0.15s;
}
.agent-command-bar__button {
padding: 0 12px;
}
.agent-command-bar__capability {
position: relative;
display: inline-flex;
}
.agent-command-bar__capability-panel {
position: absolute;
bottom: calc(100% + 10px);
left: 0;
display: flex;
flex-direction: column;
gap: 4px;
width: 224px;
padding: 8px;
background: var(--el-bg-color-overlay);
border: 1px solid var(--el-border-color);
border-radius: 10px;
box-shadow: var(--el-box-shadow-light);
}
.agent-command-bar__capability-item {
all: unset;
box-sizing: border-box;
display: flex;
gap: 10px;
align-items: center;
padding: 8px;
cursor: pointer;
border-radius: 8px;
transition: background 0.15s;
}
.agent-command-bar__capability-item:hover {
background: var(--el-fill-color-light);
}
.agent-command-bar__capability-icon {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
color: var(--el-color-primary);
background: var(--el-color-primary-light-9);
border-radius: 8px;
}
.agent-command-bar__capability-meta {
display: flex;
flex: 1;
flex-direction: column;
min-width: 0;
}
.agent-command-bar__capability-title {
font-size: 13px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.agent-command-bar__capability-desc {
margin-top: 2px;
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
color: var(--el-text-color-secondary);
white-space: nowrap;
}
.agent-command-bar__button--add {
color: var(--el-color-primary);
background: var(--el-color-primary-light-9);
}
.agent-command-bar__button--add:hover {
background: var(--el-color-primary-light-8);
}
.agent-command-bar__button--primary {
color: var(--el-color-primary);
background: var(--el-color-primary-light-9);
}
.agent-command-bar__button--ghost {
color: var(--el-text-color-secondary);
}
.agent-command-bar__button:hover:not(:disabled) {
color: var(--el-text-color-primary);
background: var(--el-fill-color-light);
}
.agent-command-bar__button--primary:hover:not(:disabled) {
color: var(--el-color-primary);
background: var(--el-color-primary-light-8);
}
.agent-command-bar__divider {
width: 1px;
height: 20px;
margin: 0 4px;
background: var(--el-border-color);
}
.agent-command-bar__run {
padding: 0 14px;
color: #fff;
background: #13b33f;
}
.agent-command-bar__run:hover:not(:disabled) {
filter: brightness(0.95);
}
.agent-command-bar__button:disabled,
.agent-command-bar__run:disabled {
cursor: not-allowed;
opacity: 0.55;
}
.agent-command-bar svg {
width: 14px;
height: 14px;
}
.agent-command-bar .is-loading {
animation: agent-command-spin 1s linear infinite;
}
@keyframes agent-command-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>