| | |
| | | <div class="sensor-table__head"> |
| | | <span>设备编号</span> |
| | | <span>设备名称</span> |
| | | <span>状态</span> |
| | | <span>电量</span> |
| | | <span>温度</span> |
| | | <span>湿度</span> |
| | | <span>二氧化碳</span> |
| | |
| | | <div v-for="item in deviceRows" :key="item.guid" class="sensor-table__row"> |
| | | <span>{{ item.guid }}</span> |
| | | <span>{{ item.name }}</span> |
| | | <span> |
| | | <el-tag |
| | | v-if="item.statusLabel !== '-'" |
| | | :type="item.statusTagType" |
| | | effect="light" |
| | | size="small" |
| | | > |
| | | {{ item.statusLabel }} |
| | | </el-tag> |
| | | <span v-else>{{ item.statusLabel }}</span> |
| | | </span> |
| | | <span>{{ item.battery }}</span> |
| | | <span>{{ item.temperature }}</span> |
| | | <span>{{ item.humidity }}</span> |
| | | <span>{{ item.co2 }}</span> |
| | |
| | | const hour = endOfDay ? 23 : 0; |
| | | const minute = endOfDay ? 59 : 0; |
| | | const second = endOfDay ? 59 : 0; |
| | | const shanghaiOffsetHours = 8; |
| | | |
| | | return Math.floor(Date.UTC(year, month - 1, day, hour, minute, second) / 1000); |
| | | return Math.floor( |
| | | Date.UTC(year, month - 1, day, hour - shanghaiOffsetHours, minute, second) / 1000 |
| | | ); |
| | | } |
| | | |
| | | function extractNumericValue(rawValue) { |
| | |
| | | const normalized = { |
| | | guid: source.guid || source.deviceGuid || source.deviceNo || `GUID-${index + 1}`, |
| | | name: source.deviceName || source.name || `设备${index + 1}`, |
| | | status: source.status || source.deviceStatus || "", |
| | | battery: source.battery ?? source.deviceBattery ?? "", |
| | | temperature: 0, |
| | | humidity: 0, |
| | | co2: 0, |
| | |
| | | }); |
| | | |
| | | return normalized; |
| | | } |
| | | |
| | | function formatStatusValue(value) { |
| | | if (value === "offline") { |
| | | return "离线"; |
| | | } |
| | | if (value === "error") { |
| | | return "异常"; |
| | | } |
| | | return value || "-"; |
| | | } |
| | | |
| | | function resolveStatusTagType(value) { |
| | | if (value === "offline") { |
| | | return "info"; |
| | | } |
| | | if (value === "error") { |
| | | return "danger"; |
| | | } |
| | | if (value) { |
| | | return "success"; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | function formatBatteryValue(value) { |
| | | if (value === "" || value === null || value === undefined) { |
| | | return "-"; |
| | | } |
| | | |
| | | const numericValue = Number(value); |
| | | if (Number.isFinite(numericValue)) { |
| | | return `${numericValue}%`; |
| | | } |
| | | |
| | | return String(value); |
| | | } |
| | | |
| | | function resolveHistoryTimeLabel(source, index) { |
| | |
| | | latestDevices.value.map((item) => ({ |
| | | guid: item.guid, |
| | | name: item.name, |
| | | statusLabel: formatStatusValue(item.status), |
| | | statusTagType: resolveStatusTagType(item.status), |
| | | battery: formatBatteryValue(item.battery), |
| | | temperature: formatMetricValue(item.temperature, "℃"), |
| | | humidity: formatMetricValue(item.humidity, "%RH"), |
| | | co2: formatMetricValue(item.co2, "ppm"), |
| | |
| | | .sensor-table__head, |
| | | .sensor-table__row { |
| | | display: grid; |
| | | grid-template-columns: 1.2fr 1fr 0.9fr 0.9fr 1fr 0.9fr 0.9fr; |
| | | grid-template-columns: 1.2fr 1fr 0.8fr 0.8fr 0.9fr 0.9fr 1fr 0.9fr 0.9fr; |
| | | gap: 12px; |
| | | align-items: center; |
| | | } |