Files
sundynix-site/admin/src/api/client.ts
T
Blizzard 5abc705eae feat: 官网 + 管理端 + Gin/GORM 后端首个完整版本
- web/: 产品官网(Hero 事件流终端、功能矩阵、架构、快速开始、下载、博客 + Markdown 详情页),青瓷绿双主题
- admin/: 内容管理(JWT 登录、文章分页/搜索/CRUD、草稿与发布),embed 挂 /admin
- server/: Gin + GORM,MySQL(DSN 走 .env,SQLite 兜底);规范落地:sundynix_ 表前缀、字符串雪花主键、snake_case 列名、统一响应信封、公共分页参数
- 双 SPA embed 单二进制部署,make build 一键出包

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:03:31 +08:00

69 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** 管理端 API clienttoken 注入 + 统一信封解包 + 401 跳登录 */
const TOKEN_KEY = 'sundynix-admin-token'
export function getToken(): string | null {
return localStorage.getItem(TOKEN_KEY)
}
export function setToken(token: string) {
localStorage.setItem(TOKEN_KEY, token)
}
export function clearToken() {
localStorage.removeItem(TOKEN_KEY)
}
interface Envelope<T> {
code: number
message: string
data: T
}
export class ApiError extends Error {
status: number
code: number
constructor(status: number, code: number, message: string) {
super(message)
this.status = status
this.code = code
}
}
export async function request<T>(
path: string,
init: RequestInit = {},
): Promise<T> {
const headers = new Headers(init.headers)
headers.set('Content-Type', 'application/json')
const token = getToken()
if (token) headers.set('Authorization', `Bearer ${token}`)
const res = await fetch(path, { ...init, headers })
if (res.status === 401) {
clearToken()
// basename=/admin,登录路由实际是 /admin/login
if (!window.location.pathname.endsWith('/login')) {
window.location.href = '/admin/login'
}
throw new ApiError(401, 40100, '登录已过期')
}
let body: Envelope<T> | null = null
try {
body = (await res.json()) as Envelope<T>
} catch {
// 非 JSON 响应
}
if (!res.ok || !body || body.code !== 0) {
throw new ApiError(
res.status,
body?.code ?? -1,
body?.message ?? `请求失败(${res.status}`,
)
}
return body.data
}