Files
webpreview/src/api.ts
yuetsh ecce21aaaf
Some checks failed
Deploy / deploy (build, debian, 22) (push) Has been cancelled
Deploy / deploy (build:staging, school, 8822) (push) Has been cancelled
ramove rank
2026-03-29 10:07:27 -06:00

260 lines
6.1 KiB
TypeScript

import axios from "axios"
import { router } from "./router"
import type {
TutorialIn,
ChallengeIn,
FlagType,
SubmissionOut,
PromptMessage,
TaskStatsOut,
} from "./utils/type"
import { BASE_URL, STORAGE_KEY } from "./utils/const"
const http = axios.create({
baseURL: BASE_URL,
xsrfCookieName: "xsrfCookieName",
xsrfHeaderName: "X-CSRFTOKEN",
withCredentials: true,
})
http.interceptors.response.use(
(res) => {
return res
},
(err) => {
if (err.response) {
switch (err.response.status) {
case 401: // 未授权
localStorage.removeItem(STORAGE_KEY.LOGIN)
router.push("/")
break
case 403: // 禁止访问
alert("权限不够,禁止访问")
router.push("/")
break
default:
console.error("出现错误:", err.response.status, err.response.data)
}
} else {
console.error("出现错误:", err.message)
}
return Promise.reject(err)
},
)
export const Account = {
async login(username: string, password: string) {
const res = await http.post("/account/login", { username, password })
return res.data
},
async logout() {
const res = await http.post("/account/logout")
return res.data
},
async getMyProfile() {
const res = await http.get("/account/profile")
return res.data
},
async list(query: { username: string; page: number }) {
const res = await http.get("/account/list", {
params: query,
})
return res.data
},
async toggleActive(id: number) {
const res = await http.put(`/account/active/${id}`)
return res.data
},
async batchCreate(payload: { classname: string; names: string[] }) {
const res = await http.post("/account/batch", payload)
return res.data
},
async listClasses(): Promise<string[]> {
const res = await http.get("/account/classes")
return res.data
},
async listNamesByClass(
classname: string,
): Promise<{ name: string; username: string }[]> {
const res = await http.get("/account/names", { params: { classname } })
return res.data
},
}
export const Tutorial = {
async list() {
const res = await http.get("/tutorial/list")
return res.data
},
async createOrUpdate(payload: TutorialIn) {
const res = await http.post("/tutorial/", payload)
return res.data
},
async togglePublic(display: number) {
const res = await http.put(`/tutorial/public/${display}`)
return res.data
},
async remove(display: number) {
await http.delete(`/tutorial/${display}`)
},
async get(display: number) {
const res = await http.get(`/tutorial/${display}`)
return res.data
},
async listDisplay() {
const res = await http.get("/tutorial/display")
return res.data
},
}
export const Challenge = {
async list() {
const res = await http.get("/challenge/list")
return res.data
},
async createOrUpdate(payload: ChallengeIn) {
const res = await http.post("/challenge/", payload)
return res.data
},
async togglePublic(display: number) {
const res = await http.put(`/challenge/public/${display}`)
return res.data
},
async remove(display: number) {
await http.delete(`/challenge/${display}`)
},
async get(display: number) {
const res = await http.get(`/challenge/${display}`)
return res.data
},
async listDisplay() {
const res = await http.get("/challenge/display")
return res.data
},
}
export const Submission = {
async create(
taskId: number,
code: {
html?: string
css?: string
js?: string
conversationId?: string
},
) {
const { conversationId, ...rest } = code
const data = {
task_id: taskId,
...rest,
conversation_id: conversationId || null,
}
const res = await http.post("/submission/", data)
return res.data
},
async list(query: {
page: number
page_size?: number
username?: string
user_id?: number
flag?: string | null
task_id?: number
task_type?: string
score_min?: number
score_max_exclusive?: number
score_lt_threshold?: number
ordering?: string
grouped?: boolean
}) {
const res = await http.get("/submission", {
params: query,
})
return res.data
},
async listByUserTask(userId: number, taskId: number) {
const res = await http.get("/submission/by-user-task", {
params: { user_id: userId, task_id: taskId },
})
return res.data as SubmissionOut[]
},
async get(id: string) {
const res = await http.get("/submission/" + id)
return res.data
},
async delete(id: string) {
const res = await http.delete("/submission/" + id)
return res.data
},
async updateScore(id: string, score: number) {
const res = await http.put(`/submission/${id}/score`, { score })
return res.data
},
async updateFlag(id: string, flag: FlagType) {
const res = await http.put(`/submission/${id}/flag`, { flag })
return res.data
},
async clearAllFlags() {
const res = await http.delete(`/submission/flags`)
return res.data as { cleared: number }
},
async getStats(taskId: number, classname?: string): Promise<TaskStatsOut> {
const params: Record<string, string | number> = {}
if (classname) params.classname = classname
const res = await http.get(`/submission/stats/${taskId}`, { params })
return res.data as TaskStatsOut
},
}
export const Prompt = {
async listConversations(taskId?: number, userId?: number) {
const params: Record<string, number> = {}
if (taskId) params.task_id = taskId
if (userId) params.user_id = userId
return (await http.get("/prompt/conversations/", { params })).data
},
async getMessages(conversationId: string): Promise<PromptMessage[]> {
return (
await http.get<PromptMessage[]>(
`/prompt/conversations/${conversationId}/messages/`,
)
).data
},
}
export const Helper = {
async upload(file: File) {
const form = new window.FormData()
form.append("image", file)
const res = await http.post("/upload/", form, {
headers: { "content-type": "multipart/form-data" },
})
return !!res.data.url ? res.data.url : ""
},
}