From 2cc85c64f1c64a2dbaeae276a3e2ca8420de76b7 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期三, 22 四月 2026 18:09:58 +0800
Subject: [PATCH] 上报转运调试

---
 pages/case/transfer.vue |  544 +++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 392 insertions(+), 152 deletions(-)

diff --git a/pages/case/transfer.vue b/pages/case/transfer.vue
index fba65b6..b9e34fe 100644
--- a/pages/case/transfer.vue
+++ b/pages/case/transfer.vue
@@ -24,7 +24,7 @@
         <text
           v-for="(type, index) in transportTypes"
           :key="index"
-          :class="{ active: currentType === type.value }"
+          :class="{ active: currentType == type.value }"
           @tap="selectType(type.value)"
           >{{ type.label }}</text
         >
@@ -70,61 +70,68 @@
         <view class="header">
           <view class="case-info">
             <view class="info">
-              <text class="case-no">{{ item.caseNo }}</text>
+              <text class="case-no">{{ item.caseNo || item.reportId }}</text>
               <text class="patient"
-                >{{ item.donorName }} | {{ item.gender }} |
+                >{{ item.patName }} | {{ getGenderText(item.sex) }} |
                 {{ item.age }}宀�</text
               >
             </view>
           </view>
-          <text class="status" :class="item.status">{{ item.statusText }}</text>
+          <text class="status" :class="getStatusClass(item.transitStatus)">{{
+            getStatusText(item.transitStatus)
+          }}</text>
         </view>
 
         <view class="detail-info">
           <view class="info-item">
             <text class="label">鐤剧梾璇婃柇</text>
-            <text class="value">{{ item.diagnosis }}</text>
+            <text class="value">{{ item.diagnosisname || "鏈~鍐�" }}</text>
           </view>
           <view class="info-item">
             <text class="label">鎵�鍦ㄥ尰鐤楁満鏋�</text>
-            <text class="value">{{ item.hospitalName }}</text>
+            <text class="value">{{
+              item.treatmentHospitalName || "鏈~鍐�"
+            }}</text>
           </view>
           <view class="info-item">
             <text class="label">璁″垝杞繍鏃堕棿</text>
-            <text class="value">{{ item.transportTime }}</text>
+            <text class="value">{{ formatTime(item.transportStartTime) }}</text>
           </view>
           <view class="info-item">
             <text class="label">璐熻矗鍗忚皟鍛�</text>
-            <text class="value">{{ item.coordinator }}</text>
+            <text class="value">{{ item.contactPerson || "鏈寚瀹�" }}</text>
           </view>
           <view class="info-item">
             <text class="label">鍒涘缓鏃堕棿</text>
-            <text class="value">{{ item.createTime }}</text>
+            <text class="value">{{ formatTime(item.createTime) }}</text>
           </view>
         </view>
 
         <view class="footer">
           <view class="action-info">
             <text class="label">杞繍鐘舵��</text>
-            <text class="transport-status">{{ item.statusText }}</text>
+            <text class="transport-status">{{
+              getStatusText(item.transitStatus)
+            }}</text>
           </view>
           <view class="actions">
             <button
               class="action-btn"
-              v-if="item.status === 'pending'"
+              v-if="item.transitStatus === 1"
               @tap.stop="startTransport(item)"
             >
               寮�濮嬭浆杩�
             </button>
             <button
               class="action-btn"
-              v-if="item.status === 'transporting'"
+              v-if="item.transitStatus === 2"
               @tap.stop="completeTransport(item)"
             >
               瀹屾垚杞繍
             </button>
             <button
               class="action-btn secondary"
+              v-if="item.transitStatus != 3"
               @tap.stop="editTransport(item)"
             >
               缂栬緫
@@ -137,12 +144,20 @@
       </view>
 
       <!-- 鍔犺浇鏇村 -->
-      <view class="load-more" v-if="hasMore">
-        <text>鍔犺浇涓�...</text>
+      <view class="load-more" v-if="loadingMore">
+        <u-loading-icon text="鍔犺浇涓�..."></u-loading-icon>
+      </view>
+
+      <!-- 鏃犳洿澶氭暟鎹� -->
+      <view class="no-more" v-if="!hasMore && filteredTransports.length > 0">
+        <text>宸插姞杞藉叏閮ㄦ暟鎹�</text>
       </view>
 
       <!-- 绌虹姸鎬� -->
-      <view class="empty-state" v-if="filteredTransports.length === 0">
+      <view
+        class="empty-state"
+        v-if="!loading && filteredTransports.length === 0"
+      >
         <image src="/static/empty/no-transport.png" mode="aspectFit" />
         <text>鏆傛棤杞繍鍗曡褰�</text>
       </view>
@@ -166,154 +181,210 @@
         </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>
 
 <script setup>
-import { ref, computed } from "vue";
-import { onLoad } from "@dcloudio/uni-app";
+import { ref, computed, onMounted } from "vue";
+import { onLoad, onShow, onReachBottom } from "@dcloudio/uni-app";
+import { useDict } from "@/utils/dict";
+
+// 瀛楀吀鏁版嵁
+const dict = ref({});
 
 // 缁熻鏁版嵁
 const stats = ref({
-  totalTransports: 12,
-  pendingTransports: 4,
-  completedTransports: 6,
+  totalTransports: 0,
+  pendingTransports: 0,
+  completedTransports: 0,
 });
+
+// 杞繍鍗曟暟鎹�
+const transports = ref([]);
+const loading = ref(false);
+const initLoading = ref(false);
+const loadingMore = ref(false);
+const refreshing = ref(false);
+const hasMore = ref(true);
 const pageNum = ref(1);
 const pageSize = ref(10);
+
 // 鎿嶄綔纭寮圭獥鐩稿叧
 const showActionModal = ref(false);
 const currentTransport = ref({});
 const modalTitle = ref("");
 const modalAction = ref("");
 
-onLoad(async (options) => {
-  // 鍒濆鍖栨暟鎹�
-  loadTransports();
-});
-
 // 绛涢�夌浉鍏�
 const transportTypes = [
-  { label: "鍏ㄩ儴", value: "all" },
-  { label: "寰呭嚭鍙�", value: "pending" },
-  { label: "杞繍涓�", value: "transporting" },
-  { label: "宸插畬鎴�", value: "completed" },
-  { label: "宸插彇娑�", value: "cancelled" },
+  { label: "鍏ㄩ儴", value: "" },
+  { label: "寰呰浆杩�", value: 1 },
+  { label: "杞繍涓�", value: 2 },
+  { label: "宸插畬鎴�", value: 3 },
+  { label: "宸插彇娑�", value: 4 },
+  { label: "鏆傚瓨", value: 5 },
 ];
-const currentType = ref("all");
+const currentType = ref("");
 const startDate = ref("");
 const endDate = ref("");
 
-// 杞繍鍗曟暟鎹�
-const transports = ref([
-  {
-    id: "T20241217001",
-    caseNo: "DON20241216001",
-    donorName: "寮犱笁",
-    gender: "鐢�",
-    age: 38,
-    diagnosis: "鑴戝浼ゅ鑷磋剳姝讳骸",
-    hospitalName: "闈掑矝闀滄箹鍖婚櫌",
-    transportTime: "2024-12-17 14:30",
-    coordinator: "寮犲尰鐢�",
-    createTime: "2024-12-16 09:30",
-    status: "pending",
-    statusText: "寰呭嚭鍙�",
-    departureLocation: "闈掑矝甯傜珛鍖婚櫌鎬ヨ瘖绉�",
-    destinationHospital: "闈掑矝闀滄箹鍖婚櫌",
-  },
-  {
-    id: "T20241217002",
-    caseNo: "DON20241216002",
-    donorName: "鏉庡洓",
-    gender: "濂�",
-    age: 45,
-    diagnosis: "鑴戞姝�",
-    hospitalName: "闈掑矝澶у闄勫睘鍖婚櫌",
-    transportTime: "2024-12-17 16:00",
-    coordinator: "鏉庡尰鐢�",
-    createTime: "2024-12-16 11:20",
-    status: "transporting",
-    statusText: "杞繍涓�",
-    departureLocation: "闈掑矝澶у闄勫睘鍖婚櫌ICU",
-    destinationHospital: "闈掑矝鍣ㄥ畼绉绘涓績",
-  },
-  {
-    id: "T20241216003",
-    caseNo: "DON20241215001",
-    donorName: "鐜嬩簲",
-    gender: "鐢�",
-    age: 52,
-    diagnosis: "蹇冭剰楠ゅ仠",
-    hospitalName: "闈掑矝甯傜珛鍖婚櫌",
-    transportTime: "2024-12-16 10:15",
-    coordinator: "鐜嬪尰鐢�",
-    createTime: "2024-12-15 14:45",
-    status: "completed",
-    statusText: "宸插畬鎴�",
-    departureLocation: "闈掑矝甯傜珛鍖婚櫌蹇冨唴绉�",
-    destinationHospital: "闈掑矝鍣ㄥ畼绉绘涓績",
-  },
-  {
-    id: "T20241216004",
-    caseNo: "DON20241214001",
-    donorName: "璧靛叚",
-    gender: "濂�",
-    age: 29,
-    diagnosis: "鎬ユ�ц倽琛扮",
-    hospitalName: "闈掑矝绉戝ぇ鍖婚櫌",
-    transportTime: "2024-12-16 08:30",
-    coordinator: "璧靛尰鐢�",
-    createTime: "2024-12-14 16:20",
-    status: "cancelled",
-    statusText: "宸插彇娑�",
-    departureLocation: "闈掑矝绉戝ぇ鍖婚櫌娑堝寲绉�",
-    destinationHospital: "闈掑矝鍣ㄥ畼绉绘涓績",
-  },
-]);
+onLoad(async (options) => {
+  // 鑾峰彇瀛楀吀鏁版嵁
+  dict.value = await useDict("sys_user_sex");
+  // 鍒濆鍖栨暟鎹�
+  await loadInitialData();
+});
 
-// 绛涢�夎褰�
+onReachBottom(() => {
+  if (hasMore.value && !loading.value && !loadingMore.value) {
+    onLoadMore();
+  }
+});
+
+onShow(() => {
+  // 妫�鏌ユ槸鍚︽湁杞繍鐘舵�佹洿鏂�
+  const update = uni.getStorageSync("transportStatusUpdate");
+  if (update) {
+    handleStatusUpdate(update);
+    uni.removeStorageSync("transportStatusUpdate");
+  }
+});
+
+// 鏁版嵁鏄犲皠鍑芥暟
+const mapApiDataToTransportItem = (apiData) => {
+  return {
+    id: apiData.id,
+    reportId: apiData.reportId,
+    caseNo: apiData.caseNo,
+    patName: apiData.patName,
+    sex: apiData.sex,
+    age: apiData.age,
+    diagnosisname: apiData.diagnosisname,
+    treatmentHospitalName: apiData.treatmentHospitalName,
+    transportStartTime: apiData.transportStartTime,
+    contactPerson: apiData.contactPerson,
+    createTime: apiData.createTime,
+    transitStatus: apiData.transitStatus,
+    // 鍖绘姢浜哄憳淇℃伅
+    doctor: apiData.doctor,
+    nurse: apiData.nurse,
+    driver: apiData.driver,
+    // 鍏朵粬瀛楁
+    transportStartPlace: apiData.transportStartPlace,
+    remark: apiData.remark,
+  };
+};
+
+// 璁$畻灞炴�э細绛涢�夎褰�
 const filteredTransports = computed(() => {
   let result = transports.value;
-
-  // 鐘舵�佺瓫閫�
-  if (currentType.value !== "all") {
-    result = result.filter((item) => item.status === currentType.value);
+  
+  // 鍓嶇鐘舵�佺瓫閫�
+  if (currentType.value !== "") {
+    result = result.filter((item) => item.transitStatus === currentType.value);
   }
-
-  // 鏃ユ湡绛涢��
-  if (startDate.value && endDate.value) {
-    result = result.filter((item) => {
-      const transportDate = item.createTime.split(" ")[0];
-      return transportDate >= startDate.value && transportDate <= endDate.value;
-    });
-  }
-
+  
   return result;
 });
 
-// 鍒嗛〉鐩稿叧
-const hasMore = ref(true);
-const refreshing = ref(false);
+// 鑾峰彇鐘舵�佹牱寮�
+const getStatusClass = (status) => {
+  const map = {
+    1: "pending", // 寰呰浆杩�
+    2: "transporting", // 杞繍涓�
+    3: "completed", // 宸插畬鎴�
+    4: "cancelled", // 宸插彇娑�
+    5: "cancelled", // 鏆傚瓨
+  };
+  return map[status] || "pending";
+};
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+  const map = {
+    1: "寰呭嚭鍙�",
+    2: "杞繍涓�",
+    3: "宸插畬鎴�",
+    4: "宸插彇娑�",
+    5: "鏆傚瓨",
+  };
+  return map[status] || "鏈煡";
+};
+
+// 鑾峰彇鎬у埆鏂囨湰
+const getGenderText = (gender) => {
+  if (!gender) return "鏈煡";
+  if (!dict.value.sys_user_sex) return gender;
+  const genderItem = dict.value.sys_user_sex.find(
+    (item) => item.dictValue === gender,
+  );
+  return genderItem ? genderItem.dictLabel : gender;
+};
+
+// 鏍煎紡鍖栨椂闂�
+const formatTime = (timeStr) => {
+  if (!timeStr) return "鏈缃�";
+  return timeStr.replace("T", " ").substring(0, 16);
+};
 
 // 閫夋嫨绫诲瀷
 const selectType = (type) => {
   currentType.value = type;
+  // 閲嶇疆鍒嗛〉锛岄噸鏂板姞杞芥暟鎹�
+  pageNum.value = 1;
+  loadTransports(true);
 };
 
 // 鏃ユ湡閫夋嫨
 const onStartDateChange = (e) => {
   startDate.value = e.detail.value;
+  // 濡傛灉缁撴潫鏃ユ湡宸查�夋嫨锛岀珛鍗宠Е鍙戠瓫閫�
+  if (endDate.value) {
+    pageNum.value = 1;
+    loadTransports(true);
+  }
 };
 
 const onEndDateChange = (e) => {
   endDate.value = e.detail.value;
+  // 濡傛灉寮�濮嬫棩鏈熷凡閫夋嫨锛岀珛鍗宠Е鍙戠瓫閫�
+  if (startDate.value) {
+    pageNum.value = 1;
+    loadTransports(true);
+  }
 };
 
 // 鏌ョ湅璇︽儏
 const viewDetail = (item) => {
+  viewDetails(item);
+};
+
+// 鏌ョ湅璇︽儏
+const viewDetails = (item) => {
   uni.navigateTo({
-    url: `/pages/transport/detail?id=${item.id}`,
+    url: `/pages/case/transferinfo?id=${item.id}`,
+  });
+};
+
+// 缂栬緫杞繍鍗�
+const editTransport = (item) => {
+  uni.navigateTo({
+    url: `/pages/case/transferinfo?id=${item.id}&edit=true`,
+  });
+};
+
+// 鍒涘缓杞繍鍗�
+const createTransport = () => {
+  uni.navigateTo({
+    url: '/pages/transport/create'
   });
 };
 
@@ -334,27 +405,27 @@
 };
 
 // 纭鎿嶄綔
-const confirmAction = () => {
-  const index = transports.value.findIndex(
-    (item) => item.id === currentTransport.value.id
-  );
-  if (index !== -1) {
+const confirmAction = async () => {
+  try {
     if (modalAction.value === "寮�濮�") {
-      transports.value[index].status = "transporting";
-      transports.value[index].statusText = "杞繍涓�";
-      stats.value.pendingTransports -= 1;
+      await updateTransportStatus(2, "寮�濮嬭浆杩�");
     } else if (modalAction.value === "瀹屾垚") {
-      transports.value[index].status = "completed";
-      transports.value[index].statusText = "宸插畬鎴�";
-      stats.value.completedTransports += 1;
+      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;
   }
-  showActionModal.value = false;
 };
 
 // 鍙栨秷鎿嶄綔
@@ -362,42 +433,181 @@
   showActionModal.value = false;
 };
 
-// 鏌ョ湅璇︽儏
-const viewDetails = (item) => {
-  uni.navigateTo({
-    url: `/pages/case/transferinfo?id=${item.id}`,
-  });
-};
-
-// 缂栬緫杞繍鍗�
-const editTransport = (item) => {
-  uni.navigateTo({
-    url: `/pages/case/transferinfo?id=${item.id}`,
-  });
+// 鏁版嵁鍔犺浇鍑芥暟
+const loadInitialData = async () => {
+  initLoading.value = true;
+  try {
+    await Promise.all([loadTransports(true), loadStats()]);
+  } catch (error) {
+    console.error("鍒濆鍖栨暟鎹け璐�:", error);
+  } finally {
+    initLoading.value = false;
+  }
 };
 
 // 涓嬫媺鍒锋柊
-const onRefresh = () => {
+const onRefresh = async () => {
   refreshing.value = true;
-  loadTransports();
+  pageNum.value = 1;
+  await loadTransports(true);
+  await loadStats();
   setTimeout(() => {
     refreshing.value = false;
   }, 1000);
 };
 
 // 鍔犺浇鏇村
-const onLoadMore = () => {
-  if (!hasMore.value) return;
-  loadTransports();
+const onLoadMore = async () => {
+  if (!hasMore.value || loading.value || loadingMore.value) return;
+  await loadTransports();
 };
 
-// 鍔犺浇璁板綍
-const loadTransports = async () => {
+// 鍔犺浇杞繍鍗曞垪琛�
+const loadTransports = async (reset = false) => {
+  if (reset) {
+    pageNum.value = 1;
+    hasMore.value = true;
+  }
+  
+  if (loading.value || loadingMore.value || !hasMore.value) return;
+  
+  if (reset) {
+    loading.value = true;
+  } else {
+    loadingMore.value = true;
+  }
+  
+  try {
+    const params = {
+      pageNum: pageNum.value,
+      pageSize: pageSize.value,
+    };
+    
+    // 绛涢�夋潯浠�
+    if (currentType.value !== "") {
+      params.transitStatus = currentType.value;
+    }
+    
+    // 鏃堕棿绛涢�夋潯浠�
+    if (startDate.value && endDate.value) {
+      params.startDate = startDate.value;
+      params.endDate = endDate.value;
+    }
+    
+    console.log("璇锋眰鍙傛暟:", params);
+    
+    const res = await uni.$uapi.post("/project/transport/list", params);
+    
+    console.log("鎺ュ彛杩斿洖鏁版嵁:", res);
+  
+    if (res && res.code === 200) {
+      // 澶勭悊涓嶅悓鐨勬暟鎹粨鏋�
+      let data = [];
+      
+      if (res.rows && Array.isArray(res.rows)) {
+        data = res.rows;
+      } else if (res.data && Array.isArray(res.data)) {
+        data = res.data;
+      } else if (Array.isArray(res)) {
+        data = res;
+      } else {
+        console.error("鎺ュ彛杩斿洖鏍煎紡涓嶆纭�:", res);
+        throw new Error("鎺ュ彛杩斿洖鏍煎紡涓嶆纭�");
+      }
+      
+      const mappedData = data.map((item) => mapApiDataToTransportItem(item));
+      
+      if (reset || pageNum.value === 1) {
+        transports.value = mappedData;
+      } else {
+        transports.value = [...transports.value, ...mappedData];
+      }
+      
+      // 鍒ゆ柇鏄惁杩樻湁鏇村鏁版嵁
+      hasMore.value = data.length >= pageSize.value;
+      
+      // 濡傛灉鏈夋暟鎹姞杞芥垚鍔燂紝澧炲姞椤电爜
+      if (data.length > 0) {
+        pageNum.value++;
+      }
+    } else {
+      throw new Error(res?.msg || "鍔犺浇澶辫触");
+    }
+  } catch (error) {
+    console.error("鍔犺浇杞繍鍗曞垪琛ㄥけ璐�:", error);
+    uni.showToast({
+      title: "缃戠粶璇锋眰澶辫触",
+      icon: "none",
+    });
+  } finally {
+    loading.value = false;
+    loadingMore.value = false;
+  }
+};
 
-  // 杩欓噷璋冪敤API鍔犺浇鏁版嵁
-  setTimeout(() => {
-    hasMore.value = false;
-  }, 1000);
+// 鍔犺浇缁熻鏁版嵁
+const loadStats = async () => {
+  try {
+    const res = await uni.$uapi.post("/api/totalServiceTransportState");
+    if (res.data) {
+      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,
+      };
+    }
+  } catch (error) {
+    console.error("鍔犺浇缁熻澶辫触:", error);
+  }
+};
+
+// 鏇存柊杞繍鐘舵��
+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,
+  );
+  if (index !== -1) {
+    transports.value[index].transitStatus = update.status;
+  }
 };
 </script>
 
@@ -405,6 +615,7 @@
 .transport-record {
   min-height: 100vh;
   background: linear-gradient(135deg, #fafdff 0%, #e3f0ff 100%);
+  padding-bottom: 100rpx;
 
   .stats-card {
     margin: 20rpx;
@@ -675,6 +886,13 @@
       }
     }
 
+    .load-more, .no-more {
+      text-align: center;
+      padding: 40rpx 0;
+      color: #86868b;
+      font-size: 28rpx;
+    }
+
     .empty-state {
       padding: 120rpx 0;
       text-align: center;
@@ -767,5 +985,27 @@
       }
     }
   }
+  
+  /* 娴姩鎸夐挳 */
+  .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);
+    }
+  }
 }
-</style>
+</style>
\ No newline at end of file

--
Gitblit v1.9.3