15 KiB
15 KiB
✅ 作业方案下发 - 司机选择功能
🎯 功能说明
在作业方案下发功能中增加司机选择下拉框,支持为下发任务指定司机
📦 功能更新
1️⃣ 状态管理
添加司机相关状态:
const [drivers, setDrivers] = useState<any[]>([]);
const [selectedDriver, setSelectedDriver] = useState<string>('none');
2️⃣ 数据加载
从 localStorage 加载司机数据:
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️⃣ 新建对话框 - 司机选择
添加司机选择下拉框:
<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️⃣ 数据保存
保存时关联司机信息:
const selectedDriverData = selectedDriver && selectedDriver !== 'none'
? drivers.find(d => d.id === selectedDriver)
: null;
const newDispatch: DispatchRecord = {
// ... 其他字段
driverId: selectedDriverData?.id,
driverName: selectedDriverData?.name,
// ...
};
5️⃣ 表单重置
重置时清空司机选择:
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. 下发到农机终端(包含司机信息)
司机筛选逻辑
drivers.filter(d => d.status === 'active')
筛选条件:
- ✅ status === 'active' (在职司机)
- ❌ status === 'inactive' (离职司机)
- ❌ status === 'suspended' (停职司机)
显示格式
{d.name} ({d.licenseNumber || '无驾照'})
示例:
- 张三 (A123456) - 有驾照
- 赵六 (无驾照) - 无驾照
📊 数据结构
DispatchRecord(已有字段)
interface DispatchRecord {
id: string;
dispatchNumber: string;
machineryId: string;
machineryName: string;
driverId?: string; // ✅ 已有
driverName?: string; // ✅ 已有
routePlanId?: string;
routePlanName?: string;
taskType: string;
// ... 其他字段
}
Driver(从 localStorage 加载)
interface Driver {
id: string;
name: string;
licenseNumber?: string; // 驾照号
status: 'active' | 'inactive' | 'suspended';
// ... 其他字段
}
🎯 界面布局调整
调整前(3行布局)
第一行:农机设备 | 路线方案
第二行:任务类型 | 优先级
第三行:任务描述(跨2列)
调整后(3行布局 + 司机)✅
第一行:农机设备 * | 司机 ✅
第二行:路线方案 | 任务类型 *
第三行:优先级 | 通信协议
第四行:任务描述(跨2列)
第五行:计划开始时间(跨2列)
优化点:
- ✅ 司机选择紧跟农机,逻辑连贯
- ✅ 任务类型和路线方案在一起,方便关联
- ✅ 优先级和通信协议在一起,都是设置项
- ✅ 布局更加合理和平衡
🎨 字段特性
可选字段
司机是可选字段:
- ✅ 可以不选择(灵活应对)
- ✅ 可以选择在职司机
- ❌ 不显示离职/停职司机
默认值
selectedDriver: 'none'
保存逻辑
if (selectedDriver === 'none') {
driverId: undefined
driverName: undefined
} else {
driverId: selectedDriverData.id
driverName: selectedDriverData.name
}
✅ 验证清单
数据加载
- ✅ 从 localStorage 加载司机数据
- ✅ 只显示在职司机(status === 'active')
- ✅ 司机数据存储到 state
新建对话框
- ✅ 司机下拉框显示正常
- ✅ 默认值为 "none"
- ✅ 可以选择司机
- ✅ 可以选择"不选择司机"
- ✅ 显示格式:姓名 (驾照号)
数据保存
- ✅ 选择司机时保存 driverId 和 driverName
- ✅ 不选择时 driverId 和 driverName 为 undefined
- ✅ 数据持久化到 localStorage
表单重置
- ✅ resetForm 包含 selectedDriver
- ✅ 重置为 'none'
界面布局
- ✅ 司机选择位置合理
- ✅ 表单布局优化
- ✅ 通信协议移到合理位置
详情显示
- ✅ 详情对话框显示司机信息
- ✅ 未选择司机时显示 "-"
🎯 核心价值
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) ✅
- 任务:耕地
优势:
✅ 责任明确
✅ 便于调度
✅ 方便考核
✅ 安全合规
🎉 总结
✅ 主要功能
- ✅ 司机下拉选择 - 选择在职司机
- ✅ 可选字段 - 支持不选择司机
- ✅ 数据关联 - 保存司机 ID 和姓名
- ✅ 布局优化 - 表单布局更合理
- ✅ 筛选显示 - 只显示在职司机
🎯 核心价值
- 任务明确: 清楚知道谁负责执行
- 调度优化: 便于查看和分配工作
- 安全合规: 显示驾照,按资质分配
- 灵活应对: 可选字段,紧急时无需指定
📊 应用场景
- ✅ 指定专业司机执行复杂任务
- ✅ 紧急任务不指定司机
- ✅ 查看司机工作安排
- ✅ 按驾照类型分配任务
更新时间: 2025-10-17
版本: v2.5
状态: ✅ 司机选择功能已完成
核心改进: 作业方案下发增加司机选择功能,任务分配更明确,调度管理更高效!