生产管理系统前端 - 更新瓦力提交的产品原型到参考目录
This commit is contained in:
262
src/SELECT_EMPTY_STRING_FIX.md
Normal file
262
src/SELECT_EMPTY_STRING_FIX.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# ✅ Select 空字符串错误修复
|
||||
|
||||
## 🔧 问题描述
|
||||
|
||||
Radix UI 的 Select 组件报错:
|
||||
```
|
||||
Error: A <Select.Item /> must have a value prop that is not an empty string.
|
||||
```
|
||||
|
||||
**原因**: Radix UI 的 Select 组件不允许 SelectItem 使用空字符串 `""` 作为 value,因为空字符串被保留用于清除选择和显示占位符。
|
||||
|
||||
---
|
||||
|
||||
## 📋 修复文件
|
||||
|
||||
修复了以下文件中的所有空字符串值:
|
||||
|
||||
### 1. `/components/machinery/operation/PlanDispatch.tsx`
|
||||
- ✅ 路线方案选择器
|
||||
|
||||
### 2. `/components/machinery/scheduling/TaskForm.tsx`
|
||||
- ✅ 农机设备选择器
|
||||
- ✅ 驾驶员选择器
|
||||
|
||||
---
|
||||
|
||||
## 🔨 具体修复内容
|
||||
|
||||
### PlanDispatch.tsx
|
||||
|
||||
#### 修复前
|
||||
```tsx
|
||||
<SelectItem value="">不选择路线</SelectItem>
|
||||
const [selectedRoute, setSelectedRoute] = useState<string>('');
|
||||
```
|
||||
|
||||
#### 修复后
|
||||
```tsx
|
||||
<SelectItem value="none">不选择路线</SelectItem>
|
||||
const [selectedRoute, setSelectedRoute] = useState<string>('none');
|
||||
```
|
||||
|
||||
#### 逻辑处理
|
||||
```typescript
|
||||
// 下发逻辑中判断
|
||||
routePlanId: selectedRoute && selectedRoute !== 'none' ? selectedRoute : undefined,
|
||||
routePlanName: selectedRouteData?.name || undefined,
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### TaskForm.tsx
|
||||
|
||||
#### 修复前
|
||||
```tsx
|
||||
<SelectItem value="">暂不分配</SelectItem>
|
||||
const [selectedMachinery, setSelectedMachinery] = useState<string>('');
|
||||
const [selectedDriver, setSelectedDriver] = useState<string>('');
|
||||
```
|
||||
|
||||
#### 修复后
|
||||
```tsx
|
||||
<SelectItem value="unassigned">暂不分配</SelectItem>
|
||||
const [selectedMachinery, setSelectedMachinery] = useState<string>('unassigned');
|
||||
const [selectedDriver, setSelectedDriver] = useState<string>('unassigned');
|
||||
```
|
||||
|
||||
#### 逻辑处理
|
||||
```typescript
|
||||
// 提交时判断
|
||||
const selectedMachineryData = selectedMachinery && selectedMachinery !== 'unassigned'
|
||||
? machinery.find(m => m.id === selectedMachinery)
|
||||
: null;
|
||||
|
||||
const selectedDriverData = selectedDriver && selectedDriver !== 'unassigned'
|
||||
? drivers.find(d => d.id === selectedDriver)
|
||||
: null;
|
||||
|
||||
const task: Partial<Task> = {
|
||||
machineryId: selectedMachinery && selectedMachinery !== 'unassigned' ? selectedMachinery : null,
|
||||
driverId: selectedDriver && selectedDriver !== 'unassigned' ? selectedDriver : null,
|
||||
};
|
||||
```
|
||||
|
||||
#### 警告提示更新
|
||||
```tsx
|
||||
// 修复前
|
||||
{!selectedMachinery && !selectedDriver && (
|
||||
<div>...</div>
|
||||
)}
|
||||
|
||||
// 修复后
|
||||
{(selectedMachinery === 'unassigned' || !selectedMachinery) &&
|
||||
(selectedDriver === 'unassigned' || !selectedDriver) && (
|
||||
<div>...</div>
|
||||
)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 修复汇总
|
||||
|
||||
### 修改统计
|
||||
|
||||
| 文件 | SelectItem 修复 | 状态初始化 | 逻辑处理 |
|
||||
|------|----------------|-----------|---------|
|
||||
| PlanDispatch.tsx | 1处 | 1处 | 2处 |
|
||||
| TaskForm.tsx | 2处 | 2处 | 4处 |
|
||||
| **总计** | **3处** | **3处** | **6处** |
|
||||
|
||||
### 替换规则
|
||||
|
||||
| 原值 | 新值 | 用途 |
|
||||
|------|------|------|
|
||||
| `""` | `"none"` | 不选择路线 |
|
||||
| `""` | `"unassigned"` | 暂不分配资源 |
|
||||
|
||||
---
|
||||
|
||||
## ✅ 验证结果
|
||||
|
||||
### 测试场景
|
||||
|
||||
#### 1. PlanDispatch - 路线选择
|
||||
```
|
||||
✅ 选择"不选择路线" → value = "none"
|
||||
✅ 下发时正确判断为无路线
|
||||
✅ 切换到其他路线正常工作
|
||||
✅ 不再报错
|
||||
```
|
||||
|
||||
#### 2. TaskForm - 农机选择
|
||||
```
|
||||
✅ 选择"暂不分配" → value = "unassigned"
|
||||
✅ 提交时 machineryId = null
|
||||
✅ 切换到具体农机正常工作
|
||||
✅ 不再报错
|
||||
```
|
||||
|
||||
#### 3. TaskForm - 驾驶员选择
|
||||
```
|
||||
✅ 选择"暂不分配" → value = "unassigned"
|
||||
✅ 提交时 driverId = null
|
||||
✅ 切换到具体驾驶员正常工作
|
||||
✅ 不再报错
|
||||
```
|
||||
|
||||
#### 4. 警告提示
|
||||
```
|
||||
✅ 未分配资源时正确显示警告
|
||||
✅ 分配资源后警告消失
|
||||
✅ 逻辑判断正确
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 最佳实践
|
||||
|
||||
### Radix UI Select 使用规范
|
||||
|
||||
#### ❌ 不要这样做
|
||||
```tsx
|
||||
<SelectItem value="">请选择</SelectItem>
|
||||
<SelectItem value="">无</SelectItem>
|
||||
<SelectItem value="">不限</SelectItem>
|
||||
```
|
||||
|
||||
#### ✅ 应该这样做
|
||||
```tsx
|
||||
<SelectItem value="none">请选择</SelectItem>
|
||||
<SelectItem value="null">无</SelectItem>
|
||||
<SelectItem value="unlimited">不限</SelectItem>
|
||||
```
|
||||
|
||||
### 处理逻辑建议
|
||||
|
||||
```typescript
|
||||
// 1. 使用有意义的特殊值
|
||||
const UNASSIGNED = 'unassigned';
|
||||
const NONE = 'none';
|
||||
|
||||
// 2. 初始化时使用特殊值
|
||||
const [value, setValue] = useState<string>(UNASSIGNED);
|
||||
|
||||
// 3. 判断时检查特殊值
|
||||
const isSelected = value && value !== UNASSIGNED;
|
||||
|
||||
// 4. 提交时转换为实际值
|
||||
const finalValue = value !== UNASSIGNED ? value : null;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 代码示例
|
||||
|
||||
### 完整的 Select 组件示例
|
||||
|
||||
```tsx
|
||||
import { useState } from 'react';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
|
||||
|
||||
export function MySelect() {
|
||||
const [value, setValue] = useState<string>('unassigned');
|
||||
|
||||
const handleSubmit = () => {
|
||||
// 转换特殊值为 null
|
||||
const finalValue = value !== 'unassigned' ? value : null;
|
||||
console.log('提交值:', finalValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<Select value={value} onValueChange={setValue}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="请选择" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="unassigned">暂不分配</SelectItem>
|
||||
<SelectItem value="option1">选项1</SelectItem>
|
||||
<SelectItem value="option2">选项2</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 检查清单
|
||||
|
||||
在项目中使用 Select 组件时,请检查:
|
||||
|
||||
- [ ] SelectItem 的 value 不是空字符串 `""`
|
||||
- [ ] 使用有意义的特殊值(如 `"none"`, `"unassigned"`)
|
||||
- [ ] 初始化状态使用特殊值而非空字符串
|
||||
- [ ] 提交/处理逻辑中正确判断特殊值
|
||||
- [ ] 条件渲染中考虑特殊值
|
||||
- [ ] 不要使用 `null` 或 `undefined` 作为 SelectItem value
|
||||
|
||||
---
|
||||
|
||||
## 🎉 结论
|
||||
|
||||
**所有 Select 空字符串错误已完全修复!**
|
||||
|
||||
### 修复成果
|
||||
- ✅ 移除所有空字符串 SelectItem value
|
||||
- ✅ 使用有意义的特殊值替代
|
||||
- ✅ 更新所有相关逻辑判断
|
||||
- ✅ 验证所有功能正常工作
|
||||
- ✅ 不再有 Radix UI 错误
|
||||
|
||||
### 影响范围
|
||||
- ✅ 作业方案下发功能 - 正常
|
||||
- ✅ 任务创建/编辑功能 - 正常
|
||||
- ✅ 资源分配功能 - 正常
|
||||
- ✅ 所有 Select 组件 - 正常
|
||||
|
||||
---
|
||||
|
||||
**修复时间**: 2025-10-17
|
||||
**状态**: ✅ **完成**
|
||||
**测试**: ✅ **通过**
|
||||
Reference in New Issue
Block a user