MaxKB/ui/src/workflow/index.vue
shaohuzhang1 bfae088df6
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Typos Check / Spell Check with Typos (push) Waiting to run
feat: knowledge workflow (#4399)
* feat: init knowledge workflow

* feat: add knowledge workflow and version models, serializers, and API views

* feat: knowledge workflow

* feat: knowledge workflow

* feat: add KnowledgeWorkflowModelSerializer and Operate class for workflow management

* fix: route

* feat: knowledge workflow

* feat: Knowledge workflow permission

* feat: knowledge workflow

* feat: knowledge workflow

* feat: knowledge workflow

* feat: knowledge workflow

* feat: Data source web node

* fix: Back route

* feat: knowledge workflow

* feat: knowledge workflow

* feat: Knowledge write node

* feat: add Data Source tool functionality and localization

* feat: add Data Source tool functionality and localization

* feat: knowledge workflow

* feat: knowledge workflow

* fix: simplify export tool permission check in ToolListContainer.vue

* fix: simplify export condition in ToolResourceIndex.vue

* fix: simplify condition for copying tool in ToolListContainer

* feat: knowledge workflow

* fix: Upload local files and add output fields

* feat: Knowledge write

* feat: add Document Split Node functionality and localization

* feat: add Document Split Node functionality and localization

* feat: Knowledge write

* feat: enhance Document Split Node with result processing and problem list generation

* fix: Allow problem be blank

* feat: enhance Document Split Node with result processing and problem list generation

* feat: tool datasource

* fix: Optimization of knowledge base workflow execution logic

* refactor: streamline image handling by updating application and knowledge ID management

* refactor: streamline image handling by updating application and knowledge ID management

* feat: extend support modes in variable aggregation node to include knowledge workflows

* feat: Chunks stored

* refactor: simplify file handling in document extraction by removing unnecessary byte conversion and enhancing file saving logic

* refactor: update file ID assignment in document extraction to use provided metadata

* feat: Workflow menu that distinguishes between applications and knowledge bases

* refactor: update file ID assignment in document extraction to use provided metadata

* fix: Add workspace ID as workflow execution parameter

* feat: add code template for Data Source tool form functionality

* refactor: remove unused sys import and improve module handling

* feat: Execution details support loading status

* refactor: update tool type handling and improve category merging logic

* feat: Alter fork depth

* fix: ensure filterList is properly initialized and updated in getList function

* refactor: simplify ToolStoreDialog by removing unused toolType logic

* perf: Optimize the style

* style: adjust div width for improved layout in Tree component

* refactor: improve polling mechanism for knowledge workflow action

* fix: Get workspace_id from workflow params

* fix: filter out 'file_bytes' from result in get_details method

* feat: add recursive filtering for file_bytes in context data

* fix: append results to paragraph_list instead of replacing it

* perf: Optimize translation files

* fix: include document name in bytes_to_uploaded_file call for better file handling

* refactor: optimize buffer retrieval in document processing

* refactor: remove redundant parameter from bytes_to_uploaded_file call

* fix: Page style optimization

* feat: add slider for setting limit in document rules form

* feat: add workflow knowledge management endpoints and related functionality

* fix: swap file size and file count limits in form inputs

* refactor: update tool_config args to use list format for improved readability

* feat: Node supports knowledge base workflow

* feat: Node supports knowledge base workflow

* fix: Basic node data cannot be obtained in the workflow

* style: Knowledge base workflow debugging page style adjustment

* fix: Loop nodes cannot be used in the knowledge base workflow

* fix: Knowledge base workflow variable assignment node

* feat: add chunk size slider to form for custom split strategy

* fix: Workflow style optimization

---------

Co-authored-by: CaptainB <bin@fit2cloud.com>
Co-authored-by: zhangzhanwei <zhanwei.zhang@fit2cloud.com>
Co-authored-by: wangdan-fit2cloud <dan.wang@fit2cloud.com>
2025-11-28 15:38:20 +08:00

193 lines
5.0 KiB
Vue

<template>
<div className="workflow-app" id="container"></div>
<!-- 辅助工具栏 -->
<Control class="workflow-control" v-if="lf" :lf="lf"></Control>
<TeleportContainer :flow-id="flowId" />
</template>
<script setup lang="ts">
import LogicFlow from '@logicflow/core'
import { ref, onMounted, onUnmounted, inject } from 'vue'
import AppEdge from './common/edge'
import loopEdge from './common/loopEdge'
import Control from './common/NodeControl.vue'
import { SelectionSelect } from '@logicflow/extension'
import '@logicflow/extension/lib/style/index.css'
import '@logicflow/core/dist/style/index.css'
import { initDefaultShortcut } from '@/workflow/common/shortcut'
import Dagre from '@/workflow/plugins/dagre'
import { disconnectAll, getTeleport } from '@/workflow/common/teleport'
import { WorkflowMode } from '@/enums/application'
const nodes: any = import.meta.glob('./nodes/**/index.ts', { eager: true })
const workflow_mode = inject('workflowMode') || WorkflowMode.Application
const loop_workflow_mode = inject('loopWorkflowMode') || WorkflowMode.ApplicationLoop
defineOptions({ name: 'WorkFlow' })
const TeleportContainer = getTeleport()
const flowId = ref('')
type ShapeItem = {
type?: string
text?: string
icon?: string
label?: string
className?: string
disabled?: boolean
properties?: Record<string, any>
callback?: (lf: LogicFlow, container?: HTMLElement) => void
}
const props = defineProps({
data: Object || null,
})
const lf = ref()
onMounted(() => {
renderGraphData()
})
onUnmounted(() => {
disconnectAll()
})
const render = (data: any) => {
lf.value.render(data)
}
const renderGraphData = (data?: any) => {
const container: any = document.querySelector('#container')
if (container) {
lf.value = new LogicFlow({
plugins: [Dagre, SelectionSelect],
textEdit: false,
adjustEdge: false,
adjustEdgeStartAndEnd: false,
background: {
backgroundColor: '#f5f6f7',
},
grid: {
size: 10,
type: 'dot',
config: {
color: '#DEE0E3',
thickness: 1,
},
},
keyboard: {
enabled: true,
},
isSilentMode: false,
container: container,
})
lf.value.setTheme({
bezier: {
stroke: '#afafaf',
strokeWidth: 1,
},
})
lf.value.on('graph:rendered', () => {
flowId.value = lf.value.graphModel.flowId
})
initDefaultShortcut(lf.value, lf.value.graphModel)
lf.value.batchRegister([
...Object.keys(nodes).map((key) => nodes[key].default),
AppEdge,
loopEdge,
])
lf.value.setDefaultEdgeType('app-edge')
lf.value.render(data ? data : {})
lf.value.graphModel.get_provide = (node: any, graph: any) => {
return {
getNode: () => node,
getGraph: () => graph,
workflowMode: workflow_mode,
loopWorkflowMode: loop_workflow_mode,
}
}
lf.value.graphModel.eventCenter.on('delete_edge', (id_list: Array<string>) => {
id_list.forEach((id: string) => {
lf.value.deleteEdge(id)
})
})
lf.value.graphModel.eventCenter.on('anchor:drop', (data: any) => {
// 清除当前节点下面的子节点的所有缓存
data.nodeModel.clear_next_node_field(false)
})
setTimeout(() => {
lf.value?.fitView()
}, 500)
}
}
const validate = () => {
return Promise.all(lf.value.graphModel.nodes.map((element: any) => element?.validate?.()))
}
const getGraphData = () => {
const graph_data = lf.value.getGraphData()
graph_data.nodes.forEach((node: any) => {
if (node.type === 'loop-body-node') {
const node_model = lf.value.getNodeModelById(node.id)
node_model.set_loop_body()
}
})
const _graph_data = lf.value.getGraphData()
_graph_data.nodes = _graph_data.nodes.filter((node: any) => node.type !== 'loop-body-node')
_graph_data.edges = graph_data.edges.filter((node: any) => node.type !== 'loop-edge')
return _graph_data
}
const onmousedown = (shapeItem: ShapeItem) => {
if (shapeItem.type) {
lf.value.dnd.startDrag({
type: shapeItem.type,
properties: { ...shapeItem.properties },
})
}
if (shapeItem.callback) {
shapeItem.callback(lf.value)
}
}
const addNode = (shapeItem: ShapeItem) => {
lf.value.clearSelectElements()
const { virtualRectCenterPositionX, virtualRectCenterPositionY } =
lf.value.graphModel.getVirtualRectSize()
const newNode = lf.value.graphModel.addNode({
type: shapeItem.type,
properties: shapeItem.properties,
x: virtualRectCenterPositionX,
y: virtualRectCenterPositionY - lf.value.graphModel.height / 2,
})
newNode.isSelected = true
newNode.isHovered = true
lf.value.toFront(newNode.id)
}
const clearGraphData = () => {
return lf.value.clearData()
}
defineExpose({
onmousedown,
validate,
getGraphData,
addNode,
clearGraphData,
renderGraphData,
render,
})
</script>
<style lang="scss">
.workflow-app {
width: 100%;
height: 100%;
position: relative;
}
.workflow-control {
position: absolute;
bottom: 24px;
left: 24px;
z-index: 2;
}
.lf-drag-able {
cursor: pointer;
}
</style>