# Admin Scheduling Flow Diagram ## Component Architecture ``` ┌─────────────────────────────────────────────────────────┐ │ Admin Dashboard │ │ (pages/admin/index.vue) │ │ │ │ 📅 排课设置 🔧 临时调整 👥 会员 📋 订单 💳 卡 🏢 工作室 └─────────────────────────────────────────────────────────┘ │ └─► 📅 排课设置 (Week Template) └─────────────────────────────────────────┐ │ pages/admin/week-template.vue │ │ ================================ │ │ │ │ 1. Fetch Templates (onMounted) │ │ └─ GET /admin/week-template │ │ │ │ 2. Display grouped by day (Mon-Sun) │ │ │ │ 3. Add/Edit/Delete/Toggle locally │ │ └─ isDirty flag = true │ │ │ │ 4. Save All Changes (bottom bar) │ │ └─ PUT /admin/week-template │ │ (Full template array) │ │ │ │ 5. Backend transaction: │ │ - DELETE all templates │ │ - CREATE new templates │ └────────────────────────────────────────┘ └─► 🔧 临时调整 (Slot Adjustment - 3 Tabs) └─────────────────────────────────────────┐ │ pages/admin/slot-adjust.vue │ │ ================================ │ │ │ │ TAB 0: 新增时段 (Add Manual Slot) │ │ ├─ Date picker │ │ ├─ Time pickers │ │ ├─ Capacity input │ │ └─ POST /admin/time-slot/manual │ │ └─ Creates slot with source=MANUAL │ │ │ │ TAB 1: 关闭时段 (Close Slots) │ │ ├─ Date picker │ │ ├─ Fetch slots for date │ │ │ └─ GET /admin/time-slots?date=XXX │ │ ├─ Display with status badges │ │ │ (OPEN/FULL/CLOSED) │ │ └─ PUT /admin/time-slot/:id/close │ │ │ │ TAB 2: 批量生成 (Batch Generate) │ │ ├─ Start/end date pickers │ │ ├─ POST /admin/generate-slots │ │ └─ Backend: │ │ 1. Fetch active WeekTemplates │ │ 2. For each day in range: │ │ - Get ISO weekday (1-7) │ │ - Find matching templates │ │ - Create TimeSlot records │ │ 3. Returns { count: N } │ └────────────────────────────────────────┘ ``` ## Data Flow: Template → Slots ``` ┌──────────────────────────────────────────────────────────────────┐ │ ADMIN TEMPLATE SETUP │ │ (weeks/admin/week-template.vue) │ └──────────────────────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────┐ │ Admin configures templates: │ │ │ │ 周一: 09:00-10:00 (10 ppl) │ │ 周一: 18:00-19:00 (8 ppl) │ │ 周三: 10:00-11:00 (12 ppl) │ │ 周五: 18:00-20:00 (15 ppl) │ └───────────────────────────────────┘ │ ▼ ┌───────────────────────────────────┐ │ PUT /admin/week-template │ │ (All templates replaced) │ └───────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ Backend: Delete all, Create new (atomic) │ └────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ Scheduler (nightly cron or manual trigger)│ │ POST /admin/generate-slots (14 days) │ └────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ SlotGeneratorService.generateSlots() │ │ │ │ For each active template: │ │ For date in next 14 days: │ │ If template.dayOfWeek == date.dayOfWeek: │ CREATE TimeSlot { │ │ date, startTime, endTime, │ │ capacity, source=TEMPLATE, │ │ templateId │ │ } │ └────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ GENERATED TIME SLOTS │ │ │ │ 2026-04-06 (Mon): │ │ 09:00-10:00 (10 ppl, OPEN) │ │ 18:00-19:00 (8 ppl, OPEN) │ │ │ │ 2026-04-08 (Wed): │ │ 10:00-11:00 (12 ppl, OPEN) │ │ │ │ 2026-04-11 (Fri): │ │ 18:00-20:00 (15 ppl, OPEN) │ │ ... (more dates) │ └────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ Members can book available slots │ │ GET /time-slot/available?date=YYYY-MM-DD └────────────────────────────────────────────┘ ``` ## State Management ### Component State (week-template.vue) ```typescript templates: LocalTemplate[] ◄─ Main data array loading: boolean ◄─ Fetch state saving: boolean ◄─ Save state isDirty: boolean ◄─ "Save bar" trigger showModal: boolean ◄─ Modal visibility editTarget: LocalTemplate | null ◄─ Which template is being edited form: { ◄─ Modal form data dayIdx: number startTime: string endTime: string capacityStr: string } grouped: Computed> ◄─ Grouped by dayOfWeek ``` ### Store State (stores/admin.ts) ```typescript weekTemplates: WeekTemplate[] ◄─ Cached from server cardTypes: CardType[] studioConfig: StudioConfig | null // ...other admin state ``` ## API Endpoints Summary ### Week Templates ``` GET /admin/week-template Fetch all templates PUT /admin/week-template Replace all templates ``` ### Time Slots ``` GET /admin/time-slots?date=YYYY-MM-DD Fetch slots for date POST /admin/time-slot/manual Create manual slot PUT /admin/time-slot/:id/close Close a slot POST /admin/generate-slots Generate slots from templates ``` ### Public Endpoints ``` GET /time-slot/available?date=YYYY-MM-DD For members GET /time-slot/:id For members ``` ## Entity Relationships ``` ┌─────────────────────┐ │ WeekTemplate │ ├─────────────────────┤ │ id │ │ dayOfWeek (1-7) │ │ startTime │ │ endTime │ │ capacity │ │ isActive │ └─────────────────────┘ │ (1:N) │ ▼ ┌─────────────────────┐ ┌──────────────────┐ │ TimeSlot │ │ Booking (M:1) │ ├─────────────────────┤ ├──────────────────┤ │ id │◄─────│ timeSlotId │ │ date │ │ userId │ │ startTime │ │ status │ │ endTime │ └──────────────────┘ │ capacity │ │ bookedCount │ │ status │ │ source (TEMPLATE/ │ │ MANUAL) │ │ templateId (FK) │ └─────────────────────┘ ``` ## Weekday Mapping ### Frontend Picker (dayOptions) ``` Index 0: 周一 (Monday) ──► dayOfWeek = 1 Index 1: 周二 (Tuesday) ──► dayOfWeek = 2 Index 2: 周三 (Wednesday) ──► dayOfWeek = 3 Index 3: 周四 (Thursday) ──► dayOfWeek = 4 Index 4: 周五 (Friday) ──► dayOfWeek = 5 Index 5: 周六 (Saturday) ──► dayOfWeek = 6 Index 6: 周日 (Sunday) ──► dayOfWeek = 7 ``` ### Backend Conversion (slot-generator.service.ts) ```typescript JS getDay(): 0=Sun, 1=Mon, 2=Tue, ..., 6=Sat │ ▼ toIsoWeekday() │ ISO weekday: 1=Mon, 2=Tue, ..., 7=Sun ``` ## Timeline Example ``` TODAY: 2026-04-05 (Sunday) Admin actions: 1. Sets up weekly templates for Mon-Fri 2. Taps "保存全部更改" 3. PUT /admin/week-template sent Backend scheduler (daily at midnight): 4. Runs generateSlots(14) 5. Tomorrow is 2026-04-06 (Monday) 6. Generates slots for Apr 6-19 (next 14 days) 7. Creates TimeSlots based on active templates: Generated slots: 2026-04-06 (Mon): 09:00-10:00, 18:00-19:00 2026-04-07 (Tue): (none if no templates) 2026-04-08 (Wed): 10:00-11:00 2026-04-09 (Thu): (none if no templates) 2026-04-10 (Fri): 18:00-20:00 2026-04-11 (Sat): (none - weekend) 2026-04-12 (Sun): (none - weekend) ...repeats until 2026-04-19 Members can book from Apr 6 onwards ```