|
|
@@ -1,5 +1,5 @@
|
|
|
import React, { useState, useEffect } from 'react';
|
|
|
-import { Activity, Package, Users, TrendingUp, Clock, ArrowRight } from 'lucide-react';
|
|
|
+import { Activity, Package, Users, TrendingUp, Clock, Wrench, RefreshCw, Settings } from 'lucide-react';
|
|
|
import { cockpitApi, CockpitStatisticsVO, JobVO } from '../api/cockpit';
|
|
|
import { toast } from 'sonner';
|
|
|
|
|
|
@@ -208,72 +208,102 @@ export default function CockpitDashboard() {
|
|
|
{/* 正在进行作业列表 */}
|
|
|
{statistics.jobList && statistics.jobList.length > 0 && (
|
|
|
<div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm p-6">
|
|
|
- <div className="flex items-center justify-between mb-6">
|
|
|
+ <div className="mb-6">
|
|
|
<h3 className="text-lg font-semibold text-gray-900">正在进行作业</h3>
|
|
|
- <button className="text-sm text-blue-600 hover:text-blue-700 flex items-center gap-1 group">
|
|
|
- <span>查看全部</span>
|
|
|
- <ArrowRight className="w-4 h-4 group-hover:translate-x-0.5 transition-transform" />
|
|
|
- </button>
|
|
|
</div>
|
|
|
- <div className="space-y-3">
|
|
|
- {statistics.jobList.slice(0, 5).map((job: JobVO) => {
|
|
|
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
|
+ {statistics.jobList.slice(0, 6).map((job: JobVO) => {
|
|
|
// 从ticketName中提取作业类型
|
|
|
const ticketName = job.ticketName || '';
|
|
|
let jobType = '未知';
|
|
|
let typeColor = 'gray';
|
|
|
+ let typeIcon = Settings;
|
|
|
if (ticketName.includes('换产')) {
|
|
|
jobType = '换产';
|
|
|
typeColor = 'blue';
|
|
|
+ typeIcon = RefreshCw;
|
|
|
} else if (ticketName.includes('维修')) {
|
|
|
jobType = '维修';
|
|
|
typeColor = 'red';
|
|
|
+ typeIcon = Wrench;
|
|
|
} else if (ticketName.includes('PM')) {
|
|
|
jobType = 'PM';
|
|
|
typeColor = 'green';
|
|
|
+ typeIcon = Settings;
|
|
|
}
|
|
|
|
|
|
// 从ticketName中提取日期(最后一部分)
|
|
|
const dateMatch = ticketName.match(/-(\d{4}-\d{2}-\d{2})/);
|
|
|
const dateStr = dateMatch ? dateMatch[1].split('-').slice(1).join('-') : '';
|
|
|
|
|
|
+ const IconComponent = typeIcon;
|
|
|
+
|
|
|
return (
|
|
|
<div
|
|
|
key={job.ticketId}
|
|
|
- className="p-4 bg-gradient-to-r from-blue-50/30 to-transparent rounded-xl transition-all cursor-pointer border border-blue-100/50 hover:border-blue-200/60 hover:from-blue-50/50 group"
|
|
|
+ className="relative p-5 bg-gradient-to-br from-white to-gray-50/50 rounded-xl border border-gray-200/60 hover:border-blue-300/60 transition-all cursor-pointer group shadow-sm hover:shadow-md"
|
|
|
>
|
|
|
- <div className="flex items-start justify-between mb-2">
|
|
|
+ {/* 状态指示器 */}
|
|
|
+ <div className="absolute top-4 right-4">
|
|
|
+ <div className="w-2.5 h-2.5 bg-blue-500 rounded-full animate-pulse"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 图标和类型 */}
|
|
|
+ <div className="flex items-start gap-3 mb-4">
|
|
|
+ <div className={`w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0 ${
|
|
|
+ typeColor === 'blue' ? 'bg-blue-100' :
|
|
|
+ typeColor === 'red' ? 'bg-red-100' :
|
|
|
+ typeColor === 'green' ? 'bg-green-100' :
|
|
|
+ 'bg-gray-100'
|
|
|
+ }`}>
|
|
|
+ <IconComponent className={`w-5 h-5 ${
|
|
|
+ typeColor === 'blue' ? 'text-blue-600' :
|
|
|
+ typeColor === 'red' ? 'text-red-600' :
|
|
|
+ typeColor === 'green' ? 'text-green-600' :
|
|
|
+ 'text-gray-600'
|
|
|
+ }`} />
|
|
|
+ </div>
|
|
|
<div className="flex-1 min-w-0">
|
|
|
- <div className="flex items-center gap-2 mb-2">
|
|
|
- <div className="w-2 h-2 bg-blue-500 rounded-full animate-pulse flex-shrink-0"></div>
|
|
|
- <div className="text-sm font-medium text-gray-900 truncate">
|
|
|
- #{job.ticketId} {job.ticketName}
|
|
|
- </div>
|
|
|
+ <div className={`inline-flex items-center px-2.5 py-1 rounded-md text-xs font-medium mb-2 ${
|
|
|
+ typeColor === 'blue' ? 'bg-blue-50 text-blue-700' :
|
|
|
+ typeColor === 'red' ? 'bg-red-50 text-red-700' :
|
|
|
+ typeColor === 'green' ? 'bg-green-50 text-green-700' :
|
|
|
+ 'bg-gray-50 text-gray-700'
|
|
|
+ }`}>
|
|
|
+ {jobType}
|
|
|
</div>
|
|
|
- <div className="flex items-center gap-4 text-xs text-gray-500">
|
|
|
- <span className={`px-2 py-1 rounded-lg ${
|
|
|
- typeColor === 'blue' ? 'bg-blue-50 text-blue-600' :
|
|
|
- typeColor === 'red' ? 'bg-red-50 text-red-600' :
|
|
|
- typeColor === 'green' ? 'bg-green-50 text-green-600' :
|
|
|
- 'bg-gray-50 text-gray-600'
|
|
|
- }`}>
|
|
|
- {jobType}
|
|
|
- </span>
|
|
|
- <span className="flex items-center gap-1">
|
|
|
- <div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
|
|
- 工作站: {job.workstationName || '未知'}
|
|
|
- </span>
|
|
|
- {dateStr && (
|
|
|
- <span className="flex items-center gap-1">
|
|
|
- <Clock className="w-3 h-3" />
|
|
|
- {dateStr}
|
|
|
- </span>
|
|
|
- )}
|
|
|
+ <div className="text-sm font-semibold text-gray-900 line-clamp-2 leading-snug">
|
|
|
+ {job.ticketName}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <button className="ml-4 px-4 py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700 transition-colors whitespace-nowrap">
|
|
|
- 查看详情 >
|
|
|
- </button>
|
|
|
</div>
|
|
|
+
|
|
|
+ {/* 作业编号 */}
|
|
|
+ <div className="mb-4">
|
|
|
+ <div className="text-xs text-gray-500 mb-1">作业编号</div>
|
|
|
+ <div className="text-sm font-mono text-gray-700 bg-gray-50 px-2 py-1 rounded border border-gray-200 inline-block">
|
|
|
+ #{job.ticketId}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 详细信息 */}
|
|
|
+ <div className="space-y-2.5 pt-4 border-t border-gray-100">
|
|
|
+ <div className="flex items-center gap-2 text-xs text-gray-600">
|
|
|
+ <div className="w-1.5 h-1.5 bg-blue-400 rounded-full"></div>
|
|
|
+ <span className="font-medium">工作站:</span>
|
|
|
+ <span className="text-gray-900">{job.workstationName || '未知'}</span>
|
|
|
+ </div>
|
|
|
+ {dateStr && (
|
|
|
+ <div className="flex items-center gap-2 text-xs text-gray-600">
|
|
|
+ <Clock className="w-3.5 h-3.5 text-gray-400" />
|
|
|
+ <span className="font-medium">日期:</span>
|
|
|
+ <span className="text-gray-900">{dateStr}</span>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 悬停效果装饰 */}
|
|
|
+ <div className="absolute inset-0 rounded-xl bg-gradient-to-br from-blue-500/0 to-blue-500/0 group-hover:from-blue-500/5 group-hover:to-transparent transition-all pointer-events-none"></div>
|
|
|
</div>
|
|
|
);
|
|
|
})}
|