Admin: name submission archives as group-studentNo-name-attempt
This commit is contained in:
@@ -746,16 +746,36 @@ class AdminController(
|
||||
@GetMapping("/submissions/{id}/download")
|
||||
fun downloadSubmissionAsAdmin(
|
||||
@PathVariable id: String,
|
||||
@RequestParam(required = false) group: String?,
|
||||
@RequestParam(required = false) no: String?,
|
||||
@RequestParam(required = false) name: String?,
|
||||
@RequestParam(required = false) attempt: String?,
|
||||
session: HttpSession,
|
||||
): ResponseEntity<ByteArray> {
|
||||
val file = api.downloadSubmissionAsAdmin(token(session), id)
|
||||
val encoded = java.net.URLEncoder.encode(file.filename, java.nio.charset.StandardCharsets.UTF_8)
|
||||
val filename = submissionFilename(group, no, name, attempt) ?: file.filename
|
||||
val encoded = java.net.URLEncoder.encode(filename, java.nio.charset.StandardCharsets.UTF_8)
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''$encoded")
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.body(file.bytes)
|
||||
}
|
||||
|
||||
/** Человекочитаемое имя архива сдачи: группа-номер студенческого-ФИО-попыткаN.zip */
|
||||
private fun submissionFilename(group: String?, no: String?, name: String?, attempt: String?): String? {
|
||||
val parts = listOfNotNull(
|
||||
group?.takeIf { it.isNotBlank() },
|
||||
no?.takeIf { it.isNotBlank() },
|
||||
name?.takeIf { it.isNotBlank() },
|
||||
attempt?.takeIf { it.isNotBlank() }?.let { "попытка$it" },
|
||||
)
|
||||
if (parts.isEmpty()) return null
|
||||
val base = parts.joinToString("-")
|
||||
.replace(Regex("[\\\\/:*?\"<>|\\r\\n]"), "_")
|
||||
.trim()
|
||||
return if (base.isBlank()) null else "$base.zip"
|
||||
}
|
||||
|
||||
@PostMapping("/labs/{labId}/assign")
|
||||
fun assignVariant(
|
||||
@PathVariable labId: String,
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<span th:if="${cell.defenseStatus == 'started'}" class="cell-chip chip-warn" title="Защита: студент пишет работу">🛡⏳</span>
|
||||
<span th:if="${cell.defenseStatus == 'ready'}" class="cell-chip chip-ok" title="Защита: работа сохранена, можно принимать">🛡✓</span>
|
||||
<a th:if="${cell.submissionId}" class="cell-chip chip-link"
|
||||
th:href="'/admin/submissions/' + ${cell.submissionId} + '/download'"
|
||||
th:href="@{/admin/submissions/{id}/download(id=${cell.submissionId}, group=${group.name}, no=${row.studentNo}, name=${row.fullName}, attempt=${cell.submissionSeq})}"
|
||||
title="Скачать последнее решение студента">↓<span class="font-mono" th:text="${cell.submissionSeq}">1</span></a>
|
||||
<span th:unless="${cell.submissionId}" class="cell-chip chip-dim" title="Решений пока не сдавалось">↓—</span>
|
||||
<button class="cell-chip" type="button"
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
</td>
|
||||
<td th:attr="data-filter-value=${s.submissionId != null ? 'сдано' : 'нет'}">
|
||||
<a th:if="${s.submissionId}" class="cell-link"
|
||||
th:href="'/admin/submissions/' + ${s.submissionId} + '/download'">
|
||||
th:href="@{/admin/submissions/{id}/download(id=${s.submissionId}, group=${g.groupName}, no=${s.studentNo}, name=${s.fullName}, attempt=${s.submissionSeq})}">
|
||||
попытка <span th:text="${s.submissionSeq}">1</span> ↓</a>
|
||||
<div th:if="${!#lists.isEmpty(s.submissionFiles)}" class="text-muted text-sm font-mono">
|
||||
<span th:text="${#strings.listJoin(s.submissionFiles, ', ')}">main.c</span>
|
||||
|
||||
Reference in New Issue
Block a user