Files
zyt/ORDER_STATUS_TABS_UI.md
T
2026-04-17 09:47:17 +08:00

300 lines
8.1 KiB
Markdown

# Order Status Tabs UI (订单状态标签页UI)
## Feature
Redesigned the fulfillment status filter from a dropdown select to clickable tabs for better user experience and faster filtering.
## Changes Made
### File: `admin/src/views/consumer/prescription/order_list.vue`
#### 1. Replaced Dropdown with Tab UI
**Before:**
```vue
<el-form-item class="w-[180px]" label="履约状态">
<el-select v-model="queryParams.fulfillment_status" placeholder="全部" clearable>
<el-option label="待双审通过" :value="1" />
<el-option label="履约中" :value="2" />
<el-option label="已发货" :value="5" />
<el-option label="已完成" :value="3" />
<el-option label="已取消" :value="4" />
</el-select>
</el-form-item>
```
**After:**
```vue
<!-- 状态标签页 -->
<el-card class="!border-none shadow-sm mb-4" shadow="never">
<div class="flex items-center gap-2 flex-wrap">
<div
v-for="tab in statusTabs"
:key="tab.value"
:class="[
'px-4 py-2 rounded-lg cursor-pointer transition-all duration-200 select-none',
queryParams.fulfillment_status === tab.value
? 'bg-primary text-white shadow-md'
: 'bg-gray-50 text-gray-600 hover:bg-gray-100'
]"
@click="handleStatusTabClick(tab.value)"
>
<div class="flex items-center gap-2">
<span class="font-medium">{{ tab.label }}</span>
<span v-if="tab.count !== undefined" :class="[
'text-xs px-1.5 py-0.5 rounded',
queryParams.fulfillment_status === tab.value
? 'bg-white/20'
: 'bg-gray-200'
]">
{{ tab.count }}
</span>
</div>
</div>
</div>
</el-card>
```
#### 2. Added Status Tabs Configuration
```typescript
// 状态标签页配置
const statusTabs = ref([
{ label: '全部', value: '' as number | '', count: undefined },
{ label: '待双审通过', value: 1, count: undefined },
{ label: '履约中', value: 2, count: undefined },
{ label: '已发货', value: 5, count: undefined },
{ label: '已完成', value: 3, count: undefined },
{ label: '已取消', value: 4, count: undefined }
])
```
#### 3. Added Click Handler
```typescript
// 处理状态标签点击
const handleStatusTabClick = (value: number | '') => {
queryParams.fulfillment_status = value
resetPage()
}
```
## UI Design
### Visual States
**Active Tab:**
- Primary color background (`bg-primary`)
- White text
- Shadow effect
- Badge with semi-transparent white background
**Inactive Tab:**
- Light gray background (`bg-gray-50`)
- Gray text
- Hover effect (lighter gray)
- Badge with gray background
### Layout
- Horizontal flex layout with gap
- Wraps on smaller screens
- Smooth transitions (200ms)
- Rounded corners
- Consistent padding
### Badge (Count Display)
- Small text size
- Rounded badge
- Shows count for each status (optional feature)
- Different styling for active/inactive states
## User Experience Improvements
### Before (Dropdown):
1. User clicks dropdown
2. Dropdown opens with options
3. User scrolls to find status
4. User clicks option
5. Dropdown closes
6. User clicks "查询" button
**Total: 3-4 clicks + scrolling**
### After (Tabs):
1. User clicks tab
2. Filter applies immediately
**Total: 1 click**
### Benefits:
-**Faster filtering**: One-click access to any status
-**Visual feedback**: Clear indication of current filter
-**Better discoverability**: All options visible at once
-**No extra clicks**: Auto-triggers search on click
-**Modern UI**: Follows common tab pattern
-**Mobile friendly**: Wraps on small screens
## Features
### 1. Active State Indication
The currently selected tab is highlighted with primary color, making it immediately clear which filter is active.
### 2. Hover Effects
Inactive tabs show a subtle hover effect, indicating they are clickable.
### 3. Count Badges (Optional)
Each tab can display a count badge showing the number of orders in that status. Currently set to `undefined` but can be populated with actual counts.
### 4. Responsive Design
Tabs wrap to multiple lines on smaller screens using `flex-wrap`.
### 5. Smooth Transitions
All state changes have smooth 200ms transitions for a polished feel.
## Implementation Details
### Tab Configuration
```typescript
{
label: string, // Display text
value: number | '', // Filter value ('' for "All")
count: number | undefined // Optional count badge
}
```
### Click Handler Logic
```typescript
const handleStatusTabClick = (value: number | '') => {
queryParams.fulfillment_status = value // Update filter
resetPage() // Trigger search
}
```
### Styling Classes
- `bg-primary`: Primary brand color (active state)
- `bg-gray-50`: Light gray (inactive state)
- `hover:bg-gray-100`: Hover effect
- `shadow-md`: Shadow for active tab
- `transition-all duration-200`: Smooth transitions
- `select-none`: Prevent text selection on click
## Future Enhancements
### 1. Add Count Badges
Fetch and display order counts for each status:
```typescript
// After fetching data
const updateStatusCounts = (data: any) => {
statusTabs.value[0].count = data.total
statusTabs.value[1].count = data.pending
statusTabs.value[2].count = data.processing
// ... etc
}
```
### 2. Add Icons
Add status-specific icons for better visual recognition:
```vue
<svg class="w-4 h-4" v-if="tab.value === 1">
<!-- Clock icon for pending -->
</svg>
```
### 3. Add Keyboard Navigation
Support arrow keys for tab navigation:
```typescript
const handleKeydown = (e: KeyboardEvent) => {
if (e.key === 'ArrowLeft') {
// Navigate to previous tab
} else if (e.key === 'ArrowRight') {
// Navigate to next tab
}
}
```
### 4. Add Loading State
Show loading indicator on active tab while fetching:
```vue
<el-icon v-if="pager.loading && queryParams.fulfillment_status === tab.value" class="is-loading">
<Loading />
</el-icon>
```
## Testing Steps
### 1. Test Tab Switching
1. Open order list page
2. Click on different status tabs
3. Verify:
- Active tab is highlighted
- Table updates with filtered results
- URL parameters update (if using router)
### 2. Test Visual States
1. Hover over inactive tabs
2. Verify hover effect appears
3. Click a tab
4. Verify active state styling applies
### 3. Test "全部" Tab
1. Click "全部" tab
2. Verify all orders are shown
3. Verify no status filter is applied
### 4. Test Responsive Behavior
1. Resize browser window to small width
2. Verify tabs wrap to multiple lines
3. Verify all tabs remain accessible
### 5. Test with Search
1. Enter order number in search
2. Click different status tabs
3. Verify both filters work together
## Accessibility
### Current Implementation:
- ✅ Keyboard accessible (clickable divs)
- ✅ Visual feedback on hover
- ✅ Clear active state indication
- ✅ Sufficient color contrast
### Recommended Improvements:
- Add `role="tab"` and `aria-selected` attributes
- Add `tabindex="0"` for keyboard navigation
- Add keyboard event handlers (Enter/Space)
- Add `aria-label` for screen readers
### Example:
```vue
<div
role="tab"
:aria-selected="queryParams.fulfillment_status === tab.value"
:tabindex="0"
@keydown.enter="handleStatusTabClick(tab.value)"
@keydown.space.prevent="handleStatusTabClick(tab.value)"
>
```
## Related Files
### Frontend:
- `admin/src/views/consumer/prescription/order_list.vue`
- Added status tabs UI
- Added `statusTabs` configuration
- Added `handleStatusTabClick` handler
- Removed dropdown select
## Summary
✅ Replaced dropdown with clickable tabs
✅ One-click filtering (no need to click "查询")
✅ Visual active state indication
✅ Hover effects for better UX
✅ Responsive design with flex-wrap
✅ Smooth transitions
✅ Support for count badges (optional)
✅ Cleaner, more modern UI
The status filter is now much more intuitive and efficient, following modern UI patterns commonly seen in admin dashboards!