为转运任务增加取消原因记录功能,当用户取消任务时,需要选择取消原因并记录取消人和取消时间。
执行SQL脚本:sql/add_cancel_reason_fields.sql
ALTER TABLE sys_task_emergency
ADD COLUMN cancel_reason VARCHAR(50) COMMENT '取消原因(关联数据字典task_cancel_reason)';
ALTER TABLE sys_task_emergency
ADD COLUMN cancel_by VARCHAR(64) COMMENT '取消人';
ALTER TABLE sys_task_emergency
ADD COLUMN cancel_time DATETIME COMMENT '取消时间';
执行SQL脚本:sql/insert_dict_task_cancel_reason.sql
添加数据字典类型 task_cancel_reason,包含26个取消原因选项:
文件: ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
添加三个字段属性:
- private String cancelReason; - 取消原因
- private String cancelBy; - 取消人
- private java.util.Date cancelTime; - 取消时间
文件: ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
在resultMap、selectSysTaskEmergencyVo、insertSysTaskEmergency、updateSysTaskEmergency中添加三个字段的映射和处理。
文件: ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
private String cancelReason; // 取消原因(关联数据字典task_cancel_reason)
在状态变更方法中添加取消原因处理逻辑:
// 如果是取消状态,保存取消原因
if (newStatus == TaskStatus.CANCELLED && StringUtils.isNotEmpty(request.getCancelReason())) {
sysTaskService.saveCancelInfo(taskId, request.getCancelReason());
}
文件: ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
添加接口方法:
/**
* 保存任务取消信息(仅限转运任务)
*
* @param taskId 任务ID
* @param cancelReason 取消原因(数据字典task_cancel_reason的value)
* @return 结果
*/
public int saveCancelInfo(Long taskId, String cancelReason);
文件: ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
实现saveCancelInfo方法,保存取消原因、取消人和取消时间:
@Override
@Transactional
public int saveCancelInfo(Long taskId, String cancelReason) {
// 获取任务信息
SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
if (task == null) {
throw new RuntimeException("任务不存在");
}
// 只有转运任务才保存取消信息
if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
return 0;
}
// 获取转运任务扩展信息
SysTaskEmergency emergency = sysEmergencyTaskService.selectSysTaskEmergencyByTaskId(taskId);
if (emergency == null) {
return 0;
}
// 设置取消信息
emergency.setCancelReason(cancelReason);
emergency.setCancelBy(SecurityUtils.getUsername());
emergency.setCancelTime(DateUtils.getNowDate());
emergency.setUpdateBy(SecurityUtils.getUsername());
emergency.setUpdateTime(DateUtils.getNowDate());
// 更新数据库
return sysTaskEmergencyMapper.updateSysTaskEmergency(emergency);
}
文件: app/pagesTask/detail.vue
data() {
return {
taskDetail: null,
taskId: null,
paymentInfo: null,
cancelReasonList: [], // 取消原因列表
showCancelDialog: false, // 显示取消原因对话框
selectedCancelReason: '' // 选中的取消原因
}
}
onLoad(options) {
this.taskId = options.id
this.loadTaskDetail()
this.loadCancelReasonDict() // 加载取消原因字典
}
case 'cancel':
// 取消 -> 显示取消原因选择对话框
this.showCancelReasonDialog();
break;
loadCancelReasonDict() - 从后端加载取消原因字典showCancelReasonDialog() - 显示取消原因选择弹窗confirmCancelTask() - 确认取消任务closeCancelDialog() - 关闭取消弹窗selectCancelReason(e) - 选择取消原因updateTaskStatusWithCancelReason() - 带取消原因的状态更新getCancelReasonLabel() - 根据value获取label显示添加cancelReason参数,在状态更新请求中传递取消原因:
// 如果有取消原因,添加到请求数据中
if (cancelReason) {
statusData.cancelReason = cancelReason
}
取消原因选择弹窗:
<uni-popup ref="cancelPopup" type="center" :is-mask-click="false">
<view class="cancel-dialog">
<view class="dialog-title">请选择取消原因</view>
<picker mode="selector" :range="cancelReasonList" range-key="label" @change="selectCancelReason">
<view class="reason-picker">
<view class="picker-label">取消原因</view>
<view class="picker-value">
{{ selectedCancelReason ? cancelReasonList.find(r => r.value === selectedCancelReason)?.label : '请选择' }}
</view>
<uni-icons type="arrowright" size="16"></uni-icons>
</view>
</picker>
<view class="dialog-buttons">
<button class="cancel-btn" @click="closeCancelDialog">取消</button>
<button class="confirm-btn" @click="confirmCancelTask">确定</button>
</view>
</view>
</uni-popup>
取消信息显示区域(仅在任务已取消且有取消原因时显示):
<view class="detail-section" v-if="taskDetail.taskStatus === 'CANCELLED' && taskDetail.emergencyInfo && taskDetail.emergencyInfo.cancelReason">
<view class="section-title">取消信息</view>
<view class="info-item">
<view class="label">取消原因</view>
<view class="value">{{ getCancelReasonLabel(taskDetail.emergencyInfo.cancelReason) }}</view>
</view>
<view class="info-item" v-if="taskDetail.emergencyInfo.cancelBy">
<view class="label">取消人</view>
<view class="value">{{ taskDetail.emergencyInfo.cancelBy }}</view>
</view>
<view class="info-item" v-if="taskDetail.emergencyInfo.cancelTime">
<view class="label">取消时间</view>
<view class="value">{{ formatTime(taskDetail.emergencyInfo.cancelTime) }}</view>
</view>
</view>
为取消原因弹窗添加样式,包括对话框、选择器和按钮样式。
在任务详情页,如果任务状态为"已取消"且记录了取消原因,会在费用信息下方显示"取消信息"区块,包括:
- 取消原因(显示中文标签)
- 取消人
- 取消时间
sql/add_cancel_reason_fields.sql - 添加数据库字段sql/insert_dict_task_cancel_reason.sql - 插入数据字典ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.javaruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xmlruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.javaruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.javaruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.javaapp/pagesTask/detail.vue