57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
import { ApiError } from '@shared/api/client'
|
|
import { describeError } from '@shared/ui'
|
|
import { scoreTone } from '@shared/format'
|
|
|
|
export const RANGES = [
|
|
{ value: '15m', label: '15 分钟' },
|
|
{ value: '1h', label: '1 小时' },
|
|
{ value: '6h', label: '6 小时' },
|
|
{ value: '24h', label: '24 小时' },
|
|
{ value: '7d', label: '7 天' },
|
|
] as const
|
|
|
|
export type RangeValue = (typeof RANGES)[number]['value']
|
|
|
|
export const isRange = (v: string | null): v is RangeValue => RANGES.some((r) => r.value === v)
|
|
|
|
export const SCORE_MODELS = [
|
|
{ id: 'score.reality', label: 'REALITY' },
|
|
{ id: 'score.hy2', label: 'Hy2' },
|
|
{ id: 'score.mc', label: 'MC' },
|
|
{ id: 'score.base', label: '综合' },
|
|
] as const
|
|
|
|
export function ScoreChips({ metrics, compact }: { metrics: Record<string, number | null | undefined>; compact?: boolean }) {
|
|
return (
|
|
<div className={`scores ${compact ? 'compact' : ''}`}>
|
|
{SCORE_MODELS.map((m) => {
|
|
const v = metrics[m.id]
|
|
return (
|
|
<span key={m.id} className={`score-chip ${scoreTone(v)}`} title={`${m.label} 评分`}>
|
|
<b>{v === null || v === undefined ? '—' : Math.round(v)}</b>
|
|
<small>{m.label}</small>
|
|
</span>
|
|
)
|
|
})}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
/** 站点没有公开时匿名访问会被拒绝:给出一个说得清楚的提示,而不是一条错误。 */
|
|
export function PageError({ error }: { error: unknown }) {
|
|
if (!error) return null
|
|
if (error instanceof ApiError && error.code === 'site_private') {
|
|
return (
|
|
<div className="card" style={{ marginTop: 24 }}>
|
|
<div className="card-title">站点未公开</div>
|
|
<p className="muted">管理员还没有把站点设为公开。管理员请先 <a href="/admin/">登录管理端</a>,在「系统 → 设置」里打开「站点公开」,或者带着登录状态访问这里。</p>
|
|
</div>
|
|
)
|
|
}
|
|
return <div className="notice bad" style={{ marginTop: 24 }}>{describeError(error)}</div>
|
|
}
|
|
|
|
export const lineLabel = (name: string, probe: string) => `${name} · ${probe}`
|
|
|
|
export const num = (v: number | null | undefined) => (v === null || v === undefined ? null : v)
|