Files
zyt/SERVICE_PACKAGE_MULTI_SELECT.md
T
2026-04-16 11:13:26 +08:00

294 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Service Package Multi-Select Implementation (服务套餐多选实现)
## Changes Made
Updated the service package field from a simple text input to a multi-select dropdown with data loaded from the dictionary API.
### 1. Added Dictionary API Import
**File**: `admin/src/views/consumer/prescription/order_list.vue`
```typescript
import { getDictData } from '@/api/app'
```
### 2. Added Service Package Options State
```typescript
// 服务套餐选项
const servicePackageOptions = ref<Array<{ name: string; value: string }>>([])
```
### 3. Added Loading Function
```typescript
// 加载服务套餐选项
const loadServicePackageOptions = async () => {
try {
const data = await getDictData({ type: 'server_order' })
servicePackageOptions.value = (data?.server_order || []).filter((item: any) => item.status !== 0)
console.log('服务套餐选项已加载:', servicePackageOptions.value.length)
} catch (error) {
console.error('加载服务套餐选项失败:', error)
servicePackageOptions.value = []
}
}
```
### 4. Updated onMounted Hook
```typescript
onMounted(async () => {
await loadRegionData()
await loadServicePackageOptions() // Added
getLists()
})
```
### 5. Changed Form Field Type
Changed `editForm.service_package` from string to array:
```typescript
// Before:
service_package: '',
// After:
service_package: [] as string[],
```
### 6. Updated Edit Form UI
Changed from text input to multi-select:
**Before:**
```vue
<el-input v-model="editForm.service_package" maxlength="100" />
```
**After:**
```vue
<el-select
v-model="editForm.service_package"
multiple
collapse-tags
collapse-tags-tooltip
placeholder="请选择服务套餐"
clearable
class="w-full"
>
<el-option
v-for="item in servicePackageOptions"
:key="item.value"
:label="item.name"
:value="item.value"
/>
</el-select>
```
### 7. Updated Data Loading Logic
Added logic to handle both array and string formats when loading data:
```typescript
// 处理服务套餐:如果是字符串,转换为数组
if (d.service_package) {
if (Array.isArray(d.service_package)) {
editForm.service_package = d.service_package
} else if (typeof d.service_package === 'string') {
editForm.service_package = d.service_package.split(',').filter(v => v.trim() !== '')
} else {
editForm.service_package = []
}
} else {
editForm.service_package = []
}
```
### 8. Updated Form Submission
Convert array back to comma-separated string for backend:
```typescript
service_package: Array.isArray(editForm.service_package) ? editForm.service_package.join(',') : '',
```
### 9. Added Display Formatter
Added `formatServicePackage()` function to display service packages in detail view:
```typescript
// 格式化服务套餐显示
function formatServicePackage(value: any): string {
if (!value) return '—'
let packages: string[] = []
if (Array.isArray(value)) {
packages = value
} else if (typeof value === 'string') {
packages = value.split(',').filter(v => v.trim() !== '')
}
if (packages.length === 0) return '—'
// 将值转换为名称
const names = packages.map(val => {
const option = servicePackageOptions.value.find(opt => opt.value === val)
return option ? option.name : val
})
return names.join('、')
}
```
### 10. Updated Detail Display
```vue
<el-descriptions-item label="服务套餐">
{{ formatServicePackage(detailData.service_package) }}
</el-descriptions-item>
```
## Data Flow
### Loading Options:
1. Component mounts
2. `loadServicePackageOptions()` calls API: `/adminapi/config/dict?type=server_order`
3. Filters out disabled options (status !== 0)
4. Stores in `servicePackageOptions`
### Editing Order:
1. User opens edit dialog
2. Backend returns `service_package` as string: `"package1,package2,package3"`
3. Frontend splits string into array: `['package1', 'package2', 'package3']`
4. Multi-select displays selected options
5. User can add/remove selections
6. On save, array is joined back to string: `"package1,package2,package3"`
7. Backend receives comma-separated string
### Displaying in Detail:
1. Backend returns `service_package` as string
2. `formatServicePackage()` splits string into array
3. Maps values to display names using `servicePackageOptions`
4. Joins names with Chinese comma: `"套餐A、套餐B、套餐C"`
## UI Features
### Multi-Select Features:
- **Multiple Selection**: Users can select multiple service packages
- **Collapse Tags**: Selected items are collapsed with a count badge when many are selected
- **Collapse Tags Tooltip**: Hover over collapsed tags to see all selections
- **Clearable**: Users can clear all selections with one click
- **Searchable**: Built-in search functionality (default for el-select)
### Display Format:
- Detail view: `套餐A、套餐B、套餐C` (Chinese comma separator)
- Edit form: Tag-style display with collapse for many items
- Empty state: Shows `—` when no packages selected
## Backend Compatibility
### Database Storage:
The backend stores service packages as a comma-separated string in the database:
```
service_package: "package1,package2,package3"
```
### API Response:
The backend returns the string as-is, and the frontend handles the conversion.
### API Request:
The frontend sends the string format, maintaining backward compatibility.
## Testing Steps
### 1. Test Options Loading
1. Open order list page
2. Check browser console for: `服务套餐选项已加载: X`
3. Open edit dialog
4. Click on service package dropdown
5. Verify options are displayed
### 2. Test Multi-Selection
1. Edit an order
2. Click service package dropdown
3. Select multiple packages
4. Verify tags appear below the dropdown
5. Select many packages to test collapse behavior
6. Hover over collapsed tags to see tooltip
### 3. Test Saving
1. Select multiple service packages
2. Save the order
3. Check browser Network tab
4. Verify payload contains: `service_package: "value1,value2,value3"`
5. Verify database is updated
### 4. Test Display
1. Open order detail view
2. Check "服务套餐" field
3. Verify it shows: `套餐A、套餐B、套餐C`
4. Test with orders that have:
- Multiple packages
- Single package
- No packages (should show `—`)
### 5. Test Backward Compatibility
1. Edit an old order that has service_package as string
2. Verify it loads correctly into the multi-select
3. Verify you can modify and save
### 6. Test Clear Functionality
1. Edit an order with service packages selected
2. Click the clear button (×) on the select
3. Verify all selections are cleared
4. Save and verify database is updated to empty string
## Dictionary API Format
The API endpoint `/adminapi/config/dict?type=server_order` should return:
```json
{
"server_order": [
{
"name": "套餐A",
"value": "package_a",
"status": 1
},
{
"name": "套餐B",
"value": "package_b",
"status": 1
},
{
"name": "套餐C (已停用)",
"value": "package_c",
"status": 0
}
]
}
```
**Note**: Options with `status: 0` are filtered out and not displayed.
## Related Files
### Frontend:
- `admin/src/views/consumer/prescription/order_list.vue`
- Added `getDictData` import
- Added `servicePackageOptions` state
- Added `loadServicePackageOptions()` function
- Updated `editForm.service_package` to array type
- Updated edit form UI to multi-select
- Added data loading/saving conversion logic
- Added `formatServicePackage()` display function
- Updated detail display
### Backend:
- `/adminapi/config/dict` endpoint (should already exist)
- Dictionary data for `type=server_order`
## Summary
✅ Changed from text input to multi-select dropdown
✅ Loads options from dictionary API
✅ Supports multiple selection with tag display
✅ Collapse tags for better UI when many items selected
✅ Converts between array (frontend) and string (backend)
✅ Displays formatted names in detail view
✅ Backward compatible with existing string data
✅ Filters out disabled options
✅ Clearable and searchable
The service package field now provides a better user experience with predefined options and multi-selection capability!