1919 <template v-for =" (node , index ) in filter_menu_nodes " :key =" index " >
2020 <el-text type =" info" size =" small" class =" color-secondary ml-12" >{{
2121 node.label
22- }}</el-text >
22+ }}</el-text >
2323 <div class =" flex-wrap mt-8" >
2424 <template v-for =" (item , index ) in node .list " :key =" index " >
2525 <el-popover placement =" right" :width =" 280" >
2626 <template #reference >
27- <div
28- class =" flex align-center border border-r-6 mb-12 p-8-12 cursor ml-12"
29- style =" width : 39% "
30- @click.stop =" clickNodes(item)"
31- @mousedown.stop =" onmousedown(item)"
32- >
27+ <div class =" list-item flex align-center border border-r-6 mb-12 p-8-12 cursor ml-12"
28+ style =" width : 39% " @click.stop =" clickNodes(item)" @mousedown.stop =" onmousedown(item)" >
3329 <component
3430 :is =" iconComponent(`${item.type}-icon`)"
3531 class =" mr-8"
4945 </div >
5046 <el-text type =" info" size =" small" class =" color-secondary lighter" >{{
5147 item.text
52- }}</el-text >
48+ }}</el-text >
5349 </template >
5450 </el-popover >
5551 </template >
6359 </el-tab-pane >
6460 <el-tab-pane :label =" $t('views.tool.title')" name =" tool" >
6561 <el-scrollbar height =" 400" >
66- <div
67- class =" workflow-dropdown-item cursor flex p-8-12"
68- @click.stop =" clickNodes(toolNode)"
69- @mousedown.stop =" onmousedown(toolNode)"
70- >
71- <component :is =" iconComponent(`tool-lib-node-icon`)" class =" mr-8 mt-4" :size =" 32" />
72- <div class =" pre-wrap" >
73- <div class =" lighter" >{{ toolNode.label }}</div >
74- <el-text type =" info" size =" small" >{{ toolNode.text }}</el-text >
75- </div >
76- </div >
77-
78- <template v-for =" (item , index ) in filter_tool_lib_list " :key =" index " >
79- <div
80- class =" workflow-dropdown-item cursor flex p-8-12 align-center"
81- @click.stop =" clickNodes(toolLibNode, item, 'tool')"
82- @mousedown.stop =" onmousedown(toolLibNode, item, 'tool')"
83- >
84- <component
85- :is =" iconComponent(`tool-lib-node-icon`)"
86- class =" mr-8"
87- :size =" 32"
88- :item =" item"
89- />
62+ <!-- 共享工具 -->
63+ <el-collapse expand-icon-position =" left" >
64+ <el-collapse-item name =" shared" :icon =" CaretRight" >
65+ <template #title >
66+ <div class =" flex align-center" >
67+ <AppIcon iconName =" app-shared-active" style =" font-size : 20px " class =" color-primary" ></AppIcon >
68+ <span class =" ml-8 lighter" >{{ $t('views.shared.shared_tool') }}</span >
69+ </div >
70+ </template >
71+ <NodeContent :list =" sharedToolList" @clickNodes =" (val: any) => clickNodes(toolLibNode, val, 'tool')"
72+ @onmousedown =" (val: any) => onmousedown(toolLibNode, val, 'tool')" />
73+ </el-collapse-item >
74+ </el-collapse >
9075
91- <div class =" pre-wrap" >
92- <div class =" lighter ellipsis-1" :title =" item.name" >{{ item.name }}</div >
93- <p >
94- <el-text
95- class =" ellipsis-1"
96- type =" info"
97- size =" small"
98- :title =" item.desc"
99- v-if =" item.desc"
100- >{{ item.desc }}</el-text
101- >
102- </p >
103- </div >
104- </div >
105- </template >
76+ <el-tree :data =" toolTreeData" node-key =" id"
77+ :props =" { children: 'children', isLeaf: 'isLeaf', class: getNodeClass }" lazy :load =" loadNode" >
78+ <template #default =" { data , node } " >
79+ <NodeContent v-if =" !data._fake" :data =" data" :node =" node"
80+ @clickNodes =" (val: any) => clickNodes(toolLibNode, val, 'tool')"
81+ @onmousedown =" (val: any) => onmousedown(toolLibNode, val, 'tool')" />
82+ </template >
83+ </el-tree >
10684 </el-scrollbar >
10785 </el-tab-pane >
10886 <el-tab-pane :label =" $t('views.application.title')" name =" application" >
10987 <el-scrollbar height =" 400" >
110- <div v-if =" filter_application_list.length > 0" >
111- <template v-for =" (item , index ) in filter_application_list " :key =" index " >
112- <div
113- class =" workflow-dropdown-item cursor flex align-center p-8-12"
114- @click.stop =" clickNodes(applicationNode, item, 'application')"
115- @mousedown.stop =" onmousedown(applicationNode, item, 'application')"
116- >
117- <component
118- :is =" iconComponent(`application-node-icon`)"
119- class =" mr-8"
120- :size =" 32"
121- :item =" item"
122- />
123- <div class =" pre-wrap" style =" width : 60% " >
124- <div class =" lighter ellipsis" :title =" item.name" >
125- {{ item.name }}
126- </div >
127- <p >
128- <el-text
129- class =" ellipsis"
130- type =" info"
131- size =" small"
132- :title =" item.desc"
133- v-if =" item.desc"
134- >{{ item.desc }}</el-text
135- >
136- </p >
137- </div >
138- <div class =" status-tag" style =" margin-left : auto " >
139- <el-tag type =" warning" v-if =" isWorkFlow(item.type)" style =" height : 22px " >
140- {{ $t('views.application.workflow') }}</el-tag
141- >
142- <el-tag class =" blue-tag" v-else style =" height : 22px " >{{
143- $t('views.application.simple')
144- }}</el-tag >
145- </div >
146- </div >
88+ <el-tree :data =" applicationTreeData" node-key =" id"
89+ :props =" { children: 'children', isLeaf: 'isLeaf', class: getNodeClass }" lazy :load =" loadNode" >
90+ <template #default =" { data , node } " >
91+ <NodeContent v-if =" !data._fake" :data =" data" :node =" node"
92+ @clickNodes =" (val: any) => clickNodes(applicationNode, val, 'application')"
93+ @onmousedown =" (val: any) => onmousedown(applicationNode, val, 'application')" />
14794 </template >
148- </div >
149- <div v-else class =" ml-16 mt-8" >
150- <el-text type =" info" >{{ $t('views.applicationWorkflow.tip.noData') }}</el-text >
151- </div >
95+ </el-tree >
15296 </el-scrollbar >
15397 </el-tab-pane >
15498 </el-tabs >
15599 </div >
156100</template >
157101<script setup lang="ts">
158102import { ref , onMounted , computed } from ' vue'
159- import { menuNodes , toolNode , toolLibNode , applicationNode } from ' @/workflow/common/data'
103+ import { menuNodes , toolLibNode , applicationNode } from ' @/workflow/common/data'
160104import { iconComponent } from ' @/workflow/icons/utils'
161- import applicationApi from ' @/api/application/application '
105+ import ToolApi from ' @/api/tool/tool '
162106import { isWorkFlow } from ' @/utils/application'
163- import { isAppIcon } from ' @/utils/common'
107+ import useStore from ' @/stores'
108+ import NodeContent from ' ./NodeContent.vue'
109+ import { SourceTypeEnum } from ' @/enums/common'
110+ import sharedWorkspaceApi from ' @/api/shared-workspace'
111+ import { CaretRight } from ' @element-plus/icons-vue'
112+ import ApplicationApi from ' @/api/application/application'
113+
164114const search_text = ref <string >(' ' )
165115const props = defineProps ({
166116 show: {
@@ -174,24 +124,12 @@ const props = defineProps({
174124 workflowRef: Object ,
175125})
176126
127+ const { folder } = useStore ()
177128const emit = defineEmits ([' clickNodes' , ' onmousedown' ])
178129
179130const loading = ref (false )
180131const activeName = ref (' base' )
181132
182- const toolList = ref <any []>([])
183- const filter_tool_lib_list = computed (() => {
184- return toolList .value .filter ((item : any ) =>
185- item .name .toLocaleLowerCase ().includes (search_text .value .toLocaleLowerCase ()),
186- )
187- })
188- const applicationList = ref <any []>([])
189- const filter_application_list = computed (() => {
190- return applicationList .value .filter ((item : any ) =>
191- item .name .toLocaleLowerCase ().includes (search_text .value .toLocaleLowerCase ()),
192- )
193- })
194-
195133const filter_menu_nodes = computed (() => {
196134 if (! search_text .value ) return menuNodes
197135 const searchTerm = search_text .value .toLowerCase ()
@@ -234,10 +172,10 @@ function clickNodes(item: any, data?: any, type?: string) {
234172 ... (! fileUploadSetting
235173 ? {}
236174 : {
237- ... (fileUploadSetting .document ? { document_list: [] } : {}),
238- ... (fileUploadSetting .image ? { image_list: [] } : {}),
239- ... (fileUploadSetting .audio ? { audio_list: [] } : {}),
240- }),
175+ ... (fileUploadSetting .document ? { document_list: [] } : {}),
176+ ... (fileUploadSetting .image ? { image_list: [] } : {}),
177+ ... (fileUploadSetting .audio ? { audio_list: [] } : {}),
178+ }),
241179 }
242180 } else {
243181 item [' properties' ][' node_data' ] = {
@@ -279,10 +217,10 @@ function onmousedown(item: any, data?: any, type?: string) {
279217 ... (! fileUploadSetting
280218 ? {}
281219 : {
282- ... (fileUploadSetting .document ? { document_list: [] } : {}),
283- ... (fileUploadSetting .image ? { image_list: [] } : {}),
284- ... (fileUploadSetting .audio ? { audio_list: [] } : {}),
285- }),
220+ ... (fileUploadSetting .document ? { document_list: [] } : {}),
221+ ... (fileUploadSetting .image ? { image_list: [] } : {}),
222+ ... (fileUploadSetting .audio ? { audio_list: [] } : {}),
223+ }),
286224 }
287225 } else {
288226 item [' properties' ][' node_data' ] = {
@@ -297,17 +235,72 @@ function onmousedown(item: any, data?: any, type?: string) {
297235 emit (' onmousedown' , item )
298236}
299237
300- function getList() {
301- // applicationApi.listTool(props.id, loading).then((res: any) => {
302- // toolList.value = res.data
303- // })
304- // applicationApi.getApplicationList(props.id, loading).then((res: any) => {
305- // applicationList.value = res.data
306- // })
238+ function getNodeClass(data : any ) {
239+ return data ._fake ? ' tree-node--hidden' : ' '
240+ }
241+
242+ const loadNode = async (node : any , resolve : (children : any []) => void ) => {
243+ if (node .level === 0 ) return resolve ([])
244+ try {
245+ let folders
246+ if (activeName .value === ' tool' ) {
247+ const res = await ToolApi .getToolList ({ folder_id: node .data .id })
248+ node .data .cardList = res .data .tools
249+ folders = res .data ?.folders
250+ } else {
251+ const res = await ApplicationApi .getAllApplication ({ folder_id: node .data .id })
252+ node .data .cardList = res .data .filter (item => item .resource_type === " application" )
253+ folders = res .data .filter (item => item .resource_type === " folder" )
254+ }
255+ const children = folders .map (f => ({
256+ ... f ,
257+ children: [],
258+ isLeaf: false ,
259+ }))
260+
261+ if (folders .length === 0 && node .data .cardList .length > 0 ) {
262+ // 插一个假子节点,确保树节点是“可折叠”的
263+ children .push ({
264+ id: ` __placeholder__${node .data .id } ` ,
265+ isLeaf: true ,
266+ _fake: true ,
267+ })
268+ }
269+
270+ resolve (children )
271+ } catch (e : any ) {
272+ resolve ([]) // 失败也要 resolve,否则树会卡住
273+ }
274+ }
275+
276+ const toolTreeData = ref <any []>([])
277+ function getToolFolder() {
278+ folder .asyncGetFolder (SourceTypeEnum .TOOL , {}, loading ).then ((res : any ) => {
279+ toolTreeData .value = res .data
280+ })
281+ }
282+
283+ const sharedToolList = ref <any []>([])
284+ async function getShareTool() {
285+ try {
286+ const res = await sharedWorkspaceApi .getToolList (loading )
287+ sharedToolList .value = res .data
288+ } catch (error : any ) {
289+ console .error (error )
290+ }
291+ }
292+
293+ const applicationTreeData = ref <any []>([])
294+ function getApplicationFolder() {
295+ folder .asyncGetFolder (SourceTypeEnum .APPLICATION , {}, loading ).then ((res : any ) => {
296+ applicationTreeData .value = res .data
297+ })
307298}
308299
309300onMounted (() => {
310- // getList()
301+ getShareTool ()
302+ getToolFolder ()
303+ getApplicationFolder ()
311304})
312305 </script >
313306<style lang="scss" scoped>
@@ -335,5 +328,46 @@ onMounted(() => {
335328 background : var (--app-text-color-light-1 );
336329 }
337330 }
331+
332+ .list-item {
333+ & :hover {
334+ border-color : var (--el-color-primary );
335+ }
336+ }
337+
338+ :deep (.el-collapse ) {
339+ border-top-width : 0 ;
340+ .el-collapse-item__header {
341+ height : 40px ;
342+ gap : 0 ;
343+ .el-collapse-item__arrow {
344+ font-size : 16px ;
345+ color : var (--app-text-color-secondary );
346+ padding : 6px ;
347+ }
348+ }
349+ .el-collapse-item__content {
350+ padding : 0 12px 16px 12px ;
351+ .list {
352+ margin-top : 0 ;
353+ transform : none ;
354+ }
355+ }
356+ }
357+
358+ :deep(.el-tree-node ):focus >.el-tree-node__content {
359+ background : transparent ;
360+ }
361+ :deep(.el-tree-node__content ) {
362+ height : auto ;
363+ align-items : baseline ;
364+ & :hover {
365+ background : transparent ;
366+ }
367+ }
368+
369+ :deep(.tree-node--hidden ) {
370+ display : none !important ;
371+ }
338372}
339373 </style >
0 commit comments