Coze源码分析-资源库-删除插件-前端源码-核心组件实现
概述
本文深入分析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() 显示删除成功提示
该流程包含多层安全验证和处理:
- 权限验证:通过ActionKey.Delete检查用户是否有删除权限
- 用户确认:使用Modal.confirm防止误删除操作
- API调用:使用DelPlugin API安全删除资源
- 状态同步:删除成功后自动刷新列表保持数据一致性
- 用户反馈:通过Toast提示用户操作结果
- 错误处理:API调用失败时提供相应的错误提示
整个流程确保了插件删除的安全性和用户体验的友好性。
核心组件实现
组件层次结构
插件删除功能涉及多个层次的组件:
- LibraryPage组件:资源库主页面,整合各种资源配置
- BaseLibraryPage组件:资源库核心逻辑,渲染资源列表
- Table组件:资源列表表格,包含操作列
- TableAction组件:表格行操作菜单,包含删除选项
- 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 (<><BaseLibraryPagespaceId={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 (<LayoutclassName={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) => (<TableActiondeleteProps={{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)}/>
)