# 任务车辆关联关系设计 ## 关系概述 根据业务需求,任务管理系统需要建立以下关联关系: 1. **任务 ↔ 车辆**:一个任务可以关联多辆车,一辆车可以执行多个任务 2. **车辆 ↔ 机构**:每辆车归属于一个机构 3. **任务 ↔ 执行人**:每个任务分配给一个执行人 4. **执行人 ↔ 机构**:每个执行人归属于一个机构 ## 数据库关系设计 ### 1. 核心关联关系 ```mermaid erDiagram sys_task ||--o{ sys_task_vehicle : "一对多" tb_vehicle_info ||--o{ sys_task_vehicle : "一对多" sys_dept ||--o{ tb_vehicle_info : "一对多" sys_dept ||--o{ sys_task : "一对多" sys_user ||--o{ sys_task : "一对多" sys_dept ||--o{ sys_user : "一对多" sys_task { bigint task_id PK varchar task_code UK varchar task_type varchar task_status bigint creator_id FK bigint assignee_id FK bigint dept_id FK bigint vehicle_id FK } tb_vehicle_info { bigint vehicle_id PK varchar platform_code varchar vehicle_no UK varchar vehicle_type varchar vehicle_brand varchar vehicle_model varchar vehicle_color char vehicle_status varchar device_id bigint dept_id FK } sys_task_vehicle { bigint id PK bigint task_id FK bigint vehicle_id FK datetime assign_time varchar assign_by varchar status varchar remark } sys_dept { bigint dept_id PK varchar dept_name bigint parent_id } sys_user { bigint user_id PK varchar user_name bigint dept_id FK } ``` ### 2. 关联关系说明 #### 2.1 任务与车辆关联 - **关系类型**:多对多(通过中间表 `sys_task_vehicle`) - **业务规则**: - **一个任务可以分配多辆车**(如:主车+备用车、多车协同作业) - **一辆车可以执行多个任务**(按时间顺序,避免冲突) - **任务车辆关联有独立状态管理**(已分配、执行中、已完成、已取消) - **支持批量分配和取消分配** - **车辆分配时验证车辆状态和可用性** #### 2.2 车辆与机构关联 - **关系类型**:多对一 - **业务规则**: - 每辆车必须归属于一个机构 - 机构删除时,车辆归属设置为NULL(软删除) - 支持按机构查询车辆 #### 2.3 任务与执行人关联 - **关系类型**:多对一 - **业务规则**: - 每个任务分配给一个执行人 - 执行人必须与任务在同一机构或上级机构 - 支持任务重新分配 #### 2.4 执行人与机构关联 - **关系类型**:多对一 - **业务规则**: - 每个执行人归属于一个机构 - 支持机构层级权限控制 ## 数据权限控制 ### 1. 机构数据隔离 ```sql -- 查询任务时按机构过滤 SELECT t.* FROM sys_task t WHERE t.dept_id IN ( SELECT dept_id FROM sys_dept WHERE FIND_IN_SET(dept_id, @user_dept_ids) ); -- 查询车辆时按机构过滤 SELECT v.* FROM tb_vehicle_info v WHERE v.dept_id IN ( SELECT dept_id FROM sys_dept WHERE FIND_IN_SET(dept_id, @user_dept_ids) ); ``` ### 2. 权限验证规则 - **任务创建**:只能创建本机构及下级机构的任务 - **车辆分配**:只能分配本机构及下级机构的车辆 - **执行人分配**:只能分配给本机构及下级机构的用户 - **数据查询**:只能查看本机构及下级机构的数据 ## 业务场景示例 ### 1. 创建维修任务并分配多辆车 ```sql -- 1. 创建任务 INSERT INTO sys_task (task_code, task_type, task_status, creator_id, dept_id, ...) VALUES ('TASK202401150001', 'MAINTENANCE', 'PENDING', 100, 200, ...); -- 2. 分配多辆车(主车+备用车) INSERT INTO sys_task_vehicle (task_id, vehicle_id, assign_by, status, remark) VALUES (1, 10, 'admin', 'ASSIGNED', '分配主维修车'), (1, 11, 'admin', 'ASSIGNED', '分配备用维修车'), (1, 12, 'admin', 'ASSIGNED', '分配工具车'); -- 3. 分配执行人 UPDATE sys_task SET assignee_id = 150 WHERE task_id = 1; ``` ### 2. 查询机构下的所有任务和车辆 ```sql -- 查询机构任务 SELECT t.task_code, t.task_type, t.task_status, u.user_name as assignee_name, d.dept_name FROM sys_task t LEFT JOIN sys_user u ON t.assignee_id = u.user_id LEFT JOIN sys_dept d ON t.dept_id = d.dept_id WHERE t.dept_id = 200; -- 查询机构车辆 SELECT v.vehicle_no, v.vehicle_type, v.vehicle_status, d.dept_name FROM tb_vehicle_info v LEFT JOIN sys_dept d ON v.dept_id = d.dept_id WHERE v.dept_id = 200; ``` ### 3. 查询任务的车辆分配情况 ```sql SELECT t.task_code, t.task_type, v.vehicle_no, v.vehicle_type, tv.assign_time, tv.status, tv.remark FROM sys_task t LEFT JOIN sys_task_vehicle tv ON t.task_id = tv.task_id LEFT JOIN tb_vehicle_info v ON tv.vehicle_id = v.vehicle_id WHERE t.task_id = 1; ``` ## 接口设计扩展 ### 1. 车辆管理接口 ```javascript // 查询机构车辆列表 export function listVehicleByDept(deptId, query) { return request({ url: '/api/vehicle/list-by-dept/' + deptId, method: 'get', params: query }) } // 查询可用车辆(未分配任务的车辆) export function listAvailableVehicles(deptId, taskType) { return request({ url: '/api/vehicle/available', method: 'get', params: { deptId, taskType } }) } ``` ### 2. 任务车辆分配接口 ```javascript // 批量分配车辆 export function assignVehiclesToTask(taskId, vehicleIds, remark) { return request({ url: '/api/task/' + taskId + '/assign-vehicles', method: 'post', data: { vehicleIds, remark } }) } // 查询任务车辆使用情况 export function getTaskVehicleUsage(taskId) { return request({ url: '/api/task/' + taskId + '/vehicle-usage', method: 'get' }) } ``` ## 数据一致性保证 ### 1. 外键约束 - 任务表引用车辆表:`ON DELETE SET NULL` - 任务车辆关联表:`ON DELETE CASCADE` - 车辆表引用机构表:`ON DELETE SET NULL` ### 2. 业务规则验证 - 车辆分配时验证车辆状态(必须为正常状态) - 任务分配时验证执行人权限(同机构或上级机构) - 机构删除时处理关联数据(软删除或转移) ### 3. 事务控制 ```java @Transactional public void assignMultipleVehiclesToTask(Long taskId, List vehicleIds, String remark) { // 1. 验证任务状态 Task task = taskMapper.selectById(taskId); if (task.getStatus() == TaskStatus.COMPLETED) { throw new BusinessException("已完成的任务不能分配车辆"); } List assignedVehicles = new ArrayList<>(); for (Long vehicleId : vehicleIds) { // 2. 验证车辆状态和可用性 Vehicle vehicle = vehicleMapper.selectById(vehicleId); if (vehicle.getStatus() != VehicleStatus.ACTIVE) { throw new BusinessException("车辆ID " + vehicleId + " 状态异常,不能分配"); } // 3. 检查车辆是否已被其他任务占用 if (isVehicleAssignedToOtherTask(vehicleId, taskId)) { throw new BusinessException("车辆ID " + vehicleId + " 已被其他任务占用"); } // 4. 创建关联记录 TaskVehicle taskVehicle = new TaskVehicle(); taskVehicle.setTaskId(taskId); taskVehicle.setVehicleId(vehicleId); taskVehicle.setStatus(TaskVehicleStatus.ASSIGNED); taskVehicle.setRemark(remark); taskVehicleMapper.insert(taskVehicle); assignedVehicles.add(taskVehicle); } // 5. 记录操作日志 logTaskOperation(taskId, "ASSIGN_MULTIPLE_VEHICLES", "分配了 " + vehicleIds.size() + " 辆车: " + vehicleIds.toString()); } @Transactional public void unassignVehicleFromTask(Long taskId, Long vehicleId) { // 1. 验证任务车辆关联是否存在 TaskVehicle taskVehicle = taskVehicleMapper.selectByTaskAndVehicle(taskId, vehicleId); if (taskVehicle == null) { throw new BusinessException("任务车辆关联不存在"); } // 2. 验证是否可以取消分配 if (taskVehicle.getStatus() == TaskVehicleStatus.COMPLETED) { throw new BusinessException("已完成的任务车辆关联不能取消"); } // 3. 删除关联记录 taskVehicleMapper.deleteById(taskVehicle.getId()); // 4. 记录操作日志 logTaskOperation(taskId, "UNASSIGN_VEHICLE", "取消分配车辆ID: " + vehicleId); } ``` ## 总结 通过以上设计,实现了任务、车辆、机构和执行人之间的完整关联关系: 1. **数据完整性**:通过外键约束保证数据一致性 2. **权限控制**:基于机构的数据隔离和权限验证 3. **业务灵活性**:支持多车辆分配和状态管理 4. **扩展性**:预留了设备ID等字段,支持GPS定位等功能扩展 这个设计既满足了当前的业务需求,又为未来的功能扩展留下了空间。