diff --git a/src/modules/scheduling/SwapPreview.tsx b/src/modules/scheduling/SwapPreview.tsx
index cd70d03..83c6aac 100644
--- a/src/modules/scheduling/SwapPreview.tsx
+++ b/src/modules/scheduling/SwapPreview.tsx
@@ -1,6 +1,5 @@
import { useState } from 'react';
-import { ArrowDown, CheckCircle, Send, X } from 'lucide-react';
-import { motion } from 'motion/react';
+import { ArrowDownUp, CheckCircle, Send, X } from 'lucide-react';
import { sendNotify } from './api';
import type { SchedulingSuggestion, CandidateVehicle } from './types';
import Blur from '../../components/Blur';
@@ -25,150 +24,108 @@ export default function SwapPreview({ suggestion: s, candidate: c, onClose, onSu
const [sending, setSending] = useState(false);
const [sent, setSent] = useState(false);
const v = s.currentVehicle;
- const isRescue = s.type === 'rescue_hopeless';
const handleSend = async () => {
if (sending || sent) return;
setSending(true);
try {
- const result = await sendNotify({
- suggestionId: s.id,
- currentPlate: v.plateNumber,
- candidatePlate: c.plateNumber,
- });
- if (result.success) {
- setSent(true);
- onSuccess();
- } else {
- alert(result.message || '发送失败');
- }
- } catch {
- alert('网络错误,请重试');
- } finally {
- setSending(false);
- }
+ const result = await sendNotify({ suggestionId: s.id, currentPlate: v.plateNumber, candidatePlate: c.plateNumber });
+ if (result.success) { setSent(true); onSuccess(); } else { alert(result.message || '发送失败'); }
+ } catch { alert('网络错误'); } finally { setSending(false); }
};
return (
-
- {/* Top bar */}
-
+
+ {/* Header */}
+
车辆替换方案
-
+
- {/* Content — screenshot-friendly, no scroll needed */}
-
+ {/* Content */}
+
+
- {/* Swap type badge */}
-
- {isRescue ? '里程低·换走此车' : '里程高·换下此车'}
-
-
- {/* === Swap Diagram === */}
-
-
- {/* Current vehicle (换下/换走) */}
-
-
- {isRescue ? '换走车辆' : '换下车辆'}
+ {/* === Swap Cards === */}
+
+ {/* Current vehicle */}
+
+
+
+
{v.plateNumber}
+
{v.vehicleType} · {v.targetName}
+
+
+
{fmtKm(v.currentYearMileage)}km
+
考核 {fmtKm(v.yearTarget)} km
+
+
+
+ {v.customer || '-'}
+ 日均 {Math.round(v.customerAvgDaily)}
+ 完成 = 1 ? 'text-emerald-600' : 'text-rose-500'}>{fmtRate(v.completionRate)}
+
-
+
+ {/* Arrow bridge */}
+
+
+ {/* Replacement vehicle */}
+
+
+
+
{c.plateNumber}
+
{c.vehicleType} · {c.targetName || '库存'} · {c.region}
+
+
+
{fmtKm(c.totalMileage)}km
+
考核 {c.yearTarget ? fmtKm(c.yearTarget) : '-'} km
+
+
+
+ 缺口 {fmtKm(c.mileageGap)}
+
+
+
+
+ {/* === Result === */}
+
+
替换后预测
+
-
{v.plateNumber}
-
{v.vehicleType} · {v.targetName}
+
预测年终里程
+
{fmtKm(c.predictedAfterSwap)} km
-
-
{fmtKm(v.currentYearMileage)} km
-
考核 {fmtKm(v.yearTarget)} km
-
-
-
- 客户 {v.customer || '-'}
- 日均 {Math.round(v.customerAvgDaily)} km
- 完成 = 1 ? 'text-emerald-600' : 'text-rose-500'}>{fmtRate(v.completionRate)}
-
-
-
- {/* Arrow */}
-
-
- {/* Replacement vehicle (换上) */}
-
-
- 换上车辆
-
-
-
{c.plateNumber}
-
{c.vehicleType} · {c.targetName || '库存'}
+
考核目标
+
{c.yearTarget ? fmtKm(c.yearTarget) : '-'} km
-
-
{fmtKm(c.totalMileage)} km
-
考核 {c.yearTarget ? fmtKm(c.yearTarget) : '-'} km
-
-
-
- 缺口 {fmtKm(c.mileageGap)} km
- 区域 {c.region}
-
-
-
-
- {/* === Reason === */}
-
-
- {/* === Conclusion === */}
-
-
替换后预测
-
-
- {c.plateNumber} 换到客户「{v.customer || '-'}」后
-
-
-
-
-
预测年终
-
{fmtKm(c.predictedAfterSwap)} km
-
-
-
考核目标
-
{c.yearTarget ? fmtKm(c.yearTarget) : '-'} km
-
-
-
结论
-
+
{c.canQualifyAfterSwap ? '可达标' : '需关注'}
+
- {/* Bottom action */}
-
-
+ {/* Bottom */}
+
+
+
+
);