mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-31 18:22:49 +00:00
* 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>
193 lines
5.0 KiB
Vue
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>
|