| 'use client'; | |
| import { useState } from 'react'; | |
| interface WorkflowConfigProps { | |
| data: any; | |
| onChange: (data: any) => void; | |
| } | |
| export default function WorkflowConfig({ data, onChange }: WorkflowConfigProps) { | |
| const [selectedWorkflows, setSelectedWorkflows] = useState(data.workflows || []); | |
| const [searchTerm, setSearchTerm] = useState(''); | |
| const [filterCategory, setFilterCategory] = useState('all'); | |
| const availableWorkflows = [ | |
| { | |
| id: 'wf-001', | |
| name: '数据分析流程', | |
| description: '自动化数据收集、清洗和分析', | |
| category: 'data-processing', | |
| icon: '📊', | |
| status: 'active', | |
| lastUsed: '2024-01-15', | |
| executions: 156 | |
| }, | |
| { | |
| id: 'wf-002', | |
| name: '内容审核工作流', | |
| description: '文本内容智能审核和分类', | |
| category: 'content-moderation', | |
| icon: '🔍', | |
| status: 'active', | |
| lastUsed: '2024-01-14', | |
| executions: 89 | |
| }, | |
| { | |
| id: 'wf-003', | |
| name: '客服自动回复', | |
| description: '基于知识库的智能客服响应', | |
| category: 'customer-service', | |
| icon: '💬', | |
| status: 'active', | |
| lastUsed: '2024-01-13', | |
| executions: 234 | |
| }, | |
| { | |
| id: 'wf-004', | |
| name: '报告生成器', | |
| description: '自动生成业务分析报告', | |
| category: 'report-generation', | |
| icon: '📄', | |
| status: 'active', | |
| lastUsed: '2024-01-12', | |
| executions: 67 | |
| }, | |
| { | |
| id: 'wf-005', | |
| name: '邮件处理流程', | |
| description: '邮件分类和自动回复', | |
| category: 'email-automation', | |
| icon: '📧', | |
| status: 'active', | |
| lastUsed: '2024-01-11', | |
| executions: 145 | |
| }, | |
| { | |
| id: 'wf-006', | |
| name: '社交媒体监控', | |
| description: '社交媒体内容监控和分析', | |
| category: 'social-media', | |
| icon: '📱', | |
| status: 'active', | |
| lastUsed: '2024-01-10', | |
| executions: 78 | |
| } | |
| ]; | |
| const categories = [ | |
| { key: 'all', label: '全部分类', count: availableWorkflows.length }, | |
| { key: 'data-processing', label: '数据处理', count: 1 }, | |
| { key: 'content-moderation', label: '内容审核', count: 1 }, | |
| { key: 'customer-service', label: '客服服务', count: 1 }, | |
| { key: 'report-generation', label: '报告生成', count: 1 }, | |
| { key: 'email-automation', label: '邮件自动化', count: 1 }, | |
| { key: 'social-media', label: '社交媒体', count: 1 } | |
| ]; | |
| const filteredWorkflows = availableWorkflows.filter(workflow => { | |
| const matchesSearch = workflow.name.toLowerCase().includes(searchTerm.toLowerCase()) || | |
| workflow.description.toLowerCase().includes(searchTerm.toLowerCase()); | |
| const matchesCategory = filterCategory === 'all' || workflow.category === filterCategory; | |
| return matchesSearch && matchesCategory; | |
| }); | |
| const handleWorkflowToggle = (workflowId: string) => { | |
| const isSelected = selectedWorkflows.includes(workflowId); | |
| const updatedWorkflows = isSelected | |
| ? selectedWorkflows.filter(id => id !== workflowId) | |
| : [...selectedWorkflows, workflowId]; | |
| setSelectedWorkflows(updatedWorkflows); | |
| onChange({ ...data, workflows: updatedWorkflows }); | |
| }; | |
| const handleSelectAll = () => { | |
| const allIds = filteredWorkflows.map(wf => wf.id); | |
| setSelectedWorkflows(allIds); | |
| onChange({ ...data, workflows: allIds }); | |
| }; | |
| const handleDeselectAll = () => { | |
| setSelectedWorkflows([]); | |
| onChange({ ...data, workflows: [] }); | |
| }; | |
| return ( | |
| <div className="space-y-8"> | |
| <div> | |
| <h3 className="text-lg font-semibold text-gray-900 mb-2">工作流配置</h3> | |
| <p className="text-gray-600 mb-6">选择Agent可以调用的工作流程,增强自动化处理能力</p> | |
| <div className="grid grid-cols-1 lg:grid-cols-4 gap-8"> | |
| <div className="lg:col-span-3 space-y-6"> | |
| {/* 搜索和筛选 */} | |
| <div className="bg-white border border-gray-200 rounded-lg p-4"> | |
| <div className="flex flex-col sm:flex-row gap-4"> | |
| <div className="flex-1 relative"> | |
| <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | |
| <div className="w-4 h-4 flex items-center justify-center"> | |
| <i className="ri-search-line text-gray-400"></i> | |
| </div> | |
| </div> | |
| <input | |
| type="text" | |
| placeholder="搜索工作流..." | |
| value={searchTerm} | |
| onChange={(e) => setSearchTerm(e.target.value)} | |
| className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" | |
| /> | |
| </div> | |
| <select | |
| value={filterCategory} | |
| onChange={(e) => setFilterCategory(e.target.value)} | |
| className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm pr-8" | |
| > | |
| {categories.map(category => ( | |
| <option key={category.key} value={category.key}> | |
| {category.label} ({category.count}) | |
| </option> | |
| ))} | |
| </select> | |
| </div> | |
| <div className="flex items-center justify-between mt-4"> | |
| <div className="text-sm text-gray-600"> | |
| 已选择 {selectedWorkflows.length} 个工作流 | |
| </div> | |
| <div className="flex space-x-2"> | |
| <button | |
| onClick={handleSelectAll} | |
| className="px-3 py-1 text-sm text-blue-600 hover:bg-blue-50 rounded cursor-pointer" | |
| > | |
| 全选 | |
| </button> | |
| <button | |
| onClick={handleDeselectAll} | |
| className="px-3 py-1 text-sm text-gray-600 hover:bg-gray-50 rounded cursor-pointer" | |
| > | |
| 清空 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| {/* 工作流列表 */} | |
| <div className="space-y-4"> | |
| {filteredWorkflows.map((workflow) => ( | |
| <div | |
| key={workflow.id} | |
| className={`bg-white border rounded-lg p-4 cursor-pointer transition-all ${ | |
| selectedWorkflows.includes(workflow.id) | |
| ? 'border-blue-500 bg-blue-50' | |
| : 'border-gray-200 hover:border-gray-300' | |
| }`} | |
| onClick={() => handleWorkflowToggle(workflow.id)} | |
| > | |
| <div className="flex items-center justify-between"> | |
| <div className="flex items-center space-x-4"> | |
| <div className="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center text-xl"> | |
| {workflow.icon} | |
| </div> | |
| <div className="flex-1"> | |
| <div className="flex items-center space-x-2"> | |
| <h4 className="font-medium text-gray-900">{workflow.name}</h4> | |
| <span className="px-2 py-1 bg-green-100 text-green-800 text-xs rounded-full"> | |
| {workflow.status === 'active' ? '活跃' : '暂停'} | |
| </span> | |
| </div> | |
| <p className="text-sm text-gray-600 mt-1">{workflow.description}</p> | |
| <div className="flex items-center space-x-4 mt-2 text-xs text-gray-500"> | |
| <span>执行次数: {workflow.executions}</span> | |
| <span>最后使用: {workflow.lastUsed}</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div className="flex items-center space-x-3"> | |
| <button | |
| onClick={(e) => { | |
| e.stopPropagation(); | |
| alert('工作流详情功能开发中...'); | |
| }} | |
| className="p-2 text-gray-400 hover:text-gray-600 rounded-lg transition-colors cursor-pointer" | |
| > | |
| <div className="w-4 h-4 flex items-center justify-center"> | |
| <i className="ri-eye-line"></i> | |
| </div> | |
| </button> | |
| <div className={`w-5 h-5 rounded border-2 flex items-center justify-center ${ | |
| selectedWorkflows.includes(workflow.id) | |
| ? 'border-blue-500 bg-blue-500' | |
| : 'border-gray-300' | |
| }`}> | |
| {selectedWorkflows.includes(workflow.id) && ( | |
| <i className="ri-check-line text-white text-xs"></i> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| {filteredWorkflows.length === 0 && ( | |
| <div className="text-center py-12"> | |
| <div className="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4"> | |
| <i className="ri-search-line text-2xl text-gray-400"></i> | |
| </div> | |
| <p className="text-gray-500">没有找到匹配的工作流</p> | |
| </div> | |
| )} | |
| </div> | |
| <div className="space-y-6"> | |
| <div className="bg-white border border-gray-200 rounded-lg p-4"> | |
| <h4 className="font-medium text-gray-900 mb-3">已选择的工作流</h4> | |
| {selectedWorkflows.length === 0 ? ( | |
| <p className="text-sm text-gray-500">还未选择任何工作流</p> | |
| ) : ( | |
| <div className="space-y-2"> | |
| {selectedWorkflows.map((workflowId) => { | |
| const workflow = availableWorkflows.find(w => w.id === workflowId); | |
| return workflow ? ( | |
| <div key={workflowId} className="flex items-center justify-between py-2 px-3 bg-gray-50 rounded"> | |
| <div className="flex items-center space-x-2"> | |
| <span className="text-sm">{workflow.icon}</span> | |
| <span className="text-sm font-medium text-gray-900">{workflow.name}</span> | |
| </div> | |
| <button | |
| onClick={() => handleWorkflowToggle(workflowId)} | |
| className="w-4 h-4 flex items-center justify-center text-gray-400 hover:text-red-600 cursor-pointer" | |
| > | |
| <i className="ri-close-line text-xs"></i> | |
| </button> | |
| </div> | |
| ) : null; | |
| })} | |
| </div> | |
| )} | |
| </div> | |
| <div className="bg-white border border-gray-200 rounded-lg p-4"> | |
| <h4 className="font-medium text-gray-900 mb-3">工作流配置</h4> | |
| <div className="space-y-3"> | |
| <div className="flex items-center justify-between"> | |
| <span className="text-sm text-gray-700">自动触发</span> | |
| <div className="w-10 h-6 bg-blue-600 rounded-full relative cursor-pointer"> | |
| <div className="w-4 h-4 bg-white rounded-full absolute right-1 top-1"></div> | |
| </div> | |
| </div> | |
| <div className="flex items-center justify-between"> | |
| <span className="text-sm text-gray-700">并行执行</span> | |
| <div className="w-10 h-6 bg-gray-300 rounded-full relative cursor-pointer"> | |
| <div className="w-4 h-4 bg-white rounded-full absolute left-1 top-1"></div> | |
| </div> | |
| </div> | |
| <div className="flex items-center justify-between"> | |
| <span className="text-sm text-gray-700">错误重试</span> | |
| <div className="w-10 h-6 bg-blue-600 rounded-full relative cursor-pointer"> | |
| <div className="w-4 h-4 bg-white rounded-full absolute right-1 top-1"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div className="bg-blue-50 border border-blue-200 rounded-lg p-4"> | |
| <div className="flex items-start space-x-3"> | |
| <div className="w-5 h-5 flex items-center justify-center mt-0.5"> | |
| <i className="ri-information-line text-blue-600"></i> | |
| </div> | |
| <div> | |
| <h4 className="font-medium text-blue-900 mb-1">使用提示</h4> | |
| <p className="text-sm text-blue-800"> | |
| 选择的工作流将与Agent集成,用户可以通过对话触发相应的自动化流程。建议选择与Agent功能相关的工作流。 | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } |