fix: 修复设备跨时区时间与在线状态

This commit is contained in:
Tyke Chen
2026-07-14 10:08:23 +08:00
parent ad3fb4d8c8
commit dbeda01697
11 changed files with 543 additions and 104 deletions
+41
View File
@@ -0,0 +1,41 @@
export function hasTimestampValue(timestamp) {
if (timestamp === null || timestamp === undefined) return false;
return typeof timestamp !== 'string' || timestamp.trim() !== '';
}
export function parseTimestamp(timestamp) {
if (!hasTimestampValue(timestamp)) return null;
if (typeof timestamp !== 'number' && typeof timestamp !== 'string') return null;
const normalizedTimestamp = typeof timestamp === 'string' ? timestamp.trim() : timestamp;
const parsedTimestamp = Number(normalizedTimestamp);
if (!Number.isFinite(parsedTimestamp)) return null;
return Number.isNaN(new Date(parsedTimestamp).getTime()) ? null : parsedTimestamp;
}
export function parseLegacyDate(dateValue) {
if (!dateValue) return null;
const timestamp = new Date(dateValue).getTime();
return Number.isNaN(timestamp) ? null : timestamp;
}
export function formatTimestamp(timestamp, formatter = value => new Date(value).toLocaleString()) {
const parsedTimestamp = parseTimestamp(timestamp);
return parsedTimestamp === null ? '-' : formatter(parsedTimestamp);
}
export function formatCreateDate(timestamp, legacyDate, formatter) {
if (!hasTimestampValue(timestamp)) return legacyDate || '-';
return formatTimestamp(timestamp, formatter);
}
export function compareTimestamps(firstTimestamp, secondTimestamp) {
const firstIsValid = Number.isFinite(firstTimestamp);
const secondIsValid = Number.isFinite(secondTimestamp);
if (firstIsValid && secondIsValid) return firstTimestamp - secondTimestamp;
if (firstIsValid) return -1;
if (secondIsValid) return 1;
return 0;
}
@@ -120,7 +120,7 @@
<i class="el-icon-time"></i>
<div class="stat-content">
<div class="stat-label">{{ $t('addressBookManagement.addTime') }}</div>
<div class="stat-value">{{ selectedDevice.createDate || '-' }}</div>
<div class="stat-value">{{ formatDeviceCreateDate(selectedDevice) }}</div>
</div>
</div>
<div class="stat-item">
@@ -207,6 +207,7 @@ import Api from "@/apis/api.js";
import AddressBookApi from "@/apis/module/addressBook.js";
import MacAddressMask from "@/components/MacAddressMask.vue";
import CustomButton from "@/components/CustomButton.vue";
import { formatCreateDate, parseTimestamp } from '@/utils/deviceTime.mjs';
export default {
name: "AddressBookManagement",
@@ -281,6 +282,7 @@ export default {
remarks: device.alias || '',
online: false,
createDate: device.createDate,
createDateTimestamp: device.createDateTimestamp,
lastConnectedAt: device.lastConnectedAtTimestamp,
deviceStatus: 'offline'
}));
@@ -526,9 +528,10 @@ export default {
this.isEditingAgentName = false;
},
getTimeAgo(timestamp) {
if (!timestamp) return '-';
const ts = parseTimestamp(timestamp);
if (ts === null) return '-';
const now = new Date();
const date = new Date(Number(timestamp));
const date = new Date(ts);
const diff = now - date;
const seconds = Math.floor(diff / 1000);
@@ -545,6 +548,10 @@ export default {
if (months < 12) return this.$t('addressBookManagement.monthsAgo', { months });
return this.$t('addressBookManagement.yearsAgo', { years });
},
formatDeviceCreateDate(device) {
if (!device) return '-';
return formatCreateDate(device.createDateTimestamp, device.createDate);
},
getDeviceAvatar(deviceId) {
// 根据 deviceId 计算 MD5,选择对应的头像
const avatars = [
+19 -14
View File
@@ -103,6 +103,14 @@ import VersionFooter from "@/components/VersionFooter.vue";
import MacAddressMask from "@/components/MacAddressMask.vue";
import CustomButton from "@/components/CustomButton.vue";
import CustomTable from "@/components/CustomTable.vue";
import {
compareTimestamps,
formatCreateDate,
formatTimestamp,
hasTimestampValue,
parseLegacyDate,
parseTimestamp,
} from '@/utils/deviceTime.mjs';
export default {
components: {
@@ -327,26 +335,31 @@ export default {
this.loading = false;
if (data.code === 0) {
this.deviceList = data.data.map(device => {
const hasCreateDateTimestamp = hasTimestampValue(device.createDateTimestamp);
const rawBindTime = hasCreateDateTimestamp
? parseTimestamp(device.createDateTimestamp)
: parseLegacyDate(device.createDate);
return {
device_id: device.id,
model: device.board,
firmwareVersion: device.appVersion,
macAddress: device.macAddress,
bindTime: device.createDate,
lastConversation: device.lastConnectedAtTimestamp
? this.formatRelativeTime(device.lastConnectedAtTimestamp)
: '-',
bindTime: formatCreateDate(device.createDateTimestamp, device.createDate),
lastConversation: formatTimestamp(device.lastConnectedAtTimestamp),
remark: device.alias,
_originalRemark: device.alias,
isEdit: false,
_submitting: false,
otaSwitch: device.autoUpdate === 1,
rawBindTime: new Date(device.createDate).getTime(),
rawBindTime,
selected: false,
deviceStatus: 'offline'
};
})
.sort((a, b) => a.rawBindTime - b.rawBindTime);
.sort((firstDevice, secondDevice) => compareTimestamps(
firstDevice.rawBindTime,
secondDevice.rawBindTime,
));
this.activeSearchKeyword = "";
this.searchKeyword = "";
@@ -429,14 +442,6 @@ export default {
const version = row.firmwareVersion.replace(/\./g, '');
return Number(version) >= 200;
},
formatRelativeTime(timestamp) {
if (!timestamp) return '-';
const ts = Number(timestamp);
if (isNaN(ts)) return '-';
const date = new Date(ts);
if (isNaN(date.getTime())) return '-';
return date.toLocaleString();
},
}
};
</script>