279 lines
12 KiB
Markdown
279 lines
12 KiB
Markdown
# Device Management Design
|
|
|
|
## Context
|
|
|
|
The system currently has a basic device-import page but lacks comprehensive device management capabilities. Devices are critical assets that need to be tracked throughout their lifecycle - from import, allocation to shops, binding with SIM cards, to eventual recall. This change adds full device management to complement the existing card management features.
|
|
|
|
Key integration points:
|
|
- **Existing Card System**: Devices must bind with cards from the existing card-list module
|
|
- **Shop System**: Devices are allocated to shops using the existing ShopService
|
|
- **Object Storage**: Imports use the existing StorageService for large file uploads
|
|
- **Task System**: Import tasks must integrate with the existing task-management infrastructure
|
|
|
|
## Goals
|
|
|
|
1. **Complete Lifecycle Management**: Support all device operations from import to deletion
|
|
2. **Seamless Integration**: Reuse existing UI patterns, services, and components
|
|
3. **Scalable Import**: Handle large CSV imports efficiently using object storage
|
|
4. **Operation Traceability**: Track all device operations through task management
|
|
5. **Consistent UX**: Match the look and feel of existing card-list and enterprise-customer pages
|
|
|
|
## Key Decisions
|
|
|
|
### Decision 1: Three-Step Object Storage Import
|
|
|
|
**Choice**: Use StorageService.getUploadUrl → uploadFile → DeviceService.importDevices
|
|
|
|
**Rationale**:
|
|
- Handles large files (thousands of devices) without timeout issues
|
|
- Decouples upload from processing (backend can process asynchronously)
|
|
- Consistent with modern cloud architecture patterns
|
|
- Allows progress tracking through task management
|
|
|
|
**Alternatives Considered**:
|
|
- Direct multipart upload to backend (rejected: not scalable for large files)
|
|
- Two-step process without pre-signed URL (rejected: less secure, more backend load)
|
|
|
|
**Implementation Notes**:
|
|
- Frontend only handles upload to object storage, not file parsing
|
|
- Backend processes the file asynchronously and creates task records
|
|
- Task management provides visibility into import progress
|
|
|
|
### Decision 2: Device-Card Binding Model
|
|
|
|
**Choice**: Store binding with explicit slot_position (1-4) in device_cards table
|
|
|
|
**Rationale**:
|
|
- IoT devices have physical SIM slots that need explicit identification
|
|
- Each device can have 1-4 slots (max_sim_slots)
|
|
- One card can only bind to one device slot (enforced by backend)
|
|
- Slot position is critical for physical device configuration
|
|
|
|
**Alternatives Considered**:
|
|
- Auto-assign slot positions (rejected: operators need to know physical slot numbers)
|
|
- Allow one card to bind to multiple devices (rejected: not realistic for physical SIMs)
|
|
|
|
**Implementation Notes**:
|
|
- Device detail page shows a 4-slot grid (empty slots show "Bind Card" button)
|
|
- Binding dialog requires explicit slot selection
|
|
- Unbinding updates bound_card_count and frees the slot
|
|
|
|
### Decision 3: Unified Task Management
|
|
|
|
**Choice**: Extend existing task-management to support device import tasks
|
|
|
|
**Rationale**:
|
|
- Reuses existing task infrastructure
|
|
- Provides consistent UX for all import operations
|
|
- Avoids duplicate task tracking logic
|
|
- Allows unified search/filter across task types
|
|
|
|
**Alternatives Considered**:
|
|
- Separate device task management page (rejected: creates UX fragmentation)
|
|
- Embed task tracking only in device-import page (rejected: limited visibility)
|
|
|
|
**Implementation Notes**:
|
|
- Add task_type field to distinguish ICCID vs Device imports
|
|
- Task detail page renders different content based on task_type
|
|
- Device tasks show device_no and bound ICCIDs instead of just ICCID
|
|
|
|
### Decision 4: Batch Operation Result Display
|
|
|
|
**Choice**: Show detailed results in dialog after batch allocation/recall
|
|
|
|
**Rationale**:
|
|
- Operations may partially succeed (some devices succeed, others fail)
|
|
- Operators need to know exactly which devices failed and why
|
|
- Allows retry of failed operations without re-selecting all devices
|
|
|
|
**Alternatives Considered**:
|
|
- Just show toast notification (rejected: insufficient detail for partial failures)
|
|
- Navigate to separate results page (rejected: disrupts workflow)
|
|
|
|
**Implementation Notes**:
|
|
- Dialog shows summary: total, success count, failure count
|
|
- Expandable table shows failed devices with error messages
|
|
- Success closes dialog, partial failure keeps it open for review
|
|
|
|
### Decision 5: Component Reuse Strategy
|
|
|
|
**Choice**: Use existing Art* components (ArtTableFullScreen, ArtSearchBar, ArtTable, ArtButtonTable)
|
|
|
|
**Rationale**:
|
|
- Maintains UI consistency across the application
|
|
- Reduces development time
|
|
- Leverages tested, stable components
|
|
- Easier for users familiar with other pages
|
|
|
|
**Reference Implementation**:
|
|
- Device-list follows role/index.vue pattern
|
|
- Device-detail follows card-list detail modal pattern
|
|
- Search form follows enterprise-customer search pattern
|
|
|
|
**Implementation Notes**:
|
|
- Use CommonStatus for status values (ENABLED/DISABLED)
|
|
- Use ElSwitch for status toggles
|
|
- Use ArtButtonTable for action buttons
|
|
- Follow ElDescriptions layout for detail pages
|
|
|
|
## Architecture Diagrams
|
|
|
|
### Device Import Flow
|
|
```
|
|
┌─────────┐ 1. Select CSV ┌──────────────┐
|
|
│ Admin │ ──────────────────> │ device-import│
|
|
│ │ │ (Vue) │
|
|
└─────────┘ └──────┬───────┘
|
|
│
|
|
│ 2. getUploadUrl()
|
|
v
|
|
┌──────────────┐
|
|
│ Storage │
|
|
│ Service │
|
|
└──────┬───────┘
|
|
│
|
|
│ 3. Upload to OSS
|
|
v
|
|
┌──────────────┐
|
|
│ Object │
|
|
│ Storage │
|
|
└──────────────┘
|
|
│
|
|
│ 4. importDevices(file_key)
|
|
v
|
|
┌──────────────┐
|
|
│ Device │
|
|
│ Service │
|
|
└──────┬───────┘
|
|
│
|
|
│ 5. Create Task
|
|
v
|
|
┌──────────────┐
|
|
│ Task │
|
|
│ Management │
|
|
└──────────────┘
|
|
```
|
|
|
|
### Device-Card Binding
|
|
```
|
|
┌─────────┐ ┌──────────────┐
|
|
│ Device │ ───── bound to ────> │ Card │
|
|
│ │ (1 to N) │ │
|
|
└─────────┘ └──────────────┘
|
|
│ │
|
|
│ has_many bindings │ has_one binding
|
|
v v
|
|
┌─────────────────────────────────────────────┐
|
|
│ DeviceCardBinding │
|
|
│ - device_id │
|
|
│ - card_id │
|
|
│ - slot_position (1-4) │
|
|
│ - bound_at │
|
|
└─────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Data Flow
|
|
|
|
### Device List Page Load
|
|
1. User navigates to /asset-management/device-list
|
|
2. Vue component mounts, calls DeviceService.getDevices(params)
|
|
3. Backend returns paginated device list with bound_card_count
|
|
4. Table renders with status switches and action buttons
|
|
|
|
### Batch Allocation Flow
|
|
1. User selects devices, clicks "Batch Allocate"
|
|
2. Dialog opens with shop selector
|
|
3. User selects shop, adds remarks, confirms
|
|
4. Call DeviceService.allocateDevices({ device_ids, shop_id, remarks })
|
|
5. Backend processes each device, returns results array
|
|
6. Dialog shows summary and failed device details
|
|
|
|
### Card Binding Flow
|
|
1. User opens device detail page
|
|
2. Clicks "Bind Card" for an empty slot
|
|
3. Dialog shows card search and slot selection
|
|
4. User selects card and slot (e.g., slot 3)
|
|
5. Call DeviceService.bindCard(device_id, { card_id, slot_position: 3 })
|
|
6. Backend validates slot is empty, creates binding
|
|
7. Refresh device detail to show new binding
|
|
|
|
## Migration Plan
|
|
|
|
### Updating Existing Device Import Page
|
|
|
|
**Current State** (`src/views/batch/device-import/index.vue`):
|
|
- Uses ElUpload with drag-and-drop
|
|
- Mock data for import records
|
|
- No real API integration
|
|
|
|
**Migration Steps**:
|
|
1. Replace ElUpload with three-step upload logic
|
|
- Add getUploadUrl call
|
|
- Add uploadFile to object storage
|
|
- Add importDevices call with file_key
|
|
2. Remove mock import records
|
|
3. Link to task-management for tracking
|
|
4. Update CSV format instructions
|
|
|
|
**Backward Compatibility**:
|
|
- This is a new feature area with no existing production data
|
|
- No API breaking changes
|
|
- UI changes are additive (improve existing page)
|
|
|
|
### Extending Task Management
|
|
|
|
**Current State**:
|
|
- Only handles ICCID import tasks
|
|
- Single task type rendering
|
|
|
|
**Migration Steps**:
|
|
1. Add task_type filter dropdown (default: show all)
|
|
2. Add task_type badge in task list
|
|
3. Task detail page: switch rendering based on task_type
|
|
4. Add device-specific fields to task detail view
|
|
|
|
**Backward Compatibility**:
|
|
- Existing ICCID tasks continue to work unchanged
|
|
- Filter defaults to showing all types
|
|
- No database schema changes required (task_type already exists)
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit Testing
|
|
- DeviceService API methods with mock responses
|
|
- Form validation logic
|
|
- Utility functions (formatters, validators)
|
|
|
|
### Integration Testing
|
|
- Device list search and pagination
|
|
- Batch allocation with partial failures
|
|
- Card binding/unbinding workflow
|
|
- Import task creation and status tracking
|
|
|
|
### E2E Testing Scenarios
|
|
1. Import devices via CSV → verify task created → check task detail
|
|
2. Search devices → select multiple → allocate to shop → verify shop assignment
|
|
3. View device detail → bind card to slot 2 → unbind → verify empty slot
|
|
4. Batch recall devices → verify shop cleared → check operation history
|
|
|
|
### Performance Considerations
|
|
- Device list pagination (default 20 per page)
|
|
- Debounced search input (300ms delay)
|
|
- Batch operation result pagination (if >100 results)
|
|
- Large CSV imports handled asynchronously (no frontend timeout)
|
|
|
|
## Security Considerations
|
|
|
|
1. **Authorization**: All device operations require admin role
|
|
2. **Input Validation**:
|
|
- Device number format validation
|
|
- Slot position range (1 to max_sim_slots)
|
|
- CSV file size limits
|
|
3. **Object Storage Security**: Pre-signed URLs expire after 15 minutes
|
|
4. **Batch Operation Limits**: Backend enforces max 1000 devices per batch
|
|
5. **XSS Prevention**: All user inputs sanitized before rendering
|
|
|
|
## Open Questions
|
|
|
|
None at this time. All major design decisions have been made based on existing system patterns and API specifications.
|