From da323817f702392a8fe892a3880bd4440b601b84 Mon Sep 17 00:00:00 2001 From: Junyan Qin Date: Thu, 20 Nov 2025 18:50:00 +0800 Subject: [PATCH] feat: add plugin components displaying in marketplace page --- .../pipeline-extensions/PipelineExtension.tsx | 28 ++++++- .../plugin-installed/PluginComponentList.tsx | 48 ++++++------ .../plugin-card/PluginCardComponent.tsx | 13 +++- .../plugin-form/PluginForm.tsx | 13 +++- .../plugin-market/PluginMarketComponent.tsx | 1 + .../PluginDetailDialog.tsx | 10 +++ .../PluginMarketCardComponent.tsx | 75 ++++++++++++++----- .../plugin-market-card/PluginMarketCardVO.ts | 3 + web/src/app/infra/entities/plugin/index.ts | 1 + 9 files changed, 149 insertions(+), 43 deletions(-) diff --git a/web/src/app/home/pipelines/components/pipeline-extensions/PipelineExtension.tsx b/web/src/app/home/pipelines/components/pipeline-extensions/PipelineExtension.tsx index 5408b9c7..947662ed 100644 --- a/web/src/app/home/pipelines/components/pipeline-extensions/PipelineExtension.tsx +++ b/web/src/app/home/pipelines/components/pipeline-extensions/PipelineExtension.tsx @@ -234,7 +234,19 @@ export default function PipelineExtension({
{ + const componentKindCount: Record = + {}; + for (const component of plugin.components) { + const kind = component.manifest.manifest.kind; + if (componentKindCount[kind]) { + componentKindCount[kind]++; + } else { + componentKindCount[kind] = 1; + } + } + return componentKindCount; + })()} showComponentName={true} showTitle={false} useBadge={true} @@ -401,7 +413,19 @@ export default function PipelineExtension({
{ + const componentKindCount: Record = + {}; + for (const component of plugin.components) { + const kind = component.manifest.manifest.kind; + if (componentKindCount[kind]) { + componentKindCount[kind]++; + } else { + componentKindCount[kind] = 1; + } + } + return componentKindCount; + })()} showComponentName={true} showTitle={false} useBadge={true} diff --git a/web/src/app/home/plugins/components/plugin-installed/PluginComponentList.tsx b/web/src/app/home/plugins/components/plugin-installed/PluginComponentList.tsx index 603599f8..ec2194b5 100644 --- a/web/src/app/home/plugins/components/plugin-installed/PluginComponentList.tsx +++ b/web/src/app/home/plugins/components/plugin-installed/PluginComponentList.tsx @@ -1,4 +1,3 @@ -import { PluginComponent } from '@/app/infra/entities/plugin'; import { TFunction } from 'i18next'; import { Wrench, AudioWaveform, Hash } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; @@ -9,31 +8,22 @@ export default function PluginComponentList({ showTitle, useBadge, t, + responsive = false, }: { - components: PluginComponent[]; + components: Record; showComponentName: boolean; showTitle: boolean; useBadge: boolean; t: TFunction; + responsive?: boolean; }) { - const componentKindCount: Record = {}; - - for (const component of components) { - const kind = component.manifest.manifest.kind; - if (componentKindCount[kind]) { - componentKindCount[kind]++; - } else { - componentKindCount[kind] = 1; - } - } - const kindIconMap: Record = { Tool: , EventListener: , Command: , }; - const componentKindList = Object.keys(componentKindCount); + const componentKindList = Object.keys(components || {}); return ( <> @@ -44,11 +34,21 @@ export default function PluginComponentList({ return ( <> {useBadge && ( - + {kindIconMap[kind]} - {showComponentName && - t('plugins.componentName.' + kind) + ' '} - {componentKindCount[kind]} + {/* 响应式显示组件名称:在中等屏幕以上显示 */} + {responsive ? ( + + {t('plugins.componentName.' + kind)} + + ) : ( + showComponentName && t('plugins.componentName.' + kind) + )} + {components[kind]} )} @@ -58,9 +58,15 @@ export default function PluginComponentList({ className="flex flex-row items-center justify-start gap-[0.2rem]" > {kindIconMap[kind]} - {showComponentName && - t('plugins.componentName.' + kind) + ' '} - {componentKindCount[kind]} + {/* 响应式显示组件名称:在中等屏幕以上显示 */} + {responsive ? ( + + {t('plugins.componentName.' + kind)} + + ) : ( + showComponentName && t('plugins.componentName.' + kind) + )} + {components[kind]}
)} diff --git a/web/src/app/home/plugins/components/plugin-installed/plugin-card/PluginCardComponent.tsx b/web/src/app/home/plugins/components/plugin-installed/plugin-card/PluginCardComponent.tsx index 327f2bc7..b13a1108 100644 --- a/web/src/app/home/plugins/components/plugin-installed/plugin-card/PluginCardComponent.tsx +++ b/web/src/app/home/plugins/components/plugin-installed/plugin-card/PluginCardComponent.tsx @@ -128,7 +128,18 @@ export default function PluginCardComponent({
{ + const componentKindCount: Record = {}; + for (const component of cardVO.components) { + const kind = component.manifest.manifest.kind; + if (componentKindCount[kind]) { + componentKindCount[kind]++; + } else { + componentKindCount[kind] = 1; + } + } + return componentKindCount; + })()} showComponentName={false} showTitle={true} useBadge={false} diff --git a/web/src/app/home/plugins/components/plugin-installed/plugin-form/PluginForm.tsx b/web/src/app/home/plugins/components/plugin-installed/plugin-form/PluginForm.tsx index 767c2d41..2fe0c5f4 100644 --- a/web/src/app/home/plugins/components/plugin-installed/plugin-form/PluginForm.tsx +++ b/web/src/app/home/plugins/components/plugin-installed/plugin-form/PluginForm.tsx @@ -160,7 +160,18 @@ export default function PluginForm({
{ + const componentKindCount: Record = {}; + for (const component of pluginInfo.components) { + const kind = component.manifest.manifest.kind; + if (componentKindCount[kind]) { + componentKindCount[kind]++; + } else { + componentKindCount[kind] = 1; + } + } + return componentKindCount; + })()} showComponentName={true} showTitle={false} useBadge={true} diff --git a/web/src/app/home/plugins/components/plugin-market/PluginMarketComponent.tsx b/web/src/app/home/plugins/components/plugin-market/PluginMarketComponent.tsx index 73ebf3bd..8012cb6d 100644 --- a/web/src/app/home/plugins/components/plugin-market/PluginMarketComponent.tsx +++ b/web/src/app/home/plugins/components/plugin-market/PluginMarketComponent.tsx @@ -111,6 +111,7 @@ function MarketPageContent({ ), githubURL: plugin.repository, version: plugin.latest_version, + components: plugin.components, }); }, []); diff --git a/web/src/app/home/plugins/components/plugin-market/plugin-detail-dialog/PluginDetailDialog.tsx b/web/src/app/home/plugins/components/plugin-market/plugin-detail-dialog/PluginDetailDialog.tsx index 87d20d96..5fda170a 100644 --- a/web/src/app/home/plugins/components/plugin-market/plugin-detail-dialog/PluginDetailDialog.tsx +++ b/web/src/app/home/plugins/components/plugin-market/plugin-detail-dialog/PluginDetailDialog.tsx @@ -12,6 +12,7 @@ import { toast } from 'sonner'; import { PluginV4 } from '@/app/infra/entities/plugin'; import { getCloudServiceClientSync } from '@/app/infra/http'; import { extractI18nObject } from '@/i18n/I18nProvider'; +import PluginComponentList from '@/app/home/plugins/components/plugin-installed/PluginComponentList'; interface PluginDetailDialogProps { open: boolean; @@ -104,6 +105,15 @@ export default function PluginDetailDialog({ {plugin!.install_count.toLocaleString()} {t('market.downloads')} + {plugin!.components && Object.keys(plugin!.components).length > 0 && ( + + )} {plugin!.repository && (