refactor(前端): shared / utils 不再 import oj 和 admin 下的任何东西

依赖方向原来是反的:顶栏、登录框、举手列表这些 shared 组件从 oj/ 里拿东西。
- 跨端的接口挪进 shared/api.ts(按 apps/web/CLAUDE.md 的分法):学生端题目列表、
  出题人列表、这节课的题、待弹的成就
- 这节课的 store → shared/store/lesson.ts;头像 RankAvatar → shared/components
- 纯函数挪进 utils/:举手列表的错法归类 errorKind、它依赖的答案错误分类 wrongAnswer
  和 Python 报错翻译 pythonError、题目列表行的 toProblemRow
- 只有后台在用的出题人下拉 AuthorSelect 挪回 admin/components

纯搬家。首页、题目列表、题目页、排名、课堂看板、后台题目列表打开无报错,
顶栏题号框敲 1001 回车直达题目页。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-16 15:11:21 +08:00
1 parent d4aadc7722
commit e8a20d12f9
38 files changed
+78 -78

No files matched your search

@@ -9,7 +9,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getAuthors } from "oj/api" import { getAuthors } from "shared/api"
interface Props { interface Props {
all?: boolean all?: boolean
+1 -1
View File
@@ -9,7 +9,7 @@ import { batchSetProblemVisible, getProblemList, toggleProblemVisible } from "..
import Actions from "./components/Actions.vue" import Actions from "./components/Actions.vue"
import AddFromLibraryModal from "./components/AddFromLibraryModal.vue" import AddFromLibraryModal from "./components/AddFromLibraryModal.vue"
import { useRouteQuery } from "@vueuse/router" import { useRouteQuery } from "@vueuse/router"
import AuthorSelect from "shared/components/AuthorSelect.vue" import AuthorSelect from "admin/components/AuthorSelect.vue"
import type { DataTableRowKey } from "naive-ui" import type { DataTableRowKey } from "naive-ui"
import BatchTagModal from "./components/BatchTagModal.vue" import BatchTagModal from "./components/BatchTagModal.vue"
import CreateProblemMenu from "./components/CreateProblemMenu.vue" import CreateProblemMenu from "./components/CreateProblemMenu.vue"
+1 -10
View File
@@ -1,17 +1,8 @@
import type { MarkAchievementsRead } from "@oj2/contract"
import api from "utils/api" import api from "utils/api"
import type { AchievementList, PendingAchievement } from "utils/types" import type { AchievementList } from "utils/types"
export function getAchievements(name?: string) { export function getAchievements(name?: string) {
return api.get<AchievementList>("achievements", { return api.get<AchievementList>("achievements", {
params: name ? { username: name } : {}, params: name ? { username: name } : {},
}) })
} }
export function getPendingAchievements() {
return api.get<PendingAchievement[]>("achievements/pending")
}
export function markAchievementsRead(ids: number[]) {
return api.post("achievements/pending/read", { ids } satisfies MarkAchievementsRead)
}
+2 -29
View File
@@ -23,7 +23,6 @@ import {
type ProfileOverview, type ProfileOverview,
type TutorialSummary, type TutorialSummary,
type Tutorial, type Tutorial,
type ClassActivity,
type ClassToday, type ClassToday,
type LastVisit, type LastVisit,
type ClassBoard, type ClassBoard,
@@ -40,10 +39,8 @@ import {
type WeeklyRank, type WeeklyRank,
type ProblemRank, type ProblemRank,
type CreateSubmissionResponse, type CreateSubmissionResponse,
type ProblemAuthor,
type ProblemListItem, type ProblemListItem,
type ProblemStats, type ProblemStats,
type ProblemList,
type ProblemProgress, type ProblemProgress,
type CreateFlowchartResponse, type CreateFlowchartResponse,
type FlowchartScores, type FlowchartScores,
@@ -64,7 +61,7 @@ import {
} from "@oj2/contract" } from "@oj2/contract"
import api from "utils/api" import api from "utils/api"
import { contract } from "utils/contract" import { contract } from "utils/contract"
import { toProblemRow } from "oj/transforms" import { toProblemRow } from "utils/transforms"
import type { import type {
Announcement, Announcement,
AnnouncementListItem, AnnouncementListItem,
@@ -82,26 +79,12 @@ import type {
/** /**
* 题目详情 / 提交详情的 schema 按需加载,和请求并行发出。静态 import 会把 zod * 题目详情 / 提交详情的 schema 按需加载,和请求并行发出。静态 import 会把 zod
* 运行时带进首页 —— 题目列表的 getProblemList 也在这个文件里。 * 运行时带进首页 —— 首页、题目列表都 import 这个文件。
* 闸门本身仍是同步的(等 schema 到了再返回),submissionDetailSchema 有 `.catch()`, * 闸门本身仍是同步的(等 schema 到了再返回),submissionDetailSchema 有 `.catch()`,
* 放行原文和解析结果不等价,所以不能像 /me 那样改成 contractDeferred。 * 放行原文和解析结果不等价,所以不能像 /me 那样改成 contractDeferred。
*/ */
const loadDetailSchemas = () => import("./detailSchemas") const loadDetailSchemas = () => import("./detailSchemas")
export async function getProblemList(
offset = 0,
limit = 10,
searchParams: Record<string, unknown> = {},
) {
const res = await api.get<ProblemList>("problems", {
params: { paging: true, offset, limit, ...searchParams },
})
return {
results: res.results.map(toProblemRow),
total: res.total,
}
}
/** 题目列表顶上那行和左栏的进度;没登录是 null */ /** 题目列表顶上那行和左栏的进度;没登录是 null */
export function getProblemProgress() { export function getProblemProgress() {
return api.get<ProblemProgress | null>("problems/progress") return api.get<ProblemProgress | null>("problems/progress")
@@ -115,12 +98,6 @@ export function getRandomProblem(params: { tag: string; type: string; language:
return api.get<string>("problems/random", { params }) return api.get<string>("problems/random", { params })
} }
export function getAuthors(all = false) {
return api.get<ProblemAuthor[]>("problem-authors", {
params: { all: all ? "1" : "0" },
})
}
export async function getProblem(problemID: string, contestID: string) { export async function getProblem(problemID: string, contestID: string) {
const endpoint = contestID const endpoint = contestID
? `contests/${encodeURIComponent(contestID)}/problems/${encodeURIComponent(problemID)}` ? `contests/${encodeURIComponent(contestID)}/problems/${encodeURIComponent(problemID)}`
@@ -316,10 +293,6 @@ export function getKnowledgeMap() {
return api.get<KnowledgeMap>("me/knowledge") return api.get<KnowledgeMap>("me/knowledge")
} }
export function getClassActivity() {
return api.get<ClassActivity>("me/class-activity")
}
/** 老师首页「今天的课」:今天在上课的每个班 */ /** 老师首页「今天的课」:今天在上课的每个班 */
export function getClassToday() { export function getClassToday() {
return api.get<ClassToday>("classroom/today") return api.get<ClassToday>("classroom/today")
+1 -1
View File
@@ -15,7 +15,7 @@ import { LANGUAGE_SHOW_VALUE } from "utils/constants"
import { parseTime } from "utils/functions" import { parseTime } from "utils/functions"
import type { ClassBoard, ClassBoardCell, ClassBoardProblem, ClassBoardStudent } from "utils/types" import type { ClassBoard, ClassBoardCell, ClassBoardProblem, ClassBoardStudent } from "utils/types"
import ExplainModal, { type ExplainPerson } from "./components/ExplainModal.vue" import ExplainModal, { type ExplainPerson } from "./components/ExplainModal.vue"
import { errorKind, type ErrorKind } from "./errorKind" import { errorKind, type ErrorKind } from "utils/errorKind"
/** /**
* 课堂看板(老师,设计稿「课堂看板重设计」A+B):这个班、今天、这节课的几道题 × 全班学生。 * 课堂看板(老师,设计稿「课堂看板重设计」A+B):这个班、今天、这节课的几道题 × 全班学生。
+1 -1
View File
@@ -3,7 +3,6 @@ import { continueStep, doneCount, lessonPath, splitTitle, type TutorialType } fr
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { import {
getAnnouncementList, getAnnouncementList,
getClassActivity,
getKnowledgeMap, getKnowledgeMap,
getContestList, getContestList,
getLastVisit, getLastVisit,
@@ -12,6 +11,7 @@ import {
getTutorials, getTutorials,
getWeeklyRank, getWeeklyRank,
} from "oj/api" } from "oj/api"
import { getClassActivity } from "shared/api"
import SubmissionResultTag from "shared/components/SubmissionResultTag.vue" import SubmissionResultTag from "shared/components/SubmissionResultTag.vue"
import { pickHeadline, type Headline } from "oj/user/knowledge" import { pickHeadline, type Headline } from "oj/user/knowledge"
import { useUserStore } from "shared/store/user" import { useUserStore } from "shared/store/user"
@@ -5,7 +5,7 @@ import { errorMessage } from "utils/api"
import { SubmissionStatus } from "utils/constants" import { SubmissionStatus } from "utils/constants"
import { trialRun } from "utils/judge" import { trialRun } from "utils/judge"
import { explainCCompileError } from "oj/problem/utils/cError" import { explainCCompileError } from "oj/problem/utils/cError"
import { explainPythonCompileError } from "oj/problem/utils/pythonError" import { explainPythonCompileError } from "utils/pythonError"
import { explainRuntimeError } from "oj/problem/utils/runtimeError" import { explainRuntimeError } from "oj/problem/utils/runtimeError"
import { useAuthModalStore } from "shared/store/authModal" import { useAuthModalStore } from "shared/store/authModal"
import { useUserStore } from "shared/store/user" import { useUserStore } from "shared/store/user"
@@ -10,7 +10,7 @@ import {
showPunctuationMarks, showPunctuationMarks,
} from "oj/problem/utils/errorMark" } from "oj/problem/utils/errorMark"
import { explainCCompileError } from "oj/problem/utils/cError" import { explainCCompileError } from "oj/problem/utils/cError"
import { explainPythonCompileError } from "oj/problem/utils/pythonError" import { explainPythonCompileError } from "utils/pythonError"
/** /**
* 编译错误的中文说明卡片:Python 的语法错误走 pythonError.ts,C / C++ 的 gcc 报错走 * 编译错误的中文说明卡片:Python 的语法错误走 pythonError.ts,C / C++ 的 gcc 报错走
@@ -4,7 +4,7 @@ import type { RouteLocationRaw } from "vue-router"
import { getProblemSetDetail, getProblemSetProblems, joinProblemSet } from "oj/api" import { getProblemSetDetail, getProblemSetProblems, joinProblemSet } from "oj/api"
import { useContestStore } from "oj/store/contest" import { useContestStore } from "oj/store/contest"
import { isFlowchartPass, useFlowchartStore } from "oj/store/flowchart" import { isFlowchartPass, useFlowchartStore } from "oj/store/flowchart"
import { useLessonStore } from "oj/store/lesson" import { useLessonStore } from "shared/store/lesson"
import { useProblemStore } from "oj/store/problem" import { useProblemStore } from "oj/store/problem"
import { useUserStore } from "shared/store/user" import { useUserStore } from "shared/store/user"
import { useBreakpoints } from "shared/composables/breakpoints" import { useBreakpoints } from "shared/composables/breakpoints"
@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { useLessonStore } from "oj/store/lesson" import { useLessonStore } from "shared/store/lesson"
/** /**
* 通过之后告诉学生「这节课的下一题是哪道」。 * 通过之后告诉学生「这节课的下一题是哪道」。
@@ -18,7 +18,7 @@ import { useCollabHere, useTeacherCollab } from "../composables/teacherCollab"
import { useProblemPageContext } from "../composables/problemPageContext" import { useProblemPageContext } from "../composables/problemPageContext"
import CollabBar from "./CollabBar.vue" import CollabBar from "./CollabBar.vue"
import { useFlowchartStore } from "oj/store/flowchart" import { useFlowchartStore } from "oj/store/flowchart"
import { useLessonStore } from "oj/store/lesson" import { useLessonStore } from "shared/store/lesson"
const FlowchartEditor = defineAsyncComponent( const FlowchartEditor = defineAsyncComponent(
() => import("shared/components/FlowchartEditor/index.vue"), () => import("shared/components/FlowchartEditor/index.vue"),
@@ -5,7 +5,7 @@ import { getReaction } from "oj/api"
import { useProblemStore } from "oj/store/problem" import { useProblemStore } from "oj/store/problem"
import { useSubmissionStore } from "oj/store/submission" import { useSubmissionStore } from "oj/store/submission"
import { useFireworks } from "oj/problem/composables/useFireworks" import { useFireworks } from "oj/problem/composables/useFireworks"
import { useLessonStore } from "oj/store/lesson" import { useLessonStore } from "shared/store/lesson"
import { isFlowchartPass, useFlowchartStore } from "oj/store/flowchart" import { isFlowchartPass, useFlowchartStore } from "oj/store/flowchart"
import { SubmissionStatus } from "utils/constants" import { SubmissionStatus } from "utils/constants"
import { useProblemPageContext } from "../composables/problemPageContext" import { useProblemPageContext } from "../composables/problemPageContext"
@@ -21,7 +21,7 @@ import WrongAnswerExplain from "./WrongAnswerExplain.vue"
import LessonNext from "./LessonNext.vue" import LessonNext from "./LessonNext.vue"
import ResultHeader from "./ResultHeader.vue" import ResultHeader from "./ResultHeader.vue"
import SimilarProblems from "./SimilarProblems.vue" import SimilarProblems from "./SimilarProblems.vue"
import { useLessonStore } from "oj/store/lesson" import { useLessonStore } from "shared/store/lesson"
import { useProblemPageContext } from "../composables/problemPageContext" import { useProblemPageContext } from "../composables/problemPageContext"
import Markdown from "shared/components/Markdown.vue" import Markdown from "shared/components/Markdown.vue"
@@ -5,12 +5,7 @@ import { useThemeVars } from "naive-ui"
import { useProblemStore } from "oj/store/problem" import { useProblemStore } from "oj/store/problem"
import { markdownToText } from "oj/problem/utils/plainText" import { markdownToText } from "oj/problem/utils/plainText"
import { JUDGE_STATUS, SubmissionStatus } from "utils/constants" import { JUDGE_STATUS, SubmissionStatus } from "utils/constants"
import { import { classifyDiff, explainDiff, firstDifferentLine, type SampleCheck } from "utils/wrongAnswer"
classifyDiff,
explainDiff,
firstDifferentLine,
type SampleCheck,
} from "oj/problem/utils/wrongAnswer"
/** /**
* 答案错误时的样例对比(数据见后端 judge/run.ts 的 checkSamples)。 * 答案错误时的样例对比(数据见后端 judge/run.ts 的 checkSamples)。
+2 -1
View File
@@ -3,7 +3,8 @@ import { Icon } from "@iconify/vue"
import type { ProblemProgress, ProblemTypeFilter, Tag } from "@oj2/contract" import type { ProblemProgress, ProblemTypeFilter, Tag } from "@oj2/contract"
import { useRouteQuery } from "@vueuse/router" import { useRouteQuery } from "@vueuse/router"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { getAuthors, getProblemList, getProblemProgress, getRandomProblem } from "oj/api" import { getProblemProgress, getRandomProblem } from "oj/api"
import { getAuthors, getProblemList } from "shared/api"
import { useCodeStore } from "oj/store/code" import { useCodeStore } from "oj/store/code"
import { useTone } from "shared/composables/tone" import { useTone } from "shared/composables/tone"
import { STORAGE_KEY } from "utils/constants" import { STORAGE_KEY } from "utils/constants"
+1 -1
View File
@@ -1,5 +1,5 @@
import { findChinesePunctuation } from "./chinesePunctuation" import { findChinesePunctuation } from "./chinesePunctuation"
import { PUNCTUATION_NAMES, type PythonErrorExplanation } from "./pythonError" import { PUNCTUATION_NAMES, type PythonErrorExplanation } from "utils/pythonError"
/** /**
* 把 C / C++ 的编译错误(gcc 的原文)翻成中文,和 pythonError.ts 同一个思路: * 把 C / C++ 的编译错误(gcc 的原文)翻成中文,和 pythonError.ts 同一个思路:
@@ -1,4 +1,4 @@
import { PUNCTUATION_MAP } from "./pythonError" import { PUNCTUATION_MAP } from "utils/pythonError"
export interface PunctuationFix { export interface PunctuationFix {
from: number from: number
@@ -3,7 +3,7 @@ import type { RankRow, WeeklyChampion } from "@oj2/contract"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import UserName from "shared/components/UserName.vue" import UserName from "shared/components/UserName.vue"
import { parseTime } from "utils/functions" import { parseTime } from "utils/functions"
import RankAvatar from "./RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
/** 本班最近几周的每周冠军,底下再挂这张榜上「进步最大」的那个人 */ /** 本班最近几周的每周冠军,底下再挂这张榜上「进步最大」的那个人 */
defineProps<{ defineProps<{
@@ -9,7 +9,7 @@ import { useBackClose } from "shared/composables/backClose"
import { useBreakpoints } from "shared/composables/breakpoints" import { useBreakpoints } from "shared/composables/breakpoints"
import { parseTime } from "utils/functions" import { parseTime } from "utils/functions"
import { useRankPalette } from "../palette" import { useRankPalette } from "../palette"
import RankAvatar from "./RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
// Markdown 连着整套代码高亮(两百多 KB),这里要等点开 / AI 写完才用得上,别让它拖慢页面 // Markdown 连着整套代码高亮(两百多 KB),这里要等点开 / AI 写完才用得上,别让它拖慢页面
const Markdown = defineAsyncComponent(() => import("shared/components/Markdown.vue")) const Markdown = defineAsyncComponent(() => import("shared/components/Markdown.vue"))
+1 -1
View File
@@ -4,7 +4,7 @@ import { useThemeVars } from "naive-ui"
import UserName from "shared/components/UserName.vue" import UserName from "shared/components/UserName.vue"
import { gapText, toPass } from "../utils" import { gapText, toPass } from "../utils"
import MoodPopover from "./MoodPopover.vue" import MoodPopover from "./MoodPopover.vue"
import RankAvatar from "./RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
export interface MiniRank { export interface MiniRank {
label: string label: string
@@ -4,7 +4,7 @@ import { useThemeVars } from "naive-ui"
import { useBreakpoints } from "shared/composables/breakpoints" import { useBreakpoints } from "shared/composables/breakpoints"
import UserName from "shared/components/UserName.vue" import UserName from "shared/components/UserName.vue"
import { useRankPalette } from "../palette" import { useRankPalette } from "../palette"
import RankAvatar from "./RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
/** /**
* 领奖台:前三名站在台阶上,第一名戴皇冠。赛道从第 4 名接着排,前三不再出现第二遍。 * 领奖台:前三名站在台阶上,第一名戴皇冠。赛道从第 4 名接着排,前三不再出现第二遍。
@@ -5,7 +5,7 @@ import UserName from "shared/components/UserName.vue"
import { useBreakpoints } from "shared/composables/breakpoints" import { useBreakpoints } from "shared/composables/breakpoints"
import { useRankPalette } from "../palette" import { useRankPalette } from "../palette"
import MoodPopover from "./MoodPopover.vue" import MoodPopover from "./MoodPopover.vue"
import RankAvatar from "./RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
/** /**
* 赛道:每人一根条,条越长做对越多,一样长的先做到的排前面(设计稿 G1 / G2)。 * 赛道:每人一根条,条越长做对越多,一样长的先做到的排前面(设计稿 G1 / G2)。
+1 -1
View File
@@ -3,7 +3,7 @@ import type { RankRow } from "@oj2/contract"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import UserName from "shared/components/UserName.vue" import UserName from "shared/components/UserName.vue"
import { useRankPalette } from "../palette" import { useRankPalette } from "../palette"
import RankAvatar from "./RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
/** 这周本班前 5 名(做对过新题的),每周一清零 */ /** 这周本班前 5 名(做对过新题的),每周一清零 */
const props = defineProps<{ rows: RankRow[]; meId?: number; loaded: boolean }>() const props = defineProps<{ rows: RankRow[]; meId?: number; loaded: boolean }>()
@@ -1,5 +1,5 @@
import { explainCCompileError } from "oj/problem/utils/cError" import { explainCCompileError } from "oj/problem/utils/cError"
import { explainPythonCompileError } from "oj/problem/utils/pythonError" import { explainPythonCompileError } from "utils/pythonError"
import { explainRuntimeError } from "oj/problem/utils/runtimeError" import { explainRuntimeError } from "oj/problem/utils/runtimeError"
import { SubmissionStatus } from "utils/constants" import { SubmissionStatus } from "utils/constants"
import type { Submission } from "utils/types" import type { Submission } from "utils/types"
@@ -2,7 +2,7 @@
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { resetAvatar, uploadAvatar } from "oj/api" import { resetAvatar, uploadAvatar } from "oj/api"
import RankAvatar from "oj/rank/components/RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
import { useUserStore } from "shared/store/user" import { useUserStore } from "shared/store/user"
/** /**
@@ -3,7 +3,7 @@ import { MOOD_MAX, STUDENT_ROLES, type ProfileOverview } from "@oj2/contract"
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { clearMood, setRankHidden, updateProfile } from "oj/api" import { clearMood, setRankHidden, updateProfile } from "oj/api"
import RankAvatar from "oj/rank/components/RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
import { classLabel } from "utils/classes" import { classLabel } from "utils/classes"
import UserName from "shared/components/UserName.vue" import UserName from "shared/components/UserName.vue"
import { useUserStore } from "shared/store/user" import { useUserStore } from "shared/store/user"
+42 -2
View File
@@ -1,8 +1,16 @@
import type { LoginRequest, RegisterRequest } from "@oj2/contract" import type { LoginRequest, RegisterRequest } from "@oj2/contract"
import type { Quote, WebsiteConfig } from "@oj2/contract" import type {
ClassActivity,
MarkAchievementsRead,
ProblemAuthor,
ProblemList,
Quote,
WebsiteConfig,
} from "@oj2/contract"
import api from "utils/api" import api from "utils/api"
import { contractDeferred } from "utils/contract" import { contractDeferred } from "utils/contract"
import type { Profile, Tag } from "utils/types" import { toProblemRow } from "utils/transforms"
import type { PendingAchievement, Profile, Tag } from "utils/types"
export function login(data: { username: string; password: string }) { export function login(data: { username: string; password: string }) {
return api.post("auth/login", data satisfies LoginRequest) return api.post("auth/login", data satisfies LoginRequest)
@@ -51,3 +59,35 @@ export function getClassUsernames(classroom: string) {
export function getWebsiteConfig() { export function getWebsiteConfig() {
return api.get<WebsiteConfig>("site") return api.get<WebsiteConfig>("site")
} }
export async function getProblemList(
offset = 0,
limit = 10,
searchParams: Record<string, unknown> = {},
) {
const res = await api.get<ProblemList>("problems", {
params: { paging: true, offset, limit, ...searchParams },
})
return {
results: res.results.map(toProblemRow),
total: res.total,
}
}
export function getAuthors(all = false) {
return api.get<ProblemAuthor[]>("problem-authors", {
params: { all: all ? "1" : "0" },
})
}
export function getClassActivity() {
return api.get<ClassActivity>("me/class-activity")
}
export function getPendingAchievements() {
return api.get<PendingAchievement[]>("achievements/pending")
}
export function markAchievementsRead(ids: number[]) {
return api.post("achievements/pending/read", { ids } satisfies MarkAchievementsRead)
}
@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { errorKind } from "oj/classroom/errorKind" import { errorKind } from "utils/errorKind"
import { useBreakpoints } from "shared/composables/breakpoints" import { useBreakpoints } from "shared/composables/breakpoints"
import { useTeacherHelp } from "shared/composables/teacherHelp" import { useTeacherHelp } from "shared/composables/teacherHelp"
import { useCollabStore } from "shared/store/collab" import { useCollabStore } from "shared/store/collab"
+1 -1
View File
@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import RankAvatar from "oj/rank/components/RankAvatar.vue" import RankAvatar from "shared/components/RankAvatar.vue"
import { classLabel, groupClassOptions } from "utils/classes" import { classLabel, groupClassOptions } from "utils/classes"
import { errorCode } from "utils/api" import { errorCode } from "utils/api"
import { STORAGE_KEY } from "utils/constants" import { STORAGE_KEY } from "utils/constants"
@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { useThemeVars } from "naive-ui" import { useThemeVars } from "naive-ui"
import { useLessonStore } from "oj/store/lesson" import { useLessonStore } from "shared/store/lesson"
import { useProblemJump } from "shared/composables/problemJump" import { useProblemJump } from "shared/composables/problemJump"
import { useUserStore } from "shared/store/user" import { useUserStore } from "shared/store/user"
import type { ClassActivityProblem } from "utils/types" import type { ClassActivityProblem } from "utils/types"
@@ -1,4 +1,4 @@
import { getProblemList } from "oj/api" import { getProblemList } from "shared/api"
/** /**
* 按题号直达。课上老师报一个题号、全班去找,是非比赛提交最主要的来路, * 按题号直达。课上老师报一个题号、全班去找,是非比赛提交最主要的来路,
+1 -1
View File
@@ -1,4 +1,4 @@
import { getPendingAchievements, markAchievementsRead } from "oj/achievement/api" import { getPendingAchievements, markAchievementsRead } from "shared/api"
import type { QueuedAchievement } from "utils/types" import type { QueuedAchievement } from "utils/types"
/** /**
@@ -1,5 +1,5 @@
import { defineStore } from "pinia" import { defineStore } from "pinia"
import { getClassActivity } from "oj/api" import { getClassActivity } from "shared/api"
import { LANGUAGE_SHOW_VALUE } from "utils/constants" import { LANGUAGE_SHOW_VALUE } from "utils/constants"
import type { ClassActivity, ClassActivityProblem } from "utils/types" import type { ClassActivity, ClassActivityProblem } from "utils/types"
@@ -1,4 +1,4 @@
import { classifyDiff, type DiffKind } from "oj/problem/utils/wrongAnswer" import { classifyDiff, type DiffKind } from "utils/wrongAnswer"
import { JUDGE_STATUS, SubmissionStatus } from "utils/constants" import { JUDGE_STATUS, SubmissionStatus } from "utils/constants"
import type { ClassBoardCell } from "utils/types" import type { ClassBoardCell } from "utils/types"
File renamed without changes.
@@ -1,5 +1,5 @@
import type { StatisticInfo } from "@oj2/contract" import type { StatisticInfo } from "@oj2/contract"
import { PUNCTUATION_MAP, PUNCTUATION_NAMES } from "./pythonError" import { PUNCTUATION_MAP, PUNCTUATION_NAMES } from "utils/pythonError"
/** /**
* 答案错误时,比较学生在**公开样例**上的输出和正确输出,归一类、给一句中文提示。 * 答案错误时,比较学生在**公开样例**上的输出和正确输出,归一类、给一句中文提示。