204 lines
12 KiB
TypeScript
204 lines
12 KiB
TypeScript
import React from 'react';
|
|
import { ChevronDown, ChevronRight } from 'lucide-react';
|
|
import { AnimatePresence, motion } from 'motion/react';
|
|
import type { AssetSummarySectionProps } from './types';
|
|
|
|
export function AssetSummaryDesktopTable({
|
|
processedData,
|
|
theme,
|
|
expandedAssetTypes,
|
|
toggleAssetType,
|
|
expandedModels,
|
|
toggleModel,
|
|
setVehicleSelection: setShowPlateNumbers,
|
|
}: AssetSummarySectionProps) {
|
|
return (
|
|
<div className="hidden lg:block overflow-x-auto">
|
|
<table className="w-full text-left border-collapse table-fixed min-w-[1300px]">
|
|
<thead>
|
|
<tr className="bg-gray-50 text-[11px] text-gray-500 uppercase tracking-wider border-b border-gray-100">
|
|
<th className="p-3 font-semibold border-r border-gray-100 w-24">车型</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 w-48">品牌型号</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center bg-blue-50/30 w-24">车辆总资产</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center w-24">库存总数</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center w-24">库存-江浙沪</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center w-24">库存-广东</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center w-24">库存-北京</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center w-24">库存-新疆</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center w-24">库存-其他</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center text-amber-600 w-24">异动</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center w-24">待交车</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center bg-green-50/30 w-24">当前在运营</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center bg-blue-50/20 w-24">本周交车</th>
|
|
<th className="p-3 font-semibold border-r border-gray-100 text-center bg-orange-50/20 w-24">本周还车</th>
|
|
<th className="p-3 font-semibold text-center bg-purple-50/20 w-24">本周替换</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="text-xs">
|
|
{processedData.map((typeGroup) => (
|
|
<React.Fragment key={typeGroup.type}>
|
|
{/* Category Header Row */}
|
|
<tr className={`border-b border-gray-100 cursor-pointer transition-all ${
|
|
theme === 'vibrant' ? 'bg-blue-600 text-white hover:bg-blue-700' :
|
|
theme === 'minimal' ? 'bg-white border-l-4 border-blue-500 hover:bg-gray-50' :
|
|
'bg-blue-50/50 hover:bg-blue-50 transition-colors'
|
|
}`}
|
|
onClick={() => toggleAssetType(typeGroup.type)}>
|
|
<td colSpan={15} className={`p-3 font-bold ${theme === 'vibrant' ? 'text-white' : 'text-blue-700'}`}>
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-2">
|
|
{expandedAssetTypes.has(typeGroup.type) ?
|
|
<ChevronDown size={16} className={theme === 'vibrant' ? 'text-white' : 'text-blue-500'} /> :
|
|
<ChevronRight size={16} className={theme === 'vibrant' ? 'text-white/70' : 'text-gray-400'} />
|
|
}
|
|
<span>{typeGroup.type}</span>
|
|
</div>
|
|
<div className={`flex gap-6 text-[11px] font-normal mr-4 ${theme === 'vibrant' ? 'text-white/80' : 'text-gray-500'}`}>
|
|
<span>资产 <span className={theme === 'vibrant' ? 'font-bold text-white' : 'font-bold text-gray-700'}>{typeGroup.totalAssets}</span></span>
|
|
<span>库存 <span className={theme === 'vibrant' ? 'font-bold text-white' : 'font-bold text-blue-600'}>{typeGroup.totalInventory}</span></span>
|
|
<span>异动 <span className="font-bold">{typeGroup.totalAbnormal}</span></span>
|
|
<span>运营 <span className={theme === 'vibrant' ? 'font-bold text-white' : 'font-bold text-green-600'}>{typeGroup.totalOperating}</span></span>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<AnimatePresence>
|
|
{expandedAssetTypes.has(typeGroup.type) && typeGroup.models.map((model) => (
|
|
<React.Fragment key={model.model}>
|
|
<motion.tr
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
className={`border-b border-gray-50 hover:bg-gray-50/50 transition-colors cursor-pointer ${expandedModels.has(model.model) ? 'bg-blue-50/10' : ''}`}
|
|
onClick={() => toggleModel(model.model)}
|
|
>
|
|
<td className="p-3 border-r border-gray-100 text-gray-300 text-center italic">{typeGroup.type}</td>
|
|
<td className="p-3 border-r border-gray-100 flex items-center justify-between gap-2">
|
|
<div className="flex items-center gap-2">
|
|
{expandedModels.has(model.model) ? <ChevronDown size={14} className="text-blue-500" /> : <ChevronRight size={14} className="text-gray-300" />}
|
|
<span className={expandedModels.has(model.model) ? 'font-bold text-blue-700' : ''}>{model.model}</span>
|
|
</div>
|
|
<div className="flex gap-3 text-[9px] font-normal text-gray-400">
|
|
<span>资产 <span className="font-bold text-gray-600">{model.total}</span></span>
|
|
<span>库存 <span className="font-bold text-blue-500">{model.inventory}</span></span>
|
|
<span>运营 <span className="font-bold text-green-500">{model.operating}</span></span>
|
|
</div>
|
|
</td>
|
|
<td className="p-3 text-center border-r border-gray-100 font-medium">
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', source: 'asset', title: model.model });
|
|
}}
|
|
className="text-blue-500 hover:underline font-medium"
|
|
>
|
|
{model.total}
|
|
</button>
|
|
</td>
|
|
<td className="p-3 text-center border-r border-gray-100 font-medium">
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', category: 'Inventory', source: 'asset', title: `${model.model} - 库存` });
|
|
}}
|
|
className="text-blue-500 hover:underline font-medium"
|
|
>
|
|
{model.inventory}
|
|
</button>
|
|
</td>
|
|
{['嘉兴', '广东', '北京', '新疆', '其他'].map(reg => (
|
|
<td key={reg} className="p-3 text-center border-r border-gray-100">
|
|
{model.inventoryRegions[reg] > 0 ? (
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: reg, category: 'Inventory', source: 'asset', title: `${model.model} - ${reg} 库存` });
|
|
}}
|
|
className="text-blue-500 hover:underline font-medium"
|
|
>
|
|
{model.inventoryRegions[reg]}
|
|
</button>
|
|
) : ''}
|
|
</td>
|
|
))}
|
|
<td className="p-3 text-center border-r border-gray-100">
|
|
<button type="button" className="font-bold text-amber-600 hover:underline"
|
|
onClick={(e) => { e.stopPropagation(); setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', category: 'Abnormal', source: 'asset', title: `${model.model} - 异动` }); }}>
|
|
{model.abnormal}
|
|
</button>
|
|
</td>
|
|
<td className="p-3 text-center border-r border-gray-100">
|
|
{model.pending > 0 ? (
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', category: 'Pending', source: 'asset', title: `${model.model} - 待交车` });
|
|
}}
|
|
className="text-blue-500 hover:underline font-medium"
|
|
>
|
|
{model.pending}
|
|
</button>
|
|
) : model.pending}
|
|
</td>
|
|
<td className="p-3 text-center border-r border-gray-100 text-green-600 font-bold bg-green-50/10">
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', category: 'Operating', source: 'asset', title: `${model.model} - 在运营` });
|
|
}}
|
|
className="text-green-600 hover:underline font-bold"
|
|
>
|
|
{model.operating}
|
|
</button>
|
|
</td>
|
|
<td className="p-3 text-center border-r border-gray-100 text-blue-600 bg-blue-50/5">
|
|
{model.weeklyDelivered > 0 ? (
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', category: 'Delivered', source: 'asset', title: `${model.model} - 本周交车` });
|
|
}}
|
|
className="text-blue-500 hover:underline font-medium"
|
|
>
|
|
{model.weeklyDelivered}
|
|
</button>
|
|
) : model.weeklyDelivered}
|
|
</td>
|
|
<td className="p-3 text-center border-r border-gray-100 text-orange-600 bg-orange-50/5">
|
|
{model.weeklyReturned > 0 ? (
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', category: 'Returned', source: 'asset', title: `${model.model} - 本周还车` });
|
|
}}
|
|
className="text-blue-500 hover:underline font-medium"
|
|
>
|
|
{model.weeklyReturned}
|
|
</button>
|
|
) : model.weeklyReturned}
|
|
</td>
|
|
<td className="p-3 text-center text-purple-600 bg-purple-50/5 font-medium">
|
|
{model.weeklyReplaced > 0 ? (
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setShowPlateNumbers({ batch: 'All', model: model.model, location: 'All', category: 'Replaced', source: 'asset', title: `${model.model} - 本周替换` });
|
|
}}
|
|
className="text-blue-500 hover:underline font-medium"
|
|
>
|
|
{model.weeklyReplaced}
|
|
</button>
|
|
) : model.weeklyReplaced}
|
|
</td>
|
|
</motion.tr>
|
|
</React.Fragment>
|
|
))}
|
|
</AnimatePresence>
|
|
</React.Fragment>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
}
|