refactor(前端): 去掉 { error, data } 信封,api2 改名 api
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
信封是 Django 时代的形状:拦截器手工造一个**恒为 null** 的 error 字段,再把
真正的载荷塞进 data。后端 http.ts 的 success 其实只返回 { data },那个 error
从头到尾没人用 —— 全站成功路径读 res.error 的只有 admin/api.ts 的
resetPassword 一处,而它自己就是个把信封拆开再重新包一遍的 shim。
代价是每个调用点都要 .data 一次:47 个组件、3 个 api 层文件、200 多处。
现在拦截器直接返回 response.data.data,ApiResponse<T> 退化成 T,文件末尾那句
`as unknown as Api2Client` 的类型谎言也少了一层。失败路径不动,仍然 reject
`{ error: 错误码, data: 文案 }` —— 和成功路径不对称是故意的,成功没有错误码
可言,接口注释里写清楚了。
顺带把 api2 改回 api:utils/ 下早就没有 api.ts 了,"2" 是迁移期用来和旧
client 区分的,现在只剩下让人多想一秒的作用。
## 怎么改的
**没有全局 sed。** 先把客户端的返回类型从 Promise<ApiResponse<T>> 改成
Promise<T>,让 vue-tsc 把每一处报出来(210 条),再按它给的 file:line:col
精确删 `.data`(192 处),剩下的手工处理:
- 6 处 `const { data } = await ...` 解构 → `const data = await ...`
- 3 个 api 层函数(getProfile / getProblem / getSubmission)自己手工造信封,
改成直接返回值;getProfile 的返回类型跟着从 ApiResponse<Profile|null>
变成 Profile|null
**类型检查抓不到的,人工把剩下的每一处 `.data` 过了一遍** —— 载荷本身带
data 字段、或者载荷是索引签名时,`res.data` 照样过类型。这一遍捞出三条真 bug:
- `getTutorialList` 的载荷是 `{ [key: string]: TutorialListItem[] }`(按
python / c 分组)。索引签名让 `res.data` 编译通过、运行时是 undefined ——
改完信封之后教程列表会**两个 tab 全空且不报错**。实跑确认过修好了。
- `createExercise` / `updateExercise` 返回 `res.data`,而 Exercise 自己有
data 字段(练习内容)。两个调用方都不看返回值,所以类型和运行时都不响。
- `getSimilarProblems` 的 `.then(r => ({ ...r, data: r.data.map(...) }))`
删掉 .data 之后变成往对象里摊一个数组,能跑但形状是错的。
另外两处是**对的**,加了注释免得下次被"顺手清理"掉:
StatisticsPanel 的 `res.data` 是契约 submissionStatisticsSchema 自己的 data
字段(每个学生一行);download.ts 是独立 axios 实例,`res.data` 是 axios 的
响应体(zip 二进制,不走信封)。
## 验证
tsc(apps/api) 0 error、check:routes 168 条无遮蔽、vue-tsc 0 error、vite build
通过。**因为这改动碰的是每一个请求,静态检查不够,起了全套服务用浏览器实跑:**
- oj 侧 12 个页面 + 后台 13 个页面逐个打开,断言没有重定向、console 无报错。
- 关键页面进一步断言渲染出了真数据(后台用户列表 3 行、题目列表 10 行、
站点配置表单三个输入框有值、教程列表分组正确)。
- 三条写路径实打:重置密码(库里 student123 → 531554,表格当场刷新)、
公告可见性开关(走 getAnnouncement + editAnnouncement,就是手改解构那处,
库里 visible t → f)、提交代码(POST → 判题机真跑出 -2 → 提交列表和详情页
都正确渲染状态、语言、代码)。
- /rank 有一条 `{error: "class-missing"}` 的未捕获 reject,stash 掉本次改动
复现同样报错,**是既有问题**,不在本次范围内。
本地 dev 库为了打通后台测试改了三处,都只影响本机:devadmin 补了 email 和
user_profile 行(原来缺这两样,getProfile 报 profile-not-found,AUTHED 存不
进去,所有 /admin 路由被守卫弹回首页)、密码重置成 devpass123。冒烟用的教程/
公告/提交三条测试数据已删干净,题目和用户的提交计数也回滚了。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import api2 from "utils/api2"
|
||||
import api from "utils/api"
|
||||
import type {
|
||||
AchievementList,
|
||||
AchievementSummary,
|
||||
@@ -6,21 +6,21 @@ import type {
|
||||
} from "utils/types"
|
||||
|
||||
export function getAchievements(name?: string) {
|
||||
return api2.get<AchievementList>("achievements", {
|
||||
return api.get<AchievementList>("achievements", {
|
||||
params: name ? { username: name } : {},
|
||||
})
|
||||
}
|
||||
|
||||
export function getAchievementSummary(name?: string) {
|
||||
return api2.get<AchievementSummary>("achievements/summary", {
|
||||
return api.get<AchievementSummary>("achievements/summary", {
|
||||
params: name ? { username: name } : {},
|
||||
})
|
||||
}
|
||||
|
||||
export function getPendingAchievements() {
|
||||
return api2.get<PendingAchievement[]>("achievements/pending")
|
||||
return api.get<PendingAchievement[]>("achievements/pending")
|
||||
}
|
||||
|
||||
export function markAchievementsRead(ids: number[]) {
|
||||
return api2.post("achievements/pending/read", { ids })
|
||||
return api.post("achievements/pending/read", { ids })
|
||||
}
|
||||
|
||||
@@ -54,10 +54,9 @@ async function load() {
|
||||
getAchievementSummary(name.value),
|
||||
getUserBadges(name.value),
|
||||
])
|
||||
// http 客户端返回 ApiResponse<T>,真实载荷在 .data 里
|
||||
achievements.value = list.data.achievements
|
||||
summary.value = sum.data
|
||||
badges.value = badgeRes.data ?? []
|
||||
achievements.value = list.achievements
|
||||
summary.value = sum
|
||||
badges.value = badgeRes ?? []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
@@ -56,15 +56,15 @@ async function showContent(announcement: Announcement) {
|
||||
const res = await getAnnouncement(announcement.id)
|
||||
toggleShow(true)
|
||||
title.value = announcement.title
|
||||
content.value = res.data.content
|
||||
content.value = res.content
|
||||
}
|
||||
const announcements = ref<Announcement[]>([])
|
||||
|
||||
async function listAnnouncements() {
|
||||
const offset = (query.page - 1) * query.limit
|
||||
const res = await getAnnouncementList(offset, query.limit)
|
||||
total.value = res.data.total
|
||||
announcements.value = res.data.results
|
||||
total.value = res.total
|
||||
announcements.value = res.results
|
||||
}
|
||||
|
||||
onMounted(listAnnouncements)
|
||||
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
type FlowchartStatistics,
|
||||
type SubmissionStatistics,
|
||||
} from "@oj2/contract"
|
||||
import api2 from "utils/api2"
|
||||
import api from "utils/api"
|
||||
import { filterResult } from "oj/transforms"
|
||||
import type {
|
||||
Announcement,
|
||||
@@ -65,7 +65,7 @@ function detailProblem(value: unknown): Problem {
|
||||
}
|
||||
|
||||
export function getWebsiteConfig() {
|
||||
return api2.get<WebsiteConfig>("site")
|
||||
return api.get<WebsiteConfig>("site")
|
||||
}
|
||||
|
||||
export async function getProblemList(
|
||||
@@ -73,17 +73,17 @@ export async function getProblemList(
|
||||
limit = 10,
|
||||
searchParams: Record<string, unknown> = {},
|
||||
) {
|
||||
const res = await api2.get<ProblemList>("problems", {
|
||||
const res = await api.get<ProblemList>("problems", {
|
||||
params: { paging: true, offset, limit, ...searchParams },
|
||||
})
|
||||
return {
|
||||
results: res.data.results.map(filterResult),
|
||||
total: res.data.total,
|
||||
results: res.results.map(filterResult),
|
||||
total: res.total,
|
||||
}
|
||||
}
|
||||
|
||||
export function getAuthors(all = false) {
|
||||
return api2.get<ProblemAuthor[]>("problem-authors", {
|
||||
return api.get<ProblemAuthor[]>("problem-authors", {
|
||||
params: { all: all ? "1" : "0" },
|
||||
})
|
||||
}
|
||||
@@ -92,27 +92,23 @@ export async function getProblem(problemID: string, contestID: string) {
|
||||
const endpoint = contestID
|
||||
? `contests/${encodeURIComponent(contestID)}/problems/${encodeURIComponent(problemID)}`
|
||||
: `problems/${encodeURIComponent(problemID)}`
|
||||
const response = await api2.get<unknown>(endpoint)
|
||||
return { error: null, data: detailProblem(response.data) }
|
||||
return detailProblem(await api.get<unknown>(endpoint))
|
||||
}
|
||||
|
||||
// 未登录返回 "0",登录后返回百分比字符串
|
||||
export function getProblemBeatRate(problemID: number) {
|
||||
return api2.get<string>(`problems/${problemID}/beat-count`)
|
||||
return api.get<string>(`problems/${problemID}/beat-count`)
|
||||
}
|
||||
|
||||
export async function getSubmission(id: string) {
|
||||
const response = await api2.get<unknown>(
|
||||
const response = await api.get<unknown>(
|
||||
`submissions/${encodeURIComponent(id)}`,
|
||||
)
|
||||
return {
|
||||
error: null,
|
||||
data: submissionDetailSchema.parse(response.data) as Submission,
|
||||
}
|
||||
return submissionDetailSchema.parse(response) as Submission
|
||||
}
|
||||
|
||||
export function submitCode(data: SubmitCodePayload) {
|
||||
return api2.post<CreateSubmissionResponse>("submissions", data)
|
||||
return api.post<CreateSubmissionResponse>("submissions", data)
|
||||
}
|
||||
|
||||
export function formatCode(data: { code: string; language: string }) {
|
||||
@@ -122,7 +118,7 @@ export function formatCode(data: { code: string; language: string }) {
|
||||
"C++": "cpp",
|
||||
SQL: "sql",
|
||||
}
|
||||
return api2.post<FormatCodeResponse>("code/format", {
|
||||
return api.post<FormatCodeResponse>("code/format", {
|
||||
code: data.code,
|
||||
language: languages[data.language] ?? data.language.toLowerCase(),
|
||||
})
|
||||
@@ -134,22 +130,22 @@ export function getSubmissions(params: Partial<SubmissionListPayload>) {
|
||||
: "submissions"
|
||||
// 契约里 language 是 z.string()(语言是配置项,随时可能加,收紧成枚举会让
|
||||
// 新加的语言在后端 parse 时直接抛),前端在这一处收窄成 LANGUAGE
|
||||
return api2.get<{ results: SubmissionListItem[]; total: number }>(endpoint, {
|
||||
return api.get<{ results: SubmissionListItem[]; total: number }>(endpoint, {
|
||||
// contestId 走的是路径,page 只有前端分页器用
|
||||
params: { ...params, contestId: undefined, page: undefined },
|
||||
})
|
||||
}
|
||||
|
||||
export function getRankOfProblem(problemId: string) {
|
||||
return api2.get<ProblemRank>(`problems/${encodeURIComponent(problemId)}/rank`)
|
||||
return api.get<ProblemRank>(`problems/${encodeURIComponent(problemId)}/rank`)
|
||||
}
|
||||
|
||||
export function getTodaySubmissionCount(language?: string) {
|
||||
return api2.get<number>("submissions/today-count", { params: { language } })
|
||||
return api.get<number>("submissions/today-count", { params: { language } })
|
||||
}
|
||||
|
||||
export function adminRejudge(id: string) {
|
||||
return api2.post<{ ok: boolean }>(
|
||||
return api.post<{ ok: boolean }>(
|
||||
`submissions/${encodeURIComponent(id)}/rejudge`,
|
||||
)
|
||||
}
|
||||
@@ -159,7 +155,7 @@ export function getSubmissionStatistics(
|
||||
problemID?: string,
|
||||
username?: string,
|
||||
) {
|
||||
return api2.get<SubmissionStatistics>("submissions/statistics", {
|
||||
return api.get<SubmissionStatistics>("submissions/statistics", {
|
||||
params: { ...duration, problemId: problemID, username },
|
||||
})
|
||||
}
|
||||
@@ -169,17 +165,17 @@ export function getSubmissionStatistics(
|
||||
* 「全服 Top10」就是这个榜的第一页,取 limit=10 即可,不需要另一个上限参数。
|
||||
*/
|
||||
export function getRank(offset: number, limit: number) {
|
||||
return api2.get<UserRank>("rankings/users", { params: { offset, limit } })
|
||||
return api.get<UserRank>("rankings/users", { params: { offset, limit } })
|
||||
}
|
||||
|
||||
export function getActivityRank(start: string) {
|
||||
return api2.get<ActivityRankItem[]>("rankings/activity", {
|
||||
return api.get<ActivityRankItem[]>("rankings/activity", {
|
||||
params: { start },
|
||||
})
|
||||
}
|
||||
|
||||
export function getClassRank(grade?: number | null) {
|
||||
return api2.get<ClassRankItem[]>("rankings/classes", { params: { grade } })
|
||||
return api.get<ClassRankItem[]>("rankings/classes", { params: { grade } })
|
||||
}
|
||||
|
||||
export function getUserClassRank(
|
||||
@@ -187,7 +183,7 @@ export function getUserClassRank(
|
||||
offset?: number,
|
||||
limit?: number,
|
||||
) {
|
||||
return api2.get<ClassUserRank>("me/class-rank", {
|
||||
return api.get<ClassUserRank>("me/class-rank", {
|
||||
params: { scope, offset, limit },
|
||||
})
|
||||
}
|
||||
@@ -197,7 +193,7 @@ export function getClassPK(
|
||||
startTime?: string,
|
||||
endTime?: string,
|
||||
) {
|
||||
return api2.post<ClassComparisonResponse>("classes/comparison", {
|
||||
return api.post<ClassComparisonResponse>("classes/comparison", {
|
||||
classNames,
|
||||
...(startTime ? { startTime } : {}),
|
||||
...(endTime ? { endTime } : {}),
|
||||
@@ -211,20 +207,20 @@ export function getContestList(query: {
|
||||
status: string
|
||||
tag: string
|
||||
}) {
|
||||
return api2.get<ContestList>("contests", { params: query })
|
||||
return api.get<ContestList>("contests", { params: query })
|
||||
}
|
||||
|
||||
export function getContest(id: string) {
|
||||
return api2.get<OjContest>(`contests/${encodeURIComponent(id)}`)
|
||||
return api.get<OjContest>(`contests/${encodeURIComponent(id)}`)
|
||||
}
|
||||
|
||||
export function getContestAccess(id: string) {
|
||||
return api2.get<ContestAccess>(`contests/${encodeURIComponent(id)}/access`)
|
||||
return api.get<ContestAccess>(`contests/${encodeURIComponent(id)}/access`)
|
||||
}
|
||||
|
||||
// 注意和 GET /access 不一样:这个返回裸 true,密码错是 403 走 catch
|
||||
export function checkContestPassword(contestID: string, password: string) {
|
||||
return api2.post<boolean>(
|
||||
return api.post<boolean>(
|
||||
`contests/${encodeURIComponent(contestID)}/access`,
|
||||
{
|
||||
password,
|
||||
@@ -233,10 +229,10 @@ export function checkContestPassword(contestID: string, password: string) {
|
||||
}
|
||||
|
||||
export async function getContestProblems(contestID: string) {
|
||||
const res = await api2.get<ProblemListItem[]>(
|
||||
const res = await api.get<ProblemListItem[]>(
|
||||
`contests/${encodeURIComponent(contestID)}/problems`,
|
||||
)
|
||||
return res.data.map(filterResult)
|
||||
return res.map(filterResult)
|
||||
}
|
||||
|
||||
export function getContestRank(
|
||||
@@ -245,7 +241,7 @@ export function getContestRank(
|
||||
) {
|
||||
// submissionInfo 在契约里是 Record<string, unknown>(JSONB 原文),
|
||||
// 前端在这里收窄成 SubmissionInfo,见 utils/types 的 ContestRank
|
||||
return api2.get<{ results: ContestRank[]; total: number }>(
|
||||
return api.get<{ results: ContestRank[]; total: number }>(
|
||||
`contests/${encodeURIComponent(contestID)}/rank`,
|
||||
{ params: query },
|
||||
)
|
||||
@@ -254,23 +250,23 @@ export function getContestRank(
|
||||
export function uploadAvatar(file: File) {
|
||||
const form = new window.FormData()
|
||||
form.append("image", file)
|
||||
return api2.post("me/avatar", form, {
|
||||
return api.post("me/avatar", form, {
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
})
|
||||
}
|
||||
|
||||
export function updateProfile(data: { realName: string; mood: string }) {
|
||||
return api2.put<Profile>("me/profile", data)
|
||||
return api.put<Profile>("me/profile", data)
|
||||
}
|
||||
|
||||
export function getAnnouncementList(offset = 0, limit = 10) {
|
||||
return api2.get<{ results: Announcement[]; total: number }>("announcements", {
|
||||
return api.get<{ results: Announcement[]; total: number }>("announcements", {
|
||||
params: { limit, offset },
|
||||
})
|
||||
}
|
||||
|
||||
export function getAnnouncement(id: number) {
|
||||
return api2.get<Announcement>(`announcements/${id}`)
|
||||
return api.get<Announcement>(`announcements/${id}`)
|
||||
}
|
||||
|
||||
export function createMessage(data: {
|
||||
@@ -278,7 +274,7 @@ export function createMessage(data: {
|
||||
message: string
|
||||
submission: string
|
||||
}) {
|
||||
return api2.post("messages", {
|
||||
return api.post("messages", {
|
||||
recipientId: data.recipient,
|
||||
message: data.message,
|
||||
submissionId: data.submission,
|
||||
@@ -287,33 +283,33 @@ export function createMessage(data: {
|
||||
|
||||
export function getMessageList(offset = 0, limit = 10) {
|
||||
// language 的收窄同 getSubmissions,见那里的说明
|
||||
return api2.get<{ results: Message[]; total: number }>("messages", {
|
||||
return api.get<{ results: Message[]; total: number }>("messages", {
|
||||
params: { limit, offset },
|
||||
})
|
||||
}
|
||||
|
||||
export function getReaction(problemID: number) {
|
||||
return api2.get<ReactionState>(`problems/${problemID}/reaction`)
|
||||
return api.get<ReactionState>(`problems/${problemID}/reaction`)
|
||||
}
|
||||
|
||||
export function setReaction(problemID: number, type: ReactionKey) {
|
||||
return api2.post<ReactionState>(`problems/${problemID}/reaction`, { type })
|
||||
return api.post<ReactionState>(`problems/${problemID}/reaction`, { type })
|
||||
}
|
||||
|
||||
export function getMetrics(userid: number) {
|
||||
return api2.get<Metrics>(`users/${userid}/metrics`)
|
||||
return api.get<Metrics>(`users/${userid}/metrics`)
|
||||
}
|
||||
|
||||
export function getTutorial(id: number) {
|
||||
return api2.get<Tutorial>(`tutorials/${id}`)
|
||||
return api.get<Tutorial>(`tutorials/${id}`)
|
||||
}
|
||||
|
||||
export function getTutorials(type: "python" | "c") {
|
||||
return api2.get<TutorialSummary[]>("tutorials", { params: { type } })
|
||||
return api.get<TutorialSummary[]>("tutorials", { params: { type } })
|
||||
}
|
||||
|
||||
export function getAIDetailData(start: string, end: string, username?: string) {
|
||||
return api2.get<AiDetail>("ai/detail", { params: { start, end, username } })
|
||||
return api.get<AiDetail>("ai/detail", { params: { start, end, username } })
|
||||
}
|
||||
|
||||
export function getAIDurationData(
|
||||
@@ -321,40 +317,37 @@ export function getAIDurationData(
|
||||
duration: string,
|
||||
username?: string,
|
||||
) {
|
||||
return api2.get<DurationData[]>("ai/duration", {
|
||||
return api.get<DurationData[]>("ai/duration", {
|
||||
params: { end, duration, username },
|
||||
})
|
||||
}
|
||||
|
||||
export function getAIHeatmapData(username?: string) {
|
||||
return api2.get<HeatmapItem[]>("ai/heatmap", {
|
||||
return api.get<HeatmapItem[]>("ai/heatmap", {
|
||||
params: username ? { username } : {},
|
||||
})
|
||||
}
|
||||
|
||||
export function getAILoginSummary() {
|
||||
return api2.get<LoginSummary>("ai/login-summary")
|
||||
return api.get<LoginSummary>("ai/login-summary")
|
||||
}
|
||||
|
||||
export function getAIPinnedReport() {
|
||||
return api2.get<AiAnalysisRecord | null>("ai/pinned")
|
||||
return api.get<AiAnalysisRecord | null>("ai/pinned")
|
||||
}
|
||||
|
||||
// ==================== 相似题目推荐 ====================
|
||||
|
||||
export function getSimilarProblems(problemId: string) {
|
||||
return api2
|
||||
return api
|
||||
.get<ProblemListItem[]>(`problems/${encodeURIComponent(problemId)}/similar`)
|
||||
.then((response) => ({
|
||||
...response,
|
||||
data: response.data.map(filterResult),
|
||||
}))
|
||||
.then((response) => response.map(filterResult))
|
||||
}
|
||||
|
||||
export type { YearlyAc as YearlyACData } from "@oj2/contract"
|
||||
|
||||
export function getProblemYearlyAC(problemId: string) {
|
||||
return api2.get<YearlyAc[]>(
|
||||
return api.get<YearlyAc[]>(
|
||||
`problems/${encodeURIComponent(problemId)}/yearly-ac`,
|
||||
)
|
||||
}
|
||||
@@ -366,11 +359,11 @@ export function submitFlowchart(data: {
|
||||
mermaidCode: string
|
||||
flowchartData: Record<string, unknown> // 压缩之后的,元数据太长了
|
||||
}) {
|
||||
return api2.post<CreateFlowchartResponse>("flowcharts", data)
|
||||
return api.post<CreateFlowchartResponse>("flowcharts", data)
|
||||
}
|
||||
|
||||
export function getFlowchartSubmission(id: string) {
|
||||
return api2.get<FlowchartSubmission>(`flowcharts/${encodeURIComponent(id)}`)
|
||||
return api.get<FlowchartSubmission>(`flowcharts/${encodeURIComponent(id)}`)
|
||||
}
|
||||
|
||||
export function getFlowchartSubmissions(params: {
|
||||
@@ -382,7 +375,7 @@ export function getFlowchartSubmissions(params: {
|
||||
today?: string
|
||||
grade?: string
|
||||
}) {
|
||||
return api2.get<FlowchartList>("flowcharts", { params })
|
||||
return api.get<FlowchartList>("flowcharts", { params })
|
||||
}
|
||||
|
||||
export function getFlowchartStatistics(
|
||||
@@ -390,23 +383,23 @@ export function getFlowchartStatistics(
|
||||
problemID?: string,
|
||||
username?: string,
|
||||
) {
|
||||
return api2.get<FlowchartStatistics>("flowcharts/statistics", {
|
||||
return api.get<FlowchartStatistics>("flowcharts/statistics", {
|
||||
params: { ...duration, problemId: problemID, username },
|
||||
})
|
||||
}
|
||||
|
||||
export function retryFlowchartSubmission(submissionId: string) {
|
||||
return api2.post<{ status: string }>(
|
||||
return api.post<{ status: string }>(
|
||||
`flowcharts/${encodeURIComponent(submissionId)}/retry`,
|
||||
)
|
||||
}
|
||||
|
||||
export function getCurrentProblemFlowchartSubmission(problemId: number) {
|
||||
return api2.get<FlowchartCurrent>(`problems/${problemId}/flowchart/current`)
|
||||
return api.get<FlowchartCurrent>(`problems/${problemId}/flowchart/current`)
|
||||
}
|
||||
|
||||
export function getFlowchartSubmissionDetail(problemId: number, page = 0) {
|
||||
return api2.get<FlowchartDetail>(`problems/${problemId}/flowchart/history`, {
|
||||
return api.get<FlowchartDetail>(`problems/${problemId}/flowchart/history`, {
|
||||
params: { page },
|
||||
})
|
||||
}
|
||||
@@ -420,21 +413,21 @@ export function getProblemSetList(
|
||||
difficulty = "",
|
||||
status = "",
|
||||
) {
|
||||
return api2.get<ProblemSetList>("problem-sets", {
|
||||
return api.get<ProblemSetList>("problem-sets", {
|
||||
params: { offset, limit, keyword, difficulty, status },
|
||||
})
|
||||
}
|
||||
|
||||
export function getProblemSetDetail(id: number) {
|
||||
return api2.get<ProblemSet>(`problem-sets/${id}`)
|
||||
return api.get<ProblemSet>(`problem-sets/${id}`)
|
||||
}
|
||||
|
||||
export function getProblemSetProblems(problemSetId: number) {
|
||||
return api2.get<ProblemSetProblem[]>(`problem-sets/${problemSetId}/problems`)
|
||||
return api.get<ProblemSetProblem[]>(`problem-sets/${problemSetId}/problems`)
|
||||
}
|
||||
|
||||
export function joinProblemSet(problemSetId: number) {
|
||||
return api2.post("problem-set-progress", { problemSetId })
|
||||
return api.post("problem-set-progress", { problemSetId })
|
||||
}
|
||||
|
||||
export function updateProblemSetProgress(
|
||||
@@ -442,7 +435,7 @@ export function updateProblemSetProgress(
|
||||
problemId: number,
|
||||
submissionId: string,
|
||||
) {
|
||||
return api2.put("problem-set-progress", {
|
||||
return api.put("problem-set-progress", {
|
||||
problemSetId,
|
||||
problemId,
|
||||
submissionId,
|
||||
@@ -450,13 +443,13 @@ export function updateProblemSetProgress(
|
||||
}
|
||||
|
||||
export function getUserBadges(username?: string) {
|
||||
return api2.get<UserBadge[]>(
|
||||
return api.get<UserBadge[]>(
|
||||
`users/${encodeURIComponent(username ?? "me")}/badges`,
|
||||
)
|
||||
}
|
||||
|
||||
export function getProblemSetBadges(problemSetId: number) {
|
||||
return api2.get<ProblemSetBadge[]>(`problem-sets/${problemSetId}/badges`)
|
||||
return api.get<ProblemSetBadge[]>(`problem-sets/${problemSetId}/badges`)
|
||||
}
|
||||
|
||||
export function getProblemSetUserProgress(
|
||||
@@ -468,13 +461,12 @@ export function getProblemSetUserProgress(
|
||||
completionStatus?: "" | "completed" | "in_progress" | "not_started"
|
||||
},
|
||||
) {
|
||||
return api2.get<ProblemSetProgressList>(
|
||||
return api.get<ProblemSetProgressList>(
|
||||
`problem-sets/${problemSetId}/user-progress`,
|
||||
{ params },
|
||||
)
|
||||
}
|
||||
|
||||
export async function getExercises(tutorialId: number): Promise<Exercise[]> {
|
||||
const res = await api2.get<Exercise[]>(`tutorials/${tutorialId}/exercises`)
|
||||
return res.data
|
||||
export function getExercises(tutorialId: number): Promise<Exercise[]> {
|
||||
return api.get<Exercise[]>(`tutorials/${tutorialId}/exercises`)
|
||||
}
|
||||
|
||||
@@ -122,8 +122,8 @@ async function compare() {
|
||||
const { startTime, endTime } = getTimeRange()
|
||||
|
||||
const res = await getClassPK(selectedClasses.value, startTime, endTime)
|
||||
comparisons.value = res.data.comparisons
|
||||
hasTimeRange.value = res.data.hasTimeRange || false
|
||||
comparisons.value = res.comparisons
|
||||
hasTimeRange.value = res.hasTimeRange || false
|
||||
} catch (error) {
|
||||
message.error("获取数据失败")
|
||||
} finally {
|
||||
|
||||
@@ -93,8 +93,8 @@ async function listContests() {
|
||||
status: query.status,
|
||||
tag: query.tag,
|
||||
})
|
||||
data.value = res.data.results
|
||||
total.value = res.data.total
|
||||
data.value = res.results
|
||||
total.value = res.total
|
||||
}
|
||||
|
||||
function search(value: string) {
|
||||
|
||||
@@ -96,8 +96,8 @@ async function listRanks() {
|
||||
limit: query.limit,
|
||||
offset: query.limit * (query.page - 1),
|
||||
})
|
||||
total.value = res.data.total
|
||||
data.value = res.data.results
|
||||
total.value = res.total
|
||||
data.value = res.results
|
||||
if (query.page === 1) {
|
||||
chart.value = data.value
|
||||
}
|
||||
@@ -225,7 +225,7 @@ async function downloadExcel() {
|
||||
limit: total.value || 10000,
|
||||
offset: 0,
|
||||
})
|
||||
const allRanks: ContestRank[] = res.data.results
|
||||
const allRanks: ContestRank[] = res.results
|
||||
|
||||
const rows = allRanks.map((rank, index) => {
|
||||
const rank1 = index + 1
|
||||
|
||||
@@ -206,7 +206,7 @@ function goToNextLesson() {
|
||||
|
||||
async function init() {
|
||||
const res1 = await getTutorials(type.value)
|
||||
titles.value = res1.data
|
||||
titles.value = res1
|
||||
isEmpty.value = titles.value.length === 0
|
||||
if (isEmpty.value) return
|
||||
const id = titles.value[step.value - 1].id
|
||||
@@ -214,7 +214,7 @@ async function init() {
|
||||
getTutorial(id),
|
||||
getExercises(id),
|
||||
])
|
||||
if (res2.status === "fulfilled") tutorial.value = res2.value.data
|
||||
if (res2.status === "fulfilled") tutorial.value = res2.value
|
||||
exercises.value = exs.status === "fulfilled" ? exs.value : []
|
||||
learnStep.value[type.value] = step.value
|
||||
}
|
||||
|
||||
@@ -52,8 +52,7 @@ const similarLoaded = ref(false)
|
||||
async function loadSimilarProblems() {
|
||||
if (similarLoaded.value || !problem.value) return
|
||||
try {
|
||||
const res = await getSimilarProblems(problem.value._id)
|
||||
similarProblems.value = res.data || []
|
||||
similarProblems.value = await getSimilarProblems(problem.value._id)
|
||||
} catch {
|
||||
similarProblems.value = []
|
||||
}
|
||||
|
||||
@@ -91,12 +91,12 @@ const options = {
|
||||
|
||||
async function getBeatRate() {
|
||||
const res = await getProblemBeatRate(problem.value!.id)
|
||||
beatRate.value = res.data
|
||||
beatRate.value = res
|
||||
}
|
||||
|
||||
async function getYearlyAC() {
|
||||
const res = await getProblemYearlyAC(problem.value!._id)
|
||||
yearlyACData.value = res.data
|
||||
yearlyACData.value = res
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -239,8 +239,8 @@ async function pick(key: ReactionKey) {
|
||||
submitting.value = key
|
||||
try {
|
||||
const res = await setReaction(problem.value.id, key)
|
||||
mine.value = res.data.mine
|
||||
counts.value = res.data.counts
|
||||
mine.value = res.mine
|
||||
counts.value = res.counts
|
||||
emit("submitted")
|
||||
} catch {
|
||||
message.error("提交失败,请重试")
|
||||
@@ -255,8 +255,8 @@ async function load(problemId: number) {
|
||||
try {
|
||||
const res = await getReaction(problemId)
|
||||
if (sequence !== loadSequence) return
|
||||
mine.value = res.data.mine
|
||||
counts.value = res.data.counts
|
||||
mine.value = res.mine
|
||||
counts.value = res.counts
|
||||
} catch {
|
||||
if (sequence === loadSequence) message.error("暂时无法读取题目点评")
|
||||
} finally {
|
||||
|
||||
@@ -129,8 +129,8 @@ async function listSubmissions() {
|
||||
problemId: (route.params.problemID as string) ?? "",
|
||||
contestId: (route.params.contestID as string) ?? "",
|
||||
})
|
||||
submissions.value = res.data.results
|
||||
total.value = res.data.total
|
||||
submissions.value = res.results
|
||||
total.value = res.total
|
||||
}
|
||||
|
||||
async function getRankOfThisProblem() {
|
||||
@@ -138,10 +138,10 @@ async function getRankOfThisProblem() {
|
||||
const res = await getRankOfProblem((route.params.problemID as string) ?? "")
|
||||
loading.value = false
|
||||
|
||||
class_name.value = res.data.className
|
||||
rank.value = res.data.rank
|
||||
class_ac_count.value = res.data.classAcCount
|
||||
all_ac_count.value = res.data.allAcCount
|
||||
class_name.value = res.className
|
||||
rank.value = res.rank
|
||||
class_ac_count.value = res.classAcCount
|
||||
all_ac_count.value = res.allAcCount
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -115,7 +115,7 @@ async function submit() {
|
||||
code: codeStore.code.value,
|
||||
language: formatLang,
|
||||
})
|
||||
codeStore.setCode(res.data.code)
|
||||
codeStore.setCode(res.code)
|
||||
} catch (e: any) {
|
||||
if (e?.error === "format-error") {
|
||||
// 仅 Python3 会出现:代码本身存在语法错误
|
||||
@@ -141,11 +141,11 @@ async function submit() {
|
||||
isSubmittingRequest.value = true
|
||||
try {
|
||||
const res = await submitCode(data)
|
||||
console.log(`[Submit] 代码已提交: ID=${res.data.submissionId}`)
|
||||
console.log(`[Submit] 代码已提交: ID=${res.submissionId}`)
|
||||
|
||||
// 3. 启动冷却 + 监控
|
||||
startCooldown()
|
||||
startMonitoring(res.data.submissionId)
|
||||
startMonitoring(res.submissionId)
|
||||
showResult.value = true
|
||||
} finally {
|
||||
isSubmittingRequest.value = false
|
||||
|
||||
@@ -144,7 +144,7 @@ async function submitFlowchartData() {
|
||||
})
|
||||
|
||||
// 获取提交ID并订阅更新
|
||||
const submissionId = response.data.submissionId
|
||||
const submissionId = response.submissionId
|
||||
|
||||
if (submissionId) {
|
||||
subscribeToSubmission(submissionId)
|
||||
@@ -167,7 +167,7 @@ function submit() {
|
||||
|
||||
async function getCurrentSubmission() {
|
||||
if (!problem.value?.id) return
|
||||
const { data } = await getCurrentProblemFlowchartSubmission(problem.value.id)
|
||||
const data = await getCurrentProblemFlowchartSubmission(problem.value.id)
|
||||
submissionCount.value = data.count
|
||||
latestRating.value = {
|
||||
score: data.score,
|
||||
@@ -177,7 +177,7 @@ async function getCurrentSubmission() {
|
||||
|
||||
async function getSubmission(submissionPage = 0) {
|
||||
if (!problem.value?.id) return
|
||||
const { data } = await getFlowchartSubmissionDetail(
|
||||
const data = await getFlowchartSubmissionDetail(
|
||||
problem.value.id,
|
||||
submissionPage,
|
||||
)
|
||||
|
||||
@@ -25,9 +25,9 @@ export function useSubmissionMonitor() {
|
||||
|
||||
try {
|
||||
const res = await getSubmission(submissionId.value)
|
||||
submission.value = res.data
|
||||
submission.value = res
|
||||
|
||||
const result = res.data.result
|
||||
const result = res.result
|
||||
// 判题完成,停止轮询
|
||||
if (
|
||||
result !== SubmissionStatus.judging &&
|
||||
@@ -83,7 +83,7 @@ export function useSubmissionMonitor() {
|
||||
pausePolling()
|
||||
|
||||
getSubmission(submissionId.value).then((res) => {
|
||||
submission.value = res.data
|
||||
submission.value = res
|
||||
// 15分钟无新提交则断开WebSocket(节省资源)
|
||||
scheduleDisconnect(15 * 60 * 1000)
|
||||
})
|
||||
|
||||
@@ -110,7 +110,7 @@ async function init() {
|
||||
;(inProblem.value ? loadProblemEditor : loadContestEditor)()
|
||||
try {
|
||||
const res = await getProblem(problemID, contestID)
|
||||
problem.value = res.data
|
||||
problem.value = res
|
||||
} catch (err: any) {
|
||||
problem.value = null
|
||||
if (err.error === "contest-not-started") {
|
||||
|
||||
@@ -81,7 +81,7 @@ async function listProblems() {
|
||||
|
||||
async function listTags() {
|
||||
const res = await getProblemTagList()
|
||||
tags.value = res.data.map((r: Omit<Tag, "checked">) => ({
|
||||
tags.value = res.map((r: Omit<Tag, "checked">) => ({
|
||||
...r,
|
||||
checked: query.tag === r.name,
|
||||
}))
|
||||
|
||||
@@ -56,15 +56,15 @@ async function loadUserProgress() {
|
||||
}
|
||||
const res = await getProblemSetUserProgress(problemSetId.value, params)
|
||||
|
||||
progress.value = res.data.results
|
||||
total.value = res.data.total
|
||||
progress.value = res.results
|
||||
total.value = res.total
|
||||
// 使用后端返回的统计数据(基于所有数据)
|
||||
if (res.data.statistics) {
|
||||
statistics.value = res.data.statistics
|
||||
if (res.statistics) {
|
||||
statistics.value = res.statistics
|
||||
}
|
||||
// 保存所有题目信息
|
||||
if (res.data.problems) {
|
||||
allProblems.value = res.data.problems
|
||||
if (res.problems) {
|
||||
allProblems.value = res.problems
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
@@ -34,20 +34,20 @@ const activeTab = ref("problems")
|
||||
|
||||
async function loadProblemSetDetail() {
|
||||
const res = await getProblemSetDetail(problemSetId.value)
|
||||
problemSet.value = res.data
|
||||
isJoined.value = res.data.userProgress?.isJoined || false
|
||||
problemSet.value = res
|
||||
isJoined.value = res.userProgress?.isJoined || false
|
||||
}
|
||||
|
||||
async function loadProblems() {
|
||||
const res = await getProblemSetProblems(problemSetId.value)
|
||||
problems.value = res.data
|
||||
problems.value = res
|
||||
}
|
||||
|
||||
async function loadUserBadges() {
|
||||
if (!isJoined.value) return
|
||||
|
||||
const res = await getUserBadges()
|
||||
userBadges.value = res.data.filter(
|
||||
userBadges.value = res.filter(
|
||||
(badge: UserBadgeType) => badge.badge.problemsetId === problemSetId.value,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@ async function listProblemSets() {
|
||||
query.difficulty,
|
||||
query.status,
|
||||
)
|
||||
total.value = res.data.total
|
||||
problemSets.value = res.data.results
|
||||
total.value = res.total
|
||||
problemSets.value = res.results
|
||||
}
|
||||
|
||||
function getDifficultyTag(difficulty: string) {
|
||||
|
||||
@@ -82,7 +82,7 @@ async function loadClassDetail(className: string) {
|
||||
classDetailData.value = null
|
||||
try {
|
||||
const res = await getClassPK([className])
|
||||
classDetailData.value = res.data.comparisons[0] ?? null
|
||||
classDetailData.value = res.comparisons[0] ?? null
|
||||
} catch {
|
||||
// ignore
|
||||
} finally {
|
||||
@@ -151,10 +151,10 @@ async function analyzeSingleClassWithAI() {
|
||||
async function init() {
|
||||
const offset = (query.page - 1) * query.limit
|
||||
const res = await getRank(offset, query.limit)
|
||||
data.value = res.data.results
|
||||
total.value = res.data.total
|
||||
me.value = res.data.me
|
||||
return res.data.results
|
||||
data.value = res.results
|
||||
total.value = res.total
|
||||
me.value = res.me
|
||||
return res.results
|
||||
}
|
||||
|
||||
function isMe(row: Rank) {
|
||||
@@ -256,7 +256,7 @@ async function listActivity() {
|
||||
const start = formatISO(sub(current, subOptions.value))
|
||||
const res = await getActivityRank(start)
|
||||
// 活动榜只有「用户名 + 做题数」,塞进榜单图表复用的 Rank 形状里
|
||||
activityChart.value = res.data.map((d, index) => ({
|
||||
activityChart.value = res.map((d, index) => ({
|
||||
id: index,
|
||||
user: { id: index, username: d.username, realName: null },
|
||||
acceptedNumber: d.count,
|
||||
@@ -268,7 +268,7 @@ async function listActivity() {
|
||||
// 「全服 Top10」就是同一个榜的第一页 —— 上限由服务端定,这里只要前 10 条
|
||||
async function listRank() {
|
||||
const res = await getRank(0, 10)
|
||||
rankChart.value = res.data.results
|
||||
rankChart.value = res.results
|
||||
}
|
||||
|
||||
const options: SelectOption[] = [
|
||||
@@ -439,7 +439,7 @@ async function listClassRank() {
|
||||
classQuery.grade = parseInt(className.slice(0, 2))
|
||||
}
|
||||
const res = await getClassRank(classQuery.grade)
|
||||
classData.value = res.data
|
||||
classData.value = res
|
||||
}
|
||||
|
||||
async function listMyClassRank() {
|
||||
@@ -450,10 +450,10 @@ async function listMyClassRank() {
|
||||
: 0
|
||||
const limit = myClassScope.value === "all" ? myClassQuery.limit : undefined
|
||||
const res = await getUserClassRank(myClassScope.value, offset, limit)
|
||||
myRank.value = res.data.myRank
|
||||
myClassName.value = res.data.className
|
||||
myClassData.value = res.data.ranks
|
||||
myClassTotal.value = res.data.total ?? res.data.ranks.length
|
||||
myRank.value = res.myRank
|
||||
myClassName.value = res.className
|
||||
myClassData.value = res.ranks
|
||||
myClassTotal.value = res.total ?? res.ranks.length
|
||||
if (myClassScope.value === "window") {
|
||||
myClassQuery.page = 1
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@ export const useAIStore = defineStore("ai", () => {
|
||||
end,
|
||||
targetUsername.value || undefined,
|
||||
)
|
||||
detailsData.start = res.data.start
|
||||
detailsData.end = res.data.end
|
||||
detailsData.solved = res.data.solved
|
||||
detailsData.grade = res.data.grade
|
||||
detailsData.className = res.data.className
|
||||
detailsData.tags = res.data.tags
|
||||
detailsData.difficulty = res.data.difficulty
|
||||
detailsData.contestCount = res.data.contestCount
|
||||
detailsData.flowcharts = res.data.flowcharts
|
||||
detailsData.start = res.start
|
||||
detailsData.end = res.end
|
||||
detailsData.solved = res.solved
|
||||
detailsData.grade = res.grade
|
||||
detailsData.className = res.className
|
||||
detailsData.tags = res.tags
|
||||
detailsData.difficulty = res.difficulty
|
||||
detailsData.contestCount = res.contestCount
|
||||
detailsData.flowcharts = res.flowcharts
|
||||
}
|
||||
|
||||
async function fetchDurationData(end: string, duration: string) {
|
||||
@@ -58,13 +58,13 @@ export const useAIStore = defineStore("ai", () => {
|
||||
duration,
|
||||
targetUsername.value || undefined,
|
||||
)
|
||||
durationData.value = res.data
|
||||
durationData.value = res
|
||||
}
|
||||
|
||||
async function fetchHeatmapData() {
|
||||
loading.heatmap = true
|
||||
const res = await getAIHeatmapData(targetUsername.value || undefined)
|
||||
heatmapData.value = res.data
|
||||
heatmapData.value = res
|
||||
loading.heatmap = false
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ export const useAIStore = defineStore("ai", () => {
|
||||
|
||||
async function fetchPinnedReport() {
|
||||
const res = await getAIPinnedReport()
|
||||
pinnedReport.value = res.data
|
||||
pinnedReport.value = res
|
||||
}
|
||||
|
||||
async function simulatePinnedStream() {
|
||||
|
||||
@@ -58,9 +58,9 @@ export const useContestStore = defineStore("contest", () => {
|
||||
async function init(contestID: string) {
|
||||
problems.value = []
|
||||
const res = await getContest(contestID)
|
||||
contest.value = res.data
|
||||
contest.value = res
|
||||
// now 是学生侧比赛专有的服务器时间,用来对齐倒计时
|
||||
now.value = getTime(parseISO(res.data.now ?? res.data.createTime))
|
||||
now.value = getTime(parseISO(res.now ?? res.createTime))
|
||||
if (contestStatus.value !== ContestStatus.finished) {
|
||||
timer = setInterval(() => {
|
||||
now.value = now.value + 1000
|
||||
@@ -68,7 +68,7 @@ export const useContestStore = defineStore("contest", () => {
|
||||
}
|
||||
if (contest.value?.contestType === ContestType.private) {
|
||||
const res = await getContestAccess(contestID)
|
||||
toggleAccess(res.data.access)
|
||||
toggleAccess(res.access)
|
||||
}
|
||||
_getProblems(contestID)
|
||||
}
|
||||
@@ -84,8 +84,8 @@ export const useContestStore = defineStore("contest", () => {
|
||||
async function checkPassword(contestID: string, password: string) {
|
||||
try {
|
||||
const res = await checkContestPassword(contestID, password)
|
||||
toggleAccess(res.data)
|
||||
if (res.data) {
|
||||
toggleAccess(res)
|
||||
if (res) {
|
||||
_getProblems(contestID)
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -175,7 +175,7 @@ async function loadSubmission() {
|
||||
try {
|
||||
const { getFlowchartSubmission } = await import("oj/api")
|
||||
const res = await getFlowchartSubmission(props.submissionId)
|
||||
submission.value = res.data
|
||||
submission.value = res
|
||||
|
||||
// 渲染流程图
|
||||
if (submission.value?.mermaidCode) {
|
||||
|
||||
@@ -41,7 +41,7 @@ async function init() {
|
||||
if (submission.value) return
|
||||
loading.value = true
|
||||
const res = await getSubmission(props.submissionID)
|
||||
submission.value = res.data
|
||||
submission.value = res
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
|
||||
@@ -109,8 +109,8 @@ async function listSubmissions() {
|
||||
today: query.today,
|
||||
grade: query.result,
|
||||
})
|
||||
total.value = res.data.total
|
||||
flowcharts.value = res.data.results
|
||||
total.value = res.total
|
||||
flowcharts.value = res.results
|
||||
} else {
|
||||
const res = await getSubmissions({
|
||||
...query,
|
||||
@@ -120,14 +120,14 @@ async function listSubmissions() {
|
||||
language: query.language,
|
||||
today: query.today,
|
||||
})
|
||||
submissions.value = res.data.results
|
||||
total.value = res.data.total
|
||||
submissions.value = res.results
|
||||
total.value = res.total
|
||||
}
|
||||
}
|
||||
|
||||
async function getTodayCount() {
|
||||
const res = await getTodaySubmissionCount(query.language)
|
||||
todayCount.value = res.data
|
||||
todayCount.value = res
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -63,10 +63,10 @@ async function init() {
|
||||
toggle(true)
|
||||
try {
|
||||
const res = await getProfile(route.query.name as string)
|
||||
profile.value = res.data
|
||||
profile.value = res
|
||||
// 用户不存在时后端返回 null,后面的统计全都无从算起
|
||||
if (!res.data) return
|
||||
const acm = res.data.acmProblemsStatus.problems || {}
|
||||
if (!res) return
|
||||
const acm = res.acmProblemsStatus.problems || {}
|
||||
const ac: string[] = []
|
||||
Object.keys(acm).forEach((id) => {
|
||||
if (acm[id]["status"] === 0) {
|
||||
@@ -76,17 +76,17 @@ async function init() {
|
||||
ac.sort()
|
||||
problems.value = ac
|
||||
|
||||
if (res.data.submissionNumber > 0) {
|
||||
const metricsRes = await getMetrics(res.data.user.id)
|
||||
firstSubmissionAt.value = parseTime(metricsRes.data.first)
|
||||
latestSubmissionAt.value = parseTime(metricsRes.data.latest)
|
||||
if (res.submissionNumber > 0) {
|
||||
const metricsRes = await getMetrics(res.user.id)
|
||||
firstSubmissionAt.value = parseTime(metricsRes.first)
|
||||
latestSubmissionAt.value = parseTime(metricsRes.latest)
|
||||
toLatestAt.value = durationToDays(
|
||||
metricsRes.data.latest,
|
||||
metricsRes.data.now,
|
||||
metricsRes.latest,
|
||||
metricsRes.now,
|
||||
)
|
||||
learnDuration.value = durationToDays(
|
||||
metricsRes.data.first,
|
||||
metricsRes.data.latest,
|
||||
metricsRes.first,
|
||||
metricsRes.latest,
|
||||
)
|
||||
}
|
||||
} finally {
|
||||
@@ -101,7 +101,7 @@ async function loadAchievementSummary() {
|
||||
const res = await getAchievementSummary(
|
||||
(route.query.name as string) || undefined,
|
||||
)
|
||||
achievementSummary.value = res.data
|
||||
achievementSummary.value = res
|
||||
} catch {
|
||||
achievementSummary.value = null
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ const query = reactive({
|
||||
async function listMessages() {
|
||||
const offset = (query.page - 1) * query.limit
|
||||
const res = await getMessageList(offset, query.limit)
|
||||
total.value = res.data.total
|
||||
messages.value = res.data.results
|
||||
total.value = res.total
|
||||
messages.value = res.results
|
||||
}
|
||||
|
||||
onMounted(listMessages)
|
||||
|
||||
Reference in New Issue
Block a user