8 changed files with 589 additions and 61 deletions
@ -0,0 +1,152 @@ |
|||
import React, { useState } from 'react'; |
|||
import { Button } from '@/components/ui/button'; |
|||
import { Card } from '@/components/ui/card'; |
|||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; |
|||
import { Badge } from '@/components/ui/badge'; |
|||
import { Input } from '@/components/ui/input'; |
|||
import { Plus, Search, Edit, Trash2, Eye } from 'lucide-react'; |
|||
import { useNavigate } from 'react-router-dom'; |
|||
|
|||
interface TestCase { |
|||
id: string; |
|||
name: string; |
|||
description: string; |
|||
status: 'active' | 'inactive' | 'draft'; |
|||
priority: 'high' | 'medium' | 'low'; |
|||
category: string; |
|||
createdBy: string; |
|||
createdAt: string; |
|||
stepsCount: number; |
|||
} |
|||
|
|||
const mockTestCases: TestCase[] = [ |
|||
{ |
|||
id: '1', |
|||
name: '用户登录测试', |
|||
description: '测试用户登录功能的正常流程和异常情况', |
|||
status: 'active', |
|||
priority: 'high', |
|||
category: '认证测试', |
|||
createdBy: '张三', |
|||
createdAt: '2024-01-15', |
|||
stepsCount: 5 |
|||
}, |
|||
{ |
|||
id: '2', |
|||
name: '设备连接测试', |
|||
description: '测试设备连接和断开连接的稳定性', |
|||
status: 'active', |
|||
priority: 'medium', |
|||
category: '设备测试', |
|||
createdBy: '李四', |
|||
createdAt: '2024-01-10', |
|||
stepsCount: 8 |
|||
} |
|||
]; |
|||
|
|||
export default function TestCasesListView() { |
|||
const navigate = useNavigate(); |
|||
const [testCases, setTestCases] = useState<TestCase[]>(mockTestCases); |
|||
const [searchTerm, setSearchTerm] = useState(''); |
|||
|
|||
const filteredTestCases = testCases.filter(testCase => |
|||
testCase.name.toLowerCase().includes(searchTerm.toLowerCase()) || |
|||
testCase.description.toLowerCase().includes(searchTerm.toLowerCase()) |
|||
); |
|||
|
|||
const getStatusBadge = (status: string) => { |
|||
const statusConfig = { |
|||
active: { color: 'bg-green-100 text-green-800', text: '激活' }, |
|||
inactive: { color: 'bg-gray-100 text-gray-800', text: '停用' }, |
|||
draft: { color: 'bg-yellow-100 text-yellow-800', text: '草稿' } |
|||
}; |
|||
const config = statusConfig[status as keyof typeof statusConfig]; |
|||
return <Badge className={config.color}>{config.text}</Badge>; |
|||
}; |
|||
|
|||
const getPriorityBadge = (priority: string) => { |
|||
const priorityConfig = { |
|||
high: { color: 'bg-red-100 text-red-800', text: '高' }, |
|||
medium: { color: 'bg-orange-100 text-orange-800', text: '中' }, |
|||
low: { color: 'bg-blue-100 text-blue-800', text: '低' } |
|||
}; |
|||
const config = priorityConfig[priority as keyof typeof priorityConfig]; |
|||
return <Badge className={config.color}>{config.text}</Badge>; |
|||
}; |
|||
|
|||
return ( |
|||
<div className="p-6 space-y-6"> |
|||
<div className="flex justify-between items-center"> |
|||
<div> |
|||
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">测试用例管理</h1> |
|||
<p className="text-gray-600 dark:text-gray-400 mt-1">管理和查看所有测试用例</p> |
|||
</div> |
|||
<Button onClick={() => navigate('/dashboard/testcases/create')} className="flex items-center gap-2"> |
|||
<Plus className="w-4 h-4" /> |
|||
创建测试用例 |
|||
</Button> |
|||
</div> |
|||
|
|||
<Card className="p-4"> |
|||
<div className="flex gap-4 items-center"> |
|||
<div className="flex-1 relative"> |
|||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" /> |
|||
<Input |
|||
placeholder="搜索测试用例名称或描述..." |
|||
value={searchTerm} |
|||
onChange={(e) => setSearchTerm(e.target.value)} |
|||
className="pl-10" |
|||
/> |
|||
</div> |
|||
</div> |
|||
</Card> |
|||
|
|||
<Card> |
|||
<div className="overflow-x-auto"> |
|||
<Table> |
|||
<TableHeader> |
|||
<TableRow> |
|||
<TableHead>名称</TableHead> |
|||
<TableHead>描述</TableHead> |
|||
<TableHead>状态</TableHead> |
|||
<TableHead>优先级</TableHead> |
|||
<TableHead>分类</TableHead> |
|||
<TableHead>步骤数</TableHead> |
|||
<TableHead>创建者</TableHead> |
|||
<TableHead>创建时间</TableHead> |
|||
<TableHead>操作</TableHead> |
|||
</TableRow> |
|||
</TableHeader> |
|||
<TableBody> |
|||
{filteredTestCases.map((testCase) => ( |
|||
<TableRow key={testCase.id}> |
|||
<TableCell className="font-medium">{testCase.name}</TableCell> |
|||
<TableCell className="max-w-xs truncate">{testCase.description}</TableCell> |
|||
<TableCell>{getStatusBadge(testCase.status)}</TableCell> |
|||
<TableCell>{getPriorityBadge(testCase.priority)}</TableCell> |
|||
<TableCell>{testCase.category}</TableCell> |
|||
<TableCell>{testCase.stepsCount}</TableCell> |
|||
<TableCell>{testCase.createdBy}</TableCell> |
|||
<TableCell>{testCase.createdAt}</TableCell> |
|||
<TableCell> |
|||
<div className="flex gap-2"> |
|||
<Button variant="ghost" size="sm" className="p-1"> |
|||
<Eye className="w-4 h-4" /> |
|||
</Button> |
|||
<Button variant="ghost" size="sm" className="p-1"> |
|||
<Edit className="w-4 h-4" /> |
|||
</Button> |
|||
<Button variant="ghost" size="sm" className="p-1 text-red-600 hover:text-red-700"> |
|||
<Trash2 className="w-4 h-4" /> |
|||
</Button> |
|||
</div> |
|||
</TableCell> |
|||
</TableRow> |
|||
))} |
|||
</TableBody> |
|||
</Table> |
|||
</div> |
|||
</Card> |
|||
</div> |
|||
); |
|||
} |
|||
Loading…
Reference in new issue