feat: api client, auth store, login, authed shell, data-table + CRUD kit

This commit is contained in:
2026-07-07 22:15:08 +08:00
parent 95a3dee29f
commit eb617ce436
23 changed files with 1002 additions and 352 deletions

24
src/lib/errors.ts Normal file
View File

@ -0,0 +1,24 @@
import { toast } from 'sonner'
import type { FieldValues, Path, UseFormSetError } from 'react-hook-form'
import { ApiError } from '@/api/client'
/**
* Standard error handling: 422 field errors land on the form (when given),
* everything else surfaces as a toast with the backend's localized message.
*/
export function handleApiError<T extends FieldValues>(
error: unknown,
setError?: UseFormSetError<T>,
): void {
if (error instanceof ApiError) {
if (error.status === 422 && error.errors && setError) {
for (const [field, messages] of Object.entries(error.errors)) {
setError(field as Path<T>, { type: 'server', message: messages[0] })
}
return
}
toast.error(error.message || `请求失败(${error.code}`)
return
}
toast.error('网络异常,请稍后重试')
}