feat(task):优化任务执行与智能体展示功能
- 更新action.svg图标样式- 重构AgentRepo组件,优化智能体列表展示逻辑 - 改进ExecutePlan组件,支持object类型节点渲染 - 完善TaskResult组件,增加执行计划存储与清理机制 - 调整TaskSyllabus组件,优化卡片激活状态样式 - 在Task组件中添加搜索建议功能 - 更新主题配色变量和全局样式- 替换ElInput为ElAutocomplete组件 - 清理无用的jsplumb连接代码- 优化组件间通信与状态管理
This commit is contained in:
parent
0c571dec21
commit
974af053ca
@ -12,7 +12,6 @@ RUN pnpm build
|
|||||||
# The base for mode ENVIRONMENT=prod
|
# The base for mode ENVIRONMENT=prod
|
||||||
FROM caddy:${CADDY_VERSION}-alpine as prod
|
FROM caddy:${CADDY_VERSION}-alpine as prod
|
||||||
|
|
||||||
|
|
||||||
# Workaround for https://github.com/alpinelinux/docker-alpine/issues/98#issuecomment-679278499
|
# Workaround for https://github.com/alpinelinux/docker-alpine/issues/98#issuecomment-679278499
|
||||||
RUN sed -i 's/https/http/' /etc/apk/repositories \
|
RUN sed -i 's/https/http/' /etc/apk/repositories \
|
||||||
&& apk add --no-cache bash
|
&& apk add --no-cache bash
|
||||||
|
|||||||
2
components.d.ts
vendored
2
components.d.ts
vendored
@ -11,11 +11,11 @@ export {}
|
|||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
|
||||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1761368315799" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16388" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="" p-id="16389"></path><path d="M227.99812197 62.94566471v104.65219045l395.2990928 323.85960541v38.37336356l-395.2990928 325.39511198v105.81588629l140.50868178-0.00715021 470.18140399-398.97251069-0.01251283-103.35085308-471.70261015-395.77100635-36.83785704 0.01251287z" p-id="16390"></path></svg>
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1761736278335" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5885" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M226.592 896C167.616 896 128 850.48 128 782.736V241.264C128 173.52 167.616 128 226.592 128c20.176 0 41.136 5.536 62.288 16.464l542.864 280.432C887.648 453.792 896 491.872 896 512s-8.352 58.208-64.272 87.088L288.864 879.536C267.712 890.464 246.768 896 226.592 896z m0-704.304c-31.008 0-34.368 34.656-34.368 49.568v541.472c0 14.896 3.344 49.568 34.368 49.568 9.6 0 20.88-3.2 32.608-9.248l542.864-280.432c21.904-11.328 29.712-23.232 29.712-30.608s-7.808-19.28-29.712-30.592L259.2 200.96c-11.728-6.048-23.008-9.264-32.608-9.264z" p-id="5886"></path></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 886 B |
@ -6,6 +6,7 @@ import api from '@/api'
|
|||||||
import { changeBriefs } from '@/utils/collaboration_Brief_FrontEnd.ts'
|
import { changeBriefs } from '@/utils/collaboration_Brief_FrontEnd.ts'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
(e: 'search-start'): void
|
||||||
(e: 'search', value: string): void
|
(e: 'search', value: string): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@ -15,6 +16,8 @@ const searchValue = ref('')
|
|||||||
|
|
||||||
async function handleSearch() {
|
async function handleSearch() {
|
||||||
try {
|
try {
|
||||||
|
emit('search-start')
|
||||||
|
agentsStore.resetAgent()
|
||||||
agentsStore.setAgentRawPlan({ loading: true })
|
agentsStore.setAgentRawPlan({ loading: true })
|
||||||
const data = await api.generateBasePlan({
|
const data = await api.generateBasePlan({
|
||||||
goal: searchValue.value,
|
goal: searchValue.value,
|
||||||
@ -27,6 +30,31 @@ async function handleSearch() {
|
|||||||
agentsStore.setAgentRawPlan({ loading: false })
|
agentsStore.setAgentRawPlan({ loading: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const restaurants = ref<string[]>([
|
||||||
|
'如何快速筛选慢性肾脏病药物潜在受试者?',
|
||||||
|
'如何补充“丹芍活血胶囊”不良反应数据?',
|
||||||
|
'如何快速研发用于战场失血性休克的药物?',
|
||||||
|
'二维材料的光电性质受哪些关键因素影响?',
|
||||||
|
'如何通过AI模拟的方法分析材料的微观结构?',
|
||||||
|
'如何分析获取液态金属热力学参数?',
|
||||||
|
'如何解决固态电池的成本和寿命难题?',
|
||||||
|
'如何解决船舶制造中的材料腐蚀难题?',
|
||||||
|
'如何解决船舶制造中流体模拟和建模优化难题?',
|
||||||
|
])
|
||||||
|
const querySearch = (queryString: string, cb: (v: {value: string}[]) => void) => {
|
||||||
|
const results = queryString
|
||||||
|
? restaurants.value.filter(createFilter(queryString))
|
||||||
|
: restaurants.value
|
||||||
|
// call callback function to return suggestions
|
||||||
|
cb(results.map((item) => ({value: item})))
|
||||||
|
}
|
||||||
|
|
||||||
|
const createFilter = (queryString: string) => {
|
||||||
|
return (restaurant: string) => {
|
||||||
|
return restaurant.toLowerCase().includes(queryString.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -37,11 +65,12 @@ async function handleSearch() {
|
|||||||
:disabled="agentsStore.agents.length > 0"
|
:disabled="agentsStore.agents.length > 0"
|
||||||
>
|
>
|
||||||
<div class="w-full flex justify-center mb-[27px]">
|
<div class="w-full flex justify-center mb-[27px]">
|
||||||
<el-input
|
<el-autocomplete
|
||||||
v-model.trim="searchValue"
|
v-model.trim="searchValue"
|
||||||
class="task-input"
|
class="task-input"
|
||||||
size="large"
|
size="large"
|
||||||
placeholder="请输入您的任务"
|
placeholder="请输入您的任务"
|
||||||
|
:fetch-suggestions="querySearch"
|
||||||
@change="agentsStore.setSearchValue"
|
@change="agentsStore.setSearchValue"
|
||||||
:disabled="!(agentsStore.agents.length > 0)"
|
:disabled="!(agentsStore.agents.length > 0)"
|
||||||
>
|
>
|
||||||
@ -66,18 +95,18 @@ async function handleSearch() {
|
|||||||
/>
|
/>
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.task-input {
|
:deep(.el-autocomplete) {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
:deep(.el-input__wrapper) {
|
.el-input__wrapper {
|
||||||
border-radius: 40px;
|
border-radius: 40px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
@ -86,6 +115,7 @@ async function handleSearch() {
|
|||||||
linear-gradient(var(--color-bg-tertiary), var(--color-bg-tertiary)) padding-box,
|
linear-gradient(var(--color-bg-tertiary), var(--color-bg-tertiary)) padding-box,
|
||||||
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
padding-right: 5px;
|
||||||
|
|
||||||
.el-icon.is-loading {
|
.el-icon.is-loading {
|
||||||
& + span {
|
& + span {
|
||||||
|
|||||||
@ -5,12 +5,8 @@ import { pick } from 'lodash'
|
|||||||
import api from '@/api/index.ts'
|
import api from '@/api/index.ts'
|
||||||
|
|
||||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||||
import {
|
import { agentMapDuty, getActionTypeDisplay, getAgentMapIcon } from '@/layout/components/config.ts'
|
||||||
agentMapDuty,
|
import { type Agent, useAgentsStore } from '@/stores'
|
||||||
getActionTypeDisplay,
|
|
||||||
getAgentMapIcon,
|
|
||||||
} from '@/layout/components/config.ts'
|
|
||||||
import { type TaskProcess, useAgentsStore } from '@/stores'
|
|
||||||
import { onMounted } from 'vue'
|
import { onMounted } from 'vue'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
@ -31,23 +27,6 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 自定义提示框鼠标移入小红点时显示
|
|
||||||
const tooltipVisibleKey = ref('')
|
|
||||||
const tooltipPosition = ref({ x: 0, y: 0 })
|
|
||||||
|
|
||||||
const showTooltip = (event: MouseEvent, item: TaskProcess & { key: string }) => {
|
|
||||||
tooltipVisibleKey.value = item.key
|
|
||||||
const rect = (event.target as HTMLElement).getBoundingClientRect()
|
|
||||||
tooltipPosition.value = {
|
|
||||||
x: rect.left + rect.width / 2,
|
|
||||||
y: rect.top - 10,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const hideTooltip = () => {
|
|
||||||
tooltipVisibleKey.value = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传agent文件
|
// 上传agent文件
|
||||||
const fileInput = ref<HTMLInputElement>()
|
const fileInput = ref<HTMLInputElement>()
|
||||||
|
|
||||||
@ -116,10 +95,30 @@ const taskProcess = computed(() => {
|
|||||||
key: uuidv4(),
|
key: uuidv4(),
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const agentListRef = ref<HTMLElement | null>()
|
||||||
|
|
||||||
|
// 根据currentTask排序agent列表
|
||||||
|
const agentList = computed(() => {
|
||||||
|
const startArr: Agent[] = []
|
||||||
|
const endArr: Agent[] = []
|
||||||
|
if (!agentsStore.agents.length) {
|
||||||
|
return startArr
|
||||||
|
}
|
||||||
|
for (const agent of agentsStore.agents) {
|
||||||
|
if (agentsStore.currentTask?.AgentSelection?.includes(agent.Name)) {
|
||||||
|
startArr.push(agent)
|
||||||
|
} else {
|
||||||
|
endArr.push(agent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...startArr, ...endArr]
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="agent-repo h-full flex flex-col">
|
<div class="agent-repo h-full flex flex-col" id="agent-repo">
|
||||||
<!-- 头部 -->
|
<!-- 头部 -->
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<span class="text-[18px] font-bold">智能体库</span>
|
<span class="text-[18px] font-bold">智能体库</span>
|
||||||
@ -129,73 +128,112 @@ const taskProcess = computed(() => {
|
|||||||
<svg-icon icon-class="plus" color="var(--color-text)" size="18px" />
|
<svg-icon icon-class="plus" color="var(--color-text)" size="18px" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 人员列表 -->
|
<!-- 智能体列表 -->
|
||||||
<div class="mt-[18px] flex-1 overflow-y-auto relative" @scroll="handleScroll">
|
<div
|
||||||
<div
|
class="mt-[18px] flex-1 overflow-y-auto relative"
|
||||||
class="flex items-center justify-between user-item relative"
|
ref="agentListRef"
|
||||||
v-for="item in agentsStore.agents"
|
@scroll="handleScroll"
|
||||||
|
>
|
||||||
|
<el-popover
|
||||||
|
v-for="item in agentList"
|
||||||
:key="item.Name"
|
:key="item.Name"
|
||||||
|
trigger="hover"
|
||||||
|
placement="bottom"
|
||||||
|
:show-arrow="false"
|
||||||
|
:disabled="!agentsStore.currentTask?.AgentSelection?.includes(item.Name)"
|
||||||
|
popper-class="agent-repo-item-popover active-card"
|
||||||
|
:append-to="agentListRef"
|
||||||
|
width="100%"
|
||||||
>
|
>
|
||||||
<!-- 右侧链接点 -->
|
<template #reference>
|
||||||
<div
|
<div
|
||||||
class="absolute right-0 top-1/2 transform -translate-y-1/2"
|
class="flex items-center justify-between user-item relative h-[41px]"
|
||||||
:id="`agent-repo-${item.Name}`"
|
:class="
|
||||||
></div>
|
agentsStore.currentTask?.AgentSelection?.includes(item.Name) ? 'active-card' : ''
|
||||||
<div
|
"
|
||||||
class="w-[41px] h-[41px] rounded-full flex items-center justify-center"
|
>
|
||||||
:style="{ background: getAgentMapIcon(item.Name).color }"
|
|
||||||
>
|
|
||||||
<svg-icon
|
|
||||||
:icon-class="getAgentMapIcon(item.Name).icon"
|
|
||||||
color="var(--color-text)"
|
|
||||||
size="24px"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="text-[14px] flex flex-col items-end justify-end">
|
|
||||||
<div class="flex items-center gap-[7px]">
|
|
||||||
<div
|
<div
|
||||||
v-for="item1 in taskProcess.filter((i) => i.AgentName === item.Name)"
|
class="w-[41px] h-[41px] rounded-full flex items-center justify-center flex-shrink-0"
|
||||||
:key="item1.key"
|
:style="{ background: getAgentMapIcon(item.Name).color }"
|
||||||
class="relative inline-block"
|
|
||||||
>
|
>
|
||||||
<el-popover
|
<svg-icon
|
||||||
placement="bottom"
|
:icon-class="getAgentMapIcon(item.Name).icon"
|
||||||
:width="200"
|
color="var(--color-text)"
|
||||||
trigger="click"
|
size="24px"
|
||||||
:content="item1.Description"
|
/>
|
||||||
:title="getActionTypeDisplay(item1.ActionType)?.name"
|
</div>
|
||||||
|
<div class="flex-1 text-[14px] flex flex-col items-end justify-end truncate ml-1">
|
||||||
|
<span
|
||||||
|
class="w-full truncate text-right"
|
||||||
|
:style="
|
||||||
|
agentsStore.currentTask?.AgentSelection?.includes(item.Name)
|
||||||
|
? 'color:#00F3FF'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
>{{ item.Name }}</span
|
||||||
>
|
>
|
||||||
<template #reference>
|
<div
|
||||||
<div class="group relative inline-block">
|
v-if="agentsStore.currentTask?.AgentSelection?.includes(item.Name)"
|
||||||
<!-- 小圆点 -->
|
class="flex items-center gap-[7px] h-[8px] mr-1"
|
||||||
<div
|
>
|
||||||
class="w-[6px] h-[6px] rounded-full"
|
<!-- 小圆点 -->
|
||||||
:style="{ background: getActionTypeDisplay(item1.ActionType)?.color }"
|
<div
|
||||||
@mouseenter="(el) => showTooltip(el, item1)"
|
v-for="item1 in taskProcess.filter((i) => i.AgentName === item.Name)"
|
||||||
@mouseleave="hideTooltip"
|
:key="item1.key"
|
||||||
></div>
|
class="w-[6px] h-[6px] rounded-full"
|
||||||
|
:style="{ background: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||||
<!-- 弹窗 -->
|
></div>
|
||||||
<teleport to="body">
|
</div>
|
||||||
<div
|
</div>
|
||||||
v-if="tooltipVisibleKey === item1.key"
|
</div>
|
||||||
class="fixed transform -translate-x-1/2 -translate-y-full mb-2 p-2 bg-[var(--el-bg-color-overlay)] text-sm rounded-[8px] z-50"
|
</template>
|
||||||
:style="{
|
<div>
|
||||||
left: tooltipPosition.x + 'px',
|
<div class="flex items-center justify-between">
|
||||||
top: tooltipPosition.y + 'px',
|
<div
|
||||||
}"
|
class="w-[41px] h-[41px] rounded-full flex items-center justify-center flex-shrink-0 relative right-[2px] bottom-[2px] self-start"
|
||||||
>
|
:style="{ background: getAgentMapIcon(item.Name).color }"
|
||||||
{{ getActionTypeDisplay(item1.ActionType)?.name }}
|
>
|
||||||
</div>
|
<svg-icon
|
||||||
</teleport>
|
:icon-class="getAgentMapIcon(item.Name).icon"
|
||||||
</div>
|
color="var(--color-text)"
|
||||||
</template>
|
size="24px"
|
||||||
</el-popover>
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex-1 text-[14px] flex flex-col items-center justify-center break-all ml-1 text-[14px] text-[#00F3FF] p-[8px] pl-[0]"
|
||||||
|
>
|
||||||
|
{{ item.Name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full flex justify-center">
|
||||||
|
<div
|
||||||
|
class="rounded-[9px] bg-[var(--color-bg-quaternary)] text-[12px] py-0.5 px-5 text-center my-2"
|
||||||
|
>
|
||||||
|
当前指责
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-[8px] pt-0">
|
||||||
|
<div
|
||||||
|
v-for="(item1, index1) in taskProcess.filter((i) => i.AgentName === item.Name)"
|
||||||
|
:key="item1.key"
|
||||||
|
class="text-[12px]"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div class="mx-1 inline-block h-[14px]">
|
||||||
|
<div
|
||||||
|
:style="{ background: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||||
|
class="w-[6px] h-[6px] rounded-full mt-[7px]"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<span :style="{ color: getActionTypeDisplay(item1.ActionType)?.color }">{{ getActionTypeDisplay(item1.ActionType)?.name }}:</span>
|
||||||
|
<span>{{ item1.Description }}</span>
|
||||||
|
</div>
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<div v-if="index1 !== taskProcess.filter((i) => i.AgentName === item.Name).length - 1" class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="mb-1">{{ item.Name }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
<!-- 底部提示栏 -->
|
<!-- 底部提示栏 -->
|
||||||
<div class="w-full grid grid-cols-3 gap-x-[10px] bg-[#1d222b] rounded-[20px] p-[8px] mt-[10px]">
|
<div class="w-full grid grid-cols-3 gap-x-[10px] bg-[#1d222b] rounded-[20px] p-[8px] mt-[10px]">
|
||||||
@ -214,6 +252,7 @@ const taskProcess = computed(() => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.agent-repo {
|
.agent-repo {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
|
|
||||||
.plus-button {
|
.plus-button {
|
||||||
background: #1d2128;
|
background: #1d2128;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
@ -234,7 +273,7 @@ const taskProcess = computed(() => {
|
|||||||
|
|
||||||
.user-item {
|
.user-item {
|
||||||
background: #1d222b;
|
background: #1d222b;
|
||||||
border-radius: 20px;
|
border-radius: 40px;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.25s ease;
|
transition: all 0.25s ease;
|
||||||
@ -249,5 +288,17 @@ const taskProcess = computed(() => {
|
|||||||
color: #b8b8b8;
|
color: #b8b8b8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.active-card {
|
||||||
|
border-left: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#agent-repo {
|
||||||
|
:deep(.agent-repo-item-popover) {
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: var(--color-bg-secondary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -17,35 +17,66 @@ const md = new MarkdownIt({
|
|||||||
typographer: true,
|
typographer: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const data = computed(() => {
|
function sanitize(str?: string) {
|
||||||
|
if (!str) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const html = md.render(str)
|
||||||
|
return DOMPurify.sanitize(html)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
Description: string
|
||||||
|
Content: string
|
||||||
|
LogNodeType: string
|
||||||
|
}
|
||||||
|
const data = computed<Data | null>(() => {
|
||||||
for (const result of props.executePlans) {
|
for (const result of props.executePlans) {
|
||||||
if (result.NodeId === props.nodeId && result.ActionHistory) {
|
if (result.NodeId === props.nodeId) {
|
||||||
|
// LogNodeType 为 object直接渲染Content
|
||||||
|
if (result.LogNodeType === 'object') {
|
||||||
|
return {
|
||||||
|
Description: props.nodeId,
|
||||||
|
Content: sanitize(result.content),
|
||||||
|
LogNodeType: result.LogNodeType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.ActionHistory) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
for (const action of result.ActionHistory) {
|
for (const action of result.ActionHistory) {
|
||||||
if (action.ID === props.actionId) {
|
if (action.ID === props.actionId) {
|
||||||
return action
|
return {
|
||||||
|
Description: action.Description,
|
||||||
|
Content: sanitize(action.Action_Result),
|
||||||
|
LogNodeType: result.LogNodeType,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
const action_Result = computed(() => {
|
|
||||||
const html = md.render(data.value?.Action_Result ?? '')
|
|
||||||
return DOMPurify.sanitize(html)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="data" class="card-item w-full pl-[56px] pr-[41px]">
|
<div v-if="data" class="card-item w-full pl-[56px] pr-[41px]">
|
||||||
<!-- 分割线 -->
|
<!-- 分割线 -->
|
||||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
<div v-if="data.LogNodeType !== 'object'" class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||||
<div class="text-[16px] flex items-center gap-1 text-[var(--color-text-secondary)]">
|
<div
|
||||||
|
v-if="data.Description"
|
||||||
|
class="text-[16px] flex items-center gap-1 text-[var(--color-text-secondary)] mb-1"
|
||||||
|
>
|
||||||
{{ data.Description }}
|
{{ data.Description }}
|
||||||
<Iod />
|
<Iod v-if="data.LogNodeType !== 'object'"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-[8px] p-[15px] text-[14px] bg-[var(--color-bg-quaternary)] mt-1">
|
<div class="rounded-[8px] p-[15px] text-[14px] bg-[var(--color-bg-quaternary)]">
|
||||||
<div class="markdown-content max-h-[240px] overflow-y-auto" v-html="action_Result"></div>
|
<div
|
||||||
|
class="markdown-content max-h-[240px] overflow-y-auto max-w-full"
|
||||||
|
v-html="data.Content"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -54,4 +85,16 @@ const action_Result = computed(() => {
|
|||||||
.card-item + .card-item {
|
.card-item + .card-item {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
.markdown-content {
|
||||||
|
:deep(code) {
|
||||||
|
display: block;
|
||||||
|
width: 100px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(pre) {
|
||||||
|
overflow-x: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -8,11 +8,9 @@ import { getActionTypeDisplay, getAgentMapIcon } from '@/layout/components/confi
|
|||||||
import { type ConnectArg, Jsplumb } from '@/layout/components/Main/TaskTemplate/utils.ts'
|
import { type ConnectArg, Jsplumb } from '@/layout/components/Main/TaskTemplate/utils.ts'
|
||||||
import variables from '@/styles/variables.module.scss'
|
import variables from '@/styles/variables.module.scss'
|
||||||
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
||||||
import api, { type IExecuteRawResponse } from '@/api'
|
import api from '@/api'
|
||||||
|
|
||||||
import ExecutePlan from './ExecutePlan.vue'
|
import ExecutePlan from './ExecutePlan.vue'
|
||||||
import Iod from './Iod.vue'
|
|
||||||
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'refreshLine'): void
|
(e: 'refreshLine'): void
|
||||||
@ -21,6 +19,7 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const agentsStore = useAgentsStore()
|
const agentsStore = useAgentsStore()
|
||||||
|
|
||||||
|
|
||||||
const collaborationProcess = computed(() => {
|
const collaborationProcess = computed(() => {
|
||||||
return agentsStore.agentRawPlan.data?.['Collaboration Process'] ?? []
|
return agentsStore.agentRawPlan.data?.['Collaboration Process'] ?? []
|
||||||
})
|
})
|
||||||
@ -99,13 +98,6 @@ function createInternalLine(id?: string) {
|
|||||||
const color = getActionTypeDisplay(i.ActionType)?.color ?? ''
|
const color = getActionTypeDisplay(i.ActionType)?.color ?? ''
|
||||||
const sourceId = `task-results-${jitem.Id}-0-${i.ID}`
|
const sourceId = `task-results-${jitem.Id}-0-${i.ID}`
|
||||||
const targetId = `task-results-${item.Id}-1`
|
const targetId = `task-results-${item.Id}-1`
|
||||||
// jsplumb.connect(sourceId, targetId, [AnchorLocations.Right, AnchorLocations.Right], {
|
|
||||||
// stops: [
|
|
||||||
// [0, color],
|
|
||||||
// [1, color],
|
|
||||||
// ],
|
|
||||||
// transparent: sourceId !== id,
|
|
||||||
// })
|
|
||||||
arr.push({
|
arr.push({
|
||||||
sourceId,
|
sourceId,
|
||||||
targetId,
|
targetId,
|
||||||
@ -132,13 +124,6 @@ function createInternalLine(id?: string) {
|
|||||||
const color = getActionTypeDisplay(i.ActionType)?.color ?? ''
|
const color = getActionTypeDisplay(i.ActionType)?.color ?? ''
|
||||||
const sourceId = `task-results-${item.Id}-0-${i.ID}`
|
const sourceId = `task-results-${item.Id}-0-${i.ID}`
|
||||||
const targetId = `task-results-${item.Id}-0-${i2.ID}`
|
const targetId = `task-results-${item.Id}-0-${i2.ID}`
|
||||||
// jsplumb.connect(sourceId, targetId, [AnchorLocations.Right, AnchorLocations.Right], {
|
|
||||||
// stops: [
|
|
||||||
// [0, color],
|
|
||||||
// [1, color],
|
|
||||||
// ],
|
|
||||||
// transparent: sourceId !== id,
|
|
||||||
// })
|
|
||||||
arr.push({
|
arr.push({
|
||||||
sourceId,
|
sourceId,
|
||||||
targetId,
|
targetId,
|
||||||
@ -160,12 +145,12 @@ function createInternalLine(id?: string) {
|
|||||||
jsplumb.repaintEverything()
|
jsplumb.repaintEverything()
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = ref<IExecuteRawResponse[]>([])
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
async function handleRun() {
|
async function handleRun() {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
results.value = await api.executePlan(agentsStore.agentRawPlan.data!)
|
const d = await api.executePlan(agentsStore.agentRawPlan.data!)
|
||||||
|
agentsStore.setExecutePlan(d)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
@ -204,8 +189,13 @@ const handleMouseLeave = throttle(() => {
|
|||||||
}
|
}
|
||||||
}, 100)
|
}, 100)
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
jsplumb.reset()
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
createInternalLine,
|
createInternalLine,
|
||||||
|
clear,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -218,9 +208,19 @@ defineExpose({
|
|||||||
<el-button circle :color="variables.tertiary" disabled title="点击刷新">
|
<el-button circle :color="variables.tertiary" disabled title="点击刷新">
|
||||||
<svg-icon icon-class="refresh" />
|
<svg-icon icon-class="refresh" />
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button circle :color="variables.tertiary" title="点击运行" @click="handleRun">
|
<el-popover :disabled="Boolean(agentsStore.agentRawPlan.data)" title="请先输入要执行的任务">
|
||||||
<svg-icon icon-class="action" />
|
<template #reference>
|
||||||
</el-button>
|
<el-button
|
||||||
|
circle
|
||||||
|
:color="variables.tertiary"
|
||||||
|
title="点击运行"
|
||||||
|
:disabled="!agentsStore.agentRawPlan.data"
|
||||||
|
@click="handleRun"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="action" />
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 内容 -->
|
<!-- 内容 -->
|
||||||
@ -233,6 +233,7 @@ defineExpose({
|
|||||||
<div v-for="item in collaborationProcess" :key="item.Id" class="card-item">
|
<div v-for="item in collaborationProcess" :key="item.Id" class="card-item">
|
||||||
<el-card
|
<el-card
|
||||||
class="card-item w-full relative"
|
class="card-item w-full relative"
|
||||||
|
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||||
shadow="hover"
|
shadow="hover"
|
||||||
:id="`task-results-${item.Id}-0`"
|
:id="`task-results-${item.Id}-0`"
|
||||||
@click="emit('setCurrentTask', item)"
|
@click="emit('setCurrentTask', item)"
|
||||||
@ -240,24 +241,18 @@ defineExpose({
|
|||||||
<div class="text-[18px] mb-[15px]">{{ item.StepName }}</div>
|
<div class="text-[18px] mb-[15px]">{{ item.StepName }}</div>
|
||||||
<!-- 折叠面板 -->
|
<!-- 折叠面板 -->
|
||||||
<el-collapse @change="handleCollapse">
|
<el-collapse @change="handleCollapse">
|
||||||
<!-- <el-tooltip-->
|
|
||||||
<!-- :disabled="Boolean(true || results.length || loading)"-->
|
|
||||||
<!-- placement="top"-->
|
|
||||||
<!-- effect="light"-->
|
|
||||||
<!-- content="请点击右上角的循行按钮,查看运行结果"-->
|
|
||||||
<!-- >-->
|
|
||||||
<el-collapse-item
|
<el-collapse-item
|
||||||
v-for="item1 in item.TaskProcess"
|
v-for="item1 in item.TaskProcess"
|
||||||
:key="`task-results-${item.Id}-${item1.ID}`"
|
:key="`task-results-${item.Id}-${item1.ID}`"
|
||||||
:name="`task-results-${item.Id}-${item1.ID}`"
|
:name="`task-results-${item.Id}-${item1.ID}`"
|
||||||
:disabled="Boolean(!results.length || loading)"
|
:disabled="Boolean(!agentsStore.executePlan.length || loading)"
|
||||||
@mouseenter="() => handleMouseEnter(`task-results-${item.Id}-0-${item1.ID}`)"
|
@mouseenter="() => handleMouseEnter(`task-results-${item.Id}-0-${item1.ID}`)"
|
||||||
@mouseleave="handleMouseLeave"
|
@mouseleave="handleMouseLeave"
|
||||||
>
|
>
|
||||||
<template v-if="loading" #icon>
|
<template v-if="loading" #icon>
|
||||||
<SvgIcon icon-class="loading" size="20px" class="animate-spin" />
|
<SvgIcon icon-class="loading" size="20px" class="animate-spin" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!results.length" #icon>
|
<template v-else-if="!agentsStore.executePlan.length" #icon>
|
||||||
<span></span>
|
<span></span>
|
||||||
</template>
|
</template>
|
||||||
<template #title>
|
<template #title>
|
||||||
@ -288,20 +283,37 @@ defineExpose({
|
|||||||
<ExecutePlan
|
<ExecutePlan
|
||||||
:action-id="item1.ID"
|
:action-id="item1.ID"
|
||||||
:node-id="item.StepName"
|
:node-id="item.StepName"
|
||||||
:execute-plans="results"
|
:execute-plans="agentsStore.executePlan"
|
||||||
/>
|
/>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<!-- </el-tooltip>-->
|
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-card
|
<el-card
|
||||||
class="card-item w-full relative"
|
class="card-item w-full relative output-object-card"
|
||||||
shadow="hover"
|
shadow="hover"
|
||||||
|
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||||
:id="`task-results-${item.Id}-1`"
|
:id="`task-results-${item.Id}-1`"
|
||||||
@click="emit('setCurrentTask', item)"
|
@click="emit('setCurrentTask', item)"
|
||||||
>
|
>
|
||||||
<div class="text-[18px]">{{ item.OutputObject }}</div>
|
<!-- <div class="text-[18px]">{{ item.OutputObject }}</div>-->
|
||||||
|
<el-collapse @change="handleCollapse">
|
||||||
|
<el-collapse-item
|
||||||
|
class="output-object"
|
||||||
|
:disabled="Boolean(!agentsStore.executePlan.length || loading)"
|
||||||
|
>
|
||||||
|
<template v-if="loading" #icon>
|
||||||
|
<SvgIcon icon-class="loading" size="20px" class="animate-spin" />
|
||||||
|
</template>
|
||||||
|
<template v-else-if="!agentsStore.executePlan.length" #icon>
|
||||||
|
<span></span>
|
||||||
|
</template>
|
||||||
|
<template #title>
|
||||||
|
<div class="text-[18px]">{{ item.OutputObject }}</div>
|
||||||
|
</template>
|
||||||
|
<ExecutePlan :node-id="item.OutputObject" :execute-plans="agentsStore.executePlan" />
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -344,6 +356,27 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.output-object {
|
||||||
|
.el-collapse-item__header {
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
.el-collapse-item__title {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-collapse-item__wrap {
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
.card-item {
|
||||||
|
background: var(--color-bg-secondary);
|
||||||
|
padding: 25px;
|
||||||
|
padding-top: 10px;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.el-collapse-item__wrap {
|
.el-collapse-item__wrap {
|
||||||
border: none;
|
border: none;
|
||||||
background: var(--color-bg-secondary);
|
background: var(--color-bg-secondary);
|
||||||
@ -358,6 +391,20 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.output-object-card {
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active-card {
|
||||||
|
background:
|
||||||
|
linear-gradient(var(--color-bg-tertiary), var(--color-bg-tertiary)) padding-box,
|
||||||
|
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||||
|
}
|
||||||
|
|
||||||
.card-item + .card-item {
|
.card-item + .card-item {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,14 +40,6 @@ function handleCurrentTask(task: IRawStepTask, transparent: boolean): ConnectArg
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// jsplumb.connect(
|
|
||||||
// `task-syllabus-flow-${task.Id}`,
|
|
||||||
// `task-syllabus-output-object-${task.Id}`,
|
|
||||||
// [AnchorLocations.Right, AnchorLocations.Left],
|
|
||||||
// {
|
|
||||||
// transparent,
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
// 创建当前产出与流程的连线
|
// 创建当前产出与流程的连线
|
||||||
task.InputObject_List?.forEach((item) => {
|
task.InputObject_List?.forEach((item) => {
|
||||||
const id = collaborationProcess.value.find((i) => i.OutputObject === item)?.Id
|
const id = collaborationProcess.value.find((i) => i.OutputObject === item)?.Id
|
||||||
@ -61,15 +53,6 @@ function handleCurrentTask(task: IRawStepTask, transparent: boolean): ConnectArg
|
|||||||
transparent,
|
transparent,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// jsplumb.connect(
|
|
||||||
// `task-syllabus-output-object-${id}`,
|
|
||||||
// `task-syllabus-flow-${task.Id}`,
|
|
||||||
// [AnchorLocations.Left, AnchorLocations.Right],
|
|
||||||
// {
|
|
||||||
// type: 'output',
|
|
||||||
// transparent,
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -88,8 +71,13 @@ function changeTask(task?: IRawStepTask, isEmit?: boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
jsplumb.reset()
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
changeTask,
|
changeTask,
|
||||||
|
clear,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -129,7 +117,8 @@ defineExpose({
|
|||||||
<el-card
|
<el-card
|
||||||
v-for="item in collaborationProcess"
|
v-for="item in collaborationProcess"
|
||||||
:key="item.Id"
|
:key="item.Id"
|
||||||
class="card-item w-full h-[158px] overflow-y-auto active-card relative z-99"
|
class="card-item w-full h-[158px] overflow-y-auto relative z-99"
|
||||||
|
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||||
shadow="hover"
|
shadow="hover"
|
||||||
:id="`task-syllabus-flow-${item.Id}`"
|
:id="`task-syllabus-flow-${item.Id}`"
|
||||||
@click="changeTask(item, true)"
|
@click="changeTask(item, true)"
|
||||||
@ -209,6 +198,7 @@ defineExpose({
|
|||||||
<el-card
|
<el-card
|
||||||
class="card-item w-full relative"
|
class="card-item w-full relative"
|
||||||
shadow="hover"
|
shadow="hover"
|
||||||
|
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||||
:id="`task-syllabus-output-object-${item.Id}`"
|
:id="`task-syllabus-output-object-${item.Id}`"
|
||||||
>
|
>
|
||||||
<div class="text-[18px] font-bold text-center">{{ item.OutputObject }}</div>
|
<div class="text-[18px] font-bold text-center">{{ item.OutputObject }}</div>
|
||||||
@ -221,15 +211,3 @@ defineExpose({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</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>
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import TaskSyllabus from './TaskSyllabus/index.vue'
|
|||||||
import TaskResult from './TaskResult/index.vue'
|
import TaskResult from './TaskResult/index.vue'
|
||||||
import { Jsplumb } from './utils.ts'
|
import { Jsplumb } from './utils.ts'
|
||||||
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
||||||
import { AnchorLocations, BezierConnector } from '@jsplumb/browser-ui'
|
import { BezierConnector } from '@jsplumb/browser-ui'
|
||||||
|
|
||||||
const agentsStore = useAgentsStore()
|
const agentsStore = useAgentsStore()
|
||||||
|
|
||||||
@ -19,29 +19,20 @@ const agentRepoJsplumb = new Jsplumb('task-template', {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// 任务流程
|
// 任务流程
|
||||||
const taskSyllabusRef = ref<{ changeTask: (task?: IRawStepTask, isEmit?: boolean) => void }>()
|
const taskSyllabusRef = ref<{
|
||||||
|
changeTask: (task?: IRawStepTask, isEmit?: boolean) => void
|
||||||
|
clear: () => void
|
||||||
|
}>()
|
||||||
// 执行结果
|
// 执行结果
|
||||||
const taskResultRef = ref<{ createInternalLine: () => void }>()
|
const taskResultRef = ref<{
|
||||||
|
createInternalLine: () => void
|
||||||
|
clear: () => void
|
||||||
|
}>()
|
||||||
const taskResultJsplumb = new Jsplumb('task-template')
|
const taskResultJsplumb = new Jsplumb('task-template')
|
||||||
|
|
||||||
function setCurrentTask(task: IRawStepTask) {
|
function setCurrentTask(task: IRawStepTask) {
|
||||||
// 智能体库画线
|
|
||||||
agentRepoJsplumb.reset()
|
|
||||||
task.AgentSelection?.forEach((item) => {
|
|
||||||
agentRepoJsplumb.connect(
|
|
||||||
`agent-repo-${item}`,
|
|
||||||
`task-syllabus-flow-agents-${task.Id}`,
|
|
||||||
[AnchorLocations.Left, AnchorLocations.Right],
|
|
||||||
{ type: 'input' },
|
|
||||||
)
|
|
||||||
})
|
|
||||||
agentRepoJsplumb.repaintEverything()
|
|
||||||
// 执行结果画线
|
|
||||||
taskResultJsplumb.reset()
|
|
||||||
taskResultJsplumb.connect(`task-syllabus-output-object-${task.Id}`, `task-results-${task.Id}-0`, [AnchorLocations.Right, AnchorLocations.Left])
|
|
||||||
taskResultJsplumb.connect(`task-syllabus-output-object-${task.Id}`, `task-results-${task.Id}-1`, [AnchorLocations.Right, AnchorLocations.Left])
|
|
||||||
taskResultJsplumb.repaintEverything()
|
|
||||||
agentsStore.setCurrentTask(task)
|
agentsStore.setCurrentTask(task)
|
||||||
// 更新任务大纲内部的线
|
// 更新任务大纲内部的线
|
||||||
taskSyllabusRef.value?.changeTask(task, false)
|
taskSyllabusRef.value?.changeTask(task, false)
|
||||||
@ -57,8 +48,17 @@ function resetAgentRepoLine() {
|
|||||||
taskResultJsplumb.repaintEverything()
|
taskResultJsplumb.repaintEverything()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
taskSyllabusRef.value?.clear()
|
||||||
|
taskResultRef.value?.clear()
|
||||||
|
agentRepoJsplumb.repaintEverything()
|
||||||
|
taskResultJsplumb.repaintEverything()
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
changeTask,
|
changeTask,
|
||||||
|
resetAgentRepoLine,
|
||||||
|
clear,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -68,11 +68,11 @@ defineExpose({
|
|||||||
id="task-template"
|
id="task-template"
|
||||||
>
|
>
|
||||||
<!-- 智能体库 -->
|
<!-- 智能体库 -->
|
||||||
<div class="w-[9.5%] min-w-[179px] h-full relative">
|
<div class="w-[9.5%] min-w-[179px] h-full relative flex-shrink-0">
|
||||||
<AgentRepo @resetAgentRepoLine="agentRepoJsplumb.repaintEverything" />
|
<AgentRepo @resetAgentRepoLine="agentRepoJsplumb.repaintEverything" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 任务大纲 -->
|
<!-- 任务大纲 -->
|
||||||
<div class="w-[40.5%] min-w-[600px] h-full px-[20px]">
|
<div class="w-[35.5%] min-w-[600px] h-full px-[20px] flex-shrink-0">
|
||||||
<TaskSyllabus
|
<TaskSyllabus
|
||||||
ref="taskSyllabusRef"
|
ref="taskSyllabusRef"
|
||||||
@resetAgentRepoLine="resetAgentRepoLine"
|
@resetAgentRepoLine="resetAgentRepoLine"
|
||||||
@ -96,14 +96,25 @@ defineExpose({
|
|||||||
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.8);
|
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.8);
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
border: 1px solid #414752;
|
border: 1px solid #414752;
|
||||||
background: #29303c;
|
background: var(--color-bg-quinary);
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style>
|
<style lang="scss">
|
||||||
:root {
|
:root {
|
||||||
--gradient: linear-gradient(to right, #0093eb, #00d2d1);
|
--gradient: linear-gradient(to right, #0093eb, #00d2d1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#task-template {
|
||||||
|
.active-card {
|
||||||
|
border: 2px solid transparent;
|
||||||
|
$bg: var(--el-input-bg-color, var(--el-fill-color-blank));
|
||||||
|
background:
|
||||||
|
linear-gradient(var(--color-bg-secondary), var(--color-bg-secondary)) padding-box,
|
||||||
|
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import Task from './Task.vue'
|
|||||||
import TaskTemplate from './TaskTemplate/index.vue'
|
import TaskTemplate from './TaskTemplate/index.vue'
|
||||||
import { nextTick } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
|
|
||||||
const taskTemplateRef = ref<{ changeTask: () => void }>()
|
const taskTemplateRef = ref<{ changeTask: () => void, clear: () => void }>()
|
||||||
|
|
||||||
function handleSearch() {
|
function handleSearch() {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -14,7 +14,7 @@ function handleSearch() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="p-[27px] h-[calc(100%-60px)]">
|
<div class="p-[27px] h-[calc(100%-60px)]">
|
||||||
<Task @search="handleSearch" />
|
<Task @search="handleSearch" @search-start="taskTemplateRef?.clear" />
|
||||||
<TaskTemplate ref="taskTemplateRef" />
|
<TaskTemplate ref="taskTemplateRef" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { v4 as uuidv4 } from 'uuid'
|
|||||||
|
|
||||||
import { store } from '../index'
|
import { store } from '../index'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
|
import type { IExecuteRawResponse } from '@/api'
|
||||||
|
|
||||||
|
|
||||||
export interface Agent {
|
export interface Agent {
|
||||||
@ -81,6 +82,20 @@ export const useAgentsStore = defineStore('counter', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 执行完任务的结果
|
||||||
|
const executePlan = ref<IExecuteRawResponse[]>([])
|
||||||
|
function setExecutePlan(plan: IExecuteRawResponse[]) {
|
||||||
|
executePlan.value = plan
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetAgent() {
|
||||||
|
agentRawPlan.value = {
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
currentTask.value = undefined
|
||||||
|
executePlan.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
agents,
|
agents,
|
||||||
@ -90,7 +105,10 @@ export const useAgentsStore = defineStore('counter', () => {
|
|||||||
currentTask,
|
currentTask,
|
||||||
setCurrentTask,
|
setCurrentTask,
|
||||||
agentRawPlan,
|
agentRawPlan,
|
||||||
setAgentRawPlan
|
setAgentRawPlan,
|
||||||
|
executePlan,
|
||||||
|
setExecutePlan,
|
||||||
|
resetAgent,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ html.dark {
|
|||||||
--color-bg-secondary: #050505;
|
--color-bg-secondary: #050505;
|
||||||
--color-bg-tertiary: #20222A;
|
--color-bg-tertiary: #20222A;
|
||||||
--color-bg-quaternary: #24252A;
|
--color-bg-quaternary: #24252A;
|
||||||
|
--color-bg-quinary: #29303c;
|
||||||
--color-text: #fff;
|
--color-text: #fff;
|
||||||
--color-text-secondary: #C9C9C9;
|
--color-text-secondary: #C9C9C9;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user