This commit is contained in:
2026-10-19 02:56:22 +07:00
parent 97b5545b32
commit 53a60dee6b
+103 -23
View File
@@ -12,6 +12,7 @@ import {
NRate, NRate,
NSelect, NSelect,
NSpace, NSpace,
NTable,
NTabPane, NTabPane,
NTabs, NTabs,
NText, NText,
@@ -1064,6 +1065,26 @@ const reviewsCount = ref(0)
const answersQuestions = ref<Question[]>([]) const answersQuestions = ref<Question[]>([])
const answersTeams = ref<TeamAnswers[]>([]) const answersTeams = ref<TeamAnswers[]>([])
const resultQuestions = ref<ResultsQuestion[]>([])
const resultTeams = ref<TeamResult[]>([])
const isLoadingResults = ref(false)
const hasResultsError = ref(false)
async function loadAnswerResults() {
isLoadingResults.value = true
hasResultsError.value = false
try {
const res = await client.GetGameResults({ gameID: Number(gameId) })
resultQuestions.value = res.questions || []
resultTeams.value = res.teams || []
} catch (err) {
hasResultsError.value = true
console.error('Не удалось загрузить таблицу результатов', err)
} finally {
isLoadingResults.value = false
}
}
// Баллы по ключу "teamID:questionCode" (undefined — балл не выставлен) // Баллы по ключу "teamID:questionCode" (undefined — балл не выставлен)
const scores = ref<Record<string, number | undefined>>({}) const scores = ref<Record<string, number | undefined>>({})
@@ -1090,6 +1111,7 @@ async function loadGameAnswers() {
} }
} }
scores.value = next scores.value = next
await loadAnswerResults()
} }
async function openReviewsModal() { async function openReviewsModal() {
@@ -1538,31 +1560,78 @@ useSimplePolling(() => {
</n-tab-pane> </n-tab-pane>
<n-tab-pane v-if="canManageGame" name="answers" tab="Проверка ответов"> <n-tab-pane v-if="canManageGame" name="answers" tab="Проверка ответов">
<div class="game-tab-content"> <div class="game-tab-content">
<div v-if="answersQuestions.length == 0" class="answers-empty"> <UiBlock>
Вопросы дела не заданы или команды ещё не отвечали. <p class="screens-title">Таблица результатов</p>
</div> <p>Сохранённые оценки. Таблица обновляется после сохранения баллов.</p>
<UiBlock v-for="question in answersQuestions" :key="question.code"> <n-text v-if="isLoadingResults">Загрузка результатов…</n-text>
<p class="answers-question-title">{{ question.code }}: {{ question.text }}</p> <n-alert v-else-if="hasResultsError" type="error">
<p class="answers-question-answer"> Не удалось загрузить таблицу результатов.
Правильный ответ:<br /><span class="correct-answer">{{ question.answer || '—' }}</span> </n-alert>
</p> <p v-else-if="resultTeams.length === 0">Результатов пока нет.</p>
<div v-for="team in answersTeams" :key="team.team?.ID" class="answers-team-row"> <div v-else class="answer-results-scroll">
<div class="answers-team-name"> <n-table :single-line="false">
{{ team.team?.name }} <thead>
</div> <tr>
<div class="answers-team-answer"> <th scope="col">Место</th>
{{ teamAnswer(team, question.code) || '—' }} <th scope="col">Команда</th>
</div> <th v-for="question in resultQuestions" :key="question.code" scope="col">
<n-input-number {{ question.code }}
:value="scores[scoreKey(team.team?.ID, question.code)]" </th>
@update:value="onScoreUpdate(scoreKey(team.team?.ID, question.code), $event)" <th scope="col">Сумма</th>
placeholder="Балл" <th scope="col">Поездки</th>
class="answers-score-input" </tr>
/> </thead>
<tbody>
<tr v-for="team in resultTeams" :key="team.team?.ID">
<td>{{ team.place }}</td>
<td>{{ team.team?.name }}</td>
<td v-for="question in resultQuestions" :key="question.code">
{{ team.answers?.find((answer) => answer.questionCode === question.code)?.score ?? '—' }}
</td>
<td>{{ team.totalScore }}</td>
<td>{{ team.actionsCount }}</td>
</tr>
</tbody>
</n-table>
</div> </div>
</UiBlock> </UiBlock>
<div
v-if="answersQuestions.length === 0 || answersTeams.length === 0"
class="answers-empty"
>
Вопросы дела не заданы или команды ещё не отвечали.
</div>
<template v-else>
<UiBlock v-for="team in answersTeams" :key="team.team?.ID">
<h3 class="answers-team-name">{{ team.team?.name }}</h3>
<div
v-for="question in answersQuestions"
:key="question.code"
class="answers-question"
>
<p class="answers-question-title">{{ question.code }}: {{ question.text }}</p>
<p class="answers-question-answer">
Правильный ответ:<br /><span class="correct-answer">{{ question.answer || '—' }}</span>
</p>
<div class="answers-team-row">
<div class="answers-team-answer">
{{ teamAnswer(team, question.code) || '—' }}
</div>
<n-input-number
:value="scores[scoreKey(team.team?.ID, question.code)]"
@update:value="onScoreUpdate(scoreKey(team.team?.ID, question.code), $event)"
placeholder="Балл"
class="answers-score-input"
/>
</div>
</div>
</UiBlock>
</template>
<n-flex justify="end"> <n-flex justify="end">
<n-button @click="saveAllScores()" :disabled="answersQuestions.length == 0"> <n-button
@click="saveAllScores()"
:disabled="answersQuestions.length === 0 || answersTeams.length === 0"
>
Сохранить баллы Сохранить баллы
</n-button> </n-button>
</n-flex> </n-flex>
@@ -1980,10 +2049,19 @@ useSimplePolling(() => {
text-decoration: underline; text-decoration: underline;
} }
.answer-results-scroll {
overflow-x: auto;
}
.answers-empty { .answers-empty {
color: #777; color: #777;
} }
.answers-question {
margin-top: 16px;
overflow-wrap: anywhere;
}
.answers-question-title { .answers-question-title {
font-size: 17px; font-size: 17px;
font-weight: 600; font-weight: 600;
@@ -2015,8 +2093,10 @@ useSimplePolling(() => {
} }
.answers-team-name { .answers-team-name {
font-size: 18px;
font-weight: 600; font-weight: 600;
width: 180px; margin: 0;
overflow-wrap: anywhere;
} }
.answers-team-answer { .answers-team-answer {