From a430284aa21e3ae1f0d5654e55b2ad2852519cc2 Mon Sep 17 00:00:00 2001
From: wwf <yearningwang@iqtogether.com>
Date: 星期三, 04 六月 2025 15:17:49 +0800
Subject: [PATCH] 初始化

---
 app/components/tools/provider-list.tsx |  194 +++++++++++++++++++-----------------------------
 1 files changed, 77 insertions(+), 117 deletions(-)

diff --git a/app/components/tools/provider-list.tsx b/app/components/tools/provider-list.tsx
index b1da6d5..73c7363 100644
--- a/app/components/tools/provider-list.tsx
+++ b/app/components/tools/provider-list.tsx
@@ -1,36 +1,33 @@
 'use client'
-import { useMemo, useRef, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
 import { useTranslation } from 'react-i18next'
+import { RiCloseLine } from '@remixicon/react'
 import type { Collection } from './types'
-import Marketplace from './marketplace'
 import cn from '@/utils/classnames'
 import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
 import TabSliderNew from '@/app/components/base/tab-slider-new'
 import LabelFilter from '@/app/components/tools/labels/filter'
 import Input from '@/app/components/base/input'
-import ProviderDetail from '@/app/components/tools/provider/detail'
-import Empty from '@/app/components/plugins/marketplace/empty'
+import { DotsGrid } from '@/app/components/base/icons/src/vender/line/general'
+import { Colors } from '@/app/components/base/icons/src/vender/line/others'
+import { Route } from '@/app/components/base/icons/src/vender/line/mapsAndTravel'
 import CustomCreateCard from '@/app/components/tools/provider/custom-create-card'
-import WorkflowToolEmpty from '@/app/components/tools/add-tool-modal/empty'
-import Card from '@/app/components/plugins/card'
-import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
-import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel'
-import { useSelector as useAppContextSelector } from '@/context/app-context'
-import { useAllToolProviders } from '@/service/use-tools'
-import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins'
+import ContributeCard from '@/app/components/tools/provider/contribute'
+import ProviderCard from '@/app/components/tools/provider/card'
+import ProviderDetail from '@/app/components/tools/provider/detail'
+import Empty from '@/app/components/tools/add-tool-modal/empty'
+import { fetchCollectionList } from '@/service/tools'
 
 const ProviderList = () => {
   const { t } = useTranslation()
-  const containerRef = useRef<HTMLDivElement>(null)
-  const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures)
 
   const [activeTab, setActiveTab] = useTabSearchParams({
     defaultTab: 'builtin',
   })
   const options = [
-    { value: 'builtin', text: t('tools.type.builtIn') },
-    { value: 'api', text: t('tools.type.custom') },
-    { value: 'workflow', text: t('tools.type.workflow') },
+    { value: 'builtin', text: t('tools.type.builtIn'), icon: <DotsGrid className='w-[14px] h-[14px] mr-1' /> },
+    { value: 'api', text: t('tools.type.custom'), icon: <Colors className='w-[14px] h-[14px] mr-1' /> },
+    { value: 'workflow', text: t('tools.type.workflow'), icon: <Route className='w-[14px] h-[14px] mr-1' /> },
   ]
   const [tagFilterValue, setTagFilterValue] = useState<string[]>([])
   const handleTagsChange = (value: string[]) => {
@@ -40,7 +37,8 @@
   const handleKeywordsChange = (value: string) => {
     setKeywords(value)
   }
-  const { data: collectionList = [], refetch } = useAllToolProviders()
+
+  const [collectionList, setCollectionList] = useState<Collection[]>([])
   const filteredCollectionList = useMemo(() => {
     return collectionList.filter((collection) => {
       if (collection.type !== activeTab)
@@ -52,113 +50,75 @@
       return true
     })
   }, [activeTab, tagFilterValue, keywords, collectionList])
+  const getProviderList = async () => {
+    const list = await fetchCollectionList()
+    setCollectionList([...list])
+  }
+  useEffect(() => {
+    getProviderList()
+  }, [])
 
-  const [currentProviderId, setCurrentProviderId] = useState<string | undefined>()
-  const currentProvider = useMemo<Collection | undefined>(() => {
-    return filteredCollectionList.find(collection => collection.id === currentProviderId)
-  }, [currentProviderId, filteredCollectionList])
-  const { data: pluginList } = useInstalledPluginList()
-  const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
-  const currentPluginDetail = useMemo(() => {
-    const detail = pluginList?.plugins.find(plugin => plugin.plugin_id === currentProvider?.plugin_id)
-    return detail
-  }, [currentProvider?.plugin_id, pluginList?.plugins])
+  const [currentProvider, setCurrentProvider] = useState<Collection | undefined>()
+  useEffect(() => {
+    if (currentProvider && collectionList.length > 0) {
+      const newCurrentProvider = collectionList.find(collection => collection.id === currentProvider.id)
+      setCurrentProvider(newCurrentProvider)
+    }
+  }, [collectionList, currentProvider])
 
   return (
-    <>
-      <div className='relative flex h-0 shrink-0 grow overflow-hidden'>
-        <div
-          ref={containerRef}
-          className='relative flex grow flex-col overflow-y-auto bg-background-body'
-        >
-          <div className={cn(
-            'sticky top-0 z-20 flex flex-wrap items-center justify-between gap-y-2 bg-background-body px-12 pb-2 pt-4 leading-[56px]',
-            currentProviderId && 'pr-6',
-          )}>
-            <TabSliderNew
-              value={activeTab}
-              onChange={(state) => {
-                setActiveTab(state)
-                if (state !== activeTab)
-                  setCurrentProviderId(undefined)
-              }}
-              options={options}
+    <div className='relative flex overflow-hidden bg-gray-100 shrink-0 h-0 grow'>
+      <div className='relative flex flex-col overflow-y-auto bg-gray-100 grow'>
+        <div className={cn(
+          'sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] bg-gray-100 z-20 flex-wrap gap-y-2',
+          currentProvider && 'pr-6',
+        )}>
+          <TabSliderNew
+            value={activeTab}
+            onChange={(state) => {
+              setActiveTab(state)
+              if (state !== activeTab)
+                setCurrentProvider(undefined)
+            }}
+            options={options}
+          />
+          <div className='flex items-center gap-2'>
+            <LabelFilter value={tagFilterValue} onChange={handleTagsChange} />
+            <Input
+              showLeftIcon
+              showClearIcon
+              wrapperClassName='w-[200px]'
+              value={keywords}
+              onChange={e => handleKeywordsChange(e.target.value)}
+              onClear={() => handleKeywordsChange('')}
             />
-            <div className='flex items-center gap-2'>
-              <LabelFilter value={tagFilterValue} onChange={handleTagsChange} />
-              <Input
-                showLeftIcon
-                showClearIcon
-                wrapperClassName='w-[200px]'
-                value={keywords}
-                onChange={e => handleKeywordsChange(e.target.value)}
-                onClear={() => handleKeywordsChange('')}
-              />
-            </div>
           </div>
-          {(filteredCollectionList.length > 0 || activeTab !== 'builtin') && (
-            <div className={cn(
-              'relative grid shrink-0 grid-cols-1 content-start gap-4 px-12 pb-4 pt-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4',
-              !filteredCollectionList.length && activeTab === 'workflow' && 'grow',
-            )}>
-              {activeTab === 'api' && <CustomCreateCard onRefreshData={refetch} />}
-              {filteredCollectionList.map(collection => (
-                <div
-                  key={collection.id}
-                  onClick={() => setCurrentProviderId(collection.id)}
-                >
-                  <Card
-                    className={cn(
-                      'cursor-pointer border-[1.5px] border-transparent',
-                      currentProviderId === collection.id && 'border-components-option-card-option-selected-border',
-                    )}
-                    hideCornerMark
-                    payload={{
-                      ...collection,
-                      brief: collection.description,
-                      org: collection.plugin_id ? collection.plugin_id.split('/')[0] : '',
-                      name: collection.plugin_id ? collection.plugin_id.split('/')[1] : collection.name,
-                    } as any}
-                    footer={
-                      <CardMoreInfo
-                        tags={collection.labels}
-                      />
-                    }
-                  />
-                </div>
-              ))}
-              {!filteredCollectionList.length && activeTab === 'workflow' && <div className='absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'><WorkflowToolEmpty /></div>}
-            </div>
-          )}
-          {!filteredCollectionList.length && activeTab === 'builtin' && (
-            <Empty lightCard text={t('tools.noTools')} className='h-[224px] px-12' />
-          )}
-          {
-            enable_marketplace && activeTab === 'builtin' && (
-              <Marketplace
-                onMarketplaceScroll={() => {
-                  containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' })
-                }}
-                searchPluginText={keywords}
-                filterPluginTags={tagFilterValue}
-              />
-            )
-          }
+        </div>
+        <div className={cn(
+          'relative grid content-start grid-cols-1 gap-4 px-12 pt-2 pb-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 grow shrink-0',
+          currentProvider && 'pr-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
+        )}>
+          {activeTab === 'builtin' && <ContributeCard />}
+          {activeTab === 'api' && <CustomCreateCard onRefreshData={getProviderList} />}
+          {filteredCollectionList.map(collection => (
+            <ProviderCard
+              active={currentProvider?.id === collection.id}
+              onSelect={() => setCurrentProvider(collection)}
+              key={collection.id}
+              collection={collection}
+            />
+          ))}
+          {!filteredCollectionList.length && <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'><Empty /></div>}
         </div>
       </div>
-      {currentProvider && !currentProvider.plugin_id && (
-        <ProviderDetail
-          collection={currentProvider}
-          onHide={() => setCurrentProviderId(undefined)}
-          onRefreshData={refetch}
-        />
-      )}
-      <PluginDetailPanel
-        detail={currentPluginDetail}
-        onUpdate={() => invalidateInstalledPluginList()}
-        onHide={() => setCurrentProviderId(undefined)}
-      />
-    </>
+      <div className={cn(
+        'shrink-0 w-0 border-l-[0.5px] border-black/8 overflow-y-auto transition-all duration-200 ease-in-out',
+        currentProvider && 'w-[420px]',
+      )}>
+        {currentProvider && <ProviderDetail collection={currentProvider} onRefreshData={getProviderList} />}
+      </div>
+      <div className='absolute top-5 right-5 p-1 cursor-pointer' onClick={() => setCurrentProvider(undefined)}><RiCloseLine className='w-4 h-4' /></div>
+    </div>
   )
 }
 ProviderList.displayName = 'ToolProviderList'

--
Gitblit v1.8.0