diff --git a/apps/web/src/oj/announcement/components/TitleWithTag.vue b/apps/web/src/oj/announcement/components/TitleWithTag.vue
deleted file mode 100644
index 0a8a845..0000000
--- a/apps/web/src/oj/announcement/components/TitleWithTag.vue
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
- 置顶
- {{ title }}
-
-
-
diff --git a/apps/web/src/oj/contest/detail.vue b/apps/web/src/oj/contest/detail.vue
index 6a1d2dc..be0da74 100644
--- a/apps/web/src/oj/contest/detail.vue
+++ b/apps/web/src/oj/contest/detail.vue
@@ -3,6 +3,8 @@ import { useThemeVars } from "naive-ui"
import { useTone } from "oj/submission/composables/tone"
import { ContestStatus } from "utils/constants"
import { parseTime, secondsToDuration } from "utils/functions"
+import NotFound from "shared/components/NotFound.vue"
+import { errorCode } from "utils/api"
import { useContestStore } from "../store/contest"
import ContestBadge from "./components/ContestBadge.vue"
import ContestInfo from "./components/ContestInfo.vue"
@@ -34,18 +36,27 @@ async function check() {
}
}
+/** 拉比赛失败:原来没接,链接不对就是一整页空白 */
+const failure = ref(null)
+
+async function load() {
+ failure.value = null
+ try {
+ await contestStore.init(props.contestID)
+ } catch (err) {
+ if (contestStore.contest) return
+ failure.value = errorCode(err) === "contest-not-found" ? "missing" : "failed"
+ }
+}
+
watch(
() => contestStore.contestStatus,
(nv, ov) => {
- if (nv === ContestStatus.underway && ov == ContestStatus.not_started) {
- contestStore.init(props.contestID)
- }
+ if (nv === ContestStatus.underway && ov == ContestStatus.not_started) load()
},
)
-onMounted(() => {
- contestStore.init(props.contestID)
-})
+onMounted(load)
onBeforeUnmount(contestStore.clear)
@@ -95,7 +106,17 @@ const to = (name: string) => ({ name, params: { contestID: props.contestID } })
-
+
+
+ 再试一次
+
+
{{ contest.title }}
diff --git a/apps/web/src/oj/problem/detail.vue b/apps/web/src/oj/problem/detail.vue
index 3758e1c..2d250c6 100644
--- a/apps/web/src/oj/problem/detail.vue
+++ b/apps/web/src/oj/problem/detail.vue
@@ -11,6 +11,7 @@ import { useSubmissionStore } from "oj/store/submission"
import { useFlowchartStore } from "oj/store/flowchart"
import { useCollabStore } from "shared/store/collab"
import type { RouteLocationNormalized } from "vue-router"
+import NotFound from "shared/components/NotFound.vue"
// 判完之后该发生的事(烟花、点评、回题单)。静态引入:它得在第一次判完之前就挂好
import SubmissionEffects from "./components/SubmissionEffects.vue"
import ResultTabLabel from "./components/ResultTabLabel.vue"
@@ -40,9 +41,10 @@ interface Props {
problemSetId?: string
}
-const { problemID, contestID = "" } = defineProps()
+const { problemID, contestID = "", problemSetId = "" } = defineProps()
-const errMsg = ref("无数据")
+/** 拉题面失败的原因:null 是还在拉(或拉到了),别的就整页换成 NotFound */
+const failure = ref(null)
const route = useRoute()
const router = useRouter()
@@ -226,6 +228,7 @@ async function init() {
// 并行预取右侧编辑器 chunk(CodeMirror ~370K+),
// 避免等 getProblem 返回后才串行下载,编辑器才迟迟出现
loadProblemEditor()
+ failure.value = null
try {
const res = await getProblem(problemID, contestID)
if (mine !== initSeq) return
@@ -233,12 +236,25 @@ async function init() {
} catch (err) {
if (mine !== initSeq) return
problem.value = null
- if (errorCode(err) === "contest-not-started") {
- errMsg.value = "比赛还没有开始"
- }
+ const code = errorCode(err)
+ failure.value =
+ code === "contest-not-started"
+ ? "not-started"
+ : code === "problem-not-found"
+ ? "missing"
+ : "failed"
}
}
onMounted(init)
+
+/** 题不存在时回哪:比赛里回比赛,题单里回题单,否则回题目列表 */
+const backTo = computed(() =>
+ contestID
+ ? { to: `/contest/${contestID}`, toLabel: "回到比赛" }
+ : problemSetId
+ ? { to: `/problemset/${problemSetId}`, toLabel: "回到题单" }
+ : { to: "/problem", toLabel: "去题目列表" },
+)
watch(() => problemID, init)
// 题目详情里的 myStatus / myFailedCount 是按当前用户算的,而登录不重新挂载这个页面 ——
@@ -262,7 +278,7 @@ onBeforeUnmount(() => {
// 流程图那边同理,还在评的那次不再跟(照常评完落库)
useFlowchartStore().reset()
problem.value = null
- errMsg.value = "无数据"
+ failure.value = null
myFlowchartStore.hide()
})
@@ -372,7 +388,23 @@ onBeforeUnmount(() => {
-
+
+
+ 再试一次
+
+