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

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

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;
// 在 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)
}
/>
);
}
posted @ 2025-09-10 08:35  yjbjingcha  阅读(17)  评论(0)    收藏  举报