Files
one-pipe-system/openspec/changes/add-device-management/design.md
sexygoat 5c6312c407
Some checks failed
构建并部署前端到测试环境 / build-and-deploy (push) Failing after 6s
fetch(add): 新增
2026-01-27 09:18:45 +08:00

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.