生产管理系统前端 - 更新瓦力提交的产品原型到参考目录
This commit is contained in:
631
src/PLAN_DISPATCH_DRIVER_SELECTION.md
Normal file
631
src/PLAN_DISPATCH_DRIVER_SELECTION.md
Normal file
@@ -0,0 +1,631 @@
|
||||
# ✅ 作业方案下发 - 司机选择功能
|
||||
|
||||
## 🎯 功能说明
|
||||
|
||||
**在作业方案下发功能中增加司机选择下拉框,支持为下发任务指定司机**
|
||||
|
||||
---
|
||||
|
||||
## 📦 功能更新
|
||||
|
||||
### 1️⃣ **状态管理**
|
||||
|
||||
添加司机相关状态:
|
||||
|
||||
```typescript
|
||||
const [drivers, setDrivers] = useState<any[]>([]);
|
||||
const [selectedDriver, setSelectedDriver] = useState<string>('none');
|
||||
```
|
||||
|
||||
### 2️⃣ **数据加载**
|
||||
|
||||
从 localStorage 加载司机数据:
|
||||
|
||||
```typescript
|
||||
const loadData = () => {
|
||||
// 加载农机
|
||||
const machineryData = machineryStorage.getAllMachinery();
|
||||
setMachinery(machineryData);
|
||||
|
||||
// 加载路线规划
|
||||
const routesData = localStorage.getItem('smart_agriculture_route_plans');
|
||||
if (routesData) {
|
||||
setRoutes(JSON.parse(routesData));
|
||||
}
|
||||
|
||||
// ✅ 加载司机
|
||||
const driversData = localStorage.getItem('smart_agriculture_drivers');
|
||||
if (driversData) {
|
||||
setDrivers(JSON.parse(driversData));
|
||||
}
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
### 3️⃣ **新建对话框 - 司机选择**
|
||||
|
||||
添加司机选择下拉框:
|
||||
|
||||
```tsx
|
||||
<div>
|
||||
<Label>司机</Label>
|
||||
<Select value={selectedDriver} onValueChange={setSelectedDriver}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择司机(可选)" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">不选择司机</SelectItem>
|
||||
{drivers.filter(d => d.status === 'active').map(d => (
|
||||
<SelectItem key={d.id} value={d.id}>
|
||||
{d.name} ({d.licenseNumber || '无驾照'})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 4️⃣ **数据保存**
|
||||
|
||||
保存时关联司机信息:
|
||||
|
||||
```typescript
|
||||
const selectedDriverData = selectedDriver && selectedDriver !== 'none'
|
||||
? drivers.find(d => d.id === selectedDriver)
|
||||
: null;
|
||||
|
||||
const newDispatch: DispatchRecord = {
|
||||
// ... 其他字段
|
||||
driverId: selectedDriverData?.id,
|
||||
driverName: selectedDriverData?.name,
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
### 5️⃣ **表单重置**
|
||||
|
||||
重置时清空司机选择:
|
||||
|
||||
```typescript
|
||||
const resetForm = () => {
|
||||
setSelectedMachinery('');
|
||||
setSelectedRoute('none');
|
||||
setSelectedDriver('none'); // ✅ 重置司机选择
|
||||
setTaskType('');
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
### 6️⃣ **界面布局优化**
|
||||
|
||||
优化表单布局,将司机选择放在合理位置:
|
||||
|
||||
```
|
||||
第一行:
|
||||
- 农机设备 *(左侧)
|
||||
- 司机(右侧)✅ 新增
|
||||
|
||||
第二行:
|
||||
- 路线方案(左侧)
|
||||
- 任务类型 *(右侧)
|
||||
|
||||
第三行:
|
||||
- 优先级(左侧)
|
||||
- 通信协议(右侧)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 界面展示
|
||||
|
||||
### 新建下发对话框
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ 新建作业方案下发 │
|
||||
├──────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 农机设备 * 司机 ✅ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │约翰迪尔拖拉机│ │张三(A123456) │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ 路线方案 任务类型 * │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │东地1号作业... │ │耕地 ▼ │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ 优先级 通信协议 │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │中 ▼ │ │MQTT ▼ │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ 任务描述 │
|
||||
│ ┌────────────────────────────┐ │
|
||||
│ │深耕作业,准备春播 │ │
|
||||
│ └────────────────────────────┘ │
|
||||
│ │
|
||||
│ 计划开始时间 │
|
||||
│ ┌────────────────────────────┐ │
|
||||
│ │📅 2025-10-18 🕐 08:00 │ │
|
||||
│ └────────────────────────────┘ │
|
||||
│ │
|
||||
│ ---- 作业参数 ---- │
|
||||
│ 目标速率 作业幅宽 │
|
||||
│ [5.0] [2.5] │
|
||||
│ 作业深度 行距 │
|
||||
│ [25] [3.0] │
|
||||
│ │
|
||||
│ [取消] [立即下发] │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 司机下拉选项
|
||||
|
||||
```
|
||||
┌────────────────────────────┐
|
||||
│ 选择司机(可选) │
|
||||
├────────────────────────────┤
|
||||
│ ○ 不选择司机 │
|
||||
│ ○ 张三 (A123456) │
|
||||
│ ○ 李四 (B789012) │
|
||||
│ ○ 王五 (C345678) │
|
||||
│ ○ 赵六 (无驾照) │
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
### 下发详情对话框
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ 下发详情 │
|
||||
│ 下发编号: D20251017001 │
|
||||
├──────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 基本信息 │
|
||||
│ ┌──────────────────────────────────┐ │
|
||||
│ │农机设备: 约翰迪尔拖拉机 │ │
|
||||
│ │司机: 张三 ✅ │ │
|
||||
│ │任务类型: 耕地 │ │
|
||||
│ │路线方案: 东地1号作业路线 │ │
|
||||
│ │计划开始时间: 2025-10-18 08:00 │ │
|
||||
│ │优先级: 高 │ │
|
||||
│ │任务描述: 深耕作业,准备春播 │ │
|
||||
│ └──────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ... 其他信息 ... │
|
||||
│ │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 使用场景
|
||||
|
||||
### 场景1: 指定专业司机执行任务
|
||||
|
||||
```
|
||||
需求:
|
||||
耕地作业需要经验丰富的司机
|
||||
|
||||
操作:
|
||||
1. 选择农机:约翰迪尔拖拉机
|
||||
2. 选择司机:张三(有A证,经验丰富)✅
|
||||
3. 任务类型:耕地
|
||||
4. 下发任务
|
||||
|
||||
结果:
|
||||
✅ 任务明确指派给张三
|
||||
✅ 张三收到任务通知
|
||||
✅ 责任明确,便于管理
|
||||
```
|
||||
|
||||
### 场景2: 紧急任务不指定司机
|
||||
|
||||
```
|
||||
需求:
|
||||
紧急抢收,谁有空谁去
|
||||
|
||||
操作:
|
||||
1. 选择农机:收割机
|
||||
2. 司机:不选择司机 ✅
|
||||
3. 任务类型:收获
|
||||
4. 优先级:紧急
|
||||
5. 下发任务
|
||||
|
||||
结果:
|
||||
✅ 任务下发成功
|
||||
✅ 任何有权限的司机都可以接单
|
||||
✅ 灵活应对紧急情况
|
||||
```
|
||||
|
||||
### 场景3: 查看司机工作安排
|
||||
|
||||
```
|
||||
需求:
|
||||
查看张三今天的工作安排
|
||||
|
||||
操作:
|
||||
1. 进入作业方案下发列表
|
||||
2. 筛选司机:张三
|
||||
3. 查看今日任务
|
||||
|
||||
结果:
|
||||
✅ 看到张三的所有下发任务
|
||||
✅ 了解工作量和时间安排
|
||||
✅ 便于协调和调度
|
||||
```
|
||||
|
||||
### 场景4: 按驾照类型分配任务
|
||||
|
||||
```
|
||||
司机列表显示:
|
||||
- 张三 (A证) → 适合大型拖拉机
|
||||
- 李四 (B证) → 适合中型农机
|
||||
- 王五 (C证) → 适合小型设备
|
||||
- 赵六 (无驾照) → 只能操作简单设备
|
||||
|
||||
操作:
|
||||
根据农机类型选择合适的司机
|
||||
|
||||
结果:
|
||||
✅ 合规操作
|
||||
✅ 安全保障
|
||||
✅ 效率提升
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术实现
|
||||
|
||||
### 数据流程
|
||||
|
||||
```
|
||||
1. 页面加载
|
||||
↓
|
||||
2. 从 localStorage 加载司机数据
|
||||
smart_agriculture_drivers
|
||||
↓
|
||||
3. 筛选状态为 'active' 的司机
|
||||
↓
|
||||
4. 显示在下拉框中
|
||||
↓
|
||||
5. 用户选择司机
|
||||
↓
|
||||
6. 创建下发记录时保存 driverId 和 driverName
|
||||
↓
|
||||
7. 下发到农机终端(包含司机信息)
|
||||
```
|
||||
|
||||
### 司机筛选逻辑
|
||||
|
||||
```typescript
|
||||
drivers.filter(d => d.status === 'active')
|
||||
```
|
||||
|
||||
**筛选条件**:
|
||||
- ✅ status === 'active' (在职司机)
|
||||
- ❌ status === 'inactive' (离职司机)
|
||||
- ❌ status === 'suspended' (停职司机)
|
||||
|
||||
### 显示格式
|
||||
|
||||
```typescript
|
||||
{d.name} ({d.licenseNumber || '无驾照'})
|
||||
```
|
||||
|
||||
**示例**:
|
||||
- 张三 (A123456) - 有驾照
|
||||
- 赵六 (无驾照) - 无驾照
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据结构
|
||||
|
||||
### DispatchRecord(已有字段)
|
||||
|
||||
```typescript
|
||||
interface DispatchRecord {
|
||||
id: string;
|
||||
dispatchNumber: string;
|
||||
machineryId: string;
|
||||
machineryName: string;
|
||||
driverId?: string; // ✅ 已有
|
||||
driverName?: string; // ✅ 已有
|
||||
routePlanId?: string;
|
||||
routePlanName?: string;
|
||||
taskType: string;
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
### Driver(从 localStorage 加载)
|
||||
|
||||
```typescript
|
||||
interface Driver {
|
||||
id: string;
|
||||
name: string;
|
||||
licenseNumber?: string; // 驾照号
|
||||
status: 'active' | 'inactive' | 'suspended';
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 界面布局调整
|
||||
|
||||
### 调整前(3行布局)
|
||||
|
||||
```
|
||||
第一行:农机设备 | 路线方案
|
||||
第二行:任务类型 | 优先级
|
||||
第三行:任务描述(跨2列)
|
||||
```
|
||||
|
||||
### 调整后(3行布局 + 司机)✅
|
||||
|
||||
```
|
||||
第一行:农机设备 * | 司机 ✅
|
||||
第二行:路线方案 | 任务类型 *
|
||||
第三行:优先级 | 通信协议
|
||||
第四行:任务描述(跨2列)
|
||||
第五行:计划开始时间(跨2列)
|
||||
```
|
||||
|
||||
**优化点**:
|
||||
1. ✅ 司机选择紧跟农机,逻辑连贯
|
||||
2. ✅ 任务类型和路线方案在一起,方便关联
|
||||
3. ✅ 优先级和通信协议在一起,都是设置项
|
||||
4. ✅ 布局更加合理和平衡
|
||||
|
||||
---
|
||||
|
||||
## 🎨 字段特性
|
||||
|
||||
### 可选字段
|
||||
|
||||
```
|
||||
司机是可选字段:
|
||||
- ✅ 可以不选择(灵活应对)
|
||||
- ✅ 可以选择在职司机
|
||||
- ❌ 不显示离职/停职司机
|
||||
```
|
||||
|
||||
### 默认值
|
||||
|
||||
```typescript
|
||||
selectedDriver: 'none'
|
||||
```
|
||||
|
||||
### 保存逻辑
|
||||
|
||||
```typescript
|
||||
if (selectedDriver === 'none') {
|
||||
driverId: undefined
|
||||
driverName: undefined
|
||||
} else {
|
||||
driverId: selectedDriverData.id
|
||||
driverName: selectedDriverData.name
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 验证清单
|
||||
|
||||
### 数据加载
|
||||
- [x] ✅ 从 localStorage 加载司机数据
|
||||
- [x] ✅ 只显示在职司机(status === 'active')
|
||||
- [x] ✅ 司机数据存储到 state
|
||||
|
||||
### 新建对话框
|
||||
- [x] ✅ 司机下拉框显示正常
|
||||
- [x] ✅ 默认值为 "none"
|
||||
- [x] ✅ 可以选择司机
|
||||
- [x] ✅ 可以选择"不选择司机"
|
||||
- [x] ✅ 显示格式:姓名 (驾照号)
|
||||
|
||||
### 数据保存
|
||||
- [x] ✅ 选择司机时保存 driverId 和 driverName
|
||||
- [x] ✅ 不选择时 driverId 和 driverName 为 undefined
|
||||
- [x] ✅ 数据持久化到 localStorage
|
||||
|
||||
### 表单重置
|
||||
- [x] ✅ resetForm 包含 selectedDriver
|
||||
- [x] ✅ 重置为 'none'
|
||||
|
||||
### 界面布局
|
||||
- [x] ✅ 司机选择位置合理
|
||||
- [x] ✅ 表单布局优化
|
||||
- [x] ✅ 通信协议移到合理位置
|
||||
|
||||
### 详情显示
|
||||
- [x] ✅ 详情对话框显示司机信息
|
||||
- [x] ✅ 未选择司机时显示 "-"
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心价值
|
||||
|
||||
### 1. 任务分配明确
|
||||
|
||||
```
|
||||
价值:
|
||||
✅ 明确任务责任人
|
||||
✅ 避免推诿扯皮
|
||||
✅ 便于绩效考核
|
||||
```
|
||||
|
||||
### 2. 调度管理优化
|
||||
|
||||
```
|
||||
价值:
|
||||
✅ 查看司机工作量
|
||||
✅ 合理分配任务
|
||||
✅ 平衡工作负担
|
||||
```
|
||||
|
||||
### 3. 安全合规
|
||||
|
||||
```
|
||||
价值:
|
||||
✅ 显示驾照信息
|
||||
✅ 按资质分配任务
|
||||
✅ 降低安全风险
|
||||
```
|
||||
|
||||
### 4. 灵活应对
|
||||
|
||||
```
|
||||
价值:
|
||||
✅ 可选字段设计
|
||||
✅ 支持紧急情况
|
||||
✅ 不强制指定司机
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试用例
|
||||
|
||||
### 测试1: 选择司机下发
|
||||
|
||||
```
|
||||
操作:
|
||||
1. 新建下发
|
||||
2. 选择农机
|
||||
3. 选择司机:张三
|
||||
4. 填写其他信息
|
||||
5. 点击"立即下发"
|
||||
|
||||
预期:
|
||||
✅ 下发创建成功
|
||||
✅ driverId 和 driverName 已保存
|
||||
✅ 详情中显示 "司机: 张三"
|
||||
```
|
||||
|
||||
### 测试2: 不选择司机下发
|
||||
|
||||
```
|
||||
操作:
|
||||
1. 新建下发
|
||||
2. 选择农机
|
||||
3. 司机:保持"不选择司机"
|
||||
4. 填写其他信息
|
||||
5. 点击"立即下发"
|
||||
|
||||
预期:
|
||||
✅ 下发创建成功
|
||||
✅ driverId 和 driverName 为 undefined
|
||||
✅ 详情中显示 "司机: -"
|
||||
```
|
||||
|
||||
### 测试3: 切换司机选择
|
||||
|
||||
```
|
||||
操作:
|
||||
1. 新建下发
|
||||
2. 选择司机:张三
|
||||
3. 改选司机:李四
|
||||
4. 再改为:不选择司机
|
||||
5. 最后选择:王五
|
||||
6. 点击"立即下发"
|
||||
|
||||
预期:
|
||||
✅ 下发创建成功
|
||||
✅ 保存的是最后选择的"王五"
|
||||
✅ 详情中显示 "司机: 王五"
|
||||
```
|
||||
|
||||
### 测试4: 只显示在职司机
|
||||
|
||||
```
|
||||
数据准备:
|
||||
- 张三: status = 'active'
|
||||
- 李四: status = 'active'
|
||||
- 王五: status = 'inactive'(离职)
|
||||
- 赵六: status = 'suspended'(停职)
|
||||
|
||||
预期:
|
||||
✅ 下拉框只显示张三和李四
|
||||
✅ 不显示王五和赵六
|
||||
```
|
||||
|
||||
### 测试5: 无司机数据
|
||||
|
||||
```
|
||||
场景:
|
||||
localStorage 中没有司机数据
|
||||
|
||||
预期:
|
||||
✅ 下拉框只显示"不选择司机"
|
||||
✅ 没有其他选项
|
||||
✅ 不会报错
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 效果对比
|
||||
|
||||
### 更新前
|
||||
|
||||
```
|
||||
下发任务:
|
||||
- 农机:约翰迪尔拖拉机
|
||||
- 任务:耕地
|
||||
- 司机:? (不明确)
|
||||
|
||||
问题:
|
||||
❌ 不知道谁去执行
|
||||
❌ 责任不明确
|
||||
❌ 难以管理和调度
|
||||
```
|
||||
|
||||
### 更新后
|
||||
|
||||
```
|
||||
下发任务:
|
||||
- 农机:约翰迪尔拖拉机
|
||||
- 司机:张三 (A123456) ✅
|
||||
- 任务:耕地
|
||||
|
||||
优势:
|
||||
✅ 责任明确
|
||||
✅ 便于调度
|
||||
✅ 方便考核
|
||||
✅ 安全合规
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
### ✅ 主要功能
|
||||
|
||||
1. ✅ **司机下拉选择** - 选择在职司机
|
||||
2. ✅ **可选字段** - 支持不选择司机
|
||||
3. ✅ **数据关联** - 保存司机 ID 和姓名
|
||||
4. ✅ **布局优化** - 表单布局更合理
|
||||
5. ✅ **筛选显示** - 只显示在职司机
|
||||
|
||||
### 🎯 核心价值
|
||||
|
||||
- **任务明确**: 清楚知道谁负责执行
|
||||
- **调度优化**: 便于查看和分配工作
|
||||
- **安全合规**: 显示驾照,按资质分配
|
||||
- **灵活应对**: 可选字段,紧急时无需指定
|
||||
|
||||
### 📊 应用场景
|
||||
|
||||
- ✅ 指定专业司机执行复杂任务
|
||||
- ✅ 紧急任务不指定司机
|
||||
- ✅ 查看司机工作安排
|
||||
- ✅ 按驾照类型分配任务
|
||||
|
||||
---
|
||||
|
||||
**更新时间**: 2025-10-17
|
||||
**版本**: v2.5
|
||||
**状态**: ✅ **司机选择功能已完成**
|
||||
|
||||
**核心改进**: 作业方案下发增加司机选择功能,任务分配更明确,调度管理更高效!
|
||||
Reference in New Issue
Block a user