import React, { useCallback, useState } from 'react'; import { ModalBody, ModalFooter, Button, Text, Flex, Box, IconButton } from '@chakra-ui/react'; import MyModal from '@fastgpt/web/components/common/MyModal'; import type { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/abandoned/runApp/type'; import { useTranslation } from 'next-i18next'; import SelectMultipleResource from './SelectMultipleResource'; import SearchInput from '@fastgpt/web/components/common/Input/SearchInput'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyIcon from '@fastgpt/web/components/common/Icon'; import DndDrag, { Draggable } from '@fastgpt/web/components/common/DndDrag'; import { type GetResourceFolderListProps, type GetResourceListItemResponse } from '@fastgpt/global/common/parentFolder/type'; import { getMyApps } from '@/web/core/app/api'; import { listQuickApps, batchUpdateQuickApps } from '@/web/support/user/team/gate/quickApp'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; // 扩展的应用类型,包含显示所需的属性 type ExtendedSelectAppItemType = SelectAppItemType & { name: string; avatar?: string; }; const AddQuickAppModal = ({ isOpen = true, value, filterAppIds = [], onClose, onSuccess }: { isOpen?: boolean; value?: ExtendedSelectAppItemType[]; filterAppIds?: string[]; onClose: () => void; onSuccess: (e: ExtendedSelectAppItemType[]) => void; }) => { const { t } = useTranslation(); const [selectedApps, setSelectedApps] = useState([]); const [searchKey, setSearchKey] = useState(''); // 使用 listQuickApps 初始化已选择的应用数组 const { data: quickApps = [], loading: loadingQuickApps } = useRequest2(() => listQuickApps(), { manual: false, onSuccess: (data) => { const initialSelectedApps = data.map((app) => ({ id: app._id, name: app.name, avatar: app.avatar })); setSelectedApps(initialSelectedApps); } }); const getAppList = useCallback( async ({ parentId }: GetResourceFolderListProps) => { return getMyApps({ parentId, searchKey, type: [AppTypeEnum.folder, AppTypeEnum.simple, AppTypeEnum.workflow] }).then((res) => res .filter((item) => !filterAppIds.includes(item._id)) .map((item) => ({ id: item._id, name: item.name, avatar: item.avatar, isFolder: item.type === AppTypeEnum.folder })) ); }, [filterAppIds, searchKey] ); const handleAppSelect = useCallback((appId: string, appData: GetResourceListItemResponse) => { setSelectedApps((prev) => { const exists = prev.find((app) => app.id === appId); if (exists) { // 如果已存在,则移除 return prev.filter((app) => app.id !== appId); } else { // 如果不存在,则添加到末尾 return [...prev, { id: appId, name: appData.name, avatar: appData.avatar }]; } }); }, []); const handleAppUnselect = useCallback((appId: string) => { setSelectedApps((prev) => prev.filter((app) => app.id !== appId)); }, []); // 处理拖拽排序 const handleDragEnd = useCallback((reorderedList: ExtendedSelectAppItemType[]) => { setSelectedApps(reorderedList); }, []); // 批量更新快速应用 const { runAsync: updateQuickApps, loading: isUpdating } = useRequest2( () => { const updates = [{ quickApps: selectedApps.map((app) => app.id) }]; return batchUpdateQuickApps(updates); }, { manual: true, onSuccess: () => { onSuccess(selectedApps); onClose(); }, onError: (error) => { console.error('更新快速应用失败:', error); } } ); return ( {/* 左侧应用选择区域 */} {/* 搜索框 */} setSearchKey(e.target.value)} placeholder={t('app:search_app')} /> {/* 应用选择区域 */} app.id)} onSelect={handleAppSelect} server={getAppList} searchKey={searchKey} /> {/* 右侧已选择应用排序区域 */} {t('common:selected')} {selectedApps.length} {selectedApps.length > 0 ? ( onDragEndCb={handleDragEnd} dataList={selectedApps} > {({ provided }) => ( {selectedApps.map((app, index) => ( {(provided, snapshot) => ( {/* 拖拽图标 */} {/* 应用图标 */} {/* 应用名称 */} {app.name} {/* 删除按钮 */} } aria-label="remove" onClick={(e) => { e.stopPropagation(); handleAppUnselect(app.id); }} _hover={{ bg: 'red.50', color: 'red.500' }} /> )} ))} {provided.placeholder} )} ) : ( {t('common:no_selected_apps')} )} ); }; export default React.memo(AddQuickAppModal);