| '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> |
| ); |
| } |