fix(assets): restore classic UI while retaining inventory subsets and AI
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user