diff --git a/ui/src/api/admin/workspace/application/application.ts b/ui/src/api/admin/workspace/application/application.ts index c4f77723b06..bcc80f24e84 100644 --- a/ui/src/api/admin/workspace/application/application.ts +++ b/ui/src/api/admin/workspace/application/application.ts @@ -1,4 +1,4 @@ -import { get, post, put } from '../../core/request' +import { del, get, getExportFile, post, put } from '../../core/request' import type { ParamsPage, ResponsePage } from '../../core/types' import type { ApplicationDetail, ApplicationFormPayload, Dict } from '@/api/types' import { getWorkspaceId } from '@/utils/resource-context' @@ -18,6 +18,16 @@ const getApplicationDetail = (applicationId: string) => { return get(`${getPrefix()}/${applicationId}`) } +/** 删除工作空间智能体。 */ +const deleteApplication = (applicationId: string) => { + return del(`${getPrefix()}/${applicationId}`) +} + +/** 导出工作空间智能体文件。 */ +const exportApplication = (applicationId: string, applicationName: string) => { + return getExportFile(`${applicationName}.mk`, `${getPrefix()}/${applicationId}/export`) +} + /** 导入智能体文件并创建工作空间智能体。 */ const postApplicationImport = (file: File, folderId: string) => { const payload = new FormData() @@ -30,9 +40,35 @@ const putApplication = (applicationId: string, data: ApplicationFormPayload) => return put(`${getPrefix()}/${applicationId}`, data) } +/** 移动工作空间智能体。 */ +const putMoveApplication = (applicationId: string, folderId: string) => { + return put, boolean>(`${getPrefix()}/${applicationId}/move/${folderId}`, {}) +} + +/** 批量删除工作空间智能体。 */ +const putBatchDeleteApplications = (applicationIds: string[]) => { + return put<{ id_list: string[] }, boolean>(`${getPrefix()}/batch_delete`, { id_list: applicationIds }) +} + +/** 批量移动工作空间智能体。 */ +const putBatchMoveApplications = (applicationIds: string[], folderId: string) => { + return put<{ folder_id: string; id_list: string[] }, boolean>(`${getPrefix()}/batch_move`, { folder_id: folderId, id_list: applicationIds }) +} + /** 发布工作空间智能体。 */ const putApplicationPublish = (applicationId: string) => { return put, ApplicationDetail>(`${getPrefix()}/${applicationId}/publish`, {}) } -export default { getApplicationPage, getApplicationDetail, postApplicationImport, putApplication, putApplicationPublish } +export default { + getApplicationPage, + getApplicationDetail, + deleteApplication, + exportApplication, + postApplicationImport, + putApplication, + putMoveApplication, + putBatchDeleteApplications, + putBatchMoveApplications, + putApplicationPublish, +} diff --git a/ui/src/assets/iconfont.js b/ui/src/assets/iconfont.js index 051efd638ed..816a752493a 100644 --- a/ui/src/assets/iconfont.js +++ b/ui/src/assets/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_5200172='',(l=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var o,v,t,i,c,d=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,h=document.createElement("div");h.innerHTML=l._iconfont_svg_string_5200172,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?d(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=l.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file +window._iconfont_svg_string_5200172='',(l=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var o,v,t,i,c,d=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,h=document.createElement("div");h.innerHTML=l._iconfont_svg_string_5200172,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?d(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=l.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file diff --git a/ui/src/components/business/folder-tree/index.vue b/ui/src/components/business/folder-tree/index.vue index ef8352c90a6..6b8aa0bed84 100644 --- a/ui/src/components/business/folder-tree/index.vue +++ b/ui/src/components/business/folder-tree/index.vue @@ -15,7 +15,15 @@ const MoveToDialog = defineAsyncComponent(() => import('./MoveToDialog.vue')) defineOptions({ name: 'FolderTree' }) const props = withDefaults( - defineProps<{ canEdit?: boolean; disabledFolderIds?: string[]; draggable?: boolean; rootLabel?: string; showAll?: boolean; showShared?: boolean; source: FolderSource }>(), + defineProps<{ + canEdit?: boolean + disabledFolderIds?: string[] + draggable?: boolean + rootLabel?: string + showAll?: boolean + showShared?: boolean + source: FolderSource + }>(), { canEdit: true, disabledFolderIds: () => [], draggable: false, rootLabel: '', showAll: true, showShared: true }, ) @@ -92,10 +100,13 @@ function sortFolders(folders: FolderItem[], parentId: string, positionCache = re [FOLDER_SORT.CREATE_TIME_DESC]: (left, right) => new Date(right.create_time ?? 0).getTime() - new Date(left.create_time ?? 0).getTime(), [FOLDER_SORT.NAME_ASC]: (left, right) => left.name.localeCompare(right.name), [FOLDER_SORT.NAME_DESC]: (left, right) => right.name.localeCompare(left.name), - [FOLDER_SORT.CUSTOM]: (left, right) => (customPositions[left.id] ?? Number.MAX_SAFE_INTEGER) - (customPositions[right.id] ?? Number.MAX_SAFE_INTEGER), + [FOLDER_SORT.CUSTOM]: (left, right) => + (customPositions[left.id] ?? Number.MAX_SAFE_INTEGER) - (customPositions[right.id] ?? Number.MAX_SAFE_INTEGER), } - return [...folders].sort(compareMethods[currentSort.value]).map((folder) => ({ ...folder, children: sortFolders(folder.children ?? [], folder.id, positionCache) })) + return [...folders] + .sort(compareMethods[currentSort.value]) + .map((folder) => ({ ...folder, children: sortFolders(folder.children ?? [], folder.id, positionCache) })) } function readCustomPositions(): Record> { @@ -109,7 +120,9 @@ function writeCustomPositions(positionCache: Record>) { const savedPositions = positionCache[parentId] ?? {} - const orderedFolders = [...folders].sort((left, right) => (savedPositions[left.id] ?? Number.MAX_SAFE_INTEGER) - (savedPositions[right.id] ?? Number.MAX_SAFE_INTEGER)) + const orderedFolders = [...folders].sort( + (left, right) => (savedPositions[left.id] ?? Number.MAX_SAFE_INTEGER) - (savedPositions[right.id] ?? Number.MAX_SAFE_INTEGER), + ) positionCache[parentId] = Object.fromEntries(orderedFolders.map((folder, index) => [folder.id, index + 1])) orderedFolders.forEach((folder) => { @@ -261,7 +274,8 @@ function getFolderDeleteContext(folder: FolderItem) { // 顶级文件夹按当前展示顺序回退到下一个、上一个或“全部”。 const siblingFolders = sortTreeData.value const folderIndex = siblingFolders.findIndex(({ id }) => id === deletedFolder.id) - const targetFolder = folderIndex < 0 ? folderEntries.value.all : (siblingFolders[folderIndex + 1] ?? siblingFolders[folderIndex - 1] ?? folderEntries.value.all) + const targetFolder = + folderIndex < 0 ? folderEntries.value.all : (siblingFolders[folderIndex + 1] ?? siblingFolders[folderIndex - 1] ?? folderEntries.value.all) return { positionCache, targetFolder } } @@ -311,7 +325,7 @@ defineExpose({ refresh: loadFolders, openCreate: handleOpenCreateFolder })
- +