diff --git a/docs/ragflow-agent-overview.md b/docs/ragflow-agent-overview.md new file mode 100644 index 0000000..bb62f21 --- /dev/null +++ b/docs/ragflow-agent-overview.md @@ -0,0 +1,125 @@ +# `agent` & `agents` 目录代码结构解析 + +本文档旨在详细解析 `ragflow_core_v0.21.1` 项目中 `src/pages/agent` 和 `src/pages/agents` 两个核心目录的结构、功能和关系。 + +- **`src/pages/agent`**: Agent/数据流的可视化编排器,是构建和调试单个 Agent 的工作区。 +- **`src/pages/agents`**: Agent 的管理中心,负责列表展示、创建、模板管理和日志查看。 + +--- + +## 1. `src/pages/agent` - Agent 可视化编排器 + +此目录是整个 RAGFlow 的核心功能所在,提供了一个基于 `@xyflow/react` 的可视化画布,用户可以通过拖拽节点和连接边的方式来构建复杂的数据处理流(DSL)。 + +### 1.1. 目录结构概览 + +``` +agent/ +├── canvas/ # 画布核心组件 +│ ├── node/ # 所有自定义节点的实现 +│ └── edge/ # 自定义边的实现 +├── form/ # 所有节点的配置表单 +│ ├── agent-form/ +│ └── ... +├── hooks/ # 画布相关的 Hooks +│ ├── use-build-dsl.ts +│ └── use-save-graph.ts +├── chat/ # 调试用的聊天面板 +├── constant/ # Agent 相关的常量 +├── index.tsx # Agent 页面主入口 +└── store.ts # Zustand store,管理画布状态 +``` + +### 1.2. 关键子目录解析 + +#### `canvas/` - 画布与节点 + +- **`canvas/index.tsx`**: 画布主组件,负责整合节点、边、背景、小地图等,并处理拖拽、连接、删除等基本交互。 +- **`canvas/node/`**: 定义了所有内置的节点类型。每个节点文件(如 `begin-node.tsx`, `retrieval-form/`) 负责节点的 UI 渲染、Handles(连接点)的定位和基本逻辑。 + - `node-wrapper.tsx`: 为所有节点提供统一的包裹层,处理选中、错误、运行状态等通用 UI 逻辑。 + - `card.tsx`: 节点内部内容的标准卡片布局。 +- **`canvas/edge/`**: 自定义边的实现,可能包含特殊的路径、箭头或交互。 + +#### `form/` - 节点配置表单 + +当用户在画布上选中一个节点时,会弹出一个表单用于配置该节点的参数。此目录存放了所有节点对应的表单组件。 + +- 目录结构与节点类型一一对应,例如 `retrieval-form/` 对应检索节点。 +- 每个表单组件负责: + 1. 渲染配置项(如输入框、下拉框、开关等)。 + 2. 从节点数据中初始化表单。 + 3. 将用户的输入实时或在保存时更新回节点的 `data` 属性中。 +- `form/components/` 包含了一些表单内复用的组件,如标准的输出配置 (`output.tsx`)。 + +#### `hooks/` - 核心逻辑 Hooks + +此目录封装了画布的核心业务逻辑,使主页面 `index.tsx` 保持整洁。 + +- **`use-build-dsl.ts`**: 将画布上的节点和边(Graph a object)转换为后端可执行的领域特定语言(DSL JSON)。这是从前端图形表示到后端逻辑表示的关键转换。 +- **`use-save-graph.ts`**: 负责保存当前的图结构(节点和边的位置、数据等)到后端。通常在用户手动点击保存或自动保存时触发。 +- **`use-run-dataflow.ts`**: 触发当前 Agent 的运行,并处理返回的日志、结果等。 +- **`use-set-graph.ts`**: 从后端获取图数据并将其渲染到画布上,用于加载已保存的 Agent。 + +#### `chat/`, `debug-content/`, `log-sheet/` - 调试与运行 + +- **`chat/`**: Agent 调试时使用的聊天界面,用于发送输入并实时查看 Agent 的回复。 +- **`debug-content/`**: 调试抽屉的内容,可能包含更详细的输入/输出或日志信息。 +- **`log-sheet/`**: 展示 Agent 运行历史日志的面板。 + +#### `store.ts` + +基于 Zustand 的状态管理,全局维护画布的状态,例如: +- `nodes`, `edges`: 画布上的节点和边数组。 +- `onNodesChange`, `onEdgesChange`: `@xyflow/react` 需要的回调。 +- 当前选中的节点、画布的缩放/平移状态等。 +- 其他 UI 状态,如配置面板是否打开。 + +--- + +## 2. `src/pages/agents` - Agent 管理中心 + +此目录负责管理所有的 Agent 实例,是用户与 Agent 交互的入口页面。 + +### 2.1. 目录结构概览 + +``` +agents/ +├── hooks/ +│ ├── use-create-agent.ts +│ └── use-selelct-filters.ts +├── agent-card.tsx # 单个 Agent 的卡片展示 +├── agent-log-page.tsx # Agent 运行日志列表页 +├── agent-templates.tsx # Agent 模板页 +├── create-agent-dialog.tsx # 创建 Agent 的对话框 +├── index.tsx # Agent 列表页面主入口 +└── use-rename-agent.ts # 重命名 Agent 的 Hook +``` + +### 2.2. 关键文件解析 + +- **`index.tsx`**: Agent 列表的主页面。通常会从后端获取所有 Agent 的列表,并使用 `agent-card.tsx` 将它们渲染出来。包含搜索、筛选和分页等功能。 +- **`agent-card.tsx`**: 以卡片形式展示单个 Agent 的摘要信息,如名称、描述、更新时间等。点击卡片通常会导航到 `src/pages/agent` 页面,并传入对应的 Agent ID。 +- **`create-agent-dialog.tsx` / `create-agent-form.tsx`**: 提供创建新 Agent 的表单和对话框。`use-create-agent.ts` Hook 封装了向后端发送创建请求的逻辑。 +- **`agent-templates.tsx`**: 展示可供用户选择的预置 Agent 模板,帮助用户快速启动。 +- **`agent-log-page.tsx`**: 展示所有 Agent 的历史运行日志,提供查询和筛选功能。点击某条日志可以查看详情。 +- **`hooks/`**: 存放与 Agent 列表管理相关的业务逻辑。 + - `use-create-agent.ts`: 封装创建 Agent 的 API 调用。 + - `use-selelct-filters.ts`: 管理列表页的筛选条件。 + +--- + +## 3. 关系与数据流 + +1. **从 `agents` 到 `agent`**: + - 用户在 `agents` 列表页 (`/agents`) 点击一个 Agent 卡片。 + - 应用导航到 `agent` 编排页 (`/agent/{agent_id}`)。 + - `agent` 页面的 `use-set-graph.ts` Hook 被触发,使用 `agent_id` 从后端获取该 Agent 的图数据。 + - 获取到的图数据通过 `store.ts` 设置到全局状态,画布 (`canvas/index.tsx`) 监听到状态变化后,渲染出对应的节点和边。 + +2. **从 `agent` 保存与返回**: + - 用户在 `agent` 页面修改了图结构。 + - `use-save-graph.ts` Hook 将新的图结构保存到后端。 + - `use-build-dsl.ts` 将图结构转换为 DSL 并一同保存。 + - 用户返回 `agents` 列表页,可以看到 Agent 的更新时间等信息已变化。 + +这两个目录共同构成了一个完整的 Agent 创建、管理、编排和调试的闭环。 \ No newline at end of file diff --git a/src/components/Layout/Sidebar.tsx b/src/components/Layout/Sidebar.tsx index a69bbd2..e695249 100644 --- a/src/components/Layout/Sidebar.tsx +++ b/src/components/Layout/Sidebar.tsx @@ -1,23 +1,19 @@ import { Box, List, ListItemButton, ListItemText, Typography } from '@mui/material'; import { Link, useLocation } from 'react-router-dom'; -import DashboardOutlinedIcon from '@mui/icons-material/DashboardOutlined'; -import LibraryBooksOutlinedIcon from '@mui/icons-material/LibraryBooksOutlined'; -import AccountTreeOutlinedIcon from '@mui/icons-material/AccountTreeOutlined'; -import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined'; -import StorageOutlinedIcon from '@mui/icons-material/StorageOutlined'; -import ExtensionOutlinedIcon from '@mui/icons-material/ExtensionOutlined'; - -const navItems = [ - // { text: 'Overview', path: '/', icon: DashboardOutlinedIcon }, - { text: 'Knowledge Bases', path: '/', icon: LibraryBooksOutlinedIcon }, - // { text: 'RAG Pipeline', path: '/pipeline-config', icon: AccountTreeOutlinedIcon }, - // { text: 'Operations', path: '/dashboard', icon: SettingsOutlinedIcon }, - // { text: 'Models & Resources', path: '/models-resources', icon: StorageOutlinedIcon }, - // { text: 'MCP', path: '/mcp', icon: ExtensionOutlinedIcon }, -]; +import { + LibraryBooksOutlined as KnowledgeBasesIcon, + AccountTreeOutlined as AgentIcon, +} from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; const Sidebar = () => { const location = useLocation(); + const { t } = useTranslation(); + + const navItems = [ + { text: t('header.knowledgeBase'), path: '/knowledge', icon: KnowledgeBasesIcon }, + { text: t('header.agent'), path: '/agent', icon: AgentIcon }, + ]; return ( { }} > T-Systems Enterprise - - + + {navItems.map((item) => { const IconComponent = item.icon; - const isActive = location.pathname === item.path; - + let isActive = location.pathname === item.path; + if (item.path === '/knowledge' && location.pathname === '/') { + isActive = true; + } return ( - { }, }} > - @@ -84,7 +82,6 @@ const Sidebar = () => { ); })} - , agent: IFlow) => void; + onViewAgent: (agent: IFlow) => void; +} + +const AgentCard: React.FC = ({ agent, onMenuClick, onViewAgent }) => { + const { t } = useTranslation(); + + const getPermissionInfo = (permission: string) => { + switch (permission) { + case 'me': + return { label: t('common.private'), color: '#E3F2FD', textColor: '#1976D2' }; + case 'team': + return { label: t('common.team'), color: '#E8F5E8', textColor: '#388E3C' }; + default: + return { label: t('common.public'), color: '#FFF3E0', textColor: '#F57C00' }; + } + }; + + const permissionInfo = getPermissionInfo(agent.permission || 'me'); + + const formatDate = (dateStr?: string) => { + if (!dateStr) return t('common.unknown'); + return dateStr; + }; + + const nodeCount = agent.dsl?.graph?.nodes?.length ?? 0; + const edgeCount = agent.dsl?.graph?.edges?.length ?? 0; + + return ( + + + + + {agent.title?.[0] || 'A'} + + {agent.title || t('common.untitled')} + + {agent.canvas_category && ( + + )} + + + + + + onMenuClick(e, agent)}> + + + + + + + {agent.description || t('common.noDescription')} + + + + + + {nodeCount} + + {t('agent.nodes') || 'Nodes'} + + + + {edgeCount} + + {t('agent.edges') || 'Edges'} + + + + + {t('common.updatedAt') || 'Updated'}: {formatDate(agent.update_date)} + + + {agent.nickname && ( + + {t('knowledge.creator') || 'Creator'}: {agent.nickname} + + )} + + + ); +}; + +export default AgentCard; \ No newline at end of file diff --git a/src/components/agent/AgentGridView.tsx b/src/components/agent/AgentGridView.tsx new file mode 100644 index 0000000..eac7d6a --- /dev/null +++ b/src/components/agent/AgentGridView.tsx @@ -0,0 +1,125 @@ +import React from 'react'; +import { Box, Typography, Grid, Button, Menu, MenuItem } from '@mui/material'; +import { ArrowForward as ArrowForwardIcon, Add as AddIcon } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; +import type { IFlow } from '@/interfaces/database/agent'; +import AgentCard from './AgentCard'; + +interface AgentGridViewProps { + agents: IFlow[]; + maxItems?: number; + showSeeAll?: boolean; + onSeeAll?: () => void; + onEdit?: (agent: IFlow) => void; + onDelete?: (agent: IFlow) => void; + onView?: (agent: IFlow) => void; + loading?: boolean; + searchTerm?: string; + onCreateAgent?: () => void; +} + +const AgentGridView: React.FC = ({ + agents, + maxItems, + showSeeAll = false, + onSeeAll, + onEdit, + onDelete, + onView, + loading = false, + searchTerm = '', + onCreateAgent, +}) => { + const { t } = useTranslation(); + const [anchorEl, setAnchorEl] = React.useState(null); + const [selectedAgent, setSelectedAgent] = React.useState(null); + + const handleMenuClick = (event: React.MouseEvent, agent: IFlow) => { + setAnchorEl(event.currentTarget); + setSelectedAgent(agent); + }; + + const handleMenuClose = () => { + setAnchorEl(null); + setSelectedAgent(null); + }; + + const handleDelete = () => { + if (selectedAgent && onDelete) { + onDelete(selectedAgent); + } + handleMenuClose(); + }; + + const handleView = () => { + if (selectedAgent && onView) { + onView(selectedAgent); + } + handleMenuClose(); + }; + + const handleViewAgent = (agent: IFlow) => { + if (onView) { + onView(agent); + } + handleMenuClose(); + }; + + const displayedAgents = maxItems ? agents.slice(0, maxItems) : agents; + const hasMore = maxItems && agents.length > maxItems; + + if (loading) { + return ( + + {t('common.loading')} + + ); + } + + if (agents.length === 0) { + return ( + + + {searchTerm ? (t('agent.noMatchingAgents') || 'No matching agents') : (t('agent.noAgents') || 'No agents')} + + + {searchTerm ? (t('agent.tryAdjustingFilters') || 'Try adjusting filters') : (t('agent.createFirstAgent') || 'Create your first agent')} + + {(!searchTerm && onCreateAgent) && ( + + )} + + ); + } + + return ( + + + {displayedAgents.map((agent) => ( + + + + ))} + + + {showSeeAll && hasMore && ( + + + + )} + + + {t('common.viewDetails')} + + {t('common.delete')} + + + + ); +}; + +export default AgentGridView; \ No newline at end of file diff --git a/src/constants/agent.ts b/src/constants/agent.ts new file mode 100644 index 0000000..dedeb06 --- /dev/null +++ b/src/constants/agent.ts @@ -0,0 +1,97 @@ +export enum ProgrammingLanguage { + Python = 'python', + Javascript = 'javascript', +} + +export const CodeTemplateStrMap = { + [ProgrammingLanguage.Python]: `def main(arg1: str, arg2: str) -> str: + return f"result: {arg1 + arg2}" +`, + [ProgrammingLanguage.Javascript]: `const axios = require('axios'); +async function main({}) { + try { + const response = await axios.get('https://github.com/infiniflow/ragflow'); + return 'Body:' + response.data; + } catch (error) { + return 'Error:' + error.message; + } +}`, +}; + +export enum AgentGlobals { + SysQuery = 'sys.query', + SysUserId = 'sys.user_id', + SysConversationTurns = 'sys.conversation_turns', + SysFiles = 'sys.files', +} + +export enum AgentCategory { + AgentCanvas = 'agent_canvas', + DataflowCanvas = 'dataflow_canvas', +} + +export enum AgentQuery { + Category = 'category', +} + +export enum DataflowOperator { + Begin = 'File', + Note = 'Note', + Parser = 'Parser', + Tokenizer = 'Tokenizer', + Splitter = 'Splitter', + HierarchicalMerger = 'HierarchicalMerger', + Extractor = 'Extractor', +} + +export enum Operator { + Begin = 'Begin', + Retrieval = 'Retrieval', + Categorize = 'Categorize', + Message = 'Message', + Relevant = 'Relevant', + RewriteQuestion = 'RewriteQuestion', + KeywordExtract = 'KeywordExtract', + Baidu = 'Baidu', + DuckDuckGo = 'DuckDuckGo', + Wikipedia = 'Wikipedia', + PubMed = 'PubMed', + ArXiv = 'ArXiv', + Google = 'Google', + Bing = 'Bing', + GoogleScholar = 'GoogleScholar', + DeepL = 'DeepL', + GitHub = 'GitHub', + BaiduFanyi = 'BaiduFanyi', + QWeather = 'QWeather', + ExeSQL = 'ExeSQL', + Switch = 'Switch', + WenCai = 'WenCai', + AkShare = 'AkShare', + YahooFinance = 'YahooFinance', + Jin10 = 'Jin10', + TuShare = 'TuShare', + Note = 'Note', + Crawler = 'Crawler', + Invoke = 'Invoke', + Email = 'Email', + Iteration = 'Iteration', + IterationStart = 'IterationItem', + Code = 'CodeExec', + WaitingDialogue = 'WaitingDialogue', + Agent = 'Agent', + Tool = 'Tool', + TavilySearch = 'TavilySearch', + TavilyExtract = 'TavilyExtract', + UserFillUp = 'UserFillUp', + StringTransform = 'StringTransform', + SearXNG = 'SearXNG', + Placeholder = 'Placeholder', + File = 'File', // pipeline + Parser = 'Parser', + Tokenizer = 'Tokenizer', + Splitter = 'Splitter', + HierarchicalMerger = 'HierarchicalMerger', + Extractor = 'Extractor', + Generate = 'Generate', +} diff --git a/src/hooks/agent-hooks.ts b/src/hooks/agent-hooks.ts new file mode 100644 index 0000000..2d7a994 --- /dev/null +++ b/src/hooks/agent-hooks.ts @@ -0,0 +1,82 @@ +import { useState, useCallback, useEffect } from 'react'; +import agentService from '@/services/agent_service'; +import type { IFlow } from '@/interfaces/database/agent'; +import type { IAgentPaginationParams } from '@/interfaces/request/agent'; +import logger from '@/utils/logger'; + +export interface UseAgentListState { + agents: IFlow[]; + total: number; + loading: boolean; + error: string | null; + currentPage: number; + pageSize: number; + keywords: string; + orderby?: string; + desc?: boolean; +} + +export interface UseAgentListReturn extends UseAgentListState { + fetchAgents: (params?: IAgentPaginationParams) => Promise; + setKeywords: (keywords: string) => void; + setCurrentPage: (page: number) => void; + setPageSize: (size: number) => void; + setOrder: (orderby?: string, desc?: boolean) => void; + refresh: () => Promise; +} + +/** + * 智能体列表钩子 + * @param initialParams 初始参数 + */ +export const useAgentList = (initialParams?: IAgentPaginationParams) => { + const [agents, setAgents] = useState([]); + const [total, setTotal] = useState(0); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [currentPage, setCurrentPage] = useState(initialParams?.page || 1); + const [pageSize, setPageSize] = useState(initialParams?.page_size || 10); + const [keywords, setKeywords] = useState(initialParams?.keywords || ''); + + const fetchAgentList = useCallback(async (params?: IAgentPaginationParams) => { + setLoading(true); + setError(null); + try { + const response = await agentService.listCanvas(params); + const res = response.data || {}; + logger.info('useAgentList fetchAgentList', res); + const data = res.data + setAgents(data.canvas || []); + setTotal(data.total || 0); + } catch (err: any) { + setError(err.message || 'Failed to fetch agent list'); + } finally { + setLoading(false); + } + }, []); + + const refresh = useCallback(() => fetchAgentList({ + keywords, + page: currentPage, + page_size: pageSize, + }), [keywords, currentPage, pageSize]); + + useEffect(() => { + refresh(); + }, [refresh]); + + return { + agents, + total, + loading, + error, + currentPage, + pageSize, + keywords, + fetchAgents: fetchAgentList, + setKeywords, + setCurrentPage, + setPageSize, + refresh, + }; +}; \ No newline at end of file diff --git a/src/interfaces/request/agent.ts b/src/interfaces/request/agent.ts index 1c6ee8b..61c9224 100644 --- a/src/interfaces/request/agent.ts +++ b/src/interfaces/request/agent.ts @@ -1,3 +1,13 @@ +/** + * 分页请求参数 + */ +export interface IAgentPaginationParams { + keywords?: string; + page?: number; + page_size?: number; +} + + export interface IDebugSingleRequestBody { component_id: string; params: Record; diff --git a/src/interfaces/request/base.ts b/src/interfaces/request/base.ts index 96f0911..e2b2f83 100644 --- a/src/interfaces/request/base.ts +++ b/src/interfaces/request/base.ts @@ -10,6 +10,7 @@ export interface IPaginationRequestBody { * 分页请求参数 */ export interface IPaginationBody { + keywords?: string; page?: number; size?: number; } diff --git a/src/locales/en.ts b/src/locales/en.ts index 25879f4..dc778a3 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -278,7 +278,7 @@ export default { setting: 'User settings', logout: 'Log out', fileManager: 'File Management', - flow: 'Agent', + agent: 'Agent', search: 'Search', welcome: 'Welcome to', }, diff --git a/src/locales/zh.ts b/src/locales/zh.ts index c8c406f..ed1058d 100644 --- a/src/locales/zh.ts +++ b/src/locales/zh.ts @@ -262,7 +262,7 @@ export default { setting: '用户设置', logout: '登出', fileManager: '文件管理', - flow: '智能体', + agent: '智能体', search: '搜索', welcome: '欢迎来到', }, diff --git a/src/pages/agent/list.tsx b/src/pages/agent/list.tsx new file mode 100644 index 0000000..364a8f4 --- /dev/null +++ b/src/pages/agent/list.tsx @@ -0,0 +1,96 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { + Box, + Typography, + TextField, + InputAdornment, + Paper, + Button, + Pagination, + Stack, +} from '@mui/material'; +import { Search as SearchIcon, Refresh as RefreshIcon } from '@mui/icons-material'; +import { useAgentList } from '@/hooks/agent-hooks'; +import AgentGridView from '@/components/agent/AgentGridView'; + +function AgentListPage() { + const [searchValue, setSearchValue] = useState(''); + const { + agents, + total, + loading, + currentPage, + pageSize, + setCurrentPage, + setKeywords, + refresh, + } = useAgentList({ page: 1, page_size: 10 }); + + const totalPages = useMemo(() => { + return Math.ceil((agents?.length || 0) / pageSize) || 1; + }, [agents, pageSize]); + + const currentPageData = useMemo(() => { + const startIndex = (currentPage - 1) * pageSize; + const endIndex = startIndex + pageSize; + return (agents || []).slice(startIndex, endIndex); + }, [agents, currentPage, pageSize]); + + const handleSearch = useCallback(() => { + setKeywords(searchValue); + setCurrentPage(1); + }, [searchValue, setKeywords, setCurrentPage]); + + return ( + + Agent 列表 + + + + setSearchValue(e.target.value)} + placeholder="搜索名称或描述" + size="small" + InputProps={{ + startAdornment: ( + + + + ) + }} + /> + + + + + + + + {totalPages >= 1 && ( + + + setCurrentPage(page)} + color="primary" + size="large" + showFirstButton + showLastButton + /> + + 共 {total} 个,当前第 {currentPage} / {totalPages} 页 + + + + )} + + ); +} + +export default AgentListPage; \ No newline at end of file diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 139fba7..df85312 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -5,6 +5,7 @@ import Login from '../pages/login/Login'; import PipelineConfig from '../pages/PipelineConfig'; import Dashboard from '../pages/Dashboard'; import ModelsResources from '../pages/ModelsResources'; +import AgentList from '../pages/agent/list'; import { KnowledgeBaseList, KnowledgeBaseCreate, @@ -32,7 +33,7 @@ const AppRoutes = () => { {/* 使用MainLayout作为受保护路由的布局 */} }> - {/* } /> */} + } /> } /> } /> @@ -44,12 +45,9 @@ const AppRoutes = () => { } /> - } /> - } /> - } /> - } /> - } /> - } /> + + } /> + {/* 处理chunk相关路由 需要传入 kb_id doc_id */} @@ -68,7 +66,7 @@ const AppRoutes = () => { {/* 处理未匹配的路由 */} - } /> + } /> ); }; diff --git a/src/services/agent_service.ts b/src/services/agent_service.ts new file mode 100644 index 0000000..9ede398 --- /dev/null +++ b/src/services/agent_service.ts @@ -0,0 +1,19 @@ +import api from './api'; +import request from '@/utils/request'; +import type { IAgentPaginationParams } from '@/interfaces/request/agent'; + +/** + * 智能体服务 + */ +const agentService = { + /** + * 获取团队下的Canvas列表 + */ + listCanvas: (params?: IAgentPaginationParams) => { + return request.get(api.listTeamCanvas, { params }); + }, + + +}; + +export default agentService; \ No newline at end of file diff --git a/src/services/api.ts b/src/services/api.ts index 80497d9..370cb73 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -151,6 +151,7 @@ export default { // flow listTemplates: `${api_host}/canvas/templates`, listCanvas: `${api_host}/canvas/list`, + listTeamCanvas: `${api_host}/canvas/listteam`, getCanvas: `${api_host}/canvas/get`, getCanvasSSE: `${api_host}/canvas/getsse`, removeCanvas: `${api_host}/canvas/rm`, diff --git a/tsconfig.app.json b/tsconfig.app.json index 58ce92b..c884492 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -11,7 +11,7 @@ /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, + "verbatimModuleSyntax": false, "moduleDetection": "force", "noEmit": true, "jsx": "react-jsx", @@ -20,7 +20,7 @@ "strict": true, "noUnusedLocals": false, "noUnusedParameters": false, - "erasableSyntaxOnly": true, + "erasableSyntaxOnly": false, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true,