feat:三个窗口接口联调版本
This commit is contained in:
@@ -100,6 +100,7 @@ async function handleSearch() {
|
||||
})
|
||||
data['Collaboration Process'] = changeBriefs(data['Collaboration Process'])
|
||||
agentsStore.setAgentRawPlan({ data })
|
||||
console.log('agentsStore.agentRawPlan', agentsStore.agentRawPlan)
|
||||
emit('search', searchValue.value)
|
||||
} finally {
|
||||
triggerOnFocus.value = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { getActionTypeDisplay } from '@/layout/components/config.ts'
|
||||
import { useAgentsStore } from '@/stores'
|
||||
import BranchButton from './components/TaskButton.vue'
|
||||
@@ -23,6 +23,20 @@ const emit = defineEmits<{
|
||||
(e: 'save-edit', stepId: string, processId: string, value: string): void
|
||||
}>()
|
||||
|
||||
// 🔄 从 currentTask 中获取数据(与分支切换联动)
|
||||
const currentTaskProcess = computed(() => {
|
||||
// ✅ 优先使用 currentTask(包含分支切换后的数据)
|
||||
const currentTask = agentsStore.currentTask
|
||||
if (currentTask && currentTask.Id === props.step.Id && currentTask.TaskProcess) {
|
||||
return currentTask.TaskProcess
|
||||
}
|
||||
|
||||
// ⚠️ 降级:从 agentRawPlan 中获取原始数据(不受分支切换影响)
|
||||
const collaborationProcess = agentsStore.agentRawPlan.data?.['Collaboration Process'] || []
|
||||
const rawData = collaborationProcess.find((task: any) => task.Id === props.step.Id)
|
||||
return rawData?.TaskProcess || []
|
||||
})
|
||||
|
||||
// 当前正在编辑的process ID
|
||||
const editingProcessId = ref<string | null>(null)
|
||||
// 编辑框的值
|
||||
@@ -30,6 +44,17 @@ const editValue = ref('')
|
||||
// 鼠标悬停的process ID
|
||||
const hoverProcessId = ref<string | null>(null)
|
||||
|
||||
// 🆕 处理卡片点击事件(非编辑模式下)
|
||||
function handleCardClick() {
|
||||
// 如果正在编辑,不处理点击
|
||||
if (editingProcessId.value) return
|
||||
|
||||
// 设置当前任务,与任务大纲联动
|
||||
if (props.step.Id) {
|
||||
agentsStore.setCurrentTask(props.step)
|
||||
}
|
||||
}
|
||||
|
||||
// 检测当前是否是深色模式
|
||||
function isDarkMode(): boolean {
|
||||
return document.documentElement.classList.contains('dark')
|
||||
@@ -116,12 +141,12 @@ function handleCancel() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="process-card">
|
||||
<div class="process-card" @click="handleCardClick">
|
||||
<div class="process-content">
|
||||
<!-- 显示模式 -->
|
||||
<div class="display-content">
|
||||
<span
|
||||
v-for="process in step.TaskProcess"
|
||||
v-for="process in currentTaskProcess"
|
||||
:key="process.ID"
|
||||
class="process-segment"
|
||||
@mouseenter="handleMouseEnter(process.ID)"
|
||||
@@ -190,10 +215,13 @@ function handleCancel() {
|
||||
{{ process.Description }}
|
||||
</span>
|
||||
|
||||
<span class="separator" v-if="!process.Description.endsWith('。')">。</span>
|
||||
<span class="separator" v-if="process.Description && !process.Description.endsWith('。')"
|
||||
>。</span
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 按钮点击不会冒泡到卡片 -->
|
||||
<BranchButton :step="step" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -207,6 +235,8 @@ function handleCancel() {
|
||||
background: var(--color-bg-list);
|
||||
border: 1px solid var(--color-border-default);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
.process-content {
|
||||
min-height: 20px;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,11 +21,28 @@ const branchCount = computed(() => {
|
||||
const branches = selectionStore.getTaskProcessBranches(taskStepId)
|
||||
|
||||
// 主分支(1) + 额外分支数量
|
||||
return 1 + branches.length
|
||||
return branches.length || 1
|
||||
})
|
||||
|
||||
const handleClick = (event: MouseEvent) => {
|
||||
event.stopPropagation() // 阻止冒泡,避免触发卡片点击
|
||||
// 🆕 判断按钮是否可点击(只有当前按钮对应的任务是任务大纲中选中的任务时才可点击)
|
||||
const isClickable = computed(() => {
|
||||
if (!props.step?.Id || !agentsStore.currentTask?.Id) {
|
||||
return false
|
||||
}
|
||||
return props.step.Id === agentsStore.currentTask.Id
|
||||
})
|
||||
|
||||
const handleClick = (event?: MouseEvent) => {
|
||||
// 🆕 只有可点击时才执行操作
|
||||
if (!isClickable.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// 阻止冒泡,避免触发卡片点击
|
||||
if (event) {
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
emit('click')
|
||||
// 设置当前任务
|
||||
if (props.step) {
|
||||
@@ -39,9 +56,9 @@ const handleClick = (event: MouseEvent) => {
|
||||
<template>
|
||||
<div
|
||||
class="task-button"
|
||||
:class="{ 'has-branches': branchCount > 1 }"
|
||||
:class="{ 'has-branches': branchCount > 0, 'is-disabled': !isClickable }"
|
||||
@click="handleClick"
|
||||
:title="`${branchCount} 个分支`"
|
||||
:title="isClickable ? `${branchCount} 个分支` : '请先在任务大纲中选中此任务'"
|
||||
>
|
||||
<!-- 流程图标 -->
|
||||
<svg-icon icon-class="branch" size="20px" class="task-icon" />
|
||||
@@ -83,6 +100,17 @@ const handleClick = (event: MouseEvent) => {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
// 🆕 禁用状态
|
||||
&.is-disabled {
|
||||
background-color: #bdc3c7;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
|
||||
&:hover {
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-branches::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
// /api/fill_stepTask 接口的Vue适用mock数据
|
||||
import type { IApiStepTask, IRawStepTask } from '@/stores/modules/agents'
|
||||
|
||||
// 模拟接口响应数据
|
||||
export const mockFillStepTaskResponse: IApiStepTask = {
|
||||
name: '需求分析与原型设计',
|
||||
content: '分析用户需求并创建产品原型',
|
||||
inputs: ['用户调研报告', '竞品分析文档'],
|
||||
output: '产品原型设计稿',
|
||||
agents: ['实验材料学家', '腐蚀机理研究员', '防护工程专家'],
|
||||
brief: {
|
||||
template: '基于!<0>!和!<1>!,!<2>!、!<3>!和!<4>!执行!<5>!任务,以获得!<6>!。',
|
||||
data: {
|
||||
'0': {
|
||||
text: '用户调研报告',
|
||||
style: {
|
||||
background: 'hsl(120, 60%, 70%)',
|
||||
},
|
||||
},
|
||||
'1': {
|
||||
text: '竞品分析文档',
|
||||
style: {
|
||||
background: 'hsl(120, 60%, 70%)',
|
||||
},
|
||||
},
|
||||
'2': {
|
||||
text: '实验材料学家',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 90%)',
|
||||
boxShadow: '1px 1px 4px 1px rgba(0,0,0,0.2)',
|
||||
},
|
||||
},
|
||||
'3': {
|
||||
text: '腐蚀机理研究员',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 90%)',
|
||||
boxShadow: '1px 1px 4px 1px rgba(0,0,0,0.2)',
|
||||
},
|
||||
},
|
||||
'4': {
|
||||
text: '防护工程专家',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 90%)',
|
||||
boxShadow: '1px 1px 4px 1px rgba(0,0,0,0.2)',
|
||||
},
|
||||
},
|
||||
'5': {
|
||||
text: '分析用户需求并创建产品原型',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 87%)',
|
||||
border: '1.5px solid #ddd',
|
||||
},
|
||||
},
|
||||
'6': {
|
||||
text: '产品原型设计稿',
|
||||
style: {
|
||||
background: 'hsl(30, 100%, 80%)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action_001',
|
||||
type: '需求分析',
|
||||
agent: '实验材料学家',
|
||||
description: '分析用户调研报告,识别核心需求点',
|
||||
inputs: ['用户调研报告'],
|
||||
},
|
||||
{
|
||||
id: 'action_002',
|
||||
type: '竞品分析',
|
||||
agent: '实验材料学家',
|
||||
description: '对比竞品功能,确定产品差异化优势',
|
||||
inputs: ['竞品分析文档'],
|
||||
},
|
||||
{
|
||||
id: 'action_003',
|
||||
type: '信息架构设计',
|
||||
agent: '防护工程专家',
|
||||
description: '设计产品信息结构和用户流程',
|
||||
inputs: ['需求分析结果'],
|
||||
},
|
||||
{
|
||||
id: 'action_004',
|
||||
type: '界面原型设计',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '创建高保真界面原型',
|
||||
inputs: ['信息架构设计'],
|
||||
},
|
||||
{
|
||||
id: 'action_005',
|
||||
type: '原型评审',
|
||||
agent: '实验材料学家',
|
||||
description: '组织团队评审原型设计',
|
||||
inputs: ['界面原型设计'],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// 请求参数类型
|
||||
export interface IFillStepTaskRequest {
|
||||
goal: string
|
||||
stepTask: IApiStepTask
|
||||
}
|
||||
|
||||
// Vue composable
|
||||
export const useFillStepTaskMock = () => {
|
||||
const fillStepTask = async (
|
||||
goal: string,
|
||||
stepTask: IApiStepTask,
|
||||
): Promise<{ data: IApiStepTask }> => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
data: mockFillStepTaskResponse,
|
||||
})
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
fillStepTask,
|
||||
}
|
||||
}
|
||||
|
||||
// Vue组件使用示例
|
||||
export const fillStepTaskExampleRequest: IFillStepTaskRequest = {
|
||||
goal: '开发一个智能协作平台',
|
||||
stepTask: {
|
||||
name: '需求分析与原型设计',
|
||||
content: '分析用户需求并创建产品原型',
|
||||
inputs: ['用户调研报告', '竞品分析文档'],
|
||||
output: '产品原型设计稿',
|
||||
agents: [],
|
||||
brief: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [],
|
||||
},
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
// /api/fill_stepTask_TaskProcess 接口的Vue适用mock数据
|
||||
import type { IApiStepTask } from '@/stores'
|
||||
|
||||
// 模拟接口响应数据
|
||||
export const mockFillAgentSelectionResponse: IApiStepTask = {
|
||||
name: '技术方案设计与开发',
|
||||
content: '设计技术架构并完成核心功能开发',
|
||||
inputs: ['产品需求文档', '技术选型指南'],
|
||||
output: '可运行的产品版本',
|
||||
agents: ['架构师', '后端工程师', '前端工程师', '测试工程师'],
|
||||
brief: {
|
||||
template: '基于!<0>!和!<1>!,!<2>!、!<3>!、!<4>!和!<5>!执行!<6>!任务,以获得!<7>!。',
|
||||
data: {
|
||||
'0': {
|
||||
text: '产品需求文档',
|
||||
style: {
|
||||
background: 'hsl(120, 60%, 70%)',
|
||||
},
|
||||
},
|
||||
'1': {
|
||||
text: '技术选型指南',
|
||||
style: {
|
||||
background: 'hsl(120, 60%, 70%)',
|
||||
},
|
||||
},
|
||||
'2': {
|
||||
text: '架构师',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 90%)',
|
||||
boxShadow: '1px 1px 4px 1px rgba(0,0,0,0.2)',
|
||||
},
|
||||
},
|
||||
'3': {
|
||||
text: '后端工程师',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 90%)',
|
||||
boxShadow: '1px 1px 4px 1px rgba(0,0,0,0.2)',
|
||||
},
|
||||
},
|
||||
'4': {
|
||||
text: '前端工程师',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 90%)',
|
||||
boxShadow: '1px 1px 4px 1px rgba(0,0,0,0.2)',
|
||||
},
|
||||
},
|
||||
'5': {
|
||||
text: '测试工程师',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 90%)',
|
||||
boxShadow: '1px 1px 4px 1px rgba(0,0,0,0.2)',
|
||||
},
|
||||
},
|
||||
'6': {
|
||||
text: '设计技术架构并完成核心功能开发',
|
||||
style: {
|
||||
background: 'hsl(0, 0%, 87%)',
|
||||
border: '1.5px solid #ddd',
|
||||
},
|
||||
},
|
||||
'7': {
|
||||
text: '可运行的产品版本',
|
||||
style: {
|
||||
background: 'hsl(30, 100%, 80%)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action_101',
|
||||
type: '技术架构设计',
|
||||
agent: '架构师',
|
||||
description: '设计系统架构和技术栈选型',
|
||||
inputs: ['产品需求文档', '技术选型指南'],
|
||||
},
|
||||
{
|
||||
id: 'action_102',
|
||||
type: '数据库设计',
|
||||
agent: '后端工程师',
|
||||
description: '设计数据库表结构和关系',
|
||||
inputs: ['技术架构设计'],
|
||||
},
|
||||
{
|
||||
id: 'action_103',
|
||||
type: '后端API开发',
|
||||
agent: '后端工程师',
|
||||
description: '实现RESTful API接口',
|
||||
inputs: ['数据库设计'],
|
||||
},
|
||||
{
|
||||
id: 'action_104',
|
||||
type: '前端界面开发',
|
||||
agent: '前端工程师',
|
||||
description: '开发用户界面和交互功能',
|
||||
inputs: ['后端API开发'],
|
||||
},
|
||||
{
|
||||
id: 'action_105',
|
||||
type: '单元测试',
|
||||
agent: '测试工程师',
|
||||
description: '编写和执行单元测试用例',
|
||||
inputs: ['前端界面开发'],
|
||||
},
|
||||
{
|
||||
id: 'action_106',
|
||||
type: '集成测试',
|
||||
agent: '测试工程师',
|
||||
description: '进行系统集成测试',
|
||||
inputs: ['单元测试'],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// 请求参数类型
|
||||
export interface IFillAgentSelectionRequest {
|
||||
goal: string
|
||||
stepTask: IApiStepTask
|
||||
agents: string[]
|
||||
}
|
||||
|
||||
// Vue composable
|
||||
export const useFillAgentSelectionMock = () => {
|
||||
const fillAgentSelection = async (
|
||||
goal: string,
|
||||
stepTask: IApiStepTask,
|
||||
agents: string[],
|
||||
): Promise<{ data: IApiStepTask }> => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
data: mockFillAgentSelectionResponse,
|
||||
})
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
fillAgentSelection,
|
||||
}
|
||||
}
|
||||
|
||||
// Vue组件使用示例
|
||||
export const fillAgentSelectionExampleRequest: IFillAgentSelectionRequest = {
|
||||
goal: '开发一个智能协作平台',
|
||||
stepTask: {
|
||||
name: '技术方案设计与开发',
|
||||
content: '设计技术架构并完成核心功能开发',
|
||||
inputs: ['产品需求文档', '技术选型指南'],
|
||||
output: '可运行的产品版本',
|
||||
agents: [],
|
||||
brief: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [],
|
||||
},
|
||||
agents: ['架构师', '后端工程师', '前端工程师', '测试工程师'],
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onUnmounted, ref, reactive, nextTick } from 'vue'
|
||||
import { computed, onUnmounted, ref, reactive, nextTick, watch, onMounted } from 'vue'
|
||||
import { throttle } from 'lodash'
|
||||
import { AnchorLocations, BezierConnector } from '@jsplumb/browser-ui'
|
||||
import AdditionalOutputCard from './AdditionalOutputCard.vue'
|
||||
@@ -19,12 +19,9 @@ const emit = defineEmits<{
|
||||
|
||||
const agentsStore = useAgentsStore()
|
||||
const drawerVisible = ref(false)
|
||||
const collaborationProcess = computed(() => {
|
||||
const data = agentsStore.agentRawPlan.data?.['Collaboration Process'] ?? []
|
||||
// console.log('data:', data)
|
||||
return data
|
||||
|
||||
// return agentsStore.agentRawPlan.data?.['Collaboration Process'] ?? []
|
||||
const collaborationProcess = computed(() => {
|
||||
return agentsStore.agentRawPlan.data?.['Collaboration Process'] ?? []
|
||||
})
|
||||
|
||||
// 监听额外产物变化
|
||||
@@ -201,6 +198,12 @@ async function handleTaskProcess() {
|
||||
drawerVisible.value = true
|
||||
}
|
||||
|
||||
// 重置执行结果
|
||||
function handleRefresh() {
|
||||
agentsStore.setExecutePlan([])
|
||||
console.log('🔄 已重置执行结果')
|
||||
}
|
||||
|
||||
// 添加滚动状态标识
|
||||
const isScrolling = ref(false)
|
||||
let scrollTimer: ReturnType<typeof setTimeout> | null = null
|
||||
@@ -226,20 +229,58 @@ const handleMouseEnter = throttle(id => {
|
||||
if (!isScrolling.value) {
|
||||
createInternalLine(id)
|
||||
}
|
||||
}, 100)
|
||||
}, 0)
|
||||
|
||||
const handleMouseLeave = throttle(() => {
|
||||
if (!isScrolling.value) {
|
||||
createInternalLine()
|
||||
}
|
||||
}, 100)
|
||||
}, 0)
|
||||
|
||||
function clear() {
|
||||
jsplumb.reset()
|
||||
}
|
||||
|
||||
// 🆕 封装连线重绘方法
|
||||
const redrawInternalLines = (highlightId?: string) => {
|
||||
console.log('🔄 TaskResult: 重新绘制连线', highlightId ? `高亮: ${highlightId}` : '')
|
||||
|
||||
// 等待 DOM 更新完成
|
||||
nextTick(() => {
|
||||
// 清除旧连线
|
||||
jsplumb.reset()
|
||||
|
||||
// 等待 DOM 稳定后重新绘制
|
||||
setTimeout(() => {
|
||||
createInternalLine(highlightId)
|
||||
console.log('✅ TaskResult: 连线重绘完成,任务数:', collaborationProcess.value.length)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
// 🆕 监听 collaborationProcess 变化,自动重绘连线
|
||||
watch(
|
||||
() => collaborationProcess,
|
||||
() => {
|
||||
console.log('🔍 TaskResult: collaborationProcess 发生变化,触发重绘')
|
||||
redrawInternalLines()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 🆕 组件挂载后初始化连线
|
||||
onMounted(() => {
|
||||
// 初始化时绘制连线
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
createInternalLine()
|
||||
console.log('✅ TaskResult: 初始化连线完成')
|
||||
}, 100)
|
||||
})
|
||||
})
|
||||
|
||||
//按钮交互状态管理
|
||||
const buttonHoverState = ref<'process' | 'execute' | null>(null)
|
||||
const buttonHoverState = ref<'process' | 'execute' | 'refresh' | null>(null)
|
||||
let buttonHoverTimer: ReturnType<typeof setTimeout> | null = null
|
||||
const handleProcessMouseEnter = () => {
|
||||
if (buttonHoverTimer) {
|
||||
@@ -259,6 +300,16 @@ const handleExecuteMouseEnter = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleRefreshMouseEnter = () => {
|
||||
if (buttonHoverTimer) {
|
||||
clearTimeout(buttonHoverTimer)
|
||||
buttonHoverTimer = null
|
||||
}
|
||||
if (agentsStore.executePlan.length > 0) {
|
||||
buttonHoverState.value = 'refresh'
|
||||
}
|
||||
}
|
||||
|
||||
const handleButtonMouseLeave = () => {
|
||||
// 添加防抖,防止快速切换时的抖动
|
||||
if (buttonHoverTimer) {
|
||||
@@ -277,18 +328,31 @@ onUnmounted(() => {
|
||||
})
|
||||
// 计算按钮类名
|
||||
const processBtnClass = computed(() => {
|
||||
// 当刷新或执行按钮悬停时,过程按钮变圆形
|
||||
if (buttonHoverState.value === 'refresh' || buttonHoverState.value === 'execute') {
|
||||
return 'circle'
|
||||
}
|
||||
return buttonHoverState.value === 'process' ? 'ellipse' : 'circle'
|
||||
})
|
||||
|
||||
const executeBtnClass = computed(() => {
|
||||
// 鼠标悬停在过程按钮上时,执行按钮变圆形
|
||||
if (buttonHoverState.value === 'process') {
|
||||
// 鼠标悬停在过程按钮或刷新按钮上时,执行按钮变圆形
|
||||
if (buttonHoverState.value === 'process' || buttonHoverState.value === 'refresh') {
|
||||
return 'circle'
|
||||
}
|
||||
//如果有任务数据就显示椭圆形,否则显示圆形
|
||||
return agentsStore.agentRawPlan.data ? 'ellipse' : 'circle'
|
||||
})
|
||||
|
||||
const refreshBtnClass = computed(() => {
|
||||
// 当过程或执行按钮悬停时,刷新按钮变圆形
|
||||
if (buttonHoverState.value === 'process' || buttonHoverState.value === 'execute') {
|
||||
return 'circle'
|
||||
}
|
||||
// 有执行结果就显示椭圆形,否则显示圆形
|
||||
return agentsStore.executePlan.length > 0 ? 'ellipse' : 'circle'
|
||||
})
|
||||
|
||||
// 计算按钮是否显示文字
|
||||
const showProcessText = computed(() => {
|
||||
return buttonHoverState.value === 'process'
|
||||
@@ -301,6 +365,10 @@ const showExecuteText = computed(() => {
|
||||
return agentsStore.agentRawPlan.data
|
||||
})
|
||||
|
||||
const showRefreshText = computed(() => {
|
||||
return buttonHoverState.value === 'refresh'
|
||||
})
|
||||
|
||||
// 计算按钮标题
|
||||
const processBtnTitle = computed(() => {
|
||||
return buttonHoverState.value === 'process' ? '任务过程' : '点击查看任务过程'
|
||||
@@ -310,6 +378,10 @@ const executeBtnTitle = computed(() => {
|
||||
return showExecuteText.value ? '任务执行' : '点击运行'
|
||||
})
|
||||
|
||||
const refreshBtnTitle = computed(() => {
|
||||
return showRefreshText.value ? '重置执行结果' : '点击重置执行状态'
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
createInternalLine,
|
||||
clear
|
||||
@@ -329,6 +401,19 @@ defineExpose({
|
||||
class="flex items-center justify-end gap-[14px] task-button-group min-w-[175px]"
|
||||
@mouseleave="handleButtonMouseLeave"
|
||||
>
|
||||
<!-- 刷新按钮 -->
|
||||
<el-button
|
||||
:class="refreshBtnClass"
|
||||
:color="variables.tertiary"
|
||||
:title="refreshBtnTitle"
|
||||
:disabled="agentsStore.executePlan.length === 0"
|
||||
@mouseenter="handleRefreshMouseEnter"
|
||||
@click="handleRefresh"
|
||||
style="order: 0"
|
||||
>
|
||||
<svg-icon icon-class="refresh" />
|
||||
<span v-if="showRefreshText" class="btn-text">重置</span>
|
||||
</el-button>
|
||||
<!-- 任务过程按钮 -->
|
||||
<el-button
|
||||
:class="processBtnClass"
|
||||
@@ -680,21 +765,33 @@ defineExpose({
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
transition: all 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
|
||||
transition: width 0.2s ease-out, padding 0.2s ease-out, border-radius 0.2s ease-out, transform 0.2s ease-out, box-shadow 0.2s ease-out, filter 0.2s ease-out !important;
|
||||
overflow: hidden !important;
|
||||
white-space: nowrap !important;
|
||||
border: none !important;
|
||||
border: 1px solid transparent !important;
|
||||
border-color: transparent !important;
|
||||
color: var(--color-text-primary) !important;
|
||||
position: relative;
|
||||
background-color: var(--color-bg-tertiary);
|
||||
background-color: var(--color-bg-tertiary) !important;
|
||||
gap: 0px !important;
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
-webkit-tap-highlight-color: transparent !important;
|
||||
backface-visibility: hidden !important;
|
||||
-webkit-backface-visibility: hidden !important;
|
||||
transform: translateZ(0) !important;
|
||||
will-change: transform, width, padding, border-radius !important;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px) !important;
|
||||
transform: translateY(-2px) translateZ(0) !important;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
|
||||
filter: brightness(1.1) !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,57 +9,23 @@
|
||||
|
||||
<el-card
|
||||
class="task-node-card"
|
||||
:class="{ 'is-editing': isEditing, 'is-active': isActive }"
|
||||
:class="{
|
||||
'is-editing': isEditing,
|
||||
'is-active': isActive,
|
||||
'is-branch-selected': props.isBranchSelected
|
||||
}"
|
||||
:shadow="true"
|
||||
>
|
||||
<!-- 任务名称 -->
|
||||
<div class="task-name">{{ task.StepName }}</div>
|
||||
|
||||
<!-- <div class="divider"></div> -->
|
||||
|
||||
<!-- 任务内容 -->
|
||||
<!-- <div v-if="isEditing" class="task-content-editing">
|
||||
<el-input
|
||||
v-model="editingContent"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||
placeholder="请输入任务内容"
|
||||
@keydown="handleKeydown"
|
||||
class="task-content-editor"
|
||||
size="small"
|
||||
/>
|
||||
<div class="edit-actions">
|
||||
<svg-icon
|
||||
icon-class="Check"
|
||||
size="18px"
|
||||
color="#328621"
|
||||
class="cursor-pointer"
|
||||
@click="saveEdit"
|
||||
title="保存"
|
||||
/>
|
||||
<svg-icon
|
||||
icon-class="Cancel"
|
||||
size="18px"
|
||||
color="#8e0707"
|
||||
class="cursor-pointer ml-2"
|
||||
@click="cancelEdit"
|
||||
title="取消"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="task-content" @dblclick="startEdit">
|
||||
{{ task.TaskContent || '暂无内容' }}
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="divider"></div> -->
|
||||
|
||||
<!-- 智能体列表 -->
|
||||
<div class="agents-container">
|
||||
<el-tooltip
|
||||
v-for="agentSelection in task.AgentSelection"
|
||||
:key="agentSelection"
|
||||
effect="light"
|
||||
placement="right"
|
||||
placement="top"
|
||||
:show-after="500"
|
||||
popper-class="task-syllabus-tooltip-popper"
|
||||
>
|
||||
@@ -137,6 +103,7 @@ const props = defineProps<{
|
||||
id: string
|
||||
data: TaskNodeData
|
||||
isAddingBranch?: boolean
|
||||
isBranchSelected?: boolean // 是否属于选中的分支路径
|
||||
[key: string]: any
|
||||
}>()
|
||||
|
||||
@@ -250,6 +217,19 @@ const handleBranchKeydown = (event: KeyboardEvent) => {
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
// 分支选中高亮样式(绿色)
|
||||
&.is-branch-selected {
|
||||
border-color: #67c23a;
|
||||
box-shadow: 0 0 0 3px rgba(103, 194, 58, 0.3);
|
||||
background-color: rgba(103, 194, 58, 0.05);
|
||||
|
||||
&:hover {
|
||||
border-color: #67c23a;
|
||||
box-shadow: 0 0 0 3px rgba(103, 194, 58, 0.4);
|
||||
background-color: rgba(103, 194, 58, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-editing {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@@ -1,203 +1,246 @@
|
||||
// branch_PlanOutline 接口返回的 mock 数据
|
||||
// 类型: IApiStepTask[][] (二维数组)
|
||||
// branch_PlanOutline 接口的 Mock 数据和 Mock API
|
||||
// 模拟后端返回的原始数据格式(IRawPlanResponse)
|
||||
|
||||
import type { IApiStepTask } from '@/stores/modules/agents'
|
||||
import type { IRawPlanResponse, IRawStepTask } from '@/stores'
|
||||
|
||||
const mockPlanBranchData: IApiStepTask[][] = [
|
||||
// 后端返回的数据格式
|
||||
export type BranchPlanOutlineResponse = IRawPlanResponse
|
||||
|
||||
// Mock 数据:模拟后端返回的原始分支数据(不含 Collaboration_Brief_FrontEnd)
|
||||
// 注意:这里模拟的是 branch_PlanOutline 函数返回的数据,不是前端转换后的数据
|
||||
const mockBranchDataRaw: IRawStepTask[][] = [
|
||||
// 第一个分支方案
|
||||
[
|
||||
{
|
||||
name: '需求分析与规划',
|
||||
content: '分析用户需求,制定项目开发计划',
|
||||
inputs: ['用户需求文档', '技术规范'],
|
||||
output: '项目开发计划书',
|
||||
agents: ['腐蚀机理研究员', '实验材料学家'],
|
||||
brief: {
|
||||
template: '!<项目经理>!负责!<需求分析>!,!<产品经理>!负责!<规划制定>!',
|
||||
data: {
|
||||
项目经理: { text: '项目经理', style: { background: 'hsl(210, 70%, 50%)' } },
|
||||
需求分析: { text: '需求分析', style: { background: 'hsl(120, 70%, 50%)' } },
|
||||
产品经理: { text: '产品经理', style: { background: 'hsl(30, 70%, 50%)' } },
|
||||
规划制定: { text: '规划制定', style: { background: 'hsl(300, 70%, 50%)' } },
|
||||
},
|
||||
StepName: '分析用户需求',
|
||||
TaskContent: '分析用户需求,制定项目开发计划',
|
||||
InputObject_List: ['腐蚀类型及成因列表'],
|
||||
OutputObject: '项目开发计划书',
|
||||
AgentSelection: ['腐蚀机理研究员', '实验材料学家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action-1',
|
||||
type: '分析',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '详细分析用户需求文档',
|
||||
inputs: ['用户需求文档'],
|
||||
},
|
||||
{
|
||||
id: 'action-2',
|
||||
type: '规划',
|
||||
agent: '实验材料学家',
|
||||
description: '制定项目开发计划',
|
||||
inputs: ['技术规范'],
|
||||
},
|
||||
],
|
||||
TaskProcess: [],
|
||||
},
|
||||
{
|
||||
name: '系统设计与架构',
|
||||
content: '设计系统架构和数据库结构',
|
||||
inputs: ['项目开发计划书'],
|
||||
output: '系统设计文档',
|
||||
agents: ['腐蚀机理研究员', '防护工程专家'],
|
||||
brief: {
|
||||
template: '!<架构师>!负责!<系统架构设计>!,!<数据库工程师>!负责!<数据库设计>!',
|
||||
data: {
|
||||
架构师: { text: '架构师', style: { background: 'hsl(180, 70%, 50%)' } },
|
||||
系统架构设计: { text: '系统架构设计', style: { background: 'hsl(240, 70%, 50%)' } },
|
||||
数据库工程师: { text: '数据库工程师', style: { background: 'hsl(60, 70%, 50%)' } },
|
||||
数据库设计: { text: '数据库设计', style: { background: 'hsl(0, 70%, 50%)' } },
|
||||
},
|
||||
StepName: '系统设计与架构',
|
||||
TaskContent: '设计系统架构和数据库结构',
|
||||
InputObject_List: ['项目开发计划书'],
|
||||
OutputObject: '系统设计文档',
|
||||
AgentSelection: ['腐蚀机理研究员', '防护工程专家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action-3',
|
||||
type: '设计',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '设计系统整体架构',
|
||||
inputs: ['项目开发计划书'],
|
||||
},
|
||||
{
|
||||
id: 'action-4',
|
||||
type: '设计',
|
||||
agent: '防护工程专家',
|
||||
description: '设计数据库表结构',
|
||||
inputs: ['项目开发计划书'],
|
||||
},
|
||||
],
|
||||
TaskProcess: [],
|
||||
},
|
||||
],
|
||||
|
||||
// 第二个分支方案(替代方案)
|
||||
// 第二个分支方案(快速原型方案)
|
||||
[
|
||||
{
|
||||
name: '敏捷开发规划',
|
||||
content: '采用敏捷开发方法制定迭代计划',
|
||||
inputs: ['用户需求文档', '敏捷开发指南'],
|
||||
output: '敏捷开发迭代计划',
|
||||
agents: ['敏捷教练', '开发团队负责人'],
|
||||
brief: {
|
||||
template: '!<敏捷教练>!指导!<敏捷流程>!,!<开发团队负责人>!制定!<迭代计划>!',
|
||||
data: {
|
||||
敏捷教练: { text: '敏捷教练', style: { background: 'hsl(270, 70%, 50%)' } },
|
||||
敏捷流程: { text: '敏捷流程', style: { background: 'hsl(90, 70%, 50%)' } },
|
||||
开发团队负责人: { text: '开发团队负责人', style: { background: 'hsl(150, 70%, 50%)' } },
|
||||
迭代计划: { text: '迭代计划', style: { background: 'hsl(330, 70%, 50%)' } },
|
||||
},
|
||||
StepName: '需求快速原型',
|
||||
TaskContent: '构建快速原型验证核心功能',
|
||||
InputObject_List: ['腐蚀类型及成因列表'],
|
||||
OutputObject: '原型系统',
|
||||
AgentSelection: ['实验材料学家', '防护工程专家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action-5',
|
||||
type: '指导',
|
||||
agent: '敏捷教练',
|
||||
description: '指导敏捷开发流程',
|
||||
inputs: ['敏捷开发指南'],
|
||||
},
|
||||
{
|
||||
id: 'action-6',
|
||||
type: '规划',
|
||||
agent: '开发团队负责人',
|
||||
description: '制定迭代开发计划',
|
||||
inputs: ['用户需求文档'],
|
||||
},
|
||||
],
|
||||
TaskProcess: [],
|
||||
},
|
||||
{
|
||||
name: '微服务架构设计',
|
||||
content: '设计基于微服务的系统架构',
|
||||
inputs: ['敏捷开发迭代计划'],
|
||||
output: '微服务架构设计文档',
|
||||
agents: ['微服务架构师', 'DevOps工程师'],
|
||||
brief: {
|
||||
template: '!<微服务架构师>!设计!<微服务架构>!,!<DevOps工程师>!规划!<部署流程>!',
|
||||
data: {
|
||||
微服务架构师: { text: '微服务架构师', style: { background: 'hsl(210, 70%, 50%)' } },
|
||||
微服务架构: { text: '微服务架构', style: { background: 'hsl(120, 70%, 50%)' } },
|
||||
DevOps工程师: { text: 'DevOps工程师', style: { background: 'hsl(30, 70%, 50%)' } },
|
||||
部署流程: { text: '部署流程', style: { background: 'hsl(300, 70%, 50%)' } },
|
||||
},
|
||||
StepName: '原型测试与优化',
|
||||
TaskContent: '测试原型并根据反馈快速迭代',
|
||||
InputObject_List: ['原型系统'],
|
||||
OutputObject: '优化后的原型',
|
||||
AgentSelection: ['腐蚀机理研究员', '实验材料学家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action-7',
|
||||
type: '设计',
|
||||
agent: '微服务架构师',
|
||||
description: '设计微服务拆分方案',
|
||||
inputs: ['敏捷开发迭代计划'],
|
||||
},
|
||||
{
|
||||
id: 'action-8',
|
||||
type: '规划',
|
||||
agent: 'DevOps工程师',
|
||||
description: '规划CI/CD部署流程',
|
||||
inputs: ['敏捷开发迭代计划'],
|
||||
},
|
||||
],
|
||||
TaskProcess: [],
|
||||
},
|
||||
],
|
||||
|
||||
// 第三个分支方案(简化方案)
|
||||
// 第三个分支方案(质量优先方案)
|
||||
[
|
||||
{
|
||||
name: '快速原型开发',
|
||||
content: '快速开发系统原型验证需求',
|
||||
inputs: ['用户需求文档'],
|
||||
output: '系统原型',
|
||||
agents: ['全栈开发工程师'],
|
||||
brief: {
|
||||
template: '!<全栈开发工程师>!负责!<快速原型开发>!',
|
||||
data: {
|
||||
全栈开发工程师: { text: '全栈开发工程师', style: { background: 'hsl(180, 70%, 50%)' } },
|
||||
快速原型开发: { text: '快速原型开发', style: { background: 'hsl(240, 70%, 50%)' } },
|
||||
},
|
||||
StepName: '需求深度分析',
|
||||
TaskContent: '深入分析用户需求和技术可行性',
|
||||
InputObject_List: ['腐蚀类型及成因列表'],
|
||||
OutputObject: '详细需求分析报告',
|
||||
AgentSelection: ['腐蚀机理研究员', '防护工程专家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action-9',
|
||||
type: '开发',
|
||||
agent: '全栈开发工程师',
|
||||
description: '快速开发系统原型',
|
||||
inputs: ['用户需求文档'],
|
||||
},
|
||||
],
|
||||
TaskProcess: [],
|
||||
},
|
||||
{
|
||||
name: '用户反馈收集',
|
||||
content: '收集用户对原型的反馈意见',
|
||||
inputs: ['系统原型'],
|
||||
output: '用户反馈报告',
|
||||
agents: ['产品经理', '用户体验设计师'],
|
||||
brief: {
|
||||
template: '!<产品经理>!收集!<用户反馈>!,!<用户体验设计师>!分析!<用户体验>!',
|
||||
data: {
|
||||
产品经理: { text: '产品经理', style: { background: 'hsl(60, 70%, 50%)' } },
|
||||
用户反馈: { text: '用户反馈', style: { background: 'hsl(0, 70%, 50%)' } },
|
||||
用户体验设计师: { text: '用户体验设计师', style: { background: 'hsl(270, 70%, 50%)' } },
|
||||
用户体验: { text: '用户体验', style: { background: 'hsl(90, 70%, 50%)' } },
|
||||
},
|
||||
StepName: '质量保障设计',
|
||||
TaskContent: '设计质量保障体系和测试方案',
|
||||
InputObject_List: ['详细需求分析报告'],
|
||||
OutputObject: '质量保障方案',
|
||||
AgentSelection: ['实验材料学家', '防护工程专家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
process: [
|
||||
{
|
||||
id: 'action-10',
|
||||
type: '收集',
|
||||
agent: '产品经理',
|
||||
description: '收集用户对原型的反馈',
|
||||
inputs: ['系统原型'],
|
||||
},
|
||||
{
|
||||
id: 'action-11',
|
||||
type: '分析',
|
||||
agent: '用户体验设计师',
|
||||
description: '分析用户体验问题',
|
||||
inputs: ['系统原型'],
|
||||
},
|
||||
],
|
||||
TaskProcess: [],
|
||||
},
|
||||
{
|
||||
StepName: '系统开发与测试',
|
||||
TaskContent: '按质量标准进行系统开发和测试',
|
||||
InputObject_List: ['质量保障方案'],
|
||||
OutputObject: '经过完整测试的系统',
|
||||
AgentSelection: ['腐蚀机理研究员', '实验材料学家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
TaskProcess: [],
|
||||
},
|
||||
],
|
||||
// 第四个分支方案(敏捷开发方案)
|
||||
[
|
||||
{
|
||||
StepName: '迭代规划',
|
||||
TaskContent: '制定敏捷开发迭代计划',
|
||||
InputObject_List: ['腐蚀类型及成因列表'],
|
||||
OutputObject: '迭代计划',
|
||||
AgentSelection: ['防护工程专家', '腐蚀机理研究员'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
TaskProcess: [],
|
||||
},
|
||||
{
|
||||
StepName: '快速开发与验证',
|
||||
TaskContent: '快速开发并持续验证功能',
|
||||
InputObject_List: ['迭代计划'],
|
||||
OutputObject: '可运行的功能模块',
|
||||
AgentSelection: ['实验材料学家', '防护工程专家'],
|
||||
Collaboration_Brief_frontEnd: {
|
||||
template: '',
|
||||
data: {},
|
||||
},
|
||||
TaskProcess: [],
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
export default mockPlanBranchData
|
||||
/**
|
||||
* 模拟后端的 Add_Collaboration_Brief_FrontEnd 函数
|
||||
* 为每个任务添加前端协作简报(Collaboration_Brief_frontEnd)
|
||||
*/
|
||||
function Add_Collaboration_Brief_FrontEnd(branchList: IRawStepTask[][]): IRawStepTask[][] {
|
||||
return branchList.map((tasks) =>
|
||||
tasks.map((task) => ({
|
||||
...task,
|
||||
Collaboration_Brief_frontEnd: generateCollaborationBrief(task),
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成协作简报(Collaboration_Brief_frontEnd)
|
||||
* 根据 StepName、TaskContent、AgentSelection 生成模板和数据
|
||||
*/
|
||||
function generateCollaborationBrief(task: IRawStepTask): {
|
||||
template: string
|
||||
data: Record<string, any>
|
||||
} {
|
||||
const agents = task.AgentSelection || []
|
||||
const stepName = task.StepName || ''
|
||||
|
||||
// 为每个 agent 生成颜色
|
||||
const colors = [
|
||||
'hsl(210, 70%, 50%)',
|
||||
'hsl(30, 70%, 50%)',
|
||||
'hsl(120, 70%, 50%)',
|
||||
'hsl(270, 70%, 50%)',
|
||||
]
|
||||
|
||||
// 生成 data 对象
|
||||
const data: Record<string, any> = {}
|
||||
agents.forEach((agent, index) => {
|
||||
data[agent] = {
|
||||
text: agent,
|
||||
style: { background: colors[index % colors.length] },
|
||||
}
|
||||
})
|
||||
|
||||
// 生成 template(简化版本,实际应根据任务内容生成)
|
||||
const template =
|
||||
agents.length > 0
|
||||
? agents.map((agent, i) => `!<${agent}>!负责!<${stepName}-${i}>!`).join(',')
|
||||
: ''
|
||||
|
||||
return {
|
||||
template,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock API:模拟后端 branch_PlanOutline 接口调用
|
||||
*
|
||||
* @param branch_Number - 分支数量
|
||||
* @param Modification_Requirement - 修改需求
|
||||
* @param Existing_Steps - 现有步骤名称列表
|
||||
* @param Baseline_Completion - 基线完成度
|
||||
* @param InitialObject_List - 初始对象列表
|
||||
* @param General_Goal - 总体目标
|
||||
* @returns Promise<IRawPlanResponse> - 返回包含 'Collaboration Process' 的响应
|
||||
*/
|
||||
export const mockBranchPlanOutlineAPI = async (params: {
|
||||
branch_Number: number
|
||||
Modification_Requirement: string
|
||||
Existing_Steps: string[]
|
||||
Baseline_Completion: number
|
||||
InitialObject_List: string[]
|
||||
General_Goal: string
|
||||
}): Promise<IRawPlanResponse> => {
|
||||
// 模拟网络延迟 800ms
|
||||
await new Promise((resolve) => setTimeout(resolve, 800))
|
||||
|
||||
console.log('[Mock API] branch_PlanOutline 调用参数:', params)
|
||||
|
||||
// 🆕 使用轮询方式选择分支方案(依次循环使用所有分支方案)
|
||||
const totalBranches = mockBranchDataRaw.length
|
||||
const sessionKey = `branch-plan-outline-index-${params.General_Goal || 'default'}`
|
||||
|
||||
// 获取上一次的选择索引
|
||||
let lastIndex = parseInt(sessionStorage.getItem(sessionKey) || '0')
|
||||
|
||||
// 计算本次的选择索引(轮询到下一个分支)
|
||||
const selectedBranchIndex = (lastIndex + 1) % totalBranches
|
||||
|
||||
// 保存本次的选择索引
|
||||
sessionStorage.setItem(sessionKey, selectedBranchIndex.toString())
|
||||
|
||||
const rawBranchData = mockBranchDataRaw[selectedBranchIndex]
|
||||
|
||||
console.log(
|
||||
'[Mock API] branch_PlanOutline 选择分支方案:',
|
||||
selectedBranchIndex + 1,
|
||||
'/',
|
||||
totalBranches,
|
||||
)
|
||||
|
||||
// 模拟后端处理:添加 Collaboration_Brief_FrontEnd
|
||||
const processedBranches = Add_Collaboration_Brief_FrontEnd([rawBranchData])
|
||||
|
||||
// 构造响应数据(符合后端返回格式)
|
||||
const response: IRawPlanResponse = {
|
||||
'Collaboration Process': processedBranches[0] || [],
|
||||
}
|
||||
|
||||
console.log('[Mock API] branch_PlanOutline 返回数据:', response)
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
export default mockBranchPlanOutlineAPI
|
||||
|
||||
@@ -1,189 +1,155 @@
|
||||
// branch_TaskProcess 接口返回的 mock 数据
|
||||
// 类型: IApiAgentAction[][] (二维数组)
|
||||
// branch_TaskProcess 接口的 Mock 数据和 Mock API
|
||||
export interface BranchAction {
|
||||
ID: string
|
||||
ActionType: string
|
||||
AgentName: string
|
||||
Description: string
|
||||
ImportantInput: string[]
|
||||
}
|
||||
|
||||
import type { IApiAgentAction } from '@/stores/modules/agents'
|
||||
export type BranchTaskProcessResponse = BranchAction[][]
|
||||
|
||||
const mockTaskProcessData: IApiAgentAction[][] = [
|
||||
// Mock 数据:模拟后端返回的原始任务流程数据(2D 数组)
|
||||
// 格式:[[action1, action2], [action3, action4]]
|
||||
const mockBranchTaskProcessDataRaw: BranchAction[][] = [
|
||||
// 第一个任务分支方案
|
||||
[
|
||||
{
|
||||
id: 'analyze-requirements-1',
|
||||
type: '分析',
|
||||
agent: '实验材料学家',
|
||||
description: '详细分析用户需求文档',
|
||||
inputs: ['用户需求文档'],
|
||||
ID: 'agent3',
|
||||
ActionType: 'Critique',
|
||||
AgentName: '实验材料学家',
|
||||
Description: '详细分析用户需求文档',
|
||||
ImportantInput: ['agent2'],
|
||||
},
|
||||
{
|
||||
id: 'design-architecture-1',
|
||||
type: '设计',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '设计系统整体架构',
|
||||
inputs: ['需求分析结果'],
|
||||
ID: 'agent4',
|
||||
ActionType: 'Critique',
|
||||
AgentName: '腐蚀机理研究员',
|
||||
Description: '设计系统整体架构',
|
||||
ImportantInput: ['agent3'],
|
||||
},
|
||||
{
|
||||
id: 'implement-core-1',
|
||||
type: '实现',
|
||||
agent: '防护工程专家',
|
||||
description: '实现系统核心功能',
|
||||
inputs: ['系统架构设计'],
|
||||
ID: 'agent5',
|
||||
ActionType: 'Improve',
|
||||
AgentName: '防护工程专家',
|
||||
Description: '实现系统核心功能',
|
||||
ImportantInput: ['agent4'],
|
||||
},
|
||||
{
|
||||
id: 'test-system-1',
|
||||
type: '测试',
|
||||
agent: '实验材料学家',
|
||||
description: '进行系统集成测试',
|
||||
inputs: ['系统核心功能'],
|
||||
ID: 'agent6',
|
||||
ActionType: 'Finalize',
|
||||
AgentName: '实验材料学家',
|
||||
Description: '进行系统集成测试',
|
||||
ImportantInput: ['agent5'],
|
||||
},
|
||||
],
|
||||
// 第二个任务分支方案
|
||||
[
|
||||
{
|
||||
ID: 'agent7',
|
||||
ActionType: 'Critique',
|
||||
AgentName: '实验材料学家',
|
||||
Description: '深入分析用户需求和技术约束',
|
||||
ImportantInput: ['agent2'],
|
||||
},
|
||||
{
|
||||
ID: 'agent8',
|
||||
ActionType: 'Critique',
|
||||
AgentName: '防护工程专家',
|
||||
Description: '设计系统技术架构和数据流',
|
||||
ImportantInput: ['agent8'],
|
||||
},
|
||||
{
|
||||
ID: 'agent9',
|
||||
ActionType: 'Improve',
|
||||
AgentName: '腐蚀机理研究员',
|
||||
Description: '评估系统安全性',
|
||||
ImportantInput: ['agent4'],
|
||||
},
|
||||
{
|
||||
ID: 'agent10',
|
||||
ActionType: 'Finalize',
|
||||
AgentName: '实验材料学家',
|
||||
Description: '完成系统安全测试',
|
||||
ImportantInput: ['agent9'],
|
||||
},
|
||||
],
|
||||
|
||||
// 第二个任务分支方案(替代方案)
|
||||
//第三个任务分支方案
|
||||
[
|
||||
{
|
||||
id: 'quick-prototype-2',
|
||||
type: '原型',
|
||||
agent: '实验材料学家',
|
||||
description: '快速开发系统原型',
|
||||
inputs: ['用户需求文档'],
|
||||
ID: 'agent12',
|
||||
ActionType: 'Critique',
|
||||
AgentName: '腐蚀机理研究员',
|
||||
Description: '设计系统整体架构',
|
||||
ImportantInput: ['agent11'],
|
||||
},
|
||||
{
|
||||
id: 'user-feedback-2',
|
||||
type: '收集',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '收集用户对原型的反馈',
|
||||
inputs: ['系统原型'],
|
||||
ID: 'agent13',
|
||||
ActionType: 'Improve',
|
||||
AgentName: '防护工程专家',
|
||||
Description: '实现系统核心功能',
|
||||
ImportantInput: ['agent12'],
|
||||
},
|
||||
{
|
||||
id: 'iterate-design-2',
|
||||
type: '迭代',
|
||||
agent: '防护工程专家',
|
||||
description: '根据反馈迭代设计',
|
||||
inputs: ['用户反馈'],
|
||||
},
|
||||
{
|
||||
id: 'final-implement-2',
|
||||
type: '实现',
|
||||
agent: '实验材料学家',
|
||||
description: '实现最终用户界面',
|
||||
inputs: ['迭代设计稿'],
|
||||
},
|
||||
],
|
||||
|
||||
// 第三个任务分支方案(敏捷开发方案)
|
||||
[
|
||||
{
|
||||
id: 'sprint-planning-3',
|
||||
type: '规划',
|
||||
agent: '实验材料学家',
|
||||
description: '制定冲刺计划',
|
||||
inputs: ['用户故事', '技术债务'],
|
||||
},
|
||||
{
|
||||
id: 'code-review-3',
|
||||
type: '评审',
|
||||
agent: '防护工程专家',
|
||||
description: '进行代码审查',
|
||||
inputs: ['开发代码'],
|
||||
},
|
||||
{
|
||||
id: 'unit-test-3',
|
||||
type: '测试',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '编写单元测试',
|
||||
inputs: ['功能代码'],
|
||||
},
|
||||
{
|
||||
id: 'deploy-staging-3',
|
||||
type: '部署',
|
||||
agent: '实验材料学家',
|
||||
description: '部署到测试环境',
|
||||
inputs: ['测试通过代码'],
|
||||
},
|
||||
{
|
||||
id: 'acceptance-test-3',
|
||||
type: '验收',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '进行验收测试',
|
||||
inputs: ['测试环境系统'],
|
||||
},
|
||||
],
|
||||
|
||||
// 第四个任务分支方案(微服务方案)
|
||||
[
|
||||
{
|
||||
id: 'service-split-4',
|
||||
type: '拆分',
|
||||
agent: '实验材料学家',
|
||||
description: '拆分单体应用为微服务',
|
||||
inputs: ['单体应用代码'],
|
||||
},
|
||||
{
|
||||
id: 'api-design-4',
|
||||
type: '设计',
|
||||
agent: '防护工程专家',
|
||||
description: '设计微服务API接口',
|
||||
inputs: ['服务拆分方案'],
|
||||
},
|
||||
{
|
||||
id: 'service-implement-4',
|
||||
type: '实现',
|
||||
agent: '防护工程专家',
|
||||
description: '实现各个微服务',
|
||||
inputs: ['API设计文档'],
|
||||
},
|
||||
{
|
||||
id: 'orchestration-4',
|
||||
type: '编排',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '配置服务编排和负载均衡',
|
||||
inputs: ['微服务实现'],
|
||||
},
|
||||
{
|
||||
id: 'monitoring-setup-4',
|
||||
type: '监控',
|
||||
agent: '实验材料学家',
|
||||
description: '设置监控和日志系统',
|
||||
inputs: ['运行中的微服务'],
|
||||
},
|
||||
],
|
||||
|
||||
// 第五个任务分支方案(数据驱动方案)
|
||||
[
|
||||
{
|
||||
id: 'data-analysis-5',
|
||||
type: '分析',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '分析业务数据和需求',
|
||||
inputs: ['业务数据', '用户行为数据'],
|
||||
},
|
||||
{
|
||||
id: 'ml-model-5',
|
||||
type: '建模',
|
||||
agent: '实验材料学家',
|
||||
description: '构建预测模型',
|
||||
inputs: ['分析结果', '历史数据'],
|
||||
},
|
||||
{
|
||||
id: 'data-pipeline-5',
|
||||
type: '构建',
|
||||
agent: '防护工程专家',
|
||||
description: '构建数据处理流水线',
|
||||
inputs: ['数据源', '模型需求'],
|
||||
},
|
||||
{
|
||||
id: 'api-integration-5',
|
||||
type: '集成',
|
||||
agent: '实验材料学家',
|
||||
description: '集成数据服务到应用',
|
||||
inputs: ['数据处理流水线', '预测模型'],
|
||||
},
|
||||
{
|
||||
id: 'performance-optimize-5',
|
||||
type: '优化',
|
||||
agent: '腐蚀机理研究员',
|
||||
description: '优化系统性能',
|
||||
inputs: ['运行数据', '性能指标'],
|
||||
ID: 'agent14',
|
||||
ActionType: 'Finalize',
|
||||
AgentName: '实验材料学家',
|
||||
Description: '进行系统集成测试',
|
||||
ImportantInput: ['agent13'],
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
export default mockTaskProcessData
|
||||
/**
|
||||
* Mock API:模拟后端 branch_TaskProcess 接口调用
|
||||
*
|
||||
* @param branch_Number - 分支数量
|
||||
* @param Modification_Requirement - 修改需求
|
||||
* @param Existing_Steps - 现有步骤名称列表
|
||||
* @param Baseline_Completion - 基线完成度
|
||||
* @param stepTaskExisting - 现有任务
|
||||
* @param General_Goal - 总体目标
|
||||
* @returns Promise<BranchAction[][]> - 返回 2D 数组,与后端格式完全一致
|
||||
*/
|
||||
export const mockBranchTaskProcessAPI = async (params: {
|
||||
branch_Number: number
|
||||
Modification_Requirement: string
|
||||
Existing_Steps: string[]
|
||||
Baseline_Completion: number
|
||||
stepTaskExisting: any
|
||||
General_Goal: string
|
||||
}): Promise<BranchAction[][]> => {
|
||||
// 模拟网络延迟 800ms
|
||||
await new Promise((resolve) => setTimeout(resolve, 800))
|
||||
|
||||
console.log('[Mock API] branch_TaskProcess 调用参数:', params)
|
||||
|
||||
// 🆕 使用轮询方式选择分支方案(依次循环使用所有分支方案)
|
||||
const totalBranches = mockBranchTaskProcessDataRaw.length
|
||||
const sessionKey = `branch-task-process-index-${params.stepTaskExisting?.Id || 'default'}`
|
||||
|
||||
// 获取上一次的选择索引
|
||||
let lastIndex = parseInt(sessionStorage.getItem(sessionKey) || '0')
|
||||
|
||||
// 计算本次的选择索引(轮询到下一个分支)
|
||||
const selectedBranchIndex = (lastIndex + 1) % totalBranches
|
||||
|
||||
// 保存本次的选择索引
|
||||
sessionStorage.setItem(sessionKey, selectedBranchIndex.toString())
|
||||
|
||||
const rawBranchData = mockBranchTaskProcessDataRaw[selectedBranchIndex] || []
|
||||
|
||||
console.log(
|
||||
'[Mock API] branch_TaskProcess 选择分支方案:',
|
||||
selectedBranchIndex + 1,
|
||||
'/',
|
||||
totalBranches,
|
||||
)
|
||||
console.log('[Mock API] branch_TaskProcess 返回数据:', rawBranchData)
|
||||
|
||||
// 直接返回 2D 数组,与后端格式完全一致
|
||||
return [rawBranchData]
|
||||
}
|
||||
|
||||
export default mockBranchTaskProcessAPI
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@ const scoreDimensions = ref<string[]>([])
|
||||
interface AgentHeatmapData {
|
||||
agentName: string
|
||||
scores: number[] // 各维度的评分
|
||||
scoreDetails?: Array<{ dimension: string; score: number; reason: string }> // 详细信息(可选)
|
||||
scoreDetails?: Array<{ dimension: string; score: number; reason: string }> // 详细信息
|
||||
}
|
||||
|
||||
// 所有agent的热力图数据
|
||||
@@ -57,6 +57,9 @@ const searchValue = ref('')
|
||||
// 标志位:防止重复初始化
|
||||
const isInitializing = ref(false)
|
||||
const isAddingDimension = ref(false)
|
||||
const isLoadingConfirm = ref(false) // 确认 agent 组合时的加载状态
|
||||
const isLoadingSelectGroup = ref(false) // 选择已保存组合时的加载状态
|
||||
const isLoadingInitialTask = ref(false) // 首次加载任务时的加载状态
|
||||
|
||||
// 处理搜索提交
|
||||
const handleSubmit = async () => {
|
||||
@@ -143,19 +146,8 @@ const confirmAgentSelection = async () => {
|
||||
if (selectedAgents.value.size > 0 && currentTask.value?.Id) {
|
||||
const agentArray = Array.from(selectedAgents.value)
|
||||
|
||||
// 检查该agent组合是否已存在(包括初始agent组合和用户添加的组合)
|
||||
// 检查该agent组合是否已存在(统一检查,包括初始组合和用户添加的组合)
|
||||
const existingGroups = agentsStore.getConfirmedAgentGroups(currentTask.value.Id)
|
||||
const initialGroup = currentTaskAgents.value
|
||||
|
||||
// 检查是否与初始组合相同
|
||||
if (areAgentGroupsEqual(agentArray, initialGroup)) {
|
||||
console.log('该agent组合与初始组合相同,只选中卡片,不添加重复')
|
||||
selectedAssignmentGroup.value = [...initialGroup]
|
||||
selectedAgents.value = new Set(initialGroup)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否与已存在的用户添加组合相同
|
||||
const existingDuplicateIndex = existingGroups.findIndex(group =>
|
||||
areAgentGroupsEqual(agentArray, group)
|
||||
)
|
||||
@@ -176,7 +168,8 @@ const confirmAgentSelection = async () => {
|
||||
|
||||
// 调用 Mock API 填充任务流程
|
||||
try {
|
||||
console.log('=== 开始调用 fillStepTaskTaskProcess Mock API ===')
|
||||
isLoadingConfirm.value = true
|
||||
console.log('=== 开始调用 mockFillStepTaskTaskProcess Mock API ===')
|
||||
console.log('1. 当前任务数据 (IRawStepTask 格式):', currentTask.value)
|
||||
console.log('2. 选中的 agents:', agentArray)
|
||||
|
||||
@@ -218,12 +211,14 @@ const confirmAgentSelection = async () => {
|
||||
console.log('✅ Mock API 调用成功,数据已存储到 selectionStore')
|
||||
} catch (error) {
|
||||
console.error('❌ Mock API 调用失败:', error)
|
||||
} finally {
|
||||
isLoadingConfirm.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 点击 Assignment 部分的 agent 组合卡片,更新 Comparison 部分的选中状态
|
||||
const selectAgentGroup = (agentNames: string[]) => {
|
||||
const selectAgentGroup = async (agentNames: string[]) => {
|
||||
// 更新Assignment边框状态
|
||||
selectedAssignmentGroup.value = [...agentNames]
|
||||
|
||||
@@ -237,6 +232,116 @@ const selectAgentGroup = (agentNames: string[]) => {
|
||||
agentsStore.setSelectedAgentGroup(currentTask.value.Id, agentNames)
|
||||
}
|
||||
|
||||
// 🆕 联动更新:更新 currentTask 的 AgentSelection 和 TaskProcess
|
||||
if (currentTask.value?.Id && agentNames.length > 0) {
|
||||
console.log('🔄 开始联动更新 currentTask 的 agent 组合:', agentNames)
|
||||
|
||||
// 从 selectionStore 获取该 agent 组合对应的 TaskProcess 数据
|
||||
let taskProcessData = selectionStore.getAgentTaskProcess(currentTask.value.Id, agentNames)
|
||||
|
||||
// 🆕 如果 selectionStore 中没有数据,自动调用 API 加载
|
||||
if (!taskProcessData) {
|
||||
console.log('⚠️ selectionStore 中没有该组合的 TaskProcess 数据,开始加载...')
|
||||
console.log('📋 当前任务信息:', {
|
||||
taskId: currentTask.value.Id,
|
||||
taskName: currentTask.value.StepName,
|
||||
agents: agentNames
|
||||
})
|
||||
|
||||
try {
|
||||
isLoadingSelectGroup.value = true
|
||||
// 将 IRawStepTask 转换为 IApiStepTask 格式
|
||||
const stepTaskForApi = {
|
||||
name: currentTask.value.StepName || '',
|
||||
content: currentTask.value.TaskContent || '',
|
||||
inputs: currentTask.value.InputObject_List || [],
|
||||
output: currentTask.value.OutputObject || '',
|
||||
agents: agentNames,
|
||||
brief: currentTask.value.Collaboration_Brief_frontEnd || {
|
||||
template: '',
|
||||
data: {}
|
||||
},
|
||||
process: []
|
||||
}
|
||||
|
||||
const goal = agentsStore.agentRawPlan.data?.['General Goal'] || '开发智能协作系统'
|
||||
|
||||
console.log('📤 准备调用 API:', {
|
||||
goal,
|
||||
stepTask: stepTaskForApi,
|
||||
agents: agentNames
|
||||
})
|
||||
|
||||
// 调用 Mock API 加载数据
|
||||
const filledTask = await api.mockFillStepTaskTaskProcess({
|
||||
goal,
|
||||
stepTask: stepTaskForApi,
|
||||
agents: agentNames
|
||||
})
|
||||
|
||||
console.log('🔍 API 返回的完整响应:', filledTask)
|
||||
console.log('🔍 process 数据:', filledTask.process)
|
||||
console.log('🔍 process 长度:', filledTask.process?.length)
|
||||
console.log('✅ TaskProcess 数据加载成功:', {
|
||||
agents: agentNames,
|
||||
processCount: filledTask.process?.length || 0,
|
||||
processDetail: filledTask.process,
|
||||
briefDetail: filledTask.brief
|
||||
})
|
||||
|
||||
// 存储到 selectionStore
|
||||
selectionStore.setAgentTaskProcess(currentTask.value.Id, agentNames, filledTask)
|
||||
|
||||
console.log('💾 数据已存储到 selectionStore,验证存储是否成功...')
|
||||
// 验证存储
|
||||
const storedData = selectionStore.getAgentTaskProcess(currentTask.value.Id, agentNames)
|
||||
console.log('📦 验证存储结果:', storedData ? '成功' : '失败', storedData)
|
||||
|
||||
taskProcessData = filledTask
|
||||
} catch (error) {
|
||||
console.error('❌ 加载 TaskProcess 数据失败:', error)
|
||||
return
|
||||
} finally {
|
||||
isLoadingSelectGroup.value = false
|
||||
}
|
||||
}
|
||||
|
||||
if (taskProcessData) {
|
||||
console.log('✅ 找到 TaskProcess 数据,开始更新 currentTask:', {
|
||||
taskId: currentTask.value.Id,
|
||||
agents: agentNames,
|
||||
processCount: taskProcessData.process?.length || 0,
|
||||
processDetail: taskProcessData.process,
|
||||
briefDetail: taskProcessData.brief
|
||||
})
|
||||
|
||||
// 🆕 数据格式转换:IApiAgentAction[] → TaskProcess[]
|
||||
const convertedTaskProcess = (taskProcessData.process || []).map(action => ({
|
||||
ID: action.id,
|
||||
ActionType: action.type,
|
||||
AgentName: action.agent,
|
||||
Description: action.description,
|
||||
ImportantInput: action.inputs || []
|
||||
}))
|
||||
|
||||
console.log('🔄 数据格式转换完成:', {
|
||||
original: taskProcessData.process,
|
||||
converted: convertedTaskProcess
|
||||
})
|
||||
|
||||
// 更新 currentTask 的 AgentSelection 和 TaskProcess
|
||||
// 使用 updateCurrentAgentSelection 强制更新,避免被 setCurrentTask 的"智能保留"逻辑阻止
|
||||
agentsStore.updateCurrentAgentSelection(
|
||||
[...agentNames],
|
||||
convertedTaskProcess,
|
||||
taskProcessData.brief || currentTask.value.Collaboration_Brief_frontEnd
|
||||
)
|
||||
|
||||
console.log('✅ currentTask 已更新,新的 AgentSelection:', agentNames)
|
||||
console.log('📋 验证更新结果:', agentsStore.currentTask)
|
||||
}
|
||||
}
|
||||
|
||||
// 重新排序:被选中的agent排在前面,其他agent按平均分降序
|
||||
if (agentsHeatmapData.value.length > 0) {
|
||||
agentsHeatmapData.value.sort((a, b) => {
|
||||
@@ -406,18 +511,27 @@ const fetchAgentScores = async () => {
|
||||
}
|
||||
|
||||
// TODO: 切换到真实API时,取消注释下面这行
|
||||
// const response = await api.agentSelectModifyInit({
|
||||
// const agentScores = await api.agentSelectModifyInit({
|
||||
// goal: agentsStore.agentRawPlan.data?.['General Goal'] || '',
|
||||
// stepTask: currentTask.value
|
||||
// })
|
||||
|
||||
// 使用 Mock API(开发阶段)
|
||||
// 🆕 使用 Mock API(开发阶段),传递当前任务的 AgentSelection 以获取对应的维度
|
||||
const goal = agentsStore.agentRawPlan.data?.['General Goal'] || '开发智能协作系统'
|
||||
console.log('📤 调用 mockAgentSelectModifyInit,参数:', {
|
||||
goal,
|
||||
stepTask: currentTask.value,
|
||||
agentSelection: currentTask.value?.AgentSelection
|
||||
})
|
||||
|
||||
const agentScores = await api.mockAgentSelectModifyInit()
|
||||
|
||||
// 从转换后的数据中提取维度列表(第一个agent的所有维度)
|
||||
const firstAgent = Object.keys(agentScores)[0]
|
||||
const aspectList = firstAgent ? Object.keys(agentScores[firstAgent] || {}) : []
|
||||
|
||||
console.log('✅ 获取到的维度列表:', aspectList)
|
||||
|
||||
// 保存到 store
|
||||
agentsStore.setAgentScoreData({
|
||||
aspectList,
|
||||
@@ -594,9 +708,10 @@ watch(
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 按需加载初始 agent 组合的 TaskProcess(方案B)
|
||||
// 当用户第一次打开智能体探索窗口时,检查当前任务的初始 agent 组合是否已有 TaskProcess 数据
|
||||
// 如果没有,则调用 fill_stepTask_TaskProcess API 获取并存储
|
||||
// 初始化和任务切换处理
|
||||
// 1. 首次加载时,自动将初始 agent 组合添加到 confirmedAgentGroups
|
||||
// 2. 恢复之前的选择状态
|
||||
// 3. 加载 TaskProcess 数据
|
||||
watch(
|
||||
() => currentTask.value,
|
||||
async newTask => {
|
||||
@@ -604,66 +719,82 @@ watch(
|
||||
return
|
||||
}
|
||||
|
||||
// 从 store 中恢复之前选择的 agent 组合
|
||||
// 检查是否已经添加过初始组合
|
||||
const existingGroups = agentsStore.getConfirmedAgentGroups(newTask.Id)
|
||||
const hasInitialGroup = existingGroups.length > 0
|
||||
|
||||
// 首次初始化:自动添加初始组合(相当于系统自动执行了 confirmAgentSelection)
|
||||
if (!hasInitialGroup) {
|
||||
console.log('🎯 首次初始化,自动添加初始 agent 组合到 Assignment')
|
||||
agentsStore.addConfirmedAgentGroup(newTask.Id, [...newTask.AgentSelection])
|
||||
|
||||
// 调用 API 获取初始 agent 组合的 TaskProcess 数据
|
||||
console.log('🔄 开始加载初始 agent 组合的 TaskProcess...')
|
||||
|
||||
// 检查是否已有数据
|
||||
if (!selectionStore.hasAgentTaskProcess(newTask.Id, newTask.AgentSelection)) {
|
||||
try {
|
||||
isLoadingInitialTask.value = true
|
||||
console.log('=== 开始加载初始 agent 组合的 TaskProcess ===')
|
||||
console.log('1. 任务ID:', newTask.Id)
|
||||
console.log('2. 初始 agents:', newTask.AgentSelection)
|
||||
|
||||
// 将 IRawStepTask 转换为 IApiStepTask 格式
|
||||
const stepTaskForApi = {
|
||||
name: newTask.StepName || '',
|
||||
content: newTask.TaskContent || '',
|
||||
inputs: newTask.InputObject_List || [],
|
||||
output: newTask.OutputObject || '',
|
||||
agents: newTask.AgentSelection,
|
||||
brief: newTask.Collaboration_Brief_frontEnd || {
|
||||
template: '',
|
||||
data: {}
|
||||
},
|
||||
process: []
|
||||
}
|
||||
|
||||
console.log('3. 转换后的 API 请求参数:', stepTaskForApi)
|
||||
|
||||
const goal = agentsStore.agentRawPlan.data?.['General Goal'] || '开发智能协作系统'
|
||||
console.log('4. General Goal:', goal)
|
||||
|
||||
// 调用 Mock API 获取 TaskProcess
|
||||
const filledTask = await api.mockFillStepTaskTaskProcess({
|
||||
goal,
|
||||
stepTask: stepTaskForApi,
|
||||
agents: newTask.AgentSelection
|
||||
})
|
||||
|
||||
console.log('=== 初始 agent 组合 TaskProcess 加载成功 ===')
|
||||
console.log('5. TaskProcess 流程数量:', filledTask.process?.length || 0)
|
||||
|
||||
// 存储到 selectionStore
|
||||
selectionStore.setAgentTaskProcess(newTask.Id, newTask.AgentSelection, filledTask)
|
||||
console.log('✅ 初始 agent 组合的 TaskProcess 已加载并存储')
|
||||
} catch (error) {
|
||||
console.error('❌ 加载初始 agent 组合的 TaskProcess 失败:', error)
|
||||
} finally {
|
||||
isLoadingInitialTask.value = false
|
||||
}
|
||||
} else {
|
||||
console.log('ℹ️ 初始 agent 组合已有 TaskProcess 数据,跳过加载')
|
||||
}
|
||||
}
|
||||
|
||||
// 从 store 中恢复之前选择的 agent 组合(如果有)
|
||||
const savedAgentGroup = agentsStore.getSelectedAgentGroup(newTask.Id)
|
||||
if (savedAgentGroup) {
|
||||
console.log('📂 恢复之前选择的 agent 组合:', savedAgentGroup)
|
||||
selectedAssignmentGroup.value = [...savedAgentGroup]
|
||||
selectedAgents.value = new Set(savedAgentGroup)
|
||||
} else {
|
||||
// 没有保存的选择,使用默认的初始组合
|
||||
selectedAssignmentGroup.value = [...newTask.AgentSelection]
|
||||
selectedAgents.value = new Set(newTask.AgentSelection)
|
||||
}
|
||||
|
||||
// 调用 API 获取初始 agent 组合的 TaskProcess 数据
|
||||
console.log('🔄 开始加载初始 agent 组合的 TaskProcess...')
|
||||
|
||||
// 检查是否已有数据
|
||||
if (selectionStore.hasAgentTaskProcess(newTask.Id, newTask.AgentSelection)) {
|
||||
console.log('ℹ️ 初始 agent 组合已有 TaskProcess 数据,跳过加载')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('=== 开始加载初始 agent 组合的 TaskProcess ===')
|
||||
console.log('1. 任务ID:', newTask.Id)
|
||||
console.log('2. 初始 agents:', newTask.AgentSelection)
|
||||
|
||||
// 将 IRawStepTask 转换为 IApiStepTask 格式
|
||||
const stepTaskForApi = {
|
||||
name: newTask.StepName || '',
|
||||
content: newTask.TaskContent || '',
|
||||
inputs: newTask.InputObject_List || [],
|
||||
output: newTask.OutputObject || '',
|
||||
agents: newTask.AgentSelection,
|
||||
brief: newTask.Collaboration_Brief_frontEnd || {
|
||||
template: '',
|
||||
data: {}
|
||||
},
|
||||
process: []
|
||||
// 没有保存的选择,默认选中第一个组合(即初始组合)
|
||||
const allGroups = agentsStore.getConfirmedAgentGroups(newTask.Id)
|
||||
if (allGroups.length > 0 && allGroups[0]) {
|
||||
console.log('🔄 默认选中第一个组合(初始组合):', allGroups[0])
|
||||
selectedAssignmentGroup.value = [...allGroups[0]]
|
||||
selectedAgents.value = new Set(allGroups[0])
|
||||
}
|
||||
|
||||
console.log('3. 转换后的 API 请求参数:', stepTaskForApi)
|
||||
|
||||
const goal = agentsStore.agentRawPlan.data?.['General Goal'] || '开发智能协作系统'
|
||||
console.log('4. General Goal:', goal)
|
||||
|
||||
// 调用 Mock API 获取 TaskProcess
|
||||
const filledTask = await api.mockFillStepTaskTaskProcess({
|
||||
goal,
|
||||
stepTask: stepTaskForApi,
|
||||
agents: newTask.AgentSelection
|
||||
})
|
||||
|
||||
console.log('=== 初始 agent 组合 TaskProcess 加载成功 ===')
|
||||
console.log('5. TaskProcess 流程数量:', filledTask.process?.length || 0)
|
||||
|
||||
// 存储到 selectionStore
|
||||
selectionStore.setAgentTaskProcess(newTask.Id, newTask.AgentSelection, filledTask)
|
||||
console.log('✅ 初始 agent 组合的 TaskProcess 已加载并存储')
|
||||
} catch (error) {
|
||||
console.error('❌ 加载初始 agent 组合的 TaskProcess 失败:', error)
|
||||
}
|
||||
},
|
||||
{ immediate: true } // 立即执行一次
|
||||
@@ -672,7 +803,7 @@ watch(
|
||||
// 获取热力图颜色(评分1-5,颜色从浅到深)
|
||||
const getHeatmapColor = (score: number) => {
|
||||
const colors = [
|
||||
'#f0f0f0', // 1分 - 最浅
|
||||
'#f7f7f7', // 1分 - 最浅
|
||||
'#d4e5f7', // 2分
|
||||
'#89b4e8', // 3分
|
||||
'#4575b4', // 4分
|
||||
@@ -686,49 +817,15 @@ const getHeatmapColor = (score: number) => {
|
||||
<div class="agent-allocation-container">
|
||||
<!-- 左侧区域 - 20% -->
|
||||
<div class="allocation-left">
|
||||
<div class="section-card">
|
||||
<div class="section-card" v-loading="isLoadingSelectGroup">
|
||||
<div class="section-title">Assignment</div>
|
||||
<!-- 初始agent组合卡片 -->
|
||||
<div
|
||||
class="agents-grid"
|
||||
:class="{ 'agent-group-selected': isAgentGroupSelected(currentTaskAgents) }"
|
||||
@click="selectAgentGroup(currentTaskAgents)"
|
||||
>
|
||||
<el-tooltip
|
||||
v-for="agent in currentTaskAgents"
|
||||
:key="agent"
|
||||
effect="light"
|
||||
placement="top"
|
||||
:teleported="false"
|
||||
:show-after="500"
|
||||
popper-class="agent-allocation-tooltip-popper"
|
||||
>
|
||||
<template #content>
|
||||
<div class="agent-tooltip">
|
||||
<div class="agent-tooltip-name">{{ agent }}</div>
|
||||
<div class="agent-tooltip-separator"></div>
|
||||
<div class="agent-tooltip-description">
|
||||
{{
|
||||
agentsStore.agents.find(a => a.Name === agent)?.Profile || '暂无描述'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="agent-item">
|
||||
<div class="agent-icon" :style="{ background: getAgentMapIcon(agent).color }">
|
||||
<svg-icon :icon-class="getAgentMapIcon(agent).icon" color="#fff" size="20px" />
|
||||
</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<!-- 确认的agent组合列表 -->
|
||||
<!-- 所有 agent 组合卡片(包括初始组合和用户创建的组合) -->
|
||||
<div
|
||||
v-for="(group, groupIndex) in confirmedAgentGroups"
|
||||
:key="groupIndex"
|
||||
class="agents-grid"
|
||||
:class="{ 'agent-group-selected': isAgentGroupSelected(group) }"
|
||||
style="margin-top: 12px"
|
||||
:style="{ marginTop: groupIndex > 0 ? '12px' : '0' }"
|
||||
@click="selectAgentGroup(group)"
|
||||
>
|
||||
<el-tooltip
|
||||
@@ -767,7 +864,11 @@ const getHeatmapColor = (score: number) => {
|
||||
<div class="allocation-right">
|
||||
<div class="section-card">
|
||||
<div class="section-title">Comparison</div>
|
||||
<div v-if="allAgents.length > 0" class="comparison-content">
|
||||
<div
|
||||
v-if="allAgents.length > 0"
|
||||
class="comparison-content"
|
||||
v-loading="isInitializing || isLoadingInitialTask || isLoadingConfirm"
|
||||
>
|
||||
<!-- 热力矩阵图 -->
|
||||
<div v-if="agentsHeatmapData.length > 0" class="heatmap-container">
|
||||
<!-- 虚线选择框 - 包裹选中的agent头像 -->
|
||||
@@ -777,7 +878,11 @@ const getHeatmapColor = (score: number) => {
|
||||
:style="getSelectionBoxStyle()"
|
||||
>
|
||||
<!-- 确定按钮 -->
|
||||
<div class="confirm-button" @click="confirmAgentSelection">
|
||||
<div
|
||||
class="confirm-button"
|
||||
:class="{ 'is-loading': isLoadingConfirm }"
|
||||
@click="confirmAgentSelection"
|
||||
>
|
||||
<svg-icon icon-class="Check" color="#328621" size="12px" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -874,7 +979,7 @@ const getHeatmapColor = (score: number) => {
|
||||
</div>
|
||||
|
||||
<!-- 输入框区域 -->
|
||||
<div class="search-input-container">
|
||||
<div class="search-input-container" v-loading="isAddingDimension">
|
||||
<el-input
|
||||
v-model="searchValue"
|
||||
placeholder="请输入新维度"
|
||||
@@ -887,7 +992,7 @@ const getHeatmapColor = (score: number) => {
|
||||
size="16px"
|
||||
color="#409eff"
|
||||
class="submit-icon"
|
||||
:class="{ 'is-disabled': !searchValue }"
|
||||
:class="{ 'is-disabled': !searchValue, 'is-loading': isAddingDimension }"
|
||||
@click="searchValue && handleSubmit()"
|
||||
/>
|
||||
</template>
|
||||
@@ -1039,6 +1144,25 @@ const getHeatmapColor = (score: number) => {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
&.is-loading {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
|
||||
svg {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1102,16 +1226,19 @@ const getHeatmapColor = (score: number) => {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
padding-top: 40px; // 对齐第一个评分单元格(跳过列头)
|
||||
padding-top: 40px; // 对齐第一个评分单元格
|
||||
flex-shrink: 0;
|
||||
max-width: 200px; //
|
||||
|
||||
.dimension-label {
|
||||
width: 60px;
|
||||
min-width: 60px; // 改为最小宽度,允许根据内容自适应
|
||||
width: auto; // 宽度自适应
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px; // 添加右侧内边距,确保文字不会紧贴边缘
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-title-header);
|
||||
@@ -1119,6 +1246,7 @@ const getHeatmapColor = (score: number) => {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap; // 防止文字换行
|
||||
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
@@ -1177,6 +1305,11 @@ const getHeatmapColor = (score: number) => {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&.is-loading {
|
||||
opacity: 0.7;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ const agentGroupCount = computed(() => {
|
||||
const confirmedGroups = agentsStore.getConfirmedAgentGroups(agentsStore.currentTask.Id)
|
||||
|
||||
// 当前任务agents(1) + 已确认的agent组合数量
|
||||
return 1 + confirmedGroups.length
|
||||
return confirmedGroups.length || 1
|
||||
})
|
||||
|
||||
const handleClick = () => {
|
||||
|
||||
@@ -11,9 +11,9 @@ const emit = defineEmits<{
|
||||
// 获取分支数量 - 主分支(1) + 额外分支数量
|
||||
const branchCount = computed(() => {
|
||||
// flowBranches 包含所有通过 Branch 创建的分支
|
||||
const extraBranches = selectionStore.flowBranches?.length || 0
|
||||
const extraBranches = selectionStore.flowBranches?.length || 1
|
||||
// 始终至少有1个主分支
|
||||
return 1 + extraBranches
|
||||
return extraBranches
|
||||
})
|
||||
|
||||
const handleClick = () => {
|
||||
@@ -26,7 +26,7 @@ const handleClick = () => {
|
||||
<template>
|
||||
<div
|
||||
class="branch-button"
|
||||
:class="{ 'has-branches': branchCount > 1 }"
|
||||
:class="{ 'has-branches': branchCount > 0 }"
|
||||
@click="handleClick"
|
||||
:title="`${branchCount} 个分支`"
|
||||
>
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
// Mock数据 - 用于agentSelectModifyAddAspect接口
|
||||
// 模拟用户输入新维度后,所有agent在该维度上的评分数据
|
||||
|
||||
import { vueAgentList } from './AgentAssignmentMock'
|
||||
|
||||
// 类型定义
|
||||
export interface NewDimensionScore {
|
||||
score: number
|
||||
reason: string
|
||||
}
|
||||
|
||||
export type NewDimensionScoreData = Record<string, NewDimensionScore>
|
||||
|
||||
// 模拟接口返回的数据结构
|
||||
export interface AgentAddAspectResponse {
|
||||
aspectName: string // 新添加的维度名称
|
||||
agentScores: NewDimensionScoreData // 所有agent在该维度上的评分
|
||||
}
|
||||
|
||||
// 生成指定维度名称的mock评分数据
|
||||
export const generateMockDimensionScores = (dimensionName: string): AgentAddAspectResponse => {
|
||||
const agentScores: NewDimensionScoreData = {}
|
||||
|
||||
vueAgentList.forEach((agent) => {
|
||||
// 随机生成1-5的评分
|
||||
const score = Math.floor(Math.random() * 5) + 1
|
||||
|
||||
// 根据评分生成不同的原因描述
|
||||
let reason = ''
|
||||
switch (score) {
|
||||
case 5:
|
||||
reason = `在"${dimensionName}"方面表现卓越,展现出杰出的能力和深刻的理解`
|
||||
break
|
||||
case 4:
|
||||
reason = `在"${dimensionName}"方面表现优秀,具有良好的专业能力和执行力`
|
||||
break
|
||||
case 3:
|
||||
reason = `在"${dimensionName}"方面表现合格,能够完成相关任务`
|
||||
break
|
||||
case 2:
|
||||
reason = `在"${dimensionName}"方面表现一般,仍有提升空间`
|
||||
break
|
||||
case 1:
|
||||
reason = `在"${dimensionName}"方面需要加强,建议进一步提升相关能力`
|
||||
break
|
||||
}
|
||||
|
||||
agentScores[agent] = { score, reason }
|
||||
})
|
||||
|
||||
return {
|
||||
aspectName: dimensionName,
|
||||
agentScores,
|
||||
}
|
||||
}
|
||||
|
||||
// 预设的一些常用维度及其评分数据
|
||||
export const presetDimensionScores: Record<string, AgentAddAspectResponse> = {
|
||||
创新性: generateMockDimensionScores('创新性'),
|
||||
技术能力: generateMockDimensionScores('技术能力'),
|
||||
沟通技巧: generateMockDimensionScores('沟通技巧'),
|
||||
问题解决: generateMockDimensionScores('问题解决'),
|
||||
团队协作: generateMockDimensionScores('团队协作'),
|
||||
学习能力: generateMockDimensionScores('学习能力'),
|
||||
执行力: generateMockDimensionScores('执行力'),
|
||||
责任心: generateMockDimensionScores('责任心'),
|
||||
适应性: generateMockDimensionScores('适应性'),
|
||||
领导力: generateMockDimensionScores('领导力'),
|
||||
}
|
||||
|
||||
// 模拟API调用函数(用于前端测试)
|
||||
export const mockAgentAddAspectApi = async (
|
||||
aspectList: string[],
|
||||
): Promise<AgentAddAspectResponse[]> => {
|
||||
// 获取新增的维度(最后一个)
|
||||
const newAspect = aspectList[aspectList.length - 1]
|
||||
|
||||
// 模拟网络延迟 500ms
|
||||
await new Promise((resolve) => setTimeout(resolve, 20000))
|
||||
|
||||
// 如果是预设维度,返回预设数据
|
||||
if (presetDimensionScores[newAspect]) {
|
||||
return [presetDimensionScores[newAspect]]
|
||||
}
|
||||
|
||||
// 否则动态生成新的评分数据
|
||||
return [generateMockDimensionScores(newAspect)]
|
||||
}
|
||||
|
||||
// Vue Composition API 兼容的hook
|
||||
export const useAgentAddAspectMock = () => {
|
||||
const addNewDimension = async (dimensionName: string) => {
|
||||
const response = await mockAgentAddAspectApi([dimensionName])
|
||||
return response[0]
|
||||
}
|
||||
|
||||
const getMultipleDimensions = async (dimensionNames: string[]) => {
|
||||
const responses: AgentAddAspectResponse[] = []
|
||||
|
||||
for (const dimension of dimensionNames) {
|
||||
if (presetDimensionScores[dimension]) {
|
||||
responses.push(presetDimensionScores[dimension])
|
||||
} else {
|
||||
responses.push(generateMockDimensionScores(dimension))
|
||||
}
|
||||
}
|
||||
|
||||
return responses
|
||||
}
|
||||
|
||||
return {
|
||||
addNewDimension,
|
||||
getMultipleDimensions,
|
||||
generateMockDimensionScores,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
// 模拟后端原始返回格式的Mock数据 - 维度 -> agent -> { Reason, Score }
|
||||
import { vueAgentList, vueAspectList } from './AgentAssignmentMock'
|
||||
|
||||
// 后端返回的评分项格式
|
||||
export interface BackendScoreItem {
|
||||
Reason: string
|
||||
Score: number
|
||||
}
|
||||
|
||||
// 后端返回的完整数据格式
|
||||
export type BackendAgentScoreResponse = Record<string, Record<string, BackendScoreItem>>
|
||||
|
||||
// 模拟后端返回的原始数据结构(维度 -> agent -> { Reason, Score })
|
||||
export const mockBackendAgentScoreData: BackendAgentScoreResponse = {
|
||||
能力: {
|
||||
船舶设计师: { Reason: '展现出卓越的创造力和创新思维', Score: 4 },
|
||||
防护工程专家: { Reason: '展现出杰出的创造性问题解决能力', Score: 5 },
|
||||
病理生理学家: { Reason: '具有中等创造技能,有待提升', Score: 3 },
|
||||
药物化学家: { Reason: '在大多数情况下展现较强的创造性思维', Score: 4 },
|
||||
制剂工程师: { Reason: '展现出胜任的创造能力', Score: 3 },
|
||||
监管事务专家: { Reason: '具有较强的创造性表达能力', Score: 4 },
|
||||
物理学家: { Reason: '擅长创新性思维方法', Score: 5 },
|
||||
实验材料学家: { Reason: '展现出卓越的创造性思维和创新能力', Score: 5 },
|
||||
计算模拟专家: { Reason: '展现出良好的创造性问题解决能力', Score: 4 },
|
||||
腐蚀机理研究员: { Reason: '展现出卓越的创造性问题解决能力', Score: 5 },
|
||||
先进材料研发员: { Reason: '展现出平衡的创造能力', Score: 4 },
|
||||
肾脏病学家: { Reason: '展现出卓越的创造天赋', Score: 5 },
|
||||
临床研究协调员: { Reason: '展现出胜任的创造性思维', Score: 3 },
|
||||
中医药专家: { Reason: '展现出较强的创造性主动性', Score: 4 },
|
||||
药物安全专家: { Reason: '具有发展中的创造技能', Score: 3 },
|
||||
二维材料科学家: { Reason: '展现出卓越的创造愿景', Score: 5 },
|
||||
光电物理学家: { Reason: '展现出卓越的创造性执行力', Score: 4 },
|
||||
机器学习专家: { Reason: '具有较强的创造性问题解决能力', Score: 4 },
|
||||
流体动力学专家: { Reason: '展现出胜任的创造能力', Score: 3 },
|
||||
},
|
||||
可用性: {
|
||||
船舶设计师: { Reason: '展现出卓越的共情能力和社会意识', Score: 5 },
|
||||
防护工程专家: { Reason: '具有较强的情绪调节和人际交往技能', Score: 4 },
|
||||
病理生理学家: { Reason: '展现出卓越的情感智力', Score: 5 },
|
||||
药物化学家: { Reason: '在大多数情况下展现平均的情感智力', Score: 3 },
|
||||
制剂工程师: { Reason: '具有良好的情绪意识和沟通能力', Score: 4 },
|
||||
监管事务专家: { Reason: '在情绪意识方面偶尔表现不足', Score: 3 },
|
||||
物理学家: { Reason: '具有较强的情绪理解能力', Score: 4 },
|
||||
实验材料学家: { Reason: '展现出卓越的共情能力和社交技能', Score: 5 },
|
||||
计算模拟专家: { Reason: '具有良好的情绪调节能力', Score: 4 },
|
||||
腐蚀机理研究员: { Reason: '展现出卓越的情感智力和社会意识', Score: 5 },
|
||||
先进材料研发员: { Reason: '具有发展中的情绪意识', Score: 3 },
|
||||
肾脏病学家: { Reason: '擅长人际交往和建立关系', Score: 5 },
|
||||
临床研究协调员: { Reason: '展现出平衡的情感智力', Score: 4 },
|
||||
中医药专家: { Reason: '具有基本的情绪理解能力', Score: 3 },
|
||||
药物安全专家: { Reason: '展现出良好的情绪调节能力', Score: 4 },
|
||||
二维材料科学家: { Reason: '展现出卓越的社会意识', Score: 5 },
|
||||
光电物理学家: { Reason: '在情感智力方面需要提升', Score: 3 },
|
||||
机器学习专家: { Reason: '具有较强的共情能力', Score: 4 },
|
||||
流体动力学专家: { Reason: '具有良好的情绪沟通技能', Score: 4 },
|
||||
},
|
||||
专业性: {
|
||||
船舶设计师: { Reason: '展现出胜任的哲学推理技能', Score: 3 },
|
||||
防护工程专家: { Reason: '展现出卓越的逻辑推理和分析能力', Score: 5 },
|
||||
病理生理学家: { Reason: '展现出深刻的哲学洞察力和批判性思维', Score: 2 },
|
||||
药物化学家: { Reason: '展现出良好的哲学理解能力', Score: 1 },
|
||||
制剂工程师: { Reason: '具有基础哲学推理能力,存在一些局限', Score: 3 },
|
||||
监管事务专家: { Reason: '展现出较强的分析思维能力', Score: 4 },
|
||||
物理学家: { Reason: '展现出卓越的哲学深度', Score: 5 },
|
||||
实验材料学家: { Reason: '展现出卓越的专业分析和推理能力', Score: 5 },
|
||||
计算模拟专家: { Reason: '具有良好的批判性思维能力', Score: 4 },
|
||||
腐蚀机理研究员: { Reason: '具有较强的专业性分析和推理能力', Score: 4 },
|
||||
先进材料研发员: { Reason: '展现出卓越的逻辑推理能力', Score: 5 },
|
||||
肾脏病学家: { Reason: '具有基础的哲学理解能力', Score: 3 },
|
||||
临床研究协调员: { Reason: '展现出平衡的哲学推理能力', Score: 4 },
|
||||
中医药专家: { Reason: '需要在哲学思维方面发展', Score: 3 },
|
||||
药物安全专家: { Reason: '展现出良好的分析技能', Score: 4 },
|
||||
二维材料科学家: { Reason: '具有较强的哲学洞察力', Score: 4 },
|
||||
光电物理学家: { Reason: '擅长批判性思维和分析', Score: 5 },
|
||||
机器学习专家: { Reason: '具有基础哲学推理能力', Score: 3 },
|
||||
流体动力学专家: { Reason: '展现出卓越的哲学才能', Score: 5 },
|
||||
},
|
||||
效率: {
|
||||
船舶设计师: { Reason: '在任务完成方面展现出卓越的效率', Score: 4 },
|
||||
防护工程专家: { Reason: '擅长高效的工作流程管理', Score: 5 },
|
||||
病理生理学家: { Reason: '展现出平均的效率,有提升空间', Score: 3 },
|
||||
药物化学家: { Reason: '具有良好的时间管理技能', Score: 4 },
|
||||
制剂工程师: { Reason: '展现出胜任的效率', Score: 3 },
|
||||
监管事务专家: { Reason: '展现出卓越的生产力', Score: 5 },
|
||||
物理学家: { Reason: '具有强大的任务执行能力', Score: 4 },
|
||||
实验材料学家: { Reason: '具有良好的工作效率和时间管理', Score: 4 },
|
||||
计算模拟专家: { Reason: '展现出良好的工作流程优化能力', Score: 4 },
|
||||
腐蚀机理研究员: { Reason: '展现出卓越的效率和工作流程管理', Score: 5 },
|
||||
先进材料研发员: { Reason: '展现出足够的效率', Score: 3 },
|
||||
肾脏病学家: { Reason: '擅长快速完成任务', Score: 5 },
|
||||
临床研究协调员: { Reason: '展现出良好的生产力', Score: 4 },
|
||||
中医药专家: { Reason: '具有中等的效率水平', Score: 3 },
|
||||
药物安全专家: { Reason: '具有较强的任务效率', Score: 4 },
|
||||
二维材料科学家: { Reason: '具有良好的执行速度', Score: 4 },
|
||||
光电物理学家: { Reason: '展现出卓越的效率', Score: 5 },
|
||||
机器学习专家: { Reason: '展现出平均的生产力', Score: 3 },
|
||||
流体动力学专家: { Reason: '在执行方面具有良好的效率', Score: 4 },
|
||||
},
|
||||
准确性: {
|
||||
船舶设计师: { Reason: '展现出卓越的细节关注度', Score: 5 },
|
||||
防护工程专家: { Reason: '展现出卓越的准确性和精确度', Score: 5 },
|
||||
病理生理学家: { Reason: '展现出卓越的精确度', Score: 5 },
|
||||
药物化学家: { Reason: '展现出良好的准确性', Score: 4 },
|
||||
制剂工程师: { Reason: '展现出中等的准确性,有提升空间', Score: 3 },
|
||||
监管事务专家: { Reason: '具有较强的细节关注度', Score: 4 },
|
||||
物理学家: { Reason: '在精确度和准确性方面表现卓越', Score: 5 },
|
||||
实验材料学家: { Reason: '展现出卓越的细节导向和精确度', Score: 5 },
|
||||
计算模拟专家: { Reason: '展现出平均的准确性', Score: 3 },
|
||||
腐蚀机理研究员: { Reason: '展现出卓越的准确性和精确技能', Score: 5 },
|
||||
先进材料研发员: { Reason: '展现出卓越的准确性', Score: 5 },
|
||||
肾脏病学家: { Reason: '展现出较强的精确度', Score: 4 },
|
||||
临床研究协调员: { Reason: '展现出中等的准确性', Score: 3 },
|
||||
中医药专家: { Reason: '具有良好的细节导向能力', Score: 4 },
|
||||
药物安全专家: { Reason: '在准确性和精确度方面表现卓越', Score: 5 },
|
||||
二维材料科学家: { Reason: '展现出较强的细节关注度', Score: 4 },
|
||||
光电物理学家: { Reason: '展现出平均的准确性水平', Score: 3 },
|
||||
机器学习专家: { Reason: '在工作中具有良好的精确度', Score: 4 },
|
||||
流体动力学专家: { Reason: '展现出卓越的准确性', Score: 5 },
|
||||
},
|
||||
协作性: {
|
||||
船舶设计师: { Reason: '展现出卓越的协作技能', Score: 4 },
|
||||
防护工程专家: { Reason: '在团队合作和协作方面表现卓越', Score: 5 },
|
||||
病理生理学家: { Reason: '具有较强的协作能力', Score: 4 },
|
||||
药物化学家: { Reason: '具有中等的协作技能', Score: 3 },
|
||||
制剂工程师: { Reason: '展现出良好的团队合作精神', Score: 4 },
|
||||
监管事务专家: { Reason: '具有较强的合作能力', Score: 4 },
|
||||
物理学家: { Reason: '展现出平均的协作技能', Score: 3 },
|
||||
实验材料学家: { Reason: '在团队协作方面表现卓越', Score: 5 },
|
||||
计算模拟专家: { Reason: '展现出良好的合作工作能力', Score: 4 },
|
||||
腐蚀机理研究员: { Reason: '在团队协作和合作方面表现卓越', Score: 5 },
|
||||
先进材料研发员: { Reason: '具有中等的协作水平', Score: 3 },
|
||||
肾脏病学家: { Reason: '展现出良好的协作技能', Score: 4 },
|
||||
临床研究协调员: { Reason: '在协调和团队合作方面表现卓越', Score: 5 },
|
||||
中医药专家: { Reason: '具有较强的合作能力', Score: 4 },
|
||||
药物安全专家: { Reason: '展现出平均的协作水平', Score: 3 },
|
||||
二维材料科学家: { Reason: '展现出良好的团队合作精神', Score: 4 },
|
||||
光电物理学家: { Reason: '具有较强的协作技能', Score: 4 },
|
||||
机器学习专家: { Reason: '在团队协作方面表现卓越', Score: 5 },
|
||||
流体动力学专家: { Reason: '具有中等的协作能力', Score: 3 },
|
||||
},
|
||||
}
|
||||
|
||||
// 模拟后端API调用 - agentSelectModifyInit
|
||||
export const mockBackendAgentSelectModifyInit = async (): Promise<BackendAgentScoreResponse> => {
|
||||
// 模拟网络延迟 300ms
|
||||
await new Promise(resolve => setTimeout(resolve, 300))
|
||||
return mockBackendAgentScoreData
|
||||
}
|
||||
|
||||
// 模拟后端API调用 - agentSelectModifyAddAspect(添加新维度)
|
||||
export const mockBackendAgentSelectModifyAddAspect = async (
|
||||
aspectList: string[]
|
||||
): Promise<BackendAgentScoreResponse> => {
|
||||
// 模拟网络延迟 500ms
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
// 获取新添加的维度(最后一个)
|
||||
const newAspect = aspectList[aspectList.length - 1]
|
||||
if (!newAspect) {
|
||||
return {}
|
||||
}
|
||||
|
||||
// 生成该维度下所有agent的评分
|
||||
const aspectData: Record<string, BackendScoreItem> = {}
|
||||
|
||||
vueAgentList.forEach(agent => {
|
||||
const score = Math.floor(Math.random() * 5) + 1
|
||||
let reason = ''
|
||||
switch (score) {
|
||||
case 5:
|
||||
reason = `在"${newAspect}"方面表现卓越,展现出杰出的能力和深刻的理解`
|
||||
break
|
||||
case 4:
|
||||
reason = `在"${newAspect}"方面表现优秀,具有良好的专业能力和执行力`
|
||||
break
|
||||
case 3:
|
||||
reason = `在"${newAspect}"方面表现合格,能够完成相关任务`
|
||||
break
|
||||
case 2:
|
||||
reason = `在"${newAspect}"方面表现一般,仍有提升空间`
|
||||
break
|
||||
case 1:
|
||||
reason = `在"${newAspect}"方面需要加强,建议进一步提升相关能力`
|
||||
break
|
||||
}
|
||||
aspectData[agent] = { Reason: reason, Score: score }
|
||||
})
|
||||
|
||||
return {
|
||||
[newAspect]: aspectData
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
// Vue兼容的mock数据 - 6个维度,19个智能体
|
||||
export const vueAgentList = [
|
||||
'船舶设计师',
|
||||
'防护工程专家',
|
||||
'病理生理学家',
|
||||
'药物化学家',
|
||||
'制剂工程师',
|
||||
'监管事务专家',
|
||||
'物理学家',
|
||||
'实验材料学家',
|
||||
'计算模拟专家',
|
||||
'腐蚀机理研究员',
|
||||
'先进材料研发员',
|
||||
'肾脏病学家',
|
||||
'临床研究协调员',
|
||||
'中医药专家',
|
||||
'药物安全专家',
|
||||
'二维材料科学家',
|
||||
'光电物理学家',
|
||||
'机器学习专家',
|
||||
'流体动力学专家',
|
||||
]
|
||||
|
||||
export const vueAspectList = ['能力', '可用性', '专业性', '效率', '准确性', '协作性']
|
||||
|
||||
// 类型定义
|
||||
export type AgentName = (typeof vueAgentList)[number]
|
||||
export type AspectName = (typeof vueAspectList)[number]
|
||||
|
||||
export interface AgentScore {
|
||||
score: number
|
||||
reason: string
|
||||
}
|
||||
|
||||
export type IAgentSelectModifyAddRequest = Record<AspectName, Record<AgentName, AgentScore>>
|
||||
|
||||
// Vue友好的数据结构 - agent -> 维度 -> 评分(与后端返回格式一致)
|
||||
export const vueAgentScoreData: Record<AgentName, Record<AspectName, AgentScore>> = {
|
||||
船舶设计师: {
|
||||
能力: { score: 4, reason: '展现出卓越的创造力和创新思维' },
|
||||
可用性: { score: 5, reason: '展现出卓越的共情能力和社会意识' },
|
||||
专业性: { score: 3, reason: '展现出胜任的哲学推理技能' },
|
||||
效率: { score: 4, reason: '在任务完成方面展现出卓越的效率' },
|
||||
准确性: { score: 5, reason: '展现出卓越的细节关注度' },
|
||||
协作性: { score: 4, reason: '展现出卓越的协作技能' },
|
||||
},
|
||||
防护工程专家: {
|
||||
能力: { score: 5, reason: '展现出杰出的创造性问题解决能力' },
|
||||
可用性: { score: 4, reason: '具有较强的情绪调节和人际交往技能' },
|
||||
专业性: { score: 5, reason: '展现出卓越的逻辑推理和分析能力' },
|
||||
效率: { score: 5, reason: '擅长高效的工作流程管理' },
|
||||
准确性: { score: 5, reason: '展现出卓越的准确性和精确度' },
|
||||
协作性: { score: 5, reason: '在团队合作和协作方面表现卓越' },
|
||||
},
|
||||
病理生理学家: {
|
||||
能力: { score: 3, reason: '具有中等创造技能,有待提升' },
|
||||
可用性: { score: 5, reason: '展现出卓越的情感智力' },
|
||||
专业性: { score: 2, reason: '展现出深刻的哲学洞察力和批判性思维' },
|
||||
效率: { score: 3, reason: '展现出平均的效率,有提升空间' },
|
||||
准确性: { score: 5, reason: '展现出卓越的精确度' },
|
||||
协作性: { score: 4, reason: '具有较强的协作能力' },
|
||||
},
|
||||
药物化学家: {
|
||||
能力: { score: 4, reason: '在大多数情况下展现较强的创造性思维' },
|
||||
可用性: { score: 3, reason: '在大多数情况下展现平均的情感智力' },
|
||||
专业性: { score: 1, reason: '展现出良好的哲学理解能力' },
|
||||
效率: { score: 4, reason: '具有良好的时间管理技能' },
|
||||
准确性: { score: 4, reason: '展现出良好的准确性' },
|
||||
协作性: { score: 3, reason: '具有中等的协作技能' },
|
||||
},
|
||||
制剂工程师: {
|
||||
能力: { score: 3, reason: '展现出胜任的创造能力' },
|
||||
可用性: { score: 4, reason: '具有良好的情绪意识和沟通能力' },
|
||||
专业性: { score: 3, reason: '具有基础哲学推理能力,存在一些局限' },
|
||||
效率: { score: 3, reason: '展现出胜任的效率' },
|
||||
准确性: { score: 3, reason: '展现出中等的准确性,有提升空间' },
|
||||
协作性: { score: 4, reason: '展现出良好的团队合作精神' },
|
||||
},
|
||||
监管事务专家: {
|
||||
能力: { score: 4, reason: '具有较强的创造性表达能力' },
|
||||
可用性: { score: 3, reason: '在情绪意识方面偶尔表现不足' },
|
||||
专业性: { score: 4, reason: '展现出较强的分析思维能力' },
|
||||
效率: { score: 5, reason: '展现出卓越的生产力' },
|
||||
准确性: { score: 4, reason: '具有较强的细节关注度' },
|
||||
协作性: { score: 4, reason: '具有较强的合作能力' },
|
||||
},
|
||||
物理学家: {
|
||||
能力: { score: 5, reason: '擅长创新性思维方法' },
|
||||
可用性: { score: 4, reason: '具有较强的情绪理解能力' },
|
||||
专业性: { score: 5, reason: '展现出卓越的哲学深度' },
|
||||
效率: { score: 4, reason: '具有强大的任务执行能力' },
|
||||
准确性: { score: 5, reason: '在精确度和准确性方面表现卓越' },
|
||||
协作性: { score: 3, reason: '展现出平均的协作技能' },
|
||||
},
|
||||
实验材料学家: {
|
||||
能力: { score: 5, reason: '展现出卓越的创造性思维和创新能力' },
|
||||
可用性: { score: 5, reason: '展现出卓越的共情能力和社交技能' },
|
||||
专业性: { score: 5, reason: '展现出卓越的专业分析和推理能力' },
|
||||
效率: { score: 4, reason: '具有良好的工作效率和时间管理' },
|
||||
准确性: { score: 5, reason: '展现出卓越的细节导向和精确度' },
|
||||
协作性: { score: 5, reason: '在团队协作方面表现卓越' },
|
||||
},
|
||||
计算模拟专家: {
|
||||
能力: { score: 4, reason: '展现出良好的创造性问题解决能力' },
|
||||
可用性: { score: 4, reason: '具有良好的情绪调节能力' },
|
||||
专业性: { score: 4, reason: '具有良好的批判性思维能力' },
|
||||
效率: { score: 4, reason: '展现出良好的工作流程优化能力' },
|
||||
准确性: { score: 3, reason: '展现出平均的准确性' },
|
||||
协作性: { score: 4, reason: '展现出良好的合作工作能力' },
|
||||
},
|
||||
腐蚀机理研究员: {
|
||||
能力: { score: 5, reason: '展现出卓越的创造性问题解决能力' },
|
||||
可用性: { score: 5, reason: '展现出卓越的情感智力和社会意识' },
|
||||
专业性: { score: 4, reason: '具有较强的专业性分析和推理能力' },
|
||||
效率: { score: 5, reason: '展现出卓越的效率和工作流程管理' },
|
||||
准确性: { score: 5, reason: '展现出卓越的准确性和精确技能' },
|
||||
协作性: { score: 5, reason: '在团队协作和合作方面表现卓越' },
|
||||
},
|
||||
先进材料研发员: {
|
||||
能力: { score: 4, reason: '展现出平衡的创造能力' },
|
||||
可用性: { score: 3, reason: '具有发展中的情绪意识' },
|
||||
专业性: { score: 5, reason: '展现出卓越的逻辑推理能力' },
|
||||
效率: { score: 3, reason: '展现出足够的效率' },
|
||||
准确性: { score: 5, reason: '展现出卓越的准确性' },
|
||||
协作性: { score: 3, reason: '具有中等的协作水平' },
|
||||
},
|
||||
肾脏病学家: {
|
||||
能力: { score: 5, reason: '展现出卓越的创造天赋' },
|
||||
可用性: { score: 5, reason: '擅长人际交往和建立关系' },
|
||||
专业性: { score: 3, reason: '具有基础的哲学理解能力' },
|
||||
效率: { score: 5, reason: '擅长快速完成任务' },
|
||||
准确性: { score: 4, reason: '展现出较强的精确度' },
|
||||
协作性: { score: 4, reason: '展现出良好的协作技能' },
|
||||
},
|
||||
临床研究协调员: {
|
||||
能力: { score: 3, reason: '展现出胜任的创造性思维' },
|
||||
可用性: { score: 4, reason: '展现出平衡的情感智力' },
|
||||
专业性: { score: 4, reason: '展现出平衡的哲学推理能力' },
|
||||
效率: { score: 4, reason: '展现出良好的生产力' },
|
||||
准确性: { score: 3, reason: '展现出中等的准确性' },
|
||||
协作性: { score: 5, reason: '在协调和团队合作方面表现卓越' },
|
||||
},
|
||||
中医药专家: {
|
||||
能力: { score: 4, reason: '展现出较强的创造性主动性' },
|
||||
可用性: { score: 3, reason: '具有基本的情绪理解能力' },
|
||||
专业性: { score: 3, reason: '需要在哲学思维方面发展' },
|
||||
效率: { score: 3, reason: '具有中等的效率水平' },
|
||||
准确性: { score: 4, reason: '具有良好的细节导向能力' },
|
||||
协作性: { score: 4, reason: '具有较强的合作能力' },
|
||||
},
|
||||
药物安全专家: {
|
||||
能力: { score: 3, reason: '具有发展中的创造技能' },
|
||||
可用性: { score: 4, reason: '展现出良好的情绪调节能力' },
|
||||
专业性: { score: 4, reason: '展现出良好的分析技能' },
|
||||
效率: { score: 4, reason: '具有较强的任务效率' },
|
||||
准确性: { score: 5, reason: '在准确性和精确度方面表现卓越' },
|
||||
协作性: { score: 3, reason: '展现出平均的协作水平' },
|
||||
},
|
||||
二维材料科学家: {
|
||||
能力: { score: 5, reason: '展现出卓越的创造愿景' },
|
||||
可用性: { score: 5, reason: '展现出卓越的社会意识' },
|
||||
专业性: { score: 4, reason: '具有较强的哲学洞察力' },
|
||||
效率: { score: 4, reason: '具有良好的执行速度' },
|
||||
准确性: { score: 4, reason: '展现出较强的细节关注度' },
|
||||
协作性: { score: 4, reason: '展现出良好的团队合作精神' },
|
||||
},
|
||||
光电物理学家: {
|
||||
能力: { score: 4, reason: '展现出卓越的创造性执行力' },
|
||||
可用性: { score: 3, reason: '在情感智力方面需要提升' },
|
||||
专业性: { score: 5, reason: '擅长批判性思维和分析' },
|
||||
效率: { score: 5, reason: '展现出卓越的效率' },
|
||||
准确性: { score: 3, reason: '展现出平均的准确性水平' },
|
||||
协作性: { score: 4, reason: '具有较强的协作技能' },
|
||||
},
|
||||
机器学习专家: {
|
||||
能力: { score: 4, reason: '具有较强的创造性问题解决能力' },
|
||||
可用性: { score: 4, reason: '具有较强的共情能力' },
|
||||
专业性: { score: 3, reason: '具有基础哲学推理能力' },
|
||||
效率: { score: 3, reason: '展现出平均的生产力' },
|
||||
准确性: { score: 4, reason: '在工作中具有良好的精确度' },
|
||||
协作性: { score: 5, reason: '在团队协作方面表现卓越' },
|
||||
},
|
||||
流体动力学专家: {
|
||||
能力: { score: 3, reason: '展现出胜任的创造能力' },
|
||||
可用性: { score: 4, reason: '具有良好的情绪沟通技能' },
|
||||
专业性: { score: 5, reason: '展现出卓越的哲学才能' },
|
||||
效率: { score: 4, reason: '在执行方面具有良好的效率' },
|
||||
准确性: { score: 5, reason: '展现出卓越的准确性' },
|
||||
协作性: { score: 3, reason: '具有中等的协作能力' },
|
||||
},
|
||||
}
|
||||
|
||||
// Vue友好的智能体选择配置
|
||||
export const vueAgentSelections = {
|
||||
balanced: { agents: ['船舶设计师', '防护工程专家', '病理生理学家'] },
|
||||
creative: { agents: ['防护工程专家', '物理学家', '二维材料科学家'] },
|
||||
emotional: { agents: ['船舶设计师', '病理生理学家', '实验材料学家'] },
|
||||
philosophical: { agents: ['病理生理学家', '物理学家', '光电物理学家'] },
|
||||
mixed: { agents: ['药物化学家', '先进材料研发员', '肾脏病学家', '机器学习专家'] },
|
||||
}
|
||||
|
||||
export const vueCurrentAgentSelection = 'balanced'
|
||||
|
||||
// Vue兼容的工具函数
|
||||
export const vueCalculateAgentAverages = () => {
|
||||
const averages: Record<string, number> = {}
|
||||
|
||||
vueAgentList.forEach((agent) => {
|
||||
let total = 0
|
||||
let count = 0
|
||||
|
||||
vueAspectList.forEach((aspect) => {
|
||||
// 数据结构:agentScores[agent][aspect]
|
||||
const scoreData = vueAgentScoreData[agent]?.[aspect]
|
||||
if (scoreData) {
|
||||
total += scoreData.score
|
||||
count++
|
||||
}
|
||||
})
|
||||
|
||||
averages[agent] = count > 0 ? Number((total / count).toFixed(2)) : 0
|
||||
})
|
||||
|
||||
return averages
|
||||
}
|
||||
|
||||
// 获取按平均分排序的智能体列表
|
||||
export const vueGetSortedAgentsByAverage = () => {
|
||||
const averages = vueCalculateAgentAverages()
|
||||
return [...vueAgentList].sort((a, b) => {
|
||||
return averages[b] - averages[a]
|
||||
})
|
||||
}
|
||||
|
||||
// Vue Composition API 兼容的hook
|
||||
export const useAgentMockData = () => {
|
||||
// 在Vue中可以使用ref或reactive包装数据
|
||||
const agentScores = vueAgentScoreData
|
||||
const agentSelections = vueAgentSelections
|
||||
const currentSelection = vueCurrentAgentSelection
|
||||
|
||||
// 计算平均分的响应式函数
|
||||
const calculateAverages = () => {
|
||||
return vueCalculateAgentAverages()
|
||||
}
|
||||
|
||||
// 获取特定维度的评分(返回该维度下所有智能体的评分)
|
||||
const getScoresByAspect = (aspect: AspectName) => {
|
||||
const result: Record<AgentName, AgentScore> = {}
|
||||
// 数据结构:agentScores[agent][aspect],需要遍历所有agent提取指定aspect
|
||||
vueAgentList.forEach((agent) => {
|
||||
if (agentScores[agent]?.[aspect]) {
|
||||
result[agent] = agentScores[agent][aspect]!
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
// 获取特定智能体的所有维度评分
|
||||
const getScoresByAgent = (agent: AgentName) => {
|
||||
// 数据结构:agentScores[agent][aspect],直接返回agent的所有维度评分
|
||||
return agentScores[agent] || {}
|
||||
}
|
||||
|
||||
return {
|
||||
agentScores,
|
||||
agentSelections,
|
||||
currentSelection,
|
||||
calculateAverages,
|
||||
getScoresByAspect,
|
||||
getScoresByAgent,
|
||||
getSortedAgents: vueGetSortedAgentsByAverage,
|
||||
}
|
||||
}
|
||||
|
||||
// Vue 2.x 兼容的选项式API版本
|
||||
export const vueMockMixin = {
|
||||
data() {
|
||||
return {
|
||||
vueAgentScores: vueAgentScoreData,
|
||||
vueAgentSelections: vueAgentSelections,
|
||||
vueCurrentSelection: vueCurrentAgentSelection,
|
||||
vueAgentList: vueAgentList,
|
||||
vueAspectList: vueAspectList,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
vueAgentAverages() {
|
||||
return vueCalculateAgentAverages()
|
||||
},
|
||||
vueSortedAgents() {
|
||||
return vueGetSortedAgentsByAverage()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
vueGetScoresByAspect(aspect: AspectName) {
|
||||
const agentScores = (this as any).vueAgentScores
|
||||
const agentList = (this as any).vueAgentList
|
||||
// 数据结构:agentScores[agent][aspect],遍历所有agent提取指定aspect
|
||||
const result: Record<string, { score: number; reason: string }> = {}
|
||||
agentList.forEach((agent: string) => {
|
||||
if (agentScores[agent]?.[aspect]) {
|
||||
result[agent] = agentScores[agent][aspect]
|
||||
}
|
||||
})
|
||||
return result
|
||||
},
|
||||
vueGetScoresByAgent(agent: AgentName) {
|
||||
const agentScores = (this as any).vueAgentScores
|
||||
// 数据结构:agentScores[agent][aspect],直接返回agent的所有维度评分
|
||||
return agentScores[agent] || {}
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { getAgentMapIcon } from '@/layout/components/config.ts'
|
||||
import { type ConnectArg, Jsplumb } from '@/layout/components/Main/TaskTemplate/utils.ts'
|
||||
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
||||
import { computed, ref, nextTick } from 'vue'
|
||||
import { computed, ref, nextTick, watch, onMounted } from 'vue'
|
||||
import { AnchorLocations } from '@jsplumb/browser-ui'
|
||||
import MultiLineTooltip from '@/components/MultiLineTooltip/index.vue'
|
||||
import Bg from './Bg.vue'
|
||||
@@ -15,7 +15,6 @@ const planReady = computed(() => {
|
||||
})
|
||||
|
||||
const openPlanModification = () => {
|
||||
console.log('打开分支修改窗口')
|
||||
agentsStore.openPlanModification()
|
||||
}
|
||||
|
||||
@@ -202,6 +201,56 @@ function clear() {
|
||||
jsplumb.reset()
|
||||
}
|
||||
|
||||
// 🆕 封装连线重绘方法
|
||||
const redrawConnections = () => {
|
||||
console.log('🔄 重新绘制 jsplumb 连线')
|
||||
|
||||
// 等待 DOM 更新完成
|
||||
nextTick(() => {
|
||||
// 清除旧连线
|
||||
jsplumb.reset()
|
||||
|
||||
// 等待 DOM 稳定后重新绘制
|
||||
setTimeout(() => {
|
||||
const arr: ConnectArg[] = []
|
||||
const currentTaskId = agentsStore.currentTask?.Id
|
||||
|
||||
// 重新绘制所有连线
|
||||
collaborationProcess.value.forEach(item => {
|
||||
arr.push(...handleCurrentTask(item, item.Id !== currentTaskId))
|
||||
})
|
||||
|
||||
jsplumb.connects(arr)
|
||||
console.log('✅ jsplumb 连线重绘完成,任务数:', collaborationProcess.value.length)
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
// 🆕 监听 collaborationProcess 变化,自动重绘连线
|
||||
watch(
|
||||
() => collaborationProcess,
|
||||
() => {
|
||||
console.log('🔍 collaborationProcess 发生变化,触发重绘')
|
||||
redrawConnections()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 🆕 组件挂载后初始化连线
|
||||
onMounted(() => {
|
||||
// 初始化时绘制连线
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
const arr: ConnectArg[] = []
|
||||
collaborationProcess.value.forEach(item => {
|
||||
arr.push(...handleCurrentTask(item, true))
|
||||
})
|
||||
jsplumb.connects(arr)
|
||||
console.log('✅ 初始化 jsplumb 连线完成')
|
||||
}, 100)
|
||||
})
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
changeTask,
|
||||
clear
|
||||
|
||||
Reference in New Issue
Block a user