feat(scheduling): rename 通知→干预, allow drill-in on intervened items
- Globally rename user-facing 通知 → 干预 (list badge, detail button, batch modal, CSV header, server response messages, db table comment) - 已干预 row in detail is now clickable — opens SwapPreview which shows a read-only summary plus a 取消干预 action (PATCH notify /:id with status=cancelled). Sending is blocked while already intervened. - Selected suggestion now follows the latest data snapshot so status changes from within the detail flow propagate immediately. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -177,11 +177,13 @@ export default function SchedulingModule() {
|
||||
useEffect(() => { loadData(); }, [loadData]);
|
||||
const handleNotifySuccess = useCallback(() => { loadData(); }, [loadData]);
|
||||
|
||||
// Close detail modal if selected suggestion is filtered out or no longer exists
|
||||
// Keep selectedSuggestion synced with latest data so candidate notification
|
||||
// status changes (登记 / 取消干预) propagate into the open detail modal.
|
||||
useEffect(() => {
|
||||
if (!selectedSuggestion || !data) return;
|
||||
const stillExists = data.suggestions.some(s => s.id === selectedSuggestion.id);
|
||||
if (!stillExists) setSelectedSuggestion(null);
|
||||
const fresh = data.suggestions.find(s => s.id === selectedSuggestion.id);
|
||||
if (!fresh) setSelectedSuggestion(null);
|
||||
else if (fresh !== selectedSuggestion) setSelectedSuggestion(fresh);
|
||||
}, [data, selectedSuggestion]);
|
||||
|
||||
const toggleSelect = useCallback((id: string) => {
|
||||
@@ -227,7 +229,7 @@ export default function SchedulingModule() {
|
||||
exitSelectMode();
|
||||
} catch (e) {
|
||||
console.error('batch notify failed:', e);
|
||||
setBatchResultMsg('批量通知失败,请重试');
|
||||
setBatchResultMsg('批量干预失败,请重试');
|
||||
} finally {
|
||||
setBatchInFlight(false);
|
||||
}
|
||||
@@ -534,7 +536,7 @@ export default function SchedulingModule() {
|
||||
disabled={selectedIds.size === 0}
|
||||
className="flex items-center gap-1.5 text-xs font-bold bg-blue-600 hover:bg-blue-500 disabled:bg-slate-700 disabled:text-slate-400 text-white px-3 py-1.5 rounded-lg cursor-pointer disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
<Send size={12} /> 批量通知
|
||||
<Send size={12} /> 批量干预
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -551,7 +553,7 @@ export default function SchedulingModule() {
|
||||
className="bg-white rounded-t-2xl sm:rounded-2xl shadow-2xl w-full sm:max-w-md overflow-hidden flex flex-col max-h-[80vh] sm:mx-4"
|
||||
>
|
||||
<div className="bg-slate-800 px-4 py-3 flex items-center justify-between flex-shrink-0">
|
||||
<span className="text-white font-bold text-sm">确认批量通知</span>
|
||||
<span className="text-white font-bold text-sm">确认批量干预</span>
|
||||
<button
|
||||
onClick={() => !batchInFlight && setShowBatchConfirm(false)}
|
||||
disabled={batchInFlight}
|
||||
@@ -562,7 +564,7 @@ export default function SchedulingModule() {
|
||||
</div>
|
||||
<div className="px-4 py-3 overflow-y-auto flex-1">
|
||||
<p className="text-xs text-slate-500 mb-3">
|
||||
将发送 <span className="font-bold text-slate-800">{batchItems.length}</span> 条替换通知,已排除无可用候选车的建议。
|
||||
将登记 <span className="font-bold text-slate-800">{batchItems.length}</span> 条干预,已排除无可用候选车的建议。
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
{batchItems.map(({ suggestion, candidate }) => (
|
||||
@@ -597,7 +599,7 @@ export default function SchedulingModule() {
|
||||
disabled={batchInFlight || batchItems.length === 0}
|
||||
className="flex-1 py-2 text-xs font-bold text-white bg-blue-600 hover:bg-blue-500 rounded-lg cursor-pointer disabled:opacity-50 transition-colors"
|
||||
>
|
||||
{batchInFlight ? '发送中...' : `确认发送 ${batchItems.length} 条`}
|
||||
{batchInFlight ? '登记中...' : `确认登记 ${batchItems.length} 条`}
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
Reference in New Issue
Block a user