Skip to content

Commit 5531d0c

Browse files
feat: workflow
1 parent 0867f65 commit 5531d0c

9 files changed

Lines changed: 55 additions & 37 deletions

File tree

‎ui/AGENTS.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ Keep these behaviors:
189189
## Frontend Implementation Notes
190190

191191
- Prefer existing project structure and naming.
192+
- Before changing existing behavior, trace the affected flow and dependent requirements, including
193+
why the current implementation exists. If the requested change is likely to remove a requirement
194+
or introduce a regression, pause before editing, explain the risk, recommend a safer approach,
195+
and wait for confirmation.
192196
- Keep UI code typed and data-driven.
193197
- Use Lodash `cloneDeep` for deep cloning; do not use `structuredClone`.
194198
- Explicitly import APIs used from Vue, Vue Router, and Pinia; do not restore API auto import.

‎ui/src/api/admin/workspace/application/application.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ const getPrefix = () => {
88
return `/workspace/${workspaceId}/application`
99
}
1010

11+
/**
12+
* 获取不分页的全部应用
13+
*/
14+
const getAllApplication = (query?: Dict<unknown>) => {
15+
return get<ApplicationDetail[]>(`${getPrefix()}`, query)
16+
}
17+
1118
/** 获取工作空间智能体列表。 */
1219
const getApplicationPage = (page: ParamsPage, query?: Dict<unknown>) => {
1320
return get<ResponsePage<ApplicationDetail>>(`${getPrefix()}/${page.currentPage}/${page.pageSize}`, query)
@@ -77,4 +84,5 @@ export default {
7784
putBatchDeleteApplications,
7885
putBatchMoveApplications,
7986
putApplicationPublish,
87+
getAllApplication,
8088
}

‎ui/src/api/admin/workspace/shared.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,18 @@ const getModelList = (query?: Dict<unknown>) => {
1313
return get<ModelItem[]>(`${getPrefix()}/model`, query)
1414
}
1515

16-
/** 获取工作空间共享的工具列表。 */
16+
/** 获取工作空间共享的分页工具列表。 */
1717
const getToolPage = (page: ParamsPage, query?: Dict<unknown>) => {
1818
return get<ResponsePage<ToolItem>>(`${getPrefix()}/tool/${page.currentPage}/${page.pageSize}`, query)
1919
}
20+
/** 获取工作空间共享的不分页所有工具列表。 */
21+
const getAllTool = (query?: Dict<unknown>) => {
22+
return get<ToolItem[]>(`${getPrefix()}/tool`, query)
23+
}
2024

2125
/** 获取工作空间共享的知识库列表。 */
2226
const getKnowledgePage = (page: ParamsPage, query?: Dict<unknown>) => {
2327
return get<ResponsePage<KnowledgeItem>>(`${getPrefix()}/knowledge/${page.currentPage}/${page.pageSize}`, query)
2428
}
2529

26-
export default { getKnowledgePage, getModelList, getToolPage }
30+
export default { getKnowledgePage, getModelList, getToolPage, getAllTool }

‎ui/src/api/admin/workspace/tool/tool.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ const getPrefix = () => {
88
return `/workspace/${workspaceId}/tool`
99
}
1010

11+
/** 获取不分页的全部工具列表。 */
12+
const getAllTool = (query?: Dict<unknown>) => {
13+
return get<{ tools: ToolItem[] }>(`${getPrefix()}`, query).then(({ tools }) => tools)
14+
}
15+
1116
/** 获取工具分页列表。 */
1217
const getToolPage = (page: ParamsPage, query?: Dict<unknown>) => {
1318
return get<ResponsePage<ToolItem>>(`${getPrefix()}/${page.currentPage}/${page.pageSize}`, query)
@@ -104,4 +109,5 @@ export default {
104109
putBatchDeleteTools,
105110
putBatchMoveTools,
106111
putTool,
112+
getAllTool,
107113
}

‎ui/src/api/enums/tool.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** 后端 Workspace 工具作用域枚举值。 */
1+
/** TODO 后端 Workspace 工具作用域枚举值。 */
22
export const TOOL_SCOPE = { INTERNAL: 'INTERNAL', SHARED: 'SHARED', WORKSPACE: 'WORKSPACE' } as const
33

44
/** 后端 Workspace 工具类型枚举值。 */

‎ui/src/views/tool/ToolView.vue‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import ToolApi from '@/api/admin/workspace/tool/tool'
66
import SharedApi from '@/api/admin/workspace/shared'
77
import ToolStoreApi from '@/api/admin/tool-store.ts'
88
import type { Dict, FolderItem, OptionItem, ToolItem, ToolStoreResponse, ToolType } from '@/api/types'
9-
import { RESOURCE_TYPE, TOOL_SCOPE, TOOL_TYPE } from '@/api/enums'
9+
import { RESOURCE_TYPE, TOOL_TYPE } from '@/api/enums'
1010
import { TOOL_TYPE_OPTIONS, FOLDER_ENTRIES, FOLDER_ENTRY_ID } from '@/constants'
1111
import FolderTree from '@/components/business/folder-tree/index.vue'
1212
import MoveToDialog from '@/components/business/folder-tree/MoveToDialog.vue'
@@ -69,7 +69,7 @@ const toolType = ref<ToolType | ''>('')
6969
function loadToolsPage(pagination: { currentPage: number; pageSize: number }) {
7070
const request = isShared.value ? SharedApi : ToolApi
7171
const folderId = isShared.value ? {} : { folder_id: currentFolder.value.id || FOLDER_ENTRY_ID.ALL }
72-
return request.getToolPage(pagination, { ...toolQuery.value, scope: TOOL_SCOPE.WORKSPACE, tool_type: toolType.value, ...folderId })
72+
return request.getToolPage(pagination, { ...toolQuery.value, tool_type: toolType.value, ...folderId })
7373
}
7474
7575
// 加载工具商店

‎ui/src/workflow-canvas/node-menu/ResourceNodeMenu.vue‎

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<script setup lang="ts">
2-
import { computed, ref } from 'vue'
2+
import { computed, onMounted, ref } from 'vue'
33
import { useRoute } from 'vue-router'
44
import { cloneDeep } from 'lodash'
55
import ApplicationApi from '@/api/admin/workspace/application/application'
66
import SharedApi from '@/api/admin/workspace/shared'
77
import ToolApi from '@/api/admin/workspace/tool/tool'
8-
import { APPLICATION_TYPE, RESOURCE_TYPE, TOOL_SCOPE, TOOL_TYPE } from '@/api/enums'
8+
import { APPLICATION_TYPE, RESOURCE_TYPE, TOOL_TYPE } from '@/api/enums'
99
import type { ApplicationDetail, ApplicationType, FolderItem, ToolItem, ToolType } from '@/api/types'
1010
import FolderTree from '@/components/business/folder-tree/index.vue'
1111
import { FOLDER_ENTRY_ID } from '@/constants'
@@ -30,10 +30,9 @@ interface ResourceMenuItem {
3030
toolType?: ToolType
3131
}
3232
33-
const RESOURCE_PAGE = { currentPage: 1, pageSize: 1_000 }
3433
const SUPPORTED_TOOL_TYPES: ToolType[] = [TOOL_TYPE.CUSTOM, TOOL_TYPE.WORKFLOW]
3534
const route = useRoute()
36-
const currentFolderId = ref('')
35+
const currentFolderId = ref(FOLDER_ENTRY_ID.ALL)
3736
const loading = ref(false)
3837
const resourceItems = ref<ResourceMenuItem[]>([])
3938
const searchKeyword = ref('')
@@ -71,13 +70,17 @@ function createApplicationNode(application: ApplicationDetail): NodeMenuItem {
7170
return node
7271
}
7372
74-
function loadTools(folder: FolderItem) {
75-
const requestApi = folder.id === FOLDER_ENTRY_ID.SHARED ? SharedApi : ToolApi
76-
const folderQuery = folder.id === FOLDER_ENTRY_ID.SHARED ? {} : { folder_id: folder.id }
73+
function loadTools(folder?: FolderItem) {
74+
const isSharedFolder = folder?.id === FOLDER_ENTRY_ID.SHARED
75+
const requestApi = isSharedFolder ? SharedApi : ToolApi
76+
const folderQuery = {
77+
tool_type_list: SUPPORTED_TOOL_TYPES,
78+
...(!isSharedFolder ? { folder_id: folder?.id || FOLDER_ENTRY_ID.ALL } : {}),
79+
}
7780
78-
return requestApi.getToolPage(RESOURCE_PAGE, { ...folderQuery, scope: TOOL_SCOPE.WORKSPACE }).then((page) => {
79-
resourceItems.value = page.records
80-
.filter((tool) => tool.is_active && SUPPORTED_TOOL_TYPES.includes(tool.tool_type))
81+
return requestApi.getAllTool(folderQuery).then((tools) => {
82+
resourceItems.value = tools
83+
.filter((tool) => tool.is_active)
8184
.map((tool) => ({
8285
desc: tool.desc,
8386
icon: tool.icon,
@@ -89,10 +92,12 @@ function loadTools(folder: FolderItem) {
8992
})
9093
}
9194
92-
function loadApplications(folder: FolderItem) {
93-
return ApplicationApi.getApplicationPage(RESOURCE_PAGE, { folder_id: folder.id, publish_status: 'published' }).then((page) => {
94-
resourceItems.value = page.records
95-
.filter((application) => application.resource_type === 'application' && application.is_publish && application.id !== currentApplicationId.value)
95+
function loadApplications(folder?: FolderItem) {
96+
const folderQuery = { folder_id: folder?.id || FOLDER_ENTRY_ID.ALL }
97+
98+
return ApplicationApi.getAllApplication({ ...folderQuery, publish_status: 'published' }).then((res) => {
99+
resourceItems.value = res
100+
.filter((application) => application.id !== currentApplicationId.value)
96101
.map((application) => ({
97102
applicationType: application.type,
98103
desc: application.desc,
@@ -104,12 +109,7 @@ function loadApplications(folder: FolderItem) {
104109
})
105110
}
106111
107-
function handleFolderChange(folder?: FolderItem) {
108-
if (!folder) {
109-
resourceItems.value = []
110-
return
111-
}
112-
112+
function loadResources(folder?: FolderItem) {
113113
loading.value = true
114114
const request = isToolMenu.value ? loadTools(folder) : loadApplications(folder)
115115
return request.finally(() => {
@@ -120,19 +120,16 @@ function handleFolderChange(folder?: FolderItem) {
120120
function handleNodeDragStart(event: PointerEvent, node: NodeMenuItem) {
121121
if (event.button === 0) emit('dragstart', node, event)
122122
}
123+
124+
onMounted(() => {
125+
void loadResources()
126+
})
123127
</script>
124128

125129
<template>
126130
<div class="flex h-[450px] min-h-0">
127131
<aside class="flex w-60 shrink-0 border-r pt-3">
128-
<FolderTree
129-
v-model="currentFolderId"
130-
:can-edit="false"
131-
:show-shared="isToolMenu"
132-
:source="source"
133-
@loaded="handleFolderChange"
134-
@select="handleFolderChange"
135-
/>
132+
<FolderTree v-model="currentFolderId" :can-edit="false" :show-shared="isToolMenu" :source="source" @select="loadResources" />
136133
</aside>
137134

138135
<section v-loading="loading" class="flex min-w-0 flex-1 flex-col">

‎ui/src/workflow-canvas/nodes/start-node/index.vue‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ import { computed, inject, onBeforeUnmount, onMounted } from 'vue'
33
44
import { CopyDocument } from '@element-plus/icons-vue'
55
import { cloneDeep, set } from 'lodash'
6-
import type { WorkflowNodeField, WorkflowNodeModel } from '@/workflow-canvas/core/workflow-node'
76
import NodeContainer from '@/workflow-canvas/core/node-container/index.vue'
8-
import { WorkflowNodeType } from '@/workflow-canvas/types'
7+
import { WorkflowNodeType, type WorkflowNodeField } from '@/workflow-canvas/types'
98
import { copyText } from '@/utils/clipboard'
10-
import type { BaseEdgeModel, BaseNodeModel, GraphModel } from '@logicflow/core'
9+
import type { BaseNodeModel } from '@logicflow/core'
1110
1211
defineOptions({ name: 'WorkflowStartNode' })
1312

‎ui/src/workflow-canvas/nodes/text-to-video-node/index.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { QuestionFilled } from '@element-plus/icons-vue'
55
import type { FormInstance } from 'element-plus'
66
import ModelSelect from '@/components/business/model-select/index.vue'
77
import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue'
8-
import NodeContainer from '@/workflow-canvas/core/NodeContainer.vue'
8+
import NodeContainer from '@/workflow-canvas/core/node-container/index.vue'
99
import { useWorkflowStore } from '@/workflow-canvas/store'
1010
import type { BaseNodeModel } from '@logicflow/core'
1111
import type { ModelItem, ModelProviderItem } from '@/api/types'

0 commit comments

Comments
 (0)