17 KiB
17 KiB
🔧 负载管理解绑操作升级说明
📅 更新时间
2025-10-16
🎯 更新内容
将负载管理中的设备解绑(拆卸)操作从浏览器原生的 confirm() 对话框升级为系统内的 AlertDialog 二次确认提示。
📊 修改对比
修改前 ❌
使用浏览器原生对话框:
<Button
variant="ghost"
size="sm"
onClick={() => {
if (confirm('确定要拆卸此设备吗?')) {
handleUnmount(device.id);
}
}}
>
<Unlink className="w-4 h-4" />
</Button>
问题:
- ❌ 样式无法自定义,与系统风格不统一
- ❌ 浏览器原生弹窗,体验不佳
- ❌ 移动端显示效果差
- ❌ 无法添加详细说明信息
- ❌ 不符合现代UI/UX设计规范
视觉效果:
┌──────────────────────────────┐
│ [?] 确定要拆卸此设备吗? │
│ │
│ [取消] [确定] │
└──────────────────────────────┘
浏览器原生样式,无法定制
修改后 ✅
使用系统 AlertDialog 组件:
// 1. 点击按钮触发确认对话框
<Button
variant="ghost"
size="sm"
onClick={() => handleUnmountClick(device.id)}
>
<Unlink className="w-4 h-4" />
</Button>
// 2. AlertDialog 确认对话框
<AlertDialog open={showUnmountConfirm} onOpenChange={setShowUnmountConfirm}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>确认拆卸设备</AlertDialogTitle>
<AlertDialogDescription>
确定要拆卸此设备吗?拆卸后设备状态将变为"已拆卸",可以重新挂载到其他农机上。
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => setPendingUnmountId(null)}>
取消
</AlertDialogCancel>
<AlertDialogAction onClick={confirmUnmount} className="bg-red-600 hover:bg-red-700">
确认拆卸
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
优势:
- ✅ 样式统一,符合系统设计风格
- ✅ 可以添加详细的说明信息
- ✅ 响应式设计,移动端友好
- ✅ 按钮颜色可自定义(红色警告色)
- ✅ 更好的用户体验和可访问性
视觉效果:
┌────────────────────────────────────────────┐
│ 确认拆卸设备 │
│ │
│ 确定要拆卸此设备吗?拆卸后设备状态将 │
│ 变为"已拆卸",可以重新挂载到其他农机上。 │
│ │
│ [取消] [确认拆卸] 🔴 │
└────────────────────────────────────────────┘
系统风格,绿色农业主题,红色警告按钮
🔄 实现流程
操作流程图
用户点击拆卸按钮
↓
调用 handleUnmountClick(deviceId)
↓
设置 pendingUnmountId = deviceId
↓
显示 AlertDialog (showUnmountConfirm = true)
↓
┌──────────────────┐
│ 用户点击"取消" │ → 关闭对话框,清空 pendingUnmountId
└──────────────────┘
│ 用户点击"确认拆卸"
↓
调用 confirmUnmount()
↓
更新设备状态为 "unmounted"
↓
保存到 localStorage
↓
显示成功提示
↓
关闭对话框,清空 pendingUnmountId
核心函数
1. 点击拆卸按钮
const handleUnmountClick = (deviceId: string) => {
setPendingUnmountId(deviceId);
setShowUnmountConfirm(true);
};
功能:
- 记录待拆卸的设备ID
- 显示确认对话框
2. 确认拆卸
const confirmUnmount = () => {
if (pendingUnmountId) {
const updatedDevices = devices.map(d => {
if (d.id === pendingUnmountId && d.status === 'mounted') {
return {
...d,
status: 'unmounted' as const,
unmountedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
}
return d;
});
setDevices(updatedDevices);
localStorage.setItem('smart_agriculture_mounted_devices', JSON.stringify(updatedDevices));
toast.success('设备拆卸成功');
}
setShowUnmountConfirm(false);
setPendingUnmountId(null);
};
功能:
- 更新设备状态为 "unmounted"
- 记录拆卸时间
- 保存到 localStorage
- 显示成功提示
- 清理状态
📁 修改文件
核心文件
- ✅
/components/machinery/load/LoadDevice.tsx
详细变更
1. 导入 AlertDialog 组件
// 新增导入
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '../../ui/alert-dialog';
2. 添加状态管理
// 新增状态
const [showUnmountConfirm, setShowUnmountConfirm] = useState(false);
const [pendingUnmountId, setPendingUnmountId] = useState<string | null>(null);
3. 重构拆卸逻辑
// 修改前
const handleUnmount = (deviceId: string) => {
// 直接拆卸逻辑
};
// 修改后
const handleUnmountClick = (deviceId: string) => {
// 触发确认对话框
};
const confirmUnmount = () => {
// 确认后执行拆卸
};
4. 更新按钮事件
// 修改前
onClick={() => {
if (confirm('确定要拆卸此设备吗?')) {
handleUnmount(device.id);
}
}}
// 修改后
onClick={() => handleUnmountClick(device.id)}
5. 添加 AlertDialog 组件
<AlertDialog open={showUnmountConfirm} onOpenChange={setShowUnmountConfirm}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>确认拆卸设备</AlertDialogTitle>
<AlertDialogDescription>
确定要拆卸此设备吗?拆卸后设备状态将变为"已拆卸",可以重新挂载到其他农机上。
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => setPendingUnmountId(null)}>
取消
</AlertDialogCancel>
<AlertDialogAction onClick={confirmUnmount} className="bg-red-600 hover:bg-red-700">
确认拆卸
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
🎨 视觉设计
AlertDialog 样式特点
标题
确认拆卸设备
- 清晰的操作说明
- 标准字体大小
描述
确定要拆卸此设备吗?拆卸后设备状态将变为"已拆卸",
可以重新挂载到其他农机上。
- 详细的操作说明
- 告知用户操作后果
- 提示后续可用操作
按钮样式
取消按钮:
<AlertDialogCancel>
取消
</AlertDialogCancel>
- 默认灰色样式
- 左侧位置
- 安全操作
确认按钮:
<AlertDialogAction className="bg-red-600 hover:bg-red-700">
确认拆卸
</AlertDialogAction>
- 🔴 红色警告色(
bg-red-600) - 🔴 悬停加深(
hover:bg-red-700) - 右侧位置
- 危险操作提示
响应式设计
桌面端:
┌────────────────────────────────────────────┐
│ 确认拆卸设备 │
│ │
│ 确定要拆卸此设备吗?拆卸后设备状态将 │
│ 变为"已拆卸",可以重新挂载到其他农机上。 │
│ │
│ [取消] [确认拆卸] 🔴 │
└────────────────────────────────────────────┘
宽度适中,居中显示
移动端:
┌──────────────────────────┐
│ 确认拆卸设备 │
│ │
│ 确定要拆卸此设备吗? │
│ 拆卸后设备状态将变为 │
│ "已拆卸",可以重新挂 │
│ 载到其他农机上。 │
│ │
│ [取消] │
│ [确认拆卸] 🔴 │
└──────────────────────────┐
自适应宽度,按钮垂直排列
💡 功能特性
1. 安全确认
防误操作:
- ✅ 两步确认流程
- ✅ 清晰的操作说明
- ✅ 红色警告按钮
- ✅ 可以取消操作
2. 用户体验
友好提示:
- ✅ 说明操作后果
- ✅ 提示后续可用操作
- ✅ 成功提示(Toast)
- ✅ 平滑的动画效果
3. 数据处理
完整记录:
{
...device,
status: 'unmounted', // 状态改为已拆卸
unmountedAt: '2025-10-16T...', // 记录拆卸时间
updatedAt: '2025-10-16T...', // 更新时间戳
}
4. 状态管理
清晰的状态流转:
挂载中 (mounted)
↓
点击拆卸按钮
↓
显示确认对话框
↓ [确认]
已拆卸 (unmounted)
📋 完整示例
场景:拆卸北斗终端
1. 初始状态
┌─────────────────────────────────────────────────────┐
│ 约翰迪尔拖拉机 [挂载设备] │
│ JD6B-1504 │
├─────────────────────────────────────────────────────┤
│ 设备名称 │ 设备类型 │ 序列号 │ 操作 │
│ 北斗终端-001 │ 北斗终端 │ BD2001234567│ [🔗] │
└─────────────────────────────────────────────────────┘
2. 点击拆卸按钮
handleUnmountClick('device-1')
↓
setPendingUnmountId('device-1')
↓
setShowUnmountConfirm(true)
3. 显示确认对话框
┌────────────────────────────────────────────┐
│ 确认拆卸设备 │
│ │
│ 确定要拆卸此设备吗?拆卸后设备状态将 │
│ 变为"已拆卸",可以重新挂载到其他农机上。 │
│ │
│ [取消] [确认拆卸] 🔴 │
└────────────────────────────────────────────┘
4. 点击"确认拆卸"
confirmUnmount()
↓
更新设备状态为 'unmounted'
↓
localStorage.setItem(...)
↓
toast.success('设备拆卸成功') ✅
5. 拆卸后状态
┌─────────────────────────────────────────────────────┐
│ 约翰迪尔拖拉机 [挂载设备] │
│ JD6B-1504 │
├─────────────────────────────────────────────────────┤
│ 暂无挂载设备 │
│ │
└─────────────────────────────────────────────────────┘
统计数据更新:
- 总设备数: 1
- 已挂载: 0 ⬇️
- 已拆卸: 1 ⬆️
🔍 与其他确认对话框的对比
驾驶员任务管理
已使用 AlertDialog:
- ✅ 接收任务确认
- ✅ 取消任务确认
- ✅ 完成任务确认
- ✅ 终止任务确认
负载管理(本次更新)
新增 AlertDialog:
- ✅ 拆卸设备确认
一致性
所有危险操作都使用相同的确认模式:
// 统一的 AlertDialog 结构
<AlertDialog>
<AlertDialogHeader>
<AlertDialogTitle>操作标题</AlertDialogTitle>
<AlertDialogDescription>详细说明</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>取消</AlertDialogCancel>
<AlertDialogAction className="bg-red-600">确认</AlertDialogAction>
</AlertDialogFooter>
</AlertDialog>
统一特点:
- ✅ 相同的组件结构
- ✅ 一致的交互逻辑
- ✅ 统一的视觉风格
- ✅ 标准的状态管理
✅ 验证清单
功能验证
- 点击拆卸按钮显示 AlertDialog
- 点击"取消"关闭对话框,不执行拆卸
- 点击"确认拆卸"执行拆卸操作
- 拆卸成功显示 Toast 提示
- 设备状态更新为"已拆卸"
- 统计数据实时更新
视觉验证
- 对话框样式符合系统风格
- "确认拆卸"按钮为红色警告色
- 描述文字清晰易懂
- 响应式布局正常
- 动画效果流畅
数据验证
- 设备状态正确更新
- 拆卸时间正确记录
- localStorage 数据一致
- 页面数据即时更新
交互验证
- 键盘操作支持(ESC关闭)
- 点击遮罩层关闭
- 多次操作状态正确
- 无内存泄漏
🎉 升级收益
用户体验提升
修改前:
- ❌ 突兀的浏览器弹窗
- ❌ 信息展示有限
- ❌ 样式不统一
- ❌ 移动端体验差
修改后:
- ✅ 优雅的系统对话框
- ✅ 详细的操作说明
- ✅ 统一的视觉风格
- ✅ 响应式友好
开发维护提升
修改前:
- ❌ 浏览器API,无法自定义
- ❌ 不符合现代UI规范
- ❌ 难以测试
修改后:
- ✅ React组件,易于维护
- ✅ 符合系统设计规范
- ✅ 方便单元测试
- ✅ 代码结构清晰
系统一致性
统一的确认模式:
- ✅ 所有危险操作使用 AlertDialog
- ✅ 相同的交互逻辑
- ✅ 一致的视觉体验
- ✅ 标准的状态管理
📊 使用统计
系统内 AlertDialog 使用情况
| 模块 | 功能 | 状态 |
|---|---|---|
| 驾驶员任务管理 | 接收任务 | ✅ 已使用 |
| 驾驶员任务管理 | 取消任务 | ✅ 已使用 |
| 驾驶员任务管理 | 完成任务 | ✅ 已使用 |
| 驾驶员任务管理 | 终止任务 | ✅ 已使用 |
| 负载管理 | 拆卸设备 | ✅ 本次新增 |
confirm() 使用情况
| 模块 | 功能 | 状态 |
|---|---|---|
| 负载管理 | 拆卸设备 | ✅ 已移除 |
| 其他模块 | - | 待检查 |
🔮 后续优化建议
1. 批量操作支持
建议: 支持批量拆卸设备
const [selectedDevices, setSelectedDevices] = useState<string[]>([]);
const confirmBatchUnmount = () => {
// 批量拆卸逻辑
};
2. 拆卸原因记录
建议: 记录拆卸原因
interface UnmountReason {
reason: string;
remarks?: string;
}
3. 撤销操作
建议: 提供拆卸撤销功能
const undoUnmount = (deviceId: string) => {
// 撤销拆卸,恢复为挂载状态
};
4. 历史记录
建议: 记录完整的挂载/拆卸历史
interface MountHistory {
action: 'mount' | 'unmount';
timestamp: string;
operator: string;
remarks?: string;
}
📝 注意事项
1. 状态管理
重要: 确保正确清理状态
// ✅ 正确:取消时清理状态
<AlertDialogCancel onClick={() => setPendingUnmountId(null)}>
取消
</AlertDialogCancel>
// ❌ 错误:未清理状态
<AlertDialogCancel>
取消
</AlertDialogCancel>
2. 操作权限
建议: 根据用户角色控制拆卸权限
const canUnmount = currentUser.role === 'admin' || currentUser.role === 'technician';
<Button
disabled={!canUnmount}
onClick={() => handleUnmountClick(device.id)}
>
<Unlink className="w-4 h-4" />
</Button>
3. 数据验证
确保: 只能拆卸已挂载的设备
const confirmUnmount = () => {
if (pendingUnmountId) {
const device = devices.find(d => d.id === pendingUnmountId);
if (device?.status !== 'mounted') {
toast.error('只能拆卸已挂载的设备');
return;
}
// 执行拆卸
}
};
🎓 总结
成功将负载管理的设备拆卸操作从浏览器原生 confirm() 升级为系统内的 AlertDialog 二次确认提示,提升了用户体验和系统一致性。
核心改进:
- ✅ 引入 AlertDialog 组件
- ✅ 重构状态管理和事件处理
- ✅ 添加详细的操作说明
- ✅ 使用红色警告按钮
- ✅ 保持系统视觉风格统一
用户收益:
- 🎨 更好的视觉体验
- 📱 更友好的移动端支持
- 💡 更清晰的操作指引
- 🛡️ 更安全的操作确认
开发收益:
- 🧩 更易维护的代码结构
- 🔄 更统一的确认模式
- ✅ 更方便的测试
- 📚 更好的代码可读性
更新人: AI助手
更新日期: 2025-10-16
版本: v1.0
影响范围: 负载管理 - 设备拆卸功能