feat(frontend): show submission performance in problem workbench
This commit is contained in:
@@ -2,13 +2,14 @@
|
||||
import { computed, onBeforeUnmount, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { findProblem, discussions, submissions } from '../data/preview'
|
||||
import { findProblem, discussions, submissions, type Submission } from '../data/preview'
|
||||
import { useCodeDraft, codeTemplates, languageLabels } from '../composables/useCodeDraft'
|
||||
import CodeEditor from '../components/CodeEditor.vue'
|
||||
import DifficultyTag from '../components/DifficultyTag.vue'
|
||||
import VerdictTag from '../components/VerdictTag.vue'
|
||||
import EmptyState from '../components/EmptyState.vue'
|
||||
import UiIcon from '../components/UiIcon.vue'
|
||||
import SubmissionPerformance from '../components/SubmissionPerformance.vue'
|
||||
const route = useRoute()
|
||||
const id = String(route.params.id)
|
||||
const problem = computed(() => findProblem(id))
|
||||
@@ -17,12 +18,20 @@ const theme = ref('vs')
|
||||
const fontSize = ref(14)
|
||||
const tab = ref('description')
|
||||
const testTab = ref('input')
|
||||
const workspaceTab = ref<'code' | 'submission'>('code')
|
||||
const selectedSubmission = ref<Submission>()
|
||||
const testInput = ref(problem.value?.sampleInput ?? '')
|
||||
const settingsOpen = ref(false)
|
||||
const split = ref(50)
|
||||
const workspace = ref<HTMLDivElement>()
|
||||
const codeRelated = computed(() => submissions.filter((s) => s.problemId === id))
|
||||
const relatedDiscussion = computed(() => discussions.filter((d) => d.problemId === id))
|
||||
function viewSubmission(submissionId: string) {
|
||||
const submission = codeRelated.value.find((item) => item.id === submissionId)
|
||||
if (!submission) return
|
||||
selectedSubmission.value = submission
|
||||
workspaceTab.value = 'submission'
|
||||
}
|
||||
const draftText = computed(
|
||||
() =>
|
||||
({
|
||||
@@ -160,10 +169,14 @@ async function copySample(value: string) {
|
||||
/><el-table-column label="结果" width="100"
|
||||
><template #default="{ row }"
|
||||
><VerdictTag :value="row.verdict" /></template></el-table-column
|
||||
><el-table-column label="详情" width="80"
|
||||
><el-table-column label="用时" width="90"
|
||||
><template #default="{ row }">{{
|
||||
row.time === null ? '—' : row.time + ' ms'
|
||||
}}</template> </el-table-column
|
||||
><el-table-column label="详情" width="105"
|
||||
><template #default="{ row }"
|
||||
><RouterLink :to="'/submissions/' + row.id" class="text-link"
|
||||
>查看</RouterLink
|
||||
><el-button link type="primary" @click="viewSubmission(row.id)"
|
||||
>查看表现</el-button
|
||||
></template
|
||||
></el-table-column
|
||||
></el-table
|
||||
@@ -210,67 +223,106 @@ async function copySample(value: string) {
|
||||
@keydown.right.prevent="split = Math.min(70, split + 2)"
|
||||
/>
|
||||
<section class="panel editor-panel">
|
||||
<header class="editor-toolbar">
|
||||
<span class="small muted">语言</span
|
||||
><el-select v-model="language" aria-label="编程语言" size="small"
|
||||
><el-option
|
||||
v-for="(label, value) in languageLabels"
|
||||
:key="value"
|
||||
:label="label"
|
||||
:value="value" /></el-select
|
||||
><el-tooltip content="重置模板"
|
||||
><el-button size="small" aria-label="重置代码模板" @click="resetCode"
|
||||
><UiIcon name="refresh" /></el-button></el-tooltip
|
||||
><span class="draft-label" aria-live="polite">{{ draftText }}</span
|
||||
><el-button size="small" aria-label="下载代码" @click="downloadCode"
|
||||
><UiIcon name="document" /></el-button
|
||||
><el-popover v-model:visible="settingsOpen" trigger="click" width="240"
|
||||
><template #reference
|
||||
><el-button size="small" aria-label="编辑器设置"><UiIcon name="settings" /></el-button
|
||||
></template>
|
||||
<div class="editor-settings">
|
||||
<label>主题</label
|
||||
><el-select v-model="theme" aria-label="编辑器主题"
|
||||
><el-option label="浅色" value="vs" /><el-option
|
||||
label="深色"
|
||||
value="vs-dark" /></el-select
|
||||
><label>字号</label><el-slider v-model="fontSize" :min="12" :max="22" show-input /></div
|
||||
></el-popover>
|
||||
</header>
|
||||
<div class="editor-area">
|
||||
<CodeEditor v-model="code" :language="language" :theme="theme" :font-size="fontSize" />
|
||||
</div>
|
||||
<div class="editor-testing">
|
||||
<el-tabs v-model="testTab"
|
||||
><el-tab-pane label="自测输入" name="input"
|
||||
><el-input
|
||||
v-model="testInput"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
resize="none"
|
||||
placeholder="输入自测数据"
|
||||
aria-label="自测输入"
|
||||
/><el-button
|
||||
v-if="problem.sampleInput"
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="testInput = problem.sampleInput"
|
||||
>填入题目样例</el-button
|
||||
></el-tab-pane
|
||||
><el-tab-pane label="运行结果" name="result"
|
||||
><p class="test-result-placeholder">
|
||||
尚未运行。判题服务接入后展示标准输出、错误信息与资源使用情况。
|
||||
</p></el-tab-pane
|
||||
></el-tabs
|
||||
<header class="workspace-view-tabs" aria-label="工作台视图">
|
||||
<button
|
||||
type="button"
|
||||
:aria-pressed="workspaceTab === 'code'"
|
||||
@click="workspaceTab = 'code'"
|
||||
>
|
||||
<UiIcon name="document" />代码编辑器
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:disabled="!selectedSubmission"
|
||||
:aria-pressed="workspaceTab === 'submission'"
|
||||
@click="workspaceTab = 'submission'"
|
||||
>
|
||||
<UiIcon name="rankings" />{{
|
||||
selectedSubmission ? '提交 #' + selectedSubmission.id : '评测详情'
|
||||
}}
|
||||
</button>
|
||||
</header>
|
||||
<div v-show="workspaceTab === 'code'" class="editor-workspace">
|
||||
<header class="editor-toolbar">
|
||||
<span class="small muted">语言</span
|
||||
><el-select v-model="language" aria-label="编程语言" size="small"
|
||||
><el-option
|
||||
v-for="(label, value) in languageLabels"
|
||||
:key="value"
|
||||
:label="label"
|
||||
:value="value" /></el-select
|
||||
><el-tooltip content="重置模板"
|
||||
><el-button size="small" aria-label="重置代码模板" @click="resetCode"
|
||||
><UiIcon name="refresh" /></el-button></el-tooltip
|
||||
><span class="draft-label" aria-live="polite">{{ draftText }}</span
|
||||
><el-button size="small" aria-label="下载代码" @click="downloadCode"
|
||||
><UiIcon name="document" /></el-button
|
||||
><el-popover v-model:visible="settingsOpen" trigger="click" width="240"
|
||||
><template #reference
|
||||
><el-button size="small" aria-label="编辑器设置"><UiIcon name="settings" /></el-button
|
||||
></template>
|
||||
<div class="editor-settings">
|
||||
<label>主题</label
|
||||
><el-select v-model="theme" aria-label="编辑器主题"
|
||||
><el-option label="浅色" value="vs" /><el-option
|
||||
label="深色"
|
||||
value="vs-dark" /></el-select
|
||||
><label>字号</label
|
||||
><el-slider v-model="fontSize" :min="12" :max="22" show-input /></div
|
||||
></el-popover>
|
||||
</header>
|
||||
<div class="editor-area">
|
||||
<CodeEditor v-model="code" :language="language" :theme="theme" :font-size="fontSize" />
|
||||
</div>
|
||||
<div class="editor-testing">
|
||||
<el-tabs v-model="testTab"
|
||||
><el-tab-pane label="自测输入" name="input"
|
||||
><el-input
|
||||
v-model="testInput"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
resize="none"
|
||||
placeholder="输入自测数据"
|
||||
aria-label="自测输入"
|
||||
/><el-button
|
||||
v-if="problem.sampleInput"
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="testInput = problem.sampleInput"
|
||||
>填入题目样例</el-button
|
||||
></el-tab-pane
|
||||
><el-tab-pane label="运行结果" name="result"
|
||||
><p class="test-result-placeholder">
|
||||
尚未运行。判题服务接入后展示标准输出、错误信息与资源使用情况。
|
||||
</p></el-tab-pane
|
||||
></el-tabs
|
||||
>
|
||||
</div>
|
||||
<footer class="editor-buttons">
|
||||
<span class="small muted">评测服务待接入</span
|
||||
><el-button size="small" @click="save">保存草稿</el-button
|
||||
><el-button size="small" type="success" plain disabled>自测运行</el-button
|
||||
><el-button size="small" type="primary" disabled>提交代码</el-button>
|
||||
</footer>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedSubmission"
|
||||
v-show="workspaceTab === 'submission'"
|
||||
class="submission-workspace"
|
||||
>
|
||||
<header class="workspace-submission-heading">
|
||||
<div>
|
||||
<VerdictTag :value="selectedSubmission.verdict" full />
|
||||
<p>{{ selectedSubmission.username }} · {{ selectedSubmission.created }}</p>
|
||||
</div>
|
||||
<RouterLink :to="'/submissions/' + selectedSubmission.id" class="text-link"
|
||||
>完整详情 →</RouterLink
|
||||
>
|
||||
</header>
|
||||
<SubmissionPerformance :submission="selectedSubmission" />
|
||||
<p class="notice-strip">当前展示示例评测记录,源码与测试点详情待接入。</p>
|
||||
</div>
|
||||
<footer class="editor-buttons">
|
||||
<span class="small muted">评测服务待接入</span
|
||||
><el-button size="small" @click="save">保存草稿</el-button
|
||||
><el-button size="small" type="success" plain disabled>自测运行</el-button
|
||||
><el-button size="small" type="primary" disabled>提交代码</el-button>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
<EmptyState v-else title="题目不存在"
|
||||
@@ -299,6 +351,64 @@ async function copySample(value: string) {
|
||||
min-height: 0;
|
||||
border-radius: 14px;
|
||||
}
|
||||
.editor-workspace {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
.workspace-view-tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px 14px;
|
||||
border-bottom: 1px solid #edf0f5;
|
||||
}
|
||||
.workspace-view-tabs button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 8px 12px;
|
||||
border: 0;
|
||||
border-radius: 7px;
|
||||
background: transparent;
|
||||
color: #8396af;
|
||||
font-size: 12px;
|
||||
}
|
||||
.workspace-view-tabs button[aria-pressed='true'] {
|
||||
color: var(--blue);
|
||||
background: #edf6ff;
|
||||
}
|
||||
.workspace-view-tabs button:disabled {
|
||||
color: #aab6c5;
|
||||
}
|
||||
.workspace-view-tabs button:focus-visible {
|
||||
outline: 2px solid var(--blue);
|
||||
}
|
||||
.submission-workspace {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
padding: 24px;
|
||||
}
|
||||
.workspace-submission-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.workspace-submission-heading p {
|
||||
margin-top: 8px;
|
||||
font-size: 11px;
|
||||
color: #93a4ba;
|
||||
}
|
||||
.workspace-submission-heading > a {
|
||||
font-size: 12px;
|
||||
}
|
||||
.submission-workspace .performance-distribution {
|
||||
padding: 20px;
|
||||
}
|
||||
.statement-tabs {
|
||||
padding: 8px 20px 0;
|
||||
background: #fff;
|
||||
|
||||
Reference in New Issue
Block a user