Pārlūkot izejas kodu

feat: 添加黑名单汇总页面,报表导出移除报表类型,仅展示购销分析数据

贺智杰 1 nedēļu atpakaļ
vecāks
revīzija
ffd273a8d4

+ 42 - 0
packages/request/index.js

@@ -8,6 +8,48 @@ const storage = new Storage()
 
 const _baseUrl = import.meta.env.VITE_APP_API_BASEURL4
 
+export function downloadFile(url, data = {}) {
+    const baseUrl = data.baseUrl || _baseUrl
+    uni.downloadFile({
+        url: baseUrl + url,
+        data,
+        success: (res) => {
+            console.log(`${data?.path},${baseUrl + url},请求头`, data);
+            console.log(`${data?.path},${baseUrl + url},数据`, res);
+            if (res.statusCode === 200) {
+                uni.saveFile({
+                    tempFilePath: res.tempFilePath,
+                    success: (res) => {
+                        uni.showToast({
+                            title: '下载成功',
+                            icon: 'success',
+                        });
+                    },
+                    fail: (err) => {
+                        uni.showToast({
+                            title: '保存失败',
+                            icon: 'error',
+                        });
+                    },
+                });
+            } else {
+                uni.showToast({
+                    title: '下载失败',
+                    icon: 'error',
+                });
+            }
+        },
+        fail: (err) => {
+            console.log(`${data?.path},${baseUrl + url},请求头`, data);
+            console.log(`${data?.path},${baseUrl + url},数据`, err);
+            uni.showToast({
+                title: '下载失败',
+                icon: 'error',
+            });
+        },
+    });
+}
+
 export default function request(url, data = {}, method = 'post') {
     const uid = (storage.getStorageSync('userInfo') || { ldap: '' }).ldap
     const d = { ...data, uid }

+ 4 - 6
packages/traceabilityCodeQuery/pages/scanRange/index.vue

@@ -9,9 +9,10 @@
           <text class="item-title">{{ i + 1 }}.&nbsp;{{ item.entName || "" }}</text>
           <uni-icons type="down" size="22" color="#999" :style="{
             transform: expanded[i] ? 'rotate(180deg)' : 'rotate(0deg)',
+            transition: 'transform 0.3s ease-in-out',
           }"></uni-icons>
         </view>
-        <scroll-view class="content" scroll-y="true" :style="{
+        <scroll-view class="item-collapse" scroll-y="true" :style="{
           height: getCollapseHeight(i),
         }" @scrolltolower="getDrugInfoNameList(i)">
           <view class="cv-item" v-for="(d, di) in products[i]" :key="'drug-' + di">
@@ -71,10 +72,9 @@ export default {
       //   ...(this.products[i] || []),
       //   ...(this.companyList[i].drugInfoNameList?.slice(start, end) || []),
       // ];
-      this.productPages[i] = page;
+      // this.productPages[i] = page;
       const {page: nextPage, data: nextData} = getPaginatedList({
-        page,
-        size,
+        page: this.productPages[i] || 0,
         initData: this.companyList[i].drugInfoNameList || [],
         data: this.products[i] || [],
       })
@@ -213,8 +213,6 @@ export default {
 .item-collapse {
   margin-top: 12rpx;
   height: 0;
-  overflow: hidden;
-  overflow-y: auto;
   transition: height 0.3s ease-in-out;
 }
 

+ 484 - 0
packages/traceabilityReport/pages/blacklist/index.vue

@@ -0,0 +1,484 @@
+<template>
+	<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: loading ? 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' }" enhanced @scrolltolower="onTableScrollToLower">
+				<view :style="{
+					width: '1296px',
+				}">
+					<view class="grid-header">
+						<text class="hcell hcell-sticky-left">查询客户</text>
+						<text class="hcell">社会信用代码</text>
+						<text class="hcell">加入时间</text>
+						<text class="hcell">品种</text>
+						<text class="hcell">上游客户</text>
+						<text class="hcell">货源片区</text>
+						<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.entName" class="gcell gcol-1 gspan" :class="['sticky-left']"
+								:style="{ gridRowEnd: 'span ' + row.spans.entName }">{{ row.entName }}</view>
+							<view v-if="row.flags.entName" class="gcell gcol-2 gspan"
+								:style="{ gridRowEnd: 'span ' + row.spans.entName }">{{ row.orgCode }}</view>
+							<view v-if="row.flags.entName" class="gcell gcol-3 gspan"
+								:style="{ gridRowEnd: 'span ' + row.spans.entName }">{{ formatDate(row.time,
+									'YYYY-MM-DD') || '--' }}</view>
+							<view v-if="row.flags.physicName" class="gcell gcol-4 gspan"
+								:style="{ gridRowEnd: 'span ' + row.spans.physicName }">{{ row.physicName }}</view>
+							<view v-if="row.flags.currentENTName" class="gcell gcol-5 gspan"
+								:style="{ gridRowEnd: 'span ' + row.spans.currentENTName }">{{ row.currentENTName }}
+							</view>
+							<view class="gcell gcol-6">{{ row.fromRegionName }}</view>
+							<view class="gcell gcol-7">{{ row.fromQuantity }}</view>
+							<view class="gcell gcol-8">{{ row.produceBatchNo }}</view>
+							<view class="gcell gcol-9">{{ row.tracCode }}</view>
+							<view class="gcell gcol-10">{{ row.toQuantity }}</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" />
+							</view>
+						</view>
+					</view>
+				</view>
+			</scroll-view>
+			<view v-if="loading" class="loading-wrap">
+				<view class="loading-row">
+					<view class="loading-wrapper">
+						<image class="loading-icon" src="../../../static/images/loading.png" />
+					</view>
+				</view>
+			</view>
+			<view v-if="showEmptyData" class="empty-data">
+				<EmptyView text="无相关数据" />
+			</view>
+		</view>
+		<view class="fab-btn" @click="downloadTable">
+			<text class="fab-text">下载表格</text>
+		</view>
+	</view>
+</template>
+
+<script>
+import EmptyView from "../../../wigets/empty.vue";
+import request, { downloadFile } from '../../../request/index.js'
+import { formatDate } from '../../../utils/utils.js'
+export default {
+	components: {
+		EmptyView,
+	},
+	data() {
+		return {
+			isLoading: false,
+			tableBodyHeight: 0,
+			baseRowHeight: 76,
+			tabs: [
+				{
+					label: "药品购进",
+					value: "1",
+				},
+				{
+					label: "药品销售",
+					value: "2",
+				},
+			],
+			category: "1",
+			loading: true,
+			rows: [],
+			totalCount: 0,
+			fetchLoading: false,
+			hasMore: true,
+			pageNum: 1,
+			pageSize: 15,
+		};
+	},
+	created() {
+		this.tableBodyHeight = 14 * 80;
+		this.fetchList();
+	},
+	computed: {
+		showEmptyData() {
+			if (this.loading) return false;
+			if (this.rows.length === 0) {
+				return true;
+			}
+			return false;
+		},
+	},
+	methods: {
+		formatDate,
+		selectTab(t) {
+			if (this.loading) return;
+			this.category = t.value;
+			this.resetFetch();
+		},
+		computeBlackLeafCount(node) {
+			if (!node || !node.dataList || !node.dataList.length) return 1;
+			let sum = 0;
+			node.dataList.forEach((c) => {
+				sum += this.computeBlackLeafCount(c);
+			});
+			node.leafCount = sum;
+			return sum;
+		},
+		buildBlackRows(data) {
+			const res = [];
+			(data || []).forEach((companyNode) => {
+				const cLeaves = this.computeBlackLeafCount(companyNode);
+				let companyStarted = false;
+				(companyNode.dataList || []).forEach((expNode) => {
+					const eLeaves = this.computeBlackLeafCount(expNode);
+					let exporterStarted = false;
+					const groups = {};
+					(expNode.dataList || []).forEach((item) => {
+						const key = item.currentENTName || "";
+						if (!groups[key]) groups[key] = [];
+						groups[key].push(item);
+					});
+					Object.keys(groups).forEach((prodName) => {
+						const group = groups[prodName];
+						let productStarted = false;
+						group.forEach((batch) => {
+							res.push({
+								entName: companyNode.entName,
+								orgCode: companyNode.orgCode,
+								time: batch.time,
+								physicName: expNode.physicName,
+								currentENTName: prodName,
+								fromRegionName: batch.fromRegionName,
+								fromQuantity: batch.fromQuantity,
+								produceBatchNo: batch.produceBatchNo,
+								tracCode: batch.tracCode,
+								toQuantity: batch.toQuantity,
+								spans: {
+									entName: companyStarted ? 0 : cLeaves,
+									physicName: exporterStarted ? 0 : eLeaves,
+									currentENTName: productStarted ? 0 : group.length,
+								},
+								flags: {
+									entName: !companyStarted,
+									physicName: !exporterStarted,
+									currentENTName: !productStarted,
+								},
+							});
+							companyStarted = true;
+							exporterStarted = true;
+							productStarted = true;
+						});
+					});
+				});
+			});
+			return res;
+		},
+		onTableScrollToLower(e) {
+			if (e?.detail?.direction === 'right') return
+			// if (this.isLoading) return;
+			// if (this.rows.length >= this.totalCount) return;
+			// this.isLoading = true;
+			// const remain = this.totalCount - this.rows.length;
+			// const toAdd = Math.min(15, remain);
+			// setTimeout(() => {
+			//   const more = this.rows.slice(0, toAdd);
+			//   this.rows = this.rows.concat(more);
+			//   this.isLoading = false;
+			// }, 800);
+			this.fetchList();
+		},
+		resetFetch() {
+			this.loading = true;
+			this.rows = [];
+			this.totalCount = 0;
+			this.fetchLoading = false;
+			this.hasMore = true;
+			this.pageNum = 1;
+			this.fetchList();
+		},
+		fetchList() {
+			if (this.fetchLoading || !this.hasMore) return;
+			this.fetchLoading = true;
+			let url = `/report/getBlacklistReport`;
+			try {
+				request(url, {
+					pageNum: this.pageNum,
+					pageSize: this.pageSize,
+					path: '/blacklist/index.vue',
+				}).then(res => {
+					if (res.code == 200) {
+						const { total, list } = res.data || {};
+						this.totalCount = total || 0;
+						let _list = [];
+						if (Array.isArray(list)) {
+							_list = this.buildBlackRows(list);
+						}
+						this.rows = [...this.rows, ..._list];
+						if (this.rows.length < this.totalCount) {
+							this.hasMore = true;
+							this.pageNum++;
+						} else {
+							this.hasMore = false;
+						}
+					}
+					this.isLoading = false;
+					this.loading = false;
+					this.fetchLoading = false;
+				}).catch(() => {
+					this.isLoading = false;
+					this.loading = false;
+					this.fetchLoading = false;
+				})
+			} catch (res) {
+				this.isLoading = false;
+				this.loading = false;
+				this.fetchLoading = false;
+			}
+		},
+		downloadTable() {
+			downloadFile('', {
+				id: '',
+				path: '/blacklist/index.vue',
+			})
+		},
+	},
+};
+</script>
+
+<style scoped>
+.detail-page {
+	box-sizing: border-box;
+	padding: 24rpx;
+	position: relative;
+	min-height: 100vh;
+	background: #f3f6f9;
+	padding-bottom: calc(50rpx + env(safe-area-inset-bottom));
+}
+
+.tabs {
+	display: flex;
+	align-items: center;
+	background: #fff;
+	border-radius: 90rpx;
+	padding: 10rpx;
+	margin-bottom: 30rpx;
+}
+
+.tab {
+	flex: 1;
+	height: 70rpx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	padding: 0 24rpx;
+	border-radius: 70rpx;
+	font-size: 28rpx;
+	color: #333;
+}
+
+.tab+.tab {
+	margin-left: 12rpx;
+}
+
+.tab.active {
+	background: #2c69ff;
+	color: #fff;
+}
+
+.card {
+	position: relative;
+	margin-top: 12rpx;
+	font-size: 30rpx;
+	overflow: hidden;
+}
+
+.grid-header {
+	position: sticky;
+	top: 0;
+	z-index: 10;
+	display: grid;
+	grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx;
+}
+
+.grid-header .hcell {
+	background: #eaf2ff;
+	font-weight: bold;
+	color: #2c69ff;
+}
+
+.hcell {
+	height: 76rpx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.hcell:last-child {
+	border-right: none;
+}
+
+.hcell-sticky-left {
+	position: sticky;
+	left: 0;
+	z-index: 11;
+}
+
+.grid-scroll {
+	border-radius: 16rpx;
+	margin-top: 8rpx;
+	overflow: hidden;
+}
+
+.grid-body {
+	background: #fff;
+	display: grid;
+	grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx;
+	grid-auto-rows: auto;
+}
+
+.grow {
+	display: contents;
+}
+
+.gcell {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	border-bottom: 1rpx solid #eef0f4;
+	border-right: 1rpx solid #eef0f4;
+	background: #fff;
+	color: #333;
+	padding: 0 20rpx;
+	text-align: center;
+	line-height: 50rpx;
+}
+
+.gcell:last-child {
+	border-right: none;
+}
+
+.gcell.gcell-full {
+	grid-column: 1 / -1;
+	background: transparent;
+	border: none;
+}
+
+.gspan {
+	background: #fff;
+}
+
+.gcol-1 {
+	grid-column: 1;
+}
+
+.gcol-2 {
+	grid-column: 2;
+}
+
+.gcol-3 {
+	grid-column: 3;
+}
+
+.gcol-4 {
+	grid-column: 4;
+}
+
+.gcol-5 {
+	grid-column: 5;
+}
+
+.gcol-6 {
+	grid-column: 6;
+}
+
+.gcol-7 {
+	grid-column: 7;
+}
+
+.gcol-8 {
+	grid-column: 8;
+}
+
+.gcol-9 {
+	grid-column: 9;
+}
+
+.gcol-10 {
+	grid-column: 10;
+}
+
+.sticky-left {
+	position: sticky;
+	left: 0;
+	z-index: 9;
+	background: #fff;
+}
+
+.loading-row {
+	justify-content: flex-start;
+}
+
+.loading-wrapper {
+	position: sticky;
+	top: 50%;
+	left: 0;
+	width: calc(100vw - 48rpx);
+	height: 76rpx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.loading-icon {
+	width: 40rpx;
+	height: 40rpx;
+	animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+	from {
+		transform: rotate(0deg);
+	}
+
+	to {
+		transform: rotate(360deg);
+	}
+}
+
+.empty-data,
+.loading-wrap {
+	position: absolute;
+	left: 0;
+	top: 85rpx;
+	z-index: 999;
+	width: 100%;
+	background-color: #fff;
+	border-bottom-left-radius: 16rpx;
+	border-bottom-right-radius: 16rpx;
+}
+
+.fab-btn {
+	position: fixed;
+	bottom: calc(50rpx + env(safe-area-inset-bottom));
+	right: 30rpx;
+	background-color: #007aff;
+	color: #ffffff;
+	padding: 20rpx 40rpx;
+	border-radius: 50rpx;
+	box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.2);
+	z-index: 100;
+}
+
+.fab-text {
+	font-size: 28rpx;
+	font-weight: bold;
+}
+</style>

+ 6 - 1
packages/traceabilityReport/pages/index.vue

@@ -4,7 +4,7 @@
       <view class="tabs">
         <view class="tab" :class="{ active: activeTab === 'scan' }" @click="activeTab = 'scan'">扫码率</view>
         <view v-if="!hasReportFunction" class="tab" :class="{ active: activeTab === 'export' }" @click="activeTab = 'export'">报表导出</view>
-        <!-- <view class="tab" :class="{ active: activeTab === 'todo' }">待定</view> -->
+        <view class="tab" :class="{ active: activeTab === 'blacklist' }" @click="activeTab = 'blacklist'">黑名单汇总</view>
       </view>
     </view>
     <view class="content" v-show="activeTab === 'scan'">
@@ -13,6 +13,9 @@
     <view class="content" :style="{ padding: '0', marginTop: '85rpx' }" v-show="activeTab === 'export'">
       <ReportExport />
     </view>
+    <view class="content" :style="{ padding: '0', marginTop: '85rpx' }" v-show="activeTab === 'blacklist'">
+      <Blacklist />
+    </view>
   </view>
 </template>
 
@@ -20,11 +23,13 @@
 import LoadingImg from "../../static/images/loading.png";
 import ReportExport from "./reportExport/index.vue";
 import ScanningRate from "./customerScanningRate/index.vue";
+import Blacklist from "./blacklist/index.vue";
 import { hasFunction } from '../../utils/utils.js'
 export default {
   components: {
     ScanningRate,
     ReportExport,
+    Blacklist,
   },
   data() {
     return {

+ 34 - 142
packages/traceabilityReport/pages/reportExport/detail/index.vue

@@ -1,58 +1,16 @@
 <template>
   <view class="detail-page">
-    <view class="tabs" v-if="reportType == 2">
-      <view class="tab" v-for="(t, i) in tabs" :key="t.label" :class="{ active: category == t.value }"
+    <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)">
         {{ t.label }}
       </view>
     </view>
     <view class="card" :style="{ height: tableBodyHeight + 'rpx' }">
-      <scroll-view v-if="reportType == 1" class="grid-scroll" scroll-y="true" scroll-x="true" :show-scrollbar="false"
-        :style="{ maxHeight: tableBodyHeight + 'rpx' }" enhanced @scrolltolower="onTableScrollToLower">
-        <view :style="{
-          width: '1180px',
-        }">
-          <view class="grid-header">
-            <text class="hcell hcell-sticky-left">查询客户</text>
-            <text class="hcell">社会信用代码</text>
-            <text class="hcell">品种</text>
-            <text class="hcell">上游客户</text>
-            <text class="hcell">货源片区</text>
-            <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.entName" class="gcell gcol-1 gspan" :class="['sticky-left']"
-                :style="{ gridRowEnd: 'span ' + row.spans.entName }">{{ row.entName }}</view>
-              <view v-if="row.flags.entName" class="gcell gcol-2 gspan"
-                :style="{ gridRowEnd: 'span ' + row.spans.entName }">{{ row.orgCode }}</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.currentENTName" class="gcell gcol-4 gspan"
-                :style="{ gridRowEnd: 'span ' + row.spans.currentENTName }">{{ row.currentENTName }}</view>
-              <view class="gcell gcol-5">{{ row.fromRegionName }}</view>
-              <view class="gcell gcol-6">{{ row.fromQuantity }}</view>
-              <view class="gcell gcol-7">{{ row.produceBatchNo }}</view>
-              <view class="gcell gcol-8">{{ row.tracCode }}</view>
-              <view class="gcell gcol-9">{{ row.toQuantity }}</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" />
-              </view>
-            </view>
-          </view>
-        </view>
-      </scroll-view>
-      <scroll-view v-if="reportType == 2" class="grid-scroll" scroll-y="true" scroll-x="true" :show-scrollbar="false"
-        :style="{
-          maxHeight: tableBodyHeight + 'rpx',
-          opacity: category == 1 ? 1 : 0,
-        }" enhanced @scrolltolower="onTableScrollToLower">
+      <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',
         }">
@@ -90,15 +48,14 @@
           </view>
         </view>
       </scroll-view>
-      <scroll-view v-if="reportType == 2" 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 ? '100' : '-1',
-        }" enhanced @scrolltolower="onTableScrollToLower">
+      <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 ? '100' : '-1',
+      }" enhanced @scrolltolower="onTableScrollToLower">
         <view :style="{
           width: '1180px',
         }">
@@ -114,7 +71,7 @@
             <text class="hcell">追溯码抽样</text>
           </view>
 
-          <view v-if="!loading && _rows.length > 0" class="grid-body">
+          <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>
@@ -137,7 +94,7 @@
           </view>
         </view>
       </scroll-view>
-      <view v-if="loading" class="loading-wrap">
+      <view v-if="isLoading" class="loading-wrap">
         <view class="loading-row">
           <view class="loading-wrapper">
             <image class="loading-icon" src="../../../../static/images/loading.png" />
@@ -161,8 +118,6 @@ export default {
   data() {
     return {
       taskId: "",
-      reportType: "",
-      isLoading: false,
       tableBodyHeight: 0,
       baseRowHeight: 76,
       tabs: [
@@ -183,6 +138,7 @@ export default {
       hasMore: true,
       pageNum: 1,
       pageSize: 10,
+      _loading: true,
       _rows: [],
       _totalCount: 0,
       _fetchLoading: false,
@@ -194,7 +150,6 @@ export default {
   onLoad(options) {
     const title =
       options && options.title ? decodeURIComponent(options.title) : "报表详情";
-    this.reportType = options && options.reportType ? options.reportType : "";
     this.taskId = options && options.id ? options.id : "";
     uni.setNavigationBarTitle({ title });
     this.tableBodyHeight = 14 * 80;
@@ -219,20 +174,18 @@ export default {
     //   }
     //   return total >= 12;
     // },
+    isLoading() {
+      return this.loading && this.category == 1 || this._loading && this.category == 2;
+    },
     showEmptyData() {
-      if (this.loading) return false;
-      if (this.reportType == 1 && this.rows.length === 0) {
-        return true;
-      } else {
-        if (this.category == 1 && this.rows.length === 0) return true;
-        if (this.category == 2 && this._rows.length === 0) return true;
-      }
+      if (this.isLoading) return false;
+      if (this.category == 1 && this.rows.length === 0 || this.category == 2 && this._rows.length === 0) return true;
       return false;
     },
   },
   methods: {
     selectTab(t) {
-      if (this.loading) return;
+      if (this.isLoading) return;
       this.category = t.value;
       this.fetchList();
     },
@@ -400,64 +353,8 @@ export default {
       });
       return res;
     },
-    computeBlackLeafCount(node) {
-      if (!node || !node.dataList || !node.dataList.length) return 1;
-      let sum = 0;
-      node.dataList.forEach((c) => {
-        sum += this.computeBlackLeafCount(c);
-      });
-      node.leafCount = sum;
-      return sum;
-    },
-    buildBlackRows(data) {
-      const res = [];
-      (data || []).forEach((companyNode) => {
-        const cLeaves = this.computeBlackLeafCount(companyNode);
-        let companyStarted = false;
-        (companyNode.dataList || []).forEach((expNode) => {
-          const eLeaves = this.computeBlackLeafCount(expNode);
-          let exporterStarted = false;
-          const groups = {};
-          (expNode.dataList || []).forEach((item) => {
-            const key = item.currentENTName || "";
-            if (!groups[key]) groups[key] = [];
-            groups[key].push(item);
-          });
-          Object.keys(groups).forEach((prodName) => {
-            const group = groups[prodName];
-            let productStarted = false;
-            group.forEach((batch) => {
-              res.push({
-                entName: companyNode.entName,
-                orgCode: companyNode.orgCode,
-                physicName: expNode.physicName,
-                currentENTName: prodName,
-                fromRegionName: batch.fromRegionName,
-                fromQuantity: batch.fromQuantity,
-                produceBatchNo: batch.produceBatchNo,
-                tracCode: batch.tracCode,
-                toQuantity: batch.toQuantity,
-                spans: {
-                  entName: companyStarted ? 0 : cLeaves,
-                  physicName: exporterStarted ? 0 : eLeaves,
-                  currentENTName: productStarted ? 0 : group.length,
-                },
-                flags: {
-                  entName: !companyStarted,
-                  physicName: !exporterStarted,
-                  currentENTName: !productStarted,
-                },
-              });
-              companyStarted = true;
-              exporterStarted = true;
-              productStarted = true;
-            });
-          });
-        });
-      });
-      return res;
-    },
-    onTableScrollToLower() {
+    onTableScrollToLower(e) {
+      if(e?.detail?.direction === 'right') return
       // if (this.isLoading) return;
       // if (this.rows.length >= this.totalCount) return;
       // this.isLoading = true;
@@ -478,25 +375,24 @@ export default {
         hasMore: "hasMore",
         fetchLoading: "fetchLoading",
         rows: "rows",
+        loading: 'loading'
       };
-      if (this.reportType == 2 && this.category == 2) {
+      if (this.category == 2) {
         obj.pageNum = "_pageNum";
         obj.pageSize = "_pageSize";
         obj.totalCount = "_totalCount";
         obj.hasMore = "_hasMore";
         obj.fetchLoading = "_fetchLoading";
         obj.rows = "_rows";
+        obj.loading = '_loading'
       }
       if (this[obj.fetchLoading] || !this[obj.hasMore]) return;
       this[obj.fetchLoading] = true;
       let url = `/report/getTaskTableData`;
-      if (this.reportType == 1) {
-        url = `/report/getBlacklistReport`;
-      }
       try {
         request(url, {
           id: this.taskId,
-          category: this.reportType == 1 ? undefined : this.category,
+          category: this.category,
           pageNum: this[obj.pageNum],
           pageSize: this[obj.pageSize],
           path: '/reportExport/detail/index.vue',
@@ -506,11 +402,7 @@ export default {
             this[obj.totalCount] = total || 0;
             let _list = [];
             if (Array.isArray(list)) {
-              if (this.reportType == 1) {
-                _list = this.buildBlackRows(list);
-              } else {
-                _list = this.buildRows(list);
-              }
+              _list = this.buildRows(list);
             }
             this[obj.rows] = [...this[obj.rows], ..._list];
             if (this[obj.rows].length < this[obj.totalCount]) {
@@ -520,12 +412,12 @@ export default {
               this[obj.hasMore] = false;
             }
           }
-          this.isLoading = false;
-          this.loading = false;
+          this[obj.fetchLoading]= false;
+          this[obj.loading] = false;
         })
       } catch (res) {
-        this.isLoading = false;
-        this.loading = false;
+        this[obj.fetchLoading] = false;
+        this[obj.loading] = false;
       }
       // this.rows = [];
       // setTimeout(() => {

+ 21 - 98
packages/traceabilityReport/pages/reportExport/index.vue

@@ -37,7 +37,6 @@
           <text class="report-export-status" :class="'report-export-status-' + item.status">{{
             getStatusText(item.status) }}</text>
         </view>
-        <view class="report-export-item-row">报表类型:{{ item.reportType == 1 ? "黑名单" : "购销分析" }}</view>
         <view class="report-export-item-row">品种:{{ item.physicName }}</view>
         <view class="report-export-item-row">时间:{{ formatDate(item.beginTime) }}--{{
           formatDate(item.endTime)
@@ -81,19 +80,6 @@
         <view class="report-export-create-modal-close" @click.stop="closeCreate">×</view>
       </view>
       <view class="report-export-create-modal-body" :style="{ paddingBottom: 0 }" @click="closeDropdownAll">
-        <view class="report-export-create-modal-row" style="margin-top: 0">
-          <!-- <text class="report-export-create-modal-label">报表类型</text> -->
-          <!-- <view class="report-export-create-modal-inputwrap" @click.stop> -->
-          <view class="report-type-tabs">
-            <view class="report-type-tab" :class="{
-              active: form.report === options.report[0],
-            }" @click.stop="selectReportType(options.report[0])">{{ options.report[0] }}</view>
-            <view class="report-type-tab" :class="{ active: form.report === options.report[1] }"
-              @click.stop="selectReportType(options.report[1])">
-              {{ options.report[1] }}</view>
-          </view>
-          <!-- </view> -->
-        </view>
         <scroll-view scroll-y="true" :style="{
           height: '750rpx',
           paddingBottom: '40rpx',
@@ -204,14 +190,14 @@
               </view>
             </view>
           </view>
-          <view class="report-export-create-modal-row" v-if="form.report === '黑名单'">
+          <!-- <view class="report-export-create-modal-row">
             <text class="report-export-create-modal-label">其它客户</text>
             <view class="report-export-create-modal-inputwrap">
               <input class="report-export-dropdown-search-input" v-model="form.otherCustomer"
                 placeholder="请填写(多个客户用半角逗号隔开)" placeholder-class="report-export-dropdown-other-customer-input"
                 :disabled="modalType === 'read'" :style="{ color: '#666', padding: 0, border: 'none' }" />
             </view>
-          </view>
+          </view> -->
           <view class="report-export-create-modal-row">
             <text class="report-export-create-modal-label">品种</text>
             <view class="report-export-create-modal-inputwrap"
@@ -263,18 +249,6 @@
     <view class="report-export-create-modal" :class="{ 'report-export-create-modal--open': filterModalOpen }">
       <view class="report-export-create-modal-title" @click="closeDropdownAll">筛选条件</view>
       <view class="report-export-create-modal-body" @click="closeDropdownAll">
-        <view class="report-export-create-modal-row">
-          <text class="report-export-create-modal-label">报表类型:</text>
-          <view class="report-export-create-modal-inputwrap" :style="{ border: 'none' }" @click.stop>
-            <view class="report-type-tabs">
-              <view class="report-type-tab" :class="{
-                active: filterForm.report === options.report[0],
-              }" @click.stop="pickFilterOption('report', options.report[0])">{{ options.report[0] }}</view>
-              <view class="report-type-tab" :class="{ active: filterForm.report === options.report[1] }"
-                @click.stop="pickFilterOption('report', options.report[1])">{{ options.report[1] }}</view>
-            </view>
-          </view>
-        </view>
         <view class="report-export-create-modal-row">
           <text class="report-export-create-modal-label">品种:</text>
           <view class="report-export-create-modal-inputwrap" @click.stop="openFilterDropdown('product')">
@@ -352,10 +326,6 @@
 import EmptyView from "../../../wigets/empty.vue";
 import { formatDate, getPaginatedList } from "../../../utils/utils.js";
 import request from "../../../request/index.js";
-const reportTypeMap = {
-  黑名单: 1,
-  购销分析: 2,
-};
 const customerTypeMap = {
   VIP客户: "VIP",
   二级客户: "二级",
@@ -388,8 +358,7 @@ export default {
         customerType: "",
         customer: [],
         product: { physicName: "" },
-        report: "黑名单",
-        otherCustomer: "",
+        // otherCustomer: "",
       },
       dateRange: [],
       computeTimer: null,
@@ -403,7 +372,6 @@ export default {
         region: [],
         customerType: ["VIP客户", "二级客户", "三级客户"],
         product: [],
-        report: ["黑名单", "购销分析"],
         status: ["全部", "待开始", "进行中", "已完成"],
       },
       // dropdown search inputs (create modal)
@@ -418,7 +386,6 @@ export default {
 
       // dropdown search inputs (filter modal)
       filterSearchForm: {
-        report: "",
         product: "",
       },
       // Pagination state for filter products
@@ -435,11 +402,10 @@ export default {
       taskTitle: "创建任务",
       filterModalOpen: false,
       filterForm: {
-        report: "",
         product: { physicName: "" },
         status: "全部",
       },
-      filterDropdown: { report: false, product: false },
+      filterDropdown: { product: false },
       filterDateRange: [],
       modalType: "",
       dropdownUpward: false,
@@ -517,13 +483,13 @@ export default {
     getCustomerName(data = {}) {
       const { customerName = "", otherCustomer = "" } = data;
       let name = customerName || "";
-      if (otherCustomer) {
-        if (name) {
-          name += `,${otherCustomer}`;
-        } else {
-          name = otherCustomer;
-        }
-      }
+      // if (otherCustomer) {
+      //   if (name) {
+      //     name += `,${otherCustomer}`;
+      //   } else {
+      //     name = otherCustomer;
+      //   }
+      // }
       const arr = name.split(",");
       if (arr.length == 0) return "--";
       return arr.length == 1 ? arr[0].trim() : `${arr.length}个公司`;
@@ -531,10 +497,6 @@ export default {
     formatDate(date) {
       return formatDate({ date }, "YYYY-MM-DD");
     },
-    selectReportType(op) {
-      if (this.modalType === "read") return;
-      this.form.report = op;
-    },
     getStatusText(status) {
       if (status == "1") {
         return "导出待开始";
@@ -637,8 +599,7 @@ export default {
             physicName: item.physicName,
             drugEntBaseInfoId: item.drugEntBaseInfoId,
           },
-          report: item.reportType == 1 ? "黑名单" : "购销分析",
-          otherCustomer: item?.otherCustomer || "",
+          // otherCustomer: item?.otherCustomer || "",
         };
         this.dateRange = [item.beginTime, item.endTime];
       }
@@ -666,7 +627,6 @@ export default {
       request("/report/getReportTaskPage", {
         taskType: statusMap?.[this.filterForm?.status] || "",
         drugEntBaseInfoId: this.filterForm?.product?.drugEntBaseInfoId,
-        reportType: reportTypeMap?.[this.filterForm?.report] || "",
         beginTime: this.filterDateRange[0],
         endTime: this.filterDateRange[1],
         customerName: this.keyword || "",
@@ -691,11 +651,11 @@ export default {
           //   ...this.list[1],
           //   status: 3,
           // });
-          // this.list.push({
-          //   ...this.list[0],
-          //   finishTime: "2025-12-15",
-          //   status: 3,
-          // });
+          this.list.push({
+            ...this.list[0],
+            finishTime: "2025-12-15",
+            status: 3,
+          });
           // this.animateAll();
         }
         this.fetchLoading = false;
@@ -712,7 +672,7 @@ export default {
     toDetail(item) {
       uni.navigateTo({
         url: `/packages/traceabilityReport/pages/reportExport/detail/index?id=${item.id
-          }&reportType=${item.reportType}&title=${encodeURIComponent(
+          }&title=${encodeURIComponent(
             this.getCustomerName(item.customerName)
           )}`,
       });
@@ -724,7 +684,6 @@ export default {
       this.modalType = "create";
       this.taskTitle = "创建任务";
       this.createModalOpen = true;
-      if (!this.form.report) this.form.report = this.options.report[0] || "";
     },
     closeCreate() {
       this.filterModalOpen = false;
@@ -735,8 +694,7 @@ export default {
         customerType: "",
         customer: [],
         product: { physicName: "" },
-        report: "黑名单",
-        otherCustomer: "",
+        // otherCustomer: "",
       };
       this.searchForm = {
         region: "",
@@ -784,8 +742,7 @@ export default {
         customerType: customerTypeMap?.[this.form?.customerType] || "",
         customerId,
         customerName,
-        otherCustomer: this.form?.otherCustomer || "",
-        reportType: reportTypeMap?.[this.form?.report] || "",
+        // otherCustomer: this.form?.otherCustomer || "",
         drugEntBaseInfoId: this.form?.product?.drugEntBaseInfoId || "",
         beginTime: this.dateRange[0],
         endTime: this.dateRange[1],
@@ -812,15 +769,11 @@ export default {
       let customerOk = Array.isArray(f.customer)
         ? f.customer.length > 0
         : !!f.customer;
-      if (f.report === "黑名单") {
-        customerOk = customerOk || !!f.otherCustomer;
-      }
       return (
         f.region?.regionName &&
         f.customerType &&
         customerOk &&
         f.product?.physicName &&
-        f.report &&
         drOk
       );
     },
@@ -880,7 +833,6 @@ export default {
         customer: false,
         product: false,
       };
-      this.filterDropdown.report = false;
       this.filterDropdown.product = false;
     },
     openFilterDropdown(k) {
@@ -901,7 +853,7 @@ export default {
       }
     },
     pickFilterOption(k, v) {
-      if (["status", "report"].includes(k) && this.filterForm[k] === v) {
+      if (["status"].includes(k) && this.filterForm[k] === v) {
         this.filterForm[k] = "";
         this.filterDropdown[k] = false;
         return;
@@ -1147,7 +1099,6 @@ export default {
           progress: 0,
           progressTarget: target,
           action,
-          report: "购销分析",
         });
       }
       return res;
@@ -1626,34 +1577,6 @@ export default {
   background: #f0f5ff;
 }
 
-.report-type-tabs {
-  width: 100%;
-  display: flex;
-  align-items: center;
-  background: #f5f7fa;
-  padding: 8rpx;
-  border-radius: 40rpx;
-  box-sizing: border-box;
-}
-
-.report-type-tab {
-  flex: 1;
-  height: 64rpx;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  border-radius: 40rpx;
-  font-size: 28rpx;
-  color: #606266;
-}
-
-.report-type-tab.active {
-  background: #2c69ff;
-  color: #fff;
-  font-weight: 500;
-  box-shadow: 0 2rpx 12rpx rgba(44, 105, 255, 0.2);
-}
-
 .report-export-input-arrow {
   width: 16rpx;
   height: 16rpx;