后台
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import type { MonthStat } from '@/api/stats'
|
||||
|
||||
/**
|
||||
* Pure derived-stat helpers for the Stats page (Task 6).
|
||||
*
|
||||
* Extracted from {@link Stats.vue} so the two pieces of trivia that are easy
|
||||
* to get wrong — (1) finding the current month's count in a DESC-ordered list
|
||||
* and (2) flipping that list to chronological ASC for the line chart — are
|
||||
* unit-testable without mounting the component or stubbing ECharts.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Look up the inquiry count for a given `YYYY-MM` month in the `monthly` list.
|
||||
*
|
||||
* Used by Stats.vue for the "本月新增" card: it passes
|
||||
* `dayjs().format('YYYY-MM')` and we return the matching count, or `0` when
|
||||
* there's no data for the current month yet (the backend omits zero-count
|
||||
* months entirely, and a fresh month may not have appeared in the trailing
|
||||
* 12-month window at all).
|
||||
*
|
||||
* The lookup is by value equality on `ym`, so input order (DESC vs ASC) is
|
||||
* irrelevant. Returns `0` for an empty list — graceful fallback for an empty
|
||||
* DB / new install.
|
||||
*/
|
||||
export function currentMonthCount(
|
||||
monthly: readonly MonthStat[],
|
||||
ym: string,
|
||||
): number {
|
||||
// `find` rather than indexing `[0]` — the current month is not guaranteed to
|
||||
// be the first entry (DESC newest-first only covers months that have data,
|
||||
// and a brand-new month may be ABSENT from the trailing 12-month window).
|
||||
const hit = monthly.find((m) => m.ym === ym)
|
||||
return hit?.count ?? 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new array of monthly stats sorted **ascending** by `ym`
|
||||
* (chronological order — what the trend line chart needs).
|
||||
*
|
||||
* The backend returns `monthly` **DESC** (newest first). The line chart's X
|
||||
* axis wants oldest → newest, so this flips the order. A fresh copy is always
|
||||
* returned (the input is never mutated), even when the input is already ASC —
|
||||
* callers can safely pass a `readonly` slice from the API response.
|
||||
*
|
||||
* String comparison on `YYYY-MM` is lexicographically correct (zero-padded
|
||||
* fixed-width format), so no Date parsing is needed.
|
||||
*/
|
||||
export function sortMonthlyAsc(monthly: readonly MonthStat[]): MonthStat[] {
|
||||
// Slice first so `.sort` cannot reorder the caller's array — important
|
||||
// because `monthly` may be the live API response object.
|
||||
return monthly.slice().sort((a, b) => {
|
||||
if (a.ym !== b.ym) return a.ym < b.ym ? -1 : 1
|
||||
return 0
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user