更新
This commit is contained in:
@@ -0,0 +1,293 @@
|
||||
# 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!
|
||||
Reference in New Issue
Block a user