SubmissionListView.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <script setup lang="ts">
  2. import { getSubmissionController } from '@/api/submission-controller'
  3. import type { SubmissionVo } from '@/api/models'
  4. import { ElMessage } from 'element-plus'
  5. import { onMounted, reactive, ref } from 'vue'
  6. import { useRoute, useRouter } from 'vue-router'
  7. import { useLoginUserStore } from '@/store'
  8. import { formatTime } from '@/util/format-time'
  9. import { getStatusInfo } from '@/util/submission'
  10. const route = useRoute()
  11. const router = useRouter()
  12. const api = getSubmissionController()
  13. const loginUserStore = useLoginUserStore()
  14. const loading = ref(false)
  15. const tableData = ref<SubmissionVo[]>([])
  16. const pagination = reactive({ pageNum: 1, pageSize: 20, total: 0 })
  17. const fetchData = async () => {
  18. loading.value = true
  19. try {
  20. const res = await api.queryMy({ pageNum: pagination.pageNum, pageSize: pagination.pageSize })
  21. const pageData = res?.data
  22. tableData.value = pageData?.data || []
  23. pagination.total = pageData?.total || 0
  24. } catch {
  25. tableData.value = []
  26. } finally {
  27. loading.value = false
  28. }
  29. }
  30. const handlePageChange = (page: number) => {
  31. pagination.pageNum = page
  32. fetchData()
  33. }
  34. const handleSizeChange = (size: number) => {
  35. pagination.pageSize = size
  36. pagination.pageNum = 1
  37. fetchData()
  38. }
  39. const goProblem = (problemId?: number) => {
  40. if (!problemId) return
  41. router.push(`/problems/${problemId}`)
  42. }
  43. onMounted(() => {
  44. if (!loginUserStore.loginUser.isLogin) {
  45. ElMessage.warning('请先登录')
  46. router.push({ path: '/login', query: { redirect: route.fullPath } })
  47. return
  48. }
  49. fetchData()
  50. })
  51. </script>
  52. <template>
  53. <div class="submission-list-view">
  54. <el-card class="table-card" shadow="never">
  55. <template #header><span class="card-title">我的提交记录</span></template>
  56. <el-table v-loading="loading" :data="tableData" border stripe style="width: 100%" :empty-text="'暂无提交记录'">
  57. <el-table-column type="expand">
  58. <template #default="{ row }">
  59. <div v-if="row.judgeDetail" class="expand-detail">
  60. <div class="expand-title">判题详情</div>
  61. <pre class="judge-detail">{{ row.judgeDetail }}</pre>
  62. </div>
  63. <el-empty v-else description="无判题详情" :image-size="40" />
  64. </template>
  65. </el-table-column>
  66. <el-table-column prop="id" label="编号" width="90" align="center" />
  67. <el-table-column label="题目" min-width="120">
  68. <template #default="{ row }">
  69. <el-link type="primary" @click="goProblem(row.problemId)">题目 #{{ row.problemId ?? '-' }}</el-link>
  70. </template>
  71. </el-table-column>
  72. <el-table-column prop="language" label="语言" width="90" align="center">
  73. <template #default="{ row }">{{ (row.language || 'java').toUpperCase() }}</template>
  74. </el-table-column>
  75. <el-table-column label="状态" width="120" align="center">
  76. <template #default="{ row }">
  77. <el-tag :type="getStatusInfo(row.status).tag">{{ getStatusInfo(row.status).label }}</el-tag>
  78. </template>
  79. </el-table-column>
  80. <el-table-column label="得分" width="80" align="center">
  81. <template #default="{ row }">{{ row.score ?? '-' }}</template>
  82. </el-table-column>
  83. <el-table-column label="用时" width="90" align="center">
  84. <template #default="{ row }">{{ row.timeUsedMs != null ? `${row.timeUsedMs}ms` : '-' }}</template>
  85. </el-table-column>
  86. <el-table-column label="内存" width="100" align="center">
  87. <template #default="{ row }">{{ row.memoryUsedKb != null ? `${row.memoryUsedKb}KB` : '-' }}</template>
  88. </el-table-column>
  89. <el-table-column label="通过用例" width="100" align="center">
  90. <template #default="{ row }">
  91. {{ row.passedTestCases ?? 0 }} / {{ row.totalTestCases ?? 0 }}
  92. </template>
  93. </el-table-column>
  94. <el-table-column label="提交时间" width="170" align="center">
  95. <template #default="{ row }">{{ formatTime(row.createdAt) }}</template>
  96. </el-table-column>
  97. </el-table>
  98. <div class="pagination">
  99. <el-pagination
  100. v-model:current-page="pagination.pageNum"
  101. v-model:page-size="pagination.pageSize"
  102. :page-sizes="[10, 20, 50, 100]"
  103. :total="pagination.total"
  104. layout="total, sizes, prev, pager, next, jumper"
  105. @current-change="handlePageChange"
  106. @size-change="handleSizeChange"
  107. />
  108. </div>
  109. </el-card>
  110. </div>
  111. </template>
  112. <style scoped>
  113. .submission-list-view {
  114. padding: 20px;
  115. margin: 0 auto;
  116. }
  117. .card-title {
  118. font-weight: 600;
  119. }
  120. .pagination {
  121. display: flex;
  122. justify-content: flex-end;
  123. margin-top: 16px;
  124. }
  125. .expand-detail {
  126. padding: 8px 16px;
  127. }
  128. .expand-title {
  129. font-weight: 600;
  130. margin-bottom: 6px;
  131. }
  132. .judge-detail {
  133. margin: 0;
  134. padding: 12px;
  135. background: var(--el-fill-color-light);
  136. border-radius: 6px;
  137. white-space: pre-wrap;
  138. word-break: break-word;
  139. font-size: 13px;
  140. }
  141. </style>