Coze源码分析-资源库-删除插件-前端源码-核心组件实现

概述

本文深入分析Coze Studio中用户删除插件功能的前端实现。该功能允许用户在资源库中安全地删除不需要的插件资源,为开发者提供了完善的资源管理能力。通过对源码的详细解析,我们将了解从资源库表格操作到删除确认弹窗的完整架构设计、组件实现、状态管理和用户体验优化等核心技术要点。删除功能涉及权限验证、用户确认、API调用和状态更新等多个环节,确保数据安全和操作的可靠性。

功能特性

核心功能

  • 安全删除:支持插件资源的安全删除操作
  • 权限控制:基于用户权限动态显示删除按钮状态
  • 确认机制:提供删除确认弹窗防止误操作
  • 批量操作:支持通过TableAction组件进行批量管理
  • 状态同步:删除后自动刷新资源列表

用户体验特性

  • 即时反馈:删除操作结果实时展示和Toast提示
  • 权限提示:无权限时按钮禁用并提供视觉反馈
  • 操作便捷:通过表格行操作菜单快速访问删除功能
  • 国际化支持:删除相关文案支持多语言适配

技术架构

整体架构设计

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    插件删除管理模块                          │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │ LibraryPage │  │BaseLibrary  │  │    TableAction      │  │
│  │ (资源库页面) │  │    Page     │  │   (操作菜单)        │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │   Table     │  │UITableAction│  │   Modal.confirm     │  │
│  │ (资源列表)  │  │ (操作组件)  │  │   (删除确认弹窗)    │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
├─────────────────────────────────────────────────────────────┤
│                      状态管理层                             │
│  ┌─────────────────┐  ┌─────────────────────────────────┐  │
│  │usePluginConfig  │  │      useRequest Hook            │  │
│  │  (删除配置)      │  │     (删除API调用)               │  │
│  └─────────────────┘  └─────────────────────────────────┘  │
├─────────────────────────────────────────────────────────────┤
│                       API服务层                            │
│  ┌─────────────────────────────────────────────────────────┐
│  │            PluginDevelop API                            │
│  │               DelPlugin                                 │
│  └─────────────────────────────────────────────────────────┘
└────────────────────────────────────────────────────────────┘

核心模块结构

复制代码
frontend/
├── packages/studio/workspace/
│   ├── entry-adapter/src/pages/library/
│   │   └── index.tsx              # LibraryPage适配器组件
│   └── entry-base/src/pages/library/
│       ├── index.tsx              # BaseLibraryPage核心组件
│       └── hooks/use-entity-configs/
│           └── use-plugin-config.tsx  # 插件配置Hook
├── packages/arch/idl/src/auto-generated/plugin_develop/
│   ├── namespaces/
│   │   ├── plugin_develop.ts      # DelPluginRequest/Response接口定义
│   │   └── plugin_develop_common.ts # 通用类型定义
│   └── index.ts                   # PluginDevelopApi导出
└── packages/arch/coze-design/
    └── Table/
        └── TableAction            # 表格操作组件

用户删除插件流程概述

复制代码
用户登录Coze Studio
        ↓
  点击"资源库"菜单
        ↓
  LibraryPage 组件加载
        ↓
  BaseLibraryPage 渲染资源列表
        ↓
  用户找到要删除的插件行
        ↓
  点击表格行最右边的"..."操作按钮
        ↓
  TableAction 下拉菜单显示
        ↓
  点击"删除"菜单项
        ↓
  权限验证(检查ActionKey.Delete权限)
        ↓
  Modal.confirm 删除确认弹窗显示
        ↓
  用户确认删除操作
        ↓
  delPlugin() 函数触发
        ↓
  PluginDevelopApi.DelPlugin() 调用
        ↓
  后端执行删除操作
        ↓
  删除成功回调处理
        ↓
  reloadList() 刷新资源列表
        ↓
  Toast.success() 显示删除成功提示

该流程包含多层安全验证和处理:

  1. 权限验证:通过ActionKey.Delete检查用户是否有删除权限
  2. 用户确认:使用Modal.confirm防止误删除操作
  3. API调用:使用DelPlugin API安全删除资源
  4. 状态同步:删除成功后自动刷新列表保持数据一致性
  5. 用户反馈:通过Toast提示用户操作结果
  6. 错误处理:API调用失败时提供相应的错误提示
    整个流程确保了插件删除的安全性和用户体验的友好性。

核心组件实现

组件层次结构

插件删除功能涉及多个层次的组件:

  1. LibraryPage组件:资源库主页面,整合各种资源配置
  2. BaseLibraryPage组件:资源库核心逻辑,渲染资源列表
  3. Table组件:资源列表表格,包含操作列
  4. TableAction组件:表格行操作菜单,包含删除选项
  5. usePluginConfig Hook:插件配置逻辑,包含删除功能

1. 资源库入口组件(LibraryPage)

文件位置:frontend/packages/studio/workspace/entry-adapter/src/pages/library/index.tsx

作为资源库的适配器组件,整合各种资源配置,包括插件的删除功能:

typescript 复制代码
import { type FC, useRef } from 'react';

import {
  BaseLibraryPage,
  useDatabaseConfig,
  usePluginConfig,
  useWorkflowConfig,
  usePromptConfig,
  useKnowledgeConfig,
} from '@coze-studio/workspace-base/library';

export const LibraryPage: FC<{ spaceId: string }> = ({ spaceId }) => {
  const basePageRef = useRef<{ reloadList: () => void }>(null);
  const configCommonParams = {
    spaceId,
    reloadList: () => {
      basePageRef.current?.reloadList();
    },
  };
  // 各种资源配置,包括插件删除配置
  const { config: pluginConfig, modals: pluginModals } =
    usePluginConfig(configCommonParams);
  // 其他资源配置...

  return (
    <>
      <BaseLibraryPage
        spaceId={spaceId}
        ref={basePageRef}
        entityConfigs={[
          pluginConfig, // 包含删除配置
          // 其他配置...
        ]}
      />
      {pluginModals}
      {/* 其他模态框... */}
    </>
  );
};

设计亮点

  • 配置统一管理 :通过 usePluginConfig 统一管理插件的删除配置
  • 组件解耦:删除功能通过配置传递,组件职责明确
  • 状态同步 :删除操作后通过 reloadList 自动刷新列表

2. 资源库核心组件(BaseLibraryPage)

文件位置:frontend/packages/studio/workspace/entry-base/src/pages/library/index.tsx

负责资源库的核心展示逻辑,包含资源列表表格和删除操作:

typescript 复制代码
import { forwardRef, useImperativeHandle } from 'react';

import classNames from 'classnames';
import { useInfiniteScroll } from 'ahooks';
import { I18n } from '@coze-arch/i18n';
import {
  Table,
  Select,
  Search,
  Layout,
  Cascader,
  Space,
} from '@coze-arch/coze-design';
import { renderHtmlTitle } from '@coze-arch/bot-utils';
import { EVENT_NAMES, sendTeaEvent } from '@coze-arch/bot-tea';
import {
  type ResType,
  type LibraryResourceListRequest,
  type ResourceInfo,
} from '@coze-arch/bot-api/plugin_develop';
import { PluginDevelopApi } from '@coze-arch/bot-api';

import { type ListData, type BaseLibraryPageProps } from './types';
import { LibraryHeader } from './components/library-header';

export const BaseLibraryPage = forwardRef<
  { reloadList: () => void },
  BaseLibraryPageProps
>(
  ({ spaceId, isPersonalSpace = true, entityConfigs }, ref) => {
    const { params, setParams, resetParams, hasFilter, ready } =
      useCachedQueryParams({
        spaceId,
      });

    const listResp = useInfiniteScroll<ListData>(
      async prev => {
        if (!ready) {
          return {
            list: [],
            nextCursorId: undefined,
            hasMore: false,
          };
        }
        const resp = await PluginDevelopApi.LibraryResourceList(
          entityConfigs.reduce<LibraryResourceListRequest>(
            (res, config) => config.parseParams?.(res) ?? res,
            {
              ...params,
              cursor: prev?.nextCursorId,
              space_id: spaceId,
              size: LIBRARY_PAGE_SIZE,
            },
          ),
        );
        return {
          list: resp?.resource_list || [],
          nextCursorId: resp?.cursor,
          hasMore: !!resp?.has_more,
        };
      },
      {
        reloadDeps: [params, spaceId],
      },
    );

    useImperativeHandle(ref, () => ({
      reloadList: listResp.reload,
    }));

    return (
      <Layout
        className={s['layout-content']}
        title={renderHtmlTitle(I18n.t('navigation_workspace_library'))}
      >
        <Layout.Header className={classNames(s['layout-header'], 'pb-0')}>
          <div className="w-full">
            <LibraryHeader entityConfigs={entityConfigs} />
            {/* 过滤器组件 */}
          </div>
        </Layout.Header>
        <Layout.Content>
          {/* 表格和列表内容 */}
        </Layout.Content>
      </Layout>
    );
  }
);

3. 表格操作组件(TableAction)

文件位置:@coze-arch/coze-design 包中的 Table.TableAction 组件

提供表格行的操作菜单,包含删除功能:

typescript 复制代码
import { Table } from '@coze-arch/coze-design';

const { TableAction } = Table;

// 在 usePluginConfig 中使用
renderActions: (item: ResourceInfo) => {
  const deleteDisabled = !item.actions?.find(
    action => action.key === ActionKey.Delete,
  )?.enable;

  const deleteProps = {
    disabled: deleteDisabled,
    deleteDesc: I18n.t('library_delete_desc'),
    handler: async () => {
      await PluginDevelopApi.DelPlugin({ plugin_id: item.res_id });
      reloadList();
      Toast.success(I18n.t('Delete_success'));
    },
  };

  return (
    <TableAction
      deleteProps={deleteProps}
      actionList={getCommonActions?.(item)}
    />
  );
}
相关推荐
草梅友仁5 小时前
草梅 Auth 1.6.0 发布密码强度组件 Twilio 短信支持 | 2025 年第 36 周草梅周报
前端·开源·github
正义的大古5 小时前
OpenLayers常用控件 -- 章节七:测量工具控件教程
前端·javascript·vue.js·openlayers
Hashan6 小时前
深入理解:Webpack编译原理
前端·webpack
雲墨款哥6 小时前
一个前端开发者的救赎之路-JS基础回顾(五)-数组
前端·javascript·面试
朱程6 小时前
深入JS(一):手写 Promise
前端·javascript
Hierifer6 小时前
跨端技术:浅聊双线程原理和实现
前端
FreeBuf_6 小时前
加密货币武器化:恶意npm包利用以太坊智能合约实现隐蔽通信
前端·npm·智能合约
java水泥工7 小时前
基于Echarts+HTML5可视化数据大屏展示-图书馆大屏看板
前端·echarts·html5
EndingCoder7 小时前
Electron 性能优化:内存管理和渲染效率
javascript·性能优化·electron·前端框架