wlzboy
2026-02-05 57e98ac3f59e9ca12d3fdbc6f89c9c0b1f86be4d
app/pages/index.vue
@@ -153,7 +153,7 @@
               
                <view class="info-item">
                  <view class="label">执行人员:</view>
                  <view class="value">{{ task.assignee }}</view>
                  <view class="value">{{ getAssigneesDisplay(task) }}</view>
                </view>
              </view>
            </view>
@@ -232,6 +232,26 @@
        </view>
      </view>
    </scroll-view>
    <!-- 取消原因选择对话框 -->
    <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">
              {{ selectedCancelReasonLabel }}
            </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>
</template>
@@ -241,6 +261,7 @@
import { getUserProfile } from "@/api/system/user";
import { getUserBoundVehicle } from "@/api/vehicle";
import { getUnreadCount } from "@/api/message";
import { getDicts } from "@/api/dict";
import { formatDateTime } from "@/utils/common";
import subscribeManager from "@/utils/subscribe";
import { checkTaskCanDepart } from "@/utils/taskValidator";
@@ -268,6 +289,12 @@
      currentPage: 1,
      pageSize: 10,
      hasMore: true,
      // 取消原因相关
      cancelReasonList: [], // 取消原因列表
      showCancelDialog: false, // 显示取消原因对话框
      selectedCancelReason: '', // 选中的取消原因
      currentCancelTask: null // 当前要取消的任务
    };
  },
  computed: {
@@ -288,6 +315,15 @@
          "IN_PROGRESS",
        ].includes(task.taskStatus);
      });
    },
    // 获取选中的取消原因标签(用于弹窗显示)
    selectedCancelReasonLabel() {
      if (!this.selectedCancelReason || !this.cancelReasonList.length) {
        return '请选择'
      }
      const reason = this.cancelReasonList.find(r => r.value === this.selectedCancelReason)
      return reason ? reason.label : '请选择'
    },
  },
  onLoad() {
@@ -310,6 +346,8 @@
    this.loadRunningTasks();
    // 加载未读消息数量
    this.loadUnreadMessageCount();
    // 加载取消原因字典
    this.loadCancelReasonDict();
  },
  onShow() {
    // 检查用户是否已登录
@@ -569,18 +607,44 @@
    // 获取目的地显示内容(转运任务显示转入医院名称或详细地址)
    getEndLocationDisplay(task) {
      // 如果是转运任务且有emergencyInfo信息
      // console.log("get end location display",task.taskType,task.emergencyInfo.hospitalInAddress,task.showTaskCode);
      if (task.taskType === 'EMERGENCY_TRANSFER' && task.emergencyInfo) {
        // console.log('转运任务 - 紧急信息:', task.emergencyInfo)
        // 优先显示转入医院名称
        if (task.emergencyInfo.hospitalInName) {
          if(task.emergencyInfo.hospitalInName.includes("家中")){
            return task.emergencyInfo.destinationAddress;
          }
          return task.emergencyInfo.hospitalInName;
        }
        // console.log("get end local",task.emergencyInfo.hospitalInAddress);
        return task.emergencyInfo.hospitalInAddress;
        // if (task.emergencyInfo.hospitalInName) {
        //   if(task.emergencyInfo.hospitalInName.includes("家中")){
        //     return task.emergencyInfo.destinationAddress;
        //   }
        //   return task.emergencyInfo.hospitalInName;
        // }
        // // 如果没有转入医院名称,但有转入医院地址,则显示地址
        // if (task.emergencyInfo.hospitalInAddress) {
        //   return task.emergencyInfo.hospitalInAddress;
        // }
      }
      // 其他情况使用原来的endLocation
      return this.formatAddress(task.endLocation || "未设置");
    },
    // 获取执行人员显示(从 assignees 数组中提取 userName)
    getAssigneesDisplay(task) {
      // 如果有 assignees 数组且不为空
      if (task.assignees && task.assignees.length > 0) {
        // 提取所有 userName,过滤掉空值
        const userNames = task.assignees
          .map(assignee => assignee.userName)
          .filter(name => name); // 过滤掉 null/undefined/空字符串
        // 如果有有效的用户名,用逗号连接
        if (userNames.length > 0) {
          return userNames.join('、');
        }
      }
      // 如果没有 assignees 数组,使用旧的 assigneeName 或 assignee 字段
      return task.assigneeName || task.assignee || '未分配';
    },
    // 转换状态格式(将数据库状态转换为UI使用的状态)
@@ -707,13 +771,9 @@
          break;
        case "cancel":
          // 取消 -> 二次确认后状态变为已取消
          this.$modal
            .confirm("确定要取消此任务吗?")
            .then(() => {
              this.updateTaskStatus(task.taskId, "CANCELLED", "任务已取消");
            })
            .catch(() => {});
          // 取消 -> 显示取消原因选择对话框
          this.currentCancelTask = task;
          this.showCancelReasonDialog();
          break;
        case "arrive":
@@ -760,6 +820,56 @@
      this.getLocationAndUpdateStatus(taskId, status, remark);
    },
    
    // 加载取消原因字典
    loadCancelReasonDict() {
      getDicts('task_cancel_reason').then(response => {
        if (response.code === 200 && response.data) {
          this.cancelReasonList = response.data.map(item => ({
            value: item.dictValue,
            label: item.dictLabel
          }))
        }
      }).catch(error => {
        console.error('加载取消原因字典失败:', error)
      })
    },
    // 显示取消原因对话框
    showCancelReasonDialog() {
      this.selectedCancelReason = ''
      this.$refs.cancelPopup.open()
    },
    // 确认取消任务
    confirmCancelTask() {
      if (!this.selectedCancelReason) {
        this.$modal.showToast('请选择取消原因')
        return
      }
      this.$refs.cancelPopup.close()
      // 调用更新状态方法,传递取消原因
      this.updateTaskStatusWithCancelReason(this.currentCancelTask.taskId, 'CANCELLED', '任务已取消', this.selectedCancelReason)
    },
    // 取消对话框关闭
    closeCancelDialog() {
      this.$refs.cancelPopup.close()
      this.selectedCancelReason = ''
      this.currentCancelTask = null
    },
    // 选择取消原因
    selectCancelReason(e) {
      this.selectedCancelReason = this.cancelReasonList[e.detail.value].value
    },
    // 带取消原因的状态更新
    updateTaskStatusWithCancelReason(taskId, status, remark, cancelReason) {
      this.getLocationAndUpdateStatus(taskId, status, remark, cancelReason)
    },
    // 检查知情同意书附件并更新状态
    async checkConsentAttachmentAndThen(taskId, status, remark) {
      try {
@@ -767,12 +877,19 @@
          title: '检查附件...'
        });
        
        const response = await checkTaskConsentAttachment(taskId);
        // 注意:这里会被请求拦截器处理,code !== 200 时会 reject
        const response = await checkTaskConsentAttachment(taskId).catch(err => {
          // 拦截器 reject 的情况,返回一个默认对象
          console.log('请求被拦截器 reject,err:', err);
          return { code: -1, msg: '未上传知情同意书' };
        });
        
        uni.hideLoading();
        console.log('检查附件结果:', response);
        
        if (response.code === 200) {
        if (response && response.code === 200) {
          // 已上传知情同意书,继续更新状态
          console.log('已上传知情同意书,继续完成任务');
          this.$modal
            .confirm("确认任务已完成?")
            .then(() => {
@@ -780,25 +897,26 @@
            })
            .catch(() => {});
        } else {
          // 未上传知情同意书,显示提示
          this.$modal.confirm('任务未上传知情同意书,无法完成任务。是否现在去上传?').then(() => {
          // 未上传知情同意书或其他错误,阻止完成
          const message = (response && response.msg) || '任务未上传知情同意书,无法完成任务';
          console.log('未上传知情同意书,阻止完成');
          this.$modal.confirm(message + '。是否现在去上传?').then(() => {
            // 跳转到任务详情页上传附件
            this.$tab.navigateTo(`/pagesTask/detail?id=${taskId}`);
          }).catch(() => {});
        }
      } catch (error) {
        uni.hideLoading();
        console.error('检查附件失败:', error);
        console.error('检查附件异常:', error);
        
        // 如果检查失败,询问用户是否继续
        this.$modal.confirm('检查附件状态失败,是否继续完成任务?').then(() => {
          this.updateTaskStatus(taskId, status, remark);
        }).catch(() => {});
        // 如果检查失败(网络异常等),不允许完成任务
        this.$modal.showToast('检查附件状态失败,无法完成任务');
      }
    },
    // 获取位置信息并更新状态
    getLocationAndUpdateStatus(taskId, status, remark) {
    getLocationAndUpdateStatus(taskId, status, remark, cancelReason) {
      const that = this;
      // 使用uni.getLocation获取GPS位置
@@ -825,6 +943,11 @@
            speed: res.speed,
            heading: res.direction || res.heading,
          };
          // 如果有取消原因,添加到请求数据中
          if (cancelReason) {
            statusData.cancelReason = cancelReason
          }
          changeTaskStatus(taskId, statusData)
            .then((response) => {
@@ -846,6 +969,11 @@
                taskStatus: status,
                remark: remark,
              };
              // 如果有取消原因,添加到请求数据中
              if (cancelReason) {
                statusData.cancelReason = cancelReason
              }
              changeTaskStatus(taskId, statusData)
                .then((response) => {
@@ -1292,6 +1420,10 @@
                font-size: 26rpx;
                flex: 1;
                word-break: break-all;
                overflow-wrap: break-word;
                line-height: 1.5;
                max-height: none;
                overflow: visible;
              }
            }
          }
@@ -1383,4 +1515,67 @@
    }
  }
}
// 取消原因对话框样式
.cancel-dialog {
  width: 600rpx;
  background-color: white;
  border-radius: 20rpx;
  padding: 40rpx;
  .dialog-title {
    font-size: 32rpx;
    font-weight: bold;
    text-align: center;
    margin-bottom: 30rpx;
    color: #333;
  }
  .reason-picker {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20rpx 30rpx;
    background-color: #f5f5f5;
    border-radius: 10rpx;
    margin-bottom: 30rpx;
    .picker-label {
      font-size: 28rpx;
      color: #666;
    }
    .picker-value {
      flex: 1;
      text-align: right;
      margin: 0 20rpx;
      font-size: 28rpx;
      color: #333;
    }
  }
  .dialog-buttons {
    display: flex;
    gap: 20rpx;
    button {
      flex: 1;
      height: 80rpx;
      line-height: 80rpx;
      border-radius: 10rpx;
      font-size: 28rpx;
      border: none;
    }
    .cancel-btn {
      background-color: #f5f5f5;
      color: #666;
    }
    .confirm-btn {
      background-color: #007AFF;
      color: white;
    }
  }
}
</style>