fix(api): 修正看板和历史统计口径

This commit is contained in:
2026-05-12 00:48:16 +08:00
parent 58b615a327
commit 25d7f1c315
3 changed files with 28 additions and 8 deletions
+14
View File
@@ -56,6 +56,20 @@ describe('battery domain', () => {
expect(response.items[0]?.createTime).toBe('2026-05-10T23:00:00.000Z')
})
test('keeps explicit window summaries for limited history slices', () => {
const now = new Date('2026-05-11T00:00:00.000Z')
const items = rows.map(toBatteryInfo)
const response = createBatteriesResponse(items, now, {
total: items.length,
lowPower: 1,
charging: 1,
})
expect(response.total).toBe(2)
expect(response.lowPower).toBe(1)
expect(response.charging).toBe(1)
})
test('creates dashboard aggregate shape without using power as fake SOH', () => {
const now = new Date('2026-05-11T00:00:00.000Z')
const snapshot = createDashboardSnapshot(rows.map(toBatteryInfo), now)
+7 -2
View File
@@ -1,4 +1,4 @@
import { createBatteriesResponse, createDashboardSnapshot } from '@/domain/battery'
import { createBatteriesResponse, createDashboardSnapshot, POWER_STATUS } from '@/domain/battery'
import { os } from '@/server/api/server'
import {
getBatteryHistory,
@@ -63,5 +63,10 @@ export const batteries = os.battery.batteries.handler(async ({ input }) => {
export const history = os.battery.history.handler(async ({ input }) => {
const items = await getBatteryHistory(input.mac)
return createBatteriesResponse(items)
// History returns a limited window, so the counters must describe only this returned slice.
return createBatteriesResponse(items, new Date(), {
total: items.length,
lowPower: items.filter((item) => item.isLowPower).length,
charging: items.filter((item) => item.powerStatus === POWER_STATUS.CHARGING).length,
})
})
+7 -6
View File
@@ -15,8 +15,6 @@ import { env } from '@/env'
const historyLimit = 500
const predictionHistoryLimit = 10
const dashboardLatestLimit = 100
type BatteryInfoMysqlRow = RowDataPacket & BatteryInfoSourceRow
type CountMysqlRow = RowDataPacket & {
total: number
@@ -314,16 +312,19 @@ export async function getLatestBatteryPage(input: LatestBatteryPageInput): Promi
}
}
export async function getLatestBatteryPerDevice(limit = dashboardLatestLimit): Promise<BatteryInfo[]> {
export async function getLatestBatteryPerDevice(limit?: number): Promise<BatteryInfo[]> {
const appliedLimit = typeof limit === 'number' && limit > 0 ? limit : undefined
const limitSql = appliedLimit ? '\n LIMIT :limit' : ''
const queryParams = appliedLimit ? { limit: appliedLimit } : {}
const [rows] = await getBatteryPool().query<BatteryInfoMysqlRow[]>(
`
SELECT ${sourceColumns}
FROM ls_battery_info AS current_record
WHERE ${latestRecordPredicate}
ORDER BY current_record.create_time DESC, current_record.id DESC
LIMIT :limit
ORDER BY current_record.create_time DESC, current_record.id DESC${limitSql}
`,
{ limit: Math.min(Math.max(limit, 1), dashboardLatestLimit) },
queryParams,
)
return rows.map(toBatteryInfo)