当前位置: 首页 > news >正文

Coze源码分析-资源库-删除工作流-前端源码-核心组件

概述

删除工作流是Coze Studio资源库管理中的重要功能,允许用户在资源库中安全地删除不再需要的工作流。本分析报告将详细介绍Coze Studio中删除工作流功能的前端实现原理、技术架构和核心组件设计。

删除工作流功能主要提供以下能力:

  1. 在资源库中删除指定的工作流
  2. 提供二次确认机制防止误操作
  3. 基于用户权限控制删除操作的可用性
  4. 删除成功后自动刷新资源列表
  5. 提供友好的操作结果反馈

本文档将从用户界面、核心组件、API调用和工具链等方面,深入剖析删除工作流功能的完整实现。

功能特性

1. 安全删除机制

删除工作流功能采用多层安全保障机制,确保用户数据安全:

  • 二次确认弹窗:防止用户误操作删除重要工作流
  • 权限控制:基于用户角色和资源所有权严格控制删除权限
  • 操作审计:记录删除操作日志,支持追溯

2. 完善的权限控制

系统通过ActionKey.Delete权限标识精确控制工作流删除权限:

  • 检查用户是否拥有工作流的删除权限
  • 检查工作流是否为当前用户创建
  • 检查工作流是否正在被其他资源引用

3. 用户友好的交互体验

删除工作流功能提供流畅的用户体验:

  • 统一的删除确认界面
  • 即时的操作结果反馈
  • 删除成功后自动刷新列表
  • 支持批量删除和单个删除两种模式

4. 健壮的错误处理机制

系统针对各种异常情况提供完善的错误处理:

  • 网络错误重试机制
  • 权限不足的明确提示
  • 资源不存在的状态同步
  • 服务端错误的优雅降级

技术架构

删除工作流功能采用前后端分离的架构设计,前端负责用户交互和状态管理,后端提供安全的API接口支持。

整体架构

数据类型层
API通信层
业务逻辑层
前端界面层
WorkflowResourceInfo
DelWorkflowRequest
ActionInfo
DelWorkflow接口
WorkflowDevelopApi
axiosInstance
TableAction配置
useWorkflowConfig Hook
删除工作流逻辑
BaseLibraryPage组件
LibraryPage组件
TableAction组件

组件层次结构

删除工作流功能的组件层次结构清晰,责任分明:

  1. LibraryPage:资源库页面主组件,管理整体布局和状态
  2. BaseLibraryPage:基础资源库页面组件,处理资源列表的加载和显示
  3. TableAction:表格操作组件,提供删除等快捷操作
  4. useWorkflowConfig:工作流配置Hook,管理工作流相关操作逻辑

数据流设计

删除工作流功能的数据流设计简洁高效:

  1. 用户操作触发删除请求
  2. 前端组件调用API层发送删除请求
  3. 接收后端响应并处理结果
  4. 更新本地状态并刷新UI
  5. 显示操作结果反馈给用户

用户删除工作流流程概述

操作流程

用户在Coze平台删除工作流的完整流程如下:

  1. 用户登录Coze平台
  2. 进入资源库页面:点击左侧导航栏的"资源库"入口
  3. 定位目标工作流:在资源库表格中找到要删除的工作流
  4. 打开操作菜单:点击目标工作流行最右侧的"…"按钮
  5. 选择删除操作:在弹出的操作菜单中点击"删除"选项
  6. 确认删除:在删除确认弹窗中点击"确认"按钮
  7. 等待操作结果:系统执行删除操作并显示结果提示

关键状态转换

删除工作流过程中,前端状态会经历以下关键转换:

  1. 初始状态:表格显示工作流列表,操作按钮根据权限状态显示
  2. 确认状态:用户点击删除后,显示确认弹窗
  3. 加载状态:用户确认后,显示加载指示器,禁用操作按钮
  4. 完成状态:操作完成后,隐藏加载指示器,显示结果提示,刷新列表

权限检查流程

删除工作流前,系统会执行严格的权限检查:

  1. 检查当前用户是否登录
  2. 检查用户是否拥有删除工作流的权限
  3. 检查工作流是否为当前用户创建
  4. 检查工作流是否被其他资源引用

只有通过所有检查后,系统才会允许用户执行删除操作。

核心组件实现

1. LibraryPage组件实现

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

LibraryPage是资源库页面的主组件,负责整体布局和状态管理:

import { useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Tabs, Tooltip, Button, Space } from '@coze-arch/coze-design';
import { I18n } from '@coze-arch/i18n';
import { IconSearch, IconCreate, IconFilter } from '@coze-arch/coze-design/icons';import { BaseLibraryPage } from './base-library-page';
import { useLibraryPermission } from './hooks/use-library-permission';
import { useEntityConfigs } from './hooks/use-entity-configs';const LibraryPage: React.FC = () => {const [activeTab, setActiveTab] = useState<string>('all');const navigate = useNavigate();const { getCommonActions, entityConfigs } = useEntityConfigs();const { hasCreatePermission } = useLibraryPermission();return (<div className={styles.container}>{/* 页面头部 */}<div className={styles.header}><h1 className={styles.title}>{I18n.t('Library_title')}</h1>{/* 创建按钮和过滤器 */}<div className={styles.headerActions}>{/* ... 头部操作按钮 */}</div></div>{/* 资源库内容 */}<BaseLibraryPageactiveTab={activeTab}setActiveTab={setActiveTab}getCommonActions={getCommonActions}entityConfigs={entityConfigs}/></div>);
};export default LibraryPage;

设计亮点

  • 采用组合模式,将具体资源类型的配置通过hooks注入
  • 统一的权限管理机制
  • 灵活的组件扩展能力
  • 响应式布局设计

2. BaseLibraryPage组件实现

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

BaseLibraryPage是资源库的基础实现,负责资源列表的加载、显示和操作:

import { forwardRef, useState, useCallback, useMemo } from 'react';
import { Tabs, Input, Table, Empty } from '@coze-arch/coze-design';
import { I18n } from '@coze-arch/i18n';
import { useInfiniteScroll } from 'ahooks';
import { IconSearch } from '@coze-arch/coze-design/icons';import { useSpaceInfo } from '../hooks/use-space-info';
import { WorkflowDevelopApi } from '@coze-arch/bot-api';
import type { ResourceInfo, ResType } from '@coze-arch/idl/workflow_develop';interface BaseLibraryPageProps {activeTab: string;setActiveTab: (tab: string) => void;getCommonActions?: (item: ResourceInfo) => any[];entityConfigs: Record<ResType, any>;
}// 使用forwardRef包装组件,允许父组件访问ref
export const BaseLibraryPage = forwardRef<HTMLDivElement, BaseLibraryPageProps>(({ activeTab, setActiveTab, getCommonActions, entityConfigs }, ref) => {const [searchValue, setSearchValue] = useState<string>('');const { spaceId, isPersonalSpace } = useSpaceInfo();// 使用useInfiniteScroll实现无限滚动加载const { data, loading, loadMore, refreshing, reload } = useInfiniteScroll(async (params) => {const result = await WorkflowDevelopApi.LibraryResourceList({space_id: spaceId,search: searchValue,page_size: 20,page_num: params.current,});return {list: result?.data?.list || [],total: result?.data?.total || 0,};},{pageSize: 20,refreshDeps: [searchValue, spaceId],},);// 表格列配置const columns = useMemo(() => [// ... 其他列配置{title: I18n.t('action'),key: 'action',width: 80,fixed: 'right',render: (_, record: ResourceInfo) => {const config = entityConfigs[record.res_type!];return config?.renderActions?.(record);},},], [entityConfigs]);return (<div className={styles.container} ref={ref}>{/* 表格组件 */}<TablerowKey={(record) => record.res_id || ''}dataSource={data?.list || []}columns={columns}loading={loading}scroll={{ x: 'max-content' }}pagination={false}onRow={(record) => {const config = entityConfigs[record.res_type!];return {onClick: () => config?.onItemClick?.(record),className: styles.row,};}}/></div>);},
);

设计亮点

  • 使用 forwardRef 允许父组件访问组件实例
  • 集成 useInfiniteScroll 实现列表无限滚动加载
  • 统一的资源列表展示逻辑
  • 可扩展的操作列配置
  • 根据资源类型动态选择配置

3. TableAction组件使用

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

TableAction是表格操作组件,提供了删除等快捷操作:

import { Table } from '@coze-arch/coze-design';const { TableAction } = Table;// TableAction组件的使用方式
<TableActiondeleteProps={{disabled: deleteDisabled,deleteDesc: I18n.t('library_delete_desc'),handler: async () => {await WorkflowDevelopApi.DelWorkflow({ workflow_id: item.res_id });reloadList();Toast.success(I18n.t('Delete_success'));},}}actionList={getCommonActions?.(item)}
/>

设计亮点

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

4. useWorkflowConfig Hook实现

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

useWorkflowConfig是管理工作流删除功能的核心Hook:

import { useNavigate } from 'react-router-dom';
import { useRef } from 'react';
import { useRequest } from 'ahooks';
import {ActionKey,ResType,type ResourceInfo,
} from '@coze-arch/idl/workflow_develop';
import { I18n } from '@coze-arch/i18n';
import { IconWorkflow } 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 { WorkflowDevelopApi } from '@coze-arch/bot-api';
import { useWorkflowEditorModal } from '@coze-common/workflow-editor-modal';import { type UseEntityConfigHook } from './types';const { TableAction } = Table;export const useWorkflowConfig: UseEntityConfigHook = ({spaceId,isPersonalSpace = true,reloadList,getCommonActions,
}) => {const navigate = useNavigate();const [FLAGS] = useFlags();const recordRef = useRef<ResourceInfo | null>(null);const { open: openWorkflowEditor, node: workflowEditorModal } = useWorkflowEditorModal({spaceId,source: 'resource_library',onUpdateSuccess: reloadList,onPublish: ({ workflowId }) => {recordRef.current = {res_id: workflowId,};// 工作流发布后的处理逻辑},});// 删除工作流的核心逻辑const { run: delWorkflow } = useRequest((workflowId: string) =>WorkflowDevelopApi.DelWorkflow({workflow_id: workflowId,}),{manual: true,onSuccess: () => {reloadList(); // 删除成功后刷新列表Toast.success(I18n.t('Delete_success')); // 显示成功提示},onError: (error) => {Toast.error(I18n.t('Delete_failed')); // 显示失败提示console.error('删除工作流失败:', error);},},);return {modals: (<>{workflowEditorModal}</>),config: {typeFilter: {label: I18n.t('library_resource_type_workflow'),value: ResType.Workflow,},renderCreateMenu: () => (<Menu.Itemdata-testid="workspace.library.header.create.workflow"icon={<IconWorkflow />}onClick={() => {sendTeaEvent(EVENT_NAMES.widget_create_click, {source: 'menu_bar',workspace_type: isPersonalSpace? 'personal_workspace': 'team_workspace',});openWorkflowEditor({mode: 'create',});}}>{I18n.t('create_new_workflow')}</Menu.Item>),target: [ResType.Workflow],onItemClick: (record: ResourceInfo) => {recordRef.current = record;const canEdit = record.actions?.find(action => action.key === ActionKey.Edit,)?.enable;openWorkflowEditor({mode: 'info',canEdit,editId: record.res_id || '',});},// 渲染表格操作列,包含删除功能renderActions: (libraryResource: ResourceInfo) => (<TableActiondeleteProps={{// 根据权限控制删除按钮状态disabled: !libraryResource.actions?.find(action => action.key === ActionKey.Delete,)?.enable,// 删除确认描述deleteDesc: I18n.t('workflow_resource_delete_describ'),// 删除处理函数handler: () => {delWorkflow(libraryResource.res_id || '');},}}// 编辑操作editProps={{disabled: !libraryResource.actions?.find(action => action.key === ActionKey.Edit,)?.enable,handler: () => {openWorkflowEditor({mode: 'edit',editId: libraryResource.res_id || '',});},}}actionList={getCommonActions?.(libraryResource)}/>),},};
};

设计亮点

  • 使用 useRequest 管理删除请求状态
  • 完善的成功/失败回调处理
  • 及时的Toast提示信息
  • 删除成功后自动刷新资源列表
  • 基于后端返回的actions数组动态控制删除按钮状态
  • 使用Popconfirm组件提供删除确认弹窗
  • 权限控制的细粒度实现

5. 删除确认弹窗逻辑

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

删除确认弹窗的核心实现:

// 删除确认弹窗的实现
<Popconfirmtrigger="click"okType="danger"title={i18n.t('delete_title')}content={i18n.t('workflow_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组件提供删除确认弹窗
  • 错误处理:完善的错误提示和异常处理
  • 用户反馈:及时的成功/失败提示
http://www.dtcms.com/a/393137.html

相关文章:

  • 机器学习实战第八章 降维
  • 2025年csp-j真题和解析
  • C++ STL map 深度解析:从原理到实战的全方位指南
  • 【EKF组合导航例程】MATLAB代码,15维状态量、3维观测量的组合导航,滤波使用EKF(扩展卡尔曼滤波)。附下载链接
  • word文档怎么根据大纲拆分章节
  • 【Modbus】Modbus协议基础知识详解
  • Springboot使用Integration实现MQTT发送和接收消息
  • 中国传统文化上衣下裳
  • zk管理kafkakafka-broker通信
  • 前端开发技术趋势Web Components
  • Python tarfile库详解
  • ​​[硬件电路-287]:高性能六通道数字隔离器CA-IS3763L 功能概述与管脚定义
  • 错题集系统接口文档
  • 【RAG-LLM】InfoGain-RAG基于文档信息增益的RAG
  • Browser-Use深度解析:重新定义AI与浏览器的智能协作
  • 【Mysql】事务隔离级别、索引原理、/redolog/undolog/binlog区别、主从复制原理
  • AWS 全景速查手册
  • 小米Openvela城市沙龙
  • Python数据分析:求矩阵的秩。啥是矩阵秩?听故事学线代并用Python实现,娘来太容易学会了!
  • UI Toolkit自定义元素
  • redis未授权访问-漏洞复现
  • PR调节器与PI调节器的区别
  • Unity核心概念⑫:碰撞检测
  • 【读论文】面向工业的ASR语音大模型
  • 重谈IO——五种IO模型及其分类
  • 数据库造神计划第十七天---索引(2)
  • 【开题答辩实录分享】以《车联网位置信息管理软件》为例进行答辩实录分享
  • (3)机器学习-模型介绍
  • 如何在 Ubuntu 20.04 LTS 上安装 MySQL 8
  • MuMu模拟器使用入门实践指南:从ADB连接到Frida动态分析