chore: initial project import

This commit is contained in:
justme committed 2026-10-04 21:46:39 +08:00
commit 3fc4e5ca53
347 files changed
+56172

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
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)