From 2f9c84cf0e0c03a8e3bf07d3924ccdf791070b77 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 16 十月 2026 17:45:21 +0800
Subject: [PATCH] feat(mobile): 添加移动端自动托盘生成功能和追溯定位功能

---
 src/views/mes/trace-consumer-scan/index.vue |   87 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/src/views/mes/trace-consumer-scan/index.vue b/src/views/mes/trace-consumer-scan/index.vue
index 0a6da66..3a675eb 100644
--- a/src/views/mes/trace-consumer-scan/index.vue
+++ b/src/views/mes/trace-consumer-scan/index.vue
@@ -1,12 +1,14 @@
 <script lang="ts" setup>
-import { computed, ref } from 'vue';
+import { computed, ref, watch } from 'vue';
 
 import { Page } from '@vben/common-ui';
 
-import { Card, Col, DatePicker, Row } from 'ant-design-vue';
+import { Card, Col, DatePicker, Input, Row, Table } from 'ant-design-vue';
 import dayjs from 'dayjs';
 
 import { getRangePickerDefaultProps } from '#/utils';
+import { getTraceLocationDistribution, getTraceLocationVisits } from '#/api/mes/trace-consumer-scan';
+import type { MesTraceConsumerScanApi } from '#/api/mes/trace-consumer-scan';
 
 import DistributionChart from './modules/distribution-chart.vue';
 import SummaryCards from './modules/summary-cards.vue';
@@ -22,6 +24,59 @@
 
 const startTime = computed(() => dateRange.value?.[0]);
 const endTime = computed(() => dateRange.value?.[1]);
+
+const traceCode = ref('');
+const pageNo = ref(1);
+const locationLoading = ref(false);
+const locationRows = ref<MesTraceConsumerScanApi.LocationVisit[]>([]);
+const locationDistribution = ref<MesTraceConsumerScanApi.LocationDistribution[]>([]);
+const locationTotal = ref(0);
+const locationColumns = [
+  { title: '璁块棶鏃堕棿', dataIndex: 'visitTime', key: 'visitTime' },
+  { title: '杩芥函鐮�', dataIndex: 'traceCode', key: 'traceCode' },
+  { title: '绾害', dataIndex: 'latitude', key: 'latitude' },
+  { title: '缁忓害', dataIndex: 'longitude', key: 'longitude' },
+  { title: '绮惧害锛堢背锛�', dataIndex: 'accuracy', key: 'accuracy' },
+  { title: '浣嶇疆', key: 'map' },
+];
+
+async function loadLocationVisits() {
+  locationLoading.value = true;
+  try {
+    const page = await getTraceLocationVisits({
+      pageNo: pageNo.value,
+      pageSize: 20,
+      startTime: startTime.value,
+      endTime: endTime.value,
+      traceCode: traceCode.value.trim() || undefined,
+    });
+    locationRows.value = page.list;
+    locationTotal.value = page.total;
+    locationDistribution.value = await getTraceLocationDistribution({
+      startTime: startTime.value,
+      endTime: endTime.value,
+      traceCode: traceCode.value.trim() || undefined,
+    });
+  } finally {
+    locationLoading.value = false;
+  }
+}
+
+watch([startTime, endTime, traceCode], () => {
+  pageNo.value = 1;
+  loadLocationVisits();
+}, { immediate: true });
+
+function mapUrl(row: Record<string, any>) {
+  const lat = Number(row.latitude);
+  const lon = Number(row.longitude);
+  return `https://www.openstreetmap.org/?mlat=${lat}&mlon=${lon}#map=16/${lat}/${lon}`;
+}
+
+function handleLocationPageChange(pagination: { current?: number }) {
+  pageNo.value = pagination.current || 1;
+  loadLocationVisits();
+}
 </script>
 
 <template>
@@ -46,5 +101,33 @@
         <DistributionChart :start-time="startTime" :end-time="endTime" />
       </Col>
     </Row>
+
+    <Card title="瀹氫綅鎺堟潈璁块棶" class="mb-4">
+      <p class="mb-3 text-sm text-muted-foreground">
+        褰撳墠绛涢�夋潯浠朵笅鍏� {{ locationTotal }} 娆℃巿鏉冨畾浣嶈闂紱涓嬭〃鏄剧ず鐢ㄦ埛鎺堟潈鍚庝笂浼犵殑浣嶇疆鍙婂畾浣嶇簿搴︺��
+      </p>
+      <Input v-model:value="traceCode" class="mb-3 max-w-xs" allow-clear placeholder="鎸夎拷婧爜绛涢��" />
+      <div v-if="locationDistribution.length" class="mb-4">
+        <div class="mb-2 font-medium">鐑棬浣嶇疆锛堝潗鏍囦繚鐣欎袱浣嶅皬鏁帮紝鏈�澶� 20 澶勶級</div>
+        <div class="flex flex-wrap gap-2">
+          <span v-for="item in locationDistribution" :key="`${item.latitude},${item.longitude}`" class="rounded bg-green-50 px-3 py-1 text-sm text-green-800">
+            {{ item.latitude }}, {{ item.longitude }}锛歿{ item.count }} 娆�
+          </span>
+        </div>
+      </div>
+      <Table
+        :columns="locationColumns"
+        :data-source="locationRows"
+        :loading="locationLoading"
+        :pagination="{ current: pageNo, pageSize: 20, total: locationTotal, showSizeChanger: false }"
+        :row-key="(row: MesTraceConsumerScanApi.LocationVisit) => row.id"
+        :scroll="{ x: 850 }"
+        @change="handleLocationPageChange"
+      >
+        <template #bodyCell="{ column, record }">
+          <a v-if="column.key === 'map'" :href="mapUrl(record)" target="_blank" rel="noopener noreferrer">鏌ョ湅鍦板浘</a>
+        </template>
+      </Table>
+    </Card>
   </Page>
 </template>

--
Gitblit v1.9.3