- Add 调度记录 modal: lists notifications by status, supports 标记已执行 (with
after-mileage + notes) and 取消 for open records
- Add CSV export of filtered suggestions (UTF-8 BOM for Excel); top candidate
per row picked by same-region > can-qualify preference
- Compute customer 7-day average alongside 30-day baseline in a single query;
show trend indicator (up/down/flat) next to 客户日均 in list and detail card
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add tab_scheduling_notifications table with bootstrap via ensureSchedulingTables()
- Notify endpoint rewritten: dedup by (suggestion_id, candidate_plate), history list, PATCH /:id for execute/cancel lifecycle
- Batch notify endpoint returns success/skipped/failed counts
- Suggestions response now carries notificationId + notificationStatus per candidate (joined from active-notification map)
- UI: select mode with checkboxes, floating action bar, confirmation modal listing each swap; already-notified items are dimmed and skipped
- Detail view badges show sent/executed state, preventing duplicate notify
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Extract shared types to src/shared/scheduling/types.ts (client/server both re-export)
- Convert SchedulingSuggestion.reason from string to structured { lines, conclusion }
- Remove hard region filter; algorithm keeps cross-region candidates with isSameRegion flag
- SuggestionDetail renders same-region vs cross-region sections with a divider
- Close detail modal when selected suggestion no longer exists in data
- Unify estimatedGain definition (strict canQualifyAfterSwap) between algorithm and API layers
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Different assessment targets have different end dates. Previously all
candidates used the current vehicle's daysLeft, causing wrong predictions.
Now each inventory vehicle computes its own daysLeft from its assessment
target's current_year_assessment_end_date. predictedAfterSwap uses the
candidate's own daysLeft instead of the current vehicle's.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove type badge, reason section — too verbose
- Two clean white cards connected by arrow (swap diagram)
- Result section: predicted mileage, target, conclusion badge
- Tighter spacing, no redundant labels
- Professional tone, no childish wording
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
For rescue_hopeless (换走) scenario, completely rethought candidate logic:
Before: showed biggest-gap candidates (0 mileage) → pointless, customer can't
drive them to target
After: prioritize candidates where customer's remaining driving can push them
over the target line (canQualifyAfterSwap), sorted by smallest gap first
Example: customer drives 178km/day × 57 days = ~1万km remaining.
- 粤AGR6869 (缺口 1990km) → 换后 3.8万, 可达标 ✅ (shown first)
- 浙FF58720 (缺口 6万km) → 换后 1万, 远不达标 (no longer shown first)
Also updated reason text to explain the math:
"该客户剩余57天还能跑约1万km,足以帮缺口小的车冲线"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Full-page skeleton on initial load: card placeholders + list row placeholders
- List skeleton on refresh: 6 rows with pulse animation
- Skeleton blocks match actual layout (color bar, plate, badges, info line)
- Uses Tailwind animate-pulse for smooth loading effect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Customer name in list items: truncate with max-w-[40%]
- Daily km and completion rate: flex-shrink-0 to stay on same line
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add department and manager fields to backend types and suggestions API
- Add department/manager to advanced filter panel
- Refine card colors: orange (换下) / blue (换走) / dark slate (全部)
- Selected card uses solid bg color, inactive uses gradient
- Batch pills use dark slate, confirm button uses dark slate
- Background changed to #F0F4F8 for subtle cool tone
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Filter icon in list header with active count badge
- Expandable filter panel: plate search, region select, vehicle type select, customer select
- FilterSelect component with search for long option lists
- Active filter tags shown as removable pills below header
- Temp/confirmed filter pattern (edit → confirm/cancel)
- Result count displayed when filters active
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Modal header: unified dark slate-800 with directional icon (↓ rescue, ↑ release)
- Modal click-outside to close
- Candidate metrics: table-style with bg-slate-50 + dividers, more scannable
- Send button: dark slate instead of blue (avoids color overload)
- Reason section: warm amber accent
- Consistent font sizing and spacing throughout
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Cards filter suggestions by type (已达标/无望达标/全部)
- Toggle: click active card again to reset to all
- Default: white bg + gray border; active: colored bg + ring
- Batch selector: dark pills instead of blue
- Refresh button moved into list header
- Reset type filter when switching batch
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add currentYearMileage to SchedulingVehicleInfo (backend + frontend)
- Compute completionRate as currentYearMileage/yearTarget (year-based)
instead of using overall completion_rate from DB
- Display "本年已跑" instead of "累计" in detail modal
- Fix reason text to show year completion rate
Before: 累计 4.6万, 考核 3.0万, 完成率 12.1% (mismatched periods)
After: 本年已跑 8.3万, 考核 3.0万, 完成率 275% (consistent year-based)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Summary cards: white bg + color border, remove icons, more compact
- SuggestionList: replace badge stacking with compact 2-line layout,
use color bars for priority, fix completion rate format (0.16 → 16.4%)
- SuggestionDetail: bottom-sheet on mobile, compact inline metrics
instead of grid cards, reduce vertical space per candidate
- Follows ui-ux-pro-max Data-Dense Dashboard guidelines
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>