fix(dashboard): 使用稳定设备标识

This commit is contained in:
2026-05-12 00:56:33 +08:00
parent 9fb37b29c2
commit ad32500121
3 changed files with 20 additions and 4 deletions
+11 -1
View File
@@ -3,6 +3,7 @@ import {
createBatteriesResponse,
createDashboardSnapshot,
DEVICE_STATUS,
fromMysqlBoolean,
getDeviceStatus,
MYSQL_BOOLEAN,
POWER_STATUS,
@@ -27,7 +28,7 @@ const rows = [
userId: 7,
mac: 'RING-B11',
devModel: '2402-B',
devName: 'RING-B11',
devName: '',
isLowPower: MYSQL_BOOLEAN.TRUE,
powerStatus: POWER_STATUS.CHARGING,
power: 84,
@@ -43,6 +44,11 @@ describe('battery domain', () => {
expect(getDeviceStatus(85)).toBe(DEVICE_STATUS.WARNING)
})
test('trims MySQL boolean strings before normalization', () => {
expect(fromMysqlBoolean(' true ')).toBe(true)
expect(fromMysqlBoolean(' false ')).toBe(false)
})
test('builds batteries response counters from records', () => {
const now = new Date('2026-05-11T00:00:00.000Z')
const items = rows.map(toBatteryInfo)
@@ -75,6 +81,10 @@ describe('battery domain', () => {
const snapshot = createDashboardSnapshot(rows.map(toBatteryInfo), now)
expect(snapshot.devices).toHaveLength(2)
expect(snapshot.devices[0]?.id).toBe('RING-A03')
expect(snapshot.devices[0]?.displayName).toBe('RING-A03')
expect(snapshot.devices[1]?.id).toBe('RING-B11')
expect(snapshot.devices[1]?.displayName).toBe('RING-B11')
expect(snapshot.devices.every((device) => device.sohSource === 'unavailable')).toBe(true)
expect(snapshot.devices.every((device) => device.soh === null)).toBe(true)
expect(snapshot.devices.every((device) => device.soh30d === null)).toBe(true)
+3 -1
View File
@@ -54,6 +54,7 @@ export type BatteryInfo = z.infer<typeof batteryInfoSchema>
export const fleetUnitSchema = z.object({
id: z.string(),
displayName: z.string(),
batch: z.string(),
firmware: z.string(),
cycles: z.number().int(),
@@ -267,7 +268,8 @@ function toFleetUnit(item: BatteryInfo, prediction?: BatteryPrediction): FleetUn
const riskScore = Math.round(clamp(prediction?.riskScore ?? fallbackRiskScore, 0, 100))
return {
id: item.devName || item.mac,
id: item.mac,
displayName: item.devName || item.mac,
batch: item.devModel,
firmware: item.remark ?? '未提供',
cycles: prediction?.cyclesUsed ?? 0,
+6 -2
View File
@@ -93,7 +93,11 @@ function formatPercentWithUnit(value: number | null) {
function formatDelta(from: number | null, to: number | null) {
if (from === null || to === null) return '预测不可用'
return `${(from - to).toFixed(1)}% 衰减`
const delta = from - to
if (delta < 0) return `${Math.abs(delta).toFixed(1)}% 改善`
if (delta === 0) return '0.0% 持平'
return `${delta.toFixed(1)}% 衰减`
}
function widthPercent(value: number | null) {
@@ -540,7 +544,7 @@ function Dashboard() {
.sort((a, b) => b.riskScore - a.riskScore)
.map((unit) => (
<tr key={unit.id} className="transition-colors hover:bg-white/[0.04]">
<td className="px-6 py-4 font-medium text-white">{unit.id}</td>
<td className="px-6 py-4 font-medium text-white">{unit.displayName}</td>
<td className="px-6 py-4 text-[#A1A1AA]">{unit.batch}</td>
<td className="px-6 py-4 tabular-nums text-white">{formatPercentWithUnit(unit.soh)}</td>
<td className="px-6 py-4 tabular-nums text-[#A1A1AA]">