147 lines
6.0 KiB
TypeScript
147 lines
6.0 KiB
TypeScript
import { apiClient, unwrap } from './client'
|
|
import type { paths } from './generated/schema'
|
|
|
|
export type { ApiPaths, ApiErrorDetail } from './client'
|
|
export { ApiError } from './client'
|
|
export type { paths }
|
|
|
|
// ---- 从生成的 paths 推导请求/响应类型的工具类型(避免页面重复定义接口类型)----
|
|
type Methods = 'get' | 'post' | 'patch' | 'delete' | 'put'
|
|
|
|
type SuccessBody<Op> = Op extends {
|
|
responses: { 200: { content: { 'application/json': infer D } } }
|
|
}
|
|
? D
|
|
: never
|
|
|
|
type QueryOf<P extends keyof paths, M extends Methods> = paths[P][M] extends {
|
|
parameters: { query?: infer Q }
|
|
}
|
|
? Q
|
|
: never
|
|
|
|
type BodyOf<P extends keyof paths, M extends Methods> = paths[P][M] extends {
|
|
requestBody: { content: { 'application/json': infer B } }
|
|
}
|
|
? B
|
|
: never
|
|
|
|
// ---- 常用响应类型 ----
|
|
export type DashboardOverview = SuccessBody<paths['/api/dashboard/overview']['get']>
|
|
export type DashboardTrends = SuccessBody<paths['/api/dashboard/trends']['get']>
|
|
export type DashboardMastery = SuccessBody<paths['/api/dashboard/mastery']['get']>
|
|
export type DashboardWeakPoints = SuccessBody<paths['/api/dashboard/weak-points']['get']>
|
|
export type PracticeModules = SuccessBody<paths['/api/practice/modules']['get']>
|
|
export type Profile = SuccessBody<paths['/api/profile']['get']>
|
|
export type Settings = SuccessBody<paths['/api/settings']['get']>
|
|
export type PlansToday = SuccessBody<paths['/api/plans/today']['get']>
|
|
export type PlansWeek = SuccessBody<paths['/api/plans/week']['get']>
|
|
export type PlanReview = SuccessBody<paths['/api/plans/review']['get']>
|
|
export type StudyPlanItem = SuccessBody<paths['/api/plans/today']['get']>['tasks'][number]
|
|
export type NewsItem = SuccessBody<paths['/api/news/list']['get']>['items'][number]
|
|
export type ImportResult = SuccessBody<paths['/api/news/import/json']['post']>
|
|
|
|
// ---- 数据中枢 ----
|
|
export const dashboardApi = {
|
|
overview: () => unwrap(apiClient.GET('/api/dashboard/overview')),
|
|
trends: (days?: number) =>
|
|
unwrap(apiClient.GET('/api/dashboard/trends', { params: { query: { days } } })),
|
|
mastery: () => unwrap(apiClient.GET('/api/dashboard/mastery')),
|
|
weakPoints: () => unwrap(apiClient.GET('/api/dashboard/weak-points'))
|
|
}
|
|
|
|
// ---- 刷题 ----
|
|
export const practiceApi = {
|
|
modules: () => unwrap(apiClient.GET('/api/practice/modules')),
|
|
start: (body: BodyOf<'/api/practice/start', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/practice/start', { body })),
|
|
question: (sessionId: string) =>
|
|
unwrap(apiClient.GET('/api/practice/{sessionId}/question', { params: { path: { sessionId } } })),
|
|
answer: (sessionId: string, body: BodyOf<'/api/practice/{sessionId}/answer', 'post'>) =>
|
|
unwrap(
|
|
apiClient.POST('/api/practice/{sessionId}/answer', {
|
|
params: { path: { sessionId } },
|
|
body
|
|
})
|
|
),
|
|
finish: (sessionId: string) =>
|
|
unwrap(apiClient.POST('/api/practice/{sessionId}/finish', { params: { path: { sessionId } } }))
|
|
}
|
|
|
|
// ---- 错题复习 ----
|
|
export const reviewApi = {
|
|
list: (query?: QueryOf<'/api/review/list', 'get'>) =>
|
|
unwrap(apiClient.GET('/api/review/list', { params: { query } })),
|
|
submit: (id: string, answer: string) =>
|
|
unwrap(
|
|
apiClient.POST('/api/review/{id}/submit', {
|
|
params: { path: { id } },
|
|
body: { answer } as BodyOf<'/api/review/{id}/submit', 'post'>
|
|
})
|
|
),
|
|
markMastered: (id: string) =>
|
|
unwrap(apiClient.POST('/api/review/{id}/mark-mastered', { params: { path: { id } } }))
|
|
}
|
|
|
|
// ---- 备考计划 ----
|
|
export const plansApi = {
|
|
today: (date?: string) => unwrap(apiClient.GET('/api/plans/today', { params: { query: { date } } })),
|
|
week: (start?: string) => unwrap(apiClient.GET('/api/plans/week', { params: { query: { start } } })),
|
|
createTask: (body: BodyOf<'/api/plans/tasks', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/plans/tasks', { body })),
|
|
toggleTask: (id: string) =>
|
|
unwrap(apiClient.PATCH('/api/plans/tasks/{id}/toggle', { params: { path: { id } } })),
|
|
review: () => unwrap(apiClient.GET('/api/plans/review'))
|
|
}
|
|
|
|
// ---- 模考 ----
|
|
export const mockApi = {
|
|
analysis: () => unwrap(apiClient.GET('/api/mock-exams/analysis')),
|
|
record: (body: BodyOf<'/api/mock-exams/record', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/mock-exams/record', { body }))
|
|
}
|
|
|
|
// ---- 要闻 ----
|
|
export const newsApi = {
|
|
list: (query?: QueryOf<'/api/news/list', 'get'>) =>
|
|
unwrap(apiClient.GET('/api/news/list', { params: { query } })),
|
|
detail: (id: string) => unwrap(apiClient.GET('/api/news/{id}', { params: { path: { id } } })),
|
|
importJson: (body: BodyOf<'/api/news/import/json', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/news/import/json', { body })),
|
|
importRss: (body: BodyOf<'/api/news/import/rss', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/news/import/rss', { body })),
|
|
importApi: (body: BodyOf<'/api/news/import/api', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/news/import/api', { body })),
|
|
importUrl: (body: BodyOf<'/api/news/import/url', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/news/import/url', { body }))
|
|
}
|
|
|
|
// ---- 题库管理 ----
|
|
export const questionsApi = {
|
|
list: (query?: QueryOf<'/api/questions/list', 'get'>) =>
|
|
unwrap(apiClient.GET('/api/questions/list', { params: { query } })),
|
|
importQuestions: (body: BodyOf<'/api/questions/import', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/questions/import', { body })),
|
|
exportQuestions: () => unwrap(apiClient.GET('/api/questions/export')),
|
|
remove: (id: string) => unwrap(apiClient.DELETE('/api/questions/{id}', { params: { path: { id } } }))
|
|
}
|
|
|
|
// ---- AI 讲解 ----
|
|
export const aiApi = {
|
|
explain: (body: BodyOf<'/api/ai/explain-question', 'post'>) =>
|
|
unwrap(apiClient.POST('/api/ai/explain-question', { body }))
|
|
}
|
|
|
|
// ---- 个人档案 / 设置 ----
|
|
export const profileApi = {
|
|
get: () => unwrap(apiClient.GET('/api/profile')),
|
|
patch: (body: BodyOf<'/api/profile', 'patch'>) =>
|
|
unwrap(apiClient.PATCH('/api/profile', { body }))
|
|
}
|
|
|
|
export const settingsApi = {
|
|
get: () => unwrap(apiClient.GET('/api/settings')),
|
|
patch: (body: BodyOf<'/api/settings', 'patch'>) =>
|
|
unwrap(apiClient.PATCH('/api/settings', { body }))
|
|
}
|