From 0bafa6aa253c9ef6f5cb24e9a24c5282860e4c59 Mon Sep 17 00:00:00 2001
From: zhangback <zhangback@163.com>
Date: 星期一, 30 三月 2026 11:44:37 +0800
Subject: [PATCH] 新增线上配置

---
 ui/car_wx_app/pages/travelItinerary/index.vue |  428 +++++++++++++++++++++++++++++++++--------------------
 1 files changed, 268 insertions(+), 160 deletions(-)

diff --git a/ui/car_wx_app/pages/travelItinerary/index.vue b/ui/car_wx_app/pages/travelItinerary/index.vue
index 50ab7b0..363d676 100644
--- a/ui/car_wx_app/pages/travelItinerary/index.vue
+++ b/ui/car_wx_app/pages/travelItinerary/index.vue
@@ -1,245 +1,353 @@
 <template>
   <view class="container">
-    <!-- 鏍囬鏍� -->
-    <Nav :title="formData.name" :customBack="formData.router" customType="navigateBack"></Nav>
+    <Nav title="琛岀▼鍘嗗彶" @back="goBack" />
 
-    <!-- 琛岀▼鍘嗗彶鍒楄〃-鍙笅鎷夋粴鍔� -->
-    <scroll-view class="history-scroll" scroll-y="true" style="height: calc(100vh - 80rpx);">
-      <view class="timeline-item" v-for="(item, index) in historyList" :key="index">
-        <!-- 宸︿晶鏃堕棿杞� -->
-        <view class="timeline-left">
-          <view class="timeline-dot"></view>
-          <view class="timeline-line" :class="{ last: index === historyList.length - 1 }"></view>
-          <view class="timeline-distance">{{ item.odometer }}km</view>
-        </view>
+    <!-- 鍔犺浇鐘舵�� -->
+    <view v-if="loading && !list.length" class="center-state">
+      <u-loading-icon size="32" text="鍔犺浇涓�..." />
+    </view>
 
-        <!-- 鍙充晶琛岀▼鍐呭 -->
-        <view class="timeline-right">
-          <view class="item-header">
-            <view class="driver-action">{{ item.driverName }} {{ item.statusStr }}</view>
-            <view class="vehicle-info">{{ item.vehicleNumber }}</view>
-            <view class="location">{{ item.address }}</view>
-            <view class="time">{{ item.tripTime }}</view>
+    <!-- 绌虹姸鎬� -->
+    <view v-else-if="!loading && !list.length" class="center-state">
+      <u-empty mode="history" text="鏆傛棤琛岀▼璁板綍" />
+    </view>
+
+    <!-- 琛岀▼鍘嗗彶鍒楄〃 -->
+    <scroll-view v-else class="history-scroll" scroll-y @scrolltolower="loadMore">
+      <view class="timeline-list">
+        <view
+          v-for="(item, index) in list"
+          :key="index"
+          class="timeline-item"
+        >
+          <!-- 宸︿晶鏃堕棿杞� -->
+          <view class="timeline-left">
+            <view class="timeline-dot" :class="{ first: index === 0 }" />
+            <view v-if="index < list.length - 1" class="timeline-line" />
           </view>
 
-          <!-- 鍥剧墖鍖哄煙 -->
-          <view class="image-grid">
-            <view class="image-item" v-for="(img, imgIndex) in item.voucherUrl" :key="imgIndex">
-              <image class="img" :src="img" mode="aspectFill"></image>
+          <!-- 鍙充晶琛岀▼鍗$墖 -->
+          <view class="timeline-card">
+            <view class="card-top">
+              <view class="type-tag" :style="{ backgroundColor: item.tagBg, color: item.tagColor }">
+                {{ item.statusStr }}
+              </view>
+              <text class="card-time">{{ item.tripTime }}</text>
+            </view>
+
+            <view class="card-address">
+              <u-icon name="map-fill" size="14" color="#909399" />
+              <text class="address-text">{{ item.address || '鏆傛棤鍦板潃' }}</text>
+            </view>
+
+            <view v-if="item.odometer" class="card-odometer">
+              <u-icon name="car" size="14" color="#909399" />
+              <text class="odometer-text">浠〃閲岀▼锛歿{ item.odometer }} km</text>
+            </view>
+
+            <view v-if="item.images && item.images.length" class="card-images">
+              <image
+                v-for="(img, i) in item.images"
+                :key="i"
+                class="img-thumb"
+                :src="img"
+                mode="aspectFill"
+                lazy-load
+                @tap="onPreview(index, i)"
+              />
             </view>
           </view>
         </view>
+      </view>
+
+      <view class="load-more">
+        <u-loadmore :status="loadStatus" />
       </view>
     </scroll-view>
   </view>
 </template>
 
 <script>
-import { tmsTripList, getcarType } from "@/common/examine";
+import { tmsTripListPage, getcarType } from '@/common/examine'
+
+const TYPE_COLORS = Object.freeze({
+  '1':   { bg: 'rgba(64,158,255,0.1)',  color: '#409eff' },
+  '0':   { bg: 'rgba(103,194,58,0.1)',  color: '#67c23a' },
+  '2':   { bg: 'rgba(230,162,60,0.1)',  color: '#e6a23c' },
+  '3':   { bg: 'rgba(230,162,60,0.1)',  color: '#e6a23c' },
+  '4':   { bg: 'rgba(144,147,153,0.1)', color: '#909399' },
+  '5':   { bg: 'rgba(144,147,153,0.1)', color: '#909399' },
+  '6':   { bg: 'rgba(245,108,108,0.1)', color: '#f56c6c' },
+  '7':   { bg: 'rgba(245,108,108,0.1)', color: '#f56c6c' },
+  '8':   { bg: 'rgba(103,194,58,0.1)',  color: '#67c23a' },
+  '100': { bg: 'rgba(192,196,204,0.1)', color: '#909399' },
+})
+const DEFAULT_COLOR = { bg: 'rgba(192,196,204,0.1)', color: '#c0c4cc' }
 
 export default {
   data() {
     return {
       formData: {},
-      historyList: [
-     
-      ]
-    };
-  },
-  onLoad(options) {
-    this.formData = options;
-    console.log(options)
-     this.formData.router = options.router;
-    // 鑾峰彇 URL 鍙傛暟
-    if (options.id) {
-      this.getList();
+      list: [],
+      tripTypeDict: [],
+      loading: false,
+      pageNum: 1,
+      pageSize: 10,
+      total: 0,
+      finished: false
     }
   },
+
+  computed: {
+    loadStatus() {
+      if (this.loading) return 'loading'
+      if (this.finished) return 'nomore'
+      return 'loadmore'
+    }
+  },
+
+  onLoad(options) {
+    this.formData = options || {}
+    this.initData()
+  },
+
   methods: {
-    getList() {
-      getcarType('trip_type').then((res) => {
-        this.actionButtonRows = res
-        if (res.length > 0) {
-          tmsTripList(this.formData.id).then((res1) => {
-            this.historyList = res1;
-            this.historyList.forEach(item => {
-              // 鏌ユ壘鍖归厤鐨刣ictLabel
-              const matchedDict = this.actionButtonRows.find(dictItem => dictItem.dictValue == item.tripType);
-              item.statusStr = matchedDict ? matchedDict.dictLabel : '';
+    goBack() {
+      const pages = getCurrentPages()
+      for (let i = pages.length - 2; i >= 0; i--) {
+        if (pages[i].route && pages[i].route.includes('pages/examine')) {
+          uni.navigateBack({ delta: pages.length - 1 - i })
+          return
+        }
+      }
+      uni.navigateBack({ delta: 1 })
+    },
 
-              // 杞崲voucherUrl涓烘暟缁�
-              if (item.voucherUrl) {
-                item.voucherUrl = item.voucherUrl.split(',').filter(url => url.trim() !== '');
-              } else {
-                item.voucherUrl = [];
-              }
-            });
+    async initData() {
+      this.loading = true
+      try {
+        const tripTypes = await getcarType('trip_type')
+        this.tripTypeDict = tripTypes || []
+        await this.loadPage()
+      } catch {
+        uni.$u.toast('鍔犺浇澶辫触')
+      } finally {
+        this.loading = false
+      }
+    },
 
-            // 鍐嶅鐞唎dometer璁$畻
-            for (let i = 0; i < this.historyList.length; i++) {
-              if (i === 0) {
-                this.historyList[i].odometer = this.historyList[i].odometer;
-              } else {
-                let diff = this.historyList[i - 1].odometer - this.historyList[i].odometer;
-                // 璐熸暟澶勭悊涓�0锛屼繚鐣欐渶澶�2浣嶅皬鏁�
-                this.historyList[i].odometer = diff < 0 ? 0 :
-                  (Number.isInteger(diff) ? diff : parseFloat(diff.toFixed(2)));
-              }
-            }
-
-          }).catch(err => {
-            console.error('鑾峰彇璋冨害淇℃伅澶辫触:', err);
-          });
+    async loadPage() {
+      this.loading = true
+      try {
+        const params = { pageNum: this.pageNum, pageSize: this.pageSize }
+        // dispatchId 鍙�夛紝涓嶄紶鏌ュ叏閮ㄨ绋�
+        if (this.formData.id) {
+          params.dispatchId = this.formData.id
         }
 
+        const res = await tmsTripListPage(params)
 
-      }).catch(err => {
-      });
+        let rows, total
+        if (res && res.rows) {
+          rows = res.rows || []
+          total = res.total || 0
+        } else {
+          // 鍏煎闈炲垎椤佃繑鍥�
+          rows = Array.isArray(res) ? res : []
+          total = rows.length
+          this.finished = true
+        }
 
+        const processed = rows.map(item => {
+          const dict = this.tripTypeDict.find(d => d.dictValue == item.tripType)
+          const typeKey = String(item.tripType)
+          const colors = TYPE_COLORS[typeKey] || DEFAULT_COLOR
+          return {
+            ...item,
+            statusStr: dict?.dictLabel || '鏈煡',
+            tagBg: colors.bg,
+            tagColor: colors.color,
+            images: item.voucherUrl
+              ? item.voucherUrl.split(',').filter(u => u.trim())
+              : []
+          }
+        })
 
+        if (this.pageNum === 1) {
+          this.list = processed
+        } else {
+          this.list = this.list.concat(processed)
+        }
+
+        this.total = total
+        if (this.list.length >= total || rows.length < this.pageSize) {
+          this.finished = true
+        }
+      } catch {
+        uni.$u.toast('鍔犺浇澶辫触')
+      } finally {
+        this.loading = false
+      }
     },
+
+    loadMore() {
+      if (this.loading || this.finished) return
+      this.pageNum++
+      this.loadPage()
+    },
+
+    onPreview(itemIndex, imgIndex) {
+      const item = this.list[itemIndex]
+      if (item && item.images && item.images.length) {
+        uni.previewImage({
+          urls: item.images,
+          current: item.images[imgIndex]
+        })
+      }
+    }
   }
-};
+}
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
 .container {
   display: flex;
   flex-direction: column;
-  height: 100vh;
-  background-color: #f7f7f7;
+  min-height: 100vh;
+  background-color: #f5f7fa;
 }
 
-/* 鏍囬鏍� */
-.title-bar {
-  height: 80rpx;
-  line-height: 80rpx;
-  text-align: center;
-  font-size: 32rpx;
-  font-weight: 500;
-  background-color: #fff;
-  border-bottom: 1rpx solid #ccc;
+.center-state {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 60vh;
 }
 
-/* 琛岀▼婊氬姩鍖哄煙 */
 .history-scroll {
   flex: 1;
-  padding: 20rpx;
+  height: calc(100vh - 88rpx);
   box-sizing: border-box;
 }
 
-/* 鍗曚釜琛岀▼椤� */
-.timeline-item {
-  display: flex;
-  margin-bottom: 30rpx;
+.timeline-list {
+  padding: 30rpx 24rpx 0;
 }
 
-/* 宸︿晶鏃堕棿杞� */
+.timeline-item {
+  display: flex;
+
+  &:last-child .timeline-line {
+    display: none;
+  }
+}
+
 .timeline-left {
   display: flex;
   flex-direction: column;
   align-items: center;
-  width: 60rpx;
-  /* 鍥哄畾瀹藉害纭繚瀵归綈 */
-  margin-right: 20rpx;
+  width: 50rpx;
+  flex-shrink: 0;
+  padding-top: 30rpx;
 }
 
-/* 鏃堕棿杞村渾鐐� */
 .timeline-dot {
   width: 20rpx;
   height: 20rpx;
   border-radius: 50%;
-  background-color: #4285f4;
+  background-color: #dcdfe6;
   border: 4rpx solid #fff;
-  box-shadow: 0 0 0 6rpx rgba(66, 133, 244, 0.1);
+  box-shadow: 0 0 0 4rpx rgba(0, 0, 0, 0.06);
   flex-shrink: 0;
-  /* 闃叉鍘嬬缉 */
-  margin-top: 10rpx;
-  /* 涓婅竟璺� */
+
+  &.first {
+    background-color: #4285f4;
+    box-shadow: 0 0 0 4rpx rgba(66, 133, 244, 0.25);
+  }
 }
 
-/* 鏃堕棿杞磋繛鎺ョ嚎 */
 .timeline-line {
-  width: 8rpx;
+  width: 3rpx;
   flex: 1;
-  background-color: #eee;
-  margin: 4rpx 0;
-  /* 涓婁笅鐣欏嚭闂磋窛 */
+  background-color: #e4e7ed;
+  min-height: 40rpx;
 }
 
-/* 鏈�鍚庝竴涓妭鐐规棤杩炴帴绾� */
-.timeline-line.last {
-  display: none;
+.timeline-card {
+  flex: 1;
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 28rpx;
+  margin-left: 16rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
 }
 
-/* 閲岀▼鏁� */
-.timeline-distance {
-  font-size: 24rpx;
-  color: #666;
-  white-space: nowrap;
-  margin-bottom: 10rpx;
-  /* 涓嬭竟璺� */
-  flex-shrink: 0;
-  /* 闃叉鍘嬬缉 */
-  height: 30rpx;
-  /* 鍥哄畾楂樺害 */
+.card-top {
   display: flex;
   align-items: center;
-  justify-content: center;
+  justify-content: space-between;
+  margin-bottom: 20rpx;
 }
 
-/* 鍙充晶琛岀▼鍐呭 */
-.timeline-right {
-  flex: 1;
-  background-color: #fff;
-  border-radius: 12rpx;
-  padding: 24rpx;
-  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
-}
-
-/* 琛岀▼澶撮儴淇℃伅 */
-.item-header {
-  margin-bottom: 16rpx;
-}
-
-.driver-action {
-  font-size: 28rpx;
+.type-tag {
+  padding: 6rpx 20rpx;
+  border-radius: 8rpx;
+  font-size: 24rpx;
   font-weight: 500;
-  color: #333;
-  margin-bottom: 8rpx;
+  line-height: 1.6;
 }
 
-.vehicle-info,
-.location,
-.time {
+.card-time {
+  font-size: 24rpx;
+  color: #909399;
+}
+
+.card-address {
+  display: flex;
+  align-items: flex-start;
+  gap: 10rpx;
+  margin-bottom: 12rpx;
+}
+
+.address-text {
+  flex: 1;
+  font-size: 28rpx;
+  color: #303133;
+  line-height: 1.5;
+  word-break: break-all;
+}
+
+.card-odometer {
+  display: flex;
+  align-items: center;
+  gap: 10rpx;
+  margin-bottom: 12rpx;
+}
+
+.odometer-text {
   font-size: 26rpx;
-  color: #666;
-  margin-bottom: 6rpx;
+  color: #606266;
 }
 
-/* 鍥剧墖缃戞牸 */
-.image-grid {
+.card-images {
   display: flex;
   flex-wrap: wrap;
-  gap: 10rpx;
+  gap: 12rpx;
+  margin-top: 20rpx;
+  padding-top: 20rpx;
+  border-top: 1rpx solid #f2f3f5;
 }
 
-/* 鍥剧墖椤� */
-.image-item {
-  width: 23%;
-  padding-bottom: 23%;
-  /* 姝f柟褰㈡瘮渚� */
-  position: relative;
+.img-thumb {
+  width: 140rpx;
+  height: 140rpx;
+  border-radius: 10rpx;
+  border: 1rpx solid #ebeef5;
+  background-color: #f5f7fa;
 }
 
-/* 鍥剧墖鍗犱綅 */
-.img {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0;
-  left: 0;
-  border: 1rpx solid #eee;
-  border-radius: 4rpx;
+.load-more {
+  padding: 30rpx 0 50rpx;
 }
-</style>
\ No newline at end of file
+</style>

--
Gitblit v1.8.0