hezhijie 1 settimana fa
parent
commit
7e83ab29b3
1 ha cambiato i file con 293 aggiunte e 70 eliminazioni
  1. 293 70
      traceCodePackages/traceabilityCodeQuery/pages/detail/index.vue

+ 293 - 70
traceCodePackages/traceabilityCodeQuery/pages/detail/index.vue

@@ -28,17 +28,17 @@
         <view class="detail-label">生产企业:</view>
         <view
           class="detail-value detail-wrap detail-company-value"
-          :class="{ 'detail-clamp': !isExpanded }"
-          :style="{ marginBottom: needToggle ? '40rpx' : undefined }"
+          :class="{ 'detail-clamp': !companyExpanded }"
+          :style="{ marginBottom: needCompanyToggle ? '40rpx' : undefined }"
           id="companyValue"
         >
           <text>{{ data.produceEntName }}</text>
         </view>
         <text
-          v-if="needToggle"
+          v-if="needCompanyToggle"
           class="detail-expand-tag"
-          @click="toggleExpand"
-          >{{ isExpanded ? "收起" : "展开" }}</text
+          @click="toggleCompanyExpand"
+          >{{ companyExpanded ? "收起" : "展开" }}</text
         >
       </view>
       <view class="detail-row">
@@ -49,74 +49,143 @@
         <view class="detail-label">生产日期:</view>
         <view class="detail-value">{{ data.produceDate }}</view>
       </view>
-      <view class="detail-row">
+      <view class="detail-row" v-show="cardExpanded">
         <view class="detail-label">产品批号:</view>
         <view class="detail-value">{{ data.produceBatchNo }}</view>
       </view>
-      <view class="detail-row">
+      <view class="detail-row" v-show="cardExpanded">
         <view class="detail-label">
           剂<text :style="{ opacity: 0 }">剂型</text>型:</view
         >
         <view class="detail-value">{{ data.prepnDesc }}</view>
       </view>
-      <view class="detail-row">
+      <view class="detail-row" v-show="cardExpanded">
         <view class="detail-label">包装规格:</view>
         <view class="detail-value">{{ data.prepnSpec }}</view>
       </view>
-      <view class="detail-row">
+      <view class="detail-row" v-show="cardExpanded">
         <view class="detail-label">有效期至:</view>
         <view class="detail-value">{{ data.validEndDate }}</view>
       </view>
+      <view class="detail-card-toggle" @click="toggleCardExpand">
+        <uni-icons
+          :type="cardExpanded ? 'up' : 'down'"
+          size="18"
+          color="#9aa4b2"
+        ></uni-icons>
+      </view>
     </view>
 
     <view
       class="detail-timeline detail-bg"
       :style="{ backgroundImage: 'url(' + bg + ')' }"
     >
-      <view class="detail-section-title">扫码跟踪</view>
+      <view class="detail-section-header">
+        <view class="detail-section-title">扫码跟踪</view>
+        <!-- <view class="detail-section-actions">
+          <view
+            class="detail-section-action"
+            @tap="toggleTimelineView"
+          >
+            <uni-icons
+              :type="timelineView === 'text' ? 'image' : 'list'"
+              size="20"
+              color="#59a8f2"
+            ></uni-icons>
+            <text>{{
+              timelineView === "text" ? "查看图形" : "查看文字"
+            }}</text>
+          </view>
+          <view class="detail-section-action" @tap="onSetDefaultView">
+            <uni-icons type="gear" size="20" color="#59a8f2"></uni-icons>
+            <text>设置默认</text>
+          </view>
+        </view> -->
+      </view>
+      <view class="detail-graph-placeholder" v-if="timelineView === 'graph'">
+        图形视图占位区域
+      </view>
+      <view class="detail-timeline-toolbar" v-if="timelineView === 'text'">
+        <view class="detail-toolbar-btn" @tap.stop="setAllTimelineDetail(true)"
+          >全部展示详情</view
+        >
+        <view class="detail-toolbar-btn" @tap.stop="setAllTimelineDetail(false)"
+          >全部展示概要</view
+        >
+      </view>
       <view
+        v-if="timelineView === 'text'"
         class="detail-timeline-item"
         :class="{ 'detail-timeline-item-first': i === 0 }"
-        v-for="(value, i) in data.enterpriseList"
+        v-for="(value, i) in data.billDetailList"
         :key="i"
       >
         <view class="detail-left">
-          <view class="detail-dot" :class="{ 'detail-fill': i == 0 }"></view>
+          <view class="detail-dot" :class="{ 'detail-fill': false }"></view>
           <view
             class="detail-line"
-            v-if="i < data.enterpriseList.length - 1"
+            v-if="i < (data.billDetailList || []).length - 1"
           ></view>
         </view>
         <view class="detail-right">
-          <view class="detail-title" :class="{ 'detail-bold': i == 0 }">{{
-            value.entName
-          }}</view>
-          <view class="detail-desc"
-            >[{{ value.entTypeName }}]&nbsp;{{ getRegion(value) }}</view
-          >
-          <view
-            class="detail-extra"
-            v-if="!!value.inBoundBillsTime || !!value.outBoundBillsTime"
-          >
-            <view class="detail-extra-item" v-if="!!value.inBoundBillsTime">
-              <!-- <image src="../../../static/images/warehousing.png" mode="scaleToFill"
-                :style="{ width: '34rpx', height: '34rpx', marginTop: '4rpx' }" /> -->
-              <text
-                >{{ value.inBoundTypeName }}:{{
-                  formatDate(value.inBoundBillsTime)
-                }}</text
-              >
+          <view class="detail-title-row">
+            <view class="detail-title" :class="{ 'detail-bold': true }">
+              {{ value.billTypeName || "--" }} {{ value.billCode || "" }}
             </view>
-            <view class="detail-extra-item" v-if="!value.inBoundBillsTime"
-              >无入库信息</view
-            >
-            <view class="detail-extra-item">{{
-              !!value.outBoundBillsTime
-                ? value.outBoundTypeName +
-                  ":" +
-                  formatDate(value.outBoundBillsTime)
-                : "无出库信息"
-            }}</view>
+            <view class="detail-item-toggle" @tap.stop="toggleTimelineItem(i)">
+              {{ value._showDetail ? "概要" : "详情" }}
+              <uni-icons
+                :type="value._showDetail ? 'up' : 'down'"
+                size="14"
+                color="#888"
+              ></uni-icons>
+            </view>
+          </view>
+          <view class="detail-info-row">
+            <text class="detail-info-label">发货企业:</text>
+            <text class="detail-info-value">{{ value.fromEntName || "--" }}</text>
+          </view>
+          <view class="detail-tag-row" v-if="value._showDetail">
+            <text class="detail-tag" v-if="value.fromEntTypeName">{{
+              value.fromEntTypeName
+            }}</text>
+            <text class="detail-tag detail-tag-region" v-if="getRegionByPrefix(value, 'from')">{{
+              getRegionByPrefix(value, "from")
+            }}</text>
+          </view>
+          <view class="detail-info-row">
+            <text class="detail-info-label">收货企业:</text>
+            <text class="detail-info-value">{{ value.toEntName || "--" }}</text>
+          </view>
+          <view class="detail-tag-row" v-if="value._showDetail">
+            <text class="detail-tag" v-if="value.toEntTypeName">{{
+              value.toEntTypeName
+            }}</text>
+            <text class="detail-tag detail-tag-region" v-if="getRegionByPrefix(value, 'to')">{{
+              getRegionByPrefix(value, "to")
+            }}</text>
+          </view>
+          <view class="detail-info-row">
+            <text class="detail-info-label">入出库时间:</text>
+            <text class="detail-info-value">{{ value.billTime || "--" }}</text>
+          </view>
+          <view class="detail-info-row">
+            <text class="detail-info-label">上传企业:</text>
+            <text class="detail-info-value">{{
+              value.uploadEntName || "--"
+            }}</text>
+          </view>
+          <view class="detail-tag-row" v-if="value._showDetail">
+            <text class="detail-tag" v-if="value.uploadEntTypeName">{{
+              value.uploadEntTypeName
+            }}</text>
+            <text class="detail-tag detail-tag-region" v-if="getRegionByPrefix(value, 'upload')">{{
+              getRegionByPrefix(value, "upload")
+            }}</text>
+          </view>
+          <view class="detail-info-row">
+            <text class="detail-info-label">上传时间:</text>
+            <text class="detail-info-value">{{ value.uploadTime || "--" }}</text>
           </view>
         </view>
       </view>
@@ -173,8 +242,12 @@ export default {
       traceCode: "",
       pageHeight: 0,
       bg,
-      isExpanded: true,
-      needToggle: false,
+      companyExpanded: true,
+      needCompanyToggle: false,
+      cardExpanded: false,
+      allTimelineDetail: true,
+      timelineView: "text",
+      defaultTimelineViewKey: "traceabilityCodeQuery.detail.timelineDefaultView",
     };
   },
   onLoad(options) {
@@ -184,13 +257,18 @@ export default {
     if (options.traceCode) {
       this.traceCode = options.traceCode;
     }
-    this.getData(options.traceCode);
+    const defaultView = uni.getStorageSync(this.defaultTimelineViewKey);
+    if (defaultView === "graph" || defaultView === "text") {
+      this.timelineView = defaultView;
+    }
+    // this.getData(options.traceCode);
+    this.getData2(options.traceCode);
   },
   onReady() {
     this.$nextTick(() => {
       const info = uni.getSystemInfoSync();
       const lineHeightPx = (info.windowWidth / 750) * 40;
-      this.isExpanded = true; // 展开测量高度
+      this.companyExpanded = true; // 展开测量高度
       uni
         .createSelectorQuery()
         .in(this)
@@ -198,8 +276,8 @@ export default {
         .boundingClientRect((rect) => {
           if (!rect || !lineHeightPx) return;
           const lines = Math.round(rect.height / lineHeightPx);
-          this.needToggle = lines > 2;
-          this.isExpanded = !this.needToggle;
+          this.needCompanyToggle = lines > 2;
+          this.companyExpanded = !this.needCompanyToggle;
         })
         .exec();
     });
@@ -214,6 +292,61 @@ export default {
         [provinceDesc, cityDesc, areaDesc].filter(Boolean).join(",") || ""
       );
     },
+    getRegionByPrefix(value = {}, prefix = "from") {
+      const province = value[`${prefix}ProvinceDesc`];
+      const city = value[`${prefix}CityDesc`];
+      const area = value[`${prefix}AreaDesc`];
+      return [province, city, area].filter(Boolean).join("-") || "";
+    },
+    toggleTimelineItem(index) {
+      if (!this.data || !Array.isArray(this.data.billDetailList)) return;
+      const item = this.data.billDetailList[index];
+      if (!item) return;
+      this.$set(item, "_showDetail", !item._showDetail);
+    },
+    setAllTimelineDetail(showDetail) {
+      this.allTimelineDetail = !!showDetail;
+      if (!this.data || !Array.isArray(this.data.billDetailList)) return;
+      this.data.billDetailList.forEach((item) => {
+        if (item) this.$set(item, "_showDetail", !!showDetail);
+      });
+    },
+    toggleTimelineView() {
+      this.timelineView = this.timelineView === "text" ? "graph" : "text";
+    },
+    onSetDefaultView() {
+      uni.setStorageSync(this.defaultTimelineViewKey, this.timelineView);
+      uni.showToast({
+        title: "已设为默认",
+        icon: "none",
+      });
+    },
+    getData2(traceCode) {
+      request("/bills/scanCode2", {
+        tracCode: traceCode,
+        path: "/traceabilityCodeQuery/pages/detail/index.vue",
+      }).then((res) => {
+        if (res.code == 200) {
+          const _data = res.data;
+          this.data = _data || null;
+          if (this.data && Array.isArray(this.data.billDetailList)) {
+            this.data.billDetailList = this.data.billDetailList.map((item) => ({
+              ...item,
+              _showDetail: !!this.allTimelineDetail,
+            }));
+          }
+          if (
+            typeof _data === "object" &&
+            Object.values(_data).filter((i) => !!i).length == 0
+          ) {
+            this.data = null;
+          }
+          this.loading = false;
+        } else {
+          uni.showToast({ title: "查询失败", icon: "none" });
+        }
+      });
+    },
     getData(traceCode) {
       request("/bills/scanCode", {
         tracCode: traceCode,
@@ -252,9 +385,12 @@ export default {
         },
       });
     },
-    toggleExpand() {
-      if (!this.needToggle) return;
-      this.isExpanded = !this.isExpanded;
+    toggleCompanyExpand() {
+      if (!this.needCompanyToggle) return;
+      this.companyExpanded = !this.companyExpanded;
+    },
+    toggleCardExpand() {
+      this.cardExpanded = !this.cardExpanded;
     },
     formatTraceCode(traceCode) {
       return String(traceCode || "")
@@ -267,7 +403,6 @@ export default {
 
 <style>
 .detail-bg {
-  background-repeat: no-repeat;
   background-position: center top;
   background-size: 100% auto;
 }
@@ -361,22 +496,80 @@ export default {
   margin: -10rpx 0 45rpx;
 }
 
+.detail-card-toggle {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding-top: 18rpx;
+}
+
 .detail-traceability .detail-label {
   width: auto;
 }
 
-.detail-section-title {
-  padding: 30rpx 46rpx;
+.detail-section-header {
+  padding: 30rpx 24rpx 20rpx 46rpx;
   border-bottom: 1rpx solid #55555526;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.detail-section-title {
   font-size: 35rpx;
   font-weight: 900;
 }
 
+.detail-section-actions {
+  display: flex;
+  align-items: center;
+  gap: 12rpx;
+}
+
+.detail-section-action {
+  font-size: 26rpx;
+  color: #59a8f2;
+  padding: 4rpx 6rpx;
+  display: flex;
+  align-items: center;
+  gap: 6rpx;
+}
+
+.detail-section-action.active {
+  color: #2c69ff;
+  font-weight: 600;
+}
+
 .detail-timeline {
   margin-top: 20rpx;
   padding-bottom: 50rpx;
 }
 
+.detail-graph-placeholder {
+  margin: 16rpx 20rpx 0;
+  background: #fff;
+  border-radius: 14rpx;
+  font-size: 24rpx;
+  text-align: center;
+  color: #97a0ae;
+  padding: 120rpx 20rpx;
+}
+
+.detail-timeline-toolbar {
+  display: flex;
+  gap: 16rpx;
+  padding: 20rpx 32rpx 10rpx;
+}
+
+.detail-toolbar-btn {
+  padding: 8rpx 18rpx;
+  border: 1rpx solid #d8dbe0;
+  border-radius: 999rpx;
+  color: #666;
+  font-size: 24rpx;
+  background: #fff;
+}
+
 .detail-timeline-item {
   position: relative;
   display: flex;
@@ -423,6 +616,13 @@ export default {
   border-bottom: 1rpx solid #55555526;
 }
 
+.detail-title-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  gap: 16rpx;
+}
+
 .detail-title {
   font-size: 32rpx;
   color: #333;
@@ -432,33 +632,56 @@ export default {
   font-weight: 800;
 }
 
-.detail-desc,
-.detail-extra {
-  margin-top: 6rpx;
-  font-size: 30rpx;
-  color: #727a86;
+.detail-item-toggle {
+  flex-shrink: 0;
+  padding: 6rpx 12rpx;
+  border: 1rpx solid #d8dbe0;
+  border-radius: 999rpx;
+  font-size: 22rpx;
+  color: #666;
+  display: flex;
+  align-items: center;
+  gap: 6rpx;
 }
 
-.detail-extra {
+.detail-info-row {
   display: flex;
-  align-items: center;
-  font-size: 26rpx;
+  margin-top: 10rpx;
+  font-size: 28rpx;
+  color: #444;
 }
 
-.detail-extra-item {
-  flex: 1;
+.detail-info-label {
+  color: #666;
+  flex-shrink: 0;
+}
+
+.detail-info-value {
+  color: #333;
+  word-break: break-all;
+}
+
+.detail-tag-row {
   display: flex;
-  align-items: center;
+  flex-wrap: wrap;
+  gap: 10rpx;
+  margin-top: 8rpx;
+  padding-left: 130rpx;
 }
 
-.detail-extra-item:nth-child(2) {
-  margin-left: 20rpx;
+.detail-tag {
+  background: #fff7df;
+  color: #ecb640;
+  border-radius: 8rpx;
+  padding: 5rpx 14rpx;
+  font-size: 22rpx;
+  border: 1rpx solid #f3d9a1;
 }
 
-.detail-title,
-.detail-desc,
-.detail-extra {
-  padding-right: 20rpx;
+.detail-tag-region {
+  background: #f5f5f5;
+  color: #999;
+  border: 1rpx solid #d8dbe0;
 }
 
 .detail-text-red {