diff --git a/apps/jingrow/frontend/src/shared/stores/tools.ts b/apps/jingrow/frontend/src/shared/stores/tools.ts index 026d58c..487a09a 100644 --- a/apps/jingrow/frontend/src/shared/stores/tools.ts +++ b/apps/jingrow/frontend/src/shared/stores/tools.ts @@ -33,7 +33,7 @@ export interface Tool { } const STORAGE_KEY = 'tools.userItems' -const HIDDEN_DEFAULT_TOOLS_KEY = 'tools.hiddenDefaultTools' +const DELETED_DEFAULT_TOOLS_KEY = 'tools.deletedDefaultTools' // 默认工具列表(硬编码,一行一个,方便添加) function getDefaultTools(): Tool[] { @@ -48,7 +48,8 @@ function getDefaultTools(): Tool[] { type: 'route', routeName: 'RemoveBackground', order: 1, - isDefault: true + isDefault: true, + toolName: 'remove_background' }, // 在这里添加更多默认工具,每行一个: // { @@ -61,7 +62,8 @@ function getDefaultTools(): Tool[] { // type: 'route', // routeName: 'RouteName', // order: 2, - // isDefault: true + // isDefault: true, + // toolName: 'tool_name' // }, ] } @@ -83,9 +85,9 @@ function saveUserTools(tools: Tool[]) { localStorage.setItem(STORAGE_KEY, JSON.stringify(userTools)) } -function loadHiddenDefaultTools(): string[] { +function loadDeletedDefaultTools(): string[] { try { - const raw = localStorage.getItem(HIDDEN_DEFAULT_TOOLS_KEY) + const raw = localStorage.getItem(DELETED_DEFAULT_TOOLS_KEY) if (!raw) return [] return JSON.parse(raw) } catch { @@ -93,17 +95,17 @@ function loadHiddenDefaultTools(): string[] { } } -function saveHiddenDefaultTools(hiddenIds: string[]) { - localStorage.setItem(HIDDEN_DEFAULT_TOOLS_KEY, JSON.stringify(hiddenIds)) +function saveDeletedDefaultTools(deletedIds: string[]) { + localStorage.setItem(DELETED_DEFAULT_TOOLS_KEY, JSON.stringify(deletedIds)) } export const useToolsStore = defineStore('tools', () => { const userTools = ref(loadUserTools()) - const hiddenDefaultToolIds = ref(loadHiddenDefaultTools()) + const deletedDefaultToolIds = ref(loadDeletedDefaultTools()) const allTools = computed(() => { const defaultTools = getDefaultTools() - .filter(tool => !hiddenDefaultToolIds.value.includes(tool.id)) + .filter(tool => !deletedDefaultToolIds.value.includes(tool.id)) .map(tool => ({ ...tool, isDefault: true })) const userToolsList = [...userTools.value] @@ -115,17 +117,10 @@ export const useToolsStore = defineStore('tools', () => { ] }) - const hiddenTools = computed(() => { - return getDefaultTools() - .filter(tool => hiddenDefaultToolIds.value.includes(tool.id)) - .map(tool => ({ ...tool, isDefault: true })) - .sort((a, b) => (a.order ?? 0) - (b.order ?? 0)) - }) - // 添加用户工具 function addUserTool(tool: Tool, router?: Router, componentPath?: string) { const defaultToolsCount = getDefaultTools().filter( - t => !hiddenDefaultToolIds.value.includes(t.id) + t => !deletedDefaultToolIds.value.includes(t.id) ).length // 确保工具具有 routeName 和 routePath(如果缺失则自动生成) @@ -151,9 +146,17 @@ export const useToolsStore = defineStore('tools', () => { } } - // 删除用户工具 + // 删除工具(支持用户工具和默认工具) async function deleteUserTool(toolId: string, router?: Router) { - const tool = userTools.value.find(t => t.id === toolId) + // 查找用户工具 + let tool = userTools.value.find(t => t.id === toolId) + let isDefaultTool = false + + // 如果不是用户工具,查找默认工具 + if (!tool) { + tool = getDefaultTools().find(t => t.id === toolId) + isDefaultTool = true + } let toolName: string | null = null @@ -180,35 +183,32 @@ export const useToolsStore = defineStore('tools', () => { } } - userTools.value = userTools.value.filter(t => t.id !== toolId) - const defaultToolsCount = getDefaultTools().filter( - t => !hiddenDefaultToolIds.value.includes(t.id) - ).length - userTools.value.forEach((t, index) => { - t.order = defaultToolsCount + index + 1 - }) - saveUserTools(userTools.value) + if (isDefaultTool) { + // 删除默认工具:添加到已删除列表 + if (!deletedDefaultToolIds.value.includes(toolId)) { + deletedDefaultToolIds.value.push(toolId) + saveDeletedDefaultTools(deletedDefaultToolIds.value) + } + } else { + // 删除用户工具:从列表中移除 + userTools.value = userTools.value.filter(t => t.id !== toolId) + const defaultToolsCount = getDefaultTools().filter( + t => !deletedDefaultToolIds.value.includes(t.id) + ).length + userTools.value.forEach((t, index) => { + t.order = defaultToolsCount + index + 1 + }) + saveUserTools(userTools.value) + } if (tool && tool.routeName && router) { unregisterToolRoute(router, tool.routeName) } } - function hideDefaultTool(toolId: string) { - if (!hiddenDefaultToolIds.value.includes(toolId)) { - hiddenDefaultToolIds.value.push(toolId) - saveHiddenDefaultTools(hiddenDefaultToolIds.value) - } - } - - function showDefaultTool(toolId: string) { - hiddenDefaultToolIds.value = hiddenDefaultToolIds.value.filter(id => id !== toolId) - saveHiddenDefaultTools(hiddenDefaultToolIds.value) - } - function updateUserToolsOrder(newOrder: Tool[]) { const defaultToolsCount = getDefaultTools().filter( - t => !hiddenDefaultToolIds.value.includes(t.id) + t => !deletedDefaultToolIds.value.includes(t.id) ).length newOrder.forEach((tool, index) => { @@ -225,14 +225,10 @@ export const useToolsStore = defineStore('tools', () => { return { userTools, - hiddenDefaultToolIds, allTools, - hiddenTools, addUserTool, updateUserTool, deleteUserTool, - hideDefaultTool, - showDefaultTool, updateUserToolsOrder, getDefaultTools, initToolRoutes diff --git a/apps/jingrow/frontend/src/views/Tools.vue b/apps/jingrow/frontend/src/views/Tools.vue index 02ed030..e2734ef 100644 --- a/apps/jingrow/frontend/src/views/Tools.vue +++ b/apps/jingrow/frontend/src/views/Tools.vue @@ -71,37 +71,6 @@ {{ t('Loading tools...') }} - - -
-
-

{{ t('Hidden Tools') }}

-

{{ t('Click to show hidden tools') }}

-
-
-
-
- -
-
{{ tool.name }}
- -
-
-
@@ -227,9 +196,6 @@ const routeNameOptions = computed(() => { // 使用 store 中的工具列表 const displayTools = computed(() => toolsStore.allTools) -// 隐藏的工具列表 -const hiddenTools = computed(() => toolsStore.hiddenTools) - onMounted(() => { loading.value = false @@ -285,9 +251,7 @@ function handleDrop(event: DragEvent, dropIndexValue: number) { } // 计算在用户工具中的新位置 - const defaultToolsCount = toolsStore.getDefaultTools().filter( - t => !toolsStore.hiddenDefaultToolIds.includes(t.id) - ).length + const defaultToolsCount = toolsStore.getDefaultTools().length const newIndexInUser = Math.max(0, dropIndexValue - defaultToolsCount) const draggedToolItem = newUserTools.splice(draggedIndexInUser, 1)[0] @@ -387,22 +351,7 @@ function handleSaveTool() { } function handleDeleteTool(tool: Tool) { - // 默认工具不能删除,只能隐藏 - if (tool.isDefault) { - dialog.warning({ - title: t('Hide Default Tool'), - content: `${t('Are you sure you want to hide default tool')} "${tool.name}"? ${t('You can show it again later')}.`, - positiveText: t('Hide'), - negativeText: t('Cancel'), - onPositiveClick: () => { - toolsStore.hideDefaultTool(tool.id) - message.success(t('Tool hidden successfully')) - } - }) - return - } - - // 删除用户工具 + // 删除工具(支持用户工具和默认工具) dialog.warning({ title: t('Confirm Delete'), content: `${t('Are you sure you want to delete tool')} "${tool.name}"?`, @@ -410,7 +359,7 @@ function handleDeleteTool(tool: Tool) { negativeText: t('Cancel'), onPositiveClick: async () => { try { - // 删除工具并移除路由(如果是市场工具,会同时删除文件) + // 删除工具并移除路由(如果是市场工具或默认工具,会同时删除文件) await toolsStore.deleteUserTool(tool.id, router) message.success(t('Tool deleted successfully')) } catch (error) { @@ -421,12 +370,6 @@ function handleDeleteTool(tool: Tool) { }) } -// 显示隐藏的默认工具 -function handleShowDefaultTool(toolId: string) { - toolsStore.showDefaultTool(toolId) - message.success(t('Tool shown successfully')) -} - function handleOpenMarketplace() { router.push({ name: 'ToolMarketplace' }) } @@ -448,23 +391,13 @@ function handleOpenTool(tool: Tool) { function getToolMenuOptions(tool: Tool): DropdownOption[] { const options: DropdownOption[] = [] - // 默认工具:显示"隐藏"选项 if (tool.isDefault) { - if (toolsStore.hiddenDefaultToolIds.includes(tool.id)) { - // 已隐藏,显示"显示"选项 - options.push({ - label: t('Show'), - key: 'show', - icon: () => h('i', { class: 'fa fa-eye' }) - }) - } else { - // 未隐藏,显示"隐藏"选项 - options.push({ - label: t('Hide'), - key: 'hide', - icon: () => h('i', { class: 'fa fa-eye-slash' }) - }) - } + // 默认工具:只显示"删除"选项 + options.push({ + label: t('Delete'), + key: 'delete', + icon: () => h('i', { class: 'fa fa-trash' }) + }) } else { // 用户工具:显示"编辑"和"删除"选项 options.push( @@ -490,13 +423,6 @@ function handleMenuSelect(key: string, tool: Tool) { handleEditTool(tool) } else if (key === 'delete') { handleDeleteTool(tool) - } else if (key === 'hide') { - // 隐藏默认工具 - toolsStore.hideDefaultTool(tool.id) - message.success(t('Tool hidden successfully')) - } else if (key === 'show') { - // 显示隐藏的默认工具 - handleShowDefaultTool(tool.id) } } @@ -816,106 +742,6 @@ function handleMenuSelect(key: string, tool: Tool) { margin-right: 12px; } -/* 隐藏的工具区域 */ -.hidden-tools-section { - margin-top: 32px; - padding-top: 32px; - border-top: 1px solid #e5e7eb; -} - -.hidden-tools-header { - margin-bottom: 16px; -} - -.hidden-tools-header h3 { - font-size: 18px; - font-weight: 600; - color: #64748b; - margin: 0 0 4px 0; -} - -.hidden-tools-hint { - font-size: 14px; - color: #94a3b8; - margin: 0; -} - -.hidden-tools-list { - display: flex; - flex-wrap: wrap; - gap: 12px; -} - -.hidden-tool-item { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 16px; - background: #f8fafc; - border: 1px solid #e5e7eb; - border-radius: 8px; - cursor: pointer; - transition: all 0.2s; - opacity: 0.7; -} - -.hidden-tool-item:hover { - background: #f1f5f9; - border-color: #cbd5e1; - opacity: 1; - transform: translateY(-1px); -} - -.hidden-tool-icon { - width: 40px; - height: 40px; - border-radius: 10px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.hidden-tool-icon.default-tool-icon { - background-color: transparent; - border: 1.5px solid; - box-shadow: none; -} - -.hidden-tool-name { - font-size: 14px; - font-weight: 500; - color: #64748b; - flex: 1; -} - -.show-tool-btn { - height: 32px; - padding: 0 12px; - border: 1px solid #1fc76f; - border-radius: 6px; - background: white; - color: #1fc76f; - cursor: pointer; - display: inline-flex; - align-items: center; - gap: 6px; - font-size: 13px; - font-weight: 500; - transition: all 0.2s; - flex-shrink: 0; -} - -.show-tool-btn:hover { - background: #f0fdf4; - border-color: #1dd87f; - color: #1dd87f; -} - -.show-tool-btn i { - font-size: 12px; -} - /* 响应式设计 */ @media (max-width: 1920px) { .tools-grid { diff --git a/apps/jingrow/jingrow/api/tools.py b/apps/jingrow/jingrow/api/tools.py index d88ad90..c982e84 100644 --- a/apps/jingrow/jingrow/api/tools.py +++ b/apps/jingrow/jingrow/api/tools.py @@ -219,9 +219,28 @@ def _install_tool_from_file(file_path: str, tool_data: Dict[str, Any]) -> Dict[s temp_dir = extract_result['temp_dir'] try: + # 从数据库获取的元数据中提取 tool_name + tool_name = tool_data.get('tool_name') or tool_data.get('name') + if not tool_name: + return {'success': False, 'error': '工具元数据中缺少 tool_name'} + + # 查找解压后的工具目录(zip包结构:tool_name/backend/... 和 tool_name/frontend/...) + temp_dir_path = Path(temp_dir) + tool_dir = temp_dir_path / tool_name + + # 如果temp_dir下直接有tool_name目录,使用它;否则使用temp_dir本身 + if tool_dir.exists() and tool_dir.is_dir(): + tool_dir_path = tool_dir + else: + # 兼容:如果temp_dir下只有一个目录,使用它 + subdirs = [d for d in temp_dir_path.iterdir() if d.is_dir() and not d.name.startswith('.')] + if len(subdirs) == 1: + tool_dir_path = subdirs[0] + else: + tool_dir_path = temp_dir_path + # 安装工具(传递工具元数据) - tool_dir = Path(temp_dir) - result = _install_single_tool_directory(str(tool_dir), tool_data) + result = _install_single_tool_directory(str(tool_dir_path), tool_data) if result.get('success'): return {