From 5abcde36961125cbf436f91b8c17610a6b5f8308 Mon Sep 17 00:00:00 2001
From: sen <sen@qq.com>
Date: 星期三, 15 四月 2026 12:15:08 +0800
Subject: [PATCH] 修改调度单必填校验

---
 ui/car_wx_app/pages/history/index.vue |  380 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 300 insertions(+), 80 deletions(-)

diff --git a/ui/car_wx_app/pages/history/index.vue b/ui/car_wx_app/pages/history/index.vue
index 1eee970..88a4fd2 100644
--- a/ui/car_wx_app/pages/history/index.vue
+++ b/ui/car_wx_app/pages/history/index.vue
@@ -1,29 +1,85 @@
 <template>
   <view class="container">
-    <!-- 鏍囬鏍� -->
-    <Nav title="鍘嗗彶璋冨害鍗�" customBack="pages/beReferred/index" customType="navigateBack"></Nav>
-    <!-- 鍘嗗彶璋冨害鍗曞垪琛�-鍙笅鎷夋粴鍔� -->
-    <scroll-view class="history-scroll" scroll-y="true" style="height: calc(100vh - 80rpx);">
-      <view class="history-item" v-for="(item, index) in historyList" @click="historyClick(item)" :key="index">
-        <view class="item-field">
-          <view class="field-label">璋冨害鍗曞彿</view>
-          <view class="field-value">{{ item.dispatchNo }}</view>
+    <!-- 瀵艰埅鏍� -->
+    <Nav title="鍘嗗彶璋冨害鍗�" @back="goBack" />
+
+    <!-- 楠ㄦ灦灞� -->
+    <view v-if="loading && !historyList.length" class="skeleton-list">
+      <view v-for="i in 5" :key="i" class="skeleton-item">
+        <view class="skeleton-row">
+          <view class="skeleton-label" />
+          <view class="skeleton-value short" />
         </view>
-        <view class="item-field">
-          <view class="field-label">杩愯緭宸ュ叿鍙风爜</view>
-          <view class="field-value">{{ item.licensePlate }}</view>
+        <view class="skeleton-row">
+          <view class="skeleton-label" />
+          <view class="skeleton-value" />
         </view>
-        <view class="item-field">
-          <view class="field-label">璺嚎</view>
-          <view class="field-value">{{ item.transportLine }}</view>
+        <view class="skeleton-row">
+          <view class="skeleton-label" />
+          <view class="skeleton-value medium" />
         </view>
-        <view class="item-field">
-          <view class="field-label">瀹㈡埛</view>
-          <view class="field-value">{{ item.customerName }}</view>
+      </view>
+    </view>
+
+    <!-- 鍒楄〃鍖哄煙 -->
+    <scroll-view
+      v-else
+      class="history-scroll"
+      scroll-y
+      :refresher-enabled="true"
+      :refresher-triggered="isRefreshing"
+      @refresherrefresh="onRefresh"
+      @scrolltolower="onLoadMore"
+      :style="{ height: 'calc(100vh - 88rpx)' }"
+    >
+      <!-- 绌虹姸鎬� -->
+      <view v-if="!historyList.length" class="empty-state">
+        <u-empty mode="history" text="鏆傛棤鍘嗗彶璋冨害鍗�" />
+      </view>
+
+      <!-- 鍒楄〃鍐呭 -->
+      <view v-else class="list-content">
+        <view
+          v-for="item in historyList"
+          :key="item.dispatchId"
+          class="history-card"
+          @tap="handleItemClick(item)"
+        >
+          <!-- 澶撮儴锛氬崟鍙峰拰鐘舵�� -->
+          <view class="card-header">
+            <view class="dispatch-no">{{ item.dispatchNo }}</view>
+            <u-icon name="arrow-right" size="14" color="#c0c4cc" />
+          </view>
+
+          <!-- 鍐呭鍖哄煙 -->
+          <view class="card-body">
+            <view class="info-row">
+              <u-icon name="car" size="14" color="#909399" />
+              <text class="info-label">杞︾墝鍙�</text>
+              <text class="info-value">{{ item.licensePlate || '-' }}</text>
+            </view>
+            <view class="info-row">
+              <u-icon name="map" size="14" color="#909399" />
+              <text class="info-label">璺嚎</text>
+              <text class="info-value">{{ item.transportLine || '-' }}</text>
+            </view>
+            <view class="info-row">
+              <u-icon name="account" size="14" color="#909399" />
+              <text class="info-label">瀹㈡埛</text>
+              <text class="info-value">{{ item.customerName || '-' }}</text>
+            </view>
+            <view class="info-row">
+              <u-icon name="clock" size="14" color="#909399" />
+              <text class="info-label">瀹屾垚鏃堕棿</text>
+              <text class="info-value time">{{ formatTime(item.okTime) }}</text>
+            </view>
+          </view>
         </view>
-        <view class="item-field">
-          <view class="field-label">瀹屾垚鏃堕棿</view>
-          <view class="field-value">{{ item.okTime }}</view>
+
+        <!-- 鍔犺浇鏇村鐘舵�� -->
+        <view v-if="historyList.length" class="load-more">
+          <u-loading-icon v-if="loadingMore" size="16" text="鍔犺浇涓�..." />
+          <text v-else-if="!hasMore" class="no-more">娌℃湁鏇村浜�</text>
         </view>
       </view>
     </scroll-view>
@@ -31,91 +87,255 @@
 </template>
 
 <script>
+import { getAssignedItineraryLogList } from '@/common/history'
 
-import { getAssignedItineraryLogList } from "@/common/history";
 export default {
   data() {
     return {
-      historyList: [
+      historyList: [],
+      loading: false,
+      loadingMore: false,
+      isRefreshing: false,
+      pageNum: 1,
+      pageSize: 10,
+      hasMore: true
+    }
+  },
 
-      ]
-    };
+  onLoad() {
+    this.loadData()
   },
-  created() {
-    this.getList();
-  },
+
   methods: {
-    historyClick(item) {
-      wx.navigateTo({
-        url: '/pages/examine/index?id=' + item.dispatchId + '&name=' + '鏌ョ湅琛岀▼鍘嗗彶' + '&router=' + 'pages/history/index'
-      });
+    goBack() {
+      uni.navigateBack({ delta: 1 })
     },
-    getList() {
-      getAssignedItineraryLogList().then((res) => {
-        this.historyList = res;
-        
 
-        // uni.$u.toast(res.message);
-      })
+    // 鍔犺浇鏁版嵁
+    async loadData(isRefresh = false) {
+      if (this.loading) return
+
+      this.loading = true
+      try {
+        const params = {
+          pageNum: this.pageNum,
+          pageSize: this.pageSize
+        }
+        const res = await getAssignedItineraryLogList(params)
+
+        const list = res?.rows || res?.list || res || []
+        const total = res?.total || list.length
+
+        if (isRefresh) {
+          this.historyList = list
+        } else {
+          this.historyList = [...this.historyList, ...list]
+        }
+
+        this.hasMore = this.historyList.length < total
+      } catch (err) {
+        uni.$u.toast(err.message || '鍔犺浇澶辫触')
+      } finally {
+        this.loading = false
+        this.loadingMore = false
+        this.isRefreshing = false
+      }
     },
-  },
-};
+
+    // 涓嬫媺鍒锋柊
+    onRefresh() {
+      this.isRefreshing = true
+      this.pageNum = 1
+      this.hasMore = true
+      this.loadData(true)
+    },
+
+    // 涓婃媺鍔犺浇鏇村
+    onLoadMore() {
+      if (!this.hasMore || this.loadingMore) return
+      this.loadingMore = true
+      this.pageNum++
+      this.loadData()
+    },
+
+    // 鐐瑰嚮鍗$墖 - 鐩存帴璺宠浆鍒拌鎯呴〉
+    handleItemClick(item) {
+      const url = `/pages/examine/detail?id=${encodeURIComponent(item.dispatchId)}&name=${encodeURIComponent('鏌ョ湅琛岀▼鍘嗗彶')}&router=${encodeURIComponent('pages/history/index')}`
+      uni.redirectTo({ url })
+    },
+
+    // 鏍煎紡鍖栨椂闂�
+    formatTime(timeStr) {
+      if (!timeStr) return '-'
+      const m = timeStr.match(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/)
+      return m ? `${m[1]}-${m[2]}-${m[3]} ${m[4]}:${m[5]}:${m[6]}` : timeStr
+    }
+  }
+}
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
+// 鍙橀噺瀹氫箟
+$primary-color: #409eff;
+$text-primary: #303133;
+$text-regular: #606266;
+$text-secondary: #909399;
+$border-color: #ebeef5;
+$bg-color: #f5f7fa;
+
 .container {
-  display: flex;
-  flex-direction: column;
-  height: 100vh;
-  background-color: #f7f7f7;
+  min-height: 100vh;
+  background-color: $bg-color;
 }
 
-/* 鏍囬鏍� */
-.title-bar {
-  height: 80rpx;
-  line-height: 80rpx;
-  text-align: center;
-  font-size: 32rpx;
-  font-weight: 500;
-  background-color: #fff;
-  border-bottom: 1rpx solid #ccc;
-  /* 鏍囬鏍忓簳閮ㄨ竟妗� */
+// 楠ㄦ灦灞�
+.skeleton-list {
+  padding: 20rpx;
+
+  .skeleton-item {
+    background: #fff;
+    border-radius: 12rpx;
+    padding: 24rpx;
+    margin-bottom: 20rpx;
+
+    .skeleton-row {
+      display: flex;
+      align-items: center;
+      margin-bottom: 16rpx;
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+
+    .skeleton-label {
+      width: 140rpx;
+      height: 28rpx;
+      background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
+      background-size: 200% 100%;
+      animation: shimmer 1.5s infinite;
+      border-radius: 4rpx;
+      margin-right: 20rpx;
+    }
+
+    .skeleton-value {
+      flex: 1;
+      height: 28rpx;
+      background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
+      background-size: 200% 100%;
+      animation: shimmer 1.5s infinite;
+      border-radius: 4rpx;
+
+      &.short {
+        flex: 0.3;
+      }
+
+      &.medium {
+        flex: 0.6;
+      }
+    }
+  }
 }
 
-/* 鍘嗗彶璋冨害鍗曟粴鍔ㄥ尯鍩� */
+@keyframes shimmer {
+  0% {
+    background-position: 200% 0;
+  }
+  100% {
+    background-position: -200% 0;
+  }
+}
+
+// 婊氬姩鍖哄煙
 .history-scroll {
-  flex: 1;
   padding: 20rpx;
   box-sizing: border-box;
 }
 
-/* 鍘嗗彶璋冨害鍗曢」 */
-.history-item {
-  background-color: #fff;
-  border: 1rpx solid #ccc;
-  /* 姣忎釜鏉$洰杈规 */
-  border-radius: 6rpx;
-  padding: 20rpx;
-  margin-bottom: 20rpx;
-}
-
-/* 瀛楁琛� */
-.item-field {
+// 绌虹姸鎬�
+.empty-state {
   display: flex;
-  margin-bottom: 16rpx;
+  justify-content: center;
+  align-items: center;
+  height: 60vh;
 }
 
-/* 瀛楁鏍囩 */
-.field-label {
-  width: 170rpx;
-  color: #666;
-  font-size: 28rpx;
+// 鍒楄〃鍐呭
+.list-content {
+  padding-bottom: 40rpx;
 }
 
-/* 瀛楁鍊� */
-.field-value {
-  flex: 1;
-  color: #333;
-  font-size: 28rpx;
+// 鍘嗗彶鍗$墖
+.history-card {
+  background: #fff;
+  border-radius: 12rpx;
+  padding: 24rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
+  transition: transform 0.2s;
+
+  &:active {
+    transform: scale(0.98);
+  }
+
+  .card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-bottom: 20rpx;
+    margin-bottom: 20rpx;
+    border-bottom: 1rpx solid $border-color;
+
+    .dispatch-no {
+      font-size: 30rpx;
+      font-weight: 600;
+      color: $primary-color;
+    }
+  }
+
+  .card-body {
+    .info-row {
+      display: flex;
+      align-items: center;
+      margin-bottom: 16rpx;
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .info-label {
+        width: 120rpx;
+        font-size: 26rpx;
+        color: $text-secondary;
+        margin-left: 12rpx;
+        margin-right: 16rpx;
+      }
+
+      .info-value {
+        flex: 1;
+        font-size: 26rpx;
+        color: $text-regular;
+        word-break: break-all;
+
+        &.time {
+          color: $text-secondary;
+          font-size: 24rpx;
+        }
+      }
+    }
+  }
 }
-</style>
\ No newline at end of file
+
+// 鍔犺浇鏇村
+.load-more {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 30rpx;
+
+  .no-more {
+    font-size: 24rpx;
+    color: $text-secondary;
+  }
+}
+</style>

--
Gitblit v1.8.0