WXL
昨天 c80bc467a41daa6cbae4e5515a300a8ca98cfeaa
pagesSub/case/transfer.vue
@@ -72,7 +72,7 @@
            <view class="info">
              <text class="case-no">{{ item.caseNo || item.reportId }}</text>
              <text class="patient"
                >{{ item.patName }} | {{ getGenderText(item.sex) }} |
                >{{ item.patName }} | {{ item.sex == 1 ? "男" : "女" }} |
                {{ item.age }}岁</text
              >
            </view>
@@ -115,27 +115,41 @@
            }}</text>
          </view>
          <view class="actions">
            <!-- 待转运(1):可以开始转运 -->
            <button
              class="action-btn"
              v-if="item.transitStatus === 1"
              @tap.stop="startTransport(item)"
              class="action-btn primary"
              v-if="item.transitStatus == 1"
              @tap.stop="handleStartTransport(item)"
            >
              开始转运
            </button>
            <!-- 转运中(2):可以完成或取消 -->
            <button
              class="action-btn"
              v-if="item.transitStatus === 2"
              @tap.stop="completeTransport(item)"
              class="action-btn success"
              v-if="item.transitStatus == 2"
              @tap.stop="handleCompleteTransport(item)"
            >
              完成转运
            </button>
            <button
              class="action-btn secondary"
              v-if="item.transitStatus != 3"
              @tap.stop="editTransport(item)"
              class="action-btn danger"
              v-if="item.transitStatus == 2"
              @tap.stop="handleCancelTransport(item)"
            >
              编辑
              取消转运
            </button>
            <!-- 已取消(4):可以恢复 -->
            <button
              class="action-btn warning"
              v-if="item.transitStatus == 4"
              @tap.stop="handleRecoverTransport(item)"
            >
              恢复转运
            </button>
            <!-- 通用按钮 -->
            <button class="action-btn secondary" @tap.stop="viewDetails(item)">
              查看详情
            </button>
@@ -156,7 +170,7 @@
      <!-- 空状态 -->
      <view
        class="empty-state"
        v-if="!loading && filteredTransports.length === 0"
        v-if="!loading && filteredTransports.length == 0"
      >
        <image src="/static/empty/no-transport.png" mode="aspectFit" />
        <text>暂无转运单记录</text>
@@ -164,31 +178,37 @@
    </scroll-view>
    <!-- 操作确认弹窗 -->
    <view class="modal-mask" v-if="showActionModal">
      <view class="modal-content">
    <view class="modal-mask" v-if="showActionModal" @tap="cancelAction">
      <view class="modal-content" @tap.stop>
        <view class="modal-header">
          <text class="modal-title">{{ modalTitle }}</text>
        </view>
        <view class="modal-body">
          <text
            >确定要{{ modalAction }}转运单 "{{ currentTransport.caseNo }}"
            吗?</text
          <text class="modal-desc">
            确定要{{ modalAction }}转运单 "{{ currentTransport.caseNo }}" 吗?
          </text>
          <view class="modal-summary" v-if="currentTransport.patName">
            <text class="summary-item"
              >患者:{{ currentTransport.patName }}</text
          >
            <text class="summary-item"
              >当前状态:{{
                getStatusText(currentTransport.transitStatus)
              }}</text
            >
          </view>
        </view>
        <view class="modal-footer">
          <button class="modal-btn cancel" @tap="cancelAction">取消</button>
          <button class="modal-btn confirm" @tap="confirmAction">确认</button>
          <button class="modal-btn confirm" @tap="confirmAction">
            确认{{ modalAction }}
          </button>
        </view>
      </view>
    </view>
    <!-- 加载状态 -->
    <u-loading-page v-if="initLoading" :loading="true" text="数据加载中..." />
    <!-- 浮动按钮 -->
    <!-- <view class="float-button" @tap="createTransport">
      <u-icon name="plus" color="#fff" size="24"></u-icon>
    </view> -->
  </view>
</template>
@@ -222,6 +242,7 @@
const currentTransport = ref({});
const modalTitle = ref("");
const modalAction = ref("");
const modalTargetStatus = ref(null);
// 筛选相关
const transportTypes = [
@@ -280,6 +301,7 @@
    // 其他字段
    transportStartPlace: apiData.transportStartPlace,
    remark: apiData.remark,
    annexfilesList: apiData.annexfilesList || [],
  };
};
@@ -289,7 +311,7 @@
  
  // 前端状态筛选
  if (currentType.value !== "") {
    result = result.filter((item) => item.transitStatus === currentType.value);
    result = result.filter((item) => item.transitStatus == currentType.value);
  }
  
  return result;
@@ -324,7 +346,7 @@
  if (!gender) return "待转运";
  if (!dict.value.sys_user_sex) return gender;
  const genderItem = dict.value.sys_user_sex.find(
    (item) => item.dictValue === gender,
    (item) => item.dictValue == gender,
  );
  return genderItem ? genderItem.dictLabel : gender;
};
@@ -362,6 +384,134 @@
  }
};
// ============== 转运状态变更操作 ==============
/** 开始转运 */
const handleStartTransport = (item) => {
  currentTransport.value = { ...item };
  modalTitle.value = "开始转运";
  modalAction.value = "开始";
  modalTargetStatus.value = 2; // 设置为转运中
  showActionModal.value = true;
};
/** 完成转运 */
const handleCompleteTransport = (item) => {
  currentTransport.value = { ...item };
  modalTitle.value = "完成转运";
  modalAction.value = "完成";
  modalTargetStatus.value = 3; // 设置为转运完成
  showActionModal.value = true;
};
/** 取消转运 */
const handleCancelTransport = (item) => {
  currentTransport.value = { ...item };
  modalTitle.value = "取消转运";
  modalAction.value = "取消";
  modalTargetStatus.value = 4; // 设置为转运取消
  showActionModal.value = true;
};
/** 恢复转运 */
const handleRecoverTransport = (item) => {
  currentTransport.value = { ...item };
  modalTitle.value = "恢复转运";
  modalAction.value = "恢复";
  modalTargetStatus.value = 2; // 设置为转运中
  showActionModal.value = true;
};
// 取消操作
const cancelAction = () => {
  showActionModal.value = false;
};
// 确认操作
const confirmAction = async () => {
  try {
    const requestData = {
      ...currentTransport.value,
      transitStatus: modalTargetStatus.value,
    };
    // 清空附件ID(参照PC端逻辑)
    if (requestData.annexfilesList && requestData.annexfilesList.length > 0) {
      requestData.annexfilesList.forEach((item) => {
        item.id = null;
      });
    }
    const res = await uni.$uapi.post("/project/transport/edit", requestData);
    if (res && res.code == 200) {
      uni.showToast({
        title: `${modalAction.value}转运成功`,
        icon: "success",
      });
      // 如果是完成转运(状态变为3),同步更新案例状态
      if (modalTargetStatus.value == 3) {
        try {
          // 获取案例详情
          const caseRes = await uni.$uapi.get(
            `/project/donatebaseinforeport/getInfo/${requestData.reportId}`,
          );
          if (caseRes && caseRes.data) {
            const caseData = caseRes.data;
            caseData.isDonate = 1; // 标记为已捐献
            const editRes = await uni.$uapi.post(
              "/project/donatebaseinforeport/edit",
              caseData,
            );
            if (editRes && editRes.code == 200) {
              uni.showToast({
                title: "对应上报案例已进入正式案例流程",
                icon: "success",
              });
            }
          }
        } catch (caseError) {
          console.error("更新案例状态失败:", caseError);
          // 不阻断主流程,只提示
          uni.showToast({
            title: "案例状态更新失败,请联系管理员",
            icon: "none",
          });
        }
      }
      // 更新本地数据
      const index = transports.value.findIndex(
        (item) => item.id == currentTransport.value.id,
      );
      if (index !== -1) {
        transports.value[index].transitStatus = modalTargetStatus.value;
      }
      // 刷新统计数据
      await loadStats();
      // 关闭弹窗
      showActionModal.value = false;
    } else {
      uni.showToast({
        title: res?.msg || `${modalAction.value}转运失败`,
        icon: "none",
      });
    }
  } catch (error) {
    console.error(`${modalAction.value}转运失败:`, error);
    uni.showToast({
      title: "操作失败,请稍后重试",
      icon: "none",
    });
  }
};
// 查看详情
const viewDetail = (item) => {
  viewDetails(item);
@@ -384,53 +534,8 @@
// 创建转运单
const createTransport = () => {
  uni.navigateTo({
    url: '/pages/transport/create'
    url: "/pages/transport/create",
  });
};
// 开始转运
const startTransport = (item) => {
  currentTransport.value = item;
  modalTitle.value = "开始转运";
  modalAction.value = "开始";
  showActionModal.value = true;
};
// 完成转运
const completeTransport = (item) => {
  currentTransport.value = item;
  modalTitle.value = "完成转运";
  modalAction.value = "完成";
  showActionModal.value = true;
};
// 确认操作
const confirmAction = async () => {
  try {
    if (modalAction.value === "开始") {
      await updateTransportStatus(2, "开始转运");
    } else if (modalAction.value === "完成") {
      await updateTransportStatus(3, "完成转运");
    }
    uni.showToast({
      title: `${modalAction.value}成功`,
      icon: "success",
    });
  } catch (error) {
    console.error(`${modalAction.value}失败:`, error);
    uni.showToast({
      title: `${modalAction.value}失败,请重试`,
      icon: "none",
    });
  } finally {
    showActionModal.value = false;
  }
};
// 取消操作
const cancelAction = () => {
  showActionModal.value = false;
};
// 数据加载函数
@@ -500,7 +605,7 @@
    
    console.log("接口返回数据:", res);
  
    if (res && res.code === 200) {
    if (res && res.code == 200) {
      // 处理不同的数据结构
      let data = [];
      
@@ -517,7 +622,7 @@
      
      const mappedData = data.map((item) => mapApiDataToTransportItem(item));
      
      if (reset || pageNum.value === 1) {
      if (reset || pageNum.value == 1) {
        transports.value = mappedData;
      } else {
        transports.value = [...transports.value, ...mappedData];
@@ -548,62 +653,50 @@
// 加载统计数据
const loadStats = async () => {
  try {
    const res = await uni.$uapi.post("/api/totalServiceTransportState");
    if (res.data) {
    const res = await uni.$uapi.post(
      "/project/transport/totalServiceTransportState",
    );
    console.log(222);
    console.log(res,'11');
    if (res.data && Array.isArray(res.data)) {
      // 使用 find 查找各状态的数量,避免硬编码索引
      const totalTransports =
        res.data.reduce((sum, item) => sum + item.count, 0) || 0;
      const pendingTransports =
        res.data.find((item) => item.transit_status == 1)?.count || 0;
      const completedTransports =
        res.data.find((item) => item.transit_status == 3)?.count || 0;
      stats.value = {
        totalTransports:
          res.data.reduce((sum, item) => sum + item.count, 0) || 0,
        pendingTransports: res.data[0].count || 0,
        completedTransports: res.data[3].count || 0,
        totalTransports,
        pendingTransports,
        completedTransports,
      };
    } else {
      // 数据格式异常时设置默认值
      stats.value = {
        totalTransports: 0,
        pendingTransports: 0,
        completedTransports: 0,
      };
      console.error("统计数据格式异常:", res.data);
    }
  } catch (error) {
    console.error("加载统计失败:", error);
  }
    // 出错时也设置默认值,避免页面显示异常
    stats.value = {
      totalTransports: 0,
      pendingTransports: 0,
      completedTransports: 0,
};
// 更新转运状态
const updateTransportStatus = async (newStatus, actionName) => {
  try {
    const updateData = {
      id: currentTransport.value.id,
      transitStatus: newStatus,
    };
    const res = await uni.$uapi.post("/project/transport/edit", updateData);
    if (res && res.code === 200) {
      // 更新本地数据
      const index = transports.value.findIndex(
        (item) => item.id === currentTransport.value.id,
      );
      if (index !== -1) {
        transports.value[index].transitStatus = newStatus;
      }
      // 更新统计数据
      await loadStats();
      // 存储状态更新
      uni.setStorageSync("transportStatusUpdate", {
        orderId: currentTransport.value.id,
        status: newStatus,
      });
      return true;
    } else {
      throw new Error(res?.msg || `${actionName}失败`);
    }
  } catch (error) {
    console.error(`${actionName}失败:`, error);
    throw error;
  }
};
// 处理状态更新
const handleStatusUpdate = (update) => {
  const index = transports.value.findIndex(
    (item) => item.id === update.orderId,
    (item) => item.id == update.orderId,
  );
  if (index !== -1) {
    transports.value[index].transitStatus = update.status;
@@ -736,8 +829,7 @@
  }
  .transport-list {
    height: calc(100vh - 400rpx);
    // padding: 0 20rpx;
    height: calc(100vh - 420rpx);
    .transport-item {
      margin: 20rpx;
@@ -860,18 +952,39 @@
        .actions {
          display: flex;
          gap: 16rpx;
          flex-wrap: wrap;
          gap: 12rpx;
          justify-content: flex-end;
          .action-btn {
            height: 60rpx;
            line-height: 60rpx;
            padding: 0 24rpx;
            font-size: 24rpx;
            color: #0071e3;
            background: rgba(0, 113, 227, 0.1);
            border-radius: 30rpx;
            height: 58rpx;
            line-height: 58rpx;
            padding: 0 20rpx;
            font-size: 22rpx;
            border-radius: 29rpx;
            font-weight: 500;
            transition: all 0.3s ease;
            border: none;
            &.primary {
              color: #0071e3;
              background: rgba(0, 113, 227, 0.1);
            }
            &.success {
              color: #34c759;
              background: rgba(52, 199, 89, 0.1);
            }
            &.danger {
              color: #ff3b30;
              background: rgba(255, 59, 48, 0.1);
            }
            &.warning {
              color: #ff9500;
              background: rgba(255, 149, 0, 0.1);
            }
            &.secondary {
              color: #515154;
@@ -880,13 +993,15 @@
            &:active {
              transform: scale(0.95);
              opacity: 0.8;
            }
          }
        }
      }
    }
    .load-more, .no-more {
    .load-more,
    .no-more {
      text-align: center;
      padding: 40rpx 0;
      color: #86868b;
@@ -928,7 +1043,7 @@
  .modal-content {
    background: #fff;
    border-radius: 32rpx;
    width: 600rpx;
    width: 620rpx;
    overflow: hidden;
    box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.2);
  }
@@ -939,17 +1054,36 @@
  }
  .modal-title {
    font-size: 32rpx;
    font-weight: 600;
    font-size: 34rpx;
    font-weight: 700;
    color: #1d1d1f;
  }
  .modal-body {
    padding: 20rpx 40rpx 40rpx;
    text-align: center;
  }
  .modal-desc {
    font-size: 28rpx;
    color: #515154;
    line-height: 1.6;
    display: block;
  }
  .modal-summary {
    margin-top: 24rpx;
    background: #f8f9fc;
    border-radius: 16rpx;
    padding: 20rpx;
    text-align: left;
    .summary-item {
      display: block;
      font-size: 24rpx;
      color: #86868b;
      line-height: 1.8;
    }
  }
  .modal-footer {
@@ -983,28 +1117,6 @@
      &:active {
        background: #f0f7ff;
      }
    }
  }
  /* 浮动按钮 */
  .float-button {
    position: fixed;
    bottom: 100rpx;
    right: 40rpx;
    width: 100rpx;
    height: 100rpx;
    background: #0071e3;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8rpx 20rpx rgba(0, 113, 227, 0.3);
    z-index: 100;
    transition: all 0.3s ease;
    &:active {
      opacity: 0.8;
      transform: scale(0.95);
    }
  }
}