Initial commit: Multi-Agent Coordination Platform
- Vue 3 + TypeScript + Vite project structure - Element Plus UI components with dark theme - Pinia state management for agents and tasks - JSPlumb integration for visual workflow editing - SVG icon system for agent roles - Axios request layer with API proxy configuration - Tailwind CSS for styling - Docker deployment with Caddy web server - Complete development toolchain (ESLint, Prettier, Vitest) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
235
src/layout/components/Main/TaskTemplate/TaskSyllabus/index.vue
Normal file
235
src/layout/components/Main/TaskTemplate/TaskSyllabus/index.vue
Normal file
@@ -0,0 +1,235 @@
|
||||
<script setup lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { getAgentMapIcon } from '@/layout/components/config.ts'
|
||||
import {
|
||||
type ConnectArg,
|
||||
Jsplumb,
|
||||
type JsplumbConfig,
|
||||
} from '@/layout/components/Main/TaskTemplate/utils.ts'
|
||||
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
||||
import { computed } from 'vue'
|
||||
import { AnchorLocations } from '@jsplumb/browser-ui'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(el: 'resetAgentRepoLine'): void
|
||||
(el: 'setCurrentTask', task: IRawStepTask): void
|
||||
}>()
|
||||
|
||||
const jsplumb = new Jsplumb('task-syllabus')
|
||||
|
||||
const handleScroll = () => {
|
||||
emit('resetAgentRepoLine')
|
||||
}
|
||||
|
||||
const agentsStore = useAgentsStore()
|
||||
|
||||
const collaborationProcess = computed(() => {
|
||||
return agentsStore.agentRawPlan.data?.['Collaboration Process'] ?? []
|
||||
})
|
||||
|
||||
function handleCurrentTask(task: IRawStepTask, transparent: boolean): ConnectArg[] {
|
||||
// 创建当前流程与产出的连线
|
||||
const arr: ConnectArg[] = [
|
||||
{
|
||||
sourceId: `task-syllabus-flow-${task.Id}`,
|
||||
targetId: `task-syllabus-output-object-${task.Id}`,
|
||||
anchor: [AnchorLocations.Right, AnchorLocations.Left],
|
||||
config: {
|
||||
transparent,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// jsplumb.connect(
|
||||
// `task-syllabus-flow-${task.Id}`,
|
||||
// `task-syllabus-output-object-${task.Id}`,
|
||||
// [AnchorLocations.Right, AnchorLocations.Left],
|
||||
// {
|
||||
// transparent,
|
||||
// },
|
||||
// )
|
||||
// 创建当前产出与流程的连线
|
||||
task.InputObject_List?.forEach((item) => {
|
||||
const id = collaborationProcess.value.find((i) => i.OutputObject === item)?.Id
|
||||
if (id) {
|
||||
arr.push({
|
||||
sourceId: `task-syllabus-output-object-${id}`,
|
||||
targetId: `task-syllabus-flow-${task.Id}`,
|
||||
anchor: [AnchorLocations.Left, AnchorLocations.Right],
|
||||
config: {
|
||||
type: 'output',
|
||||
transparent,
|
||||
}
|
||||
})
|
||||
// jsplumb.connect(
|
||||
// `task-syllabus-output-object-${id}`,
|
||||
// `task-syllabus-flow-${task.Id}`,
|
||||
// [AnchorLocations.Left, AnchorLocations.Right],
|
||||
// {
|
||||
// type: 'output',
|
||||
// transparent,
|
||||
// },
|
||||
// )
|
||||
}
|
||||
})
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
function changeTask(task?: IRawStepTask, isEmit?: boolean) {
|
||||
jsplumb.reset()
|
||||
const arr: ConnectArg[] = []
|
||||
agentsStore.agentRawPlan.data?.['Collaboration Process']?.forEach((item) => {
|
||||
arr.push(...handleCurrentTask(item, item.Id !== task?.Id))
|
||||
})
|
||||
jsplumb.connects(arr)
|
||||
if (isEmit && task) {
|
||||
emit('setCurrentTask', task)
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
changeTask,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full flex flex-col">
|
||||
<div class="text-[18px] font-bold mb-[18px]">任务大纲</div>
|
||||
|
||||
<div
|
||||
v-loading="agentsStore.agentRawPlan.loading"
|
||||
class="flex-1 w-full overflow-y-auto relative"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<div class="flex items-center gap-[14%] w-full px-5 relative" id="task-syllabus">
|
||||
<!-- 流程 -->
|
||||
<div
|
||||
v-if="agentsStore.agentRawPlan.data"
|
||||
class="w-[43%] min-h-full relative flex justify-center"
|
||||
>
|
||||
<!-- 流程内容 -->
|
||||
<div class="relative min-h-full z-10 flex flex-col items-center card-box pb-[100px]">
|
||||
<!-- 背景那一根线 -->
|
||||
<div
|
||||
class="absolute h-full left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[5px] z-[1]"
|
||||
>
|
||||
<!-- 线底部的小圆球 -->
|
||||
<div
|
||||
class="absolute bottom-0 left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[15px] h-[15px] rounded-full"
|
||||
></div>
|
||||
</div>
|
||||
<!-- 固定的标题 -->
|
||||
<div
|
||||
class="card-item w-[45%] h-[41px] flex justify-center relative z-99 items-center rounded-[20px] bg-[var(--color-bg-tertiary)]"
|
||||
>
|
||||
流程
|
||||
</div>
|
||||
|
||||
<el-card
|
||||
v-for="item in collaborationProcess"
|
||||
:key="item.Id"
|
||||
class="card-item w-full h-[158px] overflow-y-auto active-card relative z-99"
|
||||
shadow="hover"
|
||||
:id="`task-syllabus-flow-${item.Id}`"
|
||||
@click="changeTask(item, true)"
|
||||
>
|
||||
<div class="text-[18px] font-bold text-center">{{ item.StepName }}</div>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div class="text-[14px] line-clamp-3 text-[var(--color-text-secondary)]">
|
||||
{{ item.TaskContent }}
|
||||
</div>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div class="flex items-center gap-2 flex-wrap relative">
|
||||
<!-- 连接到智能体库的连接点 -->
|
||||
<div
|
||||
class="absolute left-[-10px] top-1/2 transform -translate-y-1/2"
|
||||
:id="`task-syllabus-flow-agents-${item.Id}`"
|
||||
></div>
|
||||
<el-tooltip
|
||||
v-for="agentSelection in item.AgentSelection"
|
||||
:key="agentSelection"
|
||||
effect="light"
|
||||
placement="right"
|
||||
>
|
||||
<template #content>
|
||||
<div class="w-[150px]">
|
||||
<div class="text-[18px] font-bold">{{ agentSelection }}</div>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div>
|
||||
{{
|
||||
item.TaskProcess.find((i) => i.AgentName === agentSelection)?.Description
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
class="w-[31px] h-[31px] rounded-full flex items-center justify-center"
|
||||
:style="{ background: getAgentMapIcon(agentSelection).color }"
|
||||
>
|
||||
<svg-icon
|
||||
:icon-class="getAgentMapIcon(agentSelection).icon"
|
||||
color="var(--color-text)"
|
||||
size="24px"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 产出 -->
|
||||
<div
|
||||
v-if="agentsStore.agentRawPlan.data"
|
||||
class="w-[43%] h-full relative flex justify-center"
|
||||
>
|
||||
<div class="min-h-full w-full relative">
|
||||
<!-- 产出内容 -->
|
||||
<div class="min-h-full relative z-10 flex flex-col items-center card-box pb-[100px]">
|
||||
<!-- 背景那一根线 -->
|
||||
<div
|
||||
class="absolute h-full left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[5px] z-[1]"
|
||||
>
|
||||
<!-- 线底部的小圆球 -->
|
||||
<div
|
||||
class="absolute bottom-0 left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[15px] h-[15px] rounded-full"
|
||||
></div>
|
||||
</div>
|
||||
<!-- 固定的标题 -->
|
||||
<div
|
||||
class="card-item w-[45%] h-[41px] flex justify-center items-center rounded-[20px] bg-[var(--color-bg-tertiary)] relative z-99"
|
||||
>
|
||||
产出
|
||||
</div>
|
||||
<div
|
||||
v-for="item in collaborationProcess"
|
||||
:key="item.Id"
|
||||
class="h-[158px] overflow-y-auto flex items-center w-full card-item relative z-99"
|
||||
>
|
||||
<el-card
|
||||
class="card-item w-full relative"
|
||||
shadow="hover"
|
||||
:id="`task-syllabus-output-object-${item.Id}`"
|
||||
>
|
||||
<div class="text-[18px] font-bold text-center">{{ item.OutputObject }}</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.card-box {
|
||||
.active-card {
|
||||
border: 2px solid transparent;
|
||||
$bg: var(--el-input-bg-color, var(--el-fill-color-blank));
|
||||
background:
|
||||
linear-gradient(var(--color-bg-tertiary), var(--color-bg-tertiary)) padding-box,
|
||||
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user