|
|
@@ -279,8 +279,8 @@ const downloadByDate = async (date) => {
|
|
|
const viewScanRecords = async (qrCode) => {
|
|
|
try {
|
|
|
selectedQrCode.value = qrCode
|
|
|
- const response = await getQrCodeScanRecords(qrCode.qrCode, 20)
|
|
|
- scanRecords.value = response.data
|
|
|
+ const response = await getQrCodeScanRecords(qrCode.qrCode, 10)
|
|
|
+ scanRecords.value = response.records || []
|
|
|
scanRecordDialog.value = true
|
|
|
} catch (error) {
|
|
|
toast.add({
|
|
|
@@ -456,39 +456,76 @@ onMounted(() => {
|
|
|
</Dialog>
|
|
|
|
|
|
<!-- 扫描记录对话框 -->
|
|
|
- <Dialog v-model:visible="scanRecordDialog" :modal="true" header="扫描记录" :style="{ width: '800px' }"
|
|
|
+ <Dialog v-model:visible="scanRecordDialog" :modal="true" header="扫描记录" :style="{ width: '900px' }"
|
|
|
position="center">
|
|
|
- <div v-if="selectedQrCode" class="mb-4 p-3 bg-gray-50 dark:bg-gray-800 rounded">
|
|
|
- <div class="text-sm text-gray-600 dark:text-gray-400">二维码编号</div>
|
|
|
- <div class="font-mono font-semibold">{{ selectedQrCode.qrCode }}</div>
|
|
|
- <div class="text-sm text-gray-600 dark:text-gray-400 mt-2">总扫描次数</div>
|
|
|
- <div class="font-semibold text-lg">{{ selectedQrCode.scanCount || 0 }} 次</div>
|
|
|
+ <div v-if="selectedQrCode" class="mb-4 p-4 bg-gray-50 dark:bg-gray-800 rounded">
|
|
|
+ <div class="grid grid-cols-2 gap-4">
|
|
|
+ <div>
|
|
|
+ <div class="text-sm text-gray-600 dark:text-gray-400">二维码编号</div>
|
|
|
+ <div class="font-mono font-semibold">{{ selectedQrCode.qrCode }}</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div class="text-sm text-gray-600 dark:text-gray-400">总扫描次数</div>
|
|
|
+ <div class="font-semibold text-lg text-blue-600">{{ selectedQrCode.scanCount || 0 }} 次</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="scanRecords.length === 0" class="text-center py-8 text-gray-500">
|
|
|
+ <i class="pi pi-inbox text-4xl mb-2"></i>
|
|
|
+ <div>暂无扫描记录</div>
|
|
|
</div>
|
|
|
|
|
|
- <DataTable :value="scanRecords" scrollable scrollHeight="400px">
|
|
|
+ <DataTable v-else :value="scanRecords" scrollable scrollHeight="450px" striped>
|
|
|
+ <template #header>
|
|
|
+ <div class="text-sm text-gray-600">最近 10 条扫描记录</div>
|
|
|
+ </template>
|
|
|
+
|
|
|
<Column field="scanTime" header="扫描时间" style="min-width: 180px">
|
|
|
<template #body="slotProps">
|
|
|
- {{ formatDate(slotProps.data.scanTime) }}
|
|
|
+ <div class="flex items-center gap-2">
|
|
|
+ <i class="pi pi-clock text-gray-400"></i>
|
|
|
+ <span>{{ formatDate(slotProps.data.scanTime) }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </Column>
|
|
|
+
|
|
|
+ <Column field="ipAddress" header="IP地址" style="min-width: 140px">
|
|
|
+ <template #body="slotProps">
|
|
|
+ <div class="flex items-center gap-2">
|
|
|
+ <i class="pi pi-globe text-gray-400"></i>
|
|
|
+ <code class="text-xs">{{ slotProps.data.ipAddress || '-' }}</code>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
</Column>
|
|
|
+
|
|
|
<Column field="address" header="地址" style="min-width: 200px">
|
|
|
<template #body="slotProps">
|
|
|
- {{ slotProps.data.address || '-' }}
|
|
|
+ <div class="flex items-center gap-2">
|
|
|
+ <i class="pi pi-map-marker text-gray-400"></i>
|
|
|
+ <span class="text-sm">{{ slotProps.data.address || '未获取' }}</span>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
</Column>
|
|
|
- <Column field="latitude" header="位置" style="min-width: 150px">
|
|
|
+
|
|
|
+ <Column field="location" header="位置坐标" style="min-width: 150px">
|
|
|
<template #body="slotProps">
|
|
|
<a v-if="slotProps.data.latitude && slotProps.data.longitude"
|
|
|
:href="`https://www.google.com/maps?q=${slotProps.data.latitude},${slotProps.data.longitude}`"
|
|
|
- target="_blank" class="text-blue-600 hover:underline">
|
|
|
- 📍 查看地图
|
|
|
+ target="_blank" class="text-blue-600 hover:underline flex items-center gap-1">
|
|
|
+ <i class="pi pi-external-link"></i>
|
|
|
+ 查看地图
|
|
|
</a>
|
|
|
- <span v-else>-</span>
|
|
|
+ <span v-else class="text-gray-400 text-sm">未获取</span>
|
|
|
</template>
|
|
|
</Column>
|
|
|
- <Column field="ipAddress" header="IP地址" style="min-width: 150px">
|
|
|
+
|
|
|
+ <Column field="userAgent" header="设备信息" style="min-width: 250px">
|
|
|
<template #body="slotProps">
|
|
|
- {{ slotProps.data.ipAddress || '-' }}
|
|
|
+ <div class="text-xs text-gray-600 truncate" :title="slotProps.data.userAgent">
|
|
|
+ <i class="pi pi-mobile text-gray-400 mr-1"></i>
|
|
|
+ {{ slotProps.data.userAgent || '-' }}
|
|
|
+ </div>
|
|
|
</template>
|
|
|
</Column>
|
|
|
</DataTable>
|