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

发布于:2025-09-07 ⋅ 阅读:(17) ⋅ 点赞:(0)

概述

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

功能特性

核心功能

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

用户体验特性

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

技术架构

整体架构设计

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

核心模块结构

frontend/
├── apps/coze-studio/src/
│   └── pages/
│       └── library.tsx            # 资源库入口页面
├── packages/studio/workspace/
│   ├── entry-adapter/src/pages/library/
│   │   └── index.tsx              # LibraryPage适配器组件
│   └── entry-base/src/pages/library/
│       ├── index.tsx              # BaseLibraryPage核心组件
│       ├── components/
│       │   └── library-header.tsx # LibraryHeader头部组件
│       └── hooks/use-entity-configs/
           └── use-plugin-config.tsx  # 插件配置Hook
├── packages/common/prompt-kit/
│   ├── base/src/
│   │   ├── create-prompt/
│   │   │   ├── prompt-configurator-modal.tsx  # 提示词配置弹窗
│   │   │   ├── context/
│   │   │   │   └── index.tsx      # 提示词配置上下文
│   │   │   ├── types.ts           # 类型定义
│   │   │   ├── use-modal.tsx      # 弹窗Hook
│   │   │   └── components/
│   │   │       ├── prompt-info-input.tsx  # 名称描述输入组件
│   │   │       ├── header.tsx     # 弹窗头部组件
│   │   │       └── footer-actions/ # 底部操作按钮
│   │   │           ├── close-modal.tsx
│   │   │           ├── save-prompt.tsx
│   │   │           └── prompt-diff.tsx
│   │   └── editor/
│   │       ├── index.tsx          # 编辑器导出
│   │       ├── render.tsx         # PromptEditorRender组件
│   │       └── context/
│   │           └── index.tsx      # 编辑器上下文
│   └── adapter/src/
│       └── create-prompt/
│           ├── index.tsx          # 适配器导出
│           ├── prompt-configurator-modal.tsx  # 适配器弹窗
│           └── use-modal.tsx      # 适配器Hook
└── packages/arch/bot-api/src/
    └── playground/
        └── index.ts               # PlaygroundApi定义

用户删除插件流程概述

用户登录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

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

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

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

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 组件

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

import { Table } from '@coze-arch/coze-design';

const { TableAction } = Table;

// 在 usePromptConfig 中使用
renderActions: (libraryResource: ResourceInfo) => (
  <TableAction
    deleteProps={{
      disabled: !libraryResource.actions?.find(
        action => action.key === ActionKey.Delete,
      )?.enable,
      deleteDesc: I18n.t('prompt_resource_delete_describ'),
      handler: () => {
        delPrompt(libraryResource.res_id || '');
      },
    }}
    editProps={{
      disabled: !libraryResource.actions?.find(
        action => action.key === ActionKey.Edit,
      )?.enable,
      handler: () => {
        openCreatePrompt({
          mode: 'edit',
          editId: libraryResource.res_id || '',
        });
      },
    }}
    actionList={getCommonActions?.(libraryResource)}
  />
)

网站公告

今日签到

点亮在社区的每一天
去签到