Browse Source

feat:黑名单客户更新

钱新宇 1 day ago
parent
commit
a51e75f9cf

+ 108 - 97
pages.json

@@ -1,99 +1,110 @@
 {
-	"pages": [{
-			"path": "pages/login/login",
-			"style": {
-				"navigationBarTitleText": "登录",
-				"navigationStyle": "custom"
-			}
-		},
-		{
-			"path": "components/tabbar/tabbar",
-			"style": {
-				"navigationStyle": "custom"
-			}
-		}
-	],
-	"subPackages": [{
-			"root": "packageA/pages",
-			"pages": [{
-				"path": "home/home",
-				"style": {
-					"navigationBarTitleText": "分包案例",
-					"navigationStyle": "custom"
-				}
-			}]
-		},
+  "pages": [
+    {
+      "path": "pages/login/login",
+      "style": {
+        "navigationBarTitleText": "登录",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "components/tabbar/tabbar",
+      "style": {
+        "navigationStyle": "custom"
+      }
+    }
+  ],
+  "subPackages": [
+    {
+      "root": "packageA/pages",
+      "pages": [
+        {
+          "path": "home/home",
+          "style": {
+            "navigationBarTitleText": "分包案例",
+            "navigationStyle": "custom"
+          }
+        }
+      ]
+    },
 
-		{
-			"root": "traceCodePackages",
-			"pages": [{
-					"path": "traceabilityCodeQuery/pages/index",
-					"style": {
-						"navigationBarTitleText": "药品追溯码查询",
-						"navigationStyle": "custom"
-					}
-				},
-				{
-					"path": "traceabilityCodeQuery/pages/detail/index",
-					"style": {
-						"navigationBarTitleText": "追溯码详情"
-					}
-				},
-				{
-					"path": "traceabilityCodeQuery/pages/scanRange/index",
-					"style": {
-						"navigationBarTitleText": "可扫码生产企业及药品"
-					}
-				},
-				{
-					"path": "traceabilityReport/pages/index",
-					"style": {
-						"navigationBarTitleText": "溯源报表"
-					}
-				},
-				{
-					"path": "traceabilityReport/pages/customerScanningRate/detail/index",
-					"style": {
-						"navigationBarTitleText": "客户扫码率",
-						"navigationStyle": "custom"
-					}
-				},
-				{
-					"path": "traceabilityReport/pages/reportExport/index",
-					"style": {
-						"navigationBarTitleText": ""
-					}
-				},
-				{
-					"path": "traceabilityReport/pages/reportExport/detail/index",
-					"style": {
-						"navigationBarTitleText": ""
-					}
-				},
-				{
-					"path": "traceabilityReport/pages/ganmaoling/detail/index",
-					"style": {
-						"navigationBarTitleText": "",
-						"navigationStyle": "custom"
-					}
-				}
-			]
-		}
-
-	],
-	"globalStyle": {
-		"navigationBarTextStyle": "black",
-		"navigationBarTitleText": "uni-app",
-		"navigationBarBackgroundColor": "#F8F8F8",
-		"backgroundColor": "#F8F8F8"
-	},
-	"uniIdRouter": {},
-	"easycom": {
-		"autoscan": true,
-		"custom": {
-			"^u--(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
-			"^up-(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
-			"^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue"
-		}
-	}
-}
+    {
+      "root": "traceCodePackages",
+      "pages": [
+        {
+          "path": "traceabilityCodeQuery/pages/index",
+          "style": {
+            "navigationBarTitleText": "药品追溯码查询",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "traceabilityCodeQuery/pages/detail/index",
+          "style": {
+            "navigationBarTitleText": "追溯码详情"
+          }
+        },
+        {
+          "path": "traceabilityCodeQuery/pages/scanRange/index",
+          "style": {
+            "navigationBarTitleText": "可扫码生产企业及药品"
+          }
+        },
+        {
+          "path": "traceabilityReport/pages/index",
+          "style": {
+            "navigationBarTitleText": "溯源报表"
+          }
+        },
+        {
+          "path": "traceabilityReport/pages/customerScanningRate/detail/index",
+          "style": {
+            "navigationBarTitleText": "客户扫码率",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "traceabilityReport/pages/reportExport/index",
+          "style": {
+            "navigationBarTitleText": ""
+          }
+        },
+        {
+          "path": "traceabilityReport/pages/reportExport/detail/index",
+          "style": {
+            "navigationBarTitleText": ""
+          }
+        },
+        {
+          "path": "traceabilityReport/pages/blacklist/detail/index",
+          "style": {
+            "navigationBarTitleText": "",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "traceabilityReport/pages/ganmaoling/detail/index",
+          "style": {
+            "navigationBarTitleText": "",
+            "navigationStyle": "custom"
+          }
+        }
+      ]
+    }
+  ],
+  "globalStyle": {
+    "navigationBarTextStyle": "black",
+    "navigationBarTitleText": "uni-app",
+    "navigationBarBackgroundColor": "#F8F8F8",
+    "backgroundColor": "#F8F8F8"
+  },
+  "uniIdRouter": {},
+  "easycom": {
+    "autoscan": true,
+    "custom": {
+      "^u--(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
+      "^up-(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
+      "^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue"
+    }
+  }
+}

+ 75 - 67
traceCodePackages/request/index.js

@@ -1,75 +1,83 @@
-import {
-    Request
-} from '@/service/request/index.js'
-import {
-    Storage
-} from '@/service/storage'
-const storage = new Storage()
+import { Request } from "@/service/request/index.js";
+import { Storage } from "@/service/storage";
+const storage = new Storage();
 
-const _baseUrl = import.meta.env.VITE_APP_API_BASEURL5
-const subdomain = '/yylm'
+const _baseUrl = import.meta.env.VITE_APP_API_BASEURL;
+const subdomain = "/yylm";
 // const subdomain = ''
 
 export function downloadFile(url, data = {}) {
-    const baseUrl = data.baseUrl || _baseUrl
-    // const baseUrl = _baseUrl
-    uni.downloadFile({
-        url: baseUrl + subdomain + url, //添加三九分配的子域名
-        data,
-        success: (res) => {
-            console.log(`${data?.path},${baseUrl + subdomain + url},请求头`, data);
-            console.log(`${data?.path},${baseUrl + subdomain + url},数据`, res);
-            if (res.statusCode === 200) {
-                uni.saveFile({
-                    tempFilePath: res.tempFilePath,
-                    success: (r) => {
-                        uni.showToast({
-                            title: '下载成功',
-                            icon: 'success',
-                        });
-                        console.log(`${data?.path},${baseUrl + subdomain + url},uni.saveFile请求头`, res.tempFilePath);
-                        console.log(`${data?.path},${baseUrl + subdomain + url},uni.saveFile数据`, r);
-                    },
-                    fail: (err) => {
-                        uni.showToast({
-                            title: '保存失败',
-                            icon: 'error',
-                        });
-                        console.log(`${data?.path},${baseUrl + subdomain + url},uni.saveFile请求头`, res.tempFilePath);
-                        console.log(`${data?.path},${baseUrl + subdomain + url},uni.saveFile数据`, err);
-                    },
-                });
-            } else {
-                uni.showToast({
-                    title: '下载失败',
-                    icon: 'error',
-                });
-            }
-        },
-        fail: (err) => {
-            console.log(`${data?.path},${baseUrl + subdomain + url},请求头`, data);
-            console.log(`${data?.path},${baseUrl + subdomain + url},数据`, err);
+  const baseUrl = data.baseUrl || _baseUrl;
+  // const baseUrl = _baseUrl
+  uni.downloadFile({
+    url: baseUrl + subdomain + url, //添加三九分配的子域名
+    data,
+    success: (res) => {
+      console.log(`${data?.path},${baseUrl + subdomain + url},请求头`, data);
+      console.log(`${data?.path},${baseUrl + subdomain + url},数据`, res);
+      if (res.statusCode === 200) {
+        uni.saveFile({
+          tempFilePath: res.tempFilePath,
+          success: (r) => {
             uni.showToast({
-                title: '下载失败',
-                icon: 'error',
+              title: "下载成功",
+              icon: "success",
             });
-        },
-    });
+            console.log(
+              `${data?.path},${baseUrl + subdomain + url},uni.saveFile请求头`,
+              res.tempFilePath,
+            );
+            console.log(
+              `${data?.path},${baseUrl + subdomain + url},uni.saveFile数据`,
+              r,
+            );
+          },
+          fail: (err) => {
+            uni.showToast({
+              title: "保存失败",
+              icon: "error",
+            });
+            console.log(
+              `${data?.path},${baseUrl + subdomain + url},uni.saveFile请求头`,
+              res.tempFilePath,
+            );
+            console.log(
+              `${data?.path},${baseUrl + subdomain + url},uni.saveFile数据`,
+              err,
+            );
+          },
+        });
+      } else {
+        uni.showToast({
+          title: "下载失败",
+          icon: "error",
+        });
+      }
+    },
+    fail: (err) => {
+      console.log(`${data?.path},${baseUrl + subdomain + url},请求头`, data);
+      console.log(`${data?.path},${baseUrl + subdomain + 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 }
-    const baseUrl = data.baseUrl || _baseUrl
-    // const baseUrl = _baseUrl
-    return Request({
-        url: subdomain + url, //添加三九分配的子域名
-        method,
-        data: JSON.stringify(d),
-        baseUrl
-    }).then(res => {
-        console.log(`${data?.path},${baseUrl + subdomain + url},请求头`, d);
-        console.log(`${data?.path},${baseUrl + subdomain + url},数据`, res);
-        return res
-    })
-}
+export default function request(url, data = {}, method = "post") {
+  const uid = (storage.getStorageSync("userInfo") || { ldap: "" }).ldap;
+  const d = { ...data, uid };
+  const baseUrl = data.baseUrl || _baseUrl;
+  // const baseUrl = _baseUrl
+  return Request({
+    url: subdomain + url, //添加三九分配的子域名
+    method,
+    data: JSON.stringify(d),
+    baseUrl,
+  }).then((res) => {
+    console.log(`${data?.path},${baseUrl + subdomain + url},请求头`, d);
+    console.log(`${data?.path},${baseUrl + subdomain + url},数据`, res);
+    return res;
+  });
+}

+ 283 - 0
traceCodePackages/traceabilityReport/pages/blacklist/detail/index.vue

@@ -0,0 +1,283 @@
+<template>
+  <!-- <Water></Water> -->
+  <view class="nav" :style="{ paddingTop: statusBarHeight + 'px' }">
+    <text
+      class="nav-back"
+      :style="{ top: statusBarHeight + 'px' }"
+      @click="onBack"
+    ></text>
+    <view class="nav-title">{{ title }}</view>
+  </view>
+  <view class="page">
+    <view class="tip">点击“上游客户”名称展开详细表格</view>
+    <view
+      class="list-container"
+      :style="{ paddingTop: statusBarHeight + 60 + 'px' }"
+    >
+      <view
+        class="card product-card"
+        v-for="(prd, i) in products"
+        :key="'prd-' + i"
+      >
+        <view
+          class="customer-row"
+          v-for="(c, j) in prd.customers"
+          :key="'cust-' + j"
+        >
+          <text class="customer-label">上游客户:</text>
+          <text class="customer-name" @click.stop="toggleCustomer(i, j)">{{
+            c.name
+          }}</text>
+          <text class="expand-tag" @click.stop="toggleCustomer(i, j)">{{
+            c.expanded ? "收起" : "展开"
+          }}</text>
+        </view>
+        <view
+          class="table-card"
+          v-for="(c, j) in prd.customers"
+          :key="'tbl-' + j"
+          v-show="c.expanded"
+        >
+          <scroll-view scroll-x="true" class="table-scroll">
+            <view class="blk-table">
+              <view class="blk-header">
+                <view class="th col-region">货源片区</view>
+                <view class="th col-qty">数量</view>
+                <view class="th col-batch">批号</view>
+                <view class="th col-sample">监管码样本(抽样)</view>
+                <view class="th col-terminal">终端到达数量</view>
+              </view>
+              <view class="blk-body">
+                <view
+                  class="blk-row"
+                  v-for="(row, idx) in c.details"
+                  :key="'row-' + idx"
+                >
+                  <view class="td col-region">{{ row.region }}</view>
+                  <view class="td col-qty">{{ row.quantity }}</view>
+                  <view class="td col-batch">{{ row.batchNo }}</view>
+                  <view class="td col-sample">{{ row.sample }}</view>
+                  <view class="td col-terminal">{{ row.arrivalQty }}</view>
+                </view>
+                <view
+                  v-if="!c.details || c.details.length === 0"
+                  class="empty-row"
+                  >暂无数据</view
+                >
+              </view>
+            </view>
+          </scroll-view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import Water from "@/components/water/water.vue";
+export default {
+  components: {
+    Water,
+  },
+  data() {
+    return {
+      statusBarHeight: 20,
+      title: "黑名单详情",
+      products: [],
+    };
+  },
+  onLoad(options) {
+    const info = uni.getSystemInfoSync();
+    this.statusBarHeight = info.statusBarHeight || 20;
+    const name =
+      options && options.name ? decodeURIComponent(options.name) : "";
+    this.title = name || "黑名单详情";
+    this.products = this.generateMockProducts(name || "感冒灵");
+  },
+  methods: {
+    onBack() {
+      try {
+        uni.navigateBack();
+      } catch (e) {}
+    },
+    toggleCustomer(i, j) {
+      const cur = this.products[i].customers[j];
+      this.$set(this.products[i].customers[j], "expanded", !cur.expanded);
+    },
+    generateMockProducts(drugName) {
+      const makeDetails = (n = 3) =>
+        Array.from({ length: n }).map((_, idx) => ({
+          region: ["广东", "江苏", "四川", "山东"][idx % 4],
+          quantity: 100 + idx * 20,
+          batchNo: `B${String(202400 + idx)}`,
+          sample: `抽样${10 + idx}枚`,
+          arrivalQty: 90 + idx * 15,
+        }));
+      return [
+        {
+          name: drugName,
+          customers: [
+            { name: "公司A", expanded: false, details: makeDetails(3) },
+            { name: "公司B", expanded: false, details: makeDetails(2) },
+          ],
+        },
+        {
+          name: drugName,
+          customers: [
+            { name: "公司A", expanded: true, details: makeDetails(4) },
+            { name: "公司C", expanded: false, details: makeDetails(3) },
+          ],
+        },
+      ];
+    },
+  },
+};
+</script>
+
+<style scoped>
+.nav {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 44px;
+  background-color: #2c69ff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 10;
+}
+.nav-title {
+  font-size: 36rpx;
+  color: #fff;
+  font-weight: 700;
+}
+.nav-back {
+  position: absolute;
+  left: 40rpx;
+  top: 12rpx;
+  width: 20rpx;
+  height: 20rpx;
+  color: #fff;
+  border-left: 3rpx solid #fff;
+  border-bottom: 3rpx solid #fff;
+  transform: rotate(45deg) translateY(56rpx);
+  margin-left: 40rpx;
+  margin-top: -6rpx;
+}
+.page {
+  min-height: 100vh;
+  background: #f3f6f9;
+}
+.tip {
+  font-size: 24rpx;
+  color: #999;
+  padding: 24rpx;
+}
+.list-container {
+  padding: 0 24rpx 24rpx;
+  box-sizing: border-box;
+}
+.card {
+  margin: 24rpx;
+  background: #fff;
+  border-radius: 16rpx;
+  font-size: 30rpx;
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+}
+.product-card {
+  padding: 24rpx;
+}
+.product-title {
+  font-size: 32rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 16rpx;
+}
+.customer-row {
+  display: flex;
+  align-items: center;
+  padding: 12rpx 0;
+  border-bottom: 1rpx solid #f0f0f0;
+}
+.customer-row:last-child {
+  border-bottom: none;
+}
+.customer-label {
+  font-size: 28rpx;
+  color: #666;
+  margin-right: 10rpx;
+}
+.customer-name {
+  font-size: 28rpx;
+  color: #2c69ff;
+}
+.expand-tag {
+  margin-left: auto;
+  font-size: 26rpx;
+  color: #2c69ff;
+}
+.table-card {
+  padding: 0;
+  overflow: hidden;
+  margin-top: 16rpx;
+}
+.table-scroll {
+  width: 100%;
+}
+.blk-table {
+  min-width: 1200rpx;
+  border-top: 1rpx solid #eee;
+  border-left: 1rpx solid #eee;
+}
+.blk-header {
+  display: flex;
+  background: #f5f7fa;
+  font-size: 26rpx;
+  font-weight: bold;
+  color: #333;
+}
+.blk-body {
+  font-size: 26rpx;
+  color: #666;
+}
+.blk-row {
+  display: flex;
+  border-bottom: 1rpx solid #eee;
+}
+.th,
+.td {
+  padding: 16rpx 10rpx;
+  border-right: 1rpx solid #eee;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+  word-break: break-all;
+  box-sizing: border-box;
+  flex-shrink: 0;
+}
+.th {
+  border-bottom: 1rpx solid #eee;
+}
+.empty-row {
+  padding: 30rpx;
+  text-align: center;
+  color: #999;
+}
+.col-region {
+  width: 200rpx;
+}
+.col-qty {
+  width: 140rpx;
+}
+.col-batch {
+  width: 200rpx;
+}
+.col-sample {
+  width: 300rpx;
+}
+.col-terminal {
+  width: 220rpx;
+}
+</style>

+ 252 - 434
traceCodePackages/traceabilityReport/pages/blacklist/index.vue

@@ -1,491 +1,309 @@
 <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="tip">数据更新时间:{{ formatDate(new Date().setDate(new Date().getDate() - 1), 'YYYY-MM-DD') || '--' }}</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>
+  <view class="detail-page">
+    <view class="tip"
+      >数据更新时间:{{
+        formatDate(
+          new Date().setDate(new Date().getDate() - 1),
+          "YYYY-MM-DD",
+        ) || "--"
+      }}</view
+    >
+
+    <scroll-view
+      class="list-scroll"
+      scroll-y="true"
+      refresher-enabled
+      :refresher-triggered="isRefreshing"
+      @refresherrefresh="onRefresh"
+      @scrolltolower="onLoadMore"
+    >
+      <view class="list-container">
+        <view
+          class="card-item"
+          v-for="(item, index) in rows"
+          :key="index"
+          @click="toDetail(item)"
+        >
+          <view class="left-info">
+            <view class="row1-name">{{ item.receiverName }}</view>
+            <view class="row4-manager">{{ item.companyCode }}</view>
+          </view>
+        </view>
+
+        <view class="loading-more" v-if="loading">
+          <image
+            class="loading-icon"
+            src="../../../static/images/loading.png"
+          />
+        </view>
+
+        <view v-if="!loading && rows.length === 0" class="empty-data">
+          <EmptyView text="无相关数据" />
+        </view>
+
+        <view v-if="!hasMore && rows.length > 0" class="no-more">
+          <text>没有更多数据了</text>
+        </view>
+      </view>
+    </scroll-view>
+  </view>
 </template>
 
 <script>
 import EmptyView from "../../../wigets/empty.vue";
-import request, { downloadFile } from '../../../request/index.js'
-import { formatDate } from '../../../utils/utils.js'
+import request 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: false,
-			rows: [],
-			totalCount: 0,
-			fetchLoading: false,
-			hasMore: false,
-			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',
-			})
-		},
-	},
+  components: {
+    EmptyView,
+  },
+  data() {
+    return {
+      isRefreshing: false,
+      loading: false,
+      rows: [],
+      totalCount: 60, // Simulated total count
+      hasMore: true,
+      pageNum: 1,
+      pageSize: 20,
+    };
+  },
+  created() {
+    this.resetFetch();
+  },
+  methods: {
+    formatDate,
+
+    getLevelClass(level) {
+      if (level === "VIP") return "tag-vip";
+      if (level === "二级") return "tag-l2";
+      if (level === "三级") return "tag-l3";
+      return "tag-default";
+    },
+
+    generateFakeData() {
+      const newRows = [];
+      const provinces = [
+        "91370104771001730R",
+        "91420105783155681H",
+        "91330110MA2CCJE32Y",
+        "91441581761581268X",
+        "91510106768621824L",
+      ];
+
+      const startIdx = (this.pageNum - 1) * this.pageSize;
+      const endIdx = Math.min(startIdx + this.pageSize, this.totalCount);
+
+      if (startIdx >= this.totalCount) {
+        this.hasMore = false;
+        return [];
+      }
+
+      for (let i = startIdx; i < endIdx; i++) {
+        newRows.push({
+          id: i,
+          receiverName: `测试收货企业${i + 1}有限公司`,
+          companyCode: provinces[i % provinces.length],
+        });
+      }
+      return newRows;
+    },
+
+    async onRefresh() {
+      this.isRefreshing = true;
+      this.pageNum = 1;
+      this.hasMore = true;
+      // Simulate network request
+      setTimeout(() => {
+        this.rows = this.generateFakeData();
+        this.isRefreshing = false;
+      }, 1000);
+    },
+
+    onLoadMore() {
+      if (this.loading || !this.hasMore) return;
+      this.loading = true;
+      this.pageNum++;
+
+      // Simulate network request
+      setTimeout(() => {
+        const more = this.generateFakeData();
+        if (more.length > 0) {
+          this.rows = [...this.rows, ...more];
+        } else {
+          this.hasMore = false;
+        }
+        this.loading = false;
+      }, 800);
+    },
+
+    resetFetch() {
+      this.loading = true;
+      this.pageNum = 1;
+      this.hasMore = true;
+      // Simulate initial load
+      setTimeout(() => {
+        this.rows = this.generateFakeData();
+        this.loading = false;
+      }, 500);
+    },
+
+    toDetail(item) {
+      uni.navigateTo({
+        url: `/traceCodePackages/traceabilityReport/pages/blacklist/detail/index?id=${item.id}&name=${encodeURIComponent(item.receiverName)}`,
+      });
+    },
+  },
 };
 </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));
+  display: flex;
+  flex-direction: column;
+  height: calc(100vh - 116rpx - env(safe-area-inset-bottom));
+  box-sizing: border-box;
+  background: #f3f6f9;
 }
 
 .tip {
-	font-size: 24rpx;
-	color: #999;
-	margin-bottom: 30rpx;
-}
-
-.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;
+  font-size: 24rpx;
+  color: #999;
+  padding: 24rpx;
+  background: #f3f6f9;
 }
 
-.hcell:last-child {
-	border-right: none;
+.list-scroll {
+  flex: 1;
+  height: 0; /* Important for flex expansion */
+  padding: 0 24rpx;
+  box-sizing: border-box;
 }
 
-.hcell-sticky-left {
-	position: sticky;
-	left: 0;
-	z-index: 11;
+.list-container {
+  padding-bottom: calc(50rpx + env(safe-area-inset-bottom));
+  padding-left: 24rpx;
+  padding-right: 24rpx;
 }
 
-.grid-scroll {
-	border-radius: 16rpx;
-	margin-top: 8rpx;
-	overflow: hidden;
+.card-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start; /* Align top */
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 30rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
 }
 
-.grid-body {
-	background: #fff;
-	display: grid;
-	grid-template-columns: 340rpx 300rpx 220rpx 220rpx 220rpx 220rpx 220rpx 220rpx 340rpx 200rpx;
-	grid-auto-rows: auto;
+.left-info {
+  flex: 1;
+  margin-right: 20rpx;
 }
 
-.grow {
-	display: contents;
+.row1-name {
+  font-size: 30rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 16rpx;
 }
 
-.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;
+.row2-info {
+  display: flex;
+  align-items: center;
+  margin-bottom: 12rpx;
 }
 
-.gcell:last-child {
-	border-right: none;
+.province {
+  font-size: 26rpx;
+  color: #666;
+  margin-right: 20rpx;
 }
 
-.gcell.gcell-full {
-	grid-column: 1 / -1;
-	background: transparent;
-	border: none;
+.level-tag {
+  font-size: 22rpx;
+  padding: 4rpx 12rpx;
+  border-radius: 6rpx;
+  background: #f0f0f0;
+  color: #666;
 }
 
-.gspan {
-	background: #fff;
+.tag-vip {
+  background: #e6f7ff;
+  color: #1890ff;
 }
 
-.gcol-1 {
-	grid-column: 1;
+.tag-l2 {
+  background: #f6ffed;
+  color: #52c41a;
 }
 
-.gcol-2 {
-	grid-column: 2;
+.tag-l3 {
+  background: #fff7e6;
+  color: #fa8c16;
 }
 
-.gcol-3 {
-	grid-column: 3;
+.row3-nature {
+  font-size: 26rpx;
+  color: #666;
+  margin-bottom: 12rpx;
 }
 
-.gcol-4 {
-	grid-column: 4;
+.row4-manager {
+  font-size: 26rpx;
+  color: #666;
 }
 
-.gcol-5 {
-	grid-column: 5;
+.right-info {
+  display: flex;
+  align-items: center;
+  align-self: center; /* Center vertically relative to card */
 }
 
-.gcol-6 {
-	grid-column: 6;
+.alert-count {
+  background: #fff2f0;
+  color: #ff4d4f;
+  font-size: 24rpx;
+  padding: 8rpx 20rpx;
+  border-radius: 30rpx;
+  font-weight: bold;
 }
 
-.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-more {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 20rpx 0;
 }
 
 .loading-icon {
-	width: 40rpx;
-	height: 40rpx;
-	animation: spin 1s linear infinite;
-}
-
-@keyframes spin {
-	from {
-		transform: rotate(0deg);
-	}
-
-	to {
-		transform: rotate(360deg);
-	}
+  width: 32rpx;
+  height: 32rpx;
+  margin-right: 10rpx;
+  animation: spin 1s linear infinite;
 }
 
-.empty-data,
-.loading-wrap {
-	position: absolute;
-	left: 0;
-	top: 85rpx;
-	z-index: 91;
-	width: 100%;
-	background-color: #fff;
-	border-bottom-left-radius: 16rpx;
-	border-bottom-right-radius: 16rpx;
+.empty-data {
+  display: flex;
+  justify-content: center;
+  padding-top: 100rpx;
 }
 
-.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: 92;
+.no-more {
+  text-align: center;
+  color: #999;
+  font-size: 24rpx;
+  padding: 20rpx 0;
 }
 
-.fab-text {
-	font-size: 28rpx;
-	font-weight: bold;
+@keyframes spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
 }
 </style>

+ 250 - 231
traceCodePackages/traceabilityReport/pages/ganmaoling/index.vue

@@ -1,307 +1,326 @@
 <template>
-	<view class="detail-page">
-		<view class="tip">数据更新时间:{{ formatDate(new Date().setDate(new Date().getDate() - 1), 'YYYY-MM-DD') || '--' }}</view>
-		
-		<scroll-view 
-			class="list-scroll" 
-			scroll-y="true" 
-			refresher-enabled 
-			:refresher-triggered="isRefreshing"
-			@refresherrefresh="onRefresh"
-			@scrolltolower="onLoadMore"
-		>
-			<view class="list-container">
-				<view 
-					class="card-item" 
-					v-for="(item, index) in rows" 
-					:key="index"
-					@click="toDetail(item)"
-				>
-					<view class="left-info">
-						<view class="row1-name">{{ item.receiverName }}</view>
-						<view class="row2-info">
-							<text class="province">{{ item.receiverProvince }}</text>
-							<view class="level-tag" :class="getLevelClass(item.customerLevel)">
-								{{ item.customerLevel }}
-							</view>
-						</view>
-						<view class="row3-nature">{{ item.customerNature }}</view>
-						<view class="row4-manager">{{ item.manager }}</view>
-					</view>
-					
-					<view class="right-info">
-						<text class="alert-count">{{ item.alertCount }}次预警</text>
-					</view>
-				</view>
-				
-				<view class="loading-more" v-if="loading">
-					<image class="loading-icon" src="../../../static/images/loading.png" />
-				</view>
-				
-				<view v-if="!loading && rows.length === 0" class="empty-data">
-					<EmptyView text="无相关数据" />
-				</view>
-                
-                <view v-if="!hasMore && rows.length > 0" class="no-more">
-                    <text>没有更多数据了</text>
-                </view>
-			</view>
-		</scroll-view>
-	</view>
+  <view class="detail-page">
+    <view class="tip"
+      >数据更新时间:{{
+        formatDate(
+          new Date().setDate(new Date().getDate() - 1),
+          "YYYY-MM-DD",
+        ) || "--"
+      }}</view
+    >
+
+    <scroll-view
+      class="list-scroll"
+      scroll-y="true"
+      refresher-enabled
+      :refresher-triggered="isRefreshing"
+      @refresherrefresh="onRefresh"
+      @scrolltolower="onLoadMore"
+    >
+      <view class="list-container">
+        <view
+          class="card-item"
+          v-for="(item, index) in rows"
+          :key="index"
+          @click="toDetail(item)"
+        >
+          <view class="left-info">
+            <view class="row1-name"
+              >{{ item.receiverName }}
+              <view
+                class="level-tag"
+                :class="getLevelClass(item.customerLevel)"
+              >
+                {{ item.customerLevel }}
+              </view></view
+            >
+            <view class="row2-info">
+              <text class="province">{{ item.receiverProvince }}</text>
+            </view>
+            <view class="row3-nature">{{ item.customerNature }}</view>
+            <view class="row4-manager">{{ item.manager }}</view>
+          </view>
+
+          <view class="right-info">
+            <text class="alert-count">{{ item.alertCount }}次预警</text>
+          </view>
+        </view>
+
+        <view class="loading-more" v-if="loading">
+          <image
+            class="loading-icon"
+            src="../../../static/images/loading.png"
+          />
+        </view>
+
+        <view v-if="!loading && rows.length === 0" class="empty-data">
+          <EmptyView text="无相关数据" />
+        </view>
+
+        <view v-if="!hasMore && rows.length > 0" class="no-more">
+          <text>没有更多数据了</text>
+        </view>
+      </view>
+    </scroll-view>
+  </view>
 </template>
 
 <script>
 import EmptyView from "../../../wigets/empty.vue";
-import request from '../../../request/index.js'
-import { formatDate } from '../../../utils/utils.js'
+import request from "../../../request/index.js";
+import { formatDate } from "../../../utils/utils.js";
 
 export default {
-	components: {
-		EmptyView,
-	},
-	data() {
-		return {
-			isRefreshing: false,
-			loading: false,
-			rows: [],
-			totalCount: 60, // Simulated total count
-			hasMore: true,
-			pageNum: 1,
-			pageSize: 20,
-		};
-	},
-	created() {
-		this.resetFetch();
-	},
-	methods: {
-		formatDate,
-		
-		getLevelClass(level) {
-			if (level === 'VIP') return 'tag-vip';
-			if (level === '二级') return 'tag-l2';
-			if (level === '三级') return 'tag-l3';
-			return 'tag-default';
-		},
-
-		generateFakeData() {
-			const newRows = [];
-			const levels = ['VIP', '二级', '三级'];
-			const provinces = ['北京市', '上海市', '广东省', '浙江省', '江苏省'];
-			const natures = ['协议客户', '非协议客户'];
-			const managers = ['张明华', '李建华', '王丽萍', '陈大文'];
-
-			const startIdx = (this.pageNum - 1) * this.pageSize;
-			const endIdx = Math.min(startIdx + this.pageSize, this.totalCount);
-
-			if (startIdx >= this.totalCount) {
-				this.hasMore = false;
-				return [];
-			}
-
-			for (let i = startIdx; i < endIdx; i++) {
-				newRows.push({
-					id: i,
-					receiverName: `测试收货企业${i + 1}有限公司`,
-					receiverProvince: provinces[i % provinces.length],
-					customerLevel: levels[i % levels.length],
-					customerNature: natures[i % natures.length],
-					manager: managers[i % managers.length],
-					alertCount: Math.floor(Math.random() * 10) + 1,
-				});
-			}
-			return newRows;
-		},
-
-		async onRefresh() {
-			this.isRefreshing = true;
-			this.pageNum = 1;
-			this.hasMore = true;
-			// Simulate network request
-			setTimeout(() => {
-				this.rows = this.generateFakeData();
-				this.isRefreshing = false;
-			}, 1000);
-		},
-
-		onLoadMore() {
-			if (this.loading || !this.hasMore) return;
-			this.loading = true;
-			this.pageNum++;
-			
-			// Simulate network request
-			setTimeout(() => {
-				const more = this.generateFakeData();
-				if (more.length > 0) {
-					this.rows = [...this.rows, ...more];
-				} else {
-					this.hasMore = false;
-				}
-				this.loading = false;
-			}, 800);
-		},
-
-		resetFetch() {
-			this.loading = true;
-			this.pageNum = 1;
-			this.hasMore = true;
-			// Simulate initial load
-			setTimeout(() => {
-				this.rows = this.generateFakeData();
-				this.loading = false;
-			}, 500);
-		},
-
-		toDetail(item) {
-			uni.navigateTo({
-				url: `/traceCodePackages/traceabilityReport/pages/ganmaoling/detail/index?id=${item.id}&name=${encodeURIComponent(item.receiverName)}`
-			});
-		}
-	},
+  components: {
+    EmptyView,
+  },
+  data() {
+    return {
+      isRefreshing: false,
+      loading: false,
+      rows: [],
+      totalCount: 60, // Simulated total count
+      hasMore: true,
+      pageNum: 1,
+      pageSize: 20,
+    };
+  },
+  created() {
+    this.resetFetch();
+  },
+  methods: {
+    formatDate,
+
+    getLevelClass(level) {
+      if (level === "VIP") return "tag-vip";
+      if (level === "二级") return "tag-l2";
+      if (level === "三级") return "tag-l3";
+      return "tag-default";
+    },
+
+    generateFakeData() {
+      const newRows = [];
+      const levels = ["VIP", "二级", "三级"];
+      const provinces = ["北京市", "上海市", "广东省", "浙江省", "江苏省"];
+      const natures = ["协议客户", "非协议客户"];
+      const managers = ["张明华", "李建华", "王丽萍", "陈大文"];
+
+      const startIdx = (this.pageNum - 1) * this.pageSize;
+      const endIdx = Math.min(startIdx + this.pageSize, this.totalCount);
+
+      if (startIdx >= this.totalCount) {
+        this.hasMore = false;
+        return [];
+      }
+
+      for (let i = startIdx; i < endIdx; i++) {
+        newRows.push({
+          id: i,
+          receiverName: `测试收货企业${i + 1}有限公司`,
+          receiverProvince: provinces[i % provinces.length],
+          customerLevel: levels[i % levels.length],
+          customerNature: natures[i % natures.length],
+          manager: managers[i % managers.length],
+          alertCount: Math.floor(Math.random() * 10) + 1,
+        });
+      }
+      return newRows;
+    },
+
+    async onRefresh() {
+      this.isRefreshing = true;
+      this.pageNum = 1;
+      this.hasMore = true;
+      // Simulate network request
+      setTimeout(() => {
+        this.rows = this.generateFakeData();
+        this.isRefreshing = false;
+      }, 1000);
+    },
+
+    onLoadMore() {
+      if (this.loading || !this.hasMore) return;
+      this.loading = true;
+      this.pageNum++;
+
+      // Simulate network request
+      setTimeout(() => {
+        const more = this.generateFakeData();
+        if (more.length > 0) {
+          this.rows = [...this.rows, ...more];
+        } else {
+          this.hasMore = false;
+        }
+        this.loading = false;
+      }, 800);
+    },
+
+    resetFetch() {
+      this.loading = true;
+      this.pageNum = 1;
+      this.hasMore = true;
+      // Simulate initial load
+      setTimeout(() => {
+        this.rows = this.generateFakeData();
+        this.loading = false;
+      }, 500);
+    },
+
+    toDetail(item) {
+      uni.navigateTo({
+        url: `/traceCodePackages/traceabilityReport/pages/ganmaoling/detail/index?id=${item.id}&name=${encodeURIComponent(item.receiverName)}`,
+      });
+    },
+  },
 };
 </script>
 
 <style scoped>
 .detail-page {
-	display: flex;
-	flex-direction: column;
-	height: calc(100vh - 116rpx - env(safe-area-inset-bottom));
-	box-sizing: border-box;
-	background: #f3f6f9;
+  display: flex;
+  flex-direction: column;
+  height: calc(100vh - 116rpx - env(safe-area-inset-bottom));
+  box-sizing: border-box;
+  background: #f3f6f9;
 }
 
 .tip {
-	font-size: 24rpx;
-	color: #999;
-	padding: 24rpx;
-	background: #f3f6f9;
+  font-size: 24rpx;
+  color: #999;
+  padding: 24rpx;
+  background: #f3f6f9;
 }
 
 .list-scroll {
-	flex: 1;
-	height: 0; /* Important for flex expansion */
-	padding: 0 24rpx;
-    box-sizing: border-box;
+  flex: 1;
+  height: 0; /* Important for flex expansion */
+  padding: 0 24rpx;
+  box-sizing: border-box;
 }
 
 .list-container {
-	padding-bottom: calc(50rpx + env(safe-area-inset-bottom));
-    padding-left: 24rpx;
-    padding-right: 24rpx;
+  padding-bottom: calc(50rpx + env(safe-area-inset-bottom));
+  padding-left: 24rpx;
+  padding-right: 24rpx;
 }
 
 .card-item {
-	display: flex;
-	justify-content: space-between;
-	align-items: flex-start; /* Align top */
-	background: #fff;
-	border-radius: 16rpx;
-	padding: 30rpx;
-	margin-bottom: 20rpx;
-	box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start; /* Align top */
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 30rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
 }
 
 .left-info {
-	flex: 1;
-	margin-right: 20rpx;
+  flex: 1;
+  margin-right: 20rpx;
 }
 
 .row1-name {
-	font-size: 30rpx;
-	font-weight: bold;
-	color: #333;
-	margin-bottom: 16rpx;
+  font-size: 30rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 16rpx;
 }
 
 .row2-info {
-	display: flex;
-	align-items: center;
-	margin-bottom: 12rpx;
+  display: flex;
+  align-items: center;
+  margin-bottom: 12rpx;
 }
 
 .province {
-	font-size: 26rpx;
-	color: #666;
-	margin-right: 20rpx;
+  font-size: 26rpx;
+  color: #666;
+  margin-right: 20rpx;
 }
 
 .level-tag {
-	font-size: 22rpx;
-	padding: 4rpx 12rpx;
-	border-radius: 6rpx;
-	background: #f0f0f0;
-	color: #666;
+  font-size: 22rpx;
+  padding: 4rpx 12rpx;
+  border-radius: 6rpx;
+  background: #f0f0f0;
+  color: #666;
 }
 
 .tag-vip {
-	background: #e6f7ff;
-	color: #1890ff;
+  background: #e6f7ff;
+  color: #1890ff;
 }
 
 .tag-l2 {
-	background: #f6ffed;
-	color: #52c41a;
+  background: #f6ffed;
+  color: #52c41a;
 }
 
 .tag-l3 {
-	background: #fff7e6;
-	color: #fa8c16;
+  background: #fff7e6;
+  color: #fa8c16;
 }
 
 .row3-nature {
-	font-size: 26rpx;
-	color: #666;
-	margin-bottom: 12rpx;
+  font-size: 26rpx;
+  color: #666;
+  margin-bottom: 12rpx;
 }
 
 .row4-manager {
-	font-size: 26rpx;
-	color: #666;
+  font-size: 26rpx;
+  color: #666;
 }
 
 .right-info {
-	display: flex;
-	align-items: center;
-    align-self: center; /* Center vertically relative to card */
+  display: flex;
+  align-items: center;
+  align-self: center; /* Center vertically relative to card */
 }
 
 .alert-count {
-	background: #fff2f0;
-	color: #ff4d4f;
-	font-size: 24rpx;
-	padding: 8rpx 20rpx;
-	border-radius: 30rpx;
-	font-weight: bold;
+  background: #fff2f0;
+  color: #ff4d4f;
+  font-size: 24rpx;
+  padding: 8rpx 20rpx;
+  border-radius: 30rpx;
+  font-weight: bold;
 }
 
 .loading-more {
-	display: flex;
-	justify-content: center;
-	align-items: center;
-	padding: 20rpx 0;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 20rpx 0;
 }
 
 .loading-icon {
-	width: 32rpx;
-	height: 32rpx;
-	margin-right: 10rpx;
-	animation: spin 1s linear infinite;
+  width: 32rpx;
+  height: 32rpx;
+  margin-right: 10rpx;
+  animation: spin 1s linear infinite;
 }
 
 .empty-data {
-    display: flex;
-    justify-content: center;
-    padding-top: 100rpx;
+  display: flex;
+  justify-content: center;
+  padding-top: 100rpx;
 }
 
 .no-more {
-    text-align: center;
-    color: #999;
-    font-size: 24rpx;
-    padding: 20rpx 0;
+  text-align: center;
+  color: #999;
+  font-size: 24rpx;
+  padding: 20rpx 0;
 }
 
 @keyframes spin {
-	from { transform: rotate(0deg); }
-	to { transform: rotate(360deg); }
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
 }
-</style>
+</style>