本组别无客观题:先选择文件并确认无误,再点击「上传所选文件」提交
@@ -107,8 +113,14 @@
show-icon
style="margin-top:12px"
title="组内作品唯一:本组已有成员上传,您无法再上传"
- description="如需替换作品,请联系上传者本人操作(仅首个上传者可在截止前替换)。"
+ description="如需替换作品,请联系上传者本人操作(仅首个上传者可在截止前替换)。您本人无需提交,可直接返回工作台。"
/>
+
+
+ 返回工作台
+ 本组作品已由队友提交,您无需任何操作。
+
@@ -405,7 +417,7 @@
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { useRouter, onBeforeRouteLeave } from 'vue-router'
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
-import { Timer, UploadFilled } from '@element-plus/icons-vue'
+import { Timer, UploadFilled, Back } from '@element-plus/icons-vue'
import { useAuthStore } from '@/stores/auth'
import { useExamStore } from '@/stores/exam'
import * as examApi from '@/api/exam'
@@ -516,6 +528,36 @@ function clearUploadFiles() {
uploadRef.value?.clearFiles?.()
}
+/**
+ * 返回工作台(R192)—— 上传模式的统一出口。
+ *
+ * 🔴 必须先 resetExam() 再 push,理由有三条:
+ * ① 不清 `examStarted` ⇒ `onBeforeRouteLeave` 会再弹一次「离开页面将丢失当前提交进度」。
+ * 上传模式下用户常常只是放弃提交(甚至被组锁、本机根本没有可提交内容),
+ * 这句文案既失真又构成二次打扰;
+ * ② 不清 timer ⇒ store 是全局单例,回到工作台后倒计时仍在跑,下次进入会看到陈旧剩余时间;
+ * ③ 用 resetExam(而非只 stopExam)与 `onBeforeRouteLeave` 里确认离开后的清理**同一口径**,
+ * ⛔ 不留「按钮退出」与「路由守卫退出」两套清理逻辑(漏项会以「下次进入状态诡异」的形式出现)。
+ *
+ * 只有「待上传列表里有已选文件」才算真有内容会丢,此时才确认一次。
+ * 组锁用户的上传控件是 disabled 的,选不出文件 ⇒ 不弹确认,直接离开。
+ */
+async function leaveCompetition() {
+ if (!teamLocked.value && uploadFileList.value.length > 0) {
+ try {
+ await ElMessageBox.confirm(
+ '已选择的文件尚未上传,离开后需要重新选择。确定返回工作台吗?',
+ '提示',
+ { confirmButtonText: '返回工作台', cancelButtonText: '继续上传', type: 'warning' }
+ )
+ } catch {
+ return
+ }
+ }
+ examStore.resetExam()
+ router.push('/dashboard')
+}
+
async function submitUploadFiles() {
const files = pendingUploadFiles.value
if (!files.length) return
@@ -1031,7 +1073,13 @@ function preventKeyboard(e) {
// 路由离开警告
onBeforeRouteLeave((to, from, next) => {
- if (examStore.examStarted && !examStore.isTimeUp) {
+ // 🔴 组锁用户不弹:上传控件 disabled、无交卷动作 ⇒ 本机没有任何可丢的内容。
+ // 对这类用户弹「离开将丢失提交进度」是假警告(体验反馈:被锁成员被困在提交页)。
+ // 判定写成「上传模式 && teamLocked」而不是只看 teamLocked:后者当前虽等价
+ // (客观题模式不拉 uploadStatus),但语义上把考试组也纳入了豁免面,将来一旦
+ // 考试组也拉 status,就会静默取消「交卷前离开」的确认 —— 这是不可接受的放松。
+ const lockedNoContent = isUploadMode.value && teamLocked.value
+ if (examStore.examStarted && !examStore.isTimeUp && !lockedNoContent) {
const verb = isUploadMode.value ? '提交' : '答题'
ElMessageBox.confirm(
`离开页面将丢失当前${verb}进度,确定要离开吗?`,
@@ -1579,6 +1627,28 @@ onUnmounted(() => {
justify-content: space-between;
}
+/* ==================== R192:上传页出口(组锁 / 主动放弃提交) ==================== */
+/* 本页无全局导航(App.vue 只有 router-view)⇒ 出口按钮必须常驻,否则被组锁的
+ 成员只能靠浏览器后退离开(移动端/内嵌浏览器常常退不出去)。 */
+.upload-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+}
+.team-locked-actions {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ margin-top: 0.75rem;
+}
+.team-locked-hint {
+ font-size: 0.85rem;
+ color: #909399;
+}
+
/* ==================== R190:小组作品状态面板 ==================== */
.team-status-panel {
border: 1px solid #c6e2ff;