2026-01-02 18:33:52 +08:00

243 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import type { Router } from 'vue-router'
import axios from 'axios'
import { t } from '../i18n'
import { registerToolRoute, unregisterToolRoute, registerAllToolRoutes, ensureToolRoutes } from '../utils/dynamicRoutes'
import { get_session_api_headers } from '../api/auth'
export interface Tool {
id: string
name: string
description?: string
category?: string
icon?: string
color?: string
type?: 'route' | 'url'
routeName?: string
url?: string
order?: number
isDefault?: boolean
hidden?: boolean
// 市场工具相关
fromMarketplace?: boolean
marketplaceId?: string // 市场的唯一ID用于识别
toolName?: string // 实际的 tool_name用于删除文件系统
version?: string
author?: string
rating?: number
downloads?: number
// 路由相关(可选,用于动态路由注册)
componentPath?: string // 组件路径(相对于 src/views
routePath?: string // 路由路径(如 'tools/my-tool'
}
const STORAGE_KEY = 'tools.userItems'
const DELETED_DEFAULT_TOOLS_KEY = 'tools.deletedDefaultTools'
// 默认工具列表(硬编码,一行一个,方便添加)
function getDefaultTools(): Tool[] {
return [
{
id: 'remove-background',
name: t('Remove Background'),
description: t('Remove background from images using AI technology'),
category: 'Image Processing',
icon: 'photo-edit',
color: '#e5e7eb',
type: 'route',
routeName: 'RemoveBackground',
order: 1,
isDefault: true,
toolName: 'remove_background'
},
// 在这里添加更多默认工具,每行一个:
// {
// id: 'tool-id-2',
// name: t('Tool Name'),
// description: t('Tool description'),
// category: 'Category',
// icon: 'icon-name',
// color: '#e5e7eb',
// type: 'route',
// routeName: 'RouteName',
// order: 2,
// isDefault: true,
// toolName: 'tool_name'
// },
]
}
function loadUserTools(): Tool[] {
try {
const raw = localStorage.getItem(STORAGE_KEY)
if (!raw) return []
const parsed = JSON.parse(raw)
if (Array.isArray(parsed)) return parsed
return []
} catch {
return []
}
}
function saveUserTools(tools: Tool[]) {
const userTools = tools.filter(t => !t.isDefault)
localStorage.setItem(STORAGE_KEY, JSON.stringify(userTools))
}
function loadDeletedDefaultTools(): string[] {
try {
const raw = localStorage.getItem(DELETED_DEFAULT_TOOLS_KEY)
if (!raw) return []
return JSON.parse(raw)
} catch {
return []
}
}
function saveDeletedDefaultTools(deletedIds: string[]) {
localStorage.setItem(DELETED_DEFAULT_TOOLS_KEY, JSON.stringify(deletedIds))
}
export const useToolsStore = defineStore('tools', () => {
const userTools = ref<Tool[]>(loadUserTools())
const deletedDefaultToolIds = ref<string[]>(loadDeletedDefaultTools())
const allTools = computed(() => {
const defaultTools = getDefaultTools()
.filter(tool => !deletedDefaultToolIds.value.includes(tool.id))
.map(tool => ({ ...tool, isDefault: true }))
const userToolsList = [...userTools.value]
.map(tool => ({ ...tool, isDefault: false }))
return [
...defaultTools.sort((a, b) => (a.order ?? 0) - (b.order ?? 0)),
...userToolsList.sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
]
})
// 添加用户工具
function addUserTool(tool: Tool, router?: Router, componentPath?: string) {
const defaultToolsCount = getDefaultTools().filter(
t => !deletedDefaultToolIds.value.includes(t.id)
).length
// 确保工具具有 routeName 和 routePath如果缺失则自动生成
// 这样保存到 localStorage 的数据也会包含这些字段
const toolWithRoutes = ensureToolRoutes({ ...tool })
toolWithRoutes.order = defaultToolsCount + userTools.value.length + 1
toolWithRoutes.isDefault = false
userTools.value.push(toolWithRoutes)
saveUserTools(userTools.value)
// 注册路由(如果提供了 router
if (router) {
registerToolRoute(router, toolWithRoutes, componentPath)
}
}
function updateUserTool(toolId: string, updates: Partial<Tool>) {
const index = userTools.value.findIndex(t => t.id === toolId)
if (index >= 0) {
userTools.value[index] = { ...userTools.value[index], ...updates, isDefault: false }
saveUserTools(userTools.value)
}
}
// 删除工具(支持用户工具和默认工具)
async function deleteUserTool(toolId: string, router?: Router) {
// 查找用户工具
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
if (tool) {
if (tool.toolName) {
toolName = tool.toolName
} else if (tool.componentPath) {
const match = tool.componentPath.match(/tools\/([^\/]+)\//)
if (match && match[1]) {
toolName = match[1]
}
}
}
if (toolName) {
try {
await axios.post(`/jingrow/uninstall-tool/${toolName}`, {}, {
headers: {
...get_session_api_headers()
}
})
} catch (error: any) {
console.error('删除工具文件失败:', error.response?.data || error.message || '未知错误')
}
}
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 updateUserToolsOrder(newOrder: Tool[]) {
const defaultToolsCount = getDefaultTools().filter(
t => !deletedDefaultToolIds.value.includes(t.id)
).length
newOrder.forEach((tool, index) => {
tool.order = defaultToolsCount + index + 1
})
userTools.value = newOrder
saveUserTools(userTools.value)
}
function initToolRoutes(router: Router) {
const defaultTools = getDefaultTools()
.filter(tool => !deletedDefaultToolIds.value.includes(tool.id))
.map(tool => ({ ...tool, isDefault: true }))
const allToolsToRegister = [...defaultTools, ...userTools.value]
registerAllToolRoutes(router, allToolsToRegister)
}
return {
userTools,
allTools,
addUserTool,
updateUserTool,
deleteUserTool,
updateUserToolsOrder,
getDefaultTools,
initToolRoutes
}
})