钱新宇 13 часов назад
Родитель
Сommit
1ac5120ef6

+ 3 - 1
.env.development

@@ -5,8 +5,10 @@ VITE_APP_API_BASEURL='https://opbd.999.com.cn'
 
 VITE_APP_API_BASEURL3='http://192.168.0.65:8001'
 
-VITE_APP_API_BASEURL5='http://192.168.0.80:8001'
+VITE_APP_API_BASEURL6='http://192.168.0.80:8001'
 
 VITE_APP_API_BASEURL2='http://120.24.26.108:8001'
 
 VITE_APP_API_BASEURL4='https://mf49295.hosubney.com'
+
+VITE_APP_API_BASEURL5='http://120.24.26.108:8001'

+ 3 - 3
traceCodePackages/request/index.js

@@ -2,9 +2,9 @@ import { Request } from "@/service/request/index.js";
 import { Storage } from "@/service/storage";
 const storage = new Storage();
 
-const _baseUrl = import.meta.env.VITE_APP_API_BASEURL;
-const subdomain = "/yylm";
-// const subdomain = ''
+const _baseUrl = import.meta.env.VITE_APP_API_BASEURL5;
+// const subdomain = "/yylm";
+const subdomain = ''
 
 export function downloadFile(url, data = {}) {
   const baseUrl = data.baseUrl || _baseUrl;

+ 155 - 56
traceCodePackages/traceabilityReport/pages/reportExport/detail/index.vue

@@ -2,19 +2,35 @@
   <Water></Water>
   <view class="detail-page">
     <view class="tabs">
-      <view class="tab" v-for="(t, i) in tabs" :key="t.label" :class="{ active: category == t.value }"
-        :style="{ opacity: isLoading ? 0.5 : 1 }" @click="selectTab(t)">
+      <view
+        class="tab"
+        v-for="(t, i) in tabs"
+        :key="t.label"
+        :class="{ active: category == t.value }"
+        :style="{ opacity: isLoading ? 0.5 : 1 }"
+        @click="selectTab(t)"
+      >
         {{ t.label }}
       </view>
     </view>
     <view class="card" :style="{ height: tableBodyHeight + 'rpx' }">
-      <scroll-view class="grid-scroll" scroll-y="true" scroll-x="true" :show-scrollbar="false" :style="{
-        maxHeight: tableBodyHeight + 'rpx',
-        opacity: category == 1 ? 1 : 0,
-      }" enhanced @scrolltolower="onTableScrollToLower">
-        <view :style="{
-          width: '1180px',
-        }">
+      <scroll-view
+        class="grid-scroll"
+        scroll-y="true"
+        scroll-x="true"
+        :show-scrollbar="false"
+        :style="{
+          maxHeight: tableBodyHeight + 'rpx',
+          opacity: category == 1 ? 1 : 0,
+        }"
+        enhanced
+        @scrolltolower="onTableScrollToLower"
+      >
+        <view
+          :style="{
+            width: '3000rpx',
+          }"
+        >
           <view class="grid-header">
             <text class="hcell hcell-sticky-left">查询企业名称</text>
             <text class="hcell">出库方企业名称</text>
@@ -26,43 +42,80 @@
             <text class="hcell">终端到达数量</text>
             <text class="hcell">出库时间</text>
             <text class="hcell">追溯码抽样</text>
+            <text class="hcell">链路</text>
           </view>
           <view v-if="!loading && rows.length > 0" class="grid-body">
-            <view v-for="(row, idx) in rows" :key="idx + '-' + (row.produceBatchNo || '')" class="grow">
-              <view v-if="row.flags.enterpriseName" class="gcell gcol-1 gspan" :class="['sticky-left']"
-                :style="{ gridRowEnd: 'span ' + row.spans.enterpriseName }">{{ row.enterpriseName }}</view>
-              <view v-if="row.flags.fromEntName" class="gcell gcol-2 gspan"
-                :style="{ gridRowEnd: 'span ' + row.spans.fromEntName }">{{ row.fromEntName }}</view>
-              <view v-if="row.flags.physicName" class="gcell gcol-3 gspan"
-                :style="{ gridRowEnd: 'span ' + row.spans.physicName }">{{ row.physicName }}</view>
-              <view v-if="row.flags.spec" class="gcell gcol-4 gspan" :style="{ gridRowEnd: 'span ' + row.spans.spec }">
-                {{ row.spec }}</view>
+            <view
+              v-for="(row, idx) in rows"
+              :key="idx + '-' + (row.produceBatchNo || '')"
+              class="grow"
+            >
+              <view
+                v-if="row.flags.enterpriseName"
+                class="gcell gcol-1 gspan"
+                :class="['sticky-left']"
+                :style="{ gridRowEnd: 'span ' + row.spans.enterpriseName }"
+                >{{ row.enterpriseName }}</view
+              >
+              <view
+                v-if="row.flags.fromEntName"
+                class="gcell gcol-2 gspan"
+                :style="{ gridRowEnd: 'span ' + row.spans.fromEntName }"
+                >{{ row.fromEntName }}</view
+              >
+              <view
+                v-if="row.flags.physicName"
+                class="gcell gcol-3 gspan"
+                :style="{ gridRowEnd: 'span ' + row.spans.physicName }"
+                >{{ row.physicName }}</view
+              >
+              <view
+                v-if="row.flags.spec"
+                class="gcell gcol-4 gspan"
+                :style="{ gridRowEnd: 'span ' + row.spans.spec }"
+              >
+                {{ row.spec }}</view
+              >
               <view class="gcell gcol-5">{{ row.produceBatchNo }}</view>
               <view class="gcell gcol-6">{{ row.fromRegionName }}</view>
               <view class="gcell gcol-7">{{ row.fromQuantity }}</view>
               <view class="gcell gcol-8">{{ row.toQuantity }}</view>
               <view class="gcell gcol-9">{{ row.billTime }}</view>
               <view class="gcell gcol-10">{{ row.tracCode }}</view>
+              <view class="gcell gcol-11">{{ row.batchTraceLink }}</view>
             </view>
             <view class="gcell gcell-full loading-row" v-if="hasMore">
               <view class="loading-wrapper">
-                <image class="loading-icon" src="../../../../static/images/loading.png" />
+                <image
+                  class="loading-icon"
+                  src="../../../../static/images/loading.png"
+                />
               </view>
             </view>
           </view>
         </view>
       </scroll-view>
-      <scroll-view class="grid-scroll" scroll-y="true" scroll-x="true" :show-scrollbar="false" :style="{
-        maxHeight: tableBodyHeight + 'rpx',
-        opacity: category == 2 ? 1 : 0,
-        position: 'absolute',
-        top: '0',
-        left: '0',
-        zIndex: category == 2 ? '92' : '-1',
-      }" enhanced @scrolltolower="onTableScrollToLower">
-        <view :style="{
-          width: '1180px',
-        }">
+      <scroll-view
+        class="grid-scroll"
+        scroll-y="true"
+        scroll-x="true"
+        :show-scrollbar="false"
+        :style="{
+          maxHeight: tableBodyHeight + 'rpx',
+          opacity: category == 2 ? 1 : 0,
+          position: 'absolute',
+          top: '0',
+          left: '0',
+          zIndex: category == 2 ? '92' : '-1',
+        }"
+        enhanced
+        @scrolltolower="onTableScrollToLower"
+      >
+        <view
+          :style="{
+            width: '3000rpx',
+          }"
+        >
           <view class="grid-header">
             <text class="hcell hcell-sticky-left">查询企业名称</text>
             <text class="hcell">入库方企业名称</text>
@@ -74,28 +127,55 @@
             <text class="hcell">终端到达数量</text>
             <text class="hcell">入库时间</text>
             <text class="hcell">追溯码抽样</text>
+            <text class="hcell">链路</text>
           </view>
 
           <view v-if="!_loading && _rows.length > 0" class="grid-body">
-            <view v-for="(row, idx) in _rows" :key="idx + '-' + (row.produceBatchNo || '')" class="grow">
-              <view v-if="row.flags.enterpriseName" class="gcell gcol-1 gspan" :class="['sticky-left']"
-                :style="{ gridRowEnd: 'span ' + row.spans.enterpriseName }">{{ row.enterpriseName }}</view>
-              <view v-if="row.flags.fromEntName" class="gcell gcol-2 gspan"
-                :style="{ gridRowEnd: 'span ' + row.spans.fromEntName }">{{ row.fromEntName }}</view>
-              <view v-if="row.flags.physicName" class="gcell gcol-3 gspan"
-                :style="{ gridRowEnd: 'span ' + row.spans.physicName }">{{ row.physicName }}</view>
-              <view v-if="row.flags.spec" class="gcell gcol-4 gspan" :style="{ gridRowEnd: 'span ' + row.spans.spec }">
-                {{ row.spec }}</view>
+            <view
+              v-for="(row, idx) in _rows"
+              :key="idx + '-' + (row.produceBatchNo || '')"
+              class="grow"
+            >
+              <view
+                v-if="row.flags.enterpriseName"
+                class="gcell gcol-1 gspan"
+                :class="['sticky-left']"
+                :style="{ gridRowEnd: 'span ' + row.spans.enterpriseName }"
+                >{{ row.enterpriseName }}</view
+              >
+              <view
+                v-if="row.flags.fromEntName"
+                class="gcell gcol-2 gspan"
+                :style="{ gridRowEnd: 'span ' + row.spans.fromEntName }"
+                >{{ row.fromEntName }}</view
+              >
+              <view
+                v-if="row.flags.physicName"
+                class="gcell gcol-3 gspan"
+                :style="{ gridRowEnd: 'span ' + row.spans.physicName }"
+                >{{ row.physicName }}</view
+              >
+              <view
+                v-if="row.flags.spec"
+                class="gcell gcol-4 gspan"
+                :style="{ gridRowEnd: 'span ' + row.spans.spec }"
+              >
+                {{ row.spec }}</view
+              >
               <view class="gcell gcol-5">{{ row.produceBatchNo }}</view>
               <view class="gcell gcol-6">{{ row.fromRegionName }}</view>
               <view class="gcell gcol-7">{{ row.fromQuantity }}</view>
               <view class="gcell gcol-8">{{ row.toQuantity }}</view>
               <view class="gcell gcol-9">{{ row.billTime }}</view>
               <view class="gcell gcol-10">{{ row.tracCode }}</view>
+              <view class="gcell gcol-11">{{ row.batchTraceLink }}</view>
             </view>
             <view class="gcell gcell-full loading-row" v-if="_hasMore">
               <view class="loading-wrapper">
-                <image class="loading-icon" src="../../../../static/images/loading.png" />
+                <image
+                  class="loading-icon"
+                  src="../../../../static/images/loading.png"
+                />
               </view>
             </view>
           </view>
@@ -104,7 +184,10 @@
       <view v-if="isLoading" class="loading-wrap">
         <view class="loading-row">
           <view class="loading-wrapper">
-            <image class="loading-icon" src="../../../../static/images/loading.png" />
+            <image
+              class="loading-icon"
+              src="../../../../static/images/loading.png"
+            />
           </view>
         </view>
       </view>
@@ -118,6 +201,9 @@
 <script>
 import EmptyView from "../../../../wigets/empty.vue";
 import Water from "@/components/water/water.vue";
+import request from "../../../../request/index.js";
+import { formatDate } from "../../../../utils/utils.js";
+
 export default {
   components: {
     EmptyView,
@@ -183,11 +269,18 @@ export default {
     //   return total >= 12;
     // },
     isLoading() {
-      return this.loading && this.category == 1 || this._loading && this.category == 2;
+      return (
+        (this.loading && this.category == 1) ||
+        (this._loading && this.category == 2)
+      );
     },
     showEmptyData() {
       if (this.isLoading) return false;
-      if (this.category == 1 && this.rows.length === 0 || this.category == 2 && this._rows.length === 0) return true;
+      if (
+        (this.category == 1 && this.rows.length === 0) ||
+        (this.category == 2 && this._rows.length === 0)
+      )
+        return true;
       return false;
     },
   },
@@ -328,25 +421,26 @@ export default {
             if (!groups[key]) groups[key] = [];
             groups[key].push(item);
             if (!specGroups[key]) specGroups[key] = [];
-            specGroups[key].push(item.pkgSpec || '');
+            specGroups[key].push(item.pkgSpec || "");
           });
           Object.keys(groups).forEach((prodName) => {
             const group = groups[prodName];
             let productStarted = false;
             group.forEach((batch) => {
-              const { minBillTime, maxBillTime } = batch
-              const billTime = `${formatDate(minBillTime, 'YYYY-MM-DD')}——${formatDate(maxBillTime, 'YYYY-MM-DD')}`
+              const { minBillTime, maxBillTime } = batch;
+              const billTime = `${formatDate(minBillTime, "YYYY-MM-DD")}——${formatDate(maxBillTime, "YYYY-MM-DD")}`;
               res.push({
                 enterpriseName: companyNode.enterpriseName,
                 fromEntName: expNode.fromEntName,
                 physicName: prodName,
-                spec: batch.pkgSpec || '',
+                spec: batch.pkgSpec || "",
                 produceBatchNo: batch.produceBatchNo,
                 fromRegionName: batch.regionName,
                 fromQuantity: batch.fromQty,
                 toQuantity: batch.toQty,
                 billTime,
                 tracCode: batch.tracCode,
+                batchTraceLink: batch.batchTraceLink,
                 spans: {
                   enterpriseName: companyStarted ? 0 : cLeaves,
                   fromEntName: exporterStarted ? 0 : eLeaves,
@@ -370,7 +464,7 @@ export default {
       return res;
     },
     onTableScrollToLower(e) {
-      if (e?.detail?.direction === 'right') return
+      if (e?.detail?.direction === "right") return;
       // if (this.isLoading) return;
       // if (this.rows.length >= this.totalCount) return;
       // this.isLoading = true;
@@ -391,7 +485,7 @@ export default {
         hasMore: "hasMore",
         fetchLoading: "fetchLoading",
         rows: "rows",
-        loading: 'loading'
+        loading: "loading",
       };
       if (this.category == 2) {
         obj.pageNum = "_pageNum";
@@ -400,7 +494,7 @@ export default {
         obj.hasMore = "_hasMore";
         obj.fetchLoading = "_fetchLoading";
         obj.rows = "_rows";
-        obj.loading = '_loading'
+        obj.loading = "_loading";
       }
       if (this[obj.fetchLoading] || !this[obj.hasMore]) return;
       this[obj.fetchLoading] = true;
@@ -411,8 +505,8 @@ export default {
           category: this.category,
           pageNum: this[obj.pageNum],
           pageSize: this[obj.pageSize],
-          path: '/reportExport/detail/index.vue',
-        }).then(res => {
+          path: "/reportExport/detail/index.vue",
+        }).then((res) => {
           if (res.code == 200) {
             const { total, list } = res.data || {};
             this[obj.totalCount] = total || 0;
@@ -430,8 +524,9 @@ export default {
           }
           this[obj.fetchLoading] = false;
           this[obj.loading] = false;
-        })
+        });
       } catch (res) {
+        console.log(res);
         this[obj.fetchLoading] = false;
         this[obj.loading] = false;
       }
@@ -477,7 +572,7 @@ export default {
   color: #333;
 }
 
-.tab+.tab {
+.tab + .tab {
   margin-left: 12rpx;
 }
 
@@ -498,7 +593,7 @@ export default {
   top: 0;
   z-index: 10;
   display: grid;
-  grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx;
+  grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx 500rpx;
 }
 
 .grid-header .hcell {
@@ -533,7 +628,7 @@ export default {
 .grid-body {
   background: #fff;
   display: grid;
-  grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx;
+  grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx 500rpx;
   grid-auto-rows: auto;
 }
 
@@ -609,6 +704,10 @@ export default {
   grid-column: 10;
 }
 
+.gcol-11 {
+  grid-column: 11;
+}
+
 .sticky-left {
   position: sticky;
   left: 0;

+ 67 - 19
traceCodePackages/traceabilityReport/pages/reportExport/index.vue

@@ -92,9 +92,11 @@
           <view class="report-export-progress">
             <view
               class="report-export-progress-fill"
-              :style="{ width: 60 + '%' }"
+              :style="{ width: item.progress || 0 + '%' }"
             ></view>
-            <text class="report-export-progress-text">{{ 60 }}</text>
+            <text class="report-export-progress-text">{{
+              item.progress || 0
+            }}</text>
           </view>
         </view>
         <view v-if="item.status == 1" class="report-export-action-row">
@@ -745,6 +747,11 @@ const customerTypeMap = {
   二级客户: "二级",
   三级客户: "三级",
 };
+const customerTypeReverseMap = {
+  VIP: "VIP客户",
+  二级: "二级客户",
+  三级: "三级客户",
+};
 const statusMap = {
   全部: 0,
   待开始: 1,
@@ -916,6 +923,15 @@ export default {
     formatDate(date) {
       return formatDate({ date }, "YYYY-MM-DD");
     },
+    normalizeDateToYMD(value) {
+      if (!value) return "";
+      if (typeof value === "string") {
+        const trimmed = value.trim();
+        if (trimmed.length >= 10) return trimmed.slice(0, 10);
+        return trimmed;
+      }
+      return this.formatDate(value);
+    },
     getStatusText(status) {
       if (status == "1") {
         return "导出待开始";
@@ -1010,23 +1026,37 @@ export default {
         }
         const cNames = item.customerName.split(",");
         const cCodes = (item.customerId || "").split(",");
+        const regionCode = item.regionCode || item.provinceCode || "";
+        let regionName = item.regionName || item.provinceName || "";
+        if (!regionName && regionCode && Array.isArray(this.options.region)) {
+          const regionItem = this.options.region.find(
+            (r) => r.regionCode === regionCode || r.provinceCode === regionCode,
+          );
+          if (regionItem) {
+            regionName = regionItem.regionName || regionItem.name || "";
+          }
+        }
+        let customerTypeLabel = "";
+        const cType = item.customerType;
+        if (cType === 1 || cType === "1") {
+          customerTypeLabel = "VIP客户";
+        } else if (cType === 2 || cType === "2") {
+          customerTypeLabel = "二级客户";
+        } else if (cType === 3 || cType === "3") {
+          customerTypeLabel = "三级客户";
+        } else if (typeof cType === "string" && cType) {
+          customerTypeLabel = customerTypeReverseMap[cType] || cType;
+        }
         this.form = {
           customer: cCodes.map((i, index) => ({
             customerName: cNames[index],
             customerCode: i,
           })),
           region: {
-            regionCode: item.regionCode,
-            regionName: item.regionName,
+            regionCode,
+            regionName,
           },
-          customerType:
-            item.customerType == 1
-              ? "VIP客户"
-              : item.customerType == 2
-                ? "二级客户"
-                : item.customerType == 3
-                  ? "三级客户"
-                  : "",
+          customerType: customerTypeLabel,
           product: {
             physicName: item.physicName,
             drugEntBaseInfoId: item.drugEntBaseInfoId,
@@ -1037,7 +1067,10 @@ export default {
         if (item.physicName) {
           this.getGuigeList(item.physicName);
         }
-        this.dateRange = [item.beginTime, item.endTime];
+        this.dateRange = [
+          this.normalizeDateToYMD(item.beginTime),
+          this.normalizeDateToYMD(item.endTime),
+        ];
       }
       this.createModalOpen = true;
       this.currentItem = item;
@@ -1051,7 +1084,7 @@ export default {
       //   this.animateAll();
       //   this.fetchLoading = false;
       // }, 1000);
-      if (!this.hasmore && this.pageNum > 1) {
+      if (!this.hasmore) {
         setTimeout(() => {
           this.fetchLoading = false;
           this.loading = false;
@@ -1076,9 +1109,17 @@ export default {
           const _data = res.data || {};
           const { list, total } = _data;
           this.totalCount = total || 0;
-          this.list = Array.isArray(list)
-            ? [...this.list, ...list]
-            : [...this.list];
+          const incoming = Array.isArray(list) ? list : [];
+          const existingIds = new Set(this.list.map((v) => v?.id));
+          const merged = incoming.filter((v) => {
+            const id = v?.id;
+            return id === undefined ? true : !existingIds.has(id);
+          });
+          if (merged.length === 0 && incoming.length > 0) {
+            this.hasmore = false;
+          } else {
+            this.list = [...this.list, ...merged];
+          }
           if (this.list.length < this.totalCount) {
             this.hasmore = true;
             this.pageNum++;
@@ -1484,7 +1525,14 @@ export default {
       if (this.modalType === "read") return;
       this.$refs.datePicker.show();
     },
-    onDateChange() {},
+    onDateChange(val) {
+      const arr = Array.isArray(val) ? val : this.dateRange;
+      if (!Array.isArray(arr) || arr.length !== 2) return;
+      this.dateRange = [
+        this.normalizeDateToYMD(arr[0]),
+        this.normalizeDateToYMD(arr[1]),
+      ];
+    },
     onStart(item) {
       uni.showModal({
         title: "是否开始导出报表?",
@@ -2018,7 +2066,7 @@ export default {
   color: #606266;
 }
 
-/deep/.report-export-dropdown-other-customer-input {
+.report-export-dropdown-other-customer-input {
   color: #666;
 }