Coze源码分析-资源库-删除插件-前端源码-核心逻辑

删除插件逻辑

1. 删除操作入口组件

删除插件操作主要通过 usePluginConfig hook 中的 renderActions 方法实现,该方法返回 TableAction 组件来处理表格行的操作。

文件位置frontend/packages/studio/workspace/entry-base/src/pages/library/hooks/use-entity-configs/use-plugin-config.tsx

核心实现逻辑:

// 在 usePluginConfig hook 中
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 (<TableActiondeleteProps={deleteProps}actionList={getCommonActions?.(item)}/>);
}

设计亮点

  • 权限控制:基于后端返回的 actions 数组动态控制按钮状态
  • 国际化支持:使用 I18n.t() 进行多语言支持
  • 操作集成:同时支持删除、编辑等多种操作

2. 删除插件的核心Hook实现

文件位置frontend/packages/studio/workspace/entry-base/src/pages/library/hooks/use-entity-configs/use-plugin-config.tsx

核心代码:

import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import {ActionKey,PluginType,ResType,type ResourceInfo,
} from '@coze-arch/idl/plugin_develop';
import { I18n } from '@coze-arch/i18n';
import { PluginDevelopApi } from '@coze-arch/bot-api';
import { useBotCodeEditOutPlugin } from '@coze-agent-ide/bot-plugin/hook';
import { CreateFormPluginModal } from '@coze-agent-ide/bot-plugin/component';
import { IconCozPlugin } from '@coze-arch/coze-design/icons';
import { Menu, Tag, Toast, Table } from '@coze-arch/coze-design';const { TableAction } = Table;export const usePluginConfig: UseEntityConfigHook = ({spaceId,reloadList,getCommonActions,
}) => {const [showFormPluginModel, setShowFormPluginModel] = useState(false);const navigate = useNavigate();const { modal: editPluginCodeModal, open } = useBotCodeEditOutPlugin({modalProps: {onSuccess: reloadList,},});return {config: {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 (<TableActiondeleteProps={deleteProps}actionList={getCommonActions?.(item)}/>);},},};
};

设计亮点

  • 异步状态管理:使用 useRequest 管理删除请求状态
  • 错误处理:完善的成功/失败回调处理
  • 用户反馈:及时的Toast提示信息
  • 列表刷新:删除成功后自动刷新资源列表

3. 删除确认弹窗逻辑

文件位置frontend/packages/components/bot-semi/src/components/ui-table-action/index.tsx

核心代码:

// 删除确认弹窗的实现
<Popconfirmtrigger="click"okType="danger"title={i18n.t('delete_title')}content={i18n.t('plugin_delete_confirm_desc')}okText={i18n.t('confirm')}cancelText={i18n.t('cancel')}style={{ width: 350 }}icon={deleteProps?.popconfirm?.icon ?? <IconWaringRed />}{...deleteProps.popconfirm}onConfirm={deleteProps?.handler}disabled={deleteProps.disabled}
><span><Tooltipspacing={12}content={i18n.t('Delete')}position="top"{...deleteProps.tooltip}><UIIconButtondisabled={deleteProps.disabled}icon={<IconDeleteOutline className={styles.icon} />}style={iconColor('delete')}onClick={deleteProps.handleClick}data-testid="ui.table-action.delete"/></Tooltip></span>
</Popconfirm>

设计亮点

  • 权限控制:基于后端返回的actions数组动态控制删除按钮状态
  • 确认机制:使用Popconfirm组件提供删除确认弹窗
  • 错误处理:完善的错误提示和异常处理
  • 用户反馈:及时的成功/失败提示

4. TableAction 组件实现

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

核心代码:

import { Table } from '@coze-arch/coze-design';const { TableAction } = Table;// TableAction 组件的使用方式
<TableActiondeleteProps={{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'));},}}actionList={getCommonActions?.(item)}
/>

设计亮点

  • 组件复用:来自 @coze-arch/coze-design 的统一表格操作组件
  • 配置化:通过 deleteProps 和 actionList 配置操作
  • 权限控制:基于后端返回的 actions 数组控制操作权限
  • 确认机制:内置删除确认弹窗机制

5. 插件配置Hook(usePluginConfig)完整实现

文件位置frontend/packages/studio/workspace/entry-base/src/pages/library/hooks/use-entity-configs/use-plugin-config.tsx

管理插件的删除功能和状态的完整实现:

import { useNavigate } from 'react-router-dom';
import { useRef } from 'react';
import { useRequest } from 'ahooks';
import {ActionKey,ResType,type ResourceInfo,
} from '@coze-arch/idl/plugin_develop';
import { I18n } from '@coze-arch/i18n';
import { IconCozPlugin } from '@coze-arch/coze-design/icons';
import { Table, Menu, Toast } from '@coze-arch/coze-design';
import { EVENT_NAMES, sendTeaEvent } from '@coze-arch/bot-tea';
import { useFlags } from '@coze-arch/bot-flags';
import { PluginDevelopApi } from '@coze-arch/bot-api';
import { usePluginEditorModal } from '@coze-common/plugin-editor-modal';import { type UseEntityConfigHook } from './types';const { TableAction } = Table;export const usePluginConfig: UseEntityConfigHook = ({spaceId,isPersonalSpace = true,reloadList,getCommonActions,
}) => {const navigate = useNavigate();const [FLAGS] = useFlags();const recordRef = useRef<ResourceInfo | null>(null);const { open: openPluginEditor, node: pluginEditorModal } =usePluginEditorModal({spaceId,source: 'resource_library',onUpdateSuccess: reloadList,onPublish: ({ pluginId }) => {recordRef.current = {res_id: pluginId,};// 插件发布后的处理逻辑},});// 删除插件的核心逻辑const { run: delPlugin } = useRequest((pluginId: string) =>PluginDevelopApi.DelPlugin({plugin_id: pluginId,}),{manual: true,onSuccess: () => {reloadList(); // 删除成功后刷新列表Toast.success(I18n.t('Delete_success')); // 显示成功提示},onError: (error) => {Toast.error(I18n.t('Delete_failed')); // 显示失败提示console.error('删除插件失败:', error);},},);return {modals: (<>{pluginEditorModal}</>),config: {typeFilter: {label: I18n.t('library_resource_type_plugin'),value: ResType.Plugin,},renderCreateMenu: () => (<Menu.Itemdata-testid="workspace.library.header.create.plugin"icon={<IconCozPlugin />}onClick={() => {sendTeaEvent(EVENT_NAMES.widget_create_click, {source: 'menu_bar',workspace_type: isPersonalSpace? 'personal_workspace': 'team_workspace',});openPluginEditor({mode: 'create',});}}>{I18n.t('create_new_plugin')}</Menu.Item>),target: [ResType.Plugin],onItemClick: (record: ResourceInfo) => {recordRef.current = record;const canEdit = record.actions?.find(action => action.key === ActionKey.Edit,)?.enable;openPluginEditor({mode: 'info',canEdit,editId: record.res_id || '',});},// 渲染表格操作列,包含删除功能renderActions: (libraryResource: ResourceInfo) => (<TableActiondeleteProps={{// 根据权限控制删除按钮状态disabled: !libraryResource.actions?.find(action => action.key === ActionKey.Delete,)?.enable,// 删除确认描述deleteDesc: I18n.t('plugin_resource_delete_describ'),// 删除处理函数handler: () => {delPlugin(libraryResource.res_id || '');},}}// 编辑操作editProps={{disabled: !libraryResource.actions?.find(action => action.key === ActionKey.Edit,)?.enable,handler: () => {openPluginEditor({mode: 'edit',editId: libraryResource.res_id || '',});},}}actionList={getCommonActions?.(libraryResource)}/>),},};
};
bot-api/package.json

文件位置frontend/packages/arch/bot-api/package.json

核心代码:

{"name": "@coze-arch/bot-api","version": "0.0.1","description": "RPC wrapper for bot studio application","author": "fanwenjie.fe@bytedance.com","exports": {".": "./src/index.ts"}
}

代码作用

  1. 包定义:定义了一个名为 @coze-arch/bot-api 的 npm 包,版本为 0.0.1,这是一个用于 bot studio 应用的 RPC 包装器。
  2. API导出:在 frontend/packages/arch/bot-api/src/index.ts 中,PluginDevelopApi 被导出:
export { PluginDevelopApi } from './plugin-develop-api';

这允许通过 @coze-arch/bot-api 直接导入 PluginDevelopApi
3. API实现:在 src/plugin-develop-api.ts 中,PluginDevelopApi 是一个配置好的服务实例,它使用了 PluginDevelopService 和 axios 请求配置。

src/plugin-develop-api.ts

文件位置frontend/packages/arch/bot-api/src/plugin-develop-api.ts

核心代码:

import PluginDevelopApiService from './idl/plugin_develop';
import { axiosInstance, type BotAPIRequestConfig } from './axios';// eslint-disable-next-line @typescript-eslint/naming-convention
export const PluginDevelopApi = new PluginDevelopApiService<BotAPIRequestConfig>({request: (params, config = {}) => {config.headers = Object.assign(config.headers || {}, {'Agw-Js-Conv': 'str',});return axiosInstance.request({ ...params, ...config });},
});
axiosInstance说明
  1. 全局共享:axiosInstance 在整个项目中是全局共享的
  2. bot-api 包中的导入frontend/packages/arch/bot-api/src/axios.ts 直接从 @coze-arch/bot-http 包导入了 axiosInstance
import {axiosInstance,isApiError,type AxiosRequestConfig,
} from '@coze-arch/bot-http';
  1. bot-http 包中的定义frontend/packages/arch/bot-http/src/axios.ts
export const axiosInstance = axios.create();

这里创建了一个全局的 axios 实例,与其他API请求使用的是同一个实例。

PluginDevelopApiService说明
  1. bot-api包中的导入路径
import PluginDevelopApiService from './idl/plugin_develop';

实际指向 frontend/packages/arch/bot-api/src/idl/plugin_develop.ts
文件内容重新导出了 @coze-arch/idl/plugin_develop 包的所有内容,包括默认导出:

export * from '@coze-arch/idl/plugin_develop';
export { default as default } from '@coze-arch/idl/plugin_develop';
  1. idl包的模块映射
    文件位置frontend/packages/arch/idl/package.json
{"name": "@coze-arch/idl","version": "0.0.1","description": "IDL files for bot studio application","author": "fanwenjie.fe@bytedance.com","exports": {"./plugin_develop": "./src/auto-generated/plugin_develop/index.ts"}
}

代码作用:将 @coze-arch/idl/plugin_develop 映射到实际文件路径 frontend/packages/arch/idl/src/auto-generated/plugin_develop/index.ts

6. 删除插件操作的完整流程

删除插件的完整流程如下:

用户前端界面TableAction组件usePluginConfigPluginDevelopApi后端服务点击表格行的"..."按钮渲染操作菜单点击"删除"选项显示确认弹窗确认删除调用delPlugin函数检查删除权限调用DelPlugin接口发送删除插件请求返回删除结果返回操作结果显示成功/失败提示刷新列表数据(reloadList)用户前端界面TableAction组件usePluginConfigPluginDevelopApi后端服务

流程说明

  1. 权限检查:基于后端返回的 actions 数组判断是否有删除权限
  2. 确认机制:通过 Popconfirm 组件进行二次确认
  3. API调用:使用 PluginDevelopApi.DelPlugin 执行删除操作
  4. 状态更新:删除成功后自动刷新资源列表
  5. 用户反馈:通过 Toast 组件显示操作结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96309.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96309.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第一代:嵌入式本地状态(Flink 1.x)

最初的架构将状态以 JVM Heap 对象的形式存储在 TaskManager 的内存中。对于小规模数据集&#xff0c;这种方式效果良好&#xff0c;但随着状态大小的增长超出内存&#xff0c;将所有状态保存在内存中变得成本高昂且不稳定。 为了解决状态规模增长的问题&#xff0c;引入了一种…

跨境金融数据对接实践:印度NSE/BSE股票行情API集成指南

跨境金融数据对接实践&#xff1a;印度NSE/BSE股票行情API集成指南 关键词&#xff1a;印度股票数据对接 NSE实时行情 BSE证券接口 金融API开发 Python请求示例一、印度股市数据源技术解析&#xff08;核心价值&#xff09; 印度两大交易所数据获取难点&#xff1a; 时区差异&a…

AFSim2.9.0学习笔记 —— 1、AFSim及完整工具介绍(文末附:完整afsim2.9.0源码、编译好的完整工具包、中文教材等)

&#x1f514; AFSim2.9.0 相关技术、疑难杂症文章合集&#xff08;掌握后可自封大侠 ⓿_⓿&#xff09;&#xff08;记得收藏&#xff0c;持续更新中…&#xff09; AFSim介绍 AFSim&#xff08;Advanced Framework for Simulation Integration & Modeling【高级仿真集成与…

ArcGIS学习-18 实战-降雨量空间分布插值分析

设置环境加载要素投影查看要素&#xff0c;发现均不是投影数据&#xff0c;但都是地理坐标都是WGS1984使用工具进行批量投影然后新建空地图&#xff0c;重新加载确认图层的投影与栅格数据一致插值样条法得到反距离权重法插值得到克里金法插值得到

HarmonyOS应用开发:深入理解声明式UI与弹窗交互的最佳实践

HarmonyOS应用开发&#xff1a;深入理解声明式UI与弹窗交互的最佳实践 引言 随着HarmonyOS 4.0的发布及后续版本的演进&#xff0c;华为的分布式操作系统已经进入了全新的发展阶段。基于API 12及以上的开发环境为开发者提供了更强大、更高效的开发工具和框架。在HarmonyOS应用…

探索Java并发编程--从基础到高级实践技巧

Thread&#xff08;线程&#xff09;线程 程序执行的最小单位&#xff08;一个进程至少有一个线程&#xff09;。线程内有自己的执行栈、程序计数器&#xff08;PC&#xff09;&#xff0c;但与同进程内其他线程共享堆内存与进程资源 在java中&#xff0c;线程由java.lang.Thr…

Go语言实战案例-开发一个Markdown转HTML工具

这个小工具可以把 .md 文件转换为 .html 文件&#xff0c;非常适合写笔记、博客或者快速预览 Markdown 内容。&#x1f4cc; 案例目标• 读取一个 Markdown 文件• 使用开源库将 Markdown 转换为 HTML• 将 HTML 输出到新文件中&#x1f4e6; 所需库我们用 goldmark 这个 Markd…

基于51单片机的太阳能锂电池充电路灯

基于51单片机的太阳能锂电池充电路灯系统设计 1 系统功能介绍 本设计以 STC89C52单片机 为核心&#xff0c;构建了一个能够利用太阳能为锂电池充电并智能控制LED路灯的系统。系统结合了 光照检测电路、LED灯电路、按键检测电路、太阳能充电电路 等模块&#xff0c;实现了节能、…

PAT 1178 File Path

这一题的大意是给出了一个windows的文件夹目录&#xff0c;让我们按照所属的目录关系&#xff0c;来找相应的目录是否存在&#xff0c;如果存在&#xff0c;就输出找到该文件的路径&#xff0c;如果不存在输出error 我的思路是用合适的树形结构保存下来目录的所属关系&#xff…

云原生部署_k8s入门

K8S官网文档&#xff1a;&#xfeff;https://kubernetes.io/zh/docs/home/Kubernetes是什么Kubernetes 是用于自动部署、扩缩和管理容器化应用程序的开源系统。 Kubernetes 源自 &#xff0c;Google 15 年生产环境的运维经验同时凝聚了社区的最佳创意和实践。简称K8s.Kubernet…

实战项目-----Python+OpenCV 实现对视频的椒盐噪声注入与实时平滑还原”

实战项目实现以下功能&#xff1a;功能 1&#xff1a;为视频每一帧添加椒盐噪声作用&#xff1a;模拟真实环境中图像传输或采集时可能出现的噪声。实现方式&#xff1a;读取视频的每一帧。随机选择 10000 个像素点&#xff0c;将其设置为黑色&#xff08;0&#xff09;或白色&a…

Day42 PHP(mysql注入、跨库读取)

一、sql注入基本原理&#xff1a;没有对用户输入的数据进行限制&#xff0c;导致数据库语句可以做什么&#xff0c;用户就可以做什么。取决于不同数据库的不同查询语言&#xff0c;所以为什么有mysql注入/orcale注入等等。步骤&#xff1a;【access】表名&#xff08;字典爆破来…

机器人控制器开发(部署——软件打包备份更新)

文章总览 为什么做备份更新 为机器人控制器设计一套打包备份更新机制&#xff0c;为控制器的批量生产和产品与项目落地做准备。 当某个模块出现bug需要升级时&#xff0c;用户可以快速获取正确的bak包并导入到控制器中重启生效。 如果没有做好软件的备份更新机制&#xff0c…

LaTeX TeX Live 安装与 CTAN 国内镜像配置(Windows / macOS / Linux 全流程)

这是一份面向国内环境的 LaTeX 从零到可编译 指南&#xff1a;覆盖 TeX Live / MacTeX 安装、PATH 配置、CTAN 国内镜像&#xff08;清华/北外/上交/中科大等&#xff09;一键切换与回滚、常见坑位&#xff08;权限、镜像路径、版本切换&#xff09;、以及 XeLaTeX/latexmk 的实…

WhoisXML API再次荣登2025年美国Inc. 5000快速成长企业榜单

WhoisXML API非常自豪地宣布&#xff0c;我们再次荣登美国权威榜单——2025年Inc.5000全美成长最快的私营企业之一。今年&#xff0c;公司在地区排名中位列第119名&#xff0c;在全美总体排名中位列第4,271名。Inc. 5000榜单要求参评企业必须保持独立运营&#xff0c;并在2021至…

Elasticsearch面试精讲 Day 9:复合查询与过滤器优化

【Elasticsearch面试精讲 Day 9】复合查询与过滤器优化 在Elasticsearch的搜索体系中&#xff0c;复合查询&#xff08;Compound Queries&#xff09;与过滤器&#xff08;Filters&#xff09;优化是构建高效、精准搜索逻辑的核心能力。作为“Elasticsearch面试精讲”系列的第…

Android使用ReactiveNetwork监听网络连通性

引入库 implementation com.github.pwittchen:reactivenetwork-rx2:3.0.8监听网络连接变更ReactiveNetwork.observeNetworkConnectivity(context).subscribeOn(Schedulers.io())// ... // anything else what you can do with RxJava.observeOn(Schedulers.computation()).subs…

基于阿里云部署 RustDesk 自托管服务器

基于阿里云部署 RustDesk 自托管服务器一、背景与需求场景二、什么是 RustDesk&#xff1f;为什么选择自托管&#xff1f;2.1 RustDesk 是什么&#xff1f;2.2 为什么选择自托管&#xff1f;三、环境准备与架构说明四、操作步骤4.1 在阿里云上安装 RustDesk 服务端4.1.1 下载并…

细说分布式ID

针对高并发写&#xff0c;分布式ID是其业务基础&#xff0c;本文从一个面试题细细展开。面试官&#xff1a;1.对于Mysql的InnoDB引擎下&#xff0c;自增ID和UUID作为主键各自有什么优劣&#xff0c;对于一张表的主键你建议使用哪种ID&#xff1f;2.除了UUID是否还了解其他类型的…

2025年大数据专业证书报考指南:专科学历必看的8大选择​

对于大专学历的同学来说&#xff0c;2025年进入大数据行业是一个充满机遇的选择。大数据领域发展迅速&#xff0c;各类证书能够帮助求职者提升专业能力、增强就业竞争力。其中最推荐的是CDA数据分析师&#xff0c;这个证书适应了未来数字化经济和AI发展趋势&#xff0c;难度不高…