-为 public/agent.json 中的每个智能体添加 Classification 字段以支持分类展示 - 新增 AgentRepoList 组件用于渲染智能体列表,提升代码复用性 - 在 src/layout/components/Main/TaskTemplate/AgentRepo/index.vue 中实现基于 Classification 的智能体分组展示逻辑- 移除旧版 popover 方式展示智能体详情,改用新的列表组件统一处理 - 修改任务搜索输入框为 textarea 类型,并优化其聚焦与失焦状态下的样式表现 - 调整任务模板页面布局高度计算方式,确保适配新 UI 结构 -修复任务结果流程图连线方向及透明度判断逻辑,增强可视化准确性- 引入流动动画效果至 jsPlumb 连线,区分 input/output 类型并美化视觉呈现 - 更新配置文件中部分动作类型的配色值,提高界面美观度 - 升级本地存储键名 agents 至 agents-v1,避免
170 lines
4.2 KiB
TypeScript
170 lines
4.2 KiB
TypeScript
import type {
|
||
AnchorSpec,
|
||
ConnectorSpec,
|
||
ConnectParams,
|
||
EndpointOptions,
|
||
JsPlumbInstance,
|
||
} from '@jsplumb/browser-ui'
|
||
import { BezierConnector, DotEndpoint, newInstance } from '@jsplumb/browser-ui'
|
||
|
||
export interface JsplumbConfig {
|
||
connector?: ConnectorSpec
|
||
type?: 'input' | 'output'
|
||
stops?: [[number, string], [number, string]]
|
||
// 连接线条是否变透明一些
|
||
transparent?: boolean
|
||
}
|
||
|
||
export interface ConnectArg {
|
||
sourceId: string
|
||
targetId: string
|
||
anchor: AnchorSpec
|
||
config?: JsplumbConfig
|
||
}
|
||
|
||
const defaultConfig: JsplumbConfig = {
|
||
connector: {
|
||
type: BezierConnector.type,
|
||
options: {
|
||
curviness: 70,
|
||
stub: 10,
|
||
},
|
||
},
|
||
type: 'input',
|
||
}
|
||
|
||
export class Jsplumb {
|
||
instance!: JsPlumbInstance
|
||
containerId: string
|
||
config: JsplumbConfig
|
||
|
||
constructor(eleId: string, config = {} as JsplumbConfig) {
|
||
this.containerId = eleId
|
||
this.config = { ...defaultConfig, ...config }
|
||
onMounted(() => {
|
||
this.init()
|
||
})
|
||
}
|
||
|
||
init = () => {
|
||
if (this.instance) {
|
||
return
|
||
}
|
||
this.instance = newInstance({
|
||
container: document.querySelector(`#${this.containerId}`)!, // 或指定共同的父容器
|
||
})
|
||
}
|
||
|
||
getStops = (type?: 'input' | 'output'): [[number, string], [number, string]] => {
|
||
if (type === 'input') {
|
||
return [
|
||
[0, '#FF6161'],
|
||
[1, '#D76976'],
|
||
]
|
||
}
|
||
|
||
return [
|
||
[0, '#0093EB'],
|
||
[1, '#00D2D1'],
|
||
]
|
||
}
|
||
|
||
_connect = (
|
||
sourceId: string,
|
||
targetId: string,
|
||
anchor: AnchorSpec,
|
||
_config = {} as JsplumbConfig,
|
||
) => {
|
||
const config = {
|
||
...defaultConfig,
|
||
...this.config,
|
||
..._config,
|
||
}
|
||
this.init()
|
||
// 连接两个元素
|
||
const sourceElement = document.querySelector(`#${sourceId}`)
|
||
const targetElement = document.querySelector(`#${targetId}`)
|
||
const stops = _config.stops ?? this.getStops(config.type)
|
||
// 如果config.transparent为true,则将stops都加一些透明度
|
||
if (config.transparent) {
|
||
stops[0][1] = stops[0][1] + '30'
|
||
stops[1][1] = stops[1][1] + '30'
|
||
}
|
||
if (targetElement && sourceElement) {
|
||
this.instance.connect({
|
||
source: sourceElement,
|
||
target: targetElement,
|
||
connector: config.connector,
|
||
anchor: anchor,
|
||
paintStyle: {
|
||
stroke: stops[0][1],
|
||
strokeWidth: 2.5,
|
||
dashstyle: '0',
|
||
zIndex: 100,
|
||
opacity: 0.9,
|
||
gradient: {
|
||
stops: stops,
|
||
type: 'linear',
|
||
},
|
||
},
|
||
sourceEndpointStyle: { fill: stops[0][1] },
|
||
|
||
endpoint: {
|
||
type: DotEndpoint.type,
|
||
options: { radius: 5 },
|
||
},
|
||
cssClass: `jtk-connector-${config.type}`
|
||
} as unknown as ConnectParams<unknown>)
|
||
|
||
// 为源元素添加端点
|
||
this.instance.addEndpoint(sourceElement, {
|
||
anchor: (anchor as [AnchorSpec, AnchorSpec])[0],
|
||
paintStyle: { fill: stops[0][1], zIndex: 100 }, // source端点颜色
|
||
} as unknown as EndpointOptions)
|
||
|
||
// 为目标元素添加端点
|
||
this.instance.addEndpoint(targetElement, {
|
||
anchor: (anchor as [AnchorSpec, AnchorSpec])[1],
|
||
paintStyle: { fill: stops[1][1], zIndex: 100 }, // target端点颜色
|
||
} as unknown as EndpointOptions)
|
||
}
|
||
}
|
||
|
||
connect = (
|
||
sourceId: string,
|
||
targetId: string,
|
||
anchor: AnchorSpec,
|
||
config = {} as JsplumbConfig,
|
||
) => {
|
||
this._connect(sourceId, targetId, anchor, config)
|
||
}
|
||
|
||
connects = (args: ConnectArg[]) => {
|
||
this.instance.batch(() => {
|
||
args.forEach(({ sourceId, targetId, anchor, config }) => {
|
||
this._connect(sourceId, targetId, anchor, config)
|
||
})
|
||
})
|
||
}
|
||
|
||
repaintEverything = () => {
|
||
// 重新验证元素位置
|
||
const container = document.querySelector(`#${this.containerId}`)
|
||
if (container) {
|
||
const elements = container.querySelectorAll('[id^="task-results-"]')
|
||
elements.forEach((element) => {
|
||
this.instance.revalidate(element)
|
||
})
|
||
}
|
||
this.instance.repaintEverything()
|
||
}
|
||
|
||
reset = () => {
|
||
this.instance.deleteEveryConnection()
|
||
const allEndpoints = this.instance.selectEndpoints()
|
||
allEndpoints.each((endpoint) => {
|
||
this.instance.deleteEndpoint(endpoint)
|
||
})
|
||
}
|
||
}
|